diff --git a/.clang-format b/.clang-format index c5979d77ba1..33e5d4f9d0c 100644 --- a/.clang-format +++ b/.clang-format @@ -39,7 +39,60 @@ PenaltyBreakFirstLessLess: 120 PenaltyBreakString: 1000 PenaltyExcessCharacter: 1000000 PenaltyReturnTypeOnItsOwnLine: 200 -SortIncludes: false +SortIncludes: CaseSensitive +IncludeBlocks: Regroup +IncludeCategories: + # O2Physics, PWG + - Regex: ^(<|")PWG[A-Z]{2}/.*\.h + Priority: 2 + CaseSensitive: true + # O2Physics, non-PWG + - Regex: ^(<|")(Common|ALICE3|DPG|EventFiltering|Tools|Tutorials)/.*\.h + Priority: 3 + CaseSensitive: true + # O2 + - Regex: ^(<|")(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|Field|Framework|FT0|FV0|GlobalTracking|ITS|MathUtils|MFT|MCH|MID|PHOS|PID|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*/.*\.h + Priority: 4 + CaseSensitive: true + # ROOT + - Regex: ^(<|")(T[A-Z]|Math/|Roo[A-Z])[[:alnum:]/]+\.h + Priority: 5 + CaseSensitive: true + # known third-party: KFParticle + - Regex: ^(<|")KF[A-Z][[:alnum:]]+\.h + Priority: 6 + CaseSensitive: true + # known third-party: FastJet + - Regex: ^(<|")fastjet/ + Priority: 6 + CaseSensitive: true + # known third-party: ONNX runtime + - Regex: ^(<|")onnxruntime + Priority: 6 + CaseSensitive: true + # incomplete path to DataModel + - Regex: ^(<|").*DataModel/ + Priority: 1 + CaseSensitive: true + # other third-party + - Regex: ^(<|")([[:alnum:]_]+/)+[[:alnum:]_]+\.h + Priority: 6 + CaseSensitive: true + # other local-looking file + - Regex: ^".*\. + Priority: 1 + CaseSensitive: true + # C system + - Regex: ^(<|")[[:lower:]_]+\.h(>|") + Priority: 102 + CaseSensitive: true + # C++ system + - Regex: ^(<|")[[:lower:]_/]+(>|") + Priority: 101 + CaseSensitive: true + # rest + - Regex: .* + Priority: 100 SpaceBeforeAssignmentOperators: true SpaceBeforeParens: ControlStatements SpaceInEmptyParentheses: false diff --git a/.clang-tidy b/.clang-tidy index da768906bcc..490b82a880b 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,3 +1,23 @@ CheckOptions: - - key: CheckPathRegex - value: '.*/O2/.*' + - { key: CheckPathRegex, value: ".*/O2/.*" } + # Naming conventions + - { key: readability-identifier-naming.ClassCase, value: CamelCase } + - { key: readability-identifier-naming.ClassMemberPrefix, value: m } + - { key: readability-identifier-naming.ConceptCase, value: CamelCase } + - { key: readability-identifier-naming.ConstexprVariableCase, value: CamelCase } + - { key: readability-identifier-naming.ConstexprVariableIgnoredRegexp, value: "^k[A-Z].*$" } # Allow "k" prefix. + - { key: readability-identifier-naming.EnumCase, value: CamelCase } + - { key: readability-identifier-naming.EnumConstantCase, value: CamelCase } + - { key: readability-identifier-naming.EnumConstantIgnoredRegexp, value: "^k[A-Z].*$" } # Allow "k" prefix. + - { key: readability-identifier-naming.FunctionCase, value: camelBack } + - { key: readability-identifier-naming.MacroDefinitionCase, value: UPPER_CASE } + - { key: readability-identifier-naming.MacroDefinitionIgnoredRegexp, value: "^[A-Z]+(_[A-Z]+)*_$" } # Allow the trailing underscore in header guards. + - { key: readability-identifier-naming.MemberCase, value: camelBack } + - { key: readability-identifier-naming.NamespaceCase, value: lower_case } + - { key: readability-identifier-naming.ParameterCase, value: camelBack } + - { key: readability-identifier-naming.StructCase, value: CamelCase } + - { key: readability-identifier-naming.TemplateParameterCase, value: CamelCase } + - { key: readability-identifier-naming.TypeAliasCase, value: CamelCase } + - { key: readability-identifier-naming.TypedefCase, value: CamelCase } + - { key: readability-identifier-naming.TypeTemplateParameterCase, value: CamelCase } + - { key: readability-identifier-naming.VariableCase, value: camelBack } diff --git a/ALICE3/CMakeLists.txt b/ALICE3/CMakeLists.txt index ab460641cad..10172ee7d01 100644 --- a/ALICE3/CMakeLists.txt +++ b/ALICE3/CMakeLists.txt @@ -14,4 +14,4 @@ add_subdirectory(Core) # add_subdirectory(DataModel) add_subdirectory(Tasks) add_subdirectory(TableProducer) -add_subdirectory(Tools) +# add_subdirectory(Tools) diff --git a/ALICE3/Core/CMakeLists.txt b/ALICE3/Core/CMakeLists.txt index 285c1624853..6d44d580c45 100644 --- a/ALICE3/Core/CMakeLists.txt +++ b/ALICE3/Core/CMakeLists.txt @@ -11,6 +11,7 @@ o2physics_add_library(ALICE3Core SOURCES TOFResoALICE3.cxx + TrackUtilities.cxx DelphesO2TrackSmearer.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore) diff --git a/ALICE3/Core/DelphesO2LutWriter.cxx b/ALICE3/Core/DelphesO2LutWriter.cxx index f3cba264b11..987383092ec 100644 --- a/ALICE3/Core/DelphesO2LutWriter.cxx +++ b/ALICE3/Core/DelphesO2LutWriter.cxx @@ -19,19 +19,21 @@ /// @email: preghenella@bo.infn.it /// -#include +#include "ALICE3/Core/DelphesO2LutWriter.h" #include "ALICE3/Core/DelphesO2TrackSmearer.h" -#include "ALICE3/Core/DelphesO2LutWriter.h" -#include -#include "TMatrixD.h" -#include "TVectorD.h" +#include "ALICE3/Core/FastTracker.h" +#include "ALICE3/Core/TrackUtilities.h" + #include "TAxis.h" -#include "TMatrixDSymEigen.h" #include "TDatabasePDG.h" #include "TLorentzVector.h" -#include "ALICE3/Core/FastTracker.h" -#include "ALICE3/Core/TrackUtilities.h" +#include "TMatrixD.h" +#include "TMatrixDSymEigen.h" +#include "TVectorD.h" + +#include +#include // #define USE_FWD_PARAM #ifdef USE_FWD_PARAM @@ -41,21 +43,42 @@ namespace o2::fastsim { -void DelphesO2LutWriter::printLutWriterConfiguration() +void DelphesO2LutWriter::print() const +{ + LOG(info) << " --- Printing configuration of LUT writer --- "; + LOG(info) << " -> etaMaxBarrel = " << etaMaxBarrel; + LOG(info) << " -> usePara = " << usePara; + LOG(info) << " -> useDipole = " << useDipole; + LOG(info) << " -> useFlatDipole = " << useFlatDipole; + LOG(info) << " -> mAtLeastHits = " << mAtLeastHits; + LOG(info) << " -> mAtLeastCorr = " << mAtLeastCorr; + LOG(info) << " -> mAtLeastFake = " << mAtLeastFake; + LOG(info) << " -> Nch Binning: = " << mNchBinning.toString(); + LOG(info) << " -> Radius Binning: = " << mRadiusBinning.toString(); + LOG(info) << " -> Eta Binning: = " << mEtaBinning.toString(); + LOG(info) << " -> Pt Binning: = " << mPtBinning.toString(); + LOG(info) << " --- End of configuration --- "; +} + +std::string DelphesO2LutWriter::LutBinning::toString() const { - std::cout << " --- Printing configuration of LUT writer --- " << std::endl; - std::cout << " -> etaMaxBarrel = " << etaMaxBarrel << std::endl; - std::cout << " -> usePara = " << usePara << std::endl; - std::cout << " -> useDipole = " << useDipole << std::endl; - std::cout << " -> useFlatDipole = " << useFlatDipole << std::endl; + std::string str = ""; + str.append(log ? "log" : "lin"); + str.append(" nbins: "); + str.append(std::to_string(nbins)); + str.append(" min: "); + str.append(std::to_string(min)); + str.append(" max: "); + str.append(std::to_string(max)); + return str; } bool DelphesO2LutWriter::fatSolve(lutEntry_t& lutEntry, float pt, float eta, const float mass, - int itof, - int otof, + size_t itof, + size_t otof, int q, const float nch) { @@ -65,29 +88,38 @@ bool DelphesO2LutWriter::fatSolve(lutEntry_t& lutEntry, tlv.SetPtEtaPhiM(pt, eta, 0., mass); o2::track::TrackParCov trkIn; o2::upgrade::convertTLorentzVectorToO2Track(q, tlv, {0., 0., 0.}, trkIn); + // tlv.Print(); + // return fmt::format("X:{:+.4e} Alp:{:+.3e} Par: {:+.4e} {:+.4e} {:+.4e} {:+.4e} {:+.4e} |Q|:{:d} {:s}\n", + // getX(), getAlpha(), getY(), getZ(), getSnp(), getTgl(), getQ2Pt(), getAbsCharge(), getPID().getName()); + // trkIn.print(); o2::track::TrackParCov trkOut; const int status = fat.FastTrack(trkIn, trkOut, nch); - if (status <= 0) { - Printf(" --- fatSolve: FastTrack failed --- \n"); - tlv.Print(); + if (status <= mAtLeastHits) { + LOGF(info, " --- fatSolve: FastTrack failed ---"); + // tlv.Print(); return false; } + LOGF(info, " --- fatSolve: FastTrack succeeded %d ---", status); + // trkOut.print(); lutEntry.valid = true; lutEntry.itof = fat.GetGoodHitProb(itof); lutEntry.otof = fat.GetGoodHitProb(otof); - for (int i = 0; i < 15; ++i) + static constexpr int nCov = 15; + for (int i = 0; i < nCov; ++i) lutEntry.covm[i] = trkOut.getCov()[i]; // define the efficiency auto totfake = 0.; lutEntry.eff = 1.; - for (int i = 1; i < 20; ++i) { + for (size_t i = 1; i < fat.GetNLayers(); ++i) { + if (fat.IsLayerInert(i)) + continue; // skip inert layers auto igoodhit = fat.GetGoodHitProb(i); if (igoodhit <= 0. || i == itof || i == otof) continue; lutEntry.eff *= igoodhit; auto pairfake = 0.; - for (int j = i + 1; j < 20; ++j) { + for (size_t j = i + 1; j < fat.GetNLayers(); ++j) { auto jgoodhit = fat.GetGoodHitProb(j); if (jgoodhit <= 0. || j == itof || j == otof) continue; @@ -120,42 +152,44 @@ bool DelphesO2LutWriter::fwdPara(lutEntry_t& lutEntry, float pt, float eta, floa lutEntry.valid = false; // parametrised forward response; interpolates between FAT at eta = 1.75 and a fixed parametrisation at eta = 4; only diagonal elements - if (std::fabs(eta) < etaMaxBarrel || std::fabs(eta) > 4) + static constexpr float etaLimit = 4.0f; + if (std::fabs(eta) < etaMaxBarrel || std::fabs(eta) > etaLimit) return false; if (!fatSolve(lutEntry, pt, etaMaxBarrel, mass)) return false; - float covmbarrel[15] = {0}; - for (int i = 0; i < 15; ++i) { + static constexpr int nCov = 15; + float covmbarrel[nCov] = {0}; + for (int i = 0; i < nCov; ++i) { covmbarrel[i] = lutEntry.covm[i]; } // parametrisation at eta = 4 const double beta = 1. / std::sqrt(1 + mass * mass / pt / pt / std::cosh(eta) / std::cosh(eta)); - const float dca_pos = 2.5e-4 / std::sqrt(3); // 2.5 micron/sqrt(3) - const float r0 = 0.5; // layer 0 radius [cm] + const float dcaPos = 2.5e-4 / std::sqrt(3); // 2.5 micron/sqrt(3) + const float r0 = 0.5; // layer 0 radius [cm] const float r1 = 1.3; const float r2 = 2.5; const float x0layer = 0.001; // material budget (rad length) per layer - const double sigma_alpha = 0.0136 / beta / pt * std::sqrt(x0layer * std::cosh(eta)) * (1 + 0.038 * std::log(x0layer * std::cosh(eta))); - const double dcaxy_ms = sigma_alpha * r0 * std::sqrt(1 + r1 * r1 / (r2 - r0) / (r2 - r0)); - const double dcaxy2 = dca_pos * dca_pos + dcaxy_ms * dcaxy_ms; + const double sigmaAlpha = 0.0136 / beta / pt * std::sqrt(x0layer * std::cosh(eta)) * (1 + 0.038 * std::log(x0layer * std::cosh(eta))); + const double dcaxyMs = sigmaAlpha * r0 * std::sqrt(1 + r1 * r1 / (r2 - r0) / (r2 - r0)); + const double dcaxy2 = dcaPos * dcaPos + dcaxyMs * dcaxyMs; - const double dcaz_ms = sigma_alpha * r0 * std::cosh(eta); - const double dcaz2 = dca_pos * dca_pos + dcaz_ms * dcaz_ms; + const double dcazMs = sigmaAlpha * r0 * std::cosh(eta); + const double dcaz2 = dcaPos * dcaPos + dcazMs * dcazMs; - const float Leta = 2.8 / sinh(eta) - 0.01 * r0; // m - const double relmomres_pos = 10e-6 * pt / 0.3 / Bfield / Leta / Leta * std::sqrt(720. / 15.); + const float Leta = 2.8 / std::sinh(eta) - 0.01 * r0; // m + const double relmomresPos = 10e-6 * pt / 0.3 / Bfield / Leta / Leta * std::sqrt(720. / 15.); - const float relmomres_barrel = std::sqrt(covmbarrel[14]) * pt; - const float Router = 1; // m - const float relmomres_pos_barrel = 10e-6 * pt / 0.3 / Bfield / Router / Router / std::sqrt(720. / 15.); - const float relmomres_MS_barrel = std::sqrt(relmomres_barrel * relmomres_barrel - relmomres_pos_barrel * relmomres_pos_barrel); + const float relmomresBarrel = std::sqrt(covmbarrel[14]) * pt; + const float rOuter = 1; // m + const float relmomresPosBarrel = 10e-6 * pt / 0.3 / Bfield / rOuter / rOuter / std::sqrt(720. / 15.); + const float relmomresMSBarrel = std::sqrt(relmomresBarrel * relmomresBarrel - relmomresPosBarrel * relmomresPosBarrel); // interpolate MS contrib (rel resolution 0.4 at eta = 4) - const float relmomres_MS_eta4 = 0.4 / beta * 0.5 / Bfield; - const float relmomres_MS = relmomres_MS_eta4 * pow(relmomres_MS_eta4 / relmomres_MS_barrel, (std::fabs(eta) - 4.) / (4. - etaMaxBarrel)); - const float momres_tot = pt * std::sqrt(relmomres_pos * relmomres_pos + relmomres_MS * relmomres_MS); // total absolute mom reso + const float relmomresMSEta4 = 0.4 / beta * 0.5 / Bfield; + const float relmomresMS = relmomresMSEta4 * std::pow(relmomresMSEta4 / relmomresMSBarrel, (std::fabs(eta) - 4.) / (4. - etaMaxBarrel)); + const float momresTot = pt * std::sqrt(relmomresPos * relmomresPos + relmomresMS * relmomresMS); // total absolute mom reso // Fill cov matrix diag for (int i = 0; i < 15; ++i) @@ -167,31 +201,31 @@ bool DelphesO2LutWriter::fwdPara(lutEntry_t& lutEntry, float pt, float eta, floa lutEntry.covm[2] = covmbarrel[2]; if (dcaz2 > lutEntry.covm[2]) lutEntry.covm[2] = dcaz2; - lutEntry.covm[5] = covmbarrel[5]; // sigma^2 sin(phi) - lutEntry.covm[9] = covmbarrel[9]; // sigma^2 tanl - lutEntry.covm[14] = momres_tot * momres_tot / pt / pt / pt / pt; // sigma^2 1/pt + lutEntry.covm[5] = covmbarrel[5]; // sigma^2 sin(phi) + lutEntry.covm[9] = covmbarrel[9]; // sigma^2 tanl + lutEntry.covm[14] = momresTot * momresTot / pt / pt / pt / pt; // sigma^2 1/pt // Check that all numbers are numbers for (int i = 0; i < 15; ++i) { if (std::isnan(lutEntry.covm[i])) { - Printf(" --- lutEntry.covm[%d] is NaN", i); + LOGF(info, " --- lutEntry.covm[%d] is NaN", i); return false; } } return true; } -void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, int itof, int otof) +void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, size_t itof, size_t otof) { if (useFlatDipole && useDipole) { - Printf("Both dipole and dipole flat flags are on, please use only one of them"); + LOGF(info, "Both dipole and dipole flat flags are on, please use only one of them"); return; } // output file std::ofstream lutFile(filename, std::ofstream::binary); if (!lutFile.is_open()) { - Printf("Did not manage to open output file!!"); + LOGF(info, "Did not manage to open output file!!"); return; } @@ -199,33 +233,33 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in lutHeader_t lutHeader; // pid lutHeader.pdg = pdg; - lutHeader.mass = TDatabasePDG::Instance()->GetParticle(pdg)->Mass(); - const int q = std::abs(TDatabasePDG::Instance()->GetParticle(pdg)->Charge()) / 3; + const TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pdg); + if (!particle) { + LOG(fatal) << "Cannot find particle with PDG code " << pdg; + return; + } + lutHeader.mass = particle->Mass(); + const int q = std::abs(particle->Charge()) / 3; if (q <= 0) { - Printf("Negative or null charge (%f) for pdg code %i. Fix the charge!", TDatabasePDG::Instance()->GetParticle(pdg)->Charge(), pdg); + LOGF(info, "Negative or null charge (%f) for pdg code %i. Fix the charge!", particle->Charge(), pdg); return; } lutHeader.field = field; + auto setMap = [](map_t& map, LutBinning b) { + map.log = b.log; + map.nbins = b.nbins; + map.min = b.min; + map.max = b.max; + }; // nch - lutHeader.nchmap.log = true; - lutHeader.nchmap.nbins = 20; - lutHeader.nchmap.min = 0.5; - lutHeader.nchmap.max = 3.5; + setMap(lutHeader.nchmap, mNchBinning); // radius - lutHeader.radmap.log = false; - lutHeader.radmap.nbins = 1; - lutHeader.radmap.min = 0.; - lutHeader.radmap.max = 100.; + setMap(lutHeader.radmap, mRadiusBinning); // eta - lutHeader.etamap.log = false; - lutHeader.etamap.nbins = 80; - lutHeader.etamap.min = -4.; - lutHeader.etamap.max = 4.; + setMap(lutHeader.etamap, mEtaBinning); // pt - lutHeader.ptmap.log = true; - lutHeader.ptmap.nbins = 200; - lutHeader.ptmap.min = -2; - lutHeader.ptmap.max = 2.; + setMap(lutHeader.ptmap, mPtBinning); + lutFile.write(reinterpret_cast(&lutHeader), sizeof(lutHeader)); // entries @@ -240,27 +274,27 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in int successfullCalls = 0; int failedCalls = 0; for (int inch = 0; inch < nnch; ++inch) { - Printf(" --- writing nch = %d/%d", inch, nnch); + LOGF(info, " --- writing nch = %d/%d", inch, nnch); auto nch = lutHeader.nchmap.eval(inch); lutEntry.nch = nch; fat.SetdNdEtaCent(nch); for (int irad = 0; irad < nrad; ++irad) { - Printf(" --- writing irad = %d/%d", irad, nrad); + LOGF(info, " --- writing irad = %d/%d", irad, nrad); for (int ieta = 0; ieta < neta; ++ieta) { - nCalls++; - Printf(" --- writing ieta = %d/%d", ieta, neta); + LOGF(info, " --- writing ieta = %d/%d", ieta, neta); auto eta = lutHeader.etamap.eval(ieta); lutEntry.eta = lutHeader.etamap.eval(ieta); for (int ipt = 0; ipt < npt; ++ipt) { - Printf(" --- writing ipt = %d/%d", ipt, npt); + nCalls++; + LOGF(info, " --- writing ipt = %d/%d", ipt, npt); lutEntry.pt = lutHeader.ptmap.eval(ipt); lutEntry.valid = true; if (std::fabs(eta) <= etaMaxBarrel) { // full lever arm ends at etaMaxBarrel - Printf("Solving in the barrel"); - // printf(" --- fatSolve: pt = %f, eta = %f, mass = %f, field=%f \n", lutEntry.pt, lutEntry.eta, lutHeader.mass, lutHeader.field); + LOGF(info, "Solving in the barrel"); + // LOGF(info, " --- fatSolve: pt = %f, eta = %f, mass = %f, field=%f", lutEntry.pt, lutEntry.eta, lutHeader.mass, lutHeader.field); successfullCalls++; if (!fatSolve(lutEntry, lutEntry.pt, lutEntry.eta, lutHeader.mass, itof, otof, q)) { - // printf(" --- fatSolve: error \n"); + // LOGF(info, " --- fatSolve: error"); lutEntry.valid = false; lutEntry.eff = 0.; lutEntry.eff2 = 0.; @@ -271,8 +305,8 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in failedCalls++; } } else { - Printf("Solving outside the barrel"); - // printf(" --- fwdSolve: pt = %f, eta = %f, mass = %f, field=%f \n", lutEntry.pt, lutEntry.eta, lutHeader.mass, lutHeader.field); + LOGF(info, "Solving outside the barrel"); + // LOGF(info, " --- fwdSolve: pt = %f, eta = %f, mass = %f, field=%f", lutEntry.pt, lutEntry.eta, lutHeader.mass, lutHeader.field); lutEntry.eff = 1.; lutEntry.eff2 = 1.; bool retval = true; @@ -293,7 +327,7 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in lutEntry.eff2 = lutEntryBarrel.eff2; } if (!retval) { - printf(" --- fwdSolve: error \n"); + LOGF(info, " --- fwdSolve: error"); lutEntry.valid = false; for (int i = 0; i < 15; ++i) { lutEntry.covm[i] = 0.; @@ -302,50 +336,51 @@ void DelphesO2LutWriter::lutWrite(const char* filename, int pdg, float field, in failedCalls++; } } - Printf("Diagonalizing"); + LOGF(info, "Diagonalizing"); diagonalise(lutEntry); - Printf("Writing"); + LOGF(info, "Writing"); lutFile.write(reinterpret_cast(&lutEntry), sizeof(lutEntry_t)); } } } } - Printf(" --- finished writing LUT file %s", filename); - Printf(" --- successfull calls: %d/%d, failed calls: %d/%d", successfullCalls, nCalls, failedCalls, nCalls); + LOGF(info, " --- finished writing LUT file %s", filename); + LOGF(info, " --- successfull calls: %d/%d, failed calls: %d/%d", successfullCalls, nCalls, failedCalls, nCalls); lutFile.close(); } void DelphesO2LutWriter::diagonalise(lutEntry_t& lutEntry) { - TMatrixDSym m(5); - for (int i = 0, k = 0; i < 5; ++i) { + static constexpr int kEig = 5; + TMatrixDSym m(kEig); + for (int i = 0, k = 0; i < kEig; ++i) { for (int j = 0; j < i + 1; ++j, ++k) { m(i, j) = lutEntry.covm[k]; m(j, i) = lutEntry.covm[k]; } } - m.Print(); + // m.Print(); TMatrixDSymEigen eigen(m); // eigenvalues vector TVectorD eigenVal = eigen.GetEigenValues(); - for (int i = 0; i < 5; ++i) + for (int i = 0; i < kEig; ++i) lutEntry.eigval[i] = eigenVal[i]; // eigenvectors matrix TMatrixD eigenVec = eigen.GetEigenVectors(); - for (int i = 0; i < 5; ++i) - for (int j = 0; j < 5; ++j) + for (int i = 0; i < kEig; ++i) + for (int j = 0; j < kEig; ++j) lutEntry.eigvec[i][j] = eigenVec[i][j]; // inverse eigenvectors matrix eigenVec.Invert(); - for (int i = 0; i < 5; ++i) - for (int j = 0; j < 5; ++j) + for (int i = 0; i < kEig; ++i) + for (int j = 0; j < kEig; ++j) lutEntry.eiginv[i][j] = eigenVec[i][j]; } TGraph* DelphesO2LutWriter::lutRead(const char* filename, int pdg, int what, int vs, float nch, float radius, float eta, float pt) { - Printf(" --- reading LUT file %s", filename); + LOGF(info, " --- reading LUT file %s", filename); // vs static const int kNch = 0; static const int kEta = 1; @@ -363,6 +398,7 @@ TGraph* DelphesO2LutWriter::lutRead(const char* filename, int pdg, int what, int o2::delphes::DelphesO2TrackSmearer smearer; smearer.loadTable(pdg, filename); auto lutHeader = smearer.getLUTHeader(pdg); + lutHeader->print(); map_t lutMap; switch (vs) { case kNch: @@ -381,52 +417,52 @@ TGraph* DelphesO2LutWriter::lutRead(const char* filename, int pdg, int what, int g->SetTitle(Form("LUT for %s, pdg %d, vs %d, what %d", filename, pdg, vs, what)); switch (vs) { case kNch: - Printf(" --- vs = kNch"); + LOGF(info, " --- vs = kNch"); g->GetXaxis()->SetTitle("Nch"); break; case kEta: - Printf(" --- vs = kEta"); + LOGF(info, " --- vs = kEta"); g->GetXaxis()->SetTitle("#eta"); break; case kPt: - Printf(" --- vs = kPt"); + LOGF(info, " --- vs = kPt"); g->GetXaxis()->SetTitle("p_{T} (GeV/c)"); break; default: - Printf(" --- error: unknown vs %d", vs); + LOGF(info, " --- error: unknown vs %d", vs); return nullptr; } switch (what) { case kEfficiency: - Printf(" --- what = kEfficiency"); + LOGF(info, " --- what = kEfficiency"); g->GetYaxis()->SetTitle("Efficiency (%)"); break; case kEfficiency2: - Printf(" --- what = kEfficiency2"); + LOGF(info, " --- what = kEfficiency2"); g->GetYaxis()->SetTitle("Efficiency2 (%)"); break; case kEfficiencyInnerTOF: - Printf(" --- what = kEfficiencyInnerTOF"); + LOGF(info, " --- what = kEfficiencyInnerTOF"); g->GetYaxis()->SetTitle("Inner TOF Efficiency (%)"); break; case kEfficiencyOuterTOF: - Printf(" --- what = kEfficiencyOuterTOF"); + LOGF(info, " --- what = kEfficiencyOuterTOF"); g->GetYaxis()->SetTitle("Outer TOF Efficiency (%)"); break; case kPtResolution: - Printf(" --- what = kPtResolution"); + LOGF(info, " --- what = kPtResolution"); g->GetYaxis()->SetTitle("p_{T} Resolution (%)"); break; case kRPhiResolution: - Printf(" --- what = kRPhiResolution"); + LOGF(info, " --- what = kRPhiResolution"); g->GetYaxis()->SetTitle("R#phi Resolution (#mum)"); break; case kZResolution: - Printf(" --- what = kZResolution"); + LOGF(info, " --- what = kZResolution"); g->GetYaxis()->SetTitle("Z Resolution (#mum)"); break; default: - Printf(" --- error: unknown what %d", what); + LOGF(info, " --- error: unknown what %d", what); return nullptr; } @@ -447,7 +483,7 @@ TGraph* DelphesO2LutWriter::lutRead(const char* filename, int pdg, int what, int auto lutEntry = smearer.getLUTEntry(pdg, nch, radius, eta, pt, eff); if (!lutEntry->valid || lutEntry->eff == 0.) { if (!canBeInvalid) { - Printf(" --- warning: it cannot be invalid"); + LOGF(info, " --- warning: it cannot be invalid"); } continue; } @@ -480,16 +516,16 @@ TGraph* DelphesO2LutWriter::lutRead(const char* filename, int pdg, int what, int val = lutEntry->otof * 100.; // efficiency (%) break; case kPtResolution: - val = sqrt(lutEntry->covm[14]) * lutEntry->pt * 100.; // pt resolution (%) + val = std::sqrt(lutEntry->covm[14]) * lutEntry->pt * 100.; // pt resolution (%) break; case kRPhiResolution: - val = sqrt(lutEntry->covm[0]) * 1.e4; // rphi resolution (um) + val = std::sqrt(lutEntry->covm[0]) * 1.e4; // rphi resolution (um) break; case kZResolution: - val = sqrt(lutEntry->covm[1]) * 1.e4; // z resolution (um) + val = std::sqrt(lutEntry->covm[1]) * 1.e4; // z resolution (um) break; default: - Printf(" --- error: unknown what %d", what); + LOGF(info, " --- error: unknown what %d", what); break; } g->AddPoint(cen, val); diff --git a/ALICE3/Core/DelphesO2LutWriter.h b/ALICE3/Core/DelphesO2LutWriter.h index 25faf7f382c..1528ab80bac 100644 --- a/ALICE3/Core/DelphesO2LutWriter.h +++ b/ALICE3/Core/DelphesO2LutWriter.h @@ -8,15 +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. - -/// -/// @file DelphesO2LutWriter.h -/// @brief Porting to O2Physics of DelphesO2 code. +/// \file DelphesO2LutWriter.h +/// \brief Porting to O2Physics of DelphesO2 code. /// Minimal changes have been made to the original code for adaptation purposes, formatting and commented parts have been considered. /// Relevant sources: /// DelphesO2/src/lutWrite.cc https://github.com/AliceO2Group/DelphesO2/blob/master/src/lutWrite.cc -/// @author: Roberto Preghenella -/// @email: preghenella@bo.infn.it +/// \author: Roberto Preghenella +/// \email: preghenella@bo.infn.it /// #ifndef ALICE3_CORE_DELPHESO2LUTWRITER_H_ @@ -24,8 +22,13 @@ #include "ALICE3/Core/DelphesO2TrackSmearer.h" #include "ALICE3/Core/FastTracker.h" + +#include "ReconstructionDataFormats/PID.h" + #include "TGraph.h" +#include + namespace o2::fastsim { class DelphesO2LutWriter @@ -34,7 +37,33 @@ class DelphesO2LutWriter DelphesO2LutWriter() = default; virtual ~DelphesO2LutWriter() = default; + // Setters + void setBinningNch(bool log, int nbins, float min, float max) { mNchBinning = {log, nbins, min, max}; } + void setBinningRadius(bool log, int nbins, float min, float max) { mRadiusBinning = {log, nbins, min, max}; } + void setBinningEta(bool log, int nbins, float min, float max) { mEtaBinning = {log, nbins, min, max}; } + void setBinningPt(bool log, int nbins, float min, float max) { mPtBinning = {log, nbins, min, max}; } + void setEtaMaxBarrel(float eta) { etaMaxBarrel = eta; } + void setAtLeastHits(int n) { mAtLeastHits = n; } + void setAtLeastCorr(int n) { mAtLeastCorr = n; } + void setAtLeastFake(int n) { mAtLeastFake = n; } + bool fatSolve(lutEntry_t& lutEntry, + float pt = 0.1, + float eta = 0.0, + const float mass = o2::track::pid_constants::sMasses[o2::track::PID::Pion], + size_t itof = 0, + size_t otof = 0, + int q = 1, + const float nch = 1); + + void print() const; + bool fwdSolve(float* covm, float pt = 0.1, float eta = 0.0, float mass = o2::track::pid_constants::sMasses[o2::track::PID::Pion]); + bool fwdPara(lutEntry_t& lutEntry, float pt = 0.1, float eta = 0.0, float mass = o2::track::pid_constants::sMasses[o2::track::PID::Pion], float Bfield = 0.5); + void lutWrite(const char* filename = "lutCovm.dat", int pdg = 211, float field = 0.2, size_t itof = 0, size_t otof = 0); + TGraph* lutRead(const char* filename, int pdg, int what, int vs, float nch = 0., float radius = 0., float eta = 0., float pt = 0.); + o2::fastsim::FastTracker fat; + + private: void diagonalise(lutEntry_t& lutEntry); float etaMaxBarrel = 1.75f; bool usePara = true; // use fwd parameterisation @@ -44,23 +73,19 @@ class DelphesO2LutWriter int mAtLeastHits = 4; int mAtLeastCorr = 4; int mAtLeastFake = 0; - void SetAtLeastHits(int n) { mAtLeastHits = n; } - void SetAtLeastCorr(int n) { mAtLeastCorr = n; } - void SetAtLeastFake(int n) { mAtLeastFake = n; } - void printLutWriterConfiguration(); - bool fatSolve(lutEntry_t& lutEntry, - float pt = 0.1, - float eta = 0.0, - const float mass = 0.13957000, - int itof = 0, - int otof = 0, - int q = 1, - const float nch = 1); - bool fwdSolve(float* covm, float pt = 0.1, float eta = 0.0, float mass = 0.13957000); - bool fwdPara(lutEntry_t& lutEntry, float pt = 0.1, float eta = 0.0, float mass = 0.13957000, float Bfield = 0.5); - void lutWrite(const char* filename = "lutCovm.dat", int pdg = 211, float field = 0.2, int itof = 0, int otof = 0); - TGraph* lutRead(const char* filename, int pdg, int what, int vs, float nch = 0., float radius = 0., float eta = 0., float pt = 0.); + // Binning of the LUT to make + struct LutBinning { + bool log; + int nbins; + float min; + float max; + std::string toString() const; + }; + LutBinning mNchBinning = {true, 20, 0.5f, 3.5f}; + LutBinning mRadiusBinning = {false, 1, 0.0f, 100.0f}; + LutBinning mEtaBinning = {false, 80, -4.0f, 4.0f}; + LutBinning mPtBinning = {true, 200, -2.0f, 2.0f}; ClassDef(DelphesO2LutWriter, 1); }; diff --git a/ALICE3/Core/FastTracker.cxx b/ALICE3/Core/FastTracker.cxx index 1d06958504b..15ac7939af2 100644 --- a/ALICE3/Core/FastTracker.cxx +++ b/ALICE3/Core/FastTracker.cxx @@ -9,13 +9,17 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include +#include "FastTracker.h" + +#include "ReconstructionDataFormats/TrackParametrization.h" + #include "TMath.h" #include "TMatrixD.h" -#include "TRandom.h" #include "TMatrixDSymEigen.h" -#include "FastTracker.h" +#include "TRandom.h" + +#include +#include namespace o2 { @@ -24,36 +28,6 @@ namespace fastsim // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ -FastTracker::FastTracker() -{ - // base constructor - magneticField = 20; // in kiloGauss - applyZacceptance = false; - applyMSCorrection = true; - applyElossCorrection = true; - applyEffCorrection = true; - covMatFactor = 0.99f; - verboseLevel = 0; - - // last fast-tracked track properties - covMatOK = 0; - covMatNotOK = 0; - nIntercepts = 0; - nSiliconPoints = 0; - nGasPoints = 0; - - maxRadiusSlowDet = 10; - integrationTime = 0.02; // ms - crossSectionMinB = 8; - dNdEtaCent = 2200; - dNdEtaMinB = 1; - avgRapidity = 0.45; - sigmaD = 6.0; - luminosity = 1.e27; - otherBackground = 0.0; // [0, 1] - upcBackgroundMultiplier = 1.0; -} - void FastTracker::AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi, float resZ, float eff, int type) { DetLayer newLayer(name, r, z, x0, xrho, resRPhi, resZ, eff, type); @@ -61,6 +35,17 @@ void FastTracker::AddLayer(TString name, float r, float z, float x0, float xrho, if (newLayer.getEfficiency() > 0.0f && newLayer.isInert()) { LOG(error) << "Layer " << name << " with efficiency > 0.0 should not be inert"; } + // Layers should be ordered by increasing radius, check this + if (!layers.empty() && newLayer.getRadius() < layers.back().getRadius()) { + LOG(fatal) << "Layer " << newLayer << " is not ordered correctly, it should be after layer " << layers.back(); + } + // Layers should all have different names + for (const auto& layer : layers) { + if (layer.getName() == newLayer.getName()) { + LOG(fatal) << "Layer with name " << newLayer.getName() << " already exists in FastTracker layers"; + } + } + // Add the new layer to the layers vector layers.push_back(newLayer); } @@ -78,7 +63,7 @@ DetLayer FastTracker::GetLayer(int layer, bool ignoreBarrelLayers) const return layers[layerIdx]; } -int FastTracker::GetLayerIndex(std::string name) const +int FastTracker::GetLayerIndex(const std::string& name) const { int i = 0; for (const auto& layer : layers) { @@ -211,9 +196,9 @@ float FastTracker::Dist(float z, float r) // https://github.com/AliceO2Group/DelphesO2/blob/master/src/DetectorK/DetectorK.cxx#L743 int index = 1; int nSteps = 301; - double dist = 0.0; - double dz0 = (4 * sigmaD - (-4) * sigmaD / (nSteps = 1)); - double z0 = 0.0; + float dist = 0.0; + float dz0 = (4 * sigmaD - (-4) * sigmaD / (nSteps = 1)); + float z0 = 0.0; for (int i = 0; i < nSteps; i++) { if (i == nSteps - 1) index = 1; @@ -243,7 +228,7 @@ float FastTracker::IntegratedHitDensity(float multiplicity, float radius) // porting of DetektorK::IntegratedHitDensity // see here: // https://github.com/AliceO2Group/DelphesO2/blob/master/src/DetectorK/DetectorK.cxx#L712 - float zdcHz = luminosity * 1.e24 * crossSectionMinB; + float zdcHz = luminosity * 1.e24 * mCrossSectionMinB; float den = zdcHz * integrationTime / 1000. * multiplicity * Dist(0., radius) / (o2::constants::math::TwoPI * radius); if (den < OneEventHitDensity(multiplicity, radius)) den = OneEventHitDensity(multiplicity, radius); @@ -301,6 +286,7 @@ float FastTracker::ProbGoodChiSqHit(float radius, float searchRadiusRPhi, float // returns number of intercepts (generic for now) int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackParCov& outputTrack, const float nch) { + dNdEtaCent = nch; // set the number of charged particles per unit rapidity hits.clear(); nIntercepts = 0; nSiliconPoints = 0; @@ -310,38 +296,54 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa const float initialRadius = std::hypot(posIni[0], posIni[1]); const float kTrackingMargin = 0.1; const int kMaxNumberOfDetectors = 20; + if (kMaxNumberOfDetectors < layers.size()) { + LOG(fatal) << "Too many layers in FastTracker, increase kMaxNumberOfDetectors"; + return -1; // too many layers + } + int firstActiveLayer = -1; // first layer that is not inert + for (size_t i = 0; i < layers.size(); ++i) { + if (!layers[i].isInert()) { + firstActiveLayer = i; + break; + } + } + if (firstActiveLayer <= 0) { + LOG(fatal) << "No active layers found in FastTracker, check layer setup"; + return -2; // no active layers + } const int xrhosteps = 100; const bool applyAngularCorrection = true; goodHitProbability.clear(); - for (int i = 0; i < kMaxNumberOfDetectors; ++i) + for (int i = 0; i < kMaxNumberOfDetectors; ++i) { goodHitProbability.push_back(-1.); - goodHitProbability[0] = 1.; + } + goodHitProbability[0] = 1.; // we use layer zero to accumulate // +-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+-~-<*>-~-+ // Outward pass to find intercepts int firstLayerReached = -1; int lastLayerReached = -1; new (&outputTrack)(o2::track::TrackParCov)(inputTrack); - for (uint32_t il = 0; il < layers.size(); il++) { + for (size_t il = 0; il < layers.size(); il++) { // check if layer is doable - if (layers[il].getRadius() < initialRadius) + if (layers[il].getRadius() < initialRadius) { continue; // this layer should not be attempted, but go ahead + } // check if layer is reached float targetX = 1e+3; - bool ok = true; inputTrack.getXatLabR(layers[il].getRadius(), targetX, magneticField); if (targetX > 999.f) { LOGF(debug, "Failed to find intercept for layer %d at radius %.2f cm", il, layers[il].getRadius()); break; // failed to find intercept } - ok = inputTrack.propagateTo(targetX, magneticField); - if (ok && applyMSCorrection && layers[il].getRadiationLength() > 0) { + bool ok = inputTrack.propagateTo(targetX, magneticField); + if (ok && mApplyMSCorrection && layers[il].getRadiationLength() > 0) { ok = inputTrack.correctForMaterial(layers[il].getRadiationLength(), 0, applyAngularCorrection); } - if (ok && applyElossCorrection && layers[il].getDensity() > 0) { // correct in small steps + if (ok && mApplyElossCorrection && layers[il].getDensity() > 0) { // correct in small steps for (int ise = xrhosteps; ise--;) { ok = inputTrack.correctForMaterial(0, -layers[il].getDensity() / xrhosteps, applyAngularCorrection); if (!ok) @@ -361,12 +363,14 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa break; } } - if (std::abs(inputTrack.getZ()) > layers[il].getZ() && applyZacceptance) { + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && mApplyZacceptance) { break; // out of acceptance bounds } if (layers[il].isInert()) { - LOG(info) << "Skipping inert layer: " << layers[il].getName() << " at radius " << layers[il].getRadius() << " cm"; + if (mVerboseLevel > 0) { + LOG(info) << "Skipping inert layer: " << layers[il].getName() << " at radius " << layers[il].getRadius() << " cm"; + } continue; // inert layer, skip } @@ -384,39 +388,19 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa o2::track::TrackParCov inwardTrack(inputTrack); // Enlarge covariance matrix - std::array trPars = {0.}; - for (int ip = 0; ip < 5; ip++) { + std::array trPars = {0.}; + for (int ip = 0; ip < o2::track::kNParams; ip++) { trPars[ip] = outputTrack.getParam(ip); } - std::array largeCov = {0.}; - enum { kY, - kZ, - kSnp, - kTgl, - kPtI }; // track parameter aliases - enum { kY2, - kYZ, - kZ2, - kYSnp, - kZSnp, - kSnp2, - kYTgl, - kZTgl, - kSnpTgl, - kTgl2, - kYPtI, - kZPtI, - kSnpPtI, - kTglPtI, - kPtI2 }; // cov.matrix aliases - const double kLargeErr2Coord = 5 * 5; - const double kLargeErr2Dir = 0.7 * 0.7; - const double kLargeErr2PtI = 30.5 * 30.5; - for (int ic = 15; ic--;) + static constexpr float kLargeErr2Coord = 5 * 5; + 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--;) largeCov[ic] = 0.; - largeCov[kY2] = largeCov[kZ2] = kLargeErr2Coord; - largeCov[kSnp2] = largeCov[kTgl2] = kLargeErr2Dir; - largeCov[kPtI2] = kLargeErr2PtI * trPars[kPtI] * trPars[kPtI]; + 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]; inwardTrack.setCov(largeCov); inwardTrack.checkCovariance(); @@ -434,7 +418,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa continue; // failed to propagate } - if (std::abs(inputTrack.getZ()) > layers[il].getZ() && applyZacceptance) { + if (std::abs(inputTrack.getZ()) > layers[il].getZ() && mApplyZacceptance) { continue; // out of acceptance bounds but continue inwards } @@ -444,10 +428,10 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa std::vector thisHit = {spacePoint[0], spacePoint[1], spacePoint[2]}; // towards adding cluster: move to track alpha - double alpha = inwardTrack.getAlpha(); - double xyz1[3]{ - TMath::Cos(alpha) * spacePoint[0] + TMath::Sin(alpha) * spacePoint[1], - -TMath::Sin(alpha) * spacePoint[0] + TMath::Cos(alpha) * spacePoint[1], + float alpha = inwardTrack.getAlpha(); + float xyz1[3]{ + 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)) continue; @@ -462,7 +446,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa inwardTrack.checkCovariance(); } - if (applyMSCorrection && layers[il].getRadiationLength() > 0) { + if (mApplyMSCorrection && layers[il].getRadiationLength() > 0) { if (!inputTrack.correctForMaterial(layers[il].getRadiationLength(), 0, applyAngularCorrection)) { return -6; } @@ -470,7 +454,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa return -6; } } - if (applyElossCorrection && layers[il].getDensity() > 0) { + if (mApplyElossCorrection && layers[il].getDensity() > 0) { for (int ise = xrhosteps; ise--;) { // correct in small steps if (!inputTrack.correctForMaterial(0, layers[il].getDensity() / xrhosteps, applyAngularCorrection)) { return -7; @@ -488,9 +472,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa hits.push_back(thisHit); - if (applyEffCorrection && !layers[il].isInert()) { // good hit probability calculation - double sigYCmb = o2::math_utils::sqrt(inwardTrack.getSigmaY2() + layers[il].getResolutionRPhi() * layers[il].getResolutionRPhi()); - double sigZCmb = o2::math_utils::sqrt(inwardTrack.getSigmaZ2() + layers[il].getResolutionZ() * layers[il].getResolutionZ()); + 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()); goodHitProbability[il] = ProbGoodChiSqHit(layers[il].getRadius() * 100, sigYCmb * 100, sigZCmb * 100); goodHitProbability[0] *= goodHitProbability[il]; } @@ -498,9 +482,11 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa // backpropagate to original radius float finalX = 1e+3; - inwardTrack.getXatLabR(initialRadius, finalX, magneticField); - if (finalX > 999) + bool inPropStatus = inwardTrack.getXatLabR(initialRadius, finalX, magneticField); + if (finalX > 999) { + LOG(debug) << "Failed to find intercept for initial radius " << initialRadius << " cm, x = " << finalX << " and status " << inPropStatus << " and sn = " << inwardTrack.getSnp() << " r = " << inwardTrack.getY() * inwardTrack.getY(); return -3; // failed to find intercept + } if (!inwardTrack.propagateTo(finalX, magneticField)) { return -4; // failed to propagate @@ -511,17 +497,15 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa return nIntercepts; // generate efficiency - if (applyEffCorrection) { - dNdEtaCent = nch; - float eff = 1.; - for (int i = 0; i < kMaxNumberOfDetectors; i++) { - float iGoodHit = goodHitProbability[i]; - if (iGoodHit <= 0) - continue; - - eff *= iGoodHit; - } + float eff = 1.; + for (int i = 0; i < kMaxNumberOfDetectors; i++) { + float iGoodHit = goodHitProbability[i]; + if (iGoodHit <= 0) + continue; + eff *= iGoodHit; + } + if (mApplyEffCorrection) { if (gRandom->Uniform() > eff) return -8; } @@ -530,11 +514,11 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa outputTrack.checkCovariance(); // Use covariance matrix based smearing - std::array covMat = {0.}; - for (int ii = 0; ii < 15; ii++) + std::array covMat = {0.}; + for (int ii = 0; ii < o2::track::kCovMatSize; ii++) covMat[ii] = outputTrack.getCov()[ii]; TMatrixDSym m(5); - double fcovm[5][5]; + double fcovm[5][5]; // double precision is needed for regularisation for (int ii = 0, k = 0; ii < 5; ++ii) { for (int j = 0; j < ii + 1; ++j, ++k) { @@ -544,7 +528,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } // evaluate ruben's conditional, regularise - bool makePositiveDefinite = (covMatFactor > -1e-5); // apply fix + const bool makePositiveDefinite = (covMatFactor > -1e-5); // apply fix bool rubenConditional = false; for (int ii = 0; ii < 5; ii++) { for (int jj = 0; jj < 5; jj++) { @@ -571,7 +555,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa } if (negEigVal && rubenConditional && makePositiveDefinite) { - if (verboseLevel > 0) { + if (mVerboseLevel > 0) { LOG(info) << "WARNING: this diagonalization (at pt = " << inputTrack.getPt() << ") has negative eigenvalues despite Ruben's fix! Please be careful!"; LOG(info) << "Printing info:"; LOG(info) << "Kalman updates: " << nIntercepts; @@ -585,9 +569,9 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa covMatOK++; // transform parameter vector and smear - double params_[5]; + float params_[5]; for (int ii = 0; ii < 5; ++ii) { - double val = 0.; + float val = 0.; for (int j = 0; j < 5; ++j) val += eigVec[j][ii] * outputTrack.getParam(j); // smear parameters according to eigenvalues @@ -598,7 +582,7 @@ int FastTracker::FastTrack(o2::track::TrackParCov inputTrack, o2::track::TrackPa eigVec.Invert(); // transform back params vector for (int ii = 0; ii < 5; ++ii) { - double val = 0.; + float val = 0.; for (int j = 0; j < 5; ++j) val += eigVec[j][ii] * params_[j]; outputTrack.setParam(val, ii); diff --git a/ALICE3/Core/FastTracker.h b/ALICE3/Core/FastTracker.h index 702caa9e84b..a0dba5d7ec5 100644 --- a/ALICE3/Core/FastTracker.h +++ b/ALICE3/Core/FastTracker.h @@ -12,12 +12,15 @@ #ifndef ALICE3_CORE_FASTTRACKER_H_ #define ALICE3_CORE_FASTTRACKER_H_ -#include // not a system header but megalinter thinks so -#include -#include #include "DetLayer.h" + #include "ReconstructionDataFormats/Track.h" +#include // not a system header but megalinter thinks so + +#include +#include + namespace o2 { namespace fastsim @@ -32,13 +35,16 @@ class FastTracker { public: // Constructor/destructor - FastTracker(); + FastTracker() = default; + // Destructor virtual ~FastTracker() {} // Layer and layer configuration void AddLayer(TString name, float r, float z, float x0, float xrho, float resRPhi = 0.0f, float resZ = 0.0f, float eff = 0.0f, int type = 0); DetLayer GetLayer(const int layer, bool ignoreBarrelLayers = true) const; - int GetLayerIndex(const std::string name) const; + int GetLayerIndex(const std::string& name) const; + size_t GetNLayers() const { return layers.size(); } + bool IsLayerInert(const int layer) const { return layers[layer].isInert(); } void SetRadiationLength(const std::string layerName, float x0) { layers[GetLayerIndex(layerName)].setRadiationLength(x0); } void SetRadius(const std::string layerName, float r) { layers[GetLayerIndex(layerName)].setRadius(r); } void SetResolutionRPhi(const std::string layerName, float resRPhi) { layers[GetLayerIndex(layerName)].setResolutionRPhi(resRPhi); } @@ -80,20 +86,24 @@ class FastTracker void SetIntegrationTime(float t) { integrationTime = t; } void SetMaxRadiusOfSlowDetectors(float r) { maxRadiusSlowDet = r; } void SetAvgRapidity(float y) { avgRapidity = y; } - void SetdNdEtaCent(float d) { dNdEtaCent = d; } + void SetdNdEtaCent(int d) { dNdEtaCent = d; } void SetLhcUPCscale(float s) { lhcUPCScale = s; } void SetBField(float b) { magneticField = b; } void SetMinRadTrack(float r) { fMinRadTrack = r; } void SetMagneticField(float b) { magneticField = b; } - void SetApplyZacceptance(bool b) { applyZacceptance = b; } - void SetApplyMSCorrection(bool b) { applyMSCorrection = b; } - void SetApplyElossCorrection(bool b) { applyElossCorrection = b; } + void SetApplyZacceptance(bool b) { mApplyZacceptance = b; } + void SetApplyMSCorrection(bool b) { mApplyMSCorrection = b; } + void SetApplyElossCorrection(bool b) { mApplyElossCorrection = b; } + void SetApplyEffCorrection(bool b) { mApplyEffCorrection = b; } // Getters for the last track int GetNIntercepts() const { return nIntercepts; } int GetNSiliconPoints() const { return nSiliconPoints; } int GetNGasPoints() const { return nGasPoints; } - float GetGoodHitProb(int layer) const { return goodHitProbability[layer]; } + float GetGoodHitProb(int layer) const + { + return (layer >= 0 && static_cast(layer) < goodHitProbability.size()) ? goodHitProbability[layer] : 0.0f; + } std::size_t GetNHits() const { return hits.size(); } float GetHitX(const int i) const { return hits[i][0]; } float GetHitY(const int i) const { return hits[i][1]; } @@ -106,34 +116,35 @@ class FastTracker std::vector layers; std::vector> hits; // bookkeep last added hits - // operational - bool applyZacceptance; // check z acceptance or not - bool applyMSCorrection; // Apply correction for multiple scattering - bool applyElossCorrection; // Apply correction for eloss (requires MS correction) - bool applyEffCorrection; // Apply correction for hit efficiency - int verboseLevel; // 0: not verbose, >0 more verbose - int crossSectionMinB; - int dNdEtaCent; - int dNdEtaMinB; - float integrationTime; - float magneticField; // in kiloGauss (5 = 0.5T, etc) - float covMatFactor; // covmat off-diagonal factor to use for covmat fix (negative: no factor) - float sigmaD; - float luminosity; - float otherBackground; - float maxRadiusSlowDet; - float avgRapidity; - float lhcUPCScale; - float upcBackgroundMultiplier; - float fMinRadTrack = 132.; - - uint64_t covMatOK; // cov mat has negative eigenvals - uint64_t covMatNotOK; // cov mat has negative eigenvals - - // last track information - int nIntercepts; // found in first outward propagation - int nSiliconPoints; // silicon-based space points added to track - int nGasPoints; // tpc-based space points added to track + /// configuration parameters + bool mApplyZacceptance = false; /// check z acceptance or not + bool mApplyMSCorrection = true; /// Apply correction for multiple scattering + bool mApplyElossCorrection = true; /// Apply correction for eloss (requires MS correction) + bool mApplyEffCorrection = true; /// Apply correction for hit efficiency + int mVerboseLevel = 0; /// 0: not verbose, >0 more verbose + const float mCrossSectionMinB = 8; /// Minimum bias Cross section for event under study (PbPb MinBias ~ 8 Barns) + int dNdEtaCent = 2200; /// dN/deta e.g. at centrality 0-5% (for 5 TeV PbPb) + int dNdEtaMinB = 1; /// dN/deta for minimum bias events + float integrationTime = 0.02f; /// Integration time in ms + float magneticField = 20.f; /// Magnetic field in kiloGauss (5 = 0.5T, 20 = 2T, etc) + float covMatFactor = 0.99f; /// covmat off-diagonal factor to use for covmat fix (negative: no factor) + float sigmaD = 6.0f; /// sigma for the detector resolution in cm + float luminosity = 1.e27f; /// luminosity in cm^-2 s^-1 (e.g. 1.e27 for PbPb at 5 TeV) + float otherBackground = 0.0f; /// background from other sources, e.g. pileup, in [0, 1] + float maxRadiusSlowDet = 10.f; /// maximum radius of slow detectors in cm + float avgRapidity = 0.45f; /// average rapidity for hit density calculation + float lhcUPCScale = 1.0f; /// scale factor for LHC UPC events + float upcBackgroundMultiplier = 1.0f; /// multiplier for UPC background + float fMinRadTrack = 132.f; /// minimum radius for track propagation in cm + + /// counters for covariance matrix statuses + uint64_t covMatOK = 0; /// cov mat has positive eigenvals + uint64_t covMatNotOK = 0; /// cov mat has negative eigenvals + + /// last track information + int nIntercepts = 0; /// found in first outward propagation + int nSiliconPoints = 0; /// silicon-based space points added to track + int nGasPoints = 0; /// tpc-based space points added to track std::vector goodHitProbability; ClassDef(FastTracker, 1); diff --git a/ALICE3/Core/TrackUtilities.cxx b/ALICE3/Core/TrackUtilities.cxx new file mode 100644 index 00000000000..c07fe145ccf --- /dev/null +++ b/ALICE3/Core/TrackUtilities.cxx @@ -0,0 +1,40 @@ +// 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 TrackUtilities.cxx +/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT) +/// \brief Set of utilities for the ALICE3 track handling +/// \since May 21, 2025 +/// + +#include "TrackUtilities.h" + +#include + +void o2::upgrade::convertTLorentzVectorToO2Track(const int charge, + const TLorentzVector particle, + const std::vector productionVertex, + o2::track::TrackParCov& o2track) +{ + std::array params; + std::array covm = {0.}; + float s, c, x; + o2::math_utils::sincos(static_cast(particle.Phi()), s, c); + o2::math_utils::rotateZInv(static_cast(productionVertex[0]), static_cast(productionVertex[1]), x, params[0], s, c); + params[1] = static_cast(productionVertex[2]); + params[2] = 0.; // since alpha = phi + const auto theta = 2. * std::atan(std::exp(-particle.PseudoRapidity())); + params[3] = 1. / std::tan(theta); + params[4] = charge / particle.Pt(); + + // Initialize TrackParCov in-place + new (&o2track)(o2::track::TrackParCov)(x, particle.Phi(), params, covm); +} diff --git a/ALICE3/Core/TrackUtilities.h b/ALICE3/Core/TrackUtilities.h index 3650d500aaf..9bbc00c8f09 100644 --- a/ALICE3/Core/TrackUtilities.h +++ b/ALICE3/Core/TrackUtilities.h @@ -9,23 +9,21 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// -/// \file TrackUtilities.h -/// -/// \brief Set of utilities for the ALICE3 track handling -/// +/// \file TrackUtilities.h +/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT) +/// \brief Set of utilities for the ALICE3 track handling /// \since May 21, 2025 /// #ifndef ALICE3_CORE_TRACKUTILITIES_H_ #define ALICE3_CORE_TRACKUTILITIES_H_ -#include - #include "ReconstructionDataFormats/Track.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/AnalysisHelpers.h" + #include "TLorentzVector.h" +#include + namespace o2::upgrade { @@ -37,22 +35,7 @@ namespace o2::upgrade void convertTLorentzVectorToO2Track(const int charge, const TLorentzVector particle, const std::vector productionVertex, - o2::track::TrackParCov& o2track) -{ - std::array params; - std::array covm = {0.}; - float s, c, x; - o2::math_utils::sincos(static_cast(particle.Phi()), s, c); - o2::math_utils::rotateZInv(static_cast(productionVertex[0]), static_cast(productionVertex[1]), x, params[0], s, c); - params[1] = static_cast(productionVertex[2]); - params[2] = 0.; // since alpha = phi - const auto theta = 2. * std::atan(std::exp(-particle.PseudoRapidity())); - params[3] = 1. / std::tan(theta); - params[4] = charge / particle.Pt(); - - // Initialize TrackParCov in-place - new (&o2track)(o2::track::TrackParCov)(x, particle.Phi(), params, covm); -} + o2::track::TrackParCov& o2track); /// Function to convert a TLorentzVector into a perfect Track /// \param pdgCode particle pdg @@ -60,11 +43,12 @@ void convertTLorentzVectorToO2Track(const int charge, /// \param productionVertex where the particle was produced /// \param o2track the address of the resulting TrackParCov /// \param pdg the pdg service +template void convertTLorentzVectorToO2Track(int pdgCode, TLorentzVector particle, std::vector productionVertex, o2::track::TrackParCov& o2track, - const o2::framework::Service& pdg) + const PdgService& pdg) { const auto pdgInfo = pdg->GetParticle(pdgCode); int charge = 0; @@ -78,10 +62,10 @@ void convertTLorentzVectorToO2Track(int pdgCode, /// \param particle the particle to convert (mcParticle) /// \param o2track the address of the resulting TrackParCov /// \param pdg the pdg service -template +template void convertMCParticleToO2Track(McParticleType& particle, o2::track::TrackParCov& o2track, - const o2::framework::Service& pdg) + const PdgService& pdg) { static TLorentzVector tlv; tlv.SetPxPyPzE(particle.px(), particle.py(), particle.pz(), particle.e()); @@ -92,9 +76,9 @@ void convertMCParticleToO2Track(McParticleType& particle, /// \param particle the particle to convert (mcParticle) /// \param o2track the address of the resulting TrackParCov /// \param pdg the pdg service -template +template o2::track::TrackParCov convertMCParticleToO2Track(McParticleType& particle, - const o2::framework::Service& pdg) + const PdgService& pdg) { o2::track::TrackParCov o2track; convertMCParticleToO2Track(particle, o2track, pdg); diff --git a/ALICE3/DataModel/OTFMcTrackExtra.h b/ALICE3/DataModel/OTFMcTrackExtra.h deleted file mode 100644 index bb75c86746c..00000000000 --- a/ALICE3/DataModel/OTFMcTrackExtra.h +++ /dev/null @@ -1,42 +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 OTFMcTrackExtra.h -/// \author Jesper Karlsson Gumprecht -/// \since 05/08/2024 -/// \brief Table to to hold MC information specifically for xi daughters created in the otf-tracker -/// - -#ifndef ALICE3_DATAMODEL_OTFMCTRACKEXTRA_H_ -#define ALICE3_DATAMODEL_OTFMCTRACKEXTRA_H_ - -// O2 includes -#include "Framework/AnalysisDataModel.h" - -namespace o2::aod -{ -namespace otf_mctrack_extra -{ -DECLARE_SOA_COLUMN(NewPdgCode, newPdgCode, int); //! PDG code (duplicate column but needed for particles created in the otf-tracker) -DECLARE_SOA_COLUMN(IsFromXi, isFromXi, bool); //! From Xi decayed in otf-tracker -DECLARE_SOA_COLUMN(IsFromL0, isFromL0, bool); //! From L0 decayed in otf-tracker -} // namespace otf_mctrack_extra -DECLARE_SOA_TABLE(OTFMcExtra, "AOD", "OTFMcExtra", - otf_mctrack_extra::NewPdgCode, - otf_mctrack_extra::IsFromXi, - otf_mctrack_extra::IsFromL0); - -using OTFMcTrackExtra = OTFMcExtra::iterator; - -} // namespace o2::aod - -#endif // ALICE3_DATAMODEL_OTFMCTRACKEXTRA_H_ diff --git a/ALICE3/DataModel/OTFMulticharm.h b/ALICE3/DataModel/OTFMulticharm.h index c04ad88b4bf..2c3a715f16c 100644 --- a/ALICE3/DataModel/OTFMulticharm.h +++ b/ALICE3/DataModel/OTFMulticharm.h @@ -21,6 +21,8 @@ #define ALICE3_DATAMODEL_OTFMULTICHARM_H_ // O2 includes +#include "ALICE3/DataModel/OTFStrangeness.h" + #include "Framework/AnalysisDataModel.h" namespace o2::aod @@ -36,8 +38,10 @@ DECLARE_SOA_COLUMN(XicMass, xicMass, float); DECLARE_SOA_COLUMN(XiccMass, xiccMass, float); // kine vars -DECLARE_SOA_COLUMN(Pt, pt, float); -DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(XiccPt, xiccPt, float); +DECLARE_SOA_COLUMN(XiccEta, xiccEta, float); +DECLARE_SOA_COLUMN(XicPt, xicPt, float); +DECLARE_SOA_COLUMN(XicEta, xicEta, float); // topo vars DECLARE_SOA_COLUMN(XiDCAz, xiDCAz, float); @@ -49,18 +53,18 @@ DECLARE_SOA_COLUMN(XiccDauDCA, xiccDauDCA, float); DECLARE_SOA_COLUMN(XiccDCAxy, xiccDCAxy, float); DECLARE_SOA_COLUMN(XiccDCAz, xiccDCAz, float); -DECLARE_SOA_COLUMN(PiFromXiDCAxy, piFromXiDCAxy, float); -DECLARE_SOA_COLUMN(PiFromLaDCAxy, piFromLaDCAxy, float); -DECLARE_SOA_COLUMN(PrFromLaDCAxy, prFromLaDCAxy, float); -DECLARE_SOA_COLUMN(PiFromXiDCAz, piFromXiDCAz, float); -DECLARE_SOA_COLUMN(PiFromLaDCAz, piFromLaDCAz, float); -DECLARE_SOA_COLUMN(PrFromLaDCAz, prFromLaDCAz, float); +DECLARE_SOA_COLUMN(BachDCAxy, bachDCAxy, float); +DECLARE_SOA_COLUMN(BachDCAz, bachDCAz, float); +DECLARE_SOA_COLUMN(PosDCAxy, posDCAxy, float); +DECLARE_SOA_COLUMN(PosDCAz, posDCAz, float); +DECLARE_SOA_COLUMN(NegDCAxy, negDCAxy, float); +DECLARE_SOA_COLUMN(NegDCAz, negDCAz, float); DECLARE_SOA_COLUMN(Pi1cDCAxy, pi1cDCAxy, float); -DECLARE_SOA_COLUMN(Pi2cDCAxy, pi2cDCAxy, float); -DECLARE_SOA_COLUMN(PiccDCAxy, piccDCAxy, float); DECLARE_SOA_COLUMN(Pi1cDCAz, pi1cDCAz, float); +DECLARE_SOA_COLUMN(Pi2cDCAxy, pi2cDCAxy, float); DECLARE_SOA_COLUMN(Pi2cDCAz, pi2cDCAz, float); +DECLARE_SOA_COLUMN(PiccDCAxy, piccDCAxy, float); DECLARE_SOA_COLUMN(PiccDCAz, piccDCAz, float); // Lengths @@ -75,14 +79,25 @@ 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); @@ -100,6 +115,7 @@ DECLARE_SOA_COLUMN(PiccPt, piccPt, float); DECLARE_SOA_COLUMN(PiccEta, piccEta, float); } // namespace otfmulticharm + DECLARE_SOA_TABLE(MCharmIndices, "AOD", "MCharmIndices", o2::soa::Index<>, otfmulticharm::CascadeId, @@ -108,32 +124,28 @@ DECLARE_SOA_TABLE(MCharmIndices, "AOD", "MCharmIndices", otfmulticharm::XiCCPionId); DECLARE_SOA_TABLE(MCharmCores, "AOD", "MCharmCores", - otfmulticharm::XicDauDCA, + otfmulticharm::XiccMass, + otfmulticharm::XiccPt, + otfmulticharm::XiccEta, otfmulticharm::XiccDauDCA, + otfmulticharm::XicMass, - otfmulticharm::XiccMass, - otfmulticharm::Pt, - otfmulticharm::Eta, + otfmulticharm::XicPt, + otfmulticharm::XicEta, + otfmulticharm::XicDauDCA, otfmulticharm::XiDCAxy, - otfmulticharm::XicDCAxy, - otfmulticharm::XiccDCAxy, otfmulticharm::XiDCAz, + otfmulticharm::XicDCAxy, otfmulticharm::XicDCAz, + otfmulticharm::XiccDCAxy, otfmulticharm::XiccDCAz, - otfmulticharm::PiFromXiDCAxy, - otfmulticharm::PiFromLaDCAxy, - otfmulticharm::PrFromLaDCAxy, - otfmulticharm::PiFromXiDCAz, - otfmulticharm::PiFromLaDCAz, - otfmulticharm::PrFromLaDCAz, - otfmulticharm::Pi1cDCAxy, - otfmulticharm::Pi2cDCAxy, - otfmulticharm::PiccDCAxy, otfmulticharm::Pi1cDCAz, + otfmulticharm::Pi2cDCAxy, otfmulticharm::Pi2cDCAz, + otfmulticharm::PiccDCAxy, otfmulticharm::PiccDCAz, otfmulticharm::XicDecayRadius2D, @@ -141,38 +153,53 @@ DECLARE_SOA_TABLE(MCharmCores, "AOD", "MCharmCores", otfmulticharm::XicProperLength, otfmulticharm::XicDistanceFromPV, otfmulticharm::XiccProperLength, + otfmulticharm::Pi1cPt, + otfmulticharm::Pi2cPt, + otfmulticharm::PiccPt); +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, + otfmulticharm::BachDCAxy, + otfmulticharm::BachDCAz, otfmulticharm::PosPt, otfmulticharm::PosEta, + otfmulticharm::PosDCAxy, + otfmulticharm::PosDCAz, otfmulticharm::NegPt, otfmulticharm::NegEta, + otfmulticharm::NegDCAxy, + otfmulticharm::NegDCAz, - otfmulticharm::Pi1cPt, otfmulticharm::Pi1cEta, - - otfmulticharm::Pi2cPt, otfmulticharm::Pi2cEta, - - otfmulticharm::PiccPt, otfmulticharm::PiccEta); } // namespace o2::aod diff --git a/ALICE3/DataModel/OTFRICH.h b/ALICE3/DataModel/OTFRICH.h index a81197dae93..d4d9c5257ce 100644 --- a/ALICE3/DataModel/OTFRICH.h +++ b/ALICE3/DataModel/OTFRICH.h @@ -55,6 +55,14 @@ DECLARE_SOA_DYNAMIC_COLUMN(NSigmaRich, nSigmaRich, //! General f } }); +DECLARE_SOA_COLUMN(HasSig, hasSig, bool); //! Has signal in the barrel rich (is particle over threshold) +DECLARE_SOA_COLUMN(HasSigInGas, hasSigInGas, bool); //! Has signal in the gas radiator in the barrel rich (is particle over threshold) +DECLARE_SOA_COLUMN(HasSigEl, hasSigEl, bool); //! Has nSigma electron BarrelRich (is electron over threshold) +DECLARE_SOA_COLUMN(HasSigMu, hasSigMu, bool); //! Has nSigma muon BarrelRich (is muon over threshold) +DECLARE_SOA_COLUMN(HasSigPi, hasSigPi, bool); //! Has nSigma pion BarrelRich (is pion over threshold) +DECLARE_SOA_COLUMN(HasSigKa, hasSigKa, bool); //! Has nSigma kaon BarrelRich (is kaon over threshold) +DECLARE_SOA_COLUMN(HasSigPr, hasSigPr, bool); //! Has nSigma proton BarrelRich (is proton over threshold) + } // namespace upgrade_rich DECLARE_SOA_TABLE(UpgradeRichs, "AOD", "UPGRADERICH", upgrade_rich::NSigmaElectronRich, @@ -70,6 +78,17 @@ DECLARE_SOA_TABLE(UpgradeRichs, "AOD", "UPGRADERICH", using UpgradeRich = UpgradeRichs::iterator; +DECLARE_SOA_TABLE(UpgradeRichSignals, "AOD", "UPGRADERICHSIG", + upgrade_rich::HasSig, + upgrade_rich::HasSigEl, + upgrade_rich::HasSigMu, + upgrade_rich::HasSigPi, + upgrade_rich::HasSigKa, + upgrade_rich::HasSigPr, + upgrade_rich::HasSigInGas); + +using UpgradeRichSignal = UpgradeRichSignals::iterator; + } // namespace o2::aod #endif // ALICE3_DATAMODEL_OTFRICH_H_ diff --git a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx index 82816062390..79279bbc70e 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyRichPid.cxx @@ -30,41 +30,45 @@ /// \since May 22, 2024 /// -#include -#include -#include -#include -#include +#include "TableHelper.h" -#include +#include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFRICH.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsVertexing/HelixHelper.h" +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "ALICE3/Core/TrackUtilities.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "CommonUtils/NameConf.h" -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "CommonConstants/GeomConstants.h" -#include "CommonConstants/PhysicsConstants.h" +#include "ReconstructionDataFormats/PID.h" + #include "TRandom3.h" -#include "TVector3.h" #include "TString.h" -#include "ALICE3/DataModel/OTFRICH.h" -#include "DetectorsVertexing/HelixHelper.h" -#include "TableHelper.h" -#include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "TVector3.h" +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -72,12 +76,13 @@ using namespace o2::constants::math; struct OnTheFlyRichPid { Produces upgradeRich; + Produces upgradeRichSignal; // necessary for particle charges Service pdg; // master setting: magnetic field - Configurable dBz{"dBz", 20, "magnetic field (kilogauss)"}; + Configurable magneticField{"magneticField", 0, "magnetic field (kilogauss) if 0, taken from the tracker task"}; // add rich-specific configurables here Configurable bRichNumberOfSectors{"bRichNumberOfSectors", 21, "barrel RICH number of sectors"}; @@ -100,27 +105,8 @@ struct OnTheFlyRichPid { Configurable flagIncludeTrackAngularRes{"flagIncludeTrackAngularRes", true, "flag to include or exclude track time resolution"}; Configurable multiplicityEtaRange{"multiplicityEtaRange", 0.800000012, "eta range to compute the multiplicity"}; Configurable flagRICHLoadDelphesLUTs{"flagRICHLoadDelphesLUTs", false, "flag to load Delphes LUTs for tracking correction (use recoTrack parameters if false)"}; - /*Configurable bRichRefractiveIndexSector0AndNMinus1{"bRichRefractiveIndexSector0AndMinus1", 1.03, "barrel RICH refractive index sector 0 and N-1"}; - Configurable bRichRefractiveIndexSector1AndNMinus2{"bRichRefractiveIndexSector1AndMinus2", 1.03, "barrel RICH refractive index sector 1 and N-2"}; - Configurable bRichRefractiveIndexSector2AndNMinus3{"bRichRefractiveIndexSector2AndMinus3", 1.03, "barrel RICH refractive index sector 2 and N-3"}; - Configurable bRichRefractiveIndexSector3AndNMinus4{"bRichRefractiveIndexSector3AndMinus4", 1.03, "barrel RICH refractive index sector 3 and N-4"}; - Configurable bRichRefractiveIndexSector4AndNMinus5{"bRichRefractiveIndexSector4AndMinus5", 1.03, "barrel RICH refractive index sector 4 and N-5"}; - Configurable bRichRefractiveIndexSector5AndNMinus6{"bRichRefractiveIndexSector5AndMinus6", 1.03, "barrel RICH refractive index sector 5 and N-6"}; - Configurable bRichRefractiveIndexSector6AndNMinus7{"bRichRefractiveIndexSector6AndMinus7", 1.03, "barrel RICH refractive index sector 6 and N-7"}; - Configurable bRichRefractiveIndexSector7AndNMinus8{"bRichRefractiveIndexSector7AndMinus8", 1.03, "barrel RICH refractive index sector 7 and N-8"}; - Configurable bRichRefractiveIndexSector8AndNMinus9{"bRichRefractiveIndexSector8AndMinus9", 1.03, "barrel RICH refractive index sector 8 and N-9"}; - Configurable bRichRefractiveIndexSector9AndNMinus10{"bRichRefractiveIndexSector9AndMinus10", 1.03, "barrel RICH refractive index sector 9 and N-10"}; - Configurable bRichRefractiveIndexSector10AndNMinus11{"bRichRefractiveIndexSector10AndMinus11", 1.03, "barrel RICH refractive index sector 10 and N-11"}; - Configurable bRichRefractiveIndexSector11AndNMinus12{"bRichRefractiveIndexSector11AndMinus12", 1.03, "barrel RICH refractive index sector 11 and N-12"}; - Configurable bRichRefractiveIndexSector12AndNMinus13{"bRichRefractiveIndexSector12AndMinus13", 1.03, "barrel RICH refractive index sector 12 and N-13"}; - Configurable bRichRefractiveIndexSector13AndNMinus14{"bRichRefractiveIndexSector13AndMinus14", 1.03, "barrel RICH refractive index sector 13 and N-14"}; - Configurable bRichRefractiveIndexSector14AndNMinus15{"bRichRefractiveIndexSector14AndMinus15", 1.03, "barrel RICH refractive index sector 14 and N-15"}; - Configurable bRichRefractiveIndexSector15AndNMinus16{"bRichRefractiveIndexSector15AndMinus16", 1.03, "barrel RICH refractive index sector 15 and N-16"}; - Configurable bRichRefractiveIndexSector16AndNMinus17{"bRichRefractiveIndexSector16AndMinus17", 1.03, "barrel RICH refractive index sector 16 and N-17"}; - Configurable bRichRefractiveIndexSector17AndNMinus18{"bRichRefractiveIndexSector17AndMinus18", 1.03, "barrel RICH refractive index sector 17 and N-18"}; - Configurable bRichRefractiveIndexSector18AndNMinus19{"bRichRefractiveIndexSector18AndMinus19", 1.03, "barrel RICH refractive index sector 18 and N-19"}; - Configurable bRichRefractiveIndexSector19AndNMinus20{"bRichRefractiveIndexSector19AndMinus20", 1.03, "barrel RICH refractive index sector 19 and N-20"}; - Configurable bRichRefractiveIndexSector20AndNMinus21{"bRichRefractiveIndexSector20AndMinus21", 1.03, "barrel RICH refractive index sector 20 and N-21"};*/ + Configurable gasRadiatorRindex{"gasRadiatorRindex", 1.0006f, "gas radiator refractive index"}; + Configurable gasRichRadiatorThickness{"gasRichRadiatorThickness", 25.f, "gas radiator thickness (cm)"}; Configurable bRichRefractiveIndexSector0{"bRichRefractiveIndexSector0", 1.03, "barrel RICH refractive index central(s)"}; // central(s) Configurable bRichRefractiveIndexSector1{"bRichRefractiveIndexSector1", 1.03, "barrel RICH refractive index central(s)-1 and central(s)+1"}; // central(s)-1 and central(s)+1 Configurable bRichRefractiveIndexSector2{"bRichRefractiveIndexSector2", 1.03, "barrel RICH refractive index central(s)-2 and central(s)+2"}; // central(s)-2 and central(s)+2 @@ -165,154 +151,143 @@ struct OnTheFlyRichPid { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; /// Flag unphysical and unavailable values (must be negative) - float error_value = -1000; + static constexpr float kErrorValue = -1000; // Variables projective/hybrid layout - int mNumberSectors = bRichNumberOfSectors; // 21; - float mTileLength = bRichPhotodetectorOtherModuleLength; // 18.4; // [cm] - float mTileLengthCentral = bRichPhotodetectorCentralModuleHalfLength; // 18.4 / 2.0; // [cm] - float mProjectiveLengthInner = mTileLengthCentral; - float mRadiusProjIn = bRichRadiatorInnerRadius; // 85.; // [cm] - float mRadiusProjOut = bRichPhotodetectorOuterRadius; // 112.; // [cm] - std::vector det_centers; - std::vector rad_centers; - std::vector angle_centers; - std::vector theta_min; - std::vector theta_max; + std::vector detCenters; + std::vector radCenters; + std::vector angleCenters; + std::vector thetaMin; + std::vector thetaMax; std::vector bRichRefractiveIndexSector; - std::vector aerogel_rindex; - std::vector photodetrctor_length; - std::vector gap_thickness; + std::vector aerogelRindex; + std::vector photodetrctorLength; + std::vector gapThickness; // Update projective geometry void updateProjectiveParameters() { - mNumberSectors = bRichNumberOfSectors; - mTileLength = bRichPhotodetectorOtherModuleLength; - mTileLengthCentral = bRichPhotodetectorCentralModuleHalfLength; - mProjectiveLengthInner = mTileLengthCentral; - mRadiusProjIn = bRichRadiatorInnerRadius; - mRadiusProjOut = bRichPhotodetectorOuterRadius; - const int number_of_sectors_in_z = mNumberSectors; - det_centers.resize(number_of_sectors_in_z); - rad_centers.resize(number_of_sectors_in_z); - angle_centers.resize(number_of_sectors_in_z); - theta_min.resize(number_of_sectors_in_z); - theta_max.resize(number_of_sectors_in_z); - aerogel_rindex.resize(number_of_sectors_in_z); - photodetrctor_length.resize(number_of_sectors_in_z); - gap_thickness.resize(number_of_sectors_in_z); - float square_size_barrel_cylinder = 2.0 * mTileLengthCentral; - float square_size_z = mTileLength; - float R_min = mRadiusProjIn; - float R_max = mRadiusProjOut; - std::vector theta_bi; - std::vector R0_tilt; - std::vector z0_tilt; - std::vector T_r_plus_g; - std::vector l_aerogel_z; - std::vector l_detector_z; - theta_bi.resize(number_of_sectors_in_z); - R0_tilt.resize(number_of_sectors_in_z); - z0_tilt.resize(number_of_sectors_in_z); - T_r_plus_g.resize(number_of_sectors_in_z); - l_aerogel_z.resize(number_of_sectors_in_z); - l_detector_z.resize(number_of_sectors_in_z); + const int numberOfSectorsInZ = bRichNumberOfSectors; + detCenters.resize(numberOfSectorsInZ); + radCenters.resize(numberOfSectorsInZ); + angleCenters.resize(numberOfSectorsInZ); + thetaMin.resize(numberOfSectorsInZ); + thetaMax.resize(numberOfSectorsInZ); + aerogelRindex.resize(numberOfSectorsInZ); + photodetrctorLength.resize(numberOfSectorsInZ); + gapThickness.resize(numberOfSectorsInZ); + float squareSizeBarrelCylinder = 2.0 * bRichPhotodetectorCentralModuleHalfLength; + float squareSizeZ = bRichPhotodetectorOtherModuleLength; + float rMin = bRichRadiatorInnerRadius; + float rMax = bRichPhotodetectorOuterRadius; + std::vector thetaBi; + std::vector r0Tilt; + std::vector z0Tilt; + std::vector tRPlusG; + std::vector lAerogelZ; + std::vector lDetectorZ; + thetaBi.resize(numberOfSectorsInZ); + r0Tilt.resize(numberOfSectorsInZ); + z0Tilt.resize(numberOfSectorsInZ); + tRPlusG.resize(numberOfSectorsInZ); + lAerogelZ.resize(numberOfSectorsInZ); + lDetectorZ.resize(numberOfSectorsInZ); // Odd number of sectors - if (number_of_sectors_in_z % 2 != 0) { - int i_central_mirror = static_cast((number_of_sectors_in_z) / 2.0); - float m_val = std::tan(0.0); - theta_bi[i_central_mirror] = std::atan(m_val); - R0_tilt[i_central_mirror] = R_max; - z0_tilt[i_central_mirror] = R0_tilt[i_central_mirror] * std::tan(theta_bi[i_central_mirror]); - l_detector_z[i_central_mirror] = square_size_barrel_cylinder; - l_aerogel_z[i_central_mirror] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_barrel_cylinder / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_barrel_cylinder); - T_r_plus_g[i_central_mirror] = R_max - R_min; - float t = std::tan(std::atan(m_val) + std::atan(square_size_barrel_cylinder / (2.0 * R_max * std::sqrt(1.0 + m_val * m_val) - square_size_barrel_cylinder * m_val))); - theta_max[i_central_mirror] = M_PI / 2.0 - std::atan(t); - theta_min[i_central_mirror] = M_PI / 2.0 + std::atan(t); - mProjectiveLengthInner = R_min * t; - aerogel_rindex[i_central_mirror] = bRichRefractiveIndexSector[0]; - for (int i = i_central_mirror + 1; i < number_of_sectors_in_z; i++) { - float par_a = t; - float par_b = 2.0 * R_max / square_size_z; - m_val = (std::sqrt(par_a * par_a * par_b * par_b + par_b * par_b - 1.0) + par_a * par_b * par_b) / (par_b * par_b - 1.0); - theta_min[i] = M_PI / 2.0 - std::atan(t); - theta_max[2 * i_central_mirror - i] = M_PI / 2.0 + std::atan(t); - t = std::tan(std::atan(m_val) + std::atan(square_size_z / (2.0 * R_max * std::sqrt(1.0 + m_val * m_val) - square_size_z * m_val))); - theta_max[i] = M_PI / 2.0 - std::atan(t); - theta_min[2 * i_central_mirror - i] = M_PI / 2.0 + std::atan(t); + static constexpr int kTwo = 2; + if (numberOfSectorsInZ % kTwo != 0) { + int iCentralMirror = static_cast((numberOfSectorsInZ) / 2.0); + float mVal = std::tan(0.0); + thetaBi[iCentralMirror] = std::atan(mVal); + r0Tilt[iCentralMirror] = rMax; + z0Tilt[iCentralMirror] = r0Tilt[iCentralMirror] * std::tan(thetaBi[iCentralMirror]); + lDetectorZ[iCentralMirror] = squareSizeBarrelCylinder; + lAerogelZ[iCentralMirror] = std::sqrt(1.0 + mVal * mVal) * rMin * squareSizeBarrelCylinder / (std::sqrt(1.0 + mVal * mVal) * rMax - mVal * squareSizeBarrelCylinder); + tRPlusG[iCentralMirror] = rMax - rMin; + float t = std::tan(std::atan(mVal) + std::atan(squareSizeBarrelCylinder / (2.0 * rMax * std::sqrt(1.0 + mVal * mVal) - squareSizeBarrelCylinder * mVal))); + thetaMax[iCentralMirror] = o2::constants::math::PIHalf - std::atan(t); + thetaMin[iCentralMirror] = o2::constants::math::PIHalf + std::atan(t); + bRichPhotodetectorCentralModuleHalfLength.value = rMin * t; + aerogelRindex[iCentralMirror] = bRichRefractiveIndexSector[0]; + for (int i = iCentralMirror + 1; i < numberOfSectorsInZ; i++) { + float parA = t; + float parB = 2.0 * rMax / squareSizeZ; + mVal = (std::sqrt(parA * parA * parB * parB + parB * parB - 1.0) + parA * parB * parB) / (parB * parB - 1.0); + thetaMin[i] = o2::constants::math::PIHalf - std::atan(t); + thetaMax[2 * iCentralMirror - i] = o2::constants::math::PIHalf + std::atan(t); + t = std::tan(std::atan(mVal) + std::atan(squareSizeZ / (2.0 * rMax * std::sqrt(1.0 + mVal * mVal) - squareSizeZ * mVal))); + thetaMax[i] = o2::constants::math::PIHalf - std::atan(t); + thetaMin[2 * iCentralMirror - i] = o2::constants::math::PIHalf + std::atan(t); // Forward sectors - theta_bi[i] = std::atan(m_val); - R0_tilt[i] = R_max - square_size_z / 2.0 * std::sin(std::atan(m_val)); - z0_tilt[i] = R0_tilt[i] * std::tan(theta_bi[i]); - l_detector_z[i] = square_size_z; - l_aerogel_z[i] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_z / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_z); - T_r_plus_g[i] = std::sqrt(1.0 + m_val * m_val) * (R_max - R_min) - m_val / 2.0 * (square_size_z + l_aerogel_z[i]); - aerogel_rindex[i] = bRichRefractiveIndexSector[i - i_central_mirror]; + thetaBi[i] = std::atan(mVal); + r0Tilt[i] = rMax - squareSizeZ / 2.0 * std::sin(std::atan(mVal)); + z0Tilt[i] = r0Tilt[i] * std::tan(thetaBi[i]); + lDetectorZ[i] = squareSizeZ; + lAerogelZ[i] = std::sqrt(1.0 + mVal * mVal) * rMin * squareSizeZ / (std::sqrt(1.0 + mVal * mVal) * rMax - mVal * squareSizeZ); + tRPlusG[i] = std::sqrt(1.0 + mVal * mVal) * (rMax - rMin) - mVal / 2.0 * (squareSizeZ + lAerogelZ[i]); + aerogelRindex[i] = bRichRefractiveIndexSector[i - iCentralMirror]; // Backword sectors - theta_bi[2 * i_central_mirror - i] = -std::atan(m_val); - R0_tilt[2 * i_central_mirror - i] = R_max - square_size_z / 2.0 * std::sin(std::atan(m_val)); - z0_tilt[2 * i_central_mirror - i] = -R0_tilt[i] * std::tan(theta_bi[i]); - l_detector_z[2 * i_central_mirror - i] = square_size_z; - l_aerogel_z[2 * i_central_mirror - i] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_z / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_z); - T_r_plus_g[2 * i_central_mirror - i] = std::sqrt(1.0 + m_val * m_val) * (R_max - R_min) - m_val / 2.0 * (square_size_z + l_aerogel_z[i]); - aerogel_rindex[2 * i_central_mirror - i] = bRichRefractiveIndexSector[i - i_central_mirror]; - mProjectiveLengthInner = R_min * t; // <-- At the end of the loop this will be the maximum Z + thetaBi[2 * iCentralMirror - i] = -std::atan(mVal); + r0Tilt[2 * iCentralMirror - i] = rMax - squareSizeZ / 2.0 * std::sin(std::atan(mVal)); + z0Tilt[2 * iCentralMirror - i] = -r0Tilt[i] * std::tan(thetaBi[i]); + lDetectorZ[2 * iCentralMirror - i] = squareSizeZ; + lAerogelZ[2 * iCentralMirror - i] = std::sqrt(1.0 + mVal * mVal) * rMin * squareSizeZ / (std::sqrt(1.0 + mVal * mVal) * rMax - mVal * squareSizeZ); + tRPlusG[2 * iCentralMirror - i] = std::sqrt(1.0 + mVal * mVal) * (rMax - rMin) - mVal / 2.0 * (squareSizeZ + lAerogelZ[i]); + aerogelRindex[2 * iCentralMirror - i] = bRichRefractiveIndexSector[i - iCentralMirror]; + bRichPhotodetectorCentralModuleHalfLength.value = rMin * t; // <-- At the end of the loop this will be the maximum z } } else { // Even number of sectors - float two_half_gap = 1.0; - int i_central_mirror = static_cast((number_of_sectors_in_z) / 2.0); - float m_val = std::tan(0.0); - float t = std::tan(std::atan(m_val) + std::atan(two_half_gap / (2.0 * R_max * std::sqrt(1.0 + m_val * m_val) - two_half_gap * m_val))); - mProjectiveLengthInner = R_min * t; - for (int i = i_central_mirror; i < number_of_sectors_in_z; i++) { - float par_a = t; - float par_b = 2.0 * R_max / square_size_z; - m_val = (std::sqrt(par_a * par_a * par_b * par_b + par_b * par_b - 1.0) + par_a * par_b * par_b) / (par_b * par_b - 1.0); - theta_min[i] = M_PI / 2.0 - std::atan(t); - theta_max[2 * i_central_mirror - i - 1] = M_PI / 2.0 + std::atan(t); - t = std::tan(std::atan(m_val) + std::atan(square_size_z / (2.0 * R_max * std::sqrt(1.0 + m_val * m_val) - square_size_z * m_val))); - theta_max[i] = M_PI / 2.0 - std::atan(t); - theta_min[2 * i_central_mirror - i - 1] = M_PI / 2.0 + std::atan(t); + float twoHalfGap = 1.0; + int iCentralMirror = static_cast((numberOfSectorsInZ) / 2.0); + float mVal = std::tan(0.0); + float t = std::tan(std::atan(mVal) + std::atan(twoHalfGap / (2.0 * rMax * std::sqrt(1.0 + mVal * mVal) - twoHalfGap * mVal))); + bRichPhotodetectorCentralModuleHalfLength.value = rMin * t; + for (int i = iCentralMirror; i < numberOfSectorsInZ; i++) { + float parA = t; + float parB = 2.0 * rMax / squareSizeZ; + mVal = (std::sqrt(parA * parA * parB * parB + parB * parB - 1.0) + parA * parB * parB) / (parB * parB - 1.0); + thetaMin[i] = o2::constants::math::PIHalf - std::atan(t); + thetaMax[2 * iCentralMirror - i - 1] = o2::constants::math::PIHalf + std::atan(t); + t = std::tan(std::atan(mVal) + std::atan(squareSizeZ / (2.0 * rMax * std::sqrt(1.0 + mVal * mVal) - squareSizeZ * mVal))); + thetaMax[i] = o2::constants::math::PIHalf - std::atan(t); + thetaMin[2 * iCentralMirror - i - 1] = o2::constants::math::PIHalf + std::atan(t); // Forward sectors - theta_bi[i] = std::atan(m_val); - R0_tilt[i] = R_max - square_size_z / 2.0 * std::sin(std::atan(m_val)); - z0_tilt[i] = R0_tilt[i] * std::tan(theta_bi[i]); - l_detector_z[i] = square_size_z; - l_aerogel_z[i] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_z / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_z); - T_r_plus_g[i] = std::sqrt(1.0 + m_val * m_val) * (R_max - R_min) - m_val / 2.0 * (square_size_z + l_aerogel_z[i]); - aerogel_rindex[i] = bRichRefractiveIndexSector[i - i_central_mirror]; + thetaBi[i] = std::atan(mVal); + r0Tilt[i] = rMax - squareSizeZ / 2.0 * std::sin(std::atan(mVal)); + z0Tilt[i] = r0Tilt[i] * std::tan(thetaBi[i]); + lDetectorZ[i] = squareSizeZ; + lAerogelZ[i] = std::sqrt(1.0 + mVal * mVal) * rMin * squareSizeZ / (std::sqrt(1.0 + mVal * mVal) * rMax - mVal * squareSizeZ); + tRPlusG[i] = std::sqrt(1.0 + mVal * mVal) * (rMax - rMin) - mVal / 2.0 * (squareSizeZ + lAerogelZ[i]); + aerogelRindex[i] = bRichRefractiveIndexSector[i - iCentralMirror]; // Backword sectors - theta_bi[2 * i_central_mirror - i - 1] = -std::atan(m_val); - R0_tilt[2 * i_central_mirror - i - 1] = R_max - square_size_z / 2.0 * std::sin(std::atan(m_val)); - z0_tilt[2 * i_central_mirror - i - 1] = -R0_tilt[i] * std::tan(theta_bi[i]); - l_detector_z[2 * i_central_mirror - i - 1] = square_size_z; - l_aerogel_z[2 * i_central_mirror - i - 1] = std::sqrt(1.0 + m_val * m_val) * R_min * square_size_z / (std::sqrt(1.0 + m_val * m_val) * R_max - m_val * square_size_z); - T_r_plus_g[2 * i_central_mirror - i - 1] = std::sqrt(1.0 + m_val * m_val) * (R_max - R_min) - m_val / 2.0 * (square_size_z + l_aerogel_z[i]); - aerogel_rindex[2 * i_central_mirror - i - 1] = bRichRefractiveIndexSector[i - i_central_mirror]; - mProjectiveLengthInner = R_min * t; // <-- At the end of the loop this will be the maximum Z + thetaBi[2 * iCentralMirror - i - 1] = -std::atan(mVal); + r0Tilt[2 * iCentralMirror - i - 1] = rMax - squareSizeZ / 2.0 * std::sin(std::atan(mVal)); + z0Tilt[2 * iCentralMirror - i - 1] = -r0Tilt[i] * std::tan(thetaBi[i]); + lDetectorZ[2 * iCentralMirror - i - 1] = squareSizeZ; + lAerogelZ[2 * iCentralMirror - i - 1] = std::sqrt(1.0 + mVal * mVal) * rMin * squareSizeZ / (std::sqrt(1.0 + mVal * mVal) * rMax - mVal * squareSizeZ); + tRPlusG[2 * iCentralMirror - i - 1] = std::sqrt(1.0 + mVal * mVal) * (rMax - rMin) - mVal / 2.0 * (squareSizeZ + lAerogelZ[i]); + aerogelRindex[2 * iCentralMirror - i - 1] = bRichRefractiveIndexSector[i - iCentralMirror]; + bRichPhotodetectorCentralModuleHalfLength.value = rMin * t; // <-- At the end of the loop this will be the maximum z } } // Coordinate radiali layer considerati - std::vector R0_detector; - std::vector R0_aerogel; - R0_detector.resize(number_of_sectors_in_z); - R0_aerogel.resize(number_of_sectors_in_z); - for (int i = 0; i < number_of_sectors_in_z; i++) { - R0_detector[i] = R0_tilt[i]; // + (detector_thickness / 2.0) * std::cos(theta_bi[i]) NEGLIGIBLE - det_centers[i].SetXYZ(R0_detector[i], 0, R0_detector[i] * std::tan(theta_bi[i])); - R0_aerogel[i] = R0_tilt[i] - (T_r_plus_g[i] - bRichRadiatorThickness / 2.0) * std::cos(theta_bi[i]); - rad_centers[i].SetXYZ(R0_aerogel[i], 0, R0_aerogel[i] * std::tan(theta_bi[i])); - angle_centers[i] = theta_bi[i]; - photodetrctor_length[i] = l_detector_z[i]; - gap_thickness[i] = (det_centers[i] - rad_centers[i]).Mag() - bRichRadiatorThickness / 2.0; + std::vector r0Detector; + std::vector r0Aerogel; + r0Detector.resize(numberOfSectorsInZ); + r0Aerogel.resize(numberOfSectorsInZ); + for (int i = 0; i < numberOfSectorsInZ; i++) { + r0Detector[i] = r0Tilt[i]; // + (detector_thickness / 2.0) * std::cos(thetaBi[i]) NEGLIGIBLE + detCenters[i].SetXYZ(r0Detector[i], 0, r0Detector[i] * std::tan(thetaBi[i])); + r0Aerogel[i] = r0Tilt[i] - (tRPlusG[i] - bRichRadiatorThickness / 2.0) * std::cos(thetaBi[i]); + radCenters[i].SetXYZ(r0Aerogel[i], 0, r0Aerogel[i] * std::tan(thetaBi[i])); + angleCenters[i] = thetaBi[i]; + photodetrctorLength[i] = lDetectorZ[i]; + gapThickness[i] = (detCenters[i] - radCenters[i]).Mag() - bRichRadiatorThickness / 2.0; } // DEBUG // std::cout << std::endl << std::endl; - // for (int i = 0; i < number_of_sectors_in_z; i++) { - // std::cout << "Sector " << i << ": Gap = " << gap_thickness[i] << " cm, Index aerogel = " << aerogel_rindex[i] << ", Gap thickness = " << gap_thickness[i] << " cm" << std::endl; + // for (int i = 0; i < numberOfSectorsInZ; i++) { + // std::cout << "Sector " << i << ": Gap = " << gapThickness[i] << " cm, Index aerogel = " << aerogelRindex[i] << ", Gap thickness = " << gapThickness[i] << " cm" << std::endl; // } // std::cout << std::endl << std::endl; } @@ -321,6 +296,14 @@ struct OnTheFlyRichPid { { pRandomNumberGenerator.SetSeed(0); // fully randomize + if (magneticField.value < o2::constants::math::Epsilon) { + LOG(info) << "Getting the magnetic field from the on-the-fly tracker task"; + if (!getTaskOptionValue(initContext, "on-the-fly-tracker", magneticField, false)) { + LOG(fatal) << "Could not get Bz from on-the-fly-tracker task"; + } + LOG(info) << "Bz = " << magneticField.value << " T"; + } + // Check if inheriting the LUT configuration auto configLutPath = [&](Configurable& lut) { if (lut.value != "inherit") { @@ -376,25 +359,26 @@ struct OnTheFlyRichPid { histos.add("h2dAngularResolutionVsEtaBarrelRICH", "h2dAngularResolutionVsEtaBarrelRICH", kTH2F, {axisEta, axisRingAngularResolution}); histos.add("hSectorID", "hSectorID", kTH1F, {axisSector}); - std::string particle_names1[5] = {"#it{e}", "#it{#mu}", "#it{#pi}", "#it{K}", "#it{p}"}; - std::string particle_names2[5] = {"Elec", "Muon", "Pion", "Kaon", "Prot"}; - for (int i_true = 0; i_true < 5; i_true++) { - std::string name_title_barrel_track_res = "h2dBarrelAngularResTrack" + particle_names2[i_true] + "VsP"; - std::string name_title_barrel_total_res = "h2dBarrelAngularResTotal" + particle_names2[i_true] + "VsP"; - const AxisSpec axisTrackAngularRes{static_cast(nBinsAngularRes), 0.0f, +5.0f, "Track angular resolution - " + particle_names1[i_true] + " (mrad)"}; - const AxisSpec axisTotalAngularRes{static_cast(nBinsAngularRes), 0.0f, +5.0f, "Total angular resolution - " + particle_names1[i_true] + " (mrad)"}; - histos.add(name_title_barrel_track_res.c_str(), name_title_barrel_track_res.c_str(), kTH2F, {axisMomentum, axisTrackAngularRes}); - histos.add(name_title_barrel_total_res.c_str(), name_title_barrel_total_res.c_str(), kTH2F, {axisMomentum, axisTotalAngularRes}); + const int kNspec = 5; // electron, muon, pion, kaon, proton + std::string particleNames1[kNspec] = {"#it{e}", "#it{#mu}", "#it{#pi}", "#it{K}", "#it{p}"}; + std::string particleNames2[kNspec] = {"Elec", "Muon", "Pion", "Kaon", "Prot"}; + for (int iTrue = 0; iTrue < kNspec; iTrue++) { + std::string nameTitleBarrelTrackRes = "h2dBarrelAngularResTrack" + particleNames2[iTrue] + "VsP"; + std::string nameTitleBarrelTotalRes = "h2dBarrelAngularResTotal" + particleNames2[iTrue] + "VsP"; + const AxisSpec axisTrackAngularRes{static_cast(nBinsAngularRes), 0.0f, +5.0f, "Track angular resolution - " + particleNames1[iTrue] + " (mrad)"}; + const AxisSpec axisTotalAngularRes{static_cast(nBinsAngularRes), 0.0f, +5.0f, "Total angular resolution - " + particleNames1[iTrue] + " (mrad)"}; + histos.add(nameTitleBarrelTrackRes.c_str(), nameTitleBarrelTrackRes.c_str(), kTH2F, {axisMomentum, axisTrackAngularRes}); + histos.add(nameTitleBarrelTotalRes.c_str(), nameTitleBarrelTotalRes.c_str(), kTH2F, {axisMomentum, axisTotalAngularRes}); } - for (int i_true = 0; i_true < 5; i_true++) { - for (int i_hyp = 0; i_hyp < 5; i_hyp++) { - std::string name_title = "h2dBarrelNsigmaTrue" + particle_names2[i_true] + "Vs" + particle_names2[i_hyp] + "Hypothesis"; - if (i_true == i_hyp) { - const AxisSpec axisNsigmaCorrect{static_cast(nBinsNsigmaCorrectSpecies), -10.0f, +10.0f, "N#sigma - True " + particle_names1[i_true] + " vs " + particle_names1[i_hyp] + " hypothesis"}; - histos.add(name_title.c_str(), name_title.c_str(), kTH2F, {axisMomentum, axisNsigmaCorrect}); + for (int iTrue = 0; iTrue < kNspec; iTrue++) { + for (int iHyp = 0; iHyp < kNspec; iHyp++) { + std::string nameTitle = "h2dBarrelNsigmaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis"; + if (iTrue == iHyp) { + const AxisSpec axisNsigmaCorrect{static_cast(nBinsNsigmaCorrectSpecies), -10.0f, +10.0f, "N#sigma - True " + particleNames1[iTrue] + " vs " + particleNames1[iHyp] + " hypothesis"}; + histos.add(nameTitle.c_str(), nameTitle.c_str(), kTH2F, {axisMomentum, axisNsigmaCorrect}); } else { - const AxisSpec axisNsigmaWrong{static_cast(nBinsNsigmaWrongSpecies), -10.0f, +10.0f, "N#sigma - True " + particle_names1[i_true] + " vs " + particle_names1[i_hyp] + " hypothesis"}; - histos.add(name_title.c_str(), name_title.c_str(), kTH2F, {axisMomentum, axisNsigmaWrong}); + const AxisSpec axisNsigmaWrong{static_cast(nBinsNsigmaWrongSpecies), -10.0f, +10.0f, "N#sigma - True " + particleNames1[iTrue] + " vs " + particleNames1[iHyp] + " hypothesis"}; + histos.add(nameTitle.c_str(), nameTitle.c_str(), kTH2F, {axisMomentum, axisNsigmaWrong}); } } } @@ -451,7 +435,7 @@ struct OnTheFlyRichPid { /// \param track the input track /// \param radius the radius of the layer you're calculating the length to /// \param magneticField the magnetic field to use when propagating - bool checkMagfieldLimit(o2::track::TrackParCov track, float radius, float magneticField) + bool checkMagfieldLimit(o2::track::TrackParCov track, const float radius, const float magneticField) { o2::math_utils::CircleXYf_t trcCircle; float sna, csa; @@ -470,12 +454,12 @@ struct OnTheFlyRichPid { /// returns sector hit by the track (if any), -1 otherwise /// \param eta the pseudorapidity of the tarck (assuming primary vertex at origin) - int findSector(float eta) + int findSector(const float eta) { float polar = 2.0 * std::atan(std::exp(-eta)); - for (int j_sec = 0; j_sec < mNumberSectors; j_sec++) { - if (polar > theta_max[j_sec] && polar < theta_min[j_sec]) { - return j_sec; + for (int jSector = 0; jSector < bRichNumberOfSectors; jSector++) { + if (polar > thetaMax[jSector] && polar < thetaMin[jSector]) { + return jSector; } } return -1; @@ -483,16 +467,18 @@ struct OnTheFlyRichPid { /// returns radiator radius in cm at considered eta (accounting for sector inclination) /// \param eta the pseudorapidity of the tarck (assuming primary vertex at origin) - /// \param i_sector the index of the track RICH sector - float radiusRipple(float eta, int i_sector) + /// \param iSecor the index of the track RICH sector + float radiusRipple(const float eta, const int iSecor) { - float polar = 2.0 * std::atan(std::exp(-eta)); - if (i_sector > 0) { - float R_sec_rich = rad_centers[i_sector].X(); - float z_sec_rich = rad_centers[i_sector].Z(); - return (std::pow(R_sec_rich, 2) + std::pow(z_sec_rich, 2)) / (R_sec_rich + z_sec_rich / std::tan(polar)); + if (iSecor > 0) { + const float polar = 2.0 * std::atan(std::exp(-eta)); + const float rSecRich = radCenters[iSecor].X(); + const float zSecRich = radCenters[iSecor].Z(); + const float rSecRichSquared = rSecRich * rSecRich; + const float zSecRichSquared = zSecRich * zSecRich; + return (rSecRichSquared + zSecRichSquared) / (rSecRich + zSecRich / std::tan(polar)); } else { - return error_value; + return kErrorValue; } } @@ -500,25 +486,41 @@ struct OnTheFlyRichPid { /// \param momentum the momentum of the tarck /// \param mass the mass of the particle /// \param n the refractive index of the considered sector - float CherenkovAngle(float momentum, float mass, float n) + /// \param angle the output angle (passed by reference) + /// \return true if particle is above the threshold and enough photons, false otherwise + bool cherenkovAngle(const float momentum, const float mass, const float n, float& angle) { - // Check if particle is above the threshold - if (momentum > mass / std::sqrt(n * n - 1.0)) { + if (momentum > mass / std::sqrt(n * n - 1.0)) { // Check if particle is above the threshold // Calculate angle - float angle = std::acos(std::sqrt(momentum * momentum + mass * mass) / (momentum * n)); + angle = std::acos(std::sqrt(momentum * momentum + mass * mass) / (momentum * n)); // Mean number of detected photons (SiPM PDE is accountd in multiplicative factor!!!) - float meanNumberofDetectedPhotons = 230. * std::sin(angle) * std::sin(angle) * bRichRadiatorThickness; + const float meanNumberofDetectedPhotons = 230. * std::sin(angle) * std::sin(angle) * bRichRadiatorThickness; // Require at least 3 photons on average for real angle reconstruction - if (meanNumberofDetectedPhotons > 3.) { - return angle; - } else { - return error_value; + static constexpr float kMinPhotons = 3.f; + if (meanNumberofDetectedPhotons > kMinPhotons) { + return true; // Particle is above the threshold and enough photons } - } else { - return error_value; + return false; // Particle is above the threshold, but not enough photons + } + return false; // Particle is below the threshold + } + + bool isOverTrhesholdInGasRadiator(const float momentum, const float mass) + { + if (momentum < mass / std::sqrt(gasRadiatorRindex * gasRadiatorRindex - 1.0)) { // Check if particle is above the threshold + return false; + } + const float angle = std::acos(std::sqrt(momentum * momentum + mass * mass) / (momentum * gasRadiatorRindex)); + const float meanNumberofDetectedPhotons = 230. * std::sin(angle) * std::sin(angle) * gasRichRadiatorThickness; + + // Require at least 3 photons on average for real angle reconstruction + static constexpr float kMinPhotons = 3.f; + if (meanNumberofDetectedPhotons <= kMinPhotons) { + return false; } + return true; } /// returns linear interpolation @@ -535,64 +537,66 @@ struct OnTheFlyRichPid { /// returns angular resolution for considered track eta /// \param eta the pseudorapidity of the tarck (assuming primary vertex at origin) - float AngularResolution(float eta) + float angularResolution(float eta) { // Vectors for sampling (USE ANALYTICAL EXTRAPOLATION FOR BETTER RESULTS) - float eta_sampling[] = {-2.000000, -1.909740, -1.731184, -1.552999, -1.375325, -1.198342, -1.022276, -0.847390, -0.673976, -0.502324, -0.332683, -0.165221, 0.000000, 0.165221, 0.332683, 0.502324, 0.673976, 0.847390, 1.022276, 1.198342, 1.375325, 1.552999, 1.731184, 1.909740, 2.000000}; - float res_ring_sampling_with_abs_walls[] = {0.0009165, 0.000977, 0.001098, 0.001198, 0.001301, 0.001370, 0.001465, 0.001492, 0.001498, 0.001480, 0.001406, 0.001315, 0.001241, 0.001325, 0.001424, 0.001474, 0.001480, 0.001487, 0.001484, 0.001404, 0.001273, 0.001197, 0.001062, 0.000965, 0.0009165}; - float res_ring_sampling_without_abs_walls[] = {0.0009165, 0.000977, 0.001095, 0.001198, 0.001300, 0.001369, 0.001468, 0.001523, 0.001501, 0.001426, 0.001299, 0.001167, 0.001092, 0.001179, 0.001308, 0.001407, 0.001491, 0.001508, 0.001488, 0.001404, 0.001273, 0.001196, 0.001061, 0.000965, 0.0009165}; - int size_res_vector = sizeof(eta_sampling) / sizeof(eta_sampling[0]); + static constexpr float kEtaSampling[] = {-2.000000, -1.909740, -1.731184, -1.552999, -1.375325, -1.198342, -1.022276, -0.847390, -0.673976, -0.502324, -0.332683, -0.165221, 0.000000, 0.165221, 0.332683, 0.502324, 0.673976, 0.847390, 1.022276, 1.198342, 1.375325, 1.552999, 1.731184, 1.909740, 2.000000}; + static constexpr float kResRingSamplingWithAbsWalls[] = {0.0009165, 0.000977, 0.001098, 0.001198, 0.001301, 0.001370, 0.001465, 0.001492, 0.001498, 0.001480, 0.001406, 0.001315, 0.001241, 0.001325, 0.001424, 0.001474, 0.001480, 0.001487, 0.001484, 0.001404, 0.001273, 0.001197, 0.001062, 0.000965, 0.0009165}; + static constexpr float kResRingSamplingWithoutAbsWalls[] = {0.0009165, 0.000977, 0.001095, 0.001198, 0.001300, 0.001369, 0.001468, 0.001523, 0.001501, 0.001426, 0.001299, 0.001167, 0.001092, 0.001179, 0.001308, 0.001407, 0.001491, 0.001508, 0.001488, 0.001404, 0.001273, 0.001196, 0.001061, 0.000965, 0.0009165}; + static constexpr int kSizeResVector = sizeof(kEtaSampling) / sizeof(kEtaSampling[0]); // Use binary search to find the lower and upper indices - int lowerIndex = std::lower_bound(eta_sampling, eta_sampling + size_res_vector, eta) - eta_sampling - 1; - int upperIndex = lowerIndex + 1; - if (lowerIndex >= 0 && upperIndex < size_res_vector) { + const int lowerIndex = std::lower_bound(kEtaSampling, kEtaSampling + kSizeResVector, eta) - kEtaSampling - 1; + const int upperIndex = lowerIndex + 1; + if (lowerIndex >= 0 && upperIndex < kSizeResVector) { // Resolution interpolation if (bRichFlagAbsorbingWalls) { - float interpolatedResRing = interpolate(eta, eta_sampling[lowerIndex], eta_sampling[upperIndex], res_ring_sampling_with_abs_walls[lowerIndex], res_ring_sampling_with_abs_walls[upperIndex]); + float interpolatedResRing = interpolate(eta, kEtaSampling[lowerIndex], kEtaSampling[upperIndex], kResRingSamplingWithAbsWalls[lowerIndex], kResRingSamplingWithAbsWalls[upperIndex]); // std::cout << "Interpolated y value: " << interpolatedY << std::endl; return interpolatedResRing; } else { - float interpolatedResRing = interpolate(eta, eta_sampling[lowerIndex], eta_sampling[upperIndex], res_ring_sampling_without_abs_walls[lowerIndex], res_ring_sampling_without_abs_walls[upperIndex]); + float interpolatedResRing = interpolate(eta, kEtaSampling[lowerIndex], kEtaSampling[upperIndex], kResRingSamplingWithoutAbsWalls[lowerIndex], kResRingSamplingWithoutAbsWalls[upperIndex]); // std::cout << "Interpolated y value: " << interpolatedY << std::endl; return interpolatedResRing; } } else { // std::cout << "Unable to interpolate. Target x value is outside the range of available data." << std::endl; - return error_value; + return kErrorValue; } } /// To account border effects in bRICH /// Approximation for analytic calculation: track along projective sector normal (reasonable) /// \param eta the pseudorapidity of the tarck (assuming primary vertex at origin) - /// \param tile_z_length the Z-length of the photodetector plane of the considered sector + /// \param tileZlength the Z-length of the photodetector plane of the considered sector /// \param radius the nominal radius of the Cherenkov ring - float fractionPhotonsProjectiveRICH(float eta, float tile_z_length, float radius) + float fractionPhotonsProjectiveRICH(float eta, float tileZlength, float radius) { - float polar = 2.0 * std::atan(std::exp(-eta)); - int i_sector = 0; - bool flag_sector = false; - for (int j_sec = 0; j_sec < mNumberSectors; j_sec++) { - if (polar > theta_max[j_sec] && polar < theta_min[j_sec]) { - flag_sector = true; - i_sector = j_sec; + const float polar = 2.0 * std::atan(std::exp(-eta)); + int iSecor = 0; + bool flagSector = false; + for (int jSector = 0; jSector < bRichNumberOfSectors; jSector++) { + if (polar > thetaMax[jSector] && polar < thetaMin[jSector]) { + flagSector = true; + iSecor = jSector; } } - if (flag_sector == false) { - return error_value; // <-- Returning negative value + if (flagSector == false) { + return kErrorValue; // <-- Returning negative value } - float R_sec_rich = rad_centers[i_sector].X(); - float z_sec_rich = rad_centers[i_sector].Z(); - // float R_sec_tof = det_centers[i_sector].X(); - // float z_sec_tof = det_centers[i_sector].Z(); - float radius_ripple = (std::pow(R_sec_rich, 2) + std::pow(z_sec_rich, 2)) / (R_sec_rich + z_sec_rich / std::tan(polar)); - float z_ripple = radius_ripple / std::tan(polar); - float absZ = std::hypot(radius_ripple - R_sec_rich, z_ripple - z_sec_rich); + float rSecRich = radCenters[iSecor].X(); + float zSecRich = radCenters[iSecor].Z(); + // float rSecTof = detCenters[iSecor].X(); + // float zSecTof = detCenters[iSecor].Z(); + const float rSecRichSquared = rSecRich * rSecRich; + const float zSecRichSquared = zSecRich * zSecRich; + const float radiusRipple = (rSecRichSquared + zSecRichSquared) / (rSecRich + zSecRich / std::tan(polar)); + const float zRipple = radiusRipple / std::tan(polar); + const float absZ = std::hypot(radiusRipple - rSecRich, zRipple - zSecRich); float fraction = 1.; - if (tile_z_length / 2. - absZ < radius) { - fraction = fraction - (1. / M_PI) * std::acos((tile_z_length / 2. - absZ) / radius); - if (tile_z_length / 2. + absZ < radius) { - fraction = fraction - (1. / M_PI) * std::acos((tile_z_length / 2. + absZ) / radius); + if (tileZlength / 2. - absZ < radius) { + fraction = fraction - (1. / o2::constants::math::PI) * std::acos((tileZlength / 2. - absZ) / radius); + if (tileZlength / 2. + absZ < radius) { + fraction = fraction - (1. / o2::constants::math::PI) * std::acos((tileZlength / 2. + absZ) / radius); } } return fraction; @@ -601,114 +605,124 @@ struct OnTheFlyRichPid { /// returns refined ring angular resolution /// \param eta the pseudorapidity of the tarck (assuming primary vertex at origin) /// \param n the refractive index of the considered sector - /// \param n_g the refractive index of the gas filling the RICH proximity gap - /// \param T_r the radiator thickness in cm - /// \param T_g the proximity gap thickness of the considered sector in cm - /// \param pixel_size the SiPM pixel size in cm - /// \param theta_c the Cherenkov angle for the considered track - /// \param tile_z_length the Z-length of the photodetector plane of the considered sector - float extract_ring_angular_resolution(float eta, float n, float n_g, float T_r, float T_g, float pixel_size, float theta_c, float tile_z_length) + /// \param nGas the refractive index of the gas filling the RICH proximity gap + /// \param thicknessRad the radiator thickness in cm + /// \param thicknessGas the proximity gap thickness of the considered sector in cm + /// \param pixelSize the SiPM pixel size in cm + /// \param thetaCherenkov the Cherenkov angle for the considered track + /// \param tileZlength the Z-length of the photodetector plane of the considered sector + float extractRingAngularResolution(const float eta, const float n, const float nGas, const float thicknessRad, const float thicknessGas, const float pixelSize, const float thetaCherenkov, const float tileZlength) { // Check if input angle is error value - if (theta_c <= error_value + 1) - return error_value; + if (thetaCherenkov <= kErrorValue + 1) + return kErrorValue; // Parametrization variables (notation from https://doi.org/10.1016/0168-9002(94)90532-0) - float phi_c = 0.; - float theta_p = 0.; - float sin_theta_c = std::sin(theta_c); - float cos_theta_c = std::cos(theta_c); - float x_p = std::sin(theta_p); - float z_p = std::cos(theta_p); - float sin_phi = std::sin(phi_c); - float cos_phi = std::cos(phi_c); - // float ze = T_r / (2. * z_p); - float az = z_p * cos_theta_c - x_p * sin_theta_c * cos_phi; - float e3z = std::sqrt(az * az + (n_g / n) * (n_g / n) - 1.); - float Z = T_g; - float alpha = e3z / az; - float etac = e3z * n * n; - float k = T_r / (2. * Z); - float m = 1. / (n * n); - float lambda = (1. + k * alpha * alpha * alpha) / (1. + k * alpha); - // Derivative d(theta_c)/dx - float temp1 = etac / Z; - float temp2 = alpha * e3z * cos_phi; - float temp3 = x_p * sin_theta_c * sin_phi * sin_phi; - float d_theta_x = temp1 * (temp2 - temp3); - // Derivative d(theta_c)/dy - float temp4 = etac * sin_phi / Z; - float temp5 = cos_theta_c - z_p * (1 - m) / az; - float d_theta_y = temp4 * temp5; - // Derivative d(theta_c)/dze - float temp8 = etac * sin_theta_c; - float temp9 = Z * (1.0 + k * alpha * alpha * alpha * n * n); - float temp10 = alpha * alpha * (1.0 - x_p * x_p * sin_phi * sin_phi) + lambda * x_p * x_p * sin_phi * sin_phi; - float d_theta_ze = temp8 * temp10 / temp9; - // Derivative d(theta_c)/dn - float d_theta_n = z_p / (n * az * sin_theta_c); + const float phiC = 0.; + const float thetaP = 0.; + const float sinThetaCherenkov = std::sin(thetaCherenkov); + const float cosThetaCherenkov = std::cos(thetaCherenkov); + const float xP = std::sin(thetaP); + const float zP = std::cos(thetaP); + const float sinPhi = std::sin(phiC); + const float cosPhi = std::cos(phiC); + // const float ze = thicknessRad / (2. * zP); + const float aZ = zP * cosThetaCherenkov - xP * sinThetaCherenkov * cosPhi; + const float e3z = std::sqrt(aZ * aZ + (nGas / n) * (nGas / n) - 1.); + const float z = thicknessGas; + const float alpha = e3z / aZ; + const float etac = e3z * n * n; + const float k = thicknessRad / (2. * z); + const float m = 1. / (n * n); + const float lambda = (1. + k * alpha * alpha * alpha) / (1. + k * alpha); + // Derivative d(thetaCherenkov)/dx + const float temp1 = etac / z; + const float temp2 = alpha * e3z * cosPhi; + const float temp3 = xP * sinThetaCherenkov * sinPhi * sinPhi; + const float dThetaX = temp1 * (temp2 - temp3); + // Derivative d(thetaCherenkov)/dy + const float temp4 = etac * sinPhi / z; + const float temp5 = cosThetaCherenkov - zP * (1 - m) / aZ; + const float dThetaY = temp4 * temp5; + // Derivative d(thetaCherenkov)/dze + const float temp8 = etac * sinThetaCherenkov; + const float temp9 = z * (1.0 + k * alpha * alpha * alpha * n * n); + const float temp10 = alpha * alpha * (1.0 - xP * xP * sinPhi * sinPhi) + lambda * xP * xP * sinPhi * sinPhi; + const float dThetaZe = temp8 * temp10 / temp9; + // Derivative d(thetaCherenkov)/dn + const float dThetaN = zP / (n * aZ * sinThetaCherenkov); // RMS wavelength (using Sellmeier formula with measured aerogel parameters) - float a0 = 0.0616; - float w0 = 56.5; - float n0 = 1.0307; - float w_mean = 436.0; // 450.0;//484.9;//426.0; //450;//485;//450; // nm //450 426 493.5 // 426.0 - float scaling = n / n0; - float temp11 = a0 * w0 * w0 * w_mean; - float temp12 = std::pow(w_mean * w_mean - w0 * w0, 1.5); - float temp13 = std::sqrt(w_mean * w_mean * (1.0 + a0) - w0 * w0); - float d_n_w = temp11 / (temp12 * temp13) * scaling; - float sigma_w = 115.0; + const float a0 = 0.0616; + const float w0 = 56.5; + const float n0 = 1.0307; + const float wMean = 436.0; // 450.0;//484.9;//426.0; //450;//485;//450; // nm //450 426 493.5 // 426.0 + const float scaling = n / n0; + const float temp11 = a0 * w0 * w0 * wMean; + const float temp12 = std::pow(wMean * wMean - w0 * w0, 1.5); + const float temp13 = std::sqrt(wMean * wMean * (1.0 + a0) - w0 * w0); + const float dNw = temp11 / (temp12 * temp13) * scaling; + const float sigmaW = 115.0; // RMS x y - float sigma_theta_x = pixel_size / std::sqrt(12.0); - float sigma_theta_y = pixel_size / std::sqrt(12.0); + const float sigmaThetaX = pixelSize / std::sqrt(12.0); + const float sigmaThetaY = pixelSize / std::sqrt(12.0); // RMS emission point - float sigma_theta_ze = T_r / (z_p * std::sqrt(12.0)); + const float sigmaThetaZe = thicknessRad / (zP * std::sqrt(12.0)); // Single photon angular resolution - float res_x = d_theta_x * sigma_theta_x; - float res_y = d_theta_y * sigma_theta_y; - float res_ze = d_theta_ze * sigma_theta_ze; - float res_n = d_theta_n * d_n_w * sigma_w; - float single_photon_angular_resolution = std::sqrt(std::pow(res_x, 2) + std::pow(res_y, 2) + std::pow(res_ze, 2) + std::pow(res_n, 2)); + const float resX = dThetaX * sigmaThetaX; + const float resY = dThetaY * sigmaThetaY; + const float resZe = dThetaZe * sigmaThetaZe; + const float resN = dThetaN * dNw * sigmaW; + const float resXsquared = resX * resX; + const float resYsquared = resY * resY; + const float resZesquared = resZe * resZe; + const float resNsquared = resN * resN; + const float singlePhotonAngularResolution = std::sqrt(resXsquared + resYsquared + resZesquared + resNsquared); // Fraction of photons in rings (to account loss close to sector boundary in projective geometry) - float radius = (T_r / 2.0) * std::tan(theta_c) + T_g * std::tan(std::asin((n / n_g) * std::sin(theta_c))); - float N0 = 24. * T_r / 2.; // photons for N = 1.03 at saturation ( 24/2 factor per radiator cm ) - float multiplicity_spectrum_factor = std::pow(std::sin(theta_c), 2.) / std::pow(std::sin(std::acos(1. / 1.03)), 2.); // scale multiplicity w.r.t. N = 1.03 at saturation + const float sinThetaCherenkovSquared = sinThetaCherenkov * sinThetaCherenkov; + const float radius = (thicknessRad / 2.0) * std::tan(thetaCherenkov) + thicknessGas * std::tan(std::asin((n / nGas) * sinThetaCherenkov)); + const float n0Photons = 24. * thicknessRad / 2.; // photons for N = 1.03 at saturation ( 24/2 factor per radiator cm ) + const float sinAngle = std::sin(std::acos(1. / 1.03)); + const float sinAngleSquared = sinAngle * sinAngle; + const float multiplicitySpectrumFactor = sinThetaCherenkovSquared / sinAngleSquared; // scale multiplicity w.r.t. N = 1.03 at saturation // Considering average resolution (integrated over the sector) - // float n_photons = (tile_z_length / 2.0 > radius) ? N0 * multiplicity_spectrum_factor * (1.-(2.0*radius)/(M_PI*tile_z_length)) : N0 * multiplicity_spectrum_factor * (1.-(2.0*radius)/(M_PI*tile_z_length) - (2.0/(tile_z_length*M_PI))*(-(tile_z_length/(2.0))*std::acos(tile_z_length/(2.0*radius)) + radius*std::sqrt(1.-std::pow(tile_z_length/(2.0*radius),2.0)))); + // float nPhotons = (tileZlength / 2.0 > radius) ? n0Photons * multiplicitySpectrumFactor * (1.-(2.0*radius)/(o2::constants::math::PI*tileZlength)) : n0Photons * multiplicitySpectrumFactor * (1.-(2.0*radius)/(o2::constants::math::PI*tileZlength) - (2.0/(tileZlength*o2::constants::math::PI))*(-(tileZlength/(2.0))*std::acos(tileZlength/(2.0*radius)) + radius*std::sqrt(1.-std::pow(tileZlength/(2.0*radius),2.0)))); // Considering "exact" resolution (eta by eta) - float n_photons = N0 * multiplicity_spectrum_factor * fractionPhotonsProjectiveRICH(eta, tile_z_length, radius); - if (n_photons <= error_value + 1) - return error_value; + const float nPhotons = n0Photons * multiplicitySpectrumFactor * fractionPhotonsProjectiveRICH(eta, tileZlength, radius); + if (nPhotons <= kErrorValue + 1) + return kErrorValue; // Ring angular resolution - float ring_angular_resolution = single_photon_angular_resolution / std::sqrt(n_photons); - return ring_angular_resolution; + const float ringAngularResolution = singlePhotonAngularResolution / std::sqrt(nPhotons); + return ringAngularResolution; } /// returns track angular resolution /// \param pt the transverse momentum of the tarck /// \param eta the pseudorapidity of the tarck - /// \param track_pt_resolution the absolute resolution on pt - /// \param track_pt_resolution the absolute resolution on eta + /// \param trackPtResolution the absolute resolution on pt + /// \param trackPtResolution the absolute resolution on eta /// \param mass the mass of the particle - /// \param refractive_index the refractive index of the radiator - double calculate_track_angular_resolution_advanced(float pt, float eta, float track_pt_resolution, float track_eta_resolution, float mass, float refractive_index) + /// \param refractiveIndex the refractive index of the radiator + double calculateTrackAngularResolutionAdvanced(const float pt, const float eta, const float trackPtResolution, const float trackEtaResolution, const float mass, const float refractiveIndex) { // Compute tracking contribution to timing using the error propagation formula // Uses light speed in m/ps, magnetic field in T (*0.1 for conversion kGauss -> T) - double a0 = mass * mass; - double a1 = refractive_index; - double dtheta_on_dpt = a0 / (pt * std::sqrt(a0 + std::pow(pt * std::cosh(eta), 2)) * std::sqrt(std::pow(pt * std::cosh(eta), 2) * (std::pow(a1, 2) - 1.0) - a0)); - double dtheta_on_deta = (a0 * std::tanh(eta)) / (std::sqrt(a0 + std::pow(pt * std::cosh(eta), 2)) * std::sqrt(std::pow(pt * std::cosh(eta), 2) * (std::pow(a1, 2) - 1.0) - a0)); - double track_angular_resolution = std::hypot(std::fabs(dtheta_on_dpt) * track_pt_resolution, std::fabs(dtheta_on_deta) * track_eta_resolution); - return track_angular_resolution; + const double a0 = mass * mass; + const double a1 = refractiveIndex; + const double a1Squared = a1 * a1; + const float ptCoshEta = pt * std::cosh(eta); + const float ptCoshEtaSquared = ptCoshEta * ptCoshEta; + const double dThetaOndPt = a0 / (pt * std::sqrt(a0 + ptCoshEtaSquared) * std::sqrt(ptCoshEtaSquared * (a1Squared - 1.0) - a0)); + const double dThetaOndEta = (a0 * std::tanh(eta)) / (std::sqrt(a0 + ptCoshEtaSquared) * std::sqrt(ptCoshEtaSquared * (a1Squared - 1.0) - a0)); + const double trackAngularResolution = std::hypot(std::fabs(dThetaOndPt) * trackPtResolution, std::fabs(dThetaOndEta) * trackEtaResolution); + return trackAngularResolution; } - void process(soa::Join::iterator const& collision, soa::Join const& tracks, aod::McParticles const&, aod::McCollisions const&) + void process(soa::Join::iterator const& collision, + soa::Join const& tracks, + aod::McParticles const&, + aod::McCollisions const&) { - // for (int i = 0; i < 1000; i++) - // std::cout << "Prova" << std::endl; - - o2::dataformats::VertexBase pvVtx({collision.posX(), collision.posY(), collision.posZ()}, - {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}); + const o2::dataformats::VertexBase pvVtx({collision.posX(), collision.posY(), collision.posZ()}, + {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}); std::array mcPvCov = {0.}; o2::dataformats::VertexBase mcPvVtx({0.0f, 0.0f, 0.0f}, mcPvCov); @@ -745,38 +759,54 @@ struct OnTheFlyRichPid { } for (const auto& track : tracks) { + + auto fillDummyValues = [&](bool gasRich = false) { + upgradeRich(kErrorValue, kErrorValue, kErrorValue, kErrorValue, kErrorValue); + upgradeRichSignal(false, false, false, false, false, false, gasRich); + }; + // first step: find precise arrival time (if any) // --- convert track into perfect track - if (!track.has_mcParticle()) // should always be OK but check please + if (!track.has_mcParticle()) { // should always be OK but check please + fillDummyValues(); continue; + } - auto mcParticle = track.mcParticle(); + const auto& mcParticle = track.mcParticle(); o2::track::TrackParCov o2track = o2::upgrade::convertMCParticleToO2Track(mcParticle, pdg); - // float xPv = error_value; - if (o2track.propagateToDCA(mcPvVtx, dBz)) { + // float xPv = kErrorValue; + if (o2track.propagateToDCA(mcPvVtx, magneticField)) { // xPv = o2track.getX(); } // get particle to calculate Cherenkov angle and resolution auto pdgInfo = pdg->GetParticle(mcParticle.pdgCode()); if (pdgInfo == nullptr) { + fillDummyValues(); continue; } // find track bRICH sector - int i_sector = findSector(o2track.getEta()); - if (i_sector < 0) { + const int iSecor = findSector(o2track.getEta()); + if (iSecor < 0) { + fillDummyValues(); continue; } - float expectedAngleBarrelRich = CherenkovAngle(o2track.getP(), pdgInfo->Mass(), aerogel_rindex[i_sector]); - // float barrelRICHAngularResolution = AngularResolution(o2track.getEta()); - float barrelRICHAngularResolution = extract_ring_angular_resolution(o2track.getEta(), aerogel_rindex[i_sector], bRichGapRefractiveIndex, bRichRadiatorThickness, gap_thickness[i_sector], bRICHPixelSize, expectedAngleBarrelRich, photodetrctor_length[i_sector]); - float projectiveRadiatorRadius = radiusRipple(o2track.getEta(), i_sector); + const bool expectedAngleBarrelGasRichOk = isOverTrhesholdInGasRadiator(o2track.getP(), pdgInfo->Mass()); + float expectedAngleBarrelRich = kErrorValue; + const bool expectedAngleBarrelRichOk = cherenkovAngle(o2track.getP(), pdgInfo->Mass(), aerogelRindex[iSecor], expectedAngleBarrelRich); + if (!expectedAngleBarrelRichOk) { + fillDummyValues(expectedAngleBarrelGasRichOk); + continue; // Particle is below the threshold or not enough photons + } + // float barrelRICHAngularResolution = angularResolution(o2track.getEta()); + const float barrelRICHAngularResolution = extractRingAngularResolution(o2track.getEta(), aerogelRindex[iSecor], bRichGapRefractiveIndex, bRichRadiatorThickness, gapThickness[iSecor], bRICHPixelSize, expectedAngleBarrelRich, photodetrctorLength[iSecor]); + const float projectiveRadiatorRadius = radiusRipple(o2track.getEta(), iSecor); bool flagReachesRadiator = false; - if (projectiveRadiatorRadius > error_value + 1.) { - flagReachesRadiator = checkMagfieldLimit(o2track, projectiveRadiatorRadius, dBz); + if (projectiveRadiatorRadius > kErrorValue + 1.) { + flagReachesRadiator = checkMagfieldLimit(o2track, projectiveRadiatorRadius, magneticField); } /// DISCLAIMER: Exact extrapolation of angular resolution would require track propagation /// to the RICH radiator (accounting sector inclination) in terms of (R,z). @@ -784,62 +814,94 @@ struct OnTheFlyRichPid { /// Discrepancies may be negligible, but would be more rigorous if propagation tool is available // Smear with expected resolutions - float measuredAngleBarrelRich = pRandomNumberGenerator.Gaus(expectedAngleBarrelRich, barrelRICHAngularResolution); + const float measuredAngleBarrelRich = pRandomNumberGenerator.Gaus(expectedAngleBarrelRich, barrelRICHAngularResolution); // Now we calculate the expected Cherenkov angle following certain mass hypotheses // and the (imperfect!) reconstructed track parametrizations auto recoTrack = getTrackParCov(track); - if (recoTrack.propagateToDCA(pvVtx, dBz)) { + if (recoTrack.propagateToDCA(pvVtx, magneticField)) { // xPv = recoTrack.getX(); } // Straight to Nsigma - float deltaThetaBarrelRich[5], nSigmaBarrelRich[5]; - int lpdg_array[5] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton}; - float masses[5]; - - for (int ii = 0; ii < 5; ii++) { - nSigmaBarrelRich[ii] = error_value; - - auto pdgInfoThis = pdg->GetParticle(lpdg_array[ii]); - masses[ii] = pdgInfoThis->Mass(); - float hypothesisAngleBarrelRich = CherenkovAngle(recoTrack.getP(), masses[ii], aerogel_rindex[i_sector]); + static constexpr int kNspecies = 5; + static constexpr int kEl = 0; + static constexpr int kMu = 1; + static constexpr int kPi = 2; + static constexpr int kKa = 3; + static constexpr int kPr = 4; + float nSigmaBarrelRich[kNspecies] = {kErrorValue, kErrorValue, kErrorValue, kErrorValue, kErrorValue}; + bool signalBarrelRich[kNspecies] = {false, false, false, false, false}; + float deltaThetaBarrelRich[kNspecies]; //, nSigmaBarrelRich[kNspecies]; + static constexpr int kPdgArray[kNspecies] = {kElectron, kMuonMinus, kPiPlus, kKPlus, kProton}; + static constexpr float kMasses[kNspecies] = {o2::track::pid_constants::sMasses[o2::track::PID::Electron], + o2::track::pid_constants::sMasses[o2::track::PID::Muon], + o2::track::pid_constants::sMasses[o2::track::PID::Pion], + o2::track::pid_constants::sMasses[o2::track::PID::Kaon], + o2::track::pid_constants::sMasses[o2::track::PID::Proton]}; + + for (int ii = 0; ii < kNspecies; ii++) { // Loop on the particle hypotheses + + float hypothesisAngleBarrelRich = kErrorValue; + const bool hypothesisAngleBarrelRichOk = cherenkovAngle(recoTrack.getP(), kMasses[ii], aerogelRindex[iSecor], hypothesisAngleBarrelRich); + signalBarrelRich[ii] = hypothesisAngleBarrelRichOk; // Particle is above the threshold and enough photons // Evaluate total sigma (layer + tracking resolution) float barrelTotalAngularReso = barrelRICHAngularResolution; if (flagIncludeTrackAngularRes) { - double pt_resolution = std::pow(recoTrack.getP() / std::cosh(recoTrack.getEta()), 2) * std::sqrt(recoTrack.getSigma1Pt2()); - double eta_resolution = std::fabs(std::sin(2.0 * std::atan(std::exp(-recoTrack.getEta())))) * std::sqrt(recoTrack.getSigmaTgl2()); + const float transverseMomentum = recoTrack.getP() / std::cosh(recoTrack.getEta()); + double ptResolution = transverseMomentum * transverseMomentum * std::sqrt(recoTrack.getSigma1Pt2()); + double etaResolution = std::fabs(std::sin(2.0 * std::atan(std::exp(-recoTrack.getEta())))) * std::sqrt(recoTrack.getSigmaTgl2()); if (flagRICHLoadDelphesLUTs) { - pt_resolution = mSmearer.getAbsPtRes(pdgInfoThis->PdgCode(), dNdEta, recoTrack.getEta(), recoTrack.getP() / std::cosh(recoTrack.getEta())); - eta_resolution = mSmearer.getAbsEtaRes(pdgInfoThis->PdgCode(), dNdEta, recoTrack.getEta(), recoTrack.getP() / std::cosh(recoTrack.getEta())); + ptResolution = mSmearer.getAbsPtRes(kPdgArray[ii], dNdEta, recoTrack.getEta(), transverseMomentum); + etaResolution = mSmearer.getAbsEtaRes(kPdgArray[ii], dNdEta, recoTrack.getEta(), transverseMomentum); } - // cout << endl << "Pt resolution: " << pt_resolution << ", Eta resolution: " << eta_resolution << endl << endl; - float barrelTrackAngularReso = calculate_track_angular_resolution_advanced(recoTrack.getP() / std::cosh(recoTrack.getEta()), recoTrack.getEta(), pt_resolution, eta_resolution, masses[ii], aerogel_rindex[i_sector]); + // cout << endl << "Pt resolution: " << ptResolution << ", Eta resolution: " << etaResolution << endl << endl; + const float barrelTrackAngularReso = calculateTrackAngularResolutionAdvanced(recoTrack.getP() / std::cosh(recoTrack.getEta()), recoTrack.getEta(), ptResolution, etaResolution, kMasses[ii], aerogelRindex[iSecor]); barrelTotalAngularReso = std::hypot(barrelRICHAngularResolution, barrelTrackAngularReso); - if (doQAplots && hypothesisAngleBarrelRich > error_value + 1. && measuredAngleBarrelRich > error_value + 1. && barrelRICHAngularResolution > error_value + 1. && flagReachesRadiator) { - float momentum = recoTrack.getP(); - // float pseudorapidity = recoTrack.getEta(); - // float transverse_momentum = momentum / std::cosh(pseudorapidity); - if (ii == 0 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { - histos.fill(HIST("h2dBarrelAngularResTrackElecVsP"), momentum, 1000.0 * barrelTrackAngularReso); - histos.fill(HIST("h2dBarrelAngularResTotalElecVsP"), momentum, 1000.0 * barrelTotalAngularReso); - } - if (ii == 1 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { - histos.fill(HIST("h2dBarrelAngularResTrackMuonVsP"), momentum, 1000.0 * barrelTrackAngularReso); - histos.fill(HIST("h2dBarrelAngularResTotalMuonVsP"), momentum, 1000.0 * barrelTotalAngularReso); - } - if (ii == 2 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { - histos.fill(HIST("h2dBarrelAngularResTrackPionVsP"), momentum, 1000.0 * barrelTrackAngularReso); - histos.fill(HIST("h2dBarrelAngularResTotalPionVsP"), momentum, 1000.0 * barrelTotalAngularReso); - } - if (ii == 3 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { - histos.fill(HIST("h2dBarrelAngularResTrackKaonVsP"), momentum, 1000.0 * barrelTrackAngularReso); - histos.fill(HIST("h2dBarrelAngularResTotalKaonVsP"), momentum, 1000.0 * barrelTotalAngularReso); - } - if (ii == 4 && std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { - histos.fill(HIST("h2dBarrelAngularResTrackProtVsP"), momentum, 1000.0 * barrelTrackAngularReso); - histos.fill(HIST("h2dBarrelAngularResTotalProtVsP"), momentum, 1000.0 * barrelTotalAngularReso); + if (doQAplots && + hypothesisAngleBarrelRich > kErrorValue + 1. && + measuredAngleBarrelRich > kErrorValue + 1. && + barrelRICHAngularResolution > kErrorValue + 1. && + flagReachesRadiator) { + switch (mcParticle.pdgCode()) { + case kPdgArray[kEl]: // Electron + case -kPdgArray[kEl]: // Positron + if (ii == kEl) { + histos.fill(HIST("h2dBarrelAngularResTrackElecVsP"), recoTrack.getP(), 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalElecVsP"), recoTrack.getP(), 1000.0 * barrelTotalAngularReso); + } + break; + case kPdgArray[kMu]: // Muon + case -kPdgArray[kMu]: // AntiMuon + if (ii == kMu) { + histos.fill(HIST("h2dBarrelAngularResTrackMuonVsP"), recoTrack.getP(), 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalMuonVsP"), recoTrack.getP(), 1000.0 * barrelTotalAngularReso); + } + break; + case kPdgArray[kPi]: // Pion + case -kPdgArray[kPi]: // AntiPion + if (ii == kPi) { + histos.fill(HIST("h2dBarrelAngularResTrackPionVsP"), recoTrack.getP(), 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalPionVsP"), recoTrack.getP(), 1000.0 * barrelTotalAngularReso); + } + break; + case kPdgArray[kKa]: // Kaon + case -kPdgArray[kKa]: // AntiKaon + if (ii == kKa) { + histos.fill(HIST("h2dBarrelAngularResTrackKaonVsP"), recoTrack.getP(), 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalKaonVsP"), recoTrack.getP(), 1000.0 * barrelTotalAngularReso); + } + break; + case kPdgArray[kPr]: // Proton + case -kPdgArray[kPr]: // AntiProton + if (ii == kPr) { + histos.fill(HIST("h2dBarrelAngularResTrackProtVsP"), recoTrack.getP(), 1000.0 * barrelTrackAngularReso); + histos.fill(HIST("h2dBarrelAngularResTotalProtVsP"), recoTrack.getP(), 1000.0 * barrelTotalAngularReso); + } + break; + default: + break; } } } @@ -847,7 +909,10 @@ struct OnTheFlyRichPid { /// DISCLAIMER: here tracking is accounted only for momentum value, but not for track parameters at impact point on the /// RICH radiator, since exact resolution would require photon generation and transport to photodetector. /// Effects are expected to be negligible (a few tenths of a milliradian) but further studies are required ! - if (hypothesisAngleBarrelRich > error_value + 1. && measuredAngleBarrelRich > error_value + 1. && barrelRICHAngularResolution > error_value + 1. && flagReachesRadiator) { + if (hypothesisAngleBarrelRich > kErrorValue + 1. && + measuredAngleBarrelRich > kErrorValue + 1. && + barrelRICHAngularResolution > kErrorValue + 1. && + flagReachesRadiator) { deltaThetaBarrelRich[ii] = hypothesisAngleBarrelRich - measuredAngleBarrelRich; nSigmaBarrelRich[ii] = deltaThetaBarrelRich[ii] / barrelTotalAngularReso; } @@ -855,57 +920,65 @@ struct OnTheFlyRichPid { // Fill histograms if (doQAplots) { - float momentum = recoTrack.getP(); - float pseudorapidity = recoTrack.getEta(); - float barrelRichTheta = measuredAngleBarrelRich; - - if (barrelRichTheta > error_value + 1. && barrelRICHAngularResolution > error_value + 1. && flagReachesRadiator) { - histos.fill(HIST("h2dAngleVsMomentumBarrelRICH"), momentum, barrelRichTheta); - histos.fill(HIST("h2dAngleVsEtaBarrelRICH"), pseudorapidity, barrelRichTheta); - histos.fill(HIST("h2dAngularResolutionVsMomentumBarrelRICH"), momentum, 1000 * barrelRICHAngularResolution); - histos.fill(HIST("h2dAngularResolutionVsEtaBarrelRICH"), pseudorapidity, 1000 * barrelRICHAngularResolution); - histos.fill(HIST("hSectorID"), i_sector); - - if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[0])->PdgCode()) { - histos.fill(HIST("h2dBarrelNsigmaTrueElecVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); - histos.fill(HIST("h2dBarrelNsigmaTrueElecVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); - histos.fill(HIST("h2dBarrelNsigmaTrueElecVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); - histos.fill(HIST("h2dBarrelNsigmaTrueElecVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); - histos.fill(HIST("h2dBarrelNsigmaTrueElecVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); - } - if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[1])->PdgCode()) { - histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); - histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); - histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); - histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); - histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); - } - if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[2])->PdgCode()) { - histos.fill(HIST("h2dBarrelNsigmaTruePionVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); - histos.fill(HIST("h2dBarrelNsigmaTruePionVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); - histos.fill(HIST("h2dBarrelNsigmaTruePionVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); - histos.fill(HIST("h2dBarrelNsigmaTruePionVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); - histos.fill(HIST("h2dBarrelNsigmaTruePionVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); - } - if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[3])->PdgCode()) { - histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); - histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); - histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); - histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); - histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); - } - if (std::fabs(mcParticle.pdgCode()) == pdg->GetParticle(lpdg_array[4])->PdgCode()) { - histos.fill(HIST("h2dBarrelNsigmaTrueProtVsElecHypothesis"), momentum, nSigmaBarrelRich[0]); - histos.fill(HIST("h2dBarrelNsigmaTrueProtVsMuonHypothesis"), momentum, nSigmaBarrelRich[1]); - histos.fill(HIST("h2dBarrelNsigmaTrueProtVsPionHypothesis"), momentum, nSigmaBarrelRich[2]); - histos.fill(HIST("h2dBarrelNsigmaTrueProtVsKaonHypothesis"), momentum, nSigmaBarrelRich[3]); - histos.fill(HIST("h2dBarrelNsigmaTrueProtVsProtHypothesis"), momentum, nSigmaBarrelRich[4]); + if (measuredAngleBarrelRich > kErrorValue + 1. && + barrelRICHAngularResolution > kErrorValue + 1. && + flagReachesRadiator) { + histos.fill(HIST("h2dAngleVsMomentumBarrelRICH"), recoTrack.getP(), measuredAngleBarrelRich); + histos.fill(HIST("h2dAngleVsEtaBarrelRICH"), recoTrack.getEta(), measuredAngleBarrelRich); + histos.fill(HIST("h2dAngularResolutionVsMomentumBarrelRICH"), recoTrack.getP(), 1000 * barrelRICHAngularResolution); + histos.fill(HIST("h2dAngularResolutionVsEtaBarrelRICH"), recoTrack.getEta(), 1000 * barrelRICHAngularResolution); + histos.fill(HIST("hSectorID"), iSecor); + + switch (mcParticle.pdgCode()) { + case kPdgArray[kEl]: // Electron + case -kPdgArray[kEl]: // Positron + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsElecHypothesis"), recoTrack.getP(), nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsMuonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsPionHypothesis"), recoTrack.getP(), nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsKaonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueElecVsProtHypothesis"), recoTrack.getP(), nSigmaBarrelRich[4]); + break; + case kPdgArray[kMu]: // Muon + case -kPdgArray[kMu]: // AntiMuon + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsElecHypothesis"), recoTrack.getP(), nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsMuonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsPionHypothesis"), recoTrack.getP(), nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsKaonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueMuonVsProtHypothesis"), recoTrack.getP(), nSigmaBarrelRich[4]); + break; + case kPdgArray[kPi]: // Pion + case -kPdgArray[kPi]: // AntiPion + histos.fill(HIST("h2dBarrelNsigmaTruePionVsElecHypothesis"), recoTrack.getP(), nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsMuonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsPionHypothesis"), recoTrack.getP(), nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsKaonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTruePionVsProtHypothesis"), recoTrack.getP(), nSigmaBarrelRich[4]); + break; + case kPdgArray[kKa]: // Kaon + case -kPdgArray[kKa]: // AntiKaon + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsElecHypothesis"), recoTrack.getP(), nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsMuonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsPionHypothesis"), recoTrack.getP(), nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsKaonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueKaonVsProtHypothesis"), recoTrack.getP(), nSigmaBarrelRich[4]); + break; + case kPdgArray[kPr]: // Proton + case -kPdgArray[kPr]: // AntiProton + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsElecHypothesis"), recoTrack.getP(), nSigmaBarrelRich[0]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsMuonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[1]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsPionHypothesis"), recoTrack.getP(), nSigmaBarrelRich[2]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsKaonHypothesis"), recoTrack.getP(), nSigmaBarrelRich[3]); + histos.fill(HIST("h2dBarrelNsigmaTrueProtVsProtHypothesis"), recoTrack.getP(), nSigmaBarrelRich[4]); + break; + default: + break; } } } // Sigmas have been fully calculated. Please populate the NSigma helper table (once per track) upgradeRich(nSigmaBarrelRich[0], nSigmaBarrelRich[1], nSigmaBarrelRich[2], nSigmaBarrelRich[3], nSigmaBarrelRich[4]); + upgradeRichSignal(expectedAngleBarrelRichOk, signalBarrelRich[0], signalBarrelRich[1], signalBarrelRich[2], signalBarrelRich[3], signalBarrelRich[4], expectedAngleBarrelGasRichOk); } } }; diff --git a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx index 099e42ea1b7..4c062fd0e7a 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTofPid.cxx @@ -24,40 +24,43 @@ /// \since May 22, 2024 /// -#include -#include -#include -#include +#include "TableHelper.h" -#include +#include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFTOF.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsVertexing/HelixHelper.h" +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/ASoAHelpers.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "ALICE3/Core/TrackUtilities.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "CommonUtils/NameConf.h" -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "CommonConstants/GeomConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "TRandom3.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "DetectorsVertexing/HelixHelper.h" -#include "TableHelper.h" -#include "ALICE3/Core/DelphesO2TrackSmearer.h" + #include "TEfficiency.h" #include "THashList.h" +#include "TRandom3.h" +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -84,7 +87,7 @@ struct OnTheFlyTofPid { // more could be added (especially a disk TOF at a certain z?) // in the evolution of this effort struct : ConfigurableGroup { - Configurable dBz{"dBz", 20, "magnetic field (kilogauss)"}; + Configurable magneticField{"magneticField", 0, "magnetic field (kilogauss) if 0, taken from the tracker task"}; Configurable considerEventTime{"considerEventTime", true, "flag to consider event time"}; Configurable innerTOFRadius{"innerTOFRadius", 20, "barrel inner TOF radius (cm)"}; Configurable outerTOFRadius{"outerTOFRadius", 80, "barrel outer TOF radius (cm)"}; @@ -140,6 +143,13 @@ struct OnTheFlyTofPid { void init(o2::framework::InitContext& initContext) { pRandomNumberGenerator.SetSeed(0); // fully randomize + if (simConfig.magneticField.value < o2::constants::math::Epsilon) { + LOG(info) << "Getting the magnetic field from the on-the-fly tracker task"; + if (!getTaskOptionValue(initContext, "on-the-fly-tracker", simConfig.magneticField, false)) { + LOG(fatal) << "Could not get Bz from on-the-fly-tracker task"; + } + LOG(info) << "Bz = " << simConfig.magneticField.value << " T"; + } // Check if inheriting the LUT configuration auto configLutPath = [&](Configurable& lut) { @@ -221,33 +231,33 @@ struct OnTheFlyTofPid { std::string particleNames[kParticles] = {"#it{e}", "#it{#mu}", "#it{#pi}", "#it{K}", "#it{p}"}; std::string particleNames2[kParticles] = {"Elec", "Muon", "Pion", "Kaon", "Prot"}; - for (int i_true = 0; i_true < kParticles; i_true++) { + for (int iTrue = 0; iTrue < kParticles; iTrue++) { auto addHistogram = [&](const std::string& name, const AxisSpec& axis) { return histos.add(name, "", kTH2F, {axisMomentum, axis}); }; - const AxisSpec axisTrackTimeRes{plotsConfig.nBinsTimeRes, 0.0f, +200.0f, "Track time resolution - " + particleNames[i_true] + " (ps)"}; - h2dInnerTimeResTrack[i_true] = addHistogram("iTOF/res/h2dInnerTimeResTrack" + particleNames2[i_true] + "VsP", axisTrackTimeRes); - h2dOuterTimeResTrack[i_true] = addHistogram("oTOF/res/h2dOuterTimeResTrack" + particleNames2[i_true] + "VsP", axisTrackTimeRes); - const AxisSpec axisTotalTimeRes{plotsConfig.nBinsTimeRes, 0.0f, +200.0f, "Total time resolution - " + particleNames[i_true] + " (ps)"}; - h2dInnerTimeResTotal[i_true] = addHistogram("iTOF/res/h2dInnerTimeResTotal" + particleNames2[i_true] + "VsP", axisTotalTimeRes); - h2dOuterTimeResTotal[i_true] = addHistogram("oTOF/res/h2dOuterTimeResTotal" + particleNames2[i_true] + "VsP", axisTotalTimeRes); - for (int i_hyp = 0; i_hyp < kParticles; i_hyp++) { - std::string nameTitleInner = "h2dInnerNsigmaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis"; - std::string nameTitleOuter = "h2dOuterNsigmaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis"; - std::string nameTitleInnerDelta = "h2dInnerDeltaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis"; - std::string nameTitleOuterDelta = "h2dOuterDeltaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis"; + const AxisSpec axisTrackTimeRes{plotsConfig.nBinsTimeRes, 0.0f, +200.0f, "Track time resolution - " + particleNames[iTrue] + " (ps)"}; + h2dInnerTimeResTrack[iTrue] = addHistogram("iTOF/res/h2dInnerTimeResTrack" + particleNames2[iTrue] + "VsP", axisTrackTimeRes); + h2dOuterTimeResTrack[iTrue] = addHistogram("oTOF/res/h2dOuterTimeResTrack" + particleNames2[iTrue] + "VsP", axisTrackTimeRes); + const AxisSpec axisTotalTimeRes{plotsConfig.nBinsTimeRes, 0.0f, +200.0f, "Total time resolution - " + particleNames[iTrue] + " (ps)"}; + h2dInnerTimeResTotal[iTrue] = addHistogram("iTOF/res/h2dInnerTimeResTotal" + particleNames2[iTrue] + "VsP", axisTotalTimeRes); + h2dOuterTimeResTotal[iTrue] = addHistogram("oTOF/res/h2dOuterTimeResTotal" + particleNames2[iTrue] + "VsP", axisTotalTimeRes); + for (int iHyp = 0; iHyp < kParticles; iHyp++) { + std::string nameTitleInner = "h2dInnerNsigmaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis"; + std::string nameTitleOuter = "h2dOuterNsigmaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis"; + std::string nameTitleInnerDelta = "h2dInnerDeltaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis"; + std::string nameTitleOuterDelta = "h2dOuterDeltaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis"; const AxisSpec axisX{plotsConfig.doSeparationVsPt.value ? axisPt : axisMomentum}; - const AxisSpec axisNsigmaCorrect{plotsConfig.nBinsNsigmaCorrectSpecies, plotsConfig.minNsigmaRange, plotsConfig.maxNsigmaRange, "N#sigma - True " + particleNames[i_true] + " vs " + particleNames[i_hyp] + " hypothesis"}; - const AxisSpec axisDeltaCorrect{plotsConfig.nBinsDeltaCorrectSpecies, plotsConfig.minDeltaRange, plotsConfig.maxDeltaRange, "#Delta - True " + particleNames[i_true] + " vs " + particleNames[i_hyp] + " hypothesis"}; - const AxisSpec axisNsigmaWrong{plotsConfig.nBinsNsigmaWrongSpecies, plotsConfig.minNsigmaRange, plotsConfig.maxNsigmaRange, "N#sigma - True " + particleNames[i_true] + " vs " + particleNames[i_hyp] + " hypothesis"}; - const AxisSpec axisDeltaWrong{plotsConfig.nBinsDeltaWrongSpecies, plotsConfig.minDeltaRange, plotsConfig.maxDeltaRange, "#Delta - True " + particleNames[i_true] + " vs " + particleNames[i_hyp] + " hypothesis"}; - const AxisSpec axisNSigma{i_true == i_hyp ? axisNsigmaCorrect : axisNsigmaWrong}; - const AxisSpec axisDelta{i_true == i_hyp ? axisDeltaCorrect : axisDeltaWrong}; - h2dInnerNsigmaTrue[i_true][i_hyp] = histos.add("iTOF/nsigma/h2dInnerNsigmaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis", "", kTH2F, {axisX, axisNSigma}); - h2dOuterNsigmaTrue[i_true][i_hyp] = histos.add("oTOF/nsigma/h2dOuterNsigmaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis", "", kTH2F, {axisX, axisNSigma}); - h2dInnerDeltaTrue[i_true][i_hyp] = histos.add("iTOF/delta/h2dInnerDeltaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis", "", kTH2F, {axisX, axisDelta}); - h2dOuterDeltaTrue[i_true][i_hyp] = histos.add("oTOF/delta/h2dOuterDeltaTrue" + particleNames2[i_true] + "Vs" + particleNames2[i_hyp] + "Hypothesis", "", kTH2F, {axisX, axisDelta}); + const AxisSpec axisNsigmaCorrect{plotsConfig.nBinsNsigmaCorrectSpecies, plotsConfig.minNsigmaRange, plotsConfig.maxNsigmaRange, "N#sigma - True " + particleNames[iTrue] + " vs " + particleNames[iHyp] + " hypothesis"}; + const AxisSpec axisDeltaCorrect{plotsConfig.nBinsDeltaCorrectSpecies, plotsConfig.minDeltaRange, plotsConfig.maxDeltaRange, "#Delta - True " + particleNames[iTrue] + " vs " + particleNames[iHyp] + " hypothesis"}; + const AxisSpec axisNsigmaWrong{plotsConfig.nBinsNsigmaWrongSpecies, plotsConfig.minNsigmaRange, plotsConfig.maxNsigmaRange, "N#sigma - True " + particleNames[iTrue] + " vs " + particleNames[iHyp] + " hypothesis"}; + const AxisSpec axisDeltaWrong{plotsConfig.nBinsDeltaWrongSpecies, plotsConfig.minDeltaRange, plotsConfig.maxDeltaRange, "#Delta - True " + particleNames[iTrue] + " vs " + particleNames[iHyp] + " hypothesis"}; + const AxisSpec axisNSigma{iTrue == iHyp ? axisNsigmaCorrect : axisNsigmaWrong}; + const AxisSpec axisDelta{iTrue == iHyp ? axisDeltaCorrect : axisDeltaWrong}; + h2dInnerNsigmaTrue[iTrue][iHyp] = histos.add("iTOF/nsigma/h2dInnerNsigmaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis", "", kTH2F, {axisX, axisNSigma}); + h2dOuterNsigmaTrue[iTrue][iHyp] = histos.add("oTOF/nsigma/h2dOuterNsigmaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis", "", kTH2F, {axisX, axisNSigma}); + h2dInnerDeltaTrue[iTrue][iHyp] = histos.add("iTOF/delta/h2dInnerDeltaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis", "", kTH2F, {axisX, axisDelta}); + h2dOuterDeltaTrue[iTrue][iHyp] = histos.add("oTOF/delta/h2dOuterDeltaTrue" + particleNames2[iTrue] + "Vs" + particleNames2[iHyp] + "Hypothesis", "", kTH2F, {axisX, axisDelta}); } } } @@ -397,7 +407,7 @@ struct OnTheFlyTofPid { static constexpr float kMaxEventTimeResolution = 200.f; if (sumw <= 0. || tracks.size() <= 1 || std::sqrt(1. / sumw) > kMaxEventTimeResolution) { - tzero[0] = 0.; // [ps] + tzero[0] = 0.; // [ps] tzero[1] = kMaxEventTimeResolution; // [ps] return false; } @@ -496,13 +506,13 @@ struct OnTheFlyTofPid { float xPv = -100.f; static constexpr float kTrkXThreshold = -99.f; // Threshold to consider a good propagation of the track - if (o2track.propagateToDCA(mcPvVtx, simConfig.dBz)) { + if (o2track.propagateToDCA(mcPvVtx, simConfig.magneticField)) { xPv = o2track.getX(); } float trackLengthInnerTOF = -1, trackLengthOuterTOF = -1; if (xPv > kTrkXThreshold) { - trackLengthInnerTOF = computeTrackLength(o2track, simConfig.innerTOFRadius, simConfig.dBz); - trackLengthOuterTOF = computeTrackLength(o2track, simConfig.outerTOFRadius, simConfig.dBz); + trackLengthInnerTOF = computeTrackLength(o2track, simConfig.innerTOFRadius, simConfig.magneticField); + trackLengthOuterTOF = computeTrackLength(o2track, simConfig.outerTOFRadius, simConfig.magneticField); } // get mass to calculate velocity @@ -526,12 +536,12 @@ struct OnTheFlyTofPid { float trackLengthRecoInnerTOF = -1, trackLengthRecoOuterTOF = -1; auto recoTrack = getTrackParCov(track); xPv = -100.f; - if (recoTrack.propagateToDCA(pvVtx, simConfig.dBz)) { + if (recoTrack.propagateToDCA(pvVtx, simConfig.magneticField)) { xPv = recoTrack.getX(); } if (xPv > kTrkXThreshold) { - trackLengthRecoInnerTOF = computeTrackLength(recoTrack, simConfig.innerTOFRadius, simConfig.dBz); - trackLengthRecoOuterTOF = computeTrackLength(recoTrack, simConfig.outerTOFRadius, simConfig.dBz); + trackLengthRecoInnerTOF = computeTrackLength(recoTrack, simConfig.innerTOFRadius, simConfig.magneticField); + trackLengthRecoOuterTOF = computeTrackLength(recoTrack, simConfig.outerTOFRadius, simConfig.magneticField); } // cache the track info needed for the event time calculation @@ -553,7 +563,7 @@ struct OnTheFlyTofPid { if (simConfig.considerEventTime.value) { etStatus = eventTime(tracksWithTime, tzero); if (!etStatus) { - LOG(warning) << "Event time calculation failed with " << tracksWithTime.size() << " tracks with time and " << dNdEta << " charged particles"; + LOG(debug) << "Event time calculation failed with " << tracksWithTime.size() << " tracks with time and " << dNdEta << " charged particles"; } } @@ -639,8 +649,8 @@ struct OnTheFlyTofPid { ptResolution = mSmearer.getAbsPtRes(pdgInfoThis->PdgCode(), dNdEta, pseudorapidity, momentum / std::cosh(pseudorapidity)); etaResolution = mSmearer.getAbsEtaRes(pdgInfoThis->PdgCode(), dNdEta, pseudorapidity, momentum / std::cosh(pseudorapidity)); } - float innerTrackTimeReso = calculateTrackTimeResolutionAdvanced(momentum / std::cosh(pseudorapidity), pseudorapidity, ptResolution, etaResolution, masses[ii], simConfig.innerTOFRadius, simConfig.dBz); - float outerTrackTimeReso = calculateTrackTimeResolutionAdvanced(momentum / std::cosh(pseudorapidity), pseudorapidity, ptResolution, etaResolution, masses[ii], simConfig.outerTOFRadius, simConfig.dBz); + float innerTrackTimeReso = calculateTrackTimeResolutionAdvanced(momentum / std::cosh(pseudorapidity), pseudorapidity, ptResolution, etaResolution, masses[ii], simConfig.innerTOFRadius, simConfig.magneticField); + float outerTrackTimeReso = calculateTrackTimeResolutionAdvanced(momentum / std::cosh(pseudorapidity), pseudorapidity, ptResolution, etaResolution, masses[ii], simConfig.outerTOFRadius, simConfig.magneticField); innerTotalTimeReso = std::hypot(simConfig.innerTOFTimeReso, innerTrackTimeReso); outerTotalTimeReso = std::hypot(simConfig.outerTOFTimeReso, outerTrackTimeReso); diff --git a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx index ff804b8485a..c858f5a753e 100644 --- a/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx +++ b/ALICE3/TableProducer/OTF/onTheFlyTracker.cxx @@ -23,48 +23,42 @@ /// \author Roberto Preghenella preghenella@bo.infn.it /// -#include -#include -#include -#include -#include - -#include -#include -#include -#include +#include "ALICE3/Core/DelphesO2TrackSmearer.h" +#include "ALICE3/Core/DetLayer.h" +#include "ALICE3/Core/FastTracker.h" +#include "ALICE3/Core/TrackUtilities.h" +#include "ALICE3/DataModel/OTFStrangeness.h" +#include "ALICE3/DataModel/collisionAlice3.h" +#include "ALICE3/DataModel/tracksAlice3.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "CommonConstants/MathConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsVertexing/PVertexer.h" +#include "DetectorsVertexing/PVertexerHelpers.h" +#include "Field/MagneticField.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" -#include -#include "DCAFitter/DCAFitterN.h" -#include "Common/Core/RecoDecay.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsVertexing/PVertexer.h" -#include "DetectorsVertexing/PVertexerHelpers.h" #include "SimulationDataFormat/InteractionSampler.h" -#include "Field/MagneticField.h" -#include "ITSMFTSimulation/Hit.h" -#include "ITStracking/Configuration.h" -#include "ITStracking/IOUtils.h" -#include "ITStracking/Tracker.h" -#include "ITStracking/Vertexer.h" -#include "ITStracking/VertexerTraits.h" +#include +#include +#include +#include +#include -#include "ALICE3/Core/DelphesO2TrackSmearer.h" -#include "ALICE3/Core/FastTracker.h" -#include "ALICE3/Core/DetLayer.h" -#include "ALICE3/Core/TrackUtilities.h" -#include "ALICE3/DataModel/collisionAlice3.h" -#include "ALICE3/DataModel/tracksAlice3.h" -#include "ALICE3/DataModel/OTFStrangeness.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -808,7 +802,7 @@ struct OnTheFlyTracker { std::array posClusterCandidate; trackParCov.getXYZGlo(posClusterCandidate); float r{std::hypot(posClusterCandidate[0], posClusterCandidate[1])}; - float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::its::constants::math::Pi}; + float phi{std::atan2(-posClusterCandidate[1], -posClusterCandidate[0]) + o2::constants::math::PI}; o2::fastsim::DetLayer currentTrackingLayer = fastTracker.GetLayer(i); if (currentTrackingLayer.getResolutionRPhi() > 1e-8 && currentTrackingLayer.getResolutionZ() > 1e-8) { // catch zero (though should not really happen...) diff --git a/ALICE3/TableProducer/alice3-correlatorDDbar.cxx b/ALICE3/TableProducer/alice3-correlatorDDbar.cxx index 6c270dc1cd5..b17216e9b76 100644 --- a/ALICE3/TableProducer/alice3-correlatorDDbar.cxx +++ b/ALICE3/TableProducer/alice3-correlatorDDbar.cxx @@ -14,23 +14,20 @@ /// /// \author Fabio Colamaria , INFN Bari -#include +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.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/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "ALICE3/DataModel/A3DecayFinderTables.h" - -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/HFC/DataModel/CorrelationTables.h" -// #include "PWGHF/DataModel/CandidateReconstructionTables.h" -// #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::analysis; @@ -121,6 +118,15 @@ struct alice3correlatorddbar { registry.add("hMassD0barMCRecSig", "D0bar signal candidates - MC reco;inv. mass D0bar only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassD0barMCRecRefl", "D0bar reflection candidates - MC reco;inv. mass D0bar only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hMassD0barMCRecBkg", "D0bar background candidates - MC reco;inv. mass D0bar only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMass_NoEff", "D0,D0bar candidates (wo efficiency);inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0_NoEff", "D0,D0bar candidates (wo efficiency);inv. mass D0 only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0bar_NoEff", "D0,D0bar candidates (wo efficiency);inv. mass D0bar only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0MCRecSig_NoEff", "D0 signal candidates - MC reco (wo efficiency);inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0MCRecRefl_NoEff", "D0 reflection candidates - MC reco (wo efficiency);inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0MCRecBkg_NoEff", "D0 background candidates - MC reco (wo efficiency);inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0barMCRecSig_NoEff", "D0bar signal candidates - MC reco (wo efficiency);inv. mass D0bar only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0barMCRecRefl_NoEff", "D0bar reflection candidates - MC reco (wo efficiency);inv. mass D0bar only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassD0barMCRecBkg_NoEff", "D0bar background candidates - MC reco (wo efficiency);inv. mass D0bar only (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{massAxisBins, massAxisMin, massAxisMax}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); } /// D0-D0bar correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) @@ -139,10 +145,14 @@ struct alice3correlatorddbar { if (candidate1.isSelD0() >= selectionFlagD0) { registry.fill(HIST("hMass"), candidate1.m(), candidate1.pt(), efficiencyWeight); registry.fill(HIST("hMassD0"), candidate1.m(), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass_NoEff"), candidate1.m(), candidate1.pt()); + registry.fill(HIST("hMassD0_NoEff"), candidate1.m(), candidate1.pt()); } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hMass"), candidate1.m(), candidate1.pt(), efficiencyWeight); registry.fill(HIST("hMassD0bar"), candidate1.m(), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMass_NoEff"), candidate1.m(), candidate1.pt()); + registry.fill(HIST("hMassD0bar_NoEff"), candidate1.m(), candidate1.pt()); } registry.fill(HIST("hPtCand"), candidate1.pt()); registry.fill(HIST("hPtProng0"), candidate1.ptProng0()); @@ -229,19 +239,25 @@ struct alice3correlatorddbar { if (candidate1.isSelD0() >= selectionFlagD0) { // only reco as D0 if (candidate1.mcTruthInfo() == 1) { // also matched as D0 registry.fill(HIST("hMassD0MCRecSig"), candidate1.m(), candidate1.pt(), efficiencyWeight); // here m is univoque, since a given candidate passes the selection with only a single mass option + registry.fill(HIST("hMassD0MCRecSig_NoEff"), candidate1.m(), candidate1.pt()); } else if (candidate1.mcTruthInfo() == 2) { registry.fill(HIST("hMassD0MCRecRefl"), candidate1.m(), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0MCRecRefl_NoEff"), candidate1.m(), candidate1.pt()); } else { registry.fill(HIST("hMassD0MCRecBkg"), candidate1.m(), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0MCRecBkg_NoEff"), candidate1.m(), candidate1.pt()); } } if (candidate1.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar if (candidate1.mcTruthInfo() == 2) { // also matched as D0bar registry.fill(HIST("hMassD0barMCRecSig"), candidate1.m(), candidate1.pt(), efficiencyWeight); // here m is univoque, since a given candidate passes the selection with only a single mass option + registry.fill(HIST("hMassD0barMCRecSig_NoEff"), candidate1.m(), candidate1.pt()); } else if (candidate1.mcTruthInfo() == 1) { registry.fill(HIST("hMassD0barMCRecRefl"), candidate1.m(), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0barMCRecRefl_NoEff"), candidate1.m(), candidate1.pt()); } else { registry.fill(HIST("hMassD0barMCRecBkg"), candidate1.m(), candidate1.pt(), efficiencyWeight); + registry.fill(HIST("hMassD0barMCRecBkg_NoEff"), candidate1.m(), candidate1.pt()); } } diff --git a/ALICE3/TableProducer/alice3-decaypreselector.cxx b/ALICE3/TableProducer/alice3-decaypreselector.cxx index e27e1e3ad94..527d1c1d197 100644 --- a/ALICE3/TableProducer/alice3-decaypreselector.cxx +++ b/ALICE3/TableProducer/alice3-decaypreselector.cxx @@ -63,7 +63,7 @@ using FullTracksExt = soa::Join; // For MC association in pre-selection using labeledTracks = soa::Join; using tofTracks = soa::Join; -using richTracks = soa::Join; +using richTracks = soa::Join; struct alice3decaypreselector { Produces a3decayMaps; @@ -112,9 +112,9 @@ struct alice3decaypreselector { Partition pOuterTOFPi = nabs(aod::upgrade_tof::nSigmaPionOuterTOF) > nSigmaTOF; Partition pOuterTOFKa = nabs(aod::upgrade_tof::nSigmaKaonOuterTOF) > nSigmaTOF; Partition pOuterTOFPr = nabs(aod::upgrade_tof::nSigmaProtonOuterTOF) > nSigmaTOF; - Partition pRICHPi = nabs(aod::upgrade_rich::nSigmaPionRich) > nSigmaRICH; - Partition pRICHKa = nabs(aod::upgrade_rich::nSigmaKaonRich) > nSigmaRICH; - Partition pRICHPr = nabs(aod::upgrade_rich::nSigmaProtonRich) > nSigmaRICH; + Partition pRICHPi = aod::upgrade_rich::hasSig && aod::upgrade_rich::hasSigPi && nabs(aod::upgrade_rich::nSigmaPionRich) > nSigmaRICH; + Partition pRICHKa = aod::upgrade_rich::hasSig && aod::upgrade_rich::hasSigKa && nabs(aod::upgrade_rich::nSigmaKaonRich) > nSigmaRICH; + Partition pRICHPr = aod::upgrade_rich::hasSig && aod::upgrade_rich::hasSigPr && nabs(aod::upgrade_rich::nSigmaProtonRich) > nSigmaRICH; //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* /// Initialization of mask vectors if uninitialized diff --git a/ALICE3/TableProducer/alice3-multicharmTable.cxx b/ALICE3/TableProducer/alice3-multicharmTable.cxx index 16b16c666d8..164e5f83f9b 100644 --- a/ALICE3/TableProducer/alice3-multicharmTable.cxx +++ b/ALICE3/TableProducer/alice3-multicharmTable.cxx @@ -17,41 +17,43 @@ // HF decays. Work in progress: use at your own risk! // -#include -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" +#include "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/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" #include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" + #include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" #include "DataFormatsCalibration/MeanVertexObject.h" -#include "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/RICH.h" -#include "ALICE3/DataModel/A3DecayFinderTables.h" -#include "ALICE3/DataModel/OTFStrangeness.h" -#include "ALICE3/DataModel/OTFMulticharm.h" -#include "ALICE3/DataModel/tracksAlice3.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" #include "DetectorsVertexing/PVertexer.h" #include "DetectorsVertexing/PVertexerHelpers.h" -#include "CommonConstants/PhysicsConstants.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 using namespace o2; using namespace o2::framework; @@ -68,14 +70,16 @@ 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; +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)"}; @@ -120,6 +124,7 @@ struct alice3multicharmTable { 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"}; @@ -247,6 +252,11 @@ struct alice3multicharmTable { } 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; @@ -321,6 +331,13 @@ struct alice3multicharmTable { 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) @@ -723,33 +740,46 @@ struct alice3multicharmTable { picc.globalIndex()); multiCharmCore( - thisXiCcandidate.dca, thisXiCCcandidate.dca, - thisXiCcandidate.mass, thisXiCCcandidate.mass, - thisXiCCcandidate.pt, thisXiCCcandidate.eta, + thisXiCCcandidate.mass, thisXiCCcandidate.pt, + thisXiCCcandidate.eta, thisXiCCcandidate.dca, + thisXiCcandidate.mass, thisXiCcandidate.pt, + thisXiCcandidate.eta, thisXiCcandidate.dca, xi.dcaXY(), xi.dcaZ(), xicdcaXY, xicdcaZ, xiccdcaXY, xiccdcaZ, - piFromXi.dcaXY(), piFromXi.dcaZ(), - piFromLa.dcaXY(), piFromLa.dcaZ(), - prFromLa.dcaXY(), prFromLa.dcaZ(), pi1c.dcaXY(), pi1c.dcaZ(), pi2c.dcaXY(), pi2c.dcaZ(), picc.dcaXY(), picc.dcaZ(), xicDecayRadius2D, xiccDecayRadius2D, - xicProperLength, xicDecayDistanceFromPV, + xicProperLength, + xicDecayDistanceFromPV, xiccProperLength, + pi1c.pt(), + pi2c.pt(), + picc.pt()); + + 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(), - pi1c.pt(), pi1c.eta(), - pi2c.pt(), pi2c.eta(), - picc.pt(), picc.eta()); + piFromLa.dcaXY(), piFromLa.dcaZ(), + pi1c.eta(), pi2c.eta(), picc.eta()); } } histos.fill(HIST("hCombinationsXiCC"), nCombinationsCC); diff --git a/ALICE3/Tasks/CMakeLists.txt b/ALICE3/Tasks/CMakeLists.txt index 8fb4c79ea12..06864096cf5 100644 --- a/ALICE3/Tasks/CMakeLists.txt +++ b/ALICE3/Tasks/CMakeLists.txt @@ -61,10 +61,17 @@ o2physics_add_dpl_workflow(alice3-taskcorrelationddbar o2physics_add_dpl_workflow(alice3-multicharm SOURCES alice3-multicharm.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(alice3-efficiency SOURCES alice3Efficiency.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(alice3-tracking-performance + SOURCES alice3TrackingPerformance.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + diff --git a/ALICE3/Tasks/alice3-multicharm.cxx b/ALICE3/Tasks/alice3-multicharm.cxx index 34276a800b3..15989109919 100644 --- a/ALICE3/Tasks/alice3-multicharm.cxx +++ b/ALICE3/Tasks/alice3-multicharm.cxx @@ -17,59 +17,92 @@ // HF decays. Work in progress: use at your own risk! // -#include -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" +#include "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/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" #include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.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 "ALICE3/DataModel/OTFTOF.h" -#include "ALICE3/DataModel/RICH.h" -#include "ALICE3/DataModel/A3DecayFinderTables.h" -#include "ALICE3/DataModel/OTFStrangeness.h" -#include "ALICE3/DataModel/OTFMulticharm.h" -#include "ALICE3/DataModel/tracksAlice3.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" #include "DetectorsVertexing/PVertexer.h" #include "DetectorsVertexing/PVertexerHelpers.h" -#include "CommonConstants/PhysicsConstants.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::ml; using namespace o2::framework; using namespace o2::framework::expressions; -using multicharmtracks = soa::Join; +using multiCharmTracksPID = soa::Join; +using multiCharmTracksFull = soa::Join; +#define getHist(type, name) std::get>(histPointers[name]) struct alice3multicharm { - SliceCache cache; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::map histPointers; + 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 localPath{"localPath", "MCharm_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable pathCCDB{"btdPathCCDB", "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)"}; + Configurable enableML{"enableML", false, "Enables bdt model"}; + Configurable> requiredScores{"requiredScores", {0.5, 0.75, 0.85, 0.9, 0.95, 0.99}, "Vector of different scores to try"}; + } bdt; ConfigurableAxis axisEta{"axisEta", {80, -4.0f, +4.0f}, "#eta"}; + 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 axisDCA{"axisDCA", {400, 0, 400}, "DCA (#mum)"}; ConfigurableAxis axisRadiusLarge{"axisRadiusLarge", {1000, 0, 20}, "Decay radius (cm)"}; ConfigurableAxis axisRadius{"axisRadius", {10000, 0, 10000}, "Decay radius (#mum)"}; - ConfigurableAxis axisTofTrackDelta{"axisTofTrackDelta", {1000, 0, 5000}, "TOF track time"}; + ConfigurableAxis axisTofTrackDelta{"axisTofTrackDelta", {200, 0, 1000}, "TOF track time"}; + ConfigurableAxis axisNSigma{"axisNSigma", {21, -10, 10}, "nsigma"}; ConfigurableAxis axisDecayLength{"axisDecayLength", {2000, 0, 2000}, "Decay lenght (#mum)"}; ConfigurableAxis axisDcaDaughters{"axisDcaDaughters", {200, 0, 100}, "DCA (mum)"}; + ConfigurableAxis axisBDTScore{"axisBDTScore", {100, 0, 1}, "BDT Score"}; 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"}; Configurable xiMinDCAxy{"xiMinDCAxy", -1, "[0] in |DCAxy| > [0]+[1]/pT"}; @@ -78,12 +111,10 @@ struct alice3multicharm { Configurable picMinDCAxy{"picMinDCAxy", -1, "[0] in |DCAz| > [0]+[1]/pT"}; Configurable picMinDCAz{"picMinDCAz", -1, "[0] in |DCAxy| > [0]+[1]/pT"}; - Configurable picMaxTofDiffInner{"picTofDiffInner", 1e+4, "|signal - expected| (ps)"}; Configurable picMinPt{"picMinPt", -1, "Minimum pT for Xic pions"}; Configurable piccMinDCAxy{"piccMinDCAxy", -1, "[0] in |DCAxy| > [0]+[1]/pT"}; Configurable piccMinDCAz{"piccMinDCAz", -1, "[0] in |DCAz| > [0]+[1]/pT"}; - Configurable piccMaxTofDiffInner{"piccMaxTofDiffInner", 1e+4, "|signal - expected| (ps)"}; Configurable piccMinPt{"piccMinPt", -1, "Minimum pT for Xicc pions"}; Configurable xicMaxDauDCA{"xicMaxDauDCA", 1e+4, "DCA between Xic daughters (cm)"}; @@ -101,8 +132,6 @@ 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)"}; - HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - void init(InitContext&) { histos.add("SelectionQA/hDCAXicDaughters", "hDCAXicDaughters; DCA between Xic daughters (#mum)", kTH1D, {axisDcaDaughters}); @@ -113,87 +142,351 @@ struct alice3multicharm { histos.add("SelectionQA/hDCAzXic", "hDCAzXic; Xic DCAz to PV (#mum)", kTH1D, {axisDCA}); histos.add("SelectionQA/hDCAxyXicc", "hDCAxyXicc; Xicc DCAxy to PV (#mum)", kTH1D, {axisDCA}); histos.add("SelectionQA/hDCAzXicc", "hDCAzXicc; Xicc DCAz to PV (#mum)", kTH1D, {axisDCA}); + histos.add("SelectionQA/hDecayRadiusXic", "hDecayRadiusXic; Distance (#mum)", kTH1D, {axisRadius}); + histos.add("SelectionQA/hDecayRadiusXicc", "hDecayRadiusXicc; Distance (#mum)", kTH1D, {axisRadius}); + histos.add("SelectionQA/hDecayDistanceFromPVXic", "hDecayDistanceFromPVXic; Distance (#mum)", kTH1D, {axisDecayLength}); + histos.add("SelectionQA/hProperLengthXic", "hProperLengthXic; Distance (#mum)", kTH1D, {axisDecayLength}); + histos.add("SelectionQA/hProperLengthXicc", "hProperLengthXicc; Distance (#mum)", kTH1D, {axisDecayLength}); + histos.add("SelectionQA/hPi1cDCAxy", "hPi1cDCAxy; Pi1c DCAxy (#mum)", kTH1D, {axisDCA}); + histos.add("SelectionQA/hPi1cDCAz", "hPi1cDCAz; Pi1c DCAz (#mum)", kTH1D, {axisDCA}); + histos.add("SelectionQA/hPi2cDCAxy", "hPi2cDCAxy; Pi2c DCAxy (#mum)", kTH1D, {axisDCA}); + histos.add("SelectionQA/hPi2cDCAz", "hPi2cDCAz; Pi2c DCAz (#mum)", kTH1D, {axisDCA}); + histos.add("SelectionQA/hPiccDCAxy", "hPiccDCAxy; Picc DCAxy (#mum)", kTH1D, {axisDCA}); + histos.add("SelectionQA/hPiccDCAz", "hPiccDCAz; Picc DCAz (#mum)", kTH1D, {axisDCA}); histos.add("SelectionQA/hPi1cPt", "hPi1cPt; Pi1c pT (Gev/#it(c))", kTH1D, {axisPt}); histos.add("SelectionQA/hPi2cPt", "hPi2cPt; Pi2c pT (Gev/#it(c))", kTH1D, {axisPt}); histos.add("SelectionQA/hPiccPt", "hPiccPt; Picc pT (Gev/#it(c))", kTH1D, {axisPt}); - histos.add("SelectionQA/hXicDecayRadius", "hXicDecayRadius; Distance (#mum)", kTH1D, {axisRadius}); - histos.add("SelectionQA/hXiccDecayRadius", "hXiccDecayRadius; Distance (#mum)", kTH1D, {axisRadius}); - histos.add("SelectionQA/hXicDecayDistanceFromPV", "hXicDecayDistanceFromPV; Distance (#mum)", kTH1D, {axisDecayLength}); - histos.add("SelectionQA/hProperLengthXic", "hProperLengthXic; Distance (#mum)", kTH1D, {axisDecayLength}); - histos.add("SelectionQA/hProperLengthXicc", "hProperLengthXicc; Distance (#mum)", kTH1D, {axisDecayLength}); - histos.add("SelectionQA/hInnerTofTimeDeltaPi1c", "hInnerTofTimeDeltaPi1c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("SelectionQA/hInnerTofTimeDeltaPi2c", "hInnerTofTimeDeltaPi2c; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - histos.add("SelectionQA/hInnerTofTimeDeltaPicc", "hInnerTofTimeDeltaPicc; Reco - expected pion (ps)", kTH1D, {axisTofTrackDelta}); - - 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}); - histos.add("XiccProngs/h3dBach", "h3dBach; Xicc pT (GeV/#it(c)); Bach pT (GeV/#it(c)); Bach #eta", kTH3D, {axisPt, axisPt, axisEta}); - histos.add("XiccProngs/h3dPi1c", "h3dPi1c; Xicc pT (GeV/#it(c)); Pi1c pT (GeV/#it(c)); Pi1c #eta", kTH3D, {axisPt, axisPt, axisEta}); - histos.add("XiccProngs/h3dPi2c", "h3dPi2c; Xicc pT (GeV/#it(c)); Pi2c pT (GeV/#it(c)); Pi2c #eta", kTH3D, {axisPt, axisPt, axisEta}); - histos.add("XiccProngs/h3dPicc", "h3dPicc; Xicc pT (GeV/#it(c)); Picc pT (GeV/#it(c)); Picc #eta", kTH3D, {axisPt, axisPt, axisEta}); + + auto hMCharmBuilding = histos.add("hMCharmBuilding", "hMCharmBuilding", kTH1D, {{22, -0.5, 21.5}}); + hMCharmBuilding->GetXaxis()->SetBinLabel(1, "nTotalCandidates"); + hMCharmBuilding->GetXaxis()->SetBinLabel(2, "xicMaxDauDCA"); + hMCharmBuilding->GetXaxis()->SetBinLabel(3, "xiccMaxDauDCA"); + hMCharmBuilding->GetXaxis()->SetBinLabel(4, "xiMinDCAxy"); + hMCharmBuilding->GetXaxis()->SetBinLabel(5, "xiMinDCAz"); + hMCharmBuilding->GetXaxis()->SetBinLabel(6, "pi1cMinDCAxy"); + hMCharmBuilding->GetXaxis()->SetBinLabel(7, "pi1cMinDCAz"); + hMCharmBuilding->GetXaxis()->SetBinLabel(8, "pi2cMinDCAxy"); + hMCharmBuilding->GetXaxis()->SetBinLabel(9, "pi2cMinDCAz"); + hMCharmBuilding->GetXaxis()->SetBinLabel(10, "piccMinDCAxy"); + hMCharmBuilding->GetXaxis()->SetBinLabel(11, "piccMinDCAz"); + hMCharmBuilding->GetXaxis()->SetBinLabel(12, "xicMinDCAxy"); + hMCharmBuilding->GetXaxis()->SetBinLabel(13, "xicMinDCAz"); + hMCharmBuilding->GetXaxis()->SetBinLabel(14, "xiccMaxDCAxy"); + hMCharmBuilding->GetXaxis()->SetBinLabel(15, "xiccMaxDCAz"); + hMCharmBuilding->GetXaxis()->SetBinLabel(16, "xicMinRadius"); + hMCharmBuilding->GetXaxis()->SetBinLabel(17, "xiccMinRadius"); + hMCharmBuilding->GetXaxis()->SetBinLabel(18, "xicMinProperLength"); + hMCharmBuilding->GetXaxis()->SetBinLabel(19, "xicMaxProperLength"); + hMCharmBuilding->GetXaxis()->SetBinLabel(20, "xiccMinProperLength"); + 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}); + histos.add("XiccProngs/h3dBach", "h3dBach; Xicc pT (GeV/#it(c)); Bach pT (GeV/#it(c)); Bach #eta", kTH3D, {axisPt, axisPt, axisEta}); + histos.add("XiccProngs/h3dPi1c", "h3dPi1c; Xicc pT (GeV/#it(c)); Pi1c pT (GeV/#it(c)); Pi1c #eta", kTH3D, {axisPt, axisPt, axisEta}); + histos.add("XiccProngs/h3dPi2c", "h3dPi2c; Xicc pT (GeV/#it(c)); Pi2c pT (GeV/#it(c)); Pi2c #eta", kTH3D, {axisPt, axisPt, axisEta}); + histos.add("XiccProngs/h3dPicc", "h3dPicc; Xicc pT (GeV/#it(c)); Picc pT (GeV/#it(c)); Picc #eta", kTH3D, {axisPt, axisPt, axisEta}); + } + + histos.add("hXiccMass", "hXiccMass", kTH1D, {axisXiccMass}); + histos.add("hXicMass", "hXicMass", kTH1D, {axisXicMass}); + histos.add("hXiccPt", "hXiccPt", kTH1D, {axisPt}); + histos.add("hXicPt", "hXicPt", kTH1D, {axisPt}); histos.add("h3dXicc", "h3dXicc; Xicc pT (GeV/#it(c)); Xicc #eta; Xicc mass (GeV/#it(c)^{2})", kTH3D, {axisPt, axisEta, axisXiccMass}); + + if (bdt.enableML) { + ccdb->setURL(bdt.ccdbUrl.value); + if (bdt.loadModelsFromCCDB) { + ccdbApi.init(bdt.ccdbUrl); + LOG(info) << "Fetching model for timestamp: " << bdt.timestampCCDB.value; + bool retrieveSuccessMCharm = ccdbApi.retrieveBlob(bdt.pathCCDB.value, ".", metadata, bdt.timestampCCDB.value, false, bdt.localPath.value); + + if (retrieveSuccessMCharm) { + bdtMCharm.initModel(bdt.localPath.value, bdt.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the MCharm model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + bdtMCharm.initModel(bdt.localPath.value, bdt.enableOptimizations.value); + } + + histos.add("hBDTScore", "hBDTScore", kTH1D, {axisBDTScore}); + histos.add("hBDTScoreVsXiccMass", "hBDTScoreVsXiccMass", kTH2D, {axisXiccMass, axisBDTScore}); + histos.add("hBDTScoreVsXiccPt", "hBDTScoreVsXiccPt", kTH2D, {axisPt, axisBDTScore}); + histos.add("h3dBDTScore", "h3dBDTScore", kTH3D, {axisPt, axisXiccMass, axisBDTScore}); + for (const auto& score : bdt.requiredScores.value) { + histPath = std::format("MLQA/RequiredBDTScore_{}/", static_cast(score * 100)); + histPointers.insert({histPath + "hDCAXicDaughters", histos.add((histPath + "hDCAXicDaughters").c_str(), "hDCAXicDaughters", {kTH1D, {{axisDcaDaughters}}})}); + histPointers.insert({histPath + "hDCAXiccDaughters", histos.add((histPath + "hDCAXiccDaughters").c_str(), "hDCAXiccDaughters", {kTH1D, {{axisDcaDaughters}}})}); + histPointers.insert({histPath + "hDCAxyXi", histos.add((histPath + "hDCAxyXi").c_str(), "hDCAxyXi", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hDCAzXi", histos.add((histPath + "hDCAzXi").c_str(), "hDCAzXi", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hDCAxyXic", histos.add((histPath + "hDCAxyXic").c_str(), "hDCAxyXic", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hDCAzXic", histos.add((histPath + "hDCAzXic").c_str(), "hDCAzXic", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hDCAxyXicc", histos.add((histPath + "hDCAxyXicc").c_str(), "hDCAxyXicc", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hDCAzXicc", histos.add((histPath + "hDCAzXicc").c_str(), "hDCAzXicc", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hDecayRadiusXic", histos.add((histPath + "hDecayRadiusXic").c_str(), "hDecayRadiusXic", {kTH1D, {{axisRadius}}})}); + histPointers.insert({histPath + "hDecayRadiusXicc", histos.add((histPath + "hDecayRadiusXicc").c_str(), "hDecayRadiusXicc", {kTH1D, {{axisRadius}}})}); + histPointers.insert({histPath + "hDecayDistanceFromPVXic", histos.add((histPath + "hDecayDistanceFromPVXic").c_str(), "hDecayDistanceFromPVXic", {kTH1D, {{axisDecayLength}}})}); + histPointers.insert({histPath + "hProperLengthXic", histos.add((histPath + "hProperLengthXic").c_str(), "hProperLengthXic", {kTH1D, {{axisDecayLength}}})}); + histPointers.insert({histPath + "hProperLengthXicc", histos.add((histPath + "hProperLengthXicc").c_str(), "hProperLengthXicc", {kTH1D, {{axisDecayLength}}})}); + histPointers.insert({histPath + "hPi1cDCAxy", histos.add((histPath + "hPi1cDCAxy").c_str(), "hPi1cDCAxy", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hPi1cDCAz", histos.add((histPath + "hPi1cDCAz").c_str(), "hPi1cDCAxy", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hPi2cDCAxy", histos.add((histPath + "hPi2cDCAxy").c_str(), "hPi2cDCAxy", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hPi2cDCAz", histos.add((histPath + "hPi2cDCAz").c_str(), "hPi2cDCAz", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hPiccDCAxy", histos.add((histPath + "hPiccDCAxy").c_str(), "hPiccDCAxy", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hPiccDCAz", histos.add((histPath + "hPiccDCAz").c_str(), "hPiccDCAz", {kTH1D, {{axisDCA}}})}); + histPointers.insert({histPath + "hPi1cPt", histos.add((histPath + "hPi1cPt").c_str(), "hPi1cPt", {kTH1D, {{axisPt}}})}); + histPointers.insert({histPath + "hPi2cPt", histos.add((histPath + "hPi2cPt").c_str(), "hPi2cPt", {kTH1D, {{axisPt}}})}); + histPointers.insert({histPath + "hPiccPt", histos.add((histPath + "hPiccPt").c_str(), "hPiccPt", {kTH1D, {{axisPt}}})}); + histPointers.insert({histPath + "h3dXicc", histos.add((histPath + "h3dXicc").c_str(), "h3dXicc", {kTH3D, {{axisPt, axisEta, axisXiccMass}}})}); + histPointers.insert({histPath + "hXiccMass", histos.add((histPath + "hXiccMass").c_str(), "hXiccMass", {kTH1D, {{axisXiccMass}}})}); + histPointers.insert({histPath + "hXicMass", histos.add((histPath + "hXicMass").c_str(), "hXicMass", {kTH1D, {{axisXicMass}}})}); + histPointers.insert({histPath + "hXiccPt", histos.add((histPath + "hXiccPt").c_str(), "hXiccPt", {kTH1D, {{axisPt}}})}); + histPointers.insert({histPath + "hXicPt", histos.add((histPath + "hXicPt").c_str(), "hXicPt", {kTH1D, {{axisPt}}})}); + } + } + } + + int getBin(const std::map& pdgToBin, int pdg) + { + auto it = pdgToBin.find(pdg); + return (it != pdgToBin.end()) ? it->second : 7; } - void processXicc(multicharmtracks const& multiCharmTracks) + template + void genericProcessXicc(TMCharmCands const& xiccCands) { - for (const auto& xiccCand : multiCharmTracks) { - if (xiccCand.xicDauDCA() > xicMaxDauDCA || xiccCand.xiccDauDCA() > xiccMaxDauDCA) + for (const auto& xiccCand : xiccCands) { + if (bdt.enableML) { + std::vector inputFeatures{ + xiccCand.xicDauDCA(), + xiccCand.xiccDauDCA(), + xiccCand.xiDCAxy(), + xiccCand.xicDCAxy(), + xiccCand.xiccDCAxy(), + xiccCand.xiDCAz(), + xiccCand.xicDCAz(), + xiccCand.xiccDCAz(), + xiccCand.pi1cDCAxy(), + xiccCand.pi2cDCAxy(), + xiccCand.piccDCAxy(), + xiccCand.pi1cDCAz(), + xiccCand.pi2cDCAz(), + xiccCand.piccDCAz(), + xiccCand.xicDecayRadius2D(), + xiccCand.xiccDecayRadius2D(), + xiccCand.xicProperLength(), + xiccCand.xicDistanceFromPV(), + xiccCand.xiccProperLength()}; + + float* probabilityMCharm = bdtMCharm.evalModel(inputFeatures); + float bdtScore = probabilityMCharm[1]; + + histos.fill(HIST("hBDTScore"), bdtScore); + histos.fill(HIST("hBDTScoreVsXiccMass"), xiccCand.xiccMass(), bdtScore); + histos.fill(HIST("hBDTScoreVsXiccPt"), xiccCand.xiccPt(), bdtScore); + histos.fill(HIST("h3dBDTScore"), xiccCand.xiccPt(), xiccCand.xiccMass(), bdtScore); + + for (const auto& requiredScore : bdt.requiredScores.value) { + if (bdtScore > requiredScore) { + histPath = std::format("MLQA/RequiredBDTScore_{}/", static_cast(requiredScore * 100)); + getHist(TH1, histPath + "hDCAXicDaughters")->Fill(xiccCand.xicDauDCA() * 1e+4); + getHist(TH1, histPath + "hDCAXiccDaughters")->Fill(xiccCand.xiccDauDCA() * 1e+4); + getHist(TH1, histPath + "hDCAxyXi")->Fill(std::fabs(xiccCand.xiDCAxy() * 1e+4)); + getHist(TH1, histPath + "hDCAzXi")->Fill(std::fabs(xiccCand.xiDCAz() * 1e+4)); + getHist(TH1, histPath + "hDCAxyXic")->Fill(std::fabs(xiccCand.xicDCAxy() * 1e+4)); + getHist(TH1, histPath + "hDCAzXic")->Fill(std::fabs(xiccCand.xicDCAz() * 1e+4)); + getHist(TH1, histPath + "hDCAxyXicc")->Fill(std::fabs(xiccCand.xiccDCAxy() * 1e+4)); + getHist(TH1, histPath + "hDCAzXicc")->Fill(std::fabs(xiccCand.xiccDCAz() * 1e+4)); + getHist(TH1, histPath + "hDecayRadiusXic")->Fill(xiccCand.xicDecayRadius2D() * 1e+4); + getHist(TH1, histPath + "hDecayRadiusXicc")->Fill(xiccCand.xiccDecayRadius2D() * 1e+4); + getHist(TH1, histPath + "hDecayDistanceFromPVXic")->Fill(xiccCand.xicDistanceFromPV() * 1e+4); + getHist(TH1, histPath + "hProperLengthXic")->Fill(xiccCand.xicProperLength() * 1e+4); + getHist(TH1, histPath + "hProperLengthXicc")->Fill(xiccCand.xiccProperLength() * 1e+4); + getHist(TH1, histPath + "hPi1cDCAxy")->Fill(xiccCand.pi1cDCAxy() * 1e+4); + getHist(TH1, histPath + "hPi1cDCAz")->Fill(xiccCand.pi1cDCAz() * 1e+4); + getHist(TH1, histPath + "hPi2cDCAxy")->Fill(xiccCand.pi2cDCAxy() * 1e+4); + getHist(TH1, histPath + "hPi2cDCAz")->Fill(xiccCand.pi2cDCAz() * 1e+4); + getHist(TH1, histPath + "hPiccDCAxy")->Fill(xiccCand.piccDCAxy() * 1e+4); + getHist(TH1, histPath + "hPiccDCAz")->Fill(xiccCand.piccDCAz() * 1e+4); + getHist(TH1, histPath + "hPi1cDCAz")->Fill(xiccCand.pi1cPt()); + getHist(TH1, histPath + "hPi2cDCAz")->Fill(xiccCand.pi2cPt()); + getHist(TH1, histPath + "hPiccDCAz")->Fill(xiccCand.piccPt()); + getHist(TH1, histPath + "hXiccMass")->Fill(xiccCand.xiccMass()); + getHist(TH1, histPath + "hXicMass")->Fill(xiccCand.xicMass()); + getHist(TH1, histPath + "hXiccPt")->Fill(xiccCand.xiccPt()); + getHist(TH1, histPath + "hXicPt")->Fill(xiccCand.xicPt()); + getHist(TH3, histPath + "h3dXicc")->Fill(xiccCand.xiccPt(), xiccCand.xiccEta(), xiccCand.xiccMass()); + } + } + } + + histos.fill(HIST("hMCharmBuilding"), 0); + if (xiccCand.xicDauDCA() > xicMaxDauDCA) { + continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 1); + } + + if (xiccCand.xiccDauDCA() > xiccMaxDauDCA) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 2); + } - if (std::fabs(xiccCand.xiDCAxy()) < xiMinDCAxy || std::fabs(xiccCand.xiDCAz()) < xiMinDCAz) + if (std::fabs(xiccCand.xiDCAxy()) < xiMinDCAxy) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 3); + } - if (std::fabs(xiccCand.pi1cDCAxy()) < picMinDCAxy || std::fabs(xiccCand.pi1cDCAz()) < picMinDCAz) + if (std::fabs(xiccCand.xiDCAz()) < xiMinDCAz) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 4); + } - if (std::fabs(xiccCand.pi2cDCAxy()) < picMinDCAxy || std::fabs(xiccCand.pi2cDCAz()) < picMinDCAz) + if (std::fabs(xiccCand.pi1cDCAxy()) < picMinDCAxy) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 5); + } - if (std::fabs(xiccCand.piccDCAxy()) < piccMinDCAxy || std::fabs(xiccCand.piccDCAz()) < piccMinDCAz) + if (std::fabs(xiccCand.pi1cDCAz()) < picMinDCAz) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 6); + } - if (std::fabs(xiccCand.xicDCAxy()) < xicMinDCAxy || std::fabs(xiccCand.xicDCAz()) < xicMinDCAz) + if (std::fabs(xiccCand.pi2cDCAxy()) < picMinDCAxy) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 7); + } - if (std::fabs(xiccCand.pi1cDCAxy()) < picMinDCAxy || std::fabs(xiccCand.pi1cDCAz()) < picMinDCAz) + if (std::fabs(xiccCand.pi2cDCAz()) < picMinDCAz) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 8); + } - if (std::fabs(xiccCand.pi2cDCAxy()) < picMinDCAxy || std::fabs(xiccCand.pi2cDCAz()) < picMinDCAz) + if (std::fabs(xiccCand.piccDCAxy()) < piccMinDCAxy) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 9); + } - if (std::fabs(xiccCand.xiccDCAxy()) > xiccMaxDCAxy || std::fabs(xiccCand.xiccDCAz()) > xiccMaxDCAz) + if (std::fabs(xiccCand.piccDCAz()) < piccMinDCAz) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 10); + } - // Cut on time delta as LoI for now - if (xiccCand.pi1cTofDeltaInner() > picMaxTofDiffInner) + if (std::fabs(xiccCand.xicDCAxy()) < xicMinDCAxy) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 11); + } - if (xiccCand.pi2cTofDeltaInner() > picMaxTofDiffInner) + if (std::fabs(xiccCand.xicDCAz()) < xicMinDCAz) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 12); + } - if (xiccCand.piccTofDeltaInner() > piccMaxTofDiffInner) + if (std::fabs(xiccCand.xiccDCAxy()) > xiccMaxDCAxy) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 13); + } - if (xiccCand.pi1cPt() < picMinPt || xiccCand.pi2cPt() < picMinPt) + if (std::fabs(xiccCand.xiccDCAz()) > xiccMaxDCAz) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 14); + } - if (xiccCand.piccPt() < piccMinPt) + if (xiccCand.xicDecayRadius2D() < xicMinRadius) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 15); + } - if (xiccCand.xicDecayRadius2D() < xicMinRadius) + if (xiccCand.xiccDecayRadius2D() < xiccMinRadius) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 16); + } - if (xiccCand.xiccDecayRadius2D() < xiccMinRadius) + if (xiccCand.xicProperLength() < xicMinProperLength) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 17); + } - if (xiccCand.xicProperLength() < xicMinProperLength || xiccCand.xicProperLength() > xicMaxProperLength) + if (xiccCand.xicProperLength() > xicMaxProperLength) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 18); + } - if (xiccCand.xiccProperLength() < xiccMinProperLength || xiccCand.xiccProperLength() > xiccMaxProperLength) + if (xiccCand.xiccProperLength() < xiccMinProperLength) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 19); + } - if (xiccCand.xicDistanceFromPV() < xicMinDecayDistanceFromPV) + if (xiccCand.xiccProperLength() > xiccMaxProperLength) { continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 20); + } + + if (xiccCand.xicDistanceFromPV() < xicMinDecayDistanceFromPV) { + continue; + } else { + histos.fill(HIST("hMCharmBuilding"), 21); + } histos.fill(HIST("SelectionQA/hDCAXicDaughters"), xiccCand.xicDauDCA() * 1e+4); histos.fill(HIST("SelectionQA/hDCAXiccDaughters"), xiccCand.xiccDauDCA() * 1e+4); @@ -203,29 +496,84 @@ struct alice3multicharm { histos.fill(HIST("SelectionQA/hDCAzXic"), std::fabs(xiccCand.xicDCAz() * 1e+4)); histos.fill(HIST("SelectionQA/hDCAxyXicc"), std::fabs(xiccCand.xiccDCAxy() * 1e+4)); histos.fill(HIST("SelectionQA/hDCAzXicc"), std::fabs(xiccCand.xiccDCAz() * 1e+4)); + histos.fill(HIST("SelectionQA/hDecayRadiusXic"), xiccCand.xicDecayRadius2D() * 1e+4); + histos.fill(HIST("SelectionQA/hDecayRadiusXicc"), xiccCand.xiccDecayRadius2D() * 1e+4); + histos.fill(HIST("SelectionQA/hDecayDistanceFromPVXic"), xiccCand.xicDistanceFromPV() * 1e+4); + histos.fill(HIST("SelectionQA/hProperLengthXic"), xiccCand.xicProperLength() * 1e+4); + histos.fill(HIST("SelectionQA/hProperLengthXicc"), xiccCand.xiccProperLength() * 1e+4); + histos.fill(HIST("SelectionQA/hPi1cDCAxy"), xiccCand.pi1cDCAxy() * 1e+4); + histos.fill(HIST("SelectionQA/hPi1cDCAz"), xiccCand.pi1cDCAz() * 1e+4); + histos.fill(HIST("SelectionQA/hPi2cDCAxy"), xiccCand.pi2cDCAxy() * 1e+4); + histos.fill(HIST("SelectionQA/hPi2cDCAz"), xiccCand.pi2cDCAz() * 1e+4); + histos.fill(HIST("SelectionQA/hPiccDCAxy"), xiccCand.piccDCAxy() * 1e+4); + histos.fill(HIST("SelectionQA/hPiccDCAz"), xiccCand.piccDCAz() * 1e+4); histos.fill(HIST("SelectionQA/hPi1cPt"), xiccCand.pi1cPt()); histos.fill(HIST("SelectionQA/hPi2cPt"), xiccCand.pi2cPt()); histos.fill(HIST("SelectionQA/hPiccPt"), xiccCand.piccPt()); - histos.fill(HIST("SelectionQA/hXicDecayRadius"), xiccCand.xicDecayRadius2D() * 1e+4); - histos.fill(HIST("SelectionQA/hXiccDecayRadius"), xiccCand.xiccDecayRadius2D() * 1e+4); - histos.fill(HIST("SelectionQA/hXicDecayDistanceFromPV"), xiccCand.xicDistanceFromPV() * 1e+4); - histos.fill(HIST("SelectionQA/hProperLengthXic"), xiccCand.xicProperLength() * 1e+4); - histos.fill(HIST("SelectionQA/hProperLengthXicc"), xiccCand.xiccProperLength() * 1e+4); - histos.fill(HIST("SelectionQA/hInnerTofTimeDeltaPi1c"), xiccCand.pi1cTofDeltaInner()); - histos.fill(HIST("SelectionQA/hInnerTofTimeDeltaPi2c"), xiccCand.pi2cTofDeltaInner()); - histos.fill(HIST("SelectionQA/hInnerTofTimeDeltaPicc"), xiccCand.piccTofDeltaInner()); - - histos.fill(HIST("XiccProngs/h3dNeg"), xiccCand.pt(), xiccCand.negPt(), xiccCand.negEta()); - histos.fill(HIST("XiccProngs/h3dPos"), xiccCand.pt(), xiccCand.posPt(), xiccCand.posEta()); - histos.fill(HIST("XiccProngs/h3dBach"), xiccCand.pt(), xiccCand.bachPt(), xiccCand.bachEta()); - histos.fill(HIST("XiccProngs/h3dPi1c"), xiccCand.pt(), xiccCand.pi1cPt(), xiccCand.pi1cEta()); - histos.fill(HIST("XiccProngs/h3dPi2c"), xiccCand.pt(), xiccCand.pi2cPt(), xiccCand.pi2cEta()); - histos.fill(HIST("XiccProngs/h3dPicc"), xiccCand.pt(), xiccCand.piccPt(), xiccCand.piccEta()); - histos.fill(HIST("h3dXicc"), xiccCand.pt(), xiccCand.eta(), xiccCand.xiccMass()); + + 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()); + histos.fill(HIST("XiccProngs/h3dBach"), xiccCand.xiccPt(), xiccCand.bachPt(), xiccCand.bachEta()); + histos.fill(HIST("XiccProngs/h3dPi1c"), xiccCand.xiccPt(), xiccCand.pi1cPt(), xiccCand.pi1cEta()); + histos.fill(HIST("XiccProngs/h3dPi2c"), xiccCand.xiccPt(), xiccCand.pi2cPt(), xiccCand.pi2cEta()); + histos.fill(HIST("XiccProngs/h3dPicc"), xiccCand.xiccPt(), xiccCand.piccPt(), xiccCand.piccEta()); + } + + histos.fill(HIST("hXiccMass"), xiccCand.xiccMass()); + histos.fill(HIST("hXicMass"), xiccCand.xicMass()); + histos.fill(HIST("hXiccPt"), xiccCand.xiccPt()); + histos.fill(HIST("hXicPt"), xiccCand.xicPt()); + histos.fill(HIST("h3dXicc"), xiccCand.xiccPt(), xiccCand.xiccEta(), xiccCand.xiccMass()); } } + void processXicc(aod::MCharmCores const& multiCharmTracks) + { + genericProcessXicc(multiCharmTracks); + } + + void processXiccPID(multiCharmTracksPID const& multiCharmTracks) + { + genericProcessXicc(multiCharmTracks); + } + + void processXiccExtra(multiCharmTracksFull 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); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/ALICE3/Tasks/alice3TrackingPerformance.cxx b/ALICE3/Tasks/alice3TrackingPerformance.cxx new file mode 100644 index 00000000000..bfb9418bb2c --- /dev/null +++ b/ALICE3/Tasks/alice3TrackingPerformance.cxx @@ -0,0 +1,94 @@ +// 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 alice3TrackingPerformance.cxx +/// +/// \brief This task produces the tracking performance +/// +/// \author Nicolò Jacazio, Universita del Piemonte Orientale (IT) +/// \since May 27, 2025 +/// + +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/ConfigParamRegistry.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" + +#include +#include + +using namespace o2; +using namespace o2::framework; +std::map> ptResolutionVsPt; +std::map> invPtResolutionVsPt; +std::map> dcaXyResolutionVsPt; +std::map> dcaZResolutionVsPt; + +struct alice3TrackingPerformance { + Configurable> pdgCodes{"pdgCodes", {211}, "List of PDG codes to consider for efficiency calculation"}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + Configurable> etaRange{"etaRange", {-5.f, 5.f}, "Eta range for efficiency calculation"}; + + void init(o2::framework::InitContext&) + { + const AxisSpec axisPt{100, 0, 10, "p_{T} (GeV/c)"}; + const AxisSpec axisPtDelta{100, -1, 1, "p_{T}^{gen} - p_{T}^{reco} (GeV/c)"}; + const AxisSpec axisInvPtDelta{100, -1, 1, "1./p_{T}^{gen} - 1./p_{T}^{reco} (GeV/c)^{-1}"}; + const AxisSpec axisDcaXy{100, -1, 1, "DCA_{xy} (cm)"}; + const AxisSpec axisDcaZ{100, -1, 1, "DCA_{z} (cm)"}; + for (auto pdg : pdgCodes.value) { + ptResolutionVsPt[pdg] = histos.add(Form("ptResolutionVsPt_%d", pdg), "", kTH2D, {axisPt, axisPtDelta}); + invPtResolutionVsPt[pdg] = histos.add(Form("invPtResolutionVsPt_%d", pdg), "", kTH2D, {axisPt, axisInvPtDelta}); + dcaXyResolutionVsPt[pdg] = histos.add(Form("dcaXyResolutionVsPt_%d", pdg), "", kTH2D, {axisPt, axisDcaXy}); + dcaZResolutionVsPt[pdg] = histos.add(Form("dcaZResolutionVsPt_%d", pdg), "", kTH2D, {axisPt, axisDcaZ}); + } + } + + void process(soa::Join const& tracks, + aod::McParticles const&) + { + auto isParticleSelected = [&](const o2::aod::McParticle& p) { + if (!p.isPhysicalPrimary()) { + return false; + } + if (p.eta() < etaRange.value.first) { + return false; + } + if (p.eta() > etaRange.value.second) { + return false; + } + return true; + }; + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + const auto& mcParticle = track.mcParticle(); + if (!isParticleSelected(mcParticle)) { + continue; + } + if (ptResolutionVsPt.find(mcParticle.pdgCode()) == ptResolutionVsPt.end()) { + continue; + } + ptResolutionVsPt[mcParticle.pdgCode()]->Fill(mcParticle.pt(), mcParticle.pt() - track.pt()); + invPtResolutionVsPt[mcParticle.pdgCode()]->Fill(mcParticle.pt(), 1.f / mcParticle.pt() - 1.f / track.pt()); + dcaXyResolutionVsPt[mcParticle.pdgCode()]->Fill(mcParticle.pt(), track.dcaXY()); + dcaZResolutionVsPt[mcParticle.pdgCode()]->Fill(mcParticle.pt(), track.dcaZ()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& ctx) +{ + return WorkflowSpec{adaptAnalysisTask(ctx)}; +} diff --git a/ALICE3/Tools/handleParamTOFResoALICE3.cxx b/ALICE3/Tools/handleParamTOFResoALICE3.cxx deleted file mode 100644 index 79184cfd8d2..00000000000 --- a/ALICE3/Tools/handleParamTOFResoALICE3.cxx +++ /dev/null @@ -1,132 +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 handleParamTOFResoALICE3.cxx -/// \author Nicolo' Jacazio -/// \since 2020-06-22 -/// \brief A simple tool to produce Bethe Bloch parametrization objects for the TOF PID Response -/// - -#include "CCDB/CcdbApi.h" -#include -#include "Framework/Logger.h" -#include "TFile.h" -#include "ALICE3/Core/TOFResoALICE3.h" - -using namespace o2::pid::tof; -namespace bpo = boost::program_options; - -bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv[], bpo::variables_map& vm) -{ - options.add_options()( - "url,u", bpo::value()->default_value("http://alice-ccdb.cern.ch"), "URL of the CCDB database")( - "ccdb-path,c", bpo::value()->default_value("Analysis/ALICE3/PID/TOF"), "CCDB path for storage/retrieval")( - "start,s", bpo::value()->default_value(0), "Start timestamp of object validity")( - "stop,S", bpo::value()->default_value(4108971600000), "Stop timestamp of object validity")( - "delete-previous,delete_previous,d", bpo::value()->default_value(0), "Flag to delete previous versions of converter objects in the CCDB before uploading the new one so as to avoid proliferation on CCDB")( - "save-to-file,file,f,o", bpo::value()->default_value(""), "Option to save parametrization to file instead of uploading to ccdb")( - "read-from-file,i", bpo::value()->default_value(""), "Option to get parametrization from a file")( - "reso-name,n", bpo::value()->default_value("TOFResoALICE3"), "Name of the parametrization object")( - "mode,m", bpo::value()->default_value(1), "Working mode: 0 push 1 pull and test")( - "p0", bpo::value()->default_value(20.0f), "Parameter 0 of the TOF resolution: average TOF resolution")( - "verbose,v", bpo::value()->default_value(0), "Verbose level 0, 1")( - "help,h", "Produce help message."); - try { - bpo::store(parse_command_line(argc, argv, options), vm); - - // help - if (vm.count("help")) { - LOG(info) << options; - return false; - } - - bpo::notify(vm); - } catch (const bpo::error& e) { - LOG(error) << e.what() << "\n"; - LOG(error) << "Error parsing command line arguments; Available options:"; - LOG(error) << options; - return false; - } - return true; -} - -int main(int argc, char* argv[]) -{ - bpo::options_description options("Allowed options"); - bpo::variables_map vm; - if (!initOptionsAndParse(options, argc, argv, vm)) { - return 1; - } - - const unsigned int mode = vm["mode"].as(); - const std::string path = vm["ccdb-path"].as(); - std::map metadata; - std::map* headers = nullptr; - o2::ccdb::CcdbApi api; - const std::string url = vm["url"].as(); - api.init(url); - if (!api.isHostReachable()) { - LOG(warning) << "CCDB host " << url << " is not reacheable, cannot go forward"; - return 1; - } - TOFResoALICE3* reso = nullptr; - const std::string reso_name = vm["reso-name"].as(); - if (mode == 0) { // Push mode - LOG(info) << "Handling TOF parametrization in create mode"; - const std::string input_file_name = vm["read-from-file"].as(); - if (!input_file_name.empty()) { - TFile f(input_file_name.data(), "READ"); - if (!f.IsOpen()) { - LOG(warning) << "Input file " << input_file_name << " is not reacheable, cannot get param from file"; - } - f.GetObject(reso_name.c_str(), reso); - f.Close(); - } - if (!reso) { - reso = new TOFResoALICE3(); - const std::vector resoparams = {vm["p0"].as()}; - reso->SetParameters(resoparams); - } - reso->Print(); - const std::string fname = vm["save-to-file"].as(); - if (!fname.empty()) { // Saving it to file - LOG(info) << "Saving parametrization to file " << fname; - TFile f(fname.data(), "RECREATE"); - reso->Write(); - reso->GetParameters().Write(); - f.ls(); - f.Close(); - } else { // Saving it to CCDB - LOG(info) << "Saving parametrization to CCDB " << path; - - long start = vm["start"].as(); - long stop = vm["stop"].as(); - - if (vm["delete-previous"].as()) { - api.truncate(path); - } - api.storeAsTFileAny(reso, path + "/" + reso_name, metadata, start, stop); - o2::pid::Parameters* params; - reso->GetParameters(params); - api.storeAsTFileAny(params, path + "/Parameters/" + reso_name, metadata, start, stop); - } - } else { // Pull and test mode - LOG(info) << "Handling TOF parametrization in test mode"; - const float x[7] = {1, 1, 1, 1, 1, 1, 1}; // mom, time, ev. reso, mass, length, sigma1pt, pt - reso = api.retrieveFromTFileAny(path + "/" + reso_name, metadata, -1, headers); - reso->Print(); - LOG(info) << "TOF expected resolution at p=" << x[0] << " GeV/c " - << " and mass " << x[3] << ":" << reso->operator()(x); - } - - return 0; -} diff --git a/CODEOWNERS b/CODEOWNERS index 3891598e0e8..57766839579 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -36,19 +36,21 @@ /PWGCF/Tasks @alibuild @jgrosseo @saganatt @victor-gonzalez @zchochul @lgraczykCern @prchakra @lauraser @ariedel-cern @EmilGorm @otonvd @shouqiye @glromane /PWGDQ @alibuild @iarsene @mcoquet642 @lucamicheletti93 /PWGEM @alibuild @feisenhu @dsekihat @ivorobye -/PWGEM/Dilepton @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu +/PWGEM/Dilepton @alibuild @mikesas @rbailhac @dsekihat @ivorobye @feisenhu @hscheid /PWGEM/PhotonMeson @alibuild @mikesas @rbailhac @m-c-danisch @novitzky @mhemmer-cern @dsekihat /PWGHF @alibuild @vkucera @fcolamar @fgrosa @fcatalan92 @mfaggin @mmazzilli @deepathoms @NicoleBastid @hahassan7 @jpxrk @apalasciano @zhangbiao-phy @gluparel # PWG-LF /PWGLF @alibuild @sustripathy @skundu692 -/PWGLF/Tasks/GlobalEventProperties @alibuild @sustripathy @skundu692 @gbencedi @abmodak @omvazque +/PWGLF/DataModel @alibuild @sustripathy @skundu692 @gbencedi @abmodak @fmazzasc @maciacco @dmallick2 @smaff92 @ercolessi @romainschotter +/PWGLF/Tasks/GlobalEventProperties @alibuild @sustripathy @skundu692 @gbencedi @abmodak @omvazque /PWGLF/TableProducer/GlobalEventProperties @alibuild @sustripathy @skundu692 @gbencedi @abmodak @omvazque -/PWGLF/Tasks/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @chiarapinto @maciacco -/PWGLF/TableProducer/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @chiarapinto @maciacco -/PWGLF/Tasks/Resonances @alibuild @sustripathy @skundu692 @dmallick2 @smaff92 +/PWGLF/Tasks/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @maciacco +/PWGLF/TableProducer/Nuspex @alibuild @sustripathy @skundu692 @fmazzasc @maciacco +/PWGLF/Tasks/Resonances @alibuild @sustripathy @skundu692 @dmallick2 @smaff92 /PWGLF/TableProducer/Resonances @alibuild @sustripathy @skundu692 @dmallick2 @smaff92 -/PWGLF/Tasks/Strangeness @alibuild @sustripathy @skundu692 @ercolessi @romainschotter +/PWGLF/Tasks/Strangeness @alibuild @sustripathy @skundu692 @ercolessi @romainschotter /PWGLF/TableProducer/Strangeness @alibuild @sustripathy @skundu692 @ercolessi @romainschotter +/PWGLF/Utils @alibuild @sustripathy @skundu692 @gbencedi @abmodak @fmazzasc @maciacco @dmallick2 @smaff92 @ercolessi @romainschotter # PWG-MM /PWGMM @alibuild @sustripathy @skundu692 @aalkin @jgcn @@ -56,7 +58,7 @@ /PWGMM/Lumi @alibuild @aalkin @jgcn /PWGMM/UE @alibuild @aalkin @aortizve @jgcn -/PWGUD @alibuild @pbuehler @abylinkin @rolavick +/PWGUD @alibuild @pbuehler @nystrand @rolavick /PWGJE @alibuild @lhavener @maoyx @nzardosh @fjonasALICE @mfasDa @mhemmer-cern /Tools/PIDML @alibuild @saganatt /Tools/ML @alibuild @fcatalan92 @fmazzasc diff --git a/CPPLINT.cfg b/CPPLINT.cfg index 7f7d3c357c3..96a8077f685 100644 --- a/CPPLINT.cfg +++ b/CPPLINT.cfg @@ -1 +1 @@ -filter=-build/c++11,-build/namespaces,-readability/fn_size,-readability/todo,-runtime/references,-whitespace/blank_line,-whitespace/braces,-whitespace/comments,-whitespace/indent_namespace,-whitespace/line_length,-whitespace/semicolon,-whitespace/todo +filter=-build/c++11,-build/include_order,-build/namespaces,-readability/fn_size,-readability/todo,-runtime/references,-whitespace/blank_line,-whitespace/braces,-whitespace/comments,-whitespace/indent_namespace,-whitespace/line_length,-whitespace/semicolon,-whitespace/todo diff --git a/Common/CCDB/ctpRateFetcher.cxx b/Common/CCDB/ctpRateFetcher.cxx index e20fc41616c..6940fd1e921 100644 --- a/Common/CCDB/ctpRateFetcher.cxx +++ b/Common/CCDB/ctpRateFetcher.cxx @@ -69,7 +69,7 @@ double ctpRateFetcher::fetchCTPratesClasses(o2::ccdb::BasicCCDBManager* /*ccdb*/ LOG(warn) << "Trigger class " << className << " not found in CTPConfiguration"; return -1.; } - auto rate{mScalers->getRateGivenT(timeStamp * 1.e-3, classIndex, inputType)}; + auto rate{mScalers->getRateGivenT(timeStamp * 1.e-3, classIndex, inputType, 1)}; return pileUpCorrection(rate.second); } @@ -77,7 +77,7 @@ double ctpRateFetcher::fetchCTPratesInputs(o2::ccdb::BasicCCDBManager* /*ccdb*/, { std::vector recs = mScalers->getScalerRecordO2(); if (recs[0].scalersInps.size() == 48) { - return pileUpCorrection(mScalers->getRateGivenT(timeStamp * 1.e-3, input, 7).second); + return pileUpCorrection(mScalers->getRateGivenT(timeStamp * 1.e-3, input, 7, 1).second); } else { LOG(error) << "Inputs not available"; return -1.; @@ -109,7 +109,7 @@ void ctpRateFetcher::setupRun(int runNumber, o2::ccdb::BasicCCDBManager* ccdb, u delete mScalers; delete mLHCIFdata; } - std::map metadata; + std::map metadata; mLHCIFdata = ccdb->getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); if (mLHCIFdata == nullptr) { LOG(fatal) << "GRPLHCIFData not in database, timestamp:" << timeStamp; diff --git a/Common/Core/CollisionTypeHelper.cxx b/Common/Core/CollisionTypeHelper.cxx index c22510ec82e..4d7e1de3f87 100644 --- a/Common/Core/CollisionTypeHelper.cxx +++ b/Common/Core/CollisionTypeHelper.cxx @@ -10,17 +10,20 @@ // or submit itself to any jurisdiction. /// -/// \file CollisionTypeHelper.h +/// \file CollisionTypeHelper.cxx /// \author Nicolò Jacazio nicolo.jacazio@cern.ch /// \brief Utility to handle the collision type from the GRP information /// #include "Common/Core/CollisionTypeHelper.h" + +#include "DataFormatsParameters/GRPLHCIFData.h" + #include + #include -#include "DataFormatsParameters/GRPLHCIFData.h" -std::string CollisionSystemType::getCollisionSystemName(collType collSys) +std::string o2::common::core::CollisionSystemType::getCollisionSystemName(collType collSys) { switch (collSys) { case kCollSyspp: @@ -31,17 +34,26 @@ std::string CollisionSystemType::getCollisionSystemName(collType collSys) return "XeXe"; case kCollSyspPb: return "pPb"; + case kCollSysOO: + return "OO"; + case kCollSyspO: + return "pO"; + case kCollSysNeNe: + return "NeNe"; + case kCollSysUndef: + return "Undefined"; default: + LOG(warning) << "Undefined collision system type: " << collSys; return "Undefined"; } } -int CollisionSystemType::getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif) +int o2::common::core::CollisionSystemType::getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif) { - const int ZBeamA = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamA); - const int ZBeamC = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamC); - LOG(debug) << "Collision system: " << ZBeamA << " * " << ZBeamC << " detected"; - switch (ZBeamA * ZBeamC) { + const int zBeamA = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamA); + const int zBeamC = grplhcif->getBeamZ(o2::constants::lhc::BeamDirection::BeamC); + LOG(debug) << "Collision system Z: " << zBeamA << " * " << zBeamC << " detected = " << zBeamA * zBeamC; + switch (zBeamA * zBeamC) { case 1: // pp 1*1 return kCollSyspp; case 6724: // Pb-Pb 82*82 @@ -50,8 +62,14 @@ int CollisionSystemType::getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* g return kCollSysXeXe; case 82: // p-Pb 82*1 return kCollSyspPb; + case 64: // O-O 8*8 + return kCollSysOO; + case 8: // p-O 8*1 + return kCollSyspO; + case 100: // Ne-Ne 10*10 + return kCollSysNeNe; default: - LOG(fatal) << "Undefined collision system in getCollisionTypeFromGrp with BeamA = " << ZBeamA << " and BeamC = " << ZBeamC; + LOG(fatal) << "Undefined collision system in getCollisionTypeFromGrp with Z of BeamA = " << zBeamA << " and Z of BeamC = " << zBeamC; return kCollSysUndef; } return kCollSysUndef; diff --git a/Common/Core/CollisionTypeHelper.h b/Common/Core/CollisionTypeHelper.h index 0196fdc03bb..c8dc7a21842 100644 --- a/Common/Core/CollisionTypeHelper.h +++ b/Common/Core/CollisionTypeHelper.h @@ -18,9 +18,12 @@ #ifndef COMMON_CORE_COLLISIONTYPEHELPER_H_ #define COMMON_CORE_COLLISIONTYPEHELPER_H_ -#include #include "DataFormatsParameters/GRPLHCIFData.h" +#include + +namespace o2::common::core +{ // Container for the collision system type struct CollisionSystemType { // Enum type for the collision system @@ -31,11 +34,18 @@ struct CollisionSystemType { static constexpr collType kCollSysPbPb = 1; // PbPb static constexpr collType kCollSysXeXe = 2; // XeXe static constexpr collType kCollSyspPb = 3; // pPb - static constexpr collType kNCollSys = 4; // Number of collision systems + static constexpr collType kCollSysOO = 4; // OO (Oxygen-Oxygen) + static constexpr collType kCollSyspO = 5; // pO (proton-Oxygen) + static constexpr collType kCollSysNeNe = 6; // NeNe (Neon-Neon) + static constexpr collType kNCollSys = 7; // Number of collision systems static std::string getCollisionSystemName(collType collSys); static int getCollisionTypeFromGrp(o2::parameters::GRPLHCIFData* grplhcif); }; +} // namespace o2::common::core + +using CollisionSystemType = o2::common::core::CollisionSystemType; + #endif // COMMON_CORE_COLLISIONTYPEHELPER_H_ diff --git a/Common/Core/MetadataHelper.cxx b/Common/Core/MetadataHelper.cxx index bdcb7e2e8a4..b8c2fe6ad22 100644 --- a/Common/Core/MetadataHelper.cxx +++ b/Common/Core/MetadataHelper.cxx @@ -20,13 +20,18 @@ #include "Framework/InitContext.h" #include "Framework/RunningWorkflowInfo.h" +using namespace o2::common::core; + MetadataHelper::MetadataHelper() { - const std::array keyList = {"DataType", + const std::array keyList = {"DataType", "RecoPassName", "Run", "AnchorPassName", - "AnchorProduction"}; + "AnchorProduction", + "ROOTVersion", + "LPMProductionTag", + "O2Version"}; for (const auto& key : keyList) { mMetadata[key] = "undefined"; } diff --git a/Common/Core/MetadataHelper.h b/Common/Core/MetadataHelper.h index 8519c25bc88..f3522a5d190 100644 --- a/Common/Core/MetadataHelper.h +++ b/Common/Core/MetadataHelper.h @@ -8,8 +8,6 @@ // In applying this license CERN does 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 TableHelper.h /// \author Nicolò Jacazio nicolo.jacazio@cern.ch /// \brief Utility to handle the metadata from the AOD @@ -18,10 +16,14 @@ #ifndef COMMON_CORE_METADATAHELPER_H_ #define COMMON_CORE_METADATAHELPER_H_ -#include -#include #include "Framework/ConfigContext.h" +#include +#include + +namespace o2::common::core +{ + struct MetadataHelper { /// @brief Constructor for the MetadataHelper. Defines the all the metadata keys that will be looked for and accessible MetadataHelper(); @@ -64,4 +66,6 @@ struct MetadataHelper { bool mIsInitialized = false; /// < Flag to check if the metadata has been initialized }; +} // namespace o2::common::core + #endif // COMMON_CORE_METADATAHELPER_H_ diff --git a/Common/Core/PID/TPCPIDResponse.h b/Common/Core/PID/TPCPIDResponse.h index f25e1acd69e..deafdf4fed2 100644 --- a/Common/Core/PID/TPCPIDResponse.h +++ b/Common/Core/PID/TPCPIDResponse.h @@ -74,12 +74,18 @@ class Response /// Gets the expected resolution of the track template float GetExpectedSigma(const CollisionType& collision, const TrackType& trk, const o2::track::PID::ID id) const; + /// Gets the expected resolution of the track with multTPC explicitly provided + template + float GetExpectedSigmaAtMultiplicity(const long multTPC, const TrackType& trk, const o2::track::PID::ID id) const; /// Gets the number of sigmas with respect the expected value template float GetNumberOfSigma(const CollisionType& collision, const TrackType& trk, const o2::track::PID::ID id) const; // Number of sigmas with respect to expected for MC, defining a tune-on-data signal value template float GetNumberOfSigmaMCTuned(const CollisionType& collision, const TrackType& trk, const o2::track::PID::ID id, float mcTunedTPCSignal) const; + // Number of sigmas with respect to expected for MC, defining a tune-on-data signal value, explicit multTPC + template + float GetNumberOfSigmaMCTunedAtMultiplicity(const long multTPC, const TrackType& trk, const o2::track::PID::ID id, float mcTunedTPCSignal) const; /// Gets the deviation to the expected signal template float GetSignalDelta(const TrackType& trk, const o2::track::PID::ID id) const; @@ -116,6 +122,14 @@ inline float Response::GetExpectedSignal(const TrackType& track, const o2::track /// Gets the expected resolution of the measurement template inline float Response::GetExpectedSigma(const CollisionType& collision, const TrackType& track, const o2::track::PID::ID id) const +{ + // use multTPC (legacy behaviour) if multTPC not provided + return Response::GetExpectedSigmaAtMultiplicity(collision.multTPC(), track, id); +} + +/// Gets the expected resolution of the measurement +template +inline float Response::GetExpectedSigmaAtMultiplicity(const long multTPC, const TrackType& track, const o2::track::PID::ID id) const { if (!track.hasTPC()) { return -999.f; @@ -133,7 +147,7 @@ inline float Response::GetExpectedSigma(const CollisionType& collision, const Tr const double dEdx = o2::tpc::BetheBlochAleph(static_cast(bg), mBetheBlochParams[0], mBetheBlochParams[1], mBetheBlochParams[2], mBetheBlochParams[3], mBetheBlochParams[4]) * std::pow(static_cast(o2::track::pid_constants::sCharges[id]), mChargeFactor); const double relReso = GetRelativeResolutiondEdx(p, mass, o2::track::pid_constants::sCharges[id], mResolutionParams[3]); - const std::vector values{1.f / dEdx, track.tgl(), std::sqrt(ncl), relReso, track.signed1Pt(), collision.multTPC() / mMultNormalization}; + const std::vector values{1.f / dEdx, track.tgl(), std::sqrt(ncl), relReso, track.signed1Pt(), multTPC / mMultNormalization}; const float reso = sqrt(pow(mResolutionParams[0], 2) * values[0] + pow(mResolutionParams[1], 2) * (values[2] * mResolutionParams[5]) * pow(values[0] / sqrt(1 + pow(values[1], 2)), mResolutionParams[2]) + values[2] * pow(values[3], 2) + pow(mResolutionParams[4] * values[4], 2) + pow(values[5] * mResolutionParams[6], 2) + pow(values[5] * (values[0] / sqrt(1 + pow(values[1], 2))) * mResolutionParams[7], 2)) * dEdx * mMIP; reso >= 0.f ? resolution = reso : resolution = -999.f; @@ -160,7 +174,13 @@ inline float Response::GetNumberOfSigma(const CollisionType& collision, const Tr template inline float Response::GetNumberOfSigmaMCTuned(const CollisionType& collision, const TrackType& trk, const o2::track::PID::ID id, float mcTunedTPCSignal) const { - if (GetExpectedSigma(collision, trk, id) < 0.) { + return Response::GetNumberOfSigmaMCTunedAtMultiplicity(collision.multTPC(), trk, id, mcTunedTPCSignal); +} + +template +inline float Response::GetNumberOfSigmaMCTunedAtMultiplicity(const long multTPC, const TrackType& trk, const o2::track::PID::ID id, float mcTunedTPCSignal) const +{ + if (GetExpectedSigmaAtMultiplicity(multTPC, trk, id) < 0.) { return -999.f; } if (GetExpectedSignal(trk, id) < 0.) { @@ -169,7 +189,7 @@ inline float Response::GetNumberOfSigmaMCTuned(const CollisionType& collision, c if (!trk.hasTPC()) { return -999.f; } - return ((mcTunedTPCSignal - GetExpectedSignal(trk, id)) / GetExpectedSigma(collision, trk, id)); + return ((mcTunedTPCSignal - GetExpectedSignal(trk, id)) / GetExpectedSigmaAtMultiplicity(multTPC, trk, id)); } /// Gets the deviation between the actual signal and the expected signal diff --git a/Common/Core/RecoDecay.h b/Common/Core/RecoDecay.h index 2bdf3b82b60..5b4464e112a 100644 --- a/Common/Core/RecoDecay.h +++ b/Common/Core/RecoDecay.h @@ -22,6 +22,7 @@ #include // std::array #include // std::abs, std::sqrt #include +#include // std::apply #include // std::move #include // std::vector @@ -285,6 +286,19 @@ struct RecoDecay { return static_cast(length) * static_cast(mass) / p(mom); } + /// Calculates proper lifetime times c (pseudoproper decay length) in XY from information on daughter tracks. + /// \param posPV {x, y, z} or {x, y} position of the primary vertex + /// \param posSV {x, y, z} or {x, y} position of the secondary vertex + /// \param mom array of {x, y, z} or {x, y} momentum arrays of the decay products + /// \param mass mass of the decay products + /// \return pseudoproper decay length + template + static double ctXY(const T& posPV, const U& posSV, const std::array, N>& mom, const std::array mass) + { + // c t_xy = l_xy * m c^2 / (pT c) + return distanceXY(posPV, posSV) * m(mom, mass) / std::apply([](const auto&... args) { return pt(args...); }, mom); + } + /// Calculates cosine of θ* (theta star). /// \note Implemented for 2 prongs only. /// \param arrMom array of two 3-momentum arrays @@ -718,7 +732,7 @@ struct RecoDecay { if (!arrDaughters[iProng].has_mcParticle()) { return -1; } - auto particleI = arrDaughters[iProng].mcParticle(); // ith daughter particle + auto particleI = arrDaughters[iProng].template mcParticle_as(); // ith daughter particle if (std::abs(particleI.getGenStatusCode()) == StatusCodeAfterFlavourOscillation) { // oscillation decay product spotted coefFlavourOscillation = -1; // select the sign of the mother after oscillation (and not before) break; @@ -730,7 +744,7 @@ struct RecoDecay { if (!arrDaughters[iProng].has_mcParticle()) { return -1; } - auto particleI = arrDaughters[iProng].mcParticle(); // ith daughter particle + auto particleI = arrDaughters[iProng].template mcParticle_as(); // ith daughter particle if constexpr (acceptTrackDecay) { // Replace the MC particle associated with the prong by its mother for π → μ and K → π. auto motherI = particleI.template mothers_first_as(); diff --git a/Common/Core/TableHelper.cxx b/Common/Core/TableHelper.cxx index 4af58f00428..04745ffe694 100644 --- a/Common/Core/TableHelper.cxx +++ b/Common/Core/TableHelper.cxx @@ -17,14 +17,14 @@ #include "Common/Core/TableHelper.h" -#include - #include "Framework/InitContext.h" #include "Framework/RunningWorkflowInfo.h" +#include + /// Function to print the table required in the full workflow /// @param initContext initContext of the init function -void printTablesInWorkflow(o2::framework::InitContext& initContext) +void o2::common::core::printTablesInWorkflow(o2::framework::InitContext& initContext) { auto& workflows = initContext.services().get(); for (auto const& device : workflows.devices) { @@ -37,7 +37,7 @@ void printTablesInWorkflow(o2::framework::InitContext& initContext) /// Function to check if a table is required in a workflow /// @param initContext initContext of the init function /// @param table name of the table to check for -bool isTableRequiredInWorkflow(o2::framework::InitContext& initContext, const std::string& table) +bool o2::common::core::isTableRequiredInWorkflow(o2::framework::InitContext& initContext, const std::string& table) { LOG(debug) << "Checking if table " << table << " is needed"; bool tableNeeded = false; @@ -57,7 +57,7 @@ bool isTableRequiredInWorkflow(o2::framework::InitContext& initContext, const st /// @param initContext initContext of the init function /// @param table name of the table to check for /// @param flag bool value of flag to set, if the given value is true it will be kept, disregarding the table usage in the workflow. -void enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, bool& flag) +void o2::common::core::enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, bool& flag) { if (flag) { LOG(info) << "Table enabled: " + table; @@ -75,7 +75,7 @@ void enableFlagIfTableRequired(o2::framework::InitContext& initContext, const st /// @param initContext initContext of the init function /// @param table name of the table to check for /// @param flag int value of flag to set, only if initially set to -1. Initial values of 0 or 1 will be kept disregarding the table usage in the workflow. -void enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, int& flag) +void o2::common::core::enableFlagIfTableRequired(o2::framework::InitContext& initContext, const std::string& table, int& flag) { if (flag > 0) { flag = 1; diff --git a/Common/Core/TableHelper.h b/Common/Core/TableHelper.h index f4faf9dc8c8..56d2264ed6c 100644 --- a/Common/Core/TableHelper.h +++ b/Common/Core/TableHelper.h @@ -18,12 +18,15 @@ #ifndef COMMON_CORE_TABLEHELPER_H_ #define COMMON_CORE_TABLEHELPER_H_ -#include - #include "Framework/Configurable.h" #include "Framework/InitContext.h" #include "Framework/RunningWorkflowInfo.h" +#include + +namespace o2::common::core +{ + /// Function to print the table required in the full workflow /// @param initContext initContext of the init function void printTablesInWorkflow(o2::framework::InitContext& initContext); @@ -76,14 +79,16 @@ bool getTaskOptionValue(o2::framework::InitContext& initContext, const std::stri } if (device.name == taskName) { // Found the mother task int optionCounter = 0; - for (auto const& option : device.options) { + for (const o2::framework::ConfigParamSpec& option : device.options) { if (verbose) { - LOG(info) << " Option " << optionCounter++ << " " << option.name << " = '" << option.defaultValue.asString() << "'"; + LOG(info) << " Option " << optionCounter++ << " " << option.name << " of type " << static_cast(option.type) << " = '" << option.defaultValue.asString() << "'"; } if (option.name == optName) { value = option.defaultValue.get(); if (verbose) { - LOG(info) << " Found option '" << optName << "' with value '" << value << "'"; + if constexpr (!std::is_same_v>) { + LOG(info) << " Found option '" << optName << "' with value '" << value << "'"; + } found = true; } else { return true; @@ -107,4 +112,11 @@ bool getTaskOptionValue(o2::framework::InitContext& initContext, const std::stri return getTaskOptionValue(initContext, taskName, configurable.name, configurable.value, verbose); } +} // namespace o2::common::core + +using o2::common::core::enableFlagIfTableRequired; +using o2::common::core::getTaskOptionValue; +using o2::common::core::isTableRequiredInWorkflow; +using o2::common::core::printTablesInWorkflow; + #endif // COMMON_CORE_TABLEHELPER_H_ diff --git a/Common/Core/fwdtrackUtilities.h b/Common/Core/fwdtrackUtilities.h index 13fb27c5862..74fe125c2f0 100644 --- a/Common/Core/fwdtrackUtilities.h +++ b/Common/Core/fwdtrackUtilities.h @@ -18,10 +18,18 @@ #ifndef COMMON_CORE_FWDTRACKUTILITIES_H_ #define COMMON_CORE_FWDTRACKUTILITIES_H_ +#include +#include +#include +#include +#include +#include + +#include +#include +#include + #include -#include -#include "Math/SMatrix.h" -#include "TGeoGlobalMagField.h" namespace o2::aod { diff --git a/Common/Core/macros/testCollisionTypeHelper.C b/Common/Core/macros/testCollisionTypeHelper.C new file mode 100644 index 00000000000..43624ea697e --- /dev/null +++ b/Common/Core/macros/testCollisionTypeHelper.C @@ -0,0 +1,30 @@ +// 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 testCollisionTypeHelper.C +/// \author Nicolò Jacazio nicolo.jacazio@cern.ch +/// \brief Test the CollisionTypeHelper functionality + +#include "Common/Core/CollisionTypeHelper.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPLHCIFData.h" + +void testCollisionTypeHelper(int runNumber = 544124) +{ + + auto& ccdb = o2::ccdb::BasicCCDBManager::instance(); + ccdb.setURL("http://alice-ccdb.cern.ch"); + o2::parameters::GRPLHCIFData* grpo = ccdb.getSpecificForRun("GLO/Config/GRPLHCIF", + runNumber); + grpo->print(); + int collsys = o2::common::core::CollisionSystemType::getCollisionTypeFromGrp(grpo); +} diff --git a/Common/DataModel/Centrality.h b/Common/DataModel/Centrality.h index c3074a63c67..fa7e2ec51bc 100644 --- a/Common/DataModel/Centrality.h +++ b/Common/DataModel/Centrality.h @@ -60,6 +60,11 @@ DECLARE_SOA_TABLE(CentMFTs, "AOD", "CENTMFT", cent::CentMFT); //! Ru // Run 3 variant tables DECLARE_SOA_TABLE(CentFT0CVariant1s, "AOD", "CENTFT0Cvar1", cent::CentFT0CVariant1); //! Run 3 FT0C variant 1 +// Run 3 centrality per BC (joinable with BC) +DECLARE_SOA_TABLE(BCCentFT0Ms, "AOD", "BCCENTFT0M", cent::CentFT0M, o2::soa::Marker<1>); //! Run 3 FT0M BC centrality table +DECLARE_SOA_TABLE(BCCentFT0As, "AOD", "BCCENTFT0A", cent::CentFT0A, o2::soa::Marker<1>); //! Run 3 FT0A BC centrality table +DECLARE_SOA_TABLE(BCCentFT0Cs, "AOD", "BCCENTFT0C", cent::CentFT0C, o2::soa::Marker<1>); //! Run 3 FT0C BC centrality table + using CentRun2V0M = CentRun2V0Ms::iterator; using CentRun2V0A = CentRun2V0As::iterator; using CentRun2SPDTrk = CentRun2SPDTrks::iterator; @@ -77,6 +82,10 @@ using CentNTPV = CentNTPVs::iterator; using CentNGlobal = CentNGlobals::iterator; using CentMFT = CentMFTs::iterator; +using BCCentFT0M = BCCentFT0Ms::iterator; +using BCCentFT0A = BCCentFT0As::iterator; +using BCCentFT0C = BCCentFT0Cs::iterator; + template concept HasRun2Centrality = requires(T&& t) { { t.centRun2V0M() }; diff --git a/Common/DataModel/Multiplicity.h b/Common/DataModel/Multiplicity.h index ce6aa4ba046..8d1e9b10ab3 100644 --- a/Common/DataModel/Multiplicity.h +++ b/Common/DataModel/Multiplicity.h @@ -8,6 +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. + +/// \file Multiplicity.h +/// \brief multiplicity tables +/// \author ALICE + #ifndef COMMON_DATAMODEL_MULTIPLICITY_H_ #define COMMON_DATAMODEL_MULTIPLICITY_H_ @@ -120,6 +125,7 @@ DECLARE_SOA_TABLE(MFTMults, "AOD", "MFTMULT", //! Multiplicity with MFT mult::MFTNalltracks, mult::MFTNtracks); using BarrelMults = soa::Join; using Mults = soa::Join; +using MultsRun3 = soa::Join; using FT0Mult = FT0Mults::iterator; using MFTMult = MFTMults::iterator; using Mult = Mults::iterator; @@ -197,14 +203,22 @@ DECLARE_SOA_INDEX_COLUMN(MultMCExtra, multMCExtra); DECLARE_SOA_TABLE(Mult2MCExtras, "AOD", "Mult2MCEXTRA", //! Relate reco mult entry to MC extras entry o2::soa::Index<>, mult::MultMCExtraId); +DECLARE_SOA_TABLE(MultHepMCHIs, "AOD", "MULTHEPMCHI", //! complementary table for heavy-ion mc info (subset of HepMCHeavyIons) + o2::soa::Index<>, mult::MultMCExtraId, hepmcheavyion::NcollHard, hepmcheavyion::NpartProj, hepmcheavyion::NpartTarg, + hepmcheavyion::Ncoll, hepmcheavyion::ImpactParameter); + +using MultHepMCHI = MultHepMCHIs::iterator; + namespace multZeq { -DECLARE_SOA_COLUMN(MultZeqFV0A, multZeqFV0A, float); //! Multiplicity equalized for the vertex position with the FV0A detector -DECLARE_SOA_COLUMN(MultZeqFT0A, multZeqFT0A, float); //! Multiplicity equalized for the vertex position with the FT0A detector -DECLARE_SOA_COLUMN(MultZeqFT0C, multZeqFT0C, float); //! Multiplicity equalized for the vertex position with the FT0C detector -DECLARE_SOA_COLUMN(MultZeqFDDA, multZeqFDDA, float); //! Multiplicity equalized for the vertex position with the FDDA detector -DECLARE_SOA_COLUMN(MultZeqFDDC, multZeqFDDC, float); //! Multiplicity equalized for the vertex position with the FDDC detector -DECLARE_SOA_COLUMN(MultZeqNTracksPV, multZeqNTracksPV, float); //! Multiplicity equalized for the vertex position from the PV contributors +DECLARE_SOA_COLUMN(MultZeqFV0A, multZeqFV0A, float); //! Multiplicity equalized for the vertex position with the FV0A detector +DECLARE_SOA_COLUMN(MultZeqFT0A, multZeqFT0A, float); //! Multiplicity equalized for the vertex position with the FT0A detector +DECLARE_SOA_COLUMN(MultZeqFT0C, multZeqFT0C, float); //! Multiplicity equalized for the vertex position with the FT0C detector +DECLARE_SOA_COLUMN(MultZeqFDDA, multZeqFDDA, float); //! Multiplicity equalized for the vertex position with the FDDA detector +DECLARE_SOA_COLUMN(MultZeqFDDC, multZeqFDDC, float); //! Multiplicity equalized for the vertex position with the FDDC detector +DECLARE_SOA_COLUMN(MultZeqNTracksPV, multZeqNTracksPV, float); //! Multiplicity equalized for the vertex position from the PV contributors +DECLARE_SOA_COLUMN(MultZeqNTracksGlobal, multZeqNTracksGlobal, float); //! Multiplicity equalized for the vertex position, global tracks +DECLARE_SOA_COLUMN(MultZeqMFTNtracks, multZeqMFTNtracks, float); //! Multiplicity equalized for the vertex position, MFT tracks } // namespace multZeq DECLARE_SOA_TABLE(FV0MultZeqs, "AOD", "FV0MULTZEQ", //! Multiplicity equalized for the vertex position with the FV0 detector multZeq::MultZeqFV0A); @@ -214,6 +228,10 @@ DECLARE_SOA_TABLE(FDDMultZeqs, "AOD", "FDDMULTZEQ", //! Multiplicity equalized f multZeq::MultZeqFDDA, multZeq::MultZeqFDDC); DECLARE_SOA_TABLE(PVMultZeqs, "AOD", "PVMULTZEQ", //! Multiplicity equalized for the vertex position from the PV contributors multZeq::MultZeqNTracksPV); +DECLARE_SOA_TABLE(GlobalMultZeqs, "AOD", "GLOBALMULTZEQ", //! Multiplicity equalized for the vertex position, global tracks + multZeq::MultZeqNTracksGlobal); +DECLARE_SOA_TABLE(MFTMultZeqs, "AOD", "MFTMULTZEQS", //! Multiplicity equalized for the vertex position, MFT tracks + multZeq::MultZeqMFTNtracks); using MultZeqs = soa::Join; using MultZeq = MultZeqs::iterator; diff --git a/Common/DataModel/OccupancyTables.h b/Common/DataModel/OccupancyTables.h index 4828183a269..9e14fd8f4f2 100644 --- a/Common/DataModel/OccupancyTables.h +++ b/Common/DataModel/OccupancyTables.h @@ -209,6 +209,8 @@ namespace trackmeanocc { DECLARE_SOA_INDEX_COLUMN(Track, track); +// DECLARE_SOA_INDEX_COLUMN(TracksQA, tracksQA);// this is not working + DECLARE_SOA_COLUMN(TmoPrimUnfm80, tmoPrimUnfm80, float); DECLARE_SOA_COLUMN(TmoFV0AUnfm80, tmoFV0AUnfm80, float); DECLARE_SOA_COLUMN(TmoFV0CUnfm80, tmoFV0CUnfm80, float); @@ -281,7 +283,7 @@ DECLARE_SOA_COLUMN(TwmoRobustMultExtraTableUnfm80, twmoRobustMultExtraTableUnfm8 // using Tracks = aod::Tracks; // DECLARE_SOA_INDEX_TABLE_USER(TrackMeanOccs0, Tracks, "TRACKMEANOCCS0", o2::aod::trackmeanocc::TrackId); -DECLARE_SOA_TABLE(TmoTrackId, "AOD", "TMOTRACKID", o2::aod::trackmeanocc::TrackId); +DECLARE_SOA_TABLE(TmoTrackIds, "AOD", "TMOTRACKIDS", o2::aod::trackmeanocc::TrackId); DECLARE_SOA_TABLE(TmoPrim, "AOD", "TMOPRIM", o2::soa::Index<>, // TrackMeanOccDet o2::aod::trackmeanocc::TmoPrimUnfm80); @@ -377,5 +379,21 @@ DECLARE_SOA_TABLE(TwmoRNtrackDet, "AOD", "TWMORNTRACKDET", o2::soa::Index<>, DECLARE_SOA_TABLE(TwmoRMultExtra, "AOD", "TWMORMULTEXTRA", o2::soa::Index<>, o2::aod::trackmeanocc::TwmoRobustMultExtraTableUnfm80); +using Tmo = aod::TmoTrackIds::iterator; + +using TrackQA = TracksQAVersion::iterator; + +namespace trackmeanocc +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Tmo, tmo, int64_t, TmoTrackIds, ""); +DECLARE_SOA_INDEX_COLUMN_FULL(TrackQA, trackQA, int64_t, TracksQAVersion, ""); +} // namespace trackmeanocc + +DECLARE_SOA_TABLE(TrackToTracksQA, "AOD", "TRACKTOTRACKSQA", o2::aod::trackmeanocc::TrackQAId); +DECLARE_SOA_TABLE(TrackToTmo, "AOD", "TRACKTOTMO", o2::aod::trackmeanocc::TmoId); + +DECLARE_SOA_TABLE(TrackQAToTmo, "AOD", "TRACKQATOTMO", o2::aod::trackmeanocc::TmoId); +DECLARE_SOA_TABLE(TmoToTrackQA, "AOD", "TMOTOTRACKQA", o2::aod::trackmeanocc::TrackQAId); + } // namespace o2::aod #endif // COMMON_DATAMODEL_OCCUPANCYTABLES_H_ diff --git a/Common/DataModel/PIDResponseITS.h b/Common/DataModel/PIDResponseITS.h index 6a6afdc8827..e1e2a586472 100644 --- a/Common/DataModel/PIDResponseITS.h +++ b/Common/DataModel/PIDResponseITS.h @@ -23,10 +23,12 @@ #define COMMON_DATAMODEL_PIDRESPONSEITS_H_ // O2 includes +#include "TableHelper.h" + #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/PID.h" #include "Framework/Logger.h" +#include "ReconstructionDataFormats/PID.h" namespace o2::aod { @@ -81,6 +83,8 @@ struct ITSResponse { template static float nSigmaITS(uint32_t itsClusterSizes, float momentum, float eta) { + unsigned int charge = (id == o2::track::PID::Helium3 || id == o2::track::PID::Alpha) ? 2 : 1; + momentum *= charge; const float exp = expSignal(momentum); const float average = averageClusterSize(itsClusterSizes); const float coslInv = 1. / std::cosh(eta); @@ -125,6 +129,40 @@ struct ITSResponse { 0.09, -999., -999.); } + /// Initialize the TOF response parameters in the init function of each task + /// \param initContext Initialization context. Gets the configuration parameters from the pidITS task + static void setParameters(o2::framework::InitContext& initContext, bool isMC = false) + { + float p0 = 0, p1 = 0, p2 = 0; + float p0_Z2 = 0, p1_Z2 = 0, p2_Z2 = 0; + float p0_res = 0, p1_res = 0, p2_res = 0; + float p0_res_Z2 = 0, p1_res_Z2 = 0, p2_res_Z2 = 0; + o2::framework::LabeledArray itsParams; + getTaskOptionValue(initContext, "its-pid", "itsParams", itsParams, true); + auto data = itsParams.getData(); + const int col = isMC ? 1 : 0; // 0 for Data, 1 for MC + if (data.rows != 2 || data.cols != 12) { + LOG(fatal) << "ITSResponse parameters not initialized, check the itsParams configuration"; + } + p0 = data(col, 0); + p1 = data(col, 1); + p2 = data(col, 2); + p0_Z2 = data(col, 3); + p1_Z2 = data(col, 4); + p2_Z2 = data(col, 5); + p0_res = data(col, 6); + p1_res = data(col, 7); + p2_res = data(col, 8); + p0_res_Z2 = data(col, 9); + p1_res_Z2 = data(col, 10); + p2_res_Z2 = data(col, 11); + + setParameters(p0, p1, p2, + p0_Z2, p1_Z2, p2_Z2, + p0_res, p1_res, p2_res, + p0_res_Z2, p1_res_Z2, p2_res_Z2); + } + private: static std::array mITSRespParams; static std::array mITSRespParamsZ2; diff --git a/Common/DataModel/SelectionStudyTables.h b/Common/DataModel/SelectionStudyTables.h new file mode 100644 index 00000000000..3a62c30b267 --- /dev/null +++ b/Common/DataModel/SelectionStudyTables.h @@ -0,0 +1,57 @@ +// 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 SelectionStudyTables +/// \brief tables meant to do event selection studies for O-O / light systems +/// +/// \author ALICE + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" + +#include + +#ifndef COMMON_DATAMODEL_SELECTIONSTUDYTABLES_H_ +#define COMMON_DATAMODEL_SELECTIONSTUDYTABLES_H_ + +namespace o2::aod +{ +namespace selectionstudy +{ +DECLARE_SOA_COLUMN(PtPions, ptPions, std::vector); +DECLARE_SOA_COLUMN(PtKaons, ptKaons, std::vector); +DECLARE_SOA_COLUMN(PtProtons, ptProtons, std::vector); +DECLARE_SOA_COLUMN(PtK0s, ptPK0s, std::vector); +DECLARE_SOA_COLUMN(PtLambdas, ptLambdas, std::vector); +DECLARE_SOA_COLUMN(PtXis, ptXis, std::vector); +DECLARE_SOA_COLUMN(PtOmegas, ptOmegas, std::vector); +DECLARE_SOA_COLUMN(PtPhis, ptPhis, std::vector); +DECLARE_SOA_COLUMN(PtKStars, ptKStars, std::vector); +DECLARE_SOA_COLUMN(PtDs, ptDs, std::vector); +DECLARE_SOA_COLUMN(PtLambdaCs, ptLambdaCs, std::vector); +DECLARE_SOA_COLUMN(PtJPsis, ptJPsis, std::vector); +} // namespace selectionstudy + +DECLARE_SOA_TABLE(PIDPts, "AOD", "PIDPTS", o2::soa::Index<>, + o2::aod::selectionstudy::PtPions, + o2::aod::selectionstudy::PtKaons, + o2::aod::selectionstudy::PtProtons, + o2::aod::selectionstudy::PtK0s, + o2::aod::selectionstudy::PtLambdas, + o2::aod::selectionstudy::PtXis, + o2::aod::selectionstudy::PtOmegas, + o2::aod::selectionstudy::PtPhis, + o2::aod::selectionstudy::PtKStars, + o2::aod::selectionstudy::PtDs, + o2::aod::selectionstudy::PtLambdaCs, + o2::aod::selectionstudy::PtJPsis); +} // namespace o2::aod +#endif // COMMON_DATAMODEL_SELECTIONSTUDYTABLES_H_ diff --git a/Common/DataModel/ZDCInterCalib.h b/Common/DataModel/ZDCInterCalib.h index 290a3ac61fe..d7b66575340 100644 --- a/Common/DataModel/ZDCInterCalib.h +++ b/Common/DataModel/ZDCInterCalib.h @@ -20,21 +20,23 @@ namespace o2::aod { -namespace znoutput +namespace znoutput // o2-linter: disable=name/workflow-file { -DECLARE_SOA_COLUMN(ZNApmc, commonPMZNA, float); //! PMC ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm1, ZNAPM1, float); //! PM1 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm2, ZNAPM2, float); //! PM2 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm3, ZNAPM3, float); //! PM3 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNApm4, ZNAPM4, float); //! PM4 ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNAtdc, ZNATDC, float); //! TDC ZNA // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpmc, commonPMZNC, float); //! PMC ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm1, ZNCPM1, float); //! PM1 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm2, ZNCPM2, float); //! PM2 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm3, ZNCPM3, float); //! PM3 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCpm4, ZNCPM4, float); //! PM4 ZNC // o2-linter: disable=name/o2-column -DECLARE_SOA_COLUMN(ZNCtdc, ZNCTDC, float); //! TDC ZNC // o2-linter: disable=name/o2-column - +DECLARE_SOA_COLUMN(ZNApmc, commonPMZNA, float); //! PMC ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm1, ZNAPM1, float); //! PM1 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm2, ZNAPM2, float); //! PM2 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm3, ZNAPM3, float); //! PM3 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNApm4, ZNAPM4, float); //! PM4 ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNAtdc, ZNATDC, float); //! TDC ZNA // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpmc, commonPMZNC, float); //! PMC ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm1, ZNCPM1, float); //! PM1 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm2, ZNCPM2, float); //! PM2 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm3, ZNCPM3, float); //! PM3 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCpm4, ZNCPM4, float); //! PM4 ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(ZNCtdc, ZNCTDC, float); //! TDC ZNC // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(Centrality, centrality, float); //! Centrality +DECLARE_SOA_COLUMN(Timestamp, timestamp, uint64_t); //! Timestamp +DECLARE_SOA_COLUMN(SelectionBits, selectionBits, uint8_t); //! Selection Flags } // namespace znoutput DECLARE_SOA_TABLE(ZDCInterCalib, "AOD", "ZDCIC", o2::soa::Index<>, @@ -49,7 +51,10 @@ DECLARE_SOA_TABLE(ZDCInterCalib, "AOD", "ZDCIC", o2::soa::Index<>, znoutput::ZNCpm2, znoutput::ZNCpm3, znoutput::ZNCpm4, - znoutput::ZNCtdc); + znoutput::ZNCtdc, + znoutput::Centrality, + znoutput::Timestamp, + znoutput::SelectionBits); } // namespace o2::aod #endif // COMMON_DATAMODEL_ZDCINTERCALIB_H_ diff --git a/Common/LegacyDataQA/CMakeLists.txt b/Common/LegacyDataQA/CMakeLists.txt index 08817428042..e23c1f7c29c 100644 --- a/Common/LegacyDataQA/CMakeLists.txt +++ b/Common/LegacyDataQA/CMakeLists.txt @@ -28,3 +28,8 @@ o2physics_add_dpl_workflow(pmd-qa SOURCES pmdQa.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(pcm-run2 + SOURCES pcmRun2.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Common/LegacyDataQA/pcmRun2.cxx b/Common/LegacyDataQA/pcmRun2.cxx new file mode 100644 index 00000000000..87032dd96d3 --- /dev/null +++ b/Common/LegacyDataQA/pcmRun2.cxx @@ -0,0 +1,314 @@ +// 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 pcmRun2.cxx +/// \brief Analysis using PCM photons from Run2 +/// \author M. Hemmer, marvin.hemmer@cern.ch + +#include "Common/DataModel/PIDResponseTPC.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; +struct PcmRun2 { + struct : ConfigurableGroup { + std::string prefix = "trackcuts"; + Configurable tpcFindOverFoundable{"tpcFindOverFoundable", 0.6, "Ratio of number of found TPC clusters to the number of foundable TPC clusters a track must have at least."}; + Configurable minPt{"minPt", 0.05, "Minimum pT cut for the tracks."}; + } trackcuts; + + struct : ConfigurableGroup { + std::string prefix = "pidcuts"; + Configurable minNSigmaEl{"minNSigmaEl", -3., "Minimum NSgimal electron allowed for V0 leg."}; + Configurable maxNSigmaEl{"maxNSigmaEl", +4., "Maximum NSgimal electron allowed for V0 leg."}; + Configurable doPionRejection{"doPionRejection", true, "Flag to enable pion rejection based on TPC PID for V0 legs."}; + Configurable minNSigmaPiLowP{"minNSigmaPiLowP", 1., "Minimum NSgimal pion to reject V0 legs for low 0.4 < pT/(GeV/c) < 3.5."}; + Configurable minNSigmaPiHighP{"minNSigmaPiHighP", +0.5, "Minimum NSgimal pion to reject V0 legs for pT > 3.5 GeV/c."}; + } pidcuts; + + struct : ConfigurableGroup { + std::string prefix = "v0cuts"; + Configurable minPt{"minPt", 0.02, "Minimum pT cut for the V0."}; + Configurable maxEta{"maxEta", 0.8, "Maximum absolut pseudorapidity cut for the V0."}; + Configurable maxZconv{"maxZconv", 0.8, "Maximum absolut z conversion position cut for the V0."}; + Configurable qTFactor{"qTFactor", 0.125, "qT < this * pT"}; + Configurable cosP{"cosP", 0.85, "cos of pointing angle > this value."}; + Configurable rejectTooCloseV0{"rejectTooCloseV0", true, "."}; + } v0cuts; + + using TracksWithPID = soa::Join; + + SliceCache cache; + Preslice perCollisionV0 = aod::run2::oftv0::collisionId; + + HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + void init(InitContext&) + { + + const AxisSpec thnAxisInvMass{400, 0.0, 0.8, "#it{M}_{#gamma#gamma} (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{100, 0., 20., "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisCent{20, 0., 100., "Centrality (%)"}; + const AxisSpec thnAxisCuts{5, -0.5, 4.5, "cuts"}; + const AxisSpec thnAxisNSgimaE{254, -6.35f, 6.35f, "n#sigma_{e}"}; + + registry.add("hSameEvent2D", "hSameEvent2D", HistType::kTH2D, {thnAxisInvMass, thnAxisPt}); + registry.add("hNSigmaEPt", "hNSigmaEPt", HistType::kTH2D, {thnAxisNSgimaE, thnAxisPt}); + + registry.add("hCuts", "hCuts", HistType::kTH1D, {thnAxisCuts}); + registry.add("hCutsPair", "hCutsPair", HistType::kTH1D, {thnAxisCuts}); + + }; // end init + + template + float getCosP(CollisionIter const& coll, V0Iter const& v0) + { + // V0 momentum + float px = v0.px(); + float py = v0.py(); + float pz = v0.pz(); + + // V0 decay position + float xV0 = v0.x(); + float yV0 = v0.y(); + float zV0 = v0.z(); + + // Primary vertex + float xPV = coll.posX(); + float yPV = coll.posY(); + float zPV = coll.posZ(); + + // Displacement vector r = V0 - PV + float rx = xV0 - xPV; + float ry = yV0 - yPV; + float rz = zV0 - zPV; + + // Dot product p·r + float dot = px * rx + py * ry + pz * rz; + + // Magnitudes |p| and |r| + float magP = std::sqrt(px * px + py * py + pz * pz); + float magR = std::sqrt(rx * rx + ry * ry + rz * rz); + + // Cosine of pointing angle + return dot / (magP * magR); + } + + template + bool checkLegs(V0Iter const& v0) + { + + auto posLeg = v0.template posTrack_as(); + auto negLeg = v0.template negTrack_as(); + + registry.fill(HIST("hNSigmaEPt"), posLeg.tpcNSigmaEl(), posLeg.pt()); + registry.fill(HIST("hNSigmaEPt"), negLeg.tpcNSigmaEl(), negLeg.pt()); + + // first let's check the positive leg + if (posLeg.pt() <= trackcuts.minPt.value) { + registry.fill(HIST("hCuts"), 1); + return false; + } + if (posLeg.tpcFoundOverFindableCls() <= trackcuts.tpcFindOverFoundable.value) { + registry.fill(HIST("hCuts"), 1); + return false; + } + if (posLeg.tpcNSigmaEl() <= pidcuts.minNSigmaEl.value || posLeg.tpcNSigmaEl() >= pidcuts.maxNSigmaEl.value) { + registry.fill(HIST("hCuts"), 2); + return false; + } + + float minP = 0.4f; // minimum momentum for legs + float midP = 3.5f; // momentum where we change NSigma window + if (pidcuts.doPionRejection.value && posLeg.p() > minP) { + if (posLeg.p() < midP && posLeg.tpcNSigmaPi() <= pidcuts.minNSigmaPiLowP.value) { + registry.fill(HIST("hCuts"), 2); + return false; + } else if (posLeg.p() >= midP && posLeg.tpcNSigmaPi() <= pidcuts.minNSigmaPiHighP.value) { + registry.fill(HIST("hCuts"), 2); + return false; + } + } + + // second let's check the negative leg + if (negLeg.pt() <= trackcuts.minPt.value) { + registry.fill(HIST("hCuts"), 1); + return false; + } + if (negLeg.tpcFoundOverFindableCls() <= trackcuts.tpcFindOverFoundable.value) { + registry.fill(HIST("hCuts"), 1); + return false; + } + if (negLeg.tpcNSigmaEl() <= pidcuts.minNSigmaEl.value || negLeg.tpcNSigmaEl() >= pidcuts.maxNSigmaEl.value) { + registry.fill(HIST("hCuts"), 2); + return false; + } + + if (pidcuts.doPionRejection.value && negLeg.p() > minP) { + if (negLeg.p() < midP && negLeg.tpcNSigmaPi() <= pidcuts.minNSigmaPiLowP.value) { + registry.fill(HIST("hCuts"), 2); + return false; + } else if (negLeg.p() >= midP && negLeg.tpcNSigmaPi() <= pidcuts.minNSigmaPiHighP.value) { + registry.fill(HIST("hCuts"), 2); + return false; + } + } + return true; + } + + // Pi0 from EMCal + void process(o2::aod::Collisions const& collisions, o2::aod::Run2OTFV0s const& v0s, TracksWithPID const& /*tracks*/) + { + // TODO: + // - Add TooCloseToV0 cut: if two V0s are within dAngle < 0.02 and dR < 6. then remove the V0 with higher Chi2 + // - Everything here! + // nothing yet + + const float zRslope = std::tan(2.f * std::atan(std::exp(-1.f * v0cuts.maxEta.value))); + const float z0 = 7.f; // 7 cm + const float maxZ = 10.f; + const float minR = 5.f; + const float maxR = 280.f; + const float minRExclude = 55.f; + const float maxRExclude = 72.f; + + for (const auto& collision : collisions) { + if (std::fabs(collision.posZ()) > maxZ) { + continue; + } + auto photonsPerCollision = v0s.sliceBy(perCollisionV0, collision.globalIndex()); + + for (const auto& [g1, g2] : combinations(CombinationsStrictlyUpperIndexPolicy(photonsPerCollision, photonsPerCollision))) { + registry.fill(HIST("hCutsPair"), 0); + // next V0 cuts + float cX1 = g1.x(); + float cY1 = g1.y(); + float cZ1 = g1.z(); + float cR1 = std::sqrt(std::pow(cX1, 2.) + std::pow(cY1, 2.)); + + float cX2 = g2.x(); + float cY2 = g2.y(); + float cZ2 = g2.z(); + float cR2 = std::sqrt(std::pow(cX2, 2.) + std::pow(cY2, 2.)); + + ROOT::Math::PxPyPzEVector v4Photon2(g2.px(), g2.py(), g2.pz(), g2.e()); + ROOT::Math::PxPyPzEVector v4Photon1(g1.px(), g1.py(), g1.pz(), g1.e()); + + if (!checkLegs(g1)) { + registry.fill(HIST("hCutsPair"), 1); + continue; + } + + if (!checkLegs(g2)) { + registry.fill(HIST("hCutsPair"), 1); + continue; + } + + if (cR1 < minR || (cR1 > minRExclude && cR1 < maxRExclude) || cR1 > maxR) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (v4Photon1.Pt() < v0cuts.minPt.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (std::fabs(v4Photon1.Eta()) >= v0cuts.maxEta.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (std::fabs(cZ1) > v0cuts.maxZconv.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (cR1 <= ((std::fabs(cZ1) * zRslope) - z0)) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (g1.psiPair() >= (0.18f * std::exp(-0.055f * g1.chi2NDF()))) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (g1.qt() >= (v0cuts.qTFactor.value * v4Photon1.Pt())) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (getCosP(collision, g1) <= v0cuts.cosP.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + + if (cR2 < minR || (cR2 > minRExclude && cR2 < maxRExclude) || cR2 > maxR) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (v4Photon2.Pt() < v0cuts.minPt.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (std::fabs(v4Photon2.Eta()) >= v0cuts.maxEta.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (std::fabs(cZ2) > v0cuts.maxZconv.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (cR2 <= ((std::fabs(cZ2) * zRslope) - z0)) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (g2.psiPair() >= (0.18f * std::exp(-0.055f * g2.chi2NDF()))) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (g2.qt() >= (v0cuts.qTFactor.value * v4Photon2.Pt())) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + if (getCosP(collision, g2) <= v0cuts.cosP.value) { + registry.fill(HIST("hCutsPair"), 2); + continue; + } + + ROOT::Math::PxPyPzEVector vMeson = v4Photon1 + v4Photon2; + registry.fill(HIST("hCutsPair"), 3); + registry.fill(HIST("hSameEvent2D"), vMeson.M(), vMeson.Pt()); + } // end of loop over photon pairs + } // end of loop over collision + } + PROCESS_SWITCH(PcmRun2, process, "Default process function", true); +}; // End struct PcmRun2 + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/Common/TableProducer/CMakeLists.txt b/Common/TableProducer/CMakeLists.txt index 042bd643d3e..cdd408d4bff 100644 --- a/Common/TableProducer/CMakeLists.txt +++ b/Common/TableProducer/CMakeLists.txt @@ -25,6 +25,13 @@ o2physics_add_dpl_workflow(trackselection 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 + O2::DataFormatsITSMFT COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(multiplicity-table @@ -32,6 +39,11 @@ o2physics_add_dpl_workflow(multiplicity-table PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(multcenttable + SOURCES multCentTable.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(multiplicity-extra-table SOURCES multiplicityExtraTable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -47,6 +59,11 @@ o2physics_add_dpl_workflow(timestamp PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(timestamptester + SOURCES timestampTester.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(weak-decay-indices SOURCES weakDecayIndices.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -62,6 +79,11 @@ o2physics_add_dpl_workflow(track-propagation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(track-dca-cov-filler-run2 + SOURCES trackDcaCovFillerRun2.cxx + PUBLIC_LINK_LIBRARIES O2::DetectorsBase O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(track-propagation-tester SOURCES trackPropagationTester.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::trackSelectionRequest @@ -120,8 +142,8 @@ o2physics_add_dpl_workflow(match-mft-ft0 O2::DetectorsBase O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(zdc-task-intercalib - SOURCES zdc-task-intercalib.cxx +o2physics_add_dpl_workflow(zdc-task-inter-calib + SOURCES zdcTaskInterCalib.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -150,3 +172,7 @@ o2physics_add_dpl_workflow(muon-realignment PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2::DetectorsCommonDataFormats O2::MathUtils O2::MCHTracking O2::DataFormatsMCH O2::GlobalTracking O2::MCHBase O2::MCHGeometryTransformer O2::CommonUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(selectionstudytable + SOURCES selectionStudyTable.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/Common/TableProducer/PID/CMakeLists.txt b/Common/TableProducer/PID/CMakeLists.txt index d28a3268954..e0ea2d40ab3 100644 --- a/Common/TableProducer/PID/CMakeLists.txt +++ b/Common/TableProducer/PID/CMakeLists.txt @@ -43,9 +43,14 @@ o2physics_add_dpl_workflow(pid-tof-full # TPC +o2physics_add_dpl_workflow(pid-tpc-service + SOURCES pidTPCService.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(pid-tpc-base SOURCES pidTPCBase.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(pid-tpc diff --git a/Common/TableProducer/PID/pidITS.cxx b/Common/TableProducer/PID/pidITS.cxx index fbcc801c357..1a6cdbc5491 100644 --- a/Common/TableProducer/PID/pidITS.cxx +++ b/Common/TableProducer/PID/pidITS.cxx @@ -40,7 +40,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::track; -MetadataHelper metadataInfo; +o2::common::core::MetadataHelper metadataInfo; static constexpr int nCases = 2; static constexpr int nParameters = 12; diff --git a/Common/TableProducer/PID/pidTOFMerge.cxx b/Common/TableProducer/PID/pidTOFMerge.cxx index 7de835f4653..7ea0ac3b3b1 100644 --- a/Common/TableProducer/PID/pidTOFMerge.cxx +++ b/Common/TableProducer/PID/pidTOFMerge.cxx @@ -15,29 +15,30 @@ /// \author Nicolò Jacazio nicolo.jacazio@cern.ch /// -#include -#include -#include #include +#include #include +#include +#include // O2 includes -#include "Framework/runDataProcessing.h" +#include "CCDB/BasicCCDBManager.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "CCDB/BasicCCDBManager.h" #include "TOFBase/EventTimeMaker.h" // O2Physics includes -#include "TableHelper.h" -#include "MetadataHelper.h" #include "CollisionTypeHelper.h" +#include "MetadataHelper.h" +#include "TableHelper.h" #include "pidTOFBase.h" -#include "Common/DataModel/TrackSelectionTables.h" + #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" using namespace o2; using namespace o2::framework; @@ -45,7 +46,7 @@ using namespace o2::pid; using namespace o2::framework::expressions; using namespace o2::track; -MetadataHelper metadataInfo; +o2::common::core::MetadataHelper metadataInfo; // Input data types using Run3Trks = o2::soa::Join; @@ -924,7 +925,7 @@ struct tofPidMerge { doprocessRun2.value = false; } else { if (mTOFCalibConfig.autoSetProcessFunctions()) { - LOG(info) << "Autodetecting process functions for mass and beta"; + LOG(info) << "Autodetecting process functions"; if (metadataInfo.isFullyDefined()) { if (metadataInfo.isRun3()) { doprocessRun3.value = true; @@ -972,9 +973,11 @@ struct tofPidMerge { doprocessRun2BetaM.value = false; doprocessRun3BetaM.value = false; } else { + LOG(info) << "Table for TOF beta is " << (enableTableBeta ? "enabled" : "disabled"); + LOG(info) << "Table for TOF mass is " << (enableTableMass ? "enabled" : "disabled"); if (mTOFCalibConfig.autoSetProcessFunctions()) { LOG(info) << "Autodetecting process functions for mass and beta"; - if (metadataInfo.isFullyDefined()) { + if (metadataInfo.isInitialized()) { if (metadataInfo.isRun3()) { doprocessRun3BetaM.value = true; doprocessRun2BetaM.value = false; @@ -982,7 +985,12 @@ struct tofPidMerge { doprocessRun2BetaM.value = true; doprocessRun3BetaM.value = false; } + } else { + metadataInfo.print(); + LOG(warning) << "Metadata is not defined, cannot autodetect process functions for mass and beta"; } + } else { + LOG(info) << "Process functions for mass and beta are set manually"; } if (doprocessRun2BetaM && doprocessRun3BetaM) { LOG(fatal) << "Both processRun2BetaM and processRun3BetaM are enabled. Pick one of the two"; diff --git a/Common/TableProducer/PID/pidTPC.cxx b/Common/TableProducer/PID/pidTPC.cxx index 64500a47cb7..e9c2015afbc 100644 --- a/Common/TableProducer/PID/pidTPC.cxx +++ b/Common/TableProducer/PID/pidTPC.cxx @@ -18,10 +18,10 @@ /// \brief Task to produce PID tables for TPC split for each particle. /// Only the tables for the mass hypotheses requested are filled, and only for the requested table size ("Full" or "Tiny"). The others are sent empty. /// -#include #include #include #include +#include #include // ROOT includes #include "TFile.h" @@ -29,21 +29,23 @@ #include "TSystem.h" // O2 includes +#include "MetadataHelper.h" +#include "TableHelper.h" +#include "pidTPCBase.h" + +#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Tools/ML/model.h" + #include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "Framework/ASoAHelpers.h" #include "ReconstructionDataFormats/Track.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "TableHelper.h" -#include "Tools/ML/model.h" -#include "pidTPCBase.h" -#include "MetadataHelper.h" using namespace o2; using namespace o2::framework; @@ -53,7 +55,7 @@ using namespace o2::framework::expressions; using namespace o2::track; using namespace o2::ml; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper void customize(std::vector& workflowOptions) { @@ -148,15 +150,19 @@ struct tpcPid { Configurable useNetworkHe{"useNetworkHe", 1, {"Switch for applying neural network on the helium3 mass hypothesis (if network enabled) (set to 0 to disable)"}}; Configurable useNetworkAl{"useNetworkAl", 1, {"Switch for applying neural network on the alpha mass hypothesis (if network enabled) (set to 0 to disable)"}}; Configurable networkBetaGammaCutoff{"networkBetaGammaCutoff", 0.45, {"Lower value of beta-gamma to override the NN application"}}; + Configurable networkInputBatchedMode{"networkInputBatchedMode", -1, {"-1: Takes all tracks, >0: Takes networkInputBatchedMode number of tracks at once"}}; // Parametrization configuration bool useCCDBParam = false; + std::vector track_properties; void init(o2::framework::InitContext& initContext) { // Protection for process flags - if ((doprocessStandard && doprocessMcTuneOnData) || (!doprocessStandard && !doprocessMcTuneOnData)) { - LOG(fatal) << "pid-tpc must have only one of the options 'processStandard' OR 'processMcTuneOnData' enabled. Please check your configuration."; + if (!((doprocessStandard && !doprocessStandard2 && !doprocessMcTuneOnData) || + (!doprocessStandard && doprocessStandard2 && !doprocessMcTuneOnData) || + (!doprocessStandard && !doprocessStandard2 && doprocessMcTuneOnData))) { + LOG(fatal) << "pid-tpc must have only one of the options 'processStandard', 'processStandard2', 'processMcTuneOnData' enabled. Please check your configuration."; } response = new o2::pid::tpc::Response(); // Checking the tables are requested in the workflow and enabling them @@ -294,8 +300,6 @@ struct tpcPid { std::vector createNetworkPrediction(C const& collisions, T const& tracks, B const& bcs, const size_t size) { - std::vector network_prediction; - auto start_network_total = std::chrono::high_resolution_clock::now(); if (autofetchNetworks) { const auto& bc = bcs.begin(); @@ -341,20 +345,24 @@ struct tpcPid { // Defining some network parameters int input_dimensions = network.getNumInputNodes(); int output_dimensions = network.getNumOutputNodes(); - const uint64_t track_prop_size = input_dimensions * size; const uint64_t prediction_size = output_dimensions * size; + const uint8_t numSpecies = 9; + const uint64_t total_eval_size = size * numSpecies; // 9 species - network_prediction = std::vector(prediction_size * 9); // For each mass hypotheses const float nNclNormalization = response->GetNClNormalization(); float duration_network = 0; - std::vector track_properties(track_prop_size); - uint64_t counter_track_props = 0; - int loop_counter = 0; + uint64_t counter_track_props = 0, exec_counter = 0, in_batch_counter = 0, total_input_count = 0; + uint64_t track_prop_size = networkInputBatchedMode.value; + if (networkInputBatchedMode.value <= 0) { + track_prop_size = size; // If the networkInputBatchedMode is not set, we use all tracks at once + } + track_properties.resize(track_prop_size * input_dimensions); // If the networkInputBatchedMode is set, we use the number of tracks specified in the config + std::vector network_prediction(prediction_size * numSpecies); // For each mass hypotheses // Filling a std::vector to be evaluated by the network // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector - for (int i = 0; i < 9; i++) { // Loop over particle number for which network correction is used + for (int species = 0; species < numSpecies; species++) { // Loop over particle number for which network correction is used for (auto const& trk : tracks) { if (!trk.hasTPC()) { continue; @@ -364,30 +372,38 @@ struct tpcPid { continue; } } - track_properties[counter_track_props] = trk.tpcInnerParam(); + + if ((in_batch_counter == track_prop_size) || (total_input_count == total_eval_size)) { // If the batch size is reached, reset the counter + int32_t fill_shift = (exec_counter * track_prop_size - ((total_input_count == total_eval_size) ? (total_input_count % track_prop_size) : 0)) * output_dimensions; + auto start_network_eval = std::chrono::high_resolution_clock::now(); + 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 < (in_batch_counter * output_dimensions); i += output_dimensions) { + for (int j = 0; j < output_dimensions; j++) { + network_prediction[i + j + fill_shift] = output_network[i + j]; + } + } + counter_track_props = 0; + in_batch_counter = 0; + exec_counter++; + } + + // LOG(info) << "counter_tracks_props: " << counter_track_props << "; in_batch_counter: " << in_batch_counter << "; total_input_count: " << total_input_count << "; exec_counter: " << exec_counter << "; track_prop_size: " << track_prop_size << "; size: " << size << "; track_properties.size(): " << track_properties.size(); + track_properties[counter_track_props] = trk.tpcInnerParam(); // (tracks.asArrowTable()->GetColumn("tpcInnerParam")).GetData(); 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[species]; track_properties[counter_track_props + 4] = trk.has_collision() ? collisions.iteratorAt(trk.collisionId()).multTPC() / 11000. : 1.; track_properties[counter_track_props + 5] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); if (input_dimensions == 7 && networkVersion == "2") { track_properties[counter_track_props + 6] = trk.has_collision() ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; } counter_track_props += input_dimensions; + in_batch_counter++; + total_input_count++; } - - auto start_network_eval = std::chrono::high_resolution_clock::now(); - 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]; - } - } - - counter_track_props = 0; - loop_counter += 1; } track_properties.clear(); @@ -431,6 +447,11 @@ struct tpcPid { } float nSigma = -999.f; + int multTPC = 0; + if (trk.has_collision()) { + auto collision = collisions.rawIteratorAt(trk.collisionId()); + multTPC = collision.multTPC(); + } float bg = trk.tpcInnerParam() / o2::track::pid_constants::sMasses[pid]; // estimated beta-gamma for network cutoff if (useNetworkCorrection && speciesNetworkFlags[pid] && trk.has_collision() && bg > networkBetaGammaCutoff) { @@ -453,7 +474,7 @@ struct tpcPid { LOGF(fatal, "Network output-dimensions incompatible!"); } } else { - nSigma = response->GetNumberOfSigmaMCTuned(collisions.iteratorAt(trk.collisionId()), trk, pid, tpcSignal); + nSigma = response->GetNumberOfSigmaMCTunedAtMultiplicity(multTPC, trk, pid, tpcSignal); } if (flagFull) tableFull(expSigma, nSigma); @@ -552,6 +573,98 @@ struct tpcPid { Partition mcnotTPCStandaloneTracks = (aod::track::tpcNClsFindable > static_cast(0)) && ((aod::track::itsClusterSizes > static_cast(0)) || (aod::track::trdPattern > static_cast(0)) || (aod::track::tofExpMom > 0.f && aod::track::tofChi2 > 0.f)); // To count number of tracks for use in NN array Partition mctracksWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); + void processStandard2(Coll const& collisions, Trks const& tracks, aod::DEdxsCorrected const& dedxscorrected, aod::BCsWithTimestamps const& bcs) + { + const uint64_t outTable_size = tracks.size(); + const uint64_t dedxscorrected_size = dedxscorrected.size(); + + if (dedxscorrected_size != outTable_size) { + LOG(fatal) << "Size of dEdx corrected table does not match size of tracks! dEdx size: " << dedxscorrected_size << ", tracks size: " << outTable_size; + } + + auto reserveTable = [&outTable_size](const Configurable& flag, auto& table) { + if (flag.value != 1) { + return; + } + table.reserve(outTable_size); + }; + + // Prepare memory for enabled tables + reserveTable(pidFullEl, tablePIDFullEl); + reserveTable(pidFullMu, tablePIDFullMu); + reserveTable(pidFullPi, tablePIDFullPi); + reserveTable(pidFullKa, tablePIDFullKa); + reserveTable(pidFullPr, tablePIDFullPr); + reserveTable(pidFullDe, tablePIDFullDe); + reserveTable(pidFullTr, tablePIDFullTr); + reserveTable(pidFullHe, tablePIDFullHe); + reserveTable(pidFullAl, tablePIDFullAl); + + reserveTable(pidTinyEl, tablePIDTinyEl); + reserveTable(pidTinyMu, tablePIDTinyMu); + reserveTable(pidTinyPi, tablePIDTinyPi); + reserveTable(pidTinyKa, tablePIDTinyKa); + reserveTable(pidTinyPr, tablePIDTinyPr); + reserveTable(pidTinyDe, tablePIDTinyDe); + reserveTable(pidTinyTr, tablePIDTinyTr); + reserveTable(pidTinyHe, tablePIDTinyHe); + reserveTable(pidTinyAl, tablePIDTinyAl); + + const uint64_t tracksForNet_size = (skipTPCOnly) ? notTPCStandaloneTracks.size() : tracksWithTPC.size(); + std::vector network_prediction; + + if (useNetworkCorrection) { + network_prediction = createNetworkPrediction(collisions, tracks, bcs, tracksForNet_size); + } + + uint64_t count_tracks = 0; + uint64_t count_tracks2 = 0; + + for (auto const& trk : tracks) { + // Loop on Tracks + + const auto& bc = trk.has_collision() ? collisions.iteratorAt(trk.collisionId()).bc_as() : bcs.begin(); + auto dedx_corr = dedxscorrected.iteratorAt(count_tracks2); + count_tracks2++; + if (useCCDBParam && ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } 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()); + 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()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; + response->PrintAll(); + } + auto makePidTablesDefault = [&trk, &dedx_corr, &collisions, &network_prediction, &count_tracks, &tracksForNet_size, this](const int flagFull, auto& tableFull, const int flagTiny, auto& tableTiny, const o2::track::PID::ID pid) { + makePidTables(flagFull, tableFull, flagTiny, tableTiny, pid, dedx_corr.tpcSignalCorrected(), trk, collisions, network_prediction, count_tracks, tracksForNet_size); + }; + + makePidTablesDefault(pidFullEl, tablePIDFullEl, pidTinyEl, tablePIDTinyEl, o2::track::PID::Electron); + makePidTablesDefault(pidFullMu, tablePIDFullMu, pidTinyMu, tablePIDTinyMu, o2::track::PID::Muon); + makePidTablesDefault(pidFullPi, tablePIDFullPi, pidTinyPi, tablePIDTinyPi, o2::track::PID::Pion); + makePidTablesDefault(pidFullKa, tablePIDFullKa, pidTinyKa, tablePIDTinyKa, o2::track::PID::Kaon); + makePidTablesDefault(pidFullPr, tablePIDFullPr, pidTinyPr, tablePIDTinyPr, o2::track::PID::Proton); + makePidTablesDefault(pidFullDe, tablePIDFullDe, pidTinyDe, tablePIDTinyDe, o2::track::PID::Deuteron); + makePidTablesDefault(pidFullTr, tablePIDFullTr, pidTinyTr, tablePIDTinyTr, o2::track::PID::Triton); + makePidTablesDefault(pidFullHe, tablePIDFullHe, pidTinyHe, tablePIDTinyHe, o2::track::PID::Helium3); + makePidTablesDefault(pidFullAl, tablePIDFullAl, pidTinyAl, tablePIDTinyAl, o2::track::PID::Alpha); + + if (trk.hasTPC() && (!skipTPCOnly || trk.hasITS() || trk.hasTRD() || trk.hasTOF())) { + count_tracks++; // Increment network track counter only if track has TPC, and (not skipping TPConly) or (is not TPConly) + } + } + } + PROCESS_SWITCH(tpcPid, processStandard2, "Creating PID tables with Corrected dEdx", false); void processMcTuneOnData(CollMC const& collisionsMc, TrksMC const& tracksMc, aod::BCsWithTimestamps const& bcs, aod::McParticles const&) { gRandom->SetSeed(0); // Ensure unique seed from UUID for each process call diff --git a/Common/TableProducer/PID/pidTPCBase.cxx b/Common/TableProducer/PID/pidTPCBase.cxx index cf82ea0c9d5..1f9ef4278fc 100644 --- a/Common/TableProducer/PID/pidTPCBase.cxx +++ b/Common/TableProducer/PID/pidTPCBase.cxx @@ -15,18 +15,21 @@ /// \brief Base to build tasks for TPC PID tasks. /// +#include #include #include -#include // O2 includes -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/FT0Corrected.h" #include "TableHelper.h" #include "pidTPCBase.h" + +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/DataModel/FT0Corrected.h" + +#include "CCDB/BasicCCDBManager.h" +#include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" using namespace o2; using namespace o2::framework; @@ -76,7 +79,105 @@ struct PidMultiplicity { PROCESS_SWITCH(PidMultiplicity, processStandard, "Process with tracks, needs propagated tracks", true); }; +struct DeDxCorrection { + Produces dEdxCorrected; + using BCsRun3 = soa::Join; + using ColEvSels = soa::Join; + using FullTracksIU = soa::Join; + + uint64_t minGlobalBC = 0; + Service ccdb; + ctpRateFetcher mRateFetcher; + + Str_dEdx_correction str_dedx_correction; + + // void init(InitContext& initContext) + void init(o2::framework::InitContext&) + { + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + str_dedx_correction.init(); + } + + void processRun3( + ColEvSels const& cols, + FullTracksIU const& tracks, + aod::BCsWithTimestamps const& bcs) + { + const uint64_t outTable_size = tracks.size(); + dEdxCorrected.reserve(outTable_size); + + for (auto const& trk : tracks) { + double hadronicRate; + int multTPC; + int occupancy; + if (trk.has_collision()) { + auto collision = cols.iteratorAt(trk.collisionId()); + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz + multTPC = collision.multTPC(); + occupancy = collision.trackOccupancyInTimeRange(); + } else { + auto bc = bcs.begin(); + const int runnumber = bc.runNumber(); + hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz + multTPC = 0; + occupancy = 0; + } + + float fTPCSignal = trk.tpcSignal(); + float fNormMultTPC = multTPC / 11000.; + + float fTrackOccN = occupancy / 1000.; + float fOccTPCN = fNormMultTPC * 10; //(fNormMultTPC*10).clip(0,12) + if (fOccTPCN > 12) + fOccTPCN = 12; + else if (fOccTPCN < 0) + fOccTPCN = 0; + + float fTrackOccMeanN = hadronicRate / 5; + float side = trk.tgl() > 0 ? 1 : 0; + float a1pt = std::abs(trk.signed1Pt()); + float a1pt2 = a1pt * a1pt; + float atgl = std::abs(trk.tgl()); + float mbb0R = 50 / fTPCSignal; + if (mbb0R > 1.05) + mbb0R = 1.05; + else if (mbb0R < 0.05) + mbb0R = 0.05; + // float mbb0R = max(0.05, min(50 / fTPCSignal, 1.05)); + float a1ptmbb0R = a1pt * mbb0R; + float atglmbb0R = atgl * mbb0R; + + std::vector vec_occu = {fTrackOccN, fOccTPCN, fTrackOccMeanN}; + std::vector vec_track = {mbb0R, a1pt, atgl, atglmbb0R, a1ptmbb0R, side, a1pt2}; + + float fTPCSignalN_CR0 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track); + + float mbb0R1 = 50 / (fTPCSignal / fTPCSignalN_CR0); + if (mbb0R1 > 1.05) + mbb0R1 = 1.05; + else if (mbb0R1 < 0.05) + mbb0R1 = 0.05; + + std::vector vec_track1 = {mbb0R1, a1pt, atgl, atgl * mbb0R1, a1pt * mbb0R1, side, a1pt2}; + float fTPCSignalN_CR1 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track1); + + float corrected_dEdx = fTPCSignal / fTPCSignalN_CR1; + dEdxCorrected(corrected_dEdx); + } + } + PROCESS_SWITCH(DeDxCorrection, processRun3, "dEdx correction process", false); + + void processDummy(aod::Collisions const&) {} + + PROCESS_SWITCH(DeDxCorrection, processDummy, "Do nothing", true); +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/Common/TableProducer/PID/pidTPCBase.h b/Common/TableProducer/PID/pidTPCBase.h index 937eea21c48..42dedec46ff 100644 --- a/Common/TableProducer/PID/pidTPCBase.h +++ b/Common/TableProducer/PID/pidTPCBase.h @@ -21,13 +21,22 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponseTPC.h" +#include "TMatrixD.h" + namespace o2::aod { +namespace pid +{ +DECLARE_SOA_COLUMN(TpcSignalCorrected, tpcSignalCorrected, float); //! +}; // namespace pid + DECLARE_SOA_TABLE(PIDMults, "AOD", "PIDMults", //! TPC auxiliary table for the PID o2::soa::Marker<1>, mult::MultTPC); +DECLARE_SOA_TABLE_FULL(DEdxsCorrected, "DEdxsCorrected", "AOD", "DEDXCORR", pid::TpcSignalCorrected); //! using PIDMult = PIDMults::iterator; +using DEdxCorrected = DEdxsCorrected::iterator; //! } // namespace o2::aod @@ -57,4 +66,41 @@ int getPIDIndex(const int pdgCode) // Get O2 PID index corresponding to MC PDG c } } +typedef struct Str_dEdx_correction { + TMatrixD fMatrix; + bool warning = true; + + // void init(std::vector& params) + void init() + { + double elements[32] = {0.99091, -0.015053, 0.0018912, -0.012305, + 0.081387, 0.003205, -0.0087404, -0.0028608, + 0.013066, 0.017012, -0.0018469, -0.0052177, + -0.0035655, 0.0017846, 0.0019127, -0.00012964, + 0.0049428, 0.0055592, -0.0010618, -0.0016134, + -0.0059098, 0.0013335, 0.00052133, 3.1119e-05, + -0.004882, 0.00077317, -0.0013827, 0.003249, + -0.00063689, 0.0016218, -0.00045215, -1.5815e-05}; + fMatrix.ResizeTo(4, 8); + fMatrix.SetMatrixArray(elements); + } + + float fReal_fTPCSignalN(std::vector vec1, std::vector vec2) + { + float result = 0.f; + // push 1. + vec1.insert(vec1.begin(), 1.0); + vec2.insert(vec2.begin(), 1.0); + 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]; + result += param * value1 * value2; + } + } + return result; + } +} Str_dEdx_correction; + #endif // COMMON_TABLEPRODUCER_PID_PIDTPCBASE_H_ diff --git a/Common/TableProducer/PID/pidTPCModule.h b/Common/TableProducer/PID/pidTPCModule.h new file mode 100644 index 00000000000..321b6e39329 --- /dev/null +++ b/Common/TableProducer/PID/pidTPCModule.h @@ -0,0 +1,793 @@ +// 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 pidTPCModule.h +/// \brief Task to produce PID tables for TPC split for each particle. +/// Only the tables for the mass hypotheses requested are filled, and only for the requested table size +/// ("Full" or "Tiny"). The others are sent empty. +/// \author Nicolò Jacazio nicolo.jacazio@cern.ch +/// \author Christian Sonnabend christian.sonnabend@cern.ch +/// \author Annalena Kalteyer annalena.sophie.kalteyer@cern.ch +/// \author Jeremy Wilkinson jeremy.wilkinson@cern.ch + +#ifndef COMMON_TOOLS_PIDTPCMODULE_H_ +#define COMMON_TOOLS_PIDTPCMODULE_H_ + +#include +#include +#include +#include +#include +// ROOT includes +#include "TFile.h" +#include "TRandom.h" +#include "TSystem.h" + +// O2 includes +#include "MetadataHelper.h" +#include "TableHelper.h" +#include "pidTPCBase.h" + +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Tools/ML/model.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +namespace o2::aod +{ +namespace pid +{ +struct pidTPCProducts : o2::framework::ProducesGroup { + // Intermediate tables (provide only if requested) + o2::framework::Produces dEdxCorrected; + o2::framework::Produces mult; + + // Tables produced by TPC component + o2::framework::Produces tablePIDFullEl; + o2::framework::Produces tablePIDFullMu; + o2::framework::Produces tablePIDFullPi; + o2::framework::Produces tablePIDFullKa; + o2::framework::Produces tablePIDFullPr; + o2::framework::Produces tablePIDFullDe; + o2::framework::Produces tablePIDFullTr; + o2::framework::Produces tablePIDFullHe; + o2::framework::Produces tablePIDFullAl; + + o2::framework::Produces tablePIDTinyEl; + o2::framework::Produces tablePIDTinyMu; + o2::framework::Produces tablePIDTinyPi; + o2::framework::Produces tablePIDTinyKa; + o2::framework::Produces tablePIDTinyPr; + o2::framework::Produces tablePIDTinyDe; + o2::framework::Produces tablePIDTinyTr; + o2::framework::Produces tablePIDTinyHe; + o2::framework::Produces tablePIDTinyAl; + o2::framework::Produces tableTuneOnData; +}; + +struct pidTPCConfigurables : o2::framework::ConfigurableGroup { + std::string prefix = "pidTPC"; + o2::framework::Configurable paramfile{"param-file", "", "Path to the parametrization object, if empty the parametrization is not taken from file"}; + o2::framework::Configurable ccdbPath{"ccdbPath", "Analysis/PID/TPC/Response", "Path of the TPC parametrization on the CCDB"}; + o2::framework::Configurable recoPass{"recoPass", "", "Reconstruction pass name for CCDB query (automatically takes latest object for timestamp if blank)"}; + o2::framework::Configurable ccdbTimestamp{"ccdb-timestamp", 0, "timestamp of the object used to query in CCDB the detector response. Exceptions: -1 gets the latest object, 0 gets the run dependent timestamp"}; + // Parameters for loading network from a file / downloading the file + o2::framework::Configurable useNetworkCorrection{"useNetworkCorrection", 0, "(bool) Wether or not to use the network correction for the TPC dE/dx signal"}; + o2::framework::Configurable autofetchNetworks{"autofetchNetworks", 1, "(bool) Automatically fetches networks from CCDB for the correct run number"}; + o2::framework::Configurable skipTPCOnly{"skipTPCOnly", false, "Flag to skip TPC only tracks (faster but affects the analyses that use TPC only tracks)"}; + o2::framework::Configurable networkPathLocally{"networkPathLocally", "network.onnx", "(std::string) Path to the local .onnx file. If autofetching is enabled, then this is where the files will be downloaded"}; + o2::framework::Configurable networkPathCCDB{"networkPathCCDB", "Analysis/PID/TPC/ML", "Path on CCDB"}; + o2::framework::Configurable enableNetworkOptimizations{"enableNetworkOptimizations", 1, "(bool) If the neural network correction is used, this enables GraphOptimizationLevel::ORT_ENABLE_EXTENDED in the ONNX session"}; + o2::framework::Configurable networkSetNumThreads{"networkSetNumThreads", 0, "Especially important for running on a SLURM cluster. Sets the number of threads used for execution."}; + // Configuration flags to include and exclude particle hypotheses + o2::framework::Configurable savedEdxsCorrected{"savedEdxsCorrected", -1, {"Save table with corrected dE/dx calculated on the spot. 0: off, 1: on, -1: auto"}}; + o2::framework::Configurable useCorrecteddEdx{"useCorrecteddEdx", false, "(bool) If true, use corrected dEdx value in Nsigma calculation instead of the one in the AO2D"}; + + o2::framework::Configurable pidFullEl{"pid-full-el", -1, {"Produce PID information for the Electron mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullMu{"pid-full-mu", -1, {"Produce PID information for the Muon mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullPi{"pid-full-pi", -1, {"Produce PID information for the Pion mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullKa{"pid-full-ka", -1, {"Produce PID information for the Kaon mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullPr{"pid-full-pr", -1, {"Produce PID information for the Proton mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullDe{"pid-full-de", -1, {"Produce PID information for the Deuterons mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullTr{"pid-full-tr", -1, {"Produce PID information for the Triton mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullHe{"pid-full-he", -1, {"Produce PID information for the Helium3 mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidFullAl{"pid-full-al", -1, {"Produce PID information for the Alpha mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyEl{"pid-tiny-el", -1, {"Produce PID information for the Electron mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyMu{"pid-tiny-mu", -1, {"Produce PID information for the Muon mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyPi{"pid-tiny-pi", -1, {"Produce PID information for the Pion mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyKa{"pid-tiny-ka", -1, {"Produce PID information for the Kaon mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyPr{"pid-tiny-pr", -1, {"Produce PID information for the Proton mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyDe{"pid-tiny-de", -1, {"Produce PID information for the Deuterons mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyTr{"pid-tiny-tr", -1, {"Produce PID information for the Triton mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyHe{"pid-tiny-he", -1, {"Produce PID information for the Helium3 mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable pidTinyAl{"pid-tiny-al", -1, {"Produce PID information for the Alpha mass hypothesis, overrides the automatic setup: the corresponding table can be set off (0) or on (1)"}}; + o2::framework::Configurable enableTuneOnDataTable{"enableTuneOnDataTable", -1, {"Produce tuned dE/dx signal table for MC to be used as raw signal in other tasks (default -1, 'only if needed'"}}; + o2::framework::Configurable useNetworkEl{"useNetworkEl", 1, {"Switch for applying neural network on the electron mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkMu{"useNetworkMu", 1, {"Switch for applying neural network on the muon mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkPi{"useNetworkPi", 1, {"Switch for applying neural network on the pion mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkKa{"useNetworkKa", 1, {"Switch for applying neural network on the kaon mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkPr{"useNetworkPr", 1, {"Switch for applying neural network on the proton mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkDe{"useNetworkDe", 1, {"Switch for applying neural network on the deuteron mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkTr{"useNetworkTr", 1, {"Switch for applying neural network on the triton mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkHe{"useNetworkHe", 1, {"Switch for applying neural network on the helium3 mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable useNetworkAl{"useNetworkAl", 1, {"Switch for applying neural network on the alpha mass hypothesis (if network enabled) (set to 0 to disable)"}}; + o2::framework::Configurable networkBetaGammaCutoff{"networkBetaGammaCutoff", 0.45, {"Lower value of beta-gamma to override the NN application"}}; +}; + +// helper getter - FIXME should be separate +int getPIDIndex(const int pdgCode) // Get O2 PID index corresponding to MC PDG code +{ + switch (abs(pdgCode)) { + case 11: + return o2::track::PID::Electron; + case 13: + return o2::track::PID::Muon; + case 211: + return o2::track::PID::Pion; + case 321: + return o2::track::PID::Kaon; + case 2212: + return o2::track::PID::Proton; + case 1000010020: + return o2::track::PID::Deuteron; + case 1000010030: + return o2::track::PID::Triton; + case 1000020030: + return o2::track::PID::Helium3; + case 1000020040: + return o2::track::PID::Alpha; + default: // treat as pion if not any of the above + return o2::track::PID::Pion; + } +} + +typedef struct Str_dEdx_correction { + TMatrixD fMatrix; + bool warning = true; + + // void init(std::vector& params) + void init() + { + double elements[32] = {0.99091, -0.015053, 0.0018912, -0.012305, + 0.081387, 0.003205, -0.0087404, -0.0028608, + 0.013066, 0.017012, -0.0018469, -0.0052177, + -0.0035655, 0.0017846, 0.0019127, -0.00012964, + 0.0049428, 0.0055592, -0.0010618, -0.0016134, + -0.0059098, 0.0013335, 0.00052133, 3.1119e-05, + -0.004882, 0.00077317, -0.0013827, 0.003249, + -0.00063689, 0.0016218, -0.00045215, -1.5815e-05}; + fMatrix.ResizeTo(4, 8); + fMatrix.SetMatrixArray(elements); + } + + float fReal_fTPCSignalN(std::vector vec1, std::vector vec2) + { + float result = 0.f; + // push 1. + vec1.insert(vec1.begin(), 1.0); + vec2.insert(vec2.begin(), 1.0); + 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]; + result += param * value1 * value2; + } + } + return result; + } +} Str_dEdx_correction; + +class pidTPCModule +{ + public: + pidTPCModule() + { + // constructor + } + o2::aod::pid::pidTPCConfigurables pidTPCopts; + + // TPC PID Response + o2::pid::tpc::Response* response; + + // 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; + + // Parametrization configuration + bool useCCDBParam = false; + + // for dEdx correction + ctpRateFetcher mRateFetcher; + Str_dEdx_correction str_dedx_correction; + + //__________________________________________________ + template + void init(TCCDB& ccdb, TCCDBApi& ccdbApi, 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, "***************************************************"); + } + + // initialize PID response + response = new o2::pid::tpc::Response(); + + enableFlagIfTableRequired(context, "DEdxsCorrected", pidTPCopts.savedEdxsCorrected); + + // Checking the tables are requested in the workflow and enabling them + auto enableFlag = [&](const std::string particle, o2::framework::Configurable& flag) { + enableFlagIfTableRequired(context, "pidTPC" + particle, flag); + }; + enableFlag("FullEl", pidTPCopts.pidFullEl); + enableFlag("FullMu", pidTPCopts.pidFullMu); + enableFlag("FullPi", pidTPCopts.pidFullPi); + enableFlag("FullKa", pidTPCopts.pidFullKa); + enableFlag("FullPr", pidTPCopts.pidFullPr); + enableFlag("FullDe", pidTPCopts.pidFullDe); + enableFlag("FullTr", pidTPCopts.pidFullTr); + enableFlag("FullHe", pidTPCopts.pidFullHe); + enableFlag("FullAl", pidTPCopts.pidFullAl); + + enableFlag("El", pidTPCopts.pidTinyEl); + enableFlag("Mu", pidTPCopts.pidTinyMu); + enableFlag("Pi", pidTPCopts.pidTinyPi); + enableFlag("Ka", pidTPCopts.pidTinyKa); + enableFlag("Pr", pidTPCopts.pidTinyPr); + enableFlag("De", pidTPCopts.pidTinyDe); + enableFlag("Tr", pidTPCopts.pidTinyTr); + enableFlag("He", pidTPCopts.pidTinyHe); + enableFlag("Al", pidTPCopts.pidTinyAl); + + if (metadataInfo.isMC()) { + enableFlagIfTableRequired(context, "mcTPCTuneOnData", pidTPCopts.enableTuneOnDataTable); + } + + speciesNetworkFlags[0] = pidTPCopts.useNetworkEl; + speciesNetworkFlags[1] = pidTPCopts.useNetworkMu; + speciesNetworkFlags[2] = pidTPCopts.useNetworkPi; + speciesNetworkFlags[3] = pidTPCopts.useNetworkKa; + speciesNetworkFlags[4] = pidTPCopts.useNetworkPr; + speciesNetworkFlags[5] = pidTPCopts.useNetworkDe; + speciesNetworkFlags[6] = pidTPCopts.useNetworkTr; + speciesNetworkFlags[7] = pidTPCopts.useNetworkHe; + speciesNetworkFlags[8] = pidTPCopts.useNetworkAl; + + // Initialise metadata object for CCDB calls from AO2D metadata + if (pidTPCopts.recoPass.value == "") { + if (metadataInfo.isFullyDefined()) { + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + LOGP(info, "Automatically setting reco pass for TPC Response to {} from AO2D", metadata["RecoPassName"]); + } + } else { + LOGP(info, "Setting reco pass for TPC response to user-defined name {}", pidTPCopts.recoPass.value); + metadata["RecoPassName"] = pidTPCopts.recoPass.value; + } + + /// TPC PID Response + const TString fname = pidTPCopts.paramfile.value; + if (fname != "") { // Loading the parametrization from file + LOGP(info, "Loading TPC response from file {}", fname.Data()); + try { + std::unique_ptr f(TFile::Open(fname, "READ")); + f->GetObject("Response", response); + } catch (...) { + LOGF(fatal, "Loading the TPC PID Response from file {} failed!", fname.Data()); + } + response->PrintAll(); + } else { + useCCDBParam = true; + const std::string path = pidTPCopts.ccdbPath.value; + const auto time = pidTPCopts.ccdbTimestamp.value; + 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); + 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"]; + if (!response) { + LOGF(fatal, "Unable to find any TPC object corresponding to timestamp {}!", time); + } + } + 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(); + } + } + + /// Neural network init for TPC PID + if (!pidTPCopts.useNetworkCorrection) { + return; + } else { + /// CCDB and auto-fetching + if (!pidTPCopts.autofetchNetworks) { + 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); + 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); /// Init the model evaluations + LOGP(info, "Retrieved NN corrections for production tag {}, pass number {}, and NN-Version {}", 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"; + } + } else { + /// Taking the network from local file + if (pidTPCopts.networkPathLocally.value == "") { + LOG(fatal) << "Local path must be set (flag networkPathLocally)! Aborting..."; + } + LOG(info) << "Using local file [" << pidTPCopts.networkPathLocally.value << "] for the TPC PID response correction."; + network.initModel(pidTPCopts.networkPathLocally.value, pidTPCopts.enableNetworkOptimizations.value, pidTPCopts.networkSetNumThreads.value); + std::vector dummyInput(network.getNumInputNodes(), 1.); + network.evalModel(dummyInput); // This is an initialisation and might reduce the overhead of the model + } + } else { + return; + } + } + + if (pidTPCopts.useCorrecteddEdx.value && networkVersion != "5") { + LOGF(fatal, "Using corrected dE/dx with a network version other than 5 will not work. Crashing now."); + } + } // end init + + //__________________________________________________ + template + std::vector createNetworkPrediction(TCCDB& ccdb, TCCDBApi& ccdbApi, C const& collisions, M const& mults, T const& tracks, B const& bcs, const size_t size) + { + + std::vector network_prediction; + + auto start_network_total = std::chrono::high_resolution_clock::now(); + if (pidTPCopts.autofetchNetworks) { + const auto& bc = bcs.begin(); + // Initialise correct TPC response object before NN setup (for NCl normalisation) + if (useCCDBParam && pidTPCopts.ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(pidTPCopts.ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (pidTPCopts.recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } 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()); + 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()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + 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(); + } + + 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()); + 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"]); + } 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"; + } + } + } + + // Defining some network parameters + int input_dimensions = network.getNumInputNodes(); + int output_dimensions = network.getNumOutputNodes(); + const uint64_t track_prop_size = input_dimensions * size; + const uint64_t prediction_size = output_dimensions * size; + + network_prediction = std::vector(prediction_size * 9); // For each mass hypotheses + const float nNclNormalization = response->GetNClNormalization(); + float duration_network = 0; + + std::vector track_properties(track_prop_size); + uint64_t counter_track_props = 0; + int loop_counter = 0; + + // Filling a std::vector to be evaluated by the network + // Evaluation on single tracks brings huge overhead: Thus evaluation is done on one large vector + for (int i = 0; i < 9; i++) { // Loop over particle number for which network correction is used + for (auto const& trk : tracks) { + if (!trk.hasTPC()) { + continue; + } + if (pidTPCopts.skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + continue; + } + } + 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 + 4] = trk.has_collision() ? mults[trk.collisionId()] / 11000. : 1.; + track_properties[counter_track_props + 5] = std::sqrt(nNclNormalization / trk.tpcNClsFound()); + if (input_dimensions == 7 && networkVersion == "2") { + track_properties[counter_track_props + 6] = trk.has_collision() ? collisions.iteratorAt(trk.collisionId()).ft0cOccupancyInTimeRange() / 60000. : 1.; + } + counter_track_props += input_dimensions; + } + + auto start_network_eval = std::chrono::high_resolution_clock::now(); + 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]; + } + } + + counter_track_props = 0; + loop_counter += 1; + } + track_properties.clear(); + + auto stop_network_total = std::chrono::high_resolution_clock::now(); + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval ONNX): " << duration_network / (size * 9) << "ns ; Total time (eval ONNX): " << duration_network / 1000000000 << " s"; + LOG(debug) << "Neural Network for the TPC PID response correction: Time per track (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / (size * 9) << "ns ; Total time (eval + overhead): " << std::chrono::duration>(stop_network_total - start_network_total).count() / 1000000000 << " s"; + + return network_prediction; + } + + //__________________________________________________ + template + void makePidTables(const int flagFull, NSF& tableFull, const int flagTiny, NST& tableTiny, const o2::track::PID::ID pid, const float tpcSignal, const T& trk, const long multTPC, const std::vector& network_prediction, const int& count_tracks, const int& tracksForNet_size) + { + if (flagFull != 1 && flagTiny != 1) { + return; + } + if (!trk.hasTPC() || tpcSignal < 0.f) { + if (flagFull) + tableFull(-999.f, -999.f); + if (flagTiny) + tableTiny(aod::pidtpc_tiny::binning::underflowBin); + return; + } + if (pidTPCopts.skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + if (flagFull) + tableFull(-999.f, -999.f); + if (flagTiny) + tableTiny(aod::pidtpc_tiny::binning::underflowBin); + return; + } + } + auto expSignal = response->GetExpectedSignal(trk, pid); + auto expSigma = trk.has_collision() ? response->GetExpectedSigmaAtMultiplicity(multTPC, trk, pid) : 0.07 * expSignal; // use default sigma value of 7% if no collision information to estimate resolution + if (expSignal < 0. || expSigma < 0.) { // skip if expected signal invalid + if (flagFull) + tableFull(-999.f, -999.f); + if (flagTiny) + tableTiny(aod::pidtpc_tiny::binning::underflowBin); + return; + } + + float nSigma = -999.f; + float bg = trk.tpcInnerParam() / o2::track::pid_constants::sMasses[pid]; // estimated beta-gamma for network cutoff + if (pidTPCopts.useNetworkCorrection && speciesNetworkFlags[pid] && trk.has_collision() && bg > pidTPCopts.networkBetaGammaCutoff) { + + // Here comes the application of the network. The output--dimensions of the network determine the application: 1: mean, 2: sigma, 3: sigma asymmetric + // For now only the option 2: sigma will be used. The other options are kept if there would be demand later on + if (network.getNumOutputNodes() == 1) { // Expected mean correction; no sigma correction + nSigma = (tpcSignal - network_prediction[count_tracks + tracksForNet_size * pid] * expSignal) / expSigma; + } else if (network.getNumOutputNodes() == 2) { // Symmetric sigma correction + expSigma = (network_prediction[2 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]) * expSignal; + nSigma = (tpcSignal / expSignal - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[2 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]); + } else if (network.getNumOutputNodes() == 3) { // Asymmetric sigma corection + if (tpcSignal / expSignal >= network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) { + expSigma = (network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) * expSignal; + nSigma = (tpcSignal / expSignal - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]); + } else { + expSigma = (network_prediction[3 * (count_tracks + tracksForNet_size * pid)] - network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 2]) * expSignal; + nSigma = (tpcSignal / expSignal - network_prediction[3 * (count_tracks + tracksForNet_size * pid)]) / (network_prediction[3 * (count_tracks + tracksForNet_size * pid)] - network_prediction[3 * (count_tracks + tracksForNet_size * pid) + 2]); + } + } else { + LOGF(fatal, "Network output-dimensions incompatible!"); + } + } else { + nSigma = response->GetNumberOfSigmaMCTunedAtMultiplicity(multTPC, trk, pid, tpcSignal); + } + if (flagFull) + tableFull(expSigma, nSigma); + if (flagTiny) + aod::pidtpc_tiny::binning::packInTable(nSigma, tableTiny); + }; + + //__________________________________________________ + template + void process(TCCDB& ccdb, TCCDBApi& ccdbApi, TBCs const& bcs, TCollisions const& cols, TTracks const& tracks, TTracksQA const& tracksQA, TProducts& products) + { + if (tracks.size() == 0) { + return; // empty protection + } + auto trackiterator = tracks.begin(); + if constexpr (requires { trackiterator.mcParticleId(); }) { + gRandom->SetSeed(0); // Ensure unique seed from UUID for each process call + } + + // preparatory step: we need the multiplicities for each collision + std::vector pidmults; + long totalTPCtracks = 0; + long totalTPCnotStandalone = 0; + pidmults.resize(cols.size(), 0); + + // faster counting + for (const auto& track : tracks) { + if (track.hasTPC()) { + if (track.collisionId() > -1) { + pidmults[track.collisionId()]++; + } + totalTPCtracks++; + if (track.hasITS() || track.hasTOF() || track.hasTRD()) { + totalTPCnotStandalone++; + } + } + } + + const uint64_t outTable_size = tracks.size(); + + auto reserveTable = [&outTable_size](const o2::framework::Configurable& flag, auto& table) { + if (flag.value != 1) { + return; + } + table.reserve(outTable_size); + }; + + // Prepare memory for enabled tables + reserveTable(pidTPCopts.pidFullEl, products.tablePIDFullEl); + reserveTable(pidTPCopts.pidFullMu, products.tablePIDFullMu); + reserveTable(pidTPCopts.pidFullPi, products.tablePIDFullPi); + reserveTable(pidTPCopts.pidFullKa, products.tablePIDFullKa); + reserveTable(pidTPCopts.pidFullPr, products.tablePIDFullPr); + reserveTable(pidTPCopts.pidFullDe, products.tablePIDFullDe); + reserveTable(pidTPCopts.pidFullTr, products.tablePIDFullTr); + reserveTable(pidTPCopts.pidFullHe, products.tablePIDFullHe); + reserveTable(pidTPCopts.pidFullAl, products.tablePIDFullAl); + + reserveTable(pidTPCopts.pidTinyEl, products.tablePIDTinyEl); + reserveTable(pidTPCopts.pidTinyMu, products.tablePIDTinyMu); + reserveTable(pidTPCopts.pidTinyPi, products.tablePIDTinyPi); + reserveTable(pidTPCopts.pidTinyKa, products.tablePIDTinyKa); + reserveTable(pidTPCopts.pidTinyPr, products.tablePIDTinyPr); + reserveTable(pidTPCopts.pidTinyDe, products.tablePIDTinyDe); + reserveTable(pidTPCopts.pidTinyTr, products.tablePIDTinyTr); + reserveTable(pidTPCopts.pidTinyHe, products.tablePIDTinyHe); + reserveTable(pidTPCopts.pidTinyAl, products.tablePIDTinyAl); + + const uint64_t tracksForNet_size = (pidTPCopts.skipTPCOnly) ? totalTPCnotStandalone : totalTPCtracks; + std::vector network_prediction; + + if (pidTPCopts.useNetworkCorrection) { + network_prediction = createNetworkPrediction(ccdb, ccdbApi, cols, pidmults, tracks, bcs, tracksForNet_size); + } + + uint64_t count_tracks = 0; + + //_______________________________________ + // process tracksQA in case present + std::vector indexTrack2TrackQA; + if constexpr (soa::is_table) { + for (const auto& trackQA : tracksQA) { + indexTrack2TrackQA[trackQA.trackId()] = trackQA.globalIndex(); + } + } + //_______________________________________ + + for (auto const& trk : tracks) { + // get the TPC signal to be used in the PID + float tpcSignalToEvaluatePID = trk.tpcSignal(); + + int multTPC = 0; + if (trk.has_collision()) { + multTPC = pidmults[trk.collisionId()]; + } + + // if corrected dE/dx is requested, correct it here on the spot and use that + if (pidTPCopts.useCorrecteddEdx) { + + //_________________________________________________________ + // bypass TPC signal in case TracksQA information present + if constexpr (soa::is_table) { + tpcSignalToEvaluatePID = -999.f; + if (indexTrack2TrackQA[trk.globalIndex()] != -1) { + auto trackQA = tracksQA.rawIteratorAt(indexTrack2TrackQA[trk.globalIndex()]); + tpcSignalToEvaluatePID = trackQA.tpcdEdxNorm(); + } + } + //_________________________________________________________ + + double hadronicRate; + int occupancy; + if (trk.has_collision()) { + auto collision = cols.iteratorAt(trk.collisionId()); + auto bc = collision.template bc_as(); + const int runnumber = bc.runNumber(); + hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz + occupancy = collision.trackOccupancyInTimeRange(); + } else { + auto bc = bcs.begin(); + const int runnumber = bc.runNumber(); + hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, "ZNC hadronic") * 1.e-3; // kHz + occupancy = 0; + } + + float fTPCSignal = tpcSignalToEvaluatePID; + float fNormMultTPC = multTPC / 11000.; + + float fTrackOccN = occupancy / 1000.; + float fOccTPCN = fNormMultTPC * 10; //(fNormMultTPC*10).clip(0,12) + if (fOccTPCN > 12) + fOccTPCN = 12; + else if (fOccTPCN < 0) + fOccTPCN = 0; + + float fTrackOccMeanN = hadronicRate / 5; + float side = trk.tgl() > 0 ? 1 : 0; + float a1pt = std::abs(trk.signed1Pt()); + float a1pt2 = a1pt * a1pt; + float atgl = std::abs(trk.tgl()); + float mbb0R = 50 / fTPCSignal; + if (mbb0R > 1.05) + mbb0R = 1.05; + else if (mbb0R < 0.05) + mbb0R = 0.05; + // float mbb0R = max(0.05, min(50 / fTPCSignal, 1.05)); + float a1ptmbb0R = a1pt * mbb0R; + float atglmbb0R = atgl * mbb0R; + + std::vector vec_occu = {fTrackOccN, fOccTPCN, fTrackOccMeanN}; + std::vector vec_track = {mbb0R, a1pt, atgl, atglmbb0R, a1ptmbb0R, side, a1pt2}; + + float fTPCSignalN_CR0 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track); + + float mbb0R1 = 50 / (fTPCSignal / fTPCSignalN_CR0); + if (mbb0R1 > 1.05) + mbb0R1 = 1.05; + else if (mbb0R1 < 0.05) + mbb0R1 = 0.05; + + std::vector vec_track1 = {mbb0R1, a1pt, atgl, atgl * mbb0R1, a1pt * mbb0R1, side, a1pt2}; + float fTPCSignalN_CR1 = str_dedx_correction.fReal_fTPCSignalN(vec_occu, vec_track1); + + // change the signal used for PID + tpcSignalToEvaluatePID = fTPCSignal / fTPCSignalN_CR1; + + if (pidTPCopts.savedEdxsCorrected) { + // populated cursor if requested or autodetected + products.dEdxCorrected(tpcSignalToEvaluatePID); + } + } + + const auto& bc = trk.has_collision() ? cols.rawIteratorAt(trk.collisionId()).template bc_as() : bcs.begin(); + if (useCCDBParam && pidTPCopts.ccdbTimestamp.value == 0 && !ccdb->isCachedObjectValid(pidTPCopts.ccdbPath.value, bc.timestamp())) { // Updating parametrisation only if the initial timestamp is 0 + if (pidTPCopts.recoPass.value == "") { + LOGP(info, "Retrieving latest TPC response object for timestamp {}:", bc.timestamp()); + } 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()); + 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()); + if (!response) { + LOGP(fatal, "Could not find ANY TPC response object for the timestamp {}!", bc.timestamp()); + } + } + LOG(info) << "Successfully retrieved TPC PID object from CCDB for timestamp " << bc.timestamp() << ", period " << headers["LPMProductionTag"] << ", recoPass " << headers["RecoPassName"]; + response->PrintAll(); + } + + // if this is a MC process function, go for MC tune on data processing + if constexpr (requires { trk.mcParticleId(); }) { + // Perform TuneOnData sampling for MC dE/dx + float mcTunedTPCSignal = 0.; + if (!trk.hasTPC()) { + mcTunedTPCSignal = -999.f; + } else { + if (pidTPCopts.skipTPCOnly) { + if (!trk.hasITS() && !trk.hasTRD() && !trk.hasTOF()) { + mcTunedTPCSignal = -999.f; + } + } + int pid = getPIDIndex(trk.mcParticle().pdgCode()); + + auto expSignal = response->GetExpectedSignal(trk, pid); + auto expSigma = response->GetExpectedSigmaAtMultiplicity(multTPC, trk, pid); + if (expSignal < 0. || expSigma < 0.) { // if expectation invalid then give undefined signal + mcTunedTPCSignal = -999.f; + } + float bg = trk.tpcInnerParam() / o2::track::pid_constants::sMasses[pid]; // estimated beta-gamma for network cutoff + + if (pidTPCopts.useNetworkCorrection && speciesNetworkFlags[pid] && trk.has_collision() && bg > pidTPCopts.networkBetaGammaCutoff) { + auto mean = network_prediction[2 * (count_tracks + tracksForNet_size * pid)] * expSignal; // Absolute mean, i.e. the mean dE/dx value of the data in that slice, not the mean of the NSigma distribution + auto sigma = (network_prediction[2 * (count_tracks + tracksForNet_size * pid) + 1] - network_prediction[2 * (count_tracks + tracksForNet_size * pid)]) * expSignal; + if (mean < 0.f || sigma < 0.f) { + mcTunedTPCSignal = -999.f; + } else { + mcTunedTPCSignal = gRandom->Gaus(mean, sigma); + } + } else { + mcTunedTPCSignal = gRandom->Gaus(expSignal, expSigma); + } + } + tpcSignalToEvaluatePID = mcTunedTPCSignal; // pass this for further eval + if (pidTPCopts.enableTuneOnDataTable) + products.tableTuneOnData(mcTunedTPCSignal); + } + + auto makePidTablesDefault = [&trk, &tpcSignalToEvaluatePID, &multTPC, &network_prediction, &count_tracks, &tracksForNet_size, this](const int flagFull, auto& tableFull, const int flagTiny, auto& tableTiny, const o2::track::PID::ID pid) { + this->makePidTables(flagFull, tableFull, flagTiny, tableTiny, pid, tpcSignalToEvaluatePID, trk, multTPC, network_prediction, count_tracks, tracksForNet_size); + }; + + makePidTablesDefault(pidTPCopts.pidFullEl, products.tablePIDFullEl, pidTPCopts.pidTinyEl, products.tablePIDTinyEl, o2::track::PID::Electron); + makePidTablesDefault(pidTPCopts.pidFullMu, products.tablePIDFullMu, pidTPCopts.pidTinyMu, products.tablePIDTinyMu, o2::track::PID::Muon); + makePidTablesDefault(pidTPCopts.pidFullPi, products.tablePIDFullPi, pidTPCopts.pidTinyPi, products.tablePIDTinyPi, o2::track::PID::Pion); + makePidTablesDefault(pidTPCopts.pidFullKa, products.tablePIDFullKa, pidTPCopts.pidTinyKa, products.tablePIDTinyKa, o2::track::PID::Kaon); + makePidTablesDefault(pidTPCopts.pidFullPr, products.tablePIDFullPr, pidTPCopts.pidTinyPr, products.tablePIDTinyPr, o2::track::PID::Proton); + makePidTablesDefault(pidTPCopts.pidFullDe, products.tablePIDFullDe, pidTPCopts.pidTinyDe, products.tablePIDTinyDe, o2::track::PID::Deuteron); + makePidTablesDefault(pidTPCopts.pidFullTr, products.tablePIDFullTr, pidTPCopts.pidTinyTr, products.tablePIDTinyTr, o2::track::PID::Triton); + makePidTablesDefault(pidTPCopts.pidFullHe, products.tablePIDFullHe, pidTPCopts.pidTinyHe, products.tablePIDTinyHe, o2::track::PID::Helium3); + makePidTablesDefault(pidTPCopts.pidFullAl, products.tablePIDFullAl, pidTPCopts.pidTinyAl, products.tablePIDTinyAl, o2::track::PID::Alpha); + + if (trk.hasTPC() && (!pidTPCopts.skipTPCOnly || trk.hasITS() || trk.hasTRD() || trk.hasTOF())) { + count_tracks++; // Increment network track counter only if track has TPC, and (not skipping TPConly) or (is not TPConly) + } + } + } // end process function +}; + +} // namespace pid +} // namespace o2::aod + +#endif // COMMON_TOOLS_PIDTPCMODULE_H_ diff --git a/Common/TableProducer/PID/pidTPCService.cxx b/Common/TableProducer/PID/pidTPCService.cxx new file mode 100644 index 00000000000..cff700fca1c --- /dev/null +++ b/Common/TableProducer/PID/pidTPCService.cxx @@ -0,0 +1,118 @@ +// 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 trackPropagationTester.cxx +/// \brief testing ground for track propagation +/// \author ALICE + +//=============================================================== +// +// Modularized version of TPC PID task +// +//=============================================================== + +#include +#include +#include +#include +#include +// ROOT includes +#include "TFile.h" +#include "TRandom.h" +#include "TSystem.h" + +// O2 includes +#include "MetadataHelper.h" +#include "TableHelper.h" +#include "pidTPCBase.h" +#include "pidTPCModule.h" + +#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Tools/ML/model.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.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; + +o2::common::core::MetadataHelper metadataInfo; // Metadata helper + +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; + o2::aod::pid::pidTPCModule pidTPC; + + void init(o2::framework::InitContext& initContext) + { + // CCDB boilerplate init + ccdb->setURL(ccdburl.value); + ccdb->setFatalWhenNull(false); // manual fallback in case ccdb entry empty + 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); + } + + 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); + } + void processTracksWithTracksQA(soa::Join const& collisions, soa::Join const& tracks, aod::BCsWithTimestamps const& bcs, aod::TracksQA const& tracksQA) + { + pidTPC.process(ccdb, ccdbApi, bcs, collisions, tracks, tracksQA, 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); + } + + 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); + } + + PROCESS_SWITCH(pidTpcService, processTracks, "Process Tracks", false); + PROCESS_SWITCH(pidTpcService, processTracksMC, "Process Tracks in MC (enables tune-on-data)", false); + PROCESS_SWITCH(pidTpcService, processTracksIU, "Process TracksIU (experimental)", true); +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + // Parse the metadata for later too + metadataInfo.initMetadata(cfgc); + + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/Common/TableProducer/centralityTable.cxx b/Common/TableProducer/centralityTable.cxx index 48f1598afc5..9198f79499e 100644 --- a/Common/TableProducer/centralityTable.cxx +++ b/Common/TableProducer/centralityTable.cxx @@ -38,7 +38,7 @@ using namespace o2; using namespace o2::framework; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper static constexpr int kCentRun2V0Ms = 0; static constexpr int kCentRun2V0As = 1; diff --git a/Common/TableProducer/eventSelection.cxx b/Common/TableProducer/eventSelection.cxx index b06e98b84c5..f32c4723a47 100644 --- a/Common/TableProducer/eventSelection.cxx +++ b/Common/TableProducer/eventSelection.cxx @@ -47,7 +47,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::aod::evsel; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper using BCsWithRun2InfosTimestampsAndMatches = soa::Join; using BCsWithRun3Matchings = soa::Join; @@ -84,6 +84,8 @@ struct BcSelectionTask { 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; @@ -99,6 +101,8 @@ struct BcSelectionTask { 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.}}); } @@ -256,7 +260,7 @@ struct BcSelectionTask { // 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); + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run, strLPMProductionTag); // SOR and EOR timestamps sorTimestamp = runInfo.sor; eorTimestamp = runInfo.eor; @@ -511,10 +515,11 @@ struct EventSelectionTask { 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 + 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, std::map& bcs) { @@ -580,6 +585,7 @@ struct EventSelectionTask { } } } + strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); @@ -678,7 +684,7 @@ struct EventSelectionTask { int run3min = 500000; if (run != lastRun && run >= run3min) { lastRun = run; - auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), 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 @@ -1223,7 +1229,7 @@ struct LumiTask { LOGP(debug, "Dummy process function for Run 2"); } - PROCESS_SWITCH(LumiTask, processRun2, "Process Run2 lumi task", false); + PROCESS_SWITCH(LumiTask, processRun2, "Process Run2 lumi task", true); void processRun3(BCsWithBcSelsRun3 const& bcs, aod::FT0s const&) { @@ -1280,7 +1286,7 @@ struct LumiTask { 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; + std::map metadata; metadata["runNumber"] = std::to_string(run); auto config = ccdb->getSpecific("CTP/Config/Config", ts, metadata); auto classes = config->getCTPClasses(); diff --git a/Common/TableProducer/eventSelectionService.cxx b/Common/TableProducer/eventSelectionService.cxx new file mode 100644 index 00000000000..fd713773c86 --- /dev/null +++ b/Common/TableProducer/eventSelectionService.cxx @@ -0,0 +1,205 @@ +// 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 eventSelectionTester.cxx +/// \brief unified, self-configuring event selection task +/// \author ALICE + +//=============================================================== +// +// Unified, self-configuring event selection task +// +//=============================================================== + +#include "MetadataHelper.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Tools/EventSelectionTools.h" +#include "Common/Tools/timestampModule.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.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" + +using namespace o2; +using namespace o2::framework; + +o2::common::core::MetadataHelper metadataInfo; // Metadata helper + +using BCsWithRun2InfosAndMatches = soa::Join; +using BCsWithRun3Matchings = soa::Join; +using FullTracks = soa::Join; +using FullTracksIU = soa::Join; + +struct eventselectionRun2 { + o2::common::timestamp::timestampConfigurables timestampConfigurables; + o2::common::timestamp::TimestampModule timestampMod; + + o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcSelectionModule bcselmodule; + + o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EventSelectionModule evselmodule; + + Produces timestampTable; /// Table with SOR timestamps produced by the task + Produces bcsel; + Produces evsel; + + // for slicing + SliceCache cache; + + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // buffering intermediate results for passing + std::vector timestamps; + std::vector bcselsbuffer; + + // auxiliary + Partition tracklets = (aod::track::trackType == static_cast(o2::aod::track::TrackTypeEnum::Run2Tracklet)); + Preslice perCollision = aod::track::collisionId; + + void init(o2::framework::InitContext& context) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + timestampMod.init(timestampConfigurables, metadataInfo); + bcselmodule.init(context, bcselOpts, histos, metadataInfo); + evselmodule.init(context, evselOpts, histos, metadataInfo); + } + + void process(BCsWithRun2InfosAndMatches const& bcs, + aod::Collisions const& collisions, + aod::Zdcs const&, + aod::FV0As const&, + aod::FV0Cs const&, + aod::FT0s const&, + aod::FDDs const&, + FullTracks const&) + { + timestampMod.process(bcs, ccdb, timestamps, timestampTable); + bcselmodule.processRun2(ccdb, bcs, timestamps, bcselsbuffer, bcsel); + evselmodule.processRun2(ccdb, histos, collisions, tracklets, cache, timestamps, bcselsbuffer, evsel); + } +}; + +struct eventselectionRun3 { + o2::common::timestamp::timestampConfigurables timestampConfigurables; + o2::common::timestamp::TimestampModule timestampMod; + + o2::common::eventselection::bcselConfigurables bcselOpts; + o2::common::eventselection::BcSelectionModule bcselmodule; + + o2::common::eventselection::evselConfigurables evselOpts; + o2::common::eventselection::EventSelectionModule evselmodule; + + o2::common::eventselection::lumiConfigurables lumiOpts; + o2::common::eventselection::LumiModule lumimodule; + + Produces timestampTable; /// Table with SOR timestamps produced by the task + Produces bcsel; + Produces evsel; + + // for slicing + SliceCache cache; + + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // the best: have readable cursors + // this: a stopgap solution to avoid spawning yet another device + std::vector timestamps; + std::vector bcselsbuffer; + + // auxiliary + Partition pvTracks = ((aod::track::flags & static_cast(o2::aod::track::PVContributor)) == static_cast(o2::aod::track::PVContributor)); + Preslice perCollisionIU = aod::track::collisionId; + + void init(o2::framework::InitContext& context) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + timestampMod.init(timestampConfigurables, metadataInfo); + bcselmodule.init(context, bcselOpts, histos, metadataInfo); + evselmodule.init(context, evselOpts, histos, metadataInfo); + lumimodule.init(context, lumiOpts, histos); + } + + void process(aod::Collisions const& collisions, + BCsWithRun3Matchings const& bcs, + aod::Zdcs const&, + aod::FV0As const&, + aod::FT0s const& ft0s, // to resolve iterator + aod::FDDs const&, + FullTracksIU const&) + { + timestampMod.process(bcs, ccdb, timestamps, timestampTable); + bcselmodule.processRun3(ccdb, histos, bcs, timestamps, bcselsbuffer, bcsel); + evselmodule.processRun3(ccdb, histos, bcs, collisions, pvTracks, ft0s, cache, timestamps, bcselsbuffer, evsel); + lumimodule.process(ccdb, histos, bcs, timestamps, bcselsbuffer); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + // Parse the metadata for later too + metadataInfo.initMetadata(cfgc); + + bool isRun3 = true, hasRunInfo = false; + if (cfgc.options().hasOption("aod-metadata-Run") == true) { + hasRunInfo = true; + if (cfgc.options().get("aod-metadata-Run") == "2") { + isRun3 = false; + } + } + + LOGF(info, "Event selection autoconfiguring from metadata. Availability of info for Run 2/3 is %i", hasRunInfo); + if (!hasRunInfo) { + LOGF(info, "Metadata info missing or incomplete. Make sure --aod-file is provided at the end of the last workflow and that the AO2D has metadata stored."); + LOGF(info, "Initializing with Run 3 data as default. Please note you will not be able to change settings manually."); + LOGF(info, "You should instead make sure the metadata is read in correctly."); + return WorkflowSpec{adaptAnalysisTask(cfgc)}; + } else { + LOGF(info, "Metadata successfully read in. Is this Run 3? %i - will self-configure.", isRun3); + if (isRun3) { + return WorkflowSpec{adaptAnalysisTask(cfgc)}; + } else { + return WorkflowSpec{adaptAnalysisTask(cfgc)}; + } + } + throw std::runtime_error("Unsupported run type / problem when configuring event selection!"); +} diff --git a/Common/TableProducer/mftmchMatchingML.cxx b/Common/TableProducer/mftmchMatchingML.cxx index 4c813316275..4df90bbfdd1 100644 --- a/Common/TableProducer/mftmchMatchingML.cxx +++ b/Common/TableProducer/mftmchMatchingML.cxx @@ -10,11 +10,7 @@ // or submit itself to any jurisdiction. #include -#if __has_include() -#include -#else #include -#endif #include #include #include @@ -77,11 +73,7 @@ struct mftmchMatchingML { Ort::Env env{ORT_LOGGING_LEVEL_WARNING, "model-explorer"}; Ort::SessionOptions session_options; -#if __has_include() - std::shared_ptr onnx_session = nullptr; -#else std::shared_ptr onnx_session = nullptr; -#endif OnnxModel model; template @@ -158,12 +150,6 @@ struct mftmchMatchingML { std::vector output_names; std::vector> output_shapes; -#if __has_include() - input_names = onnx_session->GetInputNames(); - input_shapes = onnx_session->GetInputShapes(); - output_names = onnx_session->GetOutputNames(); - output_shapes = onnx_session->GetOutputShapes(); -#else Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < onnx_session->GetInputCount(); ++i) { input_names.push_back(onnx_session->GetInputNameAllocated(i, tmpAllocator).get()); @@ -177,7 +163,6 @@ struct mftmchMatchingML { for (size_t i = 0; i < onnx_session->GetOutputCount(); ++i) { output_shapes.emplace_back(onnx_session->GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif auto input_shape = input_shapes[0]; input_shape[0] = 1; @@ -187,11 +172,6 @@ struct mftmchMatchingML { if (input_tensor_values[8] < cfgXYWindow) { std::vector input_tensors; -#if __has_include() - input_tensors.push_back(Ort::Experimental::Value::CreateTensor(input_tensor_values.data(), input_tensor_values.size(), input_shape)); - - std::vector output_tensors = onnx_session->Run(input_names, input_tensors, output_names); -#else Ort::MemoryInfo mem_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); input_tensors.push_back(Ort::Value::CreateTensor(mem_info, input_tensor_values.data(), input_tensor_values.size(), input_shape.data(), input_shape.size())); @@ -206,7 +186,6 @@ struct mftmchMatchingML { [&](const std::string& str) { return str.c_str(); }); std::vector output_tensors = onnx_session->Run(runOptions, inputNamesChar.data(), input_tensors.data(), input_tensors.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif const float* output_value = output_tensors[0].GetTensorData(); diff --git a/Common/TableProducer/multCentTable.cxx b/Common/TableProducer/multCentTable.cxx new file mode 100644 index 00000000000..5b0e2c16d55 --- /dev/null +++ b/Common/TableProducer/multCentTable.cxx @@ -0,0 +1,205 @@ +// 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 multCentTable.cxx +/// \brief unified, self-configuring mult/cent provider +/// \author ALICE + +//=============================================================== +// +// Unified, self-configuring multiplicity+centrality task +// still work in progress: use at your own discretion +// +//=============================================================== + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/trackUtilities.h" +#include "ReconstructionDataFormats/DCA.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsBase/GeometryManager.h" +#include "CommonUtils/NameConf.h" +#include "CCDB/CcdbApi.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/HistogramRegistry.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "CommonConstants/GeomConstants.h" +#include "Common/Tools/TrackPropagationModule.h" +#include "Common/Tools/StandardCCDBLoader.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "MetadataHelper.h" +#include "Common/Tools/MultModule.h" + +using namespace o2; +using namespace o2::framework; +// using namespace o2::framework::expressions; + +o2::common::core::MetadataHelper metadataInfo; // Metadata helper + +struct MultCentTable { + o2::common::multiplicity::standardConfigurables opts; + o2::common::multiplicity::products products; + o2::common::multiplicity::MultModule module; + + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + Service pdg; + + // hold multiplicity values for layover to centrality calculation + std::vector mults; + + // slicers + Preslice> slicerTracksIU = o2::aod::track::collisionId; + Preslice> slicerTracksIUwithSelections = o2::aod::track::collisionId; + Preslice> slicerTrackRun2 = o2::aod::track::collisionId; + + void init(o2::framework::InitContext& initContext) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + ccdb->setFatalWhenNull(false); // please never crash on your own, all exceptions captured (as they always should) + + // task-specific + module.init(metadataInfo, opts, initContext); + } + + void processRun2(soa::Join const& collisions, + soa::Join const& tracks, + soa::Join const& bcs, + aod::Zdcs const&, + aod::FV0As const&, + aod::FV0Cs const&, + aod::FT0s const&) + { + mults.clear(); + for (auto const& collision : collisions) { + o2::common::multiplicity::multEntry mult; + const auto& bc = bcs.rawIteratorAt(collision.getId()); + const uint64_t collIdx = collision.globalIndex(); + auto tracksThisCollision = tracks.sliceBy(slicerTrackRun2, collIdx); + mult = module.collisionProcessRun2(collision, tracksThisCollision, bc, products); + mults.push_back(mult); + } + } + + void processRun3(soa::Join const& collisions, + soa::Join const& tracks, + soa::Join const&, + aod::Zdcs const&, + aod::FV0As const&, + aod::FT0s const&, + aod::FDDs const&) + { + mults.clear(); + for (auto const& collision : collisions) { + o2::common::multiplicity::multEntry mult; + const auto& bc = collision.bc_as>(); + const uint64_t collIdx = collision.globalIndex(); + auto tracksThisCollision = tracks.sliceBy(slicerTracksIU, collIdx); + mult = module.collisionProcessRun3(ccdb, metadataInfo, collision, tracksThisCollision, bc, products); + mults.push_back(mult); + } + } + + void processRun3WithGlobalCounters(soa::Join const& collisions, + soa::Join const& tracks, + soa::Join const&, + aod::Zdcs const&, + aod::FV0As const&, + aod::FT0s const&, + aod::FDDs const&) + { + mults.clear(); + for (auto const& collision : collisions) { + o2::common::multiplicity::multEntry mult; + const auto& bc = collision.bc_as>(); + const uint64_t collIdx = collision.globalIndex(); + auto tracksThisCollision = tracks.sliceBy(slicerTracksIUwithSelections, collIdx); + mult = module.collisionProcessRun3(ccdb, metadataInfo, collision, tracksThisCollision, bc, products); + mults.push_back(mult); + } + } + void processMFT(soa::Join::iterator const& collision, + o2::aod::MFTTracks const& mfttracks, + soa::SmallGroups const& retracks) + { + if (opts.mEnabledTables[o2::common::multiplicity::kMFTMults]) { + // populates MFT information in the mults buffer (in addition to filling table) + module.collisionProcessMFT(collision, mfttracks, retracks, mults, products); + } + } + void processMonteCarlo(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles) + { + if (opts.mEnabledTables[o2::common::multiplicity::kMultMCExtras]) { + module.collisionProcessMonteCarlo(mcCollision, mcParticles, pdg, products); + } + } + void processMonteCarlo2Mults(soa::Join::iterator const& collision) + { + if (opts.mEnabledTables[o2::common::multiplicity::kMult2MCExtras]) { + // establish simple interlink for posterior analysis (derived data) + products.tableExtraMult2MCExtras(collision.mcCollisionId()); + } + } + void processCentralityRun2(aod::Collisions const& collisions, soa::Join const& bcs) + { + // it is important that this function is at the end of the other process functions. + // it requires `mults` to be properly set, which will only happen after the other process + // functions have been called. + + // internally, the function below will do nothing if no centrality is requested. + // it is thus safer to always keep the actual process function for centrality + // generation to true, since the requisites for being in this context are + // always fulfilled + if (collisions.size() != static_cast(mults.size())) { + LOGF(fatal, "Size of collisions doesn't match size of multiplicity buffer!"); + } + module.generateCentralitiesRun2(ccdb, metadataInfo, bcs, mults, products); + } + void processCentralityRun3(aod::Collisions const& collisions, soa::Join const& bcs, aod::FT0s const&) + { + // it is important that this function is at the end of the other process functions. + // it requires `mults` to be properly set, which will only happen after the other process + // functions have been called. + + // internally, the function below will do nothing if no centrality is requested. + // it is thus safer to always keep the actual process function for centrality + // generation to true, since the requisites for being in this context are + // always fulfilled + if (collisions.size() != static_cast(mults.size())) { + LOGF(fatal, "Size of collisions doesn't match size of multiplicity buffer!"); + } + module.generateCentralitiesRun3(ccdb, metadataInfo, bcs, mults, products); + } + + PROCESS_SWITCH(MultCentTable, processRun2, "Process Run 2", false); + PROCESS_SWITCH(MultCentTable, processRun3, "Process Run 3", true); + PROCESS_SWITCH(MultCentTable, processRun3WithGlobalCounters, "Process Run 3 + global tracking counters", false); + PROCESS_SWITCH(MultCentTable, processMFT, "Process MFT info", false); + PROCESS_SWITCH(MultCentTable, processMonteCarlo, "Process Monte Carlo information", false); + PROCESS_SWITCH(MultCentTable, processMonteCarlo2Mults, "Process Monte Carlo information", false); + PROCESS_SWITCH(MultCentTable, processCentralityRun2, "Generate Run 2 centralities", false); + PROCESS_SWITCH(MultCentTable, processCentralityRun3, "Generate Run 3 centralities", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + metadataInfo.initMetadata(cfgc); + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/Common/TableProducer/multiplicityTable.cxx b/Common/TableProducer/multiplicityTable.cxx index 6deb146daab..12cde8a9869 100644 --- a/Common/TableProducer/multiplicityTable.cxx +++ b/Common/TableProducer/multiplicityTable.cxx @@ -40,7 +40,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper static constexpr int kFV0Mults = 0; static constexpr int kFT0Mults = 1; @@ -100,6 +100,7 @@ struct MultiplicityTable { Produces tablePVZeqs; // 12 Produces tableExtraMc; // 13 Produces tableExtraMult2MCExtras; + Produces multHepMCHIs; // Not accounted for, produced using custom process function to avoid dependencies Produces mftMults; // Not accounted for, produced using custom process function to avoid dependencies Produces multsGlobal; // Not accounted for, produced based on process function processGlobalTrackingCounters @@ -734,6 +735,18 @@ struct MultiplicityTable { using Run3Tracks = soa::Join; Partition pvContribGlobalTracksEta1 = (minPtGlobalTrack < aod::track::pt && aod::track::pt < maxPtGlobalTrack) && (nabs(aod::track::eta) < 1.0f) && ((aod::track::flags & static_cast(o2::aod::track::PVContributor)) == static_cast(o2::aod::track::PVContributor)) && requireQualityTracksInFilter(); + void processHepMCHeavyIons(aod::HepMCHeavyIons const& hepmchis) + { + for (auto const& hepmchi : hepmchis) { + multHepMCHIs(hepmchi.mcCollisionId(), + hepmchi.ncollHard(), + hepmchi.npartProj(), + hepmchi.npartTarg(), + hepmchi.ncoll(), + hepmchi.impactParameter()); + } + } + void processGlobalTrackingCounters(aod::Collision const& collision, soa::Join const& tracksIU, Run3Tracks const&) { // counter from Igor @@ -808,6 +821,7 @@ struct MultiplicityTable { PROCESS_SWITCH(MultiplicityTable, processGlobalTrackingCounters, "Produce Run 3 global counters", false); PROCESS_SWITCH(MultiplicityTable, processMC, "Produce MC multiplicity tables", false); PROCESS_SWITCH(MultiplicityTable, processMC2Mults, "Produce MC -> Mult map", false); + PROCESS_SWITCH(MultiplicityTable, processHepMCHeavyIons, "Produce MultHepMCHIs tables", false); PROCESS_SWITCH(MultiplicityTable, processRun3MFT, "Produce MFT mult tables", false); }; diff --git a/Common/TableProducer/occupancyTableProducer.cxx b/Common/TableProducer/occupancyTableProducer.cxx index 2e4a01ddbb1..a700b394772 100644 --- a/Common/TableProducer/occupancyTableProducer.cxx +++ b/Common/TableProducer/occupancyTableProducer.cxx @@ -52,6 +52,24 @@ int32_t nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; // const int nBCinTF = 114048; /// CCDB value // to be obtained from CCDB in future const int nBCinDrift = 114048 / 32; /// to get from ccdb in future +template +void sortVectorOfArray(std::vector>& myVector, const int& myIDX) +{ + std::sort(myVector.begin(), myVector.end(), [myIDX](const std::array& a, const std::array& b) { + return a[myIDX] < b[myIDX]; // sort at the required index + }); +} + +template +void checkUniqueness(const std::vector>& myVector, const int& myIDX) +{ + for (size_t i = 1; i < myVector.size(); i++) { + if (myVector[i][myIDX] <= myVector[i - 1][myIDX]) { + LOG(error) << "Duplicate Entries while creating Index tables :: (vec[" << i << "][" << myIDX << "]) " << myVector[i][myIDX] << " >= " << myVector[i - 1][myIDX] << " (vec[" << i - 1 << "][" << myIDX << "])"; + } + } +} + struct OccupancyTableProducer { Service ccdb; @@ -1208,7 +1226,9 @@ struct OccupancyTableProducer { struct TrackMeanOccTableProducer { // //declare production of tables - Produces genTmoTrackId; + Produces genTmoTrackId; + Produces genTmoToTrackQA; + Produces genTrackQAToTmo; Produces genTmoPrim; Produces genTmoT0V0; @@ -1262,6 +1282,9 @@ struct TrackMeanOccTableProducer { Configurable fillQA1{"fillQA1", true, "fill QA LOG Ratios"}; Configurable fillQA2{"fillQA2", true, "fill QA condition dependent QAs"}; + Configurable buildPointerTrackQAToTMOTable{"buildPointerTrackQAToTMOTable", true, "buildPointerTrackQAToTMOTable"}; + Configurable buildPointerTMOToTrackQATable{"buildPointerTMOToTrackQATable", true, "buildPointerTMOToTrackQATable"}; + // vectors to be used for occupancy estimation std::vector occPrimUnfm80; @@ -1692,7 +1715,7 @@ struct TrackMeanOccTableProducer { } } - using MyTracksQA = aod::TracksQA_002; + using MyTracksQA = aod::TracksQAVersion; // using MyTracksQA = aod::TracksQA_002; // Process the Data int dfCount = 0; @@ -1727,6 +1750,7 @@ struct TrackMeanOccTableProducer { fillWeightMeanOccTable }; + std::vector> trackQAGIListforTMOList; template void executeTrackOccProducerProcessing(B const& BCs, C const& collisions, T const& tracks, U const& tracksQA, O const& occsRobustT0V0Prim, V const& occs, bool const& executeInThisBlock) { @@ -1871,6 +1895,9 @@ struct TrackMeanOccTableProducer { float weightMeanOccRobustNtrackDetUnfm80 = 0; float weightMeanOccRobustMultTableUnfm80 = 0; + int trackTMOcounter = -1; + trackQAGIListforTMOList.clear(); + for (const auto& trackQA : tracksQA) { auto const& track = trackQA.template track_as(); auto collision = collisions.begin(); @@ -2034,7 +2061,9 @@ struct TrackMeanOccTableProducer { // If multiple process are on, fill this table only once if (executeInThisBlock) { + trackTMOcounter++; genTmoTrackId(track.globalIndex()); + trackQAGIListforTMOList.push_back({trackQA.globalIndex(), trackTMOcounter}); } if constexpr (qaMode == fillOccRobustT0V0dependentQA) { @@ -2320,6 +2349,52 @@ struct TrackMeanOccTableProducer { } } } // end of trackQA loop + + // build the IndexTables here + if (executeInThisBlock) { + if (buildPointerTrackQAToTMOTable) { + // create pointer table from trackQA to TrackMeanOcc + sortVectorOfArray(trackQAGIListforTMOList, 0); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackQAGIListforTMOList, 0); // check the uniqueness of track.globalIndex() + + int currentIDXforCheck = 0; + int listSize = trackQAGIListforTMOList.size(); + for (const auto& trackQA : tracksQA) { + while (trackQA.globalIndex() > trackQAGIListforTMOList[currentIDXforCheck][0]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (trackQA.globalIndex() == trackQAGIListforTMOList[currentIDXforCheck][0]) { + genTrackQAToTmo(trackQAGIListforTMOList[currentIDXforCheck][1]); + } else { + genTrackQAToTmo(-1); // put a dummy index when track is not found in trackQA + } + } + } + if (buildPointerTMOToTrackQATable) { + // create pointer table from TrackMeanOcc to trackQA + sortVectorOfArray(trackQAGIListforTMOList, 1); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackQAGIListforTMOList, 1); // check the uniqueness of track.globalIndex() + + int currentIDXforCheck = 0; + int listSize = trackQAGIListforTMOList.size(); + for (int iCounter = 0; iCounter <= trackTMOcounter; iCounter++) { + while (iCounter > trackQAGIListforTMOList[currentIDXforCheck][1]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (iCounter == trackQAGIListforTMOList[currentIDXforCheck][1]) { + genTmoToTrackQA(trackQAGIListforTMOList[currentIDXforCheck][0]); + } else { + genTmoToTrackQA(-1); // put a dummy index when track is not found in trackQA + } + } + } + } // end of executeInThisBlock } // end of else block of constexpr } @@ -2602,9 +2677,88 @@ struct TrackMeanOccTableProducer { PROCESS_SWITCH(TrackMeanOccTableProducer, processFullOccTableProduer, "processFullOccTableProduer", false); }; +struct CreatePointerTables { + + Produces genTrackToTracksQA; + Produces genTrackToTmo; + + void processNothing(aod::Collisions const&) + { + return; + } + PROCESS_SWITCH(CreatePointerTables, processNothing, "process Nothing", true); + + std::vector> trackGIForTrackQAIndexList; + using MyTracksQA = aod::TracksQAVersion; + void processTrackToTrackQAPointer(aod::Tracks const& tracks, MyTracksQA const& tracksQA) + { + trackGIForTrackQAIndexList.clear(); + for (const auto& trackQA : tracksQA) { + auto const& track = trackQA.template track_as(); + trackGIForTrackQAIndexList.push_back({track.globalIndex(), trackQA.globalIndex()}); + } + + sortVectorOfArray(trackGIForTrackQAIndexList, 0); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackGIForTrackQAIndexList, 0); // check the uniqueness of track.globalIndex() + + // create pointer table + int currentIDXforCheck = 0; + int listSize = trackGIForTrackQAIndexList.size(); + + for (const auto& track : tracks) { + while (track.globalIndex() > trackGIForTrackQAIndexList[currentIDXforCheck][0]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (track.globalIndex() == trackGIForTrackQAIndexList[currentIDXforCheck][0]) { + genTrackToTracksQA(trackGIForTrackQAIndexList[currentIDXforCheck][1]); + } else { + genTrackToTracksQA(-1); // put a dummy index when track is not found in trackQA + } + } + } + PROCESS_SWITCH(CreatePointerTables, processTrackToTrackQAPointer, "processTrackToTrackQAPointer", false); + + std::vector> trackGIForTMOIndexList; + void processTrackToTrackMeanOccsPointer(aod::Tracks const& tracks, aod::TmoTrackIds const& tmoTrackIds) + { + trackGIForTMOIndexList.clear(); + int tmoCounter = -1; + for (const auto& tmoTrackId : tmoTrackIds) { + tmoCounter++; + auto const& track = tmoTrackId.template track_as(); + trackGIForTMOIndexList.push_back({track.globalIndex(), tmoCounter}); // tmoTrackId Global Index is not working :: tmoTrackId.globalIndex()}); + } + sortVectorOfArray(trackGIForTMOIndexList, 0); // sort the list //Its easy to search in a sorted list + checkUniqueness(trackGIForTMOIndexList, 0); // check the uniqueness of track.globalIndex() + + // create pointer table + int currentIDXforCheck = 0; + int listSize = trackGIForTMOIndexList.size(); + + for (const auto& track : tracks) { + while (track.globalIndex() > trackGIForTMOIndexList[currentIDXforCheck][0]) { + currentIDXforCheck++; // increment the currentIDXforCheck for missing or invalid cases e.g. value = -1; + if (currentIDXforCheck >= listSize) { + break; + } + } + if (track.globalIndex() == trackGIForTMOIndexList[currentIDXforCheck][0]) { + genTrackToTmo(trackGIForTMOIndexList[currentIDXforCheck][1]); + } else { + genTrackToTmo(-1); // put a dummy index when track is not found in trackQA + } + } + } + PROCESS_SWITCH(CreatePointerTables, processTrackToTrackMeanOccsPointer, "processTrackToTrackMeanOccsPointer", false); +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } diff --git a/Common/TableProducer/qVectorsTable.cxx b/Common/TableProducer/qVectorsTable.cxx index 9de8faf028f..bfdb319db75 100644 --- a/Common/TableProducer/qVectorsTable.cxx +++ b/Common/TableProducer/qVectorsTable.cxx @@ -19,11 +19,13 @@ /// // C++/ROOT includes. +#include +#include + #include #include +#include #include -#include -#include // o2Physics includes. #include "Framework/AnalysisDataModel.h" @@ -78,6 +80,9 @@ struct qVectorsTable { Configurable cfgMinPtOnTPC{"cfgMinPtOnTPC", 0.15, "minimum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"}; Configurable cfgMaxPtOnTPC{"cfgMaxPtOnTPC", 5., "maximum transverse momentum selection for TPC tracks participating in Q-vector reconstruction"}; + Configurable cfgEtaMax{"cfgEtaMax", 0.8, "Maximum pseudorapidiy for charged track"}; + Configurable cfgEtaMin{"cfgEtaMin", -0.8, "Minimum pseudorapidiy for charged track"}; + Configurable cfgCorrLevel{"cfgCorrLevel", 4, "calibration step: 0 = no corr, 1 = gain corr, 2 = rectr, 3 = twist, 4 = full"}; Configurable> cfgnMods{"cfgnMods", {2, 3}, "Modulation of interest"}; Configurable cfgMaxCentrality{"cfgMaxCentrality", 100.f, "max. centrality for Q vector calibration"}; @@ -149,7 +154,7 @@ struct qVectorsTable { Produces qVectorBTotVec; ///////////////////////////////////////////////////////////////// - std::unordered_map useDetector = { + std::unordered_map useDetector = { {"QvectorBTots", cfgUseBTot}, {"QvectorBNegs", cfgUseBNeg}, {"QvectorBPoss", cfgUseBPos}, @@ -437,7 +442,10 @@ struct qVectorsTable { continue; } histosQA.fill(HIST("ChTracks"), trk.pt(), trk.eta(), trk.phi(), cent); - if (std::abs(trk.eta()) > 0.8) { + if (trk.eta() > cfgEtaMax) { + continue; + } + if (trk.eta() < cfgEtaMin) { continue; } qVectTPCall[0] += trk.pt() * std::cos(trk.phi() * nmode); diff --git a/Common/TableProducer/selectionStudyTable.cxx b/Common/TableProducer/selectionStudyTable.cxx new file mode 100644 index 00000000000..4d27e358ed1 --- /dev/null +++ b/Common/TableProducer/selectionStudyTable.cxx @@ -0,0 +1,133 @@ +// 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 selectionStudyTable.cxx +/// \brief Produces tables for centrality selection bias studies +/// +/// \author ALICE +/// + +#include "Common/DataModel/SelectionStudyTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ConfigParamSpec.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct SelectionStudyTable { + Produces pidpts; + + // could be done in a vector of vectors + // left for future iteration + std::vector ptpi; + std::vector ptka; + std::vector ptpr; + std::vector ptk0; + std::vector ptla; + std::vector ptxi; + std::vector ptom; + std::vector ptph; + std::vector ptks; + std::vector ptd; + std::vector ptlc; + std::vector ptjp; + + void init(InitContext&) + { + } + + void process(aod::McCollision const&, aod::McParticles const& mcParticles) + { + ptpi.clear(); + ptka.clear(); + ptpr.clear(); + ptk0.clear(); + ptla.clear(); + ptxi.clear(); + ptom.clear(); + ptph.clear(); + ptks.clear(); + ptd.clear(); + ptlc.clear(); + ptjp.clear(); + for (auto const& mcPart : mcParticles) { + if (std::fabs(mcPart.y()) > 0.5) { + continue; // only do midrapidity particles + } + + // handle resonances first to make sure phys prim crit does not reject them + if (mcPart.pdgCode() == 333) { + ptph.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 313) { + ptks.push_back(mcPart.pt()); + } + + // resonances handled, move to primaries + if (!mcPart.isPhysicalPrimary()) { + continue; + } + if (std::abs(mcPart.pdgCode()) == 211) { + ptpi.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 321) { + ptka.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 2212) { + ptpr.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 310) { + ptk0.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 3122) { + ptla.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 3312) { + ptxi.push_back(mcPart.pt()); + } + 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()); + } + if (std::abs(mcPart.pdgCode()) == 4122) { + ptd.push_back(mcPart.pt()); + } + if (std::abs(mcPart.pdgCode()) == 443) { + ptjp.push_back(mcPart.pt()); + } + } + + pidpts(ptpi, ptka, ptpr, ptk0, ptla, ptxi, ptom, ptph, ptks, ptd, ptlc, ptjp); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/Common/TableProducer/timestamp.cxx b/Common/TableProducer/timestamp.cxx index e3d37f7129b..40ab7000772 100644 --- a/Common/TableProducer/timestamp.cxx +++ b/Common/TableProducer/timestamp.cxx @@ -29,7 +29,7 @@ using namespace o2::framework; using namespace o2::header; using namespace o2; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper struct TimestampTask { Produces timestampTable; /// Table with SOR timestamps produced by the task diff --git a/Common/TableProducer/timestampTester.cxx b/Common/TableProducer/timestampTester.cxx new file mode 100644 index 00000000000..037cd4e38f3 --- /dev/null +++ b/Common/TableProducer/timestampTester.cxx @@ -0,0 +1,72 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file timestamp.cxx +/// \author Nicolò Jacazio +/// \since 2020-06-22 +/// \brief A task to fill the timestamp table from run number. +/// Uses headers from CCDB +/// +#include "MetadataHelper.h" + +#include "Common/Tools/timestampModule.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DetectorsRaw/HBFUtils.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include + +using namespace o2::framework; +using namespace o2::header; +using namespace o2; + +o2::common::core::MetadataHelper metadataInfo; // Metadata helper + +struct TimestampTask { + Produces timestampTable; /// Table with SOR timestamps produced by the task + Service ccdb; /// CCDB manager to access orbit-reset timestamp + o2::ccdb::CcdbApi ccdb_api; /// API to access CCDB headers + + Configurable ccdb_url{"ccdb-url", "http://alice-ccdb.cern.ch", "URL of the CCDB database"}; + + o2::common::timestamp::timestampConfigurables timestampConfigurables; + o2::common::timestamp::TimestampModule timestampMod; + + std::vector timestampBuffer; + + void init(o2::framework::InitContext&) + { + // CCDB initialization + ccdb->setURL(ccdb_url.value); + ccdb_api.init(ccdb_url.value); + + // timestamp configuration + init + timestampMod.init(timestampConfigurables, metadataInfo); + } + + void process(aod::BCs const& bcs) + { + timestampMod.process(bcs, ccdb, timestampBuffer, timestampTable); + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + // Parse the metadata + metadataInfo.initMetadata(cfgc); + + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/Common/TableProducer/trackDcaCovFillerRun2.cxx b/Common/TableProducer/trackDcaCovFillerRun2.cxx new file mode 100644 index 00000000000..d07833ae9e0 --- /dev/null +++ b/Common/TableProducer/trackDcaCovFillerRun2.cxx @@ -0,0 +1,179 @@ +// 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 trackDcaCovFillerRun2.cxx +/// \author Aimeric Landou , CERN +/// \brief Fills DCA and DCA Cov tables for Run 2 tracks +// Run 2 AO2Ds cannot have their dcacov filled by the current track-propagation workflow as the workflow isn't designed for them, given Run 2 tracks are already propagated to the PV. +// This task fills the DCA Cov (and DCA) tables for Run 2 tracks by "propagating" the tracks (though given they are already at the PV it doesn't actually do the propagation) and retrieving the DCA and DCA cov given by the propagateToDCABxByBz function + +#include + +#include "TableHelper.h" +#include "Common/Tools/TrackTuner.h" +#include "DataFormatsParameters/GRPObject.h" + +using namespace o2; +using namespace o2::framework; +// using namespace o2::framework::expressions; + +struct TrackDcaCovFillerRun2 { + Produces tracksDCA; + Produces tracksDCACov; + + // Produces tunertable; + + Service ccdb; + + bool fillTracksDCA = false; + bool fillTracksDCACov = false; + int runNumber = -1; + + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + + const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; + o2::parameters::GRPMagField* grpmag = nullptr; + o2::base::MatLayerCylSet* lut = nullptr; + + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPathGrp{"ccdbPathGrp", "GLO/GRP/GRP", "CCDB path of the grp file (run2)"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + + HistogramRegistry registry{"registry"}; + + void init(o2::framework::InitContext& initContext) + { + // Checking if the tables are requested in the workflow and enabling them + fillTracksDCA = isTableRequiredInWorkflow(initContext, "TracksDCA"); + fillTracksDCACov = isTableRequiredInWorkflow(initContext, "TracksDCACov"); + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (runNumber == bc.runNumber()) { + return; + } + + // Run 2 GRP object + o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(ccdbPathGrp, bc.timestamp()); + if (grpo == nullptr) { + LOGF(fatal, "Run 2 GRP object (type o2::parameters::GRPObject) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); + } + o2::base::Propagator::initFieldFromGRP(grpo); + LOGF(info, "Setting magnetic field to %d kG for run %d from its GRP CCDB object (type o2::parameters::GRPObject)", grpo->getNominalL3Field(), bc.runNumber()); + + mMeanVtx = ccdb->getForTimeStamp(mVtxPath, bc.timestamp()); + runNumber = bc.runNumber(); + } + + // Running variables + std::array mDcaInfo; + o2::dataformats::DCA mDcaInfoCov; + o2::dataformats::VertexBase mVtx; + o2::track::TrackParametrization mTrackPar; + o2::track::TrackParametrizationWithError mTrackParCov; + + template + void fillTrackTables(TTrack const& tracks, + TParticle const&, + aod::Collisions const&, + aod::BCsWithTimestamps const& bcs) + { + if (bcs.size() == 0) { + return; + } + initCCDB(bcs.begin()); + + if constexpr (fillCovMat) { + if (fillTracksDCACov) { + tracksDCACov.reserve(tracks.size()); + } + } else { + if (fillTracksDCA) { + tracksDCA.reserve(tracks.size()); + } + } + + for (auto const& track : tracks) { + if constexpr (fillCovMat) { + if (fillTracksDCA || fillTracksDCACov) { + mDcaInfoCov.set(999, 999, 999, 999, 999); + } + setTrackParCov(track, mTrackParCov); + } else { + if (fillTracksDCA) { + mDcaInfo[0] = 999; + mDcaInfo[1] = 999; + } + setTrackPar(track, mTrackPar); + } + + if (track.has_collision()) { + auto const& collision = track.collision(); + if constexpr (fillCovMat) { + 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, mTrackParCov, 2.f, matCorr, &mDcaInfoCov); + } else { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, mTrackPar, 2.f, matCorr, &mDcaInfo); + } + } else { + if constexpr (fillCovMat) { + mVtx.setPos({mMeanVtx->getX(), mMeanVtx->getY(), mMeanVtx->getZ()}); + mVtx.setCov(mMeanVtx->getSigmaX() * mMeanVtx->getSigmaX(), 0.0f, mMeanVtx->getSigmaY() * mMeanVtx->getSigmaY(), 0.0f, 0.0f, mMeanVtx->getSigmaZ() * mMeanVtx->getSigmaZ()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, mTrackParCov, 2.f, matCorr, &mDcaInfoCov); + } else { + o2::base::Propagator::Instance()->propagateToDCABxByBz({mMeanVtx->getX(), mMeanVtx->getY(), mMeanVtx->getZ()}, mTrackPar, 2.f, matCorr, &mDcaInfo); + } + } + + if constexpr (fillCovMat) { + if (fillTracksDCA) { + tracksDCA(mDcaInfoCov.getY(), mDcaInfoCov.getZ()); + } + if (fillTracksDCACov) { + tracksDCACov(mDcaInfoCov.getSigmaY2(), mDcaInfoCov.getSigmaZ2()); + } + } else { + if (fillTracksDCA) { + tracksDCA(mDcaInfo[0], mDcaInfo[1]); + } + } + } + } + + void processCovariance(soa::Join const& tracks, aod::Collisions const& collisions, aod::BCsWithTimestamps const& bcs) + { + fillTrackTables, /*Particle*/ soa::Join, /*isMc = */ false, /*fillCovMat =*/true>(tracks, tracks, collisions, bcs); + } + PROCESS_SWITCH(TrackDcaCovFillerRun2, processCovariance, "Process with covariance", false); + + void processStandard(soa::Join const& tracks, aod::Collisions const& collisions, aod::BCsWithTimestamps const& bcs) + { + fillTrackTables, /*Particle*/ soa::Join, /*isMc = */ false, /*fillCovMat =*/false>(tracks, tracks, collisions, bcs); + } + PROCESS_SWITCH(TrackDcaCovFillerRun2, processStandard, "Process without covariance", true); +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/Common/TableProducer/trackPropagationTester.cxx b/Common/TableProducer/trackPropagationTester.cxx index 694ff77d3c0..18543ee0994 100644 --- a/Common/TableProducer/trackPropagationTester.cxx +++ b/Common/TableProducer/trackPropagationTester.cxx @@ -23,24 +23,28 @@ // //=============================================================== -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/trackUtilities.h" -#include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "CommonUtils/NameConf.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Tools/StandardCCDBLoader.h" +#include "Common/Tools/TrackPropagationModule.h" +#include "Common/Tools/TrackTuner.h" + +#include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsCalibration/MeanVertexObject.h" #include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "CommonConstants/GeomConstants.h" -#include "Common/Tools/TrackPropagationModule.h" -#include "Common/Tools/StandardCCDBLoader.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/DCA.h" + +#include // The Run 3 AO2D stores the tracks at the point of innermost update. For a track with ITS this is the innermost (or second innermost) // ITS layer. For a track without ITS, this is the TPC inner wall or for loopers in the TPC even a radius beyond that. @@ -59,6 +63,9 @@ struct TrackPropagationTester { o2::common::TrackPropagationProducts trackPropagationProducts; o2::common::TrackPropagationConfigurables trackPropagationConfigurables; + // the track tuner object -> needs to be here as it inherits from ConfigurableGroup (+ has its own copy of ccdbApi) + TrackTuner trackTunerObj; + // CCDB boilerplate declarations o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Service ccdb; @@ -76,14 +83,14 @@ struct TrackPropagationTester { ccdb->setURL(ccdburl.value); // task-specific - trackPropagation.init(trackPropagationConfigurables, registry, initContext); + trackPropagation.init(trackPropagationConfigurables, trackTunerObj, registry, initContext); } void processReal(aod::Collisions const& collisions, soa::Join const& tracks, aod::Collisions const&, aod::BCs const& bcs) { // task-specific ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); - trackPropagation.fillTrackTables(trackPropagationConfigurables, ccdbLoader, collisions, tracks, trackPropagationProducts, registry); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, registry); } PROCESS_SWITCH(TrackPropagationTester, processReal, "Process Real Data", true); @@ -91,7 +98,7 @@ struct TrackPropagationTester { void processMc(aod::Collisions const& collisions, soa::Join const& tracks, aod::McParticles const&, aod::Collisions const&, aod::BCs const& bcs) { ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); - trackPropagation.fillTrackTables(trackPropagationConfigurables, ccdbLoader, collisions, tracks, trackPropagationProducts, registry); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, registry); } PROCESS_SWITCH(TrackPropagationTester, processMc, "Process Monte Carlo", false); }; diff --git a/Common/TableProducer/zdc-task-intercalib.cxx b/Common/TableProducer/zdcTaskInterCalib.cxx similarity index 53% rename from Common/TableProducer/zdc-task-intercalib.cxx rename to Common/TableProducer/zdcTaskInterCalib.cxx index 77b590bde57..78054580b81 100644 --- a/Common/TableProducer/zdc-task-intercalib.cxx +++ b/Common/TableProducer/zdcTaskInterCalib.cxx @@ -9,12 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file zdc-task-intercalib.cxx +/// \file zdcTaskInterCalib.cxx /// \brief Task for ZDC tower inter-calibration /// \author chiara.oppedisano@cern.ch -// o2-linter: disable=name/workflow-file -// o2-linter: disable=name/file-cpp #include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" #include "Framework/HistogramRegistry.h" @@ -35,9 +33,9 @@ using namespace o2::framework::expressions; using namespace o2::aod::evsel; using BCsRun3 = soa::Join; -using ColEvSels = soa::Join; +using ColEvSels = soa::Join; -struct ZDCCalibTower { +struct ZdcTaskInterCalib { Produces zTab; @@ -48,9 +46,32 @@ struct ZDCCalibTower { Configurable tdcCut{"tdcCut", false, "Flag for TDC cut"}; Configurable tdcZNmincut{"tdcZNmincut", -2.5, "Min ZN TDC cut"}; Configurable tdcZNmaxcut{"tdcZNmaxcut", -2.5, "Max ZN TDC cut"}; + // 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 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"}; // HistogramRegistry registry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + enum SelectionCriteria { + evSel_zvtx, + evSel_sel8, + evSel_occupancy, + evSel_kNoSameBunchPileup, + evSel_kIsGoodZvtxFT0vsPV, + evSel_kNoCollInTimeRangeStandard, + evSel_kIsVertexITSTPC, + evSel_kIsGoodITSLayersAll, + evSel_allEvents, + nEventSelections + }; + void init(InitContext const&) { registry.add("ZNApmc", "ZNApmc; ZNA PMC; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); @@ -65,16 +86,93 @@ struct ZDCCalibTower { registry.add("ZNCpm4", "ZNCpm4; ZNC PM4; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); registry.add("ZNAsumq", "ZNAsumq; ZNA uncalib. sum PMQ; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); registry.add("ZNCsumq", "ZNCsumq; ZNC uncalib. sum PMQ; Entries", {HistType::kTH1F, {{nBins, -0.5, maxZN}}}); + + 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, "kkIsGoodITSLayersAll"); + } + + template + uint8_t eventSelected(TCollision collision) + { + uint8_t selectionBits = 0; + bool selected; + + registry.fill(HIST("hEventCount"), evSel_allEvents); + + selected = std::fabs(collision.posZ()) < cfgEvSelVtxZ; + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_zvtx); + registry.fill(HIST("hEventCount"), evSel_zvtx); + } + + selected = collision.sel8(); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_sel8); + registry.fill(HIST("hEventCount"), evSel_sel8); + } + + auto occupancy = collision.trackOccupancyInTimeRange(); + selected = occupancy <= cfgEvSelsMaxOccupancy; + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_occupancy); + registry.fill(HIST("hEventCount"), evSel_occupancy); + } + + selected = collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kNoSameBunchPileup); + registry.fill(HIST("hEventCount"), evSel_kNoSameBunchPileup); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodZvtxFT0vsPV); + registry.fill(HIST("hEventCount"), evSel_kIsGoodZvtxFT0vsPV); + } + + selected = collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kNoCollInTimeRangeStandard); + registry.fill(HIST("hEventCount"), evSel_kNoCollInTimeRangeStandard); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsVertexITSTPC); + registry.fill(HIST("hEventCount"), evSel_kIsVertexITSTPC); + } + + selected = collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll); + if (selected) { + selectionBits |= (uint8_t)(0x1u << evSel_kIsGoodITSLayersAll); + registry.fill(HIST("hEventCount"), evSel_kIsGoodITSLayersAll); + } + + return selectionBits; } void process(ColEvSels const& cols, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/) { // collision-based event selection + int nTowers = 4; // number of ZDC towers + for (auto const& collision : cols) { const auto& foundBC = collision.foundBC_as(); if (foundBC.has_zdc()) { const auto& zdc = foundBC.zdc(); + uint8_t evSelection = eventSelected(collision); + + float centrality = collision.centFT0C(); + // To assure that ZN have a genuine signal (tagged by the relative TDC) // we can check that the amplitude is >0 or that ADC is NOT very negative (-inf) @@ -117,7 +215,7 @@ struct ZDCCalibTower { }; // if (isZNChit) { - for (int it = 0; it < 4; it++) { + for (int it = 0; it < nTowers; it++) { pmqZNC[it] = (zdc.energySectorZNC())[it]; sumZNC += pmqZNC[it]; } @@ -129,7 +227,7 @@ struct ZDCCalibTower { registry.get(HIST("ZNCsumq"))->Fill(sumZNC); } if (isZNAhit) { - for (int it = 0; it < 4; it++) { + for (int it = 0; it < nTowers; it++) { pmqZNA[it] = (zdc.energySectorZNA())[it]; sumZNA += pmqZNA[it]; } @@ -142,7 +240,7 @@ struct ZDCCalibTower { registry.get(HIST("ZNAsumq"))->Fill(sumZNA); } if (isZNAhit || isZNChit) - zTab(pmcZNA, pmqZNA[0], pmqZNA[1], pmqZNA[2], pmqZNA[3], tdcZNC, pmcZNC, pmqZNC[0], pmqZNC[1], pmqZNC[2], pmqZNC[3], tdcZNA); + zTab(pmcZNA, pmqZNA[0], pmqZNA[1], pmqZNA[2], pmqZNA[3], tdcZNC, pmcZNC, pmqZNC[0], pmqZNC[1], pmqZNC[2], pmqZNC[3], tdcZNA, centrality, foundBC.timestamp(), evSelection); } } } @@ -151,5 +249,5 @@ struct ZDCCalibTower { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) // o2-linter: disable=name/file-cpp { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } diff --git a/Common/Tasks/CMakeLists.txt b/Common/Tasks/CMakeLists.txt index 64d4f7e6611..932398c97a9 100644 --- a/Common/Tasks/CMakeLists.txt +++ b/Common/Tasks/CMakeLists.txt @@ -81,7 +81,7 @@ o2physics_add_dpl_workflow(qvectors-correction o2physics_add_dpl_workflow(centrality-study SOURCES centralityStudy.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(flow-test diff --git a/Common/Tasks/centralityStudy.cxx b/Common/Tasks/centralityStudy.cxx index 67a387fc903..a8cdea5ac09 100644 --- a/Common/Tasks/centralityStudy.cxx +++ b/Common/Tasks/centralityStudy.cxx @@ -13,32 +13,63 @@ // Run 3 Pb-Pb centrality selections in 2023 data. It is compatible with // derived data. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/McCollisionExtra.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/CCDB/ctpRateFetcher.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPECSObject.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + #include "TH1F.h" #include "TH2F.h" +#include "TProfile.h" + +#include +#include using namespace o2; using namespace o2::framework; using BCsWithRun3Matchings = soa::Join; +#define getHist(type, name) std::get>(histPointers[name]) struct centralityStudy { // Raw multiplicities HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::map histPointers; + std::string histPath; + Service ccdb; + ctpRateFetcher mRateFetcher; + int mRunNumber; + uint64_t startOfRunTimestamp; + + // vertex Z equalization + TList* hCalibObjects; + TProfile* hVtxZFV0A; + TProfile* hVtxZFT0A; + TProfile* hVtxZFT0C; + TProfile* hVtxZNTracks; + TProfile* hVtxZNGlobals; + TProfile* hVtxZMFT; + TProfile* hVtxZFDDA; + TProfile* hVtxZFDDC; // Configurables + Configurable applyVertexZEqualization{"applyVertexZEqualization", false, "0 - no, 1 - yes"}; + Configurable do2DPlots{"do2DPlots", true, "0 - no, 1 - yes"}; Configurable doOccupancyStudyVsCentrality2d{"doOccupancyStudyVsCentrality2d", true, "0 - no, 1 - yes"}; Configurable doOccupancyStudyVsRawValues2d{"doOccupancyStudyVsRawValues2d", true, "0 - no, 1 - yes"}; Configurable doOccupancyStudyVsCentrality3d{"doOccupancyStudyVsCentrality3d", false, "0 - no, 1 - yes"}; Configurable doOccupancyStudyVsRawValues3d{"doOccupancyStudyVsRawValues3d", false, "0 - no, 1 - yes"}; + Configurable doTimeStudies{"doTimeStudies", true, "0 - no, 1 - yes"}; + Configurable doTimeStudyFV0AOuterVsFT0A3d{"doTimeStudyFV0AOuterVsFT0A3d", false, "0 - no, 1 - yes"}; Configurable doNGlobalTracksVsRawSignals{"doNGlobalTracksVsRawSignals", true, "0 - no, 1 - yes"}; Configurable applySel8{"applySel8", true, "0 - no, 1 - yes"}; Configurable applyVtxZ{"applyVtxZ", true, "0 - no, 1 - yes"}; @@ -46,10 +77,10 @@ struct centralityStudy { // Apply extra event selections Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border"}; Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border"}; - Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", true, "require events with at least one ITS-TPC track"}; - Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", true, "require events with PV position along z consistent (within 1 cm) between PV reconstructed using tracks and PV using FT0 A-C time difference"}; - Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", true, "require events with at least one of vertex contributors matched to TOF"}; - Configurable requireIsVertexTRDmatched{"requireIsVertexTRDmatched", true, "require events with at least one of vertex contributors matched to TRD"}; + Configurable requireIsVertexITSTPC{"requireIsVertexITSTPC", false, "require events with at least one ITS-TPC track"}; + 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"}; + 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 rejectITSinROFpileupStandard{"rejectITSinROFpileupStandard", false, "reject collisions in case of in-ROF ITS pileup (standard)"}; @@ -64,12 +95,19 @@ struct centralityStudy { Configurable vertexZwithT0{"vertexZwithT0", 1000.0f, "require a certain vertex-Z in BC analysis"}; Configurable minTimeDelta{"minTimeDelta", -1.0f, "reject collision if another collision is this close or less in time"}; - Configurable minFT0CforVertexZ{"minFT0CforVertexZ", 250, "minimum FT0C for vertex-Z profile calculation"}; + Configurable minFT0CforVertexZ{"minFT0CforVertexZ", -1.0f, "minimum FT0C for vertex-Z profile calculation"}; 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"}; + Configurable ccdbURL{"ccdbURL", "http://alice-ccdb.cern.ch", "ccdb url"}; + Configurable pathGRPECSObject{"pathGRPECSObject", "GLO/Config/GRPECS", "Path to GRPECS object"}; + Configurable pathVertexZ{"pathVertexZ", "Users/d/ddobrigk/Centrality/Calibration", "Path to vertexZ profiles"}; + Configurable irSource{"irSource", "ZNC hadronic", "Source of the interaction rate: (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; + Configurable irCrashOnNull{"irCrashOnNull", false, "Flag to avoid CTP RateFetcher crash."}; + Configurable irDoRateVsTime{"irDoRateVsTime", true, "Do IR plots"}; + // _______________________________________ // upc rejection criteria // reject low zna/c @@ -114,13 +152,26 @@ struct centralityStudy { ConfigurableAxis axisPVChi2{"axisPVChi2", {300, 0, 30}, "FT0C percentile"}; ConfigurableAxis axisDeltaTime{"axisDeltaTime", {300, 0, 300}, "#Delta time"}; + ConfigurableAxis axisDeltaTimestamp{"axisDeltaTimestamp", {1440, 0, 24}, "#Delta timestamp - sor (hours)"}; + ConfigurableAxis axisInteractionRate{"axisInteractionRate", {500, 0, 100}, "Binning for the interaction rate (kHz)"}; + ConfigurableAxis axisMultCoarseFV0A{"axisMultCoarseFV0A", {350, 0, 70000}, "FV0A amplitude"}; + // For profile Z ConfigurableAxis axisPVz{"axisPVz", {400, -20.0f, +20.0f}, "PVz (cm)"}; - ConfigurableAxis axisZN{"axisZN", {1100, -50.0f, +500.0f}, "ZN"}; void init(InitContext&) { + hCalibObjects = nullptr; + hVtxZFV0A = nullptr; + hVtxZFT0A = nullptr; + hVtxZFT0C = nullptr; + hVtxZNTracks = nullptr; + hVtxZNGlobals = nullptr; + hVtxZMFT = nullptr; + hVtxZFDDA = nullptr; + hVtxZFDDC = nullptr; + if (doprocessCollisions || doprocessCollisionsWithCentrality) { const AxisSpec axisCollisions{100, -0.5f, 99.5f, "Number of collisions"}; histos.add("hCollisionSelection", "hCollisionSelection", kTH1D, {{20, -0.5f, +19.5f}}); @@ -159,9 +210,9 @@ struct centralityStudy { histos.add("hFV0A_BCs", "hFV0A_BCs", kTH1D, {axisMultUltraFineFV0A}); histos.add("hFT0CvsPVz_BCs_All", "hFT0CvsPVz_BCs_All", kTProfile, {axisPVz}); histos.add("hFT0CvsPVz_BCs", "hFT0CvsPVz_BCs", kTProfile, {axisPVz}); - histos.add("hVertexZ_BCvsCO", "hVertexZ_BCvsCO", kTH2D, {axisPVz, axisPVz}); - histos.add("hZNAvsFT0C_BCs", "hZNAvsFT0C_BCs", kTH2D, {axisMultFT0C, axisZN}); - histos.add("hZNCvsFT0C_BCs", "hZNCvsFT0C_BCs", kTH2D, {axisMultFT0C, axisZN}); + histos.add("hVertexZ_BCvsCO", "hVertexZ_BCvsCO", kTH2F, {axisPVz, axisPVz}); + histos.add("hZNAvsFT0C_BCs", "hZNAvsFT0C_BCs", kTH2F, {axisMultFT0C, axisZN}); + histos.add("hZNCvsFT0C_BCs", "hZNCvsFT0C_BCs", kTH2F, {axisMultFT0C, axisZN}); } if (do2DPlots) { @@ -186,6 +237,7 @@ struct centralityStudy { histos.add("hNGlobalTracksVsZNA", "hNGlobalTracksVsZNA", kTH2F, {axisZN, axisMultGlobalTracks}); histos.add("hNGlobalTracksVsZNC", "hNGlobalTracksVsZNC", kTH2F, {axisZN, axisMultGlobalTracks}); histos.add("hNGlobalTracksVsNMFTTracks", "hNGlobalTracksVsNMFTTracks", kTH2F, {axisMultMFTTracks, axisMultGlobalTracks}); + histos.add("hNGlobalTracksVsNTPV", "hNGlobalTracksVsNTPV", kTH2F, {axisMultPVContributors, axisMultGlobalTracks}); } if (doOccupancyStudyVsRawValues2d) { @@ -227,57 +279,269 @@ struct centralityStudy { histos.add("hFT0COccupancyVsNGlobalTracksVsCentrality", "hFT0COccupancyVsNGlobalTracksVsCentrality", kTH3F, {axisFT0COccupancy, axisMultGlobalTracks, axisCentrality}); } } + + if (doTimeStudies) { + ccdb->setURL(ccdbURL); + // ccdb->setCaching(true); + // ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + if (doTimeStudyFV0AOuterVsFT0A3d) { + histos.add((histPath + "h3dFV0AVsTime").c_str(), "", {kTH3F, {{axisDeltaTimestamp, axisMultCoarseFV0A, axisMultCoarseFV0A}}}); + } + } + } + + template + void initRun(TCollision collision) + { + if (mRunNumber == collision.multRunNumber()) { + return; + } + + mRunNumber = collision.multRunNumber(); + LOGF(info, "Setting up for run: %i", mRunNumber); + + // only get object when switching runs + o2::parameters::GRPECSObject* grpo = ccdb->getForRun(pathGRPECSObject, mRunNumber); + startOfRunTimestamp = grpo->getTimeStart(); + + if (applyVertexZEqualization.value) { + // acquire vertex-Z equalization histograms if requested + LOGF(info, "Acquiring vertex-Z profiles for run %i", mRunNumber); + hCalibObjects = ccdb->getForRun(pathVertexZ, mRunNumber); + + hVtxZFV0A = static_cast(hCalibObjects->FindObject("hVtxZFV0A")); + hVtxZFT0A = static_cast(hCalibObjects->FindObject("hVtxZFT0A")); + hVtxZFT0C = static_cast(hCalibObjects->FindObject("hVtxZFT0C")); + // hVtxZFDDA = static_cast(hCalibObjects->FindObject("hVtxZFDDA")); + // hVtxZFDDC = static_cast(hCalibObjects->FindObject("hVtxZFDDC")); + hVtxZNTracks = static_cast(hCalibObjects->FindObject("hVtxZNTracksPV")); + hVtxZNGlobals = static_cast(hCalibObjects->FindObject("hVtxZNGlobals")); + hVtxZMFT = static_cast(hCalibObjects->FindObject("hVtxZMFT")); + + // Capture error + if (!hVtxZFV0A || !hVtxZFT0A || !hVtxZFT0C || !hVtxZNTracks || !hVtxZNGlobals || !hVtxZMFT) { + LOGF(error, "Problem loading CCDB objects! Please check"); + } + } + + histPath = std::format("Run_{}/", mRunNumber); + + if (doprocessCollisions || doprocessCollisionsWithCentrality) { + histPointers.insert({histPath + "hCollisionSelection", histos.add((histPath + "hCollisionSelection").c_str(), "hCollisionSelection", {kTH1D, {{20, -0.5f, +19.5f}}})}); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(1, "All collisions"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(2, "sel8 cut"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(3, "posZ cut"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(6, "kIsVertexITSTPC"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(7, "kIsGoodZvtxFT0vsPV"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(8, "kIsVertexTOFmatched"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(9, "kIsVertexTRDmatched"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(10, "kNoSameBunchPileup"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(11, "Neighbour rejection"); + getHist(TH1, histPath + "hCollisionSelection")->GetXaxis()->SetBinLabel(12, "no ITS in-ROF pileup (standard)"); + 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 + "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}}})}); + histPointers.insert({histPath + "hNMFTTracks", histos.add((histPath + "hNMFTTracks").c_str(), "hNMFTTracks", {kTH1D, {{axisMultUltraFineMFTTracks}}})}); + histPointers.insert({histPath + "hNPVContributors", histos.add((histPath + "hNPVContributors").c_str(), "hNPVContributors", {kTH1D, {{axisMultUltraFinePVContributors}}})}); + + if (applyVertexZEqualization) { + histPointers.insert({histPath + "hFT0C_Collisions_Unequalized", histos.add((histPath + "hFT0C_Collisions_Unequalized").c_str(), "hFT0C_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFT0C}}})}); + histPointers.insert({histPath + "hFT0M_Collisions_Unequalized", histos.add((histPath + "hFT0M_Collisions_Unequalized").c_str(), "hFT0M_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFT0M}}})}); + histPointers.insert({histPath + "hFV0A_Collisions_Unequalized", histos.add((histPath + "hFV0A_Collisions_Unequalized").c_str(), "hFV0A_Collisions_Unequalized", {kTH1D, {{axisMultUltraFineFV0A}}})}); + histPointers.insert({histPath + "hNGlobalTracks_Unequalized", histos.add((histPath + "hNGlobalTracks_Unequalized").c_str(), "hNGlobalTracks_Unequalized", {kTH1D, {{axisMultUltraFineGlobalTracks}}})}); + histPointers.insert({histPath + "hNMFTTracks_Unequalized", histos.add((histPath + "hNMFTTracks_Unequalized").c_str(), "hNMFTTracks_Unequalized", {kTH1D, {{axisMultUltraFineMFTTracks}}})}); + histPointers.insert({histPath + "hNPVContributors_Unequalized", histos.add((histPath + "hNPVContributors_Unequalized").c_str(), "hNPVContributors_Unequalized", {kTH1D, {{axisMultUltraFinePVContributors}}})}); + } + + histPointers.insert({histPath + "hFT0CvsPVz_Collisions_All", histos.add((histPath + "hFT0CvsPVz_Collisions_All").c_str(), "hFT0CvsPVz_Collisions_All", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFT0AvsPVz_Collisions", histos.add((histPath + "hFT0AvsPVz_Collisions").c_str(), "hFT0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFT0CvsPVz_Collisions", histos.add((histPath + "hFT0CvsPVz_Collisions").c_str(), "hFT0CvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hFV0AvsPVz_Collisions", histos.add((histPath + "hFV0AvsPVz_Collisions").c_str(), "hFV0AvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hNGlobalTracksvsPVz_Collisions", histos.add((histPath + "hNGlobalTracksvsPVz_Collisions").c_str(), "hNGlobalTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hNMFTTracksvsPVz_Collisions", histos.add((histPath + "hNMFTTracksvsPVz_Collisions").c_str(), "hNMFTTracksvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + histPointers.insert({histPath + "hNTPVvsPVz_Collisions", histos.add((histPath + "hNTPVvsPVz_Collisions").c_str(), "hNTPVvsPVz_Collisions", {kTProfile, {{axisPVz}}})}); + } + + if (do2DPlots) { + histPointers.insert({histPath + "hNContribsVsFT0C", histos.add((histPath + "hNContribsVsFT0C").c_str(), "hNContribsVsFT0C", {kTH2F, {{axisMultFT0C, axisMultPVContributors}}})}); + histPointers.insert({histPath + "hNContribsVsFV0A", histos.add((histPath + "hNContribsVsFV0A").c_str(), "hNContribsVsFV0A", {kTH2F, {{axisMultFV0A, axisMultPVContributors}}})}); + histPointers.insert({histPath + "hMatchedVsITSOnly", histos.add((histPath + "hMatchedVsITSOnly").c_str(), "hMatchedVsITSOnly", {kTH2F, {{axisMultITSOnly, axisMultITSTPC}}})}); + + // 2d correlation of fit signals + histPointers.insert({histPath + "hFT0AVsFT0C", histos.add((histPath + "hFT0AVsFT0C").c_str(), "hFT0AVsFT0C", {kTH2F, {{axisMultFT0C, axisMultFT0A}}})}); + histPointers.insert({histPath + "hFV0AVsFT0C", histos.add((histPath + "hFV0AVsFT0C").c_str(), "hFV0AVsFT0C", {kTH2F, {{axisMultFT0C, axisMultFV0A}}})}); + histPointers.insert({histPath + "hFDDAVsFT0C", histos.add((histPath + "hFDDAVsFT0C").c_str(), "hFDDAVsFT0C", {kTH2F, {{axisMultFT0C, axisMultFDDA}}})}); + histPointers.insert({histPath + "hFDDCVsFT0C", histos.add((histPath + "hFDDCVsFT0C").c_str(), "hFDDCVsFT0C", {kTH2F, {{axisMultFT0C, axisMultFDDC}}})}); + } + + if (doprocessCollisionsWithCentrality) { + // in case requested: do vs centrality debugging + histPointers.insert({histPath + "hCentrality", histos.add((histPath + "hCentrality").c_str(), "hCentrality", {kTH1F, {{axisCentrality}}})}); + histPointers.insert({histPath + "hNContribsVsCentrality", histos.add((histPath + "hNContribsVsCentrality").c_str(), "hNContribsVsCentrality", {kTH2F, {{axisCentrality, axisMultPVContributors}}})}); + histPointers.insert({histPath + "hNITSTPCTracksVsCentrality", histos.add((histPath + "hNITSTPCTracksVsCentrality").c_str(), "hNITSTPCTracksVsCentrality", {kTH2F, {{axisCentrality, axisMultPVContributors}}})}); + histPointers.insert({histPath + "hNITSOnlyTracksVsCentrality", histos.add((histPath + "hNITSOnlyTracksVsCentrality").c_str(), "hNITSOnlyTracksVsCentrality", {kTH2F, {{axisCentrality, axisMultPVContributors}}})}); + histPointers.insert({histPath + "hNGlobalTracksVsCentrality", histos.add((histPath + "hNGlobalTracksVsCentrality").c_str(), "hNGlobalTracksVsCentrality", {kTH2F, {{axisCentrality, axisMultPVContributors}}})}); + histPointers.insert({histPath + "hNMFTTracksVsCentrality", histos.add((histPath + "hNMFTTracksVsCentrality").c_str(), "hNMFTTracksVsCentrality", {kTH2F, {{axisCentrality, axisMultMFTTracks}}})}); + histPointers.insert({histPath + "hPVChi2VsCentrality", histos.add((histPath + "hPVChi2VsCentrality").c_str(), "hPVChi2VsCentrality", {kTH2F, {{axisCentrality, axisPVChi2}}})}); + histPointers.insert({histPath + "hDeltaTimeVsCentrality", histos.add((histPath + "hDeltaTimeVsCentrality").c_str(), "hDeltaTimeVsCentrality", {kTH2F, {{axisCentrality, axisDeltaTime}}})}); + } + + if (doNGlobalTracksVsRawSignals) { + histPointers.insert({histPath + "hNGlobalTracksVsFT0A", histos.add((histPath + "hNGlobalTracksVsFT0A").c_str(), "hNGlobalTracksVsFT0A", {kTH2F, {{axisMultFT0A, axisMultGlobalTracks}}})}); + histPointers.insert({histPath + "hNGlobalTracksVsFT0C", histos.add((histPath + "hNGlobalTracksVsFT0C").c_str(), "hNGlobalTracksVsFT0C", {kTH2F, {{axisMultFT0C, axisMultGlobalTracks}}})}); + histPointers.insert({histPath + "hNGlobalTracksVsFT0M", histos.add((histPath + "hNGlobalTracksVsFT0M").c_str(), "hNGlobalTracksVsFT0M", {kTH2F, {{axisMultFT0M, axisMultGlobalTracks}}})}); + histPointers.insert({histPath + "hNGlobalTracksVsFV0A", histos.add((histPath + "hNGlobalTracksVsFV0A").c_str(), "hNGlobalTracksVsFV0A", {kTH2F, {{axisMultFV0A, axisMultGlobalTracks}}})}); + histPointers.insert({histPath + "hNGlobalTracksVsNMFTTracks", histos.add((histPath + "hNGlobalTracksVsNMFTTracks").c_str(), "hNGlobalTracksVsNMFTTracks", {kTH2F, {{axisMultMFTTracks, axisMultGlobalTracks}}})}); + histPointers.insert({histPath + "hNGlobalTracksVsNTPV", histos.add((histPath + "hNGlobalTracksVsNTPV").c_str(), "hNGlobalTracksVsNTPV", {kTH2F, {{axisMultPVContributors, axisMultGlobalTracks}}})}); + } + + if (doTimeStudies) { + histPointers.insert({histPath + "hFT0AVsTime", histos.add((histPath + "hFT0AVsTime").c_str(), "hFT0AVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFT0A}}})}); + histPointers.insert({histPath + "hFT0CVsTime", histos.add((histPath + "hFT0CVsTime").c_str(), "hFT0CVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFT0C}}})}); + histPointers.insert({histPath + "hFT0MVsTime", histos.add((histPath + "hFT0MVsTime").c_str(), "hFT0MVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFT0M}}})}); + histPointers.insert({histPath + "hFV0AVsTime", histos.add((histPath + "hFV0AVsTime").c_str(), "hFV0AVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFV0A}}})}); + histPointers.insert({histPath + "hFV0AOuterVsTime", histos.add((histPath + "hFV0AOuterVsTime").c_str(), "hFV0AOuterVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultFV0A}}})}); + histPointers.insert({histPath + "hMFTTracksVsTime", histos.add((histPath + "hMFTTracksVsTime").c_str(), "hMFTTracksVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultMFTTracks}}})}); + histPointers.insert({histPath + "hNGlobalVsTime", histos.add((histPath + "hNGlobalVsTime").c_str(), "hNGlobalVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultGlobalTracks}}})}); + histPointers.insert({histPath + "hNTPVContributorsVsTime", histos.add((histPath + "hNTPVContributorsVsTime").c_str(), "hNTPVContributorsVsTime", {kTH2F, {{axisDeltaTimestamp, axisMultPVContributors}}})}); + histPointers.insert({histPath + "hPVzProfileCoVsTime", histos.add((histPath + "hPVzProfileCoVsTime").c_str(), "hPVzProfileCoVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); + histPointers.insert({histPath + "hPVzProfileBcVsTime", histos.add((histPath + "hPVzProfileBcVsTime").c_str(), "hPVzProfileBcVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); + if (irDoRateVsTime) { + histPointers.insert({histPath + "hIRProfileVsTime", histos.add((histPath + "hIRProfileVsTime").c_str(), "hIRProfileVsTime", {kTProfile, {{axisDeltaTimestamp}}})}); + } + } } template void genericProcessCollision(TCollision collision) // process this collisions { - + initRun(collision); histos.fill(HIST("hCollisionSelection"), 0); // all collisions + getHist(TH1, histPath + "hCollisionSelection")->Fill(0); + if (applySel8 && !collision.multSel8()) return; histos.fill(HIST("hCollisionSelection"), 1); + getHist(TH1, histPath + "hCollisionSelection")->Fill(1); + + // calculate vertex-Z-equalized quantities if desired + float multFV0A = collision.multFV0A(); + float multFT0A = collision.multFT0A(); + float multFT0C = collision.multFT0C(); + float multNTracksGlobal = collision.multNTracksGlobal(); + float mftNtracks = collision.mftNtracks(); + float multNTracksPV = collision.multNTracksPV(); + if (applyVertexZEqualization) { + float epsilon = 1e-2; // average value after which this collision will be disregarded + multFV0A = -1.0f; + multFT0A = -1.0f; + multFT0C = -1.0f; + multNTracksGlobal = -1.0f; + mftNtracks = -1.0f; + multNTracksPV = -1.0f; + + if (hVtxZFV0A->Interpolate(collision.multPVz()) > epsilon) { + multFV0A = hVtxZFV0A->Interpolate(0.0) * collision.multFV0A() / hVtxZFV0A->Interpolate(collision.multPVz()); + } + if (hVtxZFT0A->Interpolate(collision.multPVz()) > epsilon) { + multFT0A = hVtxZFT0A->Interpolate(0.0) * collision.multFT0A() / hVtxZFT0A->Interpolate(collision.multPVz()); + } + if (hVtxZFT0C->Interpolate(collision.multPVz()) > epsilon) { + multFT0C = hVtxZFT0C->Interpolate(0.0) * collision.multFT0C() / hVtxZFT0C->Interpolate(collision.multPVz()); + } + if (hVtxZNGlobals->Interpolate(collision.multPVz()) > epsilon) { + multNTracksGlobal = hVtxZNGlobals->Interpolate(0.0) * collision.multNTracksGlobal() / hVtxZNGlobals->Interpolate(collision.multPVz()); + } + if (hVtxZMFT->Interpolate(collision.multPVz()) > epsilon) { + mftNtracks = hVtxZMFT->Interpolate(0.0) * collision.mftNtracks() / hVtxZMFT->Interpolate(collision.multPVz()); + } + if (hVtxZNTracks->Interpolate(collision.multPVz()) > epsilon) { + multNTracksPV = hVtxZNTracks->Interpolate(0.0) * collision.multNTracksPV() / hVtxZNTracks->Interpolate(collision.multPVz()); + } + } + + bool passRejectITSROFBorder = !(rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)); + bool passRejectTFBorder = !(rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)); + bool passRequireIsVertexITSTPC = !(requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)); + bool passRequireIsGoodZvtxFT0VsPV = !(requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)); + bool passRequireIsVertexTOFmatched = !(requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)); + bool passRequireIsVertexTRDmatched = !(requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)); + bool passRejectSameBunchPileup = !(rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); + bool passRejectITSinROFpileupStandard = !(rejectITSinROFpileupStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)); + bool passRejectITSinROFpileupStrict = !(rejectITSinROFpileupStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)); + bool passSelectUPCcollisions = !(selectUPCcollisions && collision.flags() < 1); + bool passRejectCollInTimeRangeNarrow = !(rejectCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)); + // _______________________________________________________ + // sidestep vertex-Z rejection for vertex-Z profile histograms + if (passRejectITSROFBorder && passRejectTFBorder && passRequireIsVertexITSTPC && passRequireIsGoodZvtxFT0VsPV && + passRequireIsVertexTOFmatched && passRequireIsVertexTRDmatched && passRejectSameBunchPileup && passRejectITSinROFpileupStandard && passRejectITSinROFpileupStrict && + passSelectUPCcollisions && passRejectCollInTimeRangeNarrow) { + getHist(TProfile, histPath + "hFT0CvsPVz_Collisions_All")->Fill(collision.multPVz(), multFT0C * scaleSignalFT0C); + getHist(TProfile, histPath + "hFT0CvsPVz_Collisions")->Fill(collision.multPVz(), multFT0C * scaleSignalFT0C); + getHist(TProfile, histPath + "hFT0AvsPVz_Collisions")->Fill(collision.multPVz(), multFT0A * scaleSignalFT0C); + getHist(TProfile, histPath + "hFV0AvsPVz_Collisions")->Fill(collision.multPVz(), multFV0A * scaleSignalFV0A); + getHist(TProfile, histPath + "hNGlobalTracksvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksGlobal); + getHist(TProfile, histPath + "hNMFTTracksvsPVz_Collisions")->Fill(collision.multPVz(), mftNtracks); + getHist(TProfile, histPath + "hNTPVvsPVz_Collisions")->Fill(collision.multPVz(), multNTracksPV); + } + + // _______________________________________________________ + if (applyVtxZ && TMath::Abs(collision.multPVz()) > 10) return; histos.fill(HIST("hCollisionSelection"), 2); + getHist(TH1, histPath + "hCollisionSelection")->Fill(2); // _______________________________________________________ // Extra event selections start here - if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + if (!passRejectITSROFBorder) { return; } histos.fill(HIST("hCollisionSelection"), 3 /* Not at ITS ROF border */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(3); - if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + if (!passRejectTFBorder) { return; } histos.fill(HIST("hCollisionSelection"), 4 /* Not at TF border */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(4); - if (requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + if (!passRequireIsVertexITSTPC) { return; } histos.fill(HIST("hCollisionSelection"), 5 /* Contains at least one ITS-TPC track */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(5); - if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (!passRequireIsGoodZvtxFT0VsPV) { return; } histos.fill(HIST("hCollisionSelection"), 6 /* PV position consistency check */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(6); - if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + if (!passRequireIsVertexTOFmatched) { return; } histos.fill(HIST("hCollisionSelection"), 7 /* PV with at least one contributor matched with TOF */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(7); - if (requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + if (!passRequireIsVertexTRDmatched) { return; } histos.fill(HIST("hCollisionSelection"), 8 /* PV with at least one contributor matched with TRD */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(8); - if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + if (!passRejectSameBunchPileup) { return; } histos.fill(HIST("hCollisionSelection"), 9 /* Not at same bunch pile-up */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(9); // do this only if information is available if constexpr (requires { collision.timeToNext(); }) { @@ -289,27 +553,32 @@ struct centralityStudy { return; } histos.fill(HIST("hCollisionSelection"), 10 /* has suspicious neighbour */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(10); } - if (rejectITSinROFpileupStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (!passRejectITSinROFpileupStandard) { return; } histos.fill(HIST("hCollisionSelection"), 11 /* Not ITS ROF pileup (standard) */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(11); - if (rejectITSinROFpileupStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + if (!passRejectITSinROFpileupStrict) { return; } histos.fill(HIST("hCollisionSelection"), 12 /* Not ITS ROF pileup (strict) */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(12); - if (selectUPCcollisions && collision.flags() < 1) { // if zero then NOT upc, otherwise UPC + if (!passSelectUPCcollisions) { // if zero then NOT upc, otherwise UPC return; } histos.fill(HIST("hCollisionSelection"), 13 /* is UPC event */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(13); - if (rejectCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + if (!passRejectCollInTimeRangeNarrow) { return; } histos.fill(HIST("hCollisionSelection"), 14 /* Not ITS ROF pileup (strict) */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(14); if (collision.multFT0C() < upcRejection.maxFT0CforZNACselection && collision.multZNA() < upcRejection.minZNACsignal && @@ -325,9 +594,10 @@ struct centralityStudy { return; } histos.fill(HIST("hCollisionSelection"), 15 /* pass em/upc rejection */); + getHist(TH1, histPath + "hCollisionSelection")->Fill(15); // if we got here, we also finally fill the FT0C histogram, please - histos.fill(HIST("hNPVContributors"), collision.multPVTotalContributors()); + histos.fill(HIST("hNPVContributors"), collision.multNTracksPV()); 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); @@ -337,19 +607,42 @@ struct centralityStudy { histos.fill(HIST("hFV0AvsPVz_Collisions"), collision.multPVz(), collision.multFV0A() * scaleSignalFV0A); histos.fill(HIST("hNGlobalTracksvsPVz_Collisions"), collision.multPVz(), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracksvsPVz_Collisions"), collision.multPVz(), collision.mftNtracks()); - if (collision.multFT0C() > minFT0CforVertexZ) { - histos.fill(HIST("hFT0CvsPVz_Collisions"), collision.multPVz(), collision.multFT0C() * scaleSignalFT0C); + + // save vertex-Z equalized + getHist(TH1, histPath + "hNPVContributors")->Fill(multNTracksPV); + 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); + getHist(TH1, histPath + "hNGlobalTracks")->Fill(multNTracksGlobal); + getHist(TH1, histPath + "hNMFTTracks")->Fill(mftNtracks); + + if (applyVertexZEqualization.value) { + // save unequalized for cross-checks + getHist(TH1, histPath + "hNPVContributors_Unequalized")->Fill(collision.multNTracksPV()); + getHist(TH1, histPath + "hFT0C_Collisions_Unequalized")->Fill(collision.multFT0C() * scaleSignalFT0C); + getHist(TH1, histPath + "hFT0M_Collisions_Unequalized")->Fill((collision.multFT0A() + collision.multFT0C()) * scaleSignalFT0M); + getHist(TH1, histPath + "hFV0A_Collisions_Unequalized")->Fill(collision.multFV0A() * scaleSignalFV0A); + getHist(TH1, histPath + "hNGlobalTracks_Unequalized")->Fill(collision.multNTracksGlobal()); + getHist(TH1, histPath + "hNMFTTracks_Unequalized")->Fill(collision.mftNtracks()); } + if (do2DPlots) { histos.fill(HIST("hNContribsVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multPVTotalContributors()); histos.fill(HIST("hNContribsVsFV0A"), collision.multFV0A() * scaleSignalFV0A, collision.multPVTotalContributors()); histos.fill(HIST("hMatchedVsITSOnly"), collision.multNTracksITSOnly(), collision.multNTracksITSTPC()); + getHist(TH2, histPath + "hNContribsVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multPVTotalContributors()); + getHist(TH2, histPath + "hNContribsVsFV0A")->Fill(collision.multFV0A() * scaleSignalFV0A, collision.multPVTotalContributors()); + getHist(TH2, histPath + "hMatchedVsITSOnly")->Fill(collision.multNTracksITSOnly(), collision.multNTracksITSTPC()); // correlate also FIT detector signals histos.fill(HIST("hFT0AVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFT0A()); histos.fill(HIST("hFV0AVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFV0A()); histos.fill(HIST("hFDDAVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFDDA()); histos.fill(HIST("hFDDCVsFT0C"), collision.multFT0C() * scaleSignalFT0C, collision.multFDDC()); + getHist(TH2, histPath + "hFT0AVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFT0A()); + getHist(TH2, histPath + "hFV0AVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFV0A()); + getHist(TH2, histPath + "hFDDAVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFDDA()); + getHist(TH2, histPath + "hFDDCVsFT0C")->Fill(collision.multFT0C() * scaleSignalFT0C, collision.multFDDC()); } if (doOccupancyStudyVsCentrality2d) { @@ -367,15 +660,20 @@ struct centralityStudy { } if (doNGlobalTracksVsRawSignals) { - histos.fill(HIST("hNGlobalTracksVsFT0A"), collision.multFT0A(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsFT0C"), collision.multFT0C(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsFT0M"), collision.multFT0A() + collision.multFT0C(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsFV0A"), collision.multFV0A(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsFDDA"), collision.multFDDA(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsFDDC"), collision.multFDDC(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsZNA"), collision.multZNA(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsZNC"), collision.multZNC(), collision.multNTracksGlobal()); - histos.fill(HIST("hNGlobalTracksVsNMFTTracks"), collision.mftNtracks(), collision.multNTracksGlobal()); + histos.fill(HIST("hNGlobalTracksVsFT0A"), multFT0A, multNTracksGlobal); + histos.fill(HIST("hNGlobalTracksVsFT0C"), multFT0C, multNTracksGlobal); + histos.fill(HIST("hNGlobalTracksVsFT0M"), (multFT0A + multFT0C), multNTracksGlobal); + histos.fill(HIST("hNGlobalTracksVsFV0A"), multFV0A, multNTracksGlobal); + histos.fill(HIST("hNGlobalTracksVsNMFTTracks"), mftNtracks, multNTracksGlobal); + histos.fill(HIST("hNGlobalTracksVsNTPV"), multNTracksPV, multNTracksGlobal); + + // per run + getHist(TH2, histPath + "hNGlobalTracksVsFT0A")->Fill(multFT0A, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsFT0C")->Fill(multFT0C, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsFT0M")->Fill(multFT0A + multFT0C, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsFV0A")->Fill(multFV0A, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsNMFTTracks")->Fill(mftNtracks, multNTracksGlobal); + getHist(TH2, histPath + "hNGlobalTracksVsNTPV")->Fill(multNTracksPV, multNTracksGlobal); } // if the table has centrality information @@ -388,6 +686,13 @@ struct centralityStudy { histos.fill(HIST("hNGlobalTracksVsCentrality"), collision.centFT0C(), collision.multNTracksGlobal()); histos.fill(HIST("hNMFTTracksVsCentrality"), collision.centFT0C(), collision.mftNtracks()); histos.fill(HIST("hPVChi2VsCentrality"), collision.centFT0C(), collision.multPVChi2()); + getHist(TH1, histPath + "hCentrality")->Fill(collision.centFT0C()); + getHist(TH2, histPath + "hNContribsVsCentrality")->Fill(collision.centFT0C(), collision.multPVTotalContributors()); + getHist(TH2, histPath + "hNITSTPCTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksITSTPC()); + getHist(TH2, histPath + "hNITSOnlyTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksITSOnly()); + getHist(TH2, histPath + "hNGlobalTracksVsCentrality")->Fill(collision.centFT0C(), collision.multNTracksGlobal()); + getHist(TH2, histPath + "hNMFTTracksVsCentrality")->Fill(collision.centFT0C(), collision.mftNtracks()); + getHist(TH2, histPath + "hPVChi2VsCentrality")->Fill(collision.centFT0C(), collision.multPVChi2()); if (doOccupancyStudyVsCentrality2d) { histos.fill(HIST("hNcontribsProfileVsTrackOccupancyVsCentrality"), collision.trackOccupancyInTimeRange(), collision.centFT0C(), collision.multPVTotalContributors()); @@ -403,24 +708,50 @@ struct centralityStudy { histos.fill(HIST("hFT0COccupancyVsNGlobalTracksVsCentrality"), collision.ft0cOccupancyInTimeRange(), collision.multNTracksGlobal(), collision.centFT0C()); } } + + if (doTimeStudies && collision.has_multBC()) { + initRun(collision); + auto multbc = collision.template multBC_as(); + uint64_t bcTimestamp = multbc.timestamp(); + float hoursAfterStartOfRun = static_cast(bcTimestamp - startOfRunTimestamp) / 3600000.0; + + getHist(TH2, histPath + "hFT0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0A()); + getHist(TH2, histPath + "hFT0CVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0C()); + getHist(TH2, histPath + "hFT0MVsTime")->Fill(hoursAfterStartOfRun, collision.multFT0M()); + getHist(TH2, histPath + "hFV0AVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0A()); + getHist(TH2, histPath + "hFV0AOuterVsTime")->Fill(hoursAfterStartOfRun, collision.multFV0AOuter()); + getHist(TH2, histPath + "hMFTTracksVsTime")->Fill(hoursAfterStartOfRun, collision.mftNtracks()); + getHist(TH2, histPath + "hNGlobalVsTime")->Fill(hoursAfterStartOfRun, collision.multNTracksGlobal()); + getHist(TH2, histPath + "hNTPVContributorsVsTime")->Fill(hoursAfterStartOfRun, collision.multPVTotalContributors()); + getHist(TProfile, histPath + "hPVzProfileCoVsTime")->Fill(hoursAfterStartOfRun, collision.multPVz()); + getHist(TProfile, histPath + "hPVzProfileBcVsTime")->Fill(hoursAfterStartOfRun, multbc.multFT0PosZ()); + if (doTimeStudyFV0AOuterVsFT0A3d) { + histos.fill(HIST("h3dFV0AVsTime"), hoursAfterStartOfRun, collision.multFV0A(), collision.multFV0AOuter()); + } + + if (irDoRateVsTime) { + float interactionRate = mRateFetcher.fetch(ccdb.service, bcTimestamp, mRunNumber, irSource.value, irCrashOnNull) / 1000.; // kHz + getHist(TProfile, histPath + "hIRProfileVsTime")->Fill(hoursAfterStartOfRun, interactionRate); + } + } } - void processCollisions(soa::Join::iterator const& collision) + void processCollisions(soa::Join::iterator const& collision, aod::MultBCs const&) { genericProcessCollision(collision); } - void processCollisionsWithCentrality(soa::Join::iterator const& collision) + void processCollisionsWithCentrality(soa::Join::iterator const& collision, aod::MultBCs const&) { genericProcessCollision(collision); } - void processCollisionsWithCentralityWithNeighbours(soa::Join::iterator const& collision) + void processCollisionsWithCentralityWithNeighbours(soa::Join::iterator const& collision, aod::MultBCs const&) { genericProcessCollision(collision); } - void processBCs(soa::Join::iterator const& multbc, soa::Join const&) + void processBCs(soa::Join::iterator const& multbc, soa::Join const&) { // process BCs, calculate FT0C distribution // conditionals suggested by FIT team (Jacek O. et al) @@ -475,7 +806,7 @@ struct centralityStudy { } if (multbc.has_ft0Mult()) { - auto multco = multbc.ft0Mult_as>(); + auto multco = multbc.ft0Mult_as>(); if (multbc.multFT0PosZValid()) { histos.fill(HIST("hVertexZ_BCvsCO"), multco.multPVz(), multbc.multFT0PosZ()); } diff --git a/Common/Tasks/qVectorsCorrection.cxx b/Common/Tasks/qVectorsCorrection.cxx index 10e37a4c210..2d3c5c78804 100644 --- a/Common/Tasks/qVectorsCorrection.cxx +++ b/Common/Tasks/qVectorsCorrection.cxx @@ -68,6 +68,8 @@ struct qVectorsCorrection { Configurable cfgRefBName{"cfgRefBName", "TPCneg", "The name of detector for reference B"}; Configurable cfgAddEvtSel{"cfgAddEvtSel", true, "event selection"}; + Configurable cfgEvtSel{"cfgEvtSel", 0, "Event selection flags\n0: Sel8\n1: Sel8+kIsGoodZvtxFT0vsPV+kNoSameBunchPileup\n2: Sel8+kIsGoodZvtxFT0vsPV+kNoSameBunchPileup+kNoCollInTimeRangeStandard\n3: Sel8+kNoSameBunchPileup"}; + Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "total qvector number"}; Configurable cfgNbinsEP{"cfgNbinsEP", 360, "nbins for EP histograms"}; @@ -75,7 +77,6 @@ struct qVectorsCorrection { Configurable cfgQAFinal{"cfgQAFinal", false, "draw final q-vector steps"}; Configurable cfgQAFlowStudy{"cfgQAFlowStudy", false, "configurable for flow study"}; Configurable cfgQAOccupancyStudy{"cfgQAOccupancyStudy", false, "configurable for occupancy study"}; - Configurable cfgAddEvtSelPileup{"cfgAddEvtSelPileup", false, "configurable for pileup selection"}; Configurable cfgMinPt{"cfgMinPt", 0.15, "Minimum transverse momentum for charged track"}; Configurable cfgMaxEta{"cfgMaxEta", 0.8, "Maximum pseudorapidiy for charged track"}; @@ -541,16 +542,31 @@ struct qVectorsCorrection { void process(MyCollisions::iterator const& qVec, MyTracks const& tracks) { histosQA.fill(HIST("histCentFull"), qVec.cent()); - if (cfgAddEvtSel && (!qVec.sel8() || - !qVec.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV) || - !qVec.selection_bit(aod::evsel::kNoSameBunchPileup))) { - return; - } - if (cfgAddEvtSel && (qVec.trackOccupancyInTimeRange() > cfgMaxOccupancy || qVec.trackOccupancyInTimeRange() < cfgMinOccupancy)) { - return; - } - if (cfgAddEvtSelPileup && !qVec.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { - return; + if (cfgAddEvtSel) { + 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; } for (uint i = 0; i < cfgnMods->size(); i++) { diff --git a/Common/Tasks/qaMuon.cxx b/Common/Tasks/qaMuon.cxx index 1f210249089..8ef5a42f824 100644 --- a/Common/Tasks/qaMuon.cxx +++ b/Common/Tasks/qaMuon.cxx @@ -13,39 +13,44 @@ /// \author Paul Veen /// \author Chi Zhang -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/ASoAHelpers.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FwdTrackReAlignTables.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CCDBTimeStampUtils.h" -#include "CommonUtils/NameConf.h" #include "CommonUtils/ConfigurableParam.h" +#include "CommonUtils/NameConf.h" #include "DataFormatsMCH/Cluster.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" #include "DetectorsBase/GRPGeomHelper.h" +#include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" #include "Field/MagneticField.h" -#include "MathUtils/Cartesian.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "GlobalTracking/MatchGlobalFwd.h" +#include "MCHBase/TrackerParam.h" #include "MCHGeometryTransformer/Transformations.h" #include "MCHTracking/Track.h" #include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackParam.h" #include "MCHTracking/TrackFitter.h" -#include "MCHBase/TrackerParam.h" -#include "GlobalTracking/MatchGlobalFwd.h" +#include "MCHTracking/TrackParam.h" +#include "MathUtils/Cartesian.h" #include "ReconstructionDataFormats/TrackFwd.h" -#include "Common/DataModel/FwdTrackReAlignTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "TGeoGlobalMagField.h" #include "Math/Vector4D.h" +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include +#include +#include using namespace std; using namespace o2; @@ -284,6 +289,33 @@ struct muonQa { registry.add("muons/TrackPDCA", "MCH track p #times DCA", {HistType::kTH1F, {pdcaAxis}}); registry.add("muons/TrackPhi", "MCH track #phi", {HistType::kTH1F, {phiAxis}}); + // muon origin from MCH quadrants + registry.add("muons/TrackEtaPos", "MCH #mu^{+} track #eta", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg", "MCH #mu^{-} track #eta", {HistType::kTH1F, {etaAxis}}); + // -- pT and eta + registry.add("muons/TrackPt_TrackEtaPos", "track pT and #eta", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg", "track pT and #eta", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + // top-bottom + registry.add("muons/TrackEtaPos_T", "MCH #mu^{+} track #eta, top MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaPos_B", "MCH #mu^{+} track #eta, bottom MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_T", "MCH #mu^{-} track #eta, top MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_B", "MCH #mu^{-} track #eta, bottom MCH CH1", {HistType::kTH1F, {etaAxis}}); + // -- pT and eta + registry.add("muons/TrackPt_TrackEtaPos_T", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaPos_B", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_T", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_B", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + // left-right + registry.add("muons/TrackEtaPos_L", "MCH #mu^{+} track #eta, left MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaPos_R", "MCH #mu^{+} track #eta, right MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_L", "MCH #mu^{-} track #eta, left MCH CH1", {HistType::kTH1F, {etaAxis}}); + registry.add("muons/TrackEtaNeg_R", "MCH #mu^{-} track #eta, right MCH CH1", {HistType::kTH1F, {etaAxis}}); + // -- pT and eta + registry.add("muons/TrackPt_TrackEtaPos_L", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaPos_R", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_L", "track p_{T} and #eta, top MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + registry.add("muons/TrackPt_TrackEtaNeg_R", "track p_{T} and #eta, bottom MCH CH1", {HistType::kTH2F, {transverseMomentumAxis, etaAxis}}); + // ====================== // Global muons plots // ====================== @@ -535,71 +567,178 @@ struct muonQa { } if (configQAs.fEnableQADimuon) { + // single muons + AxisSpec transverseMomentumAxis = {100, 0, 30, "p_{T} (GeV/c)"}; + AxisSpec etaAxis = {40, -5, -1, "#eta"}; + AxisSpec rAbsAxis = {10, 0., 100.0, "R_{abs} (cm)"}; + AxisSpec dcaAxis = {40, 0.0, 20.0, "DCA"}; + AxisSpec phiAxis = {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})"}; AxisSpec invMassAxisFull = {5000, 0, 100, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + AxisSpec yPairAxis = {120, 0.0, 6.0, "#y_{pair}"}; + AxisSpec invMassAxis2D = {750, 0, 15, "M_{#mu^{+}#mu^{-}} (GeV/c^{2})"}; + AxisSpec pTAxis2D = {120, 0, 30, "p_{T} (GeV/c)"}; + // Single muons - dimuons correlations + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosPt_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{+} p_{T}", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegPt_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{-} p_{T}", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, pTAxis2D}}); + // + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosEta_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{+} #eta", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, etaAxis}}); + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegEta_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{-} #eta", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, etaAxis}}); + // + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosRabs_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{+} R_{abs}", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, rAbsAxis}}); + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegRabs_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{-} R_{abs}", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, rAbsAxis}}); + // + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosDca_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{+} DCA", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, dcaAxis}}); + registryDimuon.add("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegDca_MuonKine_MuonCuts", "#mu^{+}#mu^{-} and #mu^{-} DCA", {HistType::kTH3F, {invMassAxis2D, pTAxis2D, dcaAxis}}); + // + 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}}); // MCH-MID tracks with MCH acceptance cuts registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MCH acceptance cuts and combinations from the top and bottom halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MFT acceptance cuts and combinations from the top and bottom halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TPBN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} top and #mu^{-} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TNBP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} top and #mu^{+} bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MCH acceptance cuts and combinations from the left and right halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or left-right", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or left-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MFT acceptance cuts registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // MCH-MID tracks with MFT acceptance cuts and combinations from the left and right halfs of MCH registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxis}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH1F, {invMassAxisFull}}); + registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass right-right", {HistType::kTH1F, {invMassAxisFull}}); + // -- Mass and pT + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LPRN", "#mu^{+}#mu^{-} invariant mass, #mu^{+} left and #mu^{-} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LNRP", "#mu^{+}#mu^{-} invariant mass, #mu^{-} left and #mu^{+} right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); + registryDimuon.add("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, pTAxis2D}}); // Good MFT-MCH-MID tracks with MCH parameters and MFT acceptance cuts registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_MuonKine_GlobalMatchesCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); @@ -631,11 +770,42 @@ struct muonQa { registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_leading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxis}}); registryDimuon.add("dimuon/same-event/invariantMassFull_GlobalMuonKine_GlobalMatchesCuts_subleading_subleading", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH1F, {invMassAxisFull}}); - // invariant mass correlations registryDimuon.add("dimuon/same-event/invariantMass_MuonKine_vs_GlobalMuonKine", "M_{#mu^{+}#mu^{-}} - muon tracks vs. global tracks", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); registryDimuon.add("dimuon/same-event/invariantMass_ScaledMftKine_vs_GlobalMuonKine", "M_{#mu^{+}#mu^{-}} - rescaled MFT tracks vs. global tracks", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); registryDimuon.add("dimuon/same-event/invariantMass_GlobalMuonKine_subleading_vs_leading", "M_{#mu^{+}#mu^{-}} - subleading vs. leading matches", {HistType::kTH2F, {invMassCorrelationAxis, invMassCorrelationAxis}}); + + // pseudorapidity (only for MCH acceptance cuts) + // MCH-MID tracks with MCH acceptance cuts + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts", "#eta of dimuon pair", {HistType::kTH1F, {yPairAxis}}); + // -- Mass and eta + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts", "#mu^{+}#mu^{-} invariant mass", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + // -- pT and eta + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts", "#mu^{+}#mu^{-} p_{T} and #eta", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + // MCH-MID tracks with MCH acceptance cuts and combinations from the top and bottom halfs of MCH + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_TT", "#eta of dimuon pair, top-top", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_TB", "#eta of dimuon pair, top-bottom or bottom-top", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_BB", "#eta of dimuon pair, bottom-bottom", {HistType::kTH1F, {yPairAxis}}); + // -- Mass and eta + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} invariant mass, top-top", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} invariant mass, top-bottom or bottom-top", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} invariant mass, bottom-bottom", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + // -- pT and eta + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TT", "#mu^{+}#mu^{-} p_{T} and #eta, top-top", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TB", "#mu^{+}#mu^{-} p_{T} and #eta, top-bottom or bottom-top", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_BB", "#mu^{+}#mu^{-} p_{T} and #eta, bottom-bottom", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + // MCH-MID tracks with MCH acceptance cuts and combinations from the left and right halfs of MCH + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_LL", "#eta of dimuon pair, left-left", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_LR", "#eta of dimuon pair, left-right or right-left", {HistType::kTH1F, {yPairAxis}}); + registryDimuon.add("dimuon/same-event/rapPair_MuonKine_MuonCuts_RR", "#eta of dimuon pair, right-right", {HistType::kTH1F, {yPairAxis}}); + // -- Mass and eta + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} invariant mass, left-left", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} invariant mass, left-right or right-left", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} invariant mass, right-right", {HistType::kTH2F, {invMassAxis2D, yPairAxis}}); + // -- pT and eta + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_LL", "#mu^{+}#mu^{-} p_{T} and #eta, left-left", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_LR", "#mu^{+}#mu^{-} p_{T} and #eta, left-right or right-left", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); + registryDimuon.add("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_RR", "#mu^{+}#mu^{-} p_{T} and #eta, right-right", {HistType::kTH2F, {pTAxis2D, yPairAxis}}); } } @@ -965,6 +1135,46 @@ struct muonQa { return dimuon.M(); } + template + double GetMuMuPt(VarT const& track1, VarT const& track2) + { + ROOT::Math::PxPyPzMVector muon1{ + track1.px, + track1.py, + track1.pz, + o2::constants::physics::MassMuon}; + + ROOT::Math::PxPyPzMVector muon2{ + track2.px, + track2.py, + track2.pz, + o2::constants::physics::MassMuon}; + + auto dimuon = muon1 + muon2; + + return dimuon.Pt(); + } + + template + double GetMuMuRap(VarT const& track1, VarT const& track2) + { + ROOT::Math::PxPyPzMVector muon1{ + track1.px, + track1.py, + track1.pz, + o2::constants::physics::MassMuon}; + + ROOT::Math::PxPyPzMVector muon2{ + track2.px, + track2.py, + track2.pz, + o2::constants::physics::MassMuon}; + + auto dimuon = muon1 + muon2; + + return dimuon.Y(); + } + template void GetMuonPairs(TMuons const& muons, TCandidates const& matchingCandidates, const std::map& collisionInfos, std::vector& muonPairs, @@ -1446,6 +1656,56 @@ struct muonQa { registry.get(HIST("muons/TrackPhi"))->Fill(fgValuesMCH.phi * 180.0 / TMath::Pi()); registry.get(HIST("muons/TrackDCA"))->Fill(std::sqrt(fgValuesMCH.dcaX * fgValuesMCH.dcaX + fgValuesMCH.dcaY * fgValuesMCH.dcaY)); } + + // muon origin for MCH top-bottom and left-right parts + if (IsGoodMuon(fgValuesMCH, fgValuesMCHpv, configMuons.fTrackChi2MchUp, configMuons.fPMchLow, configMuons.fPtMchLow, -1.E10, 1.E10, configMuons.fRabsLow, configMuons.fRabsUp, configMuons.fSigmaPdcaUp)) { + int Quadrant = GetQuadrantPhi(fgValuesMCH.phi * 180.0 / TMath::Pi()); + int TopBottom = (Quadrant == 0 || Quadrant == 1) ? 0 : 1; + int LeftRight = (Quadrant == 0 || Quadrant == 3) ? 0 : 1; + int PosNeg = fgValuesMCH.sign > 0 ? 0 : 1; + float eta = fgValuesMCH.eta; + float pT = fgValuesMCH.pT; + + // same-event case + if (PosNeg == 0) { + registry.get(HIST("muons/TrackEtaPos"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos"))->Fill(pT, eta); + + if (TopBottom == 0) { + registry.get(HIST("muons/TrackEtaPos_T"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_T"))->Fill(pT, eta); + } else if (TopBottom == 1) { + registry.get(HIST("muons/TrackEtaPos_B"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_B"))->Fill(pT, eta); + } + + if (LeftRight == 0) { + registry.get(HIST("muons/TrackEtaPos_L"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_L"))->Fill(pT, eta); + } else if (LeftRight == 1) { + registry.get(HIST("muons/TrackEtaPos_R"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaPos_R"))->Fill(pT, eta); + } + } else if (PosNeg == 1) { + registry.get(HIST("muons/TrackEtaNeg"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg"))->Fill(pT, eta); + if (TopBottom == 0) { + registry.get(HIST("muons/TrackEtaNeg_T"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_T"))->Fill(pT, eta); + } else if (TopBottom == 1) { + registry.get(HIST("muons/TrackEtaNeg_B"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_B"))->Fill(pT, eta); + } + + if (LeftRight == 0) { + registry.get(HIST("muons/TrackEtaNeg_L"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_L"))->Fill(pT, eta); + } else if (LeftRight == 1) { + registry.get(HIST("muons/TrackEtaNeg_R"))->Fill(eta); + registry.get(HIST("muons/TrackPt_TrackEtaNeg_R"))->Fill(pT, eta); + } + } + } } if constexpr (static_cast(GlobalMuonFillMap)) { @@ -1563,7 +1823,7 @@ struct muonQa { std::vector> yPos; std::vector> thetax; std::vector> thetay; - for (int zi = 0; zi < int(zRefPlane.size()); zi++) { + for (int zi = 0; zi < static_cast(zRefPlane.size()); zi++) { xPos.emplace_back(std::array{fgVectorsMCH[zi].x, fgVectorsMFT[zi].x}); yPos.emplace_back(std::array{fgVectorsMCH[zi].y, fgVectorsMFT[zi].y}); thetax.emplace_back(std::array{ @@ -1574,7 +1834,7 @@ struct muonQa { std::atan2(fgVectorsMFT[zi].py, -1.0 * fgVectorsMFT[zi].pz) * 180 / TMath::Pi()}); } - for (int i = 0; i < int(zRefPlane.size()); i++) { + for (int i = 0; i < static_cast(zRefPlane.size()); i++) { if (same) { std::get>(trackResidualsHistos[i][quadrant]["dx_vs_x"])->Fill(std::fabs(xPos[i][1]), xPos[i][0] - xPos[i][1]); std::get>(trackResidualsHistos[i][quadrant]["dx_vs_y"])->Fill(std::fabs(yPos[i][1]), xPos[i][0] - xPos[i][1]); @@ -1947,7 +2207,7 @@ struct muonQa { } // Loop over attached clusters - for (int iCls = 0; iCls < int(fgValuesClsTmp.posClusters.size()); iCls++) { + for (int iCls = 0; iCls < static_cast(fgValuesClsTmp.posClusters.size()); iCls++) { double phiCls = std::atan2(fgValuesClsTmp.posClusters[iCls][1], fgValuesClsTmp.posClusters[iCls][0]) * 180 / TMath::Pi(); int quadrantCls = GetQuadrantPhi(phiCls); @@ -2094,7 +2354,7 @@ struct muonQa { FillMatching(muontrack, fgValuesMCH, fgValuesMFT); //// Fill global informations - registry.get(HIST("global-muons/NCandidates"))->Fill(int(globalMuonsVector.size())); + registry.get(HIST("global-muons/NCandidates"))->Fill(static_cast(globalMuonsVector.size())); for (size_t candidateIndex = 0; candidateIndex < globalMuonsVector.size(); candidateIndex++) { auto const& muon = muons.rawIteratorAt(globalMuonsVector[candidateIndex]); registry.get(HIST("global-muons/MatchChi2"))->Fill(muon.chi2MatchMCHMFT(), candidateIndex); @@ -2136,7 +2396,7 @@ struct muonQa { } //// Fill global muon candidates info - for (int i = 0; i < int(globalMuonsVector.size()); i++) { + for (int i = 0; i < static_cast(globalMuonsVector.size()); i++) { VarTrack fgValuesTmp; auto muonCandidate = muons.rawIteratorAt(globalMuonsVector[i]); FillTrack<0>(muonCandidate, fgValuesTmp); @@ -2240,12 +2500,27 @@ struct muonQa { if ((sign1 * sign2) >= 0) continue; + const auto& muonPos = fgValuesMuon1.sign > 0 ? fgValuesMuon1 : fgValuesMuon2; + const auto& muonNeg = fgValuesMuon1.sign < 0 ? fgValuesMuon1 : fgValuesMuon2; + // μ⁺ variables + double muPosPt = muonPos.pT; + double muPosEta = muonPos.eta; + double muPosRabs = muonPos.rabs; + double muPosPhi = muonPos.phi * 180.0 / TMath::Pi(); + double muPosDca = std::sqrt(muonPos.dcaX * muonPos.dcaX + muonPos.dcaY * muonPos.dcaY); + // μ⁻ variables + double muNegPt = muonNeg.pT; + double muNegEta = muonNeg.eta; + double muNegRabs = muonNeg.rabs; + double muNegPhi = muonNeg.phi * 180.0 / TMath::Pi(); + double muNegDca = std::sqrt(muonNeg.dcaX * muonNeg.dcaX + muonNeg.dcaY * muonNeg.dcaY); + int Quadrant1 = GetQuadrantPhi(muonTrack1.phi() * 180.0 / TMath::Pi()); int Quadrant2 = GetQuadrantPhi(muonTrack2.phi() * 180.0 / TMath::Pi()); int TopBottom1 = (Quadrant1 == 0 || Quadrant1 == 1) ? 0 : 1; int TopBottom2 = (Quadrant2 == 0 || Quadrant2 == 1) ? 0 : 1; - int LeftRight1 = (Quadrant1 == 0 || Quadrant1 == 2) ? 0 : 1; - int LeftRight2 = (Quadrant2 == 0 || Quadrant2 == 2) ? 0 : 1; + int LeftRight1 = (Quadrant1 == 0 || Quadrant1 == 3) ? 0 : 1; + int LeftRight2 = (Quadrant2 == 0 || Quadrant2 == 3) ? 0 : 1; bool goodMuonTracks = (IsGoodMuon(fgValuesMuon1, fgValuesMuonPV1) && IsGoodMuon(fgValuesMuon2, fgValuesMuonPV2)); bool goodGlobalMuonTracks = (IsGoodGlobalMuon(fgValuesMuon1, fgValuesMuonPV1) && IsGoodGlobalMuon(fgValuesMuon2, fgValuesMuonPV2)); @@ -2253,58 +2528,192 @@ struct muonQa { bool sameEvent = (collisionIndex1 == collisionIndex2); double mass = GetMuMuInvariantMass(fgValuesMuonPV1, fgValuesMuonPV2); + double pT = GetMuMuPt(fgValuesMuonPV1, fgValuesMuonPV2); + double yPair = GetMuMuRap(fgValuesMuonPV1, fgValuesMuonPV2); if (goodMuonTracks) { if (sameEvent) { // same-event case + // single muons + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosPt_MuonKine_MuonCuts"))->Fill(mass, pT, muPosPt); + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegPt_MuonKine_MuonCuts"))->Fill(mass, pT, muNegPt); + // + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosEta_MuonKine_MuonCuts"))->Fill(mass, pT, muPosEta); + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegEta_MuonKine_MuonCuts"))->Fill(mass, pT, muNegEta); + // + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosRabs_MuonKine_MuonCuts"))->Fill(mass, pT, muPosRabs); + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegRabs_MuonKine_MuonCuts"))->Fill(mass, pT, muNegRabs); + // + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosDca_MuonKine_MuonCuts"))->Fill(mass, pT, muPosDca); + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegDca_MuonKine_MuonCuts"))->Fill(mass, pT, muNegDca); + // + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuPosPhi_MuonKine_MuonCuts"))->Fill(mass, pT, muPosPhi); + registryDimuon.get(HIST("dimuon/same-event/single-muon-dimuon-correlations/invariantMass_pT_MuNegPhi_MuonKine_MuonCuts"))->Fill(mass, pT, muNegPhi); + // dimuons registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts"))->Fill(pT, yPair); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TT"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_TT"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TT"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TT"))->Fill(pT, yPair); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TB"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_TB"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_TB"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_TB"))->Fill(pT, yPair); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TNBP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_TNBP"))->Fill(mass, pT); + } + } } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_BB"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_BB"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_BB"))->Fill(mass, yPair); + registryDimuon.get(HIST("dimuon/same-event/pT_rapPair_MuonKine_MuonCuts_BB"))->Fill(pT, yPair); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LL"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_LL"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LL"))->Fill(mass, yPair); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LR"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_LR"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_LR"))->Fill(mass, yPair); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LNRP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_LNRP"))->Fill(mass, pT); + } + } } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_MuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_MuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_MuonCuts_RR"))->Fill(mass, pT); + registryDimuon.get(HIST("dimuon/same-event/rapPair_MuonKine_MuonCuts_RR"))->Fill(yPair); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_rapPair_MuonKine_MuonCuts_RR"))->Fill(mass, yPair); } } else { // event-mixing case registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts"))->Fill(mass, pT); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TT"))->Fill(mass, pT); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TB"))->Fill(mass, pT); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TNBP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_TNBP"))->Fill(mass, pT); + } + } } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_BB"))->Fill(mass, pT); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LL"))->Fill(mass, pT); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LR"))->Fill(mass, pT); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LNRP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_LNRP"))->Fill(mass, pT); + } + } } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_MuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_MuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_MuonCuts_RR"))->Fill(mass, pT); } } } @@ -2314,53 +2723,151 @@ struct muonQa { // same-event case registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts"))->Fill(mass, pT); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT"))->Fill(mass, pT); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB"))->Fill(mass, pT); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass, pT); + } + } } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB"))->Fill(mass, pT); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL"))->Fill(mass, pT); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR"))->Fill(mass, pT); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass, pT); + } + } } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/same-event/invariantMass_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/same-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/same-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR"))->Fill(mass, pT); } } else { // event-mixing case registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts"))->Fill(mass, pT); if (TopBottom1 == 0 && TopBottom2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TT"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TT"))->Fill(mass, pT); } else if ((TopBottom1 == 0 && TopBottom2 == 1) || (TopBottom1 == 1 && TopBottom2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TB"))->Fill(mass, pT); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TPBN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_TNBP"))->Fill(mass, pT); + } + } } else if (TopBottom1 == 1 && TopBottom2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_BB"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_BB"))->Fill(mass, pT); } if (LeftRight1 == 0 && LeftRight2 == 0) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LL"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LL"))->Fill(mass, pT); } else if ((LeftRight1 == 0 && LeftRight2 == 1) || (LeftRight1 == 1 && LeftRight2 == 0)) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LR"))->Fill(mass, pT); + if (TopBottom1 == 0 && TopBottom2 == 1) { + if (sign1 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass, pT); + } + } else if (TopBottom1 == 1 && TopBottom2 == 0) { + if (sign2 > 0) { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LPRN"))->Fill(mass, pT); + } else { + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_LNRP"))->Fill(mass, pT); + } + } } else if (LeftRight1 == 1 && LeftRight2 == 1) { registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); registryDimuon.get(HIST("dimuon/mixed-event/invariantMassFull_MuonKine_GlobalMuonCuts_RR"))->Fill(mass); + registryDimuon.get(HIST("dimuon/mixed-event/invariantMass_pT_MuonKine_GlobalMuonCuts_RR"))->Fill(mass, pT); } } } @@ -2399,7 +2906,7 @@ struct muonQa { mch::Track mchrealigned1, mchrealigned2; VarClusters fgValuesCls1, fgValuesCls2; - if (!FillClusters(muonTrack1, clusters, fgValuesCls1, mchrealigned1) || !FillClusters(muonTrack2, clusters, fgValuesCls2, mchrealigned2)) { + if (!FillClusters(mchTrack1, clusters, fgValuesCls1, mchrealigned1) || !FillClusters(mchTrack2, clusters, fgValuesCls2, mchrealigned2)) { continue; // Refit is not valid } diff --git a/Common/Tools/EventSelectionTools.h b/Common/Tools/EventSelectionTools.h new file mode 100644 index 00000000000..eef9ddaf7f6 --- /dev/null +++ b/Common/Tools/EventSelectionTools.h @@ -0,0 +1,1795 @@ +// 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 EventSelectionModule.h +/// \brief +/// \author ALICE + +#ifndef COMMON_TOOLS_EVENTSELECTIONTOOLS_H_ +#define COMMON_TOOLS_EVENTSELECTIONTOOLS_H_ + +#define bitcheck(var, nbit) ((var) & (static_cast(1) << (nbit))) +#define bitcheck64(var, nbit) ((var) & (static_cast(1) << (nbit))) + +#include "MetadataHelper.h" +#include "TableHelper.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/LHCConstants.h" +#include "DataFormatsCTP/Configuration.h" +#include "DataFormatsCTP/Scalers.h" +#include "DataFormatsFT0/Digit.h" +#include "DataFormatsITSMFT/NoiseMap.h" // missing include in TimeDeadMap.h +#include "DataFormatsITSMFT/TimeDeadMap.h" +#include "DataFormatsParameters/AggregatedRunInfo.h" +#include "DataFormatsParameters/GRPECSObject.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/HistogramRegistry.h" +#include "ITSMFTBase/DPLAlpideParam.h" +#include "ITSMFTReconstruction/ChipMappingITS.h" + +#include +#include +#include +#include +#include + +//__________________________________________ +// MultModule + +namespace o2 +{ +namespace common +{ +namespace eventselection +{ +static const double bcNS = o2::constants::lhc::LHCBunchSpacingNS; +static const int32_t nBCsPerOrbit = o2::constants::lhc::LHCMaxBunches; + +// for providing temporary buffer +// FIXME ideally cursors could be readable +// to avoid duplicate memory allocation but ok +struct bcselEntry { + uint32_t alias{0}; + uint64_t selection{0}; + uint32_t rct{0}; + int foundFT0Id = -1; + int foundFV0Id = -1; + int foundFDDId = -1; + int foundZDCId = -1; +}; + +// bc selection configurables +struct bcselConfigurables : o2::framework::ConfigurableGroup { + std::string prefix = "bcselOpts"; + o2::framework::Configurable amIneeded{"amIneeded", -1, "run BC selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTriggerBcShift{"triggerBcShift", 0, "set either custom shift or 999 for apass2/apass3 in LHC22o-t"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::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) + o2::framework::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) + o2::framework::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) + o2::framework::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) + o2::framework::Configurable confCheckRunDurationLimits{"checkRunDurationLimits", false, "Check if the BCs are within the run duration limits"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable> maxInactiveChipsPerLayer{"maxInactiveChipsPerLayer", {8, 8, 8, 111, 111, 195, 195}, "Maximum allowed number of inactive ITS chips per layer"}; + o2::framework::Configurable confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) +}; + +// event selection configurables +struct evselConfigurables : o2::framework::ConfigurableGroup { + std::string prefix = "evselOpts"; + bool isMC_metadata = false; + o2::framework::Configurable amIneeded{"amIneeded", -1, "run event selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable muonSelection{"muonSelection", 0, "0 - barrel, 1 - muon selection with pileup cuts, 2 - muon selection without pileup cuts"}; + o2::framework::Configurable maxDiffZvtxFT0vsPV{"maxDiffZvtxFT0vsPV", 1., "maximum difference (in cm) between z-vertex from FT0 and PV"}; + o2::framework::Configurable isMC{"isMC", -1, "-1 - autoset, 0 - data, 1 - MC"}; + o2::framework::Configurable confSigmaBCforHighPtTracks{"confSigmaBCforHighPtTracks", 4, "Custom sigma (in bcs) for collisions with high-pt tracks"}; + + // configurables for occupancy-based event selection + o2::framework::Configurable confTimeIntervalForOccupancyCalculationMin{"TimeIntervalForOccupancyCalculationMin", -40, "Min time diff window for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeIntervalForOccupancyCalculationMax{"TimeIntervalForOccupancyCalculationMax", 100, "Max time diff window for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeRangeVetoOnCollStandard{"TimeRangeVetoOnCollStandard", 10.0, "Exclusion of a collision if there are other collisions nearby, +/- us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confTimeRangeVetoOnCollNarrow{"TimeRangeVetoOnCollNarrow", 2.0, "Exclusion of a collision if there are other collisions nearby, +/- us"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confFT0CamplCutVetoOnCollInTimeRange{"FT0CamplPerCollCutVetoOnCollInTimeRange", 8000, "Max allowed FT0C amplitude for each nearby collision in +/- time range"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confFT0CamplCutVetoOnCollInROF{"FT0CamplPerCollCutVetoOnCollInROF", 5000, "Max allowed FT0C amplitude for each nearby collision inside this ITS ROF"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confEpsilonVzDiffVetoInROF{"EpsilonVzDiffVetoInROF", 0.3, "Minumum distance to nearby collisions along z inside this ITS ROF, cm"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confUseWeightsForOccupancyVariable{"UseWeightsForOccupancyEstimator", 1, "Use or not the delta-time weights for the occupancy estimator"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confNumberOfOrbitsPerTF{"NumberOfOrbitsPerTF", -1, "Number of orbits per Time Frame. Take from CCDB if -1"}; // o2-linter: disable=name/configurable (temporary fix) + + // configurables for light-ion event selection (testing mode) + o2::framework::Configurable confLightIonsAlternativeBcMatching{"TestAlternativeBcMatching", 0, "0 - use standard matching, 1 - try alternative for light ions"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confLightIonsModifyTimeVetoOnNearbyColl{"TestModifyTimeVetoOnNearbyColl", 0, "0 - use standard time veto, 1 - modify time range"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confLightIonsVetoOnTRDinPast{"TestVetoOnTRDinPast", 0, "0 - use standard time veto, 1 - use veto on TRD in the past events"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confLightIonsNsigmaOnVzDiff{"TestVzDiffNsigma", 3.0, "+/- nSigma on vZ difference by FT0 and by tracks"}; // o2-linter: disable=name/configurable (temporary fix) + o2::framework::Configurable confLightIonsMarginVzDiff{"TestVzDiffMargin", 0.2, "margin for +/- nSigma on vZ difference by FT0 and by tracks"}; // o2-linter: disable=name/configurable (temporary fix) +}; + +// luminosity configurables +struct lumiConfigurables : o2::framework::ConfigurableGroup { + std::string prefix = "lumiOpts"; + o2::framework::Configurable amIneeded{"amIneeded", -1, "run BC selection or not. -1: automatic; 0: no; 1: yes"}; // o2-linter: disable=name/configurable (temporary fix) +}; + +class BcSelectionModule +{ + public: + BcSelectionModule() + { + // constructor + } + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::eventselection::bcselConfigurables bcselOpts; + + 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 + + template + void init(TContext& context, TBcSelOpts const& external_bcselopts, THistoRegistry& histos, TMetadataInfo const& metadataInfo) + { + // read in configurations from the task where it's used + bcselOpts = external_bcselopts; + + if (bcselOpts.amIneeded.value < 0) { + int bcSelNeeded = -1, evSelNeeded = -1; + bcselOpts.amIneeded.value = 0; + enableFlagIfTableRequired(context, "BcSels", bcSelNeeded); + enableFlagIfTableRequired(context, "EvSels", evSelNeeded); + if (bcSelNeeded == 1) { + bcselOpts.amIneeded.value = 1; + LOGF(info, "BC Selection / Autodetection for aod::BcSels: subscription present, will generate."); + } + if (evSelNeeded == 1 && bcSelNeeded == 0) { + bcselOpts.amIneeded.value = 1; + LOGF(info, "BC Selection / Autodetection for aod::BcSels: not there, but EvSel needed. Will generate."); + } + if (bcSelNeeded == 0 && evSelNeeded == 0) { + LOGF(info, "BC Selection / Autodetection for aod::BcSels: not required. Skipping generation."); + return; + } + } + strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag + + // add counter + histos.add("bcselection/hCounterInvalidBCTimestamp", "", o2::framework::kTH1D, {{1, 0., 1.}}); + } + + //__________________________________________________ + template + bool configure(TCCDB& ccdb, TBCs const& bcs) + { + if (bcs.size() == 0) + return false; + 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->template 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 = bcselOpts.confNumberOfOrbitsPerTF < 0 ? runInfo.orbitsPerTF * nBCsPerOrbit : bcselOpts.confNumberOfOrbitsPerTF * 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->template getForTimeStamp("EventSelection/EventSelectionParams", ts); + mITSROFrameStartBorderMargin = bcselOpts.confITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : bcselOpts.confITSROFrameStartBorderMargin; + mITSROFrameEndBorderMargin = bcselOpts.confITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : bcselOpts.confITSROFrameEndBorderMargin; + mTimeFrameStartBorderMargin = bcselOpts.confTimeFrameStartBorderMargin < 0 ? par->fTimeFrameStartBorderMargin : bcselOpts.confTimeFrameStartBorderMargin; + mTimeFrameEndBorderMargin = bcselOpts.confTimeFrameEndBorderMargin < 0 ? par->fTimeFrameEndBorderMargin : bcselOpts.confTimeFrameEndBorderMargin; + // ITSROF parameters + auto alppar = ccdb->template getForTimeStamp>("ITS/Config/AlpideParam", ts); + rofOffset = alppar->roFrameBiasInBC; + rofLength = alppar->roFrameLengthInBC; + // Trigger aliases + aliases = ccdb->template getForTimeStamp("EventSelection/TriggerAliases", ts); + + // prepare map of inactive chips + auto itsDeadMap = ccdb->template 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->template 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 = 1 << 31; // setting bit 31 to indicate that rct object is missing + mapRCT->insert(std::pair(sorTimestamp, dummyValue)); + } + } + return true; + } + + //__________________________________________________ + template + void processRun2(TCCDB const& ccdb, TBCs const& bcs, TTimestamps const& timestamps, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) + { + if (bcselOpts.amIneeded.value == 0) { + bcselbuffer.clear(); + return; + } + bcselbuffer.clear(); + for (const auto& bc : bcs) { + uint64_t timestamp = timestamps[bc.globalIndex()]; + par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", timestamp); + aliases = ccdb->template getForTimeStamp("EventSelection/TriggerAliases", 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(aod::evsel::kIsBBV0A) : 0; + selection |= timeV0C > par->fV0CBBlower && timeV0C < par->fV0CBBupper ? BIT(aod::evsel::kIsBBV0C) : 0; + selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(aod::evsel::kIsBBFDA) : 0; + selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(aod::evsel::kIsBBFDC) : 0; + selection |= !(timeV0A > par->fV0ABGlower && timeV0A < par->fV0ABGupper) ? BIT(aod::evsel::kNoBGV0A) : 0; + selection |= !(timeV0C > par->fV0CBGlower && timeV0C < par->fV0CBGupper) ? BIT(aod::evsel::kNoBGV0C) : 0; + selection |= !(timeFDA > par->fFDABGlower && timeFDA < par->fFDABGupper) ? BIT(aod::evsel::kNoBGFDA) : 0; + selection |= !(timeFDC > par->fFDCBGlower && timeFDC < par->fFDCBGupper) ? BIT(aod::evsel::kNoBGFDC) : 0; + selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(aod::evsel::kIsBBT0A) : 0; + selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(aod::evsel::kIsBBT0C) : 0; + selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(aod::evsel::kIsBBZNA) : 0; + selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(aod::evsel::kIsBBZNC) : 0; + selection |= !(std::fabs(timeZNA) > par->fZNABGlower && std::fabs(timeZNA) < par->fZNABGupper) ? BIT(aod::evsel::kNoBGZNA) : 0; + selection |= !(std::fabs(timeZNC) > par->fZNCBGlower && std::fabs(timeZNC) < par->fZNCBGupper) ? BIT(aod::evsel::kNoBGZNC) : 0; + selection |= (std::pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + std::pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(aod::evsel::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(aod::evsel::kNoV0MOnVsOfPileup) : 0; + selection |= (onSPD > par->fSPDOnVsOfA + par->fSPDOnVsOfB * ofSPD) ? BIT(aod::evsel::kNoSPDOnVsOfPileup) : 0; + selection |= (multRingV0C[3] > par->fV0CasymA + par->fV0CasymB * multV0C012) ? BIT(aod::evsel::kNoV0Casymmetry) : 0; + selection |= (TESTBIT(selection, aod::evsel::kIsBBV0A) || TESTBIT(selection, aod::evsel::kIsBBV0C) || ofSPD) ? BIT(aod::evsel::kIsINT1) : 0; + selection |= (bc.has_ft0() ? TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitVertex) : 0) ? BIT(aod::evsel::kIsTriggerTVX) : 0; + + // copy remaining selection decisions from eventCuts + uint32_t eventCuts = bc.eventCuts(); + selection |= (eventCuts & 1 << aod::kTimeRangeCut) ? BIT(aod::evsel::kIsGoodTimeRange) : 0; + selection |= (eventCuts & 1 << aod::kIncompleteDAQ) ? BIT(aod::evsel::kNoIncompleteDAQ) : 0; + selection |= !(eventCuts & 1 << aod::kIsTPCLaserWarmUp) ? BIT(aod::evsel::kNoTPCLaserWarmUp) : 0; + selection |= !(eventCuts & 1 << aod::kIsTPCHVdip) ? BIT(aod::evsel::kNoTPCHVdip) : 0; + selection |= !(eventCuts & 1 << aod::kIsPileupFromSPD) ? BIT(aod::evsel::kNoPileupFromSPD) : 0; + selection |= !(eventCuts & 1 << aod::kIsV0PFPileup) ? BIT(aod::evsel::kNoV0PFPileup) : 0; + selection |= (eventCuts & 1 << aod::kConsistencySPDandTrackVertices) ? BIT(aod::evsel::kNoInconsistentVtx) : 0; + selection |= (eventCuts & 1 << aod::kPileupInMultBins) ? BIT(aod::evsel::kNoPileupInMultBins) : 0; + selection |= (eventCuts & 1 << aod::kPileUpMV) ? BIT(aod::evsel::kNoPileupMV) : 0; + selection |= (eventCuts & 1 << aod::kTPCPileUp) ? BIT(aod::evsel::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 FIXME - this is a bug, there's no hCounterTVX in this task + // if (TESTBIT(selection, aod::evsel::kIsTriggerTVX)) { + // histos.get(HIST("hCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); + // } + + uint32_t rct = 0; + + // initialize properties + o2::common::eventselection::bcselEntry entry; + entry.alias = alias; + entry.selection = selection; + entry.rct = rct; + entry.foundFT0Id = foundFT0; + entry.foundFV0Id = foundFV0; + entry.foundFDDId = foundFDD; + entry.foundZDCId = foundZDC; + bcselbuffer.push_back(entry); + + // Fill bc selection columns + bcsel(alias, selection, rct, foundFT0, foundFV0, foundFDD, foundZDC); + } // end bc loop + } // end processRun2 + + //__________________________________________________ + template + void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TTimestamps const& timestamps, TBcSelBuffer& bcselbuffer, TBcSelCursor& bcsel) + { + if (bcselOpts.amIneeded.value == 0) { + bcselbuffer.clear(); + return; + } + bcselbuffer.clear(); + if (!configure(ccdb, bcs)) + return; // don't do anything in case configuration reported not ok + + int run = bcs.iteratorAt(0).runNumber(); + // map from GlobalBC to BcId needed to find triggerBc + std::map mapGlobalBCtoBcId; + for (const auto& bc : bcs) { + mapGlobalBCtoBcId[bc.globalBC()] = bc.globalIndex(); + } + + int triggerBcShift = bcselOpts.confTriggerBcShift; + if (bcselOpts.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) + uint64_t timestamp = timestamps[bc.globalIndex()]; + // 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(timestamp); + if (itrct != mapRCT->begin()) + itrct--; + rct = itrct->second; + LOGP(debug, "sor={} eor={} ts={} rct={}", sorTimestamp, eorTimestamp, 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(aod::evsel::kIsBBV0A) : 0; + selection |= timeFDA > par->fFDABBlower && timeFDA < par->fFDABBupper ? BIT(aod::evsel::kIsBBFDA) : 0; + selection |= timeFDC > par->fFDCBBlower && timeFDC < par->fFDCBBupper ? BIT(aod::evsel::kIsBBFDC) : 0; + selection |= !(timeV0ABG > par->fV0ABGlower && timeV0ABG < par->fV0ABGupper) ? BIT(aod::evsel::kNoBGV0A) : 0; + selection |= !(timeFDABG > par->fFDABGlower && timeFDABG < par->fFDABGupper) ? BIT(aod::evsel::kNoBGFDA) : 0; + selection |= !(timeFDCBG > par->fFDCBGlower && timeFDCBG < par->fFDCBGupper) ? BIT(aod::evsel::kNoBGFDC) : 0; + selection |= !(timeT0ABG > par->fT0ABGlower && timeT0ABG < par->fT0ABGupper) ? BIT(aod::evsel::kNoBGT0A) : 0; + selection |= !(timeT0CBG > par->fT0CBGlower && timeT0CBG < par->fT0CBGupper) ? BIT(aod::evsel::kNoBGT0C) : 0; + selection |= (timeT0A > par->fT0ABBlower && timeT0A < par->fT0ABBupper) ? BIT(aod::evsel::kIsBBT0A) : 0; + selection |= (timeT0C > par->fT0CBBlower && timeT0C < par->fT0CBBupper) ? BIT(aod::evsel::kIsBBT0C) : 0; + selection |= (timeZNA > par->fZNABBlower && timeZNA < par->fZNABBupper) ? BIT(aod::evsel::kIsBBZNA) : 0; + selection |= (timeZNC > par->fZNCBBlower && timeZNC < par->fZNCBBupper) ? BIT(aod::evsel::kIsBBZNC) : 0; + selection |= (std::pow((timeZNA + timeZNC - par->fZNSumMean) / par->fZNSumSigma, 2) + std::pow((timeZNA - timeZNC - par->fZNDifMean) / par->fZNDifSigma, 2) < 1) ? BIT(aod::evsel::kIsBBZAC) : 0; + selection |= !(std::fabs(timeZNA) > par->fZNABGlower && std::fabs(timeZNA) < par->fZNABGupper) ? BIT(aod::evsel::kNoBGZNA) : 0; + selection |= !(std::fabs(timeZNC) > par->fZNCBGlower && std::fabs(timeZNC) < par->fZNCBGupper) ? BIT(aod::evsel::kNoBGZNC) : 0; + selection |= (bc.has_ft0() ? (bc.ft0().triggerMask() & BIT(o2::ft0::Triggers::bitVertex)) > 0 : 0) ? BIT(aod::evsel::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(aod::evsel::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(aod::evsel::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] <= bcselOpts.maxInactiveChipsPerLayer->at(3) && vNextInactiveChips[3] <= bcselOpts.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] <= bcselOpts.maxInactiveChipsPerLayer->at(i) && vNextInactiveChips[i] <= bcselOpts.maxInactiveChipsPerLayer->at(i); + } + isGoodITSLayersAll = true; + for (int i = 0; i < o2::itsmft::ChipMappingITS::NLayers; i++) { + isGoodITSLayersAll &= vPrevInactiveChips[i] <= bcselOpts.maxInactiveChipsPerLayer->at(i) && vNextInactiveChips[i] <= bcselOpts.maxInactiveChipsPerLayer->at(i); + } + } + + selection |= isGoodITSLayer3 ? BIT(aod::evsel::kIsGoodITSLayer3) : 0; + selection |= isGoodITSLayer0123 ? BIT(aod::evsel::kIsGoodITSLayer0123) : 0; + selection |= isGoodITSLayersAll ? BIT(aod::evsel::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 (timestamp < sorTimestamp || timestamp > eorTimestamp) { + histos.template get(HIST("bcselection/hCounterInvalidBCTimestamp"))->Fill(srun, 1); + if (bcselOpts.confCheckRunDurationLimits.value) { + LOGF(warn, "Invalid BC timestamp: %d, run: %d, sor: %d, eor: %d", timestamp, run, sorTimestamp, eorTimestamp); + alias = 0u; + selection = 0u; + } + } + + // initialize properties + o2::common::eventselection::bcselEntry entry; + entry.alias = alias; + entry.selection = selection; + entry.rct = rct; + entry.foundFT0Id = foundFT0; + entry.foundFV0Id = foundFV0; + entry.foundFDDId = foundFDD; + entry.foundZDCId = foundZDC; + bcselbuffer.push_back(entry); + + // Fill bc selection columns + bcsel(alias, selection, rct, foundFT0, foundFV0, foundFDD, foundZDC); + } // end bc loop + } // end processRun3 +}; // end BcSelectionModule + +class EventSelectionModule +{ + public: + EventSelectionModule() + { + // constructor + } + + int run3min = 500000; + int lastRun = -1; // last run number (needed to access ccdb only if run!=lastRun) + std::bitset bcPatternB; // bc pattern of colliding bunches + std::vector bcsPattern; // pattern of colliding BCs + + 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 + + // temporary (?) parameterizations for light ion runs + int runLightIons = -1; + int runListLightIons[11] = {564356, 564359, 564373, 564374, 564387, 564400, 564414, 564430, 564445, 564468, 564472}; + std::vector diffVzParMean; // parameterization for mean of diff vZ by FT0 vs by tracks + std::vector diffVzParSigma; // parameterization for stddev of diff vZ by FT0 vs by tracks + + int32_t findClosest(int64_t globalBC, 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; + } + + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::eventselection::evselConfigurables evselOpts; + + template + void init(TContext& context, TEvSelOpts const& external_evselopts, THistoRegistry& histos, TMetadataInfo const& metadataInfo) + { + // read in configurations from the task where it's used + evselOpts = external_evselopts; + + if (evselOpts.amIneeded.value < 0) { + enableFlagIfTableRequired(context, "EvSels", evselOpts.amIneeded.value); + if (evselOpts.amIneeded.value == 0) { + LOGF(info, "Event Selection / Autodetecting for aod::EvSels: not required, won't generate."); + return; + } else { + LOGF(info, "Event Selection / Autodetecting for aod::EvSels: subscription present, will generate."); + } + } + + if (metadataInfo.isFullyDefined()) { // Check if the metadata is initialized (only if not forced from the workflow configuration) + if (evselOpts.isMC == -1) { + LOGF(info, "Autosetting the MC mode based on metadata (isMC? %i)", metadataInfo.isMC()); + if (metadataInfo.isMC()) { + evselOpts.isMC.value = 1; + } else { + evselOpts.isMC.value = 0; + } + } + } + strLPMProductionTag = metadataInfo.get("LPMProductionTag"); // to extract info from ccdb by the tag + + histos.add("eventselection/hColCounterAll", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("eventselection/hColCounterTVX", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("eventselection/hColCounterAcc", "", framework::kTH1D, {{1, 0., 1.}}); + } + + //__________________________________________________ + template + bool configure(TCCDB& ccdb, TTimestamps const& timestamps, TBCs const& bcs) + { + int run = bcs.iteratorAt(0).runNumber(); + // 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); + // first bc of the first orbit + bcSOR = runInfo.orbitSOR * nBCsPerOrbit; + // duration of TF in bcs + nBCsPerTF = evselOpts.confNumberOfOrbitsPerTF < 0 ? runInfo.orbitsPerTF * nBCsPerOrbit : evselOpts.confNumberOfOrbitsPerTF * nBCsPerOrbit; + // colliding bc pattern + int64_t ts = timestamps[0]; + + // getForTimeStamp replaced with getSpecific to set metadata to zero + // avoids crash related to specific run number + auto grplhcif = ccdb->template getSpecific("GLO/Config/GRPLHCIF", ts); + bcPatternB = grplhcif->getBunchFilling().getBCPattern(); + bcsPattern = grplhcif->getBunchFilling().getFilledBCs(); + + // extract ITS ROF parameters + auto alppar = ccdb->template getForTimeStamp>("ITS/Config/AlpideParam", ts); + rofOffset = alppar->roFrameBiasInBC; + rofLength = alppar->roFrameLengthInBC; + LOGP(debug, "ITS ROF Offset={} ITS ROF Length={}", rofOffset, rofLength); + if (evselOpts.confLightIonsAlternativeBcMatching) { + for (unsigned long i = 0; i < bcsPattern.size(); i++) + LOGP(info, "bcsPattern: i={} bc={}", i, bcsPattern.at(i)); + } + + // special treatment of light ion runs + if (lastRun >= 564356 && lastRun <= 564472) { + for (unsigned long i = 0; i < sizeof(runListLightIons) / sizeof(*runListLightIons); i++) { + if (runListLightIons[i] == lastRun) { + runLightIons = lastRun; + // extract parameterization for diff of vZ by FT0 vs by tracks + auto parMeans = ccdb->template getForTimeStamp>("Users/a/altsybee/diffVzCollVsFTOmeanPar", ts); + auto parSigmas = ccdb->template getForTimeStamp>("Users/a/altsybee/diffVzCollVsFTOsigmaPar", ts); + 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]); + break; + } + } + } + + } // if run != lastRun + return true; + } + + //__________________________________________________ + template + void processRun2(TCCDB const& ccdb, THistoRegistry& histos, TCollisions const& collisions, TTracklets const& tracklets, TSlicecache& cache, TTimestamps const& timestamps, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) + { + if (evselOpts.amIneeded.value == 0) { + return; // dummy process + } + for (const auto& col : collisions) { + auto bc = col.template bc_as>(); + uint64_t timestamp = timestamps[bc.globalIndex()]; + EventSelectionParams* par = ccdb->template getForTimeStamp("EventSelection/EventSelectionParams", timestamp); + bool* applySelection = par->getSelection(evselOpts.muonSelection); + if (evselOpts.isMC == 1) { + applySelection[aod::evsel::kIsBBZAC] = 0; + applySelection[aod::evsel::kNoV0MOnVsOfPileup] = 0; + applySelection[aod::evsel::kNoSPDOnVsOfPileup] = 0; + applySelection[aod::evsel::kNoV0Casymmetry] = 0; + applySelection[aod::evsel::kNoV0PFPileup] = 0; + } + + int32_t foundBC = bc.globalIndex(); + int32_t foundFT0 = bcselbuffer[foundBC].foundFT0Id; + int32_t foundFV0 = bcselbuffer[foundBC].foundFV0Id; + int32_t foundFDD = bcselbuffer[foundBC].foundFDDId; + int32_t foundZDC = bcselbuffer[foundBC].foundZDCId; + + // copy alias decisions from bcsel table + uint32_t alias = bcselbuffer[foundBC].alias; + + // copy selection decisions from bcsel table + uint64_t selection = bcselbuffer[foundBC].selection; + + // copy rct flags from bcsel table + uint32_t rct = bcselbuffer[foundBC].rct; + + // 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(aod::evsel::kNoSPDClsVsTklBG) : 0; + selection |= !(nTkl < 6 && multV0C012 > par->fV0C012vsTklA + nTkl * par->fV0C012vsTklB) ? BIT(aod::evsel::kNoV0C012vsTklBG) : 0; // o2-linter: disable=magic-number (nTkl dependent parameterization) + + // apply int7-like selections + bool sel7 = 1; + for (int i = 0; i < aod::evsel::kNsel; i++) { + sel7 = sel7 && (applySelection[i] ? TESTBIT(selection, i) : 1); + } + + // TODO introduce array of sel[0]... sel[8] or similar? + bool sel8 = bitcheck64(selection, aod::evsel::kIsBBT0A) && bitcheck64(selection, aod::evsel::kIsBBT0C); // TODO apply other cuts for sel8 + bool sel1 = bitcheck64(selection, aod::evsel::kIsINT1); + sel1 = sel1 && bitcheck64(selection, aod::evsel::kNoBGV0A); + sel1 = sel1 && bitcheck64(selection, aod::evsel::kNoBGV0C); + sel1 = sel1 && bitcheck64(selection, aod::evsel::kNoTPCLaserWarmUp); + sel1 = sel1 && bitcheck64(selection, aod::evsel::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 (evselOpts.isMC == 1 || (!isINT1period && bitcheck(alias, kINT7)) || (isINT1period && bitcheck(alias, kINT1))) { + histos.template get(HIST("eventselection/hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); + if ((!isINT1period && sel7) || (isINT1period && sel1)) { + histos.template get(HIST("eventselection/hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); + } + } + + evsel(alias, selection, rct, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, 0, 0); + } + } // end processRun2 + + //__________________________________________________ + template + void processRun3(TCCDB const& ccdb, THistoRegistry& histos, TBCs const& bcs, TCollisions const& cols, TPVTracks const& pvTracks, TFT0s const& ft0s, TSlicecache& cache, TTimestamps const& timestamps, TBcSelBuffer const& bcselbuffer, TEvselCursor& evsel) + { + if (evselOpts.amIneeded.value == 0) { + return; // dummy process + } + if (!configure(ccdb, timestamps, bcs)) + return; // don't do anything in case configuration reported not ok + + int run = bcs.iteratorAt(0).runNumber(); + // create maps from globalBC to bc index for TVX-fired bcs + // to be used for closest TVX searches + std::map mapGlobalBcWithTVX; + std::map mapGlobalBcWithOrInFT0; + 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.has_ft0()) { + mapGlobalBcWithOrInFT0[globalBC] = bc.globalIndex(); + } + + auto selection = bcselbuffer[bc.globalIndex()].selection; + if (bitcheck64(selection, aod::evsel::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.template bc_as>(); + int32_t foundBC = bc.globalIndex(); + int32_t foundFT0 = bcselbuffer[bc.globalIndex()].foundFT0Id; + int32_t foundFV0 = bcselbuffer[bc.globalIndex()].foundFV0Id; + int32_t foundFDD = bcselbuffer[bc.globalIndex()].foundFDDId; + int32_t foundZDC = bcselbuffer[bc.globalIndex()].foundZDCId; + uint32_t rct = 0; + evsel(bcselbuffer[bc.globalIndex()].alias, bcselbuffer[bc.globalIndex()].selection, rct, kFALSE, kFALSE, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, -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 = evselOpts.confTimeIntervalForOccupancyCalculationMin * 1e3; // ns + const float timeWinOccupancyCalcMaxNS = evselOpts.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 vCollisionsPileupPerColl(cols.size(), 0); // counter of pileup in the same bc as a given collision + std::vector vBCinPatternPerColl(cols.size(), 0); // found nominal BCs for collisions + 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.template 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; + + // alternative collision-BC matching (currently: test mode, the aim is to improve pileup rejection) + if (evselOpts.confLightIonsAlternativeBcMatching) { + foundGlobalBC = globalBC; + // find closest nominal bc in pattern + for (unsigned long i = 0; i < bcsPattern.size(); i++) { + int32_t localBC = globalBC % nBCsPerOrbit; + int32_t bcFromPattern = bcsPattern.at(i); + int64_t bcDiff = bcFromPattern - localBC; + if (std::abs(bcDiff) <= 20) { + foundGlobalBC = (globalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPattern; + break; // the bc in pattern is found + } + } + + // matched with TOF --> precise time, match to TVX, but keep the nominal foundGlobalBC from pattern + if (vIsVertexTOFmatched[colIndex]) { + std::map::iterator it = mapGlobalBcWithTVX.find(foundGlobalBC); + if (it != mapGlobalBcWithTVX.end()) { + foundBCindex = it->second; // TVX at foundGlobalBC is found + } else { // check if TVX is in nearby bcs + it = mapGlobalBcWithTVX.find(foundGlobalBC + 1); // next bc + if (it != mapGlobalBcWithTVX.end()) { + // foundGlobalBC += 1; + foundBCindex = it->second; + } else { + it = mapGlobalBcWithTVX.find(foundGlobalBC - 1); // previous bc + if (it != mapGlobalBcWithTVX.end()) { + // foundGlobalBC -= 1; + foundBCindex = it->second; + } else { + foundBCindex = bc.globalIndex(); // keep original BC index + } + } + } + } // 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) { + foundGlobalBC = bestGlobalBC; + // find closest nominal bc in pattern + for (unsigned long j = 0; j < bcsPattern.size(); j++) { + int32_t bcFromPatternBest = bcsPattern.at(j); + int64_t bcDiff = bcFromPatternBest - (bestGlobalBC % nBCsPerOrbit); + if (std::abs(bcDiff) <= 20) { + foundGlobalBC = (bestGlobalBC / nBCsPerOrbit) * nBCsPerOrbit + bcFromPatternBest; + break; // the bc in pattern is found + } + } + foundBCindex = mapGlobalBcWithTVX[bestGlobalBC]; + } else { // failed to find a proper TVX with small vZ difference + foundBCindex = bc.globalIndex(); // keep original BC index + } + } // end of non-TOF matched vertices + // sanitity check: if BC was not found + if (foundBCindex == -1) { + foundBCindex = bc.globalIndex(); + } + vBCinPatternPerColl[colIndex] = foundGlobalBC; + // end of alternative coll-BC matching (test) + } else if (nPvTracksTOF > 0) { // "standard matching": + // 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, evselOpts.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); + } + // alternative matching: looking for collisions with the same nominal BC + if (evselOpts.confLightIonsAlternativeBcMatching) { + for (unsigned long iCol = 0; iCol < vBCinPatternPerColl.size(); iCol++) { + int64_t foundNominalBC = vBCinPatternPerColl[iCol]; + for (unsigned long jCol = 0; jCol < vBCinPatternPerColl.size(); jCol++) { + int64_t foundNominalBC2 = vBCinPatternPerColl[jCol]; + if (foundNominalBC2 == foundNominalBC) { + vCollisionsPileupPerColl[iCol]++; + } + } + } + } else { // continue standard matching: 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.template 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 bcselEntr = bcselbuffer[vFoundBCindex[colIndex]]; + if (bcselEntr.foundFT0Id > -1) { + // required: explicit ft0s table + auto foundFT0 = ft0s.rawIteratorAt(bcselEntr.foundFT0Id); + vAmpFT0CperColl[colIndex] = 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] > evselOpts.confFT0CamplCutVetoOnCollInROF) + nCollsInRofWithFT0CAboveVetoStandard++; + if (std::fabs(vCollVz[thisColIndex] - vZ) < evselOpts.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 < evselOpts.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 (evselOpts.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 (!evselOpts.confLightIonsModifyTimeVetoOnNearbyColl) { + if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollNarrow) + nITS567tracksForVetoNarrow += vTracksITS567perColl[thisColIndex]; + if (std::fabs(dt) < evselOpts.confTimeRangeVetoOnCollStandard) + nITS567tracksForVetoStrict += vTracksITS567perColl[thisColIndex]; + } else { // special veto ranges (tests for light ion runs) + if (dt > -4.5 && dt < 2.5) // avoid TOF- and TRD-related structures, with 0.5 us margin + nITS567tracksForVetoNarrow += vTracksITS567perColl[thisColIndex]; + + if (!evselOpts.confLightIonsVetoOnTRDinPast) { + if (dt > -25.5 && dt < 2.5) // test effect from TRD triggers in the past + nITS567tracksForVetoStrict += vTracksITS567perColl[thisColIndex]; + } else { + // counting TRD-matched vertices in a long time interval in the past + if (dt > -25.5 && dt < 2.5) + nITS567tracksForVetoStrict += vIsVertexTRDmatched[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] > evselOpts.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] > evselOpts.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); + if (!evselOpts.confLightIonsVetoOnTRDinPast) + vNoCollInTimeRangeStrict[colIndex] = (nITS567tracksForVetoStrict == 0); + else + vNoCollInTimeRangeStrict[colIndex] = (nITS567tracksForVetoStrict == 0 && nITS567tracksForVetoNarrow == 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); + auto bcselEntry = bcselbuffer[foundBC]; + int32_t foundFT0 = bcselEntry.foundFT0Id; + int32_t foundFV0 = bcselEntry.foundFV0Id; + int32_t foundFDD = bcselEntry.foundFDDId; + int32_t foundZDC = bcselEntry.foundZDCId; + + // compare zVtx from FT0 and from PV + bool isGoodZvtxFT0vsPV = 0; + if (bcselEntry.foundFT0Id > -1) { + auto foundFT0 = ft0s.rawIteratorAt(bcselEntry.foundFT0Id); + float diffVz = foundFT0.posZ() - col.posZ(); + if (runLightIons == -1) + isGoodZvtxFT0vsPV = std::fabs(diffVz) < evselOpts.maxDiffZvtxFT0vsPV; + else { // special treatment of light ion runs + float multT0A = bc.ft0().sumAmpA(); + float multT0C = bc.ft0().sumAmpC(); + float T0M = multT0A + multT0C; + // calc mean at this T0 ampl. + float x = (T0M < 50 ? 50 : T0M); + double diffMean = diffVzParMean[0] + diffVzParMean[1] * pow(x, diffVzParMean[2]) + diffVzParMean[3] * pow(x, diffVzParMean[4]); + // calc sigma at this T0 ampl. + x = (T0M < 20 ? 20 : (T0M > 1.2e4 ? 1.2e4 : T0M)); + double diffSigma = diffVzParSigma[0] + diffVzParSigma[1] * pow(x, diffVzParSigma[2]) + diffVzParSigma[3] * pow(x, diffVzParSigma[4]); + float nSigma = evselOpts.confLightIonsNsigmaOnVzDiff; + float margin = evselOpts.confLightIonsMarginVzDiff; + isGoodZvtxFT0vsPV = (diffVz > diffMean - nSigma * diffSigma - margin && diffVz < diffMean + nSigma * diffSigma + margin); + } + } + + // copy alias decisions from bcsel table + uint32_t alias = bcselEntry.alias; + + // copy selection decisions from bcsel table + uint64_t selection = bcselbuffer[bc.globalIndex()].selection; + if (evselOpts.confLightIonsAlternativeBcMatching) + selection |= vCollisionsPileupPerColl[colIndex] <= 1 ? BIT(aod::evsel::kNoSameBunchPileup) : 0; + else + selection |= vCollisionsPerBc[foundBC] <= 1 ? BIT(aod::evsel::kNoSameBunchPileup) : 0; + selection |= vIsVertexITSTPC[colIndex] ? BIT(aod::evsel::kIsVertexITSTPC) : 0; + selection |= vIsVertexTOFmatched[colIndex] ? BIT(aod::evsel::kIsVertexTOFmatched) : 0; + selection |= vIsVertexTRDmatched[colIndex] ? BIT(aod::evsel::kIsVertexTRDmatched) : 0; + selection |= isGoodZvtxFT0vsPV ? BIT(aod::evsel::kIsGoodZvtxFT0vsPV) : 0; + + // selection bits based on occupancy time pattern + selection |= vNoCollInTimeRangeNarrow[colIndex] ? BIT(aod::evsel::kNoCollInTimeRangeNarrow) : 0; + selection |= vNoCollInTimeRangeStrict[colIndex] ? BIT(aod::evsel::kNoCollInTimeRangeStrict) : 0; + selection |= vNoHighMultCollInTimeRange[colIndex] ? BIT(aod::evsel::kNoCollInTimeRangeStandard) : 0; + + // selection bits based on ITS in-ROF occupancy + selection |= vNoCollInSameRofStrict[colIndex] ? BIT(aod::evsel::kNoCollInRofStrict) : 0; + selection |= (vNoCollInSameRofStandard[colIndex] && vNoCollInSameRofWithCloseVz[colIndex]) ? BIT(aod::evsel::kNoCollInRofStandard) : 0; + selection |= vNoHighMultCollInPrevRof[colIndex] ? BIT(aod::evsel::kNoHighMultCollInPrevRof) : 0; + + // copy rct flags from bcsel table + uint32_t rct = bcselEntry.rct; + + // 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 = bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX) && bitcheck64(bcselEntry.selection, aod::evsel::kNoTimeFrameBorder) && bitcheck64(bcselEntry.selection, aod::evsel::kNoITSROFrameBorder); + + // fill counters + histos.template get(HIST("eventselection/hColCounterAll"))->Fill(Form("%d", bc.runNumber()), 1); + if (bitcheck64(bcselEntry.selection, aod::evsel::kIsTriggerTVX)) { + histos.template get(HIST("eventselection/hColCounterTVX"))->Fill(Form("%d", bc.runNumber()), 1); + } + if (sel8) { + histos.template get(HIST("eventselection/hColCounterAcc"))->Fill(Form("%d", bc.runNumber()), 1); + } + + evsel(alias, selection, rct, sel7, sel8, foundBC, foundFT0, foundFV0, foundFDD, foundZDC, + vNumTracksITS567inFullTimeWin[colIndex], vSumAmpFT0CinFullTimeWin[colIndex]); + } + } // end processRun3 +}; // end EventSelectionModule + +class LumiModule +{ + public: + LumiModule() + { + // constructor + } + + 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; + + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::eventselection::lumiConfigurables lumiOpts; + + template + void init(TContext& context, TLumiOpts const& external_lumiopts, THistoRegistry& histos) + { + lumiOpts = external_lumiopts; + + if (lumiOpts.amIneeded.value < 0) { + int bcSelNeeded = -1, evSelNeeded = -1; + lumiOpts.amIneeded.value = 0; + enableFlagIfTableRequired(context, "BcSels", bcSelNeeded); + enableFlagIfTableRequired(context, "EvSels", evSelNeeded); + if (bcSelNeeded == 1) { + lumiOpts.amIneeded.value = 1; + LOGF(info, "Luminosity / Autodetection for aod::BcSels: subscription present, will generate."); + } + if (evSelNeeded == 1 && bcSelNeeded == 0) { + lumiOpts.amIneeded.value = 1; + LOGF(info, "Luminosity / Autodetection for aod::BcSels: not there, but EvSel needed. Will generate."); + } + if (bcSelNeeded == 0 && evSelNeeded == 0) { + LOGF(info, "Luminosity / Autodetection for aod::BcSels: not required. Skipping generation."); + return; + } + } + + histos.add("luminosity/hCounterTVX", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterTCE", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZEM", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZNC", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterTVXafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterTCEafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZEMafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hCounterZNCafterBCcuts", "", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTVX", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTCE", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZEM", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZNC", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTVXafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiTCEafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZEMafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + histos.add("luminosity/hLumiZNCafterBCcuts", ";;Luminosity, 1/#mub", framework::kTH1D, {{1, 0., 1.}}); + + const int nLists = 6; + TString rctListNames[] = {"CBT", "CBT_hadronPID", "CBT_electronPID", "CBT_calo", "CBT_muon", "CBT_muon_glo"}; + histos.add("luminosity/hLumiTVXafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); + histos.add("luminosity/hLumiTCEafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); + histos.add("luminosity/hLumiZEMafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::kTH2D, {{1, 0., 1.}, {4 * nLists, -0.5, 4. * nLists - 0.5}}); + histos.add("luminosity/hLumiZNCafterBCcutsRCT", ";;Luminosity, 1/#mub", framework::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.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 1, rctListName.Data()); + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 2, (rctListName + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 3, (rctListName + "_zdc").Data()); + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->GetYaxis()->SetBinLabel(4 * i + 4, (rctListName + "_zdc" + "_fullacc").Data()); + } + } + + template + bool configure(TCCDB& ccdb, TTimestamps const& timestamps, TBCs const& bcs) + { + if (bcs.size() == 0) + return false; + int run = bcs.iteratorAt(0).runNumber(); + if (run < 500000) // o2-linter: disable=magic-number (skip for unanchored MCs) + return false; + if (run != lastRun && run >= 520259) { // o2-linter: disable=magic-number (scalers available for runs above 520120) + lastRun = run; + int64_t ts = timestamps[0]; + + // getting GRP LHCIF object to extract colliding system, energy and colliding bc pattern + auto grplhcif = ccdb->template 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(); + LOGP(info, "beamZ1={} beamZ2={} sqrts={}", beamZ1, beamZ2, sqrts); + // 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 == 8 && beamZ2 == 1) { + csTVX = 0.3874e6; // eff(TVX) = 0.807 (based on LHC25e6f); sigma(INEL)=0.48b; arxiv:2507.05853 + } else if (beamZ1 == 8 && beamZ2 == 8) { + csTVX = 1.2050e6; // eff(TVX) = 0.886 (based on LHC25e6b); sigma(INEL)=1.36b; arxiv:2507.05853 + } else if (beamZ1 == 10 && beamZ2 == 10) { + csTVX = 1.5411e6; // eff(TVX) = 0.896 (based on LHC25e6g); sigma(INEL)=1.72b; arxiv:2507.05853 + } else 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->template 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->template 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 + return true; // carry on, please + } + + //__________________________________________________ + template + void process(TCCDB& ccdb, THistoRegistry& histos, TBCs const& bcs, TTimestamps const& timestamps, TBcSelBuffer const& bcselBuffer) + { + if (lumiOpts.amIneeded.value == 0) { + return; + } + + if (!configure(ccdb, timestamps, bcs)) + return; // don't do anything in case configuration reported not ok + + int run = bcs.iteratorAt(0).runNumber(); + const char* srun = Form("%d", run); + + // processing loop + for (const auto& bc : bcs) { + auto selection = bcselBuffer[bc.globalIndex()].selection; + if (bcPatternB[bc.globalBC() % nBCsPerOrbit] == 0) // skip non-colliding bcs + continue; + + bool noBorder = TESTBIT(selection, aod::evsel::kNoTimeFrameBorder) && TESTBIT(selection, aod::evsel::kNoITSROFrameBorder); + bool isTriggerTVX = TESTBIT(selection, aod::evsel::kIsTriggerTVX); + bool isTriggerTCE = bc.has_ft0() ? (TESTBIT(selection, aod::evsel::kIsTriggerTVX) && TESTBIT(bc.ft0().triggerMask(), o2::ft0::Triggers::bitCen)) : 0; + bool isTriggerZNA = TESTBIT(selection, aod::evsel::kIsBBZNA); + bool isTriggerZNC = TESTBIT(selection, aod::evsel::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; + + auto rct = bcselBuffer[bc.globalIndex()].rct; + + if (isTriggerTVX) { + histos.template get(HIST("luminosity/hCounterTVX"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTVX"))->Fill(srun, lumiTVX); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterTVXafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTVXafterBCcuts"))->Fill(srun, lumiTVX); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiTVXafterBCcutsRCT"))->Fill(srun, i, lumiTVX); + } + } + } + + if (isTriggerTCE) { + histos.template get(HIST("luminosity/hCounterTCE"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTCE"))->Fill(srun, lumiTCE); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterTCEafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiTCEafterBCcuts"))->Fill(srun, lumiTCE); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiTCEafterBCcutsRCT"))->Fill(srun, i, lumiTCE); + } + } + } + + if (isTriggerZEM) { + histos.template get(HIST("luminosity/hCounterZEM"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZEM"))->Fill(srun, lumiZEM); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterZEMafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZEMafterBCcuts"))->Fill(srun, lumiZEM); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiZEMafterBCcutsRCT"))->Fill(srun, i, lumiZEM); + } + } + } + + if (isTriggerZNC) { + histos.template get(HIST("luminosity/hCounterZNC"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZNC"))->Fill(srun, lumiZNC); + if (noBorder) { + histos.template get(HIST("luminosity/hCounterZNCafterBCcuts"))->Fill(srun, 1); + histos.template get(HIST("luminosity/hLumiZNCafterBCcuts"))->Fill(srun, lumiZNC); + for (size_t i = 0; i < mRCTFlagsCheckers.size(); i++) { + if ((rct & mRCTFlagsCheckers[i].value()) == 0) + histos.template get(HIST("luminosity/hLumiZNCafterBCcutsRCT"))->Fill(srun, i, lumiZNC); + } + } + } + } // bcs + } // process +}; // end LumiModule + +} // namespace eventselection +} // namespace common +} // namespace o2 + +#endif // COMMON_TOOLS_EVENTSELECTIONTOOLS_H_ diff --git a/Common/Tools/MultModule.h b/Common/Tools/MultModule.h new file mode 100644 index 00000000000..2250717a601 --- /dev/null +++ b/Common/Tools/MultModule.h @@ -0,0 +1,1413 @@ +// 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 MultModule.h +/// \brief combined multiplicity + centrality module with autodetect features +/// \author ALICE + +#ifndef COMMON_TOOLS_MULTMODULE_H_ +#define COMMON_TOOLS_MULTMODULE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include "Framework/AnalysisDataModel.h" +#include "Framework/Configurable.h" +#include "Framework/HistogramSpec.h" +#include "TableHelper.h" +#include "Common/Core/TPCVDriftManager.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" +#include "TFormula.h" + +//__________________________________________ +// MultModule + +namespace o2 +{ +namespace common +{ +namespace multiplicity +{ + +// statics necessary for the configurables in this namespace +static constexpr int nParameters = 1; +static const std::vector tableNames{ + // multiplicity subcomponent + "FV0Mults", + "FV0AOuterMults", + "FT0Mults", + "FDDMults", + "ZDCMults", + "TrackletMults", + "TPCMults", + "PVMults", + "MultsExtra", + "MultSelections", + "FV0MultZeqs", + "FT0MultZeqs", + "FDDMultZeqs", + "PVMultZeqs", + "GlobalMultZeqs", + "MFTMultZeqs", + "MultMCExtras", + "Mult2MCExtras", + "MFTMults", + "MultsGlobal", + + // centrality subcomponent + "CentRun2V0Ms", + "CentRun2V0As", + "CentRun2SPDTrks", + "CentRun2SPDClss", + "CentRun2CL0s", + "CentRun2CL1s", + "CentFV0As", + "CentFT0Ms", + "CentFT0As", + "CentFT0Cs", + "CentFT0CVariant1s", + "CentFDDMs", + "CentNTPVs", + "CentNGlobals", + "CentMFTs", + "BCCentFT0Ms", + "BCCentFT0As", + "BCCentFT0Cs"}; + +static constexpr int nTablesConst = 38; + +static const std::vector parameterNames{"enable"}; +static const int defaultParameters[nTablesConst][nParameters]{ + {-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}}; + +// table index : match order above +enum tableIndex { kFV0Mults, // standard + kFV0AOuterMults, // standard + kFT0Mults, // standard + kFDDMults, // standard + kZDCMults, // standard + kTrackletMults, // Run 2 + kTPCMults, // standard + kPVMults, // standard + kMultsExtra, // standard + kMultSelections, // event selection + kFV0MultZeqs, // zeq calib, standard + kFT0MultZeqs, // zeq calib, standard + kFDDMultZeqs, // zeq calib, standard + kPVMultZeqs, // zeq calib, standard + kGlobalMultZeqs, // zeq calib, extra + kMFTMultZeqs, // zeq calib, extra + kMultMCExtras, // MC exclusive + kMult2MCExtras, // MC exclusive + kMFTMults, // requires MFT task + kMultsGlobal, // requires track selection task + + // centrality subcomponent + kCentRun2V0Ms, // Run 2 + kCentRun2V0As, // Run 2 + kCentRun2SPDTrks, // Run 2 + kCentRun2SPDClss, // Run 2 + kCentRun2CL0s, // Run 2 + kCentRun2CL1s, // Run 2 + kCentFV0As, // standard Run 3 + kCentFT0Ms, // standard Run 3 + kCentFT0As, // standard Run 3 + kCentFT0Cs, // standard Run 3 + kCentFT0CVariant1s, // standard Run 3 + kCentFDDMs, // standard Run 3 + kCentNTPVs, // standard Run 3 + kCentNGlobals, // requires track selection task + kCentMFTs, // requires MFT task + kBCCentFT0Ms, // bc centrality + kBCCentFT0As, // bc centrality + kBCCentFT0Cs, // bc centrality + kNTables }; + +struct products : o2::framework::ProducesGroup { + //__________________________________________________ + // multiplicity tables + o2::framework::Produces tableFV0; + o2::framework::Produces tableFV0AOuter; + o2::framework::Produces tableFT0; + o2::framework::Produces tableFDD; + o2::framework::Produces tableZDC; + o2::framework::Produces tableTracklet; + o2::framework::Produces tableTpc; + o2::framework::Produces tablePv; + o2::framework::Produces tableExtra; + o2::framework::Produces multSelections; + o2::framework::Produces tableFV0Zeqs; + o2::framework::Produces tableFT0Zeqs; + o2::framework::Produces tableFDDZeqs; + o2::framework::Produces tablePVZeqs; + o2::framework::Produces tableNGlobalZeqs; + o2::framework::Produces tableNMFTZeqs; + o2::framework::Produces tableExtraMc; + o2::framework::Produces tableExtraMult2MCExtras; + o2::framework::Produces mftMults; + o2::framework::Produces multsGlobal; + + //__________________________________________________ + // centrality tables (per collision / default) + o2::framework::Produces centRun2V0M; + o2::framework::Produces centRun2V0A; + o2::framework::Produces centRun2SPDTracklets; + o2::framework::Produces centRun2SPDClusters; + o2::framework::Produces centRun2CL0; + o2::framework::Produces centRun2CL1; + o2::framework::Produces centFV0A; + o2::framework::Produces centFT0M; + o2::framework::Produces centFT0A; + o2::framework::Produces centFT0C; + o2::framework::Produces centFT0CVariant1; + o2::framework::Produces centFDDM; + o2::framework::Produces centNTPV; + o2::framework::Produces centNGlobals; + o2::framework::Produces centMFTs; + o2::framework::Produces bcCentFT0A; + o2::framework::Produces bcCentFT0C; + o2::framework::Produces bcCentFT0M; + + //__________________________________________________ + // centrality tables per BC + // FIXME - future development +}; + +// for providing temporary buffer +// FIXME ideally cursors could be readable +// to avoid duplicate memory allocation but ok +struct multEntry { + float multFV0A = 0.0f; + float multFV0C = 0.0f; + float multFV0AOuter = 0.0f; + float multFT0A = 0.0f; + float multFT0C = 0.0f; + float multFDDA = 0.0f; + float multFDDC = 0.0f; + float multZNA = 0.0f; + float multZNC = 0.0f; + float multZEM1 = 0.0f; + float multZEM2 = 0.0f; + float multZPA = 0.0f; + float multZPC = 0.0f; + int multTracklets = 0; + + int multNContribs = 0; // PVMult 0.8 + int multNContribsEta1 = 0; // PVMult 1.0 + int multNContribsEtaHalf = 0; // PVMult 0.5 + int multTPC = 0; // all TPC (PV contrib unchecked) + int multHasTPC = 0; // extras + int multHasITS = 0; // extras + int multHasTOF = 0; // extras + int multHasTRD = 0; // extras + int multITSOnly = 0; // extras + int multTPCOnly = 0; // extras + int multITSTPC = 0; // extras + int multAllTracksTPCOnly = 0; // extras + int multAllTracksITSTPC = 0; // extras + + float multFV0AZeq = -999.0f; + float multFV0CZeq = -999.0f; + float multFT0AZeq = -999.0f; + float multFT0CZeq = -999.0f; + float multFDDAZeq = -999.0f; + float multFDDCZeq = -999.0f; + float multNContribsZeq = 0; + float multMFTTracksZeq = 0; + float multGlobalTracksZeq = 0; + + int multGlobalTracks = 0; // multsGlobal + int multNbrContribsEta05GlobalTrackWoDCA = 0; // multsGlobal + int multNbrContribsEta08GlobalTrackWoDCA = 0; // multsGlobal + int multNbrContribsEta10GlobalTrackWoDCA = 0; // multsGlobal + + int multMFTAllTracks = 0; // mft + int multMFTTracks = 0; // mft + + // For Run2 only + float posZ = -999.0f; + uint16_t spdClustersL0 = 0; + uint16_t spdClustersL1 = 0; +}; + +// strangenessBuilder: 1st-order configurables +struct standardConfigurables : o2::framework::ConfigurableGroup { + // self-configuration configurables + o2::framework::Configurable> enabledTables{"enabledTables", + {defaultParameters[0], nTablesConst, nParameters, tableNames, parameterNames}, + "Produce this table: -1 for autodetect; otherwise, 0/1 is false/true"}; + std::vector mEnabledTables; // Vector of enabled tables + + // Autoconfigure process functions + o2::framework::Configurable autoConfigureProcess{"autoConfigureProcess", false, "if true, will configure process function switches based on metadata"}; + + // do vertex-Z equalized or not + o2::framework::Configurable doVertexZeq{"doVertexZeq", 1, "if 1: do vertex Z eq mult table"}; + + // global track counter configurables + o2::framework::Configurable minPtGlobalTrack{"minPtGlobalTrack", 0.15, "min. pT for global tracks"}; + o2::framework::Configurable maxPtGlobalTrack{"maxPtGlobalTrack", 1e+10, "max. pT for global tracks"}; + o2::framework::Configurable minNclsITSGlobalTrack{"minNclsITSGlobalTrack", 5, "min. number of ITS clusters for global tracks"}; + o2::framework::Configurable minNclsITSibGlobalTrack{"minNclsITSibGlobalTrack", 1, "min. number of ITSib clusters for global tracks"}; + + // ccdb information + o2::framework::Configurable ccdbPathVtxZ{"ccdbPathVtxZ", "Centrality/Calibration", "The CCDB path for vertex-Z calibration"}; + o2::framework::Configurable ccdbPathCentrality{"ccdbPathCentrality", "Centrality/Estimators", "The CCDB path for centrality information"}; + o2::framework::Configurable reconstructionPass{"reconstructionPass", "", {"Apass to use when fetching the calibration tables. Empty (default) does not check for any pass. Use `metadata` to fetch it from the AO2D metadata. Otherwise it will override the metadata."}}; + + // centrality operation + o2::framework::Configurable generatorName{"generatorName", "", {"Specify if and only if this is MC. Typical: PYTHIA"}}; + o2::framework::Configurable embedINELgtZEROselection{"embedINELgtZEROselection", false, {"Option to do percentile 100.5 if not INELgtZERO"}}; +}; + +class MultModule +{ + public: + MultModule() + { + // constructor + mRunNumber = 0; + mRunNumberCentrality = 0; + lCalibLoaded = false; + lCalibObjects = nullptr; + hVtxZFV0A = nullptr; + hVtxZFT0A = nullptr; + hVtxZFT0C = nullptr; + hVtxZFDDA = nullptr; + hVtxZFDDC = nullptr; + hVtxZNTracks = nullptr; + hVtxZNMFTTracks = nullptr; + hVtxZNGlobalTracks = nullptr; + } + + // internal: calib related, vtx-z profiles + int mRunNumber; + int mRunNumberCentrality; + bool lCalibLoaded; + TList* lCalibObjects; + TProfile* hVtxZFV0A; + TProfile* hVtxZFT0A; + TProfile* hVtxZFT0C; + TProfile* hVtxZFDDA; + TProfile* hVtxZFDDC; + TProfile* hVtxZNTracks; + TProfile* hVtxZNMFTTracks; // non-legacy, added August/2025 + TProfile* hVtxZNGlobalTracks; // non-legacy, added August/2025 + + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::common::multiplicity::standardConfigurables internalOpts; + + //_________________________________________________ + // centrality-related objects + struct TagRun2V0MCalibration { + bool mCalibrationStored = false; + TFormula* mMCScale = nullptr; + float mMCScalePars[6] = {0.0}; + TH1* mhVtxAmpCorrV0A = nullptr; + TH1* mhVtxAmpCorrV0C = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2V0MInfo; + struct TagRun2V0ACalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorrV0A = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2V0AInfo; + struct TagRun2SPDTrackletsCalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorr = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2SPDTksInfo; + struct TagRun2SPDClustersCalibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorrCL0 = nullptr; + TH1* mhVtxAmpCorrCL1 = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2SPDClsInfo; + struct TagRun2CL0Calibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorr = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2CL0Info; + struct TagRun2CL1Calibration { + bool mCalibrationStored = false; + TH1* mhVtxAmpCorr = nullptr; + TH1* mhMultSelCalib = nullptr; + } Run2CL1Info; + struct CalibrationInfo { + std::string name = ""; + bool mCalibrationStored = false; + TH1* mhMultSelCalib = nullptr; + float mMCScalePars[6] = {0.0}; + TFormula* mMCScale = nullptr; + explicit CalibrationInfo(std::string name) + : name(name), + mCalibrationStored(false), + mhMultSelCalib(nullptr), + mMCScalePars{0.0}, + mMCScale(nullptr) + { + } + bool isSane(bool fatalize = false) + { + if (!mhMultSelCalib) { + return true; + } + for (int i = 1; i < mhMultSelCalib->GetNbinsX() + 1; i++) { + if (mhMultSelCalib->GetXaxis()->GetBinLowEdge(i) > mhMultSelCalib->GetXaxis()->GetBinUpEdge(i)) { + if (fatalize) { + LOG(fatal) << "Centrality calibration table " << name << " has bins with low edge > up edge"; + } + LOG(warning) << "Centrality calibration table " << name << " has bins with low edge > up edge"; + return false; + } + } + return true; + } + }; + + CalibrationInfo fv0aInfo = CalibrationInfo("FV0"); + CalibrationInfo ft0mInfo = CalibrationInfo("FT0"); + CalibrationInfo ft0aInfo = CalibrationInfo("FT0A"); + CalibrationInfo ft0cInfo = CalibrationInfo("FT0C"); + CalibrationInfo ft0cVariant1Info = CalibrationInfo("FT0Cvar1"); + CalibrationInfo fddmInfo = CalibrationInfo("FDD"); + CalibrationInfo ntpvInfo = CalibrationInfo("NTracksPV"); + CalibrationInfo nGlobalInfo = CalibrationInfo("NGlobal"); + CalibrationInfo mftInfo = CalibrationInfo("MFT"); + + template + void init(TMetadatainfo const& metadataInfo, TConfigurables& opts, TInitContext& context) + { + // read in configurations from the task where it's used + internalOpts = opts; + internalOpts.mEnabledTables.resize(nTablesConst, 0); + + LOGF(info, "Configuring tables to generate"); + auto& workflows = context.services().template get(); + + TString listOfRequestors[nTablesConst]; + for (int i = 0; i < nTablesConst; i++) { + int f = internalOpts.enabledTables->get(tableNames[i].c_str(), "enable"); + if (f == 1) { + internalOpts.mEnabledTables[i] = 1; + listOfRequestors[i] = "manual enabling"; + } + if (f == -1) { + // autodetect this table in other devices + for (o2::framework::DeviceSpec const& device : workflows.devices) { + // Step 1: check if this device subscribed to the V0data table + for (auto const& input : device.inputs) { + if (o2::framework::DataSpecUtils::partialMatch(input.matcher, o2::header::DataOrigin("AOD"))) { + auto&& [origin, description, version] = o2::framework::DataSpecUtils::asConcreteDataMatcher(input.matcher); + std::string tableNameWithVersion = tableNames[i]; + if (version > 0) { + tableNameWithVersion += Form("_%03d", version); + } + if (input.matcher.binding == tableNameWithVersion) { + LOGF(info, "Device %s has subscribed to %s (version %i)", device.name, tableNames[i], version); + listOfRequestors[i].Append(Form("%s ", device.name.c_str())); + internalOpts.mEnabledTables[i] = 1; + } + } + } + } + } + } + + // dependency checker + if (internalOpts.mEnabledTables[kCentFV0As] && !internalOpts.mEnabledTables[kFV0MultZeqs]) { + internalOpts.mEnabledTables[kFV0MultZeqs] = 1; + listOfRequestors[kFV0MultZeqs].Append(Form("%s ", "dependency check")); + } + if ((internalOpts.mEnabledTables[kCentFT0As] || internalOpts.mEnabledTables[kCentFT0Cs] || internalOpts.mEnabledTables[kCentFT0Ms] || internalOpts.mEnabledTables[kCentFT0CVariant1s]) && !internalOpts.mEnabledTables[kFT0MultZeqs]) { + internalOpts.mEnabledTables[kFT0MultZeqs] = 1; + listOfRequestors[kFT0MultZeqs].Append(Form("%s ", "dependency check")); + } + if (internalOpts.mEnabledTables[kCentFDDMs] && !internalOpts.mEnabledTables[kFDDMultZeqs]) { + internalOpts.mEnabledTables[kFDDMultZeqs] = 1; + listOfRequestors[kFDDMultZeqs].Append(Form("%s ", "dependency check")); + } + if (internalOpts.mEnabledTables[kCentMFTs] && !internalOpts.mEnabledTables[kMFTMults]) { + internalOpts.mEnabledTables[kMFTMults] = 1; + listOfRequestors[kMFTMults].Append(Form("%s ", "dependency check")); + } + if (internalOpts.mEnabledTables[kCentMFTs] && !internalOpts.mEnabledTables[kMFTMultZeqs]) { + internalOpts.mEnabledTables[kMFTMultZeqs] = 1; + listOfRequestors[kMFTMultZeqs].Append(Form("%s ", "dependency check")); + } + if (internalOpts.mEnabledTables[kCentNGlobals] && !internalOpts.mEnabledTables[kMultsGlobal]) { + internalOpts.mEnabledTables[kMultsGlobal] = 1; + listOfRequestors[kMultsGlobal].Append(Form("%s ", "dependency check")); + } + if (internalOpts.mEnabledTables[kCentNGlobals] && !internalOpts.mEnabledTables[kGlobalMultZeqs]) { + internalOpts.mEnabledTables[kGlobalMultZeqs] = 1; + listOfRequestors[kGlobalMultZeqs].Append(Form("%s ", "dependency check")); + } + if (internalOpts.embedINELgtZEROselection.value > 0 && !internalOpts.mEnabledTables[kPVMults]) { + internalOpts.mEnabledTables[kPVMults] = 1; + listOfRequestors[kPVMults].Append(Form("%s ", "dependency check")); + } + + // capture the need for PYTHIA calibration in Pb-Pb runs + if (metadataInfo.isMC() && mRunNumber >= 544013 && mRunNumber <= 545367) { + internalOpts.generatorName.value = "PYTHIA"; + } + + // capture the need for PYTHIA calibration in light ion runs automatically + if (metadataInfo.isMC() && mRunNumber >= 564250 && mRunNumber <= 564472) { + internalOpts.generatorName.value = "PYTHIA"; + } + + // list enabled tables + for (int i = 0; i < nTablesConst; i++) { + // printout to be improved in the future + if (internalOpts.mEnabledTables[i]) { + LOGF(info, " -~> Table enabled: %s, requested by %s", tableNames[i], listOfRequestors[i].Data()); + } + } + + mRunNumber = 0; + mRunNumberCentrality = 0; + lCalibLoaded = false; + hVtxZFV0A = nullptr; + hVtxZFT0A = nullptr; + hVtxZFT0C = nullptr; + hVtxZFDDA = nullptr; + hVtxZFDDC = nullptr; + hVtxZNTracks = nullptr; + hVtxZNMFTTracks = nullptr; + hVtxZNGlobalTracks = nullptr; + + opts = internalOpts; + } + + //__________________________________________________ + template + o2::common::multiplicity::multEntry collisionProcessRun2(TCollision const& collision, TTracks const& tracks, TBC const& bc, TOutputGroup& cursors) + { + // initialize properties + o2::common::multiplicity::multEntry mults; + + mults.posZ = collision.posZ(); + mults.spdClustersL0 = bc.spdClustersL0(); + mults.spdClustersL1 = bc.spdClustersL1(); + //_______________________________________________________________________ + // forward detector signals, raw + if (collision.has_fv0a()) { + for (const auto& amplitude : collision.fv0a().amplitude()) { + mults.multFV0A += amplitude; + } + } + if (collision.has_fv0c()) { + for (const auto& amplitude : collision.fv0c().amplitude()) { + mults.multFV0C += amplitude; + } + } + if (collision.has_ft0()) { + auto ft0 = collision.ft0(); + for (const auto& amplitude : ft0.amplitudeA()) { + mults.multFT0A += amplitude; + } + for (const auto& amplitude : ft0.amplitudeC()) { + mults.multFT0C += amplitude; + } + } + if (collision.has_zdc()) { + auto zdc = collision.zdc(); + mults.multZNA = zdc.energyCommonZNA(); + mults.multZNC = zdc.energyCommonZNC(); + } + + //_______________________________________________________________________ + // determine if barrel track loop is required, do it (once!) if so but save CPU if not + if (internalOpts.mEnabledTables[kPVMults] || internalOpts.mEnabledTables[kTPCMults] || internalOpts.mEnabledTables[kTrackletMults]) { + // Try to do something Similar to https://github.com/alisw/AliPhysics/blob/22862a945004f719f8e9664c0264db46e7186a48/OADB/AliPPVsMultUtils.cxx#L541C26-L541C37 + for (const auto& track : tracks) { + // check whether the track is a tracklet + if (track.trackType() == o2::aod::track::Run2Tracklet) { + if (internalOpts.mEnabledTables[kTrackletMults]) { + mults.multTracklets++; + } + if (internalOpts.mEnabledTables[kPVMults]) { + if (std::abs(track.eta()) < 1.0) { + mults.multNContribsEta1++; // pvmults + if (std::abs(track.eta()) < 0.8) { + mults.multNContribs++; // pvmults + if (std::abs(track.eta()) < 0.5) { + mults.multNContribsEtaHalf++; // pvmults + } + } + } + } + } + // check whether the track is a global ITS-TPC track + if (track.tpcNClsFindable() > 0) { + if (internalOpts.mEnabledTables[kTPCMults]) { + mults.multTPC++; + } + } + } + } + + // fill standard cursors if required + if (internalOpts.mEnabledTables[kFV0Mults]) { + cursors.tableFV0(mults.multFV0A, mults.multFV0C); + } + if (internalOpts.mEnabledTables[kFT0Mults]) { + cursors.tableFT0(mults.multFT0A, mults.multFT0C); + } + if (internalOpts.mEnabledTables[kFDDMults]) { + cursors.tableFDD(mults.multFDDA, mults.multFDDC); + } + if (internalOpts.mEnabledTables[kZDCMults]) { + cursors.tableZDC(mults.multZNA, mults.multZNC, 0.0f, 0.0f, 0.0f, 0.0f); + } + if (internalOpts.mEnabledTables[kTrackletMults]) { // Tracklets only Run2 + cursors.tableTracklet(mults.multTracklets); + } + if (internalOpts.mEnabledTables[kTPCMults]) { + cursors.tableTpc(mults.multTPC); + } + if (internalOpts.mEnabledTables[kPVMults]) { + cursors.tablePv(mults.multNContribs, mults.multNContribsEta1, mults.multNContribsEtaHalf); + } + + return mults; + } + + //__________________________________________________ + template + o2::common::multiplicity::multEntry collisionProcessRun3(TCCDB const& ccdb, TMetadataInfo const& metadataInfo, TCollision const& collision, TTracks const& tracks, TBC const& bc, TOutputGroup& cursors) + { + // initialize properties + o2::common::multiplicity::multEntry mults; + + //_______________________________________________________________________ + // preparatory steps + if (internalOpts.doVertexZeq > 0) { + if (bc.runNumber() != mRunNumber) { + mRunNumber = bc.runNumber(); // mark this run as at least tried + if (internalOpts.reconstructionPass.value == "") { + lCalibObjects = ccdb->template getForRun(internalOpts.ccdbPathVtxZ, mRunNumber); + } else if (internalOpts.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + lCalibObjects = ccdb->template getSpecificForRun(internalOpts.ccdbPathVtxZ, mRunNumber, metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = internalOpts.reconstructionPass.value; + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", internalOpts.reconstructionPass.value); + lCalibObjects = ccdb->template getSpecificForRun(internalOpts.ccdbPathVtxZ, mRunNumber, metadata); + } + + if (lCalibObjects) { + hVtxZFV0A = static_cast(lCalibObjects->FindObject("hVtxZFV0A")); + hVtxZFT0A = static_cast(lCalibObjects->FindObject("hVtxZFT0A")); + hVtxZFT0C = static_cast(lCalibObjects->FindObject("hVtxZFT0C")); + hVtxZFDDA = static_cast(lCalibObjects->FindObject("hVtxZFDDA")); + hVtxZFDDC = static_cast(lCalibObjects->FindObject("hVtxZFDDC")); + hVtxZNTracks = static_cast(lCalibObjects->FindObject("hVtxZNTracksPV")); + hVtxZNMFTTracks = static_cast(lCalibObjects->FindObject("hVtxZMFT")); + hVtxZNGlobalTracks = static_cast(lCalibObjects->FindObject("hVtxZNGlobals")); + lCalibLoaded = true; + // Capture error + if (!hVtxZFV0A || !hVtxZFT0A || !hVtxZFT0C || !hVtxZFDDA || !hVtxZFDDC || !hVtxZNTracks) { + LOGF(error, "Problem loading CCDB objects! Please check"); + lCalibLoaded = false; + } + if (!hVtxZNMFTTracks) { + LOGF(info, "MFT track counter: vertex-Z calibration not loaded, will run without."); + } + if (!hVtxZNGlobalTracks) { + LOGF(info, "Global track counter: vertex-Z calibration not loaded, will run without."); + } + } else { + LOGF(error, "Problem loading CCDB object! Please check"); + lCalibLoaded = false; + } + } + } + + //_______________________________________________________________________ + // forward detector signals, raw + if (collision.has_foundFV0()) { + const auto& fv0 = collision.foundFV0(); + for (size_t ii = 0; ii < fv0.amplitude().size(); ii++) { + auto amplitude = fv0.amplitude()[ii]; + auto channel = fv0.channel()[ii]; + mults.multFV0A += amplitude; + if (channel > 7) { + mults.multFV0AOuter += amplitude; + } + } + } else { + mults.multFV0A = -999.f; + mults.multFV0AOuter = -999.f; + } + if (collision.has_foundFT0()) { + const auto& ft0 = collision.foundFT0(); + for (const auto& amplitude : ft0.amplitudeA()) { + mults.multFT0A += amplitude; + } + for (const auto& amplitude : ft0.amplitudeC()) { + mults.multFT0C += amplitude; + } + } else { + mults.multFT0A = -999.f; + mults.multFT0C = -999.f; + } + if (collision.has_foundFDD()) { + const auto& fdd = collision.foundFDD(); + for (const auto& amplitude : fdd.chargeA()) { + mults.multFDDA += amplitude; + } + for (const auto& amplitude : fdd.chargeC()) { + mults.multFDDC += amplitude; + } + } else { + mults.multFDDA = -999.f; + mults.multFDDC = -999.f; + } + if (bc.has_zdc()) { + mults.multZNA = bc.zdc().amplitudeZNA(); + mults.multZNC = bc.zdc().amplitudeZNC(); + mults.multZEM1 = bc.zdc().amplitudeZEM1(); + mults.multZEM2 = bc.zdc().amplitudeZEM2(); + mults.multZPA = bc.zdc().amplitudeZPA(); + mults.multZPC = bc.zdc().amplitudeZPC(); + } else { + mults.multZNA = -999.f; + mults.multZNC = -999.f; + mults.multZEM1 = -999.f; + mults.multZEM2 = -999.f; + mults.multZPA = -999.f; + mults.multZPC = -999.f; + } + + // fill standard cursors if required + if (internalOpts.mEnabledTables[kTrackletMults]) { // Tracklets (only Run2) nothing to do (to be removed!) + cursors.tableTracklet(0); + } + if (internalOpts.mEnabledTables[kFV0Mults]) { + cursors.tableFV0(mults.multFV0A, mults.multFV0C); + } + if (internalOpts.mEnabledTables[kFV0AOuterMults]) { + cursors.tableFV0AOuter(mults.multFV0AOuter); + } + if (internalOpts.mEnabledTables[kFT0Mults]) { + cursors.tableFT0(mults.multFT0A, mults.multFT0C); + } + if (internalOpts.mEnabledTables[kFDDMults]) { + cursors.tableFDD(mults.multFDDA, mults.multFDDC); + } + if (internalOpts.mEnabledTables[kZDCMults]) { + cursors.tableZDC(mults.multZNA, mults.multZNC, mults.multZEM1, mults.multZEM2, mults.multZPA, mults.multZPC); + } + + //_______________________________________________________________________ + // vertex-Z equalized signals + if (internalOpts.mEnabledTables[kFV0MultZeqs]) { + if (std::fabs(collision.posZ()) < 15.0f && lCalibLoaded) { + mults.multFV0AZeq = hVtxZFV0A->Interpolate(0.0) * mults.multFV0A / hVtxZFV0A->Interpolate(collision.posZ()); + } else { + mults.multFV0AZeq = 0.0f; + } + cursors.tableFV0Zeqs(mults.multFV0AZeq); + } + if (internalOpts.mEnabledTables[kFT0MultZeqs]) { + if (std::fabs(collision.posZ()) < 15.0f && lCalibLoaded) { + mults.multFT0AZeq = hVtxZFT0A->Interpolate(0.0) * mults.multFT0A / hVtxZFT0A->Interpolate(collision.posZ()); + mults.multFT0CZeq = hVtxZFT0C->Interpolate(0.0) * mults.multFT0C / hVtxZFT0C->Interpolate(collision.posZ()); + } else { + mults.multFT0AZeq = 0.0f; + mults.multFT0CZeq = 0.0f; + } + cursors.tableFT0Zeqs(mults.multFT0AZeq, mults.multFT0CZeq); + } + if (internalOpts.mEnabledTables[kFDDMultZeqs]) { + if (std::fabs(collision.posZ()) < 15.0f && lCalibLoaded) { + mults.multFDDAZeq = hVtxZFDDA->Interpolate(0.0) * mults.multFDDA / hVtxZFDDA->Interpolate(collision.posZ()); + mults.multFDDCZeq = hVtxZFDDC->Interpolate(0.0) * mults.multFDDC / hVtxZFDDC->Interpolate(collision.posZ()); + } else { + mults.multFDDAZeq = 0.0f; + mults.multFDDCZeq = 0.0f; + } + cursors.tableFDDZeqs(mults.multFDDAZeq, mults.multFDDCZeq); + } + + //_______________________________________________________________________ + // determine if barrel track loop is required, do it (once!) if so but save CPU if not + if (internalOpts.mEnabledTables[kTPCMults] || internalOpts.mEnabledTables[kPVMults] || internalOpts.mEnabledTables[kMultsExtra] || internalOpts.mEnabledTables[kPVMultZeqs] || internalOpts.mEnabledTables[kMultsGlobal] || internalOpts.mEnabledTables[kGlobalMultZeqs]) { + // single loop to calculate all + for (const auto& track : tracks) { + if (track.hasTPC()) { + mults.multTPC++; + if (track.hasITS()) { + mults.multAllTracksITSTPC++; // multsextra + } else { + mults.multAllTracksTPCOnly++; // multsextra + } + } + // PV contributor checked explicitly + if (track.isPVContributor()) { + if (std::abs(track.eta()) < 1.0) { + mults.multNContribsEta1++; // pvmults + if (std::abs(track.eta()) < 0.8) { + mults.multNContribs++; // pvmults + if (std::abs(track.eta()) < 0.5) { + mults.multNContribsEtaHalf++; // pvmults + } + } + } + if (track.hasITS()) { + mults.multHasITS++; // multsextra + if (track.hasTPC()) + mults.multITSTPC++; // multsextra + if (!track.hasTPC() && !track.hasTOF() && !track.hasTRD()) { + mults.multITSOnly++; // multsextra + } + } + if (track.hasTPC()) { + mults.multHasTPC++; // multsextra + if (!track.hasITS() && !track.hasTOF() && !track.hasTRD()) { + mults.multTPCOnly++; // multsextra + } + } + if (track.hasTOF()) { + mults.multHasTOF++; // multsextra + } + if (track.hasTRD()) { + mults.multHasTRD++; // multsextra + } + } + + // global counters: do them only in case information is provided in tracks table + if constexpr (requires { track.isQualityTrack(); }) { + if (track.pt() < internalOpts.maxPtGlobalTrack.value && track.pt() > internalOpts.minPtGlobalTrack.value && std::fabs(track.eta()) < 1.0f && track.isPVContributor() && track.isQualityTrack()) { + if (track.itsNCls() < internalOpts.minNclsITSGlobalTrack || track.itsNClsInnerBarrel() < internalOpts.minNclsITSibGlobalTrack) { + continue; + } + mults.multNbrContribsEta10GlobalTrackWoDCA++; + + if (std::abs(track.eta()) < 0.8) { + mults.multNbrContribsEta08GlobalTrackWoDCA++; + } + if (std::abs(track.eta()) < 0.5) { + mults.multNbrContribsEta05GlobalTrackWoDCA++; + } + } + if (std::fabs(track.eta()) < 0.8 && track.tpcNClsFound() >= 80 && track.tpcNClsCrossedRows() >= 100) { + if (track.isGlobalTrack()) { + mults.multGlobalTracks++; + } + } + } // end constexpr requires track selection stuff + } + + cursors.multsGlobal(mults.multGlobalTracks, mults.multNbrContribsEta08GlobalTrackWoDCA, mults.multNbrContribsEta10GlobalTrackWoDCA, mults.multNbrContribsEta05GlobalTrackWoDCA); + + if (!hVtxZNGlobalTracks || std::fabs(collision.posZ()) > 15.0f) { + mults.multGlobalTracksZeq = mults.multGlobalTracks; // if no equalization available, don't do it + } else { + mults.multGlobalTracksZeq = hVtxZNGlobalTracks->Interpolate(0.0) * mults.multGlobalTracks / hVtxZNGlobalTracks->Interpolate(collision.posZ()); + } + + // provide vertex-Z equalized Nglobals (or non-equalized if missing or beyond range) + if (internalOpts.mEnabledTables[kGlobalMultZeqs]) { + cursors.tableNGlobalZeqs(mults.multGlobalTracksZeq); + } + } + + // fill track counters at this stage if requested + if (internalOpts.mEnabledTables[kTPCMults]) { + cursors.tableTpc(mults.multTPC); + } + if (internalOpts.mEnabledTables[kPVMults]) { + cursors.tablePv(mults.multNContribs, mults.multNContribsEta1, mults.multNContribsEtaHalf); + } + if (internalOpts.mEnabledTables[kMultsExtra]) { + cursors.tableExtra(collision.numContrib(), collision.chi2(), collision.collisionTimeRes(), + bc.runNumber(), collision.posZ(), collision.sel8(), + mults.multHasITS, mults.multHasTPC, mults.multHasTOF, mults.multHasTRD, + mults.multITSOnly, mults.multTPCOnly, mults.multITSTPC, + mults.multAllTracksTPCOnly, mults.multAllTracksITSTPC, + collision.trackOccupancyInTimeRange(), + collision.ft0cOccupancyInTimeRange(), + collision.flags()); + } + if (internalOpts.mEnabledTables[kPVMultZeqs]) { + if (std::fabs(collision.posZ()) < 15.0f && lCalibLoaded) { + mults.multNContribsZeq = hVtxZNTracks->Interpolate(0.0) * mults.multNContribs / hVtxZNTracks->Interpolate(collision.posZ()); + } else { + mults.multNContribsZeq = 0.0f; + } + cursors.tablePVZeqs(mults.multNContribsZeq); + } + + // return multiplicity object such that it is handled properly when computing centrality + return mults; + } + + //__________________________________________________ + template + void collisionProcessMonteCarlo(TMCCollision const& mccollision, TMCParticles const& mcparticles, TPDGService const& pdg, TOutputGroup& cursors) + { + int multFT0A = 0; + int multFV0A = 0; + int multFT0C = 0; + int multFDDA = 0; + int multFDDC = 0; + int multBarrelEta05 = 0; + int multBarrelEta08 = 0; + int multBarrelEta10 = 0; + for (auto const& mcPart : mcparticles) { + if (!mcPart.isPhysicalPrimary()) { + continue; + } + + auto charge = 0.; + auto* p = pdg->GetParticle(mcPart.pdgCode()); + if (p != nullptr) { + charge = p->Charge(); + } + if (std::abs(charge) < 1e-3) { + continue; // reject neutral particles in counters + } + + if (std::abs(mcPart.eta()) < 1.0) { + multBarrelEta10++; + if (std::abs(mcPart.eta()) < 0.8) { + multBarrelEta08++; + if (std::abs(mcPart.eta()) < 0.5) { + multBarrelEta05++; + } + } + } + if (-3.3 < mcPart.eta() && mcPart.eta() < -2.1) + multFT0C++; + if (3.5 < mcPart.eta() && mcPart.eta() < 4.9) + multFT0A++; + if (2.2 < mcPart.eta() && mcPart.eta() < 5.0) + multFV0A++; + if (-6.9 < mcPart.eta() && mcPart.eta() < -4.9) + multFDDC++; + if (4.7 < mcPart.eta() && mcPart.eta() < 6.3) + multFDDA++; + } + cursors.tableExtraMc(multFT0A, multFT0C, multFV0A, multFDDA, multFDDC, multBarrelEta05, multBarrelEta08, multBarrelEta10, mccollision.posZ()); + } + + //__________________________________________________ + template + void collisionProcessMFT(TCollision const& collision, TMFTTracks const& mfttracks, TBestCollisionsFwd const& retracks, TMultBuffer& mults, TOutputGroup& cursors) + { + int nAllTracks = 0; + int nTracks = 0; + + for (const auto& track : mfttracks) { + if (track.nClusters() >= 5) { // hardcoded for now + nAllTracks++; + } + } + + if (retracks.size() > 0) { + for (const auto& retrack : retracks) { + auto track = retrack.mfttrack(); + if (track.nClusters() < 5) { + continue; // min cluster requirement + } + if ((track.eta() > -2.0f) && (track.eta() < -3.9f)) { + continue; // too far to be of true interest + } + if (std::abs(retrack.bestDCAXY()) > 2.0f) { + continue; // does not point to PV properly + } + nTracks++; + } + } + cursors.mftMults(nAllTracks, nTracks); + mults[collision.globalIndex()].multMFTAllTracks = nAllTracks; + mults[collision.globalIndex()].multMFTTracks = nTracks; + + // vertex-Z equalized MFT + if (!hVtxZNMFTTracks || std::fabs(collision.posZ()) > 15.0f) { + mults[collision.globalIndex()].multMFTTracksZeq = mults[collision.globalIndex()].multMFTTracks; // if no equalization available, don't do it + } else { + mults[collision.globalIndex()].multMFTTracksZeq = hVtxZNMFTTracks->Interpolate(0.0) * mults[collision.globalIndex()].multMFTTracks / hVtxZNMFTTracks->Interpolate(collision.posZ()); + } + + // provide vertex-Z equalized Nglobals (or non-equalized if missing or beyond range) + if (internalOpts.mEnabledTables[kMFTMultZeqs]) { + cursors.tableNMFTZeqs(mults[collision.globalIndex()].multMFTTracksZeq); + } + } + + //__________________________________________________ + template + void ConfigureCentralityRun2(TCCDB& ccdb, TMetadata const& metadataInfo, TBC const& bc) + { + if (bc.runNumber() != mRunNumberCentrality) { + mRunNumberCentrality = bc.runNumber(); // mark that this run has been attempted already regardless of outcome + LOGF(info, "centrality loading procedure for timestamp=%llu, run number=%d", bc.timestamp(), bc.runNumber()); + TList* callst = nullptr; + // Check if the ccdb path is a root file + if (internalOpts.ccdbPathCentrality.value.find(".root") != std::string::npos) { + TFile f(internalOpts.ccdbPathCentrality.value.c_str(), "READ"); + f.GetObject(internalOpts.reconstructionPass.value.c_str(), callst); + if (!callst) { + f.ls(); + LOG(fatal) << "No calibration list " << internalOpts.reconstructionPass.value << " found."; + } + } else { + if (internalOpts.reconstructionPass.value == "") { + callst = ccdb->template getForRun(internalOpts.ccdbPathCentrality, bc.runNumber()); + } else if (internalOpts.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = internalOpts.reconstructionPass.value; + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", internalOpts.reconstructionPass.value); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } + } + + Run2V0MInfo.mCalibrationStored = false; + Run2V0AInfo.mCalibrationStored = false; + Run2SPDTksInfo.mCalibrationStored = false; + Run2SPDClsInfo.mCalibrationStored = false; + Run2CL0Info.mCalibrationStored = false; + Run2CL1Info.mCalibrationStored = false; + if (callst != nullptr) { + auto getccdb = [callst](const char* ccdbhname) { + TH1* h = reinterpret_cast(callst->FindObject(ccdbhname)); + return h; + }; + auto getformulaccdb = [callst](const char* ccdbhname) { + TFormula* f = reinterpret_cast(callst->FindObject(ccdbhname)); + return f; + }; + + if (internalOpts.mEnabledTables[kCentRun2V0Ms]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2V0MInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); + Run2V0MInfo.mhVtxAmpCorrV0C = getccdb("hVtx_fAmplitude_V0C_Normalized"); + Run2V0MInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0M"); + Run2V0MInfo.mMCScale = getformulaccdb(TString::Format("%s-V0M", internalOpts.generatorName->c_str()).Data()); + if ((Run2V0MInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0MInfo.mhVtxAmpCorrV0C != nullptr) && (Run2V0MInfo.mhMultSelCalib != nullptr)) { + if (internalOpts.generatorName->length() != 0) { + if (Run2V0MInfo.mMCScale != nullptr) { + for (int ixpar = 0; ixpar < 6; ++ixpar) { + Run2V0MInfo.mMCScalePars[ixpar] = Run2V0MInfo.mMCScale->GetParameter(ixpar); + } + } else { + // continue filling with non-valid values (105) + LOGF(info, "MC Scale information from V0M for run %d not available", bc.runNumber()); + } + } + Run2V0MInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from V0M for run %d corrupted, will fill V0M tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2V0As]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2V0AInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); + Run2V0AInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0A"); + if ((Run2V0AInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0AInfo.mhMultSelCalib != nullptr)) { + Run2V0AInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from V0A for run %d corrupted, will fill V0A tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2SPDTrks]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2SPDTksInfo.mhVtxAmpCorr = getccdb("hVtx_fnTracklets_Normalized"); + Run2SPDTksInfo.mhMultSelCalib = getccdb("hMultSelCalib_SPDTracklets"); + if ((Run2SPDTksInfo.mhVtxAmpCorr != nullptr) && (Run2SPDTksInfo.mhMultSelCalib != nullptr)) { + Run2SPDTksInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from SPD tracklets for run %d corrupted, will fill SPD tracklets tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2SPDClss]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2SPDClsInfo.mhVtxAmpCorrCL0 = getccdb("hVtx_fnSPDClusters0_Normalized"); + Run2SPDClsInfo.mhVtxAmpCorrCL1 = getccdb("hVtx_fnSPDClusters1_Normalized"); + Run2SPDClsInfo.mhMultSelCalib = getccdb("hMultSelCalib_SPDClusters"); + if ((Run2SPDClsInfo.mhVtxAmpCorrCL0 != nullptr) && (Run2SPDClsInfo.mhVtxAmpCorrCL1 != nullptr) && (Run2SPDClsInfo.mhMultSelCalib != nullptr)) { + Run2SPDClsInfo.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from SPD clusters for run %d corrupted, will fill SPD clusters tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2CL0s]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2CL0Info.mhVtxAmpCorr = getccdb("hVtx_fnSPDClusters0_Normalized"); + Run2CL0Info.mhMultSelCalib = getccdb("hMultSelCalib_CL0"); + if ((Run2CL0Info.mhVtxAmpCorr != nullptr) && (Run2CL0Info.mhMultSelCalib != nullptr)) { + Run2CL0Info.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from CL0 multiplicity for run %d corrupted, will fill CL0 multiplicity tables with dummy values", bc.runNumber()); + } + } + if (internalOpts.mEnabledTables[kCentRun2CL1s]) { + LOGF(debug, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + Run2CL1Info.mhVtxAmpCorr = getccdb("hVtx_fnSPDClusters1_Normalized"); + Run2CL1Info.mhMultSelCalib = getccdb("hMultSelCalib_CL1"); + if ((Run2CL1Info.mhVtxAmpCorr != nullptr) && (Run2CL1Info.mhMultSelCalib != nullptr)) { + Run2CL1Info.mCalibrationStored = true; + } else { + // continue filling with non-valid values (105) + LOGF(info, "Calibration information from CL1 multiplicity for run %d corrupted, will fill CL1 multiplicity tables with dummy values", bc.runNumber()); + } + } + } else { + LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); + } + } + } + + //__________________________________________________ + template + void ConfigureCentralityRun3(TCCDB& ccdb, TMetadata const& metadataInfo, TBC const& bc) + { + if (bc.runNumber() != mRunNumberCentrality) { + mRunNumberCentrality = bc.runNumber(); // mark that this run has been attempted already regardless of outcome + LOGF(info, "centrality loading procedure for timestamp=%llu, run number=%d", bc.timestamp(), bc.runNumber()); + TList* callst = nullptr; + // Check if the ccdb path is a root file + if (internalOpts.ccdbPathCentrality.value.find(".root") != std::string::npos) { + TFile f(internalOpts.ccdbPathCentrality.value.c_str(), "READ"); + f.GetObject(internalOpts.reconstructionPass.value.c_str(), callst); + if (!callst) { + f.ls(); + LOG(fatal) << "No calibration list " << internalOpts.reconstructionPass.value << " found."; + } + } else { + if (internalOpts.reconstructionPass.value == "") { + callst = ccdb->template getForRun(internalOpts.ccdbPathCentrality, bc.runNumber()); + } else if (internalOpts.reconstructionPass.value == "metadata") { + std::map metadata; + metadata["RecoPassName"] = metadataInfo.get("RecoPassName"); + LOGF(info, "Loading CCDB for reconstruction pass (from metadata): %s", metadataInfo.get("RecoPassName")); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } else { + std::map metadata; + metadata["RecoPassName"] = internalOpts.reconstructionPass.value; + LOGF(info, "Loading CCDB for reconstruction pass (from provided argument): %s", internalOpts.reconstructionPass.value); + callst = ccdb->template getSpecificForRun(internalOpts.ccdbPathCentrality, bc.runNumber(), metadata); + } + } + + fv0aInfo.mCalibrationStored = false; + ft0mInfo.mCalibrationStored = false; + ft0aInfo.mCalibrationStored = false; + ft0cInfo.mCalibrationStored = false; + ft0cVariant1Info.mCalibrationStored = false; + fddmInfo.mCalibrationStored = false; + ntpvInfo.mCalibrationStored = false; + nGlobalInfo.mCalibrationStored = false; + mftInfo.mCalibrationStored = false; + if (callst != nullptr) { + LOGF(info, "Getting new histograms with %d run number for %d run number", mRunNumber, bc.runNumber()); + auto getccdb = [callst, bc](struct CalibrationInfo& estimator, const o2::framework::Configurable generatorName) { // TODO: to consider the name inside the estimator structure + estimator.mhMultSelCalib = reinterpret_cast(callst->FindObject(TString::Format("hCalibZeq%s", estimator.name.c_str()).Data())); + estimator.mMCScale = reinterpret_cast(callst->FindObject(TString::Format("%s-%s", generatorName->c_str(), estimator.name.c_str()).Data())); + if (estimator.mhMultSelCalib != nullptr) { + if (generatorName->length() != 0) { + LOGF(info, "Retrieving MC calibration for %d, generator name: %s", bc.runNumber(), generatorName->c_str()); + if (estimator.mMCScale != nullptr) { + for (int ixpar = 0; ixpar < 6; ++ixpar) { + estimator.mMCScalePars[ixpar] = estimator.mMCScale->GetParameter(ixpar); + LOGF(info, "Parameter index %i value %.5f", ixpar, estimator.mMCScalePars[ixpar]); + } + } else { + LOGF(warning, "MC Scale information from %s for run %d not available", estimator.name.c_str(), bc.runNumber()); + } + } + estimator.mCalibrationStored = true; + estimator.isSane(); + } else { + LOGF(info, "Calibration information from %s for run %d not available, will fill this estimator with invalid values and continue (no crash).", estimator.name.c_str(), bc.runNumber()); + } + }; + + // invoke loading only for requested centralities + if (internalOpts.mEnabledTables[kCentFV0As]) + getccdb(fv0aInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0Ms]) + getccdb(ft0mInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0As]) + getccdb(ft0aInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0Cs]) + getccdb(ft0cInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFT0CVariant1s]) + getccdb(ft0cVariant1Info, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentFDDMs]) + getccdb(fddmInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentNTPVs]) + getccdb(ntpvInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentNGlobals]) + getccdb(nGlobalInfo, internalOpts.generatorName); + if (internalOpts.mEnabledTables[kCentMFTs]) + getccdb(mftInfo, internalOpts.generatorName); + } else { + LOGF(info, "Centrality calibration is not available in CCDB for run=%d at timestamp=%llu, will fill tables with dummy values", bc.runNumber(), bc.timestamp()); + } + } + } + + //__________________________________________________ + template + void generateCentralitiesRun3(TCCDB& ccdb, TMetadata const& metadataInfo, TBCs const& bcs, TMultBuffer const& mults, TOutputGroup& cursors) + { + // takes multiplicity buffer and generates the desirable centrality values (if any) + + // first step: did someone actually ask for it? Otherwise, go home + if ( + internalOpts.mEnabledTables[kCentFV0As] || internalOpts.mEnabledTables[kCentFT0Ms] || + internalOpts.mEnabledTables[kCentFT0As] || internalOpts.mEnabledTables[kCentFT0Cs] || + internalOpts.mEnabledTables[kCentFT0CVariant1s] || internalOpts.mEnabledTables[kCentFDDMs] || + internalOpts.mEnabledTables[kCentNTPVs] || internalOpts.mEnabledTables[kCentNGlobals] || + internalOpts.mEnabledTables[kCentMFTs] || internalOpts.mEnabledTables[kBCCentFT0Ms] || + internalOpts.mEnabledTables[kBCCentFT0As] || internalOpts.mEnabledTables[kBCCentFT0Cs]) { + // check and update centrality calibration objects for Run 3 + const auto& firstbc = bcs.begin(); + ConfigureCentralityRun3(ccdb, metadataInfo, firstbc); + + /************************************************************ + * @brief Populates a table with data based on the given calibration information and multiplicity. + * + * @param table The table to populate. + * @param estimator The calibration information. + * @param multiplicity The multiplicity value. + *************************************************************/ + + auto populateTable = [&](auto& table, struct CalibrationInfo& estimator, float multiplicity, bool isInelGt0) { + const bool assignOutOfRange = internalOpts.embedINELgtZEROselection && !isInelGt0; + auto scaleMC = [](float x, float pars[6]) { + return std::pow(((pars[0] + pars[1] * std::pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]); + }; + + float percentile = 105.0f; + float scaledMultiplicity = multiplicity; + if (estimator.mCalibrationStored) { + if (estimator.mMCScale != nullptr) { + scaledMultiplicity = scaleMC(multiplicity, estimator.mMCScalePars); + LOGF(debug, "Unscaled %s multiplicity: %f, scaled %s multiplicity: %f", estimator.name.c_str(), multiplicity, estimator.name.c_str(), scaledMultiplicity); + } + percentile = estimator.mhMultSelCalib->GetBinContent(estimator.mhMultSelCalib->FindFixBin(scaledMultiplicity)); + if (assignOutOfRange) + percentile = 100.5f; + } + LOGF(debug, "%s centrality/multiplicity percentile = %.0f for a zvtx eq %s value %.0f", estimator.name.c_str(), percentile, estimator.name.c_str(), scaledMultiplicity); + table(percentile); + return percentile; + }; + + // populate centralities per event + for (size_t iEv = 0; iEv < mults.size(); iEv++) { + bool isInelGt0 = (mults[iEv].multNContribsEta1 > 0); + if (internalOpts.mEnabledTables[kCentFV0As]) + populateTable(cursors.centFV0A, fv0aInfo, mults[iEv].multFV0AZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0Ms]) + populateTable(cursors.centFT0M, ft0mInfo, mults[iEv].multFT0AZeq + mults[iEv].multFT0CZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0As]) + populateTable(cursors.centFT0A, ft0aInfo, mults[iEv].multFT0AZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0Cs]) + populateTable(cursors.centFT0C, ft0cInfo, mults[iEv].multFT0CZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFT0CVariant1s]) + populateTable(cursors.centFT0CVariant1, ft0cVariant1Info, mults[iEv].multFT0CZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentFDDMs]) + populateTable(cursors.centFDDM, fddmInfo, mults[iEv].multFDDAZeq + mults[iEv].multFDDCZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentNTPVs]) + populateTable(cursors.centNTPV, ntpvInfo, mults[iEv].multNContribs, isInelGt0); + if (internalOpts.mEnabledTables[kCentNGlobals]) + populateTable(cursors.centNGlobals, nGlobalInfo, mults[iEv].multGlobalTracksZeq, isInelGt0); + if (internalOpts.mEnabledTables[kCentMFTs]) + populateTable(cursors.centMFTs, mftInfo, mults[iEv].multMFTTracksZeq, isInelGt0); + } + + // populate centralities per BC + for (size_t ibc = 0; ibc < static_cast(bcs.size()); ibc++) { + float bcMultFT0A = 0; + float bcMultFT0C = 0; + + const auto& bc = bcs.rawIteratorAt(ibc); + if (bc.has_foundFT0()) { + const auto& ft0 = bc.foundFT0(); + for (const auto& amplitude : ft0.amplitudeA()) { + bcMultFT0A += amplitude; + } + for (const auto& amplitude : ft0.amplitudeC()) { + bcMultFT0C += amplitude; + } + } else { + bcMultFT0A = -999.f; + bcMultFT0C = -999.f; + } + + if (internalOpts.mEnabledTables[kBCCentFT0Ms]) + populateTable(cursors.bcCentFT0M, ft0mInfo, bcMultFT0A + bcMultFT0C, true); + if (internalOpts.mEnabledTables[kBCCentFT0As]) + populateTable(cursors.bcCentFT0A, ft0aInfo, bcMultFT0A, true); + if (internalOpts.mEnabledTables[kBCCentFT0Cs]) + populateTable(cursors.bcCentFT0C, ft0cInfo, bcMultFT0C, true); + } + } + } + //__________________________________________________ + template + void generateCentralitiesRun2(TCCDB& ccdb, TMetadata const& metadataInfo, TBCs const& bcs, TMultBuffer const& mults, TOutputGroup& cursors) + { + // takes multiplicity buffer and generates the desirable centrality values (if any) + // For Run 2 + if ( + internalOpts.mEnabledTables[kCentRun2V0Ms] || internalOpts.mEnabledTables[kCentRun2V0As] || + internalOpts.mEnabledTables[kCentRun2SPDTrks] || internalOpts.mEnabledTables[kCentRun2SPDClss] || + internalOpts.mEnabledTables[kCentRun2CL0s] || internalOpts.mEnabledTables[kCentRun2CL1s]) { + // check and update centrality calibration objects for Run 3 + const auto& firstbc = bcs.begin(); + ConfigureCentralityRun2(ccdb, metadataInfo, firstbc); + + auto scaleMC = [](float x, float pars[6]) { + return std::pow(((pars[0] + pars[1] * std::pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]); + }; + + // populate centralities per event + for (size_t iEv = 0; iEv < mults.size(); iEv++) { + if (internalOpts.mEnabledTables[kCentRun2V0Ms]) { + float cV0M = 105.0f; + if (Run2V0MInfo.mCalibrationStored) { + float v0m; + if (Run2V0MInfo.mMCScale != nullptr) { + v0m = scaleMC(mults[iEv].multFV0A + mults[iEv].multFV0C, Run2V0MInfo.mMCScalePars); + LOGF(debug, "Unscaled v0m: %f, scaled v0m: %f", mults[iEv].multFV0A + mults[iEv].multFV0C, v0m); + } else { + v0m = mults[iEv].multFV0A * Run2V0MInfo.mhVtxAmpCorrV0A->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0A->FindFixBin(mults[iEv].posZ)) + + mults[iEv].multFV0C * Run2V0MInfo.mhVtxAmpCorrV0C->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0C->FindFixBin(mults[iEv].posZ)); + } + cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); + } + LOGF(debug, "centRun2V0M=%.0f", cV0M); + // fill centrality columns + cursors.centRun2V0M(cV0M); + } + if (internalOpts.mEnabledTables[kCentRun2V0As]) { + float cV0A = 105.0f; + if (Run2V0AInfo.mCalibrationStored) { + float v0a = mults[iEv].multFV0A * Run2V0AInfo.mhVtxAmpCorrV0A->GetBinContent(Run2V0AInfo.mhVtxAmpCorrV0A->FindFixBin(mults[iEv].posZ)); + cV0A = Run2V0AInfo.mhMultSelCalib->GetBinContent(Run2V0AInfo.mhMultSelCalib->FindFixBin(v0a)); + } + LOGF(debug, "centRun2V0A=%.0f", cV0A); + // fill centrality columns + cursors.centRun2V0A(cV0A); + } + if (internalOpts.mEnabledTables[kCentRun2SPDTrks]) { + float cSPD = 105.0f; + if (Run2SPDTksInfo.mCalibrationStored) { + float spdm = mults[iEv].multTracklets * Run2SPDTksInfo.mhVtxAmpCorr->GetBinContent(Run2SPDTksInfo.mhVtxAmpCorr->FindFixBin(mults[iEv].posZ)); + cSPD = Run2SPDTksInfo.mhMultSelCalib->GetBinContent(Run2SPDTksInfo.mhMultSelCalib->FindFixBin(spdm)); + } + LOGF(debug, "centSPDTracklets=%.0f", cSPD); + cursors.centRun2SPDTracklets(cSPD); + } + if (internalOpts.mEnabledTables[kCentRun2SPDClss]) { + float cSPD = 105.0f; + if (Run2SPDClsInfo.mCalibrationStored) { + float spdm = mults[iEv].spdClustersL0 * Run2SPDClsInfo.mhVtxAmpCorrCL0->GetBinContent(Run2SPDClsInfo.mhVtxAmpCorrCL0->FindFixBin(mults[iEv].posZ)) + + mults[iEv].spdClustersL1 * Run2SPDClsInfo.mhVtxAmpCorrCL1->GetBinContent(Run2SPDClsInfo.mhVtxAmpCorrCL1->FindFixBin(mults[iEv].posZ)); + cSPD = Run2SPDClsInfo.mhMultSelCalib->GetBinContent(Run2SPDClsInfo.mhMultSelCalib->FindFixBin(spdm)); + } + LOGF(debug, "centSPDClusters=%.0f", cSPD); + cursors.centRun2SPDClusters(cSPD); + } + if (internalOpts.mEnabledTables[kCentRun2CL0s]) { + float cCL0 = 105.0f; + if (Run2CL0Info.mCalibrationStored) { + float cl0m = mults[iEv].spdClustersL0 * Run2CL0Info.mhVtxAmpCorr->GetBinContent(Run2CL0Info.mhVtxAmpCorr->FindFixBin(mults[iEv].posZ)); + cCL0 = Run2CL0Info.mhMultSelCalib->GetBinContent(Run2CL0Info.mhMultSelCalib->FindFixBin(cl0m)); + } + LOGF(debug, "centCL0=%.0f", cCL0); + cursors.centRun2CL0(cCL0); + } + if (internalOpts.mEnabledTables[kCentRun2CL1s]) { + float cCL1 = 105.0f; + if (Run2CL1Info.mCalibrationStored) { + float cl1m = mults[iEv].spdClustersL1 * Run2CL1Info.mhVtxAmpCorr->GetBinContent(Run2CL1Info.mhVtxAmpCorr->FindFixBin(mults[iEv].posZ)); + cCL1 = Run2CL1Info.mhMultSelCalib->GetBinContent(Run2CL1Info.mhMultSelCalib->FindFixBin(cl1m)); + } + LOGF(debug, "centCL1=%.0f", cCL1); + cursors.centRun2CL1(cCL1); + } + } + } + } +}; // end BuilderModule + +} // namespace multiplicity +} // namespace common +} // namespace o2 + +#endif // COMMON_TOOLS_MULTMODULE_H_ diff --git a/Common/Tools/PID/handleParamTPCResponse.cxx b/Common/Tools/PID/handleParamTPCResponse.cxx index 64741503fae..242503f16e1 100644 --- a/Common/Tools/PID/handleParamTPCResponse.cxx +++ b/Common/Tools/PID/handleParamTPCResponse.cxx @@ -48,7 +48,7 @@ bool initOptionsAndParse(bpo::options_description& options, int argc, char* argv "paramMultNormalization", bpo::value()->default_value(11000.), "Multiplicity Normalization")( "paramnClNormalization", bpo::value()->default_value(152.), "Maximum nClusters for normalisation (159 for run 2, 152 for run 3)")( "useDefaultParam", bpo::value()->default_value(true), "Use default sigma parametrisation")( - "mode", bpo::value()->default_value(""), "Running mode ('read' from file, 'write' to file, 'pull' from CCDB, 'push' to CCDB)")( + "mode", bpo::value()->default_value(""), "Running mode ('read' from file, 'write' to file, 'pull' from CCDB, 'push' to CCDB)")( "help,h", "Produce help message."); setStandardOpt(options); try { diff --git a/Common/Tools/StandardCCDBLoader.h b/Common/Tools/StandardCCDBLoader.h index 6ba4c9be9a1..2134fec2666 100644 --- a/Common/Tools/StandardCCDBLoader.h +++ b/Common/Tools/StandardCCDBLoader.h @@ -16,12 +16,18 @@ #ifndef COMMON_TOOLS_STANDARDCCDBLOADER_H_ #define COMMON_TOOLS_STANDARDCCDBLOADER_H_ -#include -#include -#include -#include +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" #include "Framework/AnalysisDataModel.h" +#include +#include +#include +#include + //__________________________________________ // Standard class to load stuff // such as matLUT, B and mean Vertex diff --git a/Common/Tools/TrackPropagationModule.h b/Common/Tools/TrackPropagationModule.h index fb957a87b9d..305a7c774f2 100644 --- a/Common/Tools/TrackPropagationModule.h +++ b/Common/Tools/TrackPropagationModule.h @@ -10,22 +10,28 @@ // or submit itself to any jurisdiction. /// \file TrackPropagationModule.h -/// \brief track propagation module functionality to be used in tasks +/// \brief track propagation module functionality to be used in core services /// \author ALICE #ifndef COMMON_TOOLS_TRACKPROPAGATIONMODULE_H_ #define COMMON_TOOLS_TRACKPROPAGATIONMODULE_H_ -#include -#include -#include -#include -#include +#include "TableHelper.h" + +#include "Common/Tools/TrackTuner.h" + +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/Propagator.h" #include "Framework/AnalysisDataModel.h" #include "Framework/Configurable.h" #include "Framework/HistogramSpec.h" -#include "Common/Tools/TrackTuner.h" -#include "TableHelper.h" + +#include +#include +#include +#include +#include //__________________________________________ // track propagation module @@ -73,6 +79,7 @@ class TrackPropagationModule } // controls behaviour + bool fillTracks = false; bool fillTracksCov = false; bool fillTracksDCA = false; bool fillTracksDCACov = false; @@ -80,7 +87,6 @@ class TrackPropagationModule // pointers to objs needed for operation std::shared_ptr trackTunedTracks; - TrackTuner trackTunerObj; // Running variables std::array mDcaInfo; @@ -90,13 +96,39 @@ class TrackPropagationModule o2::track::TrackParametrizationWithError mTrackParCov; template - void init(TConfigurableGroup const& cGroup, THistoRegistry& registry, TInitContext& initContext) + void init(TConfigurableGroup const& cGroup, TrackTuner& trackTunerObj, THistoRegistry& registry, TInitContext& initContext) { // Checking if the tables are requested in the workflow and enabling them + fillTracks = isTableRequiredInWorkflow(initContext, "Tracks"); fillTracksCov = isTableRequiredInWorkflow(initContext, "TracksCov"); fillTracksDCA = isTableRequiredInWorkflow(initContext, "TracksDCA"); fillTracksDCACov = isTableRequiredInWorkflow(initContext, "TracksDCACov"); + if (!fillTracks) { + LOGF(info, "Track propagation to PV not required. Suppressing all further processing and logs."); + } + + LOGF(info, " Track propagation table detection results:"); + LOGF(info, " ---> Will generate Tracks table."); + if (fillTracksCov) { + LOGF(info, "---> Will generate TracksCov table."); + } + if (fillTracksDCA) { + LOGF(info, "---> Will generate TracksDCA table."); + } + if (fillTracksDCACov) { + LOGF(info, "---> Will generate TracksDCACov table."); + } + if (fillTracksCov) { + LOGF(info, "**************************************************************"); + LOGF(info, " Warning: TracksCov has been requested due to a subscription!"); + LOGF(info, " Please be mindful that generating track covariances requires"); + LOGF(info, " a significant extra amount of CPU and memory. If not strictly"); + LOGF(info, " necessary, requesting TracksCov should be avoided to save"); + LOGF(info, " these additional resouces."); + LOGF(info, "**************************************************************"); + } + /// TrackTuner initialization if (cGroup.useTrackTuner.value) { std::string outputStringParams = ""; @@ -127,8 +159,12 @@ class TrackPropagationModule } template - void fillTrackTables(TConfigurableGroup const& cGroup, TCCDBLoader const& ccdbLoader, TCollisions const& collisions, TTracks const& tracks, TOutputGroup& cursors, THistoRegistry& registry) + void fillTrackTables(TConfigurableGroup const& cGroup, TrackTuner& trackTunerObj, TCCDBLoader const& ccdbLoader, TCollisions const& collisions, TTracks const& tracks, TOutputGroup& cursors, THistoRegistry& registry) { + if (!fillTracks) { + return; // suppress everything + } + if (fillTracksCov) { cursors.tracksParCovPropagated.reserve(tracks.size()); cursors.tracksParCovExtensionPropagated.reserve(tracks.size()); diff --git a/Common/Tools/timestampModule.h b/Common/Tools/timestampModule.h new file mode 100644 index 00000000000..80016dbfde3 --- /dev/null +++ b/Common/Tools/timestampModule.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. + +#ifndef COMMON_TOOLS_TIMESTAMPMODULEH_ +#define COMMON_TOOLS_TIMESTAMPMODULEH_ + +#include "Framework/AnalysisDataModel.h" + +#include +#include +#include + +namespace o2 +{ +namespace common +{ +namespace timestamp +{ + +// timestamp configurables +struct timestampConfigurables : o2::framework::ConfigurableGroup { + std::string prefix = "timestamp"; + o2::framework::Configurable verbose{"verbose", false, "verbose mode"}; + o2::framework::Configurable fatalOnInvalidTimestamp{"fatalOnInvalidTimestamp", false, "Generate fatal error for invalid timestamps"}; + o2::framework::Configurable rct_path{"rct-path", "RCT/Info/RunInformation", "path to the ccdb RCT objects for the SOR timestamps"}; + o2::framework::Configurable orbit_reset_path{"orbit-reset-path", "CTP/Calib/OrbitReset", "path to the ccdb orbit-reset objects"}; + o2::framework::Configurable isRun2MC{"isRun2MC", -1, "Running mode: enable only for Run 2 MC. Timestamps are set to SOR timestamp. Default: -1 (autoset from metadata) 0 (Standard) 1 (Run 2 MC)"}; // o2-linter: disable=name/configurable (temporary fix) +}; + +//__________________________________________ +// time stamp module +// +// class to acquire time stamps to be used in +// modular (plugin) fashion + +class TimestampModule +{ + public: + TimestampModule() + { + // constructor: initialize at defaults + lastRunNumber = 0; + orbitResetTimestamp = 0; + }; + + o2::common::timestamp::timestampConfigurables timestampOpts; + + // objects necessary during processing + std::map mapRunToOrbitReset; /// Cache of orbit reset timestamps + std::map> mapRunToRunDuration; /// Cache of run duration timestamps + int lastRunNumber; /// Last run number processed + int64_t orbitResetTimestamp; /// Orbit-reset timestamp in us + std::pair runDuration; /// Pair of SOR and EOR timestamps + + template + void init(TTimestampOpts const& external_timestampOpts, TMetadatahelper const& metadataInfo) + { + timestampOpts = external_timestampOpts; + + if (timestampOpts.isRun2MC.value == -1) { + if ((!metadataInfo.isRun3()) && metadataInfo.isMC()) { + timestampOpts.isRun2MC.value = 1; + LOG(info) << "Autosetting the Run2 MC mode based on metadata"; + } else { + timestampOpts.isRun2MC.value = 0; + } + } + } + + template + void process(TBCs const& bcs, Tccdb const& ccdb, TTimestampBuffer& timestampbuffer, TCursor& timestampTable) + { + timestampbuffer.clear(); + for (auto const& bc : bcs) { + int runNumber = bc.runNumber(); + // We need to set the orbit-reset timestamp for the run number. + // This is done with caching if the run number was already processed before. + // If not the orbit-reset timestamp for the run number is queried from CCDB and added to the cache + if (runNumber == lastRunNumber) { // The run number coincides to the last run processed + LOGF(debug, "Using orbit-reset timestamp from last call"); + } else if (mapRunToOrbitReset.count(runNumber)) { // The run number was already requested before: getting it from cache! + LOGF(debug, "Getting orbit-reset timestamp from cache"); + orbitResetTimestamp = mapRunToOrbitReset[runNumber]; + runDuration = mapRunToRunDuration[runNumber]; + } else { // The run was not requested before: need to acccess CCDB! + LOGF(debug, "Getting start-of-run and end-of-run timestamps from CCDB"); + runDuration = ccdb->getRunDuration(runNumber, true); /// fatalise if timestamps are not found + int64_t sorTimestamp = runDuration.first; // timestamp of the SOR/SOX/STF in ms + int64_t eorTimestamp = runDuration.second; // timestamp of the EOR/EOX/ETF in ms + + // clear cache to prevent interference with orbit reset queries from other code + // FIXME this should not have been a problem, to be investigated + ccdb->clearCache(timestampOpts.orbit_reset_path.value.data()); + + const bool isUnanchoredRun3MC = runNumber >= 300000 && runNumber < 500000; + if (timestampOpts.isRun2MC.value == 1 || isUnanchoredRun3MC) { + // isRun2MC: bc/orbit distributions are not simulated in Run2 MC. All bcs are set to 0. + // isUnanchoredRun3MC: assuming orbit-reset is done in the beginning of each run + // Setting orbit-reset timestamp to start-of-run timestamp + orbitResetTimestamp = sorTimestamp * 1000; // from ms to us + } else if (runNumber < 300000) { // Run 2 + LOGF(debug, "Getting orbit-reset timestamp using start-of-run timestamp from CCDB"); + auto ctp = ccdb->template getSpecific>(timestampOpts.orbit_reset_path.value.data(), sorTimestamp); + orbitResetTimestamp = (*ctp)[0]; + } else { + // sometimes orbit is reset after SOR. Using EOR timestamps for orbitReset query is more reliable + LOGF(debug, "Getting orbit-reset timestamp using end-of-run timestamp from CCDB"); + auto ctp = ccdb->template getSpecific>(timestampOpts.orbit_reset_path.value.data(), eorTimestamp / 2 + sorTimestamp / 2); + orbitResetTimestamp = (*ctp)[0]; + } + + // Adding the timestamp to the cache map + std::pair::iterator, bool> check; + check = mapRunToOrbitReset.insert(std::pair(runNumber, orbitResetTimestamp)); + if (!check.second) { + LOGF(fatal, "Run number %i already existed with a orbit-reset timestamp of %llu", runNumber, check.first->second); + } + mapRunToRunDuration[runNumber] = runDuration; + LOGF(info, "Add new run number %i with orbit-reset timestamp %llu, SOR: %llu, EOR: %llu to cache", runNumber, orbitResetTimestamp, runDuration.first, runDuration.second); + } + + if (timestampOpts.verbose) { + LOGF(info, "Orbit-reset timestamp for run number %i found: %llu us", runNumber, orbitResetTimestamp); + } + int64_t timestamp{(orbitResetTimestamp + int64_t(bc.globalBC() * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000}; // us -> ms + if (timestamp < runDuration.first || timestamp > runDuration.second) { + if (timestampOpts.fatalOnInvalidTimestamp.value) { + LOGF(fatal, "Timestamp %llu us is out of run duration [%llu, %llu] ms", timestamp, runDuration.first, runDuration.second); + } else { + LOGF(debug, "Timestamp %llu us is out of run duration [%llu, %llu] ms", timestamp, runDuration.first, runDuration.second); + } + } + timestampbuffer.push_back(timestamp); // for buffering purposes + timestampTable(timestamp); + } + } +}; + +} // namespace timestamp +} // namespace common +} // namespace o2 + +#endif // COMMON_TOOLS_TIMESTAMPMODULEH_ diff --git a/DPG/Tasks/AOTEvent/CMakeLists.txt b/DPG/Tasks/AOTEvent/CMakeLists.txt index 4cf8873a59f..59e049e6356 100644 --- a/DPG/Tasks/AOTEvent/CMakeLists.txt +++ b/DPG/Tasks/AOTEvent/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(event-selection-qa SOURCES eventSelectionQa.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase O2::DataFormatsITSMFT COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(lumi-qa @@ -44,6 +44,11 @@ o2physics_add_dpl_workflow(rof-occupancy-qa PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(light-ions-evsel-qa + SOURCES lightIonsEvSelQa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(occupancy-vs-dedx-qa SOURCES dEdxVsOccupancyWithTrackQAinfo.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2::DetectorsBase diff --git a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx index a76dc9ea0f7..037fb6db839 100644 --- a/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx +++ b/DPG/Tasks/AOTEvent/detectorOccupancyQa.cxx @@ -42,29 +42,27 @@ using namespace o2; using namespace o2::framework; using namespace o2::aod::evsel; -// using BCsRun2 = soa::Join; using BCsRun3 = soa::Join; -// using ColEvSels = soa::Join; using ColEvSels = soa::Join; -// using FullTracksIU = soa::Join; using FullTracksIU = soa::Join; struct DetectorOccupancyQaTask { // configurables for study of occupancy in time windows - Configurable confAddBasicQAhistos{"AddBasicQAhistos", true, "0 - add basic histograms, 1 - skip"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confTimeIntervalForOccupancyCalculation{"TimeIntervalForOccupancyCalculation", 100, "Time interval for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confOccupancyHistCoeffNtracksForOccupancy{"HistCoeffNtracksForOccupancy", 1., "Coefficient for max nTracks in occupancy histos"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confOccupancyHistCoeffNbins2D{"HistCoeffNbins2D", 1., "Coefficient for nBins in occupancy 2D histos"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confOccupancyHistCoeffNbins3D{"HistCoeffNbins3D", 1., "Coefficient for nBins in occupancy 3D histos"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confCoeffMaxNtracksThisEvent{"CoeffMaxNtracksThisEvent", 1., "Coefficient for max nTracks or FT0 ampl in histos in a given event"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confFlagApplyROFborderCut{"ApplyROFborderCut", true, "Use ROF border cut for a current event"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confFlagApplyTFborderCut{"ApplyTFborderCut", true, "Use TF border cut for a current event"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confAddBasicQAhistos{"AddBasicQAhistos", true, "0 - add basic histograms, 1 - skip"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confTimeIntervalForOccupancyCalculation{"TimeIntervalForOccupancyCalculation", 100, "Time interval for TPC occupancy calculation, us"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confOccupancyHistCoeffNtracksForOccupancy{"HistCoeffNtracksForOccupancy", 1., "Coefficient for max nTracks in occupancy histos"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confOccupancyHistCoeffNbins2D{"HistCoeffNbins2D", 1., "Coefficient for nBins in occupancy 2D histos"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confOccupancyHistCoeffNbins3D{"HistCoeffNbins3D", 1., "Coefficient for nBins in occupancy 3D histos"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confCoeffMaxNtracksThisEvent{"CoeffMaxNtracksThisEvent", 1., "Coefficient for max nTracks or FT0 ampl in histos in a given event"}; // o2-linter: disable=name/configurable (temporary fix) + // Configurable confFlagApplyROFborderCut{"ApplyROFborderCut", true, "Use ROF border cut for a current event"}; // o2-linter: disable=name/configurable (temporary fix) + // Configurable confFlagApplyTFborderCut{"ApplyTFborderCut", true, "Use TF border cut for a current event"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagWhichTimeRange{"FlagWhichTimeRange", 0, "Whicn time range for occupancy calculation: 0 - symmetric, 1 - only past, 2 - only future"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagUseGlobalTracks{"FlagUseGlobalTracks", false, "For small time bins, use global tracks counter instead of ITSTPC tracks"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagUseNoCollInRofStrict{"FlagUseNoCollInRofStrict", false, "Suppress same-ROF events for occupancy historams"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagUseNoHighMultCollInPrevRof{"FlagUseNoHighMultCollInPrevRof", false, "Suppress high-multiplicity prev-ROF events for occupancy historams"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagCentralityIsAvailable{"FlagCentralityIsAvailable", true, "Fill centrality-related historams"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagManyHeavyHistos{"FlagManyHeavyHistos", true, "Fill more TH2, TH3, THn historams"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confFlagIsTOFIsTRDdtStudy{"FlagIsTOFIsTRDdtStudy", true, "Fill THn dt historams with isTOF and isTRD condition"}; // o2-linter: disable=name/configurable (temporary fix) // configuration for small time binning Configurable confTimeIntervalForSmallBins{"TimeIntervalForSmallBins", 100, "Time interval for TPC occupancy calculation in small bins, +/-, us"}; // o2-linter: disable=name/configurable (temporary fix) @@ -77,7 +75,7 @@ struct DetectorOccupancyQaTask { Configurable confCutPtMaxThisEvent{"PtMaxThisEvent", 100., "pt cut for particles in a current event"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confCutEtaMinTracksThisEvent{"EtaMinTracksThisEvent", -0.8, "eta cut for particles in a current event"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confCutEtaMaxTracksThisEvent{"EtaMaxTracksThisEvent", 0.8, "eta cut for particles in a current event"}; // o2-linter: disable=name/configurable (temporary fix) - Configurable confCutMinTPCcls{"MinNumTPCcls", 70, "min number of TPC clusters for a current event"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confCutMinTPCcls{"MinNumTPCcls", 50, "min number of TPC clusters for a current event"}; // o2-linter: disable=name/configurable (temporary fix) // config for QA histograms Configurable confAddTracksVsFwdHistos{"AddTracksVsFwdHistos", true, "0 - add histograms, 1 - skip"}; // o2-linter: disable=name/configurable (temporary fix) @@ -92,6 +90,12 @@ struct DetectorOccupancyQaTask { Configurable nMaxBcInTFforAnalysis{"nMaxBcInTFforAnalysis", -1, "When to stop taking collisions in TF, if -1: take all collisions"}; // o2-linter: disable=name/configurable (temporary fix) + ConfigurableAxis confAxisPtBinsForPhiStudy{"PtBinsForPhiStudy", {VARIABLE_WIDTH, 0.2, 0.6, 1.0, 2.0, 10}, "pt axis"}; + ConfigurableAxis confAxisOccupForKine{"AxisOccupForKine", {VARIABLE_WIDTH, 0, 500, 1000, 2000, 4000, 6000, 8000, 10000, 20000}, "weighted occupancy"}; + + Configurable confUsePhiAtTPCinnerR{"UsePhiAtTPCinnerR", false, "0 - not use, 1 - use"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confUseAorCsideForPhiStudy{"UseAorCsideForPhiStudy", -1, "-1 - use full eta range, 0 - A, 1 - C sides"}; // o2-linter: disable=name/configurable (temporary fix) + uint64_t minGlobalBC = 0; Service ccdb; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -100,8 +104,8 @@ struct DetectorOccupancyQaTask { int lastRunNumber = -1; int nOrbits; double minOrbit; - int64_t bcSOR = 0; // global bc of the start of the first orbit, setting 0 by default for unanchored MC - int64_t nBCsPerTF = 128 * nBCsPerOrbit; // duration of TF in bcs, should be 128*3564 or 32*3564, setting 128 orbits by default sfor unanchored MC + int64_t bcSOR = 0; // global bc of the start of the first orbit, setting 0 by default for unanchored MC + int64_t nBCsPerTF = 32 * nBCsPerOrbit; // duration of TF in bcs, should be 128*3564 or 32*3564, setting 128 orbits by default sfor unanchored MC // save time "slices" for several collisions for QA bool flagFillQAtimeOccupHist = false; @@ -116,8 +120,9 @@ struct DetectorOccupancyQaTask { ccdb->setLocalObjectValidityChecking(); const AxisSpec axisBCinTF{static_cast(nBCsPerTF), 0, static_cast(nBCsPerTF), "bc in TF"}; - histos.add("hNcolVsBcInTF", ";bc in TF; n collisions", kTH1F, {axisBCinTF}); - histos.add("hNcolVsBcInTFafterMaxBcCut", ";bc in TF; n collisions", kTH1F, {axisBCinTF}); + histos.add("hNcolVsBcInTF/hNcolVsBcInTF", ";bc in TF; n collisions", kTH1F, {axisBCinTF}); + histos.add("hNcolVsBcInTF/hNcolVsBcInTF_vertexTOFmatched", ";bc in TF; n collisions", kTH1F, {axisBCinTF}); + histos.add("hNcolVsBcInTF/hNcolVsBcInTFafterMaxBcCut", ";bc in TF; n collisions", kTH1F, {axisBCinTF}); // histograms for occupancy-in-time-window study double kMaxOccup = confOccupancyHistCoeffNtracksForOccupancy; @@ -190,6 +195,27 @@ struct DetectorOccupancyQaTask { histos.add("tpcNClsShared_vs_centr_vs_occup_pos", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisNTPCcls}); histos.add("tpcNClsShared_vs_centr_vs_occup_neg", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisNTPCcls}); + // July 2025: more for data vs MC + AxisSpec axisChi2TPC{150, 0, 15, "chi2Ncl TPC"}; + histos.add("QA_noTPCcuts/nPV_10_200/tpcNClsFindable_vs_occup_pt_02_05", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcNClsFindable_vs_occup_pt_05_10", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcNClsFindable_vs_occup_pt_above1_0", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcNClsFound_vs_occup_pt_02_05", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcNClsFound_vs_occup_pt_05_10", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcNClsFound_vs_occup_pt_above1_0", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcChi2NCl_vs_occup_pt_02_05", "", kTH2F, {axisChi2TPC, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcChi2NCl_vs_occup_pt_05_10", "", kTH2F, {axisChi2TPC, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_10_200/tpcChi2NCl_vs_occup_pt_above1_0", "", kTH2F, {axisChi2TPC, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcNClsFindable_vs_occup_pt_02_05", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcNClsFindable_vs_occup_pt_05_10", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcNClsFindable_vs_occup_pt_above1_0", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcNClsFound_vs_occup_pt_02_05", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcNClsFound_vs_occup_pt_05_10", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcNClsFound_vs_occup_pt_above1_0", "", kTH2F, {axisNTPCcls, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcChi2NCl_vs_occup_pt_02_05", "", kTH2F, {axisChi2TPC, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcChi2NCl_vs_occup_pt_05_10", "", kTH2F, {axisChi2TPC, axisOccupancyForDeDxStudies}); + histos.add("QA_noTPCcuts/nPV_above2000/tpcChi2NCl_vs_occup_pt_above1_0", "", kTH2F, {axisChi2TPC, axisOccupancyForDeDxStudies}); + AxisSpec axisFractionNclsFindableMinusPID{110, -1.1, 1.1, "TPC nClsFindableMinusPID / nClsFindable"}; histos.add("fraction_tpcNClsFindableMinusPID_vs_occup", "", kTH2D, {axisOccupancyForDeDxStudies, axisFractionNclsFindableMinusPID}); histos.add("fraction_tpcNClsFindableMinusPID_vs_occup_peripheralByV0A", "", kTH2D, {axisOccupancyForDeDxStudies, axisFractionNclsFindableMinusPID}); @@ -224,19 +250,20 @@ struct DetectorOccupancyQaTask { histos.add("track_distr_nITStrThisEv_above_2000/hEventCount", ";delta-time bin id;n events", kTH1D, {{5, -0.5, 4.5}}); const int nEtaBins = 800; - histos.add("track_distr_nITStrThisEv_10_200/hEta_lowOccupInTPC", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInRecentPast", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInCloseFuture", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInDistantFuture", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInNeighbourEvents", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - - histos.add("track_distr_nITStrThisEv_above_2000/hEta_lowOccupInTPC", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInRecentPast", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInCloseFuture", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInDistantFuture", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInNeighbourEvents", ";#eta;n tracks", kTH1D, {{nEtaBins, -1.0, 1.0}}); - - const int nPhiBins = 800; + AxisSpec axisEta{nEtaBins, -1.0, 1.0, "#eta"}; // o2-linter: disable=external-pi (temporary fix) + histos.add("track_distr_nITStrThisEv_10_200/hEta_lowOccupInTPC", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInRecentPast", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInCloseFuture", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInDistantFuture", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_10_200/hEta_highOccupInNeighbourEvents", ";#eta;n tracks", kTH1D, {axisEta}); + + histos.add("track_distr_nITStrThisEv_above_2000/hEta_lowOccupInTPC", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInRecentPast", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInCloseFuture", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInDistantFuture", ";#eta;n tracks", kTH1D, {axisEta}); + histos.add("track_distr_nITStrThisEv_above_2000/hEta_highOccupInNeighbourEvents", ";#eta;n tracks", kTH1D, {axisEta}); + + const int nPhiBins = 810; // 18*45 AxisSpec axisPhi{nPhiBins, 0, TMath::TwoPi(), "#varphi"}; // o2-linter: disable=external-pi (temporary fix) histos.add("track_distr_nITStrThisEv_10_200/hPhi_lowOccupInTPC", ";#varphi;n tracks", kTH1D, {axisPhi}); histos.add("track_distr_nITStrThisEv_10_200/hPhi_highOccupInRecentPast", ";#varphi;n tracks", kTH1D, {axisPhi}); @@ -265,13 +292,60 @@ struct DetectorOccupancyQaTask { histos.add("track_distr_nITStrThisEv_above_2000/hPt_highOccupInDistantFuture", ";p_{T};n tracks", kTH1D, {axisLogPt}); histos.add("track_distr_nITStrThisEv_above_2000/hPt_highOccupInNeighbourEvents", ";p_{T};n tracks", kTH1D, {axisLogPt}); + // July 2025: to compare data and MC (pt, eta, phi) + // AxisSpec confAxisOccupForKine{{0, 500, 1000, 2000, 4000, 6000, 20000}, "weighted occupancy"}; + // AxisSpec confAxisOccupForKine{{0, 500, 1000, 2000, 4000, 6000, 8000, 10000, 20000}, "weighted occupancy"}; + // AxisSpec confAxisPtBinsForPhiStudy{{0.2, 0.6, 1.0, 2.0, 10}, "pt bins for phi study"}; + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPt_pos", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPt_neg", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hEta_pos", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hEta_neg", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPhi_pos", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPhi_neg", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPt_pos", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPt_neg", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hEta_pos", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hEta_neg", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPhi_pos", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + histos.add("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPhi_neg", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPt_pos", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPt_neg", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hEta_pos", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hEta_neg", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_pos", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_neg", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_posInitialQA", ";#varphi;n tracks", kTH1D, {{3 * 810, -TMath::TwoPi(), 2 * TMath::TwoPi(), "#varphi"}}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_posModifiedQA", ";#varphi;n tracks", kTH1D, {{3 * 810, -TMath::TwoPi(), 2 * TMath::TwoPi(), "#varphi"}}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_negInitialQA", ";#varphi;n tracks", kTH1D, {{3 * 810, -TMath::TwoPi(), 2 * TMath::TwoPi(), "#varphi"}}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_negModifiedQA", ";#varphi;n tracks", kTH1D, {{3 * 810, -TMath::TwoPi(), 2 * TMath::TwoPi(), "#varphi"}}); + + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPt_pos", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPt_neg", ";p_{T};weighted occupancy", kTH2D, {axisLogPt, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hEta_pos", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hEta_neg", ";#eta;weighted occupancy", kTH2D, {axisEta, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPhi_pos", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + histos.add("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPhi_neg", ";#varphi;n tracks", kTH3D, {axisPhi, confAxisOccupForKine, confAxisPtBinsForPhiStudy}); + + AxisSpec axisLogPtFor2D{50, 0.05, 10, "p_{T}"}; + AxisSpec axisLogPtTpcFor2D{50, 0.05, 10, "p_{T} TPC inner"}; + histos.add("track_distr_nITStrThisEv_10_200/hPt_vs_tpcInnerPt_vs_occup", ";p_{T};p_{T} TPC inner;weighted occupancy", kTH3D, {axisLogPtFor2D, axisLogPtTpcFor2D, confAxisOccupForKine}); + histos.add("track_distr_nITStrThisEv_above_2000/hPt_vs_tpcInnerPt_vs_occup", ";p_{T};p_{T} TPC inner;weighted occupancy", kTH3D, {axisLogPtFor2D, axisLogPtTpcFor2D, confAxisOccupForKine}); + + histos.add("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy", ";bc in TF;weighted occupancy", kTH2F, {axisBCinTF, confAxisOccupForKine}); + histos.add("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy_vertexTOFmatched", ";bc in TF;weighted occupancy", kTH2F, {axisBCinTF, confAxisOccupForKine}); + histos.add("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy_nPV_10_200", ";bc in TF;weighted occupancy", kTH2F, {axisBCinTF, confAxisOccupForKine}); + histos.add("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy_nPV_above2000", ";bc in TF;weighted occupancy", kTH2F, {axisBCinTF, confAxisOccupForKine}); + // end of July 2025: to compare data and MC (pt, eta, phi) + // 3D: pt vs centr vs occup - if (confFlagManyHeavyHistos) { - histos.add("ptGlobal_vs_centr_vs_occup", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); - histos.add("ptPV_vs_centr_vs_occup", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); - histos.add("ptGlobal_vs_centr_vs_occup_NoCollStd", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); - histos.add("ptPV_vs_centr_vs_occup_NoCollStd", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); - } + // if (confFlagManyHeavyHistos) { + // histos.add("ptGlobal_vs_centr_vs_occup", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); + // histos.add("ptPV_vs_centr_vs_occup", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); + // histos.add("ptGlobal_vs_centr_vs_occup_NoCollStd", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); + // histos.add("ptPV_vs_centr_vs_occup_NoCollStd", "", kTH3F, {{20, 0, 4000, "nITStrk cls567"}, axisOccupancyForDeDxStudies, axisLogPt}); + // } } // 2D int nBins3D = 80 * confOccupancyHistCoeffNbins3D; @@ -328,6 +402,10 @@ struct DetectorOccupancyQaTask { histos.add("occupancyInTimeBins_nITS567_vs_FT0thisCol_occupByFT0_kNoCollInTimeRangeNarrow", ";time bin (#mus);FT0C this collision, this collision;n ITS567cls tracks, this collision;sum FT0 in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 100000}}); histos.add("occupancyInTimeBins_nITS567_vs_FT0thisCol_occupByFT0_kNoCollInTimeRangeNarrow_NoCollInRofStrict", ";time bin (#mus);FT0C this collision, this collision;n ITS567cls tracks, this collision;sum FT0 in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 100000}}); } + if (confFlagIsTOFIsTRDdtStudy) { + histos.add("occupancyInTimeBins_nITSTOF_vs_FT0thisCol_kNoCollInTimeRangeNarrow", ";time bin (#mus);FT0C this collision, this collision;n ITSTOF tracks, this collision;ITS tracks with 5,6,7 cls in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 10000}}); + histos.add("occupancyInTimeBins_nITSTRD_vs_FT0thisCol_kNoCollInTimeRangeNarrow", ";time bin (#mus);FT0C this collision, this collision;n ITSTRD tracks, this collision;ITS tracks with 5,6,7 cls in time window", kTHnF, {axisTimeBins, {nBins3D, 0, kMaxThisEv * 100000}, {nBinsY, 0, kMaxThisEv * 4000}, {nBins3DoccupancyAxis, 0, kMaxOccup * 10000}}); + } histos.add("thisEventITStracksInTimeBins", ";time bin (#mus);n tracks", kTH1F, {axisTimeBins}); histos.add("thisEventITSTPCtracksInTimeBins", ";time bin (#mus);n tracks", kTH1F, {axisTimeBins}); @@ -402,8 +480,8 @@ struct DetectorOccupancyQaTask { histos.add("nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeStandard", "nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeStandard", kTH2F, {axisNtracks, axisNtracksGlobal}); histos.add("nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeNarrow", "nTracksGlobal_vs_nPV_AntiNoCollInTimeRangeNarrow", kTH2F, {axisNtracks, axisNtracksGlobal}); - histos.add("nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts", "nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts", kTH2F, {axisNtracks, axisNtracksGlobal}); - histos.add("nTracksGlobal_vs_nPV_QA_after_TFborderCut", "nTracksGlobal_vs_nPV_QA_after_TFborderCut", kTH2F, {axisNtracks, axisNtracksGlobal}); + // histos.add("nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts", "nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts", kTH2F, {axisNtracks, axisNtracksGlobal}); + // histos.add("nTracksGlobal_vs_nPV_QA_after_TFborderCut", "nTracksGlobal_vs_nPV_QA_after_TFborderCut", kTH2F, {axisNtracks, axisNtracksGlobal}); histos.add("nTracksGlobal_vs_nPV_occupByFT0C_0_2500", "nTracksGlobal_vs_nPV_occupByFT0C_0_2500", kTH2F, {axisNtracks, axisNtracksGlobal}); histos.add("nTracksGlobal_vs_nPV_occupByFT0C_0_20000", "nTracksGlobal_vs_nPV_occupByFT0C_0_20000", kTH2F, {axisNtracks, axisNtracksGlobal}); @@ -416,6 +494,7 @@ struct DetectorOccupancyQaTask { // 3D histograms: nGlobalTracks with cls567 as y-axis, V0A as x-axis: histos.add("nTracksGlobal_vs_V0A_vs_occup_pure", "", kTH3F, {axisMultV0A, axisNtracksGlobal, axisOccupancyTracks}); + histos.add("nTracksGlobal_vs_V0A_vs_occup_kNoCollInTimeRangeNarrow", "", kTH3F, {axisMultV0A, axisNtracksGlobal, axisOccupancyTracks}); histos.add("nTracksGlobal_vs_V0A_vs_occup_kNoCollInTimeRangeStandard_extraCuts", "", kTH3F, {axisMultV0A, axisNtracksGlobal, axisOccupancyTracks}); // FT0C as x-axis: histos.add("nTracksGlobal_vs_FT0C_vs_occup_pure", "", kTH3F, {axisMultFT0C, axisNtracksGlobal, axisOccupancyTracks}); @@ -423,6 +502,7 @@ struct DetectorOccupancyQaTask { // 3D histograms: now - nITStracks with cls567 as y-axis, V0A as x-axis: histos.add("nPV_vs_V0A_vs_occup_pure", "", kTH3F, {axisMultV0A, axisNtracks, axisOccupancyTracks}); + histos.add("nPV_vs_V0A_vs_occup_kNoCollInTimeRangeNarrow", "", kTH3F, {axisMultV0A, axisNtracks, axisOccupancyTracks}); histos.add("nPV_vs_V0A_vs_occup_kNoCollInTimeRangeStandard_extraCuts", "", kTH3F, {axisMultV0A, axisNtracks, axisOccupancyTracks}); // FT0C as x-axis: histos.add("nPV_vs_FT0C_vs_occup_pure", "", kTH3F, {axisMultFT0C, axisNtracks, axisOccupancyTracks}); @@ -462,6 +542,8 @@ struct DetectorOccupancyQaTask { std::vector vTracksGlobalPerCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies std::vector vTracksITSTPCperColl(cols.size(), 0); // counter of tracks per found bc for occupancy studies std::vector vTracksITSTPCperCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies + std::vector vTracksITSTOFperCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies + std::vector vTracksITSTRDperCollPtEtaCuts(cols.size(), 0); // counter of tracks per found bc for occupancy studies std::vector vAmpFT0CperColl(cols.size(), 0); // amplitude FT0C per collision std::vector vTFids(cols.size(), 0); @@ -482,6 +564,8 @@ struct DetectorOccupancyQaTask { int nGlobalPtEtaCuts = 0; int nITSTPCtracks = 0; int nITSTPCtracksPtEtaCuts = 0; + int nITSTOFtracksPtEtaCuts = 0; + int nITSTRDtracksPtEtaCuts = 0; int nTOFtracks = 0; // int nTRDtracks = 0; auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); @@ -489,26 +573,26 @@ struct DetectorOccupancyQaTask { if (!track.isPVContributor()) { continue; } - if (track.itsNCls() >= 5) - nITS567cls++; + if (track.itsNCls() < 5) + continue; + nITS567cls++; nITSTPCtracks += track.hasITS() && track.hasTPC(); nTOFtracks += track.hasTOF(); - // nTRDtracks += track.hasTRD(); if (track.pt() < confCutPtMinThisEvent || track.pt() > confCutPtMaxThisEvent) continue; if (track.eta() < confCutEtaMinTracksThisEvent || track.eta() > confCutEtaMaxTracksThisEvent) continue; - if (track.itsNCls() >= 5) - nITS567clsPtEtaCuts++; + nITS567clsPtEtaCuts++; + nITSTOFtracksPtEtaCuts += track.hasITS() && track.hasTOF(); + nITSTRDtracksPtEtaCuts += track.hasITS() && track.hasTRD(); if (track.tpcNClsFound() < confCutMinTPCcls) continue; nITSTPCtracksPtEtaCuts += track.hasITS() && track.hasTPC(); - if (track.itsNCls() >= 5) - nGlobalPtEtaCuts += track.isGlobalTrack(); + nGlobalPtEtaCuts += track.isGlobalTrack(); } int32_t foundBC = bc.globalIndex(); @@ -522,12 +606,14 @@ struct DetectorOccupancyQaTask { vIsVertexTOFmatched[colIndex] = nTOFtracks > 0; - vTracksITS567perColl[colIndex] += nITS567cls; - vTracksITS567perCollPtEtaCuts[colIndex] += nITS567clsPtEtaCuts; - vTracksGlobalPerCollPtEtaCuts[colIndex] += nGlobalPtEtaCuts; + vTracksITS567perColl[colIndex] = nITS567cls; + vTracksITS567perCollPtEtaCuts[colIndex] = nITS567clsPtEtaCuts; + vTracksGlobalPerCollPtEtaCuts[colIndex] = nGlobalPtEtaCuts; - vTracksITSTPCperColl[colIndex] += nITSTPCtracks; - vTracksITSTPCperCollPtEtaCuts[colIndex] += nITSTPCtracksPtEtaCuts; + vTracksITSTPCperColl[colIndex] = nITSTPCtracks; + vTracksITSTPCperCollPtEtaCuts[colIndex] = nITSTPCtracksPtEtaCuts; + vTracksITSTOFperCollPtEtaCuts[colIndex] = nITSTOFtracksPtEtaCuts; + vTracksITSTRDperCollPtEtaCuts[colIndex] = nITSTRDtracksPtEtaCuts; // TF ids within a given cols table int tfId = (bc.globalBC() - bcSOR) / nBCsPerTF; @@ -622,11 +708,11 @@ struct DetectorOccupancyQaTask { continue; // skip if collision is close to TF border - if (confFlagApplyTFborderCut && !col.selection_bit(kNoTimeFrameBorder)) + if (!col.selection_bit(kNoTimeFrameBorder)) continue; // skip if collision is close to ROF border - if (confFlagApplyROFborderCut && !col.selection_bit(kNoITSROFrameBorder)) + if (!col.selection_bit(kNoITSROFrameBorder)) continue; std::vector vCollsAssocToGivenColl = vCollsInTimeWin[colIndex]; @@ -650,7 +736,7 @@ struct DetectorOccupancyQaTask { int nCollInTimeWindowSelIfTOF = 0; double multFT0CmainCollision = 0.f; double multFT0CInTimeWindow = 0.f; - map mUniqueBC; + std::map mUniqueBC; bool sel = col.selection_bit(kIsTriggerTVX); @@ -771,19 +857,19 @@ struct DetectorOccupancyQaTask { float integralNeighbourEvents = histos.get(HIST("thisEventITStracksInTimeBins"))->Integral(binMin, binMax); // recent past - if (integralFullDeltaTime < 150) // ~empty detector + if (integralFullDeltaTime < 200) // ~empty detector vFlagsForEtaQAvsOccupancyInDeltaTimeWins[colIndex] = 1; // recent past - if (integralPast > /*3000*/ 2500 && (integralFullDeltaTime - integralPast) < 120) // low occupancy outside the dt region of interest + if (integralPast > /*3000*/ 2500 && (integralFullDeltaTime - integralPast) < 180) // low occupancy outside the dt region of interest vFlagsForEtaQAvsOccupancyInDeltaTimeWins[colIndex] = 2; // close future - if (integralFuture1 > /*3000*/ 2500 && (integralFullDeltaTime - integralFuture1) < 120) + if (integralFuture1 > /*3000*/ 2500 && (integralFullDeltaTime - integralFuture1) < 180) vFlagsForEtaQAvsOccupancyInDeltaTimeWins[colIndex] = 3; // distant future - if (integralFuture2 > /*3000*/ 2500 && (integralFullDeltaTime - integralFuture2) < 120) + if (integralFuture2 > /*3000*/ 2500 && (integralFullDeltaTime - integralFuture2) < 180) vFlagsForEtaQAvsOccupancyInDeltaTimeWins[colIndex] = 4; // neighbour events - if (integralNeighbourEvents > /*3000*/ 2500 && (integralFullDeltaTime - integralNeighbourEvents) < 120) + if (integralNeighbourEvents > /*3000*/ 2500 && (integralFullDeltaTime - integralNeighbourEvents) < 180) vFlagsForEtaQAvsOccupancyInDeltaTimeWins[colIndex] = 5; // loop over time axis in nD histograms: @@ -815,6 +901,10 @@ struct DetectorOccupancyQaTask { if (col.selection_bit(kNoCollInTimeRangeNarrow)) { histos.fill(HIST("occupancyInTimeBins_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], confFlagUseGlobalTracks ? vTracksGlobalPerCollPtEtaCuts[colIndex] : vTracksITSTPCperCollPtEtaCuts[colIndex], nITStrInTimeBin); histos.fill(HIST("occupancyInTimeBins_nITS567_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], vTracksITS567perCollPtEtaCuts[colIndex], nITStrInTimeBin); + if (confFlagIsTOFIsTRDdtStudy) { + histos.fill(HIST("occupancyInTimeBins_nITSTOF_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], vTracksITSTOFperCollPtEtaCuts[colIndex], nITStrInTimeBin); + histos.fill(HIST("occupancyInTimeBins_nITSTRD_vs_FT0thisCol_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], vTracksITSTRDperCollPtEtaCuts[colIndex], nITStrInTimeBin); + } if (confFlagManyHeavyHistos) { histos.fill(HIST("occupancyInTimeBins_occupByFT0_kNoCollInTimeRangeNarrow"), dt, vTracksITS567perCollPtEtaCuts[colIndex], confFlagUseGlobalTracks ? vTracksGlobalPerCollPtEtaCuts[colIndex] : vTracksITSTPCperCollPtEtaCuts[colIndex], nFT0CInTimeBin); histos.fill(HIST("occupancyInTimeBins_vs_FT0thisCol_occupByFT0_kNoCollInTimeRangeNarrow"), dt, vAmpFT0CperColl[colIndex], confFlagUseGlobalTracks ? vTracksGlobalPerCollPtEtaCuts[colIndex] : vTracksITSTPCperCollPtEtaCuts[colIndex], nFT0CInTimeBin); @@ -851,24 +941,27 @@ struct DetectorOccupancyQaTask { // ### occupancy event selection QA for (const auto& col : cols) { - // if (!col.sel8()) { - // continue; - // } - if (!col.selection_bit(kIsTriggerTVX)) + if (!col.sel8()) continue; + + // if (!col.selection_bit(kIsTriggerTVX)) + // continue; + // cut on vZ for a given collision if (col.posZ() < confCutVertZMinThisEvent || col.posZ() > confCutVertZMaxThisEvent) continue; int32_t colIndex = col.globalIndex(); int64_t bcInTF = (vFoundGlobalBC[colIndex] - bcSOR) % nBCsPerTF; - histos.fill(HIST("hNcolVsBcInTF"), bcInTF); + histos.fill(HIST("hNcolVsBcInTF/hNcolVsBcInTF"), bcInTF); + if (col.selection_bit(kIsVertexTOFmatched)) + histos.fill(HIST("hNcolVsBcInTF/hNcolVsBcInTF_vertexTOFmatched"), bcInTF); // cut on the max bcId in the time frame (to avoid the artificial fade-out tail in the MC productions) if (!vIsMarkedCollForAnalysis[colIndex]) continue; - histos.fill(HIST("hNcolVsBcInTFafterMaxBcCut"), bcInTF); + histos.fill(HIST("hNcolVsBcInTF/hNcolVsBcInTFafterMaxBcCut"), bcInTF); auto multV0A = col.multFV0A(); // auto multT0A = col.multFT0A(); @@ -877,7 +970,6 @@ struct DetectorOccupancyQaTask { int nGlobalTracks = 0; int occupancy = col.trackOccupancyInTimeRange(); - auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); // pre-calc nPV @@ -892,6 +984,15 @@ struct DetectorOccupancyQaTask { continue; nPV++; } + if (occupancy >= 0) { + histos.fill(HIST("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy"), bcInTF, occupancy); + if (col.selection_bit(kIsVertexTOFmatched)) + histos.fill(HIST("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy_vertexTOFmatched"), bcInTF, occupancy); + if (nPV >= 10 && nPV < 200) + histos.fill(HIST("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy_nPV_10_200"), bcInTF, occupancy); + else if (nPV >= 2000) + histos.fill(HIST("hNcolVsBcInTF/hNcolVsBcInTF_vs_occupancy_nPV_above2000"), bcInTF, occupancy); + } // main loop for dE/dx for (const auto& track : tracksGrouped) { @@ -910,6 +1011,47 @@ struct DetectorOccupancyQaTask { histos.fill(HIST("nTrackCounter_after_cuts_QA"), 4); // nPV++; + // July 2025: more for data vs MC: + if (track.hasTPC() && occupancy >= 0) { + float pt = track.pt(); + // pt 0.2-0.5 + if (pt > 0.2 && pt < 0.5) { + if (nPV >= 10 && nPV < 400) { + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcNClsFindable_vs_occup_pt_02_05"), track.tpcNClsFindable(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcNClsFound_vs_occup_pt_02_05"), track.tpcNClsFound(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcChi2NCl_vs_occup_pt_02_05"), track.tpcChi2NCl(), occupancy); + } else if (nPV >= 2000) { + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcNClsFindable_vs_occup_pt_02_05"), track.tpcNClsFindable(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcNClsFound_vs_occup_pt_02_05"), track.tpcNClsFound(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcChi2NCl_vs_occup_pt_02_05"), track.tpcChi2NCl(), occupancy); + } + } + // pt 0.5-1.0 + else if (pt > 0.5 && pt < 1.0) { + if (nPV >= 10 && nPV < 400) { + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcNClsFindable_vs_occup_pt_05_10"), track.tpcNClsFindable(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcNClsFound_vs_occup_pt_05_10"), track.tpcNClsFound(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcChi2NCl_vs_occup_pt_05_10"), track.tpcChi2NCl(), occupancy); + } else if (nPV >= 2000) { + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcNClsFindable_vs_occup_pt_05_10"), track.tpcNClsFindable(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcNClsFound_vs_occup_pt_05_10"), track.tpcNClsFound(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcChi2NCl_vs_occup_pt_05_10"), track.tpcChi2NCl(), occupancy); + } + } + // pt > 1.0 + else if (pt > 1.0) { + if (nPV >= 10 && nPV < 400) { + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcNClsFindable_vs_occup_pt_above1_0"), track.tpcNClsFindable(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcNClsFound_vs_occup_pt_above1_0"), track.tpcNClsFound(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_10_200/tpcChi2NCl_vs_occup_pt_above1_0"), track.tpcChi2NCl(), occupancy); + } else if (nPV >= 2000) { + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcNClsFindable_vs_occup_pt_above1_0"), track.tpcNClsFindable(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcNClsFound_vs_occup_pt_above1_0"), track.tpcNClsFound(), occupancy); + histos.fill(HIST("QA_noTPCcuts/nPV_above2000/tpcChi2NCl_vs_occup_pt_above1_0"), track.tpcChi2NCl(), occupancy); + } + } + } + if (track.isGlobalTrack() && track.tpcNClsFound() >= confCutMinTPCcls) { nGlobalTracks++; histos.fill(HIST("nTrackCounter_after_cuts_QA"), 5); @@ -1034,19 +1176,19 @@ struct DetectorOccupancyQaTask { } } // end of track loop - if (confAddTracksVsFwdHistos) - histos.fill(HIST("nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts"), nPV, nGlobalTracks); + // if (confAddTracksVsFwdHistos) + // histos.fill(HIST("nTracksGlobal_vs_nPV_QA_onlyVzCut_noTFROFborderCuts"), nPV, nGlobalTracks); // skip if collision is close to TF border - if (confFlagApplyTFborderCut && !col.selection_bit(kNoTimeFrameBorder)) - continue; + // if (confFlagApplyTFborderCut && !col.selection_bit(kNoTimeFrameBorder)) + // continue; - if (confAddTracksVsFwdHistos) - histos.fill(HIST("nTracksGlobal_vs_nPV_QA_after_TFborderCut"), nPV, nGlobalTracks); + // if (confAddTracksVsFwdHistos) + // histos.fill(HIST("nTracksGlobal_vs_nPV_QA_after_TFborderCut"), nPV, nGlobalTracks); // skip if collision is close to ROF border - if (confFlagApplyROFborderCut && !col.selection_bit(kNoITSROFrameBorder)) - continue; + // if (confFlagApplyROFborderCut && !col.selection_bit(kNoITSROFrameBorder)) + // continue; histos.fill(HIST("hOccupancy"), occupancy); if (occupancy >= 0) { @@ -1057,7 +1199,7 @@ struct DetectorOccupancyQaTask { // another track loop to fill track-level histograms if (confAddBasicQAhistos) { int flagWhichDeltaTimeWin = vFlagsForEtaQAvsOccupancyInDeltaTimeWins[colIndex]; - bool flagNoCollNearby = col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard); + bool flagNoCollNearby = col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow); if (occupancy >= 0) { if (nPV >= 10 && nPV < 200) { @@ -1079,76 +1221,153 @@ struct DetectorOccupancyQaTask { continue; if (track.itsNCls() < 5) continue; - if (!(track.isGlobalTrack() && track.tpcNClsFound() >= confCutMinTPCcls)) - continue; + // if (!(track.isGlobalTrack() && track.tpcNClsFound() >= confCutMinTPCcls)) + // continue; + + bool isGoodGlobal = (track.isGlobalTrack() && track.tpcNClsFound() >= confCutMinTPCcls); + bool hasTPCspecCuts = (track.hasTPC() && track.tpcNClsFound() >= confCutMinTPCcls && track.tpcNClsCrossedRows() > 80 && track.tpcChi2NCl() < 4); + + // ### kine distr vs centr vs occup + float sign = track.sign(); + float pt = track.pt(); + float eta = track.eta(); + float phi = track.phi(); + float phiInitial = phi; + + if (confUsePhiAtTPCinnerR) { + phi -= asin(0.8 /*inner TPC radius*/ / 2 * 0.3 * sign * 0.5 / pt); + if (phi < 0) + phi += TMath::TwoPi(); + else if (phi > TMath::TwoPi()) + phi -= TMath::TwoPi(); + } - // pt vs centr vs occup - if (occupancy >= 0) { - if (confFlagManyHeavyHistos) { - histos.fill(HIST("ptGlobal_vs_centr_vs_occup"), nPV, occupancy, track.pt()); - histos.fill(HIST("ptPV_vs_centr_vs_occup"), nPV, occupancy, track.pt()); - if (col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { - histos.fill(HIST("ptGlobal_vs_centr_vs_occup_NoCollStd"), nPV, occupancy, track.pt()); - histos.fill(HIST("ptPV_vs_centr_vs_occup_NoCollStd"), nPV, occupancy, track.pt()); - } - } + bool etaInRange = true; + if (confUseAorCsideForPhiStudy == 0 && eta < 0.1) // check if we are in A side + etaInRange = false; + if (confUseAorCsideForPhiStudy == 1 && eta > -0.1) // check if we are in C side + etaInRange = false; + if (occupancy >= 0 && fabs(eta) < 0.8 && pt > 0.15 && etaInRange) { if (nPV >= 10 && nPV < 200) { - if (flagWhichDeltaTimeWin == 1 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_lowOccupInTPC"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_lowOccupInTPC"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_lowOccupInTPC"), track.pt()); - } - if (flagWhichDeltaTimeWin == 2 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInRecentPast"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInRecentPast"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInRecentPast"), track.pt()); - } - if (flagWhichDeltaTimeWin == 3 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInCloseFuture"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInCloseFuture"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInCloseFuture"), track.pt()); - } - if (flagWhichDeltaTimeWin == 4 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInDistantFuture"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInDistantFuture"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInDistantFuture"), track.pt()); - } - if (flagWhichDeltaTimeWin == 5) { - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInNeighbourEvents"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInNeighbourEvents"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInNeighbourEvents"), track.pt()); + if (isGoodGlobal) { + if (flagWhichDeltaTimeWin == 1 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_lowOccupInTPC"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_lowOccupInTPC"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_lowOccupInTPC"), pt); + } + if (flagWhichDeltaTimeWin == 2 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInRecentPast"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInRecentPast"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInRecentPast"), pt); + } + if (flagWhichDeltaTimeWin == 3 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInCloseFuture"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInCloseFuture"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInCloseFuture"), pt); + } + if (flagWhichDeltaTimeWin == 4 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInDistantFuture"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInDistantFuture"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInDistantFuture"), pt); + } + if (flagWhichDeltaTimeWin == 5) { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hEta_highOccupInNeighbourEvents"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPhi_highOccupInNeighbourEvents"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_highOccupInNeighbourEvents"), pt); + } + histos.fill(HIST("track_distr_nITStrThisEv_10_200/hPt_vs_tpcInnerPt_vs_occup"), pt, track.tpcInnerParam(), occupancy); + } // end of TPC good global + + // July 2025: for data vs MC kine distr comparison + if (sign > 0) // positive tracks + { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPt_pos"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hEta_pos"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPhi_pos"), phi, occupancy, pt); + if (hasTPCspecCuts) { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPt_pos"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hEta_pos"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPhi_pos"), phi, occupancy, pt); + } + } else // negative tracks + { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPt_neg"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hEta_neg"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/PV_hPhi_neg"), phi, occupancy, pt); + if (hasTPCspecCuts) { + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPt_neg"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hEta_neg"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_10_200/kine_vs_weighted_occup/hPhi_neg"), phi, occupancy, pt); + } } + // end of July 2025: for data vs MC kine distr comparison + } else if (nPV >= 2000) { - if (flagWhichDeltaTimeWin == 1 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_lowOccupInTPC"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_lowOccupInTPC"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_lowOccupInTPC"), track.pt()); - } - if (flagWhichDeltaTimeWin == 2 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInRecentPast"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInRecentPast"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInRecentPast"), track.pt()); - } - if (flagWhichDeltaTimeWin == 3 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInCloseFuture"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInCloseFuture"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInCloseFuture"), track.pt()); - } - if (flagWhichDeltaTimeWin == 4 && flagNoCollNearby) { - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInDistantFuture"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInDistantFuture"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInDistantFuture"), track.pt()); + if (isGoodGlobal) { + if (flagWhichDeltaTimeWin == 1 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_lowOccupInTPC"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_lowOccupInTPC"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_lowOccupInTPC"), pt); + } + if (flagWhichDeltaTimeWin == 2 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInRecentPast"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInRecentPast"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInRecentPast"), pt); + } + if (flagWhichDeltaTimeWin == 3 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInCloseFuture"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInCloseFuture"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInCloseFuture"), pt); + } + if (flagWhichDeltaTimeWin == 4 && flagNoCollNearby) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInDistantFuture"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInDistantFuture"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInDistantFuture"), pt); + } + if (flagWhichDeltaTimeWin == 5) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInNeighbourEvents"), eta); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInNeighbourEvents"), phi); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInNeighbourEvents"), pt); + } + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_vs_tpcInnerPt_vs_occup"), pt, track.tpcInnerParam(), occupancy); + } // end of TPC good global + + // July 2025: for data vs MC kine distr comparison + if (sign > 0) // positive tracks + { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPt_pos"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hEta_pos"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPhi_pos"), phi, occupancy, pt); + if (hasTPCspecCuts) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPt_pos"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hEta_pos"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_pos"), phi, occupancy, pt); + if (pt > 0.7 && pt < 1.0) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_posInitialQA"), phiInitial); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_posModifiedQA"), phi); + } + } + } else // negative tracks + { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPt_neg"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hEta_neg"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/PV_hPhi_neg"), phi, occupancy, pt); + if (hasTPCspecCuts) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPt_neg"), pt, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hEta_neg"), eta, occupancy); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_neg"), phi, occupancy, pt); + if (pt > 0.7 && pt < 1.0) { + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_negInitialQA"), phiInitial); + histos.fill(HIST("track_distr_nITStrThisEv_above_2000/kine_vs_weighted_occup/hPhi_negModifiedQA"), phi); + } + } } - if (flagWhichDeltaTimeWin == 5) { - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hEta_highOccupInNeighbourEvents"), track.eta()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPhi_highOccupInNeighbourEvents"), track.phi()); - histos.fill(HIST("track_distr_nITStrThisEv_above_2000/hPt_highOccupInNeighbourEvents"), track.pt()); - } - } - } // end of if (occupancy >= 0) - } - } // end of spec track loop to fill track histograms + // end of July 2025: for data vs MC kine distr comparison + } // end of if (nPV >= 2000) + } // end of if (occupancy >= 0) && kine cuts + } // end of spec track loop to fill track histograms + } // end of if (confAddBasicQAhistos) // occupancy vs centrality if (confFlagCentralityIsAvailable) { @@ -1197,8 +1416,11 @@ struct DetectorOccupancyQaTask { histos.fill(HIST("nTracksPV_vs_V0A_kNoCollInTimeRangeNarrow"), multV0A, nPV); histos.fill(HIST("nTracksGlobal_vs_V0A_kNoCollInTimeRangeNarrow"), multV0A, nGlobalTracks); histos.fill(HIST("nTracksGlobal_vs_nPV_kNoCollInTimeRangeNarrow"), nPV, nGlobalTracks); - if (occupancy >= 0) + if (occupancy >= 0) { histos.fill(HIST("nTracksGlobal_vs_nPV_vs_occup_kNoCollInTimeRangeNarrow"), nPV, nGlobalTracks, occupancy); + histos.fill(HIST("nTracksGlobal_vs_V0A_vs_occup_kNoCollInTimeRangeNarrow"), multV0A, nGlobalTracks, occupancy); + histos.fill(HIST("nPV_vs_V0A_vs_occup_kNoCollInTimeRangeNarrow"), multV0A, nPV, occupancy); + } } if (occupancy >= 0 && occupancy < 250) { histos.fill(HIST("nTracksPV_vs_V0A_occup_0_250"), multV0A, nPV); diff --git a/DPG/Tasks/AOTEvent/eventSelectionQa.cxx b/DPG/Tasks/AOTEvent/eventSelectionQa.cxx index 9d9dc544b58..e890b9fbab9 100644 --- a/DPG/Tasks/AOTEvent/eventSelectionQa.cxx +++ b/DPG/Tasks/AOTEvent/eventSelectionQa.cxx @@ -12,7 +12,7 @@ /// \file eventSelectionQa.cxx /// \brief Event selection QA task /// -/// \author Evgeny Kryshen +/// \author Evgeny Kryshen and Igor Altsybeev #include #include @@ -346,16 +346,32 @@ struct EventSelectionQaTask { histos.add("occupancyQA/hOccupancyByFT0CvsByTracks", "", kTH2D, {{150, 0, 15000}, {150, 0, 150000}}); // 3D histograms: nGlobalTracks with cls567 as y-axis, V0A as x-axis: - const AxisSpec axisNtracksPV{160, -0.5, 4000 - 0.5, "n ITS PV tracks"}; - const AxisSpec axisNtracksPVTPC{120, -0.5, 3000 - 0.5, "n ITS-TPC PV tracks"}; - const AxisSpec axisNtracksTPConly{120, -0.5, 6000 - 0.5, "n TPC-only tracks"}; + const AxisSpec axisNtracksPV{200, -0.5, 5000 - 0.5, "n ITS PV tracks"}; + const AxisSpec axisNtracksPVTPC{160, -0.5, 4000 - 0.5, "n ITS-TPC PV tracks"}; + const AxisSpec axisNtracksTPConly{160, -0.5, 8000 - 0.5, "n TPC-only tracks"}; const AxisSpec axisMultV0AForOccup{20, 0., static_cast(200000), "mult V0A"}; const AxisSpec axisOccupancyTracks{150, 0., 15000, "occupancy (n ITS tracks weighted)"}; histos.add("occupancyQA/hNumTracksPV_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNtracksPV, axisOccupancyTracks}); histos.add("occupancyQA/hNumTracksPVTPC_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNtracksPVTPC, axisOccupancyTracks}); + histos.add("occupancyQA/hNumTracksPVTPCLooseCuts_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNtracksPVTPC, axisOccupancyTracks}); + histos.add("occupancyQA/hNumTracksITS_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNtracksPV, axisOccupancyTracks}); + histos.add("occupancyQA/hNumTracksITSTPC_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNtracksPVTPC, axisOccupancyTracks}); + histos.add("occupancyQA/hNumTracksPV_vs_V0A_vs_occupancy_NarrowDeltaTimeCut", "", kTH3F, {axisMultV0AForOccup, axisNtracksPV, axisOccupancyTracks}); + histos.add("occupancyQA/hNumTracksPVTPC_vs_V0A_vs_occupancy_NarrowDeltaTimeCut", "", kTH3F, {axisMultV0AForOccup, axisNtracksPVTPC, axisOccupancyTracks}); + // requested by TPC experts: nTPConly tracks vs occupancy histos.add("occupancyQA/hNumTracksTPConly_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNtracksTPConly, axisOccupancyTracks}); histos.add("occupancyQA/hNumTracksTPConlyNoITS_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNtracksTPConly, axisOccupancyTracks}); - + // request from experts to add track properties vs occupancy, to compare data vs MC + const AxisSpec axisOccupancyForTrackQA{60, 0., 15000, "occupancy (n ITS tracks weighted)"}; + const AxisSpec axisNTPCcls{150, 0, 150, "n TPC clusters"}; + histos.add("occupancyQA/tpcNClsFound_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNTPCcls, axisOccupancyForTrackQA}); + histos.add("occupancyQA/tpcNClsFindable_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNTPCcls, axisOccupancyForTrackQA}); + histos.add("occupancyQA/tpcNClsShared_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNTPCcls, axisOccupancyForTrackQA}); + histos.add("occupancyQA/tpcNCrossedRows_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisNTPCcls, axisOccupancyForTrackQA}); + const AxisSpec axisChi2TPC{150, 0, 15, "chi2Ncl TPC"}; + histos.add("occupancyQA/tpcChi2_vs_V0A_vs_occupancy", "", kTH3F, {axisMultV0AForOccup, axisChi2TPC, axisOccupancyForTrackQA}); + + // ITS in-ROF occupancy histos.add("occupancyQA/hITSTracks_ev1_vs_ev2_2coll_in_ROF", ";nITStracks event #1;nITStracks event #2", kTH2D, {{200, 0., 6000}, {200, 0., 6000}}); histos.add("occupancyQA/hITSTracks_ev1_vs_ev2_2coll_in_ROF_UPC", ";nITStracks event #1;nITStracks event #2", kTH2D, {{41, -0.5, 40.5}, {41, -0.5, 40.5}}); histos.add("occupancyQA/hITSTracks_ev1_vs_ev2_2coll_in_ROF_nonUPC", ";nITStracks event #1;nITStracks event #2", kTH2D, {{200, 0., 6000}, {200, 0., 6000}}); @@ -586,10 +602,10 @@ struct EventSelectionQaTask { auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), run); // first bc of the first orbit bcSOR = runInfo.orbitSOR * nBCsPerOrbit; - // duration of TF in bcs - nBCsPerTF = runInfo.orbitsPerTF * nBCsPerOrbit; // number of orbits per TF nOrbitsPerTF = runInfo.orbitsPerTF; + // duration of TF in bcs + nBCsPerTF = nOrbitsPerTF * nBCsPerOrbit; // first orbit orbitSOR = runInfo.orbitSOR; // total number of orbits @@ -604,7 +620,8 @@ struct EventSelectionQaTask { auto alppar = ccdb->getForTimeStamp>("ITS/Config/AlpideParam", ts); rofOffset = alppar->roFrameBiasInBC; rofLength = alppar->roFrameLengthInBC; - LOGP(debug, "rofOffset={} rofLength={}", rofOffset, rofLength); + LOGP(info, "rofOffset={} rofLength={}", rofOffset, rofLength); + LOGP(info, "nOrbitsPerTF={} nBCsPerTF={}", nOrbitsPerTF, nBCsPerTF); // bc patterns auto grplhcif = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", (tsSOR + tsEOR) / 2); @@ -719,7 +736,7 @@ struct EventSelectionQaTask { double minSec = floor(tsSOR / 1000.); double maxSec = ceil(tsEOR / 1000.); - const AxisSpec axisSeconds{static_cast(maxSec - minSec), minSec, maxSec, "seconds"}; + const AxisSpec axisSeconds{maxSec - minSec < 5000 ? static_cast(maxSec - minSec) : 5000, minSec, maxSec, "seconds"}; const AxisSpec axisBcDif{600, -300., 300., "bc difference"}; histos.add("hSecondsTVXvsBcDif", "", kTH2F, {axisSeconds, axisBcDif}); histos.add("hSecondsTVXvsBcDifAll", "", kTH2F, {axisSeconds, axisBcDif}); @@ -1115,7 +1132,16 @@ struct EventSelectionQaTask { // int nTPConlyWithDeDxCut = 0; int nTPConlyNoITS = 0; int nContributorsAfterEtaTPCCuts = 0; + int nContributorsAfterEtaTPCLooseCuts = 0; + + int nTracksITS = 0; + int nTracksITSTPC = 0; + bool isTVX = col.selection_bit(kIsTriggerTVX); + + int occupancyByTracks = col.trackOccupancyInTimeRange(); + float occupancyByFT0C = col.ft0cOccupancyInTimeRange(); + for (const auto& track : tracksGrouped) { int trackBcDiff = bcDiff + track.trackTime() / o2::constants::lhc::LHCBunchSpacingNS; @@ -1127,6 +1153,14 @@ struct EventSelectionQaTask { nTPConlyNoITS++; } + if (std::fabs(track.eta()) < 0.8 && track.pt() > 0.2) { + if (track.hasITS()) { + nTracksITS++; + if (track.hasTPC()) + nTracksITSTPC++; + } + } + if (!track.isPVContributor()) continue; @@ -1136,7 +1170,22 @@ struct EventSelectionQaTask { // high-quality contributors for ROF border QA and occupancy study if (std::fabs(track.eta()) < 0.8 && track.pt() > 0.2 && track.itsNCls() >= 5) { nPV++; - if (track.tpcNClsFound() > 70 && track.tpcNClsCrossedRows() > 80 && track.itsChi2NCl() < 36 && track.tpcChi2NCl() < 4) { + if (track.hasTPC()) { + nContributorsAfterEtaTPCLooseCuts++; + + if (!isLowFlux && col.sel8() && col.selection_bit(kNoSameBunchPileup) && fabs(col.posZ()) < 10 && occupancyByTracks >= 0) { + histos.fill(HIST("occupancyQA/tpcNClsFound_vs_V0A_vs_occupancy"), multV0A, track.tpcNClsFound(), occupancyByTracks); + histos.fill(HIST("occupancyQA/tpcNClsFindable_vs_V0A_vs_occupancy"), multV0A, track.tpcNClsFindable(), occupancyByTracks); + histos.fill(HIST("occupancyQA/tpcNClsShared_vs_V0A_vs_occupancy"), multV0A, track.tpcNClsShared(), occupancyByTracks); + histos.fill(HIST("occupancyQA/tpcChi2_vs_V0A_vs_occupancy"), multV0A, track.tpcChi2NCl(), occupancyByTracks); + int tpcNClsFindableMinusCrossedRowsCorrected = track.tpcNClsFindableMinusCrossedRows(); + // correct for a buggy behaviour due to int8 and uint8 difference: + if (tpcNClsFindableMinusCrossedRowsCorrected < -70) + tpcNClsFindableMinusCrossedRowsCorrected += 256; + histos.fill(HIST("occupancyQA/tpcNCrossedRows_vs_V0A_vs_occupancy"), multV0A, track.tpcNClsFindable() - tpcNClsFindableMinusCrossedRowsCorrected, occupancyByTracks); + } + } // end of hasTPC + if (col.sel8() && fabs(col.posZ()) < 10 && track.tpcNClsFound() > 50 && track.tpcNClsCrossedRows() > 80 && track.itsChi2NCl() < 36 && track.tpcChi2NCl() < 4) { nContributorsAfterEtaTPCCuts++; // ROF border QA histos.fill(HIST("ITSROFborderQA/hFoundBC_kTVX_nITSlayers_for_ITSTPCtracks"), localBC, track.itsNCls()); @@ -1160,15 +1209,20 @@ struct EventSelectionQaTask { histos.fill(HIST("hNcontribAfterCutsVsBcInTF"), bcInTF, nContributorsAfterEtaTPCCuts); - if (!isLowFlux && col.sel8() && fabs(col.posZ()) < 10) { - int occupancyByTracks = col.trackOccupancyInTimeRange(); + if (!isLowFlux && col.sel8() && col.selection_bit(kNoSameBunchPileup) && fabs(col.posZ()) < 10) { histos.fill(HIST("occupancyQA/hOccupancyByTracks"), occupancyByTracks); - float occupancyByFT0C = col.ft0cOccupancyInTimeRange(); histos.fill(HIST("occupancyQA/hOccupancyByFT0C"), occupancyByFT0C); if (occupancyByTracks >= 0) { histos.fill(HIST("occupancyQA/hOccupancyByFT0CvsByTracks"), occupancyByTracks, occupancyByFT0C); histos.fill(HIST("occupancyQA/hNumTracksPV_vs_V0A_vs_occupancy"), multV0A, nPV, occupancyByTracks); histos.fill(HIST("occupancyQA/hNumTracksPVTPC_vs_V0A_vs_occupancy"), multV0A, nContributorsAfterEtaTPCCuts, occupancyByTracks); + histos.fill(HIST("occupancyQA/hNumTracksPVTPCLooseCuts_vs_V0A_vs_occupancy"), multV0A, nContributorsAfterEtaTPCLooseCuts, occupancyByTracks); + histos.fill(HIST("occupancyQA/hNumTracksITS_vs_V0A_vs_occupancy"), multV0A, nTracksITS, occupancyByTracks); + histos.fill(HIST("occupancyQA/hNumTracksITSTPC_vs_V0A_vs_occupancy"), multV0A, nTracksITSTPC, occupancyByTracks); + if (col.selection_bit(kNoCollInTimeRangeNarrow)) { + histos.fill(HIST("occupancyQA/hNumTracksPV_vs_V0A_vs_occupancy_NarrowDeltaTimeCut"), multV0A, nPV, occupancyByTracks); + histos.fill(HIST("occupancyQA/hNumTracksPVTPC_vs_V0A_vs_occupancy_NarrowDeltaTimeCut"), multV0A, nContributorsAfterEtaTPCCuts, occupancyByTracks); + } histos.fill(HIST("occupancyQA/hNumTracksTPConly_vs_V0A_vs_occupancy"), multV0A, nTPConly, occupancyByTracks); histos.fill(HIST("occupancyQA/hNumTracksTPConlyNoITS_vs_V0A_vs_occupancy"), multV0A, nTPConlyNoITS, occupancyByTracks); @@ -1178,7 +1232,7 @@ struct EventSelectionQaTask { continue; if (std::fabs(track.eta()) < 0.8 && track.pt() > 0.2 && track.itsNCls() >= 5) { float signedP = track.sign() * track.tpcInnerParam(); - if (std::fabs(signedP) > 0.38 && std::fabs(signedP) < 0.4 && track.tpcNClsFound() > 70 && track.tpcNClsCrossedRows() > 80 && track.itsChi2NCl() < 36 && track.tpcChi2NCl() < 4) { + if (std::fabs(signedP) > 0.38 && std::fabs(signedP) < 0.4 && track.tpcNClsFound() > 50 && track.tpcNClsCrossedRows() > 80 && track.itsChi2NCl() < 36 && track.tpcChi2NCl() < 4) { float dEdx = track.tpcSignal(); histos.fill(HIST("occupancyQA/dEdx_vs_centr_vs_occup_narrow_p_win"), nPV, occupancyByTracks, dEdx); } diff --git a/DPG/Tasks/AOTEvent/lightIonsEvSelQa.cxx b/DPG/Tasks/AOTEvent/lightIonsEvSelQa.cxx new file mode 100644 index 00000000000..2d62bba9221 --- /dev/null +++ b/DPG/Tasks/AOTEvent/lightIonsEvSelQa.cxx @@ -0,0 +1,1658 @@ +// 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 detectorOccupancyQa.cxx +/// \brief Occupancy QA task +/// +/// \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 + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::evsel; + +using BCsRun3 = soa::Join; +using ColEvSels = soa::Join; //, aod::CentFT0Cs>; +// using FullTracksIU = soa::Join; +using FullTracksIU = soa::Join; + +struct LightIonsEvSelQa { + Configurable confCutMinTPCcls{"MinNumTPCcls", 50, "min number of TPC clusters for a current event"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable nBinsTracks{"nBinsTracks", 450, "N bins in n tracks histo"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable nMaxTracks{"nMaxTracks", 450, "N max in n tracks histo"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable nMaxGlobalTracks{"nMaxGlobalTracks", 450, "N max in n tracks histo"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable nBinsMultFwd{"nBinsMultFwd", 1000, "N bins in mult fwd histo"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable nMaxMultFwd{"nMaxMultFwd", 100000, "N max in mult fwd histo"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable timeBinWidthInSec{"TimeBinWidthInSec", 10, "Width of time bins in seconds"}; // o2-linter: disable=name/configurable (temporary fix) + + Configurable nSigmaForVzDiff{"nSigmaForVzDiff", 2.5, "n +/- sigma for diff vZ"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable safetyDiffVzMargin{"SafetyDiffVzMargin", 0.5, "margin for diff vZ, cm"}; // o2-linter: disable=name/configurable (temporary fix) + + Configurable confUseDiffVzCutFromEvSel{"UseDiffVzCutFromEvSel", 0, "0 - custom diffVz cut from this task, 1 - cut from event selection"}; // o2-linter: disable=name/configurable (temporary fix) + + uint64_t minGlobalBC = 0; + Service ccdb; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + bool* applySelection = NULL; + int nBCsPerOrbit = 3564; + int lastRunNumber = -1; + double maxSec = 1; + double minSec = 0; + int64_t bcSOR = 0; // global bc of the start of the first orbit, setting 0 by default for unanchored MC + int64_t nBCsPerTF = 32 * nBCsPerOrbit; // duration of TF in bcs, should be 128*3564 or 32*3564, setting 128 orbits by default sfor unanchored MC + + // save time "slices" for several collisions for QA + bool flagFillQAtimeOccupHist = false; + int nCollisionsForTimeBinQA = 40; + int counterQAtimeOccupHistos = 0; + + void init(InitContext&) + { + // ccdb->setURL("http://ccdb-test.cern.ch:8080"); + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + // const AxisSpec axisBCinTF{static_cast(nBCsPerTF), 0, static_cast(nBCsPerTF), "bc in TF"}; + // histos.add("hNcolVsBcInTF/hNcolVsBcInTF", ";bc in TF; n collisions", kTH1F, {axisBCinTF}); + // histos.add("hNcolVsBcInTF/hNcolVsBcInTF_vertexTOFmatched", ";bc in TF; n collisions", kTH1F, {axisBCinTF}); + + // ############## + const AxisSpec axisBCs{nBCsPerOrbit, 0., static_cast(nBCsPerOrbit), ""}; + + histos.add("bcQA/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("bcQA/pastActivity/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("bcQA/futureActivity/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("bcQA/noPastActivity/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("bcQA/noFutureActivity/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("bcQA/noPastFutureActivity/hBcFV0", "", kTH1F, {axisBCs}); + + histos.add("bcQA/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("bcQA/pastActivity/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("bcQA/futureActivity/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("bcQA/noPastActivity/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("bcQA/noFutureActivity/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("bcQA/noPastFutureActivity/hBcFT0", "", kTH1F, {axisBCs}); + + histos.add("bcQA/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("bcQA/pastActivity/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("bcQA/futureActivity/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("bcQA/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("bcQA/pastActivity/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("bcQA/futureActivity/hBcZDC", "", kTH1F, {axisBCs}); + + histos.add("bcQA/specFT0bits/hBc_kIsActiveSideA", "", kTH1F, {axisBCs}); + histos.add("bcQA/specFT0bits/hBc_kIsActiveSideC", "", kTH1F, {axisBCs}); + histos.add("bcQA/specFT0bits/hBc_kIsFlangeEvent", "", kTH1F, {axisBCs}); + + histos.add("bcQA/specFT0bits/hBc_kIsActiveSideA_inTVX", "", kTH1F, {axisBCs}); + histos.add("bcQA/specFT0bits/hBc_kIsActiveSideC_inTVX", "", kTH1F, {axisBCs}); + histos.add("bcQA/specFT0bits/hBc_kIsFlangeEvent_inTVX", "", kTH1F, {axisBCs}); + + const AxisSpec axisNtracks{nBinsTracks, -0.5, nMaxTracks - 0.5, "n tracks"}; + const AxisSpec axisNtracksGlobal{nBinsTracks, -0.5, nMaxGlobalTracks - 0.5, "n tracks"}; + const AxisSpec axisMultV0A{nBinsMultFwd, 0., static_cast(nMaxMultFwd), "mult V0A"}; + const AxisSpec axisMultFT0A{nBinsMultFwd, 0., static_cast(nMaxMultFwd * 0.4), "mult FT0C"}; + const AxisSpec axisMultFT0C{nBinsMultFwd, 0., static_cast(nMaxMultFwd * 0.15), "mult FT0C"}; + const AxisSpec axisMultT0M{nBinsMultFwd * 2, 0., static_cast(nMaxMultFwd * 0.4), "mult FT0M"}; + + const AxisSpec axisMultT0MlargeBins{nBinsMultFwd, 0., static_cast(nMaxMultFwd * 0.75), "mult FT0M"}; + histos.add("multT0M_vs_multSumFT0", ";multT0M;multT0M_uncorrected", kTH2F, {axisMultT0MlargeBins, axisMultT0MlargeBins}); + + const AxisSpec axisVtxZ{800, -20., 20., ""}; + const AxisSpec axisBcDiff{600, -300., 300., "bc difference"}; + + const AxisSpec axisNcontrib{801, -0.5, 800.5, "n contributors"}; + const AxisSpec axisColTimeRes{1500, 0., 1500., "collision time resolution (ns)"}; + + AxisSpec axisVertexChi2{100, 0, 500, "Chi2 of vertex fit"}; + AxisSpec axisVertexChi2perContrib{100, 0, 10, "Chi2 of vertex fit"}; + + histos.add("noSpecSelections/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hBcOrigNoSel8", "", kTH1F, {axisBCs}); + // histos.add("noSpecSelections/hBcColNoSel8TOF", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noSpecSelections/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noSpecSelections/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noSpecSelections/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noSpecSelections/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noSpecSelections/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noSpecSelections/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noSpecSelections/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noSpecSelections/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noSpecSelections/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noSpecSelections/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noSpecSelections/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noSpecSelections/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noSpecSelections/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU/hBcOrigNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noPU/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_pvTOFmatched/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTOFmatched/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTOFmatched/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTOFmatched/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTOFmatched/hBcFV0", "", kTH1F, {axisBCs}); + // histos.add("noPU_pvTOFmatched/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTOFmatched/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTOFmatched/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_pvTOFmatched/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_pvTOFmatched/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_pvTOFmatched/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_pvTOFmatched/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_pvTOFmatched/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_pvTOFmatched/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_pvTOFmatched/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_pvTOFmatched/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_pvTOFmatched/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_pvTOFmatched/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_pvTOFmatched/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_pvTOFmatched/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_pvTRDmatched/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTRDmatched/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTRDmatched/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTRDmatched/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTRDmatched/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTRDmatched/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTRDmatched/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_pvTRDmatched/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_pvTRDmatched/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_pvTRDmatched/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_pvTRDmatched/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_pvTRDmatched/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_pvTRDmatched/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_pvTRDmatched/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_pvTRDmatched/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_pvTRDmatched/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_pvTRDmatched/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_pvTRDmatched/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_pvTRDmatched/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_notTRDmatched/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_notTRDmatched/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_notTRDmatched/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_notTRDmatched/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_notTRDmatched/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_notTRDmatched/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_notTRDmatched/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_notTRDmatched/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_notTRDmatched/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_notTRDmatched/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_notTRDmatched/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_notTRDmatched/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_notTRDmatched/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_notTRDmatched/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_notTRDmatched/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_notTRDmatched/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_notTRDmatched/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_notTRDmatched/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_pvTOFmatched_notTRDmatched/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_pvTOFmatched_notTRDmatched/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_pvTOFmatched_notTRDmatched/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_pvTOFmatched_notTRDmatched/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("bcDiffWrtClosestTVXCut/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("bcDiffWrtClosestTVXCut/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("bcDiffWrtClosestTVXCut/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("bcDiffWrtClosestTVXCut/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("bcDiffWrtClosestTVXCut/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("bcDiffWrtClosestTVXCut/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("bcDiffWrtClosestTVXCut/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("bcDiffWrtClosestTVXCut/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("bcDiffWrtClosestTVXCut/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("bcDiffWrtClosestTVXCut/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("bcDiffWrtClosestTVXCut/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + // histos.add("bcDiffWrtClosestTVXCut/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + // histos.add("bcDiffWrtClosestTVXCut/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + // histos.add("bcDiffWrtClosestTVXCut/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("bcDiffWrtClosestTVXCut/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("bcDiffWrtClosestTVXCut/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("bcDiffWrtClosestTVXCut/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("bcDiffWrtClosestTVXCut/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_bcDiffWrtOriginalBcCut/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_bcDiffWrtOriginalBcCut/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_bcDiffWrtOriginalBcCut/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_bcDiffWrtOriginalBcCut/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + // histos.add("noPU_bcDiffWrtOriginalBcCut/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + // histos.add("noPU_bcDiffWrtOriginalBcCut/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + // histos.add("noPU_bcDiffWrtOriginalBcCut/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_bcDiffWrtOriginalBcCut/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_goodVertexChi2/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVertexChi2/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVertexChi2/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVertexChi2/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVertexChi2/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVertexChi2/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVertexChi2/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_goodVertexChi2/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_goodVertexChi2/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_goodVertexChi2/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_goodVertexChi2/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + // histos.add("noPU_goodVertexChi2/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + // histos.add("noPU_goodVertexChi2/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + // histos.add("noPU_goodVertexChi2/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_goodVertexChi2/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_goodVertexChi2/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_goodVertexChi2/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_goodVertexChi2/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("narrowTimeVeto/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("narrowTimeVeto/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("narrowTimeVeto/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("narrowTimeVeto/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("narrowTimeVeto/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("narrowTimeVeto/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("narrowTimeVeto/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("narrowTimeVeto/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("narrowTimeVeto/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("narrowTimeVeto/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("narrowTimeVeto/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("narrowTimeVeto/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("narrowTimeVeto/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("narrowTimeVeto/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("narrowTimeVeto/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("narrowTimeVeto/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("narrowTimeVeto/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("narrowTimeVeto/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("strictTimeVeto/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("strictTimeVeto/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("strictTimeVeto/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("strictTimeVeto/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("strictTimeVeto/hBcFV0", "", kTH1F, {axisBCs}); + // histos.add("strictTimeVeto/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("strictTimeVeto/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("strictTimeVeto/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("strictTimeVeto/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("strictTimeVeto/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("strictTimeVeto/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("strictTimeVeto/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("strictTimeVeto/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("strictTimeVeto/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("strictTimeVeto/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("strictTimeVeto/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("strictTimeVeto/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("strictTimeVeto/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("strictTimeVeto/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noCollSameROF/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noCollSameROF/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noCollSameROF/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noCollSameROF/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noCollSameROF/hBcFV0", "", kTH1F, {axisBCs}); + // histos.add("noCollSameROF/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noCollSameROF/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noCollSameROF/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noCollSameROF/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noCollSameROF/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noCollSameROF/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noCollSameROF/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noCollSameROF/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noCollSameROF/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noCollSameROF/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noCollSameROF/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noCollSameROF/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noCollSameROF/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noCollSameROF/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("lowMultCut/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("lowMultCut/hBcOrigNoSel8", "", kTH1F, {axisBCs}); + histos.add("lowMultCut/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + + histos.add("noPU_lowMultCut/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_lowMultCut/hBcOrigNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_lowMultCut/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_lowMultCut/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_lowMultCut/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_lowMultCut/hBcFV0", "", kTH1F, {axisBCs}); + // histos.add("noPU_lowMultCut/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noPU_lowMultCut/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_lowMultCut/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_lowMultCut/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_lowMultCut/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_lowMultCut/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_lowMultCut/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_lowMultCut/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_lowMultCut/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_lowMultCut/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_lowMultCut/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_lowMultCut/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_lowMultCut/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_lowMultCut/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_lowMultCut/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("highMultCloudCut/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("highMultCloudCut/hBcOrigNoSel8", "", kTH1F, {axisBCs}); + histos.add("highMultCloudCut/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + + histos.add("noPU_highMultCloudCut/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_highMultCloudCut/hBcOrigNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_highMultCloudCut/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_highMultCloudCut/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_highMultCloudCut/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_highMultCloudCut/hBcFV0", "", kTH1F, {axisBCs}); + // histos.add("noPU_highMultCloudCut/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noPU_highMultCloudCut/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_highMultCloudCut/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_highMultCloudCut/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_highMultCloudCut/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_highMultCloudCut/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_highMultCloudCut/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_highMultCloudCut/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_highMultCloudCut/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_highMultCloudCut/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_highMultCloudCut/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_highMultCloudCut/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_highMultCloudCut/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_highMultCloudCut/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_highMultCloudCut/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_badVzDiff/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_badVzDiff/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_badVzDiff/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_badVzDiff/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_badVzDiff/hBcFV0", "", kTH1F, {axisBCs}); + // histos.add("noPU_badVzDiff/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noPU_badVzDiff/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_badVzDiff/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_badVzDiff/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_badVzDiff/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_badVzDiff/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_badVzDiff/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_badVzDiff/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_badVzDiff/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_badVzDiff/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_badVzDiff/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_badVzDiff/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_badVzDiff/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_badVzDiff/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_badVzDiff/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_goodVzDiff/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_goodVzDiff/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_goodVzDiff/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_goodVzDiff/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_goodVzDiff/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_goodVzDiff/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_goodVzDiff/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_goodVzDiff/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_goodVzDiff/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_goodVzDiff/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_goodVzDiff_narrowTimeVeto/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_goodVzDiff_narrowTimeVeto/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_goodVzDiff_strictTimeVeto/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_goodVzDiff_strictTimeVeto/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_goodVzDiff_strictTimeVeto/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_goodVzDiff_strictTimeVeto/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_goodVzDiff_strictTimeVeto/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff_strictTimeVeto/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff_strictTimeVeto/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hVertexChi2VsNcontrib", "", kTH2F, {axisNcontrib, axisVertexChi2perContrib}); + histos.add("noPU_goodVzDiff_strictTimeVeto/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_noPastActivity/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_noPastActivity/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_noPastActivity/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_noPastActivity/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_noPastActivity/hBcFV0", "", kTH1F, {axisBCs}); + // histos.add("noPU_noPastActivity/hBcFDD", "", kTH1F, {axisBCs}); + histos.add("noPU_noPastActivity/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_noPastActivity/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_noPastActivity/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_noPastActivity/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_noPastActivity/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_noPastActivity/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + // histos.add("noPU_noPastActivity/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + // histos.add("noPU_noPastActivity/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + // histos.add("noPU_noPastActivity/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_noPastActivity/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_noPastActivity/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_noPastActivity/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_noPastActivity/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_noFT0activityNearby/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_noFT0activityNearby/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_noFT0activityNearby/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_noFT0activityNearby/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_noFT0activityNearby/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_noFT0activityNearby/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_noFT0activityNearby/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_noFT0activityNearby/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_noFT0activityNearby/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_noFT0activityNearby/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_noFT0activityNearby/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + // histos.add("noPU_noFT0activityNearby/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + // histos.add("noPU_noFT0activityNearby/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + // histos.add("noPU_noFT0activityNearby/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_noFT0activityNearby/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_noFT0activityNearby/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_noFT0activityNearby/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_noFT0activityNearby/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_cutByVzDiff_pvTOF/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_pvTOF/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_pvTOF/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_pvTOF/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_pvTOF/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_pvTOF/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_pvTOF/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_cutByVzDiff_pvTOF/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_cutByVzDiff_pvTOF/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_cutByVzDiff_pvTOF/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_cutByVzDiff_pvTOF/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + histos.add("noPU_cutByVzDiff_pvTOF/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + histos.add("noPU_cutByVzDiff_pvTOF/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + histos.add("noPU_cutByVzDiff_pvTOF/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_cutByVzDiff_pvTOF/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_cutByVzDiff_pvTOF/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_cutByVzDiff_pvTOF/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_cutByVzDiff_pvTOF/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hBcColNoSel8", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hBcTVX", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hBcOrig", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hBcFT0", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hBcFV0", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hBcZDC", "", kTH1F, {axisBCs}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hVtxFT0VsVtxCol", "", kTH2F, {axisVtxZ, axisVtxZ}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hVtxFT0MinusVtxColVsMultT0M", "", kTH2F, {axisVtxZ, axisMultT0M}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/nTracksPV_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracks}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/nTracksPV_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracks}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/nTracksPV_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracks}); + // histos.add("noPU_cutByVzDiff_noFT0activityNearby/nTracksGlobal_vs_V0A", "", kTH2F, {axisMultV0A, axisNtracksGlobal}); + // histos.add("noPU_cutByVzDiff_noFT0activityNearby/nTracksGlobal_vs_T0A", "", kTH2F, {axisMultFT0A, axisNtracksGlobal}); + // histos.add("noPU_cutByVzDiff_noFT0activityNearby/nTracksGlobal_vs_T0C", "", kTH2F, {axisMultFT0C, axisNtracksGlobal}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hTVXvsBcDiffwrtOrigBc", "", kTH1F, {axisBcDiff}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hColTimeResVsNcontrib", "", kTH2F, {axisNcontrib, axisColTimeRes}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hColBcDiffVsNcontrib", "", kTH2F, {axisNcontrib, axisBcDiff}); + histos.add("noPU_cutByVzDiff_noFT0activityNearby/hNPVvsNch", "", kTH2F, {axisNcontrib, axisNcontrib}); + + histos.add("hNcontribColFromData", "", kTH1F, {axisNcontrib}); + histos.add("hNcontribAccFromData", "", kTH1F, {axisNcontrib}); + } + + Preslice perCollision = aod::track::collisionId; + + int32_t findClosest(int64_t globalBC, 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; + } + + // ##### + void processRun3( + ColEvSels const& cols, + FullTracksIU const& tracks, + BCsRun3 const& bcs, + aod::FT0s const&) + { + int runNumber = bcs.iteratorAt(0).runNumber(); + if (runNumber != lastRunNumber) { + lastRunNumber = runNumber; // do it only once + + int64_t tsSOR = 0; // dummy start-of-run timestamp + int64_t tsEOR = 1; // dummy end-of-run timestamp + + if (runNumber >= 500000) { + auto runInfo = o2::parameters::AggregatedRunInfo::buildAggregatedRunInfo(o2::ccdb::BasicCCDBManager::instance(), runNumber); + // first bc of the first orbit + bcSOR = runInfo.orbitSOR * o2::constants::lhc::LHCMaxBunches; + // duration of TF in bcs + nBCsPerTF = runInfo.orbitsPerTF * o2::constants::lhc::LHCMaxBunches; + + // start-of-run timestamp + tsSOR = runInfo.sor; + // end-of-run timestamp + tsEOR = runInfo.eor; + + LOGP(info, "bcSOR = {}, nBCsPerTF = {}", bcSOR, nBCsPerTF); + } + + minSec = floor(tsSOR / 1000.); + maxSec = ceil(tsEOR / 1000.); + int nTimeBins = static_cast((maxSec - minSec) / timeBinWidthInSec); + double timeInterval = nTimeBins * timeBinWidthInSec; + + const AxisSpec axisSeconds{nTimeBins, 0, timeInterval, "seconds"}; + histos.add("hSecondsCollisions/sel8", "", kTH1F, {axisSeconds}); + histos.add("hSecondsCollisions/noPU", "", kTH1F, {axisSeconds}); + histos.add("hSecondsCollisions/noPU_underLine", "", kTH1F, {axisSeconds}); + histos.add("hSecondsCollisions/noPU_grassOnTheRight", "", kTH1F, {axisSeconds}); + histos.add("hSecondsCollisions/noPU_good", "", kTH1F, {axisSeconds}); + + const AxisSpec axisDiffMeanVz{80, -4, 4, ""}; + histos.add("hSecondsCollisions/noPU_meanDiffVz", "", kTH2F, {axisSeconds, axisDiffMeanVz}); + histos.add("hSecondsCollisions/noPU_meanDiffVz_lowMult", "", kTH2F, {axisSeconds, axisDiffMeanVz}); + histos.add("hSecondsCollisions/noPU_meanDiffVz_highMult", "", kTH2F, {axisSeconds, axisDiffMeanVz}); + + } // end of runNumber check + + // vectors of TVX flags used for past-future studies + int nBCs = bcs.size(); + std::vector vIsTVX(nBCs, 0); + std::vector vGlobalBCs(nBCs, 0); + + std::vector vPastActivity(nBCs, 0); + std::vector vFutureActivity(nBCs, 0); + std::vector vNearbyFT0activity(nBCs, 0); + + // create maps from globalBC to bc index for TVX or FT0-OR fired bcs + // to be used for closest TVX (FT0-OR) searches + std::map mapGlobalBcWithTVX; + std::map mapGlobalBcWithTOR; + + // ### BC loop + for (const auto& bc : bcs) { + uint64_t globalBC = bc.globalBC(); + + int indexBc = bc.globalIndex(); + + if (bc.selection_bit(kIsBBT0A) || bc.selection_bit(kIsBBT0C)) { + mapGlobalBcWithTOR[globalBC] = indexBc; + } + if (bc.selection_bit(kIsTriggerTVX)) { + mapGlobalBcWithTVX[globalBC] = indexBc; + } + + // fill TVX flags for past-future searches + vIsTVX[indexBc] = bc.selection_bit(kIsTriggerTVX); + vGlobalBCs[indexBc] = globalBC; + + // ### checking nearby activities + int deltaIndex = 0; // backward move counts + int deltaBC = 0; // current difference wrt globalBC + int maxDeltaBC = 30; // maximum difference + + bool nearbyFT0activity = 0; + + // past + bool pastActivityFT0 = 0; + // bool pastActivityFDD = 0; + bool pastActivityFV0 = 0; + while (deltaBC < maxDeltaBC) { + deltaIndex++; + if (bc.globalIndex() - deltaIndex < 0) { + break; + } + const auto& bcPast = bcs.iteratorAt(bc.globalIndex() - deltaIndex); + deltaBC = globalBC - bcPast.globalBC(); + if (deltaBC < maxDeltaBC) { + pastActivityFT0 |= bcPast.has_ft0(); + pastActivityFV0 |= bcPast.has_fv0a(); + // pastActivityFDD |= bcPast.has_fdd(); + } + if (deltaBC < 2) { + if (bcPast.has_ft0()) { + std::bitset<8> triggers = bcPast.ft0().triggerMask(); + nearbyFT0activity |= (triggers[o2::ft0::RecPoints::ETriggerBits::kIsActiveSideA] || triggers[o2::ft0::RecPoints::ETriggerBits::kIsActiveSideC]); + } + } + } + // bool pastActivity = pastActivityFT0 | pastActivityFV0 | pastActivityFDD; + bool pastActivity = pastActivityFT0 | pastActivityFV0; // | pastActivityFDD; + vPastActivity[indexBc] = pastActivity; + + // future + deltaIndex = 0; + deltaBC = 0; + bool futureActivityFT0 = 0; + bool futureActivityFDD = 0; + bool futureActivityFV0 = 0; + while (deltaBC < maxDeltaBC) { + deltaIndex++; + if (bc.globalIndex() + deltaIndex >= bcs.size()) { + break; + } + const auto& bcFuture = bcs.iteratorAt(bc.globalIndex() + deltaIndex); + deltaBC = bcFuture.globalBC() - globalBC; + if (deltaBC < maxDeltaBC) { + futureActivityFT0 |= bcFuture.has_ft0(); + futureActivityFV0 |= bcFuture.has_fv0a(); + futureActivityFDD |= bcFuture.has_fdd(); + } + if (deltaBC < 2) { + if (bcFuture.has_ft0()) { + std::bitset<8> triggers = bcFuture.ft0().triggerMask(); + nearbyFT0activity |= (triggers[o2::ft0::RecPoints::ETriggerBits::kIsActiveSideA] || triggers[o2::ft0::RecPoints::ETriggerBits::kIsActiveSideC]); + } + } + } + bool futureActivity = futureActivityFT0 | futureActivityFV0 | futureActivityFDD; + vFutureActivity[indexBc] = futureActivity; + vNearbyFT0activity[indexBc] = nearbyFT0activity; + + // monitor BCs with nearby activity: + + int localBC = globalBC % nBCsPerOrbit; + if (bc.has_fv0a()) { + histos.fill(HIST("bcQA/hBcFV0"), localBC); + if (pastActivity) + histos.fill(HIST("bcQA/pastActivity/hBcFV0"), localBC); + if (futureActivity) + histos.fill(HIST("bcQA/futureActivity/hBcFV0"), localBC); + if (!pastActivity) + histos.fill(HIST("bcQA/noPastActivity/hBcFV0"), localBC); + if (!futureActivity) + histos.fill(HIST("bcQA/noFutureActivity/hBcFV0"), localBC); + if (!pastActivity && !futureActivity) + histos.fill(HIST("bcQA/noPastFutureActivity/hBcFV0"), localBC); + } + if (bc.has_ft0()) { + histos.fill(HIST("bcQA/hBcFT0"), localBC); + if (pastActivity) + histos.fill(HIST("bcQA/pastActivity/hBcFT0"), localBC); + if (futureActivity) + histos.fill(HIST("bcQA/futureActivity/hBcFT0"), localBC); + if (!pastActivity) + histos.fill(HIST("bcQA/noPastActivity/hBcFT0"), localBC); + if (!futureActivity) + histos.fill(HIST("bcQA/noFutureActivity/hBcFT0"), localBC); + if (!pastActivity && !futureActivity) + histos.fill(HIST("bcQA/noPastFutureActivity/hBcFT0"), localBC); + + // spec bits: + std::bitset<8> triggers = bc.ft0().triggerMask(); + bool isTVX = bc.selection_bit(kIsTriggerTVX); + if (triggers[o2::ft0::RecPoints::ETriggerBits::kIsActiveSideA]) { + histos.fill(HIST("bcQA/specFT0bits/hBc_kIsActiveSideA"), localBC); + if (isTVX) + histos.fill(HIST("bcQA/specFT0bits/hBc_kIsActiveSideA_inTVX"), localBC); + } + if (triggers[o2::ft0::RecPoints::ETriggerBits::kIsActiveSideC]) { + histos.fill(HIST("bcQA/specFT0bits/hBc_kIsActiveSideC"), localBC); + if (isTVX) + histos.fill(HIST("bcQA/specFT0bits/hBc_kIsActiveSideC_inTVX"), localBC); + } + if (triggers[o2::ft0::RecPoints::ETriggerBits::kIsFlangeEvent]) { + histos.fill(HIST("bcQA/specFT0bits/hBc_kIsFlangeEvent"), localBC); + if (isTVX) + histos.fill(HIST("bcQA/specFT0bits/hBc_kIsFlangeEvent_inTVX"), localBC); + } + } + if (bc.has_fdd()) { + histos.fill(HIST("bcQA/hBcFDD"), localBC); + if (pastActivity) + histos.fill(HIST("bcQA/pastActivity/hBcFDD"), localBC); + if (futureActivity) + histos.fill(HIST("bcQA/futureActivity/hBcFDD"), localBC); + } + if (bc.has_zdc()) { + histos.fill(HIST("bcQA/hBcZDC"), localBC); + if (pastActivity) + histos.fill(HIST("bcQA/pastActivity/hBcZDC"), localBC); + if (futureActivity) + histos.fill(HIST("bcQA/futureActivity/hBcZDC"), localBC); + } + + } // end of bc loop + + // ### collision loop + for (const auto& col : cols) { + if (std::abs(col.posZ()) > 10) + continue; + + const auto& foundBC = col.foundBC_as(); + uint64_t globalBC = foundBC.globalBC(); + // uint64_t orbit = globalBC / nBCsPerOrbit; + int localBC = globalBC % nBCsPerOrbit; + + int64_t ts = foundBC.timestamp(); + double secFromSOR = ts / 1000. - minSec; + + // search for nearest ft0a&ft0c entry + uint64_t globalOrigBC = col.bc_as().globalBC(); + int32_t indexClosestTVX = findClosest(globalOrigBC, mapGlobalBcWithTVX); + int bcToClosestTVXdiff = static_cast(globalOrigBC - vGlobalBCs[indexClosestTVX]); + + // selection decisions: + bool noPU = col.selection_bit(kNoSameBunchPileup); + bool pvTOFmatched = col.selection_bit(kIsVertexTOFmatched); + bool pvTRDmatched = col.selection_bit(kIsVertexTRDmatched); + bool narrowTimeVeto = col.selection_bit(kNoCollInTimeRangeNarrow); + bool strictTimeVeto = col.selection_bit(kNoCollInTimeRangeStrict); + bool noCollSameROF = col.selection_bit(kNoCollInRofStrict); + bool bcDiffWrtClosestTVXCut = (bcToClosestTVXdiff == 0); + + auto bcIndex = foundBC.globalIndex(); + // bool noNearbyActivity = (vPastActivity[bcIndex] == 0 && vFutureActivity[bcIndex] == 0); + bool noPastActivity = (vPastActivity[bcIndex] == 0); + + // ### count tracks of different types + int nPVtracks = 0; + int nGlobalTracksPV = 0; + int nGlobalTracksAll = 0; + // int nTOFtracks = 0; + auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); + for (const auto& track : tracksGrouped) { + if (track.itsNCls() < 5) + continue; + if (track.pt() < 0.2 || track.pt() > 10) + continue; + if (std::abs(track.eta()) > 0.8) + continue; + + if (track.hasITS() && track.hasTPC() && track.tpcNClsFound() > 50 && track.tpcNClsCrossedRows() > 50 && track.tpcChi2NCl() < 4) + nGlobalTracksAll++; + + if (!track.isPVContributor()) { + continue; + } + nPVtracks++; + if (track.hasITS() && track.hasTPC() && track.tpcNClsFound() > 50 && track.tpcNClsCrossedRows() > 50 && track.tpcChi2NCl() < 4) + nGlobalTracksPV++; + } // end of track loop + + histos.fill(HIST("hNcontribColFromData"), nPVtracks); + if (col.selection_bit(kIsTriggerTVX)) + histos.fill(HIST("hNcontribAccFromData"), nPVtracks); + + bool hasFT0 = foundBC.has_ft0(); + bool hasFV0A = foundBC.has_fv0a(); + + // bool noFT0activityNearby = false; + bool noFT0activityNearby = (vNearbyFT0activity[bcIndex] == 0); + // check kIsFlangeEvent + if (hasFT0) { + std::bitset<8> triggers = foundBC.ft0().triggerMask(); + if (triggers[o2::ft0::RecPoints::ETriggerBits::kIsFlangeEvent]) + noFT0activityNearby = false; + } + + float vZ = col.posZ(); + float vZft0 = hasFT0 ? foundBC.ft0().posZ() : -1000; + float diffVz = vZft0 - vZ; + + float multV0A = hasFV0A ? col.multFV0A() : 0; + + float multT0A = hasFT0 ? col.multFT0A() : 0; + float multT0C = hasFT0 ? col.multFT0C() : 0; + float multT0M = multT0A + multT0C; + if (hasFT0) { + float multT0A_uncorr = foundBC.ft0().sumAmpA(); + float multT0C_uncorr = foundBC.ft0().sumAmpC(); + float multT0M_uncorr = multT0A_uncorr + multT0C_uncorr; + + histos.fill(HIST("multT0M_vs_multSumFT0"), multT0M, multT0M_uncorr); + } + + // vZ diff (FT0 vs by tracks) + bool badVzDiff = 0; + if (confUseDiffVzCutFromEvSel) + badVzDiff = !col.selection_bit(kIsGoodZvtxFT0vsPV); + else { // tune by hand + float meanDiff = 0.0; // cm + // O-O + if (lastRunNumber == 564356) + meanDiff = -0.01; + if (lastRunNumber == 564359) + meanDiff = -0.17; + if (lastRunNumber == 564373) + meanDiff = 0.99; + if (lastRunNumber == 564374) + meanDiff = 0.57; + // Ne-Ne + if (lastRunNumber == 564468) + meanDiff = -0.51; + if (lastRunNumber == 564468) + meanDiff = -0.60; + + float stdDev = (multT0M > 10) ? 0.144723 + 13.5345 / sqrt(multT0M) : 1.5; // cm + if (multT0M > 5000) + stdDev = stdDev > 0.2 ? stdDev : 0.2; // 0.35; // cm + badVzDiff = diffVz < (meanDiff - stdDev * nSigmaForVzDiff - safetyDiffVzMargin) || diffVz > (meanDiff + stdDev * nSigmaForVzDiff + safetyDiffVzMargin); + } + + bool underLine = false; + if (hasFT0 && nPVtracks < 45. / 40000 * multV0A - 4 && nPVtracks < 20) { + underLine = true; + } + bool grassOnTheRight = false; + if (hasFT0 && nPVtracks < 220. / 40000 * multV0A - 100 && nPVtracks >= 25) { + grassOnTheRight = true; + } + + // study bc diff wrt original bc: + // auto bc = col.bc_as(); + auto bcOriginal = globalOrigBC % 3564; + float bcDiffWrtOriginal = bcOriginal - localBC; + bool bcDiffWrtOriginalBcCut = (bcDiffWrtOriginal == 0); + + // SPEC REMOVAL OF BC RANGES + // if (bcOriginal > 1200 && bcOriginal < 1300) + // continue; + // if (bcOriginal > 1700 && bcOriginal < 1900) + // continue; + + int nContributors = col.numContrib(); + float timeRes = col.collisionTimeRes(); + // int64_t bcInTF = (globalBC - bcSOR) % nBCsPerTF; + // if (col.selection_bit(kIsVertexTOFmatched)) { + // histos.fill(HIST("hColBcDiffVsNcontribWithTOF"), nContributors, bcToClosestTVXdiff); + // histos.fill(HIST("hColTimeResVsNcontribWithTOF"), nContributors, timeRes); + // histos.fill(HIST("hBcColTOF"), localBC); + // } + + float vChi2 = col.chi2(); + float vChi2perContrib = nContributors > 0 ? vChi2 / nContributors : 0; + bool goodVertexChi2 = (vChi2perContrib < 3.5); + + histos.fill(HIST("noSpecSelections/hBcColNoSel8"), localBC); + histos.fill(HIST("noSpecSelections/hBcOrigNoSel8"), bcOriginal); + + if (noPU) { + histos.fill(HIST("noPU/hBcColNoSel8"), localBC); + histos.fill(HIST("noPU/hBcOrigNoSel8"), bcOriginal); + } + if (noPU && pvTOFmatched) { + histos.fill(HIST("noPU_pvTOFmatched/hBcColNoSel8"), localBC); + } + if (noPU && pvTRDmatched) { + histos.fill(HIST("noPU_pvTRDmatched/hBcColNoSel8"), localBC); + } + if (noPU && !pvTRDmatched) { + histos.fill(HIST("noPU_notTRDmatched/hBcColNoSel8"), localBC); + } + if (bcDiffWrtClosestTVXCut) { + histos.fill(HIST("bcDiffWrtClosestTVXCut/hBcColNoSel8"), localBC); + } + if (noPU && bcDiffWrtOriginalBcCut) { + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hBcColNoSel8"), localBC); + } + if (noPU && noPastActivity) { + histos.fill(HIST("noPU_noPastActivity/hBcColNoSel8"), localBC); + } + if (noPU && noFT0activityNearby) { + histos.fill(HIST("noPU_noFT0activityNearby/hBcColNoSel8"), localBC); + } + if (noPU && badVzDiff) { + histos.fill(HIST("noPU_badVzDiff/hBcColNoSel8"), localBC); + } + if (noPU && !badVzDiff) { + histos.fill(HIST("noPU_goodVzDiff/hBcColNoSel8"), localBC); + } + if (noPU && !badVzDiff && narrowTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hBcColNoSel8"), localBC); + } + if (noPU && !badVzDiff && strictTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hBcColNoSel8"), localBC); + } + if (noPU && goodVertexChi2) { + histos.fill(HIST("noPU_goodVertexChi2/hBcColNoSel8"), localBC); + } + if (narrowTimeVeto) { + histos.fill(HIST("narrowTimeVeto/hBcColNoSel8"), localBC); + } + if (strictTimeVeto) { + histos.fill(HIST("strictTimeVeto/hBcColNoSel8"), localBC); + } + if (noCollSameROF) { + histos.fill(HIST("noCollSameROF/hBcColNoSel8"), localBC); + } + if (underLine) { + histos.fill(HIST("lowMultCut/hBcColNoSel8"), localBC); + histos.fill(HIST("lowMultCut/hBcOrigNoSel8"), bcOriginal); + } + if (noPU && underLine) { + histos.fill(HIST("noPU_lowMultCut/hBcColNoSel8"), localBC); + histos.fill(HIST("noPU_lowMultCut/hBcOrigNoSel8"), bcOriginal); + } + if (grassOnTheRight) { + histos.fill(HIST("highMultCloudCut/hBcColNoSel8"), localBC); + histos.fill(HIST("highMultCloudCut/hBcOrigNoSel8"), bcOriginal); + } + if (noPU && grassOnTheRight) { + histos.fill(HIST("noPU_highMultCloudCut/hBcColNoSel8"), localBC); + histos.fill(HIST("noPU_highMultCloudCut/hBcOrigNoSel8"), bcOriginal); + } + if (noPU && !badVzDiff && pvTOFmatched) { // noPileup_cutByVzDiff_pvTOF_noFT0act + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hBcColNoSel8"), localBC); + } + + // only here cut on sel8: + if (!col.sel8()) + continue; + + // vs time + histos.fill(HIST("hSecondsCollisions/sel8"), secFromSOR); + if (noPU) { + histos.fill(HIST("hSecondsCollisions/noPU"), secFromSOR); + if (underLine) + histos.fill(HIST("hSecondsCollisions/noPU_underLine"), secFromSOR); + if (grassOnTheRight) + histos.fill(HIST("hSecondsCollisions/noPU_grassOnTheRight"), secFromSOR); + if (!underLine && !grassOnTheRight) + histos.fill(HIST("hSecondsCollisions/noPU_good"), secFromSOR); + + if (std::abs(diffVz) < 4) { + histos.fill(HIST("hSecondsCollisions/noPU_meanDiffVz"), secFromSOR, diffVz); + if (multT0M < 1000) + histos.fill(HIST("hSecondsCollisions/noPU_meanDiffVz_lowMult"), secFromSOR, diffVz); + if (multT0M > 10000) + histos.fill(HIST("hSecondsCollisions/noPU_meanDiffVz_highMult"), secFromSOR, diffVz); + } + } + + histos.fill(HIST("noSpecSelections/hBcTVX"), localBC); + histos.fill(HIST("noSpecSelections/hBcOrig"), bcOriginal); + histos.fill(HIST("noSpecSelections/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noSpecSelections/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noSpecSelections/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noSpecSelections/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + + if (noPU) { + histos.fill(HIST("noPU/hBcTVX"), localBC); + histos.fill(HIST("noPU/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && pvTOFmatched) { + histos.fill(HIST("noPU_pvTOFmatched/hBcTVX"), localBC); + histos.fill(HIST("noPU_pvTOFmatched/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_pvTOFmatched/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_pvTOFmatched/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_pvTOFmatched/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_pvTOFmatched/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && pvTRDmatched) { + histos.fill(HIST("noPU_pvTRDmatched/hBcTVX"), localBC); + histos.fill(HIST("noPU_pvTRDmatched/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_pvTRDmatched/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_pvTRDmatched/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_pvTRDmatched/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_pvTRDmatched/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && !pvTRDmatched) { + histos.fill(HIST("noPU_notTRDmatched/hBcTVX"), localBC); + histos.fill(HIST("noPU_notTRDmatched/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_notTRDmatched/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_notTRDmatched/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_notTRDmatched/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (bcDiffWrtClosestTVXCut) { + histos.fill(HIST("bcDiffWrtClosestTVXCut/hBcTVX"), localBC); + histos.fill(HIST("bcDiffWrtClosestTVXCut/hBcOrig"), bcOriginal); + histos.fill(HIST("bcDiffWrtClosestTVXCut/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("bcDiffWrtClosestTVXCut/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("bcDiffWrtClosestTVXCut/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && bcDiffWrtOriginalBcCut) { + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hBcTVX"), localBC); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && noPastActivity) { + histos.fill(HIST("noPU_noPastActivity/hBcTVX"), localBC); + histos.fill(HIST("noPU_noPastActivity/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_noPastActivity/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_noPastActivity/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_noPastActivity/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && noFT0activityNearby) { + histos.fill(HIST("noPU_noFT0activityNearby/hBcTVX"), localBC); + histos.fill(HIST("noPU_noFT0activityNearby/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_noFT0activityNearby/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_noFT0activityNearby/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_noFT0activityNearby/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && badVzDiff) { + histos.fill(HIST("noPU_badVzDiff/hBcTVX"), localBC); + histos.fill(HIST("noPU_badVzDiff/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_badVzDiff/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_badVzDiff/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_badVzDiff/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_badVzDiff/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && !badVzDiff) { + histos.fill(HIST("noPU_goodVzDiff/hBcTVX"), localBC); + histos.fill(HIST("noPU_goodVzDiff/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_goodVzDiff/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_goodVzDiff/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_goodVzDiff/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_goodVzDiff/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && !badVzDiff && narrowTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hBcTVX"), localBC); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && !badVzDiff && strictTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hBcTVX"), localBC); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && goodVertexChi2) { + histos.fill(HIST("noPU_goodVertexChi2/hBcTVX"), localBC); + histos.fill(HIST("noPU_goodVertexChi2/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_goodVertexChi2/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_goodVertexChi2/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_goodVertexChi2/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (narrowTimeVeto) { + histos.fill(HIST("narrowTimeVeto/hBcTVX"), localBC); + histos.fill(HIST("narrowTimeVeto/hBcOrig"), bcOriginal); + histos.fill(HIST("narrowTimeVeto/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("narrowTimeVeto/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("narrowTimeVeto/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (strictTimeVeto) { + histos.fill(HIST("strictTimeVeto/hBcTVX"), localBC); + histos.fill(HIST("strictTimeVeto/hBcOrig"), bcOriginal); + histos.fill(HIST("strictTimeVeto/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("strictTimeVeto/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("strictTimeVeto/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noCollSameROF) { + histos.fill(HIST("noCollSameROF/hBcTVX"), localBC); + histos.fill(HIST("noCollSameROF/hBcOrig"), bcOriginal); + histos.fill(HIST("noCollSameROF/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noCollSameROF/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noCollSameROF/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && underLine) { + histos.fill(HIST("noPU_lowMultCut/hBcTVX"), localBC); + histos.fill(HIST("noPU_lowMultCut/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_lowMultCut/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_lowMultCut/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_lowMultCut/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_lowMultCut/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && grassOnTheRight) { + histos.fill(HIST("noPU_highMultCloudCut/hBcTVX"), localBC); + histos.fill(HIST("noPU_highMultCloudCut/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_highMultCloudCut/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_highMultCloudCut/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_highMultCloudCut/hVertexChi2VsNcontrib"), nContributors, vChi2perContrib); + histos.fill(HIST("noPU_highMultCloudCut/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && !badVzDiff && pvTOFmatched) { // noPileup_cutByVzDiff_pvTOF_noFT0act + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hBcTVX"), localBC); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + if (noPU && !badVzDiff && noFT0activityNearby) { + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hBcTVX"), localBC); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hBcOrig"), bcOriginal); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hColBcDiffVsNcontrib"), nContributors, bcToClosestTVXdiff); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hColTimeResVsNcontrib"), nContributors, timeRes); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hNPVvsNch"), nPVtracks, nGlobalTracksAll); + } + + if (foundBC.has_ft0()) { + // float multT0A = foundBC.has_ft0() ? foundBC.ft0().sumAmpA() : -999.f; + // float multT0C = foundBC.has_ft0() ? foundBC.ft0().sumAmpC() : -999.f; + + histos.fill(HIST("noSpecSelections/hBcFT0"), localBC); + histos.fill(HIST("noSpecSelections/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noSpecSelections/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noSpecSelections/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noSpecSelections/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noSpecSelections/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noSpecSelections/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + + if (noPU) { + histos.fill(HIST("noPU/hBcFT0"), localBC); + histos.fill(HIST("noPU/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && pvTOFmatched) { + histos.fill(HIST("noPU_pvTOFmatched/hBcFT0"), localBC); + histos.fill(HIST("noPU_pvTOFmatched/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_pvTOFmatched/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_pvTOFmatched/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_pvTOFmatched/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_pvTOFmatched/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_pvTOFmatched/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && pvTRDmatched) { + histos.fill(HIST("noPU_pvTRDmatched/hBcFT0"), localBC); + histos.fill(HIST("noPU_pvTRDmatched/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_pvTRDmatched/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_pvTRDmatched/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_pvTRDmatched/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_pvTRDmatched/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_pvTRDmatched/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && !pvTRDmatched) { + histos.fill(HIST("noPU_notTRDmatched/hBcFT0"), localBC); + histos.fill(HIST("noPU_notTRDmatched/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_notTRDmatched/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_notTRDmatched/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_notTRDmatched/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_notTRDmatched/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_notTRDmatched/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (bcDiffWrtClosestTVXCut) { + histos.fill(HIST("bcDiffWrtClosestTVXCut/hBcFT0"), localBC); + histos.fill(HIST("bcDiffWrtClosestTVXCut/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("bcDiffWrtClosestTVXCut/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("bcDiffWrtClosestTVXCut/nTracksPV_vs_T0A"), multT0A, nPVtracks); + // histos.fill(HIST("bcDiffWrtClosestTVXCut/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("bcDiffWrtClosestTVXCut/nTracksPV_vs_T0C"), multT0C, nPVtracks); + // histos.fill(HIST("bcDiffWrtClosestTVXCut/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && bcDiffWrtOriginalBcCut) { + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hBcFT0"), localBC); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/nTracksPV_vs_T0A"), multT0A, nPVtracks); + // histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/nTracksPV_vs_T0C"), multT0C, nPVtracks); + // histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && badVzDiff) { + histos.fill(HIST("noPU_badVzDiff/hBcFT0"), localBC); + histos.fill(HIST("noPU_badVzDiff/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_badVzDiff/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_badVzDiff/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_badVzDiff/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_badVzDiff/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_badVzDiff/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && !badVzDiff) { + histos.fill(HIST("noPU_goodVzDiff/hBcFT0"), localBC); + histos.fill(HIST("noPU_goodVzDiff/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_goodVzDiff/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_goodVzDiff/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_goodVzDiff/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && !badVzDiff && narrowTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hBcFT0"), localBC); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && !badVzDiff && strictTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hBcFT0"), localBC); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && noPastActivity) { + histos.fill(HIST("noPU_noPastActivity/hBcFT0"), localBC); + histos.fill(HIST("noPU_noPastActivity/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_noPastActivity/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_noPastActivity/nTracksPV_vs_T0A"), multT0A, nPVtracks); + // histos.fill(HIST("noPU_noPastActivity/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_noPastActivity/nTracksPV_vs_T0C"), multT0C, nPVtracks); + // histos.fill(HIST("noPU_noPastActivity/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && noFT0activityNearby) { + histos.fill(HIST("noPU_noFT0activityNearby/hBcFT0"), localBC); + histos.fill(HIST("noPU_noFT0activityNearby/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_noFT0activityNearby/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_noFT0activityNearby/nTracksPV_vs_T0A"), multT0A, nPVtracks); + // histos.fill(HIST("noPU_noFT0activityNearby/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_noFT0activityNearby/nTracksPV_vs_T0C"), multT0C, nPVtracks); + // histos.fill(HIST("noPU_noFT0activityNearby/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && goodVertexChi2) { + histos.fill(HIST("noPU_goodVertexChi2/hBcFT0"), localBC); + histos.fill(HIST("noPU_goodVertexChi2/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_goodVertexChi2/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_goodVertexChi2/nTracksPV_vs_T0A"), multT0A, nPVtracks); + // histos.fill(HIST("noPU_goodVertexChi2/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_goodVertexChi2/nTracksPV_vs_T0C"), multT0C, nPVtracks); + // histos.fill(HIST("noPU_goodVertexChi2/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (narrowTimeVeto) { + histos.fill(HIST("narrowTimeVeto/hBcFT0"), localBC); + histos.fill(HIST("narrowTimeVeto/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("narrowTimeVeto/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("narrowTimeVeto/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("narrowTimeVeto/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("narrowTimeVeto/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("narrowTimeVeto/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (strictTimeVeto) { + histos.fill(HIST("strictTimeVeto/hBcFT0"), localBC); + histos.fill(HIST("strictTimeVeto/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("strictTimeVeto/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("strictTimeVeto/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("strictTimeVeto/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("strictTimeVeto/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("strictTimeVeto/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noCollSameROF) { + histos.fill(HIST("noCollSameROF/hBcFT0"), localBC); + histos.fill(HIST("noCollSameROF/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noCollSameROF/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noCollSameROF/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noCollSameROF/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noCollSameROF/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noCollSameROF/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && underLine) { + histos.fill(HIST("noPU_lowMultCut/hBcFT0"), localBC); + histos.fill(HIST("noPU_lowMultCut/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_lowMultCut/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_lowMultCut/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_lowMultCut/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_lowMultCut/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_lowMultCut/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && grassOnTheRight) { + histos.fill(HIST("noPU_highMultCloudCut/hBcFT0"), localBC); + histos.fill(HIST("noPU_highMultCloudCut/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_highMultCloudCut/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_highMultCloudCut/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_highMultCloudCut/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_highMultCloudCut/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_highMultCloudCut/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && !badVzDiff && pvTOFmatched) { // noPileup_cutByVzDiff_pvTOF_noFT0act + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hBcFT0"), localBC); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/nTracksPV_vs_T0A"), multT0A, nPVtracks); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/nTracksPV_vs_T0C"), multT0C, nPVtracks); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + if (noPU && !badVzDiff && noFT0activityNearby) { + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hBcFT0"), localBC); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hVtxFT0VsVtxCol"), vZft0, vZ); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hVtxFT0MinusVtxColVsMultT0M"), diffVz, multT0A + multT0C); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/nTracksPV_vs_T0A"), multT0A, nPVtracks); + // histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/nTracksGlobal_vs_T0A"), multT0A, nGlobalTracksPV); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/nTracksPV_vs_T0C"), multT0C, nPVtracks); + // histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/nTracksGlobal_vs_T0C"), multT0C, nGlobalTracksPV); + } + } + + if (foundBC.has_fv0a()) { + histos.fill(HIST("noSpecSelections/hBcFV0"), localBC); + histos.fill(HIST("noSpecSelections/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noSpecSelections/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + if (noPU) { + histos.fill(HIST("noPU/hBcFV0"), localBC); + histos.fill(HIST("noPU/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && pvTOFmatched) { + histos.fill(HIST("noPU_pvTOFmatched/hBcFV0"), localBC); + histos.fill(HIST("noPU_pvTOFmatched/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_pvTOFmatched/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && pvTRDmatched) { + histos.fill(HIST("noPU_pvTRDmatched/hBcFV0"), localBC); + histos.fill(HIST("noPU_pvTRDmatched/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_pvTRDmatched/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && !pvTRDmatched) { + histos.fill(HIST("noPU_notTRDmatched/hBcFV0"), localBC); + histos.fill(HIST("noPU_notTRDmatched/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_notTRDmatched/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && pvTOFmatched && !pvTRDmatched) { // SPEC CHECK! + histos.fill(HIST("noPU_pvTOFmatched_notTRDmatched/hBcFV0"), localBC); + histos.fill(HIST("noPU_pvTOFmatched_notTRDmatched/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_pvTOFmatched_notTRDmatched/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (bcDiffWrtClosestTVXCut) { + histos.fill(HIST("bcDiffWrtClosestTVXCut/hBcFV0"), localBC); + histos.fill(HIST("bcDiffWrtClosestTVXCut/nTracksPV_vs_V0A"), multV0A, nPVtracks); + // histos.fill(HIST("bcDiffWrtClosestTVXCut/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && bcDiffWrtOriginalBcCut) { + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hBcFV0"), localBC); + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/nTracksPV_vs_V0A"), multV0A, nPVtracks); + // histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && badVzDiff) { + histos.fill(HIST("noPU_badVzDiff/hBcFV0"), localBC); + histos.fill(HIST("noPU_badVzDiff/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_badVzDiff/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && !badVzDiff) { + histos.fill(HIST("noPU_goodVzDiff/hBcFV0"), localBC); + histos.fill(HIST("noPU_goodVzDiff/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && !badVzDiff && narrowTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hBcFV0"), localBC); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && !badVzDiff && strictTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hBcFV0"), localBC); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && noPastActivity) { + histos.fill(HIST("noPU_noPastActivity/hBcFV0"), localBC); + histos.fill(HIST("noPU_noPastActivity/nTracksPV_vs_V0A"), multV0A, nPVtracks); + // histos.fill(HIST("noPU_noPastActivity/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && noFT0activityNearby) { + histos.fill(HIST("noPU_noFT0activityNearby/hBcFV0"), localBC); + histos.fill(HIST("noPU_noFT0activityNearby/nTracksPV_vs_V0A"), multV0A, nPVtracks); + // histos.fill(HIST("noPU_noFT0activityNearby/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && goodVertexChi2) { + histos.fill(HIST("noPU_goodVertexChi2/hBcFV0"), localBC); + histos.fill(HIST("noPU_goodVertexChi2/nTracksPV_vs_V0A"), multV0A, nPVtracks); + // histos.fill(HIST("noPU_goodVertexChi2/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (narrowTimeVeto) { + histos.fill(HIST("narrowTimeVeto/hBcFV0"), localBC); + histos.fill(HIST("narrowTimeVeto/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("narrowTimeVeto/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (strictTimeVeto) { + histos.fill(HIST("strictTimeVeto/hBcFV0"), localBC); + histos.fill(HIST("strictTimeVeto/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("strictTimeVeto/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noCollSameROF) { + histos.fill(HIST("noCollSameROF/hBcFV0"), localBC); + histos.fill(HIST("noCollSameROF/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noCollSameROF/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (underLine) { + histos.fill(HIST("lowMultCut/nTracksPV_vs_V0A"), multV0A, nPVtracks); + } + if (noPU && underLine) { + histos.fill(HIST("noPU_lowMultCut/hBcFV0"), localBC); + histos.fill(HIST("noPU_lowMultCut/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_lowMultCut/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (grassOnTheRight) { + histos.fill(HIST("highMultCloudCut/nTracksPV_vs_V0A"), multV0A, nPVtracks); + } + if (noPU && grassOnTheRight) { + histos.fill(HIST("noPU_highMultCloudCut/hBcFV0"), localBC); + histos.fill(HIST("noPU_highMultCloudCut/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_highMultCloudCut/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && !badVzDiff && pvTOFmatched) { // noPileup_cutByVzDiff_pvTOF_noFT0act + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hBcFV0"), localBC); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/nTracksPV_vs_V0A"), multV0A, nPVtracks); + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + if (noPU && !badVzDiff && noFT0activityNearby) { + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hBcFV0"), localBC); + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/nTracksPV_vs_V0A"), multV0A, nPVtracks); + // histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/nTracksGlobal_vs_V0A"), multV0A, nGlobalTracksPV); + } + } + if (foundBC.has_zdc()) { + histos.fill(HIST("noSpecSelections/hBcZDC"), localBC); + if (noPU) { + histos.fill(HIST("noPU/hBcZDC"), localBC); + } + if (noPU && pvTOFmatched) { + histos.fill(HIST("noPU_pvTOFmatched/hBcZDC"), localBC); + } + if (noPU && pvTRDmatched) { + histos.fill(HIST("noPU_pvTRDmatched/hBcZDC"), localBC); + } + if (noPU && !pvTRDmatched) { + histos.fill(HIST("noPU_notTRDmatched/hBcZDC"), localBC); + } + if (bcDiffWrtClosestTVXCut) { + histos.fill(HIST("bcDiffWrtClosestTVXCut/hBcZDC"), localBC); + } + if (noPU && bcDiffWrtOriginalBcCut) { + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hBcZDC"), localBC); + } + if (noPU && badVzDiff) { + histos.fill(HIST("noPU_badVzDiff/hBcZDC"), localBC); + } + if (noPU && !badVzDiff) { + histos.fill(HIST("noPU_goodVzDiff/hBcZDC"), localBC); + } + if (noPU && !badVzDiff && narrowTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hBcZDC"), localBC); + } + if (noPU && !badVzDiff && strictTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hBcZDC"), localBC); + } + if (noPU && noPastActivity) { + histos.fill(HIST("noPU_noPastActivity/hBcZDC"), localBC); + } + if (noPU && noFT0activityNearby) { + histos.fill(HIST("noPU_noFT0activityNearby/hBcZDC"), localBC); + } + if (noPU && goodVertexChi2) { + histos.fill(HIST("noPU_goodVertexChi2/hBcZDC"), localBC); + } + if (narrowTimeVeto) { + histos.fill(HIST("narrowTimeVeto/hBcZDC"), localBC); + } + if (strictTimeVeto) { + histos.fill(HIST("strictTimeVeto/hBcZDC"), localBC); + } + if (noCollSameROF) { + histos.fill(HIST("noCollSameROF/hBcZDC"), localBC); + } + if (noPU && underLine) { + histos.fill(HIST("noPU_lowMultCut/hBcZDC"), localBC); + } + if (noPU && grassOnTheRight) { + histos.fill(HIST("noPU_highMultCloudCut/hBcZDC"), localBC); + } + if (noPU && !badVzDiff && pvTOFmatched) { // noPileup_cutByVzDiff_pvTOF_noFT0act + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hBcZDC"), localBC); + } + if (noPU && !badVzDiff && noFT0activityNearby) { + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hBcZDC"), localBC); + } + } + + // bc diff wrt original bc + histos.fill(HIST("noSpecSelections/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + if (noPU) { + histos.fill(HIST("noPU/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && pvTOFmatched) { + histos.fill(HIST("noPU_pvTOFmatched/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && pvTRDmatched) { + histos.fill(HIST("noPU_pvTRDmatched/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && !pvTRDmatched) { + histos.fill(HIST("noPU_notTRDmatched/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (bcDiffWrtClosestTVXCut) { + histos.fill(HIST("bcDiffWrtClosestTVXCut/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && bcDiffWrtOriginalBcCut) { + histos.fill(HIST("noPU_bcDiffWrtOriginalBcCut/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && badVzDiff) { + histos.fill(HIST("noPU_badVzDiff/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && !badVzDiff) { + histos.fill(HIST("noPU_goodVzDiff/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && !badVzDiff && narrowTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_narrowTimeVeto/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && !badVzDiff && strictTimeVeto) { + histos.fill(HIST("noPU_goodVzDiff_strictTimeVeto/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && noPastActivity) { + histos.fill(HIST("noPU_noPastActivity/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && noFT0activityNearby) { + histos.fill(HIST("noPU_noFT0activityNearby/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && goodVertexChi2) { + histos.fill(HIST("noPU_goodVertexChi2/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (narrowTimeVeto) { + histos.fill(HIST("narrowTimeVeto/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (strictTimeVeto) { + histos.fill(HIST("strictTimeVeto/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noCollSameROF) { + histos.fill(HIST("noCollSameROF/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && underLine) { + histos.fill(HIST("noPU_lowMultCut/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && grassOnTheRight) { + histos.fill(HIST("noPU_highMultCloudCut/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && !badVzDiff && pvTOFmatched) { // noPileup_cutByVzDiff_pvTOF_noFT0act + histos.fill(HIST("noPU_cutByVzDiff_pvTOF/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + if (noPU && !badVzDiff && noFT0activityNearby) { + histos.fill(HIST("noPU_cutByVzDiff_noFT0activityNearby/hTVXvsBcDiffwrtOrigBc"), bcDiffWrtOriginal); + } + + } // end of collisions loop + } + PROCESS_SWITCH(LightIonsEvSelQa, processRun3, "Process Run3 tracking vs detector occupancy QA", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/DPG/Tasks/AOTEvent/matchingQa.cxx b/DPG/Tasks/AOTEvent/matchingQa.cxx index b59b8faba0c..3b266f047e9 100644 --- a/DPG/Tasks/AOTEvent/matchingQa.cxx +++ b/DPG/Tasks/AOTEvent/matchingQa.cxx @@ -27,7 +27,7 @@ using FullTracksIUwithLabels = soa::Join ccdb; diff --git a/DPG/Tasks/AOTEvent/timeDependentQa.cxx b/DPG/Tasks/AOTEvent/timeDependentQa.cxx index e742ee040fd..61fbb690e6c 100644 --- a/DPG/Tasks/AOTEvent/timeDependentQa.cxx +++ b/DPG/Tasks/AOTEvent/timeDependentQa.cxx @@ -41,7 +41,7 @@ using namespace o2::aod::evsel; using namespace o2::aod::rctsel; using ColEvSels = soa::Join; -using BCsRun3 = soa::Join; +using BCsRun3 = soa::Join; using BarrelTracks = soa::Join; const AxisSpec axisQoverPt{100, -1., 1., "q/p_{T}, 1/GeV"}; @@ -54,6 +54,7 @@ const AxisSpec axisSparseDcaZ{100, -1., 1., "DCA_{z}, cm"}; struct TimeDependentQaTask { Configurable confTimeBinWidthInSec{"TimeBinWidthInSec", 0.5, "Width of time bins in seconds"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confTimeWiderBinFactor{"TimeWideBinFactor", 4, "Factor for wider time bins for some 2D histograms"}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confTimeMuchWiderBinFactor{"TimeMuchWiderBinFactor", 20, "Factor for even wider time bins for some 2D histograms"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confTakeVerticesWithUPCsettings{"ConsiderVerticesWithUPCsettings", 0, "Take vertices: 0 - all , 1 - only without UPC settings, 2 - only with UPC settings"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagFillPhiVsTimeHist{"FlagFillPhiVsTimeHist", 2, "0 - don't fill , 1 - fill only for global/7cls/TRD/TOF tracks, 2 - fill also layer-by-layer"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagFillEtaPhiVsTimeHist{"FlagFillEtaPhiVsTimeHist", 0, "0 - don't fill , 1 - fill"}; // o2-linter: disable=name/configurable (temporary fix) @@ -61,6 +62,13 @@ struct TimeDependentQaTask { Configurable confFlagCheckMshape{"FlagCheckMshape", 0, "0 - don't check , 1 - check"}; // o2-linter: disable=name/configurable (temporary fix) Configurable confFlagCheckQoverPtHist{"FlagCheckQoverPtHist", 1, "0 - don't check , 1 - check"}; // o2-linter: disable=name/configurable (temporary fix) + // for O-O and Ne-Ne run + Configurable confIncludeMultDistrVsTimeHistos{"IncludeMultDistrVsTimeHistos", 0, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxNtracksForTimeDepDistributions{"MaxNtracksForTimeDepDistributions", 800, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxZNACenergyForTimeDepDistributions{"MaxZNACenergyForTimeDepDistributions", 4000, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxT0ACamplForTimeDepDistributions{"MaxT0ACamplForTimeDepDistributions", 25000, ""}; // o2-linter: disable=name/configurable (temporary fix) + Configurable confMaxV0AamplForTimeDepDistributions{"MaxV0AamplForTimeDepDistributions", 40000, ""}; // o2-linter: disable=name/configurable (temporary fix) + enum EvSelBitsToMonitor { enCollisionsAll = 0, enIsTriggerTVX, @@ -156,6 +164,7 @@ struct TimeDependentQaTask { ColEvSels const& cols, BarrelTracks const& tracks, BCsRun3 const& bcs, + aod::Zdcs const&, aod::FT0s const&) { int runNumber = bcs.iteratorAt(0).runNumber(); @@ -181,10 +190,12 @@ struct TimeDependentQaTask { maxSec = ceil(tsEOR / 1000.); int nTimeBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec); int nTimeWideBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec / confTimeWiderBinFactor); + int nTimeVeryWideBins = static_cast((maxSec - minSec) / confTimeBinWidthInSec / confTimeMuchWiderBinFactor); double timeInterval = nTimeBins * confTimeBinWidthInSec; const AxisSpec axisSeconds{nTimeBins, 0, timeInterval, "seconds"}; const AxisSpec axisSecondsWideBins{nTimeWideBins, 0, timeInterval, "seconds"}; + const AxisSpec axisSecondsVeryWideBins{nTimeVeryWideBins, 0, timeInterval, "seconds"}; histos.add("hSecondsBCsTVX", "", kTH1D, {axisSeconds}); histos.add("hSecondsBCsTVXandTFborderCuts", "", kTH1D, {axisSeconds}); @@ -194,6 +205,7 @@ struct TimeDependentQaTask { histos.add("hSecondsCollisionsTVXTFborderCutNoVzCut", "", kTH1D, {axisSeconds}); histos.add("hSecondsCollisions", "", kTH1D, {axisSeconds}); + histos.add("hSecondsCollisionsNoPileup", "", kTH1D, {axisSeconds}); histos.add("hSecondsIR", "", kTH1D, {axisSeconds}); histos.add("hSecondsVz", "", kTH1D, {axisSeconds}); histos.add("hSecondsFT0Camlp", "", kTH1D, {axisSeconds}); @@ -208,6 +220,39 @@ struct TimeDependentQaTask { histos.add("hSecondsUPCverticesBeforeSel8", "", kTH2F, {axisSeconds, {2, -0.5, 1.5, "Is vertex with UPC settings after |vZ|<10 cut"}}); histos.add("hSecondsUPCvertices", "", kTH2F, {axisSeconds, {2, -0.5, 1.5, "Is vertex with UPC settings after |vZ|<10 and sel8 cuts"}}); + // shapes of distributions (added for the O-O run monitoring) + if (confIncludeMultDistrVsTimeHistos) { + int maxNtracks = confMaxNtracksForTimeDepDistributions; + float maxZNACenergyForTimeDepDistributions = confMaxZNACenergyForTimeDepDistributions; + float maxT0ACamplForTimeDepDistributions = confMaxT0ACamplForTimeDepDistributions; + float maxV0AamplForTimeDepDistributions = confMaxV0AamplForTimeDepDistributions; + histos.add("multDistributions/hSecondsDistrPVtracks", "", kTH2D, {axisSecondsVeryWideBins, {maxNtracks, -0.5, maxNtracks - 0.5, "n PV tracks"}}); + histos.add("multDistributions/hSecondsDistrT0A", "", kTH2D, {axisSecondsVeryWideBins, {250, 0, maxT0ACamplForTimeDepDistributions, "T0A ampl"}}); + histos.add("multDistributions/hSecondsDistrT0C", "", kTH2D, {axisSecondsVeryWideBins, {250, 0, maxT0ACamplForTimeDepDistributions, "T0C ampl"}}); + histos.add("multDistributions/hSecondsDistrV0A", "", kTH2D, {axisSecondsVeryWideBins, {400, 0, maxV0AamplForTimeDepDistributions, "V0A ampl"}}); + histos.add("multDistributions/hSecondsDistrZNA", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNA ampl"}}); + histos.add("multDistributions/hSecondsDistrZNC", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNC ampl"}}); + histos.add("multDistributions/hSecondsDistrZNACdiff", "", kTH2D, {axisSecondsVeryWideBins, {600, -maxZNACenergyForTimeDepDistributions, maxZNACenergyForTimeDepDistributions, "ZN A-C diff"}}); + histos.add("multDistributions/hSecondsDistrZNACdiffNorm", "", kTH2D, {axisSecondsVeryWideBins, {200, -1., 1., "ZN A-C diff"}}); + histos.add("multDistributions/hSecondsDistrZNAampl", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNA ampl"}}); + histos.add("multDistributions/hSecondsDistrZNCampl", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNC ampl"}}); + histos.add("multDistributions/hSecondsDistrZNACdiffAmpl", "", kTH2D, {axisSecondsVeryWideBins, {200, -1., 1., "ZN A-C diff"}}); + histos.add("multDistributions/hSecondsDistrZNACdiffNormAmpl", "", kTH2D, {axisSecondsVeryWideBins, {200, -1., 1., "ZN A-C diff"}}); + + histos.add("multDistributionsNoPileup/hSecondsDistrPVtracks", "", kTH2D, {axisSecondsVeryWideBins, {maxNtracks, -0.5, maxNtracks - 0.5, "n PV tracks"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrT0A", "", kTH2D, {axisSecondsVeryWideBins, {250, 0, maxT0ACamplForTimeDepDistributions, "T0A ampl"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrT0C", "", kTH2D, {axisSecondsVeryWideBins, {250, 0, maxT0ACamplForTimeDepDistributions, "T0C ampl"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrV0A", "", kTH2D, {axisSecondsVeryWideBins, {400, 0, maxV0AamplForTimeDepDistributions, "V0A ampl"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNA", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNA ampl"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNC", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNC ampl"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNACdiff", "", kTH2D, {axisSecondsVeryWideBins, {600, -maxZNACenergyForTimeDepDistributions, maxZNACenergyForTimeDepDistributions, "ZN A-C diff"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNACdiffNorm", "", kTH2D, {axisSecondsVeryWideBins, {200, -1., 1., "ZN A-C diff"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNAampl", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNA ampl"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNCampl", "", kTH2D, {axisSecondsVeryWideBins, {320, 0, maxZNACenergyForTimeDepDistributions, "ZNC ampl"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNACdiffAmpl", "", kTH2D, {axisSecondsVeryWideBins, {200, -1., 1., "ZN A-C diff"}}); + histos.add("multDistributionsNoPileup/hSecondsDistrZNACdiffNormAmpl", "", kTH2D, {axisSecondsVeryWideBins, {200, -1., 1., "ZN A-C diff"}}); + } + // ### QA event selection bits int nEvSelBits = enNumEvSelBits; histos.add("hSecondsEventSelBits", "", kTH2F, {axisSecondsWideBins, {nEvSelBits, -0.5, nEvSelBits - 0.5, "Monitoring of event selection bits"}}); @@ -459,6 +504,8 @@ struct TimeDependentQaTask { histos.fill(HIST("hSecondsUPCvertices"), secFromSOR, isVertexUPC ? 1 : 0); histos.fill(HIST("hSecondsCollisions"), secFromSOR); + if (col.selection_bit(kNoSameBunchPileup)) + histos.fill(HIST("hSecondsCollisionsNoPileup"), secFromSOR); histos.fill(HIST("hSecondsVz"), secFromSOR, col.posZ()); histos.fill(HIST("hSecondsFT0Camlp"), secFromSOR, bc.foundFT0().sumAmpC()); histos.fill(HIST("hSecondsFT0CamlpByColMult"), secFromSOR, col.multFT0C()); @@ -534,6 +581,7 @@ struct TimeDependentQaTask { // ##### track loop auto tracksGrouped = tracks.sliceBy(perCollision, col.globalIndex()); + int nPVtracks = 0; for (const auto& track : tracksGrouped) { // if (!track.hasTPC() || !track.hasITS()) // continue; @@ -593,6 +641,8 @@ struct TimeDependentQaTask { histos.fill(HIST("PVcontrib/hSecondsNumClsIts"), secFromSOR, track.itsNCls()); histos.fill(HIST("PVcontrib/hSeconds2DNumClsIts"), secFromSOR, track.itsNCls()); histos.fill(HIST("PVcontrib/hSecondsChi2NClIts"), secFromSOR, track.itsChi2NCl()); + + nPVtracks++; } // ### global tracks @@ -728,6 +778,62 @@ struct TimeDependentQaTask { histos.fill(HIST("hSecondsITSglobalVsEtaPhi"), secFromSOR, track.eta(), track.phi()); } } + } // end of track loop + + // fill mult distributions vs time + if (confIncludeMultDistrVsTimeHistos) { + bool noPileup = col.selection_bit(kNoSameBunchPileup); + + histos.fill(HIST("multDistributions/hSecondsDistrPVtracks"), secFromSOR, nPVtracks); + + // ZNA,C + // float multZNA = bc.has_zdc() ? bc.zdc().energyCommonZNA() : -999.f; + // float multZNC = bc.has_zdc() ? bc.zdc().energyCommonZNC() : -999.f; + histos.fill(HIST("multDistributions/hSecondsDistrZNA"), secFromSOR, col.multZNA()); + histos.fill(HIST("multDistributions/hSecondsDistrZNC"), secFromSOR, col.multZNC()); + float ZNdiff = col.multZNA() - col.multZNC(); + float ZNsum = col.multZNA() + col.multZNC(); + histos.fill(HIST("multDistributions/hSecondsDistrZNACdiff"), secFromSOR, ZNdiff); + if (ZNsum > 0) + histos.fill(HIST("multDistributions/hSecondsDistrZNACdiffNorm"), secFromSOR, ZNdiff / ZNsum); + + // ZNA,C by amplitudes (suggested by Chiara O.) + float ZNAampl = bc.has_zdc() ? bc.zdc().amplitudeZNA() : 0; + float ZNCampl = bc.has_zdc() ? bc.zdc().amplitudeZNC() : 0; + histos.fill(HIST("multDistributions/hSecondsDistrZNAampl"), secFromSOR, ZNAampl); + histos.fill(HIST("multDistributions/hSecondsDistrZNCampl"), secFromSOR, ZNCampl); + float ZNdiffAmpl = ZNAampl - ZNCampl; + float ZNsumAmpl = ZNAampl + ZNCampl; + histos.fill(HIST("multDistributions/hSecondsDistrZNACdiffAmpl"), secFromSOR, ZNdiffAmpl); + if (ZNsumAmpl > 0) + histos.fill(HIST("multDistributions/hSecondsDistrZNACdiffNormAmpl"), secFromSOR, ZNdiffAmpl / ZNsumAmpl); + + // FT0A,C, V0A + // float multT0A = bc.has_ft0() ? bc.ft0().sumAmpA() : -999.f; + // float multT0C = bc.has_ft0() ? fbcundBC.ft0().sumAmpC() : -999.f; + histos.fill(HIST("multDistributions/hSecondsDistrT0A"), secFromSOR, col.multFT0A()); + histos.fill(HIST("multDistributions/hSecondsDistrT0C"), secFromSOR, col.multFT0C()); + histos.fill(HIST("multDistributions/hSecondsDistrV0A"), secFromSOR, col.multFV0A()); + + if (noPileup) { + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrPVtracks"), secFromSOR, nPVtracks); + + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNA"), secFromSOR, col.multZNA()); + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNC"), secFromSOR, col.multZNC()); + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNACdiff"), secFromSOR, ZNdiff); + if (ZNsum > 0) + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNACdiffNorm"), secFromSOR, ZNdiff / ZNsum); + + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNAampl"), secFromSOR, ZNAampl); + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNCampl"), secFromSOR, ZNCampl); + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNACdiffAmpl"), secFromSOR, ZNdiffAmpl); + if (ZNsumAmpl > 0) + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrZNACdiffNormAmpl"), secFromSOR, ZNdiffAmpl / ZNsumAmpl); + + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrT0A"), secFromSOR, col.multFT0A()); + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrT0C"), secFromSOR, col.multFT0C()); + histos.fill(HIST("multDistributionsNoPileup/hSecondsDistrV0A"), secFromSOR, col.multFV0A()); + } } } } // end of collision loop diff --git a/DPG/Tasks/AOTTrack/CMakeLists.txt b/DPG/Tasks/AOTTrack/CMakeLists.txt index 9974d3d6bc2..b125419f6d0 100644 --- a/DPG/Tasks/AOTTrack/CMakeLists.txt +++ b/DPG/Tasks/AOTTrack/CMakeLists.txt @@ -85,3 +85,8 @@ o2physics_add_dpl_workflow(tag-and-probe-dmesons PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(derived-data-creator-d0-calibration + SOURCES derivedDataCreatorD0Calibration.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCore O2::DCAFitter O2Physics::MLCore + COMPONENT_NAME Analysis) + diff --git a/DPG/Tasks/AOTTrack/D0CalibTables.h b/DPG/Tasks/AOTTrack/D0CalibTables.h new file mode 100644 index 00000000000..1564b6cebdf --- /dev/null +++ b/DPG/Tasks/AOTTrack/D0CalibTables.h @@ -0,0 +1,492 @@ +// 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 D0CalibTables.h +/// \brief Definitions of derived tables produced by data creator for D0 calibration studies +/// \author Fabrizio Grosa , CERN + +#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 + +namespace o2 +{ +namespace hf_calib +{ +enum D0MassHypo : uint8_t { + D0 = 1, + D0Bar, + D0AndD0Bar, + ND0MassHypos +}; + +const float toMicrometers = 10000.; // from cm to µm + +/// It compresses a value to a int8_t with a given precision +///\param origValue is the original values +///\param precision is the desired precision +///\return The value compressed to a int8_t +template +int8_t getCompressedInt8(T origValue, double precision) +{ + int roundValue = static_cast(std::round(origValue / precision)); + return static_cast(std::clamp(roundValue, -128, 128)); +} + +/// It compresses a value to a uint8_t with a given precision +///\param origValue is the original values +///\param precision is the desired precision +///\return The value compressed to a uint8_t +template +uint8_t getCompressedUint8(T origValue, double precision) +{ + int roundValue = static_cast(std::round(origValue / precision)); + return static_cast(std::clamp(roundValue, 0, 255)); +} + +/// It compresses a value to a uint16_t with a given precision +///\param origValue is the original values +///\param precision is the desired precision +///\return The value compressed to a uint16_t +template +uint16_t getCompressedUint16(T origValue, double precision) +{ + int roundValue = static_cast(std::round(origValue / precision)); + return static_cast(std::clamp(roundValue, 0, 65535)); +} + +/// It uses a sinh-based scaling function, which provides a compromise between fixed-step and relative quantization. +// This approach reflects typical resolution formulas and is well-suited for detector calibration data. +///\param origValue is the original value +///\param sigma0 is a asinh parameter +///\param sigma1 is a asinh parameter +///\param clampMin is the maximum value +///\param clampMax is the minimum value +///\return The value compressed +int codeSqrtScaling(float origValue, float sigma0, float sigma1, int clampMin, int clampMax) +{ + float codeF = std::asinh((sigma1 * origValue) / sigma0) / sigma0; + return std::clamp(static_cast(std::round(codeF)), clampMin, clampMax); +} + +/// It compresses the decay length (10 micron precision) +///\param decLen is the decay length in cm +///\return The decay length compressed to a uint8_t with 10 micron precision +template +uint8_t getCompressedDecayLength(T decLen) +{ + return getCompressedUint8(decLen * hf_calib::toMicrometers, 0.1); +} + +/// It compresses the normalised decay length (0.5 precision) +///\param normDecLen is the normalised decay length +///\return The normalised decay length compressed to a uint8_t with 0.5 precision +template +uint8_t getCompressedNormDecayLength(T normDecLen) +{ + return getCompressedUint8(normDecLen, 0.5); +} + +/// It compresses the pointing angle (0.005 precision) +///\param pointAngle is the pointing angle +///\return The pointing angle compressed to a uint8_t with 0.005 precision +template +uint8_t getCompressedPointingAngle(T pointAngle) +{ + return getCompressedUint8(pointAngle, 0.005); +} + +/// It compresses the cosine of pointing angle (0.001 precision) +///\param cosPa is the cosine of pointing angle +///\return The cosine of pointing angle compressed to a uint8_t with 0.001 precision +template +int8_t getCompressedCosPa(T cosPa) +{ + return getCompressedUint8(cosPa - 0.75, 0.001); // in the range from 0.75 to 1 +} + +/// It compresses the chi2 +///\param chi2 is the chi2 +///\return The chi2 compressed to a uint8_t +template +int8_t getCompressedChi2(T chi2) +{ + uint8_t compressedChi2 = static_cast(codeSqrtScaling(chi2, 0.015, 0.015, 0, 255)); + return compressedChi2; +} + +/// It compresses the number of sigma +///\param numSigma is the number of sigma +///\return The number of sigma compressed to a int8_t +template +int8_t getCompressedNumSigmaPid(T numSigma) +{ + int8_t compressedNumSigma = static_cast(codeSqrtScaling(numSigma, 0.05, 0.05, -128, 128)); + return compressedNumSigma; +} + +/// It compresses the bdt score (1./65535 precision) +///\param bdtScore is the bdt score +///\return The bdt score compressed to a uint16_t with 1./65535 precision +template +uint16_t getCompressedBdtScoreBkg(T bdtScore) +{ + return getCompressedUint16(bdtScore, 1. / 65535); +} + +/// It compresses the bdt score (1./255 precision) +///\param bdtScore is the bdt score +///\return The bdt score compressed to a uint8_t with 1./255 precision +template +uint8_t getCompressedBdtScoreSgn(T bdtScore) +{ + return getCompressedUint8(bdtScore, 1. / 255); +} + +/// It compresses the occupancy value +///\param occupancy is the occupancy value +///\return The number of occupancy compressed to a uint8_t +template +uint8_t getCompressedOccupancy(T occupancy) +{ + uint8_t compressedOcc = static_cast(codeSqrtScaling(occupancy, 0.04, 0.04, 0, 255)); + return compressedOcc; +} + +static constexpr int NBinsPtTrack = 6; +static constexpr int NCutVarsTrack = 4; +constexpr float BinsPtTrack[NBinsPtTrack + 1] = { + 0, + 0.5, + 1.0, + 1.5, + 2.0, + 3.0, + 1000.0}; +auto vecBinsPtTrack = std::vector{BinsPtTrack, BinsPtTrack + NBinsPtTrack + 1}; + +// default values for the dca_xy and dca_z cuts of displaced tracks +constexpr float CutsTrack[NBinsPtTrack][NCutVarsTrack] = {{0.0015, 2., 0.0000, 2.}, /* 0 < pt < 0.5 */ + {0.0015, 2., 0.0000, 2.}, /* 0.5 < pt < 1 */ + {0.0015, 2., 0.0000, 2.}, /* 1 < pt < 1.5 */ + {0.0015, 2., 0.0000, 2.}, /* 1.5 < pt < 2 */ + {0.0000, 2., 0.0000, 2.}, /* 2 < pt < 3 */ + {0.0000, 2., 0.0000, 2.}}; /* 3 < pt < 1000 */ +// row labels +static const std::vector labelsPtTrack{}; + +// column labels +static const std::vector labelsCutVarTrack = {"min_dcaxytoprimary", "max_dcaxytoprimary", "min_dcaztoprimary", "max_dcaztoprimary"}; + +static constexpr int NBinsPtCand = 10; +static constexpr int NCutVarsCand = 10; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr float BinsPtCand[NBinsPtCand + 1] = { + 0, + 1.0, + 2.0, + 3.0, + 4.0, + 6.0, + 8.0, + 12.0, + 24.0, + 50.0, + 1000.0}; +auto vecBinsPtCand = std::vector{BinsPtCand, BinsPtCand + NBinsPtCand + 1}; + +// default values for the cuts +constexpr float CutsCand[NBinsPtCand][NCutVarsCand] = {{0.400, 0., 10., 10., 0.97, 0.97, 0, 2, 0.01, 0.01}, /* 0 < pT < 1 */ + {0.400, 0., 10., 10., 0.97, 0.97, 0, 2, 0.01, 0.01}, /* 1 < pT < 2 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 2 < pT < 3 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 3 < pT < 4 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 4 < pT < 6 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 6 < pT < 8 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 8 < pT < 12 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 12 < pT < 24 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}, /* 24 < pT < 50 */ + {0.400, 0., 10., 10., 0.95, 0.95, 0, 2, 0.01, 0.01}}; /* 50 < pT < 1000 */ + +// row labels +static const std::vector labelsPtCand = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9"}; + +// column labels +static const std::vector labelsCutVarCand = {"delta inv. mass", "max d0d0", "max pointing angle", "max pointing angle XY", "min cos pointing angle", "min cos pointing angle XY", "min norm decay length", "min norm decay length XY", "min decay length", "min decay length XY"}; + +static constexpr int NBinsPtMl = 10; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double BinsPtMl[NBinsPtMl + 1] = { + 0, + 1.0, + 2.0, + 3.0, + 4.0, + 6.0, + 8.0, + 12.0, + 24.0, + 50.0, + 1000.0}; +auto vecBinsPtMl = std::vector{BinsPtMl, BinsPtMl + NBinsPtMl + 1}; + +// default values for the cuts +constexpr double CutsMl[NBinsPtMl][3] = {{1., 0., 0.}, /* 0 < pT < 1 */ + {1., 0., 0.}, /* 1 < pT < 2 */ + {1., 0., 0.}, /* 2 < pT < 3 */ + {1., 0., 0.}, /* 3 < pT < 4 */ + {1., 0., 0.}, /* 4 < pT < 6 */ + {1., 0., 0.}, /* 6 < pT < 8 */ + {1., 0., 0.}, /* 8 < pT < 12 */ + {1., 0., 0.}, /* 12 < pT < 24 */ + {1., 0., 0.}, /* 24 < pT < 50 */ + {1., 0., 0.}}; /* 50 < pT < 1000 */ + +// row labels +static const std::vector labelsPtMl = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3", + "pT bin 4", + "pT bin 5", + "pT bin 6", + "pT bin 7", + "pT bin 8", + "pT bin 9"}; + +// column labels +static const std::vector labelsCutMl = {"max BDT score bkg", "min BDT score prompt", "min BDT score nonprompt"}; +} // namespace hf_calib + +namespace aod +{ +namespace hf_calib +{ +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); //! Run number +DECLARE_SOA_COLUMN(Orbit, orbit, uint32_t); //! orbit ID +DECLARE_SOA_COLUMN(CentFT0C, centFT0C, uint8_t); //! FTOC centrality +DECLARE_SOA_COLUMN(OccupancyTracks, occupancyTracks, uint8_t); //! FT0 occupancy +DECLARE_SOA_COLUMN(OccupancyFT0C, occupancyFT0C, uint8_t); //! FT0 occupancy +} // namespace hf_calib + +DECLARE_SOA_TABLE(D0CalibColls, "AOD", "D0CALIBCOLL", + o2::soa::Index<>, + collision::PosX, + collision::PosY, + collision::PosZ, + collision::CovXX, + collision::CovXY, + collision::CovXZ, + collision::CovYY, + collision::CovYZ, + collision::CovZZ, + collision::NumContrib, + hf_calib::CentFT0C, + hf_calib::OccupancyTracks, + hf_calib::OccupancyFT0C, + hf_calib::Orbit, + hf_calib::RunNumber); + +namespace hf_calib +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Collision, collision, int, D0CalibColls, ""); //! Index of collision +DECLARE_SOA_COLUMN(TpcNumSigmaPi, tpcNumSigmaPi, int8_t); //! compressed NsigmaTPC for pions +DECLARE_SOA_COLUMN(TpcNumSigmaKa, tpcNumSigmaKa, int8_t); //! compressed NsigmaTPC for kaons +DECLARE_SOA_COLUMN(TofNumSigmaPi, tofNumSigmaPi, int8_t); //! compressed NsigmaTOF for pions +DECLARE_SOA_COLUMN(TofNumSigmaKa, tofNumSigmaKa, int8_t); //! compressed NsigmaTOF for kaons +DECLARE_SOA_COLUMN(ITSChi2NCl, itsChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TPCChi2NCl, tpcChi2NCl, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TRDChi2, trdChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(TOFChi2, tofChi2, uint8_t); //! compressed NsigmaTOF for kaons // o2-linter: disable=name/o2-column +DECLARE_SOA_COLUMN(CmoPrimUnfm80, cmoPrimUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoFV0AUnfm80, cmoFV0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoFT0AUnfm80, cmoFT0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoFT0CUnfm80, cmoFT0CUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoPrimUnfm80, cwmoPrimUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoFV0AUnfm80, cwmoFV0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoFT0AUnfm80, cwmoFT0AUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoFT0CUnfm80, cwmoFT0CUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CmoRobustT0V0PrimUnfm80, cmoRobustT0V0PrimUnfm80, uint8_t); +DECLARE_SOA_COLUMN(CwmoRobustT0V0PrimUnfm80, cwmoRobustT0V0PrimUnfm80, uint8_t); +} // namespace hf_calib + +DECLARE_SOA_TABLE(D0CalibTracks, "AOD", "D0CALIBTRACK", + o2::soa::Index<>, + /// *** collision index + hf_calib::CollisionId, + /// *** track pars + track::X, + track::Alpha, + track::Y, + track::Z, + track::Snp, + track::Tgl, + track::Signed1Pt, + /// *** track covs + 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, + /// *** track extra (static) + track::TPCInnerParam, + track::Flags, + track::ITSClusterSizes, + track::TPCNClsFindable, + track::TPCNClsFindableMinusFound, + track::TPCNClsFindableMinusCrossedRows, + track::TPCNClsShared, + track::TRDPattern, + hf_calib::ITSChi2NCl, + hf_calib::TPCChi2NCl, + hf_calib::TRDChi2, + hf_calib::TOFChi2, + track::TPCSignal, + track::TRDSignal, + track::Length, + track::TOFExpMom, + track::TrackTime, + track::TrackTimeRes, + /// *** track QA + trackqa::TPCTime0, + trackqa::TPCdEdxNorm, + trackqa::TPCDCAR, + trackqa::TPCDCAZ, + trackqa::TPCClusterByteMask, + trackqa::TPCdEdxMax0R, + trackqa::TPCdEdxMax1R, + trackqa::TPCdEdxMax2R, + trackqa::TPCdEdxMax3R, + trackqa::TPCdEdxTot0R, + trackqa::TPCdEdxTot1R, + trackqa::TPCdEdxTot2R, + trackqa::TPCdEdxTot3R, + trackqa::DeltaRefContParamY, + trackqa::DeltaRefContParamZ, + trackqa::DeltaRefContParamSnp, + trackqa::DeltaRefContParamTgl, + trackqa::DeltaRefContParamQ2Pt, + trackqa::DeltaRefGloParamY, + trackqa::DeltaRefGloParamZ, + trackqa::DeltaRefGloParamSnp, + trackqa::DeltaRefGloParamTgl, + trackqa::DeltaRefGloParamQ2Pt, + trackqa::DeltaTOFdX, + trackqa::DeltaTOFdZ, + /// *** DCA, Nsigma + track::DcaXY, + track::DcaZ, + hf_calib::TpcNumSigmaPi, + hf_calib::TpcNumSigmaKa, + hf_calib::TofNumSigmaPi, + hf_calib::TofNumSigmaKa, + /// *** Occupancy variables + hf_calib::CmoPrimUnfm80, + hf_calib::CmoFV0AUnfm80, + hf_calib::CmoFT0AUnfm80, + hf_calib::CmoFT0CUnfm80, + hf_calib::CwmoPrimUnfm80, + hf_calib::CwmoFV0AUnfm80, + hf_calib::CwmoFT0AUnfm80, + hf_calib::CwmoFT0CUnfm80, + hf_calib::CmoRobustT0V0PrimUnfm80, + hf_calib::CwmoRobustT0V0PrimUnfm80); + +namespace hf_calib +{ +DECLARE_SOA_INDEX_COLUMN_FULL(TrackPos, trackPos, int, D0CalibTracks, "_Pos"); //! Index of positive track +DECLARE_SOA_INDEX_COLUMN_FULL(TrackNeg, trackNeg, int, D0CalibTracks, "_Neg"); //! Index of negative track +DECLARE_SOA_COLUMN(MassHypo, massHypo, uint8_t); //! mass hypothesis for D0 (D0, D0bar, or both) +DECLARE_SOA_COLUMN(Pt, pt, float); //! D0-candidate pT +DECLARE_SOA_COLUMN(Eta, eta, float); //! D0-candidate eta +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(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 +DECLARE_SOA_COLUMN(NormDecLengthXY, normDecLengthXY, uint8_t); //! compressed normalised decay length XY +DECLARE_SOA_COLUMN(CosPa, cosPa, uint8_t); //! compressed cosine of pointing angle +DECLARE_SOA_COLUMN(CosPaXY, cosPaXY, uint8_t); //! compressed cosine of pointing angle XY +DECLARE_SOA_COLUMN(PointingAngle, pointingAngle, uint8_t); //! compressed pointing angle +DECLARE_SOA_COLUMN(PointingAngleXY, pointingAngleXY, uint8_t); //! compressed pointing angle XY +DECLARE_SOA_COLUMN(DecVtxChi2, decVtxChi2, uint8_t); //! compressed decay vertex chi2 +DECLARE_SOA_COLUMN(BdtScoreBkgD0, bdtScoreBkgD0, uint16_t); //! compressed BDT score (bkg, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScorePromptD0, bdtScorePromptD0, uint8_t); //! compressed BDT score (prompt, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScoreNonpromptD0, bdtScoreNonpromptD0, uint8_t); //! compressed BDT score (non-prompt, D0 mass hypo) +DECLARE_SOA_COLUMN(BdtScoreBkgD0bar, bdtScoreBkgD0bar, uint16_t); //! compressed BDT score (bkg, D0bar mass hypo) +DECLARE_SOA_COLUMN(BdtScorePromptD0bar, bdtScorePromptD0bar, uint8_t); //! compressed BDT score (prompt, D0bar mass hypo) +DECLARE_SOA_COLUMN(BdtScoreNonpromptD0bar, bdtScoreNonpromptD0bar, uint8_t); //! compressed BDT score (non-prompt, D0bar mass hypo) +} // namespace hf_calib + +DECLARE_SOA_TABLE(D0CalibCands, "AOD", "D0CALIBCAND", + o2::soa::Index<>, + hf_calib::CollisionId, + hf_calib::TrackPosId, + hf_calib::TrackNegId, + hf_calib::MassHypo, + hf_calib::Pt, + hf_calib::Eta, + hf_calib::Phi, + hf_calib::InvMassD0, + hf_calib::InvMassD0bar, + hf_calib::DecLength, + hf_calib::DecLengthXY, + hf_calib::NormDecLength, + hf_calib::NormDecLengthXY, + hf_calib::CosPa, + hf_calib::CosPaXY, + hf_calib::PointingAngle, + hf_calib::PointingAngleXY, + hf_calib::DecVtxChi2, + hf_calib::BdtScoreBkgD0, + hf_calib::BdtScorePromptD0, + hf_calib::BdtScoreNonpromptD0, + hf_calib::BdtScoreBkgD0bar, + hf_calib::BdtScorePromptD0bar, + hf_calib::BdtScoreNonpromptD0bar); +} // namespace aod +} // namespace o2 +#endif // DPG_TASKS_AOTTRACK_D0CALIBTABLES_H_ diff --git a/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx b/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx index c93d5980498..f247426df34 100644 --- a/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx +++ b/DPG/Tasks/AOTTrack/PID/ITS/qaPIDITS.cxx @@ -14,17 +14,18 @@ /// \brief Implementation for QA tasks of the ITS PID quantities /// -#include -#include +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" #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/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" +#include "Framework/runDataProcessing.h" + +#include +#include using namespace o2; using namespace o2::framework; @@ -183,8 +184,9 @@ struct itsPidQa { return averageClusterSizePerCoslInv(track.itsClusterSizes(), track.eta()); } - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& context) { + o2::aod::ITSResponse::setParameters(context); const AxisSpec vtxZAxis{100, -20, 20, "Vtx_{z} (cm)"}; const AxisSpec etaAxis{etaBins, "#it{#eta}"}; const AxisSpec phiAxis{phiBins, "#it{#phi}"}; diff --git a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx index 24e5a09a21a..e350f1bbf28 100644 --- a/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx +++ b/DPG/Tasks/AOTTrack/PID/TOF/qaPIDTOF.cxx @@ -15,16 +15,17 @@ /// \brief Implementation for QA tasks of the TOF PID quantities /// -#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/PIDResponse.h" #include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/PIDResponse.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" + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -135,7 +136,7 @@ struct tofPidQa { Configurable ptDeltaTEtaPhiMapMin{"ptDeltaTEtaPhiMapMin", 1.45f, "Threshold in pT to build the map of the delta time as a function of eta and phi"}; Configurable ptDeltaTEtaPhiMapMax{"ptDeltaTEtaPhiMapMax", 1.55f, "Threshold in pT to build the map of the delta time as a function of eta and phi"}; Configurable splitSignalPerCharge{"splitSignalPerCharge", true, "Split the signal per charge (reduces memory footprint if off)"}; - Configurable enableVsMomentumHistograms{"enableVsMomentumHistograms", false, "Enables plots vs momentum instead of just pT (reduces memory footprint if off)"}; + Configurable enableVsMomentumHistograms{"enableVsMomentumHistograms", 0, "1: Enables plots vs momentum instead of just pT 2: Enables plots vs momentum vs eta instead of just pT (reduces memory footprint if off)"}; Configurable requireGoodMatchTracks{"requireGoodMatchTracks", false, "Require good match tracks"}; Configurable pvContributorsMin{"pvContributorsMin", -10, "Minimum pvContributors"}; Configurable pvContributorsMax{"pvContributorsMax", 10000, "Maximum pvContributors"}; @@ -238,11 +239,16 @@ struct tofPidQa { return; } - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.add(hdelta_evtime_fill[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); histos.add(hdelta_evtime_tof[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); histos.add(hdelta_evtime_ft0[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); histos.add(hdelta_evtime_tofft0[id].data(), axisTitle, kTH2F, {pAxis, deltaAxis}); + } else if (enableVsMomentumHistograms == 2) { + histos.add(hdelta_evtime_fill[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); + histos.add(hdelta_evtime_tof[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); + histos.add(hdelta_evtime_ft0[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); + histos.add(hdelta_evtime_tofft0[id].data(), axisTitle, kTH3F, {pAxis, etaAxis, deltaAxis}); } if (splitSignalPerCharge) { @@ -598,8 +604,10 @@ struct tofPidQa { // Filling info split per ev. time if (enableEvTimeSplitting) { if (t.isEvTimeTOF() && t.isEvTimeT0AC()) { // TOF + FT0 Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_tofft0[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_tofft0[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_tofft0[id]), t.pt(), diff, t.sign()); @@ -607,8 +615,10 @@ struct tofPidQa { histos.fill(HIST(hdelta_pt_evtime_tofft0[id]), t.pt(), diff); } } else if (t.isEvTimeT0AC()) { // FT0 Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_ft0[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_ft0[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_ft0[id]), t.pt(), diff, t.sign()); @@ -616,8 +626,10 @@ struct tofPidQa { histos.fill(HIST(hdelta_pt_evtime_ft0[id]), t.pt(), diff); } } else if (t.isEvTimeTOF()) { // TOF Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_tof[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_tof[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_tof[id]), t.pt(), diff, t.sign()); @@ -625,8 +637,10 @@ struct tofPidQa { histos.fill(HIST(hdelta_pt_evtime_tof[id]), t.pt(), diff); } } else { // No Ev. Time -> Fill Ev. Time - if (enableVsMomentumHistograms) { + if (enableVsMomentumHistograms == 1) { histos.fill(HIST(hdelta_evtime_fill[id]), t.p(), diff); + } else if (enableVsMomentumHistograms == 2) { + histos.fill(HIST(hdelta_evtime_fill[id]), t.p(), t.eta(), diff); } if (splitSignalPerCharge) { histos.fill(HIST(hdelta_pt_evtime_fill[id]), t.pt(), diff, t.sign()); diff --git a/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx new file mode 100644 index 00000000000..20b50370644 --- /dev/null +++ b/DPG/Tasks/AOTTrack/derivedDataCreatorD0Calibration.cxx @@ -0,0 +1,829 @@ +// 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 derivedDataCreatorD0Calibration.cxx +/// \brief Producer of derived tables of D0 candidates, daughter tracks and collisions for calibration studies +/// +/// \author Fabrizio Grosa , CERN + +#include "D0CalibTables.h" + +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsPid.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/Multiplicity.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 + +using namespace o2; +using namespace o2::analysis; +using namespace o2::constants::physics; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_calib; + +struct DerivedDataCreatorD0Calibration { + + Produces collTable; + Produces trackTable; + Produces candTable; + + struct : ConfigurableGroup { + Configurable ptMin{"ptMin", 0.4, "min. track pT"}; + Configurable absEtaMax{"absEtaMax", 1., "max. track absolute eta"}; + Configurable> binsPt{"binsPt", std::vector{hf_calib::vecBinsPtTrack}, "track pT bin limits for DCA pT-dependent cut"}; + Configurable> limitsDca{"limitsDca", {hf_calib::CutsTrack[0], hf_calib::NBinsPtTrack, hf_calib::NCutVarsTrack, hf_calib::labelsPtTrack, hf_calib::labelsCutVarTrack}, "Single-track selections per pT bin"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0., "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 1000., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 3., "Nsigma cut on TPC only"}; + Configurable usePidTpcOnly{"usePidTpcOnly", false, "Only use TPC PID"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0., "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 1000., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 3., "Nsigma cut on TOF only"}; + std::string prefix = "trackCuts"; + } cfgTrackCuts; + + struct : ConfigurableGroup { + Configurable ptMin{"ptMin", 0., "min. D0-candidate pT"}; + Configurable> binsPt{"binsPt", std::vector{hf_calib::vecBinsPtCand}, "pT bin limits"}; + Configurable> topologicalCuts{"topologicalCuts", {hf_calib::CutsCand[0], hf_calib::NBinsPtCand, hf_calib::NCutVarsCand, hf_calib::labelsPtCand, hf_calib::labelsCutVarCand}, "D0 candidate selection per pT bin"}; + std::string prefix = "candidateCuts"; + } cfgCandCuts; + + struct : ConfigurableGroup { + Configurable apply{"apply", false, "flag to apply downsampling"}; + Configurable pathCcdbWeights{"pathCcdbWeights", "", "CCDB path containing pT-differential weights"}; + std::string prefix = "downsampling"; + } cfgDownsampling; + + struct : ConfigurableGroup { + Configurable apply{"apply", false, "flag to apply downsampling"}; + Configurable> binsPt{"binsPt", std::vector{hf_calib::vecBinsPtMl}, "pT bin limits for ML models inference"}; + Configurable> thresholdMlScores{"thresholdMlScores", {hf_calib::CutsMl[0], hf_calib::NBinsPtMl, 3, hf_calib::labelsPtMl, hf_calib::labelsCutMl}, "Threshold values for Ml output scores of D0 candidates"}; + Configurable loadMlModelsFromCCDB{"loadMlModelsFromCCDB", true, "Flag to enable or disable the loading of ML models from CCDB"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"Users/f/fgrosa/D0Calib/BDT/Pt0_1"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_pT_0_1.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + std::string prefix = "ml"; + } cfgMl; + + using TracksWCovExtraPid = soa::Join; + using CollisionsWEvSel = soa::Join; + using TrackMeanOccs = soa::Join; + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + + o2::vertexing::DCAFitterN<2> df; // 2-prong vertex fitter + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + o2::analysis::MlResponse mlResponse; + + TrackSelectorPi selectorPion; + TrackSelectorKa selectorKaon; + + int runNumber{0}; + double bz{0.}; + const float zVtxMax{10.f}; + // tolerances for preselections before vertex reconstruction + const float ptTolerance{0.1f}; + const float invMassTolerance{0.05f}; + uint32_t precisionCovMask{0xFFFFE000}; // 10 bits + uint32_t precisionDcaMask{0xFFFFFC00}; // 13 bits + + OutputObj histDownSampl{"histDownSampl"}; + + void init(InitContext const&) + { + // First we set the CCDB manager + ccdb->setURL("http://alice-ccdb.cern.ch"); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + if (cfgDownsampling.apply) { + histDownSampl.setObject(reinterpret_cast(ccdb->getSpecific(cfgDownsampling.pathCcdbWeights))); + } + + if (cfgMl.apply) { + std::vector cutDir = {o2::cuts_ml::CutDirection::CutGreater, o2::cuts_ml::CutDirection::CutSmaller, o2::cuts_ml::CutDirection::CutSmaller}; + mlResponse.configure(cfgMl.binsPt, cfgMl.thresholdMlScores, cutDir, 3); + if (cfgMl.loadMlModelsFromCCDB) { + ccdbApi.init("http://alice-ccdb.cern.ch"); + mlResponse.setModelPathsCCDB(cfgMl.onnxFileNames, ccdbApi, cfgMl.modelPathsCCDB, -1); + } else { + mlResponse.setModelPathsLocal(cfgMl.onnxFileNames); + } + mlResponse.init(); + } + + df.setPropagateToPCA(true); + df.setMaxR(200.f); + df.setMaxDZIni(4.f); + df.setMinParamChange(1.e-3f); + df.setMinRelChi2Change(0.9f); + df.setUseAbsDCA(false); + df.setWeightedFinalPCA(false); + df.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrNONE); // we are always inside the beampipe + + selectorPion.setRangePtTpc(cfgTrackCuts.ptPidTpcMin, cfgTrackCuts.ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-cfgTrackCuts.nSigmaTpcMax, cfgTrackCuts.nSigmaTpcMax); + selectorPion.setRangePtTof(cfgTrackCuts.ptPidTofMin, cfgTrackCuts.ptPidTofMax); + selectorPion.setRangeNSigmaTof(-cfgTrackCuts.nSigmaTofMax, cfgTrackCuts.nSigmaTofMax); + selectorKaon = selectorPion; + } + + void process(CollisionsWEvSel const& collisions, + aod::TrackAssoc const& trackIndices, + TracksWCovExtraPid const&, + aod::BCsWithTimestamps const&, + TrackMeanOccs const&, + aod::TracksQAVersion const&) + { + std::map selectedCollisions; // map with indices of selected collisions (key: original AOD Collision table index, value: D0 collision index) + std::map selectedTracks; // map with indices of selected tracks (key: original AOD Track table index, value: D0 daughter track index) + + for (auto const& collision : collisions) { + + // minimal event selection + if (!collision.sel8()) { + continue; + } + auto primaryVertex = getPrimaryVertex(collision); + if (std::abs(primaryVertex.getZ()) > zVtxMax) { + continue; + } + + auto covMatrixPV = primaryVertex.getCov(); + + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + initCCDB(bc, runNumber, ccdb, "GLO/Config/GRPMagField", nullptr, false); + bz = o2::base::Propagator::Instance()->getNominalBz(); + } + o2::InteractionRecord eventIR; + eventIR.setFromLong(bc.globalBC()); + + auto groupedTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); + for (auto const& trackIndexPos : groupedTrackIndices) { + auto trackPos = trackIndexPos.template track_as(); + // track selections + if (trackPos.sign() < 0) { // first positive track + continue; + } + if (!trackPos.isGlobalTrackWoDCA()) { + continue; + } + if (trackPos.pt() < cfgTrackCuts.ptMin) { + continue; + } + if (std::abs(trackPos.eta()) > cfgTrackCuts.absEtaMax) { + continue; + } + auto trackParCovPos = getTrackParCov(trackPos); + o2::dataformats::DCA dcaPos; + trackParCovPos.propagateToDCA(primaryVertex, bz, &dcaPos); + if (!isSelectedTrackDca(cfgTrackCuts.binsPt, cfgTrackCuts.limitsDca, trackParCovPos.getPt(), dcaPos.getY(), dcaPos.getZ())) { + continue; + } + + int pidTrackPosKaon{-1}; + int pidTrackPosPion{-1}; + if (cfgTrackCuts.usePidTpcOnly) { + /// kaon TPC PID positive daughter + pidTrackPosKaon = selectorKaon.statusTpc(trackPos); + /// pion TPC PID positive daughter + pidTrackPosPion = selectorPion.statusTpc(trackPos); + } else { + /// kaon TPC, TOF PID positive daughter + pidTrackPosKaon = selectorKaon.statusTpcAndTof(trackPos); + /// pion TPC, TOF PID positive daughter + pidTrackPosPion = selectorPion.statusTpcAndTof(trackPos); + } + + for (auto const& trackIndexNeg : groupedTrackIndices) { + auto trackNeg = trackIndexNeg.template track_as(); + // track selections + if (trackNeg.sign() > 0) { // second negative track + continue; + } + if (!trackNeg.isGlobalTrackWoDCA()) { + continue; + } + if (trackNeg.pt() < cfgTrackCuts.ptMin) { + continue; + } + if (std::abs(trackNeg.eta()) > cfgTrackCuts.absEtaMax) { + continue; + } + auto trackParCovNeg = getTrackParCov(trackNeg); + o2::dataformats::DCA dcaNeg; + trackParCovNeg.propagateToDCA(primaryVertex, bz, &dcaNeg); + if (!isSelectedTrackDca(cfgTrackCuts.binsPt, cfgTrackCuts.limitsDca, trackParCovNeg.getPt(), dcaNeg.getY(), dcaNeg.getZ())) { + continue; + } + + int pidTrackNegKaon{-1}; + int pidTrackNegPion{-1}; + if (cfgTrackCuts.usePidTpcOnly) { + /// kaon TPC PID negative daughter + pidTrackNegKaon = selectorKaon.statusTpc(trackNeg); + /// pion TPC PID negative daughter + pidTrackNegPion = selectorPion.statusTpc(trackNeg); + } else { + /// kaon TPC, TOF PID negative daughter + pidTrackNegKaon = selectorKaon.statusTpcAndTof(trackNeg); + /// pion TPC, TOF PID negative daughter + pidTrackNegPion = selectorPion.statusTpcAndTof(trackNeg); + } + + // preselections + // PID + uint8_t massHypo{D0MassHypo::D0AndD0Bar}; // both mass hypotheses a priori + if (pidTrackPosPion == TrackSelectorPID::Rejected || pidTrackNegKaon == TrackSelectorPID::Rejected) { + massHypo -= D0MassHypo::D0; // exclude D0 + } + if (pidTrackNegPion == TrackSelectorPID::Rejected || pidTrackPosKaon == TrackSelectorPID::Rejected) { + massHypo -= D0MassHypo::D0Bar; // exclude D0Bar + } + if (massHypo == 0) { + continue; + } + + // pt + std::array pVecNoVtxD0 = RecoDecay::pVec(trackPos.pVector(), trackNeg.pVector()); + float ptNoVtxD0 = RecoDecay::pt(pVecNoVtxD0); + if (ptNoVtxD0 - ptTolerance < cfgCandCuts.ptMin) { + continue; + } + int ptBinNoVtxD0 = findBin(cfgTrackCuts.binsPt, ptNoVtxD0 + ptTolerance); // assuming tighter selections at lower pT + if (ptBinNoVtxD0 < 0) { + continue; + } + + // d0xd0 + if (dcaPos.getY() * dcaNeg.getY() > cfgCandCuts.topologicalCuts->get(ptBinNoVtxD0, "max d0d0")) { + continue; + } + + // invariant mass + if (massHypo == D0MassHypo::D0 || massHypo == D0MassHypo::D0AndD0Bar) { + float invMassNoVtxD0 = RecoDecay::m(std::array{trackPos.pVector(), trackNeg.pVector()}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); + if (std::abs(invMassNoVtxD0 - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinNoVtxD0, "delta inv. mass") + invMassTolerance) { + massHypo -= D0MassHypo::D0; + } + } + if (massHypo >= D0MassHypo::D0Bar) { + float invMassNoVtxD0bar = RecoDecay::m(std::array{trackNeg.pVector(), trackPos.pVector()}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); + if (std::abs(invMassNoVtxD0bar - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinNoVtxD0, "delta inv. mass") + invMassTolerance) { + massHypo -= D0MassHypo::D0Bar; + } + } + if (massHypo == 0) { + continue; + } + + // reconstruct vertex + if (df.process(trackParCovPos, trackParCovNeg) == 0) { + continue; + } + const auto& secondaryVertex = df.getPCACandidate(); + auto chi2PCA = df.getChi2AtPCACandidate(); + auto covMatrixPCA = df.calcPCACovMatrixFlat(); + auto trackParAtSecVtxPos = df.getTrack(0); + auto trackParAtSecVtxNeg = df.getTrack(1); + + std::array pVecPos{}; + std::array pVecNeg{}; + trackParAtSecVtxPos.getPxPyPzGlo(pVecPos); + trackParAtSecVtxNeg.getPxPyPzGlo(pVecNeg); + std::array pVecD0 = RecoDecay::pVec(pVecPos, pVecNeg); + + // select D0 + // pt + float ptD0 = RecoDecay::pt(pVecD0); + if (ptD0 < cfgCandCuts.ptMin) { + continue; + } + int ptBinD0 = findBin(cfgTrackCuts.binsPt, ptD0); + if (ptBinD0 < 0) { + continue; + } + + // random downsampling already here + if (cfgDownsampling.apply) { + int ptBinWeights{0}; + if (ptD0 < histDownSampl->GetBinLowEdge(1)) { + ptBinWeights = 1; + } else if (ptD0 > histDownSampl->GetXaxis()->GetBinUpEdge(histDownSampl->GetNbinsX())) { + ptBinWeights = histDownSampl->GetNbinsX(); + } else { + ptBinWeights = histDownSampl->GetXaxis()->FindBin(ptD0); + } + float weight = histDownSampl->GetBinContent(ptBinWeights); + if (gRandom->Rndm() > weight) { + continue; + } + } + + // d0xd0 + if (dcaPos.getY() * dcaNeg.getY() > cfgCandCuts.topologicalCuts->get(ptBinD0, "max d0d0")) { + continue; + } + // cospa + float cosPaD0 = RecoDecay::cpa(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, pVecD0); + if (cosPaD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min cos pointing angle")) { + continue; + } + // pointing angle + float paD0 = std::acos(cosPaD0); + if (paD0 > cfgCandCuts.topologicalCuts->get(ptBinD0, "max pointing angle")) { + continue; + } + // cospa XY + float cosPaXYD0 = RecoDecay::cpaXY(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, pVecD0); + if (cosPaXYD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min cos pointing angle XY")) { + continue; + } + // pointing angle XY + float paXYD0 = std::acos(cosPaXYD0); + if (paXYD0 > cfgCandCuts.topologicalCuts->get(ptBinD0, "max pointing angle XY")) { + continue; + } + // decay length + float decLenD0 = RecoDecay::distance(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex); + if (decLenD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min decay length")) { + continue; + } + // decay length XY + float decLenXYD0 = RecoDecay::distanceXY(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex); + if (decLenXYD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min decay length XY")) { + continue; + } + // normalised decay length + float phi{0.f}, theta{0.f}; + getPointDirection(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, secondaryVertex, phi, theta); + float errorDecayLengthD0 = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + if (decLenD0 / errorDecayLengthD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min norm decay length")) { + continue; + } + // normalised decay length XY + float errorDecayLengthXYD0 = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.f) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.f)); + if (decLenXYD0 / errorDecayLengthXYD0 < cfgCandCuts.topologicalCuts->get(ptBinD0, "min norm decay length XY")) { + continue; + } + + float invMassD0{0.f}, invMassD0bar{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}); + if (std::abs(invMassD0 - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinD0, "delta inv. mass")) { + massHypo -= D0MassHypo::D0; + bdtScoresD0 = std::vector{1.f, 0.f, 0.f}; + } else { + // apply BDT models + if (cfgMl.apply) { + 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())}; + mlResponse.isSelectedMl(featuresCandD0, ptD0, bdtScoresD0); + } + } + } + if (massHypo >= D0MassHypo::D0Bar) { + invMassD0bar = RecoDecay::m(std::array{pVecNeg, pVecPos}, std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus}); + if (std::abs(invMassD0bar - o2::constants::physics::MassD0) > cfgCandCuts.topologicalCuts->get(ptBinD0, "delta inv. mass")) { + massHypo -= D0MassHypo::D0Bar; + bdtScoresD0bar = std::vector{1.f, 0.f, 0.f}; + } else { + // apply BDT models + if (cfgMl.apply) { + 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())}; + mlResponse.isSelectedMl(featuresCandD0bar, ptD0, bdtScoresD0bar); + } + } + } + if (massHypo == 0) { + continue; + } + + float etaD0 = RecoDecay::eta(pVecD0); + float phiD0 = RecoDecay::phi(pVecD0); + + // fill tables + // collision + if (!selectedCollisions.count(collision.globalIndex())) { + // fill collision table if not yet present + collTable(collision.posX(), + collision.posY(), + collision.posZ(), + collision.covXX(), + collision.covXY(), + collision.covXZ(), + collision.covYY(), + collision.covYZ(), + collision.covZZ(), + collision.numContrib(), + uint8_t(std::round(collision.centFT0C())), + getCompressedOccupancy(collision.trackOccupancyInTimeRange()), + getCompressedOccupancy(collision.ft0cOccupancyInTimeRange()), + eventIR.orbit, + runNumber); + selectedCollisions[collision.globalIndex()] = collTable.lastIndex(); + } + // tracks + if (!selectedTracks.count(trackPos.globalIndex())) { + // fill track table with positive track if not yet present + uint8_t tmoPrimUnfm80{0u}; + uint8_t tmoFV0AUnfm80{0u}; + uint8_t tmoFT0AUnfm80{0u}; + uint8_t tmoFT0CUnfm80{0u}; + uint8_t twmoPrimUnfm80{0u}; + uint8_t twmoFV0AUnfm80{0u}; + uint8_t twmoFT0AUnfm80{0u}; + uint8_t twmoFT0CUnfm80{0u}; + uint8_t tmoRobustT0V0PrimUnfm80{0u}; + uint8_t twmoRobustT0V0PrimUnfm80{0u}; + if (trackPos.has_tmo()) { + auto tmoFromTrack = trackPos.tmo_as(); // obtain track mean occupancies + tmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()); + tmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()); + tmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()); + tmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()); + twmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()); + twmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()); + twmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()); + twmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()); + tmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()); + twmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80()); + } + float tpcTime0{0.f}; + float tpcdEdxNorm{0.f}; + int16_t tpcDcaR{0}; + int16_t tpcDcaZ{0}; + uint8_t tpcClusterByteMask{0u}; + uint8_t tpcdEdxMax0R{0u}; + uint8_t tpcdEdxMax1R{0u}; + uint8_t tpcdEdxMax2R{0u}; + uint8_t tpcdEdxMax3R{0u}; + uint8_t tpcdEdxTot0R{0u}; + uint8_t tpcdEdxTot1R{0u}; + uint8_t tpcdEdxTot2R{0u}; + uint8_t tpcdEdxTot3R{0u}; + int8_t deltaRefContParamY{0}; + int8_t deltaRefITSParamZ{0}; + int8_t deltaRefContParamSnp{0}; + int8_t deltaRefContParamTgl{0}; + int8_t deltaRefContParamQ2Pt{0}; + int8_t deltaRefGloParamY{0}; + int8_t deltaRefGloParamZ{0}; + int8_t deltaRefGloParamSnp{0}; + int8_t deltaRefGloParamTgl{0}; + int8_t deltaRefGloParamQ2Pt{0}; + int8_t deltaTOFdX{0}; + int8_t deltaTOFdZ{0}; + if (trackPos.has_trackQA()) { + auto trackQA = trackPos.trackQA_as(); // obtain track QA + tpcTime0 = trackQA.tpcTime0(); + tpcdEdxNorm = trackQA.tpcdEdxNorm(); + tpcDcaR = trackQA.tpcdcaR(); + tpcDcaZ = trackQA.tpcdcaZ(); + tpcClusterByteMask = trackQA.tpcClusterByteMask(); + tpcdEdxMax0R = trackQA.tpcdEdxMax0R(); + tpcdEdxMax1R = trackQA.tpcdEdxMax1R(); + tpcdEdxMax2R = trackQA.tpcdEdxMax2R(); + tpcdEdxMax3R = trackQA.tpcdEdxMax3R(); + tpcdEdxTot0R = trackQA.tpcdEdxTot0R(); + tpcdEdxTot1R = trackQA.tpcdEdxTot1R(); + tpcdEdxTot2R = trackQA.tpcdEdxTot2R(); + tpcdEdxTot3R = trackQA.tpcdEdxTot3R(); + deltaRefContParamY = trackQA.deltaRefContParamY(); + deltaRefITSParamZ = trackQA.deltaRefITSParamZ(); + deltaRefContParamSnp = trackQA.deltaRefContParamSnp(); + deltaRefContParamTgl = trackQA.deltaRefContParamTgl(); + deltaRefContParamQ2Pt = trackQA.deltaRefContParamQ2Pt(); + deltaRefGloParamY = trackQA.deltaRefGloParamY(); + deltaRefGloParamZ = trackQA.deltaRefGloParamZ(); + deltaRefGloParamSnp = trackQA.deltaRefGloParamSnp(); + deltaRefGloParamTgl = trackQA.deltaRefGloParamTgl(); + deltaRefGloParamQ2Pt = trackQA.deltaRefGloParamQ2Pt(); + deltaTOFdX = trackQA.deltaTOFdX(); + deltaTOFdZ = trackQA.deltaTOFdZ(); + } + + trackTable(selectedCollisions[collision.globalIndex()], // stored at PV + trackPos.x(), + trackPos.alpha(), + trackPos.y(), + trackPos.z(), + trackPos.snp(), + trackPos.tgl(), + trackPos.signed1Pt(), + o2::math_utils::detail::truncateFloatFraction(trackPos.cYY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cZY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cZZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cSnpY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cSnpZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cSnpSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.cTglTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1PtTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackPos.c1Pt21Pt2(), precisionCovMask), + trackPos.tpcInnerParam(), + trackPos.flags(), + trackPos.itsClusterSizes(), + trackPos.tpcNClsFindable(), + trackPos.tpcNClsFindableMinusFound(), + trackPos.tpcNClsFindableMinusCrossedRows(), + trackPos.tpcNClsShared(), + trackPos.trdPattern(), + getCompressedChi2(trackPos.itsChi2NCl()), + getCompressedChi2(trackPos.tpcChi2NCl()), + getCompressedChi2(trackPos.trdChi2()), + getCompressedChi2(trackPos.tofChi2()), + trackPos.tpcSignal(), + trackPos.trdSignal(), + trackPos.length(), + trackPos.tofExpMom(), + trackPos.trackTime(), + trackPos.trackTimeRes(), + tpcTime0, + tpcdEdxNorm, + tpcDcaR, + tpcDcaZ, + tpcClusterByteMask, + tpcdEdxMax0R, + tpcdEdxMax1R, + tpcdEdxMax2R, + tpcdEdxMax3R, + tpcdEdxTot0R, + tpcdEdxTot1R, + tpcdEdxTot2R, + tpcdEdxTot3R, + deltaRefContParamY, + deltaRefITSParamZ, + deltaRefContParamSnp, + deltaRefContParamTgl, + deltaRefContParamQ2Pt, + deltaRefGloParamY, + deltaRefGloParamZ, + deltaRefGloParamSnp, + deltaRefGloParamTgl, + deltaRefGloParamQ2Pt, + deltaTOFdX, + deltaTOFdZ, + o2::math_utils::detail::truncateFloatFraction(dcaPos.getY(), precisionDcaMask), + o2::math_utils::detail::truncateFloatFraction(dcaPos.getZ(), precisionDcaMask), + getCompressedNumSigmaPid(trackPos.tpcNSigmaPi()), + getCompressedNumSigmaPid(trackPos.tpcNSigmaKa()), + getCompressedNumSigmaPid(trackPos.tofNSigmaPi()), + getCompressedNumSigmaPid(trackPos.tofNSigmaKa()), + tmoPrimUnfm80, + tmoFV0AUnfm80, + tmoFT0AUnfm80, + tmoFT0CUnfm80, + twmoPrimUnfm80, + twmoFV0AUnfm80, + twmoFT0AUnfm80, + twmoFT0CUnfm80, + tmoRobustT0V0PrimUnfm80, + twmoRobustT0V0PrimUnfm80); + selectedTracks[trackPos.globalIndex()] = trackTable.lastIndex(); + } + if (!selectedTracks.count(trackNeg.globalIndex())) { + // fill track table with negative track if not yet present + uint8_t tmoPrimUnfm80{0u}; + uint8_t tmoFV0AUnfm80{0u}; + uint8_t tmoFT0AUnfm80{0u}; + uint8_t tmoFT0CUnfm80{0u}; + uint8_t twmoPrimUnfm80{0u}; + uint8_t twmoFV0AUnfm80{0u}; + uint8_t twmoFT0AUnfm80{0u}; + uint8_t twmoFT0CUnfm80{0u}; + uint8_t tmoRobustT0V0PrimUnfm80{0u}; + uint8_t twmoRobustT0V0PrimUnfm80{0u}; + if (trackNeg.has_tmo()) { + auto tmoFromTrack = trackNeg.tmo_as(); // obtain track mean occupancies + tmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoPrimUnfm80()); + tmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFV0AUnfm80()); + tmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0AUnfm80()); + tmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoFT0CUnfm80()); + twmoPrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoPrimUnfm80()); + twmoFV0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFV0AUnfm80()); + twmoFT0AUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0AUnfm80()); + twmoFT0CUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoFT0CUnfm80()); + tmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.tmoRobustT0V0PrimUnfm80()); + twmoRobustT0V0PrimUnfm80 = getCompressedOccupancy(tmoFromTrack.twmoRobustT0V0PrimUnfm80()); + } + float tpcTime0{0.f}; + float tpcdEdxNorm{0.f}; + int16_t tpcDcaR{0}; + int16_t tpcDcaZ{0}; + uint8_t tpcClusterByteMask{0u}; + uint8_t tpcdEdxMax0R{0u}; + uint8_t tpcdEdxMax1R{0u}; + uint8_t tpcdEdxMax2R{0u}; + uint8_t tpcdEdxMax3R{0u}; + uint8_t tpcdEdxTot0R{0u}; + uint8_t tpcdEdxTot1R{0u}; + uint8_t tpcdEdxTot2R{0u}; + uint8_t tpcdEdxTot3R{0u}; + int8_t deltaRefContParamY{0}; + int8_t deltaRefITSParamZ{0}; + int8_t deltaRefContParamSnp{0}; + int8_t deltaRefContParamTgl{0}; + int8_t deltaRefContParamQ2Pt{0}; + int8_t deltaRefGloParamY{0}; + int8_t deltaRefGloParamZ{0}; + int8_t deltaRefGloParamSnp{0}; + int8_t deltaRefGloParamTgl{0}; + int8_t deltaRefGloParamQ2Pt{0}; + int8_t deltaTOFdX{0}; + int8_t deltaTOFdZ{0}; + if (trackNeg.has_trackQA()) { + auto trackQA = trackNeg.trackQA_as(); // obtain track QA + tpcTime0 = trackQA.tpcTime0(); + tpcdEdxNorm = trackQA.tpcdEdxNorm(); + tpcDcaR = trackQA.tpcdcaR(); + tpcDcaZ = trackQA.tpcdcaZ(); + tpcClusterByteMask = trackQA.tpcClusterByteMask(); + tpcdEdxMax0R = trackQA.tpcdEdxMax0R(); + tpcdEdxMax1R = trackQA.tpcdEdxMax1R(); + tpcdEdxMax2R = trackQA.tpcdEdxMax2R(); + tpcdEdxMax3R = trackQA.tpcdEdxMax3R(); + tpcdEdxTot0R = trackQA.tpcdEdxTot0R(); + tpcdEdxTot1R = trackQA.tpcdEdxTot1R(); + tpcdEdxTot2R = trackQA.tpcdEdxTot2R(); + tpcdEdxTot3R = trackQA.tpcdEdxTot3R(); + deltaRefContParamY = trackQA.deltaRefContParamY(); + deltaRefITSParamZ = trackQA.deltaRefITSParamZ(); + deltaRefContParamSnp = trackQA.deltaRefContParamSnp(); + deltaRefContParamTgl = trackQA.deltaRefContParamTgl(); + deltaRefContParamQ2Pt = trackQA.deltaRefContParamQ2Pt(); + deltaRefGloParamY = trackQA.deltaRefGloParamY(); + deltaRefGloParamZ = trackQA.deltaRefGloParamZ(); + deltaRefGloParamSnp = trackQA.deltaRefGloParamSnp(); + deltaRefGloParamTgl = trackQA.deltaRefGloParamTgl(); + deltaRefGloParamQ2Pt = trackQA.deltaRefGloParamQ2Pt(); + deltaTOFdX = trackQA.deltaTOFdX(); + deltaTOFdZ = trackQA.deltaTOFdZ(); + } + + trackTable(selectedCollisions[collision.globalIndex()], // stored at PV + trackNeg.x(), + trackNeg.alpha(), + trackNeg.y(), + trackNeg.z(), + trackNeg.snp(), + trackNeg.tgl(), + trackNeg.signed1Pt(), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cYY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cZY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cZZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cSnpY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cSnpZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cSnpSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.cTglTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtY(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtZ(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtSnp(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1PtTgl(), precisionCovMask), + o2::math_utils::detail::truncateFloatFraction(trackNeg.c1Pt21Pt2(), precisionCovMask), + trackNeg.tpcInnerParam(), + trackNeg.flags(), + trackNeg.itsClusterSizes(), + trackNeg.tpcNClsFindable(), + trackNeg.tpcNClsFindableMinusFound(), + trackNeg.tpcNClsFindableMinusCrossedRows(), + trackNeg.tpcNClsShared(), + trackNeg.trdPattern(), + getCompressedChi2(trackNeg.itsChi2NCl()), + getCompressedChi2(trackNeg.tpcChi2NCl()), + getCompressedChi2(trackNeg.trdChi2()), + getCompressedChi2(trackNeg.tofChi2()), + trackNeg.tpcSignal(), + trackNeg.trdSignal(), + trackNeg.length(), + trackNeg.tofExpMom(), + trackNeg.trackTime(), + trackNeg.trackTimeRes(), + tpcTime0, + tpcdEdxNorm, + tpcDcaR, + tpcDcaZ, + tpcClusterByteMask, + tpcdEdxMax0R, + tpcdEdxMax1R, + tpcdEdxMax2R, + tpcdEdxMax3R, + tpcdEdxTot0R, + tpcdEdxTot1R, + tpcdEdxTot2R, + tpcdEdxTot3R, + deltaRefContParamY, + deltaRefITSParamZ, + deltaRefContParamSnp, + deltaRefContParamTgl, + deltaRefContParamQ2Pt, + deltaRefGloParamY, + deltaRefGloParamZ, + deltaRefGloParamSnp, + deltaRefGloParamTgl, + deltaRefGloParamQ2Pt, + deltaTOFdX, + deltaTOFdZ, + o2::math_utils::detail::truncateFloatFraction(dcaNeg.getY(), precisionDcaMask), + o2::math_utils::detail::truncateFloatFraction(dcaNeg.getZ(), precisionDcaMask), + getCompressedNumSigmaPid(trackNeg.tpcNSigmaPi()), + getCompressedNumSigmaPid(trackNeg.tpcNSigmaKa()), + getCompressedNumSigmaPid(trackNeg.tofNSigmaPi()), + getCompressedNumSigmaPid(trackNeg.tofNSigmaKa()), + tmoPrimUnfm80, + tmoFV0AUnfm80, + tmoFT0AUnfm80, + tmoFT0CUnfm80, + twmoPrimUnfm80, + twmoFV0AUnfm80, + twmoFT0AUnfm80, + twmoFT0CUnfm80, + tmoRobustT0V0PrimUnfm80, + twmoRobustT0V0PrimUnfm80); + selectedTracks[trackNeg.globalIndex()] = trackTable.lastIndex(); + } + + // candidate + candTable(selectedCollisions[collision.globalIndex()], + selectedTracks[trackPos.globalIndex()], + selectedTracks[trackNeg.globalIndex()], + massHypo, + ptD0, + etaD0, + phiD0, + invMassD0, + invMassD0bar, + getCompressedDecayLength(decLenD0), + getCompressedDecayLength(decLenXYD0), + getCompressedNormDecayLength(decLenD0 / errorDecayLengthD0), + getCompressedNormDecayLength(decLenXYD0 / errorDecayLengthXYD0), + getCompressedCosPa(cosPaD0), + getCompressedCosPa(cosPaXYD0), + getCompressedPointingAngle(paD0), + getCompressedPointingAngle(paXYD0), + getCompressedChi2(chi2PCA), + getCompressedBdtScoreBkg(bdtScoresD0[0]), + getCompressedBdtScoreSgn(bdtScoresD0[1]), + getCompressedBdtScoreSgn(bdtScoresD0[2]), + getCompressedBdtScoreBkg(bdtScoresD0bar[0]), + getCompressedBdtScoreSgn(bdtScoresD0bar[1]), + getCompressedBdtScoreSgn(bdtScoresD0bar[2])); + } // end loop over negative tracks + } // end loop over positive tracks + } // end loop over collisions tracks + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/DPG/Tasks/AOTTrack/qaImpPar.cxx b/DPG/Tasks/AOTTrack/qaImpPar.cxx index 2ff3ca3761c..45f66123aee 100644 --- a/DPG/Tasks/AOTTrack/qaImpPar.cxx +++ b/DPG/Tasks/AOTTrack/qaImpPar.cxx @@ -10,33 +10,32 @@ // or submit itself to any jurisdiction. /// \author Mattia Faggin , Padova University and INFN -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/DCA.h" +#include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" // for propagation to primary vertex - #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/PIDResponse.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "CommonUtils/NameConf.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/Core/TrackSelection.h" -#include "DetectorsVertexing/PVertexer.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Framework/RunningWorkflowInfo.h" #include "CCDB/CcdbApi.h" -#include "DataFormatsCalibration/MeanVertexObject.h" #include "CommonConstants/GeomConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "DetectorsVertexing/PVertexer.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Vertex.h" #include -#include #include +#include +#include using namespace o2::framework; using namespace o2::framework::expressions; @@ -153,28 +152,47 @@ struct QaImpactPar { /// Data using CollisionRecoTable = o2::soa::Join; using TrackTable = o2::soa::Join; - using TrackFullTable = o2::soa::Join; + using TrackFullTable = o2::soa::Join; using TrackTableIU = o2::soa::Join; + /// + /// @brief process function in data, without the usage of PID info void processData(o2::soa::Filtered::iterator const& collision, const TrackTable& tracksUnfiltered, - const o2::soa::Filtered& tracks, + const o2::soa::Filtered& tracks, const TrackTableIU& tracksIU, o2::aod::BCsWithTimestamps const&) { /// here call the template processReco function auto bc = collision.bc_as(); - processReco(collision, tracksUnfiltered, tracks, tracksIU, 0, bc); + processReco(collision, tracksUnfiltered, tracks, tracksIU, 0, bc); } PROCESS_SWITCH(QaImpactPar, processData, "process data", true); + /// + /// @brief process function in data, with the possibility to use PID info + void processDataWithPid(o2::soa::Filtered::iterator const& collision, + const TrackTable& tracksUnfiltered, + const o2::soa::Filtered& tracks, + const TrackTableIU& tracksIU, + o2::aod::BCsWithTimestamps const&) + { + /// here call the template processReco function + auto bc = collision.bc_as(); + processReco(collision, tracksUnfiltered, tracks, tracksIU, 0, bc); + } + PROCESS_SWITCH(QaImpactPar, processDataWithPid, "process data with PID", false); /// MC using CollisionMCRecoTable = o2::soa::Join; + using TrackMCFullTableNoPid = o2::soa::Join; using TrackMCFullTable = o2::soa::Join; + /// + /// @brief process function in MC, without the usage of PID info void processMC(o2::soa::Filtered::iterator const& collision, TrackTable const& tracksUnfiltered, - o2::soa::Filtered const& tracks, + o2::soa::Filtered const& tracks, const TrackTableIU& tracksIU, const o2::aod::McParticles& mcParticles, const o2::aod::McCollisions&, @@ -182,9 +200,24 @@ struct QaImpactPar { { /// here call the template processReco function auto bc = collision.bc_as(); - processReco(collision, tracksUnfiltered, tracks, tracksIU, mcParticles, bc); + processReco(collision, tracksUnfiltered, tracks, tracksIU, mcParticles, bc); } PROCESS_SWITCH(QaImpactPar, processMC, "process MC", false); + /// + /// @brief process function in MC,with the possibility to use PID info + void processMCWithPid(o2::soa::Filtered::iterator const& collision, + TrackTable const& tracksUnfiltered, + o2::soa::Filtered const& tracks, + const TrackTableIU& tracksIU, + const o2::aod::McParticles& mcParticles, + const o2::aod::McCollisions&, + o2::aod::BCsWithTimestamps const&) + { + /// here call the template processReco function + auto bc = collision.bc_as(); + processReco(collision, tracksUnfiltered, tracks, tracksIU, mcParticles, bc); + } + PROCESS_SWITCH(QaImpactPar, processMCWithPid, "process MC with PID", false); /// core template process function /// template @@ -197,6 +230,11 @@ struct QaImpactPar { /// init function - declare and define histograms void init(InitContext&) { + std::array processes = {doprocessData, doprocessDataWithPid, doprocessMC, doprocessMCWithPid}; + if (std::accumulate(processes.begin(), processes.end(), 0) != 1) { + LOGP(fatal, "One and only one process function for collision study must be enabled at a time."); + } + // Primary vertex const AxisSpec collisionXAxis{100, -20.f, 20.f, "X (cm)"}; const AxisSpec collisionYAxis{100, -20.f, 20.f, "Y (cm)"}; @@ -367,7 +405,7 @@ struct QaImpactPar { } /// core template process function - template + template void processReco(const C& collision, const TrackTable& unfilteredTracks, const T& tracks, const TrackTableIU& tracksIU, const T_MC& /*mcParticles*/, o2::aod::BCsWithTimestamps::iterator const& bc) @@ -596,12 +634,14 @@ struct QaImpactPar { pt = track.pt(); p = track.p(); - tpcNSigmaPion = track.tpcNSigmaPi(); - tpcNSigmaKaon = track.tpcNSigmaKa(); - tpcNSigmaProton = track.tpcNSigmaPr(); - tofNSigmaPion = track.tofNSigmaPi(); - tofNSigmaKaon = track.tofNSigmaKa(); - tofNSigmaProton = track.tofNSigmaPr(); + if constexpr (USE_PID) { + tpcNSigmaPion = track.tpcNSigmaPi(); + tpcNSigmaKaon = track.tpcNSigmaKa(); + tpcNSigmaProton = track.tpcNSigmaPr(); + tofNSigmaPion = track.tofNSigmaPi(); + tofNSigmaKaon = track.tofNSigmaKa(); + tofNSigmaProton = track.tofNSigmaPr(); + } histograms.fill(HIST("Reco/pt"), pt); histograms.fill(HIST("Reco/hNSigmaTPCPion"), pt, tpcNSigmaPion); diff --git a/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx b/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx index 2d236ee0230..31820a7c593 100644 --- a/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx +++ b/DPG/Tasks/AOTTrack/tagAndProbeDmesons.cxx @@ -14,8 +14,8 @@ /// /// \author Fabrizio Grosa , CERN -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" +#include "PWGHF/Utils/utilsAnalysis.h" + #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" @@ -23,15 +23,22 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" #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 "DCAFitter/DCAFitterN.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGHF/Utils/utilsAnalysis.h" -#include "Tools/ML/MlResponse.h" + #include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -734,7 +741,7 @@ struct TagTwoProngDisplacedVertices { } else if (fillTopoVarsTable == 3 && !TESTBIT(isSignal, aod::tagandprobe::SignalFlags::BkgFromNoHf)) { // only background excluding tracks from other HF decays fillTable = false; } - float pseudoRndm = trackFirst.pt() * 1000. - (int64_t)(trackFirst.pt() * 1000); + float pseudoRndm = trackFirst.pt() * 1000. - static_cast(trackFirst.pt() * 1000); if (ptTag < ptTagMaxForDownsampling && pseudoRndm >= downsamplingForTopoVarTable) { fillTable = false; } @@ -899,7 +906,7 @@ struct TagTwoProngDisplacedVertices { } else if (fillTopoVarsTable == 3 && !TESTBIT(isSignal, aod::tagandprobe::SignalFlags::BkgFromNoHf)) { // only background excluding tracks from other HF decays fillTable = false; } - float pseudoRndm = trackPos.pt() * 1000. - (int64_t)(trackPos.pt() * 1000); + float pseudoRndm = trackPos.pt() * 1000. - static_cast(trackPos.pt() * 1000); if (ptTag < ptTagMaxForDownsampling && pseudoRndm >= downsamplingForTopoVarTable) { fillTable = false; } @@ -1150,6 +1157,7 @@ struct ProbeThirdTrack { Configurable> mlCutsDzeroFromDstar{"mlCutsDzeroFromDstar", {aod::tagandprobe::mlCuts[0], aod::tagandprobe::nBinsPt, 3, aod::tagandprobe::labelsEmpty, aod::tagandprobe::labelsMlScores}, "ML Selections for Kpi pairs from D0 <- D*+ decays"}; } mlConfig; Configurable ptCandMin{"ptCandMin", 0.f, "Minimum candidate pt for THnSparse filling"}; + Configurable fillTpcOnlyCase{"fillTpcOnlyCase", true, "Fill output for TPC only case (not needed for thinned data or Pb-Pb)"}; ConfigurableAxis axisPtProbe{"axisPtProbe", {VARIABLE_WIDTH, 0.05f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 12.f, 15.f, 20.f, 25.f, 30.f}, "Axis for pt Probe"}; ConfigurableAxis axisPtTag{"axisPtTag", {VARIABLE_WIDTH, 0.05f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, 1.2f, 1.5f, 2.0f, 2.5f, 3.0f, 3.5f, 4.0f, 4.5f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.f, 12.f, 15.f, 20.f, 25.f, 30.f}, "Axis for pt Tag"}; @@ -1250,6 +1258,9 @@ struct ProbeThirdTrack { for (int iChannel{0}; iChannel < aod::tagandprobe::TagChannels::NTagChannels; ++iChannel) { for (int iTrackType{0}; iTrackType < aod::tagandprobe::TrackTypes::NTrackTypes; ++iTrackType) { + if (!fillTpcOnlyCase && iTrackType == aod::tagandprobe::TrackTypes::GlobalWoDcaWoIts) { + continue; + } histos[iChannel][iTrackType] = registry.add(Form("h%sVsPtProbeTag_%s", tagChannels[iChannel].data(), trackTypes[iTrackType].data()), "; #it{p}_{T}(D) (GeV/#it{c}); #it{p}_{T}(tag) (GeV/#it{c}); #it{p}_{T}(probe) (GeV/#it{c}); #it{p}_{T}^{TPC in}(probe) (GeV/#it{c}); #it{M}(D) (GeV/#it{c}^{2}); #it{M}(tag) (GeV/#it{c}^{2}); #it{#eta}(probe); #it{N}_{cross rows}^{TPC}(probe); #chi^{2}/#it{N}_{clusters}^{TPC}(probe); #it{N}_{clusters}^{ITS}(probe);", HistType::kTHnSparseF, {axisPtD, axisPtTag, axisPtProbe, axisPtProbe, axisMass[iChannel], axisMassTag[iChannel], axisEtaProbe, axisNumCrossRowTpc, axisTpcChi2PerClus, axisNumCluIts}); @@ -1346,6 +1357,9 @@ struct ProbeThirdTrack { continue; } for (int iTrackType{0}; iTrackType < aod::tagandprobe::TrackTypes::NTrackTypes; ++iTrackType) { + if (!fillTpcOnlyCase && iTrackType == aod::tagandprobe::TrackTypes::GlobalWoDcaWoIts) { + continue; + } if (trackSelector[iTrackType].IsSelected(trackThird)) { histos[channel][iTrackType]->Fill(ptD, ptTag, ptTrackThird, ptTpcInnerTrackThird, invMass, invMassTag, etaTrackThird, numTpcCrossRowTrackThird, numTpcChi2NumCluTrackThird, numItsCluTrackThird); } diff --git a/DPG/Tasks/ITS/CMakeLists.txt b/DPG/Tasks/ITS/CMakeLists.txt index 2850271fb41..fc835ea769d 100644 --- a/DPG/Tasks/ITS/CMakeLists.txt +++ b/DPG/Tasks/ITS/CMakeLists.txt @@ -16,3 +16,8 @@ o2physics_add_dpl_workflow(its-impact-parameter-studies O2::DetectorsCommonDataFormats O2::DetectorsVertexing COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(filtertracks + SOURCES filterTracks.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/DPG/Tasks/ITS/filterTracks.cxx b/DPG/Tasks/ITS/filterTracks.cxx new file mode 100644 index 00000000000..ed35c1dd95c --- /dev/null +++ b/DPG/Tasks/ITS/filterTracks.cxx @@ -0,0 +1,430 @@ +// 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 filterTracks.cxx +/// \brief Simple task to filter tracks and save infos to trees for DCA-related studies (alignment, HF-related issues, ...) +/// +/// \author Andrea Rossi + +#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/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include + +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod::track; +using namespace o2::aod::mctracklabel; +using namespace o2::framework::expressions; + +namespace o2::aod +{ +namespace filtertracks +{ + +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! Collision index +DECLARE_SOA_COLUMN(IsInsideBeamPipe, isInsideBeamPipe, int); //! is within beam pipe +DECLARE_SOA_COLUMN(Pt, pt, float); //! track pt +DECLARE_SOA_COLUMN(Px, px, float); //! track px +DECLARE_SOA_COLUMN(Py, py, float); //! track py +DECLARE_SOA_COLUMN(Pz, pz, float); //! track pz +// DECLARE_SOA_COLUMN(Eta, eta, float); //! track eta +// DECLARE_SOA_COLUMN(X, x, float); //! track x position at the DCA to the primary vertex +// DECLARE_SOA_COLUMN(Y, y, float); //! track y position at the DCA to the primary vertex +// 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 + +///// 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 +DECLARE_SOA_COLUMN(MainBeautyAncestorPdgCode, mainBeautyAncestorPdgCode, int); //! pdgcode of beauty particle when this is an ancestor, otherwise -1 +DECLARE_SOA_COLUMN(MainMotherOrigIndex, mainMotherOrigIndex, int); //! original index in MCParticle tree of main mother: needed when checking if particles come from same mother +DECLARE_SOA_COLUMN(MainMotherNfinalStateDaught, mainMotherNfinalStateDaught, int); //! number of final state (we consider only pions, kaons, muons, electrons, protons) daughter in main mother decay. To be noted that this is computed only for decays of particles of interest (D0, Lc, K0s). If the sign is negative, it means that the decay is not in one of the desired channels (K0s->pi pi, Lc->pKpi, D0->K-pi+) + +DECLARE_SOA_COLUMN(MainMotherPt, mainMotherPt, float); //! original index in MCParticle tree of main mother: needed when chekcing if particles come from same mother +DECLARE_SOA_COLUMN(MainMotherY, mainMotherY, float); //! original index in MCParticle tree of main mother: needed when chekcing if particles come from same mother +DECLARE_SOA_COLUMN(MainBeautyAncestorPt, mainBeautyAncestorPt, float); //! original index in MCParticle tree of main mother: needed when chekcing if particles come from same mother +DECLARE_SOA_COLUMN(MainBeautyAncestorY, mainBeautyAncestorY, float); //! original index in MCParticle tree of main mother: needed when chekcing if particles come from same mother +DECLARE_SOA_COLUMN(MaxEtaDaughter, maxEtaDaughter, float); //! max (abs) eta of daughter particles, needed to reproduce acceptance cut +} // namespace filtertracks +DECLARE_SOA_TABLE(FilterColl, "AOD", "FILTERCOLL", + o2::aod::collision::BCId, + o2::aod::collision::PosX, + o2::aod::collision::PosY, + o2::aod::collision::PosZ, + o2::aod::collision::CovXX, + o2::aod::collision::CovXY, + o2::aod::collision::CovYY, + o2::aod::collision::CovXZ, + o2::aod::collision::CovYZ, + o2::aod::collision::CovZZ, + o2::aod::collision::Flags, + o2::aod::collision::Chi2, + o2::aod::collision::NumContrib, + o2::aod::collision::CollisionTime, + o2::aod::collision::CollisionTimeRes); +DECLARE_SOA_TABLE(FilterCollLite, "AOD", "FILTERCOLLLITE", + o2::aod::collision::PosX, + o2::aod::collision::PosY, + o2::aod::collision::PosZ, + o2::aod::collision::CovXX, + o2::aod::collision::CovXY, + o2::aod::collision::CovYY, + o2::aod::collision::CovXZ, + o2::aod::collision::CovYZ, + o2::aod::collision::CovZZ, + o2::aod::collision::Chi2, + o2::aod::collision::NumContrib, + o2::aod::collision::CollisionTime); +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); +DECLARE_SOA_TABLE(FiltTrackColIdx, "AOD", "FILTTRACKCOLIDX", + o2::aod::track::CollisionId); +DECLARE_SOA_TABLE(FilterTrack, "AOD", "FILTERTRACK", + aod::filtertracks::IsInsideBeamPipe, + o2::aod::track::TrackType, + o2::aod::track::X, + o2::aod::track::Alpha, + o2::aod::track::Y, + o2::aod::track::Z, + o2::aod::track::Snp, + o2::aod::track::Tgl, + o2::aod::track::Signed1Pt); +DECLARE_SOA_TABLE(FilterTrackExtr, "AOD", "FILTERTRACKEXTR", + // aod::filtertracks::Px,aod::filtertracks::Py, aod::filtertracks::Pz, + aod::filtertracks::Pt, o2::aod::track::Eta, + o2::aod::filtertracks::Charge, + o2::aod::track::DcaXY, + o2::aod::track::DcaZ, + o2::aod::track::SigmaDcaXY2, + o2::aod::track::SigmaDcaZ2, + aod::filtertracks::NsigmaTPCpi, aod::filtertracks::NsigmaTPCka, aod::filtertracks::NsigmaTPCpr, + aod::filtertracks::NsigmaTOFpi, aod::filtertracks::NsigmaTOFka, aod::filtertracks::NsigmaTOFpr); +DECLARE_SOA_TABLE(FiltTracExtDet, "AOD", "FILTTRACEXTDET", + o2::aod::track::ITSClusterSizes, + o2::aod::track::ITSChi2NCl, + o2::aod::track::TPCChi2NCl, + aod::filtertracks::TpcNCluster, + o2::aod::track::TrackTime); +DECLARE_SOA_TABLE(FilterTrackMC, "AOD", "FILTERTRACKMC", + // aod::filtertracks::Px,aod::filtertracks::Py, aod::filtertracks::Pz, + o2::aod::mcparticle::PdgCode, + o2::aod::filtertracks::IsPhysicalPrimary, + o2::aod::filtertracks::MainHfMotherPdgCode, + o2::aod::filtertracks::MainBeautyAncestorPdgCode, + o2::aod::filtertracks::MainMotherOrigIndex, + o2::aod::filtertracks::MainMotherNfinalStateDaught, + o2::aod::filtertracks::MainMotherPt, + o2::aod::filtertracks::MainMotherY, + o2::aod::filtertracks::MainBeautyAncestorPt, + o2::aod::filtertracks::MainBeautyAncestorY); +DECLARE_SOA_TABLE(GenParticles, "AOD", "GENPARTICLES", + // aod::filtertracks::Px,aod::filtertracks::Py, aod::filtertracks::Pz, + o2::aod::mcparticle::PdgCode, + o2::aod::mcparticle::McCollisionId, + o2::aod::filtertracks::MainBeautyAncestorPdgCode, + o2::aod::filtertracks::MainMotherPt, + o2::aod::filtertracks::MainMotherY, + o2::aod::filtertracks::MaxEtaDaughter, + o2::aod::filtertracks::MainBeautyAncestorPt, + o2::aod::filtertracks::MainBeautyAncestorY); +} // namespace o2::aod + +struct FilterTracks { + const static int nStudiedParticlesMc = 3; + + Produces filteredTracksCollIdx; + Produces filteredTracksTableExtra; + Produces filteredTracksTable; + Produces filteredTracksTableExtraDet; + Produces filteredTracksMC; + Produces selectedGenParticles; + Produces filterCollTable; + Produces filterCollLiteTable; + Produces filterCollPosTable; + + SliceCache cache; + // Configurable dummy{"dummy", 0, "dummy"}; + Configurable minTrackPt{"minTrackPt", 0.25, "min track pt"}; + Configurable trackDcaXyMax{"trackDcaXyMax", 0.5, "max track pt"}; + Configurable trackPtSampling{"trackPtSampling", 0, "track sampling mode"}; + Configurable produceCollTableFull{"produceCollTableFull", false, "produce full collision table"}; + Configurable produceCollTableLite{"produceCollTableLite", false, "produce lite collision table"}; + Configurable produceCollTableExtraLite{"produceCollTableExtraLite", 2, "produce extra lite collision table"}; + Configurable trackPtWeightLowPt{"trackPtWeightLowPt", 0.01f, "trackPtWeightLowPt"}; + Configurable trackPtWeightMidPt{"trackPtWeightMidPt", 0.10f, "trackPtWeightMidPt"}; + Configurable collFilterFraction{"collFilterFraction", 0.05f, "collFilterFraction"}; + + Filter trackFilter = requireGlobalTrackWoDCAInFilter() && aod::track::pt > minTrackPt&& nabs(aod::track::dcaXY) < trackDcaXyMax; + Filter collFilter = nabs(aod::collision::posZ * 10000.f - nround(aod::collision::posZ * 10000.f)) < collFilterFraction.node() * 2.f; + using CollisionsWithEvSel = soa::Join; + using TracksWithSelAndDca = soa::Join; + using TracksWithSelAndDcaMc = soa::Join; + using FilterCollisionsWithEvSel = soa::Filtered; + + float lowPtThreshold = 2.; + float midPtThreshold = 5.; + float nDigitScaleFactor = 10000.; + Partition> lowPtTracks = aod::track::pt < lowPtThreshold && (nabs(aod::track::pt * nDigitScaleFactor - nround(aod::track::pt * nDigitScaleFactor)) < trackPtWeightLowPt.node() * lowPtThreshold); + Partition> midPtTracks = aod::track::pt > lowPtThreshold&& aod::track::pt < midPtThreshold && (nabs(aod::track::pt * nDigitScaleFactor - nround(aod::track::pt * nDigitScaleFactor)) < trackPtWeightMidPt.node() * lowPtThreshold); + Partition> highPtTracks = aod::track::pt > midPtThreshold; + + Partition> lowPtTracksMC = aod::track::pt < lowPtThreshold && (nabs(aod::track::pt * nDigitScaleFactor - nround(aod::track::pt * nDigitScaleFactor)) < trackPtWeightLowPt.node() * lowPtThreshold); + Partition> midPtTracksMC = aod::track::pt > lowPtThreshold&& aod::track::pt < midPtThreshold && (nabs(aod::track::pt * nDigitScaleFactor - nround(aod::track::pt * nDigitScaleFactor)) < trackPtWeightMidPt.node() * lowPtThreshold); + Partition> highPtTracksMC = aod::track::pt > midPtThreshold; + + std::array pdgSignalParticleArray = {kK0Short, o2::constants::physics::Pdg::kD0, o2::constants::physics::Pdg::kLambdaCPlus}; // K0s, D0 and Lc + std::array pdgDecayLc = {kProton, kKMinus, kPiPlus}; + std::array pdgDecayDzero = {kKMinus, kPiPlus}; + std::array pdgDecayKzero = {kPiMinus, kPiPlus}; + const int nK0sShortDaught = 2; + + void init(InitContext&) + { + } + + void fillTableData(auto track) + { + + filteredTracksCollIdx(track.collisionId()); + filteredTracksTableExtra(track.pt(), track.eta(), track.sign(), track.dcaXY(), track.dcaZ(), track.sigmaDcaXY2(), track.sigmaDcaZ2(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()); + filteredTracksTable(track.isWithinBeamPipe() ? 1 : 0, track.trackType(), track.x(), track.alpha(), track.y(), track.z(), track.snp(), track.tgl(), track.signed1Pt()); + + filteredTracksTableExtraDet(track.itsClusterSizes(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tpcNClsFound(), track.trackTime()); + } + + void fillTableDataMC(auto track, aod::McParticles const& mcParticles) + { + + fillTableData(track); + bool hasMcParticle = track.has_mcParticle(); + if (hasMcParticle) { + /// the track is not fake + + // check whether the particle comes from a charm or beauty hadron and store its index + + auto mcparticle = track.mcParticle(); + int pdgParticleMother = 0; + for (int iSignPart = 0; iSignPart < nStudiedParticlesMc; iSignPart++) { + pdgParticleMother = pdgSignalParticleArray[iSignPart]; + auto motherIndex = RecoDecay::getMother(mcParticles, mcparticle, pdgParticleMother, true); // check whether mcparticle derives from a particle with pdg = pdgparticlemother, accepting also antiparticle (<- the true parameter) + if (motherIndex != -1) { + auto particleMother = mcParticles.rawIteratorAt(motherIndex); + // just for internal check + // double mass=particleMother.e()*particleMother.e()-particleMother.pt()*particleMother.pt()-particleMother.pz()*particleMother.pz(); + // filteredTracksMC(mcparticle.pdgCode(),mcparticle.isPhysicalPrimary(),particleMother.pdgCode(),0,motherIndex,0,particleMother.pt(),particleMother.y(),std::sqrt(mass),0); + if (pdgParticleMother == kK0Short) { + auto daughtersSlice = mcparticle.template daughters_as(); + int ndaught = daughtersSlice.size(); // might not be accurate in case K0s interact with material before decaying + if (ndaught != nK0sShortDaught) + ndaught *= -1; + filteredTracksMC(mcparticle.pdgCode(), mcparticle.isPhysicalPrimary(), particleMother.pdgCode(), 0, motherIndex, ndaught, particleMother.pt(), particleMother.y(), 0, 0); + // std::cout<<"FOUND K0s, MATCHED! size array "< indxDaughers; + if (pdgParticleMother == o2::constants::physics::Pdg::kD0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particleMother, pdgParticleMother, pdgDecayDzero, true, nullptr, 3, &indxDaughers)) { + ndaught = 2; + // std::cout<<"######## FOUND D0, MATCHED! pdg: " <(mcParticles, particleMother, pdgParticleMother, pdgDecayLc, true, nullptr, 3, &indxDaughers)) { + ndaught = 3; + } else { + ndaught = -indxDaughers.size(); + } + } + // now check whether the charm hadron is prompt or comes from beauty decay + std::vector idxBhadMothers; + if (RecoDecay::getCharmHadronOrigin(mcParticles, particleMother, false, &idxBhadMothers) == RecoDecay::OriginType::NonPrompt) { + if (idxBhadMothers.size() > 1) { + LOG(info) << "more than 1 B mother hadron found, should not be: "; + for (uint64_t iBhM = 0; iBhM < idxBhadMothers.size(); iBhM++) { + auto particleBhadr = mcParticles.rawIteratorAt(idxBhadMothers[iBhM]); + LOG(info) << particleBhadr.pdgCode(); + } + } + auto particleBhadr = mcParticles.rawIteratorAt(idxBhadMothers[0]); + // int pdgBhad=particleBhadr.pdgCode(); + filteredTracksMC(mcparticle.pdgCode(), mcparticle.isPhysicalPrimary(), particleMother.pdgCode(), particleBhadr.pdgCode(), motherIndex, ndaught, particleMother.pt(), particleMother.y(), particleBhadr.pt(), particleBhadr.y()); + } else { + filteredTracksMC(mcparticle.pdgCode(), mcparticle.isPhysicalPrimary(), particleMother.pdgCode(), 0, motherIndex, ndaught, particleMother.pt(), particleMother.y(), 0, 0); + } + break; + } + pdgParticleMother = 0; + } + if (pdgParticleMother == 0) + filteredTracksMC(mcparticle.pdgCode(), mcparticle.isPhysicalPrimary(), 0, 0, -1, 0, 0, 0, 0, 0); + // std::cout< const& tracks) + { + if (trackPtSampling == 0) { + for (auto const& track : tracks) { + fillTableData(track); + if (produceCollTableExtraLite == 2) { + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); + }; + } + } 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()); + }; + } + 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()); + }; + } + 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()); + }; + } + } + } + PROCESS_SWITCH(FilterTracks, processData, "process data", true); + 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()); + 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()); + if (produceCollTableExtraLite == 1) + filterCollPosTable(collision.posX(), collision.posY(), collision.posZ(), collision.chi2(), collision.numContrib(), collision.collisionTime()); + } + PROCESS_SWITCH(FilterTracks, processCollisions, "process collisions", true); + + void processMC(FilterCollisionsWithEvSel::iterator const& collision, soa::Filtered const& tracks, aod::McParticles const& mcParticles) + { + if (trackPtSampling == 0) { + for (auto const& track : tracks) { + fillTableDataMC(track, mcParticles); + } + } else { + auto lowPtTracksMCThisColl = lowPtTracksMC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + for (auto const& track : lowPtTracksMCThisColl) { + fillTableDataMC(track, mcParticles); + } + auto midPtTracksMCThisColl = midPtTracksMC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + for (auto const& track : midPtTracksMCThisColl) { + fillTableDataMC(track, mcParticles); + } + auto highPtTracksMCThisColl = highPtTracksMC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + for (auto const& track : highPtTracksMCThisColl) { + fillTableDataMC(track, mcParticles); + } + } + + for (auto const& mcpart : mcParticles) { // NOTE THAT OF COURSE IN CASE OF SAMPLING THE GEN TABLE WON'T MATCH THE RECO EVEN CONSIDERING EFFICIENCY + int pdgCode = mcpart.pdgCode(); + // for(int iSignPart=0;iSignPart<3;iSignPart++){ + + std::vector indxDaughers; + float etamax = 0; + bool isMatchedToSignal = false; + if (std::abs(pdgCode) == kK0Short) { + isMatchedToSignal = RecoDecay::isMatchedMCGen(mcParticles, mcpart, kK0Short, pdgDecayKzero, true, nullptr, 1, &indxDaughers); + } + if (std::abs(pdgCode) == o2::constants::physics::Pdg::kD0) { + isMatchedToSignal = RecoDecay::isMatchedMCGen(mcParticles, mcpart, o2::constants::physics::Pdg::kD0, pdgDecayDzero, true, nullptr, 3, &indxDaughers); + } else if (std::abs(pdgCode) == o2::constants::physics::Pdg::kLambdaCPlus) { + isMatchedToSignal = RecoDecay::isMatchedMCGen(mcParticles, mcpart, o2::constants::physics::Pdg::kLambdaCPlus, pdgDecayLc, true, nullptr, 3, &indxDaughers); + // std::cout<<"Lc found, matched to MC? "<(); + // int ndaught = daughtersLxSlice.size(); + // for(auto lcDaught : daughtersLxSlice){ + // std::cout<<"Lc daught, total daught "< etamax) { + etamax = eta; + } + } + if (pdgCode == kK0Short) { + selectedGenParticles(mcpart.pdgCode(), mcpart.mcCollisionId(), 0, mcpart.pt(), mcpart.y(), etamax, 0, 0); + continue; + } + std::vector idxBhadMothers; + if (RecoDecay::getCharmHadronOrigin(mcParticles, mcpart, false, &idxBhadMothers) == RecoDecay::OriginType::NonPrompt) { + if (idxBhadMothers.size() > 1) { + LOG(info) << "loop on gen particles: more than 1 B mother hadron found, should not be: "; + for (uint64_t iBhM = 0; iBhM < idxBhadMothers.size(); iBhM++) { + auto particleBhadr = mcParticles.rawIteratorAt(idxBhadMothers[iBhM]); + LOG(info) << particleBhadr.pdgCode(); + } + } + auto particleBhadr = mcParticles.rawIteratorAt(idxBhadMothers[0]); + // int pdgBhad=particleBhadr.pdgCode(); + selectedGenParticles(mcpart.pdgCode(), mcpart.mcCollisionId(), particleBhadr.pdgCode(), mcpart.pt(), mcpart.y(), etamax, particleBhadr.pt(), particleBhadr.y()); + } else { + selectedGenParticles(mcpart.pdgCode(), mcpart.mcCollisionId(), 0, mcpart.pt(), mcpart.y(), etamax, 0, 0); + } + } + // + } + } + PROCESS_SWITCH(FilterTracks, processMC, "process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/DPG/Tasks/MFT/aQCMFTTracks.cxx b/DPG/Tasks/MFT/aQCMFTTracks.cxx index 8b264102150..5b5f4a71aa4 100644 --- a/DPG/Tasks/MFT/aQCMFTTracks.cxx +++ b/DPG/Tasks/MFT/aQCMFTTracks.cxx @@ -16,46 +16,73 @@ /// \author David Grund /// \since +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" + #include "CCDB/BasicCCDBManager.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.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 "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "CommonConstants/LHCConstants.h" #include "Framework/TimingInfo.h" -#include "DataFormatsITSMFT/ROFRecord.h" +#include "Framework/runDataProcessing.h" #include #include +#include + using namespace o2; using namespace o2::framework; using namespace o2::aod; struct CheckMFT { - HistogramRegistry registry{"registry", - {// 2d histograms - {"mMFTTrackEtaPhi_5_MinClusters", "Track #eta , #phi (NCls >= 5); #eta; #phi", {HistType::kTH2F, {{50, -4, -2}, {100, -3.2, 3.2}}}}, - {"mMFTTrackXY_5_MinClusters", "Track Position (NCls >= 5); x; y", {HistType::kTH2F, {{320, -16, 16}, {320, -16, 16}}}}, - {"mMFTTrackEtaPhi_7_MinClusters", "Track #eta , #phi (NCls >= 7); #eta; #phi", {HistType::kTH2F, {{50, -4, -2}, {100, -3.2, 3.2}}}}, - {"mMFTTrackXY_7_MinClusters", "Track Position (NCls >= 7); x; y", {HistType::kTH2F, {{320, -16, 16}, {320, -16, 16}}}}, - {"mMFTTrackEtaPhi_8_MinClusters", "Track #eta , #phi (NCls >= 8); #eta; #phi", {HistType::kTH2F, {{50, -4, -2}, {100, -3.2, 3.2}}}}, - {"mMFTTrackXY_8_MinClusters", "Track Position (NCls >= 8); x; y", {HistType::kTH2F, {{320, -16, 16}, {320, -16, 16}}}}, - // 1d histograms - {"mMFTTrackEta", "Track #eta; #eta; # entries", {HistType::kTH1F, {{50, -4, -2}}}}, - {"mMFTTrackNumberOfClusters", "Number Of Clusters Per Track; # clusters; # entries", {HistType::kTH1F, {{10, 0.5, 10.5}}}}, - {"mMFTTrackPhi", "Track #phi; #phi; # entries", {HistType::kTH1F, {{100, -3.2, 3.2}}}}, - {"mMFTTrackTanl", "Track tan #lambda; tan #lambda; # entries", {HistType::kTH1F, {{100, -25, 0}}}}, - {"mMFTTrackInvQPt", "Track q/p_{T}; q/p_{T} [1/GeV]; # entries", {HistType::kTH1F, {{250, -10, 10}}}}}}; + HistogramRegistry registry{"registry"}; + Configurable avClsPlots{"avClsPlots", false, "Enable average cluster plots"}; + + void init(o2::framework::InitContext&) + { + + const AxisSpec etaAxis{50, -4, -2, "#eta"}; + const AxisSpec phiAxis{100, -3.2, 3.2, "#phi"}; + const AxisSpec xAxis{320, -16, 16, "x"}; + const AxisSpec clsAxis{10, 0.5, 10.5, "# clusters"}; + const AxisSpec yAxis{320, -16, 16, "y"}; + const AxisSpec tanLamAxis{100, -25, 0, "tan #lambda"}; + const AxisSpec invQPtAxis{250, -10, 10, "q/p_{T} [1/GeV]"}; + + registry.add("mMFTTrackPhi", "Track #phi", {HistType::kTH1F, {phiAxis}}); + registry.add("mMFTTrackTanl", "Track tan #lambda", {HistType::kTH1F, {tanLamAxis}}); + registry.add("mMFTTrackInvQPt", "Track q/p_{T}", {HistType::kTH1F, {invQPtAxis}}); + registry.add("mMFTTrackEta", "Track #eta", {HistType::kTH1F, {etaAxis}}); + + registry.add("mMFTTrackEtaPhi_5_MinClusters", "Track Position (NCls >= 5)", {HistType::kTH2F, {etaAxis, phiAxis}}); + registry.add("mMFTTrackEtaPhi_6_MinClusters", "Track Position (NCls >= 6)", {HistType::kTH2F, {etaAxis, phiAxis}}); + registry.add("mMFTTrackEtaPhi_7_MinClusters", "Track Position (NCls >= 7)", {HistType::kTH2F, {etaAxis, phiAxis}}); + registry.add("mMFTTrackEtaPhi_8_MinClusters", "Track Position (NCls >= 8)", {HistType::kTH2F, {etaAxis, phiAxis}}); + + registry.add("mMFTTrackXY_5_MinClusters", "Track Position (NCls >= 5)", {HistType::kTH2F, {xAxis, yAxis}}); + registry.add("mMFTTrackXY_6_MinClusters", "Track Position (NCls >= 6)", {HistType::kTH2F, {xAxis, yAxis}}); + registry.add("mMFTTrackXY_7_MinClusters", "Track Position (NCls >= 7)", {HistType::kTH2F, {xAxis, yAxis}}); + registry.add("mMFTTrackXY_8_MinClusters", "Track Position (NCls >= 8)", {HistType::kTH2F, {xAxis, yAxis}}); + registry.add("mMFTTrackNumberOfClusters", "Number Of Clusters Per Track", {HistType::kTH1F, {clsAxis}}); + + if (avClsPlots) { + registry.add("mMFTTrackAvgClusters", "Average number of clusters per track; p;# clusters; # entries", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}}); + registry.add("mMFTTrackAvgClustersTru", "Average number of clusters per track; p;# clusters; # entries", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}}); + if (doprocessMC) { + registry.add("mMFTTrackAvgClustersHe", "Average number of clusters per track; p;# clusters; # entries", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}}); + registry.add("mMFTTrackAvgClustersTruHe", "Average number of clusters per track; p;# clusters; # entries", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 100}}}); + } + } + } void process(aod::MFTTracks const& mfttracks) { - for (auto& track : mfttracks) { + for (const auto& track : mfttracks) { // 2d histograms float x = track.x(); float y = track.y(); @@ -65,14 +92,48 @@ struct CheckMFT { if (nCls >= 5) { registry.fill(HIST("mMFTTrackXY_5_MinClusters"), x, y); registry.fill(HIST("mMFTTrackEtaPhi_5_MinClusters"), eta, phi); - if (nCls >= 7) { - registry.fill(HIST("mMFTTrackXY_7_MinClusters"), x, y); - registry.fill(HIST("mMFTTrackEtaPhi_7_MinClusters"), eta, phi); - if (nCls >= 8) { - registry.fill(HIST("mMFTTrackXY_8_MinClusters"), x, y); - registry.fill(HIST("mMFTTrackEtaPhi_8_MinClusters"), eta, phi); + if (nCls >= 6) { + registry.fill(HIST("mMFTTrackXY_6_MinClusters"), x, y); + registry.fill(HIST("mMFTTrackEtaPhi_6_MinClusters"), eta, phi); + if (nCls >= 7) { + registry.fill(HIST("mMFTTrackXY_7_MinClusters"), x, y); + registry.fill(HIST("mMFTTrackEtaPhi_7_MinClusters"), eta, phi); + if (nCls >= 8) { + registry.fill(HIST("mMFTTrackXY_8_MinClusters"), x, y); + registry.fill(HIST("mMFTTrackEtaPhi_8_MinClusters"), eta, phi); + } + } + } + } + if (avClsPlots) { + static constexpr int kNcls = 10; + std::array clsSize; + for (unsigned int layer = 0; layer < kNcls; layer++) { + clsSize[layer] = (track.mftClusterSizesAndTrackFlags() >> (layer * 6)) & 0x3f; + // LOG(info) << "Layer " << layer << ": " << clsSize[layer]; + } + float avgCls = 0; + for (unsigned int layer = 0; layer < kNcls; layer++) { + avgCls += clsSize[layer]; + } + avgCls /= track.nClusters(); + + std::sort(clsSize.begin(), clsSize.end()); + float truncatedAvgCls = 0; + int ncls = 0; + for (unsigned int layer = 0; layer < kNcls; layer++) { + if (clsSize[layer] > 0) { + truncatedAvgCls += clsSize[layer]; + ncls++; + if (ncls >= 3) { + break; // we take the average of the first 5 non-zero clusters + } } } + truncatedAvgCls /= ncls; + + registry.fill(HIST("mMFTTrackAvgClusters"), track.p(), avgCls); + registry.fill(HIST("mMFTTrackAvgClustersTru"), track.p(), truncatedAvgCls); } // 1d histograms registry.fill(HIST("mMFTTrackEta"), eta); @@ -82,6 +143,49 @@ struct CheckMFT { registry.fill(HIST("mMFTTrackInvQPt"), track.signed1Pt()); } } + + void processMC(soa::Join const& mfttracks, + aod::McParticles const&) + { + static constexpr int kNcls = 10; + for (const auto& track : mfttracks) { + if (avClsPlots) { + std::array clsSize; + for (unsigned int layer = 0; layer < kNcls; layer++) { + clsSize[layer] = (track.mftClusterSizesAndTrackFlags() >> (layer * 6)) & 0x3f; + // LOG(info) << "Layer " << layer << ": " << clsSize[layer]; + } + float avgCls = 0; + for (unsigned int layer = 0; layer < kNcls; layer++) { + avgCls += clsSize[layer]; + } + avgCls /= track.nClusters(); + + std::sort(clsSize.begin(), clsSize.end()); + float truncatedAvgCls = 0; + int ncls = 0; + for (unsigned int layer = 0; layer < kNcls; layer++) { + if (clsSize[layer] > 0) { + truncatedAvgCls += clsSize[layer]; + ncls++; + if (ncls >= 3) { + break; // we take the average of the first 5 non-zero clusters + } + } + } + truncatedAvgCls /= ncls; + + if (track.has_mcParticle()) { + const auto& mcParticle = track.mcParticle(); + if (std::abs(mcParticle.pdgCode()) == 1000020040) { // He4 + registry.fill(HIST("mMFTTrackAvgClustersHe"), track.p(), avgCls); + registry.fill(HIST("mMFTTrackAvgClustersTruHe"), track.p(), truncatedAvgCls); + } + } + } + } + } + PROCESS_SWITCH(CheckMFT, processMC, "Process MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx index 6c3d1304cfe..2a2d644e7c4 100644 --- a/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx +++ b/DPG/Tasks/TPC/tpcSkimsTableCreator.cxx @@ -17,29 +17,33 @@ /// \author Jeremy Wilkinson #include "tpcSkimsTableCreator.h" + #include + #include -#include #include +#include /// ROOT #include "TRandom3.h" /// O2 -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" /// O2Physics +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/OccupancyTables.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "Common/DataModel/OccupancyTables.h" +#include "Common/TableProducer/PID/pidTPCBase.h" using namespace o2; using namespace o2::framework; @@ -52,6 +56,7 @@ struct TreeWriterTpcV0 { Service ccdb; using Trks = soa::Join; + using TrksWithDEdxCorrection = soa::Join; using Colls = soa::Join; using MyBCTable = soa::Join; using V0sWithID = soa::Join; @@ -89,7 +94,7 @@ struct TreeWriterTpcV0 { ctpRateFetcher mRateFetcher; /// Funktion to fill skimmed tables - template + template void fillSkimmedV0Table(V0 const& v0, T const& track, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) { @@ -111,7 +116,13 @@ struct TreeWriterTpcV0 { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTree(track.tpcSignal(), + float usedDedx; + if constexpr (doUseCorreceddEdx) { + usedDedx = track.tpcSignalCorrected(); + } else { + usedDedx = track.tpcSignal(); + } + rowTPCTree(usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -140,7 +151,7 @@ struct TreeWriterTpcV0 { } }; - template + template void fillSkimmedV0TableWithdEdxTrQA(V0 const& v0, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate) { @@ -162,7 +173,13 @@ struct TreeWriterTpcV0 { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTreeWithdEdxTrkQA(track.tpcSignal(), + float usedDedx; + if constexpr (doUseCorreceddEdx) { + usedDedx = track.tpcSignalCorrected(); + } else { + usedDedx = track.tpcSignal(); + } + rowTPCTreeWithdEdxTrkQA(usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -193,7 +210,7 @@ struct TreeWriterTpcV0 { }; /// Function to fill skimmed tables - template + template void fillSkimmedV0TableWithTrQA(V0 const& v0, T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, float hadronicRate, int bcGlobalIndex, int bcTimeFrameId, int bcBcInTimeFrame) { @@ -215,7 +232,13 @@ struct TreeWriterTpcV0 { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTreeWithTrkQA(track.tpcSignal(), + float usedDedx; + if constexpr (doUseCorreceddEdx) { + usedDedx = track.tpcSignalCorrected(); + } else { + usedDedx = track.tpcSignal(); + } + rowTPCTreeWithTrkQA(usedDedx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -376,6 +399,69 @@ struct TreeWriterTpcV0 { } /// process Standard PROCESS_SWITCH(TreeWriterTpcV0, processStandard, "Standard V0 Samples for PID", true); + void processStandardWithCorrecteddEdx(Colls::iterator const& collision, soa::Filtered const& tracks, V0sWithID const& v0s, aod::BCsWithTimestamps const&) + { + /// Check event slection + if (!isEventSelected(collision, tracks)) { + return; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + + rowTPCTree.reserve(tracks.size()); + + /// Loop over v0 candidates + for (const auto& v0 : v0s) { + auto posTrack = v0.posTrack_as>(); + auto negTrack = v0.negTrack_as>(); + if (v0.v0addid() == -1) { + continue; + } + // gamma + if (static_cast(posTrack.pidbit() & (1 << 0)) && static_cast(negTrack.pidbit() & (1 << 0))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaEl(), posTrack.tofNSigmaEl(), posTrack.tpcExpSignalEl(posTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaEl(), negTrack.tofNSigmaEl(), negTrack.tpcExpSignalEl(negTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + } + // Ks0 + if (static_cast(posTrack.pidbit() & (1 << 1)) && static_cast(negTrack.pidbit() & (1 << 1))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Lambda + if (static_cast(posTrack.pidbit() & (1 << 2)) && static_cast(negTrack.pidbit() & (1 << 2))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(posTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaPr(), posTrack.tofNSigmaPr(), posTrack.tpcExpSignalPr(posTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Antilambda + if (static_cast(posTrack.pidbit() & (1 << 3)) && static_cast(negTrack.pidbit() & (1 << 3))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0Table(v0, posTrack, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(negTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0Table(v0, negTrack, collision, negTrack.tpcNSigmaPr(), negTrack.tofNSigmaPr(), negTrack.tpcExpSignalPr(negTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + } + } + } /// process Standard + PROCESS_SWITCH(TreeWriterTpcV0, processStandardWithCorrecteddEdx, "Standard V0 Samples for PID with corrected dEdx", false); + Preslice perCollisionTracks = aod::track::collisionId; Preslice perCollisionV0s = aod::v0data::collisionId; void processWithdEdxTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) @@ -470,6 +556,99 @@ struct TreeWriterTpcV0 { } /// process with dEdx from TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithdEdxTrQA, "Standard V0 Samples with dEdx from Track QA for PID", false); + Preslice perCollisionTracksWithNewDEdx = aod::track::collisionId; + void processWithdEdxTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracksWithNewDEdx, collision.globalIndex()); + auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + /// Check event slection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + rowTPCTreeWithTrkQA.reserve(tracks.size()); + /// Loop over v0 candidates + for (const auto& v0 : v0s) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + if (v0.v0addid() == -1) { + continue; + } + aod::TracksQA posTrackQA; + aod::TracksQA negTrackQA; + bool existPosTrkQA; + bool existNegTrkQA; + if (labelTrack2TrackQA[posTrack.globalIndex()] != -1) { + posTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[posTrack.globalIndex()]); + existPosTrkQA = true; + } else { + posTrackQA = tracksQA.iteratorAt(0); + existPosTrkQA = false; + } + if (labelTrack2TrackQA[negTrack.globalIndex()] != -1) { + negTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[negTrack.globalIndex()]); + existNegTrkQA = true; + } else { + negTrackQA = tracksQA.iteratorAt(0); + existNegTrkQA = false; + } + + // gamma + if (static_cast(posTrack.pidbit() & (1 << 0)) && static_cast(negTrack.pidbit() & (1 << 0))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaEl(), posTrack.tofNSigmaEl(), posTrack.tpcExpSignalEl(posTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaEl(), negTrack.tofNSigmaEl(), negTrack.tpcExpSignalEl(negTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate); + } + } + // Ks0 + if (static_cast(posTrack.pidbit() & (1 << 1)) && static_cast(negTrack.pidbit() & (1 << 1))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Lambda + if (static_cast(posTrack.pidbit() & (1 << 2)) && static_cast(negTrack.pidbit() & (1 << 2))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(posTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPr(), posTrack.tofNSigmaPr(), posTrack.tpcExpSignalPr(posTrack.tpcSignal()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } + // Antilambda + if (static_cast(posTrack.pidbit() & (1 << 3)) && static_cast(negTrack.pidbit() & (1 << 3))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithdEdxTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(negTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithdEdxTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPr(), negTrack.tofNSigmaPr(), negTrack.tpcExpSignalPr(negTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + } + } + } + } + } /// process with dEdx from TrackQA + PROCESS_SWITCH(TreeWriterTpcV0, processWithdEdxTrQAWithCorrecteddEdx, "Standard V0 Samples with dEdx from Track QA for PID with corrected dEdx", false); + void processWithTrQA(Colls const& collisions, Trks const& myTracks, V0sWithID const& myV0s, MyBCTable const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; @@ -565,10 +744,105 @@ struct TreeWriterTpcV0 { } /// process with TrackQA PROCESS_SWITCH(TreeWriterTpcV0, processWithTrQA, "Standard V0 Samples with Track QA for PID", false); + void processWithTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, V0sWithID const& myV0s, MyBCTable const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracksWithNewDEdx, collision.globalIndex()); + auto v0s = myV0s.sliceBy(perCollisionV0s, collision.globalIndex()); + /// Check event slection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + const int bcGlobalIndex = bc.globalIndex(); + const int bcTimeFrameId = bc.tfId(); + const int bcBcInTimeFrame = bc.bcInTF(); + rowTPCTreeWithTrkQA.reserve(tracks.size()); + /// Loop over v0 candidates + for (const auto& v0 : v0s) { + auto posTrack = v0.posTrack_as(); + auto negTrack = v0.negTrack_as(); + if (v0.v0addid() == -1) { + continue; + } + aod::TracksQA posTrackQA; + aod::TracksQA negTrackQA; + bool existPosTrkQA; + bool existNegTrkQA; + if (labelTrack2TrackQA[posTrack.globalIndex()] != -1) { + posTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[posTrack.globalIndex()]); + existPosTrkQA = true; + } else { + posTrackQA = tracksQA.iteratorAt(0); + existPosTrkQA = false; + } + if (labelTrack2TrackQA[negTrack.globalIndex()] != -1) { + negTrackQA = tracksQA.iteratorAt(labelTrack2TrackQA[negTrack.globalIndex()]); + existNegTrkQA = true; + } else { + negTrackQA = tracksQA.iteratorAt(0); + existNegTrkQA = false; + } + + // gamma + if (static_cast(posTrack.pidbit() & (1 << 0)) && static_cast(negTrack.pidbit() & (1 << 0))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaEl(), posTrack.tofNSigmaEl(), posTrack.tpcExpSignalEl(posTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisElectrons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Electron], maxPt4dwnsmplTsalisElectrons)) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaEl(), negTrack.tofNSigmaEl(), negTrack.tpcExpSignalEl(negTrack.tpcSignalCorrected()), o2::track::PID::Electron, runnumber, dwnSmplFactor_El, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + // Ks0 + if (static_cast(posTrack.pidbit() & (1 << 1)) && static_cast(negTrack.pidbit() & (1 << 1))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + // Lambda + if (static_cast(posTrack.pidbit() & (1 << 2)) && static_cast(negTrack.pidbit() & (1 << 2))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(posTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPr(), posTrack.tofNSigmaPr(), posTrack.tpcExpSignalPr(posTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPi(), negTrack.tofNSigmaPi(), negTrack.tpcExpSignalPi(negTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + // Antilambda + if (static_cast(posTrack.pidbit() & (1 << 3)) && static_cast(negTrack.pidbit() & (1 << 3))) { + if (downsampleTsalisCharged(posTrack.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion], maxPt4dwnsmplTsalisPions)) { + fillSkimmedV0TableWithTrQA(v0, posTrack, posTrackQA, existPosTrkQA, collision, posTrack.tpcNSigmaPi(), posTrack.tofNSigmaPi(), posTrack.tpcExpSignalPi(posTrack.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + if (downsampleTsalisCharged(negTrack.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton], maxPt4dwnsmplTsalisProtons)) { + if (std::abs(negTrack.tofNSigmaPr()) <= nSigmaTOFdautrack) { + fillSkimmedV0TableWithTrQA(v0, negTrack, negTrackQA, existNegTrkQA, collision, negTrack.tpcNSigmaPr(), negTrack.tofNSigmaPr(), negTrack.tpcExpSignalPr(negTrack.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } + } + } + } + } /// process with TrackQA + PROCESS_SWITCH(TreeWriterTpcV0, processWithTrQAWithCorrecteddEdx, "Standard V0 Samples with Track QA for PID with corrected dEdx", false); + void processDummy(Colls const&) {} PROCESS_SWITCH(TreeWriterTpcV0, processDummy, "Dummy function", false); -}; /// struct TreeWriterTpcV0 +}; /// struct TreeWriterTpcV0 struct TreeWriterTPCTOF { @@ -580,6 +854,12 @@ struct TreeWriterTPCTOF { aod::pidTOFFullEl, aod::pidTOFFullPi, aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullDe, aod::pidTOFFullTr, aod::TrackSelection>; + using TrksWithDEdxCorrection = soa::Join; using Colls = soa::Join; using MyBCTable = soa::Join; @@ -674,7 +954,7 @@ struct TreeWriterTPCTOF { }; /// Function to fill trees - template + template void fillSkimmedTPCTOFTable(T const& track, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, double hadronicRate) { @@ -689,7 +969,13 @@ struct TreeWriterTPCTOF { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTOFTree(track.tpcSignal(), + float usedEdx; + if constexpr (doCorrectdEdx) { + usedEdx = track.tpcSignalCorrected(); + } else { + usedEdx = track.tpcSignal(); + } + rowTPCTOFTree(usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -711,7 +997,7 @@ struct TreeWriterTPCTOF { hadronicRate); } }; - template + template void fillSkimmedTPCTOFTableWithdEdxTrkQA(T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, double hadronicRate) { @@ -726,7 +1012,13 @@ struct TreeWriterTPCTOF { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTOFTreeWithdEdxTrkQA(track.tpcSignal(), + float usedEdx; + if constexpr (doCorrectdEdx) { + usedEdx = track.tpcSignalCorrected(); + } else { + usedEdx = track.tpcSignal(); + } + rowTPCTOFTreeWithdEdxTrkQA(usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -751,7 +1043,7 @@ struct TreeWriterTPCTOF { } }; /// Function to fill trees - template + template void fillSkimmedTPCTOFTableWithTrkQA(T const& track, TQA const& trackQA, bool existTrkQA, C const& collision, const float nSigmaTPC, const float nSigmaTOF, const float nSigmaITS, const float dEdxExp, const o2::track::PID::ID id, int runnumber, double dwnSmplFactor, double hadronicRate, int bcGlobalIndex, int bcTimeFrameId, int bcBcInTimeFrame) { @@ -766,7 +1058,13 @@ struct TreeWriterTPCTOF { const double pseudoRndm = track.pt() * 1000. - static_cast(track.pt() * 1000); if (pseudoRndm < dwnSmplFactor) { - rowTPCTOFTreeWithTrkQA(track.tpcSignal(), + float usedEdx; + if constexpr (doCorrectdEdx) { + usedEdx = track.tpcSignalCorrected(); + } else { + usedEdx = track.tpcSignal(); + } + rowTPCTOFTreeWithTrkQA(usedEdx, 1. / dEdxExp, track.tpcInnerParam(), track.tgl(), @@ -869,8 +1167,55 @@ struct TreeWriterTPCTOF { fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignal()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); } } /// Loop tracks - } /// process + } /// process PROCESS_SWITCH(TreeWriterTPCTOF, processStandard, "Standard Samples for PID", true); + + void processStandard2(Colls::iterator const& collision, soa::Filtered const& tracks, aod::BCsWithTimestamps const&) + { + /// Check event selection + if (!isEventSelected(collision, tracks)) { + return; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + + rowTPCTOFTree.reserve(tracks.size()); + for (auto const& trk : tracks) { + /// Fill tree for tritons/* */ + if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } + /// Fill tree for deuterons + if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } + /// Fill tree for protons + if (trk.tpcInnerParam() <= maxMomTPCOnlyPr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPCOnlyPr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPr && std::abs(trk.tofNSigmaPr()) < nSigmaTOF_TPCTOF_Pr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPC_TPCTOF_Pr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + /// Fill tree for kaons + if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() <= maxMomTPCOnlyKa && std::abs(trk.tpcNSigmaKa()) < nSigmaTPCOnlyKa && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() > maxMomTPCOnlyKa && std::abs(trk.tofNSigmaKa()) < nSigmaTOF_TPCTOF_Ka && std::abs(trk.tpcNSigmaKa()) < nSigmaTPC_TPCTOF_Ka && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } + /// Fill tree pions + if (trk.tpcInnerParam() <= maxMomTPCOnlyPi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPCOnlyPi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPi && std::abs(trk.tofNSigmaPi()) < nSigmaTOF_TPCTOF_Pi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPC_TPCTOF_Pi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTable(trk, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } /// Loop tracks + } /// process + PROCESS_SWITCH(TreeWriterTPCTOF, processStandard2, "Standard Samples for PID with corrected dEdx", false); + Preslice perCollisionTracks = aod::track::collisionId; void processWithdEdxTrQA(Colls const& collisions, Trks const& myTracks, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) { @@ -949,6 +1294,86 @@ struct TreeWriterTPCTOF { } } /// process PROCESS_SWITCH(TreeWriterTPCTOF, processWithdEdxTrQA, "Samples for PID with TrackQA info", false); + + Preslice perCollisionTracksWithCorrecteddEdx = aod::track::collisionId; + void processWithdEdxTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, aod::BCsWithTimestamps const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracksWithCorrecteddEdx, collision.globalIndex()); + auto tracksWithITSPid = soa::Attach(tracks); + /// Check event selection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + rowTPCTOFTreeWithTrkQA.reserve(tracks.size()); + for (auto const& trk : tracksWithITSPid) { + if (!((trackSelection == 0) || + ((trackSelection == 1) && trk.isGlobalTrack()) || + ((trackSelection == 2) && trk.isGlobalTrackWoPtEta()) || + ((trackSelection == 3) && trk.isGlobalTrackWoDCA()) || + ((trackSelection == 4) && trk.isQualityTrack()) || + ((trackSelection == 5) && trk.isInAcceptanceTrack()))) { + continue; + } + // get the corresponding trackQA using labelTracks2TracKQA and get variables of interest + aod::TracksQA trackQA; + bool existTrkQA; + if (labelTrack2TrackQA[trk.globalIndex()] != -1) { + trackQA = tracksQA.iteratorAt(labelTrack2TrackQA[trk.globalIndex()]); + existTrkQA = true; + } else { + trackQA = tracksQA.iteratorAt(0); + existTrkQA = false; + } + /// Fill tree for tritons + if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate); + } + /// Fill tree for deuterons + if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate); + } + /// Fill tree for protons + if (trk.tpcInnerParam() <= maxMomTPCOnlyPr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPCOnlyPr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPr && std::abs(trk.tofNSigmaPr()) < nSigmaTOF_TPCTOF_Pr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPC_TPCTOF_Pr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate); + } + /// Fill tree for kaons + if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() <= maxMomTPCOnlyKa && std::abs(trk.tpcNSigmaKa()) < nSigmaTPCOnlyKa && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() > maxMomTPCOnlyKa && std::abs(trk.tofNSigmaKa()) < nSigmaTOF_TPCTOF_Ka && std::abs(trk.tpcNSigmaKa()) < nSigmaTPC_TPCTOF_Ka && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate); + } + /// Fill tree pions + if (trk.tpcInnerParam() <= maxMomTPCOnlyPi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPCOnlyPi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPi && std::abs(trk.tofNSigmaPi()) < nSigmaTOF_TPCTOF_Pi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPC_TPCTOF_Pi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithdEdxTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate); + } + } /// Loop tracks + } + } /// process + PROCESS_SWITCH(TreeWriterTPCTOF, processWithdEdxTrQAWithCorrecteddEdx, "Samples for PID with TrackQA info with corrected dEdx", false); + void processWithTrQA(Colls const& collisions, Trks const& myTracks, MyBCTable const&, aod::TracksQAVersion const& tracksQA) { std::vector labelTrack2TrackQA; @@ -1029,6 +1454,88 @@ struct TreeWriterTPCTOF { } } /// process PROCESS_SWITCH(TreeWriterTPCTOF, processWithTrQA, "Samples for PID with TrackQA info", false); + + void processWithTrQAWithCorrecteddEdx(Colls const& collisions, TrksWithDEdxCorrection const& myTracks, MyBCTable const&, aod::TracksQAVersion const& tracksQA) + { + std::vector labelTrack2TrackQA; + labelTrack2TrackQA.clear(); + labelTrack2TrackQA.resize(myTracks.size(), -1); + for (const auto& trackQA : tracksQA) { + int64_t trackId = trackQA.trackId(); + int64_t trackQAIndex = trackQA.globalIndex(); + labelTrack2TrackQA[trackId] = trackQAIndex; + } + for (const auto& collision : collisions) { + auto tracks = myTracks.sliceBy(perCollisionTracks, collision.globalIndex()); + auto tracksWithITSPid = soa::Attach(tracks); + /// Check event selection + if (!isEventSelected(collision, tracks)) { + continue; + } + auto bc = collision.bc_as(); + const int runnumber = bc.runNumber(); + float hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), runnumber, irSource) * 1.e-3; + const int bcGlobalIndex = bc.globalIndex(); + const int bcTimeFrameId = bc.tfId(); + const int bcBcInTimeFrame = bc.bcInTF(); + rowTPCTOFTreeWithTrkQA.reserve(tracks.size()); + for (auto const& trk : tracksWithITSPid) { + if (!((trackSelection == 0) || + ((trackSelection == 1) && trk.isGlobalTrack()) || + ((trackSelection == 2) && trk.isGlobalTrackWoPtEta()) || + ((trackSelection == 3) && trk.isGlobalTrackWoDCA()) || + ((trackSelection == 4) && trk.isQualityTrack()) || + ((trackSelection == 5) && trk.isInAcceptanceTrack()))) { + continue; + } + // get the corresponding trackQA using labelTracks2TracKQA and get variables of interest + aod::TracksQA trackQA; + bool existTrkQA; + if (labelTrack2TrackQA[trk.globalIndex()] != -1) { + trackQA = tracksQA.iteratorAt(labelTrack2TrackQA[trk.globalIndex()]); + existTrkQA = true; + } else { + trackQA = tracksQA.iteratorAt(0); + existTrkQA = false; + } + /// Fill tree for tritons + if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() <= maxMomTPCOnlyTr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPCOnlyTr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyTr && trk.tpcInnerParam() > maxMomTPCOnlyTr && std::abs(trk.tofNSigmaTr()) < nSigmaTOF_TPCTOF_Tr && std::abs(trk.tpcNSigmaTr()) < nSigmaTPC_TPCTOF_Tr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Triton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaTr(), trk.tofNSigmaTr(), trk.itsNSigmaTr(), trk.tpcExpSignalTr(trk.tpcSignalCorrected()), o2::track::PID::Triton, runnumber, dwnSmplFactor_Tr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree for deuterons + if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() <= maxMomTPCOnlyDe && std::abs(trk.tpcNSigmaDe()) < nSigmaTPCOnlyDe && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyDe && trk.tpcInnerParam() > maxMomTPCOnlyDe && std::abs(trk.tofNSigmaDe()) < nSigmaTOF_TPCTOF_De && std::abs(trk.tpcNSigmaDe()) < nSigmaTPC_TPCTOF_De && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Deuteron])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.itsNSigmaDe(), trk.tpcExpSignalDe(trk.tpcSignalCorrected()), o2::track::PID::Deuteron, runnumber, dwnSmplFactor_De, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree for protons + if (trk.tpcInnerParam() <= maxMomTPCOnlyPr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPCOnlyPr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPr && std::abs(trk.tofNSigmaPr()) < nSigmaTOF_TPCTOF_Pr && std::abs(trk.tpcNSigmaPr()) < nSigmaTPC_TPCTOF_Pr && downsampleTsalisCharged(trk.pt(), downsamplingTsalisProtons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Proton])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.itsNSigmaPr(), trk.tpcExpSignalPr(trk.tpcSignalCorrected()), o2::track::PID::Proton, runnumber, dwnSmplFactor_Pr, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree for kaons + if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() <= maxMomTPCOnlyKa && std::abs(trk.tpcNSigmaKa()) < nSigmaTPCOnlyKa && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() < maxMomHardCutOnlyKa && trk.tpcInnerParam() > maxMomTPCOnlyKa && std::abs(trk.tofNSigmaKa()) < nSigmaTOF_TPCTOF_Ka && std::abs(trk.tpcNSigmaKa()) < nSigmaTPC_TPCTOF_Ka && downsampleTsalisCharged(trk.pt(), downsamplingTsalisKaons, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Kaon])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaKa(), trk.tofNSigmaKa(), trk.itsNSigmaKa(), trk.tpcExpSignalKa(trk.tpcSignalCorrected()), o2::track::PID::Kaon, runnumber, dwnSmplFactor_Ka, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + /// Fill tree pions + if (trk.tpcInnerParam() <= maxMomTPCOnlyPi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPCOnlyPi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } else if (trk.tpcInnerParam() > maxMomTPCOnlyPi && std::abs(trk.tofNSigmaPi()) < nSigmaTOF_TPCTOF_Pi && std::abs(trk.tpcNSigmaPi()) < nSigmaTPC_TPCTOF_Pi && downsampleTsalisCharged(trk.pt(), downsamplingTsalisPions, sqrtSNN, o2::track::pid_constants::sMasses[o2::track::PID::Pion])) { + fillSkimmedTPCTOFTableWithTrkQA(trk, trackQA, existTrkQA, collision, trk.tpcNSigmaPi(), trk.tofNSigmaPi(), trk.itsNSigmaPi(), trk.tpcExpSignalPi(trk.tpcSignalCorrected()), o2::track::PID::Pion, runnumber, dwnSmplFactor_Pi, hadronicRate, bcGlobalIndex, bcTimeFrameId, bcBcInTimeFrame); + } + } /// Loop tracks + } + } /// process + PROCESS_SWITCH(TreeWriterTPCTOF, processWithTrQAWithCorrecteddEdx, "Samples for PID with TrackQA info with correced dEdx", false); + void processDummy(Colls const&) {} PROCESS_SWITCH(TreeWriterTPCTOF, processDummy, "Dummy function", false); diff --git a/EventFiltering/PWGCF/CFFilterAll.cxx b/EventFiltering/PWGCF/CFFilterAll.cxx index 589228edc5f..efc7625b215 100644 --- a/EventFiltering/PWGCF/CFFilterAll.cxx +++ b/EventFiltering/PWGCF/CFFilterAll.cxx @@ -61,8 +61,8 @@ enum CFTriggers { kPPRho, kPD, kLD, - kRhoD, kPhiD, + kRhoD, kNTriggers }; diff --git a/EventFiltering/PWGCF/CFFilterQA.cxx b/EventFiltering/PWGCF/CFFilterQA.cxx index 372b3387dc1..fe084669b8a 100644 --- a/EventFiltering/PWGCF/CFFilterQA.cxx +++ b/EventFiltering/PWGCF/CFFilterQA.cxx @@ -1033,7 +1033,7 @@ struct CFFilterQA { std::vector setValuesBB(aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) { - map metadata; + std::map metadata; auto h = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); // auto h = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); //check if possible to use this without getting fatal if (!h) { @@ -1055,7 +1055,7 @@ struct CFFilterQA { std::vector setValuesAvg(aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) { - map metadata; + std::map metadata; auto h = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); // auto h = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); //check if possible to use this without getting fatal if (!h) { diff --git a/EventFiltering/PWGEM/EMPhotonFilter.cxx b/EventFiltering/PWGEM/EMPhotonFilter.cxx index a254c7245a1..3e88524a89b 100644 --- a/EventFiltering/PWGEM/EMPhotonFilter.cxx +++ b/EventFiltering/PWGEM/EMPhotonFilter.cxx @@ -12,16 +12,19 @@ // \brief software trigger 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 "Common/DataModel/CaloClusters.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" using namespace o2; using namespace o2::soa; @@ -128,7 +131,7 @@ struct EMPhotonFilter { return false; } - if (track.pt() < minpt || abs(track.eta()) > maxeta) { + if (track.pt() < minpt || std::fabs(track.eta()) > maxeta) { return false; } @@ -158,7 +161,7 @@ struct EMPhotonFilter { dca_3d = 999.f; } else { float chi2 = (track.dcaXY() * track.dcaXY() * track.cZZ() + track.dcaZ() * track.dcaZ() * track.cYY() - 2. * track.dcaXY() * track.dcaZ() * track.cZY()) / det; - dca_3d = std::sqrt(std::abs(chi2) / 2.); + dca_3d = std::sqrt(std::fabs(chi2) / 2.); } if (dca_3d > dca_3d_sigma_max) { return false; @@ -174,23 +177,23 @@ struct EMPhotonFilter { template void runFilter(TCollisions const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPhotons3 const& /*photons3*/, TV0Legs const&, TDielectrons const& dielectrons, TEMPrimaryElectrons const& /*emprimaryelectrons*/) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { mHistManager.fill(HIST("hEventCounter"), 1.); bool keepEvent[kNtrg]{false}; if (collision.sel8()) { mHistManager.fill(HIST("hEventCounter"), 2.); } - if (abs(collision.posZ()) < 10.f) { + if (std::fabs(collision.posZ()) < 10.f) { mHistManager.fill(HIST("hEventCounter"), 3.); } if (collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { mHistManager.fill(HIST("hEventCounter"), 4.); } - if (collision.sel8() && abs(collision.posZ()) < 10.f) { + if (collision.sel8() && std::fabs(collision.posZ()) < 10.f) { mHistManager.fill(HIST("hEventCounter"), 5.); } - if (collision.sel8() && abs(collision.posZ()) < 10.f && collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + if (collision.sel8() && std::fabs(collision.posZ()) < 10.f && collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { mHistManager.fill(HIST("hEventCounter"), 6.); } @@ -203,7 +206,7 @@ struct EMPhotonFilter { auto photons1_per_coll = photons1.sliceBy(perCollision_pcm, collision.globalIndex()); auto dielectrons_per_coll = dielectrons.sliceBy(perCollision_ee, collision.globalIndex()); - for (auto& v0photon : photons1_per_coll) { + for (const auto& v0photon : photons1_per_coll) { auto pos_sv = v0photon.template posTrack_as(); auto ele_sv = v0photon.template negTrack_as(); if (!isSelectedSecondary(pos_sv) || !isSelectedSecondary(ele_sv)) { @@ -215,7 +218,7 @@ struct EMPhotonFilter { } } // end of single v0 photon loop - for (auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photons1_per_coll, dielectrons_per_coll))) { + for (const auto& [g1, g2] : combinations(CombinationsFullIndexPolicy(photons1_per_coll, dielectrons_per_coll))) { auto pos_sv = g1.template posTrack_as(); auto ele_sv = g1.template negTrack_as(); if (!isSelectedSecondary(pos_sv) || !isSelectedSecondary(ele_sv)) { @@ -279,8 +282,8 @@ struct EMPhotonFilter { if (clu2.trackdist() < 1.) { // select neutral clusters. Disp, Ncell cuts? continue; } - double m = pow(clu.e() + clu2.e(), 2) - pow(clu.px() + clu2.px(), 2) - - pow(clu.py() + clu2.py(), 2) - pow(clu.pz() + clu2.pz(), 2); + double m = std::pow(clu.e() + clu2.e(), 2) - std::pow(clu.px() + clu2.px(), 2) - + std::pow(clu.py() + clu2.py(), 2) - std::pow(clu.pz() + clu2.pz(), 2); if (m > ePair * ePair) { keepEvent[kPHOS_Pair] |= true; break; @@ -325,13 +328,10 @@ struct EMPhotonFilter { } // end of collision loop } - Filter PCMFilter = o2::aod::v0photonkf::dcaXYtopv < max_dcatopv_xy_v0 && o2::aod::v0photonkf::dcaZtopv < max_dcatopv_z_v0; - using filteredV0PhotonsKF = Filtered; - Filter DalitzEEFilter = o2::aod::dalitzee::sign == 0; // analyze only uls using filteredDalitzEEs = Filtered; - void process_PCM(MyCollisions const& collisions, filteredV0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, filteredDalitzEEs const& dielectrons, MyPrimaryElectrons const& emprimaryelectrons) + void process_PCM(MyCollisions const& collisions, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, filteredDalitzEEs const& dielectrons, MyPrimaryElectrons const& emprimaryelectrons) { const uint8_t system = EM_Filter_PhotonType::kPCM; runFilter(collisions, v0photons, nullptr, nullptr, v0legs, dielectrons, emprimaryelectrons); @@ -351,7 +351,7 @@ struct EMPhotonFilter { runFilter(collisions, nullptr, nullptr, clusters, nullptr, nullptr, nullptr); } - void process_PCM_PHOS(MyCollisions const& collisions, filteredV0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, filteredDalitzEEs const& dielectrons, MyPrimaryElectrons const& emprimaryelectrons, CluCandidates const& clusters) + void process_PCM_PHOS(MyCollisions const& collisions, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, filteredDalitzEEs const& dielectrons, MyPrimaryElectrons const& emprimaryelectrons, CluCandidates const& clusters) { const uint8_t system = EM_Filter_PhotonType::kPCM | EM_Filter_PhotonType::kPHOS; runFilter(collisions, v0photons, clusters, nullptr, v0legs, dielectrons, emprimaryelectrons); diff --git a/EventFiltering/PWGHF/HFFilter.cxx b/EventFiltering/PWGHF/HFFilter.cxx index 4c0d2d891de..ed03e983d04 100644 --- a/EventFiltering/PWGHF/HFFilter.cxx +++ b/EventFiltering/PWGHF/HFFilter.cxx @@ -8,7 +8,6 @@ // In applying this license CERN does 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 /// \file HFFilter.cxx /// \brief task for selection of events with HF signals @@ -20,40 +19,61 @@ /// \author Federica Zanone , Heidelberg University /// \author Antonio Palasciano , INFN Bari -#include -#include -#include -#include - -#include "TRandom3.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "EventFiltering/PWGHF/HFFilterHelpers.h" +#include "EventFiltering/filterTables.h" +// +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +// +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/Core/RecoDecay.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 +#include +#include +#include +#include + +#include +#include +#include +#include + +#include -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" - -#include "EventFiltering/filterTables.h" -#include "EventFiltering/PWGHF/HFFilterHelpers.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -137,10 +157,7 @@ struct HfFilter { // Main struct for HF triggers Configurable acceptBdtBkgOnly{"acceptBdtBkgOnly", true, "Enable / disable selection based on BDT bkg score only"}; // CCDB configuration - o2::ccdb::CcdbApi ccdbApi; - Service ccdb; Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - int currentRun{0}; // needed to detect if the run changed and trigger update of calibrations etc. // TPC PID calibrations Configurable setTPCCalib{"setTPCCalib", 0, "0 is not use re-calibrations, 1 is compute TPC post-calibrated n-sigmas, 2 is using TPC Spline"}; @@ -150,7 +167,7 @@ struct HfFilter { // Main struct for HF triggers Configurable ccdbBBAntiPion{"ccdbBBAntiPion", "Users/l/lserksny/PIDAntiPion", "Path to the CCDB ocject for antiPion BB param"}; Configurable ccdbBBKaon{"ccdbBBKaon", "Users/l/lserksny/PIDPion", "Path to the CCDB ocject for Kaon BB param"}; Configurable ccdbBBAntiKaon{"ccdbBBAntiKaon", "Users/l/lserksny/PIDAntiPion", "Path to the CCDB ocject for antiKaon BB param"}; - Configurable ccdbPathTPC{"ccdbPathTPC", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the CCDB object"}; + Configurable ccdbPathTPC{"ccdbPathTPC", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the CCDB object"}; // parameter for Optimisation Tree Configurable applyOptimisation{"applyOptimisation", false, "Flag to enable or disable optimisation"}; @@ -159,6 +176,27 @@ struct HfFilter { // Main struct for HF triggers Configurable applyDownscale{"applyDownscale", false, "Flag to enable or disable the application of downscale factors"}; Configurable> downscaleFactors{"downscaleFactors", {defDownscaleFactors[0], kNtriggersHF, 1, hfTriggerNames, labelsDownscaleFactor}, "Downscale factors for each trigger (from 0 to 1)"}; + Service ccdb; + + using BigTracksMCPID = soa::Join; + using BigTracksPID = soa::Join; + using TracksIUPID = soa::Join; + using CollsWithEvSel = soa::Join; + + using Hf2ProngsWithMl = soa::Join; + using Hf3ProngsWithMl = soa::Join; + + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + Preslice v0sPerCollision = aod::v0::collisionId; + Preslice hf2ProngPerCollision = aod::track_association::collisionId; + Preslice hf3ProngPerCollision = aod::track_association::collisionId; + Preslice cascPerCollision = aod::cascade::collisionId; + Preslice photonsPerCollision = aod::v0photonkf::collisionId; + PresliceUnsorted trackedCascadesPerCollision = aod::track::collisionId; + + o2::ccdb::CcdbApi ccdbApi; + int currentRun{0}; // needed to detect if the run changed and trigger update of calibrations etc. + // array of BDT thresholds std::array, kNCharmParticles> thresholdBDTScores; @@ -169,7 +207,6 @@ struct HfFilter { // Main struct for HF triggers o2::vertexing::DCAFitterN<3> dfBtoDstar; // fitter for Beauty Hadron to D* vertex (3-prong vertex fitter) o2::vertexing::DCAFitterN<2> dfStrangeness; // fitter for V0s and cascades (2-prong vertex fitter) - HistogramRegistry registry{"registry"}; std::shared_ptr hProcessedEvents; // QA histos @@ -198,7 +235,9 @@ struct HfFilter { // Main struct for HF triggers // helper object HfFilterHelper helper; - void init(InitContext&) + HistogramRegistry registry{"registry"}; + + void init(InitContext& initContext) { helper.setHighPtTriggerThresholds(ptThresholds->get(0u, 0u), ptThresholds->get(0u, 1u)); helper.setPtTriggerThresholdsForFemto(ptThresholdsForFemto->get(0u, 0u), ptThresholdsForFemto->get(0u, 1u)); @@ -243,6 +282,30 @@ struct HfFilter { // Main struct for HF triggers helper.setVtxConfiguration(dfBtoDstar, true); } + // fetch config of track-index-skim-creator to apply the same cut on DeltaMassKK for Ds + std::vector ptBinsDsSkimCreator{}; + LabeledArray cutsDsSkimCreator{}; + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-track-index-skim-creator") == 0) { + for (const auto& option : device.options) { + if (option.name.compare("binsPtDsToKKPi") == 0) { + auto ptBins = option.defaultValue.get(); + double lastEl{-1.e6}; + int iPt{0}; + while (ptBins[iPt] > lastEl) { + ptBinsDsSkimCreator.push_back(ptBins[iPt]); + lastEl = ptBins[iPt]; + iPt++; + } + } else if (option.name.compare("cutsDsToKKPi") == 0) { + cutsDsSkimCreator = option.defaultValue.get>(); + } + } + } + } + helper.setPreselDsToKKPi(ptBinsDsSkimCreator, cutsDsSkimCreator); + hProcessedEvents = registry.add("fProcessedEvents", "HF - event filtered;;counts", HistType::kTH1D, {{kNtriggersHF + 2, -0.5, +kNtriggersHF + 1.5}}); for (auto iBin = 0; iBin < kNtriggersHF + 2; ++iBin) { if (iBin < 2) @@ -360,22 +423,6 @@ struct HfFilter { // Main struct for HF triggers thresholdBDTScores = {thresholdBDTScoreD0ToKPi, thresholdBDTScoreDPlusToPiKPi, thresholdBDTScoreDSToPiKK, thresholdBDTScoreLcToPiKP, thresholdBDTScoreXicToPiKP}; } - using BigTracksMCPID = soa::Join; - using BigTracksPID = soa::Join; - using TracksIUPID = soa::Join; - using CollsWithEvSel = soa::Join; - - using Hf2ProngsWithMl = soa::Join; - using Hf3ProngsWithMl = soa::Join; - - Preslice trackIndicesPerCollision = aod::track_association::collisionId; - Preslice v0sPerCollision = aod::v0::collisionId; - Preslice hf2ProngPerCollision = aod::track_association::collisionId; - Preslice hf3ProngPerCollision = aod::track_association::collisionId; - Preslice cascPerCollision = aod::cascade::collisionId; - Preslice photonsPerCollision = aod::v0photonkf::collisionId; - PresliceUnsorted trackedCascadesPerCollision = aod::track::collisionId; - void process(CollsWithEvSel const& collisions, aod::BCsWithTimestamps const&, aod::V0s const& v0s, diff --git a/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx b/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx index ab46a5e2504..3cd5a047bb9 100644 --- a/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx +++ b/EventFiltering/PWGHF/HFFilterCharmHadronSignals.cxx @@ -8,37 +8,53 @@ // In applying this license CERN does 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 /// \file HFFilterCharmHadronSignals.cxx /// \brief task for the quality control of the signals of D0, D+, Ds+, Lc+, and D*+ selected in the HFFilter.cxx task /// /// \author Fabrizio Grosa , CERN -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "EventFiltering/PWGHF/HFFilterHelpers.h" +// +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +// +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" - -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "EventFiltering/filterTables.h" -#include "EventFiltering/PWGHF/HFFilterHelpers.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 using namespace o2; using namespace o2::analysis; diff --git a/EventFiltering/PWGHF/HFFilterHelpers.h b/EventFiltering/PWGHF/HFFilterHelpers.h index 72b2f71cae4..e6202c5a000 100644 --- a/EventFiltering/PWGHF/HFFilterHelpers.h +++ b/EventFiltering/PWGHF/HFFilterHelpers.h @@ -8,7 +8,6 @@ // In applying this license CERN does 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 /// \file HFFilterHelpers.h /// \brief Header file with definition of variables, methods, and tables used in the HFFilter.cxx task @@ -23,41 +22,47 @@ #ifndef EVENTFILTERING_PWGHF_HFFILTERHELPERS_H_ #define EVENTFILTERING_PWGHF_HFFILTERHELPERS_H_ +#include "EventFiltering/filterTables.h" +// +#include "PWGHF/Core/SelectorCuts.h" +// +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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 -#include "Math/GenVector/Boost.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" - -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/MathConstants.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" - -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "EventFiltering/filterTables.h" - namespace o2::aod { @@ -273,7 +278,7 @@ constexpr float massB0 = o2::constants::physics::MassB0; constexpr float massBs = o2::constants::physics::MassBS; constexpr float massLb = o2::constants::physics::MassLambdaB0; constexpr float massXib = o2::constants::physics::MassXiB0; -constexpr float massBc = 6.2744700f; // TODO add Bc mass to o2::constants::physics +constexpr float massBc = o2::constants::physics::MassBCPlus; constexpr float massSigmaCPlusPlus = o2::constants::physics::MassSigmaCPlusPlus; constexpr float massSigmaC0 = o2::constants::physics::MassSigmaC0; constexpr float massK0Star892 = o2::constants::physics::MassK0Star892; @@ -589,6 +594,15 @@ class HfFilterHelper mSigmaPars3Prongs[1] = 0.00176f; mDeltaMassPars3Prongs[0] = -0.0025f; mDeltaMassPars3Prongs[1] = 0.0001f; + } else if (recoPass == "2025_pass1") { + mSigmaPars2Prongs[0] = 0.01424f; + mSigmaPars2Prongs[1] = 0.00178f; + mDeltaMassPars2Prongs[0] = -0.013f; + mDeltaMassPars2Prongs[1] = 0.00029f; + mSigmaPars3Prongs[0] = 0.00796f; + mSigmaPars3Prongs[1] = 0.00176f; + mDeltaMassPars3Prongs[0] = -0.013f; + mDeltaMassPars3Prongs[1] = 0.00029f; } else { LOGP(fatal, "Mass resolution parametrisation {} not supported! Please set 2023_pass3", recoPass.data()); } @@ -596,6 +610,12 @@ class HfFilterHelper void setNumSigmaForDeltaMassCharmHadCut(float nSigma) { mNumSigmaDeltaMassCharmHad = nSigma; } + void setPreselDsToKKPi(std::vector ptBins, o2::framework::LabeledArray preselections) + { + mPtBinsPreselDsToKKPi = ptBins; + mPreselDsToKKPi = preselections; + } + // helper functions for selections template bool isSelectedHighPt2Prong(const T& pt); @@ -785,6 +805,9 @@ class HfFilterHelper 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 std::array, 8> mBetheBlochPiKaPrDe{}; // Bethe-Bloch parametrisations for pions, antipions, kaons, antikaons, protons, antiprotons, deuterons, antideuterons in TPC + // Ds cuts from track-index-skim-creator + std::vector mPtBinsPreselDsToKKPi{}; // pT bins for pre-selections for Ds from track-index-skim-creator + o2::framework::LabeledArray mPreselDsToKKPi{}; // pre-selections for Ds from track-index-skim-creator }; /// Selection of high-pt 2-prong candidates @@ -1066,13 +1089,20 @@ inline int8_t HfFilterHelper::isDsPreselected(const P& pTrackSameChargeFirst, co } // check delta-mass for phi resonance + auto ptDs = RecoDecay::pt(pTrackSameChargeFirst, pTrackSameChargeSecond, pTrackOppositeCharge); + auto ptBinDs = findBin(mPtBinsPreselDsToKKPi, ptDs); + if (ptBinDs == -1) { + return retValue; + } + auto invMassKKFirst = RecoDecay::m(std::array{pTrackSameChargeFirst, pTrackOppositeCharge}, std::array{massKa, massKa}); auto invMassKKSecond = RecoDecay::m(std::array{pTrackSameChargeSecond, pTrackOppositeCharge}, std::array{massKa, massKa}); - if (std::fabs(invMassKKFirst - massPhi) < 0.02) { + float cutValueMassKK = mPreselDsToKKPi.get(ptBinDs, 4u); + if (std::fabs(invMassKKFirst - massPhi) < cutValueMassKK) { retValue |= BIT(0); } - if (std::fabs(invMassKKSecond - massPhi) < 0.02) { + if (std::fabs(invMassKKSecond - massPhi) < cutValueMassKK) { retValue |= BIT(1); } diff --git a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx index 2a5dda41464..b7a9637ba10 100644 --- a/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx +++ b/EventFiltering/PWGHF/HFFilterPrepareMLSamples.cxx @@ -8,7 +8,6 @@ // In applying this license CERN does 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 /// \file HFFilterPrepareMLSamples.cxx /// \brief task for trainings of ML models to be used in the HFFilter.cxx task @@ -19,31 +18,41 @@ /// \author Biao Zhang , CCNU /// \author Antonio Palasciano , INFN Bari -#include -#if __has_include() -#include // needed for HFFilterHelpers, to be fixed -#else -#include -#endif - -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "EventFiltering/PWGHF/HFFilterHelpers.h" +// +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +// +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include -#include "EventFiltering/PWGHF/HFFilterHelpers.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::analysis; diff --git a/EventFiltering/PWGLF/filterf1proton.cxx b/EventFiltering/PWGLF/filterf1proton.cxx index abdfe9c272a..8919d851580 100644 --- a/EventFiltering/PWGLF/filterf1proton.cxx +++ b/EventFiltering/PWGLF/filterf1proton.cxx @@ -436,7 +436,7 @@ struct filterf1proton { std::vector setValuesBB(o2::ccdb::CcdbApi& ccdbApi, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) { - map metadata; + std::map metadata; auto h = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); // auto h = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); // check if possible to use this without getting fatal if (!h) { diff --git a/EventFiltering/PWGLF/nucleiFilter.cxx b/EventFiltering/PWGLF/nucleiFilter.cxx index 54f3ed507ad..443df675533 100644 --- a/EventFiltering/PWGLF/nucleiFilter.cxx +++ b/EventFiltering/PWGLF/nucleiFilter.cxx @@ -10,42 +10,48 @@ // or submit itself to any jurisdiction. // O2 includes -#include -#include +#include "../filterTables.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" +#include "PWGLF/DataModel/LFPIDTOFGenericTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/Vtx3BodyTables.h" +#include "PWGLF/Utils/pidTOFGeneric.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.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 "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "../filterTables.h" +#include "Math/GenVector/Boost.h" +#include "Math/Vector4D.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsTOF/ParameterContainers.h" -#include "CCDB/BasicCCDBManager.h" -#include "DCAFitter/DCAFitterN.h" -#include "PWGLF/DataModel/pidTOFGeneric.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/Core/PID/PIDTOF.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +o2::common::core::MetadataHelper metadataInfo; + namespace { @@ -120,7 +126,9 @@ struct nucleiFilter { o2::base::MatLayerCylSet* lut = nullptr; o2::vertexing::DCAFitterN<2> fitter2body; o2::vertexing::DCAFitterN<3> fitter3body; - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; + // TOF response and input parameters + o2::pid::tof::TOFResoParamsV3 mRespParamsV3; + o2::aod::pidtofgeneric::TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration // configurable for hypertriton 3body decay struct : ConfigurableGroup { Configurable bFieldInput{"trgH3L3Body.mBz", -999, "bz field, -999 is automatic"}; @@ -153,20 +161,12 @@ struct nucleiFilter { Configurable grpmagPath{"trgH3L3Body.grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable lutPath{"trgH3L3Body.lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"trgH3L3Body.geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - // CCDB TOF PID paras - Configurable timestamp{"trgH3L3Body.ccdb-timestamp", -1, "timestamp of the object"}; - Configurable paramFileName{"trgH3L3Body.paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; - Configurable parametrizationPath{"trgH3L3Body.parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; - Configurable passName{"trgH3L3Body.passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; - Configurable timeShiftCCDBPath{"trgH3L3Body.timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; - Configurable loadResponseFromCCDB{"trgH3L3Body.loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable fatalOnPassNotAvailable{"trgH3L3Body.fatalOnPassNotAvailable", false, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; } trgH3L3Body; HistogramRegistry qaHists{"qaHists", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; OutputObj hProcessedEvents{TH1D("hProcessedEvents", ";;Number of filtered events", kNtriggers + 1, -0.5, static_cast(kNtriggers) + 0.5)}; - void init(InitContext&) + void init(InitContext& initContext) { std::vector ptBinning = {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.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4., 5.}; @@ -214,6 +214,11 @@ struct nucleiFilter { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + + // Initialization of TOF PID parameters for fH3L3Body + mTOFCalibConfig.metadataInfo = metadataInfo; + mTOFCalibConfig.inheritFromBaseTask(initContext); + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); // Getting the parametrization parameters } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -264,65 +269,7 @@ struct nucleiFilter { o2::base::Propagator::Instance()->setMatLUT(lut); } - // Initial TOF PID Paras, copied from pidTOF.cxx - trgH3L3Body.timestamp.value = bc.timestamp(); - ccdb->setTimestamp(trgH3L3Body.timestamp.value); - // Not later than now objects - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - // TODO: implement the automatic pass name detection from metadata - if (trgH3L3Body.passName.value == "") { - trgH3L3Body.passName.value = "unanchored"; // temporary default - LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << trgH3L3Body.passName.value << "'"; - } - LOG(info) << "Using parameter collection, starting from pass '" << trgH3L3Body.passName.value << "'"; - - const std::string fname = trgH3L3Body.paramFileName.value; - if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << trgH3L3Body.parametrizationPath.value; - if (1) { - o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, trgH3L3Body.parametrizationPath.value); - LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV2, trgH3L3Body.passName.value)) { - if (trgH3L3Body.fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", trgH3L3Body.passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", trgH3L3Body.passName.value.data()); - } - } else { - mRespParamsV2.setShiftParameters(paramCollection.getPars(trgH3L3Body.passName.value)); - mRespParamsV2.printShiftParameters(); - } - } else { - mRespParamsV2.loadParamFromFile(fname.data(), trgH3L3Body.parametrizationPath.value); - } - } else if (trgH3L3Body.loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << trgH3L3Body.parametrizationPath.value << " for timestamp " << trgH3L3Body.timestamp.value; - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(trgH3L3Body.parametrizationPath.value, trgH3L3Body.timestamp.value); - paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV2, trgH3L3Body.passName.value)) { // Attempt at loading the parameters with the pass defined - if (trgH3L3Body.fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", trgH3L3Body.passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", trgH3L3Body.passName.value.data()); - } - } else { // Pass is available, load non standard parameters - mRespParamsV2.setShiftParameters(paramCollection->getPars(trgH3L3Body.passName.value)); - mRespParamsV2.printShiftParameters(); - } - } - mRespParamsV2.print(); - if (trgH3L3Body.timeShiftCCDBPath.value != "") { - if (trgH3L3Body.timeShiftCCDBPath.value.find(".root") != std::string::npos) { - mRespParamsV2.setTimeShiftParameters(trgH3L3Body.timeShiftCCDBPath.value, "gmean_Pos", true); - mRespParamsV2.setTimeShiftParameters(trgH3L3Body.timeShiftCCDBPath.value, "gmean_Neg", false); - } else { - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", trgH3L3Body.timeShiftCCDBPath.value.c_str()), trgH3L3Body.timestamp.value), true); - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", trgH3L3Body.timeShiftCCDBPath.value.c_str()), trgH3L3Body.timestamp.value), false); - } - } - - bachelorTOFPID.SetParams(mRespParamsV2); + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, bc); } enum { @@ -568,7 +515,7 @@ struct nucleiFilter { float tofNSigmaDeuteron = -999; if (track2.has_collision() && track2.hasTOF()) { auto originalcol = track2.collision_as(); - tofNSigmaDeuteron = bachelorTOFPID.GetTOFNSigma(track2, originalcol, collision); + tofNSigmaDeuteron = bachelorTOFPID.GetTOFNSigma(mRespParamsV3, track2, originalcol, collision); } if (track2.p() > trgH3L3Body.minDeuteronPUseTOF && (tofNSigmaDeuteron < trgH3L3Body.tofPIDNSigmaMin || tofNSigmaDeuteron > trgH3L3Body.tofPIDNSigmaMax)) { continue; @@ -671,6 +618,7 @@ struct nucleiFilter { WorkflowSpec defineDataProcessing(ConfigContext const& cfg) { + metadataInfo.initMetadata(cfg); return WorkflowSpec{ adaptAnalysisTask(cfg)}; } diff --git a/EventFiltering/PWGLF/strangenessFilter.cxx b/EventFiltering/PWGLF/strangenessFilter.cxx index fea1290cc0c..ceabf8eddfb 100644 --- a/EventFiltering/PWGLF/strangenessFilter.cxx +++ b/EventFiltering/PWGLF/strangenessFilter.cxx @@ -516,8 +516,10 @@ struct strangenessFilter { o2::parameters::GRPMagField* grpmag = ccdb->getForRun("GLO/Config/GRPMagField", run); o2::base::Propagator::initFieldFromGRP(grpmag); mBz = static_cast(grpmag->getNominalL3Field()); - mMeanMultT0C = ccdb->getForRun>("Users/e/ekryshen/meanT0C", run); - mMeanMultT0A = ccdb->getForRun>("Users/e/ekryshen/meanT0A", run); + if (useNormalisedMult) + mMeanMultT0C = ccdb->getForRun>("Users/e/ekryshen/meanT0C", run); + if (useNormalisedMult) + mMeanMultT0A = ccdb->getForRun>("Users/e/ekryshen/meanT0A", run); mDCAFitter.setBz(mBz); mDCAFitter.setPropagateToPCA(propToDCA); diff --git a/EventFiltering/PWGMM/multFilter.cxx b/EventFiltering/PWGMM/multFilter.cxx index cf9057a28a3..fe641438a43 100644 --- a/EventFiltering/PWGMM/multFilter.cxx +++ b/EventFiltering/PWGMM/multFilter.cxx @@ -8,24 +8,23 @@ // In applying this license CERN does 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/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.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 "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/TrackSelection.h" + +#include +#include using namespace o2; using namespace o2::framework; @@ -58,6 +57,9 @@ struct multFilter { Configurable sel8{"sel8", 1, "apply sel8 event selection"}; Configurable selt0time{"selt0time", 0, "apply 1ns cut T0A and T0C"}; Configurable selt0vtx{"selt0vtx", 0, "apply T0 vertext trigger"}; + Configurable isTimeFrameBorderCut{"isTimeFrameBorderCut", 1, "apply timeframe border cut"}; + Configurable isSameBunchPileup{"isSameBunchPileup", 1, "apply same bunch pileup cut"}; + Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", 1, "apply good vtx FT0vsPV cut"}; Configurable avPyT0A{"avPyT0A", 8.16, "nch from pythia T0A"}; Configurable avPyT0C{"avPyT0C", 8.83, "nch from pythia T0C"}; @@ -358,6 +360,19 @@ struct multFilter { return; } + if (isTimeFrameBorderCut && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + tags(false, false, false, false, false, false, false); + return; + } + if (isSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + tags(false, false, false, false, false, false, false); + return; + } + if (isGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + tags(false, false, false, false, false, false, false); + return; + } + multiplicity.fill(HIST("hMultFV0sel"), sumAmpFV0); multiplicity.fill(HIST("hMultFV01to4Ringsel"), sumAmpFV01to4Ring); multiplicity.fill(HIST("hMultFV05Ringsel"), sumAmpFV05Ring); diff --git a/EventFiltering/Zorro.cxx b/EventFiltering/Zorro.cxx index 8b47d0c2d3f..ccdf063307d 100644 --- a/EventFiltering/Zorro.cxx +++ b/EventFiltering/Zorro.cxx @@ -12,13 +12,31 @@ #include "Zorro.h" -#include -#include +#include "EventFiltering/ZorroHelper.h" + +#include +#include +#include +#include +#include +#include +#include +#include -#include +#include +#include +#include -#include "CCDB/BasicCCDBManager.h" -#include "CommonDataFormat/InteractionRecord.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using o2::InteractionRecord; @@ -181,24 +199,18 @@ std::vector Zorro::initCCDB(o2::ccdb::BasicCCDBManager* ccdb, int runNumber mLastSelectedIdx = 0; mTOIs.clear(); mTOIidx.clear(); - while (!tois.empty()) { - size_t pos = tois.find(","); - pos = (pos == std::string::npos) ? tois.size() : pos; - std::string token = tois.substr(0, pos); - // Trim leading and trailing whitespaces from the token - token.erase(0, token.find_first_not_of(" ")); - token.erase(token.find_last_not_of(" ") + 1); + std::vector tokens = o2::utils::Str::tokenize(tois, ','); // tokens are trimmed + for (auto const& token : tokens) { int bin = findBin(mSelections, token) - 2; mTOIs.push_back(token); mTOIidx.push_back(bin); - tois = tois.erase(0, pos + 1); } mTOIcounts.resize(mTOIs.size(), 0); LOGF(info, "Zorro initialized for run %d, triggers of interest:", runNumber); for (size_t i{0}; i < mTOIs.size(); ++i) { LOGF(info, ">>> %s : %i", mTOIs[i].data(), mTOIidx[i]); } - mZorroSummary.setupTOIs(mTOIs.size(), tois); + mZorroSummary.setupTOIs(mTOIs.size(), mTOIs); std::vector toiCounters(mTOIs.size(), 0.); for (size_t i{0}; i < mTOIs.size(); ++i) { toiCounters[i] = mSelections->GetBinContent(mTOIidx[i] + 2); @@ -212,7 +224,7 @@ std::bitset<128> Zorro::fetch(uint64_t bcGlobalId, uint64_t tolerance) { mLastResult.reset(); if (bcGlobalId < mBCranges.front().getMin().toLong() - tolerance || bcGlobalId > mBCranges.back().getMax().toLong() + tolerance) { - setupHelpers((mOrbitResetTimestamp + int64_t(bcGlobalId * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000); + setupHelpers((mOrbitResetTimestamp + static_cast(bcGlobalId * o2::constants::lhc::LHCBunchSpacingNS * 1e-3)) / 1000); } o2::dataformats::IRFrame bcFrame{InteractionRecord::long2IR(bcGlobalId) - tolerance, InteractionRecord::long2IR(bcGlobalId) + tolerance}; @@ -306,7 +318,7 @@ void Zorro::setupHelpers(int64_t timestamp) std::sort(mZorroHelpers->begin(), mZorroHelpers->end(), [](const auto& a, const auto& b) { return std::min(a.bcAOD, a.bcEvSel) < std::min(b.bcAOD, b.bcEvSel); }); mBCranges.clear(); mAccountedBCranges.clear(); - for (auto helper : *mZorroHelpers) { + for (const auto& helper : *mZorroHelpers) { mBCranges.emplace_back(InteractionRecord::long2IR(std::min(helper.bcAOD, helper.bcEvSel)), InteractionRecord::long2IR(std::max(helper.bcAOD, helper.bcEvSel))); } mAccountedBCranges.resize(mBCranges.size(), false); diff --git a/EventFiltering/Zorro.h b/EventFiltering/Zorro.h index c818e45ce48..f03badab2ce 100644 --- a/EventFiltering/Zorro.h +++ b/EventFiltering/Zorro.h @@ -9,24 +9,31 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Zero Obstacles Results Retriever for Offline trigger selections + +/// +/// \file Zorro.h +/// \brief Zero Obstacles Results Retriever for Offline trigger selections +/// \author M Puccio +/// #ifndef EVENTFILTERING_ZORRO_H_ #define EVENTFILTERING_ZORRO_H_ +#include "ZorroHelper.h" +#include "ZorroSummary.h" + +#include +#include + +#include +#include + #include -#include +#include #include #include #include -#include "TH1D.h" -#include "TH2D.h" -#include "CommonDataFormat/IRFrame.h" -#include "Framework/HistogramRegistry.h" -#include "ZorroHelper.h" -#include "ZorroSummary.h" - namespace o2 { namespace ccdb @@ -54,9 +61,10 @@ class Zorro std::vector getTOIcounters() const { return mTOIcounts; } std::vector getTriggerOfInterestResults(uint64_t bcGlobalId, uint64_t tolerance = 100); std::vector getTriggerOfInterestResults() const; + int getNTOIs() const { return mTOIs.size(); } - void setCCDBpath(std::string path) { mBaseCCDBPath = path; } - void setBaseCCDBPath(std::string path) { mBaseCCDBPath = path; } + void setCCDBpath(const std::string& path) { mBaseCCDBPath = path; } + void setBaseCCDBPath(const std::string& path) { mBaseCCDBPath = path; } void setBCtolerance(int tolerance) { mBCtolerance = tolerance; } ZorroSummary* getZorroSummary() { return &mZorroSummary; } @@ -70,8 +78,8 @@ class Zorro int mRunNumber = 0; std::pair mRunDuration; int64_t mOrbitResetTimestamp = 0; - TH1* mAnalysedTriggers; /// Accounting for all triggers in the current run - TH1* mAnalysedTriggersOfInterest; /// Accounting for triggers of interest in the current run + TH1* mAnalysedTriggers = nullptr; /// Accounting for all triggers in the current run + TH1* mAnalysedTriggersOfInterest = nullptr; /// Accounting for triggers of interest in the current run std::vector mRunNumberHistos; std::vector mAnalysedTriggersList; /// Per run histograms diff --git a/EventFiltering/ZorroHelper.h b/EventFiltering/ZorroHelper.h index 8bcc6240bc0..e80a07ef994 100644 --- a/EventFiltering/ZorroHelper.h +++ b/EventFiltering/ZorroHelper.h @@ -13,7 +13,8 @@ #ifndef EVENTFILTERING_ZORROHELPER_H_ #define EVENTFILTERING_ZORROHELPER_H_ -#include "Rtypes.h" +#include +#include struct ZorroHelper { ULong64_t bcAOD, bcEvSel, trigMask[2], selMask[2]; diff --git a/EventFiltering/ZorroSummary.cxx b/EventFiltering/ZorroSummary.cxx index ee241f49108..0a1012c3edc 100644 --- a/EventFiltering/ZorroSummary.cxx +++ b/EventFiltering/ZorroSummary.cxx @@ -11,7 +11,12 @@ #include "ZorroSummary.h" -#include "TCollection.h" +#include +#include + +#include + +#include void ZorroSummary::Copy(TObject& c) const { @@ -42,7 +47,7 @@ Long64_t ZorroSummary::Merge(TCollection* list) mTOIcounters[runNumber] = entry->getTOIcounters().at(runNumber); } else { auto& thisCounters = mAnalysedTOIcounters[runNumber]; - for (size_t i = 0; i < thisCounters.size(); ++i) { + for (std::size_t i = 0; i < thisCounters.size(); ++i) { thisCounters[i] += currentAnalysedToiCounters[i]; } } @@ -66,4 +71,4 @@ double ZorroSummary::getNormalisationFactor(int toiId) const } return totalTVX * totalAnalysedTOI / totalTOI; -} \ No newline at end of file +} diff --git a/EventFiltering/ZorroSummary.h b/EventFiltering/ZorroSummary.h index b4d401adba4..51019aeef18 100644 --- a/EventFiltering/ZorroSummary.h +++ b/EventFiltering/ZorroSummary.h @@ -15,6 +15,9 @@ #include +#include +#include + #include #include #include @@ -28,10 +31,16 @@ class ZorroSummary : public TNamed virtual void Copy(TObject& c) const; // NOLINT: Making this override breaks compilation for unknown reason virtual Long64_t Merge(TCollection* list); - void setupTOIs(int ntois, const std::string& toinames) + void setupTOIs(int ntois, const std::vector& toinames) { mNtois = ntois; - mTOInames = toinames; + if (toinames.size() == 0) { + return; + } + mTOInames = toinames[0]; + for (size_t i = 1; i < toinames.size(); i++) { + mTOInames += "," + toinames[i]; + } } void setupRun(int runNumber, double tvxCountes, const std::vector& toiCounters) { @@ -41,9 +50,7 @@ class ZorroSummary : public TNamed mRunNumber = runNumber; mTVXcounters[runNumber] = tvxCountes; mTOIcounters[runNumber] = toiCounters; - if (mAnalysedTOIcounters.find(runNumber) == mAnalysedTOIcounters.end()) { - mAnalysedTOIcounters[runNumber] = std::vector(mNtois, 0ull); - } + mAnalysedTOIcounters.try_emplace(runNumber, std::vector(mNtois, 0ull)); mCurrentAnalysedTOIcounters = &mAnalysedTOIcounters[runNumber]; } double getNormalisationFactor(int toiId) const; @@ -55,7 +62,7 @@ class ZorroSummary : public TNamed mCurrentAnalysedTOIcounters->at(toiId)++; } - std::string getTOInames() const { return mTOInames; } + const auto& getTOInames() const { return mTOInames; } const auto& getTOIcounters() const { return mTOIcounters; } const auto& getTVXcounters() const { return mTVXcounters; } const auto& getAnalysedTOIcounters() const { return mAnalysedTOIcounters; } @@ -73,4 +80,4 @@ class ZorroSummary : public TNamed ClassDef(ZorroSummary, 1); }; -#endif // EVENTFILTERING_ZORROSUMMARY_H_ \ No newline at end of file +#endif // EVENTFILTERING_ZORROSUMMARY_H_ diff --git a/EventFiltering/macros/getMenu.C b/EventFiltering/macros/getMenu.C new file mode 100644 index 00000000000..692ebe396f3 --- /dev/null +++ b/EventFiltering/macros/getMenu.C @@ -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. + +#include "CCDB/BasicCCDBManager.h" + +#include +#include + +#include + +void getMenu(int runNumber, std::string baseCCDBPath = "Users/m/mpuccio/EventFiltering/OTS/Chunked/") +{ + auto& ccdb = o2::ccdb::BasicCCDBManager::instance(); + TH1* counters = ccdb.getForRun(baseCCDBPath + "FilterCounters", runNumber); + TAxis* axis = counters->GetXaxis(); + + std::vector binLabels(axis->GetNbins() - 2); // skip first and last bins + std::cout << "Menu for run " << runNumber << ":\n"; + for (int i = 2; i < axis->GetNbins(); ++i) { + binLabels[i - 1] = axis->GetBinLabel(i); + std::cout << "Id " << i - 2 << ": " << axis->GetBinLabel(i) << "\n"; + } +} diff --git a/EventFiltering/macros/uploadOTSobjects.C b/EventFiltering/macros/uploadOTSobjects.C index 2a9be2de17e..8e4c6c27136 100644 --- a/EventFiltering/macros/uploadOTSobjects.C +++ b/EventFiltering/macros/uploadOTSobjects.C @@ -67,6 +67,13 @@ void uploadOTSobjects(std::string inputList, std::string passName, bool useAlien api.storeAsTFile(scalers, baseCCDBpath + "FilterCounters", metadata, duration.first, duration.second + 1); api.storeAsTFile(filters, baseCCDBpath + "SelectionCounters", metadata, duration.first, duration.second + 1); TH1* hCounterTVX = static_cast(scalersFile->Get("bc-selection-task/hCounterTVX")); + if (!hCounterTVX) { + hCounterTVX = static_cast(scalersFile->Get("lumi-task/hCounterTVX")); + if (!hCounterTVX) { + std::cout << "No hCounterTVX histogram found in the file, skipping upload for run " << runString << std::endl; + continue; + } + } api.storeAsTFile(hCounterTVX, baseCCDBpath + "InspectedTVX", metadata, duration.first, duration.second + 1); std::vector zorroHelpers; diff --git a/PWGCF/Core/CorrelationContainer.cxx b/PWGCF/Core/CorrelationContainer.cxx index a910cf2d1b9..1421288bd18 100644 --- a/PWGCF/Core/CorrelationContainer.cxx +++ b/PWGCF/Core/CorrelationContainer.cxx @@ -115,7 +115,7 @@ CorrelationContainer::CorrelationContainer(const char* name, const char* objTitl triggerAxis.insert(triggerAxis.end(), userAxis.begin(), userAxis.end()); mTriggerHist = HistFactory::createHist({"mTriggerHist", "d^{2}N_{ch}/d#varphid#eta", {HistType::kStepTHnF, triggerAxis, fgkCFSteps}}).release(); - mTrackHistEfficiency = HistFactory::createHist({"mTrackHistEfficiency", "Tracking efficiency", {HistType::kStepTHnD, {efficiencyAxis[0], efficiencyAxis[1], {4, -0.5, 3.5, "species"}, correlationAxis[3], efficiencyAxis[2]}, fgkCFSteps}}).release(); + mTrackHistEfficiency = HistFactory::createHist({"mTrackHistEfficiency", "Tracking efficiency", {HistType::kStepTHnD, {efficiencyAxis[0], efficiencyAxis[1], {5, -0.5, 4.5, "species"}, correlationAxis[3], efficiencyAxis[2]}, fgkCFSteps}}).release(); mEventCount = HistFactory::createHist({"mEventCount", ";step;centrality;count", {HistType::kTH2F, {{fgkCFSteps + 2, -2.5, -0.5 + fgkCFSteps, "step"}, correlationAxis[3]}}}).release(); } @@ -309,7 +309,7 @@ void CorrelationContainer::resetBinLimits(THnBase* grid, int max_dimension) for (Int_t i = 0; i < max_dimension; i++) { if (grid->GetAxis(i)->TestBit(TAxis::kAxisRange)) { - grid->GetAxis(i)->SetRangeUser(0, -1); + grid->GetAxis(i)->SetRange(0, 0); // reset range } } } @@ -681,8 +681,11 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati Double_t sums[] = {0, 0, 0}; Double_t errors[] = {0, 0, 0}; + Int_t checkBinYBegin = 1; // tracksSame->GetXaxis()->FindBin(-0.79); + Int_t checkBinYEnd = tracksSame->GetNbinsY(); // tracksSame->GetXaxis()->FindBin(0.79); + for (Int_t x = 1; x <= tracksSame->GetNbinsX(); x++) { - for (Int_t y = 1; y <= tracksSame->GetNbinsY(); y++) { + for (Int_t y = checkBinYBegin; y <= checkBinYEnd; y++) { sums[0] += tracksSame->GetBinContent(x, y); errors[0] += tracksSame->GetBinError(x, y); sums[1] += tracksMixed->GetBinContent(x, y); @@ -693,7 +696,7 @@ TH2* CorrelationContainer::getSumOfRatios(CorrelationContainer* mixed, Correlati tracksSame->Divide(tracksMixed); for (Int_t x = 1; x <= tracksSame->GetNbinsX(); x++) { - for (Int_t y = 1; y <= tracksSame->GetNbinsY(); y++) { + for (Int_t y = checkBinYBegin; y <= checkBinYEnd; y++) { sums[2] += tracksSame->GetBinContent(x, y); errors[2] += tracksSame->GetBinError(x, y); } diff --git a/PWGCF/DataModel/CorrelationsDerived.h b/PWGCF/DataModel/CorrelationsDerived.h index fcaf300c2f3..9be8ac7d58e 100644 --- a/PWGCF/DataModel/CorrelationsDerived.h +++ b/PWGCF/DataModel/CorrelationsDerived.h @@ -11,11 +11,12 @@ #ifndef PWGCF_DATAMODEL_CORRELATIONSDERIVED_H_ #define PWGCF_DATAMODEL_CORRELATIONSDERIVED_H_ -#include +#include "Common/DataModel/Centrality.h" #include "Framework/ASoA.h" #include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/Centrality.h" + +#include namespace o2::aod { @@ -85,6 +86,22 @@ using CFTrackWithLabel = CFTracksWithLabel::iterator; //------transient CF-filter to CF-2prong-filter DECLARE_SOA_TABLE(CFCollRefs, "AOD", "CFCOLLREF", o2::soa::Index<>, track::CollisionId); //! Transient cf collision index table +//------multiplicity set +namespace cfmultset +{ +DECLARE_SOA_COLUMN(Multiplicities, multiplicities, std::vector); //! List of auxiliary multiplicities +enum MultiplicityEstimators : uint8_t { + CentFT0C = 0x1, + MultFV0A = 0x2, + MultNTracksPV = 0x4, + MultNTracksGlobal = 0x8 +}; + +} // namespace cfmultset +DECLARE_SOA_TABLE(CFMultSets, "AOD", "CFMULTSET", cfmultset::Multiplicities); //! Auxilary multiplicity set table + +using CFMultSet = CFMultSets::iterator; + // Reco using CFCollRef = CFCollRefs::iterator; @@ -123,6 +140,10 @@ enum ParticleDecay { JPsiToEE, JPsiToMuMu, Generic2Prong, + PhiToKK, + K0stoPiPi, + LambdatoPPi, + AntiLambdatoPiP }; } // namespace cf2prongtrack DECLARE_SOA_TABLE(CF2ProngTracks, "AOD", "CF2PRONGTRACK", //! Reduced track table @@ -148,13 +169,20 @@ using CF2ProngTrackml = CF2ProngTrackmls::iterator; namespace cf2prongmcpart { -DECLARE_SOA_INDEX_COLUMN_FULL(CFParticleDaugh0, cfParticleDaugh0, int, CFMcParticles, "_0"); //! Index to prong 1 CFMcParticle -DECLARE_SOA_INDEX_COLUMN_FULL(CFParticleDaugh1, cfParticleDaugh1, int, CFMcParticles, "_1"); //! Index to prong 2 CFMcParticle +DECLARE_SOA_INDEX_COLUMN_FULL(CFParticleDaugh0, cfParticleDaugh0, int, CFMcParticles, "_0"); //! Index to prong 1 CFMcParticle +DECLARE_SOA_INDEX_COLUMN_FULL(CFParticleDaugh1, cfParticleDaugh1, int, CFMcParticles, "_1"); //! Index to prong 2 CFMcParticle +DECLARE_SOA_COLUMN(Decay, decay, uint8_t); //! Particle decay and flags +DECLARE_SOA_DYNAMIC_COLUMN(McDecay, mcDecay, [](uint8_t decay) -> uint8_t { return decay & 0x7f; }); //! MC particle decay +enum ParticleDecayFlags { + Prompt = 0x80 +}; } // namespace cf2prongmcpart DECLARE_SOA_TABLE(CF2ProngMcParts, "AOD", "CF2PRONGMCPART", //! Table for the daughter particles of a 2-prong particle, to be joined with CFMcParticles o2::soa::Index<>, cf2prongmcpart::CFParticleDaugh0Id, - cf2prongmcpart::CFParticleDaugh1Id) + cf2prongmcpart::CFParticleDaugh1Id, + cf2prongmcpart::Decay, + cf2prongmcpart::McDecay) using CF2ProngMcPart = CF2ProngMcParts::iterator; } // namespace o2::aod diff --git a/PWGCF/DataModel/FemtoDerived.h b/PWGCF/DataModel/FemtoDerived.h index 4caf0166303..3be2baadc37 100644 --- a/PWGCF/DataModel/FemtoDerived.h +++ b/PWGCF/DataModel/FemtoDerived.h @@ -208,7 +208,8 @@ namespace fdhf enum CharmHadronMassHypo { wrongParticle = 0, lcToPKPi = 1, - lcToPiKP = 2 + lcToPiKP = 2, + dplusToPiKPi = 4 }; DECLARE_SOA_COLUMN(GIndexCol, gIndexCol, int); //! Global index for the collision DECLARE_SOA_COLUMN(TimeStamp, timeStamp, int64_t); //! Timestamp for the collision @@ -227,7 +228,7 @@ DECLARE_SOA_COLUMN(Prong2Eta, prong2Eta, float); //! Track et DECLARE_SOA_COLUMN(Prong0Phi, prong0Phi, float); //! Track phi of charm hadron prong0 DECLARE_SOA_COLUMN(Prong1Phi, prong1Phi, float); //! Track phi of charm hadron prong1 DECLARE_SOA_COLUMN(Prong2Phi, prong2Phi, float); //! Track phi of charm hadron prong2 -DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int8_t); //! Selection of mass hypothesis for charm hadron (1 for Lc -> pkpi, 2 for Lc -> pikp) +DECLARE_SOA_COLUMN(CandidateSelFlag, candidateSelFlag, int8_t); //! Selection of mass hypothesis for charm hadron (1 for Lc -> pkpi, 2 for Lc -> pikp, 4 for D+ -> pikpi) DECLARE_SOA_COLUMN(BDTBkg, bdtBkg, float); //! Background score using Boosted Decision Tree for charm hadron DECLARE_SOA_COLUMN(BDTPrompt, bdtPrompt, float); //! Prompt signal score using Boosted Decision Tree for charm hadron DECLARE_SOA_COLUMN(BDTFD, bdtFD, float); //! Feed-down score using Boosted Decision Tree for charm hadron @@ -312,6 +313,24 @@ DECLARE_SOA_TABLE(FDHfCand, "AOD", "FDHFCAND", //! Table to store the derived da fdhf::Phi, fdhf::Pt); +DECLARE_SOA_TABLE(FDHfPairs, "AOD", "FDHFPAIRS", //! table to store results for HF femtoscopy + fdhf::CharmM, + fdhf::CharmPt, + fdhf::TrkPt, + fdhf::BDTBkg, + fdhf::BDTPrompt, + fdhf::BDTFD, + fdhf::Kstar, + fdhf::KT, + fdhf::MT, + fdhf::Mult, + fdhf::MultPercentile, + fdhf::Charge, + fdhf::PairSign, + fdhf::ProcessType, + fdhf::FlagMc, + fdhf::OriginMcRec); + DECLARE_SOA_TABLE(FDHfCharm, "AOD", "FDHFCHARM", //! table to store results for HF femtoscopy fdhf::GIndexCol, fdhf::TimeStamp, @@ -319,12 +338,13 @@ DECLARE_SOA_TABLE(FDHfCharm, "AOD", "FDHFCHARM", //! table to store results for fdhf::CharmPt, fdhf::CharmEta, fdhf::CharmPhi, + fdhf::Prong0Id, + fdhf::Prong1Id, + fdhf::Prong2Id, fdhf::Charge, fdhf::BDTBkg, fdhf::BDTPrompt, - fdhf::BDTFD, - fdhf::FlagMc, - fdhf::OriginMcRec); + fdhf::BDTFD); DECLARE_SOA_TABLE(FDHfTrk, "AOD", "FDHFTRK", //! table to store results for HF femtoscopy fdhf::GIndexCol, @@ -332,6 +352,7 @@ DECLARE_SOA_TABLE(FDHfTrk, "AOD", "FDHFTRK", //! table to store results for HF f fdhf::TrkPt, fdhf::TrkEta, fdhf::TrkPhi, + fdhf::TrackId, femtodreamparticle::Sign, femtodreamparticle::TPCNClsFound, track::TPCNClsFindable, @@ -353,6 +374,9 @@ DECLARE_SOA_TABLE(FDHfCandMC, "AOD", "FDHFCANDMC", //! Table for reconstructed M DECLARE_SOA_TABLE(FDParticlesIndex, "AOD", "FDPARTICLEINDEX", //! Table track index to match associate particle with charm hadron prongs o2::soa::Index<>, fdhf::TrackId); +DECLARE_SOA_TABLE(FDTrkTimeStamp, "AOD", "FDHFTRKTIMESTAMP", //! Time Stampe of track associate event + o2::soa::Index<>, + fdhf::TimeStamp); DECLARE_SOA_TABLE_STAGED(FDParticles, "FDPARTICLE", o2::soa::Index<>, diff --git a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx index 99ed000b01a..dd212faf22d 100644 --- a/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/MeanptFluctuations.cxx @@ -9,45 +9,53 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" +/// \file MeanptFluctuations.cxx +/// \brief Task for analyzing fluctuation upto fourth order of inclusive hadrons +/// \author Swati Saha -#include "Common/DataModel/EventSelection.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.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/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#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 "TH2D.h" -#include "TH1D.h" #include "TRandom3.h" -#include "TMath.h" -#include "TF1.h" + +#include +#include +#include +#include +#include +#include +#include namespace o2::aod { -namespace ptQn +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(N_ch, n_ch, float); //! no of charged particles/multiplicity 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 ptQn -DECLARE_SOA_TABLE(MultPtQn, "AOD", "PTQN", ptQn::Q1, ptQn::Q2, ptQn::Q3, ptQn::Q4, ptQn::N_ch, ptQn::Centrality); //! table to store e-by-e sum of pT, (pT)^2, (pT)^3, (pT)^4 of tracks, multiplicity and centrality +} // 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; @@ -56,34 +64,84 @@ using namespace o2::framework::expressions; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; -struct MeanptFluctuations_QA_QnTable { +struct MeanptFluctuationsQAQnTable { Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutPreSelEta{"cfgCutPreSelEta", 0.8f, "|eta| cfgCutPreSelPt{"cfgCutPreSelPt", 5.0f, "Maximum allowed pT"}; Configurable cfgCutPtLower{"cfgCutPtLower", 0.2f, "Lower pT cut"}; Configurable cfgCutPtUpper{"cfgCutPtUpper", 3.0f, "Higher pT cut"}; Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; - // Configurable cfgCutTrackDcaXY{"cfgCutTrackDcaXY", 0.2f, "Maximum DcaXY"}; + Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; Configurable cfgCutTrackDcaZ{"cfgCutTrackDcaZ", 2.0f, "Maximum DcaZ"}; - ConfigurableAxis nchAxis{"nchAxis", {5000, 0.5, 5000.5}, ""}; + 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"}; + 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 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"}; + Configurable cfgEvSelkNoTimeFrameBorder{"cfgEvSelkNoTimeFrameBorder", true, "TimeFrame border event selection cut"}; + Configurable cfgCentralityEstimator{"cfgCentralityEstimator", 1, "Centrlaity estimatore choice: 1-->FT0C, 2-->FT0A; 3-->FT0M, 4-->FV0A"}; + + 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; 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") // Filter command*********** Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < 0.8f) && (aod::track::pt > cfgCutPtLower) && (aod::track::pt < 5.0f) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutTpcChi2NCl) && (nabs(aod::track::dcaZ) < cfgCutTrackDcaZ); - // Filter trackFilter = (nabs(aod::track::eta) < 0.8f) && (aod::track::pt > cfgCutPtLower) && (aod::track::pt < 5.0f) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutTpcChi2NCl) && (nabs(aod::track::dcaXY) < cfgCutTrackDcaZ) && (nabs(aod::track::dcaZ) < cfgCutTrackDcaZ); + Filter trackFilter = (nabs(aod::track::eta) < cfgCutPreSelEta) && (aod::track::pt > cfgCutPtLower) && (aod::track::pt < cfgCutPreSelPt) && (requireGlobalTrackInFilter()) && (aod::track::tpcChi2NCl < cfgCutTpcChi2NCl) && (aod::track::itsChi2NCl < cfgCutItsChi2NCl) && (nabs(aod::track::dcaZ) < cfgCutTrackDcaZ); // 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"}; + 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"}; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // filtering collisions and tracks*********** - using aodCollisions = soa::Filtered>; + using AodCollisions = soa::Filtered>; // using aodCollisions = soa::Filtered>; - using aodTracks = soa::Filtered>; + using AodTracks = soa::Filtered>; // Event selection cuts - Alex TF1* fMultPVCutLow = nullptr; @@ -101,14 +159,12 @@ struct MeanptFluctuations_QA_QnTable { // 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.8, 2.0, 2.2, 2.4, 2.8, 3.2, 3.6, 4.}; AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; - std::vector centBining = {0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}; - AxisSpec centAxis = {centBining, "centrality (%)"}; // Add histograms to histogram manager (as in the output object of in AliPhysics) 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}); - histos.add("hPhi", ";#phi", kTH1F, {{100, 0., 2. * M_PI}}); + histos.add("hPhi", ";#phi", kTH1F, {{100, 0., o2::constants::math::TwoPI}}); histos.add("hEta", ";#eta", kTH1F, {{100, -2.01, 2.01}}); histos.add("hCentrality", ";centrality (%)", kTH1F, {{90, 0, 90}}); histos.add("hDcaXY", ";#it{dca}_{XY}", kTH1F, {{1000, -5, 5}}); @@ -116,6 +172,22 @@ struct MeanptFluctuations_QA_QnTable { histos.add("hMeanPt", "", kTProfile, {centAxis}); histos.add("Hist2D_globalTracks_PVTracks", "", {HistType::kTH2D, {nchAxis, nchAxis}}); histos.add("Hist2D_cent_nch", "", {HistType::kTH2D, {nchAxis, centAxis}}); + // before selection + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_PVTracks_beforeSel", "", {HistType::kTH2D, {nchAxis, nchAxis}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_centFT0C_beforeSel", "", {HistType::kTH2D, {centAxis, nchAxis}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_PVTracks_centFT0C_beforeSel", "", {HistType::kTH2D, {centAxis, nchAxis}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_V0ATracks_beforeSel", "", {HistType::kTH2D, {nchAxis3, nchAxis}}); + histos.add("MultCorrelationPlots/BeforeSelection/His2D_globalTracks_T0ATracks_beforeSel", "", {HistType::kTH2D, {nchAxis2, nchAxis}}); + 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, {nchAxis, nchAxis}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_centFT0C_afterSel", "", {HistType::kTH2D, {centAxis, nchAxis}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_PVTracks_centFT0C_afterSel", "", {HistType::kTH2D, {centAxis, nchAxis}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_V0ATracks_afterSel", "", {HistType::kTH2D, {nchAxis3, nchAxis}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_globalTracks_T0ATracks_afterSel", "", {HistType::kTH2D, {nchAxis2, nchAxis}}); + histos.add("MultCorrelationPlots/AfterSelection/His2D_V0ATracks_T0CTracks_afterSel", "", {HistType::kTH2D, {nchAxis2, nchAxis3}}); + } // Event selection - Alex if (cfgUse22sEventCut) { @@ -132,6 +204,33 @@ struct MeanptFluctuations_QA_QnTable { fMultMultPVCut->SetParameters(-0.1, 0.785, -4.7e-05); } + 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); + } + } //! end init function template @@ -144,8 +243,10 @@ struct MeanptFluctuations_QA_QnTable { float vtxz = -999; if (collision.numContrib() > 1) { vtxz = collision.posZ(); - float zRes = TMath::Sqrt(collision.covZZ()); - if (zRes > 0.25 && collision.numContrib() < 20) + float zRes = std::sqrt(collision.covZZ()); + float zResMax = 0.25; + float numContribMin = 20; + if (zRes > zResMax && collision.numContrib() < numContribMin) vtxz = -999; } auto multNTracksPV = collision.multNTracksPV(); @@ -166,35 +267,135 @@ struct MeanptFluctuations_QA_QnTable { return 1; } - Produces mult_ptQn; + 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; + } + + Produces multPtQn; // void process(aod::Collision const& coll, aod::Tracks const& inputTracks) - void process(aodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, aodTracks const& inputTracks) + void process(AodCollisions::iterator const& coll, aod::BCsWithTimestamps const&, AodTracks const& inputTracks) { - if (!coll.sel8()) + if (!coll.sel8()) { + return; + } + if (cfgUseGoodITSLayerAllCut && !(coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { return; + } + if (cfgEvSelkNoSameBunchPileup && !(coll.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { + return; + } + if (cfgEvSelkNoITSROFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + return; + } + if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { + return; + } + + 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()); - const auto CentralityFT0C = coll.centFT0C(); - if (cfgUse22sEventCut && !eventSelected(coll, inputTracks.size(), CentralityFT0C)) + const auto centralityFT0C = coll.centFT0C(); + if (cfgUse22sEventCut && !eventSelected(coll, inputTracks.size(), centralityFT0C)) + return; + if (cfgUseSmallIonAdditionalEventCut && !eventSelectedSmallion(coll, inputTracks.size(), centralityFT0C)) 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()); + } + histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); - histos.fill(HIST("hCentrality"), coll.centFT0C()); + + double cent = 0.0; + int centChoiceFT0C = 1; + int centChoiceFT0A = 2; + int centChoiceFT0M = 3; + int centChoiceFV0A = 4; + if (cfgCentralityEstimator == centChoiceFT0C) + cent = coll.centFT0C(); + else if (cfgCentralityEstimator == centChoiceFT0A) + cent = coll.centFT0A(); + else if (cfgCentralityEstimator == centChoiceFT0M) + cent = coll.centFT0M(); + else if (cfgCentralityEstimator == centChoiceFV0A) + cent = coll.centFV0A(); + + histos.fill(HIST("hCentrality"), cent); + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), inputTracks.size()); - histos.fill(HIST("Hist2D_cent_nch"), inputTracks.size(), CentralityFT0C); + histos.fill(HIST("Hist2D_cent_nch"), inputTracks.size(), centralityFT0C); // variables - double cent = coll.centFT0C(); - double pT_sum = 0.0; - double N = 0.0; + 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 n_ch = 0.0; + float nCh = 0.0; - for (auto track : inputTracks) { // Loop over tracks + for (const auto& track : inputTracks) { // Loop over tracks + + if (!track.has_collision()) { + continue; + } + + if (!track.isPVContributor()) { + continue; + } + + if (!(track.itsNCls() > cfgITScluster) || !(track.tpcNClsFound() >= cfgTPCcluster) || !(track.tpcNClsCrossedRows() >= cfgTPCnCrossedRows)) { + continue; + } histos.fill(HIST("hP"), track.p()); histos.fill(HIST("hPt"), track.pt()); @@ -203,44 +404,45 @@ struct MeanptFluctuations_QA_QnTable { histos.fill(HIST("hDcaXY"), track.dcaXY()); histos.fill(HIST("hDcaZ"), track.dcaZ()); - pT_sum += track.pt(); - N += 1.0; + pTsum += track.pt(); + nN += 1.0; float pT = track.pt(); - // calculating Q1, Q2, Q3, Q4. N_ch + // calculating Q1, Q2, Q3, Q4. Nch if (track.pt() > cfgCutPtLower && track.pt() < cfgCutPtUpper && track.sign() != 0) { - q1 = q1 + pow(pT, 1.0); - q2 = q2 + pow(pT, 2.0); - q3 = q3 + pow(pT, 3.0); - q4 = q4 + pow(pT, 4.0); - n_ch = n_ch + 1; + 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; } } - mult_ptQn(q1, q2, q3, q4, n_ch, cent); + multPtQn(q1, q2, q3, q4, nCh, cent); // MeanPt - if (N > 0.0f) - histos.fill(HIST("hMeanPt"), cent, pT_sum / N); + if (nN > 0.0f) + histos.fill(HIST("hMeanPt"), cent, pTsum / nN); } }; -struct MeanptFluctuations_analysis { +struct MeanptFluctuationsAnalysis { - Configurable cfgNSubsample{"cfgNSubsample", 10, "Number of subsamples"}; + 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}, ""}; - expressions::Filter Nch_filter = aod::ptQn::n_ch > 3.0f; + float minNch = 3.0f; + expressions::Filter nchFilter = aod::pt_qn::nch > minNch; using FilteredMultPtQn = soa::Filtered; // 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"}; + 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; + std::vector>> subSample; TRandom3* fRndm = new TRandom3(0); void init(o2::framework::InitContext&) @@ -256,49 +458,49 @@ struct MeanptFluctuations_analysis { 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); + 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}})); + 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 mean_term1; - float variance_term1; - float skewness_term1; - float kurtosis_term1; + 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.n_ch(), event_ptqn.q1(), event_ptqn.q2()); + // LOGF(info, "Centrality= %f Nch= %f Q1= %f Q2= %f", event_ptqn.centrality(), event_ptqn.nch(), event_ptqn.q1(), event_ptqn.q2()); // calculating observables - mean_term1 = event_ptqn.q1() / event_ptqn.n_ch(); - variance_term1 = (TMath::Power(event_ptqn.q1(), 2.0f) - event_ptqn.q2()) / (event_ptqn.n_ch() * (event_ptqn.n_ch() - 1.0f)); - skewness_term1 = (TMath::Power(event_ptqn.q1(), 3.0f) - 3.0f * event_ptqn.q2() * event_ptqn.q1() + 2.0f * event_ptqn.q3()) / (event_ptqn.n_ch() * (event_ptqn.n_ch() - 1.0f) * (event_ptqn.n_ch() - 2.0f)); - kurtosis_term1 = (TMath::Power(event_ptqn.q1(), 4.0f) - (6.0f * event_ptqn.q4()) + (8.0f * event_ptqn.q1() * event_ptqn.q3()) - (6.0f * TMath::Power(event_ptqn.q1(), 2.0f) * event_ptqn.q2()) + (3.0f * TMath::Power(event_ptqn.q2(), 2.0f))) / (event_ptqn.n_ch() * (event_ptqn.n_ch() - 1.0f) * (event_ptqn.n_ch() - 2.0f) * (event_ptqn.n_ch() - 3.0f)); + 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.n_ch(), mean_term1); - registry.get(HIST("Prof_var_t1"))->Fill(event_ptqn.centrality(), event_ptqn.n_ch(), variance_term1); - registry.get(HIST("Prof_skew_t1"))->Fill(event_ptqn.centrality(), event_ptqn.n_ch(), skewness_term1); - registry.get(HIST("Prof_kurt_t1"))->Fill(event_ptqn.centrality(), event_ptqn.n_ch(), kurtosis_term1); - registry.fill(HIST("Hist2D_Nch_centrality"), event_ptqn.centrality(), event_ptqn.n_ch()); - registry.fill(HIST("Hist2D_meanpt_centrality"), event_ptqn.centrality(), mean_term1); + 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 l_Random = fRndm->Rndm(); - int SampleIndex = static_cast(cfgNSubsample * l_Random); - Subsample[SampleIndex][0]->Fill(event_ptqn.centrality(), event_ptqn.n_ch(), mean_term1); - Subsample[SampleIndex][1]->Fill(event_ptqn.centrality(), event_ptqn.n_ch(), variance_term1); - Subsample[SampleIndex][2]->Fill(event_ptqn.centrality(), event_ptqn.n_ch(), skewness_term1); - Subsample[SampleIndex][3]->Fill(event_ptqn.centrality(), event_ptqn.n_ch(), kurtosis_term1); + 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); } }; @@ -306,7 +508,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { // Equivalent to the AddTask in AliPhysics return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; } diff --git a/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx index 8598d18e2cd..216ce8ffc00 100644 --- a/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/eventMeanPtId.cxx @@ -91,7 +91,7 @@ struct EventMeanPtId { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; TH2D* ptHistogramAllchargeRec = nullptr; - + Configurable ptMax{"ptMax", 2.0, "maximum pT"}; Configurable ptMin{"ptMin", 0.15, "minimum pT"}; Configurable> ptBins{"ptBins", {0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20, 1.25, 1.30, 1.35, 1.40, 1.45, 1.50, 1.55, 1.60, 1.65, 1.70, 1.75, 1.80, 1.85, 1.90, 1.95, 2.00}, "p_{T} bins"}; @@ -109,7 +109,7 @@ struct EventMeanPtId { TList* lst = ccdb->getForTimeStamp(cfgPathCCDB.value, -1); ptHistogramAllchargeRec = reinterpret_cast(lst->FindObject("hPtEta_rec")); - } + } 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})"}; @@ -126,7 +126,7 @@ struct EventMeanPtId { AxisSpec nSigmaTOFAxispid = {170, -8.5, 8.5, "n#sigma_{TOF}"}; AxisSpec centAxis = {100, 0., 100., "centrality"}; AxisSpec subAxis = {30, 0., 30., "sample"}; - //AxisSpec nchAxis = {4000, 0., 4000., "nch"}; + // AxisSpec nchAxis = {4000, 0., 4000., "nch"}; AxisSpec nchAxis = {nchBins, nchMin, nchMax, "nch"}; AxisSpec varAxis1 = {400, 0., 4., "var1"}; AxisSpec varAxis2 = {400, 0., 4., "var2"}; @@ -243,10 +243,10 @@ struct EventMeanPtId { histos.add("Data/hITSchi2perCluster_after", "ITS #Chi^{2}/Cluster", kTH1D, {chi2Axis}); histos.add("Data/hTPCCrossedrows_after", "Crossed TPC rows", kTH1D, {crossedRowTpcAxis}); histos.add("Data/hcent_nacc", "hcent_nacc", kTH2D, {centAxis, nchAxis}); - + histos.addClone("Data/", "Rec/"); // rec histograms - histos.add("hcent_nacc_corr", "hcent_nacc_corr", kTH2D, {centAxis, nchAxis}); + histos.add("hcent_nacc_corr", "hcent_nacc_corr", kTH2D, {centAxis, nchAxis}); histos.add("NSigamaTPCpion_rec", "NSigamaTPCpion_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); histos.add("NSigamaTPCkaon_rec", "NSigamaTPCkaon_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); histos.add("NSigamaTPCproton_rec", "NSigamaTPCproton_rec", kTH2D, {pAxis, nSigmaTPCAxispid}); @@ -361,7 +361,7 @@ struct EventMeanPtId { histos.add("hEffVar2x_data", "hEffVar2x_data", kTH2D, {subAxis, nchAxis}); histos.add("hEffVarx_data", "hEffVarx_data", kTH2D, {subAxis, nchAxis}); histos.add("hEffVar2Meanptx_data", "hEffVar2Meanptx_data", kTH2D, {nchAxis, varAxis2}); - } + } // Configurables Configurable cVtxZcut{"cVtxZcut", 10.f, "Vertex Z"}; @@ -474,7 +474,9 @@ struct EventMeanPtId { // if (std::fabs(track.dcaXY()) > cDcaXYcut) {return false;} histos.fill(HIST("tracksel"), 3); - if (std::fabs(track.dcaZ()) > cDcaZcut) {return false;} + if (std::fabs(track.dcaZ()) > cDcaZcut) { + return false; + } histos.fill(HIST("tracksel"), 4); if (std::fabs(track.eta()) >= cEtacut) { @@ -490,26 +492,36 @@ struct EventMeanPtId { } histos.fill(HIST("tracksel"), 6); - if (track.tpcNClsCrossedRows() < cTPCcrosscut) {return false;} + if (track.tpcNClsCrossedRows() < cTPCcrosscut) { + return false; + } histos.fill(HIST("tracksel"), 7); - if (track.itsChi2NCl() > cItsChiCut) {return false;} + if (track.itsChi2NCl() > cItsChiCut) { + return false; + } histos.fill(HIST("tracksel"), 8); - if (track.tpcChi2NCl() > cTpcChiCut) {return false;} + if (track.tpcChi2NCl() > cTpcChiCut) { + return false; + } histos.fill(HIST("tracksel"), 9); if (track.sign() == 0) return false; if (citsNCluster) { - if (track.itsNCls() < cnITSClustersCut) { return false; } - histos.fill(HIST("tracksel"), 10); + if (track.itsNCls() < cnITSClustersCut) { + return false; + } + histos.fill(HIST("tracksel"), 10); } - if(ctpcNClusterFound) { - if (track.tpcNClsFound() < ctpcNClsCut) {return false;} - histos.fill(HIST("tracksel"), 11); + if (ctpcNClusterFound) { + if (track.tpcNClsFound() < ctpcNClsCut) { + return false; + } + histos.fill(HIST("tracksel"), 11); } return true; // if all checks pass, accept the collision @@ -605,21 +617,21 @@ struct EventMeanPtId { return false; } - double getEfficiency(double pt, double eta, TH2D* ptHistogramAllchargeRec) + double getEfficiency(double pt, double eta, TH2D* ptHistogramAllchargeRec) { - int xbin = ptHistogramAllchargeRec->GetXaxis()->FindBin(pt); - int ybin = ptHistogramAllchargeRec->GetYaxis()->FindBin(eta); + int xbin = ptHistogramAllchargeRec->GetXaxis()->FindBin(pt); + int ybin = ptHistogramAllchargeRec->GetYaxis()->FindBin(eta); - if(xbin < 1 || xbin > ptHistogramAllchargeRec->GetNbinsX() || ybin < 1 || ybin > ptHistogramAllchargeRec->GetNbinsY()) { + if (xbin < 1 || xbin > ptHistogramAllchargeRec->GetNbinsX() || ybin < 1 || ybin > ptHistogramAllchargeRec->GetNbinsY()) { LOGF(warn, "pt or eta out of histograms bounds : %f, eta = %f", pt, eta); return 1e-6; - } - double eff = ptHistogramAllchargeRec->GetBinContent(xbin, ybin); - return (eff > 0) ? eff : 1e-6; // Avoid division by zero + } + double eff = ptHistogramAllchargeRec->GetBinContent(xbin, ybin); + return (eff > 0) ? eff : 1e-6; // Avoid division by zero } - //++++++++++++++++++++++++++++++++++++DATA CALCULATION +++++++++++++++++++++++++++++++++++++++++++++++++++++// - void processData(aod::MyCollision const& coll, aod::MyTracks const& inputTracks) + //++++++++++++++++++++++++++++++++++++DATA CALCULATION +++++++++++++++++++++++++++++++++++++++++++++++++++++// + void processData(aod::MyCollision const& coll, aod::MyTracks const& inputTracks) { histos.fill(HIST("hEventcounter"), 1.); histos.fill(HIST("Data/hZvtx_before_sel"), coll.posZ()); @@ -633,11 +645,11 @@ struct EventMeanPtId { const auto cent = coll.centFT0C(); histos.fill(HIST("Data/hCentrality"), cent); - double nchAll = 0., nchAllBfCut = 0., nchEta = 0., nchPt = 0., nch = 0., nchPi = 0., nchKa = 0., nchPr = 0.; + double nchAll = 0., nchAllBfCut = 0., nchEta = 0., nchPt = 0., nch = 0., nchPi = 0., nchKa = 0., nchPr = 0.; double q1 = 0., q2 = 0., var1 = 0., var2 = 0.; double sumPtWeight = 0., sumWeight = 0., sumPtPtWeight = 0., var1Eff = 0., var2Eff = 0.; double q1Pi = 0., q2Pi = 0., var1Pi = 0., var2Pi = 0.; - double q1Ka = 0., q2Ka = 0., var1Ka = 0., var2Ka = 0.; + double q1Ka = 0., q2Ka = 0., var1Ka = 0., var2Ka = 0.; double q1Pr = 0., q2Pr = 0., var1Pr = 0., var2Pr = 0.; int sample = histos.get(HIST("Data/hZvtx_after_sel8"))->GetEntries(); @@ -650,7 +662,7 @@ struct EventMeanPtId { histos.fill(HIST("Data/hTPCchi2perCluster_before"), track.tpcChi2NCl()); histos.fill(HIST("Data/hITSchi2perCluster_before"), track.itsChi2NCl()); histos.fill(HIST("Data/hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); - + if (std::fabs(track.eta()) <= cEtacut) { nchEta++; histos.fill(HIST("Data/hnchTrue"), nchEta); @@ -662,8 +674,8 @@ struct EventMeanPtId { if (track.sign() == 0) continue; if (!selTrack(track)) - continue; - + continue; + nchAll += 1.; q1 += track.pt(); q2 += (track.pt() * track.pt()); @@ -683,10 +695,10 @@ struct EventMeanPtId { histos.fill(HIST("Data/hPEta"), track.p(), track.eta()); histos.fill(HIST("Data/hNsigmaTPC"), track.p(), track.tpcNSigmaPr()); - double eff = getEfficiency(track.pt(), track.eta(), ptHistogramAllchargeRec); + double eff = getEfficiency(track.pt(), track.eta(), ptHistogramAllchargeRec); if (eff < threshold) - continue; - double weight = 1./eff; + continue; + double weight = 1. / eff; sumPtWeight += track.pt() / eff; sumPtPtWeight += (track.pt() * track.pt()) / (eff * eff); sumWeight += weight; @@ -779,19 +791,19 @@ struct EventMeanPtId { histos.fill(HIST("Data/hdEdx_afterselection1"), track.p(), track.tpcSignal()); histos.fill(HIST("Data/hTOFbeta_afterselection1"), track.p(), track.beta()); } - + } // Track loop ends! histos.fill(HIST("Data/hcent_nacc"), cent, nchAll); - if (nchAll < cTwoPtlCut2) + if (nchAll < cTwoPtlCut2) return; var1 = (q1 * q1 - q2) / (nchAll * (nchAll - 1)); var2 = (q1 / nchAll); - - //------------------ Efficiency corrected histograms --------------- + + //------------------ Efficiency corrected histograms --------------- var1Eff = (sumPtWeight * sumPtWeight - sumPtPtWeight) / (sumWeight * (sumWeight - 1)); var2Eff = (sumPtWeight / sumWeight); - + //---------------------- pions ---------------------------------------- if (nchPi >= cTwoPtlCut2) { var1Pi = (q1Pi * q1Pi - q2Pi) / (nchPi * (nchPi - 1)); @@ -807,8 +819,8 @@ struct EventMeanPtId { var1Pr = (q1Pr * q1Pr - q2Pr) / (nchPr * (nchPr - 1)); var2Pr = (q1Pr / nchPr); } - - //------------------ all charges------------------------------------- + + //------------------ all charges------------------------------------- histos.fill(HIST("Data/hVar1"), sample, cent, var1); histos.fill(HIST("Data/hVar2"), sample, cent, var2); histos.fill(HIST("Data/hVarc"), sample, cent); @@ -823,12 +835,12 @@ struct EventMeanPtId { histos.fill(HIST("Data/hVar2p"), sample, cent, var2Pr); histos.fill(HIST("Data/hVar2meanptp"), cent, var2Pr); - //-----------------------nch------------------------------------- + //-----------------------nch------------------------------------- histos.fill(HIST("Data/hVar1x"), sample, nchAll, var1); histos.fill(HIST("Data/hVar2x"), sample, nchAll, var2); histos.fill(HIST("Data/hVarx"), sample, nchAll); histos.fill(HIST("Data/hVar2meanptx"), nchAll, var2); - + histos.fill(HIST("hEffVar1x_data"), sample, nchAll, var1Eff); histos.fill(HIST("hEffVar2x_data"), sample, nchAll, var2Eff); histos.fill(HIST("hEffVarx_data"), sample, nchAll); @@ -860,7 +872,7 @@ struct EventMeanPtId { } // event loop ends! PROCESS_SWITCH(EventMeanPtId, processData, "process real data information", false); - + //++++++++++++++++++++++++++++++++++++MC Reconstructed +++++++++++++++++++++++++++++++++++++++++++++++++++++// SliceCache cache; @@ -874,12 +886,12 @@ struct EventMeanPtId { histos.fill(HIST("Rec/hZvtx_before_sel"), coll.posZ()); histos.fill(HIST("hVtxZ_before_gen"), coll.mcCollision().posZ()); - if (!selCollision(coll))//add + if (!selCollision(coll)) // add return; float cent = coll.centFT0C(); histos.fill(HIST("Rec/hZvtx_after_sel8"), coll.posZ()); - histos.fill(HIST("Rec/hCentrality"), cent); + histos.fill(HIST("Rec/hCentrality"), cent); double nch = 0., nchPi = 0., nchKa = 0., nchPr = 0., nchAll = 0., nchAllBfCut = 0., nchEta = 0., nchPt = 0.; double q1 = 0., q2 = 0.; @@ -887,7 +899,7 @@ struct EventMeanPtId { double var1 = 0., var2 = 0.; double var1Pi = 0., var2Pi = 0., var1Ka = 0., var2Ka = 0., var1Pr = 0., var2Pr = 0.; double sumPtWeight = 0., sumWeight = 0., sumPtPtWeight = 0., var1Eff = 0., var2Eff = 0.; - + int sample = histos.get(HIST("Rec/hZvtx_after_sel8"))->GetEntries(); sample = sample % 30; @@ -907,21 +919,21 @@ struct EventMeanPtId { histos.fill(HIST("Rec/hnchTrue_pt"), nchPt); } if (!selTrack(track)) - continue; + continue; // if (std::fabs(track.y()) > 0.5) continue; histos.fill(HIST("hPt_rec"), track.pt()); histos.fill(HIST("hEta_rec"), track.eta()); - + double eff = getEfficiency(track.pt(), track.eta(), ptHistogramAllchargeRec); - if (eff < threshold) + if (eff < threshold) continue; double weight = 1.0 / eff; sumPtWeight += track.pt() * weight; sumPtPtWeight += (track.pt() * track.pt() * weight * weight); sumWeight += weight; - - histos.fill(HIST("hPt_rec_corr"), track.pt() , weight); - histos.fill(HIST("hEta_rec_corr"), track.eta() , weight); + + histos.fill(HIST("hPt_rec_corr"), track.pt(), weight); + histos.fill(HIST("hEta_rec_corr"), track.eta(), weight); auto mcParticle = track.mcParticle(); nchAll += 1.; @@ -996,7 +1008,7 @@ struct EventMeanPtId { if (track.beta() > 1) continue; histos.fill(HIST("ptHistogramPionrec"), track.pt()); - histos.fill(HIST("hPtEta_pi_rec"), track.pt(), track.eta()); + histos.fill(HIST("hPtEta_pi_rec"), track.pt(), track.eta()); histos.fill(HIST("Rec/hPtPion"), track.pt()); histos.fill(HIST("Rec/hEtaPion"), track.eta()); histos.fill(HIST("Rec/hyPion"), track.rapidity(massPi)); @@ -1013,8 +1025,8 @@ struct EventMeanPtId { q1Pi += track.pt(); q2Pi += (track.pt() * track.pt()); - histos.fill(HIST("hPyPion_rec"), track.p(), track.rapidity(massPi)); - histos.fill(HIST("hPtyPion_rec"), track.pt(), track.rapidity(massPi)); + histos.fill(HIST("hPyPion_rec"), track.p(), track.rapidity(massPi)); + histos.fill(HIST("hPtyPion_rec"), track.pt(), track.rapidity(massPi)); } //===========================kaon=============================================================== @@ -1031,7 +1043,7 @@ struct EventMeanPtId { if (track.beta() > 1) continue; histos.fill(HIST("ptHistogramKaonrec"), track.pt()); - histos.fill(HIST("hPtEta_ka_rec"), track.pt(), track.eta()); + histos.fill(HIST("hPtEta_ka_rec"), track.pt(), track.eta()); histos.fill(HIST("Rec/hPtKaon"), track.pt()); histos.fill(HIST("Rec/hEtaKaon"), track.eta()); histos.fill(HIST("Rec/hyKaon"), track.rapidity(massKa)); @@ -1066,7 +1078,7 @@ struct EventMeanPtId { if (track.beta() > 1) continue; histos.fill(HIST("ptHistogramProtonrec"), track.pt()); - histos.fill(HIST("hPtEta_pr_rec"), track.pt(), track.eta()); + histos.fill(HIST("hPtEta_pr_rec"), track.pt(), track.eta()); histos.fill(HIST("Rec/hPtProton"), track.pt()); histos.fill(HIST("Rec/hEtaProton"), track.eta()); histos.fill(HIST("Rec/hyProton"), track.rapidity(massPr)); @@ -1106,7 +1118,7 @@ struct EventMeanPtId { histos.fill(HIST("Rec/hVar2"), sample, cent, var2); histos.fill(HIST("Rec/hVarc"), sample, cent); histos.fill(HIST("Rec/hVar2meanpt"), cent, var2); - + //---------------------- pions ---------------------------------------- if (nchPi >= cTwoPtlCut2) { var1Pi = (q1Pi * q1Pi - q2Pi) / (nchPi * (nchPi - 1)); @@ -1116,8 +1128,7 @@ struct EventMeanPtId { if (nchKa >= cTwoPtlCut2) { var1Ka = (q1Ka * q1Ka - q2Ka) / (nchKa * (nchKa - 1)); var2Ka = (q1Ka / nchKa); - - } + } //---------------------------- protons ---------------------------------- if (nchPr >= cTwoPtlCut2) { var1Pr = (q1Pr * q1Pr - q2Pr) / (nchPr * (nchPr - 1)); @@ -1164,7 +1175,6 @@ struct EventMeanPtId { histos.fill(HIST("hEffVar2x_Naccorr_xaxis_rec"), sample, sumWeight, var2); histos.fill(HIST("hEffVarx_Naccorr_xaxis_rec"), sample, sumWeight); - //================= generated level============================== const auto& mccolgen = coll.mcCollision_as(); @@ -1226,7 +1236,7 @@ struct EventMeanPtId { if (mcpart.pdgCode() == PDG_t::kPiPlus || mcpart.pdgCode() == PDG_t::kPiMinus) { histos.fill(HIST("ptHistogramPion"), mcpart.pt()); - histos.fill(HIST("hPtEta_pi_gen"), mcpart.pt(), mcpart.eta()); + histos.fill(HIST("hPtEta_pi_gen"), mcpart.pt(), mcpart.eta()); histos.fill(HIST("hPty_pi_gen"), mcpart.pt(), mcpart.y()); nchPiGen += 1.; q1PiGen += mcpart.pt(); @@ -1236,8 +1246,8 @@ struct EventMeanPtId { if (mcpart.pdgCode() == PDG_t::kKPlus || mcpart.pdgCode() == PDG_t::kKMinus) { histos.fill(HIST("ptHistogramKaon"), mcpart.pt()); - histos.fill(HIST("hPtEta_ka_gen"), mcpart.pt(), mcpart.eta()); - histos.fill(HIST("hPty_ka_gen"), mcpart.pt(), mcpart.y()); + histos.fill(HIST("hPtEta_ka_gen"), mcpart.pt(), mcpart.eta()); + histos.fill(HIST("hPty_ka_gen"), mcpart.pt(), mcpart.y()); nchKaGen += 1.; q1KaGen += mcpart.pt(); q2KaGen += (mcpart.pt() * mcpart.pt()); @@ -1246,8 +1256,8 @@ struct EventMeanPtId { if (mcpart.pdgCode() == PDG_t::kProton || mcpart.pdgCode() == PDG_t::kProtonBar) { histos.fill(HIST("ptHistogramProton"), mcpart.pt()); - histos.fill(HIST("hPtEta_pr_gen"), mcpart.pt(), mcpart.eta()); - histos.fill(HIST("hPty_pr_gen"), mcpart.pt(), mcpart.y()); + histos.fill(HIST("hPtEta_pr_gen"), mcpart.pt(), mcpart.eta()); + histos.fill(HIST("hPty_pr_gen"), mcpart.pt(), mcpart.y()); nchPrGen += 1.; q1PrGen += mcpart.pt(); q2PrGen += (mcpart.pt() * mcpart.pt()); @@ -1268,8 +1278,7 @@ struct EventMeanPtId { histos.fill(HIST("hVar2_gen"), sampleGen, cent, var2AllGen); histos.fill(HIST("hVarc_gen"), sampleGen, cent); - -//--------------------------Pions------------------------------------------- + //--------------------------Pions------------------------------------------- if (nchPiGen >= cTwoPtlCut2) { var1PiGen = (q1PiGen * q1PiGen - q2PiGen) / (nchPiGen * (nchPiGen - 1)); var2PiGen = (q1PiGen / nchPiGen); @@ -1304,11 +1313,11 @@ struct EventMeanPtId { } // void process PROCESS_SWITCH(EventMeanPtId, processMcReco, "Process reconstructed", true); - - }; +}; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; return workflow; } + \ No newline at end of file diff --git a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx index c2b1a3d71ab..d6eca57ad0e 100644 --- a/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/meanPtFlucId.cxx @@ -45,92 +45,120 @@ using namespace std; struct MeanPtFlucId { Configurable nPBins{"nPBins", 300, ""}; - Configurable nPartBins{"nPartBins", 250, ""}; - Configurable nCentBins{"nCentBins", 101, ""}; - Configurable nRapBins{"nRapBins", 100, ""}; + Configurable nPartBins{"nPartBins", 100, ""}; Configurable nPhiBins{"nPhiBins", 100, ""}; - Configurable cfgCutPtMax{"cfgCutPtMax", 3.0, "maximum pT"}; - Configurable cfgCutPtMin{"cfgCutPtMin", 0.15, "minimum pT"}; + Configurable cfgCutPtMax{"cfgCutPtMax", 2.0, "maximum pT"}; + Configurable cfgCutPtMin{"cfgCutPtMin", 0.2, "minimum pT"}; Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut"}; Configurable cfgCutRap{"cfgCutRap", 0.5, "Rapidity Cut"}; - Configurable cfgCutDcaZ{"cfgCutDcaZ", 0.3, "DCAz cut"}; - Configurable cfgCutPosZ{"cfgCutPosZ", 10.0, "cut for vertex Z"}; - Configurable cfgCutNSig2{"cfgCutNSig2", 2.0, "nSigma cut (2)"}; - Configurable cfgCutNSig3{"cfgCutNSig3", 3.0, "nSigma cut (3)"}; + Configurable cfgCutDcaZ{"cfgCutDcaZ", 0.15, "DCAz cut"}; + Configurable cfgCutPosZ{"cfgCutPosZ", 7.0, "cut for vertex Z"}; + Configurable cfgPosZ{"cfgPosZ", true, "Position Z"}; + Configurable cfgCutNSig2{"cfgCutNSig2", 2.0, "nSigma cut: 2"}; + Configurable cfgCutNSig3{"cfgCutNSig3", 3.0, "nSigma cut: 3"}; + Configurable cfgCutNSig5{"cfgCutNSig5", 5.0, "nSigma cut: 5"}; + Configurable cfgSelCutNSigPi{"cfgSelCutNSigPi", 2.0, "nSigma cut for pion selection"}; + Configurable cfgSelCutNSigKa{"cfgSelCutNSigKa", 3.0, "nSigma cut for kaon selection"}; + Configurable cfgSelCutNSigPr{"cfgSelCutNSigPr", 2.0, "nSigma cut for proton selection"}; + Configurable cfgRejCutNSigPi{"cfgRejCutNSigPi", 3.0, "nSigma cut for rejection of other particles while selecting pion"}; Configurable cfgCutPiPtMin{"cfgCutPiPtMin", 0.2, "Minimum pion p_{T} cut"}; Configurable cfgCutKaPtMin{"cfgCutKaPtMin", 0.3, "Minimum kaon p_{T} cut"}; Configurable cfgCutPrPtMin{"cfgCutPrPtMin", 0.5, "Minimum proton p_{T} cut"}; Configurable cfgCutPiThrsldP{"cfgCutPiThrsldP", 0.6, "Threshold p cut pion"}; Configurable cfgCutKaThrsldP{"cfgCutKaThrsldP", 0.6, "Threshold p cut kaon"}; Configurable cfgCutPrThrsldP{"cfgCutPrThrsldP", 1.0, "Threshold p cut proton "}; - Configurable cfgCutPiP1{"cfgCutPiP1", 0.5, "pion p cut-1"}; - Configurable cfgCutPiP2{"cfgCutPiP2", 0.6, "pion p cut-2"}; - Configurable cfgCutKaP1{"cfgCutKaP1", 0.4, "kaon p cut-1"}; - Configurable cfgCutKaP2{"cfgCutKaP2", 0.6, "kaon p cut-2"}; - Configurable cfgCutKaP3{"cfgCutKaP3", 1.2, "kaon p cut-3"}; - Configurable cfgCutPrP1{"cfgCutPrP1", 0.9, "proton p cut-1"}; - Configurable cfgCutPrP2{"cfgCutPrP2", 1.0, "proton p cut-2"}; - Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency"}; - Configurable cfgWeightPtCh{"cfgWeightPtCh", true, "Efficiency correction (pT) for charged particles"}; - Configurable cfgWeightPtId{"cfgWeightPtId", false, "Efficiency correction (pT) "}; - Configurable cfgWeightPtYId{"cfgWeightPtYId", false, "Efficiency correction (pT, rap) "}; - Configurable cfgWeightPtEtaId{"cfgWeightPtEtaId", true, "Efficiency correction (pT, Eta) "}; - Configurable cfgPurityId{"cfgPurityId", false, "Purity correction"}; - Configurable cfgMCReco{"cfgMCReco", false, ""}; - Configurable cfgMCTruth{"cfgMCTruth", false, ""}; - Configurable cfgPosZ{"cfgPosZ", true, "Position Z"}; Configurable cfgSel8{"cfgSel8", true, "Sel8 trigger"}; + Configurable cfgMinWeight{"cfgMinWeight", 1e-6, "Minimum weight for efficiency correction"}; Configurable cfgNoSameBunchPileup{"cfgNoSameBunchPileup", true, "kNoSameBunchPileup"}; Configurable cfgIsVertexITSTPC{"cfgIsVertexITSTPC", true, "kIsVertexITSTPC"}; Configurable cfgRejTrk{"cfgRejTrk", true, "Rejected Tracks"}; + Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency"}; + Configurable cfgCorrection{"cfgCorrection", true, "Correction"}; + Configurable cfgWeightPtCh{"cfgWeightPtCh", true, "Efficiency correction (pT) for charged particles"}; + Configurable cfgWeightPtId{"cfgWeightPtId", false, "Efficiency correction (pT) "}; + Configurable cfgWeightPtEtaId{"cfgWeightPtEtaId", false, "Efficiency correction (pT) "}; + Configurable cfgPurityId{"cfgPurityId", false, "Purity correction"}; ConfigurableAxis multTPCBins{"multTPCBins", {150, 0, 150}, "TPC Multiplicity bins"}; ConfigurableAxis multFT0MBins{"multFT0MBins", {1000, 0, 5000}, "Forward Multiplicity bins"}; - ConfigurableAxis multFT0MMCBins{"multFT0MMCBins", {250, 0, 250}, "Forward Multiplicity bins"}; - ConfigurableAxis dcaXYBins{"dcaXYBins", {100, -0.15, 0.15}, "dcaXY bins"}; - ConfigurableAxis dcaZBins{"dcaZBins", {100, -1.2, 1.2}, "dcaZ bins"}; ConfigurableAxis qNBins{"qNBins", {1000, 0., 100.}, "nth moments bins"}; - ConfigurableAxis tpNBins{"tpNBins", {300, 0., 3000.}, ""}; - ConfigurableAxis tpDBins{"tpDBins", {100, 0., 2000.}, ""}; + ConfigurableAxis nPairBins{"nPairBins", {2000, 0, 10000}, "nPair bins"}; + ConfigurableAxis dcaXYBins{"dcaXYBins", {100, -0.15, 0.15}, "dcaXY bins"}; + ConfigurableAxis dcaZBins{"dcaZBins", {500, -1.2, 1.2}, "dcaZ bins"}; + Configurable> ptBins{"ptBins", {0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.05, 1.10, 1.15, 1.20, 1.25, 1.30, 1.35, 1.40, 1.45, 1.50, 1.55, 1.60, 1.65, 1.70, 1.75, 1.80, 1.85, 1.90, 1.95, 2.00}, "p_{T} bins"}; Configurable> etaBins{"etaBins", {-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.15, -0.1, -0.05, 0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8}, "#eta bins"}; - Configurable> rapBins{"rapBins", {-0.6, -0.55, -0.5, -0.45, -0.4, -0.35, -0.3, -0.25, -0.2, -0.15, -0.1, -0.05, 0.0, 0.05, 0.1, 0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6}, "#rap bins"}; Configurable cfgUrlCCDB{"cfgUrlCCDB", "http://ccdb-test.cern.ch:8080", "url of ccdb"}; Configurable cfgPathCCDB{"cfgPathCCDB", "Users/t/tgahlaut/weightCorr/", "Path for ccdb-object"}; Service ccdb; - - using MyAllTracks = soa::Join; - using MyRun3Collisions = soa::Join; - using MyRun3MCCollisions = soa::Join; - using MyMCTracks = soa::Join; - Service pdg; HistogramRegistry hist{"hist", {}, OutputObjHandlingPolicy::AnalysisObject}; TH1D* hWeightPt = nullptr; TH1D* hPurePt = nullptr; - TH2D* hWeightPtRap = nullptr; - TH2D* hWeightPtEta = nullptr; TH1D* hWeightPtPi = nullptr; TH1D* hWeightPtKa = nullptr; TH1D* hWeightPtPr = nullptr; TH1D* hPurePtPi = nullptr; TH1D* hPurePtKa = nullptr; TH1D* hPurePtPr = nullptr; - TH2D* hWeightPtRapPi = nullptr; - TH2D* hWeightPtRapKa = nullptr; - TH2D* hWeightPtRapPr = nullptr; - TH2D* hWeightPtEtaPi = nullptr; - TH2D* hWeightPtEtaKa = nullptr; - TH2D* hWeightPtEtaPr = nullptr; + + enum CollisionLabels { + kTotCol = 1, + kPassSelCol + }; + + enum TrackLabels { + kTracksBeforeHasMcParticle = 1, + kAllTracks, + kAllSelPassed + }; + + enum SelCollisionLabels { + kBeforeSelCol = 1, + kSelColPosZ, + kSelColSel8, + kSelColNoSameBunchPileup, + kSelColIsVertexITSTPC, + }; + + enum class PIDType { + kNone, + kPions, + kKaons, + kProtons + }; + + enum Mode { + QA_Charged = 0, + QA_Pion, + QA_Kaon, + QA_Proton, + Analysis_Charged, + Analysis_Pion, + Analysis_Kaon, + Analysis_Proton, + Gen_Charged, + Gen_Pion, + Gen_Kaon, + Gen_Proton + }; + + static constexpr std::string_view Dire[] = { + "QA/after/", + "QA/Pion/", + "QA/Kaon/", + "QA/Proton/", + "Analysis/Charged/", + "Analysis/Pion/", + "Analysis/Kaon/", + "Analysis/Proton/", + "Gen/Charged/", + "Gen/Pion/", + "Gen/Kaon/", + "Gen/Proton/"}; void init(InitContext const&) { @@ -147,37 +175,29 @@ struct MeanPtFlucId { hPurePtPi = reinterpret_cast(lst->FindObject("hPurePtPi")); hPurePtKa = reinterpret_cast(lst->FindObject("hPurePtKa")); hPurePtPr = reinterpret_cast(lst->FindObject("hPurePtPr")); - hWeightPtRapPi = reinterpret_cast(lst->FindObject("hWeightPtRapPi")); - hWeightPtRapKa = reinterpret_cast(lst->FindObject("hWeightPtRapKa")); - hWeightPtRapPr = reinterpret_cast(lst->FindObject("hWeightPtRapPr")); - hWeightPtEtaPi = reinterpret_cast(lst->FindObject("hWeightPtEtaPi")); - hWeightPtEtaKa = reinterpret_cast(lst->FindObject("hWeightPtEtaKa")); - hWeightPtEtaPr = reinterpret_cast(lst->FindObject("hWeightPtEtaPr")); - - if (!hWeightPt || !hWeightPtPi || !hWeightPtKa || !hWeightPtPr || !hWeightPtRapPi || !hWeightPtRapKa || !hWeightPtRapPr || !hWeightPtEtaPi || !hWeightPtEtaKa || !hWeightPtEtaPr || !hPurePtPi || !hPurePtKa || !hPurePtPr) { + + if (!hWeightPt || !hWeightPtPi || !hWeightPtKa || !hWeightPtPr || !hPurePtPi || !hPurePtKa || !hPurePtPr) { LOGF(info, "FATAL!! Could not find required histograms in CCDB"); } } - const AxisSpec axisEvents{10, 0, 10, "Counts"}; + const AxisSpec axisCol{3, 1, 4, ""}; + const AxisSpec axisTrack{5, 1, 6, ""}; + const AxisSpec axisEvents{10, 1, 11, "Counts"}; const AxisSpec axisEta{etaBins, "#eta"}; const AxisSpec axisPhi{nPhiBins, 0., +7., "#phi (rad)"}; - const AxisSpec axisY{rapBins, "y"}; + const AxisSpec axisY{100, -0.6, 0.6, "y"}; const AxisSpec axisPt{ptBins, "p_{T} (GeV/c)"}; - const AxisSpec axisPt2{40, 0., 4., "p_{T}^2 (GeV/c)^2"}; const AxisSpec axisP{nPBins, 0., 3., "p (GeV/c)"}; const AxisSpec axisInnerParam{nPBins, 0., 3., "p_{InnerParam } (GeV/c)"}; const AxisSpec axisPart{nPartBins, 0., 18., " "}; const AxisSpec axisQn{qNBins, ""}; - const AxisSpec axisTpN{tpNBins, "(Q_{1}^{2} - Q_{2})"}; - const AxisSpec axisTpD{tpDBins, "N_{pairs}"}; - const AxisSpec axisDeno{100, 1., 2.0, "#frac{1}{#sqrt{1 - #frac{1}{N}}}"}; + const AxisSpec axisNpair{nPairBins, "N_{pairs}"}; const AxisSpec axisMeanPt{100, 0., 3., "M(p_{T}) (GeV/c)"}; const AxisSpec axisMult{100, 0, 100, "N_{ch}"}; const AxisSpec axisMultTPC{multTPCBins, "N_{TPC} "}; const AxisSpec axisMultFT0M{multFT0MBins, "N_{FT0M}"}; - const AxisSpec axisMultFT0MMC{multFT0MMCBins, "N_{FT0M}"}; - const AxisSpec axisCentFT0C{nCentBins, 0, 101, "FT0C (%)"}; + const AxisSpec axisCentFT0M{101, 0, 101, "FT0M (%)"}; const AxisSpec axisVtxZ{80, -20., 20., "V_{Z} (cm)"}; const AxisSpec axisDCAz{dcaZBins, "DCA_{Z} (cm)"}; const AxisSpec axisDCAxy{dcaXYBins, "DCA_{XY} (cm)"}; @@ -188,168 +208,104 @@ struct MeanPtFlucId { const AxisSpec axisChi2{40, 0., 40., "Chi2"}; const AxisSpec axisCrossedTPC{300, 0, 300, "Crossed TPC"}; const AxisSpec axisM2{100, 0., 1.4, "#it{m}^{2} (GeV/#it{c}^{2})^{2}"}; + const AxisSpec axisPid{300, 0, 3000, "PID"}; - HistogramConfigSpec qNHist({HistType::kTHnSparseD, {axisMultTPC, axisQn, axisMultFT0M}}); - HistogramConfigSpec partHist({HistType::kTHnSparseD, {axisMultTPC, axisPart, axisMultFT0M}}); - HistogramConfigSpec denoHist({HistType::kTHnSparseD, {axisMultTPC, axisDeno, axisMultFT0M}}); - HistogramConfigSpec qNMCHist({HistType::kTHnSparseD, {axisMultTPC, axisQn, axisMultFT0M}}); - HistogramConfigSpec partMCHist({HistType::kTHnSparseD, {axisMultTPC, axisPart, axisMultFT0M}}); - HistogramConfigSpec denoMCHist({HistType::kTHnSparseD, {axisMultTPC, axisDeno, axisMultFT0M}}); + HistogramConfigSpec qNHist({HistType::kTHnSparseD, {axisCentFT0M, axisQn}}); + HistogramConfigSpec partHist({HistType::kTHnSparseD, {axisCentFT0M, axisPart}}); + HistogramConfigSpec qNMCHist({HistType::kTHnSparseD, {axisCentFT0M, axisQn}}); + HistogramConfigSpec partMCHist({HistType::kTHnSparseD, {axisCentFT0M, axisPart}}); HistogramConfigSpec tofNSigmaHist({HistType::kTH2D, {axisP, axisTOFNsigma}}); HistogramConfigSpec tofSignalHist({HistType::kTH2D, {axisP, axisTOFSignal}}); HistogramConfigSpec tpcNSigmaHist({HistType::kTH2D, {axisP, axisTPCNsigma}}); HistogramConfigSpec tpcSignalHist({HistType::kTH2D, {axisP, axisTPCSignal}}); HistogramConfigSpec tpcTofHist({HistType::kTH2D, {axisTPCNsigma, axisTOFNsigma}}); HistogramConfigSpec pvsM2Hist({HistType::kTH2D, {axisM2, axisP}}); - - HistogramConfigSpec tofNSigmaHist1({HistType::kTH2D, {axisInnerParam, axisTOFNsigma}}); - HistogramConfigSpec tofSignalHist1({HistType::kTH2D, {axisInnerParam, axisTOFSignal}}); - HistogramConfigSpec tpcNSigmaHist1({HistType::kTH2D, {axisInnerParam, axisTPCNsigma}}); HistogramConfigSpec tpcSignalHist1({HistType::kTH2D, {axisInnerParam, axisTPCSignal}}); - HistogramConfigSpec tpcTofHist1({HistType::kTH2D, {axisTPCNsigma, axisTOFNsigma}}); HistogramConfigSpec pvsM2Hist1({HistType::kTH2D, {axisM2, axisInnerParam}}); - // QA Plots: + // QA Plots hist.add("QA/before/h_Counts", "Counts", kTH1D, {axisEvents}); hist.add("QA/before/h_VtxZ", "V_{Z}", kTH1D, {axisVtxZ}); - hist.add("QA/before/h_Pt", "p_{T}", kTH1D, {axisPt}); - hist.add("QA/before/h_Eta", "#eta ", kTH1D, {axisEta}); - hist.add("QA/before/h_Phi", "#phi ", kTH1D, {axisPhi}); - hist.add("QA/before/h_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); - hist.add("QA/before/h_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); - hist.add("QA/before/h2_DcaZ", "DCA_{Z}", kTH2D, {{axisPt}, {axisDCAz}}); - hist.add("QA/before/h2_DcaXY", "DCA_{XY}", kTH2D, {{axisPt}, {axisDCAxy}}); hist.add("QA/before/h_NTPC", "N_{TPC}", kTH1D, {axisMultTPC}); hist.add("QA/before/h_NFT0M", "FT0M Multiplicity", kTH1D, {axisMultFT0M}); - hist.add("QA/before/h_Cent", "FT0C (%)", kTH1D, {axisCentFT0C}); - hist.add("QA/before/h_CentM", "FT0M (%)", kTH1D, {axisCentFT0C}); + hist.add("QA/before/h_CentM", "FT0M (%)", kTH1D, {axisCentFT0M}); hist.add("QA/before/h2_TPCSignal", "TPC Signal", tpcSignalHist); hist.add("QA/before/h2_TOFSignal", "TOF Signal", tofSignalHist); hist.add("QA/before/h2_pvsm2", "p vs m^{2}", pvsM2Hist); - hist.add("QA/before/innerParam/h2_TPCSignal", "TPC Signal", tpcSignalHist1); - hist.add("QA/before/innerParam/h2_TOFSignal", "TOF Signal", tofSignalHist1); - hist.add("QA/before/innerParam/h2_pvsm2", "p vs m^{2}", pvsM2Hist1); - hist.addClone("QA/before/", "QA/after/"); + hist.add("QA/before/h_Pt", "p_{T}", kTH1D, {axisPt}); + hist.add("QA/before/h_Eta", "#eta ", kTH1D, {axisEta}); + hist.add("QA/before/h_Phi", "#phi ", kTH1D, {axisPhi}); + hist.add("QA/before/h_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); + hist.add("QA/before/h_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); + hist.add("QA/before/h2_DcaZ", "DCA_{Z}", kTH2D, {{axisPt}, {axisDCAz}}); + hist.add("QA/before/h2_DcaXY", "DCA_{XY}", kTH2D, {{axisPt}, {axisDCAxy}}); + + hist.add("QA/after/h_counts_evSelCuts", "Event selection cuts", kTH1D, {axisEvents}); hist.add("QA/after/h_TPCChi2perCluster", "TPC #Chi^{2}/Cluster", kTH1D, {axisChi2}); hist.add("QA/after/h_ITSChi2perCluster", "ITS #Chi^{2}/Cluster", kTH1D, {axisChi2}); hist.add("QA/after/h_crossedTPC", "Crossed TPC", kTH1D, {axisCrossedTPC}); - hist.add("QA/after/h_counts_evSelCuts", "Event selection cuts", kTH1D, {axisEvents}); - hist.add("QA/after/h_VtxZReco", "Simulated Vertex Z", kTH1D, {axisVtxZ}); - - hist.add("QA/after/h2_PvsPinner", "p_{InnerParam} vs p", kTH2D, {{axisP}, {axisInnerParam}}); - hist.add("QA/after/h2_Pt_Eta", "p_{T} vs #eta ", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/after/h2_NTPC_Cent", "N_{TPC} vs FT0C(%)", kTH2D, {{axisCentFT0C}, {axisMultTPC}}); - hist.add("QA/after/h2_NTPC_CentM", "N_{TPC} vs FT0M(%)", kTH2D, {{axisCentFT0C}, {axisMultTPC}}); + hist.add("QA/after/h2_NTPC_CentM", "N_{TPC} vs FT0M(%)", kTH2D, {{axisCentFT0M}, {axisMultTPC}}); hist.add("QA/after/h2_NTPC_NFT0M", "N_{TPC} vs N_{FT0M}", kTH2D, {{axisMultFT0M}, {axisMultTPC}}); - hist.add("QA/after/p_NTPC_NFT0M", "N_{TPC} vs N_{FT0M} (Profile)", kTProfile, {axisMultFT0M}); - hist.add("QA/after/p_NTPC_Cent", "N_{TPC} vs FT0C(%) (Profile)", kTProfile, {axisCentFT0C}); - - hist.add("QA/after/h_Pt2", "p_{T}^2", kTH1D, {axisPt2}); - hist.add("QA/after/h_Pt_weighted", "weighted pT distribution", kTH1D, {axisPt}); - hist.add("QA/after/h_Pt2_weighted", "weighted pT distribution", kTH1D, {axisPt2}); - hist.add("QA/after/h2_Pt_NFT0M", "p_{T} in Multiplicity Classes ", kTH2D, {{axisPt}, {axisMultFT0M}}); - hist.add("QA/after/h_PtEtaPhi_NFT0M", "p_{T}, #eta, #phi in Multiplicity Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisMultFT0M}}); - hist.add("QA/after/h_PtEtaPhi_centFT0M", "p_{T}, #eta, #phi in centrality Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisCentFT0C}}); - hist.add("QA/after/h2_pt_nch", "Truth", kTH2D, {{axisMult}, {axisPt}}); - hist.add("QA/after/h3_nft0m_pt_nch", "Reco", kTHnSparseD, {{axisMult}, {axisPt}, {axisMultFT0M}}); - hist.add("QA/after/h2_pt_nch_prof", "Truth", kTProfile, {axisMult}); + hist.add("QA/after/p_NTPC_CentM", "N_{TPC} vs FT0M(%) (Profile)", kTProfile, {axisCentFT0M}); + hist.add("QA/after/h_DCAxy_primary", "DCA_{XY} (Primary)", kTH1D, {axisDCAxy}); + hist.add("QA/after/h_DCAz_primary", "DCA_{Z} (Primary)", kTH1D, {axisDCAz}); + hist.add("QA/after/h_DCAxy_secondary", "DCA_{XY} (Secondary)", kTH1D, {axisDCAxy}); + hist.add("QA/after/h_DCAz_secondary", "DCA_{Z} (Secondary)", kTH1D, {axisDCAz}); + hist.add("QA/after/innerParam/h2_TPCSignal", "TPC Signal", tpcSignalHist1); + + hist.add("QA/Charged/h_Pt", "p_{T}", kTH1D, {axisPt}); + hist.add("QA/Charged/h_Eta", "#eta ", kTH1D, {axisEta}); + hist.add("QA/Charged/h_Phi", "#phi ", kTH1D, {axisPhi}); + hist.add("QA/Charged/h_DcaZ", "DCA_{Z}", kTH1D, {axisDCAz}); + hist.add("QA/Charged/h_DcaXY", "DCA_{XY}", kTH1D, {axisDCAxy}); + hist.add("QA/Charged/h2_DcaZ", "DCA_{Z}", kTH2D, {{axisPt}, {axisDCAz}}); + hist.add("QA/Charged/h2_DcaXY", "DCA_{XY}", kTH2D, {{axisPt}, {axisDCAxy}}); + hist.add("QA/Charged/h_Pt_weighted", "weighted pT distribution", kTH1D, {axisPt}); + hist.add("QA/Charged/h2_Pt_Eta", "p_{T} vs #eta ", kTH2D, {{axisEta}, {axisPt}}); + hist.add("QA/Charged/h2_Pt_centFT0M", "p_{T} in centrality Classes ", kTH2D, {{axisCentFT0M}, {axisPt}}); + hist.add("QA/Charged/h3_PtEtaPhi", "p_{T}, #eta, #phi ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}}); + + hist.addClone("QA/Charged/", "QA/Pion/"); hist.add("QA/Pion/before/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist); + hist.add("QA/Pion/before/h2_TPCNsigma_tof", "n #sigma_{TPC}", tpcNSigmaHist); hist.add("QA/Pion/before/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist); hist.add("QA/Pion/before/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist); hist.add("QA/Pion/h_Rap", "y ", kTH1D, {axisY}); - hist.add("QA/Pion/h_RapTruth", "y ", kTH1D, {axisY}); - hist.add("QA/Pion/h_Eta", "Pseudorapidity ", kTH1D, {axisEta}); - hist.add("QA/Pion/h_EtaTruth", "Pseudorapidity (Reco Truth) ", kTH1D, {axisEta}); - hist.add("QA/Pion/h_Phi", "Azimuthal Distribution ", kTH1D, {axisPhi}); - hist.add("QA/Pion/h_DcaZ", "DCA_{z}", kTH1D, {axisDCAz}); - hist.add("QA/Pion/h_DcaXY", "DCA_{xy}", kTH1D, {axisDCAxy}); - hist.add("QA/Pion/h_Pt", "p_{T} ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_Pt2", "p_{T}^2 ", kTH1D, {axisPt2}); hist.add("QA/Pion/h_PtPos", "p_{T} (positive) ", kTH1D, {axisPt}); hist.add("QA/Pion/h_PtNeg", "p_{T} (negative) ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_PtTruth", "p_{T} ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_PtTruth2", "p_{T}^2 ", kTH1D, {axisPt2}); - hist.add("QA/Pion/h_PtPosTruth", "p_{T} (positive) ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_PtNegTruth", "p_{T} (negative) ", kTH1D, {axisPt}); - hist.add("QA/Pion/h_Pt_weighted", "weighted pT distribution", kTH1D, {axisPt}); - hist.add("QA/Pion/h_Pt2_weighted", "weighted pT distribution", kTH1D, {axisPt2}); - - hist.add("QA/Pion/h2_Pt_Rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt}}); - hist.add("QA/Pion/h2_PtTruth_Rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt}}); - hist.add("QA/Pion/h2_PtTruth_Eta", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/Pion/h2_Pt_Eta", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/Pion/h2_DcaZ", "DCA_{z}", kTH2D, {{axisPt}, {axisDCAz}}); - hist.add("QA/Pion/h2_DcaXY", "DCA_{xy}", kTH2D, {{axisPt}, {axisDCAxy}}); - hist.add("QA/Pion/h2_Pt_Rap_weighted", "p_{T} vs y weighted", kTH2D, {{axisY}, {axisPt}}); - hist.add("QA/Pion/h2_Pt_Eta_weighted", "p_{T} vs #eta weighted", kTH2D, {{axisEta}, {axisPt}}); - hist.add("QA/Pion/h2_Pt_NFT0M", "p_{T} in Multiplicity Classes ", kTH2D, {{axisPt}, {axisMultFT0M}}); - - hist.add("QA/Pion/h_PtEtaPhi_NFT0M", "p_{T}, #eta, #phi in Multiplicity Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisMultFT0M}}); - hist.add("QA/Pion/h_PtEtaPhi_centFT0M", "p_{T}, #eta, #phi in centrality Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisCentFT0C}}); - - hist.add("QA/Pion/h2_PtTruth_NFT0M", "p_{T} in Multiplicity Classes ", kTH2D, {{axisPt}, {axisMultFT0M}}); - hist.add("QA/Pion/h2_pt_nch", "Reco", kTH2D, {{axisMult}, {axisPt}}); - hist.add("QA/Pion/h3_nft0m_pt_nch", "Reco", kTHnSparseD, {{axisMult}, {axisPt}, {axisMultFT0M}}); - hist.add("QA/Pion/h2_pt_nch_prof", "Reco", kTProfile, {axisMult}); - + hist.add("QA/Pion/h_PtTruth", "p_{T} (Truth)", kTH1D, {axisPt}); + hist.add("QA/Pion/h_PtPosTruth", "p_{T} (positive) (Truth)", kTH1D, {axisPt}); + hist.add("QA/Pion/h_PtNegTruth", "p_{T} (negative) (Truth) ", kTH1D, {axisPt}); hist.add("QA/Pion/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist); - hist.add("QA/Pion/h2_TPCNsigma_El", "n #sigma_{TPC, El}", tpcNSigmaHist); - hist.add("QA/Pion/h2_TOFNsigma_El", "n #sigma_{TOF, El}", tofNSigmaHist); hist.add("QA/Pion/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist); hist.add("QA/Pion/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist); hist.add("QA/Pion/h2_TPCSignal", "TPC Signal ", tpcSignalHist); hist.add("QA/Pion/h2_TOFSignal", "TOF Signal", tofSignalHist); + hist.add("QA/Pion/innerParam/h2_TPCSignal", "TPC Signal", tpcSignalHist1); hist.add("QA/Pion/h2_pvsm2", "p vs m^{2}", pvsM2Hist); - - hist.add("QA/Pion/innerParam/before/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist1); - hist.add("QA/Pion/innerParam/before/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist1); - hist.add("QA/Pion/innerParam/before/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist1); - hist.add("QA/Pion/innerParam/h2_TPCNsigma", "n #sigma_{TPC}", tpcNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TPCNsigma_El", "n #sigma_{TPC, El}", tpcNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TOFNsigma_El", "n #sigma_{TOF, El}", tofNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TOFNsigma", "n #sigma_{TOF}", tofNSigmaHist1); - hist.add("QA/Pion/innerParam/h2_TpcTofNsigma", "n #sigma_{TPC} vs n #sigma_{TOF}", tpcTofHist1); - hist.add("QA/Pion/innerParam/h2_TPCSignal", "TPC Signal ", tpcSignalHist1); - hist.add("QA/Pion/innerParam/h2_TOFSignal", "TOF Signal", tofSignalHist1); - hist.add("QA/Pion/innerParam/h2_pvsm2", "p vs m^{2}", pvsM2Hist1); - + hist.add("QA/Pion/h_PtTruth_primary", "p_{T} (Truth Primary)", kTH1D, {axisPt}); + hist.add("QA/Pion/h_PtTruth_secondary", "p_{T} (Truth Secondary)", kTH1D, {axisPt}); hist.addClone("QA/Pion/", "QA/Kaon/"); hist.addClone("QA/Pion/", "QA/Proton/"); - // Analysis Plots: + // AnalysisPlots hist.add("Analysis/Charged/h_Mult", "Multiplicity", kTH1D, {axisMult}); - hist.add("Analysis/Charged/h_Mult_weighted", "Multiplicity", kTH1D, {axisMult}); - hist.add("Analysis/Charged/h_Q1", "Q1", qNHist); - hist.add("Analysis/Charged/h_Q2", "Q2", qNHist); - hist.add("Analysis/Charged/h_Q3", "Q3", qNHist); - hist.add("Analysis/Charged/h_Q4", "Q4", qNHist); - hist.add("Analysis/Charged/h_mean_pT", " ", kTH1D, {axisMeanPt}); - hist.add("Analysis/Charged/p_mean_pT_Mult_var", " ", kTProfile, {axisMultTPC}); - hist.add("Analysis/Charged/p_CheckNCh", " 1/denominator vs N_{TPC} ", kTProfile, {axisMultTPC}); - hist.add("Analysis/Charged/h_CheckNCh", " 1/denominator vs N_{TPC} ", denoHist); - hist.add("Analysis/Charged/h_Q1_var", "Q1 vs N_{TPC}", qNHist); - hist.add("Analysis/Charged/h_N_var", "N vs N_{TPC}", kTHnSparseD, {axisMultTPC, axisMult, axisMultFT0M}); - hist.add("Analysis/Charged/h_twopart_nume_Mult_var", "twopart numerator", kTHnSparseD, {axisMultTPC, axisTpN, axisMultFT0M}); - hist.add("Analysis/Charged/h_twopart_deno_Mult_var", "twopart denominator", kTHnSparseD, {axisMultTPC, axisTpD, axisMultFT0M}); + hist.add("Analysis/Charged/h_N_CentFT0M", "Multiplicity vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisMult}); + hist.add("Analysis/Charged/h_Npair_CentFT0M", "Npair vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisNpair}); + hist.add("Analysis/Charged/h_Q1_CentFT0M", "Q1 vs CentFT0M", qNHist); + hist.add("Analysis/Charged/h_Q2_CentFT0M", "Q2 vs CentFT0M", qNHist); + hist.add("Analysis/Charged/h_twopart1_CentFT0M", "twopart (neum)", qNMCHist); hist.add("Analysis/Charged/h_mean_pT_Mult_var", " vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_mean_pT_Mult_skew", " vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_mean_pT_Mult_kurto", " vs N_{TPC} ", partHist); hist.add("Analysis/Charged/h_twopart_Mult_var", "Twopart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_twopart_Mult_skew", "Twopart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_twopart_Mult_kurto", "Twopart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_threepart_Mult_skew", "Threepart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_threepart_Mult_kurto", "Threepart vs N_{TPC} ", partHist); - hist.add("Analysis/Charged/h_fourpart_Mult_kurto", "Fourpart vs N_{TPC} ", partHist); - - hist.add("Analysis/Charged/p_twopart_MultFT0M", "Twopart vs N_{FT0M} ", kTProfile, {axisMultFT0M}); - hist.add("Analysis/Charged/p_mean_pT_MultFT0M", " vs N_{FT0M} ", kTProfile, {axisMultFT0M}); + hist.add("Analysis/Charged/p_twopart_CentFT0M", "Twopart vs cent_{FT0M} ", kTProfile, {axisCentFT0M}); + hist.add("Analysis/Charged/p_mean_pT_CentFT0M", " vs cent_{FT0M} ", kTProfile, {axisCentFT0M}); hist.addClone("Analysis/Charged/", "Analysis/Pion/"); hist.addClone("Analysis/Charged/", "Analysis/Kaon/"); @@ -359,126 +315,95 @@ struct MeanPtFlucId { hist.add("Gen/h_Counts", "Counts", kTH1D, {axisEvents}); hist.add("Gen/h_VtxZ", "Vertex Z ", kTH1D, {axisVtxZ}); hist.add("Gen/h_VtxZ_b", "Vertex Z ", kTH1D, {axisVtxZ}); - hist.add("Gen/h_NTPC", "Mid rapidity Multiplicity", kTH1D, {axisMultTPC}); - hist.add("Gen/h_NFT0C", "Forward Multiplicity", kTH1D, {axisMultFT0MMC}); - hist.add("Gen/h2_NTPC_NFT0M", "NTPC vs Forward Multiplicity", kTH2D, {{axisMultFT0M}, {axisMultTPC}}); - hist.add("Gen/h_NSim", "Truth Multiplicity TPC", kTH1D, {axisMultTPC}); hist.add("Gen/h2_NTPC_NSim", "Reco vs Truth Multiplicty TPC", kTH2D, {{axisMultTPC}, {axisMultTPC}}); - hist.add("Gen/h2_NChSim_NSim", "Truth Multiplicty NCh vs NTPC", kTH2D, {{axisMultTPC}, {axisMultTPC}}); - hist.add("Gen/Charged/h_PtEtaPhi_NFT0M", "p_{T}, #eta, #phi in Multiplicity Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisMultFT0M}}); - hist.add("Gen/Charged/h_PtEtaPhi_centFT0M", "p_{T}, #eta, #phi in centrality Classes ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}, {axisCentFT0C}}); hist.add("Gen/Charged/h_EtaTruth", "#eta ", kTH1D, {axisEta}); hist.add("Gen/Charged/h_PhiTruth", "#phi ", kTH1D, {axisPhi}); hist.add("Gen/Charged/h_PtTruth", "p_{T} ", kTH1D, {axisPt}); - hist.add("Gen/Charged/h_PtTruth2", "p_{T}^2 ", kTH1D, {axisPt2}); - hist.add("Gen/Charged/h2_PtTruth_Eta", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); - hist.add("Gen/Charged/h2_PtTruth_NFT0M", "p_{T} in Multiplicity Classes", kTH2D, {{axisPt}, {axisMultFT0M}}); + hist.add("Gen/Charged/h2_Pt_EtaTruth", "p_{T} vs #eta", kTH2D, {{axisEta}, {axisPt}}); + hist.add("Gen/Charged/h2_PtTruth_centFT0M", "p_{T} in centrality Classes ", kTH2D, {{axisCentFT0M}, {axisPt}}); + hist.add("Gen/Charged/h_PtEtaPhiTruth", "p_{T}, #eta, #phi ", kTHnSparseD, {{axisPt}, {axisEta}, {axisPhi}}); hist.add("Gen/Charged/h_Mult", "Multiplicity", kTH1D, {axisMult}); - hist.add("Gen/Charged/h_Mult_weighted", "Multiplicity", kTH1D, {axisMult}); - - hist.add("Gen/Charged/h2_pt_nch", "Truth", kTH2D, {{axisMult}, {axisPt}}); - hist.add("Gen/Charged/h3_nft0m_pt_nch", "Truth", kTHnSparseD, {{axisMult}, {axisPt}, {axisMultFT0M}}); - hist.add("Gen/Charged/h2_pt_nch_prof", "Truth", kTProfile, {axisMult}); - hist.add("Gen/Charged/h_mean_pT", " ", kTH1D, {axisMeanPt}); - - hist.add("Gen/Charged/h_Q1", "Q1", qNMCHist); - hist.add("Gen/Charged/h_Q2", "Q2", qNMCHist); - hist.add("Gen/Charged/h_Q3", "Q3", qNMCHist); - hist.add("Gen/Charged/h_Q4", "Q4", qNMCHist); - hist.add("Gen/Charged/h_Q1_var", "Q1 vs N_{TPC}", qNMCHist); - hist.add("Gen/Charged/h_N_var", "N vs N_{TPC}", kTHnSparseD, {axisMultTPC, axisMult, axisMultFT0M}); - hist.add("Gen/Charged/h_twopart_nume_Mult_var", "twopart numerator", kTHnSparseD, {axisMultTPC, axisTpN, axisMultFT0M}); - hist.add("Gen/Charged/h_twopart_deno_Mult_var", "twopart denominator", kTHnSparseD, {axisMultTPC, axisTpD, axisMultFT0M}); - - hist.add("Gen/Charged/p_mean_pT_Mult_var", " ", kTProfile, {axisMultTPC}); - hist.add("Gen/Charged/p_CheckNCh", " 1/denominator vs N_{TPC} ", kTProfile, {axisMultTPC}); - hist.add("Gen/Charged/h_CheckNCh", " 1/denominator vs N_{TPC} ", denoMCHist); + hist.add("Gen/Charged/h_N_CentFT0M", "Multiplicity vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisMult}); + hist.add("Gen/Charged/h_Npair_CentFT0M", "Npair vs CentFT0M", kTHnSparseD, {axisCentFT0M, axisNpair}); + hist.add("Gen/Charged/h_Q1_CentFT0M", "Q1", qNMCHist); + hist.add("Gen/Charged/h_Q2_CentFT0M", "Q2", qNMCHist); + hist.add("Gen/Charged/h_twopart1_CentFT0M", "twopart (neum)", qNMCHist); hist.add("Gen/Charged/h_mean_pT_Mult_var", " vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_mean_pT_Mult_skew", " vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_mean_pT_Mult_kurto", " vs N_{TPC} ", partMCHist); hist.add("Gen/Charged/h_twopart_Mult_var", "Twopart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_twopart_Mult_skew", "Twopart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_twopart_Mult_kurto", "Twopart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_threepart_Mult_skew", "Threepart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_threepart_Mult_kurto", "Threepart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/h_fourpart_Mult_kurto", "Fourpart vs N_{TPC} ", partMCHist); - hist.add("Gen/Charged/p_twopart_MultFT0M", "Twopart vs N_{TPC} ", kTProfile, {axisMultFT0M}); - hist.add("Gen/Charged/p_mean_pT_MultFT0M", " vs N_{TPC} ", kTProfile, {axisMultFT0M}); + hist.add("Gen/Charged/p_twopart_CentFT0M", "Twopart vs CentFT0M ", kTProfile, {axisCentFT0M}); + hist.add("Gen/Charged/p_mean_pT_CentFT0M", " vs CentFT0M ", kTProfile, {axisCentFT0M}); hist.addClone("Gen/Charged/", "Gen/Pion/"); hist.add("Gen/Pion/h_RapTruth", "y", kTH1D, {axisY}); - hist.add("Gen/Pion/h2_PtTruth_Rap", "p_{T} vs y", kTH2D, {{axisY}, {axisPt}}); hist.add("Gen/Pion/h_PtPosTruth", "p_{T} (positive) ", kTH1D, {axisPt}); hist.add("Gen/Pion/h_PtNegTruth", "p_{T} (negative) ", kTH1D, {axisPt}); hist.addClone("Gen/Pion/", "Gen/Kaon/"); hist.addClone("Gen/Pion/", "Gen/Proton/"); - } - enum Mode { - QA_Charged = 0, - QA_Pion, - QA_Kaon, - QA_Proton, - Analysis_Charged, - Analysis_Pion, - Analysis_Kaon, - Analysis_Proton, - Gen_Charged, - Gen_Pion, - Gen_Kaon, - Gen_Proton - }; + hist.add("QA/h_collisions_info", "Collisions info", kTH1D, {axisCol}); + hist.add("Gen/h_collisions_info", "Collisions info", kTH1D, {axisCol}); + hist.add("Gen/h_collision_recgen", "Number of Collisions ", kTH1D, {axisCol}); + hist.add("Gen/h2_collision_posZ", "Reco vs truth posZ ", kTH2D, {{axisVtxZ}, {axisVtxZ}}); + hist.add("Tracks/h_tracks_info", "Track info", kTH1D, {axisTrack}); + hist.add("Tracks/h2_tracks_pid_before_sel", "Track pid info before selection", kTH2D, {{axisPid}, {axisPt}}); + + hist.get(HIST("QA/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); + hist.get(HIST("QA/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); + hist.get(HIST("Gen/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kTotCol, "kTotCol"); + hist.get(HIST("Gen/h_collisions_info"))->GetXaxis()->SetBinLabel(CollisionLabels::kPassSelCol, "kPassSelCol"); + hist.get(HIST("Tracks/h_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kTracksBeforeHasMcParticle, "kTracksBeforeHasMcParticle"); + hist.get(HIST("Tracks/h_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllTracks, "kAllTracks"); + hist.get(HIST("Tracks/h_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kAllSelPassed, "kAllSelPassed"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kBeforeSelCol, "kBeforeSelCol"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColPosZ, "kSelColPosZ"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColSel8, "kSelColSel8"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColNoSameBunchPileup, "kSelColNoSameBunchPileup"); + hist.get(HIST("QA/after/h_counts_evSelCuts"))->GetXaxis()->SetBinLabel(SelCollisionLabels::kSelColIsVertexITSTPC, "kSelColIsVertexITSTPC"); + } - static constexpr std::string_view Dire[] = { - "QA/after/", - "QA/Pion/", - "QA/Kaon/", - "QA/Proton/", - "Analysis/Charged/", - "Analysis/Pion/", - "Analysis/Kaon/", - "Analysis/Proton/", - "Gen/Charged/", - "Gen/Pion/", - "Gen/Kaon/", - "Gen/Proton/"}; + float centFT0M = 0.; + int nTPC = 0, nFT0M = 0; // Event selection cuts: template bool selRun3Col(T const& col) { - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 0); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kBeforeSelCol); if (cfgPosZ) { if (std::abs(col.posZ()) > cfgCutPosZ) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 1); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColPosZ); } + centFT0M = col.centFT0M(); + nTPC = col.multNTracksHasTPC(); + nFT0M = col.multFT0M(); + if (cfgSel8) { if (!col.sel8()) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 2); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColSel8); } if (cfgNoSameBunchPileup) { if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 4); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColNoSameBunchPileup); } if (cfgIsVertexITSTPC) { if (!col.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { return false; } - hist.fill(HIST("QA/after/h_counts_evSelCuts"), 5); + hist.fill(HIST("QA/after/h_counts_evSelCuts"), kSelColIsVertexITSTPC); } return true; @@ -494,7 +419,7 @@ struct MeanPtFlucId { if (track.pt() < cfgCutPtMin) return false; - if (track.pt() > cfgCutPtMax) + if (track.pt() >= cfgCutPtMax) return false; if (track.sign() == 0) @@ -504,9 +429,10 @@ struct MeanPtFlucId { return false; if (std::fabs(track.dcaZ()) > (0.0105 + 0.035 / std::pow(track.p(), 1.1))) + return false; - if (std::abs(track.eta()) >= cfgCutEta) - return false; + if (std::abs(track.eta()) >= cfgCutEta) + return false; return true; } @@ -515,109 +441,90 @@ struct MeanPtFlucId { template bool rejectTracks(T const& track) { - if (((track.tpcNSigmaEl()) > -3. && - (track.tpcNSigmaEl()) < 5.) && - (std::fabs(track.tpcNSigmaPi()) > 3 && - std::fabs(track.tpcNSigmaKa()) > 3 && - std::fabs(track.tpcNSigmaPr()) > 3)) { + if (((track.tpcNSigmaEl()) > -cfgCutNSig3 && + (track.tpcNSigmaEl()) < cfgCutNSig5) && + (std::fabs(track.tpcNSigmaPi()) > cfgCutNSig3 && + std::fabs(track.tpcNSigmaKa()) > cfgCutNSig3 && + std::fabs(track.tpcNSigmaPr()) > cfgCutNSig3)) { return true; } return false; } - template - bool selElectrons(T const& track) + template + bool identifyParticle(T const& track, float momThreshold) { - if (std::fabs(track.tpcNSigmaEl()) < cfgCutNSig3) { - return true; - } - return false; - } + const int sp = static_cast(s1); + const int sq = static_cast(s2); + const int sr = static_cast(s3); + std::vector vTpcNSigma = {-999., track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; + std::vector vTofNSigma = {-999., track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr()}; + bool isTofPidFlag = false, isTpcPidFlag = false; + + float nSigmaSelCut = 0.; + float nSigmaTofRejCut = 0.; + float nSigmaTpcRejCut = 0.; + if constexpr (s1 == PIDType::kProtons) { + nSigmaSelCut = cfgSelCutNSigPr; + nSigmaTofRejCut = std::fabs(vTofNSigma[sp]); + nSigmaTpcRejCut = std::fabs(vTpcNSigma[sp]); + } else if constexpr (s1 == PIDType::kKaons) { + nSigmaSelCut = cfgSelCutNSigKa; + nSigmaTofRejCut = std::fabs(vTofNSigma[sp]); + nSigmaTpcRejCut = std::fabs(vTpcNSigma[sp]); + } else if constexpr (s1 == PIDType::kPions) { + nSigmaSelCut = cfgSelCutNSigPi; + nSigmaTofRejCut = cfgRejCutNSigPi; + nSigmaTpcRejCut = cfgRejCutNSigPi; + } - // PID selction cuts for Low momentum Pions - template - bool selPi(T const& track) - { - if (track.pt() >= cfgCutPiPtMin && - track.p() <= cfgCutPiThrsldP) { - if (!track.hasTOF() && - std::fabs(track.tpcNSigmaPi()) < cfgCutNSig2) { - return true; + if (track.hasTOF()) { + if (std::fabs(vTofNSigma[sp]) < nSigmaSelCut && + std::fabs(vTofNSigma[sq]) > nSigmaTofRejCut && + std::fabs(vTofNSigma[sr]) > nSigmaTofRejCut) { + isTofPidFlag = true; } - - if (track.hasTOF() && - std::fabs(track.tpcNSigmaPi()) < cfgCutNSig2 && - std::fabs(track.tofNSigmaPi()) < cfgCutNSig3) { - return true; + if (std::fabs(vTpcNSigma[sp]) < cfgCutNSig2) { + isTpcPidFlag = true; } - } else if (track.hasTOF() && - track.p() > cfgCutPiThrsldP && - std::fabs(track.tpcNSigmaPi()) < cfgCutNSig3 && - std::fabs(track.tofNSigmaPi()) < cfgCutNSig3) { - - return true; - } - - return false; - } - - // PID selction cuts for Low momentum Kaons - template - bool selKa(T const& track) - { - if (track.pt() >= cfgCutKaPtMin && - track.p() <= cfgCutKaThrsldP) { - if (!track.hasTOF() && - std::fabs(track.tpcNSigmaKa()) < cfgCutNSig2) { - return true; + } else { // select from TPC Only + if (track.p() >= momThreshold) { + return false; } - - if (track.hasTOF() && - std::fabs(track.tpcNSigmaKa()) < cfgCutNSig2 && - std::fabs(track.tofNSigmaKa()) < cfgCutNSig3) { - return true; + if (std::fabs(vTpcNSigma[sp]) < nSigmaSelCut && + std::fabs(vTpcNSigma[sq]) > nSigmaTpcRejCut && + std::fabs(vTpcNSigma[sr]) > nSigmaTpcRejCut) { + isTofPidFlag = true; + isTpcPidFlag = true; } } - if (track.hasTOF() && - track.p() > cfgCutKaThrsldP && - std::fabs(track.tpcNSigmaKa()) < cfgCutNSig3 && - ((std::fabs(track.tofNSigmaKa()) < cfgCutNSig3 && track.p() <= cfgCutKaP3) || - (std::fabs(track.tofNSigmaKa()) < cfgCutNSig2 && track.p() > cfgCutKaP3))) { - return true; + if (isTofPidFlag && isTpcPidFlag) { + return true; // Track is identified as one of the particles } - return false; + return false; // Track is not identified as any of the particles } - // PID selction cuts for Low momentum Protons - template - bool selPr(T const& track) + // Get corrected weight for the track: + template + float getCorrectedWeight(T1 hWeightPt, T1 hPurePt, float pt, bool cfgWeightPt, bool cfgPurity) { + float weight = 1.0; + float purity = 1.0; - if (track.pt() >= cfgCutPrPtMin && - track.p() <= cfgCutPrThrsldP) { - if (!track.hasTOF() && - std::fabs(track.tpcNSigmaPr()) < cfgCutNSig2) { - return true; - } - - if (track.hasTOF() && - std::fabs(track.tpcNSigmaPr()) < cfgCutNSig2 && - std::fabs(track.tofNSigmaPr()) < cfgCutNSig3) { - return true; - } - } else if (track.hasTOF() && - track.p() > cfgCutPrThrsldP && - std::fabs(track.tpcNSigmaPr()) < cfgCutNSig3 && - std::fabs(track.tofNSigmaPr()) < cfgCutNSig3) { + if (cfgPurity) { + purity = hPurePt->GetBinContent(hPurePt->FindBin(pt)); + } - return true; + if (cfgWeightPt) { + float weightPt = hWeightPt->GetBinContent(hWeightPt->FindBin(pt)); + weight = purity * weightPt; } - return false; + return weight; } // Fill hist before selection cuts: @@ -636,8 +543,7 @@ struct MeanPtFlucId { hist.fill(HIST("QA/before/h_VtxZ"), col.posZ()); hist.fill(HIST("QA/before/h_Counts"), 2); hist.fill(HIST("QA/before/h_NTPC"), col.multNTracksHasTPC()); - hist.fill(HIST("QA/before/h_Cent"), col.centFT0C()); - hist.fill(HIST("QA/after/h_CentM"), col.centFT0M()); + hist.fill(HIST("QA/before/h_CentM"), col.centFT0M()); hist.fill(HIST("QA/before/h_NFT0M"), col.multFT0M()); } @@ -647,34 +553,28 @@ struct MeanPtFlucId { { hist.fill(HIST("QA/after/h_VtxZ"), col.posZ()); hist.fill(HIST("QA/after/h_Counts"), 2); - hist.fill(HIST("QA/after/h_NTPC"), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/h_Cent"), col.centFT0C()); - hist.fill(HIST("QA/after/h_CentM"), col.centFT0M()); - hist.fill(HIST("QA/after/h_NFT0M"), col.multFT0M()); - hist.fill(HIST("QA/after/h2_NTPC_NFT0M"), col.multFT0M(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/h2_NTPC_Cent"), col.centFT0C(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/h2_NTPC_CentM"), col.centFT0M(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/p_NTPC_Cent"), col.centFT0C(), col.multNTracksHasTPC()); - hist.fill(HIST("QA/after/p_NTPC_NFT0M"), col.multFT0M(), col.multNTracksHasTPC()); + hist.fill(HIST("QA/after/h_NTPC"), nTPC); + hist.fill(HIST("QA/after/h_CentM"), centFT0M); + hist.fill(HIST("QA/after/h_NFT0M"), nFT0M); + hist.fill(HIST("QA/after/h2_NTPC_NFT0M"), nFT0M, nTPC); + hist.fill(HIST("QA/after/h2_NTPC_CentM"), centFT0M, nTPC); + hist.fill(HIST("QA/after/p_NTPC_CentM"), centFT0M, nTPC); + hist.fill(HIST("QA/after/p_NTPC_NFT0M"), nFT0M, nTPC); } // Fill Charged particles QA: template - void fillChargedQAHistos(T const& track, int nFT0M, double centFT0M) + void fillChargedQAHistos(T const& track, float centFT0M) { - hist.fill(HIST("QA/after/h_Eta"), track.eta()); - hist.fill(HIST("QA/after/h_Phi"), track.phi()); - hist.fill(HIST("QA/after/h_Pt"), track.pt()); - hist.fill(HIST("QA/after/h_Pt2"), track.pt() * track.pt()); - hist.fill(HIST("QA/after/h2_Pt_NFT0M"), track.pt(), nFT0M); - hist.fill(HIST("QA/after/h_PtEtaPhi_NFT0M"), track.pt(), track.eta(), track.phi(), nFT0M); - hist.fill(HIST("QA/after/h_PtEtaPhi_centFT0M"), track.pt(), track.eta(), track.phi(), centFT0M); - hist.fill(HIST("QA/after/h2_PvsPinner"), track.p(), track.tpcInnerParam()); - hist.fill(HIST("QA/after/h2_Pt_Eta"), track.eta(), track.pt()); - hist.fill(HIST("QA/after/h_DcaZ"), track.dcaZ()); - hist.fill(HIST("QA/after/h_DcaXY"), track.dcaXY()); - hist.fill(HIST("QA/after/h2_DcaXY"), track.pt(), track.dcaXY()); - hist.fill(HIST("QA/after/h2_DcaZ"), track.pt(), track.dcaZ()); + hist.fill(HIST("QA/Charged/h_Eta"), track.eta()); + hist.fill(HIST("QA/Charged/h_Phi"), track.phi()); + hist.fill(HIST("QA/Charged/h2_Pt_centFT0M"), centFT0M, track.pt()); + hist.fill(HIST("QA/Charged/h3_PtEtaPhi"), track.pt(), track.eta(), track.phi()); + hist.fill(HIST("QA/Charged/h2_Pt_Eta"), track.eta(), track.pt()); + hist.fill(HIST("QA/Charged/h_DcaZ"), track.dcaZ()); + hist.fill(HIST("QA/Charged/h_DcaXY"), track.dcaXY()); + hist.fill(HIST("QA/Charged/h2_DcaXY"), track.pt(), track.dcaXY()); + hist.fill(HIST("QA/Charged/h2_DcaZ"), track.pt(), track.dcaZ()); hist.fill(HIST("QA/after/h_TPCChi2perCluster"), track.tpcChi2NCl()); hist.fill(HIST("QA/after/h_ITSChi2perCluster"), track.itsChi2NCl()); @@ -689,95 +589,48 @@ struct MeanPtFlucId { hist.fill(HIST("QA/before/h2_TPCSignal"), track.p(), track.tpcSignal()); hist.fill(HIST("QA/before/h2_pvsm2"), track.mass() * track.mass(), track.p()); - hist.fill(HIST("QA/Pion/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPi()); + if (!track.hasTOF()) + hist.fill(HIST("QA/Pion/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPi()); + if (track.hasTOF()) + hist.fill(HIST("QA/Pion/before/h2_TPCNsigma_tof"), track.p(), track.tpcNSigmaPi()); hist.fill(HIST("QA/Pion/before/h2_TOFNsigma"), track.p(), track.tofNSigmaPi()); hist.fill(HIST("QA/Pion/before/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - hist.fill(HIST("QA/Proton/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPr()); + if (!track.hasTOF()) + hist.fill(HIST("QA/Proton/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaPr()); + if (track.hasTOF()) + hist.fill(HIST("QA/Proton/before/h2_TPCNsigma_tof"), track.p(), track.tpcNSigmaPr()); hist.fill(HIST("QA/Proton/before/h2_TOFNsigma"), track.p(), track.tofNSigmaPr()); hist.fill(HIST("QA/Proton/before/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - hist.fill(HIST("QA/Kaon/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaKa()); + if (!track.hasTOF()) + hist.fill(HIST("QA/Kaon/before/h2_TPCNsigma"), track.p(), track.tpcNSigmaKa()); + if (track.hasTOF()) + hist.fill(HIST("QA/Kaon/before/h2_TPCNsigma_tof"), track.p(), track.tpcNSigmaKa()); hist.fill(HIST("QA/Kaon/before/h2_TOFNsigma"), track.p(), track.tofNSigmaKa()); hist.fill(HIST("QA/Kaon/before/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); - - hist.fill(HIST("QA/before/innerParam/h2_TOFSignal"), track.tpcInnerParam(), track.beta()); - hist.fill(HIST("QA/before/innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); - hist.fill(HIST("QA/before/innerParam/h2_pvsm2"), track.mass() * track.mass(), track.tpcInnerParam()); - - hist.fill(HIST("QA/Pion/innerParam/before/h2_TPCNsigma"), track.tpcInnerParam(), track.tpcNSigmaPi()); - hist.fill(HIST("QA/Pion/innerParam/before/h2_TOFNsigma"), track.tpcInnerParam(), track.tofNSigmaPi()); - hist.fill(HIST("QA/Pion/innerParam/before/h2_TpcTofNsigma"), track.tpcNSigmaPi(), track.tofNSigmaPi()); - hist.fill(HIST("QA/Proton/innerParam/before/h2_TPCNsigma"), track.tpcInnerParam(), track.tpcNSigmaPr()); - hist.fill(HIST("QA/Proton/innerParam/before/h2_TOFNsigma"), track.tpcInnerParam(), track.tofNSigmaPr()); - hist.fill(HIST("QA/Proton/innerParam/before/h2_TpcTofNsigma"), track.tpcNSigmaPr(), track.tofNSigmaPr()); - hist.fill(HIST("QA/Kaon/innerParam/before/h2_TPCNsigma"), track.tpcInnerParam(), track.tpcNSigmaKa()); - hist.fill(HIST("QA/Kaon/innerParam/before/h2_TOFNsigma"), track.tpcInnerParam(), track.tofNSigmaKa()); - hist.fill(HIST("QA/Kaon/innerParam/before/h2_TpcTofNsigma"), track.tpcNSigmaKa(), track.tofNSigmaKa()); } // Moments Calculation: - void moments(double pt, double weight, double& Q1, double& Q2, double& Q3, double& Q4) + void moments(float pt, float weight, double& Q1, double& Q2) { Q1 += pt * weight; - Q2 += pt * pt * weight; - Q3 += pt * pt * pt * weight; - Q4 += pt * pt * pt * pt * weight; + Q2 += pt * pt * weight * weight; } - template - float getCorrectedWeight(T1 hWeightPt, T1 hPurePt, T2 hWeightPtY, T2 hWeightPtEta, double pt, double rap, double eta, bool cfgWeightPt, bool cfgWeightPtY, bool cfgWeightPtEta, bool cfgPurity) + template + void fillIdParticleQAHistos(T const& track, float rap, float nSigmaTPC, float nSigmaTOF, float centFT0M, T1 hWeightPt, T1 hPurePt, bool cfgWeightPtId, bool cfgPurityId, double& NW, double& NW2, double& Q1, double& Q2) { - float weight = 1.0; - float purity = 1.0; - if (cfgPurity) { - purity = hPurePt->GetBinContent(hPurePt->FindBin(pt)); - } else { - purity = 1.0; - } - - if (cfgWeightPt) { - float weightPt = hWeightPt->GetBinContent(hWeightPt->FindBin(pt)); - weight = purity * weightPt; - } else if (cfgWeightPtY) { - float weightPtY = hWeightPtY->GetBinContent(hWeightPtY->FindBin(rap, pt)); - weight = purity * weightPtY; - } else if (cfgWeightPtEta) { - float weightPtEta = hWeightPtEta->GetBinContent(hWeightPtEta->FindBin(eta, pt)); - weight = purity * weightPtEta; - } else { - weight = 1.0; - } - return weight; - } + float pt = track.pt(); + float eta = track.eta(); + float phi = track.phi(); + float weight = getCorrectedWeight(hWeightPt, hPurePt, pt, cfgWeightPtId, cfgPurityId); - // Fill after PID cut QA hist: - template - void fillIdParticleQAHistos(T const& track, double rap, double nSigmaTPC, double nSigmaTOF, int nFT0M, double centFT0M, T1 hWeightPt, T1 hPurePt, T2 hWeightPtY, T2 hWeightPtEta, bool cfgWeightPtId, bool cfgWeightPtYId, bool cfgWeightPtEtaId, bool cfgPurityId, int& N, double& NW, double& Q1, double& Q2, double& Q3, double& Q4, float& weight) - { - double pt = track.pt(); - double eta = track.eta(); - weight = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtY, hWeightPtEta, pt, rap, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - if (weight == 0) + if (std::abs(weight) < cfgMinWeight) return; NW += weight; - N++; - moments(pt, weight, Q1, Q2, Q3, Q4); - - if (cfgWeightPtYId) - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Rap_weighted"), rap, pt, weight); - - if (cfgWeightPtEtaId) - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta_weighted"), eta, pt, weight); - - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt_weighted"), pt, weight); - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt2_weighted"), pt * pt, weight); + NW2 += weight * weight; + moments(pt, weight, Q1, Q2); - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt"), pt); - hist.fill(HIST(Dire[Mode]) + HIST("h_Pt2"), pt * pt); - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_NFT0M"), pt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_PtEtaPhi_NFT0M"), pt, eta, track.phi(), nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_PtEtaPhi_centFT0M"), pt, eta, track.phi(), centFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta"), eta, pt); if (track.sign() > 0) { hist.fill(HIST(Dire[Mode]) + HIST("h_PtPos"), pt); } @@ -785,50 +638,46 @@ struct MeanPtFlucId { hist.fill(HIST(Dire[Mode]) + HIST("h_PtNeg"), pt); } + if (cfgWeightPtEtaId) + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta_weighted"), eta, pt, weight); + + hist.fill(HIST(Dire[Mode]) + HIST("h_Pt_weighted"), pt, weight); + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_centFT0M"), centFT0M, pt); + hist.fill(HIST(Dire[Mode]) + HIST("h3_PtEtaPhi"), pt, eta, phi); + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Eta"), eta, pt); hist.fill(HIST(Dire[Mode]) + HIST("h_Eta"), eta); - hist.fill(HIST(Dire[Mode]) + HIST("h_Phi"), track.phi()); + hist.fill(HIST(Dire[Mode]) + HIST("h_Phi"), phi); hist.fill(HIST(Dire[Mode]) + HIST("h_Rap"), rap); - hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_Rap"), rap, pt); hist.fill(HIST(Dire[Mode]) + HIST("h_DcaZ"), track.dcaZ()); hist.fill(HIST(Dire[Mode]) + HIST("h_DcaXY"), track.dcaXY()); hist.fill(HIST(Dire[Mode]) + HIST("h2_DcaZ"), pt, track.dcaZ()); hist.fill(HIST(Dire[Mode]) + HIST("h2_DcaXY"), pt, track.dcaXY()); - hist.fill(HIST(Dire[Mode]) + HIST("h2_TPCNsigma_El"), track.p(), track.tpcNSigmaEl()); - hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFNsigma_El"), track.p(), track.tofNSigmaEl()); hist.fill(HIST(Dire[Mode]) + HIST("h2_TPCNsigma"), track.p(), nSigmaTPC); hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFNsigma"), track.p(), nSigmaTOF); hist.fill(HIST(Dire[Mode]) + HIST("h2_TpcTofNsigma"), nSigmaTPC, nSigmaTOF); hist.fill(HIST(Dire[Mode]) + HIST("h2_TPCSignal"), track.p(), track.tpcSignal()); + hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); hist.fill(HIST(Dire[Mode]) + HIST("h2_TOFSignal"), track.p(), track.beta()); hist.fill(HIST(Dire[Mode]) + HIST("h2_pvsm2"), track.mass() * track.mass(), track.p()); + hist.fill(HIST("QA/after/h2_TPCSignal"), track.p(), track.tpcSignal()); + hist.fill(HIST("QA/after/innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); hist.fill(HIST("QA/after/h2_TOFSignal"), track.p(), track.beta()); hist.fill(HIST("QA/after/h2_pvsm2"), track.mass() * track.mass(), track.p()); - - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCNsigma_El"), track.tpcInnerParam(), track.tpcNSigmaEl()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TOFNsigma_El"), track.tpcInnerParam(), track.tofNSigmaEl()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCNsigma"), track.tpcInnerParam(), nSigmaTPC); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TOFNsigma"), track.tpcInnerParam(), nSigmaTOF); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TpcTofNsigma"), nSigmaTPC, nSigmaTOF); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_TOFSignal"), track.tpcInnerParam(), track.beta()); - hist.fill(HIST(Dire[Mode]) + HIST("innerParam/h2_pvsm2"), track.mass() * track.mass(), track.tpcInnerParam()); - hist.fill(HIST("QA/after/innerParam/h2_TPCSignal"), track.tpcInnerParam(), track.tpcSignal()); - hist.fill(HIST("QA/after/innerParam/h2_TOFSignal"), track.tpcInnerParam(), track.beta()); - hist.fill(HIST("QA/after/innerParam/h2_pvsm2"), track.mass() * track.mass(), track.tpcInnerParam()); } template - void fillPtMCHist(double pt, double eta, double rap, int nFT0M, int pid, int pdgCodePos, int pdgCodeNeg) + void fillPtMCHist(bool cfgGen, float pt, float eta, float rap, float phi, float centFT0M, int pid, int pdgCodePos, int pdgCodeNeg) { - hist.fill(HIST(Dire[Mode]) + HIST("h_PtTruth"), pt); - hist.fill(HIST(Dire[Mode]) + HIST("h_PtTruth2"), pt * pt); - hist.fill(HIST(Dire[Mode]) + HIST("h_EtaTruth"), eta); - hist.fill(HIST(Dire[Mode]) + HIST("h_RapTruth"), rap); - hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_NFT0M"), pt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_Rap"), rap, pt); - hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_Eta"), eta, pt); + if (cfgGen) { + hist.fill(HIST(Dire[Mode]) + HIST("h_EtaTruth"), eta); + hist.fill(HIST(Dire[Mode]) + HIST("h_RapTruth"), rap); + hist.fill(HIST(Dire[Mode]) + HIST("h2_PtTruth_centFT0M"), centFT0M, pt); + hist.fill(HIST(Dire[Mode]) + HIST("h2_Pt_EtaTruth"), eta, pt); + hist.fill(HIST(Dire[Mode]) + HIST("h_PhiTruth"), phi); + hist.fill(HIST(Dire[Mode]) + HIST("h_PtEtaPhiTruth"), pt, eta, phi); + } if (pid == pdgCodePos) { hist.fill(HIST(Dire[Mode]) + HIST("h_PtPosTruth"), pt); @@ -839,420 +688,303 @@ struct MeanPtFlucId { } template - void fillAnalysisHistos(int nTPC, int nFT0M, int N, double NW, double Q1, double Q2, double Q3, double Q4) + void fillAnalysisHistos(bool cfgCorrection, float centFT0M, double nW, double nW2, double Q1, double Q2) { - if (NW == 0) { + if (nW == 0) { return; } - double twopart1 = ((Q1 * Q1) - Q2); - double threepart1 = ((Q1 * Q1 * Q1) - (3 * Q2 * Q1) + 2 * Q3); - double fourpart1 = ((Q1 * Q1 * Q1 * Q1) - (6 * Q2 * Q1 * Q1) + (3 * Q2 * Q2) + (8 * Q3 * Q1) - 6 * Q4); - - hist.fill(HIST(Dire[Mode]) + HIST("h_Mult"), N); - hist.fill(HIST(Dire[Mode]) + HIST("h_Mult_weighted"), NW); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q1"), nTPC, Q1, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q2"), nTPC, Q2, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q3"), nTPC, Q3, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_Q4"), nTPC, Q4, nFT0M); - - if (NW > 1) { - double meanPt = Q1 / NW; - double nPair = (NW * (NW - 1)); - double twopart = twopart1 / nPair; - double checkNDenoVar = (1 / std::sqrt(1 - (1 / NW))); - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT"), meanPt); - hist.fill(HIST(Dire[Mode]) + HIST("p_mean_pT_Mult_var"), nTPC, meanPt); - hist.fill(HIST(Dire[Mode]) + HIST("p_mean_pT_MultFT0M"), nFT0M, meanPt); - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_var"), nTPC, meanPt, nFT0M); - - hist.fill(HIST(Dire[Mode]) + HIST("h_Q1_var"), nTPC, Q1, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_N_var"), nTPC, N, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_nume_Mult_var"), nTPC, twopart1, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_deno_Mult_var"), nTPC, nPair, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_var"), nTPC, twopart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("p_CheckNCh"), nTPC, checkNDenoVar); - hist.fill(HIST(Dire[Mode]) + HIST("h_CheckNCh"), nTPC, checkNDenoVar, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("p_twopart_MultFT0M"), nFT0M, twopart); - - if (NW > 2) { - double nTriplet = (NW * (NW - 1) * (NW - 2)); - double threepart = threepart1 / nTriplet; - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_skew"), nTPC, meanPt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_skew"), nTPC, twopart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_threepart_Mult_skew"), nTPC, threepart, nFT0M); - - if (NW > 3) { - double nQuad = (NW * (NW - 1) * (NW - 2) * (NW - 3)); - double fourpart = fourpart1 / nQuad; - hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_kurto"), nTPC, meanPt, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_kurto"), nTPC, twopart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_threepart_Mult_kurto"), nTPC, threepart, nFT0M); - hist.fill(HIST(Dire[Mode]) + HIST("h_fourpart_Mult_kurto"), nTPC, fourpart, nFT0M); - } - } - } - } - template - void fillMeanPt(int N, int nFT0M, double pt, float w) - { - hist.fill(HIST(Dire[Mode]) + HIST("h2_pt_nch"), N, pt, w); - hist.fill(HIST(Dire[Mode]) + HIST("h2_pt_nch_prof"), N, pt, w); - hist.fill(HIST(Dire[Mode]) + HIST("h3_nft0m_pt_nch"), N, pt, nFT0M, w); - } + hist.fill(HIST(Dire[Mode]) + HIST("h_Mult"), nW); - template - void fillHistos(T const& col, U const& tracks) - { - int nCh = 0, nTPC = 0, nFT0M = 0; - double centFT0M = 0, vtxZ = 0, vtxZSim = 0; - double nChW = 0; - - int nPi = 0, nKa = 0, nPr = 0; - double nPiW = 0, nKaW = 0, nPrW = 0; - double ptCh = 0, q1Ch = 0, q2Ch = 0, q3Ch = 0, q4Ch = 0; - double ptPi = 0, q1Pi = 0, q2Pi = 0, q3Pi = 0, q4Pi = 0; - double ptPr = 0, q1Pr = 0, q2Pr = 0, q3Pr = 0, q4Pr = 0; - double ptKa = 0, q1Ka = 0, q2Ka = 0, q3Ka = 0, q4Ka = 0; - - int nChSim = 0, nSim = 0, nFT0CSim = 0; - int nPiSim = 0, nKaSim = 0, nPrSim = 0; - double eta = 0, etaSim = -999, rapSim = -999; - double ptChSim = 0, q1ChSim = 0, q2ChSim = 0, q3ChSim = 0, q4ChSim = 0; - double ptPiSim = 0, q1PiSim = 0, q2PiSim = 0, q3PiSim = 0, q4PiSim = 0; - double ptPrSim = 0, q1PrSim = 0, q2PrSim = 0, q3PrSim = 0, q4PrSim = 0; - double ptKaSim = 0, q1KaSim = 0, q2KaSim = 0, q3KaSim = 0, q4KaSim = 0; - - float wghtCh = 1.0, wghtPi = 1.0, wghtKa = 1.0, wghtPr = 1.0; + double nPair = 0., meanPt = 0., twopart1 = 0., twopart = 0.; - if constexpr (DataFlag) { - nTPC = col.multNTracksHasTPC(); - nFT0M = col.multFT0M(); - centFT0M = col.centFT0M(); - vtxZ = col.posZ(); - - fillAfterQAHistos(col); - for (const auto& track : tracks) { - if (!selTrack(track)) { - continue; - } - - double nSigmaTPCPi = track.tpcNSigmaPi(); - double nSigmaTPCKa = track.tpcNSigmaKa(); - double nSigmaTPCPr = track.tpcNSigmaPr(); - double nSigmaTOFPi = track.tofNSigmaPi(); - double nSigmaTOFKa = track.tofNSigmaKa(); - double nSigmaTOFPr = track.tofNSigmaPr(); - double rapPi = track.rapidity(MassPiPlus); - double rapKa = track.rapidity(MassKPlus); - double rapPr = track.rapidity(MassProton); - - if (std::fabs(track.eta()) < 0.8) { - ptCh = track.pt(); - wghtCh = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtRap, hWeightPtEta, ptCh, 0.0, eta, cfgWeightPtCh, false, false, false); - nChW += wghtCh; - nCh++; - moments(ptCh, wghtCh, q1Ch, q2Ch, q3Ch, q4Ch); - - hist.fill(HIST("QA/after/h_Pt_weighted"), ptCh, wghtCh); - hist.fill(HIST("QA/after/h_Pt2_weighted"), ptCh * ptCh, wghtCh); + if (cfgCorrection) { + nPair = nW * nW - nW2; + } else { + if (nW > 1) { + nPair = nW * (nW - 1); + } + } - fillChargedQAHistos(track, nFT0M, centFT0M); + if (nPair > 0) { + meanPt = Q1 / nW; + twopart1 = (Q1 * Q1 - Q2); + twopart = twopart1 / nPair; - fillBeforePIDQAHistos(track); + hist.fill(HIST(Dire[Mode]) + HIST("h_mean_pT_Mult_var"), centFT0M, meanPt); + hist.fill(HIST(Dire[Mode]) + HIST("h_twopart_Mult_var"), centFT0M, twopart); + hist.fill(HIST(Dire[Mode]) + HIST("p_mean_pT_CentFT0M"), centFT0M, meanPt); + hist.fill(HIST(Dire[Mode]) + HIST("p_twopart_CentFT0M"), centFT0M, twopart); + hist.fill(HIST(Dire[Mode]) + HIST("h_twopart1_CentFT0M"), centFT0M, twopart1); + } - if (rejectTracks(track)) { - return; - } + hist.fill(HIST(Dire[Mode]) + HIST("h_Mult"), nW); + hist.fill(HIST(Dire[Mode]) + HIST("h_N_CentFT0M"), centFT0M, nW); + hist.fill(HIST(Dire[Mode]) + HIST("h_Npair_CentFT0M"), centFT0M, nPair); + hist.fill(HIST(Dire[Mode]) + HIST("h_Q1_CentFT0M"), centFT0M, Q1); + hist.fill(HIST(Dire[Mode]) + HIST("h_Q2_CentFT0M"), centFT0M, Q2); + } - if (selPi(track)) { - fillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi, nFT0M, centFT0M, hWeightPtPi, hPurePtPi, hWeightPtRapPi, hWeightPtEtaPi, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPi, nPiW, q1Pi, q2Pi, q3Pi, q4Pi, wghtPi); - } + template + void fillRecoHistos(C const& col, T const& tracks) + { + double nChW = 0., nChW2 = 0., q1Ch = 0., q2Ch = 0.; + float wghtCh = 1.0; + double nPiW = 0., nPiW2 = 0., q1Pi = 0., q2Pi = 0.; + double nKaW = 0., nKaW2 = 0., q1Ka = 0., q2Ka = 0.; + double nPrW = 0., nPrW2 = 0., q1Pr = 0., q2Pr = 0.; + float pt = 0., eta = 0., phi = 0.; - if (selKa(track)) { - fillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa, nFT0M, centFT0M, hWeightPtKa, hPurePtKa, hWeightPtRapKa, hWeightPtEtaKa, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nKa, nKaW, q1Ka, q2Ka, q3Ka, q4Ka, wghtKa); - } + hist.fill(HIST("QA/h_collisions_info"), kTotCol); - if (selPr(track)) { - fillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr, nFT0M, centFT0M, hWeightPtPr, hPurePtPr, hWeightPtRapPr, hWeightPtEtaPr, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPr, nPrW, q1Pr, q2Pr, q3Pr, q4Pr, wghtPr); - } - } - } - } else if constexpr (RecoFlag) { - if (!col.has_mcCollision()) { - LOGF(warning, "No MC collision for this collision, skip..."); + if constexpr (DataFlag) { + if (!selRun3Col(col)) { return; } - nTPC = col.multNTracksHasTPC(); - nFT0M = col.multFT0M(); - centFT0M = col.centFT0M(); - vtxZ = col.posZ(); + } - fillAfterQAHistos(col); + hist.fill(HIST("QA/h_collisions_info"), kPassSelCol); - vtxZSim = col.mcCollision().posZ(); - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - LOGF(warning, "No MC Particle for this track, skip..."); - continue; - } - auto mcPart = track.mcParticle(); - int pid = mcPart.pdgCode(); - - double nSigmaTPCPi = track.tpcNSigmaPi(); - double nSigmaTPCKa = track.tpcNSigmaKa(); - double nSigmaTPCPr = track.tpcNSigmaPr(); - double nSigmaTOFPi = track.tofNSigmaPi(); - double nSigmaTOFKa = track.tofNSigmaKa(); - double nSigmaTOFPr = track.tofNSigmaPr(); - double rapPi = track.rapidity(MassPiPlus); - double rapKa = track.rapidity(MassKPlus); - double rapPr = track.rapidity(MassProton); - - //______________________________Reconstructed Level____________________________________________________// - - if (selTrack(track)) { - - eta = track.eta(); - ptCh = track.pt(); - wghtCh = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtRap, hWeightPtEta, ptCh, 0.0, eta, cfgWeightPtCh, false, false, false); - nChW += wghtCh; - nCh++; - moments(ptCh, wghtCh, q1Ch, q2Ch, q3Ch, q4Ch); - fillChargedQAHistos(track, nFT0M, centFT0M); - - hist.fill(HIST("QA/after/h_Pt_weighted"), ptCh, wghtCh); - hist.fill(HIST("QA/after/h_Pt2_weighted"), ptCh * ptCh, wghtCh); - - fillBeforePIDQAHistos(track); - - if (cfgRejTrk == true && rejectTracks(track)) { - return; - } - - if (selPi(track)) { - ptPi = track.pt(); - fillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi, nFT0M, centFT0M, hWeightPtPi, hPurePtPi, hWeightPtRapPi, hWeightPtEtaPi, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPi, nPiW, q1Pi, q2Pi, q3Pi, q4Pi, wghtPi); - if (std::abs(pid) == kPiPlus) { - fillPtMCHist(ptPi, eta, rapPi, nFT0M, pid, kPiPlus, kPiMinus); - } - } - if (selKa(track)) { - ptKa = track.pt(); - fillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa, nFT0M, centFT0M, hWeightPtKa, hPurePtKa, hWeightPtRapKa, hWeightPtEtaKa, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nKa, nKaW, q1Ka, q2Ka, q3Ka, q4Ka, wghtKa); - if (std::abs(pid) == kKPlus) { - fillPtMCHist(ptKa, eta, rapKa, nFT0M, pid, kKPlus, kKMinus); - } - } + fillAfterQAHistos(col); - if (selPr(track)) { - ptPr = track.pt(); - fillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr, nFT0M, centFT0M, hWeightPtPr, hPurePtPr, hWeightPtRapPr, hWeightPtEtaPr, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId, nPr, nPrW, q1Pr, q2Pr, q3Pr, q4Pr, wghtPr); - if (std::abs(pid) == kProton) { - fillPtMCHist(ptPr, eta, rapPr, nFT0M, pid, kProton, kProtonBar); - } - } - } + for (auto const& track : tracks) { + float nSigmaTPCPi = track.tpcNSigmaPi(); + float nSigmaTPCKa = track.tpcNSigmaKa(); + float nSigmaTPCPr = track.tpcNSigmaPr(); + float nSigmaTOFPi = track.tofNSigmaPi(); + float nSigmaTOFKa = track.tofNSigmaKa(); + float nSigmaTOFPr = track.tofNSigmaPr(); + float rapPi = track.rapidity(MassPiPlus); + float rapKa = track.rapidity(MassKPlus); + float rapPr = track.rapidity(MassProton); - //___________________________________Truth Level____________________________________________________// - if (!mcPart.isPhysicalPrimary()) { - continue; - } - auto charge = 0.; - auto* pd = pdg->GetParticle(pid); - if (pd != nullptr) { - charge = pd->Charge(); - } - if (std::fabs(charge) < 1e-3) { - continue; - } - if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { + if constexpr (RecoFlag) { + if (!track.has_mcParticle()) { + hist.fill(HIST("Tracks/h_tracks_info"), kTracksBeforeHasMcParticle); continue; } + } + hist.fill(HIST("Tracks/h_tracks_info"), kAllTracks); - if (std::fabs(mcPart.eta()) < 0.8) { - nSim++; + if (!selTrack(track)) { + continue; + } + hist.fill(HIST("Tracks/h_tracks_info"), kAllSelPassed); + + pt = track.pt(); + if constexpr (RecoFlag) { + hist.fill(HIST("Tracks/h2_tracks_pid_before_sel"), track.mcParticle().pdgCode(), track.pt()); + + auto mc = track.template mcParticle_as(); + pt = mc.pt(); + eta = mc.eta(); + phi = mc.phi(); + + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/after/h_DCAxy_primary"), track.dcaXY()); + hist.fill(HIST("QA/after/h_DCAz_primary"), track.dcaZ()); + } else { + hist.fill(HIST("QA/after/h_DCAxy_secondary"), track.dcaXY()); + hist.fill(HIST("QA/after/h_DCAz_secondary"), track.dcaZ()); } + } - if (mcPart.eta() > -3.3 || mcPart.eta() < -2.1) { - nFT0CSim++; - } + // Charged particles: + wghtCh = getCorrectedWeight(hWeightPt, hPurePt, pt, cfgWeightPtCh, false); - if (mcPart.pt() > cfgCutPtMin && mcPart.pt() < cfgCutPtMax) { - - if (std::abs(mcPart.eta()) < 0.8) { - nChSim++; - ptChSim = mcPart.pt(); - etaSim = mcPart.eta(); - moments(ptChSim, 1.0, q1ChSim, q2ChSim, q3ChSim, q4ChSim); - hist.fill(HIST("Gen/Charged/h_PtTruth"), ptChSim); - hist.fill(HIST("Gen/Charged/h_PtTruth2"), ptChSim * ptChSim); - hist.fill(HIST("Gen/Charged/h2_PtTruth_NFT0M"), ptChSim, nFT0M); - hist.fill(HIST("Gen/Charged/h2_PtTruth_Eta"), etaSim, ptChSim); - hist.fill(HIST("Gen/Charged/h_EtaTruth"), etaSim); - hist.fill(HIST("Gen/Charged/h_PhiTruth"), mcPart.phi()); - - hist.fill(HIST("Gen/Charged/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Charged/h_PtEtaPhi_NFT0M"), ptChSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Charged/h_PtEtaPhi_centFT0M"), ptChSim, etaSim, mcPart.phi(), centFT0M); - - if (std::abs(pid) == kPiPlus && mcPart.pt() >= cfgCutPiPtMin) { - rapSim = mcPart.y(); - nPiSim++; - ptPiSim = mcPart.pt(); - moments(ptPiSim, 1.0, q1PiSim, q2PiSim, q3PiSim, q4PiSim); - fillPtMCHist(ptPiSim, etaSim, rapSim, nFT0M, pid, kPiPlus, kPiMinus); - - hist.fill(HIST("Gen/Pion/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Pion/h_PtEtaPhi_NFT0M"), ptPiSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Pion/h_PtEtaPhi_centFT0M"), ptPiSim, etaSim, mcPart.phi(), centFT0M); - } + if (std::abs(wghtCh) < cfgMinWeight) + return; - if (std::abs(pid) == kKPlus && mcPart.pt() >= cfgCutKaPtMin) { - nKaSim++; - ptKaSim = mcPart.pt(); - moments(ptKaSim, 1.0, q1KaSim, q2KaSim, q3KaSim, q4KaSim); - fillPtMCHist(ptKaSim, etaSim, rapSim, nFT0M, pid, kKPlus, kKMinus); + nChW += wghtCh; + nChW2 += wghtCh * wghtCh; + moments(pt, wghtCh, q1Ch, q2Ch); + hist.fill(HIST("QA/Charged/h_Pt"), track.pt()); + fillChargedQAHistos(track, centFT0M); - hist.fill(HIST("Gen/Kaon/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Kaon/h_PtEtaPhi_NFT0M"), ptKaSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Kaon/h_PtEtaPhi_centFT0M"), ptKaSim, etaSim, mcPart.phi(), centFT0M); - } + fillBeforePIDQAHistos(track); - if (std::abs(pid) == kProton && mcPart.pt() >= cfgCutPrPtMin) { - nPrSim++; - ptPrSim = mcPart.pt(); - moments(ptPrSim, 1.0, q1PrSim, q2PrSim, q3PrSim, q4PrSim); - fillPtMCHist(ptPrSim, etaSim, rapSim, nFT0M, pid, kProton, kProtonBar); + // identified particles: + if (cfgRejTrk && rejectTracks(track)) { + continue; + } + auto selIDPion = identifyParticle(track, cfgCutPiThrsldP); + auto selIDKaon = identifyParticle(track, cfgCutKaThrsldP); + auto selIDProton = identifyParticle(track, cfgCutPrThrsldP); + if (selIDPion && pt >= cfgCutPiPtMin) { + hist.fill(HIST("QA/Pion/h_Pt"), track.pt()); + fillIdParticleQAHistos(track, rapPi, nSigmaTPCPi, nSigmaTOFPi, centFT0M, hWeightPtPi, hPurePtPi, cfgWeightPtId, cfgPurityId, nPiW, nPiW2, q1Pi, q2Pi); + } + if (selIDKaon && pt >= cfgCutKaPtMin) { + hist.fill(HIST("QA/Kaon/h_Pt"), track.pt()); + fillIdParticleQAHistos(track, rapKa, nSigmaTPCKa, nSigmaTOFKa, centFT0M, hWeightPtKa, hPurePtKa, cfgWeightPtId, cfgPurityId, nKaW, nKaW2, q1Ka, q2Ka); + } + if (selIDProton && pt >= cfgCutPrPtMin) { + hist.fill(HIST("QA/Proton/h_Pt"), track.pt()); + fillIdParticleQAHistos(track, rapPr, nSigmaTPCPr, nSigmaTOFPr, centFT0M, hWeightPtPr, hPurePtPr, cfgWeightPtId, cfgPurityId, nPrW, nPrW2, q1Pr, q2Pr); + } - hist.fill(HIST("Gen/Proton/h_PhiTruth"), mcPart.phi()); - hist.fill(HIST("Gen/Proton/h_PtEtaPhi_NFT0M"), ptPrSim, etaSim, mcPart.phi(), nFT0M); - hist.fill(HIST("Gen/Proton/h_PtEtaPhi_centFT0M"), ptPrSim, etaSim, mcPart.phi(), centFT0M); + if constexpr (RecoFlag) { + auto mc = track.template mcParticle_as(); + int pid = mc.pdgCode(); + if (selIDPion && pt >= cfgCutPiPtMin) { + if (std::abs(pid) == kPiPlus) { + hist.fill(HIST("QA/Pion/h_PtTruth"), pt); + fillPtMCHist(false, pt, eta, rapPi, phi, centFT0M, pid, kPiPlus, kPiMinus); + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/Pion/h_PtTruth_primary"), pt); + } else { + hist.fill(HIST("QA/Pion/h_PtTruth_secondary"), pt); } } } - } - - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - LOGF(warning, "No MC Particle for this track, skip..."); - continue; - } - auto mcPart = track.mcParticle(); - int pid = mcPart.pdgCode(); - - if (selTrack(track)) { - double pt = track.pt(); - double eta = track.eta(); - float wght = getCorrectedWeight(hWeightPt, hPurePt, hWeightPtRap, hWeightPtEta, pt, 0.0, eta, cfgWeightPtCh, false, false, false); - fillMeanPt(nCh, nFT0M, pt, wght); - - if (selPi(track)) { - float wghtId = getCorrectedWeight(hWeightPtPi, hPurePtPi, hWeightPtRapPi, hWeightPtEtaPi, pt, 0.0, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - fillMeanPt(nPi, nFT0M, pt, wghtId); - } - if (selKa(track)) { - float wghtId = getCorrectedWeight(hWeightPtKa, hPurePtKa, hWeightPtRapKa, hWeightPtEtaKa, pt, 0.0, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - fillMeanPt(nKa, nFT0M, pt, wghtId); - } - if (selPr(track)) { - float wghtId = getCorrectedWeight(hWeightPtPr, hPurePtPr, hWeightPtRapPr, hWeightPtEtaPr, pt, 0.0, eta, cfgWeightPtId, cfgWeightPtYId, cfgWeightPtEtaId, cfgPurityId); - fillMeanPt(nPr, nFT0M, pt, wghtId); + if (selIDKaon && pt >= cfgCutKaPtMin) { + if (std::abs(pid) == kKPlus) { + hist.fill(HIST("QA/Kaon/h_PtTruth"), pt); + fillPtMCHist(false, pt, eta, rapKa, phi, centFT0M, pid, kKPlus, kKMinus); + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/Kaon/h_PtTruth_primary"), pt); + } else { + hist.fill(HIST("QA/Kaon/h_PtTruth_secondary"), pt); + } } } - - if (!mcPart.isPhysicalPrimary()) { - continue; - } - auto charge = 0.; - auto* pd = pdg->GetParticle(pid); - if (pd != nullptr) { - charge = pd->Charge(); - } - if (std::fabs(charge) < 1e-3) { - continue; - } - if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { - continue; - } - - if (mcPart.pt() > cfgCutPtMin && mcPart.pt() < cfgCutPtMax) { - - if (std::abs(mcPart.eta()) < 0.8) { - double pt = mcPart.pt(); - float wght = 1.0; - fillMeanPt(nChSim, nFT0M, pt, wght); - - if (std::abs(pid) == kPiPlus && mcPart.pt() >= cfgCutPiPtMin) { - fillMeanPt(nPiSim, nFT0M, pt, wght); - } - if (std::abs(pid) == kKPlus && mcPart.pt() >= cfgCutKaPtMin) { - fillMeanPt(nKaSim, nFT0M, pt, wght); - } - if (std::abs(pid) == kProton && mcPart.pt() >= cfgCutPrPtMin) { - fillMeanPt(nPrSim, nFT0M, pt, wght); + if (selIDProton && pt >= cfgCutPrPtMin) { + if (std::abs(pid) == kProton) { + hist.fill(HIST("QA/Proton/h_PtTruth"), pt); + fillPtMCHist(false, pt, eta, rapPr, phi, centFT0M, pid, kProton, kProtonBar); + if (mc.isPhysicalPrimary()) { + hist.fill(HIST("QA/Proton/h_PtTruth_primary"), pt); + } else { + hist.fill(HIST("QA/Proton/h_PtTruth_secondary"), pt); } } } } + } + fillAnalysisHistos(cfgCorrection, centFT0M, nChW, nChW2, q1Ch, q2Ch); + fillAnalysisHistos(cfgCorrection, centFT0M, nPiW, nPiW2, q1Pi, q2Pi); + fillAnalysisHistos(cfgCorrection, centFT0M, nKaW, nKaW2, q1Ka, q2Ka); + fillAnalysisHistos(cfgCorrection, centFT0M, nPrW, nPrW2, q1Pr, q2Pr); + } - hist.fill(HIST("Gen/h_Counts"), 2); - hist.fill(HIST("QA/after/h_VtxZReco"), vtxZ); - hist.fill(HIST("Gen/h_VtxZ"), vtxZSim); - - if (nSim > 0) - hist.fill(HIST("Gen/h_NSim"), nSim); + template + void fillGenHistos(C const& mcCol, M const& mcParticles) + { + int nSim = 0; + double nChSim = 0., q1ChSim = 0., q2ChSim = 0.; + double nPiSim = 0., q1PiSim = 0., q2PiSim = 0.; + double nKaSim = 0., q1KaSim = 0., q2KaSim = 0.; + double nPrSim = 0., q1PrSim = 0., q2PrSim = 0.; + float pt = 0, eta = 0, phi = 0, rap = 0; + for (auto const& mcPart : mcParticles) { + if (!mcPart.isPhysicalPrimary()) { + continue; + } - if (nSim > 0 && nChSim > 0) - hist.fill(HIST("Gen/h2_NChSim_NSim"), nSim, nChSim); + auto pid = mcPart.pdgCode(); + if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { + continue; + } - if (nSim > 0 && nTPC > 0) - hist.fill(HIST("Gen/h2_NTPC_NSim"), nSim, nTPC); + pt = mcPart.pt(); + eta = mcPart.eta(); + phi = mcPart.phi(); + if (std::abs(eta) < cfgCutEta) { + nSim++; + } - hist.fill(HIST("Gen/h_NTPC"), nTPC); - hist.fill(HIST("Gen/h_NFT0C"), nFT0CSim); - hist.fill(HIST("Gen/h2_NTPC_NFT0M"), nFT0M, nTPC); + if (pt >= cfgCutPtMin && pt < cfgCutPtMax && std::abs(eta) < cfgCutEta) { + nChSim++; + moments(pt, 1.0, q1ChSim, q2ChSim); + hist.fill(HIST("Gen/Charged/h_PtTruth"), pt); + hist.fill(HIST("Gen/Charged/h_EtaTruth"), eta); + hist.fill(HIST("Gen/Charged/h_PhiTruth"), phi); + hist.fill(HIST("Gen/Charged/h2_Pt_EtaTruth"), eta, pt); + hist.fill(HIST("Gen/Charged/h2_PtTruth_centFT0M"), centFT0M, pt); + hist.fill(HIST("Gen/Charged/h_PtEtaPhiTruth"), pt, eta, phi); + + rap = mcPart.y(); + if (std::abs(pid) == kPiPlus && mcPart.pt() > cfgCutPiPtMin) { + nPiSim++; + moments(pt, 1.0, q1PiSim, q2PiSim); + hist.fill(HIST("Gen/Pion/h_PtTruth"), pt); + fillPtMCHist(true, pt, eta, rap, phi, centFT0M, pid, kPiMinus, kPiMinus); + } + if (std::abs(pid) == kKPlus && mcPart.pt() > cfgCutKaPtMin) { + nKaSim++; + moments(pt, 1.0, q1KaSim, q2KaSim); + hist.fill(HIST("Gen/Kaon/h_PtTruth"), pt); + fillPtMCHist(true, pt, eta, rap, phi, centFT0M, pid, kKMinus, kKMinus); + } + if (std::abs(pid) == kProton && mcPart.pt() > cfgCutPrPtMin) { + nPrSim++; + moments(pt, 1.0, q1PrSim, q2PrSim); + hist.fill(HIST("Gen/Proton/h_PtTruth"), pt); + fillPtMCHist(true, pt, eta, rap, phi, centFT0M, pid, kProtonBar, kProtonBar); + } + } + } + fillAnalysisHistos(false, centFT0M, nChSim, nChSim, q1ChSim, q2ChSim); + fillAnalysisHistos(false, centFT0M, nPiSim, nPiSim, q1PiSim, q2PiSim); + fillAnalysisHistos(false, centFT0M, nKaSim, nKaSim, q1KaSim, q2KaSim); + fillAnalysisHistos(false, centFT0M, nPrSim, nPrSim, q1PrSim, q2PrSim); + hist.fill(HIST("Gen/h_Counts"), 2); + hist.fill(HIST("Gen/h_VtxZ"), mcCol.posZ()); + hist.fill(HIST("Gen/h_NSim"), nSim); + hist.fill(HIST("Gen/h2_NTPC_NSim"), nSim, nTPC); + } - double nChSim1 = static_cast(nChSim); - double nPiSim1 = static_cast(nPiSim); - double nKaSim1 = static_cast(nKaSim); - double nPrSim1 = static_cast(nPrSim); + template + void analyzeMC(M const& mcCol, C const& cols, T const& tracks, P const& mcParts) + { + // fillBeforeQAHistos(cols.begin(), tracks); + hist.fill(HIST("Gen/h_VtxZ_b"), mcCol.posZ()); + int nRecCols = cols.size(); + if (nRecCols == 0) { + hist.fill(HIST("Gen/h_collision_recgen"), nRecCols); + } + // Do not analyze if more than one reco collision is accociated to one mc gen collision + if (nRecCols != 1) { + return; + } + hist.fill(HIST("Gen/h_collisions_info"), kTotCol); - fillAnalysisHistos(nTPC, nFT0M, nChSim, nChSim1, q1ChSim, q2ChSim, q3ChSim, q4ChSim); - fillAnalysisHistos(nTPC, nFT0M, nPiSim, nPiSim1, q1PiSim, q2PiSim, q3PiSim, q4PiSim); - fillAnalysisHistos(nTPC, nFT0M, nKaSim, nKaSim1, q1KaSim, q2KaSim, q3KaSim, q4KaSim); - fillAnalysisHistos(nTPC, nFT0M, nPrSim, nPrSim1, q1PrSim, q2PrSim, q3PrSim, q4PrSim); + // Check the reco collision + if (!cols.begin().has_mcCollision() || !selRun3Col(cols.begin()) || cols.begin().mcCollisionId() != mcCol.globalIndex()) { + return; } - fillAnalysisHistos(nTPC, nFT0M, nCh, nChW, q1Ch, q2Ch, q3Ch, q4Ch); - fillAnalysisHistos(nTPC, nFT0M, nPi, nPiW, q1Pi, q2Pi, q3Pi, q4Pi); - fillAnalysisHistos(nTPC, nFT0M, nKa, nKaW, q1Ka, q2Ka, q3Ka, q4Ka); - fillAnalysisHistos(nTPC, nFT0M, nPr, nPrW, q1Pr, q2Pr, q3Pr, q4Pr); + hist.fill(HIST("Gen/h_collisions_info"), kPassSelCol); + hist.fill(HIST("Gen/h2_collision_posZ"), mcCol.posZ(), cols.begin().posZ()); + + auto sTracks = tracks.sliceBy(perCollision, cols.begin().globalIndex()); + fillRecoHistos(cols.begin(), sTracks); + fillGenHistos(mcCol, mcParts); } + using MyAllTracks = soa::Join; + using MyRun3Collisions = soa::Join; + using MyRun3MCCollisions = soa::Join; + using MyMCTracks = soa::Join; + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + void processRun3(MyRun3Collisions::iterator const& col, MyAllTracks const& tracks) { - // Before Collision and Track Cuts: fillBeforeQAHistos(col, tracks); - - // After Collision and Track Cuts: - if (selRun3Col(col)) { - fillHistos(col, tracks); - } + fillRecoHistos(col, tracks); } PROCESS_SWITCH(MeanPtFlucId, processRun3, "Process for Run-3", false); - void processMCRecoSimRun3(MyRun3MCCollisions::iterator const& col, aod::McCollisions const&, MyMCTracks const& tracks, aod::McParticles const&) + void processMCRecoSimRun3(aod::McCollisions::iterator const& mcCol, soa::SmallGroups const& cols, MyMCTracks const& tracks, aod::McParticles const& mcParts) { - // Before Collision and Track Cuts: - fillBeforeQAHistos(col, tracks); - - hist.fill(HIST("Gen/h_VtxZ_b"), col.mcCollision().posZ()); - - // After Collision and Track Cuts: - if (selRun3Col(col)) { - fillHistos(col, tracks); - } + analyzeMC(mcCol, cols, tracks, mcParts); } PROCESS_SWITCH(MeanPtFlucId, processMCRecoSimRun3, "process MC Reconstructed & Truth Run-3", true); }; diff --git a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx index f94b6161330..c33bdd9cb22 100644 --- a/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx +++ b/PWGCF/EbyEFluctuations/Tasks/netchargeFluctuations.cxx @@ -15,33 +15,38 @@ /// For RUN-3 /// /// \author Nida Malik -#include // Include for std::vector +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.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/PIDResponse.h" -#include "Common/Core/trackUtilities.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/Core/TrackSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/MathConstants.h" -#include "Common/DataModel/FT0Corrected.h" -#include "Framework/AnalysisDataModel.h" +#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "Common/CCDB/TriggerAliases.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "CommonConstants/PhysicsConstants.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" + #include "TProfile.h" #include "TProfile2D.h" #include "TRandom3.h" +#include +#include // Include for std::vector + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -52,50 +57,6 @@ namespace o2 { namespace aod { -namespace net_charge -{ -DECLARE_SOA_COLUMN(PosCharge, posCharge, float); -DECLARE_SOA_COLUMN(NegCharge, negCharge, float); -DECLARE_SOA_COLUMN(PosSqCharge, posSqCharge, float); -DECLARE_SOA_COLUMN(NegSqCharge, negSqCharge, float); -DECLARE_SOA_COLUMN(TermPCharge, termPCharge, float); -DECLARE_SOA_COLUMN(TermNCharge, termNCharge, float); -DECLARE_SOA_COLUMN(PosNegCharge, posNegCharge, float); -DECLARE_SOA_COLUMN(Centrality, centrality, float); -} // namespace net_charge - -namespace net_charge_gen -{ -DECLARE_SOA_COLUMN(PosCharge, posCharge, float); -DECLARE_SOA_COLUMN(NegCharge, negCharge, float); -DECLARE_SOA_COLUMN(PosSqCharge, posSqCharge, float); -DECLARE_SOA_COLUMN(NegSqCharge, negSqCharge, float); -DECLARE_SOA_COLUMN(TermPCharge, termPCharge, float); -DECLARE_SOA_COLUMN(TermNCharge, termNCharge, float); -DECLARE_SOA_COLUMN(PosNegCharge, posNegCharge, float); -DECLARE_SOA_COLUMN(Centrality, centrality, float); -} // namespace net_charge_gen - -DECLARE_SOA_TABLE(NetCharge, "AOD", "NETChargefluct", - net_charge::PosCharge, - net_charge::NegCharge, - net_charge::PosSqCharge, - net_charge::NegSqCharge, - net_charge::TermPCharge, - net_charge::TermNCharge, - net_charge::PosNegCharge, - net_charge::Centrality); - -DECLARE_SOA_TABLE(NetChargeGen, "AOD", "NETfluctGen", - net_charge_gen::PosCharge, - net_charge_gen::NegCharge, - net_charge_gen::PosSqCharge, - net_charge_gen::NegSqCharge, - net_charge_gen::TermPCharge, - net_charge_gen::TermNCharge, - net_charge_gen::PosNegCharge, - net_charge_gen::Centrality); - using MyCollisionsRun2 = soa::Join; using MyCollisionRun2 = MyCollisionsRun2::iterator; using MyCollisionsRun3 = soa::Join; @@ -120,15 +81,19 @@ enum RunType { }; struct NetchargeFluctuations { - Produces netCharge; - Produces netChargeGen; Service pdgService; - + Service ccdb; + TRandom3* fRndm = new TRandom3(0); HistogramRegistry histogramRegistry{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Configurables + 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/efftest", "Path for ccdb-object"}; + Configurable cfgLoadEff{"cfgLoadEff", true, "Load efficiency"}; + Configurable vertexZcut{"vertexZcut", 10.f, "Vertex Z"}; - Configurable etaCut{"etaCut", 0.8, "Eta cut"}; + Configurable etaCut{"etaCut", 0.8f, "Eta cut"}; Configurable ptMinCut{"ptMinCut", 0.2, "Pt min cut"}; Configurable ptMaxCut{"ptMaxCut", 5.0, "Pt max cut"}; Configurable dcaXYCut{"dcaXYCut", 0.12, "DCA XY cut"}; @@ -136,98 +101,185 @@ struct NetchargeFluctuations { Configurable tpcCrossCut{"tpcCrossCut", 70, "TPC crossrows cut"}; Configurable itsChiCut{"itsChiCut", 70, "ITS chi2 cluster cut"}; Configurable tpcChiCut{"tpcChiCut", 70, "TPC chi2 cluster cut"}; + Configurable centMin{"centMin", 0.0f, "cenrality min for delta eta"}; + Configurable centMax{"centMax", 10.0f, "cenrality max for delta eta"}; + Configurable cfgNSubsample{"cfgNSubsample", 30, "Number of subsamples for Error"}; + Configurable deltaEta{"deltaEta", 8, "Delta eta bin count"}; + Configurable threshold{"threshold", 1e-6, "Delta eta bin count"}; // Event selections - Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; // sel8 - Configurable cInt7Trig{"cInt7Trig", true, "kINT7 MB Trigger"}; // kINT7 - Configurable cSel7Trig{"cSel7Trig", true, "Sel7 (V0A + V0C) Selection Run2"}; // sel7 - Configurable cTFBorder{"cTFBorder", false, "Timeframe Border Selection"}; // pileup - Configurable cNoItsROBorder{"cNoItsROBorder", false, "No ITSRO Border Cut"}; // pileup - Configurable cItsTpcVtx{"cItsTpcVtx", false, "ITS+TPC Vertex Selection"}; // pileup - Configurable cPileupReject{"cPileupReject", false, "Pileup rejection"}; // pileup - Configurable cZVtxTimeDiff{"cZVtxTimeDiff", false, "z-vtx time diff selection"}; // pileup - Configurable cIsGoodITSLayers{"cIsGoodITSLayers", false, "Good ITS Layers All"}; // pileup + Configurable cSel8Trig{"cSel8Trig", true, "Sel8 (T0A + T0C) Selection Run3"}; // sel8 + Configurable cInt7Trig{"cInt7Trig", true, "kINT7 MB Trigger"}; // kINT7 + Configurable cSel7Trig{"cSel7Trig", true, "Sel7 (V0A + V0C) Selection Run2"}; // sel7 + Configurable cTFBorder{"cTFBorder", false, "Timeframe Border Selection"}; // pileup + Configurable cNoItsROBorder{"cNoItsROBorder", false, "No ITSRO Border Cut"}; // pileup + Configurable cItsTpcVtx{"cItsTpcVtx", false, "ITS+TPC Vertex Selection"}; // pileup + Configurable cPileupReject{"cPileupReject", false, "Pileup rejection"}; // pileup + Configurable cZVtxTimeDiff{"cZVtxTimeDiff", false, "z-vtx time diff selection"}; // pileup + Configurable cfgUseGoodItsLayerAllCut{"cfgUseGoodItsLayerAllCut", false, "Good ITS Layers All"}; // pileup + Configurable cDcaXy{"cDcaXy", false, "Dca XY cut"}; + Configurable cDcaZ{"cDcaZ", false, "Dca Z cut"}; + Configurable cTpcCr{"cTpcCr", false, "tpc crossrows"}; + Configurable cItsChi{"cItsChi", false, "ITS chi"}; + Configurable cTpcChi{"cTpcChi", false, "TPC chi"}; + + // CCDB efficiency histograms + TH2D* efficiency = nullptr; // Initialization - float cent = 0.; - float mult = 0.; void init(o2::framework::InitContext&) { - const AxisSpec vtxzAxis = {80, -20, 20, "V_{Z} (cm)"}; + const AxisSpec vtxzAxis = {800, -20, 20, "V_{Z} (cm)"}; const AxisSpec dcaAxis = {250, -0.5, 0.5, "DCA_{xy} (cm)"}; const AxisSpec dcazAxis = {250, -0.5, 0.5, "DCA_{z} (cm)"}; const AxisSpec ptAxis = {70, 0.0, 7.0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec etaAxis = {20, -1., 1., "#eta"}; + const AxisSpec deltaEtaAxis = {9, 0, 1.8, "#eta"}; const AxisSpec centAxis = {100, 0., 100., "centrality"}; const AxisSpec multAxis = {200, 0., 10000., "FT0M Amplitude"}; - const AxisSpec tpcChiAxis = {140, 0., 7., "Chi2"}; - const AxisSpec itsChiAxis = {80, 0., 40., "Chi2"}; - const AxisSpec crossedRowAxis = {160, 0., 160., "TPC Crossed rows"}; + const AxisSpec tpcChiAxis = {1400, 0., 7., "Chi2"}; + const AxisSpec itsChiAxis = {800, 0., 40., "Chi2"}; + const AxisSpec crossedRowAxis = {1600, 0., 160., "TPC Crossed rows"}; const AxisSpec eventsAxis = {10, 0, 10, ""}; const AxisSpec signAxis = {20, -10, 10, ""}; - - histogramRegistry.add("hVtxZ_before", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("hDcaXY_before", "", kTH1F, {dcaAxis}); - histogramRegistry.add("hDcaZ_before", "", kTH1F, {dcazAxis}); - histogramRegistry.add("hTPCchi2perCluster_before", "", kTH1D, {tpcChiAxis}); - histogramRegistry.add("hITSchi2perCluster_before", "", kTH1D, {itsChiAxis}); - histogramRegistry.add("hTPCCrossedrows_before", "", kTH1D, {crossedRowAxis}); - histogramRegistry.add("hPtDcaXY_before", "", kTH2D, {ptAxis, dcaAxis}); - histogramRegistry.add("hPtDcaZ_before", "", kTH2D, {ptAxis, dcazAxis}); - histogramRegistry.add("hVtxZ_after", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("hDcaXY_after", "", kTH1F, {dcaAxis}); - histogramRegistry.add("hDcaZ_after", "", kTH1F, {dcazAxis}); - histogramRegistry.add("hTPCchi2perCluster_after", "", kTH1D, {tpcChiAxis}); - histogramRegistry.add("hITSchi2perCluster_after", "", kTH1D, {itsChiAxis}); - histogramRegistry.add("hTPCCrossedrows_after", "", kTH1D, {crossedRowAxis}); - histogramRegistry.add("hPtDcaXY_after", "", kTH2D, {ptAxis, dcaAxis}); - histogramRegistry.add("hPtDcaZ_after", "", kTH2D, {ptAxis, dcazAxis}); - histogramRegistry.add("hEta", "", kTH1F, {etaAxis}); - histogramRegistry.add("hPt", "", kTH1F, {ptAxis}); - histogramRegistry.add("hCentrality", "", kTH1F, {centAxis}); - histogramRegistry.add("hMultiplicity", "", kTH1F, {multAxis}); - histogramRegistry.add("rec_hVtxZ_before", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("gen_hVtxZ_before", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("rec_hDcaXY_before", "", kTH1D, {dcaAxis}); - histogramRegistry.add("rec_hDcaZ_before", "", kTH1D, {dcazAxis}); - histogramRegistry.add("rec_hTPCchi2perCluster_before", "TPC #Chi^{2}/Cluster", kTH1D, {tpcChiAxis}); - histogramRegistry.add("rec_hITSchi2perCluster_before", "ITS #Chi^{2}/Cluster", kTH1D, {itsChiAxis}); - histogramRegistry.add("rec_hTPCCrossedrows_before", "Crossed TPC rows", kTH1D, {crossedRowAxis}); - histogramRegistry.add("rec_hVtxZ_after", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("gen_hVtxZ_after", "", kTH1F, {vtxzAxis}); - histogramRegistry.add("rec_hDcaXY_after", "", kTH1D, {dcaAxis}); - histogramRegistry.add("rec_hDcaZ_after", "", kTH1D, {dcazAxis}); - histogramRegistry.add("rec_hTPCchi2perCluster_after", "TPC #Chi^{2}/Cluster", kTH1D, {tpcChiAxis}); - histogramRegistry.add("rec_hITSchi2perCluster_after", "ITS #Chi^{2}/Cluster", kTH1D, {itsChiAxis}); - histogramRegistry.add("rec_hTPCCrossedrows_after", "Crossed TPC rows", kTH1D, {crossedRowAxis}); - histogramRegistry.add("gen_hEta", "", kTH1F, {etaAxis}); - histogramRegistry.add("rec_hEta", "", kTH1F, {etaAxis}); - histogramRegistry.add("gen_hSign", "", kTH1F, {signAxis}); - histogramRegistry.add("gen_hPt", "", kTH1F, {ptAxis}); - histogramRegistry.add("rec_hPt", "", kTH1F, {ptAxis}); - histogramRegistry.add("rec_hPtDcaXY_after", "hPtDCAxy", kTH2D, {ptAxis, dcaAxis}); - histogramRegistry.add("rec_hPtDcaZ_after", "hPtDCAz", kTH2D, {ptAxis, dcazAxis}); - histogramRegistry.add("rec_hCentrality", "", kTH1D, {centAxis}); - histogramRegistry.add("gen_hCentrality", "", kTH1D, {centAxis}); - histogramRegistry.add("rec_hMultiplicity", "", kTH1D, {multAxis}); - histogramRegistry.add("gen_hMultiplicity", "", kTH1D, {multAxis}); + const AxisSpec nchAxis = {5000, 0, 5000, "Nch"}; + const AxisSpec nch1Axis = {1500, 0, 1500, "Nch"}; + const AxisSpec nchpAxis = {50000, 0, 50000, "Nch"}; + + std::vector centBining = {0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; + AxisSpec cent1Axis = {centBining, "Multiplicity percentile from FT0M (%)"}; + + auto noSubsample = static_cast(cfgNSubsample); + float maxSubsample = 1.0 * noSubsample; + AxisSpec subsampleAxis = {noSubsample, 0.0, maxSubsample, "subsample no."}; + + histogramRegistry.add("QA/hVtxZ_before", "", kTH1F, {vtxzAxis}); + histogramRegistry.add("QA/hDcaXY_before", "", kTH1F, {dcaAxis}); + histogramRegistry.add("QA/hDcaZ_before", "", kTH1F, {dcazAxis}); + histogramRegistry.add("QA/hTPCchi2perCluster_before", "", kTH1D, {tpcChiAxis}); + histogramRegistry.add("QA/hITSchi2perCluster_before", "", kTH1D, {itsChiAxis}); + histogramRegistry.add("QA/hTPCCrossedrows_before", "", kTH1D, {crossedRowAxis}); + histogramRegistry.add("QA/hPtDcaXY_before", "", kTH2D, {ptAxis, dcaAxis}); + histogramRegistry.add("QA/hPtDcaZ_before", "", kTH2D, {ptAxis, dcazAxis}); + histogramRegistry.add("QA/hVtxZ_after", "", kTH1F, {vtxzAxis}); + histogramRegistry.add("QA/hDcaXY_after", "", kTH1F, {dcaAxis}); + histogramRegistry.add("QA/hDcaZ_after", "", kTH1F, {dcazAxis}); + histogramRegistry.add("QA/hTPCchi2perCluster_after", "", kTH1D, {tpcChiAxis}); + histogramRegistry.add("QA/hITSchi2perCluster_after", "", kTH1D, {itsChiAxis}); + histogramRegistry.add("QA/hTPCCrossedrows_after", "", kTH1D, {crossedRowAxis}); + histogramRegistry.add("QA/hPtDcaXY_after", "", kTH2D, {ptAxis, dcaAxis}); + histogramRegistry.add("QA/hPtDcaZ_after", "", kTH2D, {ptAxis, dcazAxis}); + histogramRegistry.add("QA/hEta", "", kTH1F, {etaAxis}); + histogramRegistry.add("QA/cent_hEta", "", kTH2F, {cent1Axis, etaAxis}); + histogramRegistry.add("QA/hPt", "", kTH1F, {ptAxis}); + histogramRegistry.add("QA/cent_hPt", "", kTH2F, {cent1Axis, ptAxis}); + histogramRegistry.add("QA/hPt_eta", "", kTH2F, {ptAxis, etaAxis}); + histogramRegistry.add("QA/hCentrality", "", kTH1F, {centAxis}); + histogramRegistry.add("QA/hMultiplicity", "", kTH1F, {multAxis}); + + histogramRegistry.add("gen/hVtxZ_before", "", kTH1F, {vtxzAxis}); + histogramRegistry.add("gen/hVtxZ_after", "", kTH1F, {vtxzAxis}); + histogramRegistry.add("gen/hPt", "", kTH1F, {ptAxis}); + histogramRegistry.add("gen/cent_hPt", "", kTH2F, {centAxis, ptAxis}); + histogramRegistry.add("gen/hEta", "", kTH1F, {etaAxis}); + histogramRegistry.add("gen/cent_hEta", "", kTH2F, {centAxis, etaAxis}); + histogramRegistry.add("gen/hSign", "", kTH1F, {signAxis}); + histogramRegistry.add("gen/hPt_eta", "", kTH2F, {ptAxis, etaAxis}); + histogramRegistry.add("gen/cent_pos", "cent vs fpos", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/cent_neg", "cent vs fneg", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/cent_termp", "cent vs termp", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/cent_termn", "cent vs termn", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/cent_pos_sq", "cent vs sqfpos", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/cent_neg_sq", "cent vs sqfneg", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/cent_posneg", "cent vs fpos*fneg", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/cent_nch", "cent vs nch", kTProfile, {cent1Axis}); + histogramRegistry.add("gen/nch", "", kTH1F, {nchAxis}); + histogramRegistry.add("gen/delta_eta_eta", "delta_eta ", kTH1F, {etaAxis}); + histogramRegistry.add("gen/delta_eta_pos", "delta_eta vs fpos ", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("gen/delta_eta_neg", "delta_eta vs fneg ", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("gen/delta_eta_termp", "delta_eta vs termp ", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("gen/delta_eta_termn", "delta_eta vs termn ", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("gen/delta_eta_pos_sq", "delta_eta vs pos_sq ", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("gen/delta_eta_neg_sq", "delta_eta vs neg_sq ", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("gen/delta_eta_posneg", "delta_eta vs posneg ", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("gen/delta_eta_nch", "delta_eta vs nchGen ", kTProfile, {deltaEtaAxis}); + + histogramRegistry.add("data/nch", "", kTH1D, {nchAxis}); + histogramRegistry.add("data/cent_nch", "", kTProfile, {cent1Axis}); + histogramRegistry.add("data/nch_pos", "", kTH1D, {nchAxis}); + histogramRegistry.add("data/cent_nch_pos", "", kTH2D, {centAxis, nchAxis}); + histogramRegistry.add("data/nch_neg", "", kTH1D, {nchAxis}); + histogramRegistry.add("data/cent_nch_neg", "", kTH2D, {centAxis, nchAxis}); + histogramRegistry.add("data/nch_negpos", "", kTH1D, {nchpAxis}); + histogramRegistry.add("data/cent_nch_negpos", "", kTH2D, {centAxis, nchpAxis}); + histogramRegistry.add("data/cent_pos", "cent vs fpos", kTProfile, {cent1Axis}); + histogramRegistry.add("data/cent_neg", "cent vs fneg", kTProfile, {cent1Axis}); + histogramRegistry.add("data/cent_termp", "cent vs termp", kTProfile, {cent1Axis}); + histogramRegistry.add("data/cent_termn", "cent vs termn", kTProfile, {cent1Axis}); + histogramRegistry.add("data/cent_pos_sq", "cent vs sqfpos", kTProfile, {cent1Axis}); + histogramRegistry.add("data/cent_neg_sq", "cent vs sqfneg", kTProfile, {cent1Axis}); + 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}); + histogramRegistry.add("data/cent_pos_cor", "", kTProfile, {cent1Axis}); + histogramRegistry.add("data/cent_neg_cor", "", kTProfile, {cent1Axis}); + histogramRegistry.add("data/delta_eta_cent", "Centrality", kTH1F, {cent1Axis}); + histogramRegistry.add("data/delta_eta_eta", "eta", kTH1F, {etaAxis}); + histogramRegistry.add("data/delta_eta_nchTotal", "delta_eta vs nchTotal", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_nch", "delta_eta vs nch", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_nchCor", "delta_eta vs nchCor", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_pos", "delta_eta vs fpos", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_neg", "delta_eta vs fneg", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_termp", "delta_eta vs termp", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_termn", "delta_eta vs termn", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_pos_sq", "delta_eta vs sqfpos", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_neg_sq", "delta_eta vs sqfneg", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_posneg", "delta_eta vs fpos*fneg", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_pos_cor", "delta_eta vs fpos_cor", kTProfile, {deltaEtaAxis}); + histogramRegistry.add("data/delta_eta_neg_cor", "delta_eta vs fneg_cor", kTProfile, {deltaEtaAxis}); + + histogramRegistry.add("subsample/pos", "", kTProfile2D, {cent1Axis, subsampleAxis}); + histogramRegistry.add("subsample/neg", "", kTProfile2D, {cent1Axis, subsampleAxis}); + histogramRegistry.add("subsample/termp", "", kTProfile2D, {cent1Axis, subsampleAxis}); + histogramRegistry.add("subsample/termn", "", kTProfile2D, {cent1Axis, subsampleAxis}); + histogramRegistry.add("subsample/pos_sq", "", kTProfile2D, {cent1Axis, subsampleAxis}); + histogramRegistry.add("subsample/neg_sq", "", kTProfile2D, {cent1Axis, subsampleAxis}); + histogramRegistry.add("subsample/posneg", "", kTProfile2D, {cent1Axis, subsampleAxis}); + + if (cfgLoadEff) { + ccdb->setURL(cfgUrlCCDB.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + // ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + // LOGF(info, "Getting object %s", ccdbPath.value.data()); + + TList* list = ccdb->getForTimeStamp(cfgPathCCDB.value, -1); + efficiency = reinterpret_cast(list->FindObject("efficiency_Run3")); + if (!efficiency) { + LOGF(info, "FATAL!! Could not find required histograms in CCDB"); + } + } } template - bool selCollision(C const& coll) + bool selCollision(C const& coll, float& cent, float& mult) { - if (std::abs(coll.posZ()) > vertexZcut) { - return false; - } // Reject the collisions with large vertex-z + if (std::abs(coll.posZ()) > vertexZcut) + return false; if constexpr (run == kRun3) { - if (cSel8Trig && !coll.sel8()) { return false; } // require min bias trigger cent = coll.centFT0M(); // centrality for run3 mult = coll.multFT0M(); // multiplicity for run3 - } else { + } else if constexpr (run == kRun2) { if (cInt7Trig && !coll.alias_bit(kINT7)) { return false; } @@ -238,402 +290,536 @@ struct NetchargeFluctuations { mult = coll.multFV0M(); // multiplicity for run2 } - if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) return false; - } - - if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) return false; - } - - if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) return false; - } - - if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) return false; - } - - if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { + if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) + return false; + if (cfgUseGoodItsLayerAllCut && !(coll.selection_bit(aod::evsel::kIsGoodITSLayersAll))) return false; - } - return true; // if all checks pass, accept the collision + return true; + } + + template + void fillBeforeQA(T const& track) + { + histogramRegistry.fill(HIST("QA/hTPCchi2perCluster_before"), track.tpcChi2NCl()); + histogramRegistry.fill(HIST("QA/hITSchi2perCluster_before"), track.itsChi2NCl()); + histogramRegistry.fill(HIST("QA/hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); + histogramRegistry.fill(HIST("QA/hDcaXY_before"), track.dcaXY()); + histogramRegistry.fill(HIST("QA/hDcaZ_before"), track.dcaZ()); + histogramRegistry.fill(HIST("QA/hPtDcaXY_before"), track.pt(), track.dcaXY()); + histogramRegistry.fill(HIST("QA/hPtDcaZ_before"), track.pt(), track.dcaZ()); + } + + template + void fillAfterQA(T const& track) + { + histogramRegistry.fill(HIST("QA/hDcaXY_after"), track.dcaXY()); + histogramRegistry.fill(HIST("QA/hDcaZ_after"), track.dcaZ()); + histogramRegistry.fill(HIST("QA/hPt"), track.pt()); + histogramRegistry.fill(HIST("QA/hEta"), track.eta()); + histogramRegistry.fill(HIST("QA/hPt_eta"), track.pt(), track.eta()); + histogramRegistry.fill(HIST("QA/hPtDcaXY_after"), track.pt(), track.dcaXY()); + histogramRegistry.fill(HIST("QA/hPtDcaZ_after"), track.pt(), track.dcaZ()); + histogramRegistry.fill(HIST("QA/hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); + histogramRegistry.fill(HIST("QA/hTPCchi2perCluster_after"), track.tpcChi2NCl()); + histogramRegistry.fill(HIST("QA/hITSchi2perCluster_after"), track.itsChi2NCl()); } template bool selTrack(T const& track) { - if (!track.isGlobalTrack()) { + if (!track.isGlobalTrack()) return false; - } // accept only global tracks - - if (std::fabs(track.dcaXY()) > dcaXYCut) { + if (std::fabs(track.eta()) >= etaCut) return false; - } - - if (std::fabs(track.dcaZ()) > dcaZCut) { + if (track.pt() <= ptMinCut || track.pt() >= ptMaxCut) return false; - } - - if (std::fabs(track.eta()) >= etaCut) { + if (track.sign() == 0) return false; - } - - if (track.pt() <= ptMinCut || track.pt() >= ptMaxCut) { + if (cDcaXy && std::fabs(track.dcaXY()) > dcaXYCut) return false; - } - - if (track.tpcNClsCrossedRows() < tpcCrossCut) { + if (cDcaZ && std::fabs(track.dcaZ()) > dcaZCut) return false; - } - - if (track.itsChi2NCl() > itsChiCut) { + if (cTpcCr && track.tpcNClsCrossedRows() < tpcCrossCut) return false; - } - - if (track.tpcChi2NCl() > tpcChiCut) { + if (cItsChi && track.itsChi2NCl() > itsChiCut) + return false; + if (cTpcChi && track.tpcChi2NCl() > tpcChiCut) return false; + + return true; + } + + double getEfficiency(float pt, float eta, TH2D* hEff) + { + if (!hEff) { + return 1e-6; + } + int binX = hEff->GetXaxis()->FindBin(pt); + int binY = hEff->GetYaxis()->FindBin(eta); + if (binX < 1 || binX > hEff->GetNbinsX() || binY < 1 || binY > hEff->GetNbinsY()) { + return 1e-6; } + double eff = hEff->GetBinContent(binX, binY); + return eff; + } - return true; // if all checks pass, accept the collision + void fillHistograms(float nch, float cent, float fpos, float fneg, float posneg, float termp, float termn) + { + histogramRegistry.fill(HIST("data/nch"), nch); + histogramRegistry.fill(HIST("data/cent_nch"), cent, nch); + histogramRegistry.fill(HIST("data/nch_pos"), fpos); + histogramRegistry.fill(HIST("data/cent_nch_pos"), cent, fpos); + histogramRegistry.fill(HIST("data/nch_neg"), fneg); + histogramRegistry.fill(HIST("data/cent_nch_neg"), cent, fneg); + histogramRegistry.fill(HIST("data/nch_negpos"), posneg); + histogramRegistry.fill(HIST("data/cent_nch_negpos"), cent, posneg); + + histogramRegistry.fill(HIST("data/cent_pos"), cent, fpos); + histogramRegistry.fill(HIST("data/cent_neg"), cent, fneg); + histogramRegistry.fill(HIST("data/cent_termp"), cent, termp); + histogramRegistry.fill(HIST("data/cent_termn"), cent, termn); + histogramRegistry.fill(HIST("data/cent_pos_sq"), cent, fpos * fpos); + histogramRegistry.fill(HIST("data/cent_neg_sq"), cent, fneg * fneg); + histogramRegistry.fill(HIST("data/cent_posneg"), cent, posneg); + + float lRandom = fRndm->Rndm(); + int sampleIndex = static_cast(cfgNSubsample * lRandom); + + histogramRegistry.fill(HIST("subsample/pos"), cent, sampleIndex, fpos); + histogramRegistry.fill(HIST("subsample/neg"), cent, sampleIndex, fneg); + histogramRegistry.fill(HIST("subsample/termp"), cent, sampleIndex, termp); + histogramRegistry.fill(HIST("subsample/termn"), cent, sampleIndex, termn); + histogramRegistry.fill(HIST("subsample/pos_sq"), cent, sampleIndex, fpos * fpos); + histogramRegistry.fill(HIST("subsample/neg_sq"), cent, sampleIndex, fneg * fneg); + histogramRegistry.fill(HIST("subsample/posneg"), cent, sampleIndex, posneg); } template - void calculation(C const& coll, T const& tracks) + void calculationData(C const& coll, T const& tracks) { - histogramRegistry.fill(HIST("hVtxZ_before"), coll.posZ()); - - if (!selCollision(coll)) { + float cent = -1, mult = -1; + histogramRegistry.fill(HIST("QA/hVtxZ_before"), coll.posZ()); + if (!selCollision(coll, cent, mult)) { return; } - - histogramRegistry.fill(HIST("hVtxZ_after"), coll.posZ()); - histogramRegistry.fill(HIST("hCentrality"), cent); - histogramRegistry.fill(HIST("hMultiplicity"), mult); + histogramRegistry.fill(HIST("QA/hVtxZ_after"), coll.posZ()); + histogramRegistry.fill(HIST("QA/hCentrality"), cent); + 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; for (const auto& track : tracks) { - histogramRegistry.fill(HIST("hTPCchi2perCluster_before"), track.tpcChi2NCl()); - histogramRegistry.fill(HIST("hITSchi2perCluster_before"), track.itsChi2NCl()); - histogramRegistry.fill(HIST("hTPCCrossedrows_before"), track.tpcNClsCrossedRows()); - histogramRegistry.fill(HIST("hDcaXY_before"), track.dcaXY()); - histogramRegistry.fill(HIST("hDcaZ_before"), track.dcaZ()); - histogramRegistry.fill(HIST("hPtDcaXY_before"), track.pt(), track.dcaXY()); - histogramRegistry.fill(HIST("hPtDcaZ_before"), track.pt(), track.dcaZ()); - - if (!selTrack(track)) { - continue; - } - if (track.sign() == 0) + + double eff = getEfficiency(track.pt(), track.eta(), efficiency); + if (eff < threshold) continue; - histogramRegistry.fill(HIST("hDcaXY_after"), track.dcaXY()); - histogramRegistry.fill(HIST("hDcaZ_after"), track.dcaZ()); - histogramRegistry.fill(HIST("hPt"), track.pt()); - histogramRegistry.fill(HIST("hEta"), track.eta()); - histogramRegistry.fill(HIST("hPtDcaXY_after"), track.pt(), track.dcaXY()); - histogramRegistry.fill(HIST("hPtDcaZ_after"), track.pt(), track.dcaZ()); - histogramRegistry.fill(HIST("hTPCCrossedrows_after"), track.tpcNClsCrossedRows()); - histogramRegistry.fill(HIST("hTPCchi2perCluster_after"), track.tpcChi2NCl()); - histogramRegistry.fill(HIST("hITSchi2perCluster_after"), track.itsChi2NCl()); + double weight = 1.0 / eff; + fillBeforeQA(track); + nchTotal += 1; + nchTotalCor += weight; + if (!selTrack(track)) + continue; + nch += 1; + fillAfterQA(track); + histogramRegistry.fill(HIST("QA/cent_hEta"), cent, track.eta()); + histogramRegistry.fill(HIST("QA/cent_hPt"), cent, track.pt()); + histogramRegistry.fill(HIST("data/hPt_cor"), track.pt(), weight); + histogramRegistry.fill(HIST("data/hEta_cor"), track.eta(), weight); + + nchCor += weight; if (track.sign() == 1) { fpos += 1; - termp = fpos * (fpos - 1); - } - - if (track.sign() == -1) { + posWeight += weight; + } else if (track.sign() == -1) { fneg += 1; - termn = fneg * (fneg - 1); + negWeight += weight; } - posneg = fpos * fneg; - netCharge(fpos, fneg, fpos * fpos, fneg * fneg, termp, termn, posneg, cent); - } // tracks - - return; + } // 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); + 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); } template - void histosMcRecoGen(C const& coll, T const& inputTracks, M const& mcCollisions, P const& mcParticles) + void calculationMc(C const& coll, T const& inputTracks, M const& mcCollisions, P const& mcParticles) { (void)mcCollisions; if (!coll.has_mcCollision()) { return; } - - histogramRegistry.fill(HIST("gen_hVtxZ_before"), coll.mcCollision().posZ()); - histogramRegistry.fill(HIST("rec_hVtxZ_before"), coll.posZ()); - - if (cNoItsROBorder && !coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { - return; - } - if (cTFBorder && !coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - return; - } - if (cPileupReject && !coll.selection_bit(aod::evsel::kNoSameBunchPileup)) { - return; - } - if (cZVtxTimeDiff && !coll.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { - return; - } - if (cItsTpcVtx && !coll.selection_bit(aod::evsel::kIsVertexITSTPC)) { + histogramRegistry.fill(HIST("gen/hVtxZ_before"), coll.mcCollision().posZ()); + float cent = -1, mult = -1; + histogramRegistry.fill(HIST("QA/hVtxZ_before"), coll.posZ()); + if (!selCollision(coll, cent, mult)) { return; } + histogramRegistry.fill(HIST("QA/hVtxZ_after"), coll.posZ()); + histogramRegistry.fill(HIST("QA/hCentrality"), cent); + histogramRegistry.fill(HIST("QA/hMultiplicity"), mult); - if (std::abs(coll.posZ()) > vertexZcut) { - return; - } + int fpos = 0, fneg = 0, posneg = 0, termn = 0, termp = 0; + int nch = 0, nchCor = 0; + double posRecWeight = 0, negRecWeight = 0; - if constexpr (run == kRun3) { - if (cSel8Trig && !coll.sel8()) { - return; - } + for (const auto& track : inputTracks) { + fillBeforeQA(track); + if (!selTrack(track)) + continue; + nch += 1; + fillAfterQA(track); + histogramRegistry.fill(HIST("QA/cent_hEta"), cent, track.eta()); + histogramRegistry.fill(HIST("QA/cent_hPt"), cent, track.pt()); - cent = coll.centFT0M(); // centrality for run3 - mult = coll.multFT0M(); - } else { - if (cSel7Trig && !coll.sel7()) { - return; - } + double eff = getEfficiency(track.pt(), track.eta(), efficiency); + if (eff < threshold) + continue; + double weight = 1.0 / eff; + histogramRegistry.fill(HIST("data/hPt_cor"), track.pt(), weight); + histogramRegistry.fill(HIST("data/hEta_cor"), track.eta(), weight); - cent = coll.centRun2V0M(); // centrality for run2 - mult = coll.multFV0M(); // multiplicity for run2 - } + if (track.sign() == 1) { + fpos += 1; + posRecWeight += weight; + } else if (track.sign() == -1) { + fneg += 1; + negRecWeight += weight; + } + nchCor = posRecWeight + negRecWeight; + } // track + termp = fpos * (fpos - 1); + termn = fneg * (fneg - 1); + posneg = fpos * fneg; + 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("rec_hVtxZ_after"), coll.posZ()); - histogramRegistry.fill(HIST("rec_hCentrality"), cent); - histogramRegistry.fill(HIST("rec_hMultiplicity"), mult); + fillHistograms(nch, cent, fpos, fneg, posneg, termp, termn); - int posRec = 0, negRec = 0, posNegRec = 0, termNRec = 0, termPRec = 0; - int posGen = 0, negGen = 0, posNegGen = 0, termNGen = 0, termPGen = 0; + int posGen = 0, negGen = 0, posNegGen = 0, termNGen = 0, termPGen = 0, nchGen = 0; const auto& mccolgen = coll.template mcCollision_as(); - if (std::abs(mccolgen.posZ()) > vertexZcut) { + if (std::abs(mccolgen.posZ()) > vertexZcut) return; - } - const auto& mcpartgen = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolgen.globalIndex(), cache); - histogramRegistry.fill(HIST("gen_hVtxZ_after"), mccolgen.posZ()); - - for (const auto& track : inputTracks) { - if (!track.isGlobalTrack()) + histogramRegistry.fill(HIST("gen/hVtxZ_after"), mccolgen.posZ()); + for (const auto& mcpart : mcpartgen) { + if (std::fabs(mcpart.eta()) >= etaCut) continue; - if (std::fabs(track.dcaXY()) > dcaXYCut) + if (!mcpart.isPhysicalPrimary()) continue; - if (std::fabs(track.dcaZ()) > dcaZCut) + int pid = mcpart.pdgCode(); + auto sign = 0; + auto* pd = pdgService->GetParticle(pid); + if (pd != nullptr) { + sign = pd->Charge() / 3.; + } + if (sign == 0) continue; - if (std::fabs(track.eta()) > etaCut) + if (std::abs(pid) != kElectron && + std::abs(pid) != kMuonMinus && + std::abs(pid) != kPiPlus && + std::abs(pid) != kKPlus && + std::abs(pid) != kProton) continue; - if ((track.pt() <= ptMinCut) || (track.pt() >= ptMaxCut)) + if (std::fabs(mcpart.eta()) >= etaCut) continue; - if (track.sign() == 0) { + if ((mcpart.pt() <= ptMinCut) || (mcpart.pt() >= ptMaxCut)) continue; + histogramRegistry.fill(HIST("gen/hPt"), mcpart.pt()); + histogramRegistry.fill(HIST("gen/cent_hPt"), cent, mcpart.pt()); + histogramRegistry.fill(HIST("gen/hEta"), mcpart.eta()); + histogramRegistry.fill(HIST("gen/cent_hEta"), cent, mcpart.eta()); + histogramRegistry.fill(HIST("gen/hSign"), sign); + histogramRegistry.fill(HIST("gen/hPt_eta"), mcpart.pt(), mcpart.eta()); + nchGen += 1; + if (sign == 1) { + posGen += 1; } + if (sign == -1) { + negGen += 1; + } + } + termPGen = posGen * (posGen - 1); + termNGen = negGen * (negGen - 1); + posNegGen = posGen * negGen; + histogramRegistry.fill(HIST("gen/cent_pos"), cent, posGen); + histogramRegistry.fill(HIST("gen/cent_neg"), cent, negGen); + histogramRegistry.fill(HIST("gen/cent_termp"), cent, termPGen); + histogramRegistry.fill(HIST("gen/cent_termn"), cent, termNGen); + histogramRegistry.fill(HIST("gen/cent_pos_sq"), cent, posGen * posGen); + histogramRegistry.fill(HIST("gen/cent_neg_sq"), cent, negGen * negGen); + histogramRegistry.fill(HIST("gen/cent_posneg"), cent, posNegGen); + histogramRegistry.fill(HIST("gen/cent_nch"), cent, nchGen); + histogramRegistry.fill(HIST("gen/nch"), nchGen); + + } // void - histogramRegistry.fill(HIST("rec_hPt"), track.pt()); - histogramRegistry.fill(HIST("rec_hEta"), track.eta()); + template + void calculationDeltaEta(C const& coll, T const& tracks, float deta1, float deta2) + { + float cent = -1, mult = -1; + if (!selCollision(coll, cent, mult)) + return; + if (!(cent >= centMin && cent < centMax)) + 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; + for (const auto& track : tracks) { + nchTotal += 1; + if (!selTrack(track)) + continue; + nch += 1; + double eff = getEfficiency(track.pt(), track.eta(), efficiency); + if (eff < threshold) + continue; + double weight = 1.0 / eff; + nchCor += weight; + double eta = track.eta(); + if (eta < deta1 || eta > deta2) + continue; + + histogramRegistry.fill(HIST("data/delta_eta_eta"), eta); if (track.sign() == 1) { - posRec += 1; - termPRec = posRec * (posRec - 1); + fpos++; + posWeight += weight; + } else if (track.sign() == -1) { + fneg++; + negWeight += weight; } + } + termp = fpos * (fpos - 1); + termn = fneg * (fneg - 1); + posneg = fpos * fneg; + + 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); + } - if (track.sign() == -1) { - negRec += 1; - termNRec = negRec * (negRec - 1); + template + void calculationMcDeltaEta(C const& coll, T const& inputTracks, M const& mcCollisions, P const& mcParticles, float deta1, float deta2) + { + (void)mcCollisions; + + if (!coll.has_mcCollision()) + return; + + float cent = -1, mult = -1; + if (!selCollision(coll, cent, mult)) + return; + if (!(cent >= centMin && cent < centMax)) + return; + histogramRegistry.fill(HIST("data/delta_eta_cent"), cent); + + 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; + + for (const auto& track : inputTracks) { + nchTotal += 1; + if (!selTrack(track)) + continue; + double eta = track.eta(); + if (eta < deta1 || eta > deta2) + continue; + + histogramRegistry.fill(HIST("data/delta_eta_eta"), eta); + double eff = getEfficiency(track.pt(), eta, efficiency); + if (eff < threshold) + continue; + double weight = 1.0 / eff; + nch += 1; + nchCor += weight; + if (track.sign() == 1) { + fpos += 1; + posRecWeight += weight; + } else if (track.sign() == -1) { + fneg += 1; + negRecWeight += weight; } + } // tracks - posNegRec = posRec * negRec; + termp = fpos * (fpos - 1); + termn = fneg * (fneg - 1); + posneg = fpos * fneg; + + 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, 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); - netCharge(posRec, negRec, posRec * posRec, negRec * negRec, - termPRec, termNRec, posNegRec, cent); - } // loop over inputTracks (reco) + const auto& mccolgen = coll.template mcCollision_as(); + + if (std::abs(mccolgen.posZ()) > vertexZcut) + return; + const auto& mcpartgen = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mccolgen.globalIndex(), cache); + + int posGen = 0, negGen = 0, posNegGen = 0, termNGen = 0, termPGen = 0, nchGen = 0; for (const auto& mcpart : mcpartgen) { - if (!mcpart.isPhysicalPrimary()) { + if (!mcpart.isPhysicalPrimary()) continue; - } + int pid = mcpart.pdgCode(); auto sign = 0; auto* pd = pdgService->GetParticle(pid); if (pd != nullptr) { sign = pd->Charge() / 3.; } - if (sign == 0) { + if (sign == 0) continue; - } - // auto pdgServicecode = mcpart.pdgCode(); - if (std::abs(pid) != kElectron && std::abs(pid) != kMuonMinus && std::abs(pid) != kPiPlus && std::abs(pid) != kKPlus && std::abs(pid) != kProton) { + if (std::abs(pid) != kElectron && + std::abs(pid) != kMuonMinus && + std::abs(pid) != kPiPlus && + std::abs(pid) != kKPlus && + std::abs(pid) != kProton) continue; - } - if (std::fabs(mcpart.eta()) > etaCut) + if (std::fabs(mcpart.eta()) >= etaCut) continue; if ((mcpart.pt() <= ptMinCut) || (mcpart.pt() >= ptMaxCut)) continue; - histogramRegistry.fill(HIST("gen_hPt"), mcpart.pt()); - histogramRegistry.fill(HIST("gen_hEta"), mcpart.eta()); - histogramRegistry.fill(HIST("gen_hSign"), sign); + double mcEta = mcpart.eta(); + if (mcEta < deta1 || mcEta > deta2) + continue; + + histogramRegistry.fill(HIST("gen/delta_eta_eta"), mcpart.eta()); + + nchGen += 1; if (sign == 1) { posGen += 1; - termPGen = posGen * (posGen - 1); } - if (sign == -1) { negGen += 1; - termNGen = negGen * (negGen - 1); } + } - posNegGen = posGen * negGen; + termPGen = posGen * (posGen - 1); + termNGen = negGen * (negGen - 1); + posNegGen = posGen * negGen; - netChargeGen(posGen, negGen, posGen * posGen, negGen * negGen, - termPGen, termNGen, posNegGen, cent); + histogramRegistry.fill(HIST("gen/delta_eta_pos"), deltaEtaWidth, posGen); + histogramRegistry.fill(HIST("gen/delta_eta_neg"), deltaEtaWidth, negGen); + histogramRegistry.fill(HIST("gen/delta_eta_termp"), deltaEtaWidth, termPGen); + histogramRegistry.fill(HIST("gen/delta_eta_termn"), deltaEtaWidth, termNGen); + histogramRegistry.fill(HIST("gen/delta_eta_pos_sq"), deltaEtaWidth, posGen * posGen); + histogramRegistry.fill(HIST("gen/delta_eta_neg_sq"), deltaEtaWidth, negGen * negGen); + histogramRegistry.fill(HIST("gen/delta_eta_posneg"), deltaEtaWidth, posNegGen); + histogramRegistry.fill(HIST("gen/delta_eta_nch"), deltaEtaWidth, nchGen); - } // particle } // void SliceCache cache; Preslice mcTrack = o2::aod::mcparticle::mcCollisionId; + // process function for Data Run3 void processDataRun3(aod::MyCollisionRun3 const& coll, aod::MyTracks const& tracks) { - calculation(coll, tracks); + calculationData(coll, tracks); + for (int ii = 0; ii < deltaEta; ii++) { + float etaMin = -0.1f * (ii + 1); + float etaMax = 0.1f * (ii + 1); + + calculationDeltaEta(coll, tracks, etaMin, etaMax); + } } - PROCESS_SWITCH(NetchargeFluctuations, processDataRun3, "Process for Run3 DATA", false); + PROCESS_SWITCH(NetchargeFluctuations, processDataRun3, "Process for Run3 DATA", true); + // process function for Data Run2 void processDataRun2(aod::MyCollisionRun2 const& coll, aod::MyTracks const& tracks) { - calculation(coll, tracks); + calculationData(coll, tracks); + for (int ii = 0; ii < deltaEta; ii++) { + float etaMin = -0.1f * (ii + 1); // -0.1, -0.2, ..., -0.8 + float etaMax = 0.1f * (ii + 1); // +0.1, +0.2, ..., +0.8 + + calculationDeltaEta(coll, tracks, etaMin, etaMax); + } } PROCESS_SWITCH(NetchargeFluctuations, processDataRun2, "Process for Run2 DATA", false); + // process function for MC Run3 + void processMcRun3(aod::MyMCCollisionRun3 const& coll, aod::MyMCTracks const& inputTracks, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { - histosMcRecoGen(coll, inputTracks, mcCollisions, mcParticles); + calculationMc(coll, inputTracks, mcCollisions, mcParticles); + for (int ii = 0; ii < deltaEta; ii++) { + float etaMin = -0.1f * (ii + 1); + float etaMax = 0.1f * (ii + 1); + 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 void processMcRun2(aod::MyMCCollisionRun2 const& coll, aod::MyMCTracks const& inputTracks, aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) { - histosMcRecoGen(coll, inputTracks, mcCollisions, mcParticles); + calculationMc(coll, inputTracks, mcCollisions, mcParticles); + for (int ii = 0; ii < deltaEta; ii++) { + float etaMin = -0.1f * (ii + 1); + float etaMax = 0.1f * (ii + 1); + calculationMcDeltaEta(coll, inputTracks, mcCollisions, mcParticles, etaMin, etaMax); + } } PROCESS_SWITCH(NetchargeFluctuations, processMcRun2, "Process reconstructed", false); +}; -}; // struct - -struct NetchargeAnalysis { - Configurable cfSubSample{"cfSubSample", 30, "Number of subsamples"}; - HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::vector>> net; - std::vector>> subSample; - std::vector>> genSubSample; - TRandom3* fRndm = new TRandom3(0); - - void init(o2::framework::InitContext&) - { - std::vector centBinning = {0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; - AxisSpec centAxis = {centBinning, "centrality"}; - - registry.add("data/pos_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("data/neg_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("data/termp_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("data/termn_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("data/pos_sq_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("data/neg_sq_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("data/posneg_vs_cent", "", {HistType::kTProfile, {centAxis}}); - - registry.add("gen/pos_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("gen/neg_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("gen/termp_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("gen/termn_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("gen/pos_sq_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("gen/neg_sq_vs_cent", "", {HistType::kTProfile, {centAxis}}); - registry.add("gen/posneg_vs_cent", "", {HistType::kTProfile, {centAxis}}); - - subSample.resize(cfSubSample); - genSubSample.resize(cfSubSample); - - for (int i = 0; i < cfSubSample; ++i) { - subSample[i].resize(7); - genSubSample[i].resize(7); - - subSample[i][0] = std::get>(registry.add(Form("data/subSample_%d/pos_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - subSample[i][1] = std::get>(registry.add(Form("data/subSample_%d/neg_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - subSample[i][2] = std::get>(registry.add(Form("data/subSample_%d/termp_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - subSample[i][3] = std::get>(registry.add(Form("data/subSample_%d/termn_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - subSample[i][4] = std::get>(registry.add(Form("data/subSample_%d/pos_sq_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - subSample[i][5] = std::get>(registry.add(Form("data/subSample_%d/neg_sq_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - subSample[i][6] = std::get>(registry.add(Form("data/subSample_%d/posneg_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - - genSubSample[i][0] = std::get>(registry.add(Form("gen/genSubSample_%d/pos_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - genSubSample[i][1] = std::get>(registry.add(Form("gen/genSubSample_%d/neg_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - genSubSample[i][2] = std::get>(registry.add(Form("gen/genSubSample_%d/termp_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - genSubSample[i][3] = std::get>(registry.add(Form("gen/genSubSample_%d/termn_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - genSubSample[i][4] = std::get>(registry.add(Form("gen/genSubSample_%d/pos_sq_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - genSubSample[i][5] = std::get>(registry.add(Form("gen/genSubSample_%d/neg_sq_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - genSubSample[i][6] = std::get>(registry.add(Form("gen/genSubSample_%d/posneg_vs_cent", i), "", {HistType::kTProfile, {centAxis}})); - } - - } // void - - void processData(aod::NetCharge::iterator const& event_netcharge) - { - registry.get(HIST("data/pos_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.posCharge()); - registry.get(HIST("data/neg_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.negCharge()); - registry.get(HIST("data/termp_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.termPCharge()); - registry.get(HIST("data/termn_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.termNCharge()); - registry.get(HIST("data/pos_sq_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.posSqCharge()); - registry.get(HIST("data/neg_sq_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.negSqCharge()); - registry.get(HIST("data/posneg_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.posNegCharge()); - - int sampleIndex = static_cast(cfSubSample * fRndm->Rndm()); - subSample[sampleIndex][0]->Fill(event_netcharge.centrality(), event_netcharge.posCharge()); - subSample[sampleIndex][1]->Fill(event_netcharge.centrality(), event_netcharge.negCharge()); - subSample[sampleIndex][2]->Fill(event_netcharge.centrality(), event_netcharge.termPCharge()); - subSample[sampleIndex][3]->Fill(event_netcharge.centrality(), event_netcharge.termNCharge()); - subSample[sampleIndex][4]->Fill(event_netcharge.centrality(), event_netcharge.posSqCharge()); - subSample[sampleIndex][5]->Fill(event_netcharge.centrality(), event_netcharge.negSqCharge()); - subSample[sampleIndex][6]->Fill(event_netcharge.centrality(), event_netcharge.posNegCharge()); - } // void - PROCESS_SWITCH(NetchargeAnalysis, processData, "Process reconstructed and Data", true); - - void processGen(aod::NetChargeGen::iterator const& event_netcharge) - { - registry.get(HIST("gen/pos_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.posCharge()); - registry.get(HIST("gen/neg_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.negCharge()); - registry.get(HIST("gen/termp_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.termPCharge()); - registry.get(HIST("gen/termn_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.termNCharge()); - registry.get(HIST("gen/pos_sq_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.posSqCharge()); - registry.get(HIST("gen/neg_sq_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.negSqCharge()); - registry.get(HIST("gen/posneg_vs_cent"))->Fill(event_netcharge.centrality(), event_netcharge.posNegCharge()); - - int sampleIndex = static_cast(cfSubSample * fRndm->Rndm()); - genSubSample[sampleIndex][0]->Fill(event_netcharge.centrality(), event_netcharge.posCharge()); - genSubSample[sampleIndex][1]->Fill(event_netcharge.centrality(), event_netcharge.negCharge()); - genSubSample[sampleIndex][2]->Fill(event_netcharge.centrality(), event_netcharge.termPCharge()); - genSubSample[sampleIndex][3]->Fill(event_netcharge.centrality(), event_netcharge.termNCharge()); - genSubSample[sampleIndex][4]->Fill(event_netcharge.centrality(), event_netcharge.posSqCharge()); - genSubSample[sampleIndex][5]->Fill(event_netcharge.centrality(), event_netcharge.negSqCharge()); - genSubSample[sampleIndex][6]->Fill(event_netcharge.centrality(), event_netcharge.posNegCharge()); - } // void - PROCESS_SWITCH(NetchargeAnalysis, processGen, "Process generated", true); - -}; // struct Netcharge_analysis - +// struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - {adaptAnalysisTask(cfgc)}, - {adaptAnalysisTask(cfgc)} - - }; + {adaptAnalysisTask(cfgc)}}; } diff --git a/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx new file mode 100644 index 00000000000..f0ec5f81685 --- /dev/null +++ b/PWGCF/EbyEFluctuations/Tasks/v0ptHadPiKaProt.cxx @@ -0,0 +1,562 @@ +// 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 v0ptHadPiKaProt.cxx +/// \brief Task for analyzing v0(pT) of inclusive hadrons, pions, kaons, and, protons +/// \author Swati Saha + +#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/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/MathConstants.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 +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct V0ptHadPiKaProt { + + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutTpcChi2NCl{"cfgCutTpcChi2NCl", 2.5f, "Maximum TPCchi2NCl"}; + Configurable cfgCutItsChi2NCl{"cfgCutItsChi2NCl", 36.0f, "Maximum ITSchi2NCl"}; + Configurable cfgCutTrackDcaZ{"cfgCutTrackDcaZ", 2.0f, "Maximum 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"}; + Configurable cfgCutPtUpperTPC{"cfgCutPtUpperTPC", 0.6f, "Upper pT cut for PID using TPC only"}; + Configurable cfgnSigmaOtherParticles{"cfgnSigmaOtherParticles", 3.0f, "PID nSigma cut to remove other particles (default:3)"}; + 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"}; + ConfigurableAxis nchAxis{"nchAxis", {5000, 0.5, 5000.5}, ""}; + ConfigurableAxis centAxis{"centAxis", {90, 0., 90.}, "Centrality/Multiplicity percentile bining"}; + 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 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"}; + + // 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"}; + + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::vector>> subSample; + TRandom3* funRndm = new TRandom3(0); + + // 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); + + // Filtering collisions and tracks*********** + using AodCollisions = soa::Filtered>; + using AodTracks = soa::Filtered>; + + // Equivalent of the AliRoot task UserCreateOutputObjects + void init(o2::framework::InitContext&) + { + // 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})"}; + AxisSpec noAxis = {1, 0, 1, "no axis"}; + AxisSpec nSigmaAxis = {200, -5.0, 5.0, "n#sigma"}; + + // Add histograms to histogram manager (as in the output object of in AliPhysics) + + // QA hists + histos.add("hZvtx_after_sel", ";Z (cm)", kTH1F, {{240, -12, 12}}); + histos.add("hCentrality", ";centrality (%)", kTH1F, {{90, 0, 90}}); + 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("hMeanPt", "", kTProfile, {centAxis}); + + // 2D histograms of nSigma + // before cut + histos.add("h2DnsigmaPionTpcVsPtBeforeCut", "2D hist of nSigmaTPC vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonTpcVsPtBeforeCut", "2D hist of nSigmaTPC vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonTpcVsPtBeforeCut", "2D hist of nSigmaTPC vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionTofVsPtBeforeCut", "2D hist of nSigmaTOF vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonTofVsPtBeforeCut", "2D hist of nSigmaTOF vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonTofVsPtBeforeCut", "2D hist of nSigmaTOF vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionTpcVsTofBeforeCut", "2D hist of nSigmaTPC vs. nSigmaTOF (pion)", kTH2F, {nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonTpcVsTofBeforeCut", "2D hist of nSigmaTPC vs. nSigmaTOF (kaon)", kTH2F, {nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonTpcVsTofBeforeCut", "2D hist of nSigmaTPC vs. nSigmaTOF (proton)", kTH2F, {nSigmaAxis, nSigmaAxis}); + // after cut + histos.add("h2DnsigmaPionTpcVsPtAfterCut", "2D hist of nSigmaTPC vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonTpcVsPtAfterCut", "2D hist of nSigmaTPC vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonTpcVsPtAfterCut", "2D hist of nSigmaTPC vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionTofVsPtAfterCut", "2D hist of nSigmaTOF vs. pT (pion)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonTofVsPtAfterCut", "2D hist of nSigmaTOF vs. pT (kaon)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonTofVsPtAfterCut", "2D hist of nSigmaTOF vs. pT (proton)", kTH2F, {ptAxis, nSigmaAxis}); + histos.add("h2DnsigmaPionTpcVsTofAfterCut", "2D hist of nSigmaTPC vs. nSigmaTOF (pion)", kTH2F, {nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaKaonTpcVsTofAfterCut", "2D hist of nSigmaTPC vs. nSigmaTOF (kaon)", kTH2F, {nSigmaAxis, nSigmaAxis}); + histos.add("h2DnsigmaProtonTpcVsTofAfterCut", "2D hist of nSigmaTPC vs. nSigmaTOF (proton)", kTH2F, {nSigmaAxis, nSigmaAxis}); + + // Analysis profiles + + histos.add("Prof_A_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_C_had", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_D_had", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Bone_had", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Btwo_had", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + + histos.add("Prof_A_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_C_pi", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_D_pi", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Bone_pi", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Btwo_pi", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + + histos.add("Prof_A_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_C_ka", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_D_ka", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Bone_ka", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Btwo_ka", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + + histos.add("Prof_A_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_C_prot", "", {HistType::kTProfile2D, {centAxis, ptAxis}}); + histos.add("Prof_D_prot", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Bone_prot", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + histos.add("Prof_Btwo_prot", "", {HistType::kTProfile2D, {centAxis, noAxis}}); + + // initial array + 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/Prof_A_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSample[i][1] = std::get>(histos.add(Form("subSample_%d/Prof_C_had", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSample[i][2] = std::get>(histos.add(Form("subSample_%d/Prof_D_had", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSample[i][3] = std::get>(histos.add(Form("subSample_%d/Prof_Bone_had", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSample[i][4] = std::get>(histos.add(Form("subSample_%d/Prof_Btwo_had", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + + subSample[i][5] = std::get>(histos.add(Form("subSample_%d/Prof_A_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSample[i][6] = std::get>(histos.add(Form("subSample_%d/Prof_C_pi", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSample[i][7] = std::get>(histos.add(Form("subSample_%d/Prof_D_pi", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSample[i][8] = std::get>(histos.add(Form("subSample_%d/Prof_Bone_pi", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSample[i][9] = std::get>(histos.add(Form("subSample_%d/Prof_Btwo_pi", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + + subSample[i][10] = std::get>(histos.add(Form("subSample_%d/Prof_A_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSample[i][11] = std::get>(histos.add(Form("subSample_%d/Prof_C_ka", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSample[i][12] = std::get>(histos.add(Form("subSample_%d/Prof_D_ka", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSample[i][13] = std::get>(histos.add(Form("subSample_%d/Prof_Bone_ka", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + subSample[i][14] = std::get>(histos.add(Form("subSample_%d/Prof_Btwo_ka", i), "", {HistType::kTProfile2D, {centAxis, noAxis}})); + + subSample[i][15] = std::get>(histos.add(Form("subSample_%d/Prof_A_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + subSample[i][16] = std::get>(histos.add(Form("subSample_%d/Prof_C_prot", i), "", {HistType::kTProfile2D, {centAxis, ptAxis}})); + 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}})); + } + } // end init + + //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + template + bool selectionProton(const T& candidate) + { + if (!candidate.hasTPC()) + return false; + int flag = 0; //! pid check main flag + + 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) { + 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 < 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; //! pid check main flag + + 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) { + 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 < 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; //! pid check main flag + + 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) { + 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 < 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; + } + + // process Data + void process(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))) { + return; + } + if (cfgEvSelkNoITSROFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoITSROFrameBorder))) { + return; + } + if (cfgEvSelkNoTimeFrameBorder && !(coll.selection_bit(o2::aod::evsel::kNoTimeFrameBorder))) { + return; + } + + // Centrality + double cent = 0.0; + if (cfgCentralityChoice == 1) + cent = coll.centFT0C(); + else if (cfgCentralityChoice == 2) + cent = coll.centFT0A(); + else if (cfgCentralityChoice == 3) + cent = coll.centFT0M(); + else if (cfgCentralityChoice == 4) + cent = coll.centFV0A(); + + histos.fill(HIST("hZvtx_after_sel"), coll.posZ()); + histos.fill(HIST("hCentrality"), cent); + histos.fill(HIST("Hist2D_globalTracks_PVTracks"), coll.multNTracksPV(), inputTracks.size()); + histos.fill(HIST("Hist2D_cent_nch"), inputTracks.size(), cent); + + // Analysis variables + 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}; + TH1D* fPtProfileHad = new TH1D("fPtProfileHad", "fPtProfileHad", 20, binsarray); + TH1D* fPtProfilePi = new TH1D("fPtProfilePi", "fPtProfilePi", 20, binsarray); + TH1D* fPtProfileKa = new TH1D("fPtProfileKa", "fPtProfileKa", 20, binsarray); + TH1D* fPtProfileProt = new TH1D("fPtProfileProt", "fPtProfileProt", 20, binsarray); + double pTsumEtaLeftHad = 0.0; + double nSumEtaLeftHad = 0.0; + double pTsumEtaRightHad = 0.0; + double nSumEtaRightHad = 0.0; + double nSumEtaLeftPi = 0.0; + double nSumEtaLeftKa = 0.0; + double nSumEtaLeftProt = 0.0; + + for (const auto& track : inputTracks) { // Loop over tracks + + if (!track.has_collision()) { + continue; + } + + if (!track.isPVContributor()) { + continue; + } + + if (!(track.itsNCls() > cfgITScluster) || !(track.tpcNClsFound() >= cfgTPCcluster) || !(track.tpcNClsCrossedRows() >= cfgTPCnCrossedRows)) { + continue; + } + + 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()); + + double trkPt = track.pt(); + double trkEta = track.eta(); + + // inclusive charged particles + if (track.sign() != 0) { + if (trkEta < cfgCutEtaLeft) { + fPtProfileHad->Fill(trkPt); + pTsumEtaLeftHad += trkPt; + nSumEtaLeftHad += 1.0; + } + if (trkEta > cfgCutEtaRight) { + pTsumEtaRightHad += trkPt; + nSumEtaRightHad += 1.0; + } + } + + // PID QAs before selection + double nSigmaTpcPi = track.tpcNSigmaPi(); + double nSigmaTpcKa = track.tpcNSigmaKa(); + double nSigmaTpcProt = track.tpcNSigmaPr(); + double nSigmaTofPi = track.tofNSigmaPi(); + double nSigmaTofKa = track.tofNSigmaKa(); + double nSigmaTofProt = track.tofNSigmaPr(); + histos.fill(HIST("h2DnsigmaPionTpcVsPtBeforeCut"), trkPt, nSigmaTpcPi); + histos.fill(HIST("h2DnsigmaKaonTpcVsPtBeforeCut"), trkPt, nSigmaTpcKa); + histos.fill(HIST("h2DnsigmaProtonTpcVsPtBeforeCut"), trkPt, nSigmaTpcProt); + histos.fill(HIST("h2DnsigmaPionTofVsPtBeforeCut"), trkPt, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaKaonTofVsPtBeforeCut"), trkPt, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaProtonTofVsPtBeforeCut"), trkPt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaPionTpcVsTofBeforeCut"), nSigmaTpcPi, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaKaonTpcVsTofBeforeCut"), nSigmaTpcKa, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaProtonTpcVsTofBeforeCut"), nSigmaTpcProt, nSigmaTofProt); + + // identified particles selection + bool isPion = selectionPion(track); + bool isKaon = selectionKaon(track); + bool isProton = selectionProton(track); + + // PID QAs after selection + if (isPion) { + histos.fill(HIST("h2DnsigmaPionTpcVsPtAfterCut"), trkPt, nSigmaTpcPi); + histos.fill(HIST("h2DnsigmaPionTofVsPtAfterCut"), trkPt, nSigmaTofPi); + histos.fill(HIST("h2DnsigmaPionTpcVsTofAfterCut"), nSigmaTpcPi, nSigmaTofPi); + } + if (isKaon) { + histos.fill(HIST("h2DnsigmaKaonTpcVsPtAfterCut"), trkPt, nSigmaTpcKa); + histos.fill(HIST("h2DnsigmaKaonTofVsPtAfterCut"), trkPt, nSigmaTofKa); + histos.fill(HIST("h2DnsigmaKaonTpcVsTofAfterCut"), nSigmaTpcKa, nSigmaTofKa); + } + if (isProton) { + histos.fill(HIST("h2DnsigmaProtonTpcVsPtAfterCut"), trkPt, nSigmaTpcProt); + histos.fill(HIST("h2DnsigmaProtonTofVsPtAfterCut"), trkPt, nSigmaTofProt); + histos.fill(HIST("h2DnsigmaProtonTpcVsTofAfterCut"), nSigmaTpcProt, nSigmaTofProt); + } + + if (track.sign() != 0) { + if (trkPt < cfgCutPtUpperPID) { + if (trkEta < cfgCutEtaLeft) { + if (isPion) { + fPtProfilePi->Fill(trkPt); + nSumEtaLeftPi += 1.0; + } + if (isKaon) { + fPtProfileKa->Fill(trkPt); + nSumEtaLeftKa += 1.0; + } + if (isProton && trkPt > cfgCutPtLowerProt) { + fPtProfileProt->Fill(trkPt); + nSumEtaLeftProt += 1.0; + } + } + } + } + + } // End track loop + + // selecting subsample and filling profiles + float lRandom = funRndm->Rndm(); + int sampleIndex = static_cast(cfgNSubsample * lRandom); + + if (nSumEtaRightHad > 0 && nSumEtaLeftHad > 0) { + for (int i = 0; i < nbinsHad; i++) { + histos.get(HIST("Prof_A_had"))->Fill(cent, fPtProfileHad->GetBinCenter(i + 1), (fPtProfileHad->GetBinContent(i + 1) / nSumEtaLeftHad)); + histos.get(HIST("Prof_C_had"))->Fill(cent, fPtProfileHad->GetBinCenter(i + 1), ((fPtProfileHad->GetBinContent(i + 1) / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + histos.get(HIST("Prof_Bone_had"))->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + histos.get(HIST("Prof_Btwo_had"))->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + histos.get(HIST("Prof_D_had"))->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + + subSample[sampleIndex][0]->Fill(cent, fPtProfileHad->GetBinCenter(i + 1), (fPtProfileHad->GetBinContent(i + 1) / nSumEtaLeftHad)); + subSample[sampleIndex][1]->Fill(cent, fPtProfileHad->GetBinCenter(i + 1), ((fPtProfileHad->GetBinContent(i + 1) / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][2]->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][3]->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + subSample[sampleIndex][4]->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + } + } + + if (nSumEtaRightHad > 0 && nSumEtaLeftHad > 0 && nSumEtaLeftPi > 0) { + for (int i = 0; i < nbinsPid; i++) { + histos.get(HIST("Prof_A_pi"))->Fill(cent, fPtProfilePi->GetBinCenter(i + 1), (fPtProfilePi->GetBinContent(i + 1) / nSumEtaLeftPi)); + histos.get(HIST("Prof_C_pi"))->Fill(cent, fPtProfilePi->GetBinCenter(i + 1), ((fPtProfilePi->GetBinContent(i + 1) / nSumEtaLeftPi) * (pTsumEtaRightHad / nSumEtaRightHad))); + histos.get(HIST("Prof_Bone_pi"))->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + histos.get(HIST("Prof_Btwo_pi"))->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + histos.get(HIST("Prof_D_pi"))->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + + subSample[sampleIndex][5]->Fill(cent, fPtProfilePi->GetBinCenter(i + 1), (fPtProfilePi->GetBinContent(i + 1) / nSumEtaLeftPi)); + subSample[sampleIndex][6]->Fill(cent, fPtProfilePi->GetBinCenter(i + 1), ((fPtProfilePi->GetBinContent(i + 1) / nSumEtaLeftPi) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][7]->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][8]->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + subSample[sampleIndex][9]->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + } + } + + if (nSumEtaRightHad > 0 && nSumEtaLeftHad > 0 && nSumEtaLeftKa > 0) { + for (int i = 0; i < nbinsPid; i++) { + histos.get(HIST("Prof_A_ka"))->Fill(cent, fPtProfileKa->GetBinCenter(i + 1), (fPtProfileKa->GetBinContent(i + 1) / nSumEtaLeftKa)); + histos.get(HIST("Prof_C_ka"))->Fill(cent, fPtProfileKa->GetBinCenter(i + 1), ((fPtProfileKa->GetBinContent(i + 1) / nSumEtaLeftKa) * (pTsumEtaRightHad / nSumEtaRightHad))); + histos.get(HIST("Prof_Bone_ka"))->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + histos.get(HIST("Prof_Btwo_ka"))->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + histos.get(HIST("Prof_D_ka"))->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + + subSample[sampleIndex][10]->Fill(cent, fPtProfileKa->GetBinCenter(i + 1), (fPtProfileKa->GetBinContent(i + 1) / nSumEtaLeftKa)); + subSample[sampleIndex][11]->Fill(cent, fPtProfileKa->GetBinCenter(i + 1), ((fPtProfileKa->GetBinContent(i + 1) / nSumEtaLeftKa) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][12]->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][13]->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + subSample[sampleIndex][14]->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + } + } + if (nSumEtaRightHad > 0 && nSumEtaLeftHad > 0 && nSumEtaLeftProt > 0) { + for (int i = 1; i < nbinsPid; i++) { + histos.get(HIST("Prof_A_prot"))->Fill(cent, fPtProfileProt->GetBinCenter(i + 1), (fPtProfileProt->GetBinContent(i + 1) / nSumEtaLeftProt)); + histos.get(HIST("Prof_C_prot"))->Fill(cent, fPtProfileProt->GetBinCenter(i + 1), ((fPtProfileProt->GetBinContent(i + 1) / nSumEtaLeftProt) * (pTsumEtaRightHad / nSumEtaRightHad))); + histos.get(HIST("Prof_Bone_prot"))->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + histos.get(HIST("Prof_Btwo_prot"))->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + histos.get(HIST("Prof_D_prot"))->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + + subSample[sampleIndex][15]->Fill(cent, fPtProfileProt->GetBinCenter(i + 1), (fPtProfileProt->GetBinContent(i + 1) / nSumEtaLeftProt)); + subSample[sampleIndex][16]->Fill(cent, fPtProfileProt->GetBinCenter(i + 1), ((fPtProfileProt->GetBinContent(i + 1) / nSumEtaLeftProt) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][17]->Fill(cent, 0.5, ((pTsumEtaLeftHad / nSumEtaLeftHad) * (pTsumEtaRightHad / nSumEtaRightHad))); + subSample[sampleIndex][18]->Fill(cent, 0.5, (pTsumEtaLeftHad / nSumEtaLeftHad)); + subSample[sampleIndex][19]->Fill(cent, 0.5, (pTsumEtaRightHad / nSumEtaRightHad)); + } + } + + fPtProfileHad->Delete(); + fPtProfilePi->Delete(); + fPtProfileKa->Delete(); + fPtProfileProt->Delete(); + + } // End process loop +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx b/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx index 9acef964220..6eaf78e8036 100644 --- a/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx +++ b/PWGCF/Femto/TableProducer/PiDeuteronFemto.cxx @@ -15,30 +15,9 @@ /// \author CMY /// \date 2025-04-10 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include // std::prev - -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" +#include "PWGCF/Femto/DataModel/PionDeuteronTables.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/Utils/svPoolCreator.h" #include "Common/Core/PID/PIDTOF.h" #include "Common/Core/PID/TPCPIDResponse.h" @@ -52,21 +31,40 @@ #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" - #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" #include "CCDB/BasicCCDBManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGCF/Femto/DataModel/PionDeuteronTables.h" -#include "PWGLF/Utils/svPoolCreator.h" +#include "Math/Boost.h" +#include "Math/Vector4D.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include // std::prev +#include +#include using namespace o2; using namespace o2::framework; @@ -163,7 +161,7 @@ struct PiDeuteronFemto { Configurable settingCutNsigmaTPCDe{"settingCutNsigmaTPCDe", 2.5f, "Value of the TPC Nsigma cut on De"}; Configurable settingCutNsigmaITSDe{"settingCutNsigmaITSDe", 2.5f, "Value of the ITD Nsigma cut on De"}; Configurable settingCutPinMinTOFPi{"settingCutPinMinTOFPi", 0.5f, "Minimum Pin to apply the TOF cut on Pions"}; - Configurable settingCutPinMinTOFITSDe{"settingCutPinMinTOFITSDe", 1.2f, "Minimum pT to apply the TOF ITS cut on De"}; + Configurable settingCutPinMinTOFITSDe{"settingCutPinMinTOFITSDe", 1.2f, "Minimum p to apply the TOF ITS cut on De"}; Configurable settingCutNsigmaTOFTPCDe{"settingCutNsigmaTOFTPCDe", 2.5f, "Value of the De TOF TPC Nsigma cut"}; Configurable settingCutNsigmaTOFTPCPi{"settingCutNsigmaTOFTPCPi", 3.0f, "Value of the Pion TOF TPC Nsigma cut"}; Configurable settingNoMixedEvents{"settingNoMixedEvents", 5, "Number of mixed events per event"}; @@ -182,6 +180,7 @@ struct PiDeuteronFemto { Configurable settingSaveUSandLS{"settingSaveUSandLS", true, "Save All Pairs"}; Configurable settingFillMultiplicity{"settingFillMultiplicity", false, "Fill multiplicity table"}; + Configurable settingUseBBcomputeDeNsigma{"settingUseBBcomputeDeNsigma", false, "Use BB params to compute De TPC Nsigma"}; // Zorro Configurable settingSkimmedProcessing{"settingSkimmedProcessing", false, "Skimmed dataset processing"}; @@ -231,25 +230,35 @@ struct PiDeuteronFemto { {"hEmptyPool", "svPoolCreator did not find track pairs false/true", {HistType::kTH1F, {{2, -0.5, 1.5}}}}, {"hdcaxyDe", ";DCA_{xy} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, {"hdcazDe", ";DCA_{z} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hdcazDe_min", ";DCA_{z}-min (cm)", {HistType::kTH1F, {{20, -1.0f, 1.0f}}}}, {"hNClsDeITS", ";N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, {"hNClsPiITS", ";N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, {"hDePitInvMass", "; M(De + p) (GeV/#it{c}^{2})", {HistType::kTH1F, {{300, 3.74f, 4.34f}}}}, {"hDePt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, {"hPiPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{120, -3.0f, 3.0f}}}}, + {"hDeEta", "eta distribution; #eta(De)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hPiEta", "eta distribution; #eta(#pi)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hDePhi", "phi distribution; phi(De)", {HistType::kTH1F, {{600, -4.0f, 4.0f}}}}, + {"hPiPhi", "phi distribution; phi(#pi)", {HistType::kTH1F, {{600, -4.0f, 4.0f}}}}, {"h2dEdxDecandidates", "dEdx distribution; #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, - {"h2NsigmaDeTPC", "NsigmaDe TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(De)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2dEdx", "dEdx distribution; #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, + {"h2NsigmaDeTPC", "NsigmaDe TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(De)", {HistType::kTH2F, {{100, -2.0f, 2.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaDeComb", "NsigmaDe TPCTOF comb distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{comb}(De)", {HistType::kTH2F, {{100, -2.0f, 2.0f}, {100, 0.0f, 5.0f}}}}, + {"h2NsigmaPiComb", "NsigmaPi TPCTOF comb distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{comb}(#pi)", {HistType::kTH2F, {{100, -2.0f, 2.0f}, {100, 0.0f, 5.0f}}}}, {"h2NsigmaDeTPC_preselection", "NsigmaDe TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(De)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"h2NsigmaDeTPC_preselecComp", "NsigmaDe TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(De)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"h2NSigmaDeITS_preselection", "NsigmaDe ITS distribution; signed #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS} De", {HistType::kTH2F, {{50, -5.0f, 5.0f}, {120, -3.0f, 3.0f}}}}, - {"h2NSigmaDeITS", "NsigmaDe ITS distribution; signed #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS} De", {HistType::kTH2F, {{50, -5.0f, 5.0f}, {120, -3.0f, 3.0f}}}}, - {"h2NsigmaPiTPC", "NsigmaPi TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NSigmaDeITS", "NsigmaDe ITS distribution; signed #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS} De", {HistType::kTH2F, {{100, -2.0f, 2.0f}, {120, -3.0f, 3.0f}}}}, + {"h2NsigmaPiTPC", "NsigmaPi TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, {"h2NsigmaPiTPC_preselection", "NsigmaDe TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(De)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"h2NsigmaPiTOF", "NsigmaPi TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaPiTOF", "NsigmaPi TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaDeTOF", "NsigmaDe TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(De)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, {"h2NsigmaPiTOF_preselection", "NsigmaPi TOF distribution; #iit{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"hkStar_LS_M", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, {"hkStar_LS_A", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, {"hkStar_US_M", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, {"hkStar_US_A", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, + {"hkStar_All", ";kStar (GeV/c)", {HistType::kTH1F, {{300, 0.0f, 3.0f}}}}, {"hisBkgEM", "; isBkgEM;", {HistType::kTH1F, {{3, -1, 2}}}}}, OutputObjHandlingPolicy::AnalysisObject, false, @@ -279,7 +288,7 @@ struct PiDeuteronFemto { for (int i = 0; i < numParticles; i++) { mBBparamsDe[i] = settingBetheBlochParams->get("De", Form("p%i", i)); } - mBBparamsDe[5] = settingBetheBlochParams->get("De", "resolution"); // wdf? + mBBparamsDe[5] = settingBetheBlochParams->get("De", "resolution"); std::vector selectionLabels = {"All", "Track selection", "PID"}; for (int i = 0; i < Selections::kAll; i++) { @@ -393,21 +402,25 @@ struct PiDeuteronFemto { { auto tpcNSigmaPi = candidate.tpcNSigmaPi(); mQaRegistry.fill(HIST("h2NsigmaPiTPC_preselection"), candidate.tpcInnerParam(), tpcNSigmaPi); - if (candidate.hasTOF() && candidate.tpcInnerParam() > settingCutPinMinTOFPi) { + if (std::abs(candidate.pt()) < settingCutPiptMin || std::abs(candidate.pt()) > settingCutPiptMax) + return false; + if (candidate.hasTOF() && candidate.tpcInnerParam() >= settingCutPinMinTOFPi) { auto tofNSigmaPi = candidate.tofNSigmaPi(); + auto combNsigma = std::sqrt(tofNSigmaPi * tofNSigmaPi + tpcNSigmaPi * tpcNSigmaPi); - if (std::abs(tpcNSigmaPi) > settingCutNsigmaTPCPi) { - return false; - } mQaRegistry.fill(HIST("h2NsigmaPiTOF_preselection"), candidate.pt(), tofNSigmaPi); - if (std::sqrt(tofNSigmaPi * tofNSigmaPi + tpcNSigmaPi * tpcNSigmaPi) > settingCutNsigmaTOFTPCPi) { + if (combNsigma > settingCutNsigmaTOFTPCPi) { return false; } - mQaRegistry.fill(HIST("h2NsigmaPiTPC"), candidate.pt(), tpcNSigmaPi); - mQaRegistry.fill(HIST("h2NsigmaPiTOF"), candidate.pt(), tofNSigmaPi); + mQaRegistry.fill(HIST("h2NsigmaPiTPC"), candidate.sign() * candidate.pt(), tpcNSigmaPi); + mQaRegistry.fill(HIST("h2NsigmaPiTOF"), candidate.sign() * candidate.pt(), tofNSigmaPi); + mQaRegistry.fill(HIST("h2NsigmaPiComb"), candidate.sign() * candidate.pt(), combNsigma); return true; - } else if (std::abs(tpcNSigmaPi) < settingCutNsigmaTPCPi) { - mQaRegistry.fill(HIST("h2NsigmaPiTPC"), candidate.pt(), tpcNSigmaPi); + } else if (candidate.tpcInnerParam() < settingCutPinMinTOFPi) { + if (std::abs(tpcNSigmaPi) > settingCutNsigmaTPCPi) { + return false; + } + mQaRegistry.fill(HIST("h2NsigmaPiTPC"), candidate.sign() * candidate.pt(), tpcNSigmaPi); return true; } return false; @@ -425,35 +438,47 @@ struct PiDeuteronFemto { bool selectionPIDDe(const Ttrack& candidate) { float tpcInnerParam = candidate.tpcInnerParam(); + mQaRegistry.fill(HIST("h2dEdx"), candidate.sign() * tpcInnerParam, candidate.tpcSignal()); - if (tpcInnerParam < settingCutPinMinDe) { + if (std::abs(tpcInnerParam) < settingCutPinMinDe) { return false; } + float tpcNSigmaDe; + if (settingUseBBcomputeDeNsigma) { + tpcNSigmaDe = computeNSigmaDe(candidate); + } else { + tpcNSigmaDe = candidate.tpcNSigmaDe(); + } - auto tpcNSigmaDe = computeNSigmaDe(candidate); mQaRegistry.fill(HIST("h2NsigmaDeTPC_preselection"), candidate.sign() * candidate.pt(), tpcNSigmaDe); mQaRegistry.fill(HIST("h2NsigmaDeTPC_preselecComp"), candidate.sign() * candidate.pt(), candidate.tpcNSigmaDe()); + if (std::abs(candidate.pt()) < settingCutDeptMin || std::abs(candidate.pt()) > settingCutDeptMax) + return false; if (candidate.hasTOF() && candidate.tpcInnerParam() > settingCutPinMinTOFITSDe) { auto tofNSigmaDe = candidate.tofNSigmaDe(); - if (std::abs(tpcNSigmaDe) > settingCutNsigmaTPCDe) { + auto combNsigma = std::sqrt(tofNSigmaDe * tofNSigmaDe + tpcNSigmaDe * tpcNSigmaDe); + if (combNsigma > settingCutNsigmaTOFTPCDe) { return false; } - if (std::sqrt(tofNSigmaDe * tofNSigmaDe + tpcNSigmaDe * tpcNSigmaDe) > settingCutNsigmaTOFTPCDe) { + mQaRegistry.fill(HIST("h2dEdxDecandidates"), candidate.sign() * tpcInnerParam, candidate.tpcSignal()); + mQaRegistry.fill(HIST("h2NsigmaDeComb"), candidate.sign() * candidate.pt(), combNsigma); + mQaRegistry.fill(HIST("h2NsigmaDeTPC"), candidate.sign() * candidate.pt(), tpcNSigmaDe); + mQaRegistry.fill(HIST("h2NsigmaDeTOF"), candidate.sign() * candidate.pt(), tofNSigmaDe); + return true; + } else if (candidate.tpcInnerParam() <= settingCutPinMinTOFITSDe) { + if (std::abs(tpcNSigmaDe) > settingCutNsigmaTPCDe) { return false; } o2::aod::ITSResponse mResponseITS; auto itsnSigmaDe = mResponseITS.nSigmaITS(candidate.itsClusterSizes(), candidate.p(), candidate.eta()); - mQaRegistry.fill(HIST("h2NSigmaDeITS_preselection"), candidate.sign() * candidate.pt(), itsnSigmaDe); - if (itsnSigmaDe < settingCutNsigmaITSDe) { + if (std::abs(itsnSigmaDe) > settingCutNsigmaITSDe) { return false; } - mQaRegistry.fill(HIST("h2dEdxDecandidates"), candidate.sign() * tpcInnerParam, candidate.tpcSignal()); mQaRegistry.fill(HIST("h2NsigmaDeTPC"), candidate.sign() * candidate.pt(), tpcNSigmaDe); mQaRegistry.fill(HIST("h2NSigmaDeITS"), candidate.sign() * candidate.pt(), itsnSigmaDe); - return true; - } else if (std::abs(tpcNSigmaDe) < settingCutNsigmaTPCDe) { - mQaRegistry.fill(HIST("h2NsigmaDeTPC"), candidate.sign() * candidate.pt(), tpcNSigmaDe); + // mQaRegistry.fill(HIST("h2NsigmaDeComb"), candidate.sign() * candidate.pt(), combNsigma); + mQaRegistry.fill(HIST("h2dEdxDecandidates"), candidate.sign() * tpcInnerParam, candidate.tpcSignal()); return true; } return false; @@ -506,8 +531,7 @@ struct PiDeuteronFemto { } piDecand.momDe = std::array{trackDe.px(), trackDe.py(), trackDe.pz()}; - for (int i = 0; i < numCoordinates; i++) - piDecand.momPi = std::array{trackPi.px(), trackPi.py(), trackPi.pz()}; + piDecand.momPi = std::array{trackPi.px(), trackPi.py(), trackPi.pz()}; float invMass = 0; invMass = RecoDecay::m(std::array{piDecand.momDe, piDecand.momPi}, std::array{o2::constants::physics::MassDeuteron, o2::constants::physics::MassPiPlus}); if (settingCutInvMass > 0 && invMass > settingCutInvMass) { @@ -691,9 +715,14 @@ struct PiDeuteronFemto { { mQaRegistry.fill(HIST("hDePt"), piDecand.recoPtDe()); mQaRegistry.fill(HIST("hPiPt"), piDecand.recoPtPi()); + mQaRegistry.fill(HIST("hDeEta"), piDecand.recoEtaDe()); + mQaRegistry.fill(HIST("hPiEta"), piDecand.recoEtaPi()); + mQaRegistry.fill(HIST("hDePhi"), piDecand.recoPhiDe()); + mQaRegistry.fill(HIST("hPiPhi"), piDecand.recoPhiPi()); mQaRegistry.fill(HIST("hDePitInvMass"), piDecand.invMass); mQaRegistry.fill(HIST("hdcaxyDe"), piDecand.dcaxyDe); mQaRegistry.fill(HIST("hdcazDe"), piDecand.dcazDe); + mQaRegistry.fill(HIST("hdcazDe_min"), (abs(piDecand.dcazDe) - settingCutDeDCAzMin)); mQaRegistry.fill(HIST("hNClsDeITS"), piDecand.nClsItsDe); mQaRegistry.fill(HIST("hNClsPiITS"), piDecand.nClsItsPi); mQaRegistry.fill(HIST("hisBkgEM"), piDecand.isBkgEM); @@ -722,21 +751,27 @@ struct PiDeuteronFemto { double computeKstar(const PiDecandidate& piDecand) { - TLorentzVector he3, hadron; - float massHe3 = 2.80839; - float massHad = 0.1395704; - he3.SetPtEtaPhiM(abs(piDecand.recoPtDe()), piDecand.recoEtaDe(), piDecand.recoPhiDe(), massHe3); - hadron.SetPtEtaPhiM(abs(piDecand.recoPtPi()), piDecand.recoEtaPi(), piDecand.recoPhiPi(), massHad); - - TLorentzVector p_total_lab = he3 + hadron; - TVector3 v_cm = p_total_lab.BoostVector(); - TLorentzVector p1_cm = he3; - TLorentzVector p2_cm = hadron; - p1_cm.Boost(-v_cm); - p2_cm.Boost(-v_cm); - TLorentzVector p_diff_cm = p1_cm - p2_cm; - double kStar = sqrt(p_diff_cm.X() * p_diff_cm.X() + p_diff_cm.Y() * p_diff_cm.Y() + p_diff_cm.Z() * p_diff_cm.Z()); - return kStar / 2.0; + constexpr double massDe = o2::constants::physics::MassDeuteron; + constexpr double massHad = o2::constants::physics::MassPiPlus; + + const ROOT::Math::PtEtaPhiMVector De(std::abs(piDecand.recoPtDe()), piDecand.recoEtaDe(), piDecand.recoPhiDe(), massDe); + const ROOT::Math::PtEtaPhiMVector Had(std::abs(piDecand.recoPtPi()), piDecand.recoEtaPi(), piDecand.recoPhiPi(), massHad); + const ROOT::Math::PtEtaPhiMVector trackSum = De + Had; + + 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 DeCMS(De); + ROOT::Math::PxPyPzMVector HadCMS(Had); + + const ROOT::Math::Boost boostPRF = ROOT::Math::Boost(-betax, -betay, -betaz); + DeCMS = boostPRF(DeCMS); + HadCMS = boostPRF(HadCMS); + + const ROOT::Math::PxPyPzMVector RelKstar = DeCMS - HadCMS; + return 0.5 * RelKstar.P(); } void fillKstar(const PiDecandidate& piDecand) @@ -750,11 +785,6 @@ struct PiDeuteronFemto { float DeDCAxyMin = 0.015 + 0.0305 / TMath::Power(piDecand.recoPtDe(), 1.1); if (abs(piDecand.dcaxyDe) > DeDCAxyMin || abs(piDecand.dcazDe) > settingCutDeDCAzMin || abs(piDecand.dcaxyPi) > settingCutPiDCAxyMin || abs(piDecand.dcazPi) > settingCutPiDCAzMin) return; - if (std::abs(piDecand.recoPtPi()) < settingCutPiptMin || std::abs(piDecand.recoPtPi()) > settingCutPiptMax) - return; - if (std::abs(piDecand.recoPtDe()) < settingCutDeptMin || std::abs(piDecand.recoPtDe()) > settingCutDeptMax) - return; - fillHistograms(piDecand); double kstar = computeKstar(piDecand); @@ -771,6 +801,7 @@ struct PiDeuteronFemto { mQaRegistry.fill(HIST("hkStar_US_A"), kstar); } } + mQaRegistry.fill(HIST("hkStar_All"), kstar); } // ================================================================================================================== diff --git a/PWGCF/Femto3D/DataModel/singletrackselector.h b/PWGCF/Femto3D/DataModel/singletrackselector.h index c7323d15a32..d7f4f0822d3 100644 --- a/PWGCF/Femto3D/DataModel/singletrackselector.h +++ b/PWGCF/Femto3D/DataModel/singletrackselector.h @@ -135,7 +135,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(dIsGoodZvtxFT0vsPV, isGoodZvtxFT0vsPV, [](uint64_t se DECLARE_SOA_DYNAMIC_COLUMN(dIsVertexITSTPC, isVertexITSTPC, [](uint64_t selBit) -> bool { return TESTBIT(selBit, evsel::kIsVertexITSTPC); }); DECLARE_SOA_DYNAMIC_COLUMN(dIsVertexTOForTRDmatched, isVertexTOForTRDmatched, [](uint64_t selBit) -> int { return static_cast(TESTBIT(selBit, evsel::kIsVertexTOFmatched)) + static_cast(TESTBIT(selBit, evsel::kIsVertexTRDmatched)); }); DECLARE_SOA_DYNAMIC_COLUMN(dNoCollInTimeRangeStandard, noCollInTimeRangeStandard, [](uint64_t selBit) -> bool { return TESTBIT(selBit, evsel::kNoCollInTimeRangeStandard); }); - +DECLARE_SOA_DYNAMIC_COLUMN(dIsGoodITSLayersAll, isGoodITSLayersAll, [](uint64_t selBit) -> bool { return TESTBIT(selBit, evsel::kIsGoodITSLayersAll); }); } // namespace singletrackselector DECLARE_SOA_TABLE(SingleCollSels, "AOD", "SINGLECOLLSEL", // Table of the variables for single track selection. @@ -154,7 +154,8 @@ DECLARE_SOA_TABLE(SingleCollExtras_v1, "AOD", "SINGLECOLLEXTR1", // Joinable col singletrackselector::dIsGoodZvtxFT0vsPV, singletrackselector::dIsVertexITSTPC, singletrackselector::dIsVertexTOForTRDmatched, - singletrackselector::dNoCollInTimeRangeStandard); + singletrackselector::dNoCollInTimeRangeStandard, + singletrackselector::dIsGoodITSLayersAll); using SingleCollExtras = SingleCollExtras_v1; diff --git a/PWGCF/Femto3D/Tasks/CMakeLists.txt b/PWGCF/Femto3D/Tasks/CMakeLists.txt index 62a7b310690..4090fea6795 100644 --- a/PWGCF/Femto3D/Tasks/CMakeLists.txt +++ b/PWGCF/Femto3D/Tasks/CMakeLists.txt @@ -22,4 +22,9 @@ o2physics_add_dpl_workflow(femto3d-pair-task o2physics_add_dpl_workflow(femto3d-pair-task-mc SOURCES femto3dPairTaskMC.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(femto3d-pid-optimization + SOURCES PIDoptimization.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/Femto3D/Tasks/PIDoptimization.cxx b/PWGCF/Femto3D/Tasks/PIDoptimization.cxx new file mode 100644 index 00000000000..acf08e13079 --- /dev/null +++ b/PWGCF/Femto3D/Tasks/PIDoptimization.cxx @@ -0,0 +1,304 @@ +// 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 optimization of particle identification for femtoscopic analysis. +/// \author Sofia Tomassini +/// \since July 2025 + +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.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/StaticFor.h" +#include "Framework/runDataProcessing.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector4D.h" +#include "TMath.h" +#include "TRandom3.h" +#include + +#include "fairlogger/Logger.h" + +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +namespace o2::aod +{ +using SelectedTracks = soa::Join; +} +struct PidOptimization { + + HistogramRegistry histos{"Histos"}; + + Configurable _removeSameBunchPileup{"removeSameBunchPileup", false, ""}; + Configurable _requestGoodZvtxFT0vsPV{"requestGoodZvtxFT0vsPV", false, ""}; + Configurable _requestVertexITSTPC{"requestVertexITSTPC", false, ""}; + Configurable _requestVertexTOForTRDmatched{"requestVertexTOFmatched", 0, "0 -> no selectio; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; + Configurable _requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; + Configurable> _IRcut{"IRcut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; + Configurable> _OccupancyCut{"OccupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; + + Configurable _sign{"sign", 1, "sign of a track"}; + Configurable _vertexZ{"VertexZ", 20.0, "abs vertexZ value limit"}; + Configurable _min_P{"min_P", 0.0, "lower mometum limit"}; + Configurable _max_P{"max_P", 100.0, "upper mometum limit"}; + Configurable _eta{"eta", 100.0, "abs eta value limit"}; + + Configurable> _dcaXY{"dcaXY", std::vector{0.3f, 0.0f, 0.0f}, "abs dcaXY value limit; formula: [0] + [1]*pT^[2]"}; + Configurable> _dcaZ{"dcaZ", std::vector{0.3f, 0.0f, 0.0f}, "abs dcaZ value limit; formula: [0] + [1]*pT^[2]"}; + Configurable _tpcNClsFound{"minTpcNClsFound", 0, "minimum allowed number of TPC clasters"}; + Configurable _tpcChi2NCl{"tpcChi2NCl", 100.0, "upper limit for chi2 value of a fit over TPC clasters"}; + Configurable _tpcCrossedRowsOverFindableCls{"tpcCrossedRowsOverFindableCls", 0, "lower limit of TPC CrossedRows/FindableCls value"}; + Configurable _tpcFractionSharedCls{"maxTpcFractionSharedCls", 0.4, "maximum fraction of TPC shared clasters"}; + Configurable _itsNCls{"minItsNCls", 0, "minimum allowed number of ITS clasters for a track"}; + Configurable _itsChi2NCl{"itsChi2NCl", 100.0, "upper limit for chi2 value of a fit over ITS clasters for a track"}; + Configurable _particlePDG{"particlePDG", 2212, "PDG code of a particle to perform PID for (only pion, kaon, proton and deurton are supported now)"}; + Configurable> _tpcNSigma{"tpcNSigma", std::pair{-100, 100}, "Nsigma range in TPC before the TOF is used"}; + Configurable> _itsNSigma{"itsNSigma", std::pair{-100, 100}, "Nsigma range in ITS to use along with TPC"}; + Configurable _PIDtrshld{"PIDtrshld", 10.0, "value of momentum from which the PID is done with TOF (before that only TPC is used)"}; + Configurable> _tofNSigma{"tofNSigma", std::pair{-100, 100}, "Nsigma range in TOF"}; + Configurable> _tpcNSigmaResidual{"tpcNSigmaResidual", std::pair{-10, 10}, "residual TPC Nsigma cut to use with the TOF"}; + Configurable _particlePDGtoReject{"particlePDGtoReject", 211, "PDG codes of perticles that will be rejected with TOF (only pion, kaon, proton and deurton are supported now)"}; + Configurable> _rejectWithinNsigmaTOF{"rejectWithinNsigmaTOF", std::pair{-10, 10}, "TOF rejection Nsigma range for particles specified with PDG to be rejected"}; + + std::shared_ptr ITShisto; + std::shared_ptr TPChisto; + std::shared_ptr TOFhisto; + std::shared_ptr ITSvsTPChisto; + std::shared_ptr dcaxy_p; + std::shared_ptr dcaxy_pt; + std::shared_ptr dcaz_p; + std::shared_ptr dcaz_pt; + + void init(o2::framework::InitContext& context) + { + o2::aod::ITSResponse::setParameters(context); + histos.add("vtz", "vtz", kTH1F, {{100, -20., 20., "vtxz"}}); + histos.add("eta", "eta", kTH1F, {{200, -2.5, 2.5, "eta"}}); + histos.add("phi", "phi", kTH1F, {{200, 0., 2. * M_PI, "phi"}}); + histos.add("px", "px", kTH1F, {{100, 0., 5., "px"}}); + histos.add("py", "py", kTH1F, {{100, 0., 5., "py"}}); + histos.add("pz", "pz", kTH1F, {{100, 0., 5., "pz"}}); + histos.add("p", "p", kTH1F, {{100, 0., 5., "p"}}); + histos.add("pt", "pt", kTH1F, {{100, 0., 5., "pt"}}); + histos.add("sign", "sign", kTH1F, {{3, -1.5, 1.5, "sign"}}); + histos.add("TPCClusters", "TPCClusters", kTH1F, {{163, -0.5, 162.5, "NTPCClust"}}); + histos.add("TPCCrossedRowsOverFindableCls", "TPCCrossedRowsOverFindableCls", kTH1F, {{100, 0.0, 10.0, "NcrossedRowsOverFindable"}}); + histos.add("TPCFractionSharedCls", "TPCFractionSharedCls", kTH1F, {{100, 0.0, 1.0, "TPCsharedFraction"}}); + histos.add("ITSClusters", "ITSClusters", kTH1F, {{10, -0.5, 9.5, "NITSClust"}}); + histos.add("ITSchi2", "ITSchi2", kTH1F, {{100, 0.0, 40., "ITSchi2"}}); + histos.add("TPCchi2", "TPCchi2", kTH1F, {{100, 0.0, 6., "TPCchi2"}}); + + dcaxy_p = histos.add("dcaxy_p", "dcaxy_p", kTH2F, {{100, 0., 5.0, "p"}, {500, -0.5, 0.5, "dcaxy"}}); + dcaxy_pt = histos.add("dcaxy_pt", "dcaxy_pt", kTH2F, {{100, 0., 5.0, "pt"}, {500, -0.5, 0.5, "dcaxy"}}); + dcaz_p = histos.add("dcaz_p", "dcaz_p", kTH2F, {{100, 0., 5.0, "p"}, {500, -0.5, 0.5, "dcaz"}}); + dcaz_pt = histos.add("dcaz_pt", "dcaz_pt", kTH2F, {{100, 0., 5.0, "pt"}, {500, -0.5, 0.5, "dcaxy"}}); + + ITShisto = histos.add(Form("nsigmaITS_PDG%i", _particlePDG.value), Form("nsigmaITS_PDG%i", _particlePDG.value), kTH2F, {{100, 0., 10.}, {1000, -50., 50.}}); + TPChisto = histos.add(Form("nsigmaTPC_PDG%i", _particlePDG.value), Form("nsigmaTPC_PDG%i", _particlePDG.value), kTH2F, {{100, 0., 10.}, {1000, -50., 50.}}); + TOFhisto = histos.add(Form("nsigmaTOF_PDG%i", _particlePDG.value), Form("nsigmaTOF_PDG%i", _particlePDG.value), kTH2F, {{100, 0., 10.}, {2000, -100., 100.}}); + + ITSvsTPChisto = histos.add(Form("nsigmaITSvsTPC_PDG%i", _particlePDG.value), Form("nsigmaITSvsTPC_PDG%i", _particlePDG.value), kTH2F, {{1000, -50., 50.}, {1000, -50., 50.}}); + } + + template + inline float getITSNsigma(TrackType const& track, int const& PDG) + { + switch (PDG) { + case 211: + return track.itsNSigmaPi(); + case 321: + return track.itsNSigmaKa(); + case 2212: + return track.itsNSigmaPr(); + case 1000010020: + return track.itsNSigmaDe(); + case 0: + return -1000.0; + default: + LOG(fatal) << "Cannot interpret PDG for ITS selection: " << PDG; + return -1000.0; + } + } + template + inline float getTPCNsigma(TrackType const& track, int const& PDG) + { + switch (PDG) { + case 211: + return track.tpcNSigmaPi(); + case 321: + return track.tpcNSigmaKa(); + case 2212: + return track.tpcNSigmaPr(); + case 1000010020: + return track.tpcNSigmaDe(); + case 0: + return -1000.0; + default: + LOG(fatal) << "Cannot interpret PDG for TPC selection: " << PDG; + return -1000.0; + } + } + template + inline float getTOFNsigma(TrackType const& track, int const& PDG) + { + switch (PDG) { + case 211: + return track.tofNSigmaPi(); + case 321: + return track.tofNSigmaKa(); + case 2212: + return track.tofNSigmaPr(); + case 1000010020: + return track.tofNSigmaDe(); + case 0: + return -1000.0; + default: + LOG(fatal) << "Cannot interpret PDG for TOF selection: " << PDG; + return -1000.0; + } + } + + bool isInRange(float value, std::pair range) + { + return value > range.first && value < range.second; + } + + void process(soa::Join const& collisions, aod::SelectedTracks const& tracks) + { + auto tracksWithItsPid = soa::Attach(tracks); + + for (auto& collision : collisions) { + if (!collision.sel8() || abs(collision.posZ()) > _vertexZ) + continue; + if (_requestGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) + continue; + if (_removeSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + if (_requestGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + if (_requestVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + continue; + // if (_requestVertexTOForTRDmatched > collision.selection_bit(o2::aod::evsel::kisVertexTOForTRDmatched())) + // continue; + if (_requestNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) + continue; + // if (collision.multPerc() < _centCut.value.first || collision.multPerc() >= _centCut.value.second) + // continue; + // if (collision.hadronicRate() < _IRcut.value.first || collision.hadronicRate() >= _IRcut.value.second) + // continue; + if (collision.trackOccupancyInTimeRange() < _OccupancyCut.value.first || collision.trackOccupancyInTimeRange() >= _OccupancyCut.value.second) + continue; + + histos.fill(HIST("vtz"), collision.posZ()); + } + + for (auto& track : tracksWithItsPid) { + if (track.sign() != _sign) + continue; + if (track.p() < _min_P || track.p() > _max_P || abs(track.eta()) > _eta) + continue; + if ((track.itsChi2NCl() >= _itsChi2NCl) || (track.itsChi2NCl() <= 0.f) || (track.tpcChi2NCl() <= 0.f) || (track.tpcChi2NCl() >= _tpcChi2NCl)) + continue; + if ((track.tpcFractionSharedCls()) > _tpcFractionSharedCls || (track.tpcNClsFound()) < _tpcNClsFound || (track.tpcCrossedRowsOverFindableCls()) < _tpcCrossedRowsOverFindableCls || (track.itsNCls()) < _itsNCls) + continue; + if (std::fabs(track.dcaXY()) > _dcaXY.value[0] + _dcaXY.value[1] * std::pow(track.pt(), _dcaXY.value[2]) || std::fabs(track.dcaZ()) > _dcaZ.value[0] + _dcaZ.value[1] * std::pow(track.pt(), _dcaZ.value[2])) + continue; + + bool belowThreshold = track.p() < _PIDtrshld; + float tpcSigma = getTPCNsigma(track, _particlePDG); + float itsSigma = getITSNsigma(track, _particlePDG); + float tofSigma = getTOFNsigma(track, _particlePDG); + float tofRejection = getTOFNsigma(track, _particlePDGtoReject); + + bool passTPC = belowThreshold ? isInRange(tpcSigma, _tpcNSigma.value) : isInRange(tpcSigma, _tpcNSigmaResidual.value); + + bool passITS = belowThreshold ? isInRange(itsSigma, _itsNSigma.value) : true; + + bool passTOF = belowThreshold ? true : (isInRange(tofSigma, _tofNSigma.value) && !isInRange(tofRejection, _rejectWithinNsigmaTOF.value)); + + if (passTPC && passITS && passTOF) { + histos.fill(HIST("eta"), track.eta()); + histos.fill(HIST("phi"), track.phi()); + histos.fill(HIST("px"), track.px()); + histos.fill(HIST("py"), track.py()); + histos.fill(HIST("pz"), track.pz()); + histos.fill(HIST("p"), track.p()); + histos.fill(HIST("pt"), track.pt()); + histos.fill(HIST("sign"), track.sign()); + histos.fill(HIST("dcaxy_p"), track.p(), track.dcaXY()); + histos.fill(HIST("dcaxy_pt"), track.pt(), track.dcaXY()); + histos.fill(HIST("dcaz_p"), track.p(), track.dcaZ()); + histos.fill(HIST("dcaz_pt"), track.pt(), track.dcaZ()); + histos.fill(HIST("TPCClusters"), track.tpcNClsFound()); + histos.fill(HIST("TPCCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + histos.fill(HIST("TPCFractionSharedCls"), track.tpcFractionSharedCls()); + histos.fill(HIST("ITSClusters"), track.itsNCls()); + histos.fill(HIST("ITSchi2"), track.itsChi2NCl()); + histos.fill(HIST("TPCchi2"), track.tpcChi2NCl()); + + switch (_particlePDG) { + case 211: + ITShisto->Fill(track.p(), track.itsNSigmaPi()); + TPChisto->Fill(track.p(), track.tpcNSigmaPi()); + TOFhisto->Fill(track.p(), track.tofNSigmaPi()); + ITSvsTPChisto->Fill(track.itsNSigmaPi(), track.tpcNSigmaPi()); + break; + case 321: + ITShisto->Fill(track.p(), track.itsNSigmaKa()); + TPChisto->Fill(track.p(), track.tpcNSigmaKa()); + TOFhisto->Fill(track.p(), track.tofNSigmaKa()); + ITSvsTPChisto->Fill(track.itsNSigmaKa(), track.tpcNSigmaKa()); + break; + case 2212: + ITShisto->Fill(track.p(), track.itsNSigmaPr()); + TPChisto->Fill(track.p(), track.tpcNSigmaPr()); + TOFhisto->Fill(track.p(), track.tofNSigmaPr()); + ITSvsTPChisto->Fill(track.itsNSigmaPr(), track.tpcNSigmaPr()); + break; + case 1000010020: + ITShisto->Fill(track.p(), track.itsNSigmaDe()); + TPChisto->Fill(track.p(), track.tpcNSigmaDe()); + TOFhisto->Fill(track.p(), track.tofNSigmaDe()); + ITSvsTPChisto->Fill(track.itsNSigmaDe(), track.tpcNSigmaDe()); + break; + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx b/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx index 83aa740795c..db6c12dc14c 100644 --- a/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dPairTask.cxx @@ -55,6 +55,7 @@ struct FemtoCorrelations { Configurable _requestVertexITSTPC{"requestVertexITSTPC", false, ""}; Configurable _requestVertexTOForTRDmatched{"requestVertexTOFmatched", 0, "0 -> no selectio; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; Configurable _requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; + Configurable _requestIsGoodITSLayersAll{"requestIsGoodITSLayersAll", false, "cut time intervals with dead ITS staves"}; Configurable> _IRcut{"IRcut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; Configurable> _OccupancyCut{"OccupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; @@ -423,6 +424,8 @@ struct FemtoCorrelations { continue; if (_requestNoCollInTimeRangeStandard && !track.template singleCollSel_as>().noCollInTimeRangeStandard()) continue; + if (_requestIsGoodITSLayersAll && !track.template singleCollSel_as>().isGoodITSLayersAll()) + continue; if (track.tpcFractionSharedCls() > _tpcFractionSharedCls || track.itsNCls() < _itsNCls) continue; if (track.template singleCollSel_as>().multPerc() < *_centBins.value.begin() || track.template singleCollSel_as>().multPerc() >= *(_centBins.value.end() - 1)) @@ -473,7 +476,8 @@ struct FemtoCorrelations { continue; if (_requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) continue; - + if (_requestIsGoodITSLayersAll && !collision.isGoodITSLayersAll()) + continue; if (selectedtracks_1.find(collision.globalIndex()) == selectedtracks_1.end()) { if (IsIdentical) continue; diff --git a/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx b/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx index b776d34e629..252fb5fc410 100644 --- a/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dPairTaskMC.cxx @@ -51,6 +51,7 @@ struct FemtoCorrelationsMC { Configurable _requestVertexITSTPC{"requestVertexITSTPC", false, ""}; Configurable _requestVertexTOForTRDmatched{"requestVertexTOFmatched", 0, "0 -> no selectio; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; Configurable _requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; + Configurable _requestIsGoodITSLayersAll{"requestIsGoodITSLayersAll", false, "cut time intervals with dead ITS staves"}; Configurable> _IRcut{"IRcut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; Configurable> _OccupancyCut{"OccupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; @@ -350,7 +351,8 @@ struct FemtoCorrelationsMC { continue; if (_requestNoCollInTimeRangeStandard && !track.template singleCollSel_as>().noCollInTimeRangeStandard()) continue; - + if (_requestIsGoodITSLayersAll && !track.template singleCollSel_as>().isGoodITSLayersAll()) + continue; unsigned int centBin = o2::aod::singletrackselector::getBinIndex(track.template singleCollSel_as>().multPerc(), _centBins); if (track.sign() == _sign_1 && (track.p() < _PIDtrshld_1 ? o2::aod::singletrackselector::TPCselection(track, TPCcuts_1, _itsNSigma_1.value) : o2::aod::singletrackselector::TOFselection(track, TOFcuts_1, _tpcNSigmaResidual_1.value))) { @@ -412,7 +414,8 @@ struct FemtoCorrelationsMC { continue; if (_requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) continue; - + if (_requestIsGoodITSLayersAll && !collision.isGoodITSLayersAll()) + continue; if (selectedtracks_1.find(collision.globalIndex()) == selectedtracks_1.end()) { if (IsIdentical) continue; diff --git a/PWGCF/Femto3D/Tasks/femto3dQA.cxx b/PWGCF/Femto3D/Tasks/femto3dQA.cxx index 64858324b48..b31f3cd970e 100644 --- a/PWGCF/Femto3D/Tasks/femto3dQA.cxx +++ b/PWGCF/Femto3D/Tasks/femto3dQA.cxx @@ -52,6 +52,7 @@ struct QAHistograms { Configurable _requestVertexITSTPC{"requestVertexITSTPC", false, ""}; Configurable _requestVertexTOForTRDmatched{"requestVertexTOFmatched", 0, "0 -> no selectio; 1 -> vertex is matched to TOF or TRD; 2 -> matched to both;"}; Configurable _requestNoCollInTimeRangeStandard{"requestNoCollInTimeRangeStandard", false, ""}; + Configurable _requestIsGoodITSLayersAll{"requestIsGoodITSLayersAll", false, "cut time intervals with dead ITS staves"}; Configurable> _IRcut{"IRcut", std::pair{0.f, 100.f}, "[min., max.] IR range to keep events within"}; Configurable> _OccupancyCut{"OccupancyCut", std::pair{0, 10000}, "[min., max.] occupancy range to keep events within"}; @@ -181,6 +182,8 @@ struct QAHistograms { continue; if (_requestNoCollInTimeRangeStandard && !collision.noCollInTimeRangeStandard()) continue; + if (_requestIsGoodITSLayersAll && !collision.isGoodITSLayersAll()) + continue; if (collision.multPerc() < _centCut.value.first || collision.multPerc() >= _centCut.value.second) continue; if (collision.hadronicRate() < _IRcut.value.first || collision.hadronicRate() >= _IRcut.value.second) @@ -206,7 +209,8 @@ struct QAHistograms { continue; if (_requestNoCollInTimeRangeStandard && !track.template singleCollSel_as().noCollInTimeRangeStandard()) continue; - + if (_requestIsGoodITSLayersAll && !track.template singleCollSel_as().isGoodITSLayersAll()) + continue; if (std::fabs(track.template singleCollSel_as().posZ()) > _vertexZ) continue; if (track.template singleCollSel_as().multPerc() < _centCut.value.first || track.template singleCollSel_as().multPerc() >= _centCut.value.second) diff --git a/PWGCF/FemtoDream/Core/femtoDreamContainer.h b/PWGCF/FemtoDream/Core/femtoDreamContainer.h index 5e0222a4f07..3d95fc08311 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamContainer.h +++ b/PWGCF/FemtoDream/Core/femtoDreamContainer.h @@ -202,10 +202,12 @@ class FemtoDreamContainer { const float kT = FemtoDreamMath::getkT(part1, mMassOne, part2, mMassTwo); if constexpr (isHF) { - float mP2; - if (part2.candidateSelFlag() == o2::aod::fdhf::lcToPKPi) { + float mP2 = 0.0; + if (part2.candidateSelFlag() == o2::aod::fdhf::dplusToPiKPi) { + mP2 = part2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); + } else if (part2.candidateSelFlag() == o2::aod::fdhf::lcToPKPi) { mP2 = part2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); - } else { + } else if (part2.candidateSelFlag() == o2::aod::fdhf::lcToPiKP) { mP2 = part2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); } mHistogramRegistry->fill(HIST(mFolderSuffix[mEventType]) + HIST(o2::aod::femtodreamMCparticle::MCTypeName[mc]) + HIST("/relPairkstarmP2"), femtoObs, mP2); diff --git a/PWGCF/FemtoDream/Core/femtoDreamUtils.h b/PWGCF/FemtoDream/Core/femtoDreamUtils.h index c5db8dcc70e..f9bb60633f3 100644 --- a/PWGCF/FemtoDream/Core/femtoDreamUtils.h +++ b/PWGCF/FemtoDream/Core/femtoDreamUtils.h @@ -52,6 +52,9 @@ inline float getMass(int pdgCode) case o2::constants::physics::Pdg::kPhi: mass = o2::constants::physics::MassPhi; break; + case o2::constants::physics::Pdg::kDPlus: + mass = o2::constants::physics::MassDPlus; + break; case o2::constants::physics::Pdg::kLambdaCPlus: mass = o2::constants::physics::MassLambdaCPlus; break; diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx index 7272382f357..0e190295508 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTask.cxx @@ -13,39 +13,45 @@ /// \brief Tasks that produces the track tables used for the pairing /// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de -#include -#include -#include -#include +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamCascadeSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" +#include "PWGCF/FemtoDream/Core/femtoDreamV0Selection.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" + #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h" -#include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" -#include "PWGCF/FemtoDream/Core/femtoDreamV0Selection.h" -#include "PWGCF/FemtoDream/Core/femtoDreamCascadeSelection.h" -#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "EventFiltering/Zorro.h" -#include "PWGCF/DataModel/FemtoDerived.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" -#include "TMath.h" +#include + #include "Math/Vector4D.h" +#include "TMath.h" + +#include + +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::aod::rctsel; using namespace o2::analysis::femtoDream; namespace o2::aod @@ -205,6 +211,12 @@ struct femtoDreamProducerTask { } OptionTrackSpecialSelections; + struct : o2::framework::ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", false, "Check event quality in run condition table"}; + Configurable cfgEvtRCTFlagCheckerLabel{"cfgEvtRCTFlagCheckerLabel", "CBT_hadronPID", "Evt sel: RCT flag checker label"}; + Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; + } rctCut; + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry TrackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry V0Registry{"V0", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -214,6 +226,7 @@ struct femtoDreamProducerTask { float mMagField; std::string zorroTriggerNames = ""; Service ccdb; /// Accessing the CCDB + RCTFlagsChecker rctChecker; void init(InitContext&) { @@ -255,6 +268,8 @@ struct femtoDreamProducerTask { zorroTriggerNames.pop_back(); } + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, false, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + colCuts.setCuts(ConfEvtZvtx.value, ConfEvtTriggerCheck.value, ConfEvtTriggerSel.value, ConfEvtOfflineCheck.value, ConfEvtAddOfflineCheck.value, ConfIsRun3.value); colCuts.init(&qaRegistry); @@ -568,6 +583,7 @@ struct femtoDreamProducerTask { if (!colCuts.isSelectedCollision(col)) { return; } + if (ConfIsActivateV0.value) { if (colCuts.isEmptyCollision(col, tracks, trackCuts) && colCuts.isEmptyCollision(col, fullV0s, v0Cuts, tracks)) { return; @@ -578,6 +594,10 @@ struct femtoDreamProducerTask { } } + if (rctCut.requireRCTFlagChecker && !rctChecker(col)) { + return; + } + outputCollision(vtxZ, mult, multNtr, spher, mMagField); if constexpr (isMC) { fillMCCollision(col); diff --git a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx index 9e7a30a9719..33f07d2772e 100644 --- a/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx +++ b/PWGCF/FemtoDream/TableProducer/femtoDreamProducerTaskForSpecificAnalysis.cxx @@ -13,24 +13,24 @@ /// \brief Tasks that reads the track tables and creates track triplets; only three identical particles can be used /// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de -#include -#include +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h" +#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.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 "TDatabasePDG.h" +#include "Framework/runDataProcessing.h" -#include "PWGCF/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" -#include "PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h" -#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" -#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" +#include +#include using namespace o2; using namespace o2::analysis::femtoDream; @@ -38,7 +38,7 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -struct femtoDreamProducerTaskForSpecificAnalysis { +struct FemtoDreamProducerTaskForSpecificAnalysis { SliceCache cache; @@ -49,33 +49,45 @@ struct femtoDreamProducerTaskForSpecificAnalysis { float mMassOne = -999, mMassTwo = -999, mMassThree = -999; int collisions = 0; - Configurable ConfNumberOfTracks{"ConfNumberOfTracks", 3, "Number of tracks"}; - Configurable ConfNumberOfV0{"ConfNumberOfV0", 0, "Number of V0"}; - Configurable ConfNumberOfCascades{"ConfNumberOfCascades", 0, "Number of Cascades"}; + // Require bitmask selection for candidates + Configurable confRequireBitmask{"confRequireBitmask", false, "Require bitmask selection for candidates"}; + + // Number of candidates required + Configurable confNumberOfTracks{"confNumberOfTracks", 3, "Number of tracks"}; + Configurable confNumberOfV0{"confNumberOfV0", 0, "Number of V0"}; + Configurable confNumberOfCascades{"confNumberOfCascades", 0, "Number of Cascades"}; /// Track selection - Configurable ConfPIDthrMom{"ConfPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; - Configurable ConfTPCPIDBit{"ConfTPCPIDBit", 16, "PID TPC bit from cutCulator "}; - Configurable ConfTPCTOFPIDBit{"ConfTPCTOFPIDBit", 8, "PID TPCTOF bit from cutCulator"}; + Configurable confPIDthrMom{"confPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; + Configurable confTPCPIDBit{"confTPCPIDBit", 16, "PID TPC bit from cutCulator "}; + Configurable confTPCTOFPIDBit{"confTPCTOFPIDBit", 8, "PID TPCTOF bit from cutCulator"}; + Configurable confCutPart{"confCutPart", 0, "Track - Selection bit from cutCulator for part"}; + Configurable confCutPartAntiPart{"confCutPartAntiPart", 0, "Track - Selection bit from cutCulator for antipart"}; /// Partition for selected particles - Partition SelectedParts = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && - ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= ConfPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCTOFPIDBit)); + Partition selectedParts = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= confPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, confTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, confTPCTOFPIDBit)); /// V0 selection - Configurable Conf_minInvMass_V0{"Conf_minInvMass_V0", 1.08, "Minimum invariant mass of V0 (particle)"}; - Configurable Conf_maxInvMass_V0{"Conf_maxInvMass_V0", 1.15, "Maximum invariant mass of V0 (particle)"}; - Configurable Conf_minInvMassAnti_V0{"Conf_minInvMassAnti_V0", 1.08, "Minimum invariant mass of V0 (antiparticle)"}; - Configurable Conf_maxInvMassAnti_V0{"Conf_maxInvMassAnti_V0", 1.15, "Maximum invariant mass of V0 (antiparticle)"}; + Configurable confMinInvMassV0{"confMinInvMassV0", 1.08, "Minimum invariant mass of V0 (particle)"}; + Configurable confMaxInvMassV0{"confMaxInvMassV0", 1.15, "Maximum invariant mass of V0 (particle)"}; + Configurable confMinInvMassAntiV0{"confMinInvMassAntiV0", 1.08, "Minimum invariant mass of V0 (antiparticle)"}; + Configurable confMaxInvMassAntiV0{"confMaxInvMassAntiV0", 1.15, "Maximum invariant mass of V0 (antiparticle)"}; + Configurable confCutV0SameForAntipart{"confCutV0SameForAntipart", 0, "V0 - Selection bit from cutCulator for part/antipart"}; + Configurable confChildPosCutV0{"confChildPosCutV0", 149, "Selection bit for positive child of V0"}; + Configurable confChildPosTPCBitV0{"confChildPosTPCBitV0", 2, "PID TPC bit for positive child of V0"}; + Configurable confChildNegCutV0{"confChildNegCutV0", 149, "Selection bit for negative child of V0"}; + Configurable confChildNegTPCBitV0{"confChildNegTPCBitV0", 2, "PID TPC bit for negative child of V0"}; + /// Cascade selection - Configurable Conf_minInvMass_Cascade{"Conf_minInvMass_Cascade", 1.2, "Minimum invariant mass of Cascade (particle)"}; - Configurable Conf_maxInvMass_Cascade{"Conf_maxInvMass_Cascade", 1.5, "Maximum invariant mass of Cascade (particle)"}; + Configurable confMinInvMassCascade{"confMinInvMassCascade", 1.2, "Minimum invariant mass of Cascade (particle)"}; + Configurable confMaxInvMassCascade{"confMaxInvMassCascade", 1.5, "Maximum invariant mass of Cascade (particle)"}; // Partition for selected particles - Partition SelectedV0s = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)); - Partition SelectedCascades = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kCascade)); + Partition selectedV0s = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kV0)); + Partition selectedCascades = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kCascade)); - HistogramRegistry EventRegistry{"EventRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry eventRegistry{"eventRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; static constexpr uint32_t kSignPlusMask = 1 << 1; @@ -94,9 +106,13 @@ struct femtoDreamProducerTaskForSpecificAnalysis { void init(InitContext&) { - EventRegistry.add("hStatistiscs", ";bin;Entries", kTH1F, {{3, 0, 3}}); - // get bit for the collision mask + eventRegistry.add("hStatistiscs", ";bin;Entries", kTH1F, {{3, 0, 3}}); + // Never run V0s and Cascades together as this will DOUBLE the track number and induce self correlations + if ((doprocessCollisionsWithNTracksAndNCascades && doprocessCollisionsWithNTracksAndNV0)) { + LOG(fatal) << "Never run V0s and Cascades together as this will DOUBLE the track number and induce self correlations!"; + } } + /// This function stores accepted collisions in derived data /// @tparam PartitionType /// @tparam PartType @@ -105,36 +121,66 @@ struct femtoDreamProducerTaskForSpecificAnalysis { /// @param groupSelectedV0s partition for the second particle passed by the process function /// @param parts femtoDreamParticles table template - void createSpecifiedDerivedData(o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedV0s, PartType parts) + void createSpecifiedDerivedData(const o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedV0s, PartType parts) { /// check tracks int tracksCount = 0; int antitracksCount = 0; - for (auto& part : groupSelectedTracks) { + for (const auto& part : groupSelectedTracks) { if (part.cut() & 1) { - antitracksCount++; + if (!confRequireBitmask || ncheckbit(part.cut(), confCutPartAntiPart)) { + antitracksCount++; + } } else { - tracksCount++; + if (!confRequireBitmask || ncheckbit(part.cut(), confCutPart)) { + tracksCount++; + } } } /// check V0s - int V0Count = 0; + int v0Count = 0; int antiV0Count = 0; - for (auto& V0 : groupSelectedV0s) { - if ((V0.mLambda() > Conf_minInvMass_V0) && (V0.mLambda() < Conf_maxInvMass_V0)) { - V0Count++; - } else if ((V0.mAntiLambda() > Conf_minInvMassAnti_V0) && (V0.mAntiLambda() < Conf_maxInvMassAnti_V0)) { - antiV0Count++; + 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++; + } } } std::vector tmpIDtrack; - if ((V0Count >= ConfNumberOfV0 && tracksCount >= ConfNumberOfTracks) || (antiV0Count >= ConfNumberOfV0 && antitracksCount >= ConfNumberOfTracks)) { - EventRegistry.fill(HIST("hStatistiscs"), 1); + if ((v0Count >= confNumberOfV0 && tracksCount >= confNumberOfTracks) || (antiV0Count >= confNumberOfV0 && antitracksCount >= confNumberOfTracks)) { + eventRegistry.fill(HIST("hStatistiscs"), 1); outputCollision(col.posZ(), col.multV0M(), col.multNtr(), col.sphericity(), col.magField()); - for (auto& femtoParticle : parts) { + for (const auto& femtoParticle : parts) { if (aod::femtodreamparticle::ParticleType::kTrack == femtoParticle.partType()) { std::vector childIDs = {0, 0}; outputParts(outputCollision.lastIndex(), @@ -190,23 +236,23 @@ struct femtoDreamProducerTaskForSpecificAnalysis { } } } else { - EventRegistry.fill(HIST("hStatistiscs"), 2); + 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 processCollisionsWithNTracksAndNV0(o2::aod::FDCollision& col, - o2::aod::FDParticles& parts) + void processCollisionsWithNTracksAndNV0(const o2::aod::FDCollision& col, + const o2::aod::FDParticles& parts) { - EventRegistry.fill(HIST("hStatistiscs"), 0); - auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupSelectedV0s = SelectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + eventRegistry.fill(HIST("hStatistiscs"), 0); + auto thegroupSelectedParts = selectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupSelectedV0s = selectedV0s->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); createSpecifiedDerivedData(col, thegroupSelectedParts, thegroupSelectedV0s, parts); } - PROCESS_SWITCH(femtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNV0, "Enable producing data with ppp collisions for data", true); + PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNV0, "Enable producing data with ppp collisions for data", true); /// This function stores accepted collisions in derived data /// @tparam PartitionType @@ -216,13 +262,13 @@ struct femtoDreamProducerTaskForSpecificAnalysis { /// @param groupSelectedV0s partition for the second particle passed by the process function /// @param parts femtoDreamParticles table template - void createSpecifiedDerivedData_TrkCascade(o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedCascades, PartType parts) + void createSpecifiedDerivedDataTrkCascade(const o2::aod::FDCollision& col, PartitionType groupSelectedTracks, PartitionType groupSelectedCascades, PartType parts) { /// check tracks int tracksCount = 0; int antitracksCount = 0; - for (auto& part : groupSelectedTracks) { + for (const auto& part : groupSelectedTracks) { if (part.cut() & 1) { antitracksCount++; } else { @@ -231,11 +277,11 @@ struct femtoDreamProducerTaskForSpecificAnalysis { } /// check Cascades - int CascadeCount = 0; + int ascadeCount = 0; int antiCascadeCount = 0; - for (auto& casc : groupSelectedCascades) { + for (const auto& casc : groupSelectedCascades) { if ((casc.cut() & kSignPlusMask) == kSignPlusMask) { - CascadeCount++; + ascadeCount++; } else { antiCascadeCount++; } @@ -243,11 +289,11 @@ struct femtoDreamProducerTaskForSpecificAnalysis { std::vector tmpIDtrack; - if ((CascadeCount >= ConfNumberOfCascades && tracksCount >= ConfNumberOfTracks) || (antiCascadeCount >= ConfNumberOfCascades && antitracksCount >= ConfNumberOfTracks)) { - EventRegistry.fill(HIST("hStatistiscs"), 1); + if ((ascadeCount >= confNumberOfCascades && tracksCount >= confNumberOfTracks) || (antiCascadeCount >= confNumberOfCascades && antitracksCount >= confNumberOfTracks)) { + eventRegistry.fill(HIST("hStatistiscs"), 1); outputCollision(col.posZ(), col.multV0M(), col.multNtr(), col.sphericity(), col.magField()); - for (auto& femtoParticle : parts) { + for (const auto& femtoParticle : parts) { if (aod::femtodreamparticle::ParticleType::kTrack == femtoParticle.partType()) { std::vector childIDs = {0, 0}; outputParts(outputCollision.lastIndex(), @@ -323,29 +369,29 @@ struct femtoDreamProducerTaskForSpecificAnalysis { } } } else { - EventRegistry.fill(HIST("hStatistiscs"), 2); + 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 processCollisionsWithNTracksAndNCascades(o2::aod::FDCollision& col, - o2::aod::FDParticles& parts) + void processCollisionsWithNTracksAndNCascades(const o2::aod::FDCollision& col, + const o2::aod::FDParticles& parts) { - EventRegistry.fill(HIST("hStatistiscs"), 0); - auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - auto thegroupSelectedCascades = SelectedCascades->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + eventRegistry.fill(HIST("hStatistiscs"), 0); + auto thegroupSelectedParts = selectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + auto thegroupSelectedCascades = selectedCascades->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); - createSpecifiedDerivedData_TrkCascade(col, thegroupSelectedParts, thegroupSelectedCascades, parts); + createSpecifiedDerivedDataTrkCascade(col, thegroupSelectedParts, thegroupSelectedCascades, parts); } - PROCESS_SWITCH(femtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNCascades, "Enable producing data with tracks and Cascades collisions for data", true); + PROCESS_SWITCH(FemtoDreamProducerTaskForSpecificAnalysis, processCollisionsWithNTracksAndNCascades, "Enable producing data with tracks and Cascades collisions for data", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), }; return workflow; } diff --git a/PWGCF/FemtoDream/Tasks/CMakeLists.txt b/PWGCF/FemtoDream/Tasks/CMakeLists.txt index ecc4f689ae0..3341346bb24 100644 --- a/PWGCF/FemtoDream/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoDream/Tasks/CMakeLists.txt @@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(femtodream-triplet-track-track-track PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtodream-triplet-track-track-track-pb-pb + SOURCES femtoDreamTripletTaskTrackTrackTrackPbPb.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtodream-pair-track-v0 SOURCES femtoDreamPairTaskTrackV0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -54,6 +59,11 @@ o2physics_add_dpl_workflow(femtodream-collision-masker PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtodream-pair-efficiency + SOURCES femtoDreamPairEfficiency.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtodream-hash SOURCES femtoDreamHashTask.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx index 1ca9d808073..fddbee16a88 100644 --- a/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx +++ b/PWGCF/FemtoDream/Tasks/femtoDreamCollisionMasker.cxx @@ -244,7 +244,7 @@ struct femoDreamCollisionMasker { NegChildPIDTPCBits.at(CollisionMasks::kPartTwo).push_back(option.defaultValue.get()); } } - } else if (device.name.find("femto-dream-triplet-task-track-track-track") != std::string::npos) { + } else if ((device.name.find("femto-dream-triplet-task-track-track-track") != std::string::npos) || (device.name.find("femto-dream-triplet-task-track-track-track-pb-pb") != std::string::npos)) { LOG(info) << "Matched workflow: " << device.name; TaskFinder = CollisionMasks::kTrackTrackTrack; for (auto const& option : device.options) { diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamPairEfficiency.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamPairEfficiency.cxx new file mode 100644 index 00000000000..613bc1989be --- /dev/null +++ b/PWGCF/FemtoDream/Tasks/femtoDreamPairEfficiency.cxx @@ -0,0 +1,623 @@ +// 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 femtoDreamPairEfficiency.cxx +/// \brief Task to produce dNdeta for pair triggered events +/// \author Anton Riedel, TU München, anton.riedel@cern.ch +/// heaviyly inspiered by phik0shortanalysis.cxx + +#include "PWGCF/FemtoDream/Core/femtoDreamMath.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.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 "TPDGCode.h" + +#include "fairlogger/Logger.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; +using namespace o2::aod::track; + +struct FemtoDreamPairEfficiency { + + using Collisions = soa::Join; + using RecoCollisions = soa::Join; + using GenCollisions = soa::Join; + + // Defining the type of the tracks for data and MC + using FullTracks = soa::Join; + using FullMCTracks = soa::Join; + // filter for tracks + 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; + + Filter trackFilter = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && + ncheckbit(aod::track::trackCutFlag, TrackSelectionITS) && + ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC), ncheckbit(aod::track::trackCutFlag, TrackSelectionTPC), true) && + ncheckbit(aod::track::trackCutFlag, TrackSelectionDCA) && + ncheckbit(aod::track::trackCutFlag, TrackSelectionFlags::kInAcceptanceTracks); + + using FilteredFullTracks = soa::Filtered; + using FilteredFullMCTracks = soa::Filtered; + + Service pdgDB; + + SliceCache cache; + Preslice perColMc = mcparticle::mcCollisionId; + + // Event Selections + struct : ConfigurableGroup { + std::string prefix = std::string("EventSelection"); + Configurable zvtxAbsMax{"zvtxAbsMax", 10.f, "|z-Vertex| max"}; + Configurable offlineCheck{"offlineCheck", true, "Check for Sel8"}; + Configurable etaAbsMax{"etaAbsMax", 0.8f, "Common eta cut for particles in dNdEta distribution"}; + Configurable kstarMax{"kstarMax", 999.f, "Cut on kstar"}; + } eventSelection; + + struct : ConfigurableGroup { + std::string prefix = std::string("EventBinning"); + ConfigurableAxis zvtxBinning{"zvtxBinning", {240, -12, 12}, "z-vertex Binning"}; + ConfigurableAxis centBinning{"centBinning", {120, 0, 120}, "Centrality Binning"}; + ConfigurableAxis multBinning{"multBinning", {300, 0, 300}, "Multiplicity Binning"}; + ConfigurableAxis dNdetaBinning{"dNdetaBinning", {200, -1, 1}, "dNdeta Binning"}; + ConfigurableAxis kstarBinning{"kstarBinning", {200, 0, 2}, "dNdeta Binning"}; + ConfigurableAxis pairBinning{"pairBinning", {50, 0, 50}, "pair Binning"}; + } eventBinning; + + // Track 1 selections + struct : ConfigurableGroup { + std::string prefix = std::string("SelectionTrack1"); + Configurable sign{"sign", 1, "Sign of charge"}; + Configurable ptMin{"ptMin", 0.0f, "pt min"}; + Configurable ptMax{"ptMax", 3.0f, "pt max"}; + Configurable etaAbsMax{"etaAbsMax", 0.8f, "|eta| max"}; + Configurable dcazAbsMax{"dcazAbsMax", 0.1f, "|dca_z| max"}; + Configurable useDcaxyPtDepCut{"useDcaxyPtDepCut", true, "|dca_z| max"}; + Configurable tpcClusterMin{"tpcClusterMin", 80.f, "TPC clusters min"}; + Configurable tpcCrossedOverClusterMin{"tpcCrossedOverClusterMin", 0.83f, "TPC clusters/TPC crossed rows min"}; + Configurable tpcCrossedMin{"tpcCrossedMin", 70.f, "TPC crossed rows min"}; + Configurable tpcSharedMax{"tpcSharedMax", 160.f, "TPC shared clusters max"}; + Configurable itsClusterMin{"itsClusterMin", 0.f, "ITS clusters min"}; + Configurable itsIbClusterMin{"itsIbClusterMin", 0.f, "ITS inner barrle min"}; + Configurable pdgCode{"pdgCode", 2212, "PDG code"}; + Configurable pidThreshold{"pidThreshold", 0.75f, "Momentum threshold for PID"}; + Configurable itsNsigmaMax{"itsNsigmaMax", 99.f, "its nsigma max"}; + Configurable tpcNsigmaMax{"tpcNsigmaMax", 3.f, "TPC nsigma max"}; + Configurable tpctofNsigmaMax{"tpctofNsigmaMax", 3.f, "TPCTOC nsigma max"}; + } trackCuts1; + + // Track 2 selections + struct : ConfigurableGroup { + std::string prefix = std::string("SelectionTrack2"); + Configurable sign{"sign", 1, "Sign of charge"}; + Configurable ptMin{"ptMin", 0.0f, "pt min"}; + Configurable ptMax{"ptMax", 3.0f, "pt max"}; + Configurable etaAbsMax{"etaAbsMax", 0.8f, "|eta| max"}; + Configurable dcazAbsMax{"dcazAbsMax", 0.1f, "|dca_z| max"}; + Configurable useDcaxyPtDepCut{"useDcaxyPtDepCut", true, "|dca_z| max"}; + Configurable tpcClusterMin{"tpcClusterMin", 80.f, "TPC clusters min"}; + Configurable tpcCrossedOverClusterMin{"tpcCrossedOverClusterMin", 0.83f, "TPC clusters/TPC crossed rows min"}; + Configurable tpcCrossedMin{"tpcCrossedMin", 70.f, "TPC crossed rows min"}; + Configurable tpcSharedMax{"tpcSharedMax", 160.f, "TPC shared clusters max"}; + Configurable itsClusterMin{"itsClusterMin", 0.f, "ITS clusters min"}; + Configurable itsIbClusterMin{"itsIbClusterMin", 0.f, "ITS inner barrle min"}; + Configurable pdgCode{"pdgCode", 2212, "PDG code"}; + Configurable pidThreshold{"pidThreshold", 0.75f, "Momentum threshold for PID"}; + Configurable itsNsigmaMax{"itsNsigmaMax", 99.f, "its nsigma max"}; + Configurable tpcNsigmaMax{"tpcNsigmaMax", 3.f, "TPC nsigma max"}; + Configurable tpctofNsigmaMax{"tpctofNsigmaMax", 3.f, "TPCTOC nsigma max"}; + } trackCuts2; + + HistogramRegistry dataEventHist{"dataEventHist", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry mcEventHist{"mcEventHist", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + HistogramRegistry dataTrackHist{"dataTrackHist", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + + void init(InitContext&) + { + dataEventHist.add("hDataEventSelection", "hDataEventSelection", kTH1F, {{6, -0.5f, 5.5f}}); + dataEventHist.get(HIST("hDataEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + dataEventHist.get(HIST("hDataEventSelection"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + dataEventHist.get(HIST("hDataEventSelection"))->GetXaxis()->SetBinLabel(3, "posZ cut"); + dataEventHist.get(HIST("hDataEventSelection"))->GetXaxis()->SetBinLabel(4, "INEL>0 cut"); + dataEventHist.get(HIST("hDataEventSelection"))->GetXaxis()->SetBinLabel(5, "With at least a pair"); + dataEventHist.get(HIST("hDataEventSelection"))->GetXaxis()->SetBinLabel(6, "With at least a lowkstar pair"); + + // Event information + dataEventHist.add("hDataVertexZ", "hVertexZ", kTH1F, {eventBinning.zvtxBinning}); + dataEventHist.add("hDataMultiplicity", "hMultiplicity", kTH1F, {eventBinning.multBinning}); + dataEventHist.add("hDataCentrality", "Centrality", kTH1F, {eventBinning.centBinning}); + + // Eta distribution for dN/deta values estimation in Data + dataEventHist.add("hDataCentralityVsEtaDistribtion", "Eta vs multiplicity in Data", kTH2F, {eventBinning.centBinning, eventBinning.dNdetaBinning}); + + dataTrackHist.add("Track1/pt", "Track 1 pt", kTH1F, {{600, 0, 6}}); + dataTrackHist.add("Track1/eta", "Track 1 eta", kTH1F, {{200, -1, 1}}); + dataTrackHist.add("Track1/phi", "Track 1 phi", kTH1F, {{720, 0, o2::constants::math::TwoPI}}); + dataTrackHist.add("Track1/tpcCluster", "Track 1 cluster", kTH1F, {{160, 0, 160}}); + dataTrackHist.add("Track1/tpcCrossed", "Track 1 crossed rows", kTH1F, {{160, 0, 160}}); + dataTrackHist.add("Track1/tpcShared", "Track 1 cluster shared", kTH1F, {{160, 0, 160}}); + dataTrackHist.add("Track1/itsCluster", "Track 1 its cluster", kTH1F, {{7, 0, 7}}); + dataTrackHist.add("Track1/itsIbCluster", "Track 1 its cluster inner barrel", kTH1F, {{3, 0, 3}}); + dataTrackHist.add("Track1/itsNsigma", "Track 1 nsigma its", kTH2F, {{600, 0, 6}, {1000, -5, 5}}); + dataTrackHist.add("Track1/tpcNsigma", "Track 1 nsigma tpc", kTH2F, {{600, 0, 6}, {1000, -5, 5}}); + dataTrackHist.add("Track1/tpctofNsigma", "Track 1 nsigma tpctof", kTH2F, {{600, 0, 6}, {500, 0, 5}}); + + dataTrackHist.add("Track2/pt", "Track 2 pt", kTH1F, {{600, 0, 6}}); + dataTrackHist.add("Track2/eta", "Track 2 eta", kTH1F, {{200, -1, 1}}); + dataTrackHist.add("Track2/phi", "Track 2 phi", kTH1F, {{720, 0, o2::constants::math::TwoPI}}); + dataTrackHist.add("Track2/tpcCluster", "Track 2 cluster", kTH1F, {{160, 0, 160}}); + dataTrackHist.add("Track2/tpcCrossed", "Track 2 crossed rows", kTH1F, {{160, 0, 160}}); + dataTrackHist.add("Track2/tpcShared", "Track 2 cluster shared", kTH1F, {{160, 0, 160}}); + dataTrackHist.add("Track2/itsCluster", "Track 2 its cluster", kTH1F, {{0, 0, 7}}); + dataTrackHist.add("Track2/itsIbCluster", "Track 2 its cluster inner barrel", kTH1F, {{3, 0, 3}}); + dataTrackHist.add("Track2/itsNsigma", "Track 2 nsigma its", kTH2F, {{600, 0, 6}, {1000, -5, 5}}); + dataTrackHist.add("Track2/tpcNsigma", "Track 2 nsigma tpc", kTH2F, {{600, 0, 6}, {1000, -5, 5}}); + dataTrackHist.add("Track2/tpctofNsigma", "Track 2 nsigma tpctof", kTH2F, {{600, 0, 6}, {500, 0, 5}}); + + mcEventHist.add("hRecoEventSelection", "hRecoEventSelection", kTH1F, {{7, -0.5f, 6.5f}}); + mcEventHist.get(HIST("hRecoEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + mcEventHist.get(HIST("hRecoEventSelection"))->GetXaxis()->SetBinLabel(2, "Sel8 cut"); + mcEventHist.get(HIST("hRecoEventSelection"))->GetXaxis()->SetBinLabel(3, "posZ cut"); + mcEventHist.get(HIST("hRecoEventSelection"))->GetXaxis()->SetBinLabel(4, "INEL>0 cut"); + mcEventHist.get(HIST("hRecoEventSelection"))->GetXaxis()->SetBinLabel(5, "With at least a gen coll"); + mcEventHist.get(HIST("hRecoEventSelection"))->GetXaxis()->SetBinLabel(6, "With at least a pair"); + mcEventHist.get(HIST("hRecoEventSelection"))->GetXaxis()->SetBinLabel(7, "With at least a lowkstar pair"); + + mcEventHist.add("hGenEventSelection", "hGenEventSelection", kTH1F, {{6, -0.5f, 5.5f}}); + mcEventHist.get(HIST("hGenEventSelection"))->GetXaxis()->SetBinLabel(1, "All collisions"); + mcEventHist.get(HIST("hGenEventSelection"))->GetXaxis()->SetBinLabel(2, "posZ cut"); + mcEventHist.get(HIST("hGenEventSelection"))->GetXaxis()->SetBinLabel(3, "INEL>0 cut"); + mcEventHist.get(HIST("hGenEventSelection"))->GetXaxis()->SetBinLabel(4, "With at least a pair"); + mcEventHist.get(HIST("hGenEventSelection"))->GetXaxis()->SetBinLabel(5, "With at least a lowkstar pair"); + mcEventHist.get(HIST("hGenEventSelection"))->GetXaxis()->SetBinLabel(6, "With at least a reco coll"); + + // MC Event information for Rec and Gen + mcEventHist.add("hRecoMcVertexZ", "McVertexZ of reconstructed collision", kTH1F, {eventBinning.zvtxBinning}); + mcEventHist.add("hRecoMcMultiplicity", "McMultiplicity of reconstructed collision", kTH1F, {eventBinning.multBinning}); + mcEventHist.add("hRecoMcCentrality", "McCentrality of reconstructed collision", kTH1F, {eventBinning.centBinning}); + mcEventHist.add("hRecoMcKstar", "Mck* in reconstructed collision", kTH1F, {eventBinning.kstarBinning}); + mcEventHist.add("hRecoMcNumberOfPair", "McNumber of pairs in reconstructed collision", kTH1F, {eventBinning.pairBinning}); + + mcEventHist.add("hRecoMcCentralityVsEtaDistribution", "McCentrality vs Eta in Reco", kTH2F, {eventBinning.centBinning, eventBinning.dNdetaBinning}); + mcEventHist.add("hRecoMcCentralityVsMcEtaDistribution", "McCentrality vs McEta in Reco (Check)", kTH2F, {eventBinning.centBinning, eventBinning.dNdetaBinning}); + + mcEventHist.add("hGenMcVertexZ", "McVertex of generated collision", kTH1F, {eventBinning.zvtxBinning}); + mcEventHist.add("hGenMcMultiplicity", "McMultiplicity fo generated collision", kTH1F, {eventBinning.multBinning}); + mcEventHist.add("hGenMcCentrality", "McCentrality of generated collision", kTH1F, {eventBinning.centBinning}); + mcEventHist.add("hGenMcKstar", "Mckk* of generated collision", kTH1F, {eventBinning.kstarBinning}); + mcEventHist.add("hGenMcNumberOfPair", "McNumber of pairs in generated collision", kTH1F, {eventBinning.pairBinning}); + + mcEventHist.add("hGenMcCentralityWithAllAssoc", "McCentrality in all associated collision", kTH1F, {eventBinning.centBinning}); + mcEventHist.add("hGenMcCentralityWithAssoc", "McCentrality in associated collision", kTH1F, {eventBinning.centBinning}); + mcEventHist.add("hGenMcCentralityVsMcEtaDistribution", "McCentrality vs McdNdEta in generated collision", kTH2F, {eventBinning.centBinning, eventBinning.dNdetaBinning}); + mcEventHist.add("hGenMcCentralityVsMcEtaDistributionWithAllAssoc", "McCentrality vs McdNdEta in all associated collisions", kTH2F, {eventBinning.centBinning, eventBinning.dNdetaBinning}); + mcEventHist.add("hGenMcCentralityVsMcEtaDistributionWithAssoc", "McCentrality vs McdNdEta in associated collisions", kTH2F, {eventBinning.centBinning, eventBinning.dNdetaBinning}); + } + + int pairsFound = 0; + std::vector vecKstar{}; + + template + bool checkRecoTrackSelections(const T1& track, const T2& sel) + { + if (track.sign() != sel.sign.value) { + return false; + } + if (track.pt() < sel.ptMin.value || track.pt() > sel.ptMax.value) { + return false; + } + if (std::fabs(track.eta()) > sel.etaAbsMax.value) { + return false; + } + if (sel.useDcaxyPtDepCut.value && std::fabs(track.dcaXY()) > (0.0105 + (0.035 / std::powf(track.pt(), 1.1f)))) { + return false; + } + if (std::fabs(track.dcaZ()) > sel.dcazAbsMax.value) { + return false; + } + if (track.tpcNClsFound() < sel.tpcClusterMin.value) { + return false; + } + if (track.tpcNClsCrossedRows() < sel.tpcCrossedMin.value) { + return false; + } + if (track.tpcNClsShared() > sel.tpcSharedMax.value) { + return false; + } + if (track.itsNCls() < sel.itsClusterMin.value) { + return false; + } + if (track.itsNClsInnerBarrel() < sel.itsIbClusterMin.value) { + return false; + } + return true; + } + + template + std::array getNSigmaValues(const T& track, int pdgCode) + { + std::array nsigma; + switch (std::abs(pdgCode)) { + case kPiPlus: + nsigma[0] = track.itsNSigmaPi(); + nsigma[1] = track.tpcNSigmaPi(); + nsigma[2] = track.tofNSigmaPi(); + break; + case kKPlus: + nsigma[0] = track.itsNSigmaKa(); + nsigma[1] = track.tpcNSigmaKa(); + nsigma[2] = track.tofNSigmaKa(); + break; + case kProton: + nsigma[0] = track.itsNSigmaPr(); + nsigma[1] = track.tpcNSigmaPr(); + nsigma[2] = track.tofNSigmaPr(); + break; + case constants::physics::kDeuteron: + nsigma[0] = track.itsNSigmaDe(); + nsigma[1] = track.tpcNSigmaDe(); + nsigma[2] = track.tofNSigmaDe(); + break; + default: + LOG(fatal) << "PDG code " << pdgCode << " is not supported"; + } + return nsigma; + } + + template + bool checkRecoTrackPidSelections(const T1& track, const T2& sel) + { + auto nsigma = getNSigmaValues(track, sel.pdgCode.value); + if (track.p() < sel.pidThreshold.value) { + if (std::fabs(nsigma[1]) > sel.tpcNsigmaMax.value || std::fabs(nsigma[0]) > sel.itsNsigmaMax.value) { + return false; + } + } else { + if (std::hypot(nsigma[1], nsigma[2]) > sel.tpctofNsigmaMax.value) { + return false; + } + } + return true; + } + + template + bool checkEventSelections(const T& col, bool qa) + { + if constexpr (!isMc) { + if (qa) { + dataEventHist.fill(HIST("hDataEventSelection"), 0); // all collisins + } + if (!col.sel8()) { + return false; + } + if (qa) { + dataEventHist.fill(HIST("hDataEventSelection"), 1); // sel8 collisions + } + if (std::fabs(col.posZ()) > eventSelection.zvtxAbsMax.value) { + return false; + } + if (qa) { + dataEventHist.fill(HIST("hDataEventSelection"), 2); // vertex-Z selected + } + if (!col.isInelGt0()) { + return false; + } + if (qa) { + dataEventHist.fill(HIST("hDataEventSelection"), 3); // INEL>0 collisions + } + } else { + if (qa) { + mcEventHist.fill(HIST("hRecoEventSelection"), 0); // all collisions + } + if (!col.sel8()) { + return false; + } + if (qa) { + mcEventHist.fill(HIST("hRecoEventSelection"), 1); // sel8 collisions + } + if (std::fabs(col.posZ()) > eventSelection.zvtxAbsMax.value) { + return false; + } + if (qa) { + mcEventHist.fill(HIST("hRecoEventSelection"), 2); // vertex-Z selected + } + if (!col.isInelGt0()) { + return false; + } + if (qa) { + mcEventHist.fill(HIST("hRecoEventSelection"), 3); // INEL>0 collisions + } + } + return true; + } + + template + int countRecoPairs(const T& tracks) + { + int pairs = 0; + for (auto track1 = tracks.begin(); track1 != tracks.end(); track1++) { + if (!checkRecoTrackSelections(track1, trackCuts1) || !checkRecoTrackPidSelections(track1, trackCuts1)) { + continue; + } + for (auto track2 = track1 + 1; track2 != tracks.end(); track2++) { + if (!checkRecoTrackSelections(track2, trackCuts2) || !checkRecoTrackPidSelections(track2, trackCuts2)) { + continue; + } + + auto nsigma1 = getNSigmaValues(track1, trackCuts1.pdgCode.value); + dataTrackHist.fill(HIST("Track1/pt"), track1.pt()); + dataTrackHist.fill(HIST("Track1/eta"), track1.eta()); + dataTrackHist.fill(HIST("Track1/phi"), track1.phi()); + dataTrackHist.fill(HIST("Track1/tpcCluster"), track1.tpcNClsFound()); + dataTrackHist.fill(HIST("Track1/tpcCrossed"), track1.tpcNClsCrossedRows()); + dataTrackHist.fill(HIST("Track1/tpcShared"), track1.tpcNClsShared()); + dataTrackHist.fill(HIST("Track1/itsCluster"), track1.itsNCls()); + dataTrackHist.fill(HIST("Track1/itsIbCluster"), track1.itsNClsInnerBarrel()); + dataTrackHist.fill(HIST("Track1/itsNsigma"), track1.p(), nsigma1[0]); + dataTrackHist.fill(HIST("Track1/tpcNsigma"), track1.p(), nsigma1[1]); + dataTrackHist.fill(HIST("Track1/tpctofNsigma"), track1.p(), std::hypot(nsigma1[1], nsigma1[2])); + + auto nsigma2 = getNSigmaValues(track2, trackCuts2.pdgCode.value); + dataTrackHist.fill(HIST("Track2/pt"), track2.pt()); + dataTrackHist.fill(HIST("Track2/eta"), track2.eta()); + dataTrackHist.fill(HIST("Track2/phi"), track2.phi()); + dataTrackHist.fill(HIST("Track2/tpcCluster"), track2.tpcNClsFound()); + dataTrackHist.fill(HIST("Track2/tpcCrossed"), track2.tpcNClsCrossedRows()); + dataTrackHist.fill(HIST("Track2/tpcShared"), track2.tpcNClsShared()); + dataTrackHist.fill(HIST("Track2/itsCluster"), track2.itsNCls()); + dataTrackHist.fill(HIST("Track2/itsIbCluster"), track2.itsNClsInnerBarrel()); + dataTrackHist.fill(HIST("Track2/itsNsigma"), track2.p(), nsigma2[0]); + dataTrackHist.fill(HIST("Track2/tpcNsigma"), track2.p(), nsigma2[1]); + dataTrackHist.fill(HIST("Track2/tpctofNsigma"), track1.p(), std::hypot(nsigma2[1], nsigma2[2])); + + pairs++; + + vecKstar.push_back(femtoDream::FemtoDreamMath::getkstar(track1, femtoDream::getMass(trackCuts1.pdgCode.value), track2, femtoDream::getMass(trackCuts2.pdgCode.value))); + } + } + return pairs; + } + + template + int countGenPairs(const T& tracks) + { + int pairs = 0; + for (auto track1 = tracks.begin(); track1 != tracks.end(); track1++) { + if (!track1.isPhysicalPrimary() || + track1.pdgCode() != trackCuts1.pdgCode.value || + track1.pt() < trackCuts1.ptMin.value || + track1.pt() > trackCuts1.ptMax.value || + std::fabs(track1.eta()) > trackCuts1.etaAbsMax.value) { + continue; + } + for (auto track2 = track1 + 1; track2 != tracks.end(); track2++) { + if (!track2.isPhysicalPrimary() || + track2.pdgCode() != trackCuts2.pdgCode.value || + track2.pt() < trackCuts2.ptMin.value || + track2.pt() > trackCuts2.ptMax.value || + std::fabs(track2.eta()) > trackCuts2.etaAbsMax.value) { + continue; + } + vecKstar.push_back(femtoDream::FemtoDreamMath::getkstar(track1, femtoDream::getMass(trackCuts1.pdgCode.value), track2, femtoDream::getMass(trackCuts2.pdgCode.value))); + pairs++; + } + } + return pairs; + } + + void processdNdetaData(Collisions::iterator const& collision, FilteredFullTracks const& tracks) + { + if (!checkEventSelections(collision, true)) + return; + + auto tracksWithItsPid = soa::Attach(tracks); + + vecKstar.clear(); + pairsFound = countRecoPairs(tracksWithItsPid); + + if (pairsFound == 0) { + return; + } + dataEventHist.fill(HIST("hDataEventSelection"), 4); // found a pair + + if (*std::min_element(vecKstar.begin(), vecKstar.end()) > eventSelection.kstarMax) { + return; + } + + dataEventHist.fill(HIST("hDataEventSelection"), 5); // found a lowkstar pair + + float centrality = collision.centFT0M(); + + dataEventHist.fill(HIST("hDataVertexZ"), collision.posZ()); + dataEventHist.fill(HIST("hDataMultiplicity"), collision.multNTracksPV()); + dataEventHist.fill(HIST("hDataCentrality"), centrality); + + for (const auto& track : tracks) + dataEventHist.fill(HIST("hDataCentralityVsEtaDistribtion"), centrality, track.eta()); + } + + PROCESS_SWITCH(FemtoDreamPairEfficiency, processdNdetaData, "Process function for dN/deta values in MCReco", true); + + void processdNdetaMCReco(RecoCollisions::iterator const& collision, FilteredFullMCTracks const& McTracks, GenCollisions const&, McParticles const& mcParticles) + { + if (!checkEventSelections(collision, true)) { + return; + } + if (!collision.has_mcCollision()) { + return; + } + mcEventHist.fill(HIST("hRecoEventSelection"), 4); + + const auto& mcCollision = collision.mcCollision_as(); + auto mcParticlesThisColl = mcParticles.sliceByCached(mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + + vecKstar.clear(); + pairsFound = countGenPairs(mcParticlesThisColl); + + if (pairsFound == 0) { + return; + } + mcEventHist.fill(HIST("hRecoEventSelection"), 5); + + if (*std::min_element(vecKstar.begin(), vecKstar.end()) > eventSelection.kstarMax) { + return; + } + mcEventHist.fill(HIST("hRecoEventSelection"), 6); + + float genCentrality = mcCollision.centFT0M(); + + mcEventHist.fill(HIST("hRecoMcVertexZ"), mcCollision.posZ()); + mcEventHist.fill(HIST("hRecoMcMultiplicity"), mcCollision.multMCNParticlesEta08()); + mcEventHist.fill(HIST("hRecoMcCentrality"), mcCollision.centFT0M()); + mcEventHist.fill(HIST("hRecoMcNumberOfPair"), vecKstar.size()); + for (const auto& kstar : vecKstar) { + mcEventHist.fill(HIST("hRecoMcKstar"), kstar); + } + + for (const auto& track : McTracks) { + if (!track.has_mcParticle()) + continue; + auto mcTrack = track.mcParticle_as(); + if (!mcTrack.isPhysicalPrimary() || std::fabs(mcTrack.eta()) > eventSelection.etaAbsMax.value) + continue; + + mcEventHist.fill(HIST("hRecoMcCentralityVsEtaDistribution"), genCentrality, mcTrack.eta()); + } + + for (const auto& mcParticle : mcParticlesThisColl) { + if (!mcParticle.isPhysicalPrimary() || std::fabs(mcParticle.eta()) > eventSelection.etaAbsMax.value) { + continue; + } + auto pdgTrack = pdgDB->GetParticle(mcParticle.pdgCode()); + if (pdgTrack == nullptr) { + continue; + } + if (pdgTrack->Charge() == 0) { + continue; + } + mcEventHist.fill(HIST("hRecoMcCentralityVsMcEtaDistribution"), genCentrality, mcParticle.eta()); + } + } + PROCESS_SWITCH(FemtoDreamPairEfficiency, processdNdetaMCReco, "Process function for dN/deta values in MCReco", true); + + void processdNdetaMCGen(GenCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, McParticles const& mcParticles) + { + mcEventHist.fill(HIST("hGenEventSelection"), 0); + if (std::fabs(mcCollision.posZ()) > eventSelection.zvtxAbsMax.value) { + return; + } + mcEventHist.fill(HIST("hGenEventSelection"), 1); + if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + return; + } + mcEventHist.fill(HIST("hGenEventSelection"), 2); + vecKstar.clear(); + pairsFound = countGenPairs(mcParticles); + if (pairsFound == 0) { + return; + } + mcEventHist.fill(HIST("hGenEventSelection"), 3); + if (*std::min_element(vecKstar.begin(), vecKstar.end()) > eventSelection.kstarMax) { + return; + } + mcEventHist.fill(HIST("hGenEventSelection"), 4); + + mcEventHist.fill(HIST("hGenMcVertexZ"), mcCollision.posZ()); + mcEventHist.fill(HIST("hGenMcMultiplicity"), mcCollision.multMCNParticlesEta08()); + mcEventHist.fill(HIST("hGenMcCentrality"), mcCollision.centFT0M()); + mcEventHist.fill(HIST("hGenMcNumberOfPair"), vecKstar.size()); + + for (const auto& kstar : vecKstar) { + mcEventHist.fill(HIST("hGenMcKstar"), kstar); + } + + float genCentrality = mcCollision.centFT0M(); + uint64_t numberAssocCollisions = 0; + + for (const auto& collision : collisions) { + if (checkEventSelections(collision, false)) { + mcEventHist.fill(HIST("hGenMcCentralityWithAllAssoc"), genCentrality); + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.eta()) > eventSelection.etaAbsMax.value) + continue; + auto pdgTrack = pdgDB->GetParticle(mcParticle.pdgCode()); + if (pdgTrack == nullptr) + continue; + if (pdgTrack->Charge() == 0) + continue; + mcEventHist.fill(HIST("hGenMcCentralityVsMcEtaDistributionWithAllAssoc"), genCentrality, mcParticle.eta()); + } + numberAssocCollisions++; + } + } + + if (numberAssocCollisions > 0) { + mcEventHist.fill(HIST("hGenMcCentralityWithAssoc"), genCentrality); + mcEventHist.fill(HIST("hGenEventSelection"), 5); + } + + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.eta()) > eventSelection.etaAbsMax.value) + continue; + + auto pdgTrack = pdgDB->GetParticle(mcParticle.pdgCode()); + if (pdgTrack == nullptr) { + continue; + } + if (pdgTrack->Charge() == 0) { + continue; + } + + mcEventHist.fill(HIST("hGenMcCentralityVsMcEtaDistribution"), genCentrality, mcParticle.eta()); + if (numberAssocCollisions > 0) { + mcEventHist.fill(HIST("hGenMcCentralityVsMcEtaDistributionWithAssoc"), genCentrality, mcParticle.eta()); + } + } + } + PROCESS_SWITCH(FemtoDreamPairEfficiency, processdNdetaMCGen, "Process function for dN/deta values in MCReco", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx new file mode 100644 index 00000000000..698aa5e6c63 --- /dev/null +++ b/PWGCF/FemtoDream/Tasks/femtoDreamTripletTaskTrackTrackTrackPbPb.cxx @@ -0,0 +1,530 @@ +// 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 femtoDreamTripletTaskTrackTrackTrackPbPb.cxx +/// \brief Tasks that reads the track tables and creates track triplets; only three identical particles can be used +/// \author Laura Serksnyte, TU München, laura.serksnyte@tum.de + +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamContainerThreeBody.h" +#include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" + +#include "Framework/ASoAHelpers.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 "TDatabasePDG.h" + +#include +#include + +using namespace o2; +using namespace o2::analysis::femtoDream; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct femtoDreamTripletTaskTrackTrackTrackPbPb { + SliceCache cache; + Preslice perCol = aod::femtodreamparticle::fdCollisionId; + + Configurable ConfCentralityMin{"ConfCentralityMin", 0, "Minimum Centrality Percentile"}; + Configurable ConfCentralityMax{"ConfCentralityMax", 10, "Maximum Centrality Percentile"}; + + Filter EventCentrality = aod::femtodreamcollision::multV0M >= ConfCentralityMin && aod::femtodreamcollision::multV0M <= ConfCentralityMax; + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + + using MaskedCollisions = soa::Filtered>; + using MaskedCollision = MaskedCollisions::iterator; + aod::femtodreamcollision::BitMaskType MaskBit = -1; + float mMassOne = -999, mMassTwo = -999, mMassThree = -999; + + /// Particle selection part + + // which CPR to use, old is with a possible bug and new is fixed + Configurable ConfUseOLD_possiblyWrong_CPR{"ConfUseOLD_possiblyWrong_CPR", true, "Use for old CPR, which possibly has a bug. This is implemented only for debugging reasons to compare old and new code on hyperloop datasets."}; + + /// Table for both particles + Configurable ConfTracksInMixedEvent{"ConfTracksInMixedEvent", 1, "Number of tracks of interest, contained in the mixed event sample: 1 - only events with at least one track of interest are used in mixing; ...; 3 - only events with at least three track of interest are used in mixing. Max value is 3"}; + Configurable ConfMaxpT{"ConfMaxpT", 4.05f, "Maximum transverse momentum of the particles"}; + Configurable ConfMinpT{"ConfMinpT", 0.3f, "Minimum transverse momentum of the particles"}; + Configurable ConfMaxDCAxy{"ConfMaxDCAxy", -0.1f, "Maximum DCAxy of the particles"}; + Configurable ConfMinDCAxy{"ConfMinDCAxy", 0.1f, "Minimum DCAxy of the particles"}; + Configurable ConfPIDthrMom{"ConfPIDthrMom", 1.f, "Momentum threshold from which TPC and TOF are required for PID"}; + Configurable ConfAtWhichRadiiToCut{"ConfAtWhichRadiiToCut", 1, "At which radii perform deta dphi selection: 0 - at PV, 1 - averaged phi, 2 - at given radii"}; + Configurable ConfAtWhichTPCRadii{"ConfAtWhichTPCRadii", 85., "If ConfAtWhichRadiiToCut = 2; this allows to select at which TPC radii to cut"}; + Configurable ConfTPCPIDBit{"ConfTPCPIDBit", 16, "PID TPC bit from cutCulator "}; + Configurable ConfTPCTOFPIDBit{"ConfTPCTOFPIDBit", 8, "PID TPCTOF bit from cutCulator"}; + 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 ConfDCACutPtDep{"ConfDCACutPtDep", false, "Use pt dependent dca cut for tracks"}; + + // Which particles to analyse; currently support only for same species and cuts triplets + Configurable ConfPDGCodePart{"ConfPDGCodePart", 2212, "Particle PDG code"}; + Configurable ConfCutPart{"ConfCutPart", 5542474, "Track - Selection bit from cutCulator"}; + + /// Partition for selected particles + Partition SelectedParts = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= ConfPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCTOFPIDBit)) && + (ncheckbit(aod::femtodreamparticle::cut, ConfCutPart)) && + (aod::femtodreamparticle::pt < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT) && + ifnode(ConfDCACutPtDep, (nabs(aod::femtodreamparticle::tempFitVar) < 0.004f + (0.013f / aod::femtodreamparticle::pt)), + ((aod::femtodreamparticle::tempFitVar >= ConfMinDCAxy) && + (aod::femtodreamparticle::tempFitVar <= ConfMaxDCAxy))); + ; + + Partition> SelectedPartsMC = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= ConfPIDthrMom, ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCPIDBit), ncheckbit(aod::femtodreamparticle::pidcut, ConfTPCTOFPIDBit)) && + (ncheckbit(aod::femtodreamparticle::cut, ConfCutPart)) && + (aod::femtodreamparticle::pt < ConfMaxpT) && + (aod::femtodreamparticle::pt > ConfMinpT) && + ifnode(ConfDCACutPtDep, (nabs(aod::femtodreamparticle::tempFitVar) < 0.004f + (0.013f / aod::femtodreamparticle::pt)), + ((aod::femtodreamparticle::tempFitVar >= ConfMinDCAxy) && + (aod::femtodreamparticle::tempFitVar <= ConfMaxDCAxy))); + ; + + /// Histogramming of Selected Particles + FemtoDreamParticleHisto trackHistoSelectedParts; + FemtoDreamParticleHisto trackHistoALLSelectedParts; + + /// Histogramming for Event + FemtoDreamEventHisto eventHisto; + + /// particle part + ConfigurableAxis ConfTempFitVarBins{"ConfTempFitVarBins", {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 ConfBinmultTempFit{"ConfBinmultTempFit", {1, 0, 1}, "multiplicity Binning for the TempFitVar plot"}; + + /// Correlation part + ConfigurableAxis ConfMultBins{"ConfMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis ConfVtxBins{"ConfVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + + ColumnBinningPolicy colBinning{{ConfVtxBins, ConfMultBins}, true}; + + ConfigurableAxis ConfQ3Bins{"ConfQ3Bins", {2000, 0., 8.}, "binning Q3"}; + ConfigurableAxis ConfQ3BinsFor4D{"ConfQ3BinsFor4D", {500, 0., 2.}, "binning Q3 for 4D hist"}; + Configurable ConfNEventsMix{"ConfNEventsMix", 5, "Number of events for mixing"}; + Configurable ConfIsCPR{"ConfIsCPR", true, "Close Pair Rejection"}; + Configurable ConfFillCPRQA{"ConfFillCPRQA", false, "Fill Close Pair Rejection plots as a function of eta and phi"}; + Configurable ConfCPRPlotPerRadii{"ConfCPRPlotPerRadii", false, "Plot CPR per radii"}; + Configurable ConfCPRdeltaPhiMax{"ConfCPRdeltaPhiMax", 0.01, "Max. Delta Phi for Close Pair Rejection"}; + Configurable ConfCPRdeltaEtaMax{"ConfCPRdeltaEtaMax", 0.01, "Max. Delta Eta for Close Pair Rejection"}; + Configurable ConfMaxQ3IncludedInCPRPlots{"ConfMaxQ3IncludedInCPRPlots", 8., "Maximum Q3, for which the pair CPR is included in plots"}; + ConfigurableAxis ConfDummy{"ConfDummy", {1, 0, 1}, "Dummy axis"}; + + FemtoDreamContainerThreeBody sameEventCont; + FemtoDreamContainerThreeBody mixedEventCont; + FemtoDreamPairCleaner pairCleaner; + FemtoDreamDetaDphiStar pairCloseRejectionSE; + FemtoDreamDetaDphiStar pairCloseRejectionME; + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry ThreeBodyQARegistry{"ThreeBodyQARegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext& context) + { + + eventHisto.init(&qaRegistry, false); + + colBinning = {{ConfVtxBins, ConfMultBins}, true}; + + trackHistoSelectedParts.init(&qaRegistry, ConfBinmultTempFit, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); + trackHistoALLSelectedParts.init(&qaRegistry, ConfBinmultTempFit, ConfDummy, ConfTempFitVarpTBins, ConfDummy, ConfDummy, ConfTempFitVarBins, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfDummy, ConfIsMC, ConfPDGCodePart); + + ThreeBodyQARegistry.add("TripletTaskQA/hSECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + ThreeBodyQARegistry.add("TripletTaskQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + ThreeBodyQARegistry.add("TripletTaskQA/particle_pT_in_Triplet_SE", "; p_{T1} ; p_{T2} ; p_{T3} ; Q_{3}", kTHnSparseF, {ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfQ3BinsFor4D}); + ThreeBodyQARegistry.add("TripletTaskQA/particle_pT_in_Triplet_ME", "; p_{T1} ; p_{T2} ; p_{T3} ; Q_{3}", kTHnSparseF, {ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfTempFitVarpTBins, ConfQ3BinsFor4D}); + std::vector tmpVecMult = ConfMultBins; + framework::AxisSpec multAxis = {tmpVecMult, "Multiplicity"}; + ThreeBodyQARegistry.add("TripletTaskQA/hSEMultVSGoodTracks", ";Mult;GoodT", kTH2F, {multAxis, {100, 0, 100}}); + ThreeBodyQARegistry.add("TripletTaskQA/hTripletsPerEventBelow14", ";Triplets;Entries", kTH1F, {{10, 0, 10}}); + ThreeBodyQARegistry.add("TripletTaskQA/NumberOfTacksPassingSelection", ";Triplets;Entries", kTH1F, {{30, 0, 30}}); + if (ConfIsMC) { + ThreeBodyQARegistry.add("TrackMC_QA/hMazzachi", ";gen;(reco-gen)/gen", kTH2F, {{100, ConfMinpT, ConfMaxpT}, {300, -1, 1}}); + } + ThreeBodyQARegistry.add("TripletTaskQA/hCentrality", ";Centrality; Q3", kTH2F, {{100, 0, 100}, ConfQ3Bins}); + ThreeBodyQARegistry.add("TripletTaskQA/hCentralityME", ";Centrality;Entries", kTH1F, {{100, 0.0, 100.0}}); + + sameEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); + mixedEventCont.init(&resultRegistry, ConfQ3Bins, ConfMultBins, ConfIsMC); + sameEventCont.setPDGCodes(ConfPDGCodePart, ConfPDGCodePart, ConfPDGCodePart); + mixedEventCont.setPDGCodes(ConfPDGCodePart, ConfPDGCodePart, ConfPDGCodePart); + pairCleaner.init(&qaRegistry); // SERKSNYTE : later check if init should be updated to have 3 separate histos + if (ConfIsCPR.value) { + pairCloseRejectionSE.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 1, ConfUseOLD_possiblyWrong_CPR, ConfMaxQ3IncludedInCPRPlots, false, ConfAtWhichRadiiToCut, ConfAtWhichTPCRadii, ConfFillCPRQA); + pairCloseRejectionME.init(&resultRegistry, &qaRegistry, ConfCPRdeltaPhiMax.value, ConfCPRdeltaEtaMax.value, ConfCPRPlotPerRadii.value, 2, ConfUseOLD_possiblyWrong_CPR, ConfMaxQ3IncludedInCPRPlots, false, ConfAtWhichRadiiToCut, ConfAtWhichTPCRadii, ConfFillCPRQA); + } + + // get masses + mMassOne = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + mMassTwo = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + mMassThree = TDatabasePDG::Instance()->GetParticle(ConfPDGCodePart)->Mass(); + + // get bit for the collision mask + std::bitset<8 * sizeof(aod::femtodreamcollision::BitMaskType)> mask; + int index = 0; + auto& workflows = context.services().get(); + for (DeviceSpec const& device : workflows.devices) { + if (device.name.find("femto-dream-triplet-task-track-track-track-pb-pb") != std::string::npos) { + if (containsNameValuePair(device.options, "ConfCutPart", ConfCutPart.value) && + containsNameValuePair(device.options, "ConfTPCPIDBit", ConfTPCPIDBit.value) && + containsNameValuePair(device.options, "ConfTPCTOFPIDBit", ConfTPCTOFPIDBit.value) && + containsNameValuePair(device.options, "ConfPIDthrMom", ConfPIDthrMom.value) && + containsNameValuePair(device.options, "ConfMaxpT", ConfMaxpT.value) && + containsNameValuePair(device.options, "ConfMinpT", ConfMinpT.value) && + containsNameValuePair(device.options, "ConfMaxDCAxy", ConfMaxDCAxy.value) && + containsNameValuePair(device.options, "ConfMinDCAxy", ConfMinDCAxy.value)) { + mask.set(index); + MaskBit = static_cast(mask.to_ulong()); + LOG(info) << "Device name matched: " << device.name; + LOG(info) << "Bitmask for collisions: " << mask.to_string(); + break; + } else { + index++; + } + } + } + + if ((doprocessSameEvent && doprocessSameEventMasked) || + (doprocessMixedEvent && doprocessMixedEventMasked) || + (doprocessSameEventMC && doprocessSameEventMCMasked) || + (doprocessMixedEventMC && doprocessMixedEventMCMasked)) { + LOG(fatal) << "Normal and masked processing cannot be activated simultaneously!"; + } + } + + template + void fillCollision(CollisionType col) + { + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hSECollisionBins"), colBinning.getBin({col.posZ(), col.multNtr()})); + eventHisto.fillQA(col); + } + + /// This function processes the same event and takes care of all the histogramming + /// @tparam PartitionType + /// @tparam PartType + /// @tparam isMC: enables Monte Carlo truth specific histograms + /// @param groupSelectedParts partition for the first particle passed by the process function + /// @param parts femtoDreamParticles table (in case of Monte Carlo joined with FemtoDreamMCLabels) + /// @param magFieldTesla magnetic field of the collision + /// @param multCol multiplicity of the collision + template + void doSameEvent(PartitionType groupSelectedParts, PartType parts, float magFieldTesla, int multCol, float centCol) + { + /// Histogramming same event + int numberOfTracksPassingSelection = 0; + for (auto& part : groupSelectedParts) { + numberOfTracksPassingSelection = numberOfTracksPassingSelection + 1; + trackHistoSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, multCol, centCol); + } + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/NumberOfTacksPassingSelection"), numberOfTracksPassingSelection); + + /// Now build the combinations + int numberOfTriplets = 0; + for (auto& [p1, p2, p3] : combinations(CombinationsStrictlyUpperIndexPolicy(groupSelectedParts, groupSelectedParts, groupSelectedParts))) { + auto Q3 = FemtoDreamMath::getQ3(p1, mMassOne, p2, mMassTwo, p3, mMassThree); + + if (ConfIsCPR.value) { + if (pairCloseRejectionSE.isClosePair(p1, p2, parts, magFieldTesla, Q3)) { + continue; + } + if (pairCloseRejectionSE.isClosePair(p2, p3, parts, magFieldTesla, Q3)) { + continue; + } + if (pairCloseRejectionSE.isClosePair(p1, p3, parts, magFieldTesla, Q3)) { + continue; + } + } + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + if (!pairCleaner.isCleanPair(p2, p3, parts)) { + continue; + } + if (!pairCleaner.isCleanPair(p1, p3, parts)) { + continue; + } + + // fill pT of all three particles as a function of Q3 for lambda calculations + if (Q3 < 1.4) { + numberOfTriplets = numberOfTriplets + 1; + } + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_SE"), p1.pt(), p2.pt(), p3.pt(), Q3); + sameEventCont.setTriplet(p1, p2, p3, multCol, Q3); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentrality"), centCol, Q3); + } + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hTripletsPerEventBelow14"), numberOfTriplets); + } + + /// process function to call doSameEvent with Data + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processSameEvent(FilteredFDCollision& col, + o2::aod::FDParticles& parts) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEvent, "Enable processing same event", true); + + /// process function to call doSameEvent with Data which has a mask for containing particles or not + /// \param col subscribe to the collision table (Data) + /// \param parts subscribe to the femtoDreamParticleTable + void processSameEventMasked(MaskedCollision& col, o2::aod::FDParticles& parts) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + } + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEventMasked, "Enable processing same event with masks", false); + + /// process function for to call doSameEvent with Monte Carlo + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// \param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processSameEventMC(o2::aod::FDCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + ThreeBodyQARegistry.fill(HIST("TrackMC_QA/hMazzachi"), part.fdMCParticle().pt(), (part.pt() - part.fdMCParticle().pt()) / part.fdMCParticle().pt()); + } + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEventMC, "Enable processing same event for Monte Carlo", false); + + /// process function for to call doSameEvent with Monte Carlo which has a mask for containing particles or not + /// \param col subscribe to the collision table (Monte Carlo Reconstructed reconstructed) + /// \param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// \param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processSameEventMCMasked(MaskedCollision& col, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + fillCollision(col); + auto thegroupSelectedParts = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + for (auto& part : thegroupSelectedParts) { + trackHistoALLSelectedParts.fillQA(part, aod::femtodreamparticle::kPt, col.multNtr(), col.multV0M()); + ThreeBodyQARegistry.fill(HIST("TrackMC_QA/hMazzachi"), part.fdMCParticle().pt(), (part.pt() - part.fdMCParticle().pt()) / part.fdMCParticle().pt()); + } + if (thegroupSelectedParts.size() < 3) { + return; + } + doSameEvent(thegroupSelectedParts, parts, col.magField(), col.multNtr(), col.multV0M()); + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processSameEventMCMasked, "Enable processing same event for Monte Carlo", false); + + /// This function processes the mixed event + /// \tparam PartitionType + /// \tparam PartType + /// \tparam isMC: enables Monte Carlo truth specific histograms + /// \param groupPartsOne partition for the first particle passed by the process function + /// \param groupPartsTwo partition for the second particle passed by the process function + /// \param groupPartsThree partition for the third particle passed by the process function + /// \param parts femtoDreamParticles table (in case of Monte Carlo joined with FemtoDreamMCLabels) + /// \param magFieldTesla magnetic field of the collision + /// \param multCol multiplicity of the collision + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartitionType groupPartsThree, PartType parts, float magFieldTesla, int multCol) + { + for (auto& [p1, p2, p3] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo, groupPartsThree))) { + + auto Q3 = FemtoDreamMath::getQ3(p1, mMassOne, p2, mMassTwo, p3, mMassThree); + if (ConfIsCPR.value) { + if (pairCloseRejectionME.isClosePair(p1, p2, parts, magFieldTesla, Q3)) { + continue; + } + if (pairCloseRejectionME.isClosePair(p2, p3, parts, magFieldTesla, Q3)) { + continue; + } + + if (pairCloseRejectionME.isClosePair(p1, p3, parts, magFieldTesla, Q3)) { + continue; + } + } + // fill pT of all three particles as a function of Q3 for lambda calculations + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/particle_pT_in_Triplet_ME"), p1.pt(), p2.pt(), p3.pt(), Q3); + mixedEventCont.setTriplet(p1, p2, p3, multCol, Q3); + } + } + + /// process function for to call doMixedEvent with Data + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoDreamParticleTable + void processMixedEvent(FilteredFDCollisions& cols, + o2::aod::FDParticles& parts) + { + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, cols, cols, cols)) { + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision1.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision2.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision3.multV0M()); + + auto groupPartsOne = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEvent, "Enable processing mixed events", true); + + /// process function for to call doMixedEvent with Data which has a mask for containing particles or not + /// @param cols subscribe to the collisions table (Data) + /// @param parts subscribe to the femtoDreamParticleTable + void processMixedEventMasked(MaskedCollisions& cols, o2::aod::FDParticles& parts) + { + Partition PartitionMaskedCol1 = (ConfTracksInMixedEvent == 1 && (aod::femtodreamcollision::bitmaskTrackOne & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 2 && (aod::femtodreamcollision::bitmaskTrackTwo & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 3 && (aod::femtodreamcollision::bitmaskTrackThree & MaskBit) == MaskBit); + + PartitionMaskedCol1.bindTable(cols); + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered)) { + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision1.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision2.multV0M()); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hCentralityME"), collision3.multV0M()); + + auto groupPartsOne = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedParts->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEventMasked, "Enable processing mixed events", false); + + /// brief process function for to call doMixedEvent with Monte Carlo + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// @param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMC(o2::aod::FDCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, cols, cols, cols)) { + + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + // CONSIDER testing different strategies to which events to use + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEventMC, "Enable processing mixed events MC", false); + + /// brief process function for to call doMixedEvent with Monte Carlo which has a mask for containing particles or not + /// @param cols subscribe to the collisions table (Monte Carlo Reconstructed reconstructed) + /// @param parts subscribe to joined table FemtoDreamParticles and FemtoDreamMCLables to access Monte Carlo truth + /// @param FemtoDreamMCParticles subscribe to the Monte Carlo truth table + void processMixedEventMCMasked(MaskedCollisions& cols, + soa::Join& parts, + o2::aod::FDMCParticles&) + { + Partition PartitionMaskedCol1 = (ConfTracksInMixedEvent == 1 && (aod::femtodreamcollision::bitmaskTrackOne & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 2 && (aod::femtodreamcollision::bitmaskTrackTwo & MaskBit) == MaskBit) || + (ConfTracksInMixedEvent == 3 && (aod::femtodreamcollision::bitmaskTrackThree & MaskBit) == MaskBit); + PartitionMaskedCol1.bindTable(cols); + + for (auto& [collision1, collision2, collision3] : soa::selfCombinations(colBinning, ConfNEventsMix, -1, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol1.mFiltered)) { + + const int multiplicityCol = collision1.multNtr(); + ThreeBodyQARegistry.fill(HIST("TripletTaskQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); + + auto groupPartsOne = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsThree = SelectedPartsMC->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision3.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + const auto& magFieldTesla3 = collision3.magField(); + + if ((magFieldTesla1 != magFieldTesla2) || (magFieldTesla2 != magFieldTesla3) || (magFieldTesla1 != magFieldTesla3)) { + continue; + } + // CONSIDER testing different strategies to which events to use + + doMixedEvent(groupPartsOne, groupPartsTwo, groupPartsThree, parts, magFieldTesla1, multiplicityCol); + } + } + PROCESS_SWITCH(femtoDreamTripletTaskTrackTrackTrackPbPb, processMixedEventMCMasked, "Enable processing mixed events MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h index 3a389da705e..ff8206ea551 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h @@ -252,9 +252,9 @@ class FemtoUniverseCascadeSelection femto_universe_selection::kLowerLimit, // cascade tran rad min femto_universe_selection::kUpperLimit, // cascade tran rad max femto_universe_selection::kUpperLimit, // cascade maximum distance of decay vertex to PV - femto_universe_selection::kLowerLimit, // DCA pos to PV max - femto_universe_selection::kLowerLimit, // DCA neg to PV max - femto_universe_selection::kLowerLimit, // DCA bach to PV max + femto_universe_selection::kLowerLimit, // DCA pos to PV min + femto_universe_selection::kLowerLimit, // DCA neg to PV min + femto_universe_selection::kLowerLimit, // DCA bach to PV min femto_universe_selection::kLowerLimit, // DCA v0 to PV max femto_universe_selection::kLowerLimit, // v0 mass min femto_universe_selection::kUpperLimit, // v0 mass max @@ -276,10 +276,10 @@ class FemtoUniverseCascadeSelection "Minimum cascade transverse radius (cm)", "Maximum cascade transverse radius (cm)", "Maximum distance of cascade from primary vertex", - "Maximum DCA of positive track form primary vertex", - "Maximum DCA of negative track form primary vertex", - "Maximum DCA of bachelor track form primary vertex", - "Maximum DCA of v0 form primary vertex", + "Minimum DCA of positive track form primary vertex", + "Minimum DCA of negative track form primary vertex", + "Minimum DCA of bachelor track form primary vertex", + "Minimum DCA of v0 form primary vertex", "Minimum V0 mass", "Maximum V0 mass"}; ///< Helper information for the ///< different selections diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h index 04478ec7e0f..8b5df274887 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h @@ -20,17 +20,21 @@ #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECONTAINER_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSECONTAINER_H_ -#include -#include -#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "Framework/HistogramRegistry.h" #include "Common/Core/RecoDecay.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" + +#include "Framework/HistogramRegistry.h" #include "Math/Vector4D.h" -#include "TMath.h" #include "TDatabasePDG.h" +#include "TMath.h" + +#include + +#include +#include using namespace o2::framework; @@ -53,7 +57,7 @@ enum EventType { same, ///< Pair from same event /// \brief Container for all histogramming related to the correlation function. The two /// particles of the pair are passed here, and the correlation function and QA histograms /// are filled according to the specified observable -/// \tparam eventType Type of the event (same/mixed) +/// \tparam eventType Type of the event (same or mixed) /// \tparam obs Observable to be computed (k*/Q_inv/...) template class FemtoUniverseContainer diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h index 0a06b3513e8..1e336f20abd 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h @@ -19,16 +19,19 @@ #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEDETADPHISTAR_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEDETADPHISTAR_H_ -#include -#include -#include -#include "TMath.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseAngularContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" -#include "Framework/HistogramRegistry.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseFemtoContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Framework/HistogramRegistry.h" + +#include "TMath.h" + +#include +#include +#include namespace o2::analysis { @@ -68,6 +71,9 @@ class FemtoUniverseDetaDphiStar histdetadpimixed[0][0] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[0][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); histdetadpimixed[0][1] = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][0])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiqlcmssame = mHistogramRegistry->add((dirName + static_cast(HistNamesSame[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {100, -0.15, 0.15}, {100, -0.15, 0.15}}); + histdetadpiqlcmsmixed = mHistogramRegistry->add((dirName + static_cast(HistNamesMixed[1][7])).c_str(), "; #it{q}_{LCMS}; #Delta #eta; #Delta #phi", kTH3F, {{100, 0.0, 0.5}, {100, -0.15, 0.15}, {100, -0.15, 0.15}}); + if (plotForEveryRadii) { for (int i = 0; i < 9; i++) { histdetadpiRadii[0][i] = mHistogramRegistryQA->add((dirName + static_cast(HistNamesRadii[0][i])).c_str(), "; #Delta #eta; #Delta #phi", kTH2F, {{100, -0.15, 0.15}, {100, -0.15, 0.15}}); @@ -276,7 +282,7 @@ class FemtoUniverseDetaDphiStar auto indexOfDaughterpart2 = (ChosenEventType == femto_universe_container::EventType::mixed ? part2.globalIndex() : part2.index()) + CascChildTable[i][1]; auto daughterpart1 = particles.begin() + indexOfDaughterpart1; auto daughterpart2 = particles.begin() + indexOfDaughterpart2; - if (isSameSignCPR && (daughterpart1.sign() != daughterpart2.sign())) + if (isSameSignCPR && (daughterpart1.mAntiLambda() != daughterpart2.mAntiLambda())) // mAntiLambda() is used here as sign getter continue; auto deta = daughterpart1.eta() - daughterpart2.eta(); auto dphiAvg = averagePhiStar(*daughterpart1, *daughterpart2, i); @@ -407,23 +413,141 @@ class FemtoUniverseDetaDphiStar } } + /// Check if pair is close or not + template + bool isClosePairAtITS(Part const& part1, Part const& part2, float lmagfield, uint8_t ChosenEventType) + { + magfield = lmagfield; + + if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { + /// Track-Track combination + // check if provided particles are in agreement with the class instantiation + if (part1.partType() != o2::aod::femtouniverseparticle::ParticleType::kTrack || part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kTrack) { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar instantiation! Please provide kTrack,kTrack candidates."; + return false; + } + auto deta = part1.eta() - part2.eta(); + auto dphiAvg = part1.phi() - part2.phi(); + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadpisame[0][0]->Fill(deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadpimixed[0][0]->Fill(deta, dphiAvg); + } else { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; + } + + if (std::pow(dphiAvg, 2) / std::pow(cutDeltaPhiStarMax, 2) + std::pow(deta, 2) / std::pow(cutDeltaEtaMax, 2) < 1.) { + return true; + } else { + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadpisame[0][1]->Fill(deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadpimixed[0][1]->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 { + LOG(fatal) << "FemtoUniversePairCleaner: Combination of objects not defined - quitting!"; + return false; + } + } + + /// Check if pair is close or not + template + bool isClosePairFrac(Part const& part1, Part const& part2, float lmagfield, uint8_t ChosenEventType, bool IsDphiAvgOrDist, float DistMax, float FracMax) + { + magfield = lmagfield; + + if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { + /// Track-Track combination + // check if provided particles are in agreement with the class instantiation + if (part1.partType() != o2::aod::femtouniverseparticle::ParticleType::kTrack || part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kTrack) { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar instantiation! Please provide kTrack,kTrack candidates."; + return false; + } + auto deta = part1.eta() - part2.eta(); + auto dphiAvg = averagePhiStar(part1, part2, 0); + auto distfrac = averagePhiStarFrac(part1, part2, DistMax); + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadpisame[0][0]->Fill(deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadpimixed[0][0]->Fill(deta, dphiAvg); + } else { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; + } + + if (IsDphiAvgOrDist) { + if (std::pow(dphiAvg, 2) / std::pow(cutDeltaPhiStarMax, 2) + std::pow(deta, 2) / std::pow(cutDeltaEtaMax, 2) < 1.) { + return true; + } else { + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadpisame[0][1]->Fill(deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadpimixed[0][1]->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 (distfrac > FracMax) { + return true; + } else { + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadpisame[0][1]->Fill(deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadpimixed[0][1]->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 { + LOG(fatal) << "FemtoUniversePairCleaner: Combination of objects not defined - quitting!"; + return false; + } + } + + /// Check if pair is close or not + template + void ClosePairqLCMS(Part const& part1, Part const& part2, float lmagfield, uint8_t ChosenEventType, double qlcms) // add typename Parts and variable parts for adding MClabels + { + magfield = lmagfield; + if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kTrack) { + auto deta = part1.eta() - part2.eta(); + auto dphiAvg = averagePhiStar(part1, part2, 0); + + if (ChosenEventType == femto_universe_container::EventType::same) { + histdetadpiqlcmssame->Fill(qlcms, deta, dphiAvg); + } else if (ChosenEventType == femto_universe_container::EventType::mixed) { + histdetadpiqlcmsmixed->Fill(qlcms, deta, dphiAvg); + } else { + LOG(fatal) << "FemtoUniverseDetaDphiStar: passed arguments don't agree with FemtoUniverseDetaDphiStar's type of events! Please provide same or mixed."; + } + } + } + private: HistogramRegistry* mHistogramRegistry = nullptr; ///< For main output HistogramRegistry* mHistogramRegistryQA = nullptr; ///< For QA output static constexpr std::string_view DirNames[6] = {"kTrack_kTrack/", "kTrack_kV0/", "kV0_kV0/", "kTrack_kPhi/", "kTrack_kD0/", "kCascade_kCascade/"}; - static constexpr std::string_view HistNamesSame[2][7] = {{"detadphidetadphi0BeforeSame_0", "detadphidetadphi0BeforeSame_1", "detadphidetadphi0BeforeSame_2", + static constexpr std::string_view HistNamesSame[2][8] = {{"detadphidetadphi0BeforeSame_0", "detadphidetadphi0BeforeSame_1", "detadphidetadphi0BeforeSame_2", "detadphidetadphi0BeforeSame_3", "detadphidetadphi0BeforeSame_4", "detadphidetadphi0BeforeSame_5", - "detadphidetadphi0BeforeSame_6"}, + "detadphidetadphi0BeforeSame_6", "detadphidetadphi0BeforeSameqLCMS"}, {"detadphidetadphi0AfterSame_0", "detadphidetadphi0AfterSame_1", "detadphidetadphi0AfterSame_2", "detadphidetadphi0AfterSame_3", "detadphidetadphi0AfterSame_4", "detadphidetadphi0AfterSame_5", - "detadphidetadphi0AfterSame_6"}}; - static constexpr std::string_view HistNamesMixed[2][7] = {{"detadphidetadphi0BeforeMixed_0", "detadphidetadphi0BeforeMixed_1", "detadphidetadphi0BeforeMixed_2", + "detadphidetadphi0AfterSame_6", "detadphidetadphi0AfterSameqLCMS"}}; + static constexpr std::string_view HistNamesMixed[2][8] = {{"detadphidetadphi0BeforeMixed_0", "detadphidetadphi0BeforeMixed_1", "detadphidetadphi0BeforeMixed_2", "detadphidetadphi0BeforeMixed_3", "detadphidetadphi0BeforeMixed_4", "detadphidetadphi0BeforeMixed_5", - "detadphidetadphi0BeforeMixed_6"}, + "detadphidetadphi0BeforeMixed_6", "detadphidetadphi0BeforeMixedqLCMS"}, {"detadphidetadphi0AfterMixed_0", "detadphidetadphi0AfterMixed_1", "detadphidetadphi0AfterMixed_2", "detadphidetadphi0AfterMixed_3", "detadphidetadphi0AfterMixed_4", "detadphidetadphi0AfterMixed_5", - "detadphidetadphi0AfterMixed_6"}}; + "detadphidetadphi0AfterMixed_6", "detadphidetadphi0AfterMixedqLCMS"}}; static constexpr std::string_view HistNamesRadii[7][9] = {{"detadphidetadphi0Before_0_0", "detadphidetadphi0Before_0_1", "detadphidetadphi0Before_0_2", "detadphidetadphi0Before_0_3", "detadphidetadphi0Before_0_4", "detadphidetadphi0Before_0_5", @@ -471,6 +595,9 @@ class FemtoUniverseDetaDphiStar std::array, 2>, 7> histdetadpimixed{}; std::array, 9>, 7> histdetadpiRadii{}; + std::shared_ptr histdetadpiqlcmssame{}; + std::shared_ptr histdetadpiqlcmsmixed{}; + /// Calculate phi at all required radii stored in TmpRadiiTPC /// Magnetic field to be provided in Tesla template @@ -529,6 +656,36 @@ class FemtoUniverseDetaDphiStar return dPhiAvg / static_cast(entries); } + /// Calculate average phi + template + float averagePhiStarFrac(const T1& part1, const T2& part2, float maxdist) + { + std::vector tmpVec1; + std::vector tmpVec2; + phiAtRadiiTPC(part1, tmpVec1); + phiAtRadiiTPC(part2, tmpVec2); + int num = tmpVec1.size(); + float dphi = 0; + int entries = 0; + double distance = 0; + int badpoints = 0; + + for (int i = 0; i < num; i++) { + if (tmpVec1.at(i) != 999 && tmpVec2.at(i) != 999) { + dphi = tmpVec1.at(i) - tmpVec2.at(i); + entries++; + } else { + dphi = 0; + } + dphi = TVector2::Phi_mpi_pi(dphi); + distance = 2 * TMath::Sin(TMath::Abs(dphi) * 0.5) * TmpRadiiTPC[i]; + if (distance < maxdist) { + badpoints++; + } + } + return badpoints / entries; + } + // Get particle charge from mask template float getCharge(const T1& part) diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h index 9936a5430d6..74e37d27a66 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h @@ -16,22 +16,22 @@ #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEFFICIENCYCORRECTION_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEEFFICIENCYCORRECTION_H_ +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + #include #include #include #include #include - #include + #include #include -#include -#include #include #include - -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include +#include namespace o2::analysis::femto_universe::efficiency_correction { @@ -50,6 +50,7 @@ struct EffCorConfigurableGroup : framework::ConfigurableGroup { framework::Configurable confEffCorCCDBPath{"confEffCorCCDBPath", "", "[Efficiency Correction] CCDB path to histograms"}; framework::Configurable> confEffCorCCDBTimestamps{"confEffCorCCDBTimestamps", {}, "[Efficiency Correction] Timestamps of histograms in CCDB (0 can be used as a placeholder, e.g. when running subwagons)"}; framework::Configurable confEffCorVariables{"confEffCorVariables", "pt", "[Efficiency Correction] Variables for efficiency correction histogram dimensions (available: 'pt'; 'pt,eta'; 'pt,mult'; 'pt,eta,mult')"}; + framework::Configurable confEffCorSetMultToConst{"confEffCorSetMultToConst", false, "[Efficiency Correction] Multiplicity for the histograms set to the constant value"}; }; class EfficiencyCorrection @@ -62,6 +63,7 @@ class EfficiencyCorrection auto init(framework::HistogramRegistry* registry, std::vector axisSpecs) -> void { shouldFillHistograms = config->confEffCorFillHist; + shouldSetMultToConst = config->confEffCorSetMultToConst; histRegistry = registry; if (shouldFillHistograms) { @@ -115,7 +117,7 @@ class EfficiencyCorrection } } - template + template requires IsOneOrTwo void fillTruthHist(auto particle) { @@ -126,10 +128,10 @@ class EfficiencyCorrection histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hMCTruth"), particle.pt(), particle.eta(), - particle.fdCollision().multV0M()); + shouldSetMultToConst ? 100 : particle.template fdCollision_as().multV0M()); } - template + template requires IsOneOrTwo void fillRecoHist(auto particle, int particlePDG) { @@ -149,7 +151,7 @@ class EfficiencyCorrection histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hPrimary"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; case (o2::aod::femtouniverse_mc_particle::kDaughter): @@ -158,33 +160,34 @@ class EfficiencyCorrection histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hSecondary"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; case (o2::aod::femtouniverse_mc_particle::kMaterial): histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hMaterial"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; case (o2::aod::femtouniverse_mc_particle::kFake): histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hFake"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; default: histRegistry->fill(HIST(histDirectory) + HIST("/") + HIST(histSuffix[N - 1]) + HIST("/hOther"), mcParticle.pt(), mcParticle.eta(), - particle.fdCollision().multV0M()); + particle.template fdCollision_as().multV0M()); break; } } } + template auto getWeight(ParticleNo partNo, auto particle) -> float { auto weight = 1.0f; @@ -203,9 +206,9 @@ class EfficiencyCorrection } else if (config->confEffCorVariables.value == "pt,eta") { bin = hWeights->FindBin(particle.pt(), particle.eta()); } else if (config->confEffCorVariables.value == "pt,mult") { - bin = hWeights->FindBin(particle.pt(), particle.fdCollision().multV0M()); + bin = hWeights->FindBin(particle.pt(), particle.template fdCollision_as().multV0M()); } else if (config->confEffCorVariables.value == "pt,eta,mult") { - bin = hWeights->FindBin(particle.pt(), particle.eta(), particle.fdCollision().multV0M()); + bin = hWeights->FindBin(particle.pt(), particle.eta(), particle.template fdCollision_as().multV0M()); } else { LOGF(fatal, notify("Unknown configuration for efficiency variables")); return weight; @@ -276,6 +279,7 @@ class EfficiencyCorrection bool shouldApplyCorrection{false}; bool shouldFillHistograms{false}; + bool shouldSetMultToConst{false}; o2::ccdb::BasicCCDBManager& ccdb{o2::ccdb::BasicCCDBManager::instance()}; std::array hLoaded{nullptr, nullptr}; diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h b/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h index b6a54f60b71..b27d8e25abf 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h @@ -131,6 +131,23 @@ class FemtoUniversePairCleaner return false; } return part1.globalIndex() != part2.globalIndex(); + } else if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kV0 && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kCascade) { + /// V0-Cascade combination where part1 is a V0 and part2 is a cascade + if (part1.partType() != o2::aod::femtouniverseparticle::ParticleType::kV0 || part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kCascade) { + LOG(fatal) << "FemtoUniversePairCleaner: passed arguments don't agree with FemtoUniversePairCleaner instantiation! Please provide first argument kV0 candidate and second argument kCascade candidate."; + return false; + } + // part1 v0 children + const auto& posChild1 = particles.iteratorAt(part1.index() - 2); + const auto& negChild1 = particles.iteratorAt(part1.index() - 1); + // part2 cascade children + const auto& posChild2 = particles.iteratorAt(part2.index() - 3); + const auto& negChild2 = particles.iteratorAt(part2.index() - 2); + const auto& bachelor2 = particles.iteratorAt(part2.index() - 1); + if (posChild1.globalIndex() == posChild2.globalIndex() || negChild1.globalIndex() == negChild2.globalIndex() || posChild1.globalIndex() == bachelor2.globalIndex() || negChild1.globalIndex() == bachelor2.globalIndex()) { + return false; + } + return part1.globalIndex() != part2.globalIndex(); } else if constexpr (kPartOneType == o2::aod::femtouniverseparticle::ParticleType::kTrack && kPartTwoType == o2::aod::femtouniverseparticle::ParticleType::kD0) { /// Track-D0 combination part1 is hadron and part2 is D0 if (part2.partType() != o2::aod::femtouniverseparticle::ParticleType::kD0) { diff --git a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h index 865efa0f36d..dc46dae8df7 100644 --- a/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h +++ b/PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h @@ -20,11 +20,13 @@ #ifndef PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPARTICLEHISTO_H_ #define PWGCF_FEMTOUNIVERSE_CORE_FEMTOUNIVERSEPARTICLEHISTO_H_ -#include -#include #include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "Framework/HistogramRegistry.h" + #include "CommonConstants/MathConstants.h" +#include "Framework/HistogramRegistry.h" + +#include +#include using namespace o2::framework; // o2-linter: disable=using-directive @@ -266,6 +268,10 @@ class FemtoUniverseParticleHisto if constexpr (mc == o2::aod::femtouniverse_mc_particle::MCType::kRecon) { mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST(o2::aod::femtouniverseparticle::TempFitVarName[mParticleType]), part.pt(), part.tempFitVar()); } + if constexpr (mParticleType == o2::aod::femtouniverseparticle::ParticleType::kCascade) { + mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/hInvMassXi"), part.mLambda()); + mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/hInvMassOmega"), part.mAntiLambda()); + } } template @@ -318,8 +324,6 @@ class FemtoUniverseParticleHisto mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/hDecayVtxX"), part.decayVtxX()); mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/hDecayVtxY"), part.decayVtxY()); mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/hDecayVtxZ"), part.decayVtxZ()); - mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/hInvMassXi"), part.mLambda()); - mHistogramRegistry->fill(histFolder + HIST(o2::aod::femtouniverse_mc_particle::MCTypeName[mc]) + HIST("/hInvMassOmega"), part.mAntiLambda()); } } diff --git a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h index 9a191441f1e..c103b52791e 100644 --- a/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h +++ b/PWGCF/FemtoUniverse/DataModel/FemtoDerived.h @@ -139,23 +139,6 @@ DECLARE_SOA_COLUMN(MKaon, mKaon, float); //! The invariant mass of V } // namespace femtouniverseparticle -/// FemtoUniverseCascadeTrack -namespace femtouniversecascparticle -{ - -DECLARE_SOA_COLUMN(DcaV0daughters, dcaV0daughters, float); //! DCA between V0 daughters -DECLARE_SOA_COLUMN(Cpav0, cpav0, float); //! V0 cos of pointing angle -DECLARE_SOA_COLUMN(V0radius, v0radius, float); //! V0 transverse radius -DECLARE_SOA_COLUMN(CpaCasc, cpaCasc, float); //! cascade cosinus of pointing angle -DECLARE_SOA_COLUMN(Dcacascdaughters, dcacascdaughters, float); //! DCA between cascade daughters -DECLARE_SOA_COLUMN(Cascradius, cascradius, float); //! cascade transverse radius -DECLARE_SOA_COLUMN(Dcapostopv, dcapostopv, float); //! DCA of positive daughter to PV -DECLARE_SOA_COLUMN(Dcanegtopv, dcanegtopv, float); //! DCA of negative daughter to PV -DECLARE_SOA_COLUMN(Dcabachtopv, dcabachtopv, float); //! DCA of bachelor track to PV -DECLARE_SOA_COLUMN(Dcav0topv, dcav0topv, float); //! DCA of V0 to PV - -} // namespace femtouniversecascparticle - DECLARE_SOA_TABLE(FDParticles, "AOD", "FDPARTICLE", o2::soa::Index<>, femtouniverseparticle::FdCollisionId, @@ -176,6 +159,23 @@ DECLARE_SOA_TABLE(FDParticles, "AOD", "FDPARTICLE", femtouniverseparticle::P); using FDParticle = FDParticles::iterator; +/// FemtoUniverseCascadeTrack +namespace femtouniversecascparticle +{ +DECLARE_SOA_INDEX_COLUMN(FDParticle, fdParticle); +DECLARE_SOA_COLUMN(DcaV0daughters, dcaV0daughters, float); //! DCA between V0 daughters +DECLARE_SOA_COLUMN(Cpav0, cpav0, float); //! V0 cos of pointing angle +DECLARE_SOA_COLUMN(V0radius, v0radius, float); //! V0 transverse radius*/ +DECLARE_SOA_COLUMN(CpaCasc, cpaCasc, float); //! cascade cosinus of pointing angle +DECLARE_SOA_COLUMN(Dcacascdaughters, dcacascdaughters, float); //! DCA between cascade daughters +DECLARE_SOA_COLUMN(Cascradius, cascradius, float); //! cascade transverse radius +DECLARE_SOA_COLUMN(Dcapostopv, dcapostopv, float); //! DCA of positive daughter to PV +DECLARE_SOA_COLUMN(Dcanegtopv, dcanegtopv, float); //! DCA of negative daughter to PV +DECLARE_SOA_COLUMN(Dcabachtopv, dcabachtopv, float); //! DCA of bachelor track to PV +DECLARE_SOA_COLUMN(Dcav0topv, dcav0topv, float); //! DCA of V0 to PV + +} // namespace femtouniversecascparticle + DECLARE_SOA_TABLE(FDExtParticles, "AOD", "FDEXTPARTICLE", femtouniverseparticle::Sign, femtouniverseparticle::TpcNClsFound, @@ -221,16 +221,7 @@ using FDFullParticle = FDExtParticles::iterator; DECLARE_SOA_TABLE(FDCascParticles, "AOD", "FDCASCPARTICLE", o2::soa::Index<>, femtouniverseparticle::FdCollisionId, - femtouniverseparticle::Pt, - femtouniverseparticle::Eta, - femtouniverseparticle::Phi, - femtouniverseparticle::PartType, - femtouniverseparticle::Cut, - femtouniverseparticle::PidCut, - femtouniverseparticle::TempFitVar, - femtouniverseparticle::ChildrenIds, - femtouniverseparticle::MLambda, - femtouniverseparticle::MAntiLambda, + femtouniversecascparticle::FDParticleId, femtouniverseparticle::Theta, femtouniverseparticle::Px, femtouniverseparticle::Py, diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx index 8152aee0d5e..9ab5dcecd68 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerMCTruthTask.cxx @@ -14,35 +14,35 @@ /// \author Malgorzata Janik, WUT Warsaw, majanik@cern.ch /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch -#include -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h" -#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" -#include "Framework/ASoAHelpers.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" + #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "Math/Vector4D.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "ReconstructionDataFormats/Track.h" -#include "TMath.h" -#include "TLorentzVector.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::analysis::femto_universe; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; namespace o2::aod { @@ -71,7 +71,7 @@ int getRowDaughters(int daughID, T const& vecID) return rowInPrimaryTrackTableDaugh; } -struct femtoUniverseProducerMCTruthTask { +struct FemtoUniverseProducerMCTruthTask { int mRunNumber; float mMagField; Service ccdb; /// Accessing the CCDB @@ -83,29 +83,26 @@ struct femtoUniverseProducerMCTruthTask { // Produces outputPartsMC; // Analysis configs - Configurable ConfIsTrigger{"ConfIsTrigger", false, "Store all collisions"}; // Choose if filtering or skimming version is run - Configurable ConfIsRun3{"ConfIsRun3", false, "Running on Run3 or pilot"}; - Configurable ConfIsMC{"ConfIsMC", false, "Running on MC; implemented only for Run3"}; - Configurable ConfIsForceGRP{"ConfIsForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"}; - Configurable ConfIsActivateV0{"ConfIsActivateV0", true, "Activate filling of V0 into femtouniverse tables"}; - Configurable ConfIsActivatePhi{"ConfIsActivatePhi", true, "Activate filling of Phi into femtouniverse tables"}; - Configurable> ConfPDGCodes{"ConfPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; - Configurable ConfAnalysisWithPID{"ConfAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles"}; + Configurable confIsRun3{"confIsRun3", false, "Running on Run3 or pilot"}; + Configurable confIsMC{"confIsMC", false, "Running on MC; implemented only for Run3"}; + Configurable confIsForceGRP{"confIsForceGRP", false, "Set true if the magnetic field configuration is not available in the usual CCDB directory (e.g. for Run 2 converted data or unanchorad Monte Carlo)"}; + Configurable> confPDGCodes{"confPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; + Configurable confAnalysisWithPID{"confAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles"}; /// Event cuts - Configurable ConfEvtUseTPCmult{"ConfEvtUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; - Configurable ConfEvtZvtx{"ConfEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; - Configurable ConfEvtTriggerCheck{"ConfEvtTriggerCheck", true, "Evt sel: check for trigger"}; - Configurable ConfEvtTriggerSel{"ConfEvtTriggerSel", kINT7, "Evt sel: trigger"}; - Configurable ConfEvtOfflineCheck{"ConfEvtOfflineCheck", false, "Evt sel: check for offline selection"}; - Configurable ConfCentFT0Min{"ConfCentFT0Min", 0.f, "Min CentFT0 value for centrality selection"}; - Configurable ConfCentFT0Max{"ConfCentFT0Max", 200.f, "Max CentFT0 value for centrality selection"}; + Configurable confEvtZvtx{"confEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable confEvtTriggerCheck{"confEvtTriggerCheck", true, "Evt sel: check for trigger"}; + Configurable confEvtTriggerSel{"confEvtTriggerSel", kINT7, "Evt sel: trigger"}; + Configurable confEvtOfflineCheck{"confEvtOfflineCheck", false, "Evt sel: check for offline selection"}; + Configurable confCentFT0Min{"confCentFT0Min", 0.f, "Min CentFT0 value for centrality selection"}; + Configurable confCentFT0Max{"confCentFT0Max", 200.f, "Max CentFT0 value for centrality selection"}; + Configurable confDoSpher{"confDoSpher", false, "Calculate sphericity. If false sphericity will take value of 2."}; // Track cuts struct : o2::framework::ConfigurableGroup { - Configurable ConfPtLowFilterCut{"ConfPtLowFilterCut", 0.14, "Lower limit for Pt for the filtering tracks"}; // pT low - Configurable ConfPtHighFilterCut{"ConfPtHighFilterCut", 5.0, "Higher limit for Pt for the filtering tracks"}; // pT high - Configurable ConfEtaFilterCut{"ConfEtaFilterCut", 0.8, "Eta cut for the filtering tracks"}; + Configurable confPtLowFilterCut{"confPtLowFilterCut", 0.14, "Lower limit for Pt for the filtering tracks"}; // pT low + Configurable confPtHighFilterCut{"confPtHighFilterCut", 5.0, "Higher limit for Pt for the filtering tracks"}; // pT high + Configurable confEtaFilterCut{"confEtaFilterCut", 0.8, "Eta cut for the filtering tracks"}; } ConfFilteringTracks; FemtoUniverseCollisionSelection colCuts; @@ -118,7 +115,7 @@ struct femtoUniverseProducerMCTruthTask { LOGF(fatal, "Neither processFullData nor processFullMC enabled. Please choose one."); } - colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtTriggerSel, ConfEvtOfflineCheck, ConfIsRun3, ConfCentFT0Min, ConfCentFT0Max); + colCuts.setCuts(confEvtZvtx, confEvtTriggerCheck, confEvtTriggerSel, confEvtOfflineCheck, confIsRun3, confCentFT0Min, confCentFT0Max); colCuts.init(&qaRegistry); trackCuts.init(&qaRegistry); @@ -135,16 +132,23 @@ struct femtoUniverseProducerMCTruthTask { } template - void fillCollisions(CollisionType const& col, TrackType const& /*tracks*/) + void fillCollisions(CollisionType const& col, TrackType const& tracks) { - for (auto& c : col) { + for (const auto& c : col) { const auto vtxZ = c.posZ(); - const auto spher = 0; // colCuts.computeSphericity(col, tracks); - int mult = 0; - int multNtr = 0; + float mult = confIsRun3 ? c.multFV0M() : 0.5 * (c.multFV0M()); + int multNtr = confIsRun3 ? c.multNTracksPV() : c.multTracklets(); + // Removing collisions with Zvtx > 10 cm + if (std::abs(vtxZ) > confEvtZvtx) { + continue; + } // colCuts.fillQA(c); //for now, TODO: create a configurable so in the FemroUniverseCollisionSelection.h there is an option to plot QA just for the posZ - outputCollision(vtxZ, mult, multNtr, spher, mMagField); + if (confDoSpher) { + outputCollision(vtxZ, mult, multNtr, colCuts.computeSphericity(col, tracks), mMagField); + } else { + outputCollision(vtxZ, mult, multNtr, 2, mMagField); + } } } @@ -153,26 +157,26 @@ struct femtoUniverseProducerMCTruthTask { { std::vector childIDs = {0, 0}; // these IDs are necessary to keep track of the children - for (auto& particle : tracks) { + for (const auto& particle : tracks) { /// if the most open selection criteria are not fulfilled there is no /// point looking further at the track - if (particle.eta() < -ConfFilteringTracks.ConfEtaFilterCut || particle.eta() > ConfFilteringTracks.ConfEtaFilterCut) + if (particle.eta() < -ConfFilteringTracks.confEtaFilterCut || particle.eta() > ConfFilteringTracks.confEtaFilterCut) continue; - if (particle.pt() < ConfFilteringTracks.ConfPtLowFilterCut || particle.pt() > ConfFilteringTracks.ConfPtHighFilterCut) + if (particle.pt() < ConfFilteringTracks.confPtLowFilterCut || particle.pt() > ConfFilteringTracks.confPtHighFilterCut) continue; - uint32_t pdgCode = (uint32_t)particle.pdgCode(); + int pdgCode = particle.pdgCode(); - if (ConfAnalysisWithPID) { + if (confAnalysisWithPID) { bool pass = false; - std::vector tmpPDGCodes = ConfPDGCodes; // necessary due to some features of the Configurable - for (uint32_t pdg : tmpPDGCodes) { - if (pdgCode == 333) { // phi meson + std::vector tmpPDGCodes = confPDGCodes; // necessary due to some features of the Configurable + for (const int& pdg : tmpPDGCodes) { + if (pdgCode == Pdg::kPhi) { // phi meson pass = true; - } else if (pdgCode == 421) { // D0 meson + } else if (pdgCode == Pdg::kD0) { // D0 meson pass = true; - } else if (pdgCode == 411) { // D+ meson + } else if (pdgCode == Pdg::kDPlus) { // D+ meson pass = true; } else if (static_cast(pdg) == static_cast(pdgCode)) { if (particle.isPhysicalPrimary()) @@ -220,11 +224,11 @@ struct femtoUniverseProducerMCTruthTask { fillCollisions(collisions, mcParticles); fillParticles(mcParticles); } - PROCESS_SWITCH(femtoUniverseProducerMCTruthTask, processTrackMC, "Provide MC data for track analysis", true); + PROCESS_SWITCH(FemtoUniverseProducerMCTruthTask, processTrackMC, "Provide MC data for track analysis", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; return workflow; } diff --git a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx index 00ed3161ce7..1415e905f39 100644 --- a/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx +++ b/PWGCF/FemtoUniverse/TableProducer/femtoUniverseProducerTask.cxx @@ -17,45 +17,52 @@ /// \author Pritam Chakraborty, WUT Warsaw, pritam.chakraborty@cern.ch /// \author Shirajum Monira, WUT Warsaw, shirajum.monira@cern.ch -#include -#include -#include -#include -#include -#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" +#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "CommonConstants/PhysicsConstants.h" #include "Common/CCDB/ctpRateFetcher.h" -#include "Common/Core/trackUtilities.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/Centrality.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + +#include "CommonConstants/PhysicsConstants.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCollisionSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseV0Selection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseCascadeSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePhiSelection.h" -#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Core/HfHelper.h" #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 "Math/Vector4D.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" -#include "TMath.h" +#include + +#include "Math/Vector4D.h" #include "TLorentzVector.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "TMath.h" +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::analysis::femto_universe; @@ -121,6 +128,7 @@ struct FemtoUniverseProducerTask { Produces outputCascParts; Configurable confIsDebug{"confIsDebug", true, "Enable Debug tables"}; + Configurable confIsUseCutculator{"confIsUseCutculator", true, "Enable cutculator for track cuts"}; // Choose if filtering or skimming version is run // Configurable confIsTrigger{"confIsTrigger", false, "Store all collisions"}; //Commented: not used configurable // Choose if running on converted data or Run3 / Pilot @@ -133,31 +141,35 @@ 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"}; + /// Event filtering (used for v0-cascade analysis) + Configurable zorroMask{"zorroMask", "", "zorro trigger class to select on (empty: none)"}; + /// Event cuts FemtoUniverseCollisionSelection colCuts; - Configurable confEvtUseTPCmult{"confEvtUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; - Configurable confEvtZvtx{"confEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; - Configurable confEvtTriggerCheck{"confEvtTriggerCheck", true, "Evt sel: check for trigger"}; - Configurable confEvtTriggerSel{"confEvtTriggerSel", kINT7, "Evt sel: trigger"}; - Configurable confEvtOfflineCheck{"confEvtOfflineCheck", false, "Evt sel: check for offline selection"}; - Configurable confIsActivateV0{"confIsActivateV0", false, "Activate filling of V0 into femtouniverse tables"}; - Configurable confActivateSecondaries{"confActivateSecondaries", false, "Fill secondary MC gen particles that were reconstructed"}; - Configurable confIsActivateCascade{"confIsActivateCascade", false, "Activate filling of Cascade into femtouniverse tables"}; - Configurable confIsActivatePhi{"confIsActivatePhi", false, "Activate filling of Phi into femtouniverse tables"}; - Configurable confIsActiveD0{"confIsActiveD0", false, "Activate filling FU tables for D0/D0bar mesons"}; - Configurable confMCTruthAnalysisWithPID{"confMCTruthAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles (for MC Truth)"}; - Configurable> confMCTruthPDGCodes{"confMCTruthPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; - Configurable confCentFT0Min{"confCentFT0Min", 0.f, "Min CentFT0 value for centrality selection"}; - Configurable confCentFT0Max{"confCentFT0Max", 200.f, "Max CentFT0 value for centrality selection"}; - Configurable confEvIsGoodZvtxFT0vsPV{"confEvIsGoodZvtxFT0vsPV", true, "Require kIsGoodZvtxFT0vsPV selection on Events."}; - Configurable confEvNoSameBunchPileup{"confEvNoSameBunchPileup", true, "Require kNoSameBunchPileup selection on Events."}; - Configurable confIsUsePileUp{"confIsUsePileUp", true, "Required for choosing whether to run the pile-up cuts"}; - Configurable confEvIsVertexITSTPC{"confEvIsVertexITSTPC", true, "Require kIsVertexITSTPC selection on Events"}; - Configurable confTPCOccupancyMin{"confTPCOccupancyMin", 0, "Minimum value for TPC Occupancy selection"}; - Configurable confTPCOccupancyMax{"confTPCOccupancyMax", 500, "Maximum value for TPC Occupancy selection"}; - - Filter customCollCentFilter = (aod::cent::centFT0C > confCentFT0Min) && - (aod::cent::centFT0C < confCentFT0Max); + struct : o2::framework::ConfigurableGroup { + Configurable confEvtUseTPCmult{"confEvtUseTPCmult", false, "Use multiplicity based on the number of tracks with TPC information"}; + Configurable confEvtZvtx{"confEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable confEvtTriggerCheck{"confEvtTriggerCheck", true, "Evt sel: check for trigger"}; + Configurable confEvtTriggerSel{"confEvtTriggerSel", kINT7, "Evt sel: trigger"}; + Configurable confEvtOfflineCheck{"confEvtOfflineCheck", false, "Evt sel: check for offline selection"}; + Configurable confIsActivateV0{"confIsActivateV0", false, "Activate filling of V0 into femtouniverse tables"}; + Configurable confActivateSecondaries{"confActivateSecondaries", false, "Fill secondary MC gen particles that were reconstructed"}; + Configurable confIsActivateCascade{"confIsActivateCascade", false, "Activate filling of Cascade into femtouniverse tables"}; + Configurable confIsActivatePhi{"confIsActivatePhi", false, "Activate filling of Phi into femtouniverse tables"}; + Configurable confIsActiveD0{"confIsActiveD0", false, "Activate filling FU tables for D0/D0bar mesons"}; + Configurable confMCTruthAnalysisWithPID{"confMCTruthAnalysisWithPID", true, "1: take only particles with specified PDG, 0: all particles (for MC Truth)"}; + Configurable> confMCTruthPDGCodes{"confMCTruthPDGCodes", std::vector{211, -211, 2212, -2212, 333}, "PDG of particles to be stored"}; + Configurable confCentFT0Min{"confCentFT0Min", 0.f, "Min CentFT0 value for centrality selection"}; + Configurable confCentFT0Max{"confCentFT0Max", 200.f, "Max CentFT0 value for centrality selection"}; + Configurable confEvIsGoodZvtxFT0vsPV{"confEvIsGoodZvtxFT0vsPV", true, "Require kIsGoodZvtxFT0vsPV selection on Events."}; + Configurable confEvNoSameBunchPileup{"confEvNoSameBunchPileup", true, "Require kNoSameBunchPileup selection on Events."}; + Configurable confIsUsePileUp{"confIsUsePileUp", true, "Required for choosing whether to run the pile-up cuts"}; + Configurable confEvIsVertexITSTPC{"confEvIsVertexITSTPC", true, "Require kIsVertexITSTPC selection on Events"}; + Configurable confTPCOccupancyMin{"confTPCOccupancyMin", 0, "Minimum value for TPC Occupancy selection"}; + Configurable confTPCOccupancyMax{"confTPCOccupancyMax", 500, "Maximum value for TPC Occupancy selection"}; + } ConfGeneral; + Filter customCollCentFilter = (aod::cent::centFT0C > ConfGeneral.confCentFT0Min) && + (aod::cent::centFT0C < ConfGeneral.confCentFT0Max); // just sanity check to make sure in case there are problems in conversion or // MC production it does not affect results @@ -196,7 +208,6 @@ struct FemtoUniverseProducerTask { // V0 FemtoUniverseV0Selection v0Cuts; struct : o2::framework::ConfigurableGroup { - // Configurable confIsFillV0s{"confIsFillV0s", false, "Choice to fill V0s"}; //Commented: not used configurable Configurable> confV0Sign{FemtoUniverseV0Selection::getSelectionName(femto_universe_v0_selection::kV0Sign, "ConfV0"), std::vector{-1, 1}, FemtoUniverseV0Selection::getSelectionHelper(femto_universe_v0_selection::kV0Sign, "V0 selection: ")}; Configurable> confV0PtMin{FemtoUniverseV0Selection::getSelectionName(femto_universe_v0_selection::kV0pTMin, "ConfV0"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniverseV0Selection::getSelectionHelper(femto_universe_v0_selection::kV0pTMin, "V0 selection: ")}; Configurable> confV0PtMax{FemtoUniverseV0Selection::getSelectionName(femto_universe_v0_selection::kV0pTMax, "ConfV0"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniverseV0Selection::getSelectionHelper(femto_universe_v0_selection::kV0pTMax, "V0 selection: ")}; @@ -245,7 +256,6 @@ struct FemtoUniverseProducerTask { // CASCADE FemtoUniverseCascadeSelection cascadeCuts; struct : o2::framework::ConfigurableGroup { - // Configurable confIsFillCascades{"confIsFillCascades", false, "Choice to fill cascades"}; //Commented: not used configurable Configurable> confCascSign{FemtoUniverseCascadeSelection::getSelectionName(femto_universe_cascade_selection::kCascadeSign, "ConfCasc"), std::vector{-1, 1}, FemtoUniverseCascadeSelection::getSelectionHelper(femto_universe_cascade_selection::kCascadeSign, "Cascade selection: ")}; Configurable> confCascPtMin{FemtoUniverseCascadeSelection::getSelectionName(femto_universe_cascade_selection::kCascadepTMin, "ConfCasc"), std::vector{0.3f, 0.4f, 0.5f}, FemtoUniverseCascadeSelection::getSelectionHelper(femto_universe_cascade_selection::kCascadepTMin, "Cascade selection: ")}; Configurable> confCascPtMax{FemtoUniverseCascadeSelection::getSelectionName(femto_universe_cascade_selection::kCascadepTMax, "ConfCasc"), std::vector{3.3f, 3.4f, 3.5f}, FemtoUniverseCascadeSelection::getSelectionHelper(femto_universe_cascade_selection::kCascadepTMax, "Cascade selection: ")}; @@ -279,10 +289,6 @@ struct FemtoUniverseProducerTask { Configurable confXiInvMassUpLimit{"confXiInvMassUpLimit", 1.40, "Upper limit of the Xi invariant mass"}; Configurable confOmegaInvMassLowLimit{"confOmegaInvMassLowLimit", 1.60, "Lower limit of the Omega invariant mass"}; Configurable confOmegaInvMassUpLimit{"confOmegaInvMassUpLimit", 1.80, "Upper limit of the Omega invariant mass"}; - - // Configurable confCascRejectCompetingMass{"confCascRejectCompetingMass", false, "Switch on to reject Omegas (for Xi) or Xis (for Omegas)"}; - // Configurable confCascInvCompetingMassLowLimit{"confCascInvCompetingMassLowLimit", 1.66, "Lower limit of the cascade invariant mass for competing mass rejection"}; - // Configurable confCascInvCompetingMassUpLimit{"confCascInvCompetingMassUpLimit", 1.68, "Upper limit of the cascade invariant mass for competing mass rejection"}; } ConfCascadeSelection; // PHI @@ -321,6 +327,15 @@ struct FemtoUniverseProducerTask { Configurable> classMlD0D0bar{"classMlD0D0bar", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; } ConfD0Selection; + // PID bitmask configurables + struct : o2::framework::ConfigurableGroup { + Configurable confMinMomTOF{"confMinMomTOF", 0.75, "momentum threshold for particle identification using TOF"}; + Configurable confNsigmaTPCParticleChild{"confNsigmaTPCParticleChild", 3.0, "TPC Sigma for particle (daugh & bach) momentum < Confmom"}; + Configurable confNsigmaTOFParticleChild{"confNsigmaTOFParticleChild", 3.0, "TOF Sigma for particle (daugh & bach) momentum > Confmom"}; + Configurable confNsigmaTPCParticle{"confNsigmaTPCParticle", 3.0, "TPC Sigma for particle (track) momentum < Confmom"}; + Configurable confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle (track) momentum > Confmom"}; + } ConfPIDBitmask; + HfHelper hfHelper; bool isKaonNSigma(float mom, float nsigmaTPCK, float nsigmaTOFK) { @@ -407,6 +422,65 @@ struct FemtoUniverseProducerTask { } } + bool isNSigmaTPC(float nsigmaTPCParticle) + { + return (std::abs(nsigmaTPCParticle) < ConfPIDBitmask.confNsigmaTPCParticleChild); + } + + bool isNSigmaTOF(float mom, float nsigmaTOFParticle, bool hasTOF) + { + // Cut only on daughter and bachelor tracks, that have TOF signal + if (mom > ConfPIDBitmask.confMinMomTOF && hasTOF) { + return (std::abs(nsigmaTOFParticle) < ConfPIDBitmask.confNsigmaTOFParticleChild); + } else { + return true; + } + } + + bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle) + { + if (mom <= ConfPIDBitmask.confMinMomTOF) { + return (std::abs(nsigmaTPCParticle) < ConfPIDBitmask.confNsigmaTPCParticle); + } else { + return (TMath::Hypot(nsigmaTOFParticle, nsigmaTPCParticle) < ConfPIDBitmask.confNsigmaCombinedParticle); + } + } + + template + aod::femtouniverseparticle::CutContainerType PIDBitmask(const TrackType& track) + { + static const o2::track::PID pids[] = {o2::track::PID::Proton, o2::track::PID::Pion, o2::track::PID::Kaon}; + aod::femtouniverseparticle::CutContainerType mask = 0u; + for (UInt_t i = 0; i < 3; ++i) { + if (isNSigmaTPC(trackCuts.getNsigmaTPC(track, pids[i]))) + mask |= (1u << i); + if (isNSigmaTOF(track.p(), trackCuts.getNsigmaTOF(track, pids[i]), track.hasTOF())) + mask |= (8u << i); + if (isNSigmaCombined(track.p(), trackCuts.getNsigmaTPC(track, pids[i]), trackCuts.getNsigmaTOF(track, pids[i]))) + mask |= (64u << i); + } + if (track.hasTOF()) + mask |= (512u); + return mask; + } + + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + int mRunNumberZorro = 0; + + HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; + HistogramRegistry cascadeQaRegistry{"CascadeQAHistos", {}, OutputObjHandlingPolicy::QAObject}; + + void initZorro(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumberZorro == bc.runNumber()) + return; + + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), zorroMask.value); + zorro.populateHistRegistry(qaRegistry, bc.runNumber()); + mRunNumberZorro = bc.runNumber(); + } + /// \todo should we add filter on min value pT/eta of V0 and daughters? /*Filter v0Filter = (nabs(aod::v0data::x) < V0DecVtxMax.value) && (nabs(aod::v0data::y) < V0DecVtxMax.value) && @@ -414,9 +488,6 @@ struct FemtoUniverseProducerTask { // (aod::v0data::v0radius > V0TranRadV0Min.value); to be added, not working // for now do not know why - HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::QAObject}; - HistogramRegistry cascadeQaRegistry{"CascadeQAHistos", {}, OutputObjHandlingPolicy::QAObject}; - int mRunNumber = 0; float mMagField; Service ccdb; /// Accessing the CCDB @@ -424,16 +495,18 @@ struct FemtoUniverseProducerTask { void init(InitContext&) { - if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == false && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTrackD0MC || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3 || doprocessTruthAndFullMCCentRun3V0) == false) { + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackV0Cascade || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == false && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTrackD0MC || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3 || doprocessTruthAndFullMCCentRun3V0) == false) { LOGF(fatal, "Neither processFullData nor processFullMC enabled. Please choose one."); } - if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == true && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTrackD0MC || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3 || doprocessTruthAndFullMCCentRun3V0) == true) { + if ((doprocessFullData || doprocessTrackPhiData || doprocessTrackData || doprocessTrackV0 || doprocessTrackCascadeData || doprocessTrackV0Cascade || doprocessTrackD0mesonData || doprocessTrackD0DataML || doprocessTrackCentRun2Data || doprocessTrackV0CentRun2Data || doprocessTrackCentRun3Data || doprocessV0CentRun3Data || doprocessCascadeCentRun3Data || doprocessTrackDataCentPP) == true && (doprocessFullMC || doprocessTrackMC || doprocessTrackMCTruth || doprocessTrackMCGen || doprocessTruthAndFullMCV0 || doprocessTrackD0MC || doprocessTruthAndFullMCCasc || doprocessFullMCCent || doprocessTrackCentRun3DataMC || doprocessTruthAndFullMCCentRun3 || doprocessTruthAndFullMCCentRun3V0) == true) { LOGF(fatal, "Cannot enable process Data and process MC at the same time. " "Please choose one."); } - colCuts.setCuts(confEvtZvtx, confEvtTriggerCheck, confEvtTriggerSel, confEvtOfflineCheck, confIsRun3, confCentFT0Min, confCentFT0Max); + zorroSummary.setObject(zorro.getZorroSummary()); + + colCuts.setCuts(ConfGeneral.confEvtZvtx, ConfGeneral.confEvtTriggerCheck, ConfGeneral.confEvtTriggerSel, ConfGeneral.confEvtOfflineCheck, confIsRun3, ConfGeneral.confCentFT0Min, ConfGeneral.confCentFT0Max); colCuts.init(&qaRegistry); trackCuts.setSelection(ConfTrkSelection.confTrkCharge, femto_universe_track_selection::kSign, femto_universe_selection::kEqual); @@ -458,7 +531,7 @@ struct FemtoUniverseProducerTask { /// different type! // v0Cuts.setSelection(ConfV0Selection->getRow(0), // femto_universe_v0_selection::kDecVtxMax, femto_universe_selection::kAbsUpperLimit); - if (confIsActivateV0) { + if (ConfGeneral.confIsActivateV0) { // initializing for V0 v0Cuts.setSelection(ConfV0Selection.confV0Sign, femto_universe_v0_selection::kV0Sign, femto_universe_selection::kEqual); v0Cuts.setSelection(ConfV0Selection.confV0PtMin, femto_universe_v0_selection::kV0pTMin, femto_universe_selection::kLowerLimit); @@ -501,7 +574,7 @@ struct FemtoUniverseProducerTask { // } } - if (confIsActivateCascade) { + if (ConfGeneral.confIsActivateCascade) { // initializing for cascades cascadeCuts.setSelection(ConfCascadeSelection.confCascSign, femto_universe_cascade_selection::kCascadeSign, femto_universe_selection::kEqual); cascadeCuts.setSelection(ConfCascadeSelection.confCascPtMin, femto_universe_cascade_selection::kCascadepTMin, femto_universe_selection::kLowerLimit); @@ -548,13 +621,9 @@ struct FemtoUniverseProducerTask { cascadeCuts.init(&cascadeQaRegistry); // invmass cuts cascadeCuts.setInvMassLimits(ConfCascadeSelection.confXiInvMassLowLimit, ConfCascadeSelection.confOmegaInvMassLowLimit, ConfCascadeSelection.confXiInvMassUpLimit, ConfCascadeSelection.confOmegaInvMassUpLimit); - - /*if (ConfCascadeSelection.confCascRejectCompetingMass) { - cascadeCuts.setCompetingInvMassLimits(ConfCascadeSelection.confCascInvCompetingMassLowLimit, ConfCascadeSelection.confCascInvCompetingMassUpLimit); - }*/ } - if (confIsActivatePhi) { + if (ConfGeneral.confIsActivatePhi) { // initializing for Phi meson phiCuts.init(&qaRegistry); } @@ -786,7 +855,7 @@ struct FemtoUniverseProducerTask { template void fillMCParticleD0(ParticleType const& hfCand) { - if (std::abs(hfCand.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(hfCand.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // get corresponding MC particle and its info int pdgCode = 0; int hfCandOrigin = 99; @@ -835,7 +904,7 @@ struct FemtoUniverseProducerTask { /// FemtoUniverseRun2 is defined V0M/2 multNtr = col.multTracklets(); } - if (confEvtUseTPCmult) { + if (ConfGeneral.confEvtUseTPCmult) { multNtr = col.multTPC(); } @@ -847,11 +916,19 @@ struct FemtoUniverseProducerTask { if (!colCuts.isSelected(col)) { return false; } - if (!confIsUsePileUp) { + + if (zorroMask.value != "") { + auto bc = col.template bc_as(); + initZorro(bc); + if (!zorro.isSelected(col.template bc_as().globalBC())) + return false; + } + + if (!ConfGeneral.confIsUsePileUp) { outputCollision(vtxZ, mult, multNtr, confDoSpher ? colCuts.computeSphericity(col, tracks) : 2, mMagField); colCuts.fillQA(col); return true; - } else if ((!confEvNoSameBunchPileup || col.selection_bit(aod::evsel::kNoSameBunchPileup)) && (!confEvIsGoodZvtxFT0vsPV || col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && (!confEvIsVertexITSTPC || col.selection_bit(aod::evsel::kIsVertexITSTPC))) { + } else if ((!ConfGeneral.confEvNoSameBunchPileup || col.selection_bit(aod::evsel::kNoSameBunchPileup)) && (!ConfGeneral.confEvIsGoodZvtxFT0vsPV || col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && (!ConfGeneral.confEvIsVertexITSTPC || col.selection_bit(aod::evsel::kIsVertexITSTPC))) { outputCollision(vtxZ, mult, multNtr, confDoSpher ? colCuts.computeSphericity(col, tracks) : 2, mMagField); colCuts.fillQA(col); return true; @@ -874,7 +951,7 @@ struct FemtoUniverseProducerTask { /// FemtoUniverseRun2 is defined V0M/2 multNtr = col.multTracklets(); } - if (confEvtUseTPCmult) { + if (ConfGeneral.confEvtUseTPCmult) { multNtr = col.multTPC(); } @@ -886,11 +963,11 @@ struct FemtoUniverseProducerTask { if (!colCuts.isSelected(col)) { return false; } - if (!confIsUsePileUp) { + if (!ConfGeneral.confIsUsePileUp) { outputCollision(vtxZ, mult, multNtr, confDoSpher ? colCuts.computeSphericity(col, tracks) : 2, mMagField); colCuts.fillQA(col); return true; - } else if ((!confEvNoSameBunchPileup || col.selection_bit(aod::evsel::kNoSameBunchPileup)) && (!confEvIsGoodZvtxFT0vsPV || col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && (!confEvIsVertexITSTPC || col.selection_bit(aod::evsel::kIsVertexITSTPC))) { + } else if ((!ConfGeneral.confEvNoSameBunchPileup || col.selection_bit(aod::evsel::kNoSameBunchPileup)) && (!ConfGeneral.confEvIsGoodZvtxFT0vsPV || col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && (!ConfGeneral.confEvIsVertexITSTPC || col.selection_bit(aod::evsel::kIsVertexITSTPC))) { outputCollision(vtxZ, mult, multNtr, confDoSpher ? colCuts.computeSphericity(col, tracks) : 2, mMagField); colCuts.fillQA(col); return true; @@ -907,7 +984,7 @@ struct FemtoUniverseProducerTask { float mult = confIsRun3 ? c.multFV0M() : 0.5 * (c.multFV0M()); int multNtr = confIsRun3 ? c.multNTracksPV() : c.multTracklets(); - if (std::abs(vtxZ) > confEvtZvtx) { + if (std::abs(vtxZ) > ConfGeneral.confEvtZvtx) { continue; } @@ -953,7 +1030,7 @@ struct FemtoUniverseProducerTask { // in case of trigger run - store such collisions but don't store any // particle candidates for such collisions - if (!colCuts.isSelectedRun3(col) || (occupancy < confTPCOccupancyMin || occupancy > confTPCOccupancyMax)) { + if (!colCuts.isSelectedRun3(col) || (occupancy < ConfGeneral.confTPCOccupancyMin || occupancy > ConfGeneral.confTPCOccupancyMax)) { return false; } else { if (col.selection_bit(aod::evsel::kNoSameBunchPileup) && @@ -975,7 +1052,7 @@ struct FemtoUniverseProducerTask { { const auto vtxZ = col.posZ(); - if (std::abs(vtxZ) > confEvtZvtx) { + if (std::abs(vtxZ) > ConfGeneral.confEvtZvtx) { return false; } else { outputCollision(vtxZ, 0, 0, 2, mMagField); @@ -1015,24 +1092,16 @@ struct FemtoUniverseProducerTask { auto cutContainer = trackCuts.getCutContainer(track); // now the table is filled - if (!confIsActivateCascade) { - outputParts(outputCollision.lastIndex(), track.pt(), track.eta(), - track.phi(), aod::femtouniverseparticle::ParticleType::kTrack, - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kCuts), - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kPID), - track.dcaXY(), childIDs, 0, - track.sign()); // sign getter is mAntiLambda() - } else { - outputCascParts(outputCollision.lastIndex(), track.pt(), track.eta(), - track.phi(), aod::femtouniverseparticle::ParticleType::kTrack, - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kCuts), - cutContainer.at( - femto_universe_track_selection::TrackContainerPosition::kPID), - track.dcaXY(), childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } + outputParts(outputCollision.lastIndex(), track.pt(), track.eta(), + track.phi(), aod::femtouniverseparticle::ParticleType::kTrack, + cutContainer.at( + femto_universe_track_selection::TrackContainerPosition::kCuts), + confIsUseCutculator ? cutContainer.at( + femto_universe_track_selection::TrackContainerPosition::kPID) + : PIDBitmask(track), + track.dcaXY(), childIDs, 0, + track.sign()); // sign getter is mAntiLambda() + tmpIDtrack.push_back(track.globalIndex()); if (confIsDebug) { fillDebugParticle(track); @@ -1083,11 +1152,11 @@ struct FemtoUniverseProducerTask { v0.positiveeta(), v0.positivephi(), aod::femtouniverseparticle::ParticleType::kV0Child, cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosCuts), - cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosPID), + confIsUseCutculator ? cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosPID) : PIDBitmask(postrack), 0., childIDs, 0, - 0); + postrack.sign()); const int rowOfPosTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(postrack, o2::aod::femtouniverseparticle::ParticleType::kV0Child); @@ -1103,11 +1172,11 @@ struct FemtoUniverseProducerTask { v0.negativephi(), aod::femtouniverseparticle::ParticleType::kV0Child, cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), - cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), + confIsUseCutculator ? cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID) : PIDBitmask(negtrack), 0., childIDs, 0, - 0); + negtrack.sign()); const int rowOfNegTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(negtrack, o2::aod::femtouniverseparticle::ParticleType::kV0Child); @@ -1160,28 +1229,18 @@ struct FemtoUniverseProducerTask { childIDs[1] = 0; // neg childIDs[2] = 0; // bachelor float hasTOF = posTrackCasc.hasTOF() ? 1 : 0; - outputCascParts(outputCollision.lastIndex(), - casc.positivept(), - casc.positiveeta(), - casc.positivephi(), - aod::femtouniverseparticle::ParticleType::kV0Child, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosCuts), - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosPID), - hasTOF, - childIDs, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - const int rowOfPosTrack = outputCascParts.lastIndex(); + outputParts(outputCollision.lastIndex(), + casc.positivept(), + casc.positiveeta(), + casc.positivephi(), + aod::femtouniverseparticle::ParticleType::kV0Child, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosCuts), + PIDBitmask(posTrackCasc), // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kPosPID), + hasTOF, + childIDs, + 0, + posTrackCasc.sign()); + const int rowOfPosTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(posTrackCasc, o2::aod::femtouniverseparticle::ParticleType::kV0Child); } @@ -1192,28 +1251,18 @@ struct FemtoUniverseProducerTask { childIDs[1] = rowInPrimaryTrackTableNeg; // neg childIDs[2] = 0; // bachelor hasTOF = negTrackCasc.hasTOF() ? 1 : 0; - outputCascParts(outputCollision.lastIndex(), - casc.negativept(), - casc.negativeeta(), - casc.negativephi(), - aod::femtouniverseparticle::ParticleType::kV0Child, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), - hasTOF, - childIDs, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - const int rowOfNegTrack = outputCascParts.lastIndex(); + outputParts(outputCollision.lastIndex(), + casc.negativept(), + casc.negativeeta(), + casc.negativephi(), + aod::femtouniverseparticle::ParticleType::kV0Child, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), + PIDBitmask(negTrackCasc), // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), + hasTOF, + childIDs, + 0, + negTrackCasc.sign()); + const int rowOfNegTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(negTrackCasc, o2::aod::femtouniverseparticle::ParticleType::kV0Child); } @@ -1225,44 +1274,36 @@ struct FemtoUniverseProducerTask { childIDs[1] = 0; // neg childIDs[2] = rowInPrimaryTrackTableBach; // bachelor hasTOF = bachTrackCasc.hasTOF() ? 1 : 0; - outputCascParts(outputCollision.lastIndex(), - casc.bachelorpt(), - casc.bacheloreta(), - casc.bachelorphi(), - aod::femtouniverseparticle::ParticleType::kCascadeBachelor, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), - hasTOF, - childIDs, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0); - const int rowOfBachTrack = outputCascParts.lastIndex(); + outputParts(outputCollision.lastIndex(), + casc.bachelorpt(), + casc.bacheloreta(), + casc.bachelorphi(), + aod::femtouniverseparticle::ParticleType::kCascadeBachelor, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegCuts), + PIDBitmask(bachTrackCasc), // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kNegPID), + hasTOF, + childIDs, + 0, + bachTrackCasc.sign()); + const int rowOfBachTrack = outputParts.lastIndex(); if constexpr (isMC) { fillMCParticle(bachTrackCasc, o2::aod::femtouniverseparticle::ParticleType::kCascadeBachelor); } // cascade std::vector indexCascChildID = {rowOfPosTrack, rowOfNegTrack, rowOfBachTrack}; + outputParts(outputCollision.lastIndex(), + casc.pt(), + casc.eta(), + casc.phi(), + aod::femtouniverseparticle::ParticleType::kCascade, + 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kV0), + 0, + 0, + indexCascChildID, + casc.mXi(), + casc.mOmega()); outputCascParts(outputCollision.lastIndex(), - casc.pt(), - casc.eta(), - casc.phi(), - aod::femtouniverseparticle::ParticleType::kCascade, - 0, // cutContainerV0.at(femto_universe_v0_selection::V0ContainerPosition::kV0), - 0, - 0, - indexCascChildID, - casc.mXi(), - casc.mOmega(), + outputParts.lastIndex(), casc.dcaV0daughters(), casc.v0cosPA(col.posX(), col.posY(), col.posZ()), casc.v0radius(), @@ -1690,15 +1731,15 @@ struct FemtoUniverseProducerTask { uint32_t pdgCode = static_cast(particle.pdgCode()); - if (confMCTruthAnalysisWithPID) { + if (ConfGeneral.confMCTruthAnalysisWithPID) { bool pass = false; - std::vector tmpPDGCodes = confMCTruthPDGCodes; // necessary due to some features of the Configurable + std::vector tmpPDGCodes = ConfGeneral.confMCTruthPDGCodes; // necessary due to some features of the Configurable for (auto const& pdg : tmpPDGCodes) { if (static_cast(pdg) == static_cast(pdgCode)) { if (pdgCode == 333) { // && (recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) { // ATTENTION: all Phi mesons are NOT primary particles pass = true; } else { - if (confStoreMCmothers || particle.isPhysicalPrimary() || (confActivateSecondaries && recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) + if (confStoreMCmothers || particle.isPhysicalPrimary() || (ConfGeneral.confActivateSecondaries && recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) pass = true; } } @@ -1725,30 +1766,21 @@ struct FemtoUniverseProducerTask { tmpIDtrack.push_back(particle.globalIndex()); continue; } - if (!confIsActivateCascade) { - outputParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - pdgCode, - variablePDG, - childIDs, - 0, - 0); - } else { + + if (ConfGeneral.confIsActivateCascade) childIDs.push_back(0); - outputCascParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - pdgCode, - pdgCode, - childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + pdgCode, + variablePDG, + childIDs, + 0, + 0); + if (confIsDebug) { fillDebugParticle(particle); } @@ -1764,7 +1796,7 @@ struct FemtoUniverseProducerTask { childIDs[0] = 0; childIDs[1] = 0; auto minDaughs = 2ul; - if (confIsActivateCascade) { + if (ConfGeneral.confIsActivateCascade) { childIDs.push_back(0); minDaughs = 3ul; } @@ -1782,29 +1814,18 @@ struct FemtoUniverseProducerTask { int32_t variablePDG = confStoreMCmothers ? getMotherPDG(particle) : particle.pdgCode(); - if (!confIsActivateCascade) { - outputParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - static_cast(particle.pdgCode()), - variablePDG, - childIDs, - 0, - 0); - } else { - outputCascParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - static_cast(particle.pdgCode()), - particle.pdgCode(), - childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - } + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + static_cast(particle.pdgCode()), + variablePDG, + childIDs, + 0, + 0); + if (confIsDebug) { fillDebugParticle(particle); } @@ -1836,9 +1857,9 @@ struct FemtoUniverseProducerTask { uint32_t pdgCode = static_cast(particle.pdgCode()); - if (confMCTruthAnalysisWithPID) { + if (ConfGeneral.confMCTruthAnalysisWithPID) { bool pass = false; - std::vector tmpPDGCodes = confMCTruthPDGCodes; // necessary due to some features of the Configurable + std::vector tmpPDGCodes = ConfGeneral.confMCTruthPDGCodes; // necessary due to some features of the Configurable for (auto const& pdg : tmpPDGCodes) { if (static_cast(pdg) == static_cast(pdgCode)) { if (pdgCode == 333) { // && (recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) { // ATTENTION: all Phi mesons are NOT primary particles @@ -1846,7 +1867,7 @@ struct FemtoUniverseProducerTask { } else if (pdgCode == 421) { pass = true; } else { - if (particle.isPhysicalPrimary() || (confActivateSecondaries && recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) + if (particle.isPhysicalPrimary() || (ConfGeneral.confActivateSecondaries && recoMcIds && recoMcIds->get().contains(particle.globalIndex()))) pass = true; } } @@ -1860,11 +1881,11 @@ struct FemtoUniverseProducerTask { tmpIDtrack.push_back(particle.globalIndex()); continue; } - if (confIsActiveD0) { + if (ConfGeneral.confIsActiveD0) { auto mcD0origin = aod::femtouniverseparticle::ParticleType::kMCTruthTrack; float ptGenB = -1; - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { if (ConfD0Selection.yD0D0barCandGenMax >= 0. && std::abs(RecoDecay::y(particle.pVector(), o2::constants::physics::MassD0)) > ConfD0Selection.yD0D0barCandGenMax) { continue; } @@ -1890,15 +1911,15 @@ struct FemtoUniverseProducerTask { ptGenB); // pT of the B hadron (mother particle, only when non-prompt D0) } } else { - outputCascParts(outputCollision.lastIndex(), - particle.pt(), - particle.eta(), - particle.phi(), - aod::femtouniverseparticle::ParticleType::kMCTruthTrack, - 0, - pdgCode, - pdgCode, - childIDs, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + outputParts(outputCollision.lastIndex(), + particle.pt(), + particle.eta(), + particle.phi(), + aod::femtouniverseparticle::ParticleType::kMCTruthTrack, + 0, + pdgCode, + pdgCode, + childIDs, 0, 0); } if (confIsDebug) { fillDebugParticle(particle); @@ -1957,16 +1978,13 @@ struct FemtoUniverseProducerTask { const auto colcheck = fillCollisions(col, tracks); if (colcheck) { fillTracks(tracks); - if (confIsActivateV0) { + if (ConfGeneral.confIsActivateV0) { fillV0(col, fullV0s, tracks); } - if (confIsActivatePhi) { + if (ConfGeneral.confIsActivatePhi) { fillPhi(col, tracks); } } - // if (confIsActivateCascade) { - // fillCascade(col, fullCascades, tracks); - // } } void processFullData(aod::FemtoFullCollision const& col, @@ -2009,6 +2027,26 @@ struct FemtoUniverseProducerTask { } PROCESS_SWITCH(FemtoUniverseProducerTask, processTrackCascadeData, "Provide experimental data for track cascades", false); + void processTrackV0Cascade(aod::FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + soa::Filtered const& tracks, + o2::aod::V0Datas const& fullV0s, + o2::aod::CascDatas const& fullCascades) + { + getMagneticFieldTesla(col.bc_as()); + const auto colcheck = fillCollisions(col, tracks); + if (colcheck) { + fillTracks(tracks); + if (ConfGeneral.confIsActivateV0) { + fillV0(col, fullV0s, tracks); + } + if (ConfGeneral.confIsActivateCascade) { + fillCascade(col, fullCascades, tracks); + } + } + } + PROCESS_SWITCH(FemtoUniverseProducerTask, processTrackV0Cascade, "Provide experimental data for track, v0 and cascades", false); + /*void processTrackV0CentRun3(aod::FemtoFullCollisionCentRun3 const& col, aod::BCsWithTimestamps const&, soa::Filtered const& tracks, @@ -2336,6 +2374,47 @@ struct FemtoUniverseProducerTask { } PROCESS_SWITCH(FemtoUniverseProducerTask, processTruthAndFullMCCasc, "Provide both MC truth and reco for tracks and Cascades", false); + void processTruthAndFullMCCentRun3Casc( + aod::McCollisions const& mccols, + aod::McParticles const& mcParticles, + aod::FemtoFullCollisionCentRun3MCs const& collisions, + soa::Filtered> const& tracks, + soa::Join const& fullCascades, + aod::BCsWithTimestamps const&) + { + + // recos + std::set recoMcIds; + for (const auto& col : collisions) { + auto groupedTracks = tracks.sliceBy(perCollisionTracks, col.globalIndex()); + auto groupedCascParts = fullCascades.sliceBy(perCollisionCascs, col.globalIndex()); + getMagneticFieldTesla(col.bc_as()); + const auto colcheck = fillCollisionsCentRun3(col); + if (colcheck) { + fillTracks(groupedTracks); + fillCascade(col, groupedCascParts, groupedTracks); + } + for (const auto& track : groupedTracks) { + if (trackCuts.isSelectedMinimal(track)) + recoMcIds.insert(track.mcParticleId()); + } + } + + // truth + for (const auto& mccol : mccols) { + auto groupedCollisions = collisions.sliceBy(recoCollsPerMCCollCentPbPb, mccol.globalIndex()); + for (const auto& col : groupedCollisions) { + const auto colcheck = fillMCTruthCollisionsCentRun3(col); // fills the reco collisions for mc collision + if (colcheck) { + auto groupedMCParticles = mcParticles.sliceBy(perMCCollision, mccol.globalIndex()); + outputCollExtra(1.0, 1.0); + fillParticles(groupedMCParticles, recoMcIds); // fills mc particles + } + } + } + } + PROCESS_SWITCH(FemtoUniverseProducerTask, processTruthAndFullMCCentRun3Casc, "Provide both MC truth and reco for tracks and cascades with centrality", false); + Preslice> perCollisionD0s = aod::track::collisionId; void processTrackD0MC(aod::McCollisions const& mccols, aod::TracksWMc const&, diff --git a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt index 0a4682a7f7a..346188d08fd 100644 --- a/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt +++ b/PWGCF/FemtoUniverse/Tasks/CMakeLists.txt @@ -34,6 +34,11 @@ o2physics_add_dpl_workflow(femtouniverse-pair-track-nucleus PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtouniverse-pair-track-v0-helicity + SOURCES femtoUniversePairTaskTrackV0Helicity.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtouniverse-pair-track-track-threedrelmom-mult-kt-extended SOURCES femtoUniversePairTaskTrackTrack3DMultKtExtended.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -59,6 +64,11 @@ o2physics_add_dpl_workflow(femtouniverse-pair-track-cascade-extended PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(femtouniverse-pair-v0-cascade-extended + SOURCES femtoUniversePairTaskV0CascadeExtended.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(femtouniverse-pair-track-d0 SOURCES femtoUniversePairTaskTrackD0.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore @@ -97,4 +107,4 @@ o2physics_add_dpl_workflow(femtouniverse-efficiency-base o2physics_add_executable(femtouniverse-cutculator SOURCES femtoUniverseCutCulator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx index d35aa3fa779..f82657be1d9 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseDebugV0.cxx @@ -13,25 +13,30 @@ /// \brief Tasks that reads the particle tables and fills QA histograms for V0s /// \author Luca Barioglio, TU München, luca.barioglio@cern.ch /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch +/// \author Anna-Mariia Andrushko, WUT Warsaw, anna-mariia.andrushko@cern.ch -#include -#include -#include -#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Common/DataModel/PIDResponse.h" + +#include "DataFormatsParameters/GRPObject.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 "DataFormatsParameters/GRPObject.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include + +#include +#include using namespace o2; using namespace o2::analysis::femto_universe; @@ -45,51 +50,70 @@ struct FemtoUniverseDebugV0 { SliceCache cache; - Configurable confPDGCodeV0{"confPDGCodeV0", 3122, "V0 -- PDG code"}; - Configurable confPDGCodePositiveChild{"confPDGCodePositiveChild", 2212, "Positive Child -- PDG code"}; - Configurable confPDGCodeNegativeChild{"confPDGCodeNegativeChild", 211, "Negative Child -- PDG code"}; - Configurable confCutV0{"confCutV0", 338, "V0 -- Selection bit from cutCulator"}; - ConfigurableAxis confV0TempFitVarBins{"confV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis confV0TempFitVarpTBins{"confV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; - - Configurable confCutPositiveChild{"confCutPositiveChild", 150, "Positive Child of V0 -- Selection bit from cutCulator"}; - Configurable confCutNegativeChild{"confCutNegativeChild", 149, "Negative Child of V0 -- Selection bit from cutCulator"}; - Configurable confPositiveChildPIDnSigmaMax{"confPositiveChildPIDnSigmaMax", 3.f, "Positive Child of V0 -- Selection bit from cutCulator"}; - Configurable confNegativeChildPIDnSigmaMax{"confNegativeChildPIDnSigmaMax", 3.f, "Negative Child of V0 -- Selection bit from cutCulator"}; - Configurable confPositiveChildIndex{"confPositiveChildIndex", 1, "Positive Child of V0 -- Index from cutCulator"}; - Configurable confNegativeChildIndex{"confNegativeChildIndex", 0, "Negative Child of V0 -- Index from cutCulator"}; - Configurable> confChildPIDnSigmaMax{"confChildPIDnSigmaMax", std::vector{4.f, 3.f}, "V0 child selection: max. PID nSigma TPC"}; - Configurable confChildnSpecies{"confChildnSpecies", 2, "Number of particle spieces (for V0 children) with PID info"}; - ConfigurableAxis confChildTempFitVarBins{"confChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; - ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; - + /// V0 configurables + struct : o2::framework::ConfigurableGroup { + Configurable confPDGCodeV0{"confPDGCodeV0", 3122, "V0 -- PDG code"}; + Configurable confPDGCodePositiveChild{"confPDGCodePositiveChild", 2212, "Positive Child -- PDG code"}; + Configurable confPDGCodeNegativeChild{"confPDGCodeNegativeChild", 211, "Negative Child -- PDG code"}; + Configurable confCutV0{"confCutV0", 338, "V0 -- Selection bit from cutCulator"}; + ConfigurableAxis confV0TempFitVarBins{"confV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confV0TempFitVarpTBins{"confV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + } V0configs; // o2-linter: disable=name/function-variable + + /// Children configurables + struct : o2::framework::ConfigurableGroup { + Configurable confCutPositiveChild{"confCutPositiveChild", 150, "Positive Child of V0 -- Selection bit from cutCulator"}; + Configurable confCutNegativeChild{"confCutNegativeChild", 149, "Negative Child of V0 -- Selection bit from cutCulator"}; + Configurable confPositiveChildPIDnSigmaMax{"confPositiveChildPIDnSigmaMax", 3.f, "Positive Child of V0 -- Selection bit from cutCulator"}; + Configurable confNegativeChildPIDnSigmaMax{"confNegativeChildPIDnSigmaMax", 3.f, "Negative Child of V0 -- Selection bit from cutCulator"}; + Configurable confPositiveChildIndex{"confPositiveChildIndex", 1, "Positive Child of V0 -- Index from cutCulator"}; + Configurable confNegativeChildIndex{"confNegativeChildIndex", 0, "Negative Child of V0 -- Index from cutCulator"}; + Configurable> confChildPIDnSigmaMax{"confChildPIDnSigmaMax", std::vector{4.f, 3.f}, "V0 child selection: max. PID nSigma TPC"}; + Configurable confChildnSpecies{"confChildnSpecies", 2, "Number of particle spieces (for V0 children) with PID info"}; + ConfigurableAxis confChildTempFitVarBins{"confChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; + } childconfigs; + + Configurable confIsMC{"confIsMC", false, "Enable additional histograms in the case of a Monte Carlo run"}; + + /// Partitioning using FemtoFullParticles = soa::Join; - Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && ((aod::femtouniverseparticle::cut & confCutV0) == confCutV0); + + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && ((aod::femtouniverseparticle::cut & V0configs.confCutV0) == V0configs.confCutV0); + + Partition> partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && ((aod::femtouniverseparticle::cut & V0configs.confCutV0) == V0configs.confCutV0); + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; /// Histogramming FemtoUniverseEventHisto eventHisto; FemtoUniverseParticleHisto positiveChildHistos; FemtoUniverseParticleHisto negativeChildHistos; - FemtoUniverseParticleHisto V0Histos; + FemtoUniverseParticleHisto V0Histos; // o2-linter: disable=name/function-variable /// Histogram output - HistogramRegistry EventRegistry{"Event", {}, OutputObjHandlingPolicy::AnalysisObject}; - HistogramRegistry V0Registry{"FullV0QA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry eventRegistry{"Event", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry V0Registry{"FullV0QA", {}, OutputObjHandlingPolicy::AnalysisObject}; // o2-linter: disable=name/function-variable HistogramRegistry thetaRegistry{"ThetaQA", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { - eventHisto.init(&EventRegistry); - positiveChildHistos.init(&V0Registry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, confPDGCodePositiveChild.value, true); - negativeChildHistos.init(&V0Registry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, confPDGCodeNegativeChild, true); - V0Histos.init(&V0Registry, confV0TempFitVarpTBins, confV0TempFitVarBins, false, confPDGCodeV0.value, true); - - thetaRegistry.add("Theta/hTheta", " ; p (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {50, -5, 5}}); + eventHisto.init(&eventRegistry); + positiveChildHistos.init(&V0Registry, childconfigs.confChildTempFitVarpTBins, childconfigs.confChildTempFitVarBins, confIsMC, V0configs.confPDGCodePositiveChild.value, true); + negativeChildHistos.init(&V0Registry, childconfigs.confChildTempFitVarpTBins, childconfigs.confChildTempFitVarBins, confIsMC, V0configs.confPDGCodeNegativeChild.value, true); + V0Histos.init(&V0Registry, V0configs.confV0TempFitVarpTBins, V0configs.confV0TempFitVarBins, confIsMC, V0configs.confPDGCodeV0.value, true); + + thetaRegistry.add("Theta/hTheta", " ; p (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); + thetaRegistry.add("Theta/PositiveChild/hThetaPt", " ; p_{T} (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); + thetaRegistry.add("Theta/PositiveChild/hThetaEta", " ; #eta; cos(#theta)", kTH2F, {{100, -1, 1}, {110, -1.1, 1.1}}); + thetaRegistry.add("Theta/PositiveChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); + 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}}); } - /// Produce QA plots for V0 selection in FemtoUniverse framework - void process(o2::aod::FdCollision const& col, FemtoFullParticles const& parts) + /// Produce QA plots for V0 and its children on real data + void processData(o2::aod::FdCollision const& col, FemtoFullParticles const& parts) { auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); eventHisto.fillQA(col); @@ -107,20 +131,70 @@ struct FemtoUniverseDebugV0 { // Check cuts on V0 children if (positiveChild.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kV0Child) && negativeChild.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kV0Child) && - isFullPIDSelected(positiveChild.pidCut(), positiveChild.p(), 999.f, confPositiveChildIndex.value, confChildnSpecies.value, confChildPIDnSigmaMax.value, confPositiveChildPIDnSigmaMax.value, 1.f) && - isFullPIDSelected(negativeChild.pidCut(), negativeChild.p(), 999.f, confNegativeChildIndex.value, confChildnSpecies.value, confChildPIDnSigmaMax.value, confNegativeChildPIDnSigmaMax.value, 1.f)) { - auto positiveChildMass = pdg->Mass(confPDGCodePositiveChild); - auto negativeChildMass = pdg->Mass(confPDGCodeNegativeChild); + isFullPIDSelected(positiveChild.pidCut(), positiveChild.p(), 999.f, childconfigs.confPositiveChildIndex.value, childconfigs.confChildnSpecies.value, childconfigs.confChildPIDnSigmaMax.value, childconfigs.confPositiveChildPIDnSigmaMax.value, 1.f) && + isFullPIDSelected(negativeChild.pidCut(), negativeChild.p(), 999.f, childconfigs.confNegativeChildIndex.value, childconfigs.confChildnSpecies.value, childconfigs.confChildPIDnSigmaMax.value, childconfigs.confNegativeChildPIDnSigmaMax.value, 1.f)) { + auto positiveChildMass = pdg->Mass(V0configs.confPDGCodePositiveChild); + auto negativeChildMass = pdg->Mass(V0configs.confPDGCodeNegativeChild); + auto positiveChildBoosted = FemtoUniverseMath::boostPRF(positiveChild, positiveChildMass, negativeChild, negativeChildMass); + auto cosineTheta = (positiveChildBoosted.Px() * part.px() + positiveChildBoosted.Py() * part.py() + positiveChildBoosted.Pz() * part.pz()) / (positiveChildBoosted.P() * part.p()); + + V0Histos.fillQA(part); + positiveChildHistos.fillQA(positiveChild); + negativeChildHistos.fillQA(negativeChild); + + thetaRegistry.fill(HIST("Theta/hTheta"), part.p(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaPt"), positiveChild.pt(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaEta"), positiveChild.eta(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaPhi"), positiveChild.phi(), cosineTheta); + thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPt"), negativeChild.pt(), cosineTheta); + thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaEta"), negativeChild.eta(), cosineTheta); + thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPhi"), negativeChild.phi(), cosineTheta); + } + } + } + PROCESS_SWITCH(FemtoUniverseDebugV0, processData, "Enable processing on real data", true); + + /// Produce QA plots for V0 and its children on Monte Carlo + void processMC(o2::aod::FdCollision const& col, soa::Join const& parts, o2::aod::FdMCParticles const&) + { + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + eventHisto.fillQA(col); + for (const auto& part : groupPartsOne) { + if (!part.has_children()) { + continue; + } + const auto& positiveChild = parts.iteratorAt(part.index() - 2); + const auto& negativeChild = parts.iteratorAt(part.index() - 1); + if (positiveChild.globalIndex() != part.childrenIds()[0] || negativeChild.globalIndex() != part.childrenIds()[1]) { + LOG(warn) << "Indices of V0 children do not match"; + continue; + } + + // Check cuts on V0 children + if (positiveChild.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kV0Child) && + negativeChild.partType() == uint8_t(aod::femtouniverseparticle::ParticleType::kV0Child) && + isFullPIDSelected(positiveChild.pidCut(), positiveChild.p(), 999.f, childconfigs.confPositiveChildIndex.value, childconfigs.confChildnSpecies.value, childconfigs.confChildPIDnSigmaMax.value, childconfigs.confPositiveChildPIDnSigmaMax.value, 1.f) && + isFullPIDSelected(negativeChild.pidCut(), negativeChild.p(), 999.f, childconfigs.confNegativeChildIndex.value, childconfigs.confChildnSpecies.value, childconfigs.confChildPIDnSigmaMax.value, childconfigs.confNegativeChildPIDnSigmaMax.value, 1.f)) { + auto positiveChildMass = pdg->Mass(V0configs.confPDGCodePositiveChild); + auto negativeChildMass = pdg->Mass(V0configs.confPDGCodeNegativeChild); auto positiveChildBoosted = FemtoUniverseMath::boostPRF(positiveChild, positiveChildMass, negativeChild, negativeChildMass); auto cosineTheta = (positiveChildBoosted.Px() * part.px() + positiveChildBoosted.Py() * part.py() + positiveChildBoosted.Pz() * part.pz()) / (positiveChildBoosted.P() * part.p()); V0Histos.fillQA(part); positiveChildHistos.fillQA(positiveChild); negativeChildHistos.fillQA(negativeChild); + thetaRegistry.fill(HIST("Theta/hTheta"), part.p(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaPt"), positiveChild.pt(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaEta"), positiveChild.eta(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaPhi"), positiveChild.phi(), cosineTheta); + thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPt"), negativeChild.pt(), cosineTheta); + thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaEta"), negativeChild.eta(), cosineTheta); + thetaRegistry.fill(HIST("Theta/NegativeChild/hThetaPhi"), negativeChild.phi(), cosineTheta); } } } + PROCESS_SWITCH(FemtoUniverseDebugV0, processMC, "Enable processing on Monte Carlo", false); }; WorkflowSpec diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx index 92e42134f0a..cc0ab0077c8 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniverseEfficiencyBase.cxx @@ -14,15 +14,16 @@ /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch /// \author Alicja Płachta, WUT Warsaw, alicja.plachta@cern.ch -#include +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" + #include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" #include "Framework/HistogramRegistry.h" #include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" +#include using namespace o2; using namespace o2::analysis::femto_universe; @@ -36,6 +37,8 @@ struct FemtoUniverseEfficiencyBase { Preslice perCol = aod::femtouniverseparticle::fdCollisionId; Configurable confIsDebug{"confIsDebug", true, "Enable debug histograms"}; + Configurable confIsMCGen{"confIsMCGen", false, "Enable QA histograms for MC Gen"}; + Configurable confIsMCReco{"confIsMCReco", false, "Enable QA histograms for MC Reco"}; // Collisions Configurable confZVertex{"confZVertex", 10.f, "Event sel: Maximum z-Vertex (cm)"}; @@ -156,10 +159,11 @@ struct FemtoUniverseEfficiencyBase { { eventHisto.init(&qaRegistry); - trackHistoPartOneGen.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarPDGBins, 0, confPDGCodePartOne, false); - trackHistoPartOneRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, 0, confPDGCodePartOne, confIsDebug); + 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}}}); 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)) { trackHistoV0OneRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarCPABins, 0, confPDGCodePartOne, confIsDebug); trackHistoV0OneChildPosRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, 0, 0, confIsDebug, "posChildV0_1"); @@ -169,9 +173,10 @@ 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) { - trackHistoPartTwoGen.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarPDGBins, 0, confPDGCodePartTwo, false); - trackHistoPartTwoRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarDCABins, 0, confPDGCodePartTwo, confIsDebug); + 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}}}); if (confParticleTypePartTwo == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) { trackHistoV0TwoRec.init(&qaRegistry, confTempFitVarpTBins, confTempFitVarCPABins, 0, confPDGCodePartTwo, confIsDebug); @@ -369,6 +374,9 @@ struct FemtoUniverseEfficiencyBase { } const auto mcParticle = part.fdMCParticle(); + registryPDG.fill(HIST("part1/PDGvspTall"), part.pt(), mcParticle.pdgMCTruth()); + trackHistoPartOneRec.fillQA(part); + if (!(mcParticle.partOriginMCTruth() == aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kPrimary)) { continue; } @@ -377,7 +385,6 @@ struct FemtoUniverseEfficiencyBase { continue; } - trackHistoPartOneRec.fillQA(part); registryPDG.fill(HIST("part1/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); registryMCOrigin.fill(HIST("part1/hPt"), mcParticle.pt()); } @@ -393,6 +400,9 @@ struct FemtoUniverseEfficiencyBase { } const auto mcParticle = part.fdMCParticle(); + registryPDG.fill(HIST("part2/PDGvspTall"), part.pt(), mcParticle.pdgMCTruth()); + trackHistoPartTwoRec.fillQA(part); + if (!(mcParticle.partOriginMCTruth() == aod::femtouniverse_mc_particle::ParticleOriginMCTruth::kPrimary)) { continue; } @@ -401,7 +411,6 @@ struct FemtoUniverseEfficiencyBase { continue; } - trackHistoPartTwoRec.fillQA(part); registryPDG.fill(HIST("part2/PDGvspT"), part.pt(), mcParticle.pdgMCTruth()); registryMCOrigin.fill(HIST("part2/hPt"), mcParticle.pt()); } @@ -604,12 +613,20 @@ struct FemtoUniverseEfficiencyBase { // MCGen auto thegrouppartsOneMCGen = partsOneMCGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegrouppartsTwoMCGen = partsTwoMCGen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doMCGen(thegrouppartsOneMCGen, thegrouppartsTwoMCGen); + if (confIsMCGen) { + doMCGen(thegrouppartsOneMCGen, thegrouppartsTwoMCGen); + } else { + doMCGen(thegrouppartsOneMCGen, thegrouppartsTwoMCGen); + } // MCRec auto thegroupPartsTrackOneRec = partsTrackOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsTrackTwoRec = partsTrackTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); if (confIsDebug) { - doMCRecTrackTrack(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); + if (confIsMCGen) { + doMCRecTrackTrack(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); + } else { + doMCRecTrackTrack(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); + } } else { doMCRecTrackTrack(thegroupPartsTrackOneRec, thegroupPartsTrackTwoRec); } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx index e4ebe2db60a..6d6e22c5bb2 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackCascadeExtended.cxx @@ -14,22 +14,26 @@ /// \author Barbara Chytla, WUT Warsaw, barbara.chytla@cern.ch /// \author Shirajum Monira, WUT Warsaw, shirajum.monira@cern.ch -#include -#include -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StepTHn.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" #include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Framework/ASoAHelpers.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 + +#include +#include using namespace o2; using namespace o2::soa; @@ -42,17 +46,14 @@ struct femtoUniversePairTaskTrackCascadeExtended { Service pdgMC; SliceCache cache; - using FemtoFullParticles = soa::Join; - Preslice perCol = aod::femtouniverseparticle::fdCollisionId; - - using FemtoRecoParticles = soa::Join; - Preslice perColReco = aod::femtouniverseparticle::fdCollisionId; + using FemtoFullParticles = soa::Join; + using FemtoRecoFullParticles = soa::Join; + using FemtoRecoBasicParticles = soa::Join; ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; ConfigurableAxis confChildTempFitVarBins{"confChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; Configurable confCascInvMassLowLimit{"confCascInvMassLowLimit", 1.315, "Lower limit of the Casc invariant mass"}; Configurable confCascInvMassUpLimit{"confCascInvMassUpLimit", 1.325, "Upper limit of the Casc invariant mass"}; - Configurable confCascTranRad{"confCascTranRad", 0.5, "Cascade transverse radius"}; Configurable confNSigmaTPCPion{"confNSigmaTPCPion", 4, "NSigmaTPCPion"}; Configurable confNSigmaTPCProton{"confNSigmaTPCProton", 4, "NSigmaTPCProton"}; @@ -64,8 +65,9 @@ struct femtoUniversePairTaskTrackCascadeExtended { // configurations for correlation part Configurable confTrackChoicePartOne{"confTrackChoicePartOne", 0, "0:Proton, 1:Pion, 2:Kaon"}; Configurable confTrkPDGCodePartOne{"confTrkPDGCodePartOne", 2212, "Particle 1 (Track) - PDG code"}; - Configurable confCascType1{"confCascType1", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade combination"}; - Configurable confCascType2{"confCascType2", 0, "select one of the V0s (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for cascade-cascade combination"}; + Configurable confCascPDGCodePartTwo{"confCascPDGCodePartTwo", 3312, "Particle 2 (Cascade) - PDG code"}; + Configurable confCascType1{"confCascType1", 0, "select one of the Cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for track-cascade combination"}; + Configurable confCascType2{"confCascType2", 0, "select one of the Cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3) for cascade-cascade combination"}; Configurable confIsCPR{"confIsCPR", false, "Close Pair Rejection"}; 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"}; @@ -83,6 +85,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { Configurable confNsigmaTPCParticle{"confNsigmaTPCParticle", 3.0, "TPC Sigma for particle (track) momentum < Confmom"}; Configurable confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle (track) momentum > Confmom"}; Configurable confNsigmaTPCParticleChild{"confNsigmaTPCParticleChild", 3.0, "TPC Sigma for particle (daugh & bach) momentum < Confmom"}; + Configurable confCheckTOFBachelorOnly{"confCheckTOFBachelorOnly", false, "Enable TOF for Cascade bachelor only"}; Configurable confNsigmaTOFParticleChild{"confNsigmaTOFParticleChild", 3.0, "TOF Sigma for particle (daugh & bach) momentum > Confmom"}; ConfigurableAxis confkstarBins{"confkstarBins", {1500, 0., 6.}, "binning kstar"}; @@ -99,23 +102,27 @@ struct femtoUniversePairTaskTrackCascadeExtended { 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 confTrkTempFitVarpTBins{"confTrkTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; ConfigurableAxis confTrkTempFitVarBins{"confTrkTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + Configurable confNEventsMix{"confNEventsMix", 5, "Number of events for mixing"}; Filter collisionFilter = (nabs(aod::collision::posZ) < confZVertexCut); using FilteredFDCollisions = soa::Filtered; using FilteredFDCollision = FilteredFDCollisions::iterator; - /// Partition for particle 1 (track) - Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); - Partition partsOneMCgen = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); - Partition partsOneMCreco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + /// Partition for particle 1 using extended table (track) + Partition partsOneFull = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + + /// Partition for particle 1 without extended table (track) + Partition partsOneBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + Partition partsOneMCgenBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + Partition partsOneMCrecoBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::mAntiLambda == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); - /// Partition for particle 2 (cascade) - Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); - Partition partsTwoMCgen = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); - Partition partsTwoMCreco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + /// Partition for particle 2 using extended table (cascade) + Partition partsTwoFull = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); - /// Partition for cascades - Partition cascs = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)); + /// Partition for particle 2 without extended table (cascade) + Partition partsTwoBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + Partition partsTwoMCgenBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + Partition partsTwoMCrecoBasic = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); /// Histogramming for track particle FemtoUniverseParticleHisto trackHistoPartOnePos; @@ -186,18 +193,20 @@ struct femtoUniversePairTaskTrackCascadeExtended { } template - bool isParticleTPC(const T& part, int id) + bool isParticleTPC(const T& part, int id, float* partSigma = 0) { const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; - + if (partSigma) + *partSigma = tpcNSigmas[id]; return isNSigmaTPC(tpcNSigmas[id]); } template - bool isParticleTOF(const T& part, int id) + bool isParticleTOF(const T& part, int id, float* partSigma = 0) { const float tofNSigmas[3] = {unPackInTable(part.tofNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePi()), unPackInTable(part.tofNSigmaStoreKa())}; - + if (partSigma) + *partSigma = tofNSigmas[id]; return isNSigmaTOF(part.p(), tofNSigmas[id], part.tempFitVar()); } @@ -244,10 +253,19 @@ struct femtoUniversePairTaskTrackCascadeExtended { rXiQA.add("hInvMpTmult", "hInvMpTmult", kTH3F, {{ptAxis}, {aXiMassAxis}, {multAxis}}); eventHisto.init(&qaRegistry); + /// nSigma debug histograms for the selected particle species only i.e. not sigmas of all particles mixed together qaRegistry.add("Tracks_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("Tracks_pos/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("Tracks_neg/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); qaRegistry.add("Tracks_neg/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + qaRegistry.add("V0Child_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("V0Child_neg/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("hBachelor/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("V0Child_pos/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("V0Child_neg/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("hBachelor/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); // MC gen registryMCgen.add("plus/MCgenCasc", "MC gen cascades;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); @@ -284,34 +302,28 @@ struct femtoUniversePairTaskTrackCascadeExtended { sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); + sameEventCont.setPDGCodes(confTrkPDGCodePartOne, confCascPDGCodePartTwo); + mixedEventCont.setPDGCodes(confTrkPDGCodePartOne, confCascPDGCodePartTwo); + pairCleaner.init(&qaRegistry); + pairCleanerCasc.init(&qaRegistry); if (confIsCPR.value) { pairCloseRejection.init(&resultRegistry, &qaRegistry, confCPRdeltaPhiCutMin.value, confCPRdeltaPhiCutMax.value, confCPRdeltaEtaCutMin.value, confCPRdeltaEtaCutMax.value, confCPRChosenRadii.value, confCPRPlotPerRadii.value, 0, 0, confIsSameSignCPR.value); } } - void processCascades(const FilteredFDCollision& col, const FemtoFullParticles& parts) + void processCascadeQA([[maybe_unused]] const FilteredFDCollision& col, const FemtoFullParticles& parts, const aod::FDCascParticles& fdcascs) { - auto groupCascs = cascs->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - // const int multCol = col.multNtr(); + for (const auto& casc : fdcascs) { + const auto& part = casc.fdParticle_as(); + rXiQA.fill(HIST("hMassXi"), part.mLambda()); - for (const auto& casc : groupCascs) { - rXiQA.fill(HIST("hMassXi"), casc.mLambda()); + const auto& posChild = parts.iteratorAt(part.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); - // if (!invMCascade(casc.mLambda(), casc.mAntiLambda())) - // continue; - - const auto& posChild = parts.iteratorAt(casc.index() - 3); - const auto& negChild = parts.iteratorAt(casc.index() - 2); - const auto& bachelor = parts.iteratorAt(casc.index() - 1); - - // if (casc.transRadius() < confCascTranRad) - // continue; - // std::cout< confNSigmaTPCProton) { continue; } @@ -330,10 +342,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { continue; } - rXiQA.fill(HIST("hPtXi"), casc.pt()); - rXiQA.fill(HIST("hEtaXi"), casc.eta()); - rXiQA.fill(HIST("hPhiXi"), casc.phi()); - rXiQA.fill(HIST("hMassXiSelected"), casc.mLambda()); + rXiQA.fill(HIST("hPtXi"), part.pt()); + rXiQA.fill(HIST("hEtaXi"), part.eta()); + rXiQA.fill(HIST("hPhiXi"), part.phi()); + rXiQA.fill(HIST("hMassXiSelected"), part.mLambda()); rXiQA.fill(HIST("hDCAV0Daughters"), casc.dcaV0daughters()); rXiQA.fill(HIST("hV0CosPA"), casc.cpav0()); rXiQA.fill(HIST("hV0TranRad"), casc.v0radius()); @@ -344,17 +356,19 @@ struct femtoUniversePairTaskTrackCascadeExtended { rXiQA.fill(HIST("hDcaNegtoPV"), casc.dcanegtopv()); rXiQA.fill(HIST("hDcaBachtoPV"), casc.dcabachtopv()); rXiQA.fill(HIST("hDcaV0toPV"), casc.dcav0topv()); - rXiQA.fill(HIST("hInvMpT"), casc.pt(), casc.mLambda()); - - posChildHistos.fillQA(posChild); - negChildHistos.fillQA(negChild); - bachHistos.fillQABase(bachelor, HIST("hBachelor")); + rXiQA.fill(HIST("hInvMpT"), part.pt(), part.mLambda()); } } - PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processCascades, "Enable processing cascades", false); + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processCascadeQA, "Enable processing cascades", false); + + template + using hasSigma = decltype(std::declval().tpcNSigmaStorePr()); + /// track - cascade correlations - void processSameEvent(const FilteredFDCollision& col, const FemtoFullParticles& parts) + template + void doSameEvent(const FilteredFDCollision& col, const TableType& parts, PartitionType& partsOne, PartitionType& partsTwo) { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); @@ -366,70 +380,119 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!invMCascade(part.mLambda(), part.mAntiLambda(), confCascType1)) /// mLambda stores Xi mass, mAntiLambda stores Omega mass continue; - cascQAHistos.fillQA(part); - - const auto& posChild = parts.iteratorAt(part.index() - 3); - const auto& negChild = parts.iteratorAt(part.index() - 2); - const auto& bachelor = parts.iteratorAt(part.index() - 1); + const auto& posChild = parts.iteratorAt(part.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); /// Child particles must pass this condition to be selected - if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) - continue; + if constexpr (std::experimental::is_detected::value) { + float posChildTPC, negChildTPC, bachelorTPC, posChildTOF, negChildTOF, bachelorTOF; + if (!isParticleTPC(posChild, CascChildTable[confCascType1][0], &posChildTPC) || !isParticleTPC(negChild, CascChildTable[confCascType1][1], &negChildTPC) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2], &bachelorTPC)) + continue; - if (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) - continue; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild, CascChildTable[confCascType1][0], &posChildTOF) || !isParticleTOF(negChild, CascChildTable[confCascType1][1], &negChildTOF))) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2], &bachelorTOF)) + continue; + + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + bachHistos.fillQABase(bachelor, HIST("hBachelor")); + + qaRegistry.fill(HIST("V0Child_pos/nSigmaTPC"), posChild.p(), posChildTPC); + qaRegistry.fill(HIST("V0Child_neg/nSigmaTPC"), negChild.p(), negChildTPC); + qaRegistry.fill(HIST("hBachelor/nSigmaTPC"), bachelor.p(), bachelorTPC); + if (!confCheckTOFBachelorOnly) { + qaRegistry.fill(HIST("V0Child_pos/nSigmaTOF"), posChild.p(), posChildTOF); + qaRegistry.fill(HIST("V0Child_neg/nSigmaTOF"), negChild.p(), negChildTOF); + } + qaRegistry.fill(HIST("hBachelor/nSigmaTOF"), bachelor.p(), bachelorTOF); + + cascQAHistos.fillQA(part); + + } else { + if ((posChild.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + continue; - posChildHistos.fillQA(posChild); - negChildHistos.fillQA(negChild); - bachHistos.fillQABase(bachelor, HIST("hBachelor")); + if ((!confCheckTOFBachelorOnly && ((posChild.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + continue; + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + bachHistos.fillQABase(bachelor, HIST("hBachelor")); + cascQAHistos.fillQA(part); + } rXiQA.fill(HIST("hInvMpTmult"), part.pt(), part.mLambda(), multCol); } - for (const auto& part : groupPartsOne) { - /// PID plot for track particle - const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; - const float tofNSigmas[3] = {unPackInTable(part.tofNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePi()), unPackInTable(part.tofNSigmaStoreKa())}; + if constexpr (std::experimental::is_detected::value) { + for (const auto& part : groupPartsOne) { + /// PID plot for track particle + const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; + const float tofNSigmas[3] = {unPackInTable(part.tofNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePi()), unPackInTable(part.tofNSigmaStoreKa())}; - if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne])) - continue; + if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne])) + continue; - if (part.sign() > 0) { - qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); - qaRegistry.fill(HIST("Tracks_pos/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); - trackHistoPartOnePos.fillQA(part); - } else if (part.sign() < 0) { - qaRegistry.fill(HIST("Tracks_neg/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); - qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); - trackHistoPartOneNeg.fillQA(part); + if (part.mAntiLambda() > 0) { + qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_pos/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); + trackHistoPartOnePos.fillQA(part); + } else if (part.mAntiLambda() < 0) { + qaRegistry.fill(HIST("Tracks_neg/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); + 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)) continue; // PID - if (!isParticleCombined(p1, confTrackChoicePartOne)) - continue; + if constexpr (std::experimental::is_detected::value) { + if (!isParticleCombined(p1, confTrackChoicePartOne)) + continue; + } else { + if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + continue; + } // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { continue; } - const auto& posChild = parts.iteratorAt(p2.index() - 3); - const auto& negChild = parts.iteratorAt(p2.index() - 2); - const auto& bachelor = parts.iteratorAt(p2.index() - 1); - /// Child particles must pass this condition to be selected - if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) - continue; - if (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) - continue; + const auto& posChild = parts.iteratorAt(p2.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); + /// Child particles must pass this condition to be selected + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) + continue; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]))) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) + continue; + } else { + if ((posChild.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + continue; + if ((!confCheckTOFBachelorOnly && ((posChild.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + continue; + } sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); } } + + void processSameEvent(const FilteredFDCollision& col, const FemtoFullParticles& parts) + { + doSameEvent(col, parts, partsOneFull, partsTwoFull); + } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEvent, "Enable processing same event for track - cascade", false); + + void processSameEventBitmask(const FilteredFDCollision& col, const aod::FDParticles& parts) + { + doSameEvent(col, parts, partsOneBasic, partsTwoBasic); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventBitmask, "Enable processing same event for track - cascade using bitmask for PID", false); + /// cascade - cascade correlations - void processSameEventCasc(const FilteredFDCollision& col, const FemtoFullParticles& parts) + template + void doSameEventCasc(const FilteredFDCollision& col, const TableType& parts, PartitionType& partsTwo) { const auto& magFieldTesla = col.magField(); @@ -443,23 +506,34 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!invMCascade(part.mLambda(), part.mAntiLambda(), confCascType1)) /// mLambda stores Xi mass, mAntiLambda stores Omega mass continue; - cascQAHistos.fillQA(part); + if constexpr (std::experimental::is_detected::value) + cascQAHistos.fillQA(part); + else + cascQAHistos.fillQA(part); - const auto& posChild = parts.iteratorAt(part.index() - 3); - const auto& negChild = parts.iteratorAt(part.index() - 2); - const auto& bachelor = parts.iteratorAt(part.index() - 1); + const auto& posChild = parts.iteratorAt(part.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); /// Check daughters of first cascade - if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) - continue; - if (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) - continue; + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) + continue; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]))) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) + continue; + + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + bachHistos.fillQABase(bachelor, HIST("hBachelor")); + } else { + if ((posChild.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + continue; + if ((!confCheckTOFBachelorOnly && ((posChild.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + continue; - posChildHistos.fillQA(posChild); - negChildHistos.fillQA(negChild); - bachHistos.fillQABase(bachelor, HIST("hBachelor")); - /// Check daughters of second cascade - /*if (isParticleTPC(posChild, CascChildTable[confCascType2][0]) && isParticleTPC(negChild, CascChildTable[confCascType2][1]) && isParticleTPC(bachelor, CascChildTable[confCascType2][2])) { - }*/ + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + bachHistos.fillQABase(bachelor, HIST("hBachelor")); + } } auto pairDuplicateCheckFunc = [&](auto& p1, auto& p2) -> void { @@ -489,22 +563,38 @@ struct femtoUniversePairTaskTrackCascadeExtended { return; } } - const auto& posChild1 = parts.iteratorAt(p1.index() - 3); - const auto& negChild1 = parts.iteratorAt(p1.index() - 2); - const auto& bachelor1 = parts.iteratorAt(p1.index() - 1); + + const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor1 = parts.iteratorAt(p1.globalIndex() - 1 - parts.begin().globalIndex()); /// Child particles must pass this condition to be selected - if (!isParticleTPC(posChild1, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType1][2])) - return; - if (!isParticleTOF(posChild1, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType1][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType1][2])) - return; - const auto& posChild2 = parts.iteratorAt(p2.index() - 3); - const auto& negChild2 = parts.iteratorAt(p2.index() - 2); - const auto& bachelor2 = parts.iteratorAt(p2.index() - 1); + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild1, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType1][2])) + return; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild1, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType1][1]))) || !isParticleTOF(bachelor1, CascChildTable[confCascType1][2])) + return; + } else { + if ((posChild1.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild1.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor1.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + return; + if ((!confCheckTOFBachelorOnly && ((posChild1.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild1.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor1.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + return; + } + + const auto& posChild2 = parts.iteratorAt(p2.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild2 = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor2 = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); /// Child particles must pass this condition to be selected - if (!isParticleTPC(posChild2, CascChildTable[confCascType2][0]) || !isParticleTPC(negChild2, CascChildTable[confCascType2][1]) || !isParticleTPC(bachelor2, CascChildTable[confCascType2][2])) - return; - if (!isParticleTOF(posChild2, CascChildTable[confCascType2][0]) || !isParticleTOF(negChild2, CascChildTable[confCascType2][1]) || !isParticleTOF(bachelor2, CascChildTable[confCascType2][2])) - return; + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild2, CascChildTable[confCascType2][0]) || !isParticleTPC(negChild2, CascChildTable[confCascType2][1]) || !isParticleTPC(bachelor2, CascChildTable[confCascType2][2])) + return; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild2, CascChildTable[confCascType2][0]) || !isParticleTOF(negChild2, CascChildTable[confCascType2][1]))) || !isParticleTOF(bachelor2, CascChildTable[confCascType2][2])) + return; + } else { + if ((posChild2.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild2.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor2.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + return; + if ((!confCheckTOFBachelorOnly && ((posChild2.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild2.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor2.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + return; + } sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); }; @@ -527,13 +617,27 @@ struct femtoUniversePairTaskTrackCascadeExtended { } } } + + void processSameEventCasc(const FilteredFDCollision& col, const FemtoFullParticles& parts) + { + doSameEventCasc(col, parts, partsTwoFull); + } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventCasc, "Enable processing same event for cascade - cascade", false); + + void processSameEventCascBitmask(const FilteredFDCollision& col, const aod::FDParticles& parts) + { + doSameEventCasc(col, parts, partsTwoBasic); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventCascBitmask, "Enable processing same event for cascade - cascade using bitmask for PID", false); + /// track - cascade correlations - void processMixedEvent(const FilteredFDCollisions& cols, const FemtoFullParticles& parts) + template + void doMixedEvent(const FilteredFDCollisions& cols, const TableType& parts, PartitionType& partsOne, PartitionType& partsTwo) { - ColumnBinningPolicy colBinning{{confVtxBins, confMultBins}, true}; + ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; + ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; - for (const auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); @@ -543,24 +647,36 @@ struct femtoUniversePairTaskTrackCascadeExtended { const auto& magFieldTesla2 = collision2.magField(); if (magFieldTesla1 != magFieldTesla2) { - continue; + return; } 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)) continue; // PID - if (!isParticleCombined(p1, confTrackChoicePartOne)) - continue; + if constexpr (std::experimental::is_detected::value) { + if (!isParticleCombined(p1, confTrackChoicePartOne)) + continue; + } else { + if ((p1.pidCut() & (64u << confTrackChoicePartOne)) == 0) + continue; + } - const auto& posChild = parts.iteratorAt(p2.index() - 3); - const auto& negChild = parts.iteratorAt(p2.index() - 2); - const auto& bachelor = parts.iteratorAt(p2.index() - 1); + const auto& posChild = parts.iteratorAt(p2.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); /// Child particles must pass this condition to be selected - if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) - continue; - if (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) - continue; + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) + continue; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]))) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) + continue; + } else { + if ((posChild.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + continue; + if ((!confCheckTOFBachelorOnly && ((posChild.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + continue; + } // track cleaning if (!pairCleaner.isCleanPair(p1, p2, parts)) { @@ -569,11 +685,36 @@ struct femtoUniversePairTaskTrackCascadeExtended { mixedEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); } + }; + + if (confUseCent) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + } + } else { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + } } } + + void processMixedEvent(const FilteredFDCollisions& cols, const FemtoFullParticles& parts) + { + doMixedEvent(cols, parts, partsOneFull, partsTwoFull); + } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEvent, "Enable processing mixed event for track - cascade", false); + + void processMixedEventBitmask(const FilteredFDCollisions& cols, const aod::FDParticles& parts) + { + doMixedEvent(cols, parts, partsOneBasic, partsTwoBasic); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventBitmask, "Enable processing mixed event for track - cascade using bitmask for PID", false); + /// cascade - cascade correlations - void processMixedEventCasc(const FilteredFDCollisions& cols, const FemtoFullParticles& parts) + template + void doMixedEventCasc(const FilteredFDCollisions& cols, const TableType& parts, PartitionType& partsTwo) { ColumnBinningPolicy colBinning{{confVtxBins, confMultBins}, true}; @@ -597,22 +738,37 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType2)) continue; - const auto& posChild1 = parts.iteratorAt(p1.index() - 3); - const auto& negChild1 = parts.iteratorAt(p1.index() - 2); - const auto& bachelor1 = parts.iteratorAt(p1.index() - 1); + const auto& posChild1 = parts.iteratorAt(p1.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild1 = parts.iteratorAt(p1.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor1 = parts.iteratorAt(p1.globalIndex() - 1 - parts.begin().globalIndex()); /// Child particles must pass this condition to be selected - if (!isParticleTPC(posChild1, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType1][2])) - return; - if (!isParticleTOF(posChild1, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType1][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType1][2])) - return; - const auto& posChild2 = parts.iteratorAt(p2.index() - 3); - const auto& negChild2 = parts.iteratorAt(p2.index() - 2); - const auto& bachelor2 = parts.iteratorAt(p2.index() - 1); + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild1, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType1][2])) + return; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild1, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType1][1]))) || !isParticleTOF(bachelor1, CascChildTable[confCascType1][2])) + return; + } else { + if ((posChild1.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild1.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor1.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + return; + if ((!confCheckTOFBachelorOnly && ((posChild1.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild1.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor1.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + return; + } + + const auto& posChild2 = parts.iteratorAt(p2.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild2 = parts.iteratorAt(p2.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor2 = parts.iteratorAt(p2.globalIndex() - 1 - parts.begin().globalIndex()); /// Child particles must pass this condition to be selected - if (!isParticleTPC(posChild2, CascChildTable[confCascType2][0]) || !isParticleTPC(negChild2, CascChildTable[confCascType2][1]) || !isParticleTPC(bachelor2, CascChildTable[confCascType2][2])) - return; - if (!isParticleTOF(posChild2, CascChildTable[confCascType2][0]) || !isParticleTOF(negChild2, CascChildTable[confCascType2][1]) || !isParticleTOF(bachelor2, CascChildTable[confCascType2][2])) - return; + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild2, CascChildTable[confCascType2][0]) || !isParticleTPC(negChild2, CascChildTable[confCascType2][1]) || !isParticleTPC(bachelor2, CascChildTable[confCascType2][2])) + return; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild2, CascChildTable[confCascType2][0]) || !isParticleTOF(negChild2, CascChildTable[confCascType2][1]))) || !isParticleTOF(bachelor2, CascChildTable[confCascType2][2])) + return; + } else { + if ((posChild2.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild2.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor2.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + return; + if ((!confCheckTOFBachelorOnly && ((posChild2.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild2.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor2.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + return; + } // track cleaning if (!pairCleanerCasc.isCleanPair(p1, p2, parts)) { continue; @@ -627,21 +783,35 @@ struct femtoUniversePairTaskTrackCascadeExtended { } } } + + void processMixedEventCasc(const FilteredFDCollisions& cols, const FemtoFullParticles& parts) + { + doMixedEventCasc(cols, parts, partsTwoFull); + } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventCasc, "Enable processing mixed event for cascade - cascade", false); - // MC truth - void processSameEventMCgen(const FilteredFDCollision& col, [[maybe_unused]] const FemtoFullParticles& parts) + + void processMixedEventCascBitmask(const FilteredFDCollisions& cols, const aod::FDParticles& parts) + { + doMixedEventCasc(cols, parts, partsTwoBasic); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventCascBitmask, "Enable processing mixed event for cascade - cascade using bitmask for PID", false); + + // MC truth for track - cascade + void processSameEventMCgen(const FilteredFDCollision& col, [[maybe_unused]] const aod::FDParticles& parts) { - auto groupPartsOne = partsOneMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - auto groupPartsTwo = partsTwoMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + + auto groupPartsOne = partsOneMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); eventHisto.fillQA(col); for (const auto& part : groupPartsTwo) { int pdgCode = static_cast(part.pidCut()); - if ((confCascType1 == 0 && pdgCode != 3334) || (confCascType1 == 2 && pdgCode != -3334) || (confCascType1 == 1 && pdgCode != 3312) || (confCascType1 == 3 && pdgCode != -3312)) + if ((confCascType1 == 0 && pdgCode != kOmegaMinus) || (confCascType1 == 2 && pdgCode != kOmegaPlusBar) || (confCascType1 == 1 && pdgCode != kXiMinus) || (confCascType1 == 3 && pdgCode != kXiPlusBar)) continue; - cascQAHistos.fillQA(part); + cascQAHistos.fillQA(part); for (const auto& part : groupPartsOne) { int pdgCode = static_cast(part.pidCut()); @@ -663,22 +833,61 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (static_cast(p1.pidCut()) != confTrkPDGCodePartOne) continue; int pdgCodeCasc = static_cast(p2.pidCut()); - if ((confCascType1 == 0 && pdgCodeCasc != 3334) || (confCascType1 == 2 && pdgCodeCasc != -3334) || (confCascType1 == 1 && pdgCodeCasc != 3312) || (confCascType1 == 3 && pdgCodeCasc != -3312)) + if ((confCascType1 == 0 && pdgCodeCasc != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc != kXiPlusBar)) continue; - sameEventCont.setPair(p1, p2, col.multNtr(), confUse3D, 1.0f); + sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); } } } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventMCgen, "Enable processing same event MC truth for track - cascade", false); - void processMixedEventMCgen(const FilteredFDCollisions& cols, [[maybe_unused]] const FemtoFullParticles& parts) + // MC truth for cascade - cascade + void processSameEventCascMCgen(const FilteredFDCollision& col, [[maybe_unused]] const aod::FDParticles& parts) + { + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + + auto groupPartsTwo = partsTwoMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + eventHisto.fillQA(col); + + for (const auto& part : groupPartsTwo) { + int pdgCode = static_cast(part.pidCut()); + if ((confCascType1 == 0 && pdgCode != kOmegaMinus) || (confCascType1 == 2 && pdgCode != kOmegaPlusBar) || (confCascType1 == 1 && pdgCode != kXiMinus) || (confCascType1 == 3 && pdgCode != kXiPlusBar)) + continue; + + cascQAHistos.fillQA(part); + + auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { + int pdgCodeCasc1 = static_cast(p1.pidCut()); + if ((confCascType1 == 0 && pdgCodeCasc1 != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc1 != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc1 != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc1 != kXiPlusBar)) + return; + int pdgCodeCasc2 = static_cast(p2.pidCut()); + if ((confCascType2 == 0 && pdgCodeCasc2 != kOmegaMinus) || (confCascType2 == 2 && pdgCodeCasc2 != kOmegaPlusBar) || (confCascType2 == 1 && pdgCodeCasc2 != kXiMinus) || (confCascType2 == 3 && pdgCodeCasc2 != kXiPlusBar)) + return; + sameEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); + }; + + if (confCascType1 == confCascType2) { + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) + pairProcessFunc(p1, p2); + } else { + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) + pairProcessFunc(p1, p2); + } + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processSameEventCascMCgen, "Enable processing same event MC truth for cascade - cascade", false); + + // MC truth for track - cascade + void processMixedEventMCgen(const FilteredFDCollisions& cols, [[maybe_unused]] const aod::FDParticles& parts) { ColumnBinningPolicy colBinning{{confVtxBins, confMultBins}, true}; for (const auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); - auto groupPartsOne = partsOneMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - auto groupPartsTwo = partsTwoMCgen->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + auto groupPartsOne = partsOneMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); const auto& magFieldTesla1 = collision1.magField(); const auto& magFieldTesla2 = collision2.magField(); @@ -690,16 +899,46 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (static_cast(p1.pidCut()) != confTrkPDGCodePartOne) continue; int pdgCodeCasc = static_cast(p2.pidCut()); - if ((confCascType1 == 0 && pdgCodeCasc != 3334) || (confCascType1 == 2 && pdgCodeCasc != -3334) || (confCascType1 == 1 && pdgCodeCasc != 3312) || (confCascType1 == 3 && pdgCodeCasc != -3312)) + if ((confCascType1 == 0 && pdgCodeCasc != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc != kXiPlusBar)) continue; - mixedEventCont.setPair(p1, p2, collision1.multNtr(), confUse3D, 1.0f); + mixedEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); } } } PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventMCgen, "Enable processing mixed event MC truth for track - cascade", false); + // MC truth for cascade - cascade + void processMixedEventCascMCgen(const FilteredFDCollisions& cols, [[maybe_unused]] const aod::FDParticles& parts) + { + ColumnBinningPolicy colBinning{{confVtxBins, confMultBins}, true}; + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); + + auto groupPartsOne = partsTwoMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCgenBasic->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + int pdgCodeCasc1 = static_cast(p1.pidCut()); + if ((confCascType1 == 0 && pdgCodeCasc1 != kOmegaMinus) || (confCascType1 == 2 && pdgCodeCasc1 != kOmegaPlusBar) || (confCascType1 == 1 && pdgCodeCasc1 != kXiMinus) || (confCascType1 == 3 && pdgCodeCasc1 != kXiPlusBar)) + continue; + int pdgCodeCasc2 = static_cast(p2.pidCut()); + if ((confCascType2 == 0 && pdgCodeCasc2 != kOmegaMinus) || (confCascType2 == 2 && pdgCodeCasc2 != kOmegaPlusBar) || (confCascType2 == 1 && pdgCodeCasc2 != kXiMinus) || (confCascType2 == 3 && pdgCodeCasc2 != kXiPlusBar)) + continue; + mixedEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); + } + } + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMixedEventCascMCgen, "Enable processing mixed event MC truth for cascade - cascade", false); + /// This function fills MC truth particles from derived MC table - void processMCgen(aod::FDCascParticles const& parts) + void processMCgen(aod::FDParticles const& parts) { for (const auto& part : parts) { if (part.partType() != uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) @@ -711,10 +950,10 @@ struct femtoUniversePairTaskTrackCascadeExtended { continue; } - if ((confCascType1 == 0 && pdgCode == 3334) || (confCascType1 == 1 && pdgCode == 3312)) { + if ((confCascType1 == 0 && pdgCode == kOmegaMinus) || (confCascType1 == 1 && pdgCode == kXiMinus)) { registryMCgen.fill(HIST("plus/MCgenCasc"), part.pt(), part.eta()); continue; - } else if ((confCascType1 == 0 && pdgCode == -3334) || (confCascType1 == 1 && pdgCode == -3312)) { + } else if ((confCascType1 == 0 && pdgCode == kOmegaPlusBar) || (confCascType1 == 1 && pdgCode == kXiPlusBar)) { registryMCgen.fill(HIST("minus/MCgenCasc"), part.pt(), part.eta()); continue; } @@ -722,7 +961,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (pdgParticle->Charge() > 0.0) { registryMCgen.fill(HIST("plus/MCgenAllPt"), part.pt()); } - if (pdgCode == 2212) { + if (pdgCode == kProton) { registryMCgen.fill(HIST("plus/MCgenPr"), part.pt(), part.eta()); registryMCgen.fill(HIST("plus/MCgenPrPt"), part.pt()); } @@ -730,7 +969,7 @@ struct femtoUniversePairTaskTrackCascadeExtended { if (pdgParticle->Charge() < 0.0) { registryMCgen.fill(HIST("minus/MCgenAllPt"), part.pt()); } - if (pdgCode == -2212) { + if (pdgCode == kProtonBar) { registryMCgen.fill(HIST("minus/MCgenPr"), part.pt(), part.eta()); registryMCgen.fill(HIST("minus/MCgenPrPt"), part.pt()); } @@ -739,7 +978,8 @@ struct femtoUniversePairTaskTrackCascadeExtended { PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMCgen, "Process MC truth data for cascades", false); - void processMCReco(FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + template + void doMCReco(TableType const& parts, aod::FdMCParticles const& mcparts) { for (const auto& part : parts) { auto mcPartId = part.fdMCParticleId(); @@ -748,44 +988,85 @@ struct femtoUniversePairTaskTrackCascadeExtended { const auto& mcpart = mcparts.iteratorAt(mcPartId); // if (part.partType() == aod::femtouniverseparticle::ParticleType::kCascade) { - if ((confCascType1 == 0 && mcpart.pdgMCTruth() == 3334) || (confCascType1 == 1 && mcpart.pdgMCTruth() == 3312)) { - const auto& posChild = parts.iteratorAt(part.index() - 3); - const auto& negChild = parts.iteratorAt(part.index() - 2); - const auto& bachelor = parts.iteratorAt(part.index() - 1); + if ((confCascType1 == 0 && mcpart.pdgMCTruth() == kOmegaMinus) || (confCascType1 == 1 && mcpart.pdgMCTruth() == kXiMinus)) { + const auto& posChild = parts.iteratorAt(part.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); /// Daughters that do not pass this condition are not selected - if (isParticleTPC(posChild, CascChildTable[confCascType1][0]) && isParticleTPC(negChild, CascChildTable[confCascType1][1]) && isParticleTPC(bachelor, CascChildTable[confCascType1][2])) { - registryMCreco.fill(HIST("plus/MCrecoCascade"), mcpart.pt(), mcpart.eta()); + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild, CascChildTable[confCascType1][0]) || !isParticleTPC(negChild, CascChildTable[confCascType1][1]) || !isParticleTPC(bachelor, CascChildTable[confCascType1][2])) + continue; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild, CascChildTable[confCascType1][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1][1]))) || !isParticleTOF(bachelor, CascChildTable[confCascType1][2])) + continue; + } else { + if ((posChild.pidCut() & (1u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (1u << CascChildTable[confCascType1][1])) == 0 || (bachelor.pidCut() & (1u << CascChildTable[confCascType1][2])) == 0) + continue; + if ((!confCheckTOFBachelorOnly && ((posChild.pidCut() & (8u << CascChildTable[confCascType1][0])) == 0 || (negChild.pidCut() & (8u << CascChildTable[confCascType1][1])) == 0)) || (bachelor.pidCut() & (8u << CascChildTable[confCascType1][2])) == 0) + continue; } - } else if ((confCascType1 == 0 && mcpart.pdgMCTruth() == -3334) || (confCascType1 == 1 && mcpart.pdgMCTruth() == -3312)) { - /// Daughters that do not pass this condition are not selected - const auto& posChild = parts.iteratorAt(part.index() - 3); - const auto& negChild = parts.iteratorAt(part.index() - 2); - const auto& bachelor = parts.iteratorAt(part.index() - 1); - if (isParticleTPC(posChild, CascChildTable[confCascType1 + 2][0]) && isParticleTPC(negChild, CascChildTable[confCascType1 + 2][1]) && isParticleTPC(bachelor, CascChildTable[confCascType1 + 2][2])) { - registryMCreco.fill(HIST("minus/MCrecoCascade"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("plus/MCrecoCascade"), mcpart.pt(), mcpart.eta()); + + } else if ((confCascType1 == 0 && mcpart.pdgMCTruth() == kOmegaPlusBar) || (confCascType1 == 1 && mcpart.pdgMCTruth() == kXiPlusBar)) { + const auto& posChild = parts.iteratorAt(part.globalIndex() - 3 - parts.begin().globalIndex()); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 2 - parts.begin().globalIndex()); + const auto& bachelor = parts.iteratorAt(part.globalIndex() - 1 - parts.begin().globalIndex()); + if constexpr (std::experimental::is_detected::value) { + if (!isParticleTPC(posChild, CascChildTable[confCascType1 + 2][0]) && !isParticleTPC(negChild, CascChildTable[confCascType1 + 2][1]) && !isParticleTPC(bachelor, CascChildTable[confCascType1 + 2][2])) + continue; + if ((!confCheckTOFBachelorOnly && (!isParticleTOF(posChild, CascChildTable[confCascType1 + 2][0]) || !isParticleTOF(negChild, CascChildTable[confCascType1 + 2][1]))) || !isParticleTOF(bachelor, CascChildTable[confCascType1 + 2][2])) + continue; + } else { + if ((posChild.pidCut() & (1u << CascChildTable[confCascType1 + 2][0])) == 0 || (negChild.pidCut() & (1u << CascChildTable[confCascType1 + 2][1])) == 0 || (bachelor.pidCut() & (1u << CascChildTable[confCascType1 + 2][2])) == 0) + continue; + if ((!confCheckTOFBachelorOnly && ((posChild.pidCut() & (8u << CascChildTable[confCascType1 + 2][0])) == 0 || (negChild.pidCut() & (8u << CascChildTable[confCascType1 + 2][1])) == 0)) || (bachelor.pidCut() & (8u << CascChildTable[confCascType1 + 2][2])) == 0) + continue; } + registryMCreco.fill(HIST("minus/MCrecoCascade"), mcpart.pt(), mcpart.eta()); } + } else if (part.partType() == aod::femtouniverseparticle::ParticleType::kTrack) { - if (part.sign() > 0) { + if (part.mAntiLambda() > 0) { registryMCreco.fill(HIST("plus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == 2212 && isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) { - registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); - registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); + if (mcpart.pdgMCTruth() != kProton) + continue; + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) + continue; + } else { + if ((part.pidCut() & 64u) == 0) + continue; } - } - - if (part.sign() < 0) { + registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); + } else if (part.mAntiLambda() < 0) { registryMCreco.fill(HIST("minus/MCrecoAllPt"), mcpart.pt()); - if (mcpart.pdgMCTruth() == -2212 && isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) { - registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); - registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); + if (mcpart.pdgMCTruth() != kProtonBar) + continue; + if constexpr (std::experimental::is_detected::value) { + if (!isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) + continue; + } else { + if ((part.pidCut() & 64u) == 0) + continue; } + registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); } } } } - PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMCReco, "Process MC reco data for cascades", false); + void processMCReco(FemtoRecoFullParticles const& parts, aod::FdMCParticles const& mcparts) + { + doMCReco(parts, mcparts); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMCReco, "Process MC reco data for cascades using nSigma for PID", false); + + void processMCRecoBitmask(FemtoRecoBasicParticles const& parts, aod::FdMCParticles const& mcparts) + { + doMCReco(parts, mcparts); + } + PROCESS_SWITCH(femtoUniversePairTaskTrackCascadeExtended, processMCRecoBitmask, "Process MC reco data for cascades using Bitmask for PID", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx index 851c329d992..98a697434ac 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackPhi.cxx @@ -16,29 +16,31 @@ /// \author Anton Riedel, TU München, anton.riedel@tum.de /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch -#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/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseTrackSelection.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCalculator.h" #include #include +#include +#include + using namespace o2; using namespace o2::analysis::femto_universe; -using namespace o2::analysis::femto_universe::efficiency; +using namespace o2::analysis::femto_universe::efficiency_correction; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; @@ -187,8 +189,10 @@ struct FemtoUniversePairTaskTrackPhi { ColumnBinningPolicy colBinning{{ConfBinsVtx, ConfBinsMult}, true}; - EfficiencyConfigurableGroup effConfGroup; - EfficiencyCalculator efficiencyCalculator{&effConfGroup}; + HistogramRegistry effCorrRegistry{"EfficiencyCorrection", {}, OutputObjHandlingPolicy::AnalysisObject}; + + EffCorConfigurableGroup effCorConfGroup; + EfficiencyCorrection effCorrection{&effCorConfGroup}; float weight = 1; @@ -372,6 +376,12 @@ struct FemtoUniversePairTaskTrackPhi { } } + /// @returns 1 if positive, -1 if negative, 0 if zero + auto sign(auto number) -> int8_t + { + return (number > 0) - (number < 0); + } + void init(InitContext&) { if (ConfIsMC) { @@ -383,7 +393,14 @@ struct FemtoUniversePairTaskTrackPhi { registryMCpT.add("MCReco/C_p_pT", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); registryMCpT.add("MCReco/NC_p_pT", "; #it{p_T} (GeV/#it{c}); Counts", kTH1F, {{100, 0, 10}}); } - efficiencyCalculator.init(); + + effCorrection.init( + &effCorrRegistry, + { + static_cast(ConfBinsTempFitVarpT), + {ConfBinsEta, -1, 1}, + ConfBinsMult, + }); eventHisto.init(&qaRegistry); qaRegistry.add("PhiDaugh_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); @@ -467,7 +484,7 @@ struct FemtoUniversePairTaskTrackPhi { } } - template + template void doSameEvent(PartitionType groupPartsTrack, PartitionType groupPartsPhi, PartType parts, float magFieldTesla, int multCol, [[maybe_unused]] MCParticles mcParts = nullptr) { for (auto const& phicandidate : groupPartsPhi) { @@ -493,6 +510,10 @@ struct FemtoUniversePairTaskTrackPhi { qaRegistry.fill(HIST("PhiDaugh_neg/hDCAxy"), negChild.p(), negChild.tempFitVar()); trackHistoPartPhi.fillQA(phicandidate); + if constexpr (isMC) { + // reco + effCorrection.fillRecoHist(phicandidate, 333); + } } for (auto const& track : groupPartsTrack) { @@ -529,6 +550,10 @@ struct FemtoUniversePairTaskTrackPhi { qaRegistry.fill(HIST("Hadron_neg/nSigmaTOFPr"), track.p(), tofNSigmaPr); } trackHistoPartTrack.fillQA(track); + + if constexpr (isMC) { + effCorrection.fillRecoHist(track, ConfTrackPDGCode); + } } /// Now build the combinations @@ -556,13 +581,8 @@ struct FemtoUniversePairTaskTrackPhi { if (!pairCleaner.isCleanPair(track, phicandidate, parts)) { continue; } - - weight = efficiencyCalculator.getWeight(ParticleNo::ONE, phicandidate.pt()) * efficiencyCalculator.getWeight(ParticleNo::TWO, track.pt()); - - if constexpr (std::is_same::value) - sameEventCont.setPair(track, phicandidate, multCol, ConfUse3D, weight); - else - sameEventCont.setPair(track, phicandidate, multCol, ConfUse3D, weight); + weight = effCorrection.getWeight(ParticleNo::ONE, phicandidate) * effCorrection.getWeight(ParticleNo::TWO, track); + sameEventCont.setPair(track, phicandidate, multCol, ConfUse3D, weight); } // // Used for better fitting of invariant mass background. @@ -592,7 +612,7 @@ struct FemtoUniversePairTaskTrackPhi { // } } - template + template void doMixedEvent(PartitionType groupPartsTrack, PartitionType groupPartsPhi, PartType parts, float magFieldTesla, int multCol, [[maybe_unused]] MCParticles mcParts = nullptr) { for (auto const& [track, phicandidate] : combinations(CombinationsFullIndexPolicy(groupPartsTrack, groupPartsPhi))) { @@ -612,13 +632,8 @@ struct FemtoUniversePairTaskTrackPhi { continue; } } - - weight = efficiencyCalculator.getWeight(ParticleNo::ONE, phicandidate.pt()) * efficiencyCalculator.getWeight(ParticleNo::TWO, track.pt()); - - if constexpr (std::is_same::value) - mixedEventCont.setPair(track, phicandidate, multCol, ConfUse3D, weight); - else - mixedEventCont.setPair(track, phicandidate, multCol, ConfUse3D, weight); + weight = effCorrection.getWeight(ParticleNo::ONE, phicandidate) * effCorrection.getWeight(ParticleNo::TWO, track); + mixedEventCont.setPair(track, phicandidate, multCol, ConfUse3D, weight); } } @@ -626,17 +641,14 @@ struct FemtoUniversePairTaskTrackPhi { { auto thegroupPartsTrack = partsTrack->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsPhi = partsPhi->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - // auto thegroupPartsPhiDaugh = partsPhiDaugh->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - // auto thegroupPartsKaons = partsKaons->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); eventHisto.fillQA(col); - doSameEvent(thegroupPartsTrack, thegroupPartsPhi, parts, col.magField(), col.multNtr()); + doSameEvent(thegroupPartsTrack, thegroupPartsPhi, parts, col.magField(), col.multNtr()); } PROCESS_SWITCH(FemtoUniversePairTaskTrackPhi, processSameEvent, "Enable processing same event", true); void processMixedEvent(FilteredFDCollisions const& cols, FilteredFemtoFullParticles const& parts) { for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { - const int multiplicityCol = collision1.multNtr(); mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinning.getBin({collision1.posZ(), multiplicityCol})); @@ -650,7 +662,7 @@ struct FemtoUniversePairTaskTrackPhi { continue; } - doMixedEvent(groupPartsTrack, groupPartsPhi, parts, magFieldTesla1, multiplicityCol); + doMixedEvent(groupPartsTrack, groupPartsPhi, parts, magFieldTesla1, multiplicityCol); } } PROCESS_SWITCH(FemtoUniversePairTaskTrackPhi, processMixedEvent, "Enable processing mixed events", true); @@ -658,12 +670,11 @@ struct FemtoUniversePairTaskTrackPhi { ///--------------------------------------------MC-------------------------------------------------/// void processSameEventMCReco(FilteredFDCollision const& col, FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) { + eventHisto.fillQA(col); + // Reco auto thegroupPartsTrack = partsTrackMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); auto thegroupPartsPhi = partsPhiMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - // auto thegroupPartsPhiDaugh = partsPhiDaugh->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - // auto thegroupPartsKaons = partsKaons->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - eventHisto.fillQA(col); - doSameEvent(thegroupPartsTrack, thegroupPartsPhi, parts, col.magField(), col.multNtr(), mcparts); + doSameEvent(thegroupPartsTrack, thegroupPartsPhi, parts, col.magField(), col.multNtr(), mcparts); } PROCESS_SWITCH(FemtoUniversePairTaskTrackPhi, processSameEventMCReco, "Enable processing same event for MC Reco", true); @@ -684,7 +695,7 @@ struct FemtoUniversePairTaskTrackPhi { auto groupPartsTrack = partsTrackMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); auto groupPartsPhi = partsPhiMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); - doMixedEvent(groupPartsTrack, groupPartsPhi, parts, magFieldTesla1, multiplicityCol, mcparts); + doMixedEvent(groupPartsTrack, groupPartsPhi, parts, magFieldTesla1, multiplicityCol, mcparts); } } PROCESS_SWITCH(FemtoUniversePairTaskTrackPhi, processMixedEventMCReco, "Enable processing mixed events for MC Reco", false); @@ -702,6 +713,10 @@ struct FemtoUniversePairTaskTrackPhi { continue; } + if (pdgCode == ConfTrackPDGCode) { + effCorrection.fillTruthHist(part); + } + // charge + if (pdgParticle->Charge() > 0.0) { registryMCtruth.fill(HIST("MCtruthAllPositivePt"), part.pt()); @@ -719,6 +734,7 @@ struct FemtoUniversePairTaskTrackPhi { if (pdgCode == 333) { registryMCtruth.fill(HIST("MCtruthPhi"), part.pt(), part.eta()); registryMCtruth.fill(HIST("MCtruthPhiPt"), part.pt()); + effCorrection.fillTruthHist(part); continue; } @@ -750,12 +766,12 @@ struct FemtoUniversePairTaskTrackPhi { if (mcpart.pdgMCTruth() == ConfTrackPDGCode && (part.pt() > ConfTrackPtLow) && (part.pt() < ConfTrackPtHigh) && isParticleNSigmaAccepted(part.p(), trackCuts.getNsigmaTPC(part, o2::track::PID::Proton), trackCuts.getNsigmaTOF(part, o2::track::PID::Proton), trackCuts.getNsigmaTPC(part, o2::track::PID::Pion), trackCuts.getNsigmaTOF(part, o2::track::PID::Pion), trackCuts.getNsigmaTPC(part, o2::track::PID::Kaon), trackCuts.getNsigmaTOF(part, o2::track::PID::Kaon))) { registryMCpT.fill(HIST("MCReco/NC_p_pT"), part.pt()); - float weightTrack = efficiencyCalculator.getWeight(ParticleNo::TWO, part.pt()); + float weightTrack = effCorrection.getWeight(ParticleNo::TWO, part); registryMCpT.fill(HIST("MCReco/C_p_pT"), part.pt(), weightTrack); } if ((mcpart.pdgMCTruth() == 333) && (part.partType() == aod::femtouniverseparticle::ParticleType::kPhi) && (part.pt() > ConfPhiPtLow) && (part.pt() < ConfPhiPtHigh)) { registryMCpT.fill(HIST("MCReco/NC_phi_pT"), part.pt()); - float weightPhi = efficiencyCalculator.getWeight(ParticleNo::ONE, part.pt()); + float weightPhi = effCorrection.getWeight(ParticleNo::ONE, part); registryMCpT.fill(HIST("MCReco/C_phi_pT"), part.pt(), weightPhi); } @@ -778,7 +794,6 @@ struct FemtoUniversePairTaskTrackPhi { registryMCreco.fill(HIST("MCrecoPnegPt"), mcpart.pt()); } } - } // partType kTrack } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx index 852fb802d68..06665491396 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackExtended.cxx @@ -567,7 +567,12 @@ struct FemtoUniversePairTaskTrackTrackExtended { weight *= effCorrection.getWeight(ParticleNo::TWO, p2); } - sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight); + if (swpart) + sameEventCont.setPair(p1, p2, multCol, twotracksconfigs.confUse3D, weight); + else + sameEventCont.setPair(p2, p1, multCol, twotracksconfigs.confUse3D, weight); + + swpart = !swpart; } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx index 977342a3939..2a813550b22 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackTrackSpherHarMultKtExtended.cxx @@ -182,6 +182,11 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { Configurable cfgProcessMultBins{"cfgProcessMultBins", true, "Process kstar histograms in multiplicity bins (in multiplicity bins)"}; Configurable cfgProcessKtBins{"cfgProcessKtBins", true, "Process kstar histograms in kT bins (if cfgProcessMultBins is set false, this will not be processed regardless this Configurable state)"}; Configurable cfgProcessKtMt3DCF{"cfgProcessKtMt3DCF", false, "Process 3D histograms in kT and Mult bins"}; + Configurable ConfIsFillAngqLCMS{"ConfIsFillAngqLCMS", true, "Fill qLCMS vs dEta vs dPhi"}; + 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 confCPRIsAtITS{"confCPRIsAtITS", false, "Close Pair Rejection at ITS or TPC"}; + Configurable confCPRDphiAvgOrDist{"confCPRDphiAvgOrDist", true, "Close Pair Rejection by radial or angular seperation"}; FemtoUniverseSHContainer sameEventCont; FemtoUniverseSHContainer mixedEventCont; @@ -481,8 +486,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } if (ConfIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { - continue; + if (confCPRIsAtITS.value) { + if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } else { + if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, confCPRDphiAvgOrDist, confCPRDistMax, confCPRFracMax)) { + continue; + } } } @@ -505,8 +516,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } if (ConfIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { - continue; + if (confCPRIsAtITS.value) { + if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } else { + if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::same, confCPRDphiAvgOrDist, confCPRDistMax, confCPRFracMax)) { + continue; + } } } @@ -519,12 +536,21 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { double rand; rand = randgen->Rndm(); + std::vector f3d; + double kv; + switch (ContType) { case 2: { if (rand > 0.5) { sameEventMultContPP.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else if (rand <= 0.5) { sameEventMultContPP.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::same, kv); } break; } @@ -532,8 +558,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 3: { if (rand > 0.5) { sameEventMultContMM.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else if (rand <= 0.5) { sameEventMultContMM.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::same, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::same, kv); } break; } @@ -633,8 +665,8 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// \param parts femtoUniverseParticles table (in case of Monte Carlo joined with FemtoUniverseMCLabels) /// \param magFieldTesla magnetic field of the collision /// \param multCol multiplicity of the collision - template - void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, PartType parts, float magFieldTesla, int multCol, int ContType) + template + void doMixedEvent(PartitionType groupPartsOne, PartitionType groupPartsTwo, float magFieldTesla, int multCol, int ContType) { for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { @@ -648,8 +680,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { } if (ConfIsCPR.value) { - if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::mixed)) { - continue; + if (confCPRIsAtITS.value) { + if (pairCloseRejection.isClosePairAtITS(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed)) { + continue; + } + } else { + if (pairCloseRejection.isClosePairFrac(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed, confCPRDphiAvgOrDist, confCPRDistMax, confCPRFracMax)) { + continue; + } } } @@ -657,6 +695,9 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { double rand; rand = randgen->Rndm(); + std::vector f3d; + double kv; + switch (ContType) { case 1: { if (rand > 0.5) { @@ -670,8 +711,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 2: { if (rand > 0.5) { mixedEventMultContPP.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else { mixedEventMultContPP.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed, kv); } break; } @@ -679,8 +726,14 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { case 3: { if (rand > 0.5) { mixedEventMultContMM.fillMultNumDen(p1, p2, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p1, mass1, p2, mass2, ConfIsIden); } else { mixedEventMultContMM.fillMultNumDen(p2, p1, femto_universe_sh_container::EventType::mixed, 2, multCol, kT, ConfIsIden); + f3d = FemtoUniverseMath::newpairfunc(p2, mass2, p1, mass1, ConfIsIden); + } + if (ConfIsFillAngqLCMS) { + kv = std::sqrt(f3d[1] * f3d[1] + f3d[2] * f3d[2] + f3d[3] * f3d[3]); + pairCloseRejection.ClosePairqLCMS(p1, p2, magFieldTesla, femto_universe_container::EventType::mixed, kv); } break; } @@ -693,9 +746,9 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// process function for to call doMixedEvent with Data /// @param cols subscribe to the collisions table (Data) - /// @param parts subscribe to the femtoUniverseParticleTable + /// @param subscribe to the femtoUniverseParticleTable void processMixedEventCent(FilteredFDCollisions const& cols, - FilteredFemtoFullParticles const& parts) + FilteredFemtoFullParticles const&) { randgen = new TRandom2(0); @@ -714,17 +767,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, parts, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); } 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, parts, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); } 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, parts, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); } } delete randgen; @@ -735,7 +788,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// @param cols subscribe to the collisions table (Data) /// @param parts subscribe to the femtoUniverseParticleTable void processMixedEventNtr(FilteredFDCollisions const& cols, - FilteredFemtoFullParticles const& parts) + FilteredFemtoFullParticles const&) { randgen = new TRandom2(0); @@ -754,17 +807,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, parts, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); } 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, parts, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); } 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, parts, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); } } delete randgen; @@ -796,7 +849,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table void processMixedEventMCCent(o2::aod::FdCollisions const& cols, - soa::Join const& parts, + soa::Join const&, o2::aod::FdMCParticles const&) { randgen = new TRandom2(0); @@ -818,17 +871,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, parts, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); } 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, parts, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); } 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, parts, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); } } delete randgen; @@ -840,7 +893,7 @@ struct femtoUniversePairTaskTrackTrackSpherHarMultKtExtended { /// @param parts subscribe to joined table FemtoUniverseParticles and FemtoUniverseMCLables to access Monte Carlo truth /// @param FemtoUniverseMCParticles subscribe to the Monte Carlo truth table void processMixedEventMCNtr(o2::aod::FdCollisions const& cols, - soa::Join const& parts, + soa::Join const&, o2::aod::FdMCParticles const&) { randgen = new TRandom2(0); @@ -862,17 +915,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, parts, magFieldTesla1, multiplicityCol, 1); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 1); } 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, parts, magFieldTesla1, multiplicityCol, 2); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 2); } 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, parts, magFieldTesla1, multiplicityCol, 3); + doMixedEvent(groupPartsOne, groupPartsTwo, magFieldTesla1, multiplicityCol, 3); } } delete randgen; diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx index cd8506ced21..cd7cf167027 100644 --- a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Extended.cxx @@ -15,24 +15,27 @@ /// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch /// \author Shirajum Monira, WUT Warsaw, shirajum.monira.dokt@pw.edu.pl -#include -#include -#include -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" -#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" -#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" #include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEfficiencyCorrection.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + #include #include #include +#include +#include +#include + using namespace o2; using namespace o2::soa; using namespace o2::framework; @@ -40,6 +43,7 @@ using namespace o2::framework::expressions; using namespace o2::analysis::femto_universe; using namespace o2::aod::pidutils; using namespace o2::track; +using namespace o2::analysis::femto_universe::efficiency_correction; struct FemtoUniversePairTaskTrackV0Extended { @@ -140,6 +144,9 @@ struct FemtoUniversePairTaskTrackV0Extended { // Efficiency Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; + EffCorConfigurableGroup effCorConfGroup; + EfficiencyCorrection effCorrection{&effCorConfGroup}; + static constexpr unsigned int V0ChildTable[][2] = {{0, 1}, {1, 0}, {1, 1}}; // Table to select the V0 children FemtoUniverseContainer sameEventCont; @@ -154,8 +161,6 @@ struct FemtoUniversePairTaskTrackV0Extended { HistogramRegistry registryMCtruth{"MCtruthHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry registryMCreco{"MCrecoHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; - HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; - std::unique_ptr plocalEffFile; std::unique_ptr plocalEffp1; std::unique_ptr plocalEffp2; @@ -228,7 +233,7 @@ struct FemtoUniversePairTaskTrackV0Extended { posChildV0Type2.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildV0Type2"); negChildV0Type2.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildV0Type2"); - mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + qaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); // 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}}}); @@ -300,6 +305,8 @@ struct FemtoUniversePairTaskTrackV0Extended { LOGF(info, "Loaded efficiency histograms for V0-V0."); } } + + effCorrection.init(&qaRegistry, {static_cast(confV0TempFitVarpTBins), {confEtaBins, -2, 2}, confMultBins}); } /// This function processes the same event for track - V0 template @@ -379,7 +386,7 @@ struct FemtoUniversePairTaskTrackV0Extended { } /// This function processes the same event for V0 - V0 - template + template void doSameEventV0(FilteredFDCollision const& col, PartType const& parts, PartitionType& groupPartsTwo, [[maybe_unused]] MCParticles mcParts = nullptr) { const auto& magFieldTesla = col.magField(); @@ -402,6 +409,9 @@ struct FemtoUniversePairTaskTrackV0Extended { 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); + } } /// Check daughters of second V0 particle if (isParticleTPC(posChild, V0ChildTable[confV0Type2][0]) && isParticleTPC(negChild, V0ChildTable[confV0Type2][1])) { @@ -410,6 +420,9 @@ struct FemtoUniversePairTaskTrackV0Extended { 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); + } } } @@ -481,14 +494,14 @@ struct FemtoUniversePairTaskTrackV0Extended { void processSameEventV0(FilteredFDCollision const& col, FemtoFullParticles const& parts) { auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doSameEventV0(col, parts, groupPartsTwo); + doSameEventV0(col, parts, groupPartsTwo); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processSameEventV0, "Enable processing same event for V0 - V0", false); void processSameEventV0MCReco(FilteredFDCollision const& col, FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) { auto groupPartsTwo = partsTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); - doSameEventV0(col, parts, groupPartsTwo, mcparts); + doSameEventV0(col, parts, groupPartsTwo, mcparts); } PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Extended, processSameEventV0MCReco, "Enable processing same event for V0 - V0 MC Reco", false); @@ -565,6 +578,7 @@ struct FemtoUniversePairTaskTrackV0Extended { negChildV0Type1.fillQABase(negChild, HIST("negChildV0Type1")); qaRegistry.fill(HIST("V0Type1/hInvMassLambdaVsCent"), multCol, part.mLambda()); qaRegistry.fill(HIST("V0Type1/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); + effCorrection.fillTruthHist(part); } if ((confV0Type2 == 0 && pdgCode == kLambda0) || (confV0Type2 == 1 && pdgCode == kLambda0Bar)) { trackHistoV0Type2.fillQABase(part, HIST("V0Type2")); @@ -572,6 +586,7 @@ struct FemtoUniversePairTaskTrackV0Extended { negChildV0Type2.fillQABase(negChild, HIST("negChildV0Type2")); qaRegistry.fill(HIST("V0Type2/hInvMassLambdaVsCent"), multCol, part.mLambda()); qaRegistry.fill(HIST("V0Type2/hInvMassAntiLambdaVsCent"), multCol, part.mAntiLambda()); + effCorrection.fillTruthHist(part); } } @@ -657,12 +672,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } @@ -729,12 +744,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } @@ -799,12 +814,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } @@ -837,12 +852,12 @@ struct FemtoUniversePairTaskTrackV0Extended { if (confUseCent) { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); } } else { for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { mixedCollProcessFunc(collision1, collision2); - mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + qaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); } } } diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx new file mode 100644 index 00000000000..b5fe5fbdc5a --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskTrackV0Helicity.cxx @@ -0,0 +1,976 @@ +// 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 femtoUniversePairTaskTrackV0Helicity.cxx +/// \brief Tasks that build pairs of track particles and v0s +/// \author Andi Mathis, TU München, andreas.mathis@ph.tum.de +/// \author Zuzanna Chochulska, WUT Warsaw & CTU Prague, zchochul@cern.ch +/// \author Shirajum Monira, WUT Warsaw, shirajum.monira.dokt@pw.edu.pl + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseMath.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Framework/ASoAHelpers.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 +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femto_universe; +using namespace o2::aod::pidutils; +using namespace o2::track; + +struct FemtoUniversePairTaskTrackV0Helicity { + + Service pdg; + Service pdgMC; + + SliceCache cache; + using FemtoFullParticles = soa::Join; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + using FemtoRecoParticles = soa::Join; + Preslice perColMC = aod::femtouniverseparticle::fdCollisionId; + + /// To apply narrow cut + Configurable confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; + Configurable confEta{"confEta", 0.8, "Eta cut for the global track"}; + + /// Particle 1 (track) + Configurable confTrkPDGCodePartOne{"confTrkPDGCodePartOne", 211, "Particle 1 (Track) - PDG code"}; + Configurable confTrackChoicePartOne{"confTrackChoicePartOne", 1, "0:Proton, 1:Pion, 2:Kaon"}; + ConfigurableAxis confTrkTempFitVarBins{"confTrkTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confTrkTempFitVarpTBins{"confTrkTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + Configurable confChargePart1{"confChargePart1", 0, "sign of particle 1"}; + Configurable confHPtPart1{"confHPtPart1", 4.0f, "higher limit for pt of particle 1"}; + Configurable confLPtPart1{"confLPtPart1", 0.3f, "lower limit for pt of particle 1"}; + Configurable confmom{"confmom", 0.5, "momentum threshold for particle identification using TOF"}; + Configurable confNsigmaTPCParticle{"confNsigmaTPCParticle", 3.0, "TPC Sigma for particle momentum < confmom"}; + Configurable confNsigmaCombinedParticle{"confNsigmaCombinedParticle", 3.0, "TPC and TOF Sigma (combined) for particle momentum > confmom"}; + + Filter collisionFilter = (nabs(aod::collision::posZ) < confZVertexCut); + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + Partition partsOneMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + Partition partsOneMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kTrack)) && (aod::femtouniverseparticle::sign == confChargePart1) && (nabs(aod::femtouniverseparticle::eta) < confEta) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + + /// Histogramming for particle 1 + FemtoUniverseParticleHisto trackHistoPartOnePos; + FemtoUniverseParticleHisto trackHistoPartOneNeg; + + /// Particle 2 (V0) + Configurable confV0PDGCodePartTwo{"confV0PDGCodePartTwo", 3122, "Particle 2 (V0) - PDG code"}; + ConfigurableAxis confV0TempFitVarBins{"confV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confV0TempFitVarpTBins{"confV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + Configurable confV0Type1{"confV0Type1", 0, "select one of the V0s (lambda = 0, anti-lambda = 1, k0 = 2) for v0-v0 and Track-v0 combination"}; + Configurable confV0Type2{"confV0Type2", 0, "select one of the V0s (lambda = 0, anti-lambda = 1, k0 = 2) for v0-v0 combination"}; + Configurable confV0InvMassLowLimit{"confV0InvMassLowLimit", 1.10, "Lower limit of the V0 invariant mass"}; + Configurable confV0InvMassUpLimit{"confV0InvMassUpLimit", 1.13, "Upper limit of the V0 invariant mass"}; + ConfigurableAxis confChildTempFitVarBins{"confChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; + 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 confPDGCodeV0{"confPDGCodeV0", 3122, "V0 -- PDG code"}; + Configurable confPDGCodePosChild{"confPDGCodePosChild", 2212, "Positive Child -- PDG code"}; + Configurable confPDGCodeNegChild{"confPDGCodeNegChild", 211, "Negative Child -- PDG code"}; + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + Partition partsTwoMC = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + Partition partsTwoMCReco = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + + /// Histogramming for particle 2 + FemtoUniverseParticleHisto trackHistoPartTwo; + FemtoUniverseParticleHisto posChildHistos; + FemtoUniverseParticleHisto negChildHistos; + + FemtoUniverseParticleHisto trackHistoV0Type1; + FemtoUniverseParticleHisto posChildV0Type1; + FemtoUniverseParticleHisto negChildV0Type1; + FemtoUniverseParticleHisto trackHistoV0Type2; + FemtoUniverseParticleHisto posChildV0Type2; + FemtoUniverseParticleHisto negChildV0Type2; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + /// 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 confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + Configurable confUseCent{"confUseCent", false, "Use centrality in place of multiplicity"}; + ConfigurableAxis confMultBins{"confMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis confVtxBins{"confVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + Configurable confNEventsMix{"confNEventsMix", 5, "Number of events for mixing"}; + 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 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)"}; + + // Efficiency + Configurable confLocalEfficiency{"confLocalEfficiency", "", "Local path to efficiency .root file"}; + + static constexpr unsigned int V0ChildTable[][2] = {{0, 1}, {1, 0}, {1, 1}}; // Table to select the V0 children + + FemtoUniverseContainer sameEventCont; + FemtoUniverseContainer mixedEventCont; + FemtoUniversePairCleaner pairCleaner; + FemtoUniversePairCleaner pairCleanerV0; + FemtoUniverseDetaDphiStar pairCloseRejection; + FemtoUniverseDetaDphiStar pairCloseRejectionV0; + + /// Histogram output + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry thetaRegistry{"ThetaQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry registryMCtruth{"MCtruthHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry registryMCreco{"MCrecoHistos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; + HistogramRegistry mixQaRegistry{"mixQaRegistry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + std::unique_ptr plocalEffFile; + std::unique_ptr plocalEffp1; + std::unique_ptr plocalEffp2; + + bool isNSigmaCombined(float mom, float nsigmaTPCParticle, float nsigmaTOFParticle) + { + if (mom <= confmom) { + return (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle); + } else { + return (std::hypot(nsigmaTOFParticle, nsigmaTPCParticle) < confNsigmaCombinedParticle); + } + } + + bool invMLambda(float invMassLambda, float invMassAntiLambda) + { + if ((invMassLambda < confV0InvMassLowLimit || invMassLambda > confV0InvMassUpLimit) && (invMassAntiLambda < confV0InvMassLowLimit || invMassAntiLambda > confV0InvMassUpLimit)) { + return false; + } + return true; + } + + bool isNSigmaTPC(float nsigmaTPCParticle) + { + if (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticle) { + return true; + } else { + return false; + } + } + + template + bool isParticleCombined(const T& part, int id) + { + const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; + // const float tofNSigmas[3] = {part.tofNSigmaPr(), part.tofNSigmaPi(), part.tofNSigmaKa()}; + const float tofNSigmas[3] = {unPackInTable(part.tofNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePi()), unPackInTable(part.tofNSigmaStoreKa())}; + + return isNSigmaCombined(part.p(), tpcNSigmas[id], tofNSigmas[id]); + } + + template + bool isParticleTPC(const T& part, int id) + { + const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; + + return isNSigmaTPC(tpcNSigmas[id]); + } + + void init(InitContext&) + { + eventHisto.init(&qaRegistry); + qaRegistry.add("Tracks_pos/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Tracks_pos/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Tracks_neg/nSigmaTPC", "; #it{p} (GeV/#it{c}); n#sigma_{TPC}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + qaRegistry.add("Tracks_neg/nSigmaTOF", "; #it{p} (GeV/#it{c}); n#sigma_{TOF}", kTH2F, {{100, 0, 10}, {200, -4.975, 5.025}}); + trackHistoPartOnePos.init(&qaRegistry, confTrkTempFitVarpTBins, confTrkTempFitVarBins, confIsMC, confTrkPDGCodePartOne); + trackHistoPartOneNeg.init(&qaRegistry, confTrkTempFitVarpTBins, confTrkTempFitVarBins, confIsMC, confTrkPDGCodePartOne); + trackHistoPartTwo.init(&qaRegistry, confV0TempFitVarpTBins, confV0TempFitVarBins, confIsMC, confV0PDGCodePartTwo, true); + posChildHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true); + negChildHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true); + + trackHistoV0Type1.init(&qaRegistry, confV0TempFitVarpTBins, confV0TempFitVarBins, confIsMC, confV0PDGCodePartTwo, true, "V0Type1"); + posChildV0Type1.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildV0Type1"); + negChildV0Type1.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildV0Type1"); + trackHistoV0Type2.init(&qaRegistry, confV0TempFitVarpTBins, confV0TempFitVarBins, confIsMC, confV0PDGCodePartTwo, true, "V0Type2"); + posChildV0Type2.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildV0Type2"); + negChildV0Type2.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildV0Type2"); + + // Helicity angle + thetaRegistry.add("Theta/hTheta", " ; p (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); + thetaRegistry.add("Theta/PositiveChild/hThetaPt", " ; p_{T} (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); + thetaRegistry.add("Theta/PositiveChild/hThetaEta", " ; #eta; cos(#theta)", kTH2F, {{100, -1, 1}, {110, -1.1, 1.1}}); + thetaRegistry.add("Theta/PositiveChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); + 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}}); + + mixQaRegistry.add("MixingQA/hMECollisionBins", ";bin;Entries", kTH1F, {{120, -0.5, 119.5}}); + + // MC truth + registryMCtruth.add("plus/MCtruthLambda", "MC truth Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("minus/MCtruthLambda", "MC truth Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("plus/MCtruthAllPt", "MC truth all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthAllPt", "MC truth all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + + registryMCtruth.add("plus/MCtruthPi", "MC truth pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("plus/MCtruthPr", "MC truth protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("minus/MCtruthPi", "MC truth pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCtruth.add("minus/MCtruthPr", "MC truth protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCtruth.add("plus/MCtruthPiPt", "MC truth pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("plus/MCtruthPrPt", "MC truth protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthPiPt", "MC truth pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCtruth.add("minus/MCtruthPrPt", "MC truth protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + registryMCtruth.add("ThetaMCTruth/hTheta", " ; p (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); + registryMCtruth.add("ThetaMCTruth/PositiveChild/hThetaPt", " ; p_{T} (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); + registryMCtruth.add("ThetaMCTruth/PositiveChild/hThetaEta", " ; #eta; cos(#theta)", kTH2F, {{100, -1, 1}, {110, -1.1, 1.1}}); + registryMCtruth.add("ThetaMCTruth/PositiveChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); + registryMCtruth.add("ThetaMCTruth/NegativeChild/hThetaPt", " ; p_{T} (GeV/#it{c}); cos(#theta)", kTH2F, {{100, 0, 10}, {110, -1.1, 1.1}}); + registryMCtruth.add("ThetaMCTruth/NegativeChild/hThetaEta", " ; #eta; cos(#theta)", kTH2F, {{100, -1, 1}, {110, -1.1, 1.1}}); + registryMCtruth.add("ThetaMCTruth/NegativeChild/hThetaPhi", " ; #phi; cos(#theta)", kTH2F, {{100, -1, 7}, {110, -1.1, 1.1}}); + + // MC reco + registryMCreco.add("plus/MCrecoLambda", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("plus/MCrecoLambdaChildPr", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("plus/MCrecoLambdaChildPi", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoLambda", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoLambdaChildPr", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoLambdaChildPi", "MC reco Lambdas;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCreco.add("plus/MCrecoAllPt", "MC reco all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("minus/MCrecoAllPt", "MC reco all;#it{p}_{T} (GeV/c); #eta", {HistType::kTH1F, {{500, 0, 5}}}); + + registryMCreco.add("plus/MCrecoPi", "MC reco pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("plus/MCrecoPr", "MC reco protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCreco.add("minus/MCrecoPi", "MC reco pions;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + registryMCreco.add("minus/MCrecoPr", "MC reco protons;#it{p}_{T} (GeV/c); #eta", {HistType::kTH2F, {{500, 0, 5}, {400, -1.0, 1.0}}}); + + registryMCreco.add("plus/MCrecoPiPt", "MC reco pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("plus/MCrecoPrPt", "MC reco protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("minus/MCrecoPiPt", "MC reco pions;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + registryMCreco.add("minus/MCrecoPrPt", "MC reco protons;#it{p}_{T} (GeV/c)", {HistType::kTH1F, {{500, 0, 5}}}); + + sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); + sameEventCont.setPDGCodes(confTrkPDGCodePartOne, confV0PDGCodePartTwo); + mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); + mixedEventCont.setPDGCodes(confTrkPDGCodePartOne, confV0PDGCodePartTwo); + + 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 (!confLocalEfficiency.value.empty()) { + plocalEffFile = std::unique_ptr(TFile::Open(confLocalEfficiency.value.c_str(), "read")); + if (!plocalEffFile || plocalEffFile.get()->IsZombie()) + LOGF(fatal, "Could not load efficiency histogram from %s", confLocalEfficiency.value.c_str()); + if (doprocessSameEvent || doprocessMixedEvent) { + plocalEffp1 = (confChargePart1 > 0) ? std::unique_ptr(plocalEffFile.get()->Get("PrPlus")) : std::unique_ptr(plocalEffFile.get()->Get("PrMinus")); // note: works only for protons for now + plocalEffp2 = (confV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + LOGF(info, "Loaded efficiency histograms for track-V0."); + } else if (doprocessSameEventV0 || doprocessMixedEventV0) { + plocalEffp1 = (confV0Type1 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + plocalEffp2 = (confV0Type2 == 0) ? std::unique_ptr(plocalEffFile.get()->Get("Lambda")) : std::unique_ptr(plocalEffFile.get()->Get("AntiLambda")); + LOGF(info, "Loaded efficiency histograms for V0-V0."); + } + } + } + /// This function processes the same event for track - V0 + template + void doSameEvent(FilteredFDCollision const& col, PartType const& parts, PartitionType& groupPartsOne, PartitionType& groupPartsTwo, [[maybe_unused]] MCParticles mcParts = nullptr) + { + const auto& magFieldTesla = col.magField(); + + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + + eventHisto.fillQA(col); + + /// Histogramming same event + for (const auto& part : groupPartsTwo) { + if (!invMLambda(part.mLambda(), part.mAntiLambda())) + continue; + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild, V0ChildTable[confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[confV0Type1][1])) + continue; + + auto posChildMass = pdg->Mass(confPDGCodePosChild); + auto negChildMass = pdg->Mass(confPDGCodeNegChild); + auto posChildBoosted = FemtoUniverseMath::boostPRF(posChild, posChildMass, negChild, negChildMass); + auto cosineTheta = (posChildBoosted.Px() * part.px() + posChildBoosted.Py() * part.py() + posChildBoosted.Pz() * part.pz()) / (posChildBoosted.P() * part.p()); + + trackHistoPartTwo.fillQA(part); + posChildHistos.fillQA(posChild); + negChildHistos.fillQA(negChild); + + thetaRegistry.fill(HIST("Theta/hTheta"), part.p(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaPt"), posChild.pt(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaEta"), posChild.eta(), cosineTheta); + thetaRegistry.fill(HIST("Theta/PositiveChild/hThetaPhi"), posChild.phi(), cosineTheta); + 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); + } + + for (const auto& part : groupPartsOne) { + /// PID plot for particle 1 + const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; + const float tofNSigmas[3] = {unPackInTable(part.tofNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePi()), unPackInTable(part.tofNSigmaStoreKa())}; + + if (!isNSigmaCombined(part.p(), tpcNSigmas[confTrackChoicePartOne], tofNSigmas[confTrackChoicePartOne])) + continue; + if (part.sign() > 0) { + qaRegistry.fill(HIST("Tracks_pos/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_pos/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); + trackHistoPartOnePos.fillQA(part); + } else if (part.sign() < 0) { + qaRegistry.fill(HIST("Tracks_neg/nSigmaTPC"), part.p(), tpcNSigmas[confTrackChoicePartOne]); + qaRegistry.fill(HIST("Tracks_neg/nSigmaTOF"), part.p(), tofNSigmas[confTrackChoicePartOne]); + trackHistoPartOneNeg.fillQA(part); + } + } + + /// Now build the combinations + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + // Lambda invariant mass cut + if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + continue; + /// PID using stored binned nsigma + if (!isParticleCombined(p1, confTrackChoicePartOne)) + continue; + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + if (confIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } + const auto& posChild = parts.iteratorAt(p2.index() - 2); + const auto& negChild = parts.iteratorAt(p2.index() - 1); + + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild, V0ChildTable[confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[confV0Type1][1])) + continue; + + float weight = 1.0f; + if (plocalEffp1) + weight = plocalEffp1.get()->GetBinContent(plocalEffp1->FindBin(p1.pt(), p1.eta())) * plocalEffp2.get()->GetBinContent(plocalEffp2->FindBin(p2.pt(), p2.eta())); + if constexpr (std::is_same::value) + sameEventCont.setPair(p1, p2, multCol, confUse3D, weight); + else + sameEventCont.setPair(p1, p2, multCol, confUse3D, weight); + } + } + + void processSameEvent(FilteredFDCollision const& col, FemtoFullParticles const& parts) + { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo); + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processSameEvent, "Enable processing same event for track - V0", false); + + void processSameEventMCReco(FilteredFDCollision const& col, FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + { + auto groupPartsOne = partsOneMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwoMCReco->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + doSameEvent(col, parts, groupPartsOne, groupPartsTwo, mcparts); + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processSameEventMCReco, "Enable processing same event for track - V0 MC Reco", false); + + /// This function processes the same event for V0 - V0 + void processSameEventV0(FilteredFDCollision const& col, FemtoFullParticles const& parts) + { + const auto& magFieldTesla = col.magField(); + + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + + eventHisto.fillQA(col); + + /// Histogramming same event + for (const auto& part : groupPartsTwo) { + if (!invMLambda(part.mLambda(), part.mAntiLambda())) + continue; + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + + /// Check daughters of first V0 particle + if (isParticleTPC(posChild, V0ChildTable[confV0Type1][0]) && isParticleTPC(negChild, V0ChildTable[confV0Type1][1])) { + trackHistoV0Type1.fillQABase(part, HIST("V0Type1")); + posChildV0Type1.fillQABase(posChild, HIST("posChildV0Type1")); + negChildV0Type1.fillQABase(negChild, HIST("negChildV0Type1")); + } + /// Check daughters of second V0 particle + if (isParticleTPC(posChild, V0ChildTable[confV0Type2][0]) && isParticleTPC(negChild, V0ChildTable[confV0Type2][1])) { + trackHistoV0Type2.fillQABase(part, HIST("V0Type2")); + posChildV0Type2.fillQABase(posChild, HIST("posChildV0Type2")); + negChildV0Type2.fillQABase(negChild, HIST("negChildV0Type2")); + } + } + + auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { + // Lambda invariant mass cut for p1 + if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + return; + // Lambda invariant mass cut for p2 + if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + return; + // track cleaning + if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { + return; + } + if (confIsCPR.value) { + if (pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + return; + } + } + const auto& posChild1 = parts.iteratorAt(p1.index() - 2); + const auto& negChild1 = parts.iteratorAt(p1.index() - 1); + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild1, V0ChildTable[confV0Type1][0]) || !isParticleTPC(negChild1, V0ChildTable[confV0Type1][1])) + return; + + const auto& posChild2 = parts.iteratorAt(p2.index() - 2); + const auto& negChild2 = parts.iteratorAt(p2.index() - 1); + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild2, V0ChildTable[confV0Type2][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type2][1])) + return; + + sameEventCont.setPair(p1, p2, multCol, confUse3D); + }; + if (confV0Type1 == confV0Type2) { + /// Now build the combinations for identical V0s + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } + } else { + /// Now build the combinations for not identical identical V0s + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } + } + } + + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processSameEventV0, "Enable processing same event for V0 - V0", false); + + /// This function processes MC same events for Track - V0 + void processMCSameEvent(FilteredFDCollision const& col, FemtoFullParticles const& parts) + { + const auto& magFieldTesla = col.magField(); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + + eventHisto.fillQA(col); + + /// Histogramming same event + for (const auto& part : groupPartsTwo) { + int pdgCode = static_cast(part.pidCut()); + if ((confV0Type1 == 0 && pdgCode != confPDGCodeV0) || (confV0Type1 == 1 && pdgCode != -confPDGCodeV0)) + continue; + trackHistoPartTwo.fillQA(part); + } + + for (const auto& part : groupPartsOne) { + int pdgCode = static_cast(part.pidCut()); + if (pdgCode != confTrkPDGCodePartOne) + continue; + const auto& pdgParticle = pdgMC->GetParticle(pdgCode); + if (!pdgParticle) { + continue; + } + /// PID plot for particle 1 + if (pdgParticle->Charge() > 0.0) { + trackHistoPartOnePos.fillQA(part); + } else if (pdgParticle->Charge() < 0.0) { + trackHistoPartOneNeg.fillQA(part); + } + } + + /// Now build the combinations + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (static_cast(p1.pidCut()) != confTrkPDGCodePartOne) + continue; + int pdgCode2 = static_cast(p2.pidCut()); + if ((confV0Type1 == 0 && pdgCode2 != confPDGCodeV0) || (confV0Type1 == 1 && pdgCode2 != -confPDGCodeV0)) + continue; + // track cleaning + if (confIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla, femto_universe_container::EventType::same)) { + continue; + } + } + sameEventCont.setPair(p1, p2, multCol, confUse3D); + } + } + + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMCSameEvent, "Enable processing same event for MC truth track - V0", false); + + /// This function processes MC same events for V0 - V0 + void processMCSameEventV0(FilteredFDCollision const& col, FemtoFullParticles const& /*parts*/) + { + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + const int multCol = confUseCent ? col.multV0M() : col.multNtr(); + + eventHisto.fillQA(col); + + /// Histogramming same event + for (const auto& part : groupPartsTwo) { + int pdgCode = static_cast(part.pidCut()); + if ((confV0Type1 == 0 && pdgCode != confPDGCodeV0) || (confV0Type1 == 1 && pdgCode != -confPDGCodeV0)) + continue; + trackHistoPartTwo.fillQA(part); + } + + auto pairProcessFunc = [&](auto& p1, auto& p2) -> void { + int pdgCode1 = static_cast(p1.pidCut()); + if ((confV0Type1 == 0 && pdgCode1 != confPDGCodeV0) || (confV0Type1 == 1 && pdgCode1 != -confPDGCodeV0)) + return; + int pdgCode2 = static_cast(p2.pidCut()); + if ((confV0Type2 == 0 && pdgCode2 != confPDGCodeV0) || (confV0Type2 == 1 && pdgCode2 != -confPDGCodeV0)) + return; + sameEventCont.setPair(p1, p2, multCol, confUse3D); + }; + /// Now build the combinations + if (confV0Type1 == confV0Type2) { + /// Now build the combinations for identical V0s + for (const auto& [p1, p2] : combinations(CombinationsStrictlyUpperIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } + } else { + /// Now build the combinations for not identical identical V0s + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsTwo, groupPartsTwo))) { + pairProcessFunc(p1, p2); + } + } + } + + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMCSameEventV0, "Enable processing same event for MC truth V0 - V0", false); + + /// This function processes the mixed event for track - V0 + template + void doMixedEvent(FilteredFDCollisions const& cols, PartType const& parts, PartitionType& partitionOne, PartitionType& partitionTwo, [[maybe_unused]] MCParticles mcParts = nullptr) + { + ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; + ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { + const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); + + auto groupPartsOne = partitionOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partitionTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + return; + } + + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + // Lambda invariant mass cut + if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) + continue; + /// PID using stored binned nsigma + if (!isParticleCombined(p1, confTrackChoicePartOne)) + continue; + + const auto& posChild = parts.iteratorAt(p2.globalIndex() - 2); + const auto& negChild = parts.iteratorAt(p2.globalIndex() - 1); + /// Daughters that do not pass this condition are not selected + if (!isParticleTPC(posChild, V0ChildTable[confV0Type1][0]) || !isParticleTPC(negChild, V0ChildTable[confV0Type1][1])) + continue; + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + if (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 constexpr (std::is_same::value) + mixedEventCont.setPair(p1, p2, multCol, confUse3D, weight); + else + mixedEventCont.setPair(p1, p2, multCol, confUse3D, weight); + } + }; + + if (confUseCent) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + } + } else { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + } + } + } + + void processMixedEvent(FilteredFDCollisions const& cols, FemtoFullParticles const& parts) + { + doMixedEvent(cols, parts, partsOne, partsTwo); + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMixedEvent, "Enable processing mixed event for track - V0", false); + + void processMixedEventMCReco(FilteredFDCollisions const& cols, FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + { + doMixedEvent(cols, parts, partsOneMCReco, partsTwoMCReco, mcparts); + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMixedEventMCReco, "Enable processing mixed event for track - V0 for MC Reco", false); + + /// This function processes the mixed event for V0 - V0 + void processMixedEventV0(FilteredFDCollisions const& cols, FemtoFullParticles const& parts) + { + ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; + ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { + const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); + + auto groupPartsOne = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + return; + } + + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + // Lambda invariant mass cut for p1 + if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) { + continue; + } + // Lambda invariant mass cut for p2 + if (!invMLambda(p2.mLambda(), p2.mAntiLambda())) { + 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[confV0Type1][0]) || !isParticleTPC(negChild1, V0ChildTable[confV0Type1][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[confV0Type2][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type2][1])) + continue; + + // track cleaning + if (!pairCleanerV0.isCleanPair(p1, p2, parts)) { + continue; + } + if (confIsCPR.value) { + if (pairCloseRejectionV0.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + continue; + } + } + mixedEventCont.setPair(p1, p2, multCol, confUse3D); + } + }; + + if (confUseCent) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + } + } else { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMixedEventV0, "Enable processing mixed events for V0 - V0", false); + + /// This function processes MC mixed events for Track - V0 + void processMCMixedEvent(FilteredFDCollisions const& cols, FemtoFullParticles const& parts) + { + ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; + ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { + const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); + + auto groupPartsOne = partsOneMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + return; + } + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (static_cast(p1.pidCut()) != confTrkPDGCodePartOne) + continue; + int pdgCode2 = static_cast(p2.pidCut()); + if ((confV0Type1 == 0 && pdgCode2 != confPDGCodeV0) || (confV0Type1 == 1 && pdgCode2 != -confPDGCodeV0)) + continue; + if (confIsCPR.value) { + if (pairCloseRejection.isClosePair(p1, p2, parts, magFieldTesla1, femto_universe_container::EventType::mixed)) { + continue; + } + } + mixedEventCont.setPair(p1, p2, multCol, confUse3D); + } + }; + + if (confUseCent) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + } + } else { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + } + } + } + + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMCMixedEvent, "Enable processing mixed events for MC truth track - V0", false); + + /// This function processes MC mixed events for V0 - V0 + void processMCMixedEventV0(FilteredFDCollisions const& cols, FemtoFullParticles const& /*parts*/) + { + ColumnBinningPolicy colBinningMult{{confVtxBins, confMultBins}, true}; + ColumnBinningPolicy colBinningCent{{confVtxBins, confMultBins}, true}; + + auto mixedCollProcessFunc = [&](auto& collision1, auto& collision2) -> void { + const int multCol = confUseCent ? collision1.multV0M() : collision1.multNtr(); + + auto groupPartsOne = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwoMC->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + int pdgCode1 = static_cast(p1.pidCut()); + if ((confV0Type1 == 0 && pdgCode1 != confPDGCodeV0) || (confV0Type1 == 1 && pdgCode1 != -confPDGCodeV0)) + continue; + int pdgCode2 = static_cast(p2.pidCut()); + if ((confV0Type2 == 0 && pdgCode2 != confPDGCodeV0) || (confV0Type2 == 1 && pdgCode2 != -confPDGCodeV0)) + continue; + mixedEventCont.setPair(p1, p2, multCol, confUse3D); + } + }; + + if (confUseCent) { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningCent, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningCent.getBin({collision1.posZ(), collision1.multV0M()})); + } + } else { + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinningMult, confNEventsMix, -1, cols, cols)) { + mixedCollProcessFunc(collision1, collision2); + mixQaRegistry.fill(HIST("MixingQA/hMECollisionBins"), colBinningMult.getBin({collision1.posZ(), collision1.multNtr()})); + } + } + } + + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMCMixedEventV0, "Enable processing mixed events for MC truth V0 - V0", false); + ///--------------------------------------------MC-------------------------------------------------/// + + /// This function fills MC truth particles from derived MC table + void processMCTruth(aod::FDParticles const& parts) + { + for (const auto& part : parts) { + if (part.partType() != uint8_t(aod::femtouniverseparticle::ParticleType::kMCTruthTrack)) + continue; + + int pdgCode = static_cast(part.pidCut()); + const auto& pdgParticle = pdgMC->GetParticle(pdgCode); + if (!pdgParticle) { + continue; + } + + if (pdgCode == 3122) { + registryMCtruth.fill(HIST("plus/MCtruthLambda"), part.pt(), part.eta()); + continue; + } else if (pdgCode == -3122) { + registryMCtruth.fill(HIST("minus/MCtruthLambda"), part.pt(), part.eta()); + continue; + } + + if (pdgParticle->Charge() > 0.0) { + registryMCtruth.fill(HIST("plus/MCtruthAllPt"), part.pt()); + } + if (pdgCode == 211) { + registryMCtruth.fill(HIST("plus/MCtruthPi"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("plus/MCtruthPiPt"), part.pt()); + } + if (pdgCode == 2212) { + registryMCtruth.fill(HIST("plus/MCtruthPr"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("plus/MCtruthPrPt"), part.pt()); + } + + if (pdgParticle->Charge() < 0.0) { + registryMCtruth.fill(HIST("minus/MCtruthAllPt"), part.pt()); + } + if (pdgCode == -211) { + registryMCtruth.fill(HIST("minus/MCtruthPi"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("minus/MCtruthPiPt"), part.pt()); + } + if (pdgCode == -2212) { + registryMCtruth.fill(HIST("minus/MCtruthPr"), part.pt(), part.eta()); + registryMCtruth.fill(HIST("minus/MCtruthPrPt"), part.pt()); + } + + // Helicity angle + const auto& posChild = parts.iteratorAt(part.index() - 2); + const auto& negChild = parts.iteratorAt(part.index() - 1); + + auto posChildMass = pdg->Mass(confPDGCodePosChild); + auto negChildMass = pdg->Mass(confPDGCodeNegChild); + auto posChildBoosted = FemtoUniverseMath::boostPRF(posChild, posChildMass, negChild, negChildMass); + auto cosineTheta = (posChildBoosted.Px() * part.px() + posChildBoosted.Py() * part.py() + posChildBoosted.Pz() * part.pz()) / (posChildBoosted.P() * part.p()); + + registryMCtruth.fill(HIST("ThetaMCTruth/hTheta"), part.p(), cosineTheta); + registryMCtruth.fill(HIST("ThetaMCTruth/PositiveChild/hThetaPt"), posChild.pt(), cosineTheta); + registryMCtruth.fill(HIST("ThetaMCTruth/PositiveChild/hThetaEta"), posChild.eta(), cosineTheta); + registryMCtruth.fill(HIST("ThetaMCTruth/PositiveChild/hThetaPhi"), posChild.phi(), cosineTheta); + registryMCtruth.fill(HIST("ThetaMCTruth/NegativeChild/hThetaPt"), negChild.pt(), cosineTheta); + registryMCtruth.fill(HIST("ThetaMCTruth/NegativeChild/hThetaEta"), negChild.eta(), cosineTheta); + registryMCtruth.fill(HIST("ThetaMCTruth/NegativeChild/hThetaPhi"), negChild.phi(), cosineTheta); + } + } + + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMCTruth, "Process MC truth data", false); + + void processMCReco(FemtoRecoParticles const& parts, aod::FdMCParticles const& mcparts) + { + for (const auto& part : parts) { + auto mcPartId = part.fdMCParticleId(); + if (mcPartId == -1) + continue; // no MC particle + const auto& mcpart = mcparts.iteratorAt(mcPartId); + // + if (part.partType() == aod::femtouniverseparticle::ParticleType::kV0) { + if (mcpart.pdgMCTruth() == 3122) { + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); + /// Daughters that do not pass this condition are not selected + if (isParticleTPC(posChild, 0) && isParticleTPC(negChild, 1)) { + registryMCreco.fill(HIST("plus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // lambda + if (auto mcpartIdChild = posChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("plus/MCrecoLambdaChildPr"), mcpartChild.pt(), mcpartChild.eta()); // lambda proton child + } + if (auto mcpartIdChild = negChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("plus/MCrecoLambdaChildPi"), mcpartChild.pt(), mcpartChild.eta()); // lambda pion child + } + } + } else if (mcpart.pdgMCTruth() == -3122) { + const auto& posChild = parts.iteratorAt(part.globalIndex() - 2); + const auto& negChild = parts.iteratorAt(part.globalIndex() - 1); + /// Daughters that do not pass this condition are not selected + if (isParticleTPC(posChild, 1) && isParticleTPC(negChild, 0)) { + registryMCreco.fill(HIST("minus/MCrecoLambda"), mcpart.pt(), mcpart.eta()); // anti-lambda + if (auto mcpartIdChild = posChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("minus/MCrecoLambdaChildPi"), mcpartChild.pt(), mcpartChild.eta()); // anti-lambda pion child + } + if (auto mcpartIdChild = negChild.fdMCParticleId(); mcpartIdChild != -1) { + const auto& mcpartChild = mcparts.iteratorAt(mcpartIdChild); + registryMCreco.fill(HIST("minus/MCrecoLambdaChildPr"), mcpartChild.pt(), mcpartChild.eta()); // anti-lambda proton child + } + } + } + } else if (part.partType() == aod::femtouniverseparticle::ParticleType::kTrack) { + if (part.sign() > 0) { + registryMCreco.fill(HIST("plus/MCrecoAllPt"), mcpart.pt()); + if (mcpart.pdgMCTruth() == 211 && isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tofNSigmaStorePi()))) { + registryMCreco.fill(HIST("plus/MCrecoPi"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("plus/MCrecoPiPt"), mcpart.pt()); + } else if (mcpart.pdgMCTruth() == 2212 && isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) { + registryMCreco.fill(HIST("plus/MCrecoPr"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("plus/MCrecoPrPt"), mcpart.pt()); + } + } + + if (part.sign() < 0) { + registryMCreco.fill(HIST("minus/MCrecoAllPt"), mcpart.pt()); + if (mcpart.pdgMCTruth() == -211 && isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tofNSigmaStorePi()))) { + registryMCreco.fill(HIST("minus/MCrecoPi"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("minus/MCrecoPiPt"), mcpart.pt()); + } else if (mcpart.pdgMCTruth() == -2212 && isNSigmaCombined(part.p(), unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePr()))) { + registryMCreco.fill(HIST("minus/MCrecoPr"), mcpart.pt(), mcpart.eta()); + registryMCreco.fill(HIST("minus/MCrecoPrPt"), mcpart.pt()); + } + } + } // partType + } + } + + PROCESS_SWITCH(FemtoUniversePairTaskTrackV0Helicity, processMCReco, "Process MC reco data", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskV0CascadeExtended.cxx b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskV0CascadeExtended.cxx new file mode 100644 index 00000000000..a9212ab208a --- /dev/null +++ b/PWGCF/FemtoUniverse/Tasks/femtoUniversePairTaskV0CascadeExtended.cxx @@ -0,0 +1,329 @@ +// 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 femtoUniversePairTaskV0CascadeExtended.cxx +/// \brief Task for v0-cascade correlations and QA +/// \author Shirajum Monira, WUT Warsaw, shirajum.monira@cern.ch + +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseContainer.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseDetaDphiStar.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseEventHisto.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniversePairCleaner.h" +#include "PWGCF/FemtoUniverse/Core/FemtoUniverseParticleHisto.h" +#include "PWGCF/FemtoUniverse/Core/femtoUtils.h" +#include "PWGCF/FemtoUniverse/DataModel/FemtoDerived.h" + +#include "Framework/ASoAHelpers.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 +#include + +using namespace o2; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::analysis::femto_universe; +using namespace o2::aod::pidutils; + +struct FemtoUniversePairTaskV0CascadeExtended { + + SliceCache cache; + using FemtoParticles = soa::Join; + Preslice perCol = aod::femtouniverseparticle::fdCollisionId; + + /// applying narrow cut + Configurable confZVertexCut{"confZVertexCut", 10.f, "Event sel: Maximum z-Vertex (cm)"}; + + Filter collisionFilter = (nabs(aod::collision::posZ) < confZVertexCut); + using FilteredFDCollisions = soa::Filtered; + using FilteredFDCollision = FilteredFDCollisions::iterator; + + /// particle 1 (v0) + Configurable confHPtPart1{"confHPtPart1", 4.0f, "higher limit for pt of particle 1"}; + Configurable confLPtPart1{"confLPtPart1", 0.5f, "lower limit for pt of particle 1"}; + Configurable confV0Type{"confV0Type", 0, "select one of the V0s (lambda = 0, anti-lambda = 1, k0 = 2)"}; + Configurable confV0InvMassLowLimit{"confV0InvMassLowLimit", 1.10, "Lower limit of the V0 invariant mass"}; + Configurable confV0InvMassUpLimit{"confV0InvMassUpLimit", 1.13, "Upper limit of the V0 invariant mass"}; + Configurable confV0PDGCode{"confV0PDGCode", 3122, "Particle 1 (V0) - PDG code"}; + + /// particle 2 (cascade) + 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 confCascType{"confCascType", 0, "select one of the cascades (Omega = 0, Xi = 1, anti-Omega = 2, anti-Xi = 3)"}; + Configurable confCascInvMassLowLimit{"confCascInvMassLowLimit", 1.315, "Lower limit of the cascade invariant mass"}; + Configurable confCascInvMassUpLimit{"confCascInvMassUpLimit", 1.325, "Upper limit of the cascade invariant mass"}; + + /// nSigma cuts + Configurable confmom{"confmom", 0.75, "momentum threshold for particle identification using TOF"}; + Configurable confNsigmaTPCParticleChild{"confNsigmaTPCParticleChild", 3.0, "TPC Sigma for cascade (daugh & bach) momentum < Confmom"}; + Configurable confNsigmaTOFParticleChild{"confNsigmaTOFParticleChild", 3.0, "TOF Sigma for cascade (daugh & bach) momentum > Confmom"}; + + /// for correlation part + Configurable confIsMC{"confIsMC", false, "Enable additional Histograms in the case of a MonteCarlo Run"}; + ConfigurableAxis confkstarBins{"confkstarBins", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis confMultBins{"confMultBins", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f, 200.0f, 99999.f}, "Mixing bins - multiplicity"}; + ConfigurableAxis confkTBins{"confkTBins", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis confmTBins{"confmTBins", {225, 0., 7.5}, "binning mT"}; + 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 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)"}; + Configurable confEtaBins{"confEtaBins", 29, "Number of eta bins in deta dphi"}; + Configurable confPhiBins{"confPhiBins", 29, "Number of phi bins in deta dphi"}; + Configurable confUse3D{"confUse3D", false, "Enable three dimensional histogramms (to be used only for analysis with high statistics): k* vs mT vs multiplicity"}; + ConfigurableAxis confVtxBins{"confVtxBins", {VARIABLE_WIDTH, -10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}, "Mixing bins - z-vertex"}; + ConfigurableAxis confTrkTempFitVarpTBins{"confTrkTempFitVarpTBins", {20, 0.5, 4.05}, "pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis confTrkTempFitVarBins{"confTrkTempFitVarBins", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confChildTempFitVarBins{"confChildTempFitVarBins", {300, -0.15, 0.15}, "V0 child: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + ConfigurableAxis confChildTempFitVarpTBins{"confChildTempFitVarpTBins", {20, 0.5, 4.05}, "V0 child: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis confV0TempFitVarpTBins{"confV0TempFitVarpTBins", {20, 0.5, 4.05}, "V0: pT binning of the pT vs. TempFitVar plot"}; + ConfigurableAxis confV0TempFitVarBins{"confV0TempFitVarBins", {300, 0.95, 1.}, "V0: binning of the TempFitVar in the pT vs. TempFitVar plot"}; + + /// Partition for particle 1 + Partition partsOne = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kV0)) && (aod::femtouniverseparticle::pt < confHPtPart1) && (aod::femtouniverseparticle::pt > confLPtPart1); + + /// Partition for particle 2 + Partition partsTwo = (aod::femtouniverseparticle::partType == uint8_t(aod::femtouniverseparticle::ParticleType::kCascade)) && (aod::femtouniverseparticle::pt < confHPtPart2) && (aod::femtouniverseparticle::pt > confLPtPart2); + + /// Histogramming for v0 + FemtoUniverseParticleHisto trackHistoV0; + FemtoUniverseParticleHisto posChildV0; + FemtoUniverseParticleHisto negChildV0; + + /// Histogramming for cascade + FemtoUniverseParticleHisto posChildHistosCasc; + FemtoUniverseParticleHisto negChildHistosCasc; + FemtoUniverseParticleHisto bachHistosCasc; + FemtoUniverseParticleHisto cascQAHistos; + + /// Histogramming for Event + FemtoUniverseEventHisto eventHisto; + + FemtoUniverseContainer sameEventCont; + FemtoUniverseContainer mixedEventCont; + FemtoUniversePairCleaner pairCleaner; + + HistogramRegistry qaRegistry{"TrackQA", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry resultRegistry{"Correlations", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Table to select v0 daughters + static constexpr unsigned int V0ChildTable[][2] = {{0, 1}, {1, 0}, {1, 1}}; + + bool invMLambda(float invMassLambda, float invMassAntiLambda) + { + if ((invMassLambda < confV0InvMassLowLimit || invMassLambda > confV0InvMassUpLimit) && (invMassAntiLambda < confV0InvMassLowLimit || invMassAntiLambda > confV0InvMassUpLimit)) { + return false; + } + return true; + } + + // Table to select cascade daughters + // Charges: = +--, +--, +-+, +-+ + static constexpr unsigned int CascChildTable[][3] = {{0, 1, 2}, {0, 1, 1}, {1, 0, 2}, {1, 0, 1}}; + + bool invMCascade(float invMassXi, float invMassOmega, int cascType) + { + return (((cascType == 1 || cascType == 3) && (invMassXi > confCascInvMassLowLimit && invMassXi < confCascInvMassUpLimit)) || ((cascType == 0 || cascType == 2) && (invMassOmega > confCascInvMassLowLimit && invMassOmega < confCascInvMassUpLimit))); + } + + bool isNSigmaTPC(float nsigmaTPCParticle) + { + if (std::abs(nsigmaTPCParticle) < confNsigmaTPCParticleChild) { + return true; + } else { + return false; + } + } + + bool isNSigmaTOF(float mom, float nsigmaTOFParticle, float hasTOF) + { + // Cut only on daughter and bachelor tracks, that have TOF signal + if (mom > confmom && hasTOF == 1) { + if (std::abs(nsigmaTOFParticle) < confNsigmaTOFParticleChild) { + return true; + } else { + return false; + } + } else { + return true; + } + } + + template + bool isParticleTPC(const T& part, int id) + { + const float tpcNSigmas[3] = {unPackInTable(part.tpcNSigmaStorePr()), unPackInTable(part.tpcNSigmaStorePi()), unPackInTable(part.tpcNSigmaStoreKa())}; + + return isNSigmaTPC(tpcNSigmas[id]); + } + + template + bool isParticleTOF(const T& part, int id) + { + const float tofNSigmas[3] = {unPackInTable(part.tofNSigmaStorePr()), unPackInTable(part.tofNSigmaStorePi()), unPackInTable(part.tofNSigmaStoreKa())}; + + return isNSigmaTOF(part.p(), tofNSigmas[id], part.tempFitVar()); + } + + void init(InitContext const&) + { + trackHistoV0.init(&qaRegistry, confV0TempFitVarpTBins, confV0TempFitVarBins, confIsMC, confV0PDGCode, true, "trackHistoV0"); + posChildV0.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildV0"); + negChildV0.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildV0"); + + posChildHistosCasc.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "posChildCasc"); + negChildHistosCasc.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "negChildCasc"); + bachHistosCasc.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true, "hBachelor"); + cascQAHistos.init(&qaRegistry, confChildTempFitVarpTBins, confChildTempFitVarBins, false, 0, true); + + sameEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); + mixedEventCont.init(&resultRegistry, confkstarBins, confMultBins, confkTBins, confmTBins, confMultBins3D, confmTBins3D, confEtaBins, confPhiBins, confIsMC, confUse3D); + pairCleaner.init(&qaRegistry); + } + + /// v0-cascade correlations same event + void processSameEvent(const FilteredFDCollision& col, const FemtoParticles& parts) + { + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, col.globalIndex(), cache); + + eventHisto.fillQA(col); + + for (const auto& part : groupPartsTwo) { + /// inv Mass check for cascade + if (!invMCascade(part.mLambda(), part.mAntiLambda(), confCascType)) + continue; + + cascQAHistos.fillQA(part); + + const auto& posChild1 = parts.iteratorAt(part.index() - 3); + const auto& negChild1 = parts.iteratorAt(part.index() - 2); + const auto& bachelor1 = parts.iteratorAt(part.index() - 1); + /// Children of cascade must pass this condition to be selected + if (!isParticleTPC(posChild1, CascChildTable[confCascType][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType][2])) + continue; + + if (!isParticleTOF(posChild1, CascChildTable[confCascType][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType][2])) + continue; + + posChildHistosCasc.fillQABase(posChild1, HIST("posChildCasc")); + negChildHistosCasc.fillQABase(negChild1, HIST("negChildCasc")); + bachHistosCasc.fillQABase(bachelor1, HIST("hBachelor")); + } + for (const auto& part : groupPartsOne) { + /// inv Mass check for V0s + if (!invMLambda(part.mLambda(), part.mAntiLambda())) + continue; + const auto& posChild2 = parts.iteratorAt(part.index() - 2); + const auto& negChild2 = parts.iteratorAt(part.index() - 1); + /// Daughters of v0 must pass this condition to be selected + if (!isParticleTPC(posChild2, V0ChildTable[confV0Type][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type][1])) + continue; + + trackHistoV0.fillQABase(part, HIST("trackHistoV0")); + posChildV0.fillQABase(posChild2, HIST("posChildV0")); + negChildV0.fillQABase(negChild2, HIST("negChildV0")); + } + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + continue; + // Cascase inv Mass cut (mLambda stores Xi mass, mAntiLambda stored Omega mass) + if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType)) + continue; + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + // V0 + const auto& posChild2 = parts.iteratorAt(p1.index() - 2); + const auto& negChild2 = parts.iteratorAt(p1.index() - 1); + /// Daughters of v0 must pass this condition to be selected + if (!isParticleTPC(posChild2, V0ChildTable[confV0Type][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type][1])) + continue; + // cascade + const auto& posChild1 = parts.iteratorAt(p2.index() - 3); + const auto& negChild1 = parts.iteratorAt(p2.index() - 2); + const auto& bachelor1 = parts.iteratorAt(p2.index() - 1); + /// Daughters of cascade must pass this condition to be selected + if (!isParticleTPC(posChild1, CascChildTable[confCascType][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType][2])) + continue; + + if (!isParticleTOF(posChild1, CascChildTable[confCascType][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType][2])) + continue; + + sameEventCont.setPair(p1, p2, col.multNtr(), confUse3D, 1.0f); + } + } + PROCESS_SWITCH(FemtoUniversePairTaskV0CascadeExtended, processSameEvent, "Enable processing same event for v0 - cascade", false); + + /// v0-cascade correlations mixed event + void processMixedEvent(const FilteredFDCollisions& cols, const FemtoParticles& parts) + { + ColumnBinningPolicy colBinning{{confVtxBins, confMultBins}, true}; + + for (const auto& [collision1, collision2] : soa::selfCombinations(colBinning, 5, -1, cols, cols)) { + const int multCol = collision1.multNtr(); + + auto groupPartsOne = partsOne->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision1.globalIndex(), cache); + auto groupPartsTwo = partsTwo->sliceByCached(aod::femtouniverseparticle::fdCollisionId, collision2.globalIndex(), cache); + + const auto& magFieldTesla1 = collision1.magField(); + const auto& magFieldTesla2 = collision2.magField(); + + if (magFieldTesla1 != magFieldTesla2) { + continue; + } + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(groupPartsOne, groupPartsTwo))) { + if (!invMLambda(p1.mLambda(), p1.mAntiLambda())) + continue; + // Cascase inv Mass cut (mLambda stores Xi mass, mAntiLambda stored Omega mass) + if (!invMCascade(p2.mLambda(), p2.mAntiLambda(), confCascType)) + continue; + // V0 + const auto& posChild2 = parts.iteratorAt(p1.index() - 2); + const auto& negChild2 = parts.iteratorAt(p1.index() - 1); + /// Daughters of v0 must pass this condition to be selected + if (!isParticleTPC(posChild2, V0ChildTable[confV0Type][0]) || !isParticleTPC(negChild2, V0ChildTable[confV0Type][1])) + continue; + // cascade + const auto& posChild1 = parts.iteratorAt(p2.index() - 3); + const auto& negChild1 = parts.iteratorAt(p2.index() - 2); + const auto& bachelor1 = parts.iteratorAt(p2.index() - 1); + /// Daughters of cascade must pass this condition to be selected + if (!isParticleTPC(posChild1, CascChildTable[confCascType][0]) || !isParticleTPC(negChild1, CascChildTable[confCascType][1]) || !isParticleTPC(bachelor1, CascChildTable[confCascType][2])) + continue; + + if (!isParticleTOF(posChild1, CascChildTable[confCascType][0]) || !isParticleTOF(negChild1, CascChildTable[confCascType][1]) || !isParticleTOF(bachelor1, CascChildTable[confCascType][2])) + continue; + + // track cleaning + if (!pairCleaner.isCleanPair(p1, p2, parts)) { + continue; + } + + mixedEventCont.setPair(p1, p2, multCol, confUse3D, 1.0f); + } + } + } + PROCESS_SWITCH(FemtoUniversePairTaskV0CascadeExtended, processMixedEvent, "Enable processing mixed event for v0 - cascade", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc), + }; + return workflow; +} diff --git a/PWGCF/Flow/TableProducer/zdcQVectors.cxx b/PWGCF/Flow/TableProducer/zdcQVectors.cxx index f8ba2cbb0b7..c748b1f51ec 100644 --- a/PWGCF/Flow/TableProducer/zdcQVectors.cxx +++ b/PWGCF/Flow/TableProducer/zdcQVectors.cxx @@ -144,6 +144,7 @@ struct ZdcQVectors { using BCsRun3 = soa::Join; enum SelectionCriteria { + evSel_FilteredEvent, evSel_Zvtx, evSel_sel8, evSel_occupancy, @@ -228,8 +229,8 @@ struct ZdcQVectors { } // end of capCOORDS } // end of sides - registry.add("QA/centrality_before", "centrality_before", kTH1D, {{200, 0, 100}}); - registry.add("QA/centrality_after", "centrality_after", kTH1D, {{200, 0, 100}}); + registry.add("QA/centrality_before", "centrality_before", kTH1D, {{100, 0, 100}}); + registry.add("QA/centrality_after", "centrality_after", kTH1D, {{100, 0, 100}}); registry.add("QA/ZNA_Energy", "ZNA_Energy", kTProfile, {{8, 0, 8}}); registry.add("QA/ZNC_Energy", "ZNC_Energy", kTProfile, {{8, 0, 8}}); @@ -251,12 +252,31 @@ struct ZdcQVectors { registry.add("QA/before/ZNC_Qx", "ZNC_Qx", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNC_Qy", "ZNC_Qy", kTProfile, {{1, 0, 1.}}); + registry.add("QA/before/ZNA_Qx_vs_Centrality", "ZNA_Qx_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + registry.add("QA/before/ZNA_Qy_vs_Centrality", "ZNA_Qy_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + registry.add("QA/before/ZNC_Qx_vs_Centrality", "ZNC_Qx_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + registry.add("QA/before/ZNC_Qy_vs_Centrality", "ZNC_Qy_vs_Centrality", kTH2D, {{100, 0, 100}, {200, -2, 2}}); + + registry.add("QA/before/ZNA_pmC_vs_Centrality", "ZNA_pmC_vs_Centrality", kTH2D, {{100, 0, 100}, {300, 0, 300}}); + registry.add("QA/before/ZNA_pmSUM_vs_Centrality", "ZNA_pmSUM_vs_Centrality", kTH2D, {{100, 0, 100}, {300, 0, 300}}); + registry.add("QA/before/ZNA_pm1_vs_Centrality", "ZNA_pm1_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + registry.add("QA/before/ZNA_pm2_vs_Centrality", "ZNA_pm2_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + registry.add("QA/before/ZNA_pm3_vs_Centrality", "ZNA_pm3_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + registry.add("QA/before/ZNA_pm4_vs_Centrality", "ZNA_pm4_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + + registry.add("QA/before/ZNC_pmC_vs_Centrality", "ZNC_pmC_vs_Centrality", kTH2D, {{100, 0, 100}, {300, 0, 300}}); + registry.add("QA/before/ZNC_pmSUM_vs_Centrality", "ZNC_pmSUM_vs_Centrality", kTH2D, {{100, 0, 100}, {300, 0, 300}}); + registry.add("QA/before/ZNC_pm1_vs_Centrality", "ZNC_pm1_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + registry.add("QA/before/ZNC_pm2_vs_Centrality", "ZNC_pm2_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + registry.add("QA/before/ZNC_pm3_vs_Centrality", "ZNC_pm3_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + registry.add("QA/before/ZNC_pm4_vs_Centrality", "ZNC_pm4_vs_Centrality", kTH2D, {{100, 0, 100}, {100, 0, 1}}); + + registry.addClone("QA/before/", "QA/after/"); + registry.add("QA/before/ZNA_Qx_noEq", "ZNA_Qx_noEq", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNA_Qy_noEq", "ZNA_Qy_noEq", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNC_Qx_noEq", "ZNC_Qx_noEq", kTProfile, {{1, 0, 1.}}); registry.add("QA/before/ZNC_Qy_noEq", "ZNC_Qy_noEq", kTProfile, {{1, 0, 1.}}); - - registry.addClone("QA/before/", "QA/after/"); } // Tower mean energies vs. centrality used for tower gain equalisation @@ -273,6 +293,7 @@ struct ZdcQVectors { registry.add("vmean/hvertex_vz", "hvertex_vz", kTProfile, {{1, 0., 1.}}); registry.add("hEventCount", "Number of Event; Cut; #Events Passed Cut", {HistType::kTH1D, {{nEventSelections, 0, nEventSelections}}}); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_FilteredEvent + 1, "Filtered events"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_Zvtx + 1, "Z vertex cut event"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_sel8 + 1, "Sel8"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_occupancy + 1, "kOccupancy"); @@ -290,7 +311,7 @@ struct ZdcQVectors { { if (std::fabs(collision.posZ()) > cfgVtxZ) return 0; - registry.fill(HIST("hEventCount"), evSel_sel8); + registry.fill(HIST("hEventCount"), evSel_Zvtx); if (!collision.sel8()) return 0; @@ -403,6 +424,11 @@ 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("/ZNA_Qx_vs_Centrality"), centrality, qxa); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNA_Qy_vs_Centrality"), centrality, qya); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNC_Qx_vs_Centrality"), centrality, qxc); + registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/ZNC_Qy_vs_Centrality"), centrality, qyc); + // add psi!! double psiA = 1.0 * std::atan2(qxc, qxa); registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/hSPplaneA"), psiA, centrality, 1); @@ -536,6 +562,8 @@ struct ZdcQVectors { if (cfgFillCommonRegistry) registry.fill(HIST("QA/centrality_before"), cent); + registry.fill(HIST("hEventCount"), evSel_FilteredEvent); + if (!eventSelected(collision, cent)) { // event not selected isSelected = false; @@ -560,6 +588,7 @@ struct ZdcQVectors { runnumber = foundBC.runNumber(); // load new calibrations for new runs only + // UPLOAD Energy calibration and vmean in 1 histogram! if (runnumber != lastRunNumber) { cal.calibfilesLoaded[2] = false; cal.calibList[2] = nullptr; @@ -587,11 +616,9 @@ struct ZdcQVectors { // load the calibrations for the mean v loadCalibrations(foundBC.timestamp(), cfgMeanv.value); - if (!cal.calibfilesLoaded[1]) { - registry.get(HIST("vmean/hvertex_vx"))->Fill(Form("%d", runnumber), v[0]); - registry.get(HIST("vmean/hvertex_vy"))->Fill(Form("%d", runnumber), v[1]); - registry.get(HIST("vmean/hvertex_vz"))->Fill(Form("%d", runnumber), v[2]); - } + registry.get(HIST("vmean/hvertex_vx"))->Fill(Form("%d", runnumber), v[0]); + registry.get(HIST("vmean/hvertex_vy"))->Fill(Form("%d", runnumber), v[1]); + registry.get(HIST("vmean/hvertex_vz"))->Fill(Form("%d", runnumber), v[2]); bool isZNAhit = true; bool isZNChit = true; @@ -679,6 +706,7 @@ struct ZdcQVectors { registry.get(HIST("QA/before/ZNC_pm3"))->Fill(Form("%d", runnumber), eZN[6]); registry.get(HIST("QA/before/ZNC_pm4"))->Fill(Form("%d", runnumber), eZN[7]); + registry.get(HIST("QA/after/ZNA_pm1"))->Fill(Form("%d", runnumber), e[0]); registry.get(HIST("QA/after/ZNA_pm2"))->Fill(Form("%d", runnumber), e[1]); registry.get(HIST("QA/after/ZNA_pm3"))->Fill(Form("%d", runnumber), e[2]); registry.get(HIST("QA/after/ZNA_pm4"))->Fill(Form("%d", runnumber), e[3]); @@ -686,6 +714,40 @@ struct ZdcQVectors { registry.get(HIST("QA/after/ZNC_pm2"))->Fill(Form("%d", runnumber), e[5]); registry.get(HIST("QA/after/ZNC_pm3"))->Fill(Form("%d", runnumber), e[6]); registry.get(HIST("QA/after/ZNC_pm4"))->Fill(Form("%d", runnumber), e[7]); + + double sumZNAbefore = eZN[0] + eZN[1] + eZN[2] + eZN[3]; + double sumZNAafter = e[0] + e[1] + e[2] + e[3]; + + double sumZNCbefore = eZN[4] + eZN[5] + eZN[6] + eZN[7]; + double sumZNCafter = e[4] + e[5] + e[6] + e[7]; + + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNA()); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pmSUM_vs_Centrality"), centrality, sumZNAbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm1_vs_Centrality"), centrality, eZN[0] / sumZNAbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm2_vs_Centrality"), centrality, eZN[1] / sumZNAbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm3_vs_Centrality"), centrality, eZN[2] / sumZNAbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNA_pm4_vs_Centrality"), centrality, eZN[3] / sumZNAbefore); + + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNC()); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pmSUM_vs_Centrality"), centrality, sumZNCbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm1_vs_Centrality"), centrality, eZN[4] / sumZNCbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm2_vs_Centrality"), centrality, eZN[5] / sumZNCbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm3_vs_Centrality"), centrality, eZN[6] / sumZNCbefore); + registry.fill(HIST("QA/") + HIST("before") + HIST("/ZNC_pm4_vs_Centrality"), centrality, eZN[7] / sumZNCbefore); + + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNA()); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pmSUM_vs_Centrality"), centrality, sumZNAafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm1_vs_Centrality"), centrality, e[0] / sumZNAafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm2_vs_Centrality"), centrality, e[1] / sumZNAafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm3_vs_Centrality"), centrality, e[2] / sumZNAafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNA_pm4_vs_Centrality"), centrality, e[3] / sumZNAafter); + + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pmC_vs_Centrality"), centrality, zdcCol.energyCommonZNC()); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pmSUM_vs_Centrality"), centrality, sumZNCafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm1_vs_Centrality"), centrality, e[4] / sumZNCafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm2_vs_Centrality"), centrality, e[5] / sumZNCafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm3_vs_Centrality"), centrality, e[6] / sumZNCafter); + registry.fill(HIST("QA/") + HIST("after") + HIST("/ZNC_pm4_vs_Centrality"), centrality, e[7] / sumZNCafter); } // Now calculate Q-vector diff --git a/PWGCF/Flow/Tasks/CMakeLists.txt b/PWGCF/Flow/Tasks/CMakeLists.txt index c59895487cf..e368eef4c73 100644 --- a/PWGCF/Flow/Tasks/CMakeLists.txt +++ b/PWGCF/Flow/Tasks/CMakeLists.txt @@ -83,3 +83,8 @@ o2physics_add_dpl_workflow(flow-ese-p-he3 SOURCES flowEsePHe3.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(flow-ese-task + SOURCES flowEseTask.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/Flow/Tasks/flowEsePHe3.cxx b/PWGCF/Flow/Tasks/flowEsePHe3.cxx index 61582f233b3..2a4955c1419 100644 --- a/PWGCF/Flow/Tasks/flowEsePHe3.cxx +++ b/PWGCF/Flow/Tasks/flowEsePHe3.cxx @@ -36,6 +36,8 @@ #include "Framework/RunningWorkflowInfo.h" #include "Framework/StaticFor.h" +#include "DataFormatsTPC/BetheBlochAleph.h" + #include "Common/DataModel/Qvectors.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" @@ -51,45 +53,299 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; namespace o2::aod { -namespace flow_ese_p_he3 +namespace ese_var_table { -DECLARE_SOA_COLUMN(NPidFlag, nPidFlag, int8_t); // unqualified -1, hadron 0, proton 1, he3 2, proton+he3 3 -} // namespace flow_ese_p_he3 -DECLARE_SOA_TABLE(PHe3ESEFlags, "AOD", "PHe3ESEFlags", flow_ese_p_he3::NPidFlag); +DECLARE_SOA_COLUMN(EseVtz, eseVtz, float); +DECLARE_SOA_COLUMN(EseCentFT0C, eseCentFT0C, float); +DECLARE_SOA_COLUMN(EsePsi2FT0C, esePsi2FT0C, float); +DECLARE_SOA_COLUMN(Eseq2Tar, eseq2Tar, float); +DECLARE_SOA_COLUMN(Eseq2Ref, eseq2Ref, float); +DECLARE_SOA_COLUMN(EseTarSign, eseTarSign, int8_t); +DECLARE_SOA_COLUMN(EseTarTPCInnerParam, eseTarTPCInnerParam, float); +DECLARE_SOA_COLUMN(EseTarTPCSignal, eseTarTPCSignal, float); +DECLARE_SOA_COLUMN(EseTarPt, eseTarPt, float); +DECLARE_SOA_COLUMN(EseTarEta, eseTarEta, float); +DECLARE_SOA_COLUMN(EseTarPhi, eseTarPhi, float); +DECLARE_SOA_COLUMN(EseTarDCAxy, eseTarDCAxy, float); +DECLARE_SOA_COLUMN(EseTarDCAz, eseTarDCAz, float); +DECLARE_SOA_COLUMN(EseTarTPCNcls, eseTarTPCNcls, uint8_t); +DECLARE_SOA_COLUMN(EseTarITSNcls, eseTarITSNcls, uint8_t); +DECLARE_SOA_COLUMN(EseTarTPCChi2NDF, eseTarTPCChi2NDF, float); +DECLARE_SOA_COLUMN(EseTarITSChi2NDF, eseTarITSChi2NDF, float); +DECLARE_SOA_COLUMN(EseTarTPCNSigma, eseTarTPCNSigma, float); +DECLARE_SOA_COLUMN(EseTarTOFNSigma, eseTarTOFNSigma, float); +DECLARE_SOA_COLUMN(EseTarITSNSigma, eseTarITSNSigma, float); +DECLARE_SOA_COLUMN(EseTarITSClusSize, eseTarITSClusSize, uint32_t); +} // namespace ese_var_table + +DECLARE_SOA_TABLE(ESETable, "AOD", "ESETable", + ese_var_table::EseVtz, + ese_var_table::EseCentFT0C, + ese_var_table::EsePsi2FT0C, + ese_var_table::Eseq2Tar, + ese_var_table::Eseq2Ref, + ese_var_table::EseTarSign, + ese_var_table::EseTarTPCInnerParam, + ese_var_table::EseTarTPCSignal, + ese_var_table::EseTarPt, + ese_var_table::EseTarEta, + ese_var_table::EseTarPhi, + ese_var_table::EseTarDCAxy, + ese_var_table::EseTarDCAz, + ese_var_table::EseTarTPCNcls, + ese_var_table::EseTarITSNcls, + ese_var_table::EseTarTPCChi2NDF, + ese_var_table::EseTarITSChi2NDF, + ese_var_table::EseTarTPCNSigma, + ese_var_table::EseTarTOFNSigma, + ese_var_table::EseTarITSNSigma, + ese_var_table::EseTarITSClusSize); } // namespace o2::aod -namespace pid_flags -{ -// constexpr int8_t kUnqualified = -1; -// constexpr int8_t kUnPOIHadron = 0; -constexpr int8_t kProton = 1; -constexpr int8_t kHe3 = 2; -constexpr int8_t kProtonHe3 = 3; -} // namespace pid_flags - -namespace event_selection -{ -constexpr int kFT0AV0ASigma = 5; -} +struct ESECandidate { + float vtz; + float centFT0C; + float psi2FT0C; + float q2Tar; + float q2Ref; + int8_t signTar; + float tpcInnerParamTar; + float tpcSignalTar; + float ptTar; + float etaTar; + float phiTar; + float dcaXYTar; + float dcaZTar; + uint8_t tpcNclsTar; + uint8_t itsNclsTar; + float tpcChi2NDFTar; + float itsChi2NDFTar; + float tpcNSigmaTar; + float tofNSigmaTar; + float itsNSigmaTar; + uint32_t itsClusSizeTar; +}; + +struct ESEReference { + int8_t signRef; + float ptRef; + float v2Ref; +}; -namespace fourier_mode +namespace ese_parameters { -// constexpr int kMode1 = 1; -constexpr int kMode2 = 2; -// constexpr int kMode3 = 3; -} // namespace fourier_mode +constexpr uint8_t kProton = 0; +constexpr uint8_t kDeuteron = 1; +constexpr uint8_t kTriton = 2; +constexpr uint8_t kHe3 = 3; +constexpr uint8_t kAlpha = 4; +constexpr uint8_t kPion = 5; +constexpr uint8_t kKaon = 6; +constexpr uint8_t kHadron = 7; +constexpr int kFT0AV0ASigma = 5; +constexpr int kRMSMode = 0; +constexpr int kTPCMode = 1; +constexpr int kTOFOnlyMode = 2; +constexpr float Amplitudelow = 1e-8; +constexpr float Charges[8]{1.f, 1.f, 1.f, 2.f, 2.f, 1.f, 1.f, 1.f}; +constexpr float Masses[5]{MassProton, MassDeuteron, MassTriton, MassHelium3, MassAlpha}; +constexpr double BetheBlochDefault[5][6]{ + {-136.71, 0.441, 0.2269, 1.347, 0.8035, 0.09}, + {-136.71, 0.441, 0.2269, 1.347, 0.8035, 0.09}, + {-239.99, 1.155, 1.099, 1.137, 1.006, 0.09}, + {-321.34, 0.6539, 1.591, 0.8225, 2.363, 0.09}, + {-586.66, 1.859, 4.435, 0.282, 3.201, 0.09}}; +constexpr double BbMomScalingDefault[5][2]{// 0:poscharged 1:negcharged + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}, + {1., 1.}}; +constexpr int Open3DPIDPlots[3][1]{ + {0}, + {0}, + {0}}; +constexpr int OpenEvSel[10][1]{ + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {0}, + {1}}; +constexpr int OpenTrackSel[7][1]{ + {1}, + {1}, + {1}, + {1}, + {1}, + {1}, + {1}}; +constexpr double TPCnSigmaCutDefault[7][2]{ + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}}; +constexpr double ITSnSigmaCutDefault[7][2]{ + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}, + {-3., 3.}}; +constexpr double POverZPreselection[7][2]{ + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}, + {0.15, 99.}}; +constexpr double EtaPreselection[7][2]{ + {0.9}, + {0.9}, + {0.9}, + {0.8}, + {0.9}, + {0.9}, + {0.9}}; +constexpr double TPCNclsPreselection[7][2]{ + {50, 160}, + {50, 160}, + {50, 160}, + {100, 160}, + {50, 160}, + {50, 160}, + {50, 160}}; +constexpr double ITSNclsPreselection[7][2]{ + {5, 7}, + {5, 7}, + {5, 7}, + {5, 7}, + {5, 7}, + {5, 7}, + {5, 7}}; +constexpr double TPCChi2Preselection[7][2]{ + {0, 10}, + {0, 10}, + {0, 10}, + {0.5, 4}, + {0, 10}, + {0, 10}, + {0, 10}}; +constexpr double ITSChi2Preselection[7][2]{ + {0, 36}, + {0, 36}, + {0, 36}, + {0, 36}, + {0, 36}, + {0, 36}, + {0, 36}}; +constexpr double DCAxyPreselection[7][2]{ + {1}, + {1}, + {1}, + {0.1}, + {1}, + {1}, + {1}, +}; +constexpr double DCAzPreselection[7][2]{ + {5}, + {5}, + {5}, + {1}, + {5}, + {5}, + {5}, +}; +static const std::vector names{"proton", "deuteron", "triton", "He3", "alpha"}; +static const std::vector namesFull{"proton", "deuteron", "triton", "He3", "alpha", "pion", "kaon"}; +static const std::vector chargeLabelNames{"Positive", "Negative"}; +static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; +static const std::vector plot3DPIDNames{"TOF vs ITS", "ITS vs TPC", "TOF vs TPC"}; +static const std::vector openEventSelNames{"EvSelkIsGoodZvtxFT0vsPV", "EvSelkNoSameBunchPileup", "EvSelkNoCollInTimeRangeStandard", "EvSelkIsGoodITSLayersAll", "EvSelkNoCollInRofStandard", "EvSelkNoHighMultCollInPrevRof", "EvSelOccupancy", "EvSelMultCorrelationPVTracks", "EvSelMultCorrelationGlobalTracks", "EvSelV0AT0ACut"}; +static const std::vector openTrackSelNames{"passedITSNCls", "passedITSChi2NDF", "passedITSHits", "passedTPCChi2NDF", "passedTPCCrossedRowsOverNCls", "passedDCAxy", "passedDCAz"}; +static const std::vector plot3DConfigNames{"Open related 3D nSigma plots"}; +static const std::vector openEventSelConfigNames{"Open related event selection options"}; +static const std::vector openTrackSelConfigNames{"Open track selection from TrackSelection table"}; +static const std::vector pidTPCnSigmaNames{"n#sigma_{TPC} Low", "n#sigma_{TPC} High"}; +static const std::vector pidITSnSigmaNames{"n#sigma_{ITS} Low", "n#sigma_{ITS} High"}; +static const std::vector pidPOverZNames{"p/z Low", "p/z High"}; +static const std::vector pidEtaNames{"Abs Eta Max"}; +static const std::vector pidTPCNclsNames{"TPCNcls Low", "TPCNcls High"}; +static const std::vector pidITSNclsNames{"ITSNcls Low", "ITSNcls High"}; +static const std::vector pidTPCChi2Names{"TPCChi2 Low", "TPCChi2 High"}; +static const std::vector pidITSChi2Names{"ITSChi2 Low", "ITSChi2 High"}; +static const std::vector pidDCAxyNames{"Abs DCAxy Max"}; +static const std::vector pidDCAzNames{"Abs DCAz Max"}; +std::vector eseCandidates; +std::vector eseReferences; +// Tar ptr +std::shared_ptr hPIDQATar1D[12]; +std::shared_ptr hPIDQATar2D[4]; +std::shared_ptr hPIDQATar3D[3]; +std::shared_ptr hv2Tar[2]; +std::shared_ptr hESEQATar1D[4]; +std::shared_ptr hESEQATar2D; +std::shared_ptr hESETar; +// Ref ptr +std::shared_ptr hPIDQARef1D[12]; +std::shared_ptr hPIDQARef2D[4]; +std::shared_ptr hPIDQARef3D[3]; +std::shared_ptr hv2Ref[2]; +std::shared_ptr hESEQARef1D[4]; +std::shared_ptr hESEQARef2D; +} // namespace ese_parameters -using TracksPID = soa::Join; -struct FillPIDcolums { +using TracksPIDFull = soa::Join; - HistogramRegistry histosQA{"histosQAPID", {}, OutputObjHandlingPolicy::AnalysisObject}; +struct FlowEsePHe3 { + EventPlaneHelper helperEP; + o2::aod::ITSResponse itsResponse; + HistogramRegistry histsESE{"histsESE", {}, OutputObjHandlingPolicy::AnalysisObject}; + // process POI control + Configurable cfgTarName{"cfgTarName", "kHe3", "Name of the v2 particle: kProton, kDeuteron, kTriton, kHe3, kAlpha"}; + Configurable cfgRefName{"cfgRefName", "kProton", "Name of the q2 reference particle: kProton, kDeuteron, kTriton, kHe3, kAlpha"}; + // total control config + Configurable cfgOpenAllowCrossTrack{"cfgOpenAllowCrossTrack", true, "Allow one track to be identified as different kind of PID particles"}; + Configurable cfgOpenFullEventQA{"cfgOpenFullEventQA", true, "Open full QA plots for event QA"}; + Configurable cfgOpenPIDQA{"cfgOpenPIDQA", true, "Open PID QA plots"}; + Configurable cfgOpenv2Tar{"cfgOpenv2Tar", true, "Open v2(EP) for Tar patricle"}; + Configurable cfgOpenv2Ref{"cfgOpenv2Ref", true, "Open v2(EP) for Ref patricle"}; + Configurable cfgOpenESE{"cfgOpenESE", true, "Open ESE plots"}; + Configurable cfgOpenESEQA{"cfgOpenESEQA", true, "Open ESE QA plots"}; + Configurable> cfgOpen3DPIDPlots{"cfgOpen3DPIDPlots", {ese_parameters::Open3DPIDPlots[0], 3, 1, ese_parameters::plot3DPIDNames, ese_parameters::plot3DConfigNames}, "3D PID QA Plots switch configuration"}; + // Qvec configs + Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; + Configurable cfgRefAName{"cfgRefAName", "TPCpos", "The name of detector for reference A"}; + Configurable cfgRefBName{"cfgRefBName", "TPCneg", "The name of detector for reference B"}; + Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "total qvector number"}; + // pre event selection(filter) + Configurable cfgVtzCut{"cfgVtzCut", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCentMin{"cfgCentMin", 0.0f, "Centrality min"}; + Configurable cfgCentMax{"cfgCentMax", 100.0f, "Centrality max"}; + // event selection configs + Configurable cfgCutOccupancyLow{"cfgCutOccupancyLow", 0, "Low boundary cut on TPC occupancy"}; + Configurable cfgCutOccupancyHigh{"cfgCutOccupancyHigh", 3000, "High boundary cut on TPC occupancy"}; + Configurable> cfgOpenEvSel{"cfgOpenEvSel", {ese_parameters::OpenEvSel[0], 10, 1, ese_parameters::openEventSelNames, ese_parameters::openEventSelConfigNames}, "Event selection switch configuration"}; + // track selection configs + Configurable> cfgOpenTrackSel{"cfgOpenTrackSel", {ese_parameters::OpenTrackSel[0], 7, 1, ese_parameters::openTrackSelNames, ese_parameters::openTrackSelConfigNames}, "Track selection switch configuration"}; Configurable cfgMinPtPID{"cfgMinPtPID", 0.15, "Minimum track #P_{t} for PID"}; Configurable cfgMaxPtPID{"cfgMaxPtPID", 99.9, "Maximum track #P_{t} for PID"}; - Configurable cfgMaxEtaPID{"cfgMaxEtaPID", 0.8, "Maximum track #eta for PID"}; + Configurable cfgMaxEtaPID{"cfgMaxEtaPID", 0.9, "Maximum track #eta for PID"}; Configurable cfgMinTPCChi2NCl{"cfgMinTPCChi2NCl", 0, "Minimum chi2 per cluster TPC for PID if not use costom track cuts"}; Configurable cfgMinChi2NClITS{"cfgMinChi2NClITS", 0, "Minimum chi2 per cluster ITS for PID if not use costom track cuts"}; Configurable cfgMaxTPCChi2NCl{"cfgMaxTPCChi2NCl", 4, "Maximum chi2 per cluster TPC for PID if not use costom track cuts"}; @@ -100,517 +356,216 @@ struct FillPIDcolums { Configurable cfgMaxITSCls{"cfgMaxITSCls", 999, "Max ITS clusters for PID if not use costom track cuts"}; Configurable cfgMaxDCAxy{"cfgMaxDCAxy", 99, "Maxium DCAxy for standard PID tracking"}; Configurable cfgMaxDCAz{"cfgMaxDCAz", 2, "Maxium DCAz for standard PID tracking"}; - Configurable cfgPtMaxforTPCOnlyPIDPrton{"cfgPtMaxforTPCOnlyPIDPrton", 0.4, "Maxmium track pt for TPC only PID, at RMS PID mode for proton"}; - Configurable cfgPtMaxforTPCOnlyPIDHe3{"cfgPtMaxforTPCOnlyPIDHe3", 0.5, "Maxmium track pt for TPC only PID, at RMS PID mode for he3"}; - - Configurable cfgProtonPIDMode{"cfgProtonPIDMode", 2, "Proton PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; - Configurable cfgHe3PIDMode{"cfgHe3PIDMode", 1, "He3 PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; - - Configurable cfgOpenpassedITSNCls{"cfgOpenpassedITSNCls", false, "useTrackSelectionTables passedITSNCls for basic track selection"}; - Configurable cfgOpenpassedITSChi2NDF{"cfgOpenpassedITSChi2NDF", false, "useTrackSelectionTables passedITSChi2NDF for basic track selection"}; - Configurable cfgOpenpassedITSHits{"cfgOpenpassedITSHits", false, "useTrackSelectionTables passedITSHits for basic track selection"}; - Configurable cfgOpenpassedTPCChi2NDF{"cfgOpenpassedTPCChi2NDF", false, "useTrackSelectionTables passedTPCChi2NDF for basic track selection"}; - Configurable cfgOpenpassedTPCCrossedRowsOverNCls{"cfgOpenpassedTPCCrossedRowsOverNCls", false, "useTrackSelectionTables passedTPCCrossedRowsOverNCls for basic track selection"}; - Configurable cfgOpenpassedDCAxy{"cfgOpenpassedDCAxy", false, "useTrackSelectionTables passedDCAxy for basic track selection"}; - Configurable cfgOpenpassedDCAz{"cfgOpenpassedDCAz", false, "useTrackSelectionTables passedDCAz for basic track selection"}; - - Configurable cfgQuietMode{"cfgQuietMode", false, "open quiet mode for saving cpu cost and only do some basic QA plots"}; - Configurable cfgOpenPIDITSProton{"cfgOpenPIDITSProton", true, "open ITS assistance cut for proton PID"}; - Configurable cfgOpenPIDITSHe3{"cfgOpenPIDITSHe3", false, "open ITS assistance cut for He3 PID"}; - Configurable cfgOpenPIDByPtProtonMain{"cfgOpenPIDByPtProtonMain", false, "Selection Proton by pt its pt binnings for main selection"}; - Configurable cfgOpenPIDByPtHe3Main{"cfgOpenPIDByPtHe3Main", false, "Selection He3 by pt its pt binnings for main selection"}; - Configurable cfgOpenPIDByPtProtonITS{"cfgOpenPIDByPtProtonITS", false, "Selection Proton by pt its pt binnings for ITS selection"}; - Configurable cfgOpenPIDByPtHe3ITS{"cfgOpenPIDByPtHe3ITS", false, "Selection He3 by pt its pt binnings for ITS selection"}; - Configurable cfgOpenHe3ITSPtCut{"cfgOpenHe3ITSPtCut", true, "Do He3 ITS contamination cut"}; - Configurable cfgOpenAllowCrossTrack{"cfgOpenAllowCrossTrack", false, "Allow one track to be identified as different kind of PID particles"}; - - Configurable cfgOpenPlotnSigmaTOFITSPt{"cfgOpenPlotnSigmaTOFITSPt", true, "plot nSigmaTOF vs nSigmaITS vs Pt"}; - Configurable cfgOpenPlotnSigmaITSTPCPt{"cfgOpenPlotnSigmaITSTPCPt", true, "plot nSigmaITS vs nSigmaTOF vs Pt"}; - Configurable cfgOpenPlotnSigmaTOFTPCPt{"cfgOpenPlotnSigmaTOFTPCPt", true, "plot nSigmaTOF vs nSigmaTPC vs Pt"}; - - Configurable> cfgPtCutProton{"cfgPtCutProton", {0.15, 99.}, "Pt limit for Proton"}; - Configurable> cfgPtCutHe3{"cfgPtCutHe3", {0.15, 99.}, "Pt limit for He3"}; - Configurable> cfgnSigmaCutTPCProton{"cfgnSigmaCutTPCProton", {-3, 3}, "TPC nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutTPCHe3{"cfgnSigmaCutTPCHe3", {-2, 2}, "TPC nsigma cut limit for He3"}; + Configurable cfgPtMaxforTPCOnlyPIDProton{"cfgPtMaxforTPCOnlyPIDProton", 0.4, "Maxmium track pt for TPC only PID, at RMS PID mode for proton"}; + Configurable cfgPtMaxforTPCOnlyPIDPion{"cfgPtMaxforTPCOnlyPIDPion", 0.4, "Maxmium track pt for TPC only PID, at RMS PID mode for pion"}; + Configurable cfgPtMaxforTPCOnlyPIDKaon{"cfgPtMaxforTPCOnlyPIDKaon", 0.4, "Maxmium track pt for TPC only PID, at RMS PID mode for kaon"}; + // PID configs + Configurable cfgOpenITSPreselection{"cfgOpenITSPreselection", false, "Use nSigma ITS preselection for light nuclei"}; + Configurable> cfgPOverZPreselection{"cfgPOverZPreselection", {ese_parameters::POverZPreselection[0], 7, 2, ese_parameters::namesFull, ese_parameters::pidPOverZNames}, "P/Z preselection for light nuclei"}; + Configurable> cfgEtaPreselection{"cfgEtaPreselection", {ese_parameters::EtaPreselection[0], 7, 1, ese_parameters::namesFull, ese_parameters::pidEtaNames}, "Eta preselection for light nuclei"}; + Configurable> cfgTPCNclsPreselection{"cfgTPCNclsPreselection", {ese_parameters::TPCNclsPreselection[0], 7, 2, ese_parameters::namesFull, ese_parameters::pidTPCNclsNames}, "TPCNcls preselection for light nuclei"}; + Configurable> cfgITSNclsPreselection{"cfgITSNclsPreselection", {ese_parameters::ITSNclsPreselection[0], 7, 2, ese_parameters::namesFull, ese_parameters::pidITSNclsNames}, "ITSNcls preselection for light nuclei"}; + Configurable> cfgTPCChi2Preselection{"cfgTPCChi2Preselection", {ese_parameters::TPCChi2Preselection[0], 7, 2, ese_parameters::namesFull, ese_parameters::pidTPCChi2Names}, "TPCChi2 preselection for light nuclei"}; + Configurable> cfgITSChi2Preselection{"cfgITSChi2Preselection", {ese_parameters::ITSChi2Preselection[0], 7, 2, ese_parameters::namesFull, ese_parameters::pidITSChi2Names}, "ITSChi2 preselection for light nuclei"}; + Configurable> cfgDCAxyPreselection{"cfgDCAxyPreselection", {ese_parameters::DCAxyPreselection[0], 7, 1, ese_parameters::namesFull, ese_parameters::pidDCAxyNames}, "DCAxy preselection for light nuclei"}; + Configurable> cfgDCAzPreselection{"cfgDCAzPreselection", {ese_parameters::DCAzPreselection[0], 7, 1, ese_parameters::namesFull, ese_parameters::pidDCAzNames}, "DCAz preselection for light nuclei"}; Configurable> cfgnSigmaCutTOFProton{"cfgnSigmaCutTOFProton", {-1.5, 1.5}, "TOF nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutTOFHe3{"cfgnSigmaCutTOFHe3", {-1.5, 1.5}, "TOF nsigma cut limit for He3"}; - Configurable> cfgnSigmaCutITSProton{"cfgnSigmaCutITSProton", {-3, 3}, "ITS nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutITSHe3{"cfgnSigmaCutITSHe3", {-3, 3}, "ITS nsigma cut limit for He3"}; Configurable> cfgnSigmaCutRMSProton{"cfgnSigmaCutRMSProton", {-3, 3}, "RMS nsigma cut limit for Proton"}; - Configurable> cfgnSigmaCutRMSHe3{"cfgnSigmaCutRMSHe3", {-3, 3}, "RMS nsigma cut limit for He3"}; - - Configurable> cfgPtBinProtonPID{"cfgPtBinProtonPID", {0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 3.0, 3.5, 4.0, 5.0, 6.0}, "pt bin for pion PIDnsigma"}; - Configurable> cfgPtBinHe3PID{"cfgPtBinHe3PID", {2, 2.2, 2.4, 2.6, 2.8, 3, 3.2, 3.6, 4, 4.4, 4.8, 5.2, 5.6, 6, 6.4, 7.2, 8, 10}, "pt bin for pion PIDnsigma"}; - - Configurable> cfgnSigmaTPCProtonPtUpper{"cfgnSigmaTPCProtonPtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaTPC cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTOFProtonPtUpper{"cfgnSigmaTOFProtonPtUpper", {1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5}, "nSigmaTOF cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaITSProtonPtUpper{"cfgnSigmaITSProtonPtUpper", {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, "nSigmaITS cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaRMSProtonPtUpper{"cfgnSigmaRMSProtonPtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaRMS cut upper limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTPCProtonPtLower{"cfgnSigmaTPCProtonPtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaTPC cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTOFProtonPtLower{"cfgnSigmaTOFProtonPtLower", {-1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5}, "nSigmaTOF cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaITSProtonPtLower{"cfgnSigmaITSProtonPtLower", {-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, "nSigmaITS cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaRMSProtonPtLower{"cfgnSigmaRMSProtonPtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaRMS cut lower limit anchored to proton pt bins"}; - Configurable> cfgnSigmaTPCHe3PtUpper{"cfgnSigmaTPCHe3PtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaTPC cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaTOFHe3PtUpper{"cfgnSigmaTOFHe3PtUpper", {1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5}, "nSigmaTOF cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaITSHe3PtUpper{"cfgnSigmaITSHe3PtUpper", {2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}, "nSigmaITS cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaRMSHe3PtUpper{"cfgnSigmaRMSHe3PtUpper", {3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3}, "nSigmaRMS cut upper limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaTPCHe3PtLower{"cfgnSigmaTPCHe3PtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaTPC cut lower limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaTOFHe3PtLower{"cfgnSigmaTOFHe3PtLower", {-1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5, -1.5}, "nSigmaTOF cut lower limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaITSHe3PtLower{"cfgnSigmaITSHe3PtLower", {-2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2}, "nSigmaITS cut lower limit anchored to He3 pt bins"}; - Configurable> cfgnSigmaRMSHe3PtLower{"cfgnSigmaRMSHe3PtLower", {-3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3}, "nSigmaRMS cut lower limit anchored to He3 pt bins"}; - - ConfigurableAxis cfgrigidityBins{"cfgrigidityBins", {200, -10.f, 10.f}, "Binning for rigidity #it{p}^{TPC}/#it{z}"}; - ConfigurableAxis cfgdedxBins{"cfgdedxBins", {1000, 0.f, 1000.f}, "Binning for dE/dx"}; + Configurable> cfgnSigmaCutTOFPion{"cfgnSigmaCutTOFPion", {-1.5, 1.5}, "TOF nsigma cut limit for Pion"}; + Configurable> cfgnSigmaCutRMSPion{"cfgnSigmaCutRMSPion", {-3, 3}, "RMS nsigma cut limit for Pion"}; + Configurable> cfgnSigmaCutTOFKaon{"cfgnSigmaCutTOFKaon", {-1.5, 1.5}, "TOF nsigma cut limit for Kaon"}; + Configurable> cfgnSigmaCutRMSKaon{"cfgnSigmaCutRMSKaon", {-3, 3}, "RMS nsigma cut limit for Kaon"}; + Configurable cfgUseSelfnSigmaTPCProton{"cfgUseSelfnSigmaTPCProton", true, "Use self nSigma TPC for Proton PID"}; + Configurable cfgProtonPIDMode{"cfgProtonPIDMode", 2, "Proton PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; + Configurable cfgPionPIDMode{"cfgPionPIDMode", 2, "Pion PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; + Configurable cfgKaonPIDMode{"cfgKaonPIDMode", 2, "Kaon PID mode: 0 for TPC + RMS(TPC,TOF), 1 for TPC only, 2 for TOF only"}; + Configurable> cfgnSigmaTPC{"cfgnSigmaTPC", {ese_parameters::TPCnSigmaCutDefault[0], 7, 2, ese_parameters::namesFull, ese_parameters::pidTPCnSigmaNames}, "TPC nSigma selection for light nuclei"}; + Configurable> cfgnSigmaITS{"cfgnSigmaITS", {ese_parameters::ITSnSigmaCutDefault[0], 7, 2, ese_parameters::namesFull, ese_parameters::pidITSnSigmaNames}, "ITS nSigma selection for light nuclei"}; + // PID BBself paras config + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {ese_parameters::BetheBlochDefault[0], 5, 6, ese_parameters::names, ese_parameters::betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgMomentumScalingBetheBloch{"cfgMomentumScalingBetheBloch", {ese_parameters::BbMomScalingDefault[0], 5, 2, ese_parameters::names, ese_parameters::chargeLabelNames}, "TPC Bethe-Bloch momentum scaling for light nuclei"}; + Configurable cfgCompensatePIDinTracking{"cfgCompensatePIDinTracking", true, "If true, divide tpcInnerParam by the electric charge"}; + // Axias configs ConfigurableAxis cfgnSigmaBinsTPC{"cfgnSigmaBinsTPC", {200, -5.f, 5.f}, "Binning for n sigma TPC"}; ConfigurableAxis cfgnSigmaBinsTOF{"cfgnSigmaBinsTOF", {200, -5.f, 5.f}, "Binning for n sigma TOF"}; ConfigurableAxis cfgnSigmaBinsITS{"cfgnSigmaBinsITS", {200, -5.f, 5.f}, "Binning for n sigma ITS"}; - ConfigurableAxis cfgnSigmaBinsRMS{"cfgnSigmaBinsRMS", {100, 0.f, 10.f}, "Combination Binning for TPC&TOF nsigma"}; - ConfigurableAxis cfgaxisptPID{"cfgaxisptPID", {120, 0, 12}, "Binning for P_{t} PID"}; - ConfigurableAxis cfgaxispPID{"cfgaxispPID", {50, 0, 5}, "Binning for P PID"}; - ConfigurableAxis cfgaxisetaPID{"cfgaxisetaPID", {90, -0.9, 0.9}, "Binning for Pt QA"}; + ConfigurableAxis cfgaxispt{"cfgaxispt", {100, 0, 10}, "Binning for P_{t}"}; ConfigurableAxis cfgaxisDCAz{"cfgaxisDCAz", {200, -1, 1}, "Binning for DCAz"}; ConfigurableAxis cfgaxisDCAxy{"cfgaxisDCAxy", {100, -0.5, 0.5}, "Binning for DCAxy"}; - ConfigurableAxis cfgaxisChi2Ncls{"cfgaxisChi2Ncls", {100, 0, 100}, "Binning for Chi2Ncls TPC/ITS"}; + ConfigurableAxis cfgaxisChi2Ncls{"cfgaxisChi2Ncls", {100, 0, 30}, "Binning for Chi2Ncls TPC/ITS"}; + ConfigurableAxis cfgaxisCent{"cfgaxisCent", {90, 0, 90}, ""}; + ConfigurableAxis cfgaxisq2Tar{"cfgaxisq2Tar", {100, 0, 2}, "Binning for q_{2} traget particle"}; + ConfigurableAxis cfgaxisq2Ref{"cfgaxisq2Ref", {120, 0, 12}, "Binning for q_{2} reference particle"}; + ConfigurableAxis cfgq2NumeratorTar{"cfgq2NumeratorTar", {20, 0, 2}, "q2 Numerator bin for tar particle"}; + ConfigurableAxis cfgq2NumeratorRef{"cfgq2NumeratorRef", {100, 0, 10}, "q2 Numerator bin for ref particle"}; + ConfigurableAxis cfgq2DenominatorTar{"cfgq2DenominatorTar", {20, 0, 2}, "q2 Denominator bin for tar particle"}; + ConfigurableAxis cfgq2DenominatorRef{"cfgq2DenominatorRef", {50, 0, 5}, "q2 Denominator bin for ref particle"}; - // Function for He3 TPC-ITS mismatching cuts referd to by chiara's slides - TF1* fNSigmaITSPt = nullptr; + uint8_t poiTar; + uint8_t poiRef; + int detId; + int refAId; + int refBId; + int detInd; + int refAInd; + int refBInd; + // Function for He3 purity cut refered from luca's slides + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + + Filter collisionFilter = (nabs(aod::collision::posZ) < cfgVtzCut) && (aod::cent::centFT0C > cfgCentMin) && (aod::cent::centFT0C < cfgCentMax); + + Produces eseTable; template - bool trackSelBasic(const TrackType track) + float getNSigmaTPCSelfBB(const TrackType track, uint8_t POI) { - if ((track.pt() < cfgMinPtPID) || (track.pt() > cfgMaxPtPID)) - return false; - if (std::abs(track.eta()) > cfgMaxEtaPID) - return false; - if (cfgOpenpassedITSNCls) { - if (!track.passedITSNCls()) - return false; - } else { - if (track.itsNCls() < cfgMinITSCls || track.itsNCls() > cfgMaxITSCls) - return false; - } - if (cfgOpenpassedITSChi2NDF) { - if (!track.passedITSChi2NDF()) - return false; - } else { - if (track.itsChi2NCl() < cfgMinChi2NClITS || track.itsChi2NCl() > cfgMaxChi2NClITS) - return false; - } - if (cfgOpenpassedITSHits) { - if (!track.passedITSHits()) - return false; - } - if (cfgOpenpassedTPCChi2NDF) { - if (!track.passedTPCChi2NDF()) - return false; - } else { - if (track.tpcChi2NCl() < cfgMinTPCChi2NCl || track.tpcChi2NCl() > cfgMaxTPCChi2NCl) - return false; - } - if (cfgOpenpassedTPCCrossedRowsOverNCls) { - if (!track.passedTPCCrossedRowsOverNCls()) - return false; - } - if (cfgOpenpassedDCAxy) { - if (!track.passedDCAxy()) - return false; - } else { - if (std::abs(track.dcaXY()) > cfgMaxDCAxy) - return false; - } - if (cfgOpenpassedDCAz) { - if (!track.passedDCAz()) - return false; - } else { - if (std::abs(track.dcaZ()) > cfgMaxDCAz) - return false; + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + const int iC{track.sign() < 0}; + switch (POI) { + case ese_parameters::kProton: { + const double bgScaling[2]{ese_parameters::Charges[0] * cfgMomentumScalingBetheBloch->get(0u, 0u) / ese_parameters::Masses[0], ese_parameters::Charges[0] * cfgMomentumScalingBetheBloch->get(0u, 1u) / ese_parameters::Masses[0]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(0u, 0u), cfgBetheBlochParams->get(0u, 1u), cfgBetheBlochParams->get(0u, 2u), cfgBetheBlochParams->get(0u, 3u), cfgBetheBlochParams->get(0u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(0u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kDeuteron: { + const double bgScaling[2]{ese_parameters::Charges[1] * cfgMomentumScalingBetheBloch->get(1u, 0u) / ese_parameters::Masses[1], ese_parameters::Charges[1] * cfgMomentumScalingBetheBloch->get(1u, 1u) / ese_parameters::Masses[1]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(1u, 0u), cfgBetheBlochParams->get(1u, 1u), cfgBetheBlochParams->get(1u, 2u), cfgBetheBlochParams->get(1u, 3u), cfgBetheBlochParams->get(1u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(1u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kTriton: { + const double bgScaling[2]{ese_parameters::Charges[2] * cfgMomentumScalingBetheBloch->get(2u, 0u) / ese_parameters::Masses[2], ese_parameters::Charges[2] * cfgMomentumScalingBetheBloch->get(2u, 1u) / ese_parameters::Masses[2]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(2u, 0u), cfgBetheBlochParams->get(2u, 1u), cfgBetheBlochParams->get(2u, 2u), cfgBetheBlochParams->get(2u, 3u), cfgBetheBlochParams->get(2u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(2u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kHe3: { + const double bgScaling[2]{ese_parameters::Charges[3] * cfgMomentumScalingBetheBloch->get(3u, 0u) / ese_parameters::Masses[3], ese_parameters::Charges[3] * cfgMomentumScalingBetheBloch->get(3u, 1u) / ese_parameters::Masses[3]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(3u, 0u), cfgBetheBlochParams->get(3u, 1u), cfgBetheBlochParams->get(3u, 2u), cfgBetheBlochParams->get(3u, 3u), cfgBetheBlochParams->get(3u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(3u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + case ese_parameters::kAlpha: { + const double bgScaling[2]{ese_parameters::Charges[4] * cfgMomentumScalingBetheBloch->get(4u, 0u) / ese_parameters::Masses[4], ese_parameters::Charges[4] * cfgMomentumScalingBetheBloch->get(4u, 1u) / ese_parameters::Masses[4]}; + double expBethe{tpc::BetheBlochAleph(static_cast(correctedTpcInnerParam * bgScaling[iC]), cfgBetheBlochParams->get(4u, 0u), cfgBetheBlochParams->get(4u, 1u), cfgBetheBlochParams->get(4u, 2u), cfgBetheBlochParams->get(4u, 3u), cfgBetheBlochParams->get(4u, 4u))}; + double expSigma{expBethe * cfgBetheBlochParams->get(4u, 5u)}; + double nSigmaTPC{static_cast((track.tpcSignal() - expBethe) / expSigma)}; + return nSigmaTPC; + } + default: + return -99.f; } - if (track.tpcNClsFound() < cfgMinTPCCls || track.tpcNClsFound() > cfgMaxTPCCls) - return false; - return true; } template - bool pidProtonSel(const TrackType track, float nSigmaLower, float nSigmaUpper) - { // proton == 1 , He3 == 2 - if (track.pt() < cfgPtCutProton.value[0] || track.pt() > cfgPtCutProton.value[1]) - return false; - float nSigmaUse = -999; - switch (cfgProtonPIDMode) { - case 0: // RMS - nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDPrton) ? std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr()) : track.tpcNSigmaPr(); - break; - case 1: // TPC only - nSigmaUse = track.tpcNSigmaPr(); - break; - case 2: // TOF only - nSigmaUse = track.tofNSigmaPr(); - break; - } - if (nSigmaUse < nSigmaLower || nSigmaUse > nSigmaUpper) { - return false; - } else { - return true; - } - } + float getNSigmaTPC(const TrackType track, uint8_t POI) + { + switch (POI) { + case ese_parameters::kProton: { + float nSigmaUse = (cfgUseSelfnSigmaTPCProton ? getNSigmaTPCSelfBB(track, ese_parameters::kProton) : track.tpcNSigmaPr()); + return nSigmaUse; + } - template - bool pidHe3Sel(const TrackType track, float nSigmaLower, float nSigmaUpper) - { // proton == 1 , He3 == 2 - if (track.pt() < cfgPtCutHe3.value[0] || track.pt() > cfgPtCutHe3.value[1]) - return false; - float nSigmaUse = -999; - switch (cfgHe3PIDMode) { - case 0: // RMS - nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDHe3) ? std::hypot(track.tpcNSigmaHe(), track.tofNSigmaHe()) : track.tpcNSigmaHe(); - break; - case 1: // TPC only - nSigmaUse = track.tpcNSigmaHe(); - break; - case 2: // TOF only - nSigmaUse = track.tofNSigmaHe(); - break; - } - if (nSigmaUse < nSigmaLower || nSigmaUse > nSigmaUpper) { - return false; - } else { - return true; + case ese_parameters::kDeuteron: { + return getNSigmaTPCSelfBB(track, ese_parameters::kDeuteron); + } + + case ese_parameters::kTriton: { + return getNSigmaTPCSelfBB(track, ese_parameters::kTriton); + } + + case ese_parameters::kHe3: { + return getNSigmaTPCSelfBB(track, ese_parameters::kHe3); + } + + case ese_parameters::kAlpha: { + return getNSigmaTPCSelfBB(track, ese_parameters::kAlpha); + } + + case ese_parameters::kPion: { + return track.tpcNSigmaPi(); + } + + case ese_parameters::kKaon: { + return track.tpcNSigmaKa(); + } + + default: + LOGF(error, "Unknown POI: %d", POI); + return 0; } } template - int crossTrackID(const TrackType track) + float getNSigmaTOF(const TrackType track, uint8_t POI) { - if (track.tpcNSigmaPr() < track.tpcNSigmaHe()) { - return 0; - } else { - return 1; + switch (POI) { + case ese_parameters::kProton: { + return track.tofNSigmaPr(); + } + case ese_parameters::kDeuteron: { + return track.tofNSigmaDe(); + } + case ese_parameters::kTriton: { + return track.tofNSigmaTr(); + } + case ese_parameters::kHe3: { + return track.tofNSigmaHe(); + } + case ese_parameters::kAlpha: { + return track.tofNSigmaAl(); + } + case ese_parameters::kPion: { + return track.tofNSigmaPi(); + } + case ese_parameters::kKaon: { + return track.tofNSigmaKa(); + } + default: + return -99.f; } } - void init(InitContext const&) + template + float getNSigmaITS(const TrackType track, uint8_t POI) { - if (cfgOpenHe3ITSPtCut) { - fNSigmaITSPt = new TF1("fNSigmaITSPt", "[0]/pow(x,0.5) - [2]", 0.02, 1000); - fNSigmaITSPt->SetParameters(4.6, 0.5, 4.5); - } - AxisSpec axisITSNcls = {10, -1.5, 8.5, "ITSNcls"}; - AxisSpec axisTPCNcls = {160, 0, 160, "TPCNcls"}; - if (!cfgQuietMode) { - histosQA.add("QA/hist_dEdxTPC_All", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", {HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}}); - histosQA.add("QA/Proton/hist_dEdxTPC_Pr", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", {HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}}); - histosQA.add("QA/He3/hist_dEdxTPC_He3", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x}", {HistType::kTH2F, {cfgrigidityBins, cfgdedxBins}}); - histosQA.add("QA/hist_pt_All", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxisptPID}}); - histosQA.add("QA/Proton/hist_pt_Pr", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxisptPID}}); - histosQA.add("QA/He3/hist_pt_He3", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxisptPID}}); - histosQA.add("QA/hist_eta_All", ";#it{#eta};counts", {HistType::kTH1F, {cfgaxisetaPID}}); - histosQA.add("QA/Proton/hist_eta_Pr", ";#it{#eta};counts", {HistType::kTH1F, {cfgaxisetaPID}}); - histosQA.add("QA/He3/hist_eta_He3", ";#it{#eta};counts", {HistType::kTH1F, {cfgaxisetaPID}}); - histosQA.add("QA/hist_ITSNcls_All", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); - histosQA.add("QA/Proton/hist_ITSNcls_Pr", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); - histosQA.add("QA/He3/hist_ITSNcls_He3", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); - histosQA.add("QA/hist_TPCNcls_All", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); - histosQA.add("QA/Proton/hist_TPCNcls_Pr", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); - histosQA.add("QA/He3/hist_TPCNcls_He3", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); - histosQA.add("QA/hist_ITSChi2NDF_All", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/Proton/hist_ITSChi2NDF_Pr", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/He3/hist_ITSChi2NDF_He3", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/hist_TPCChi2NDF_All", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/Proton/hist_TPCChi2NDF_Pr", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/He3/hist_TPCChi2NDF_He3", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); - histosQA.add("QA/hist_DCAxy_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); - histosQA.add("QA/Proton/hist_DCAxy_Pr", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); - histosQA.add("QA/He3/hist_DCAxy_He3", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); - histosQA.add("QA/hist_DCAz_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); - histosQA.add("QA/Proton/hist_DCAz_Pr", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); - histosQA.add("QA/He3/hist_DCAz_He3", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); - histosQA.add("QA/Proton/hist_nSigmaTPC_Pr", ";n_{#sigma}TPC", {HistType::kTH1F, {cfgnSigmaBinsTPC}}); - histosQA.add("QA/Proton/hist_nSigmaTPCPt_Pr", ";#it{p}_{T};n_{#sigma}TPC", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTPC}}); - histosQA.add("QA/Proton/hist_nSigmaTOF_Pr", ";n_{#sigma}TOF", {HistType::kTH1F, {cfgnSigmaBinsTOF}}); - histosQA.add("QA/Proton/hist_nSigmaTOFPt_Pr", ";#it{p}_{T};n_{#sigma}TOF", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTOF}}); - histosQA.add("QA/Proton/hist_nSigmaITS_Pr", ";n_{#sigma}ITS", {HistType::kTH1F, {cfgnSigmaBinsITS}}); - histosQA.add("QA/Proton/hist_nSigmaITSPt_Pr", ";#it{p}_{T};n_{#sigma}ITS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsITS}}); - histosQA.add("QA/Proton/hist_nSigmaRMS_Pr", ";n_{#sigma}RMS", {HistType::kTH1F, {cfgnSigmaBinsRMS}}); - histosQA.add("QA/Proton/hist_nSigmaRMSPt_Pr", ";#it{p}_{T};n_{#sigma}RMS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsRMS}}); - histosQA.add("QA/He3/hist_nSigmaTPC_He3", ";n_{#sigma}TPC", {HistType::kTH1F, {cfgnSigmaBinsTPC}}); - histosQA.add("QA/He3/hist_nSigmaTPCPt_He3", ";#it{p}_{T};n_{#sigma}TPC", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTPC}}); - histosQA.add("QA/He3/hist_nSigmaTOF_He3", ";n_{#sigma}TOF", {HistType::kTH1F, {cfgnSigmaBinsTOF}}); - histosQA.add("QA/He3/hist_nSigmaTOFPt_He3", ";#it{p}_{T};n_{#sigma}TOF", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsTOF}}); - histosQA.add("QA/He3/hist_nSigmaITS_He3", ";n_{#sigma}ITS", {HistType::kTH1F, {cfgnSigmaBinsITS}}); - histosQA.add("QA/He3/hist_nSigmaITSPt_He3", ";#it{p}_{T};n_{#sigma}ITS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsITS}}); - histosQA.add("QA/He3/hist_nSigmaRMS_He3", ";n_{#sigma}RMS", {HistType::kTH1F, {cfgnSigmaBinsRMS}}); - histosQA.add("QA/He3/hist_nSigmaRMSPt_He3", ";#it{p}_{T};n_{#sigma}RMS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsRMS}}); - if (cfgOpenHe3ITSPtCut) { - histosQA.add("QA/He3/hist_nSigmaITSPt_He3_unCuted", ";#it{p}_{T};n_{#sigma}ITS", {HistType::kTH2F, {cfgaxisptPID, cfgnSigmaBinsITS}}); - } - if (cfgOpenPlotnSigmaTOFITSPt) { - histosQA.add("QA/Proton/hist_nSigmaTOFITSPt_Pr", ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxisptPID}}); - histosQA.add("QA/He3/hist_nSigmaTOFITSPt_He3", ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxisptPID}}); - } - if (cfgOpenPlotnSigmaITSTPCPt) { - histosQA.add("QA/Proton/hist_nSigmaITSTPCPt_Pr", ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxisptPID}}); - histosQA.add("QA/He3/hist_nSigmaITSTPCPt_He3", ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxisptPID}}); - } - if (cfgOpenPlotnSigmaTOFTPCPt) { - histosQA.add("QA/Proton/hist_nSigmaTOFTPCPt_Pr", ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxisptPID}}); - histosQA.add("QA/He3/hist_nSigmaTOFTPCPt_He3", ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", {HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxisptPID}}); + switch (POI) { + case ese_parameters::kProton: { + return itsResponse.nSigmaITS(track); } - } - } - Produces pidEsePHe3Table; - void process(TracksPID const& tracks) - { - auto tracksWithITSPid = soa::Attach(tracks); - int8_t pidFlag; - for (const auto& track : tracksWithITSPid) { - histosQA.fill(HIST("QA/hist_dEdxTPC_All"), track.sign() * track.tpcInnerParam(), track.tpcSignal()); - histosQA.fill(HIST("QA/hist_pt_All"), track.pt()); - histosQA.fill(HIST("QA/hist_eta_All"), track.eta()); - histosQA.fill(HIST("QA/hist_ITSNcls_All"), track.itsNCls()); - histosQA.fill(HIST("QA/hist_TPCNcls_All"), track.tpcNClsFound()); - histosQA.fill(HIST("QA/hist_ITSChi2NDF_All"), track.itsChi2NCl()); - histosQA.fill(HIST("QA/hist_TPCChi2NDF_All"), track.tpcChi2NCl()); - histosQA.fill(HIST("QA/hist_DCAxy_All"), track.dcaXY()); - histosQA.fill(HIST("QA/hist_DCAz_All"), track.dcaZ()); - if (!trackSelBasic(track)) { - pidFlag = -1; - } else { - int currentPtBinPr = -1, currentPtBinHe3 = -1; - if (cfgOpenPIDByPtProtonMain || (cfgOpenPIDByPtProtonITS && cfgOpenPIDITSProton)) { - for (int i = 0; i < static_cast(cfgPtBinProtonPID.value.size()) - 1; ++i) { - if (track.pt() >= cfgPtBinProtonPID.value[i] && track.pt() < cfgPtBinProtonPID.value[i + 1]) { - currentPtBinPr = i; - break; - } - } - } - if (cfgOpenPIDByPtHe3Main || (cfgOpenPIDByPtHe3ITS && cfgOpenPIDITSHe3)) { - for (int i = 0; i < static_cast(cfgPtBinHe3PID.value.size()) - 1; ++i) { - if (track.pt() >= cfgPtBinHe3PID.value[i] && track.pt() < cfgPtBinHe3PID.value[i + 1]) { - currentPtBinHe3 = i; - break; - } - } - } - float nSigmaTPCCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutTPCProton.value[0] : cfgnSigmaTPCProtonPtLower.value[currentPtBinPr]; - float nSigmaTPCCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutTPCProton.value[1] : cfgnSigmaTPCProtonPtUpper.value[currentPtBinPr]; - float nSigmaTOFCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutTOFProton.value[0] : cfgnSigmaTOFProtonPtLower.value[currentPtBinPr]; - float nSigmaTOFCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutTOFProton.value[1] : cfgnSigmaTOFProtonPtUpper.value[currentPtBinPr]; - float nSigmaRMSCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutRMSProton.value[0] : cfgnSigmaRMSProtonPtLower.value[currentPtBinPr]; - float nSigmaRMSCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutRMSProton.value[1] : cfgnSigmaRMSProtonPtUpper.value[currentPtBinPr]; - float nSigmaITSCutPrPtLower = (currentPtBinPr == -1) ? cfgnSigmaCutITSProton.value[0] : cfgnSigmaITSProtonPtLower.value[currentPtBinPr]; - float nSigmaITSCutPrPtUpper = (currentPtBinPr == -1) ? cfgnSigmaCutITSProton.value[1] : cfgnSigmaITSProtonPtUpper.value[currentPtBinPr]; - float nSigmaTPCCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutTPCHe3.value[0] : cfgnSigmaTPCHe3PtLower.value[currentPtBinHe3]; - float nSigmaTPCCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutTPCHe3.value[1] : cfgnSigmaTPCHe3PtUpper.value[currentPtBinHe3]; - float nSigmaTOFCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutTOFHe3.value[0] : cfgnSigmaTOFHe3PtLower.value[currentPtBinHe3]; - float nSigmaTOFCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutTOFHe3.value[1] : cfgnSigmaTOFHe3PtUpper.value[currentPtBinHe3]; - float nSigmaRMSCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutRMSHe3.value[0] : cfgnSigmaRMSHe3PtLower.value[currentPtBinHe3]; - float nSigmaRMSCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutRMSHe3.value[1] : cfgnSigmaRMSHe3PtUpper.value[currentPtBinHe3]; - float nSigmaITSCutHe3PtLower = (currentPtBinHe3 == -1) ? cfgnSigmaCutITSHe3.value[0] : cfgnSigmaITSHe3PtLower.value[currentPtBinHe3]; - float nSigmaITSCutHe3PtUpper = (currentPtBinHe3 == -1) ? cfgnSigmaCutITSHe3.value[1] : cfgnSigmaITSHe3PtUpper.value[currentPtBinHe3]; - float nSigmaMainLowerPr = -999, nSigmaMainUpperPr = -999; - float nSigmaMainLowerHe3 = -999, nSigmaMainUpperHe3 = -999; - switch (cfgProtonPIDMode) { - case 0: - nSigmaMainLowerPr = nSigmaRMSCutPrPtLower; - nSigmaMainUpperPr = nSigmaRMSCutPrPtUpper; - break; - case 1: - nSigmaMainLowerPr = nSigmaTPCCutPrPtLower; - nSigmaMainUpperPr = nSigmaTPCCutPrPtUpper; - break; - case 2: - nSigmaMainLowerPr = nSigmaTOFCutPrPtLower; - nSigmaMainUpperPr = nSigmaTOFCutPrPtUpper; - break; - } - switch (cfgHe3PIDMode) { - case 0: - nSigmaMainLowerHe3 = nSigmaRMSCutHe3PtLower; - nSigmaMainUpperHe3 = nSigmaRMSCutHe3PtUpper; - break; - case 1: - nSigmaMainLowerHe3 = nSigmaTPCCutHe3PtLower; - nSigmaMainUpperHe3 = nSigmaTPCCutHe3PtUpper; - break; - case 2: - nSigmaMainLowerHe3 = nSigmaTOFCutHe3PtLower; - nSigmaMainUpperHe3 = nSigmaTOFCutHe3PtUpper; - break; - } - bool kIsPr = false, kIsHe3 = false; - // Identify Proton - if (pidProtonSel(track, nSigmaMainLowerPr, nSigmaMainUpperPr)) { - kIsPr = true; - if (cfgOpenPIDITSProton) { - if (track.itsNSigmaPr() < nSigmaITSCutPrPtLower || track.itsNSigmaPr() > nSigmaITSCutPrPtUpper) { - kIsPr = false; - } - } - } - // Identify He3 - if (pidHe3Sel(track, nSigmaMainLowerHe3, nSigmaMainUpperHe3)) { - kIsHe3 = true; - if (cfgOpenPIDITSHe3) { - if (track.itsNSigmaHe() < nSigmaITSCutHe3PtLower || track.itsNSigmaHe() > nSigmaITSCutHe3PtUpper) { - kIsHe3 = false; - } - } - } - // Cross track rejection - if (!cfgOpenAllowCrossTrack) { - if (kIsPr && kIsHe3) { - switch (crossTrackID(track)) { - case 0: - kIsPr = true; - kIsHe3 = false; - break; - case 1: - kIsPr = false; - kIsHe3 = true; - break; - } - } - } - // Filter He3 contaimination - if (cfgOpenHe3ITSPtCut && kIsHe3) { - if (!cfgQuietMode) { - histosQA.fill(HIST("QA/He3/hist_nSigmaITSPt_He3_unCuted"), track.pt(), track.itsNSigmaHe()); - } - if (track.itsNSigmaHe() < fNSigmaITSPt->Eval(track.pt())) { - kIsHe3 = false; - } - } - pidFlag = (kIsHe3 << 1) | kIsPr; - // Fill QA histograms - if (!cfgQuietMode) { - if (kIsPr) { - histosQA.fill(HIST("QA/Proton/hist_dEdxTPC_Pr"), track.sign() * track.tpcInnerParam(), track.tpcSignal()); - histosQA.fill(HIST("QA/Proton/hist_pt_Pr"), track.pt()); - histosQA.fill(HIST("QA/Proton/hist_eta_Pr"), track.eta()); - histosQA.fill(HIST("QA/Proton/hist_ITSNcls_Pr"), track.itsNCls()); - histosQA.fill(HIST("QA/Proton/hist_TPCNcls_Pr"), track.tpcNClsFound()); - histosQA.fill(HIST("QA/Proton/hist_ITSChi2NDF_Pr"), track.itsChi2NCl()); - histosQA.fill(HIST("QA/Proton/hist_TPCChi2NDF_Pr"), track.tpcChi2NCl()); - histosQA.fill(HIST("QA/Proton/hist_DCAxy_Pr"), track.dcaXY()); - histosQA.fill(HIST("QA/Proton/hist_DCAz_Pr"), track.dcaZ()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTPC_Pr"), track.tpcNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTPCPt_Pr"), track.pt(), track.tpcNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOF_Pr"), track.tofNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOFPt_Pr"), track.pt(), track.tofNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaITS_Pr"), track.itsNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaITSPt_Pr"), track.pt(), track.itsNSigmaPr()); - histosQA.fill(HIST("QA/Proton/hist_nSigmaRMS_Pr"), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())); - histosQA.fill(HIST("QA/Proton/hist_nSigmaRMSPt_Pr"), track.pt(), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())); - if (cfgOpenPlotnSigmaTOFITSPt) { - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOFITSPt_Pr"), track.tofNSigmaPr(), track.itsNSigmaPr(), track.pt()); - } - if (cfgOpenPlotnSigmaITSTPCPt) { - histosQA.fill(HIST("QA/Proton/hist_nSigmaITSTPCPt_Pr"), track.itsNSigmaPr(), track.tpcNSigmaPr(), track.pt()); - } - if (cfgOpenPlotnSigmaTOFTPCPt) { - histosQA.fill(HIST("QA/Proton/hist_nSigmaTOFTPCPt_Pr"), track.tofNSigmaPr(), track.tpcNSigmaPr(), track.pt()); - } - } - if (kIsHe3) { - histosQA.fill(HIST("QA/He3/hist_dEdxTPC_He3"), track.sign() * track.tpcInnerParam(), track.tpcSignal()); - histosQA.fill(HIST("QA/He3/hist_pt_He3"), track.pt()); - histosQA.fill(HIST("QA/He3/hist_eta_He3"), track.eta()); - histosQA.fill(HIST("QA/He3/hist_ITSNcls_He3"), track.itsNCls()); - histosQA.fill(HIST("QA/He3/hist_TPCNcls_He3"), track.tpcNClsFound()); - histosQA.fill(HIST("QA/He3/hist_ITSChi2NDF_He3"), track.itsChi2NCl()); - histosQA.fill(HIST("QA/He3/hist_TPCChi2NDF_He3"), track.tpcChi2NCl()); - histosQA.fill(HIST("QA/He3/hist_DCAxy_He3"), track.dcaXY()); - histosQA.fill(HIST("QA/He3/hist_DCAz_He3"), track.dcaZ()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTPC_He3"), track.tpcNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTPCPt_He3"), track.pt(), track.tpcNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTOF_He3"), track.tofNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaTOFPt_He3"), track.pt(), track.tofNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaITS_He3"), track.itsNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaITSPt_He3"), track.pt(), track.itsNSigmaHe()); - histosQA.fill(HIST("QA/He3/hist_nSigmaRMS_He3"), std::hypot(track.tpcNSigmaHe(), track.tofNSigmaHe())); - histosQA.fill(HIST("QA/He3/hist_nSigmaRMSPt_He3"), track.pt(), std::hypot(track.tpcNSigmaHe(), track.tofNSigmaHe())); - if (cfgOpenPlotnSigmaTOFITSPt) { - histosQA.fill(HIST("QA/He3/hist_nSigmaTOFITSPt_He3"), track.tofNSigmaHe(), track.itsNSigmaHe(), track.pt()); - } - if (cfgOpenPlotnSigmaITSTPCPt) { - histosQA.fill(HIST("QA/He3/hist_nSigmaITSTPCPt_He3"), track.itsNSigmaHe(), track.tpcNSigmaHe(), track.pt()); - } - if (cfgOpenPlotnSigmaTOFTPCPt) { - histosQA.fill(HIST("QA/He3/hist_nSigmaTOFTPCPt_He3"), track.tofNSigmaHe(), track.tpcNSigmaHe(), track.pt()); - } - } - } + case ese_parameters::kDeuteron: { + return itsResponse.nSigmaITS(track); + } + case ese_parameters::kTriton: { + return itsResponse.nSigmaITS(track); + } + case ese_parameters::kHe3: { + return itsResponse.nSigmaITS(track); + } + case ese_parameters::kAlpha: { + return itsResponse.nSigmaITS(track); + } + case ese_parameters::kPion: { + return itsResponse.nSigmaITS(track); } - pidEsePHe3Table(pidFlag); + case ese_parameters::kKaon: { + return itsResponse.nSigmaITS(track); + } + default: + return -99.f; } } -}; - -struct FlowEsePHe3 { - HistogramRegistry histos{"histosmain", {}, OutputObjHandlingPolicy::AnalysisObject}; - - Configurable> cfgnMods{"cfgnMods", {2}, "Modulation of interest"}; - Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; - Configurable cfgRefAName{"cfgRefAName", "TPCpos", "The name of detector for reference A"}; - Configurable cfgRefBName{"cfgRefBName", "TPCneg", "The name of detector for reference B"}; - Configurable cfgnTotalSystem{"cfgnTotalSystem", 7, "total qvector number"}; - - Configurable cfgVtzCut{"cfgVtzCut", 10.0f, "Accepted z-vertex range"}; - Configurable cfgCentMin{"cfgCentMin", 0.0f, "Centrality min"}; - Configurable cfgCentMax{"cfgCentMax", 100.0f, "Centrality max"}; - - Configurable cfgCutOccupancyLow{"cfgCutOccupancyLow", 0, "Low boundary cut on TPC occupancy"}; - Configurable cfgCutOccupancyHigh{"cfgCutOccupancyHigh", 3000, "High boundary cut on TPC occupancy"}; - Configurable cfgUseAdditionalEventCut{"cfgUseAdditionalEventCut", true, "Use additional event cut beyond sel8"}; - Configurable cfgOpenEvSelkIsGoodZvtxFT0vsPV{"cfgOpenEvSelkIsGoodZvtxFT0vsPV", true, "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"}; - Configurable cfgOpenEvSelkNoSameBunchPileup{"cfgOpenEvSelkNoSameBunchPileup", true, "rejects collisions which are associated with the same found-by-T0 bunch crossing"}; - Configurable cfgOpenEvSelkNoCollInTimeRangeStandard{"cfgOpenEvSelkNoCollInTimeRangeStandard", true, "no collisions in specified time range"}; - Configurable cfgOpenEvSelkIsGoodITSLayersAll{"cfgOpenEvSelkIsGoodITSLayersAll", true, "cut time intervals with dead ITS staves"}; - Configurable cfgOpenEvSelkNoCollInRofStandard{"cfgOpenEvSelkNoCollInRofStandard", true, "no other collisions in this Readout Frame with per-collision multiplicity above threshold"}; - Configurable cfgOpenEvSelkNoHighMultCollInPrevRof{"cfgOpenEvSelkNoHighMultCollInPrevRof", true, "veto an event if FT0C amplitude in previous ITS ROF is above threshold"}; - Configurable cfgOpenEvSelOccupancy{"cfgOpenEvSelOccupancy", true, "Occupancy cut"}; - Configurable cfgOpenEvSelMultCorrelationPVTracks{"cfgOpenEvSelMultCorrelationPVTracks", true, "Multiplicity correlation cut for PVtracks vs centrality(FT0C)"}; - Configurable cfgOpenEvSelMultCorrelationGlobalTracks{"cfgOpenEvSelMultCorrelationGlobalTracks", false, "Multiplicity correlation cut for Globaltracks vs centrality(FT0C)"}; - Configurable cfgOpenEvSelV0AT0ACut{"cfgOpenEvSelV0AT0ACut", true, "V0A T0A 5 sigma cut"}; - Configurable cfgOpenFullEventQA{"cfgOpenFullEventQA", true, "Open full QA plots for event QA"}; - Configurable cfgOpenv2q{"cfgOpenv2q", true, "Open v2(EP)and q calculation for Proton and He3"}; - Configurable cfgOpenESE{"cfgOpenESE", true, "Open ESE process"}; - Configurable cfgOpenESEChargeSeperation{"cfgOpenESEChargeSeperation", true, "Open ESE for postive and negative charge repectivily"}; - Configurable cfgOpenESEProton{"cfgOpenESEProton", true, "Open ESE Proton process"}; - Configurable cfgOpenESEHe3{"cfgOpenESEHe3", true, "Open ESE He3 process"}; - - ConfigurableAxis cfgaxisQvecF{"cfgaxisQvecF", {300, -1, 1}, ""}; - ConfigurableAxis cfgaxisCent{"cfgaxisCent", {90, 0, 90}, ""}; - ConfigurableAxis cfgaxispt{"cfgaxispt", {100, 0, 10}, ""}; - ConfigurableAxis cfgaxisCentForQA{"cfgaxisCentForQA", {100, 0, 100}, "centrality for event QA"}; - ConfigurableAxis cfgaxisNch{"cfgaxisNch", {4000, 0, 4000}, "N_{ch}"}; - ConfigurableAxis cfgaxisT0C{"cfgaxisT0C", {70, 0, 70000}, "N_{ch} (T0C)"}; - ConfigurableAxis cfgaxisT0A{"cfgaxisT0A", {200, 0, 200000}, "N_{ch} (T0A)"}; - ConfigurableAxis cfgaxisNchPV{"cfgaxisNchPV", {4000, 0, 4000}, "N_{ch} (PV)"}; - ConfigurableAxis cfgaxisq2{"cfgaxisq2", {120, 0, 12}, "Binning for P_{t} PID"}; - - EventPlaneHelper helperEP; - SliceCache cache; - - int detId; - int refAId; - int refBId; - // Additional Event selection cuts - Copy from flowGenericFramework.cxx - TF1* fMultPVCutLow = nullptr; - TF1* fMultPVCutHigh = nullptr; - TF1* fMultCutLow = nullptr; - TF1* fMultCutHigh = nullptr; - TF1* fT0AV0AMean = nullptr; - TF1* fT0AV0ASigma = nullptr; - - Filter collisionFilter = (nabs(aod::collision::posZ) < cfgVtzCut) && (aod::cent::centFT0C > cfgCentMin) && (aod::cent::centFT0C < cfgCentMax); - Filter properPIDfilter = aod::flow_ese_p_he3::nPidFlag >= (int8_t)0; // Only POI - - Partition>> protonTrackSet = ((aod::flow_ese_p_he3::nPidFlag == pid_flags::kProton) || (aod::flow_ese_p_he3::nPidFlag == pid_flags::kProtonHe3)); - Partition>> he3TrackSet = ((aod::flow_ese_p_he3::nPidFlag == pid_flags::kHe3) || (aod::flow_ese_p_he3::nPidFlag == pid_flags::kProtonHe3)); template int getDetId(const T& name) @@ -637,160 +592,472 @@ struct FlowEsePHe3 { } } + template + uint8_t getPOI(const T& POI) + { + if (POI.value == "kProton") { + return ese_parameters::kProton; + } else if (POI.value == "kDeuteron") { + return ese_parameters::kDeuteron; + } else if (POI.value == "kTriton") { + return ese_parameters::kTriton; + } else if (POI.value == "kHe3") { + return ese_parameters::kHe3; + } else if (POI.value == "kAlpha") { + return ese_parameters::kAlpha; + } else if (POI.value == "kPion") { + return ese_parameters::kPion; + } else if (POI.value == "kKaon") { + return ese_parameters::kKaon; + } else if (POI.value == "kHadron") { + return ese_parameters::kHadron; + } else { + LOGF(error, "Unknown POIstr: %s", POI.value.c_str()); + return 0; + } + } + + float calculateq2(const float qx, const float qy, const int multi) + { + if (multi <= 0) { + return 0.f; + } else { + return std::hypot(qx, qy) / std::sqrt(static_cast(multi)); + } + } + template - bool selEvent(const CollType& collision, const int multTrk, const float centrality) + bool eventSelBasic(const CollType& collision, const int64_t multTrk, const float centrality, bool fillQA) { - histos.fill(HIST("QA/histEventCountDetail"), 0.5); - if (cfgOpenEvSelkIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (!collision.sel8()) return false; + if (fillQA) { + histsESE.fill(HIST("EventQA/histEventCount"), 0.5); } - if (cfgOpenEvSelkIsGoodZvtxFT0vsPV) { - histos.fill(HIST("QA/histEventCountDetail"), 1.5); + if (cfgOpenEvSel->get(0u) && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (fillQA && cfgOpenEvSel->get(0u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 1.5); } - if (cfgOpenEvSelkNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (cfgOpenEvSel->get(1u) && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return false; } - if (cfgOpenEvSelkNoSameBunchPileup) { - histos.fill(HIST("QA/histEventCountDetail"), 2.5); + if (fillQA && cfgOpenEvSel->get(1u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 2.5); } - if (cfgOpenEvSelkNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (cfgOpenEvSel->get(2u) && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return false; } - if (cfgOpenEvSelkNoCollInTimeRangeStandard) { - histos.fill(HIST("QA/histEventCountDetail"), 3.5); + if (fillQA && cfgOpenEvSel->get(2u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 3.5); } - if (cfgOpenEvSelkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (cfgOpenEvSel->get(3u) && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { return false; } - if (cfgOpenEvSelkIsGoodITSLayersAll) { - histos.fill(HIST("QA/histEventCountDetail"), 4.5); + if (fillQA && cfgOpenEvSel->get(3u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 4.5); } - if (cfgOpenEvSelkNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (cfgOpenEvSel->get(4u) && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return false; } - if (cfgOpenEvSelkNoCollInRofStandard) { - histos.fill(HIST("QA/histEventCountDetail"), 5.5); + if (fillQA && cfgOpenEvSel->get(4u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 5.5); } - if (cfgOpenEvSelkNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (cfgOpenEvSel->get(5u) && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { return false; } - if (cfgOpenEvSelkNoHighMultCollInPrevRof) { - histos.fill(HIST("QA/histEventCountDetail"), 6.5); + if (fillQA && cfgOpenEvSel->get(5u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 6.5); } auto multNTracksPV = collision.multNTracksPV(); auto occupancy = collision.trackOccupancyInTimeRange(); - if (cfgOpenEvSelOccupancy && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { + if (cfgOpenEvSel->get(6u) && (occupancy < cfgCutOccupancyLow || occupancy > cfgCutOccupancyHigh)) { return false; } - if (cfgOpenEvSelOccupancy) { - histos.fill(HIST("QA/histEventCountDetail"), 7.5); + if (fillQA && cfgOpenEvSel->get(6u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 7.5); } - if (cfgOpenEvSelMultCorrelationPVTracks) { + if (cfgOpenEvSel->get(7u)) { if (multNTracksPV < fMultPVCutLow->Eval(centrality)) return false; if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) return false; } - if (cfgOpenEvSelMultCorrelationPVTracks) { - histos.fill(HIST("QA/histEventCountDetail"), 8.5); + if (fillQA && cfgOpenEvSel->get(7u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 8.5); } - if (cfgOpenEvSelMultCorrelationGlobalTracks) { + if (cfgOpenEvSel->get(8u)) { if (multTrk < fMultCutLow->Eval(centrality)) return false; if (multTrk > fMultCutHigh->Eval(centrality)) return false; } - if (cfgOpenEvSelMultCorrelationGlobalTracks) { - histos.fill(HIST("QA/histEventCountDetail"), 9.5); + if (fillQA && cfgOpenEvSel->get(8u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 9.5); } - if (cfgOpenEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > event_selection::kFT0AV0ASigma * fT0AV0ASigma->Eval(collision.multFT0A()))) { + if (cfgOpenEvSel->get(9u) && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > ese_parameters::kFT0AV0ASigma * fT0AV0ASigma->Eval(collision.multFT0A()))) { return false; } - if (cfgOpenEvSelV0AT0ACut) { - histos.fill(HIST("QA/histEventCountDetail"), 10.5); + if (fillQA && cfgOpenEvSel->get(9u)) { + histsESE.fill(HIST("EventQA/histEventCount"), 10.5); + } + if (fillQA) { + histsESE.fill(HIST("EventQA/histVtz"), collision.posZ()); + histsESE.fill(HIST("EventQA/histCent"), centrality); } return true; } + template + bool trackSelBasic(const TrackType track) + { + if ((track.pt() < cfgMinPtPID) || (track.pt() > cfgMaxPtPID)) + return false; + if (std::abs(track.eta()) > cfgMaxEtaPID) + return false; + if (cfgOpenTrackSel->get(0u)) { + if (!track.passedITSNCls()) + return false; + } else { + if (track.itsNCls() < cfgMinITSCls || track.itsNCls() > cfgMaxITSCls) + return false; + } + if (cfgOpenTrackSel->get(1u)) { + if (!track.passedITSChi2NDF()) + return false; + } else { + if (track.itsChi2NCl() < cfgMinChi2NClITS || track.itsChi2NCl() > cfgMaxChi2NClITS) + return false; + } + if (cfgOpenTrackSel->get(2u)) { + if (!track.passedITSHits()) + return false; + } + if (cfgOpenTrackSel->get(3u)) { + if (!track.passedTPCChi2NDF()) + return false; + } else { + if (track.tpcChi2NCl() < cfgMinTPCChi2NCl || track.tpcChi2NCl() > cfgMaxTPCChi2NCl) + return false; + } + if (cfgOpenTrackSel->get(4u)) { + if (!track.passedTPCCrossedRowsOverNCls()) + return false; + } + if (cfgOpenTrackSel->get(5u)) { + if (!track.passedDCAxy()) + return false; + } else { + if (std::abs(track.dcaXY()) > cfgMaxDCAxy) + return false; + } + if (cfgOpenTrackSel->get(6u)) { + if (!track.passedDCAz()) + return false; + } else { + if (std::abs(track.dcaZ()) > cfgMaxDCAz) + return false; + } + if (track.tpcNClsFound() < cfgMinTPCCls || track.tpcNClsFound() > cfgMaxTPCCls) + return false; + return true; + } + template - void fillHistosQvec(const CollType& collision, int nmode) + void fillEventQAhistBe(const CollType collision, const int multTrk, const float centrality) { - int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - if (nmode == fourier_mode::kMode2) { - if (collision.qvecAmp()[detId] > 1e-8) { - histos.fill(HIST("QA/histQvec_CorrL0_V2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.centFT0C()); - histos.fill(HIST("QA/histQvec_CorrL1_V2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.centFT0C()); - histos.fill(HIST("QA/histQvec_CorrL2_V2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.centFT0C()); - histos.fill(HIST("QA/histQvec_CorrL3_V2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL0_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL1_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL2_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.centFT0C()); - histos.fill(HIST("QA/histEvtPl_CorrL3_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.centFT0C()); - } - if (collision.qvecAmp()[detId] > 1e-8 && collision.qvecAmp()[refAId] > 1e-8 && collision.qvecAmp()[refBId] > 1e-8) { - histos.fill(HIST("QA/histQvecRes_SigRefAV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode)); - histos.fill(HIST("QA/histQvecRes_SigRefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode)); - histos.fill(HIST("QA/histQvecRes_RefARefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode)); - } + histsESE.fill(HIST("EventQA/hist_globalTracks_centT0C_before"), centrality, multTrk); + histsESE.fill(HIST("EventQA/hist_PVTracks_centT0C_before"), centrality, collision.multNTracksPV()); + histsESE.fill(HIST("EventQA/hist_globalTracks_PVTracks_before"), collision.multNTracksPV(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multT0A_before"), collision.multFT0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multV0A_before"), collision.multFV0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_multV0A_multT0A_before"), collision.multFT0A(), collision.multFV0A()); + histsESE.fill(HIST("EventQA/hist_multT0C_centT0C_before"), centrality, collision.multFT0C()); + } + + template + void fillEventQAhistAf(const CollType collision, const int multTrk, const float centrality) + { + histsESE.fill(HIST("EventQA/hist_globalTracks_centT0C_after"), centrality, multTrk); + histsESE.fill(HIST("EventQA/hist_PVTracks_centT0C_after"), centrality, collision.multNTracksPV()); + histsESE.fill(HIST("EventQA/hist_globalTracks_PVTracks_after"), collision.multNTracksPV(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multT0A_after"), collision.multFT0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_globalTracks_multV0A_after"), collision.multFV0A(), multTrk); + histsESE.fill(HIST("EventQA/hist_multV0A_multT0A_after"), collision.multFT0A(), collision.multFV0A()); + histsESE.fill(HIST("EventQA/hist_multT0C_centT0C_after"), centrality, collision.multFT0C()); + } + + template + void fillTrackQAhist(const TrackType track) + { + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + histsESE.fill(HIST("TrackQA/hist_dEdxTPC_All"), track.sign() * correctedTpcInnerParam, track.tpcSignal()); + histsESE.fill(HIST("TrackQA/hist_pt_All"), track.pt()); + histsESE.fill(HIST("TrackQA/hist_eta_All"), track.eta()); + histsESE.fill(HIST("TrackQA/hist_phi_All"), track.phi()); + histsESE.fill(HIST("TrackQA/hist_DCAxy_All"), track.dcaXY()); + histsESE.fill(HIST("TrackQA/hist_DCAz_All"), track.dcaZ()); + histsESE.fill(HIST("TrackQA/hist_ITSNcls_All"), track.itsNCls()); + histsESE.fill(HIST("TrackQA/hist_TPCNcls_All"), track.tpcNClsFound()); + histsESE.fill(HIST("TrackQA/hist_ITSChi2NDF_All"), track.itsChi2NCl()); + histsESE.fill(HIST("TrackQA/hist_TPCChi2NDF_All"), track.tpcChi2NCl()); + histsESE.fill(HIST("TrackQA/hist_MomRes_All"), track.p(), 1 - (correctedTpcInnerParam / track.p())); + if (heliumPID) { + histsESE.fill(HIST("TrackQA/hist_He3AlphaTrackcounts_All"), 1.5); + } else { + histsESE.fill(HIST("TrackQA/hist_He3AlphaTrackcounts_All"), 0.5); + } + } + + template + void fillHistosQvec(const CollType& collision) + { + if (collision.qvecAmp()[detId] > ese_parameters::Amplitudelow) { + histsESE.fill(HIST("PlanQA/histQvec_CorrL0_V2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histQvec_CorrL1_V2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histQvec_CorrL2_V2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histQvec_CorrL3_V2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL0_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], 2), collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL1_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], 2), collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL2_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], 2), collision.centFT0C()); + histsESE.fill(HIST("PlanQA/histEvtPl_CorrL3_V2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2), collision.centFT0C()); + } + if (collision.qvecAmp()[detId] > ese_parameters::Amplitudelow && collision.qvecAmp()[refAId] > ese_parameters::Amplitudelow && collision.qvecAmp()[refBId] > ese_parameters::Amplitudelow) { + histsESE.fill(HIST("PlanQA/histQvecRes_SigRefAV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], 2), 2)); + histsESE.fill(HIST("PlanQA/histQvecRes_SigRefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], 2), 2)); + histsESE.fill(HIST("PlanQA/histQvecRes_RefARefBV2"), collision.centFT0C(), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], 2), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], 2), 2)); } } template - float calculateq2(const TrackType tracks, float psi2, float cent, int pidmode) // pidmode 1 for proton , 2 for he3 + bool pidSel(const TrackType& track, uint8_t POI) { - int multi = tracks.size(); - if (multi > 0) { - float q2x = 0, q2y = 0; - for (const auto& track : tracks) { - q2x += std::cos(2 * track.phi()); - q2y += std::sin(2 * track.phi()); - if (pidmode == pid_flags::kProton) { - if (track.sign() > 0) { - histos.fill(HIST("V2/histCosV2EP_Pr_Pos"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); - } else { - histos.fill(HIST("V2/histCosV2EP_Pr_Neg"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); + // Hadron + if (POI == ese_parameters::kHadron) + return true; + // PID particles + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + if (correctedTpcInnerParam < cfgPOverZPreselection->get(POI, 0u) || correctedTpcInnerParam > cfgPOverZPreselection->get(POI, 1u)) { + return false; + } + if (std::abs(track.eta()) > cfgEtaPreselection->get(POI)) { + return false; + } + if (track.tpcNClsFound() < cfgTPCNclsPreselection->get(POI, 0u) || track.tpcNClsFound() > cfgTPCNclsPreselection->get(POI, 1u)) { + return false; + } + if (track.itsNCls() < cfgITSNclsPreselection->get(POI, 0u) || track.itsNCls() > cfgITSNclsPreselection->get(POI, 1u)) { + return false; + } + if (track.tpcChi2NCl() < cfgTPCChi2Preselection->get(POI, 0u) || track.tpcChi2NCl() > cfgTPCChi2Preselection->get(POI, 1u)) { + return false; + } + if (track.itsChi2NCl() < cfgITSChi2Preselection->get(POI, 0u) || track.itsChi2NCl() > cfgITSChi2Preselection->get(POI, 1u)) { + return false; + } + if (std::abs(track.dcaXY()) > cfgDCAxyPreselection->get(POI)) { + return false; + } + if (std::abs(track.dcaZ()) > cfgDCAzPreselection->get(POI)) { + return false; + } + float nSigmaTPC{0.f}; + switch (POI) { + case ese_parameters::kProton: { + if (cfgProtonPIDMode == ese_parameters::kRMSMode) { // RMS mode + float nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDProton) ? std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr()) : track.tpcNSigmaPr(); + if (nSigmaUse < cfgnSigmaCutRMSProton.value[0] || nSigmaUse > cfgnSigmaCutRMSProton.value[1]) { + return false; + } + } else if (cfgProtonPIDMode == ese_parameters::kTPCMode) { // TPC mode + nSigmaTPC = getNSigmaTPC(track, ese_parameters::kProton); + } else if (cfgProtonPIDMode == ese_parameters::kTOFOnlyMode) { // TOF only mode + if (!track.hasTOF()) + return false; + if (track.tofNSigmaPr() < cfgnSigmaCutTOFProton.value[0] || track.tofNSigmaPr() > cfgnSigmaCutTOFProton.value[1]) { + return false; + } + } + break; + } + + case ese_parameters::kDeuteron: { + nSigmaTPC = getNSigmaTPC(track, ese_parameters::kDeuteron); + break; + } + + case ese_parameters::kTriton: { + nSigmaTPC = getNSigmaTPC(track, ese_parameters::kTriton); + break; + } + + case ese_parameters::kHe3: { + nSigmaTPC = getNSigmaTPC(track, ese_parameters::kHe3); + break; + } + + case ese_parameters::kAlpha: { + nSigmaTPC = getNSigmaTPC(track, ese_parameters::kAlpha); + break; + } + + case ese_parameters::kPion: { + if (cfgPionPIDMode == ese_parameters::kRMSMode) { // RMS mode + float nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDPion) ? std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()) : track.tpcNSigmaPi(); + if (nSigmaUse < cfgnSigmaCutRMSPion.value[0] || nSigmaUse > cfgnSigmaCutRMSPion.value[1]) { + return false; + } + } else if (cfgPionPIDMode == ese_parameters::kTPCMode) { // TPC mode + nSigmaTPC = getNSigmaTPC(track, ese_parameters::kPion); + } else if (cfgPionPIDMode == ese_parameters::kTOFOnlyMode) { // TOF only mode + if (!track.hasTOF()) + return false; + if (track.tofNSigmaPi() < cfgnSigmaCutTOFPion.value[0] || track.tofNSigmaPi() > cfgnSigmaCutTOFPion.value[1]) { + return false; } } - if (pidmode == pid_flags::kHe3) { - if (track.sign() > 0) { - histos.fill(HIST("V2/histCosV2EP_He3_Pos"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); - } else { - histos.fill(HIST("V2/histCosV2EP_He3_Neg"), track.pt(), cent, std::cos(2 * (track.phi() - psi2))); + break; + } + + case ese_parameters::kKaon: { + if (cfgKaonPIDMode == ese_parameters::kRMSMode) { // RMS mode + float nSigmaUse = (track.pt() > cfgPtMaxforTPCOnlyPIDKaon) ? std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()) : track.tpcNSigmaKa(); + if (nSigmaUse < cfgnSigmaCutRMSKaon.value[0] || nSigmaUse > cfgnSigmaCutRMSKaon.value[1]) { + return false; + } + } else if (cfgKaonPIDMode == ese_parameters::kTPCMode) { // TPC mode + nSigmaTPC = getNSigmaTPC(track, ese_parameters::kKaon); + } else if (cfgKaonPIDMode == ese_parameters::kTOFOnlyMode) { // TOF only mode + if (!track.hasTOF()) + return false; + if (track.tofNSigmaKa() < cfgnSigmaCutTOFKaon.value[0] || track.tofNSigmaKa() > cfgnSigmaCutTOFKaon.value[1]) { + return false; } } + break; + } + + default: + LOGF(error, "Unknown POI: %d", POI); + return false; + } + if (nSigmaTPC < cfgnSigmaTPC->get(POI, 0u) || nSigmaTPC > cfgnSigmaTPC->get(POI, 1u)) { + return false; + } + if (cfgOpenITSPreselection) { + float nSigmaITS{getNSigmaITS(track, POI)}; + if (nSigmaITS < cfgnSigmaITS->get(POI, 0u) || nSigmaITS > cfgnSigmaITS->get(POI, 1u)) { + return false; } - return std::hypot(q2x, q2y) / std::sqrt(multi); - } else { - return 0; } + return true; } - template - void processESE(const TrackType tracks, float psi2, float q2, float cent, int pidmode, bool spcharge) // pidmode 1 for proton , 2 for he3 + template + void fillESECandidates(Tcoll const& collision, Ttrks const& tracks, float& q2Tarx, float& q2Tary, int& multiTar, float& q2Refx, float& q2Refy, int& multiRef) { - for (const auto& track : tracks) { - if (pidmode == pid_flags::kProton) { - if (spcharge) { - if (track.sign() > 0) { - histos.fill(HIST("ESE/hist_v2PosPr_Cent_Pt_q2He3"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); - } else { - histos.fill(HIST("ESE/hist_v2NegPr_Cent_Pt_q2He3"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); - } + float psi2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], 2); + float q2Tarinit{0.f}; + float q2Refinit{0.f}; + for (const auto& track : tracks) { // loop on tracks + if (!trackSelBasic(track)) { + continue; + } + // we fill the track info QA in the main process + fillTrackQAhist(track); + bool kIsTar{false}; + bool kIsRef{false}; + kIsTar = pidSel(track, poiTar); + kIsRef = pidSel(track, poiRef); + if (kIsTar && kIsRef && !cfgOpenAllowCrossTrack && poiRef != ese_parameters::kHadron) { + if (getNSigmaTPC(track, poiTar) < getNSigmaTPC(track, poiRef)) { + kIsRef = false; } else { - histos.fill(HIST("ESE/hist_v2Pr_Cent_Pt_q2He3"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); + kIsTar = false; } } - if (pidmode == pid_flags::kHe3) { - if (spcharge) { - if (track.sign() > 0) { - histos.fill(HIST("ESE/hist_v2PosHe3_Cent_Pt_q2Pr"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); - } else { - histos.fill(HIST("ESE/hist_v2NegHe3_Cent_Pt_q2Pr"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); + if (kIsTar) { + multiTar++; + q2Tarx += std::cos(2 * track.phi()); + q2Tary += std::sin(2 * track.phi()); + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + float nSigmaTPCTar{getNSigmaTPC(track, poiTar)}; + float nSigmaTOFTar{getNSigmaTOF(track, poiTar)}; + float nSigmaITSTar{getNSigmaITS(track, poiTar)}; + if (cfgOpenPIDQA) { + ese_parameters::hPIDQATar1D[0]->Fill(ese_parameters::Charges[poiTar] * track.pt()); + ese_parameters::hPIDQATar1D[1]->Fill(track.eta()); + ese_parameters::hPIDQATar1D[2]->Fill(track.phi()); + ese_parameters::hPIDQATar1D[3]->Fill(track.itsNCls()); + ese_parameters::hPIDQATar1D[4]->Fill(track.tpcNClsFound()); + ese_parameters::hPIDQATar1D[5]->Fill(track.itsChi2NCl()); + ese_parameters::hPIDQATar1D[6]->Fill(track.tpcChi2NCl()); + ese_parameters::hPIDQATar1D[7]->Fill(track.dcaXY()); + ese_parameters::hPIDQATar1D[8]->Fill(track.dcaZ()); + ese_parameters::hPIDQATar1D[9]->Fill(nSigmaTPCTar); + ese_parameters::hPIDQATar1D[10]->Fill(nSigmaTOFTar); + ese_parameters::hPIDQATar1D[11]->Fill(nSigmaITSTar); + ese_parameters::hPIDQATar2D[0]->Fill(track.sign() * correctedTpcInnerParam, track.tpcSignal()); + ese_parameters::hPIDQATar2D[1]->Fill(ese_parameters::Charges[poiTar] * track.pt(), nSigmaTPCTar); + ese_parameters::hPIDQATar2D[2]->Fill(ese_parameters::Charges[poiTar] * track.pt(), nSigmaTOFTar); + ese_parameters::hPIDQATar2D[3]->Fill(ese_parameters::Charges[poiTar] * track.pt(), nSigmaITSTar); + if (cfgOpen3DPIDPlots->get(0u)) { + ese_parameters::hPIDQATar3D[0]->Fill(nSigmaTOFTar, nSigmaITSTar, ese_parameters::Charges[poiTar] * track.pt()); + } + if (cfgOpen3DPIDPlots->get(1u)) { + ese_parameters::hPIDQATar3D[1]->Fill(nSigmaITSTar, nSigmaTPCTar, ese_parameters::Charges[poiTar] * track.pt()); + } + if (cfgOpen3DPIDPlots->get(2u)) { + ese_parameters::hPIDQATar3D[2]->Fill(nSigmaTOFTar, nSigmaTPCTar, ese_parameters::Charges[poiTar] * track.pt()); } - } else { - histos.fill(HIST("ESE/hist_v2He3_Cent_Pt_q2Pr"), track.pt(), cent, q2, std::cos(2 * (track.phi() - psi2))); + } + ese_parameters::eseCandidates.emplace_back(ESECandidate{ + collision.posZ(), collision.centFT0C(), psi2, q2Tarinit, q2Refinit, static_cast(track.sign()), correctedTpcInnerParam, track.tpcSignal(), ese_parameters::Charges[poiTar] * track.pt(), track.eta(), track.phi(), + track.dcaXY(), track.dcaZ(), static_cast(track.tpcNClsFound()), track.itsNCls(), track.tpcChi2NCl(), track.itsChi2NCl(), + nSigmaTPCTar, nSigmaTOFTar, nSigmaITSTar, track.itsClusterSizes()}); + } + if (kIsRef) { + multiRef++; + q2Refx += std::cos(2 * track.phi()); + q2Refy += std::sin(2 * track.phi()); + if (cfgOpenPIDQA && poiRef != ese_parameters::kHadron) { + bool heliumPID = track.pidForTracking() == o2::track::PID::Helium3 || track.pidForTracking() == o2::track::PID::Alpha; + float correctedTpcInnerParam = (heliumPID && cfgCompensatePIDinTracking) ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); + float nSigmaTPCRef{getNSigmaTPC(track, poiRef)}; + float nSigmaTOFRef{getNSigmaTOF(track, poiRef)}; + float nSigmaITSRef{getNSigmaITS(track, poiRef)}; + ese_parameters::hPIDQARef1D[0]->Fill(ese_parameters::Charges[poiRef] * track.pt()); + ese_parameters::hPIDQARef1D[1]->Fill(track.eta()); + ese_parameters::hPIDQARef1D[2]->Fill(track.phi()); + ese_parameters::hPIDQARef1D[3]->Fill(track.itsNCls()); + ese_parameters::hPIDQARef1D[4]->Fill(track.tpcNClsFound()); + ese_parameters::hPIDQARef1D[5]->Fill(track.itsChi2NCl()); + ese_parameters::hPIDQARef1D[6]->Fill(track.tpcChi2NCl()); + ese_parameters::hPIDQARef1D[7]->Fill(track.dcaXY()); + ese_parameters::hPIDQARef1D[8]->Fill(track.dcaZ()); + ese_parameters::hPIDQARef1D[9]->Fill(nSigmaTPCRef); + ese_parameters::hPIDQARef1D[10]->Fill(nSigmaTOFRef); + ese_parameters::hPIDQARef1D[11]->Fill(nSigmaITSRef); + ese_parameters::hPIDQARef2D[0]->Fill(track.sign() * correctedTpcInnerParam, track.tpcSignal()); + ese_parameters::hPIDQARef2D[1]->Fill(ese_parameters::Charges[poiRef] * track.pt(), nSigmaTPCRef); + ese_parameters::hPIDQARef2D[2]->Fill(ese_parameters::Charges[poiRef] * track.pt(), nSigmaTOFRef); + ese_parameters::hPIDQARef2D[3]->Fill(ese_parameters::Charges[poiRef] * track.pt(), nSigmaITSRef); + if (cfgOpen3DPIDPlots->get(0u)) { + ese_parameters::hPIDQARef3D[0]->Fill(nSigmaTOFRef, nSigmaITSRef, ese_parameters::Charges[poiRef] * track.pt()); + } + if (cfgOpen3DPIDPlots->get(1u)) { + ese_parameters::hPIDQARef3D[1]->Fill(nSigmaITSRef, nSigmaTPCRef, ese_parameters::Charges[poiRef] * track.pt()); + } + if (cfgOpen3DPIDPlots->get(2u)) { + ese_parameters::hPIDQARef3D[2]->Fill(nSigmaTOFRef, nSigmaTPCRef, ese_parameters::Charges[poiRef] * track.pt()); + } + } + if (cfgOpenv2Ref) { + ese_parameters::eseReferences.emplace_back(ESEReference{static_cast(track.sign()), ese_parameters::Charges[poiRef] * track.pt(), std::cos(2 * (track.phi() - psi2))}); } } } @@ -798,6 +1065,17 @@ struct FlowEsePHe3 { void init(InitContext const&) { + poiTar = getPOI(cfgTarName); + if (poiTar == ese_parameters::kHadron) { + LOGF(info, "This work flow is not designed to run over inclusive hadrons v2 ESE, you can only set the reference to be hadron, Reset Tar to He3"); + poiTar = ese_parameters::kHe3; + } + if (poiTar == poiRef) { + LOGF(error, "The POI and the reference cannot be the same, please change the configuration, Reset Tar to He3 Ref to Proton"); + poiTar = ese_parameters::kHe3; + poiRef = ese_parameters::kProton; + } + poiRef = getPOI(cfgRefName); detId = getDetId(cfgDetName); refAId = getDetId(cfgRefAName); refBId = getDetId(cfgRefBName); @@ -807,169 +1085,235 @@ struct FlowEsePHe3 { refAId = 4; refBId = 5; } - 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); + detInd = detId * 4 + cfgnTotalSystem * 4 * (2 - 2); + refAInd = refAId * 4 + cfgnTotalSystem * 4 * (2 - 2); + refBInd = refBId * 4 + cfgnTotalSystem * 4 * (2 - 2); - 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); + 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); - 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); - } + AxisSpec axisITSNcls = {10, -1.5, 8.5, "ITSNcls"}; + AxisSpec axisTPCNcls = {160, 0, 160, "TPCNcls"}; AxisSpec axisEvtPl = {100, -1.0 * constants::math::PI, constants::math::PI}; - AxisSpec axisvertexz = {100, -15., 15., "vrtx_{Z} [cm]"}; - histos.add("QA/histEventCount", "", {HistType::kTH1F, {{3, 0.0, 3.0}}}); - histos.get(HIST("QA/histEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos.get(HIST("QA/histEventCount"))->GetXaxis()->SetBinLabel(2, "after sel8"); - histos.get(HIST("QA/histEventCount"))->GetXaxis()->SetBinLabel(3, "after additional event cut"); - if (cfgUseAdditionalEventCut) { - histos.add("QA/histEventCountDetail", "Number of Event;; Count", {HistType::kTH1F, {{11, 0, 11}}}); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(1, "after sel8"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(2, "kIsGoodZvtxFT0vsPV"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(8, "occupancy"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(9, "MultCorrelationPVTracks"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(10, "MultCorrelationGlobalTracks"); - histos.get(HIST("QA/histEventCountDetail"))->GetXaxis()->SetBinLabel(11, "cfgEvSelV0AT0ACut"); - } + AxisSpec axisPhi = {200, -2.1 * constants::math::PI, 2.1 * constants::math::PI}; + AxisSpec axisCentForQA = {100, 0, 100}; + AxisSpec axisCharge = {4, -2, 2, "Charge"}; + AxisSpec axisRigidity = {200, -10, 10, "#it{p}^{TPC}/#it{z}"}; + AxisSpec axisdEdx = {1400, 0, 1400, "dE/dx [arb. units]"}; + AxisSpec axisEta = {200, -1.0, 1.0, "#eta"}; + AxisSpec axisQvecF = {300, -1, 1, "Qvec"}; + AxisSpec axisNch = {4000, 0, 4000, "N_{ch}"}; + AxisSpec axisT0C = {70, 0, 70000, "N_{ch} (T0C)"}; + AxisSpec axisT0A = {70, 0, 70000, "N_{ch} (T0A)"}; + AxisSpec axisNchPV = {4000, 0, 4000, "N_{ch} (PV)"}; + AxisSpec axisCos = {102, -1.02, 1.02, "Cos"}; + // hists for event level QA + histsESE.add("EventQA/histEventCount", ";Event Count;Counts", {HistType::kTH1F, {{11, 0, 11}}}); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(1, "after sel8"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(2, "kIsGoodZvtxFT0vsPV"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(8, "occupancy"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(9, "MultCorrelationPVTracks"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(10, "MultCorrelationGlobalTracks"); + histsESE.get(HIST("EventQA/histEventCount"))->GetXaxis()->SetBinLabel(11, "cfgEvSelV0AT0ACut"); + histsESE.add("EventQA/histVtz", ";#it{Vtz} (cm);Counts", {HistType::kTH1F, {{200, -20., +20.}}}); + histsESE.add("EventQA/histCent", ";Centrality (%);Counts", {HistType::kTH1F, {{100, 0., 100.}}}); if (cfgOpenFullEventQA) { - histos.add("QA/hist_globalTracks_centT0C_before", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNch}}); - histos.add("QA/hist_PVTracks_centT0C_before", "before cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNchPV}}); - histos.add("QA/hist_globalTracks_PVTracks_before", "before cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {cfgaxisNchPV, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multT0A_before", "before cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multV0A_before", "before cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_multV0A_multT0A_before", "before cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {cfgaxisT0A, cfgaxisT0A}}); - histos.add("QA/hist_multT0C_centT0C_before", "before cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisT0C}}); - histos.add("QA/hist_globalTracks_centT0C_after", "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNch}}); - histos.add("QA/hist_PVTracks_centT0C_after", "after cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisNchPV}}); - histos.add("QA/hist_globalTracks_PVTracks_after", "after cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {cfgaxisNchPV, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multT0A_after", "after cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_globalTracks_multV0A_after", "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {cfgaxisT0A, cfgaxisNch}}); - histos.add("QA/hist_multV0A_multT0A_after", "after cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {cfgaxisT0A, cfgaxisT0A}}); - histos.add("QA/hist_multT0C_centT0C_after", "after cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {cfgaxisCentForQA, cfgaxisT0C}}); - } - histos.add("QA/histVertexZRec", ";vrtx_{Z} [cm];counts", {HistType::kTH1F, {axisvertexz}}); - histos.add("QA/histCentrality", ";Centrality;counts", {HistType::kTH1F, {cfgaxisCentForQA}}); - histos.add("QA/histProtonNum", "ProtonNum;counts", {HistType::kTH1F, {{100, 0, 100}}}); - histos.add("QA/histHe3Num", "He3Num;counts", {HistType::kTH1F, {{20, 0, 20}}}); - histos.add("QA/histQvec_CorrL0_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histQvec_CorrL1_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histQvec_CorrL2_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histQvec_CorrL3_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {cfgaxisQvecF, cfgaxisQvecF, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL0_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL1_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL2_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histEvtPl_CorrL3_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); - histos.add("QA/histQvecRes_SigRefAV2", ";Centrality;Cos(Sig-RefA)", {HistType::kTProfile, {cfgaxisCent}}); - histos.add("QA/histQvecRes_SigRefBV2", ";Centrality;Cos(Sig-RefB)", {HistType::kTProfile, {cfgaxisCent}}); - histos.add("QA/histQvecRes_RefARefBV2", ";Centrality;Cos(RefA-RefB)", {HistType::kTProfile, {cfgaxisCent}}); - if (cfgOpenv2q) { - histos.add("V2/histCosV2EP_Pr_Pos", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("V2/histCosV2EP_Pr_Neg", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("V2/histCosV2EP_He3_Pos", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("V2/histCosV2EP_He3_Neg", ";#it{p}_{T};Centrality", {HistType::kTProfile2D, {cfgaxispt, cfgaxisCent}}); - histos.add("q2/hist_q2_Cen_Pr", ";q_{2} (TPC);Centrality", {HistType::kTH2F, {cfgaxisq2, cfgaxisCent}}); - histos.add("q2/hist_q2_Cen_He3", ";q_{2} (TPC);Centrality", {HistType::kTH2F, {cfgaxisq2, cfgaxisCent}}); - histos.add("q2/hist_q2_Pr", ";q_{2} (TPC);counts", {HistType::kTH1F, {cfgaxisq2}}); - histos.add("q2/hist_q2_He3", ";q_{2} (TPC);counts", {HistType::kTH1F, {cfgaxisq2}}); + histsESE.add("EventQA/hist_globalTracks_centT0C_before", "before cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); + histsESE.add("EventQA/hist_PVTracks_centT0C_before", "before cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, axisNchPV}}); + histsESE.add("EventQA/hist_globalTracks_PVTracks_before", "before cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {axisNchPV, axisNch}}); + histsESE.add("EventQA/hist_globalTracks_multT0A_before", "before cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + histsESE.add("EventQA/hist_globalTracks_multV0A_before", "before cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + histsESE.add("EventQA/hist_multV0A_multT0A_before", "before cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); + histsESE.add("EventQA/hist_multT0C_centT0C_before", "before cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); + histsESE.add("EventQA/hist_globalTracks_centT0C_after", "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); + histsESE.add("EventQA/hist_PVTracks_centT0C_after", "after cut;Centrality T0C;mulplicity PV tracks", {HistType::kTH2D, {axisCentForQA, axisNchPV}}); + histsESE.add("EventQA/hist_globalTracks_PVTracks_after", "after cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {axisNchPV, axisNch}}); + histsESE.add("EventQA/hist_globalTracks_multT0A_after", "after cut;mulplicity T0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + histsESE.add("EventQA/hist_globalTracks_multV0A_after", "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + histsESE.add("EventQA/hist_multV0A_multT0A_after", "after cut;mulplicity T0A;mulplicity V0A", {HistType::kTH2D, {axisT0A, axisT0A}}); + histsESE.add("EventQA/hist_multT0C_centT0C_after", "after cut;Centrality T0C;mulplicity T0C", {HistType::kTH2D, {axisCentForQA, axisT0C}}); } - if (cfgOpenESE) { - if (cfgOpenESEChargeSeperation) { - if (cfgOpenESEProton) { - histos.add("ESE/hist_v2PosPr_Cent_Pt_q2He3", ";#it{p}_{T};q_{2}(He3);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - histos.add("ESE/hist_v2NegPr_Cent_Pt_q2He3", ";#it{p}_{T};q_{2}(He3);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - } - if (cfgOpenESEHe3) { - histos.add("ESE/hist_v2PosHe3_Cent_Pt_q2Pr", ";#it{p}_{T};q_{2}(Proton);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); - histos.add("ESE/hist_v2NegHe3_Cent_Pt_q2Pr", ";#it{p}_{T};q_{2}(Proton);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); + histsESE.add("PlanQA/histQvec_CorrL0_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {axisQvecF, axisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histQvec_CorrL1_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {axisQvecF, axisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histQvec_CorrL2_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {axisQvecF, axisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histQvec_CorrL3_V2", ";#it{Q_{x}};#it{Q_{y}};Centrality", {HistType::kTH3F, {axisQvecF, axisQvecF, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL0_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL1_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL2_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histEvtPl_CorrL3_V2", ";EventPlane angle;Centrality", {HistType::kTH2F, {axisEvtPl, cfgaxisCent}}); + histsESE.add("PlanQA/histQvecRes_SigRefAV2", ";Centrality;Cos(Sig-RefA)", {HistType::kTProfile, {cfgaxisCent}}); + histsESE.add("PlanQA/histQvecRes_SigRefBV2", ";Centrality;Cos(Sig-RefB)", {HistType::kTProfile, {cfgaxisCent}}); + histsESE.add("PlanQA/histQvecRes_RefARefBV2", ";Centrality;Cos(RefA-RefB)", {HistType::kTProfile, {cfgaxisCent}}); + // hists for track level QA + histsESE.add("TrackQA/hist_dEdxTPC_All", ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x} [arb. units]", {HistType::kTH2F, {axisRigidity, axisdEdx}}); + histsESE.add("TrackQA/hist_pt_All", ";#it{p}_{T};counts", {HistType::kTH1F, {cfgaxispt}}); + histsESE.add("TrackQA/hist_eta_All", ";#it{#eta};counts", {HistType::kTH1F, {axisEta}}); + histsESE.add("TrackQA/hist_phi_All", ";#it{#phi};counts", {HistType::kTH1F, {axisPhi}}); + histsESE.add("TrackQA/hist_ITSNcls_All", ";ITSNcls;counts", {HistType::kTH1F, {axisITSNcls}}); + histsESE.add("TrackQA/hist_TPCNcls_All", ";TPCNcls;counts", {HistType::kTH1F, {axisTPCNcls}}); + histsESE.add("TrackQA/hist_ITSChi2NDF_All", ";ITS#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); + histsESE.add("TrackQA/hist_TPCChi2NDF_All", ";TPC#it{#chi^{2}}/NDF;counts", {HistType::kTH1F, {cfgaxisChi2Ncls}}); + histsESE.add("TrackQA/hist_DCAxy_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAxy}}); + histsESE.add("TrackQA/hist_DCAz_All", ";#it{DCA_{xy}};counts", {HistType::kTH1F, {cfgaxisDCAz}}); + histsESE.add("TrackQA/hist_MomRes_All", ";#it{p};Res(1 - corrted_p/track_p)", {HistType::kTH2F, {{100, 0, 10}, {100, -1, 1}}}); + histsESE.add("TrackQA/hist_He3AlphaTrackcounts_All", ";Track counts;Counts", {HistType::kTH1F, {{2, 0, 2}}}); + histsESE.get(HIST("TrackQA/hist_He3AlphaTrackcounts_All"))->GetXaxis()->SetBinLabel(1, "All Tracks"); + histsESE.get(HIST("TrackQA/hist_He3AlphaTrackcounts_All"))->GetXaxis()->SetBinLabel(2, "He3+Alpha"); + // v2 and ESEPlots + /// QA plots + if (cfgOpenPIDQA) { + ese_parameters::hPIDQATar2D[0] = histsESE.add(Form("ESE/TrackQA/hist_dEdxTPC_%s", cfgTarName.value.c_str()), ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x} [arb. units]", HistType::kTH2F, {axisRigidity, axisdEdx}); + ese_parameters::hPIDQATar1D[0] = histsESE.add(Form("ESE/TrackQA/hist_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};counts", HistType::kTH1F, {cfgaxispt}); + ese_parameters::hPIDQATar1D[1] = histsESE.add(Form("ESE/TrackQA/hist_eta_%s", cfgTarName.value.c_str()), ";#it{#eta};counts", HistType::kTH1F, {axisEta}); + ese_parameters::hPIDQATar1D[2] = histsESE.add(Form("ESE/TrackQA/hist_phi_%s", cfgTarName.value.c_str()), ";#it{#phi};counts", HistType::kTH1F, {axisPhi}); + ese_parameters::hPIDQATar1D[3] = histsESE.add(Form("ESE/TrackQA/hist_ITSNcls_%s", cfgTarName.value.c_str()), ";ITSNcls;counts", HistType::kTH1F, {axisITSNcls}); + ese_parameters::hPIDQATar1D[4] = histsESE.add(Form("ESE/TrackQA/hist_TPCNcls_%s", cfgTarName.value.c_str()), ";TPCNcls;counts", HistType::kTH1F, {axisTPCNcls}); + ese_parameters::hPIDQATar1D[5] = histsESE.add(Form("ESE/TrackQA/hist_ITSChi2NDF_%s", cfgTarName.value.c_str()), ";ITS#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQATar1D[6] = histsESE.add(Form("ESE/TrackQA/hist_TPCChi2NDF_%s", cfgTarName.value.c_str()), ";TPC#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQATar1D[7] = histsESE.add(Form("ESE/TrackQA/hist_DCAxy_%s", cfgTarName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAxy}); + ese_parameters::hPIDQATar1D[8] = histsESE.add(Form("ESE/TrackQA/hist_DCAz_%s", cfgTarName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAz}); + ese_parameters::hPIDQATar1D[9] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_%s", cfgTarName.value.c_str()), ";n#sigmaTPC;counts", HistType::kTH1F, {cfgnSigmaBinsTPC}); + ese_parameters::hPIDQATar2D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};n#sigmaTPC", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTPC}); + ese_parameters::hPIDQATar1D[10] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_%s", cfgTarName.value.c_str()), ";n#sigmaTOF;counts", HistType::kTH1F, {cfgnSigmaBinsTOF}); + ese_parameters::hPIDQATar2D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};n#sigmaTOF", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTOF}); + ese_parameters::hPIDQATar1D[11] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_%s", cfgTarName.value.c_str()), ";n#sigmaITS;counts", HistType::kTH1F, {cfgnSigmaBinsITS}); + ese_parameters::hPIDQATar2D[3] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_pt_%s", cfgTarName.value.c_str()), ";#it{p}_{T};n#sigmaITS", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsITS}); + if (cfgRefName.value != "kHadron") { + ese_parameters::hPIDQARef2D[0] = histsESE.add(Form("ESE/TrackQA/hist_dEdxTPC_%s", cfgRefName.value.c_str()), ";#it{p}^{TPC}/#it{z} (GeV/c);d#it{E}/d#it{x} [arb. units]", HistType::kTH2F, {axisRigidity, axisdEdx}); + ese_parameters::hPIDQARef1D[0] = histsESE.add(Form("ESE/TrackQA/hist_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};counts", HistType::kTH1F, {cfgaxispt}); + ese_parameters::hPIDQARef1D[1] = histsESE.add(Form("ESE/TrackQA/hist_eta_%s", cfgRefName.value.c_str()), ";#it{#eta};counts", HistType::kTH1F, {axisEta}); + ese_parameters::hPIDQARef1D[2] = histsESE.add(Form("ESE/TrackQA/hist_phi_%s", cfgRefName.value.c_str()), ";#it{#phi};counts", HistType::kTH1F, {axisPhi}); + ese_parameters::hPIDQARef1D[3] = histsESE.add(Form("ESE/TrackQA/hist_ITSNcls_%s", cfgRefName.value.c_str()), ";ITSNcls;counts", HistType::kTH1F, {axisITSNcls}); + ese_parameters::hPIDQARef1D[4] = histsESE.add(Form("ESE/TrackQA/hist_TPCNcls_%s", cfgRefName.value.c_str()), ";TPCNcls;counts", HistType::kTH1F, {axisTPCNcls}); + ese_parameters::hPIDQARef1D[5] = histsESE.add(Form("ESE/TrackQA/hist_ITSChi2NDF_%s", cfgRefName.value.c_str()), ";ITS#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQARef1D[6] = histsESE.add(Form("ESE/TrackQA/hist_TPCChi2NDF_%s", cfgRefName.value.c_str()), ";TPC#it{#chi^{2}}/NDF;counts", HistType::kTH1F, {cfgaxisChi2Ncls}); + ese_parameters::hPIDQARef1D[7] = histsESE.add(Form("ESE/TrackQA/hist_DCAxy_%s", cfgRefName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAxy}); + ese_parameters::hPIDQARef1D[8] = histsESE.add(Form("ESE/TrackQA/hist_DCAz_%s", cfgRefName.value.c_str()), ";#it{DCA_{xy}};counts", HistType::kTH1F, {cfgaxisDCAz}); + ese_parameters::hPIDQARef1D[9] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_%s", cfgRefName.value.c_str()), ";n#sigmaTPC;counts", HistType::kTH1F, {cfgnSigmaBinsTPC}); + ese_parameters::hPIDQARef2D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTPC_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};n#sigmaTPC", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTPC}); + ese_parameters::hPIDQARef1D[10] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_%s", cfgRefName.value.c_str()), ";n#sigmaTOF;counts", HistType::kTH1F, {cfgnSigmaBinsTOF}); + ese_parameters::hPIDQARef2D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOF_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};n#sigmaTOF", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsTOF}); + ese_parameters::hPIDQARef1D[11] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_%s", cfgRefName.value.c_str()), ";n#sigmaITS;counts", HistType::kTH1F, {cfgnSigmaBinsITS}); + ese_parameters::hPIDQARef2D[3] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITS_pt_%s", cfgRefName.value.c_str()), ";#it{p}_{T};n#sigmaITS", HistType::kTH2F, {cfgaxispt, cfgnSigmaBinsITS}); + } + if (cfgOpen3DPIDPlots->get(0u)) { + ese_parameters::hPIDQATar3D[0] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFITSPt_%s", cfgTarName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxispt}); + if (cfgRefName.value != "kHadron") { + ese_parameters::hPIDQARef3D[0] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFITSPt_%s", cfgRefName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}ITS;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsITS, cfgaxispt}); } - } else { - if (cfgOpenESEProton) { - histos.add("ESE/hist_v2Pr_Cent_Pt_q2He3", ";#it{p}_{T};q_{2}(He3);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); + } + if (cfgOpen3DPIDPlots->get(1u)) { + ese_parameters::hPIDQATar3D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITSTPCPt_%s", cfgTarName.value.c_str()), ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxispt}); + if (cfgRefName.value != "kHadron") { + ese_parameters::hPIDQARef3D[1] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaITSTPCPt_%s", cfgRefName.value.c_str()), ";n_{#sigma}ITS;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsITS, cfgnSigmaBinsTPC, cfgaxispt}); } - if (cfgOpenESEHe3) { - histos.add("ESE/hist_v2He3_Cent_Pt_q2Pr", ";#it{p}_{T};q_{2}(Proton);Centrality", HistType::kTProfile3D, {cfgaxispt, cfgaxisq2, cfgaxisCent}); + } + if (cfgOpen3DPIDPlots->get(2u)) { + ese_parameters::hPIDQATar3D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFTPCPt_%s", cfgTarName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxispt}); + if (cfgRefName.value != "kHadron") { + ese_parameters::hPIDQARef3D[2] = histsESE.add(Form("ESE/TrackQA/hist_nSigmaTOFTPCPt_%s", cfgRefName.value.c_str()), ";n_{#sigma}TOF;n_{#sigma}TPC;#it{p}_{T}", HistType::kTH3F, {cfgnSigmaBinsTOF, cfgnSigmaBinsTPC, cfgaxispt}); } } } + // v2 plots + if (cfgOpenv2Tar) { + ese_parameters::hv2Tar[0] = histsESE.add(Form("ESE/V2/hist_%sPosV2", cfgTarName.value.c_str()), ";#it{p}_{T};Centrality (%);#it{q}_{2}", {HistType::kTProfile3D, {cfgaxispt, cfgaxisCent, cfgaxisq2Tar}}); + ese_parameters::hv2Tar[1] = histsESE.add(Form("ESE/V2/hist_%sNegV2", cfgTarName.value.c_str()), ";#it{p}_{T};Centrality (%);#it{q}_{2}", {HistType::kTProfile3D, {cfgaxispt, cfgaxisCent, cfgaxisq2Tar}}); + } + if (cfgOpenv2Ref) { + ese_parameters::hv2Ref[0] = histsESE.add(Form("ESE/V2/hist_%sPosV2", cfgRefName.value.c_str()), ";#it{p}_{T};Centrality (%);#it{q}_{2}", {HistType::kTProfile3D, {cfgaxispt, cfgaxisCent, cfgaxisq2Ref}}); + ese_parameters::hv2Ref[1] = histsESE.add(Form("ESE/V2/hist_%sNegV2", cfgRefName.value.c_str()), ";#it{p}_{T};Centrality (%);#it{q}_{2}", {HistType::kTProfile3D, {cfgaxispt, cfgaxisCent, cfgaxisq2Ref}}); + } + // ESE plots + if (cfgOpenESEQA) { + ese_parameters::hESEQATar1D[0] = histsESE.add(Form("ESE/ESEQA/hist_%sNum", cfgTarName.value.c_str()), ";Num_{Proton}/Event;counts", HistType::kTH1F, {{100, 0, 100}}); + ese_parameters::hESEQATar1D[1] = histsESE.add(Form("ESE/ESEQA/hist_%sq2", cfgTarName.value.c_str()), ";#it{q}_{2};counts", HistType::kTH1F, {cfgaxisq2Tar}); + ese_parameters::hESEQATar1D[2] = histsESE.add(Form("ESE/ESEQA/hist_%sq2Numerator", cfgTarName.value.c_str()), ";#it{q}_{2} numerator;counts", HistType::kTH1F, {cfgq2NumeratorTar}); + ese_parameters::hESEQATar1D[3] = histsESE.add(Form("ESE/ESEQA/hist_%sq2Denominator", cfgTarName.value.c_str()), ";#it{q}_{2} denominator;counts", HistType::kTH1F, {cfgq2DenominatorTar}); + ese_parameters::hESEQATar2D = histsESE.add(Form("ESE/ESEQA/hist_%sq2_Cent", cfgTarName.value.c_str()), ";#it{q}_{2};Centrality (%)", HistType::kTH2F, {cfgaxisq2Tar, cfgaxisCent}); + ese_parameters::hESEQARef1D[0] = histsESE.add(Form("ESE/ESEQA/hist_%sNum", cfgRefName.value.c_str()), ";Num_{He3}/Event;counts", HistType::kTH1F, {{10, 0, 10}}); + ese_parameters::hESEQARef1D[1] = histsESE.add(Form("ESE/ESEQA/hist_%sq2", cfgRefName.value.c_str()), ";#it{q}_{2};counts", HistType::kTH1F, {cfgaxisq2Ref}); + ese_parameters::hESEQARef1D[2] = histsESE.add(Form("ESE/ESEQA/hist_%sq2Numerator", cfgRefName.value.c_str()), ";#it{q}_{2} numerator;counts", HistType::kTH1F, {cfgq2NumeratorRef}); + ese_parameters::hESEQARef1D[3] = histsESE.add(Form("ESE/ESEQA/hist_%sq2Denominator", cfgRefName.value.c_str()), ";#it{q}_{2} denominator;counts", HistType::kTH1F, {cfgq2DenominatorRef}); + ese_parameters::hESEQARef2D = histsESE.add(Form("ESE/ESEQA/hist_%sq2_Cent", cfgRefName.value.c_str()), ";#it{q}_{2};Centrality (%)", HistType::kTH2F, {cfgaxisq2Ref, cfgaxisCent}); + } + if (cfgOpenESE) { + ese_parameters::hESETar = histsESE.add(Form("ESE/ESE/histESE_%s", cfgTarName.value.c_str()), ";#it{p}_{T};Centrality (%);#it{q}_{2};cos(#phi-#Psi_{2});Charge", HistType::kTHnSparseF, {cfgaxispt, cfgaxisCent, cfgaxisq2Ref, axisCos, axisCharge}); + } } - void process(soa::Filtered>::iterator const& collision, soa::Filtered> const& tracks) + void process(soa::Filtered>::iterator const& collision, TracksPIDFull const& tracks) { - const auto cent = collision.centFT0C(); - histos.fill(HIST("QA/histEventCount"), 0.5); - if (!collision.sel8()) - return; - if (tracks.size() < 1) - return; - histos.fill(HIST("QA/histEventCount"), 1.5); - if (cfgOpenFullEventQA) { - histos.fill(HIST("QA/hist_globalTracks_centT0C_before"), cent, tracks.size()); - histos.fill(HIST("QA/hist_PVTracks_centT0C_before"), cent, collision.multNTracksPV()); - histos.fill(HIST("QA/hist_globalTracks_PVTracks_before"), collision.multNTracksPV(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multT0A_before"), collision.multFT0A(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multV0A_before"), collision.multFV0A(), tracks.size()); - histos.fill(HIST("QA/hist_multV0A_multT0A_before"), collision.multFT0A(), collision.multFV0A()); - histos.fill(HIST("QA/hist_multT0C_centT0C_before"), cent, collision.multFT0C()); - } - if (cfgUseAdditionalEventCut && !selEvent(collision, tracks.size(), cent)) { + ese_parameters::eseCandidates.clear(); + ese_parameters::eseReferences.clear(); + const float centrality{collision.centFT0C()}; + const int64_t multTrk{tracks.size()}; + if (cfgOpenFullEventQA) + fillEventQAhistBe(collision, multTrk, centrality); + if (!eventSelBasic(collision, multTrk, centrality, true)) return; + if (cfgOpenFullEventQA) + fillEventQAhistAf(collision, multTrk, centrality); + float q2Tarx{0.}; + float q2Tary{0.}; + float q2Refx{0.}; + float q2Refy{0.}; + int multiTar{0}; + int multiRef{0}; + fillHistosQvec(collision); + fillESECandidates(collision, tracks, q2Tarx, q2Tary, multiTar, q2Refx, q2Refy, multiRef); + float q2Tar{calculateq2(q2Tarx, q2Tary, multiTar)}; + float q2Ref{calculateq2(q2Refx, q2Refy, multiRef)}; + if (cfgOpenESEQA) { + ese_parameters::hESEQATar1D[0]->Fill(multiTar); + ese_parameters::hESEQATar1D[1]->Fill(q2Tar); + ese_parameters::hESEQATar1D[2]->Fill(std::hypot(q2Tarx, q2Tary)); + ese_parameters::hESEQATar1D[3]->Fill(std::sqrt(static_cast(multiTar))); + ese_parameters::hESEQATar2D->Fill(q2Tar, centrality); + ese_parameters::hESEQARef1D[0]->Fill(multiRef); + ese_parameters::hESEQARef1D[1]->Fill(q2Ref); + ese_parameters::hESEQARef2D->Fill(q2Ref, centrality); + ese_parameters::hESEQARef1D[2]->Fill(std::hypot(q2Refx, q2Refy)); + ese_parameters::hESEQARef1D[3]->Fill(std::sqrt(static_cast(multiRef))); } - histos.fill(HIST("QA/histEventCount"), 2.5); - histos.fill(HIST("QA/histCentrality"), cent); - histos.fill(HIST("QA/histVertexZRec"), collision.posZ()); - if (cfgOpenFullEventQA) { - histos.fill(HIST("QA/hist_globalTracks_centT0C_after"), cent, tracks.size()); - histos.fill(HIST("QA/hist_PVTracks_centT0C_after"), cent, collision.multNTracksPV()); - histos.fill(HIST("QA/hist_globalTracks_PVTracks_after"), collision.multNTracksPV(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multT0A_after"), collision.multFT0A(), tracks.size()); - histos.fill(HIST("QA/hist_globalTracks_multV0A_after"), collision.multFV0A(), tracks.size()); - histos.fill(HIST("QA/hist_multV0A_multT0A_after"), collision.multFT0A(), collision.multFV0A()); - histos.fill(HIST("QA/hist_multT0C_centT0C_after"), cent, collision.multFT0C()); - } - auto tracksPr = protonTrackSet->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - auto tracksHe3 = he3TrackSet->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - int multiPr = tracksPr.size(); - int multiHe3 = tracksHe3.size(); - // LOGF(info, Form("Collison ID + 1; Proton Num:%d; He3 Num:%d;\n", multiPr, multiHe3)); - histos.fill(HIST("QA/histProtonNum"), multiPr); - histos.fill(HIST("QA/histHe3Num"), multiHe3); - if (multiPr < 1 && multiHe3 < 1) - return; // Reject Collisions without enough POI - for (auto i = 0; i < static_cast(cfgnMods->size()); i++) { - int detIndGlobal = detId * 4 + cfgnTotalSystem * 4 * (cfgnMods->at(i) - 2); - float psiNGlobal = helperEP.GetEventPlane(collision.qvecRe()[detIndGlobal + 3], collision.qvecIm()[detIndGlobal + 3], cfgnMods->at(i)); - if (cfgnMods->at(i) == fourier_mode::kMode2) { - // LOGF(info, "Process q2\n"); - float q2Proton = calculateq2(tracksPr, psiNGlobal, cent, 1); - float q2He3 = calculateq2(tracksHe3, psiNGlobal, cent, 2); - histos.fill(HIST("q2/hist_q2_Pr"), q2Proton); - histos.fill(HIST("q2/hist_q2_He3"), q2He3); - histos.fill(HIST("q2/hist_q2_Cen_Pr"), q2Proton, cent); - histos.fill(HIST("q2/hist_q2_Cen_He3"), q2He3, cent); - if (cfgOpenESE && multiPr > 0 && multiHe3 > 0) { - // LOGF(info, "Process ESE\n"); - if (cfgOpenESEProton) { - processESE(tracksPr, psiNGlobal, q2Proton, cent, 1, cfgOpenESEChargeSeperation); - } - if (cfgOpenESEHe3) { - processESE(tracksHe3, psiNGlobal, q2He3, cent, 2, cfgOpenESEChargeSeperation); - } + if (cfgOpenv2Ref) { + for (const auto& c : ese_parameters::eseReferences) { + if (c.signRef > 0) { + ese_parameters::hv2Ref[0]->Fill(c.ptRef, centrality, q2Ref, c.v2Ref); + } else { + ese_parameters::hv2Ref[1]->Fill(c.ptRef, centrality, q2Ref, c.v2Ref); + } + } + } + if (multiTar == 0) + return; + for (const auto& c : ese_parameters::eseCandidates) { + eseTable(c.vtz, c.centFT0C, c.psi2FT0C, q2Tar, q2Ref, c.signTar, c.tpcInnerParamTar, c.tpcSignalTar, c.ptTar, c.etaTar, c.phiTar, c.dcaXYTar, c.dcaZTar, c.tpcNclsTar, c.itsNclsTar, c.tpcChi2NDFTar, c.itsChi2NDFTar, c.tpcNSigmaTar, c.tofNSigmaTar, c.itsNSigmaTar, c.itsClusSizeTar); + if (cfgOpenESE) { + ese_parameters::hESETar->Fill(c.ptTar, c.centFT0C, q2Ref, std::cos(2 * (c.phiTar - c.psi2FT0C)), c.signTar); + } + if (cfgOpenv2Tar) { + if (c.signTar > 0) { + ese_parameters::hv2Tar[0]->Fill(c.ptTar, c.centFT0C, q2Tar, std::cos(2 * (c.phiTar - c.psi2FT0C))); + } else { + ese_parameters::hv2Tar[1]->Fill(c.ptTar, c.centFT0C, q2Tar, std::cos(2 * (c.phiTar - c.psi2FT0C))); } - // LOGF(info, "Process for this event over\n"); } - fillHistosQvec(collision, cfgnMods->at(i)); } } }; @@ -977,7 +1321,6 @@ struct FlowEsePHe3 { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), }; } diff --git a/PWGCF/Flow/Tasks/flowEseTask.cxx b/PWGCF/Flow/Tasks/flowEseTask.cxx new file mode 100644 index 00000000000..15bb95d27be --- /dev/null +++ b/PWGCF/Flow/Tasks/flowEseTask.cxx @@ -0,0 +1,455 @@ +// 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 flowEseTask.cxx +/// \brief Task for flow and event shape engineering correlation with other observation. +/// \author Alice Collaboration +/// \since 2023-05-15 +/// \version 1.0 +/// +/// This task calculates flow and event shape engineering +/// using Q-vector and event plane methods. + +// C++/ROOT includes. +#include +#include +#include +#include +#include + +#include +#include +#include + +// o2Physics includes. +#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" + +#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/StaticFor.h" +#include "Framework/runDataProcessing.h" + +// o2 includes. + +using namespace o2; +using namespace o2::framework; + +using MyCollisions = soa::Join; +using MyTracks = soa::Join; +using BCsWithRun3Matchings = soa::Join; + +struct FlowEseTask { + HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + Configurable> cfgNmods{"cfgNmods", {2}, "Modulation of interest"}; + Configurable cfgDetName{"cfgDetName", "FT0C", "The name of detector to be analyzed"}; + Configurable cfgRefAName{"cfgRefAName", "TPCpos", "The name of detector for reference A"}; + Configurable cfgRefBName{"cfgRefBName", "TPCneg", "The name of detector for reference B"}; + + Configurable cfgMinPt{"cfgMinPt", 0.15f, "Minimum transverse momentum for charged track"}; + Configurable cfgMaxEta{"cfgMaxEta", 0.8f, "Maximum pseudorapidiy for charged track"}; + Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.1f, "Maximum transverse DCA"}; + Configurable cfgMaxDCAzToPVcut{"cfgMaxDCAzToPVcut", 1.0f, "Maximum longitudinal DCA"}; + + ConfigurableAxis cfgAxisQvecF{"cfgAxisQvecF", {300, -1, 1}, ""}; + ConfigurableAxis cfgAxisQvec{"cfgAxisQvec", {100, -3, 3}, ""}; + ConfigurableAxis cfgAxisCent{"cfgAxisCent", {100, 0, 100}, ""}; + + ConfigurableAxis cfgAxisCos{"cfgAxisCos", {102, -1.02, 1.02}, ""}; + ConfigurableAxis cfgAxisPt{"cfgAxisPt", {100, 0, 10}, ""}; + ConfigurableAxis cfgAxisCentMerged{"cfgAxisCentMerged", {20, 0, 100}, ""}; + ConfigurableAxis cfgAxisMultNum{"cfgAxisMultNum", {300, 0, 2700}, ""}; + ConfigurableAxis cfgaxisQ{"cfgaxisQ", {1000, 0, 1000}, ""}; + + static constexpr float kMinAmplitudeThreshold = 1e-4f; + static constexpr int kDefaultModulation = 2; + static constexpr std::array kCent = {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}; + static constexpr std::array kSeparator = {125, 204, 110, 172, 92, 143, 74, 116, 57, 92, 43, 70, 31, 50, 21, 34, 14, 22, 5, 9}; + + EventPlaneHelper helperEP; + + void init(InitContext const&) + { + AxisSpec axisCent{cfgAxisCent, "centrality"}; + AxisSpec axisQvec{cfgAxisQvec, "Q"}; + AxisSpec axisQvecF{cfgAxisQvecF, "Q"}; + AxisSpec axisEvtPl = {100, -1.0 * constants::math::PI, constants::math::PI}; + + AxisSpec axisCos{cfgAxisCos, "angle function"}; + AxisSpec axisPt{cfgAxisPt, "trasverse momentum"}; + AxisSpec axisCentMerged{cfgAxisCentMerged, "merged centrality"}; + AxisSpec axisMultNum{cfgAxisMultNum, "statistic of mult"}; + AxisSpec axisQ{cfgaxisQ, "result of q2"}; + + histosQA.add(Form("histQvecV2"), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecCent"), "", {HistType::kTH2F, {axisQ, axisCent}}); + histosQA.add(Form("histEvtPlV2"), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histQvecRes_SigRefAV2"), "", {HistType::kTH2F, {axisQvecF, axisCent}}); + histosQA.add(Form("histCosDetV2"), "", {HistType::kTH3F, {axisCentMerged, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_0010Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_0010Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_0010Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_1020Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_1020Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_1020Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_2030Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_2030Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_2030Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_3040Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_3040Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_3040Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_4050Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_4050Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_4050Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_5060Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_5060Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_5060Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_6070Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_6070Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_6070Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_7080Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_7080Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_7080Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_8090Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_8090Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_8090Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_9010Left"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_9010Mid"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histCosDetV2_9010Right"), "", {HistType::kTH3F, {axisQvecF, axisPt, axisCos}}); + histosQA.add(Form("histMult_Cent"), "", {HistType::kTH2F, {axisMultNum, axisCent}}); + } + + template + bool selectEvent(CollType const& collision) + { + if (!collision.sel8()) { + return false; + } + if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return false; + } + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + + return true; + } + + template + bool selectTrack(TrackType const& track) + { + if (track.pt() < cfgMinPt) { + return false; + } + if (std::abs(track.eta()) > cfgMaxEta) { + return false; + } + if (!track.passedITSNCls()) { + return false; + } + if (!track.passedITSChi2NDF()) { + return false; + } + if (!track.passedITSHits()) { + return false; + } + if (!track.passedTPCCrossedRowsOverNCls()) { + return false; + } + if (!track.passedTPCChi2NDF()) { + return false; + } + if (!track.passedDCAxy()) { + return false; + } + if (!track.passedDCAz()) { + return false; + } + + return true; + } + + template + void fillHistosQvec(CollType const& collision, int nmode) + { + if (nmode == kDefaultModulation) { + histosQA.fill(HIST("histQvecV2"), collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], + collision.centFT0C()); + histosQA.fill(HIST("histQvecCent"), std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()), collision.centFT0C()); + histosQA.fill(HIST("histEvtPlV2"), + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), + collision.centFT0C()); + histosQA.fill(HIST("histQvecRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), + collision.centFT0C()); + histosQA.fill(HIST("histMult_Cent"), collision.sumAmplFT0C(), collision.centFT0C()); + } + } + + template + void fillHistosFlow(CollType const& collision, TrackType const& tracks, int nmode) + { + double q2 = std::sqrt(collision.qvecFT0CReVec()[0] * collision.qvecFT0CReVec()[0] + collision.qvecFT0CImVec()[0] * collision.qvecFT0CImVec()[0]) * std::sqrt(collision.sumAmplFT0C()); + if (collision.sumAmplFT0C() < kMinAmplitudeThreshold) { + return; + } + for (auto const& trk : tracks) { + if (!selectTrack(trk)) { + continue; + } + if (nmode == kDefaultModulation) { + histosQA.fill(HIST("histCosDetV2"), collision.centFT0C(), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + if (collision.centFT0C() > kCent[0] && collision.centFT0C() <= kCent[1] && q2 < kSeparator[0]) { + histosQA.fill(HIST("histCosDetV2_0010Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[0] && collision.centFT0C() <= kCent[1] && q2 > kSeparator[0] && q2 <= kSeparator[1]) { + histosQA.fill(HIST("histCosDetV2_0010Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[0] && collision.centFT0C() <= kCent[1] && q2 > kSeparator[1]) { + histosQA.fill(HIST("histCosDetV2_0010Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[1] && collision.centFT0C() <= kCent[2] && q2 < kSeparator[2]) { + histosQA.fill(HIST("histCosDetV2_1020Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[1] && collision.centFT0C() <= kCent[2] && q2 > kSeparator[2] && q2 <= kSeparator[3]) { + histosQA.fill(HIST("histCosDetV2_1020Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[1] && collision.centFT0C() <= kCent[2] && q2 > kSeparator[3]) { + histosQA.fill(HIST("histCosDetV2_1020Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[2] && collision.centFT0C() <= kCent[3] && q2 < kSeparator[4]) { + histosQA.fill(HIST("histCosDetV2_2030Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[2] && collision.centFT0C() <= kCent[3] && q2 > kSeparator[4] && q2 <= kSeparator[5]) { + histosQA.fill(HIST("histCosDetV2_2030Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[2] && collision.centFT0C() <= kCent[3] && q2 > kSeparator[5]) { + histosQA.fill(HIST("histCosDetV2_2030Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[3] && collision.centFT0C() <= kCent[4] && q2 < kSeparator[6]) { + histosQA.fill(HIST("histCosDetV2_3040Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[3] && collision.centFT0C() <= kCent[4] && q2 > kSeparator[6] && q2 <= kSeparator[7]) { + histosQA.fill(HIST("histCosDetV2_3040Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[3] && collision.centFT0C() <= kCent[4] && q2 > kSeparator[7]) { + histosQA.fill(HIST("histCosDetV2_3040Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[4] && collision.centFT0C() <= kCent[5] && q2 < kSeparator[8]) { + histosQA.fill(HIST("histCosDetV2_4050Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[4] && collision.centFT0C() <= kCent[5] && q2 > kSeparator[8] && q2 <= kSeparator[9]) { + histosQA.fill(HIST("histCosDetV2_4050Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[4] && collision.centFT0C() <= kCent[5] && q2 > kSeparator[9]) { + histosQA.fill(HIST("histCosDetV2_4050Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[5] && collision.centFT0C() <= kCent[6] && q2 < kSeparator[10]) { + histosQA.fill(HIST("histCosDetV2_5060Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[5] && collision.centFT0C() <= kCent[6] && q2 > kSeparator[10] && q2 <= kSeparator[11]) { + histosQA.fill(HIST("histCosDetV2_5060Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[5] && collision.centFT0C() <= kCent[6] && q2 > kSeparator[11]) { + histosQA.fill(HIST("histCosDetV2_5060Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[6] && collision.centFT0C() <= kCent[7] && q2 < kSeparator[12]) { + histosQA.fill(HIST("histCosDetV2_6070Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[6] && collision.centFT0C() <= kCent[7] && q2 > kSeparator[12] && q2 <= kSeparator[13]) { + histosQA.fill(HIST("histCosDetV2_6070Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[6] && collision.centFT0C() <= kCent[7] && q2 > kSeparator[13]) { + histosQA.fill(HIST("histCosDetV2_6070Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[7] && collision.centFT0C() <= kCent[8] && q2 < kSeparator[14]) { + histosQA.fill(HIST("histCosDetV2_7080Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[7] && collision.centFT0C() <= kCent[8] && q2 > kSeparator[14] && q2 <= kSeparator[15]) { + histosQA.fill(HIST("histCosDetV2_7080Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[7] && collision.centFT0C() <= kCent[8] && q2 > kSeparator[15]) { + histosQA.fill(HIST("histCosDetV2_7080Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[8] && collision.centFT0C() <= kCent[9] && q2 < kSeparator[16]) { + histosQA.fill(HIST("histCosDetV2_8090Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[8] && collision.centFT0C() <= kCent[9] && q2 > kSeparator[16] && q2 <= kSeparator[17]) { + histosQA.fill(HIST("histCosDetV2_8090Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[8] && collision.centFT0C() <= kCent[9] && q2 > kSeparator[17]) { + histosQA.fill(HIST("histCosDetV2_8090Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[9] && collision.centFT0C() <= kCent[10] && q2 < kSeparator[18]) { + histosQA.fill(HIST("histCosDetV2_9010Left"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[9] && collision.centFT0C() <= kCent[10] && q2 > kSeparator[18] && q2 <= kSeparator[19]) { + histosQA.fill(HIST("histCosDetV2_9010Mid"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + if (collision.centFT0C() > kCent[9] && collision.centFT0C() <= kCent[10] && q2 > kSeparator[19]) { + histosQA.fill(HIST("histCosDetV2_9010Right"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], collision.qvecFT0CImVec()[0], nmode), helperEP.GetEventPlane(collision.qvecTPCposReVec()[0], collision.qvecTPCposImVec()[0], nmode), nmode), trk.pt(), + std::cos(static_cast(nmode) * (trk.phi() - + helperEP.GetEventPlane(collision.qvecFT0CReVec()[0], + collision.qvecFT0CImVec()[0], + nmode)))); + } + } + } + } + + void process(MyCollisions::iterator const& collision, MyTracks const& tracks) + { + if (!selectEvent(collision)) { + return; + } + for (std::size_t i = 0; i < cfgNmods->size(); i++) { + fillHistosQvec(collision, cfgNmods->at(i)); + fillHistosFlow(collision, tracks, cfgNmods->at(i)); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx index c4d9d5d0ef7..bf001b02df2 100644 --- a/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx +++ b/PWGCF/Flow/Tasks/flowGfwOmegaXi.cxx @@ -14,39 +14,45 @@ /// \since Sep/13/2024 /// \brief This task is to caculate V0s and cascades flow by GenericFramework -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "GFWPowerArray.h" #include "GFW.h" #include "GFWCumulant.h" +#include "GFWPowerArray.h" #include "GFWWeights.h" -#include "Common/DataModel/Qvectors.h" -#include "Common/Core/EventPlaneHelper.h" -#include "ReconstructionDataFormats/Track.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/trackUtilities.h" + #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGMM/Mult/DataModel/Index.h" + +#include "Common/Core/EventPlaneHelper.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/PIDResponseITS.h" +#include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" +#include + #include "TList.h" -#include -#include #include #include #include +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -55,14 +61,24 @@ namespace { std::shared_ptr refc22[10]; std::shared_ptr refc24[10]; +std::shared_ptr refc22Full[10]; +std::shared_ptr refc32[10]; std::shared_ptr k0sc22[10]; std::shared_ptr k0sc24[10]; +std::shared_ptr k0sc22Full[10]; +std::shared_ptr k0sc32[10]; std::shared_ptr lambdac22[10]; std::shared_ptr lambdac24[10]; +std::shared_ptr lambdac22Full[10]; +std::shared_ptr lambdac32[10]; std::shared_ptr xic22[10]; std::shared_ptr xic24[10]; +std::shared_ptr xic22Full[10]; +std::shared_ptr xic32[10]; std::shared_ptr omegac22[10]; std::shared_ptr omegac24[10]; +std::shared_ptr omegac22Full[10]; +std::shared_ptr omegac32[10]; } // namespace #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -70,39 +86,78 @@ std::shared_ptr omegac24[10]; struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.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(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") O2_DEFINE_CONFIGURABLE(cfgMassBins, std::vector, (std::vector{80, 32, 14, 16}), "Number of K0s, Lambda, Xi, Omega mass axis bins for c22") O2_DEFINE_CONFIGURABLE(cfgDeltaPhiLocDen, int, 3, "Number of delta phi for local density, 200 bins in 2 pi") - // topological cut for V0 - O2_DEFINE_CONFIGURABLE(cfgv0_radius, float, 5.0f, "minimum decay radius") - O2_DEFINE_CONFIGURABLE(cfgv0_v0cospa, float, 0.995f, "minimum cosine of pointing angle") - O2_DEFINE_CONFIGURABLE(cfgv0_dcadautopv, float, 0.1f, "minimum daughter DCA to PV") - O2_DEFINE_CONFIGURABLE(cfgv0_dcav0dau, float, 0.5f, "maximum DCA among V0 daughters") - O2_DEFINE_CONFIGURABLE(cfgv0_mk0swindow, float, 0.1f, "Invariant mass window of K0s") - O2_DEFINE_CONFIGURABLE(cfgv0_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") - O2_DEFINE_CONFIGURABLE(cfgv0_ArmPodocut, float, 0.2f, "Armenteros Podolski cut for K0") - // topological cut for cascade - O2_DEFINE_CONFIGURABLE(cfgcasc_radius, float, 0.5f, "minimum decay radius") - O2_DEFINE_CONFIGURABLE(cfgcasc_casccospa, float, 0.999f, "minimum cosine of pointing angle") - 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_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") - // track quality and type selections - O2_DEFINE_CONFIGURABLE(cfgtpcclusters, int, 70, "minimum number of TPC clusters requirement") - O2_DEFINE_CONFIGURABLE(cfgitsclusters, int, 1, "minimum number of ITS clusters requirement") - O2_DEFINE_CONFIGURABLE(cfgtpcclufindable, int, 1, "minimum number of findable TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgtpccrossoverfindable, int, 1, "minimum number of Ratio crossed rows over findable clusters") + + struct : ConfigurableGroup { + std::string prefix = "v0BuilderOpts"; + // topological cut for V0 + O2_DEFINE_CONFIGURABLE(cfgv0_radius, float, 5.0f, "minimum decay radius") + O2_DEFINE_CONFIGURABLE(cfgv0_v0cospa, float, 0.995f, "minimum cosine of pointing angle") + O2_DEFINE_CONFIGURABLE(cfgv0_dcadautopv, float, 0.1f, "minimum daughter DCA to PV") + O2_DEFINE_CONFIGURABLE(cfgv0_dcav0dau, float, 0.5f, "maximum DCA among V0 daughters") + O2_DEFINE_CONFIGURABLE(cfgv0_mk0swindow, float, 0.1f, "Invariant mass window of K0s") + O2_DEFINE_CONFIGURABLE(cfgv0_mlambdawindow, float, 0.04f, "Invariant mass window of lambda") + O2_DEFINE_CONFIGURABLE(cfgv0_ArmPodocut, float, 0.2f, "Armenteros Podolski cut for K0") + } v0BuilderOpts; + + struct : ConfigurableGroup { + std::string prefix = "cascBuilderOpts"; + // topological cut for cascade + O2_DEFINE_CONFIGURABLE(cfgcasc_radius, float, 0.5f, "minimum decay radius") + O2_DEFINE_CONFIGURABLE(cfgcasc_casccospa, float, 0.999f, "minimum cosine of pointing angle") + 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_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") + O2_DEFINE_CONFIGURABLE(cfgcasc_compmassrej, float, 0.008f, "Invariant mass window of lambda") + } cascBuilderOpts; + + struct : ConfigurableGroup { + std::string prefix = "trkQualityOpts"; + // track selections + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for ref tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtDauMin, float, 0.2f, "Minimal pT for daughter tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtDauMax, float, 10.0f, "Maximal pT for daughter tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtK0sMin, float, 0.2f, "Minimal pT for K0s") + O2_DEFINE_CONFIGURABLE(cfgCutPtK0sMax, float, 10.0f, "Maximal pT for K0s") + O2_DEFINE_CONFIGURABLE(cfgCutPtLambdaMin, float, 0.2f, "Minimal pT for Lambda") + O2_DEFINE_CONFIGURABLE(cfgCutPtLambdaMax, float, 10.0f, "Maximal pT for Lambda") + O2_DEFINE_CONFIGURABLE(cfgCutPtXiMin, float, 0.2f, "Minimal pT for Xi") + O2_DEFINE_CONFIGURABLE(cfgCutPtXiMax, float, 10.0f, "Maximal pT for Xi") + O2_DEFINE_CONFIGURABLE(cfgCutPtOmegaMin, float, 0.2f, "Minimal pT for Omega") + O2_DEFINE_CONFIGURABLE(cfgCutPtOmegaMax, float, 10.0f, "Maximal pT for Omega") + O2_DEFINE_CONFIGURABLE(cfgCutPtPIDDauMin, float, 0.15f, "Minimal pT for daughter PID") + // track quality selections for daughter track + O2_DEFINE_CONFIGURABLE(cfgCheckITSNCls, bool, false, "check minimum number of ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgCheckITSHits, bool, false, "check minimum number of ITS hits") + O2_DEFINE_CONFIGURABLE(cfgCheckITSChi2NDF, bool, false, "check ITS Chi2NDF") + O2_DEFINE_CONFIGURABLE(cfgCheckGlobalTrack, bool, false, "check global track") + } trkQualityOpts; + + struct : ConfigurableGroup { + std::string prefix = "evtSelOpts"; + O2_DEFINE_CONFIGURABLE(cfgDoTVXinTRD, bool, true, "check kTVXinTRD") + O2_DEFINE_CONFIGURABLE(cfgDoNoTimeFrameBorder, bool, true, "check kNoTimeFrameBorder") + O2_DEFINE_CONFIGURABLE(cfgDoNoITSROFrameBorder, bool, true, "check kNoITSROFrameBorder") + O2_DEFINE_CONFIGURABLE(cfgDoNoSameBunchPileup, bool, true, "check kNoITSROFrameBorder") + O2_DEFINE_CONFIGURABLE(cfgDoIsGoodZvtxFT0vsPV, bool, true, "check kIsGoodZvtxFT0vsPV") + 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(cfgMultPVCut, int, 5, "Use apassX MultPVCut function or not (-1)") + O2_DEFINE_CONFIGURABLE(cfgDoV0AT0Acut, bool, true, "do V0A-T0A cut") + } evtSeleOpts; + O2_DEFINE_CONFIGURABLE(cfgCasc_rapidity, float, 0.5, "rapidity") - O2_DEFINE_CONFIGURABLE(cfgNSigmatpctof, std::vector, (std::vector{3, 3, 3, 3, 3, 3}), "tpc and tof NSigma for Pion Proton Kaon") + O2_DEFINE_CONFIGURABLE(cfgNSigmapid, std::vector, (std::vector{9, 9, 9, 3, 3, 3, 3, 3, 3}), "tpc, tof and its NSigma for Pion Proton Kaon") 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(cfgLocDenParaXi, std::vector, (std::vector{-0.000986187, -3.86861, -0.000912481, -3.29206, -0.000859271, -2.89389, -0.000817039, -2.61201, -0.000788792, -2.39079, -0.000780182, -2.19276, -0.000750457, -2.07205, -0.000720279, -1.96865, -0.00073247, -1.85642, -0.000695091, -1.82625, -0.000693332, -1.72679, -0.000681225, -1.74305, -0.000652818, -1.92608, -0.000618892, -2.31985}), "Local density efficiency function parameter for Xi, exp(Ax + B)") @@ -110,13 +165,14 @@ struct FlowGfwOmegaXi { O2_DEFINE_CONFIGURABLE(cfgLocDenParaK0s, std::vector, (std::vector{-0.00043057, -3.2435, -0.000385085, -2.97687, -0.000350298, -2.81502, -0.000326159, -2.71091, -0.000299563, -2.65448, -0.000294284, -2.60865, -0.000277938, -2.589, -0.000277091, -2.56983, -0.000272783, -2.56825, -0.000252706, -2.58996, -0.000247834, -2.63158, -0.00024379, -2.76976, -0.000286468, -2.92484, -0.000310149, -3.27746}), "Local density efficiency function parameter for K0s, exp(Ax + B)") O2_DEFINE_CONFIGURABLE(cfgLocDenParaLambda, std::vector, (std::vector{-0.000510948, -4.4846, -0.000460629, -4.14465, -0.000433729, -3.94173, -0.000412751, -3.81839, -0.000411211, -3.72502, -0.000401511, -3.68426, -0.000407461, -3.67005, -0.000379371, -3.71153, -0.000392828, -3.73214, -0.000403996, -3.80717, -0.000403376, -3.90917, -0.000354624, -4.34629, -0.000477606, -4.66307, -0.000541139, -4.61364}), "Local density efficiency function parameter for Lambda, exp(Ax + B)") // switch - O2_DEFINE_CONFIGURABLE(cfgcheckDauTPC, bool, true, "check daughter tracks TPC or not") - O2_DEFINE_CONFIGURABLE(cfgcheckDauTOF, bool, false, "check daughter tracks TOF or not") O2_DEFINE_CONFIGURABLE(cfgDoAccEffCorr, bool, false, "do acc and eff corr") O2_DEFINE_CONFIGURABLE(cfgDoLocDenCorr, bool, false, "do local density corr") O2_DEFINE_CONFIGURABLE(cfgDoJackknife, bool, false, "do jackknife") + O2_DEFINE_CONFIGURABLE(cfgOutputV0, bool, true, "Fill and output V0s flow") + O2_DEFINE_CONFIGURABLE(cfgOutputCasc, bool, true, "Fill and output cascades flow") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgOutputLocDenWeights, bool, false, "Fill and output local density weights") + O2_DEFINE_CONFIGURABLE(cfgOutputQA, bool, false, "do QA") ConfigurableAxis cfgaxisVertex{"cfgaxisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis cfgaxisPhi{"cfgaxisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; @@ -124,7 +180,8 @@ struct FlowGfwOmegaXi { ConfigurableAxis cfgaxisPt{"cfgaxisPt", {VARIABLE_WIDTH, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.20, 2.40, 2.60, 2.80, 3.00, 3.50, 4.00, 4.50, 5.00, 5.50, 6.00, 10.0}, "pt (GeV)"}; ConfigurableAxis cfgaxisPtXi{"cfgaxisPtXi", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; ConfigurableAxis cfgaxisPtOmega{"cfgaxisPtOmega", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; - ConfigurableAxis cfgaxisPtV0{"cfgaxisPtV0", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; + ConfigurableAxis cfgaxisPtK0s{"cfgaxisPtK0s", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; + ConfigurableAxis cfgaxisPtLambda{"cfgaxisPtLambda", {VARIABLE_WIDTH, 0.9, 1.1, 1.3, 1.5, 1.7, 1.9, 2.1, 2.3, 2.5, 2.7, 2.9, 3.9, 4.9, 5.9, 9.9}, "pt (GeV)"}; ConfigurableAxis cfgaxisOmegaMassforflow{"cfgaxisOmegaMassforflow", {16, 1.63f, 1.71f}, "Inv. Mass (GeV)"}; ConfigurableAxis cfgaxisXiMassforflow{"cfgaxisXiMassforflow", {14, 1.3f, 1.37f}, "Inv. Mass (GeV)"}; ConfigurableAxis cfgaxisK0sMassforflow{"cfgaxisK0sMassforflow", {40, 0.4f, 0.6f}, "Inv. Mass (GeV)"}; @@ -135,12 +192,12 @@ 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) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((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); using TracksPID = soa::Join; - using AodTracks = soa::Filtered>; // tracks filter + using AodTracks = soa::Filtered>; // tracks filter using AodCollisions = soa::Filtered>; // collisions filter - using DaughterTracks = soa::Join; + using DaughterTracks = soa::Join; // Connect to ccdb Service ccdb; @@ -158,10 +215,10 @@ struct FlowGfwOmegaXi { // define global variables GFW* fGFW = new GFW(); // GFW class used from main src std::vector corrconfigs; - std::vector cfgAcceptance = cfgAcceptancePath; - std::vector cfgEfficiency = cfgEfficiencyPath; - std::vector cfgNSigma = cfgNSigmatpctof; - std::vector cfgmassbins = cfgMassBins; + std::vector cfgAcceptance; + std::vector cfgEfficiency; + std::vector cfgNSigma; + std::vector cfgmassbins; std::vector mAcceptance; std::vector mEfficiency; @@ -179,8 +236,14 @@ struct FlowGfwOmegaXi { int nXiPtBins = 0; TAxis* fXiPtAxis = nullptr; - int nV0PtBins = 0; - TAxis* fV0PtAxis = nullptr; + int nOmegaPtBins = 0; + TAxis* fOmegaPtAxis = nullptr; + + int nK0sPtBins = 0; + TAxis* fK0sPtAxis = nullptr; + + int nLambdaPtBins = 0; + TAxis* fLambdaPtAxis = nullptr; TAxis* fMultAxis = nullptr; @@ -198,6 +261,11 @@ struct FlowGfwOmegaXi { ccdb->setCaching(true); ccdb->setCreatedNotAfter(cfgnolaterthan.value); + cfgAcceptance = cfgAcceptancePath; + cfgEfficiency = cfgEfficiencyPath; + cfgNSigma = cfgNSigmapid; + cfgmassbins = cfgMassBins; + // Set the pt, mult and phi Axis; o2::framework::AxisSpec axisPt = cfgaxisPt; nPtBins = axisPt.binEdges.size() - 1; @@ -207,9 +275,17 @@ struct FlowGfwOmegaXi { nXiPtBins = axisXiPt.binEdges.size() - 1; fXiPtAxis = new TAxis(nXiPtBins, &(axisXiPt.binEdges)[0]); - o2::framework::AxisSpec axisV0Pt = cfgaxisPtV0; - nV0PtBins = axisV0Pt.binEdges.size() - 1; - fV0PtAxis = new TAxis(nV0PtBins, &(axisV0Pt.binEdges)[0]); + o2::framework::AxisSpec axisOmegaPt = cfgaxisPtOmega; + nOmegaPtBins = axisOmegaPt.binEdges.size() - 1; + fOmegaPtAxis = new TAxis(nOmegaPtBins, &(axisOmegaPt.binEdges)[0]); + + o2::framework::AxisSpec axisK0sPt = cfgaxisPtK0s; + nK0sPtBins = axisK0sPt.binEdges.size() - 1; + fK0sPtAxis = new TAxis(nK0sPtBins, &(axisK0sPt.binEdges)[0]); + + o2::framework::AxisSpec axisLambdaPt = cfgaxisPtLambda; + nLambdaPtBins = axisLambdaPt.binEdges.size() - 1; + fLambdaPtAxis = new TAxis(nLambdaPtBins, &(axisLambdaPt.binEdges)[0]); o2::framework::AxisSpec axisMult = axisMultiplicity; int nMultBins = axisMult.binEdges.size() - 1; @@ -217,7 +293,7 @@ struct FlowGfwOmegaXi { fOmegaMass = new TAxis(cfgmassbins[3], 1.63, 1.71); - fXiMass = new TAxis(cfgmassbins[2], 1.3, 1.37); + fXiMass = new TAxis(cfgmassbins[2], 1.29, 1.36); fK0sMass = new TAxis(cfgmassbins[0], 0.4, 0.6); @@ -238,109 +314,142 @@ struct FlowGfwOmegaXi { registry.add("hEtaPhiVtxzPOIOmega", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, {20, -10, 10}}}); registry.add("hEtaPhiVtxzPOIK0s", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, {20, -10, 10}}}); registry.add("hEtaPhiVtxzPOILambda", "", {HistType::kTH3D, {cfgaxisPhi, cfgaxisEta, {20, -10, 10}}}); - registry.add("hEventCount", "", {HistType::kTH2D, {{4, 0, 4}, {4, 0, 4}}}); - 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, "before topological cut"); - registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "after topological cut"); - registry.get(HIST("hEventCount"))->GetYaxis()->SetBinLabel(1, "K0s"); - registry.get(HIST("hEventCount"))->GetYaxis()->SetBinLabel(2, "Lambda"); - registry.get(HIST("hEventCount"))->GetYaxis()->SetBinLabel(3, "XiMinus"); - registry.get(HIST("hEventCount"))->GetYaxis()->SetBinLabel(4, "Omega"); + + registry.add("hEventCount", "", {HistType::kTH1D, {{12, 0, 12}}}); + 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"); // QA - // 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}}}); - // Cascade QA - registry.add("QAhisto/Casc/hqaCasccosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqaCasccosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqaCascV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqaCascV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascV0toPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); - registry.add("QAhisto/Casc/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); - registry.add("QAhisto/Casc/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + 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}}}); + // Cascade QA + registry.add("QAhisto/Casc/hqaCasccosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqaCasccosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqaCascV0cosPAbefore", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqaCascV0cosPAafter", "", {HistType::kTH1D, {{1000, 0.95, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascV0toPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascV0toPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascBachtoPVbefore", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascBachtoPVafter", "", {HistType::kTH1D, {{1000, -10, 10}}}); + registry.add("QAhisto/Casc/hqadcaCascdaubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascdauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascV0daubefore", "", {HistType::kTH1D, {{100, 0, 1}}}); + registry.add("QAhisto/Casc/hqadcaCascV0dauafter", "", {HistType::kTH1D, {{100, 0, 1}}}); + } // cumulant of flow registry.add("c22", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); + registry.add("c32", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("c24", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); - registry.add("K0sc22", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); - registry.add("Lambdac22", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); + registry.add("c22Full", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("c22dpt", ";Centrality (%) ; C_{2}{2}", {HistType::kTProfile2D, {cfgaxisPt, axisMultiplicity}}); registry.add("c24dpt", ";Centrality (%) ; C_{2}{4}", {HistType::kTProfile2D, {cfgaxisPt, axisMultiplicity}}); + registry.add("c22Fulldpt", ";Centrality (%) ; C_{2}{2}", {HistType::kTProfile2D, {cfgaxisPt, axisMultiplicity}}); // pt-diff cumulant of flow + // v2 registry.add("Xic22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - registry.add("Omegac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - registry.add("K0sc22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - registry.add("Lambdac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + registry.add("Omegac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + registry.add("K0sc22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac22dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); registry.add("Xic24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - registry.add("Omegac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - registry.add("K0sc24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - registry.add("Lambdac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + registry.add("Omegac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + registry.add("K0sc24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac24dpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisLambdaMassforflow, axisMultiplicity}}); + registry.add("Xic22Fulldpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); + registry.add("Omegac22Fulldpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + registry.add("K0sc22Fulldpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac22Fulldpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); + + registry.add("Xic24_gapdpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); + registry.add("Omegac24_gapdpt", ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + // v3 + registry.add("Xic32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); + registry.add("Omegac32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + registry.add("K0sc32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + registry.add("Lambdac32dpt", ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); // for Jackknife if (cfgDoJackknife) { int nsubevent = 10; for (int i = 1; i <= nsubevent; i++) { refc22[i - 1] = registry.add(Form("Jackknife/REF/c22_%d", i), ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); refc24[i - 1] = registry.add(Form("Jackknife/REF/c24_%d", i), ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); + refc22Full[i - 1] = registry.add(Form("Jackknife/REF/c22Full_%d", i), ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); xic22[i - 1] = registry.add(Form("Jackknife/Xi/Xic22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - omegac22[i - 1] = registry.add(Form("Jackknife/Omega/Omegac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - k0sc22[i - 1] = registry.add(Form("Jackknife/K0s/K0sc22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - lambdac22[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + omegac22[i - 1] = registry.add(Form("Jackknife/Omega/Omegac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + k0sc22[i - 1] = registry.add(Form("Jackknife/K0s/K0sc22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + lambdac22[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac22dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); xic24[i - 1] = registry.add(Form("Jackknife/Xi/Xic24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); - omegac24[i - 1] = registry.add(Form("Jackknife/Omega/Omegac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisOmegaMassforflow, axisMultiplicity}}); - k0sc24[i - 1] = registry.add(Form("Jackknife/K0s/K0sc24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisK0sMassforflow, axisMultiplicity}}); - lambdac24[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtV0, cfgaxisLambdaMassforflow, axisMultiplicity}}); + omegac24[i - 1] = registry.add(Form("Jackknife/Omega/Omegac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + k0sc24[i - 1] = registry.add(Form("Jackknife/K0s/K0sc24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + lambdac24[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac24dpt_%d", i), ";pt ; C_{2}{4} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); + refc32[i - 1] = registry.add(Form("Jackknife/REF/c32_%d", i), ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); + xic22Full[i - 1] = registry.add(Form("Jackknife/Xi/Xic22Fulldpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); + omegac22Full[i - 1] = registry.add(Form("Jackknife/Omega/Omegac22Fulldpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + k0sc22Full[i - 1] = registry.add(Form("Jackknife/K0s/K0sc22Fulldpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + lambdac22Full[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac22Fulldpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); + xic32[i - 1] = registry.add(Form("Jackknife/Xi/Xic32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtXi, cfgaxisXiMassforflow, axisMultiplicity}}); + omegac32[i - 1] = registry.add(Form("Jackknife/Omega/Omegac32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtOmega, cfgaxisOmegaMassforflow, axisMultiplicity}}); + k0sc32[i - 1] = registry.add(Form("Jackknife/K0s/K0sc32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtK0s, cfgaxisK0sMassforflow, axisMultiplicity}}); + lambdac32[i - 1] = registry.add(Form("Jackknife/Lambda/Lambdac32dpt_%d", i), ";pt ; C_{2}{2} ", {HistType::kTProfile3D, {cfgaxisPtLambda, cfgaxisLambdaMassforflow, axisMultiplicity}}); } } // MC True flow registry.add("MC/c22MC", ";Centrality (%) ; C_{2}{2} ", {HistType::kTProfile, {axisMultiplicity}}); registry.add("MC/Xic22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtXi, axisMultiplicity}}); - registry.add("MC/Omegac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtXi, axisMultiplicity}}); - registry.add("MC/K0sc22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtV0, axisMultiplicity}}); - registry.add("MC/Lambdac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtV0, axisMultiplicity}}); + registry.add("MC/Omegac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtOmega, axisMultiplicity}}); + registry.add("MC/K0sc22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtK0s, axisMultiplicity}}); + registry.add("MC/Lambdac22dptMC", ";pt ; C_{2}{2} ", {HistType::kTProfile2D, {cfgaxisPtLambda, axisMultiplicity}}); // InvMass(GeV) of casc and v0 AxisSpec axisOmegaMass = {80, 1.63f, 1.71f, "Inv. Mass (GeV)"}; AxisSpec axisXiMass = {70, 1.3f, 1.37f, "Inv. Mass (GeV)"}; AxisSpec axisK0sMass = {400, 0.4f, 0.6f, "Inv. Mass (GeV)"}; AxisSpec axisLambdaMass = {160, 1.08f, 1.16f, "Inv. Mass (GeV)"}; registry.add("InvMassXi_all", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisXiMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassOmega_all", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassOmega", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassOmega_all", "", {HistType::kTHnSparseF, {cfgaxisPtOmega, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); registry.add("InvMassXi", "", {HistType::kTHnSparseF, {cfgaxisPtXi, axisXiMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassK0s_all", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisK0sMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassLambda_all", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassK0s", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisK0sMass, cfgaxisEta, axisMultiplicity}}); - registry.add("InvMassLambda", "", {HistType::kTHnSparseF, {cfgaxisPtV0, axisLambdaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassOmega", "", {HistType::kTHnSparseF, {cfgaxisPtOmega, axisOmegaMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassK0s_all", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, axisK0sMass, cfgaxisEta, axisMultiplicity}}); + registry.add("InvMassLambda_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}}); // for local density correlation - registry.add("MC/densityMCGenK0s", "", {HistType::kTH3D, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity}}); - registry.add("MC/densityMCGenLambda", "", {HistType::kTH3D, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity}}); + registry.add("MC/densityMCGenK0s", "", {HistType::kTH3D, {cfgaxisPtK0s, cfgaxisNch, cfgaxisLocalDensity}}); + registry.add("MC/densityMCGenLambda", "", {HistType::kTH3D, {cfgaxisPtLambda, cfgaxisNch, cfgaxisLocalDensity}}); registry.add("MC/densityMCGenXi", "", {HistType::kTH3D, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity}}); - registry.add("MC/densityMCGenOmega", "", {HistType::kTH3D, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity}}); - registry.add("MC/densityMCRecK0s", "", {HistType::kTHnSparseF, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity, axisK0sMass}}); - registry.add("MC/densityMCRecLambda", "", {HistType::kTHnSparseF, {cfgaxisPtV0, cfgaxisNch, cfgaxisLocalDensity, axisLambdaMass}}); + registry.add("MC/densityMCGenOmega", "", {HistType::kTH3D, {cfgaxisPtOmega, cfgaxisNch, cfgaxisLocalDensity}}); + registry.add("MC/densityMCRecK0s", "", {HistType::kTHnSparseF, {cfgaxisPtK0s, cfgaxisNch, cfgaxisLocalDensity, axisK0sMass}}); + registry.add("MC/densityMCRecLambda", "", {HistType::kTHnSparseF, {cfgaxisPtLambda, cfgaxisNch, cfgaxisLocalDensity, axisLambdaMass}}); registry.add("MC/densityMCRecXi", "", {HistType::kTHnSparseF, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity, axisXiMass}}); - registry.add("MC/densityMCRecOmega", "", {HistType::kTHnSparseF, {cfgaxisPtXi, cfgaxisNch, cfgaxisLocalDensity, axisOmegaMass}}); + registry.add("MC/densityMCRecOmega", "", {HistType::kTHnSparseF, {cfgaxisPtOmega, cfgaxisNch, cfgaxisLocalDensity, axisOmegaMass}}); // Data fGFW->AddRegion("reffull", -0.8, 0.8, 1, 1); // ("name", etamin, etamax, ptbinnum, bitmask)eta region -0.8 to 0.8 fGFW->AddRegion("refN10", -0.8, -0.4, 1, 1); fGFW->AddRegion("refP10", 0.4, 0.8, 1, 1); + fGFW->AddRegion("olxidaudpt", -0.8, 0.8, 1, 2048); + fGFW->AddRegion("olomegadaudpt", -0.8, 0.8, 1, 4096); // POI fGFW->AddRegion("poiN10dpt", -0.8, -0.4, nPtBins, 32); fGFW->AddRegion("poiP10dpt", 0.4, 0.8, nPtBins, 32); @@ -359,18 +468,14 @@ struct FlowGfwOmegaXi { fGFW->AddRegion("poiOmegafulldpt", -0.8, 0.8, nOmegaptMassBins, 4); fGFW->AddRegion("poiOmegaP", 0.4, 0.8, 1, 4); fGFW->AddRegion("poiOmegaN", -0.8, -0.4, 1, 4); - int nK0sptMassBins = nV0PtBins * cfgmassbins[0]; + int nK0sptMassBins = nK0sPtBins * cfgmassbins[0]; fGFW->AddRegion("poiK0sPdpt", 0.4, 0.8, nK0sptMassBins, 8); fGFW->AddRegion("poiK0sNdpt", -0.8, -0.4, nK0sptMassBins, 8); fGFW->AddRegion("poiK0sfulldpt", -0.8, 0.8, nK0sptMassBins, 8); - fGFW->AddRegion("poiK0sP", 0.4, 0.8, 1, 8); - fGFW->AddRegion("poiK0sN", -0.8, 0.4, 1, 8); - int nLambdaptMassBins = nV0PtBins * cfgmassbins[1]; + int nLambdaptMassBins = nLambdaPtBins * cfgmassbins[1]; fGFW->AddRegion("poiLambdaPdpt", 0.4, 0.8, nLambdaptMassBins, 16); fGFW->AddRegion("poiLambdaNdpt", -0.8, -0.4, nLambdaptMassBins, 16); fGFW->AddRegion("poiLambdafulldpt", -0.8, 0.8, nLambdaptMassBins, 16); - fGFW->AddRegion("poiLambdaP", 0.4, 0.8, 1, 16); - fGFW->AddRegion("poiLambdaN", -0.8, -0.4, 1, 16); // MC fGFW->AddRegion("refN10MC", -0.8, -0.4, 1, 64); fGFW->AddRegion("refP10MC", 0.4, 0.8, 1, 64); @@ -384,40 +489,77 @@ struct FlowGfwOmegaXi { fGFW->AddRegion("poiLambdaNdptMC", -0.8, -0.4, nLambdaptMassBins, 1024); // pushback // Data + // v2 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiP10dpt {2} refN10 {-2}", "Poi10Gap22dpta", kTRUE)); // 0 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiN10dpt {2} refP10 {-2}", "Poi10Gap22dptb", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poifulldpt reffull | poioldpt {2 2 -2 -2}", "Poi10Gap24dpt", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poifulldpt reffull | poioldpt {2 -2}", "PoiFull22dpt", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdpt {2} refN10 {-2}", "Xi10Gap22a", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiNdpt {2} refP10 {-2}", "Xi10Gap22b", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXifulldpt reffull {2 2 -2 -2}", "Xi10Gap24", kTRUE)); // 5 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiNdpt {2} refP10 {-2}", "Xi10Gap22b", kTRUE)); // 5 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXifulldpt reffull {2 2 -2 -2}", "Xi10Gap24", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXifulldpt {2} reffull {-2}", "XiFull22", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaPdpt {2} refN10 {-2}", "Omega10Gap22a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdpt {2} refP10 {-2}", "Omega10Gap22b", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegafulldpt reffull {2 2 -2 -2}", "Xi10Gap24", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegafulldpt reffull {2 2 -2 -2}", "Omega10Gap24", kTRUE)); // 10 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegafulldpt {2} reffull {-2}", "OmegaFull22", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sPdpt {2} refN10 {-2}", "K0short10Gap22a", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sNdpt {2} refP10 {-2}", "K0short10Gap22b", kTRUE)); // 10 - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sfulldpt reffull {2 2 -2 -2}", "Xi10Gap24", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sNdpt {2} refP10 {-2}", "K0short10Gap22b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sfulldpt reffull {2 2 -2 -2}", "K0short10Gap24", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sfulldpt {2} reffull {-2}", "K0shortFull22", kTRUE)); // 15 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaPdpt {2} refN10 {-2}", "Lambda10Gap22a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaNdpt {2} refP10 {-2}", "Lambda10Gap22b", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdafulldpt reffull {2 2 -2 -2}", "Xi10Gap24a", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {2} refN10 {-2}", "Ref10Gap22a", kFALSE)); // 15 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdafulldpt reffull {2 2 -2 -2}", "LambdaFull24", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdafulldpt {2} reffull {-2}", "LambdaFull22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {2} refN10 {-2}", "Ref10Gap22a", kFALSE)); // 20 corrconfigs.push_back(fGFW->GetCorrelatorConfig("reffull reffull {2 2 -2 -2}", "Ref10Gap24", kFALSE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("reffull reffull {2 -2}", "RefFull22", kFALSE)); + // v3 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdpt {3} refN10 {-3}", "Xi10Gap32a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiNdpt {3} refP10 {-3}", "Xi10Gap32b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaPdpt {3} refN10 {-3}", "Omega10Gap32a", kTRUE)); // 25 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdpt {3} refP10 {-3}", "Omega10Gap32b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sPdpt {3} refN10 {-3}", "K0short10Gap32a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sNdpt {3} refP10 {-3}", "K0short10Gap32b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaPdpt {3} refN10 {-3}", "Lambda10Gap32a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaNdpt {3} refP10 {-3}", "Lambda10Gap32b", kTRUE)); // 30 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10 {3} refN10 {-3}", "Ref10Gap32a", kFALSE)); // MC - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdptMC {2} refN10MC {-2}", "MCXi10Gap22a", kTRUE)); // 17 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdptMC {2} refN10MC {-2}", "MCXi10Gap22a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiNdptMC {2} refP10MC {-2}", "MCXi10Gap22b", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaPdptMC {2} refN10MC {-2}", "MCOmega10Gap22a", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdptMC {2} refP10MC {-2}", "MCOmega10Gap22b", kTRUE)); // 20 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdptMC {2} refP10MC {-2}", "MCOmega10Gap22b", kTRUE)); // 35 corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sPdptMC {2} refN10MC {-2}", "MCK0s10Gap22a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiK0sNdptMC {2} refP10MC {-2}", "MCK0s10Gap22b", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaPdptMC {2} refN10MC {-2}", "MCLambda10Gap22a", kTRUE)); corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiLambdaNdptMC {2} refP10MC {-2}", "MCLambda10Gap22b", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10MC {2} refN10MC {-2}", "MCRef10Gap22a", kFALSE)); // 25 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("refP10MC {2} refN10MC {-2}", "MCRef10Gap22a", kFALSE)); // 40 + + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiPdpt refN10 {2 2 -2 -2}", "Xi10Gap24a", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXiNdpt refP10 {2 2 -2 -2}", "Xi10Gap24b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXifulldpt {2} olxidaudpt {-2}", "XiFullol22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiXifulldpt olxidaudpt {2 2 -2 -2}", "XiFullol24", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaPdpt refN10 {2 2 -2 -2}", "Omega10Gap24a", kTRUE)); // 45 + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegaNdpt refP10 {2 2 -2 -2}", "Omega10Gap24b", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegafulldpt {2} olomegadaudpt {-2}", "OmegaFullol22", kTRUE)); + corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiOmegafulldpt olomegadaudpt {2 2 -2 -2}", "OmegaFullol24", kTRUE)); fGFW->CreateRegions(); // finalize the initialization // used for event selection - fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x - 3.5*([5]+[6must ]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); - fMultPVCutLow->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); - fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x + 3.5*([5]+[6]*x+[7]*x*x+[8]*x*x*x+[9]*x*x*x*x)", 0, 100); - fMultPVCutHigh->SetParameters(3257.29, -121.848, 1.98492, -0.0172128, 6.47528e-05, 154.756, -1.86072, -0.0274713, 0.000633499, -3.37757e-06); + int caseapass4 = 4; + int caseapass5 = 5; + if (evtSeleOpts.cfgMultPVCut.value == caseapass4) { + 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); + } + if (evtSeleOpts.cfgMultPVCut.value == caseapass5) { + 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(3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05); + 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(3074.43, -106.192, 1.46176, -0.00968364, 2.61923e-05, 182.128, -7.43492, 0.193901, -0.00256715, 1.22594e-05); + } + 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); @@ -493,11 +635,11 @@ struct FlowGfwOmegaXi { if (PDGCode == kXiMinus) { fpt = fXiPtAxis; } else if (PDGCode == kOmegaMinus) { - fpt = fXiPtAxis; + fpt = fOmegaPtAxis; } else if (PDGCode == kK0Short) { - fpt = fV0PtAxis; + fpt = fK0sPtAxis; } else if (PDGCode == kLambda0) { - fpt = fV0PtAxis; + fpt = fLambdaPtAxis; } else { LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); return; @@ -529,18 +671,64 @@ struct FlowGfwOmegaXi { fMass = fXiMass; } else if (PDGCode == kOmegaMinus) { nMassBins = cfgmassbins[3]; + nptbins = nOmegaPtBins; + fpt = fOmegaPtAxis; + fMass = fOmegaMass; + } else if (PDGCode == kK0Short) { + nMassBins = cfgmassbins[0]; + nptbins = nK0sPtBins; + fpt = fK0sPtAxis; + fMass = fK0sMass; + } else if (PDGCode == kLambda0) { + nMassBins = cfgmassbins[1]; + nptbins = nLambdaPtBins; + fpt = fLambdaPtAxis; + fMass = fLambdaMass; + } else { + LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); + return; + } + for (int massbin = 1; massbin <= nMassBins; massbin++) { + float dnx = 0; + float val = 0; + dnx = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kTRUE).real(); + if (dnx == 0) + continue; + val = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real() / dnx; + if (std::fabs(val) < 1) { + registry.fill(tarName, fpt->GetBinCenter(ptbin), fMass->GetBinCenter(massbin), cent, val, dnx); + } + } + return; + } + + // remove auto-corr + template + void fillProfilepTMass(const GFW::CorrConfig& corrconf, const GFW::CorrConfig& corrconfol, const ConstStr& tarName, const int& ptbin, const int& PDGCode, const float& cent) + { + int nMassBins = 0; + int nptbins = 0; + TAxis* fMass = nullptr; + TAxis* fpt = nullptr; + if (PDGCode == kXiMinus) { + nMassBins = cfgmassbins[2]; nptbins = nXiPtBins; fpt = fXiPtAxis; + fMass = fXiMass; + } else if (PDGCode == kOmegaMinus) { + nMassBins = cfgmassbins[3]; + nptbins = nOmegaPtBins; + fpt = fOmegaPtAxis; fMass = fOmegaMass; } else if (PDGCode == kK0Short) { nMassBins = cfgmassbins[0]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nK0sPtBins; + fpt = fK0sPtAxis; fMass = fK0sMass; } else if (PDGCode == kLambda0) { nMassBins = cfgmassbins[1]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nLambdaPtBins; + fpt = fLambdaPtAxis; fMass = fLambdaMass; } else { LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); @@ -549,10 +737,14 @@ struct FlowGfwOmegaXi { for (int massbin = 1; massbin <= nMassBins; massbin++) { float dnx = 0; float val = 0; + float dnxol = 0; dnx = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kTRUE).real(); + dnxol = fGFW->Calculate(corrconfol, (ptbin - 1) + ((massbin - 1) * nptbins), kTRUE).real(); + dnx = dnx - dnxol; if (dnx == 0) continue; - val = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real() / dnx; + val = (fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real() - fGFW->Calculate(corrconfol, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real()) / dnx; + if (std::fabs(val) < 1) { registry.fill(tarName, fpt->GetBinCenter(ptbin), fMass->GetBinCenter(massbin), cent, val, dnx); } @@ -574,18 +766,63 @@ struct FlowGfwOmegaXi { fMass = fXiMass; } else if (PDGCode == kOmegaMinus) { nMassBins = cfgmassbins[3]; + nptbins = nOmegaPtBins; + fpt = fOmegaPtAxis; + fMass = fOmegaMass; + } else if (PDGCode == kK0Short) { + nMassBins = cfgmassbins[0]; + nptbins = nK0sPtBins; + fpt = fK0sPtAxis; + fMass = fK0sMass; + } else if (PDGCode == kLambda0) { + nMassBins = cfgmassbins[1]; + nptbins = nLambdaPtBins; + fpt = fLambdaPtAxis; + fMass = fLambdaMass; + } else { + LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); + return; + } + for (int massbin = 1; massbin <= nMassBins; massbin++) { + float dnx = 0; + float val = 0; + dnx = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kTRUE).real(); + if (dnx == 0) + continue; + val = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real() / dnx; + if (std::fabs(val) < 1) { + TProfile3D->Fill(fpt->GetBinCenter(ptbin), fMass->GetBinCenter(massbin), cent, val, dnx); + } + } + return; + } + + // remove auto-corr + void fillProfilepTMass(const GFW::CorrConfig& corrconf, const GFW::CorrConfig& corrconfol, std::shared_ptr TProfile3D, const int& ptbin, const int& PDGCode, const float& cent) + { + int nMassBins = 0; + int nptbins = 0; + TAxis* fMass = nullptr; + TAxis* fpt = nullptr; + if (PDGCode == kXiMinus) { + nMassBins = cfgmassbins[2]; nptbins = nXiPtBins; fpt = fXiPtAxis; + fMass = fXiMass; + } else if (PDGCode == kOmegaMinus) { + nMassBins = cfgmassbins[3]; + nptbins = nOmegaPtBins; + fpt = fOmegaPtAxis; fMass = fOmegaMass; } else if (PDGCode == kK0Short) { nMassBins = cfgmassbins[0]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nK0sPtBins; + fpt = fK0sPtAxis; fMass = fK0sMass; } else if (PDGCode == kLambda0) { nMassBins = cfgmassbins[1]; - nptbins = nV0PtBins; - fpt = fV0PtAxis; + nptbins = nLambdaPtBins; + fpt = fLambdaPtAxis; fMass = fLambdaMass; } else { LOGF(error, "Error, please put in correct PDGCode of K0s, Lambda, Xi or Omega"); @@ -594,10 +831,13 @@ struct FlowGfwOmegaXi { for (int massbin = 1; massbin <= nMassBins; massbin++) { float dnx = 0; float val = 0; + float dnxol = 0; dnx = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kTRUE).real(); + dnxol = fGFW->Calculate(corrconfol, (ptbin - 1) + ((massbin - 1) * nptbins), kTRUE).real(); + dnx = dnx - dnxol; if (dnx == 0) continue; - val = fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real() / dnx; + val = (fGFW->Calculate(corrconf, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real() - fGFW->Calculate(corrconfol, (ptbin - 1) + ((massbin - 1) * nptbins), kFALSE).real()) / dnx; if (std::fabs(val) < 1) { TProfile3D->Fill(fpt->GetBinCenter(ptbin), fMass->GetBinCenter(massbin), cent, val, dnx); } @@ -670,38 +910,45 @@ struct FlowGfwOmegaXi { template bool eventSelected(TCollision collision, const float centrality) { - if (collision.alias_bit(kTVXinTRD)) { + if (evtSeleOpts.cfgDoTVXinTRD.value && collision.alias_bit(kTVXinTRD)) { // TRD triggered return false; } - if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + registry.fill(HIST("hEventCount"), 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; } - if (!collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + registry.fill(HIST("hEventCount"), 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; } - if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + registry.fill(HIST("hEventCount"), 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; } - if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + registry.fill(HIST("hEventCount"), 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; } - if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + registry.fill(HIST("hEventCount"), 6.5); + if (evtSeleOpts.cfgDoNoCollInTimeRangeStandard.value && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { // no collisions in specified time range return 0; } - if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + registry.fill(HIST("hEventCount"), 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); float vtxz = -999; if (collision.numContrib() > 1) { vtxz = collision.posZ(); @@ -716,36 +963,43 @@ struct FlowGfwOmegaXi { if (std::fabs(vtxz) > cfgCutVertex) return false; - if (multNTracksPV < fMultPVCutLow->Eval(centrality)) - return false; - if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) - return false; - if (occupancy > cfgCutOccupancyHigh) + int caseapass4 = 4; + int caseapass5 = 5; + if (evtSeleOpts.cfgMultPVCut.value == caseapass4 || evtSeleOpts.cfgMultPVCut.value == caseapass5) { + if (multNTracksPV < fMultPVCutLow->Eval(centrality)) + return false; + if (multNTracksPV > fMultPVCutHigh->Eval(centrality)) + return false; + } + registry.fill(HIST("hEventCount"), 9.5); + + if (occupancy > evtSeleOpts.cfgCutOccupancyHigh.value) return 0; + registry.fill(HIST("hEventCount"), 10.5); // V0A T0A 5 sigma cut - int nsigma = 5; - if (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > nsigma * fT0AV0ASigma->Eval(collision.multFT0A())) - return 0; + if (evtSeleOpts.cfgDoV0AT0Acut.value) { + int nsigma = 5; + if (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > nsigma * fT0AV0ASigma->Eval(collision.multFT0A())) + return 0; + } + registry.fill(HIST("hEventCount"), 11.5); return true; } void processData(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, aod::CascDataExt const& Cascades, aod::V0Datas const& V0s, DaughterTracks const&) { + o2::aod::ITSResponse itsResponse; int nTot = tracks.size(); - int candNumAll[4] = {0, 0, 0, 0}; - int candNum[4] = {0, 0, 0, 0}; - int nspecies = 5; - for (int i = 0; i < nspecies - 1; i++) { - registry.fill(HIST("hEventCount"), 0.5, i + 0.5); - } + registry.fill(HIST("hEventCount"), 0.5); if (nTot < 1) return; fGFW->Clear(); const auto cent = collision.centFT0C(); if (!collision.sel8()) return; + registry.fill(HIST("hEventCount"), 1.5); if (eventSelected(collision, cent)) return; TH1D* hLocalDensity = new TH1D("hphi", "hphi", 400, -constants::math::TwoPI, constants::math::TwoPI); @@ -755,9 +1009,6 @@ struct FlowGfwOmegaXi { registry.fill(HIST("hVtxZ"), vtxz); registry.fill(HIST("hMult"), nTot); registry.fill(HIST("hCent"), cent); - for (int i = 0; i < nspecies - 1; i++) { - registry.fill(HIST("hEventCount"), 1.5, i + 0.5); - } float weff = 1; float wacc = 1; @@ -775,10 +1026,10 @@ struct FlowGfwOmegaXi { registry.fill(HIST("hEtaPhiVtxzREF"), track.phi(), track.eta(), vtxz, wacc); registry.fill(HIST("hPt"), track.pt()); int ptbin = fPtAxis->FindBin(track.pt()) - 1; - if ((track.pt() > cfgCutPtMin) && (track.pt() < cfgCutPtMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 1); //(eta, ptbin, phi, wacc*weff, bitmask) } - if ((track.pt() > cfgCutPtPOIMin) && (track.pt() < cfgCutPtPOIMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtPOIMin.value) && (track.pt() < trkQualityOpts.cfgCutPtPOIMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 32); if (cfgDoLocDenCorr) { hLocalDensity->Fill(track.phi(), wacc * weff); @@ -793,272 +1044,375 @@ struct FlowGfwOmegaXi { registry.fill(HIST("hCentvsNch"), cent, nch); } // fill GFW of V0 flow - double lowpt = 0.4; - for (const auto& v0 : V0s) { - auto v0posdau = v0.posTrack_as(); - auto v0negdau = v0.negTrack_as(); - // check tpc - bool isK0s = false; - bool isLambda = false; - // fill QA - registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); - // check daughter TPC and TOF - // K0short - if (v0.qtarm() / std::fabs(v0.alpha()) > cfgv0_ArmPodocut && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < cfgv0_mk0swindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassK0s_all"), v0.pt(), v0.mK0Short(), v0.eta(), cent); - isK0s = true; - candNumAll[0] = candNumAll[0] + 1; - registry.fill(HIST("QAhisto/V0/hqaarm_podoafter"), v0.alpha(), v0.qtarm()); - } - // Lambda and antiLambda - if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(v0posdau.tofNSigmaPr()) < cfgNSigma[4] || v0posdau.pt() < lowpt) && (std::fabs(v0negdau.tofNSigmaPi()) < cfgNSigma[3] || v0negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); - isLambda = true; - candNumAll[1] = candNumAll[1] + 1; - } else if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(v0negdau.tofNSigmaPr()) < cfgNSigma[4] || v0negdau.pt() < lowpt) && (std::fabs(v0posdau.tofNSigmaPi()) < cfgNSigma[3] || v0posdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassLambda_all"), v0.pt(), v0.mLambda(), v0.eta(), cent); - isLambda = true; - candNumAll[1] = candNumAll[1] + 1; - } - // fill QA before cut - 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 && !isLambda) - continue; - // track quality check - if (v0posdau.tpcNClsFound() < cfgtpcclusters) - continue; - if (v0negdau.tpcNClsFound() < cfgtpcclusters) - continue; - if (v0posdau.tpcNClsFindable() < cfgtpcclufindable) - continue; - if (v0negdau.tpcNClsFindable() < cfgtpcclufindable) - continue; - if (v0posdau.tpcCrossedRowsOverFindableCls() < cfgtpccrossoverfindable) - continue; - if (v0posdau.itsNCls() < cfgitsclusters) - continue; - if (v0negdau.itsNCls() < cfgitsclusters) - continue; - // topological cut - if (v0.v0radius() < cfgv0_radius) - continue; - if (v0.v0cosPA() < cfgv0_v0cospa) - continue; - if (v0.dcaV0daughters() > cfgv0_dcav0dau) - continue; - if (std::fabs(v0.dcapostopv()) < cfgv0_dcadautopv) - continue; - if (std::fabs(v0.dcanegtopv()) < cfgv0_dcadautopv) - continue; - // fill QA after cut - 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) { - if (cfgDoAccEffCorr) - setCurrentParticleWeights(weff, wacc, v0, vtxz, 1); - if (cfgDoLocDenCorr) { - int phibin = -999; - phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(v0.phi(), -constants::math::PI)); - double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); - setCurrentLocalDensityWeights(wloc, v0, density, 1); - if (cfgOutputLocDenWeights) - registry.fill(HIST("MC/densityMCRecK0s"), v0.pt(), nch, density, v0.mK0Short()); + double lowpt = trkQualityOpts.cfgCutPtPIDDauMin.value; + + if (cfgOutputV0) { + for (const auto& v0 : V0s) { + auto v0posdau = v0.posTrack_as(); + auto v0negdau = v0.negTrack_as(); + // check tpc + bool isK0s = false; + bool isLambda = false; + + if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (v0negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + + // fill QA + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/V0/hqaarm_podobefore"), v0.alpha(), v0.qtarm()); } - candNum[0] = candNum[0] + 1; - registry.fill(HIST("InvMassK0s"), v0.pt(), v0.mK0Short(), v0.eta(), cent); - registry.fill(HIST("hEtaPhiVtxzPOIK0s"), v0.phi(), v0.eta(), vtxz, wacc); - fGFW->Fill(v0.eta(), fV0PtAxis->FindBin(v0.pt()) - 1 + ((fK0sMass->FindBin(v0.mK0Short()) - 1) * nV0PtBins), v0.phi(), wacc * weff * wloc, 8); - if (cfgOutputNUAWeights) - fWeightsK0s->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); - } - if (isLambda) { - if (cfgDoAccEffCorr) - setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); - if (cfgDoLocDenCorr) { - int phibin = -999; - phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(v0.phi(), -constants::math::PI)); - double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); - setCurrentLocalDensityWeights(wloc, v0, density, 2); - if (cfgOutputLocDenWeights) - registry.fill(HIST("MC/densityMCRecLambda"), v0.pt(), nch, density, v0.mLambda()); + // check daughter TPC and TOF + // K0short + if (v0.pt() > trkQualityOpts.cfgCutPtK0sMin.value && v0.pt() < trkQualityOpts.cfgCutPtK0sMax.value) { + 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(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()); + } + } + } + // Lambda and antiLambda + 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(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; + } + } + // 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 && !isLambda) + continue; + // track quality check + if (!v0posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) + continue; + if (!v0negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) + continue; + if (!v0posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) + continue; + if (!v0negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) + continue; + if (!v0posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (!v0negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!v0posdau.hasTPC() || !v0posdau.hasITS()) + continue; + if (!v0negdau.hasTPC() || !v0negdau.hasITS()) + continue; + } + // // topological cut + if (v0.v0radius() < v0BuilderOpts.cfgv0_radius.value) + continue; + if (v0.v0cosPA() < v0BuilderOpts.cfgv0_v0cospa.value) + continue; + if (v0.dcaV0daughters() > v0BuilderOpts.cfgv0_dcav0dau.value) + continue; + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) + continue; + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) + 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 (isK0s) { + if (cfgDoAccEffCorr) + setCurrentParticleWeights(weff, wacc, v0, vtxz, 1); + if (cfgDoLocDenCorr) { + int phibin = -999; + phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(v0.phi(), -constants::math::PI)); + double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); + setCurrentLocalDensityWeights(wloc, v0, density, 1); + if (cfgOutputLocDenWeights) + registry.fill(HIST("MC/densityMCRecK0s"), v0.pt(), nch, density, v0.mK0Short()); + } + registry.fill(HIST("InvMassK0s"), v0.pt(), v0.mK0Short(), v0.eta(), cent); + registry.fill(HIST("hEtaPhiVtxzPOIK0s"), v0.phi(), v0.eta(), vtxz, wacc); + fGFW->Fill(v0.eta(), fK0sPtAxis->FindBin(v0.pt()) - 1 + ((fK0sMass->FindBin(v0.mK0Short()) - 1) * nK0sPtBins), v0.phi(), wacc * weff * wloc, 8); + if (cfgOutputNUAWeights) + fWeightsK0s->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); + } + if (isLambda) { + if (cfgDoAccEffCorr) + setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); + if (cfgDoLocDenCorr) { + int phibin = -999; + phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(v0.phi(), -constants::math::PI)); + double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); + setCurrentLocalDensityWeights(wloc, v0, density, 2); + if (cfgOutputLocDenWeights) + registry.fill(HIST("MC/densityMCRecLambda"), v0.pt(), nch, density, v0.mLambda()); + } + registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); + registry.fill(HIST("hEtaPhiVtxzPOILambda"), v0.phi(), v0.eta(), vtxz, wacc); + fGFW->Fill(v0.eta(), fK0sPtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nK0sPtBins), v0.phi(), wacc * weff * wloc, 16); + if (cfgOutputNUAWeights) + fWeightsLambda->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); } - candNum[1] = candNum[1] + 1; - registry.fill(HIST("InvMassLambda"), v0.pt(), v0.mLambda(), v0.eta(), cent); - registry.fill(HIST("hEtaPhiVtxzPOILambda"), v0.phi(), v0.eta(), vtxz, wacc); - fGFW->Fill(v0.eta(), fV0PtAxis->FindBin(v0.pt()) - 1 + ((fLambdaMass->FindBin(v0.mLambda()) - 1) * nV0PtBins), v0.phi(), wacc * weff * wloc, 16); - if (cfgOutputNUAWeights) - fWeightsLambda->fill(v0.phi(), v0.eta(), vtxz, v0.pt(), cent, 0); } } + // fill GFW of casc flow - for (const auto& casc : Cascades) { - auto bachelor = casc.bachelor_as(); - auto posdau = casc.posTrack_as(); - auto negdau = casc.negTrack_as(); - // check TPC - if (cfgcheckDauTPC && (!posdau.hasTPC() || !negdau.hasTPC() || !bachelor.hasTPC())) { - continue; - } - bool isOmega = false; - bool isXi = false; - // Omega and antiOmega - if (casc.sign() < 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); - isOmega = true; - candNumAll[3] = candNumAll[3] + 1; - } else if (casc.sign() > 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); - isOmega = true; - candNumAll[3] = candNumAll[3] + 1; - } - // Xi and antiXi - if (casc.sign() < 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); - isXi = true; - candNumAll[2] = candNumAll[2] + 1; - } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) && - (!cfgcheckDauTOF || ((std::fabs(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)))) { - registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); - isXi = true; - candNumAll[2] = candNumAll[2] + 1; - } - // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); - - if (!isXi && !isOmega) - continue; - // topological cut - if (casc.cascradius() < cfgcasc_radius) - continue; - if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_casccospa) - continue; - if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_v0cospa) - continue; - if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cfgcasc_dcav0topv) - continue; - if (std::fabs(casc.dcabachtopv()) < cfgcasc_dcabachtopv) - continue; - if (casc.dcacascdaughters() > cfgcasc_dcacascdau) - continue; - if (casc.dcaV0daughters() > cfgcasc_dcav0dau) - continue; - if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cfgcasc_mlambdawindow) - continue; - // track quality check - if (bachelor.tpcNClsFound() < cfgtpcclusters) - continue; - if (posdau.tpcNClsFound() < cfgtpcclusters) - continue; - if (negdau.tpcNClsFound() < cfgtpcclusters) - continue; - if (bachelor.itsNCls() < cfgitsclusters) - continue; - if (posdau.itsNCls() < cfgitsclusters) - continue; - if (negdau.itsNCls() < cfgitsclusters) - continue; - // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); - - if (isOmega) { - if (cfgDoAccEffCorr) - setCurrentParticleWeights(weff, wacc, casc, vtxz, 4); - if (cfgDoLocDenCorr) { - int phibin = -999; - phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(casc.phi(), -constants::math::PI)); - double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); - setCurrentLocalDensityWeights(wloc, casc, density, 4); - if (cfgOutputLocDenWeights) - registry.fill(HIST("MC/densityMCRecOmega"), casc.pt(), nch, density, casc.mOmega()); + if (cfgOutputCasc) { + for (const auto& casc : Cascades) { + auto bachelor = casc.bachelor_as(); + auto posdau = casc.posTrack_as(); + auto negdau = casc.negTrack_as(); + // check TPC + bool isOmega = false; + bool isXi = false; + + if (bachelor.pt() < trkQualityOpts.cfgCutPtDauMin.value || bachelor.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + + // Omega and antiOmega + 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(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + 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(bachelor.tofNSigmaKa()) < cfgNSigma[5] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[8]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + registry.fill(HIST("InvMassOmega_all"), casc.pt(), casc.mOmega(), casc.eta(), cent); + isOmega = true; + } } - candNum[3] = candNum[3] + 1; - registry.fill(HIST("hEtaPhiVtxzPOIOmega"), casc.phi(), casc.eta(), vtxz, wacc); - registry.fill(HIST("InvMassOmega"), casc.pt(), casc.mOmega(), casc.eta(), cent); - fGFW->Fill(casc.eta(), fXiPtAxis->FindBin(casc.pt()) - 1 + ((fOmegaMass->FindBin(casc.mOmega()) - 1) * nXiPtBins), casc.phi(), wacc * weff * wloc, 4); - if (cfgOutputNUAWeights) - fWeightsOmega->fill(casc.phi(), casc.eta(), vtxz, casc.pt(), cent, 0); - } - if (isXi) { - if (cfgDoAccEffCorr) - setCurrentParticleWeights(weff, wacc, casc, vtxz, 3); - if (cfgDoLocDenCorr) { - int phibin = -999; - phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(casc.phi(), -constants::math::PI)); - double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); - setCurrentLocalDensityWeights(wloc, casc, density, 3); - if (cfgOutputLocDenWeights) - registry.fill(HIST("MC/densityMCRecXi"), casc.pt(), nch, density, casc.mXi()); + // Xi and antiXi + 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(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPr()) < cfgNSigma[4] || posdau.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPi()) < cfgNSigma[3] || negdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + 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(bachelor.tofNSigmaPi()) < cfgNSigma[3] || bachelor.pt() < lowpt) && (std::fabs(negdau.tofNSigmaPr()) < cfgNSigma[4] || negdau.pt() < lowpt) && (std::fabs(posdau.tofNSigmaPi()) < cfgNSigma[3] || posdau.pt() < lowpt)) && + ((std::fabs(itsResponse.nSigmaITS(bachelor)) < cfgNSigma[6]) || bachelor.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(posdau)) < cfgNSigma[7]) || posdau.pt() < lowpt) && ((std::fabs(itsResponse.nSigmaITS(negdau)) < cfgNSigma[6]) || negdau.pt() < lowpt)) { + registry.fill(HIST("InvMassXi_all"), casc.pt(), casc.mXi(), casc.eta(), cent); + isXi = true; + } + } + // fill QA + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + } + + if (!isXi && !isOmega) + continue; + // // topological cut + if (casc.cascradius() < cascBuilderOpts.cfgcasc_radius.value) + continue; + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_casccospa.value) + continue; + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_v0cospa.value) + continue; + if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascBuilderOpts.cfgcasc_dcav0topv.value) + continue; + if (std::fabs(casc.dcabachtopv()) < cascBuilderOpts.cfgcasc_dcabachtopv.value) + continue; + if (casc.dcacascdaughters() > cascBuilderOpts.cfgcasc_dcacascdau.value) + continue; + if (casc.dcaV0daughters() > cascBuilderOpts.cfgcasc_dcav0dau.value) + continue; + if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascBuilderOpts.cfgcasc_mlambdawindow.value) + continue; + // // track quality check + if (!bachelor.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) + continue; + if (!posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) + continue; + if (!negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) + continue; + if (!bachelor.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) + continue; + if (!posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) + continue; + if (!negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) + continue; + if (!bachelor.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (!posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (!negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) + continue; + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!bachelor.hasTPC() || !bachelor.hasITS()) + continue; + if (!posdau.hasTPC() || !posdau.hasITS()) + continue; + if (!negdau.hasTPC() || !negdau.hasITS()) + continue; + } + if (isXi && std::fabs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < cascBuilderOpts.cfgcasc_compmassrej.value) { + isXi = false; + } + if (isOmega && std::fabs(casc.mXi() - o2::constants::physics::MassXiMinus) < cascBuilderOpts.cfgcasc_compmassrej.value) { + isXi = false; + } + // fill QA + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + } + + float weffBac = 1; + float weffPos = 1; + float weffNeg = 1; + float waccBac = 1; + float waccPos = 1; + float waccNeg = 1; + if (isOmega) { + if (cfgDoAccEffCorr) { + setCurrentParticleWeights(weff, wacc, casc, vtxz, 4); + setCurrentParticleWeights(weffBac, waccBac, bachelor, vtxz, 0); + setCurrentParticleWeights(weffPos, waccPos, posdau, vtxz, 0); + setCurrentParticleWeights(weffNeg, waccNeg, negdau, vtxz, 0); + } + if (cfgDoLocDenCorr) { + int phibin = -999; + phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(casc.phi(), -constants::math::PI)); + double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); + setCurrentLocalDensityWeights(wloc, casc, density, 4); + if (cfgOutputLocDenWeights) + registry.fill(HIST("MC/densityMCRecOmega"), casc.pt(), nch, density, casc.mOmega()); + } + registry.fill(HIST("hEtaPhiVtxzPOIOmega"), casc.phi(), casc.eta(), vtxz, wacc); + registry.fill(HIST("InvMassOmega"), casc.pt(), casc.mOmega(), casc.eta(), cent); + fGFW->Fill(casc.eta(), fOmegaPtAxis->FindBin(casc.pt()) - 1 + ((fOmegaMass->FindBin(casc.mOmega()) - 1) * nOmegaPtBins), casc.phi(), wacc * weff * wloc, 4); + fGFW->Fill(bachelor.eta(), 1, bachelor.phi(), waccBac * weffBac * wloc, 4096); + fGFW->Fill(posdau.eta(), 1, posdau.phi(), waccPos * weffPos * wloc, 4096); + fGFW->Fill(negdau.eta(), 1, negdau.phi(), waccNeg * weffNeg * wloc, 4096); + + if (cfgOutputNUAWeights) + fWeightsOmega->fill(casc.phi(), casc.eta(), vtxz, casc.pt(), cent, 0); + } + if (isXi) { + if (cfgDoAccEffCorr) { + setCurrentParticleWeights(weff, wacc, casc, vtxz, 3); + setCurrentParticleWeights(weffBac, waccBac, bachelor, vtxz, 0); + setCurrentParticleWeights(weffPos, waccPos, posdau, vtxz, 0); + setCurrentParticleWeights(weffNeg, waccNeg, negdau, vtxz, 0); + } + if (cfgDoLocDenCorr) { + int phibin = -999; + phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(casc.phi(), -constants::math::PI)); + double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); + setCurrentLocalDensityWeights(wloc, casc, density, 3); + if (cfgOutputLocDenWeights) + registry.fill(HIST("MC/densityMCRecXi"), casc.pt(), nch, density, casc.mXi()); + } + registry.fill(HIST("hEtaPhiVtxzPOIXi"), casc.phi(), casc.eta(), vtxz, wacc); + registry.fill(HIST("InvMassXi"), casc.pt(), casc.mXi(), casc.eta(), cent); + fGFW->Fill(casc.eta(), fXiPtAxis->FindBin(casc.pt()) - 1 + ((fXiMass->FindBin(casc.mXi()) - 1) * nXiPtBins), casc.phi(), wacc * weff * wloc, 2); + fGFW->Fill(bachelor.eta(), 1, bachelor.phi(), waccBac * weffBac * wloc, 2048); + fGFW->Fill(posdau.eta(), 1, posdau.phi(), waccPos * weffPos * wloc, 2048); + fGFW->Fill(negdau.eta(), 1, negdau.phi(), waccNeg * weffNeg * wloc, 2048); + + if (cfgOutputNUAWeights) + fWeightsXi->fill(casc.phi(), casc.eta(), vtxz, casc.pt(), cent, 0); } - candNum[2] = candNum[2] + 1; - registry.fill(HIST("hEtaPhiVtxzPOIXi"), casc.phi(), casc.eta(), vtxz, wacc); - registry.fill(HIST("InvMassXi"), casc.pt(), casc.mXi(), casc.eta(), cent); - fGFW->Fill(casc.eta(), fXiPtAxis->FindBin(casc.pt()) - 1 + ((fXiMass->FindBin(casc.mXi()) - 1) * nXiPtBins), casc.phi(), wacc * weff * wloc, 2); - if (cfgOutputNUAWeights) - fWeightsXi->fill(casc.phi(), casc.eta(), vtxz, casc.pt(), cent, 0); - } - } - for (int i = 0; i < nspecies - 1; i++) { - if (candNumAll[i] > 0) { - registry.fill(HIST("hEventCount"), 2.5, i + 0.5); - } - if (candNum[i] > 0) { - registry.fill(HIST("hEventCount"), 3.5, i + 0.5); } } + delete hLocalDensity; // Filling cumulant with ROOT TProfile and loop for all ptBins - fillProfile(corrconfigs.at(15), HIST("c22"), cent); - fillProfile(corrconfigs.at(16), HIST("c24"), cent); + fillProfile(corrconfigs.at(20), HIST("c22"), cent); + fillProfile(corrconfigs.at(21), HIST("c24"), cent); + fillProfile(corrconfigs.at(22), HIST("c22Full"), cent); + fillProfile(corrconfigs.at(31), HIST("c32"), cent); for (int i = 1; i <= nPtBins; i++) { fillProfilepT(corrconfigs.at(0), HIST("c22dpt"), i, cent); fillProfilepT(corrconfigs.at(1), HIST("c22dpt"), i, cent); fillProfilepT(corrconfigs.at(2), HIST("c24dpt"), i, cent); + fillProfilepT(corrconfigs.at(3), HIST("c22Fulldpt"), i, cent); } - for (int i = 1; i <= nV0PtBins; i++) { - fillProfilepTMass(corrconfigs.at(9), HIST("K0sc22dpt"), i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(10), HIST("K0sc22dpt"), i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(11), HIST("K0sc24dpt"), i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(12), HIST("Lambdac22dpt"), i, kLambda0, cent); - fillProfilepTMass(corrconfigs.at(13), HIST("Lambdac22dpt"), i, kLambda0, cent); - fillProfilepTMass(corrconfigs.at(14), HIST("Lambdac24dpt"), i, kLambda0, cent); + if (cfgOutputV0) { + for (int i = 1; i <= nK0sPtBins; i++) { + fillProfilepTMass(corrconfigs.at(12), HIST("K0sc22dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(13), HIST("K0sc22dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(14), HIST("K0sc24dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(15), HIST("K0sc22Fulldpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(27), HIST("K0sc32dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(28), HIST("K0sc32dpt"), i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { + fillProfilepTMass(corrconfigs.at(16), HIST("Lambdac22dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(17), HIST("Lambdac22dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(18), HIST("Lambdac24dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(19), HIST("Lambdac22Fulldpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(29), HIST("Lambdac32dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(30), HIST("Lambdac32dpt"), i, kLambda0, cent); + } } - for (int i = 1; i <= nXiPtBins; i++) { - fillProfilepTMass(corrconfigs.at(3), HIST("Xic22dpt"), i, kXiMinus, cent); - fillProfilepTMass(corrconfigs.at(4), HIST("Xic22dpt"), i, kXiMinus, cent); - fillProfilepTMass(corrconfigs.at(5), HIST("Xic24dpt"), i, kXiMinus, cent); - fillProfilepTMass(corrconfigs.at(6), HIST("Omegac22dpt"), i, kOmegaMinus, cent); - fillProfilepTMass(corrconfigs.at(7), HIST("Omegac22dpt"), i, kOmegaMinus, cent); - fillProfilepTMass(corrconfigs.at(8), HIST("Omegac24dpt"), i, kOmegaMinus, cent); + if (cfgOutputCasc) { + for (int i = 1; i <= nXiPtBins; i++) { + fillProfilepTMass(corrconfigs.at(4), HIST("Xic22dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(5), HIST("Xic22dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(6), corrconfigs.at(44), HIST("Xic24dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(7), corrconfigs.at(43), HIST("Xic22Fulldpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(23), HIST("Xic32dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(24), HIST("Xic32dpt"), i, kXiMinus, cent); + + fillProfilepTMass(corrconfigs.at(41), HIST("Xic24_gapdpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(42), HIST("Xic24_gapdpt"), i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { + fillProfilepTMass(corrconfigs.at(8), HIST("Omegac22dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(9), HIST("Omegac22dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(10), corrconfigs.at(48), HIST("Omegac24dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(11), corrconfigs.at(47), HIST("Omegac22Fulldpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(25), HIST("Omegac32dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(26), HIST("Omegac32dpt"), i, kOmegaMinus, cent); + + fillProfilepTMass(corrconfigs.at(45), HIST("Omegac24_gapdpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(46), HIST("Omegac24_gapdpt"), i, kOmegaMinus, cent); + } } // Fill subevents flow if (cfgDoJackknife) { @@ -1068,23 +1422,45 @@ struct FlowGfwOmegaXi { for (int j = 1; j <= nsubevent; j++) { if (eventrdm > (j - 1) && eventrdm < j) continue; - fillProfile(corrconfigs.at(15), refc22[j - 1], cent); - fillProfile(corrconfigs.at(16), refc24[j - 1], cent); - for (int i = 1; i <= nV0PtBins; i++) { - fillProfilepTMass(corrconfigs.at(9), k0sc22[j - 1], i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(10), k0sc22[j - 1], i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(11), k0sc24[j - 1], i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(12), lambdac22[j - 1], i, kLambda0, cent); - fillProfilepTMass(corrconfigs.at(13), lambdac22[j - 1], i, kLambda0, cent); - fillProfilepTMass(corrconfigs.at(14), lambdac24[j - 1], i, kLambda0, cent); + fillProfile(corrconfigs.at(20), refc22[j - 1], cent); + fillProfile(corrconfigs.at(21), refc24[j - 1], cent); + fillProfile(corrconfigs.at(22), refc22Full[j - 1], cent); + fillProfile(corrconfigs.at(31), refc32[j - 1], cent); + if (cfgOutputV0) { + for (int i = 1; i <= nK0sPtBins; i++) { + fillProfilepTMass(corrconfigs.at(12), k0sc22[j - 1], i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(13), k0sc22[j - 1], i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(14), k0sc24[j - 1], i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(15), k0sc22Full[j - 1], i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(27), k0sc32[j - 1], i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(28), k0sc32[j - 1], i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { + fillProfilepTMass(corrconfigs.at(16), lambdac22[j - 1], i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(17), lambdac22[j - 1], i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(18), lambdac24[j - 1], i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(19), lambdac22Full[j - 1], i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(29), lambdac32[j - 1], i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(30), lambdac32[j - 1], i, kLambda0, cent); + } } - for (int i = 1; i <= nXiPtBins; i++) { - fillProfilepTMass(corrconfigs.at(3), xic22[j - 1], i, kXiMinus, cent); - fillProfilepTMass(corrconfigs.at(4), xic22[j - 1], i, kXiMinus, cent); - fillProfilepTMass(corrconfigs.at(5), xic24[j - 1], i, kXiMinus, cent); - fillProfilepTMass(corrconfigs.at(6), omegac22[j - 1], i, kOmegaMinus, cent); - fillProfilepTMass(corrconfigs.at(7), omegac22[j - 1], i, kOmegaMinus, cent); - fillProfilepTMass(corrconfigs.at(8), omegac24[j - 1], i, kOmegaMinus, cent); + if (cfgOutputCasc) { + for (int i = 1; i <= nXiPtBins; i++) { + fillProfilepTMass(corrconfigs.at(4), xic22[j - 1], i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(5), xic22[j - 1], i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(6), corrconfigs.at(44), xic24[j - 1], i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(7), corrconfigs.at(43), xic22Full[j - 1], i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(23), xic32[j - 1], i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(24), xic32[j - 1], i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { + fillProfilepTMass(corrconfigs.at(8), omegac22[j - 1], i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(9), omegac22[j - 1], i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(10), corrconfigs.at(48), omegac24[j - 1], i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(11), corrconfigs.at(47), omegac22Full[j - 1], i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(25), omegac32[j - 1], i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(26), omegac32[j - 1], i, kOmegaMinus, cent); + } } } } @@ -1114,10 +1490,7 @@ struct FlowGfwOmegaXi { if (mcParticle.has_tracks()) { auto const& tracks = mcParticle.tracks_as(); for (const auto& track : tracks) { - if (track.pt() < cfgCutPtPOIMin || track.pt() > cfgCutPtPOIMax) { - continue; - } - if (std::fabs(track.eta()) > cfgCutEta) { + if (std::fabs(track.eta()) > trkQualityOpts.cfgCutEta.value) { continue; } if (!(track.isGlobalTrack())) { @@ -1127,10 +1500,10 @@ struct FlowGfwOmegaXi { continue; } int ptbin = fPtAxis->FindBin(mcParticle.pt()) - 1; - if ((mcParticle.pt() > cfgCutPtMin) && (mcParticle.pt() < cfgCutPtMax)) { + if ((mcParticle.pt() > trkQualityOpts.cfgCutPtMin.value) && (mcParticle.pt() < trkQualityOpts.cfgCutPtMax.value)) { fGFW->Fill(mcParticle.eta(), ptbin, mcParticle.phi(), 1, 64); //(eta, ptbin, phi, wacc*weff, bitmask) } - if ((mcParticle.pt() > cfgCutPtPOIMin) && (mcParticle.pt() < cfgCutPtPOIMax)) { + if ((mcParticle.pt() > trkQualityOpts.cfgCutPtPOIMin.value) && (mcParticle.pt() < trkQualityOpts.cfgCutPtPOIMax.value)) { hLocalDensity->Fill(mcParticle.phi(), 1); hLocalDensity->Fill(RecoDecay::constrainAngle(mcParticle.phi(), -constants::math::TwoPI), 1); nch++; @@ -1146,7 +1519,7 @@ struct FlowGfwOmegaXi { int pdgCode = std::abs(straGen.pdgCode()); if (pdgCode != PDG_t::kXiMinus && pdgCode != PDG_t::kOmegaMinus && pdgCode != PDG_t::kK0Short && pdgCode != PDG_t::kLambda0) continue; - if (std::fabs(straGen.eta()) > cfgCutEta) + if (std::fabs(straGen.eta()) > trkQualityOpts.cfgCutEta.value) continue; if (pdgCode == PDG_t::kXiMinus) { @@ -1161,7 +1534,7 @@ struct FlowGfwOmegaXi { double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCGenOmega"), straGen.pt(), nch, density); - fGFW->Fill(straGen.eta(), fXiPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 256); + fGFW->Fill(straGen.eta(), fOmegaPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 256); } if (pdgCode == PDG_t::kK0Short) { @@ -1169,28 +1542,32 @@ struct FlowGfwOmegaXi { double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCGenK0s"), straGen.pt(), nch, density); - fGFW->Fill(straGen.eta(), fXiPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 512); + fGFW->Fill(straGen.eta(), fK0sPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 512); } if (pdgCode == PDG_t::kLambda0) { int phibin = hLocalDensity->FindBin(RecoDecay::constrainAngle(straGen.phi(), -constants::math::PI)); double density = hLocalDensity->Integral(phibin - cfgDeltaPhiLocDen, phibin + cfgDeltaPhiLocDen); if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCGenLambda"), straGen.pt(), nch, density); - fGFW->Fill(straGen.eta(), fXiPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 1024); + fGFW->Fill(straGen.eta(), fLambdaPtAxis->FindBin(straGen.pt()) - 1, straGen.phi(), 1, 1024); } } - fillProfile(corrconfigs.at(25), HIST("MC/c22MC"), cent); - for (int i = 1; i <= nV0PtBins; i++) { - fillProfilepTMC(corrconfigs.at(21), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); - fillProfilepTMC(corrconfigs.at(22), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); - fillProfilepTMC(corrconfigs.at(23), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); - fillProfilepTMC(corrconfigs.at(24), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); + fillProfile(corrconfigs.at(40), HIST("MC/c22MC"), cent); + for (int i = 1; i <= nK0sPtBins; i++) { + fillProfilepTMC(corrconfigs.at(36), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); + fillProfilepTMC(corrconfigs.at(37), HIST("MC/K0sc22dptMC"), i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { + fillProfilepTMC(corrconfigs.at(38), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); + fillProfilepTMC(corrconfigs.at(39), HIST("MC/Lambdac22dptMC"), i, kLambda0, cent); } for (int i = 1; i <= nXiPtBins; i++) { - fillProfilepTMC(corrconfigs.at(17), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); - fillProfilepTMC(corrconfigs.at(18), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); - fillProfilepTMC(corrconfigs.at(19), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); - fillProfilepTMC(corrconfigs.at(20), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); + fillProfilepTMC(corrconfigs.at(32), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); + fillProfilepTMC(corrconfigs.at(33), HIST("MC/Xic22dptMC"), i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { + fillProfilepTMC(corrconfigs.at(34), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); + fillProfilepTMC(corrconfigs.at(35), HIST("MC/Omegac22dptMC"), i, kOmegaMinus, cent); } delete hLocalDensity; @@ -1218,36 +1595,36 @@ struct FlowGfwOmegaXi { double nch = 0; for (const auto& track : tracks) { - if (!track.has_mcParticle()) - continue; - if (track.pt() < cfgCutPtPOIMin || track.pt() > cfgCutPtPOIMax) + if (track.pt() < trkQualityOpts.cfgCutPtPOIMin.value || track.pt() > trkQualityOpts.cfgCutPtPOIMax.value) continue; - if (std::fabs(track.eta()) > cfgCutEta) + if (std::fabs(track.eta()) > trkQualityOpts.cfgCutEta.value) continue; if (!(track.isGlobalTrack())) continue; if (track.tpcChi2NCl() > cfgCutChi2prTPCcls) continue; - auto mcParticle = track.mcParticle_as(); if (cfgDoAccEffCorr) { if (!setCurrentParticleWeights(weff, wacc, track, vtxz, 0)) continue; } + nch += wacc * weff; + if (!track.has_mcParticle()) + continue; + auto mcParticle = track.mcParticle_as(); registry.fill(HIST("hPhi"), track.phi()); registry.fill(HIST("hPhicorr"), track.phi(), wacc); registry.fill(HIST("hEta"), track.eta()); registry.fill(HIST("hEtaPhiVtxzREF"), track.phi(), track.eta(), vtxz, wacc); registry.fill(HIST("hPt"), track.pt()); int ptbin = fPtAxis->FindBin(track.pt()) - 1; - if ((track.pt() > cfgCutPtMin) && (track.pt() < cfgCutPtMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtMin.value) && (track.pt() < trkQualityOpts.cfgCutPtMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 1); //(eta, ptbin, phi, wacc*weff, bitmask) } - if ((track.pt() > cfgCutPtPOIMin) && (track.pt() < cfgCutPtPOIMax)) { + if ((track.pt() > trkQualityOpts.cfgCutPtPOIMin.value) && (track.pt() < trkQualityOpts.cfgCutPtPOIMax.value)) { fGFW->Fill(track.eta(), ptbin, track.phi(), wacc * weff, 32); if (cfgDoLocDenCorr) { hLocalDensity->Fill(mcParticle.phi(), wacc * weff); hLocalDensity->Fill(RecoDecay::constrainAngle(mcParticle.phi(), -constants::math::TwoPI), wacc * weff); - nch += wacc * weff; } } } @@ -1263,50 +1640,74 @@ struct FlowGfwOmegaXi { auto negdau = casc.negTrack_as(); auto posdau = casc.posTrack_as(); auto bachelor = casc.bachelor_as(); + if (bachelor.pt() < trkQualityOpts.cfgCutPtDauMin.value || bachelor.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAbefore"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAbefore"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVbefore"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVbefore"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdaubefore"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0daubefore"), casc.dcaV0daughters()); + } // track quality check - if (bachelor.tpcNClsFound() < cfgtpcclusters) + if (!bachelor.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (posdau.tpcNClsFound() < cfgtpcclusters) + if (!posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (negdau.tpcNClsFound() < cfgtpcclusters) + if (!negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (bachelor.itsNCls() < cfgitsclusters) + if (!bachelor.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (posdau.itsNCls() < cfgitsclusters) + if (!posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (negdau.itsNCls() < cfgitsclusters) + if (!negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - // topological cut - if (casc.cascradius() < cfgcasc_radius) + if (!bachelor.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_casccospa) + if (!posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cfgcasc_v0cospa) + if (!negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cfgcasc_dcav0topv) + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!bachelor.hasTPC() || !bachelor.hasITS()) + continue; + if (!posdau.hasTPC() || !posdau.hasITS()) + continue; + if (!negdau.hasTPC() || !negdau.hasITS()) + continue; + } + // // topological cut + if (casc.cascradius() < cascBuilderOpts.cfgcasc_radius.value) continue; - if (std::fabs(casc.dcabachtopv()) < cfgcasc_dcabachtopv) + if (casc.casccosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_casccospa.value) continue; - if (casc.dcacascdaughters() > cfgcasc_dcacascdau) + if (casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ()) < cascBuilderOpts.cfgcasc_v0cospa.value) continue; - if (casc.dcaV0daughters() > cfgcasc_dcav0dau) + if (std::fabs(casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())) < cascBuilderOpts.cfgcasc_dcav0topv.value) continue; - if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cfgcasc_mlambdawindow) + if (std::fabs(casc.dcabachtopv()) < cascBuilderOpts.cfgcasc_dcabachtopv.value) + continue; + if (casc.dcacascdaughters() > cascBuilderOpts.cfgcasc_dcacascdau.value) + continue; + if (casc.dcaV0daughters() > cascBuilderOpts.cfgcasc_dcav0dau.value) + continue; + if (std::fabs(casc.mLambda() - o2::constants::physics::MassLambda0) > cascBuilderOpts.cfgcasc_mlambdawindow.value) continue; // fill QA - registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); - registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + if (cfgOutputQA) { + registry.fill(HIST("QAhisto/Casc/hqaCasccosPAafter"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqaCascV0cosPAafter"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0toPVafter"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + registry.fill(HIST("QAhisto/Casc/hqadcaCascBachtoPVafter"), casc.dcabachtopv()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascdauafter"), casc.dcacascdaughters()); + registry.fill(HIST("QAhisto/Casc/hqadcaCascV0dauafter"), casc.dcaV0daughters()); + } // Omega and antiOmega int pdgCode{cascMC.pdgCode()}; double cascPt{cascMC.pt()}; @@ -1314,7 +1715,7 @@ struct FlowGfwOmegaXi { double cascEta{cascMC.eta()}; if (std::abs(pdgCode) == kOmegaMinus) { if (casc.sign() < 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 4); if (cfgDoLocDenCorr) { @@ -1325,9 +1726,9 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecOmega"), cascPt, nch, density, casc.mOmega()); } - fGFW->Fill(cascEta, fXiPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); + fGFW->Fill(cascEta, fOmegaPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); } else if (casc.sign() > 0 && std::fabs(casc.yOmega()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaKa()) < cfgNSigma[2] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 4); if (cfgDoLocDenCorr) { @@ -1338,13 +1739,13 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecOmega"), cascPt, nch, density, casc.mOmega()); } - fGFW->Fill(cascEta, fXiPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); + fGFW->Fill(cascEta, fOmegaPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 4); } } // Xi and antiXi if (std::abs(pdgCode) == kXiMinus) { if (casc.sign() < 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(negdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 3); if (cfgDoLocDenCorr) { @@ -1357,7 +1758,7 @@ struct FlowGfwOmegaXi { } fGFW->Fill(cascEta, fXiPtAxis->FindBin(cascPt) - 1, cascPhi, wacc * weff * wloc, 2); } else if (casc.sign() > 0 && std::fabs(casc.yXi()) < cfgCasc_rapidity && - (!cfgcheckDauTPC || (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + (std::fabs(bachelor.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(posdau.tpcNSigmaPi()) < cfgNSigma[0])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, casc, vtxz, 3); if (cfgDoLocDenCorr) { @@ -1380,45 +1781,58 @@ struct FlowGfwOmegaXi { auto v0negdau = v0.negTrack_as(); auto v0posdau = v0.posTrack_as(); - // fill QA before cut - 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()); - // track quality check - if (v0posdau.tpcNClsFound() < cfgtpcclusters) + if (v0posdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0posdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) + continue; + if (v0negdau.pt() < trkQualityOpts.cfgCutPtDauMin.value || v0negdau.pt() > trkQualityOpts.cfgCutPtDauMax.value) continue; - if (v0negdau.tpcNClsFound() < cfgtpcclusters) + + // 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()); + } + // // track quality check + if (!v0posdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (v0posdau.tpcNClsFindable() < cfgtpcclufindable) + if (!v0negdau.passedITSNCls() && trkQualityOpts.cfgCheckITSNCls.value) continue; - if (v0negdau.tpcNClsFindable() < cfgtpcclufindable) + if (!v0posdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (v0posdau.tpcCrossedRowsOverFindableCls() < cfgtpccrossoverfindable) + if (!v0negdau.passedITSHits() && trkQualityOpts.cfgCheckITSHits.value) continue; - if (v0posdau.itsNCls() < cfgitsclusters) + if (!v0posdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; - if (v0negdau.itsNCls() < cfgitsclusters) + if (!v0negdau.passedITSChi2NDF() && trkQualityOpts.cfgCheckITSChi2NDF.value) continue; + if (trkQualityOpts.cfgCheckGlobalTrack.value) { + if (!v0posdau.hasTPC() || !v0posdau.hasITS()) + continue; + if (!v0negdau.hasTPC() || !v0negdau.hasITS()) + continue; + } // topological cut - if (v0.v0radius() < cfgv0_radius) + if (v0.v0radius() < v0BuilderOpts.cfgv0_radius.value) continue; - if (v0.v0cosPA() < cfgv0_v0cospa) + if (v0.v0cosPA() < v0BuilderOpts.cfgv0_v0cospa.value) continue; - if (v0.dcaV0daughters() > cfgv0_dcav0dau) + if (v0.dcaV0daughters() > v0BuilderOpts.cfgv0_dcav0dau.value) continue; - if (std::fabs(v0.dcapostopv()) < cfgv0_dcadautopv) + if (std::fabs(v0.dcapostopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) continue; - if (std::fabs(v0.dcanegtopv()) < cfgv0_dcadautopv) + if (std::fabs(v0.dcanegtopv()) < v0BuilderOpts.cfgv0_dcadautopv.value) continue; // fill QA after cut - 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 (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()); + } int pdgCode{v0MC.pdgCode()}; double v0Pt{v0MC.pt()}; @@ -1426,8 +1840,9 @@ struct FlowGfwOmegaXi { double v0Eta{v0MC.eta()}; // K0short if (std::abs(pdgCode) == kK0Short) { - if (v0.qtarm() / std::fabs(v0.alpha()) > cfgv0_ArmPodocut && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < cfgv0_mk0swindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + 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])) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 1); if (cfgDoLocDenCorr) { @@ -1438,12 +1853,12 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecK0s"), v0Pt, nch, density, v0.mK0Short()); } - fGFW->Fill(v0Eta, fV0PtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 8); + fGFW->Fill(v0Eta, fK0sPtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 8); } } // Lambda and antiLambda - if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0posdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0negdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + 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])) { if (std::abs(pdgCode) == kLambda0) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); @@ -1455,10 +1870,10 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecLambda"), v0Pt, nch, density, v0.mLambda()); } - fGFW->Fill(v0Eta, fV0PtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); + fGFW->Fill(v0Eta, fLambdaPtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); } - } else if (std::fabs(v0.mLambda() - o2::constants::physics::MassLambda) < cfgv0_mlambdawindow && - (!cfgcheckDauTPC || (std::fabs(v0negdau.tpcNSigmaPr()) < cfgNSigma[1] && std::fabs(v0posdau.tpcNSigmaPi()) < cfgNSigma[0]))) { + } 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])) { if (std::abs(pdgCode) == kLambda0) { if (cfgDoAccEffCorr) setCurrentParticleWeights(weff, wacc, v0, vtxz, 2); @@ -1470,23 +1885,36 @@ struct FlowGfwOmegaXi { if (cfgOutputLocDenWeights) registry.fill(HIST("MC/densityMCRecLambda"), v0Pt, nch, density, v0.mLambda()); } - fGFW->Fill(v0Eta, fV0PtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); + fGFW->Fill(v0Eta, fLambdaPtAxis->FindBin(v0Pt) - 1, v0Phi, wacc * weff * wloc, 16); } } } delete hLocalDensity; - fillProfile(corrconfigs.at(15), HIST("c22"), cent); - for (int i = 1; i <= nV0PtBins; i++) { - fillProfilepTMass(corrconfigs.at(9), HIST("K0sc22dpt"), i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(10), HIST("K0sc22dpt"), i, kK0Short, cent); - fillProfilepTMass(corrconfigs.at(12), HIST("Lambdac22dpt"), i, kLambda0, cent); - fillProfilepTMass(corrconfigs.at(13), HIST("Lambdac22dpt"), i, kLambda0, cent); + fillProfile(corrconfigs.at(20), HIST("c22"), cent); + fillProfile(corrconfigs.at(31), HIST("c32"), cent); + for (int i = 1; i <= nK0sPtBins; i++) { + fillProfilepTMass(corrconfigs.at(12), HIST("K0sc22dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(13), HIST("K0sc22dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(27), HIST("K0sc32dpt"), i, kK0Short, cent); + fillProfilepTMass(corrconfigs.at(28), HIST("K0sc32dpt"), i, kK0Short, cent); + } + for (int i = 1; i <= nLambdaPtBins; i++) { + fillProfilepTMass(corrconfigs.at(16), HIST("Lambdac22dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(17), HIST("Lambdac22dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(29), HIST("Lambdac32dpt"), i, kLambda0, cent); + fillProfilepTMass(corrconfigs.at(30), HIST("Lambdac32dpt"), i, kLambda0, cent); } for (int i = 1; i <= nXiPtBins; i++) { - fillProfilepTMass(corrconfigs.at(3), HIST("Xic22dpt"), i, kXiMinus, cent); fillProfilepTMass(corrconfigs.at(4), HIST("Xic22dpt"), i, kXiMinus, cent); - fillProfilepTMass(corrconfigs.at(6), HIST("Omegac22dpt"), i, kOmegaMinus, cent); - fillProfilepTMass(corrconfigs.at(7), HIST("Omegac22dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(5), HIST("Xic22dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(23), HIST("Xic32dpt"), i, kXiMinus, cent); + fillProfilepTMass(corrconfigs.at(24), HIST("Xic32dpt"), i, kXiMinus, cent); + } + for (int i = 1; i <= nOmegaPtBins; i++) { + fillProfilepTMass(corrconfigs.at(8), HIST("Omegac22dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(9), HIST("Omegac22dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(25), HIST("Omegac32dpt"), i, kOmegaMinus, cent); + fillProfilepTMass(corrconfigs.at(26), HIST("Omegac32dpt"), i, kOmegaMinus, cent); } } PROCESS_SWITCH(FlowGfwOmegaXi, processMCRec, "", true); diff --git a/PWGCF/Flow/Tasks/flowMc.cxx b/PWGCF/Flow/Tasks/flowMc.cxx index b310096ef40..5884fa0e127 100644 --- a/PWGCF/Flow/Tasks/flowMc.cxx +++ b/PWGCF/Flow/Tasks/flowMc.cxx @@ -54,13 +54,26 @@ struct FlowMc { Configurable minB{"minB", 0.0f, "min impact parameter"}; Configurable maxB{"maxB", 20.0f, "max impact parameter"}; + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") + O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 1000.0f, "Maximal pT for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, false, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgCutPtRefMin, float, 0.2f, "Minimal pT for ref tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtRefMax, float, 3.0f, "Maximal pT for ref tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 6.0f, "minimum ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 50.0f, "minimum TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") + O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgCutTPCcrossedrows, float, 70.0f, "minimum TPC crossed rows") + O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 0.2f, "DCAxy cut for tracks") + O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); + O2_DEFINE_CONFIGURABLE(cfgDCAxyFunction, std::string, "(0.0015+0.005/(x^1.1))", "Functional form of pt-dependent DCAxy cut"); + O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz cut for tracks") + O2_DEFINE_CONFIGURABLE(cfgCutDCAzPtDepEnabled, bool, false, "switch of DCAz pt dependent cut") + O2_DEFINE_CONFIGURABLE(cfgEnableITSCuts, bool, true, "switch of enabling ITS based track selection cuts") + O2_DEFINE_CONFIGURABLE(cfgTrkSelRun3ITSMatch, bool, false, "GlobalTrackRun3ITSMatching::Run3ITSall7Layers selection") O2_DEFINE_CONFIGURABLE(cfgFlowAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgFlowEfficiency, std::string, "", "CCDB path to efficiency object") O2_DEFINE_CONFIGURABLE(cfgCentVsIPTruth, std::string, "", "CCDB path to centrality vs IP truth") @@ -70,6 +83,10 @@ struct FlowMc { O2_DEFINE_CONFIGURABLE(cfgFlowCumulantNbootstrap, int, 30, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, false, "Use track density efficiency correction") O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrSlopeFactor, float, 1.0f, "A factor to scale the track density efficiency slope") + O2_DEFINE_CONFIGURABLE(cfgRecoEvRejectMC, bool, false, "reject both MC and Reco events when reco do not pass") + O2_DEFINE_CONFIGURABLE(cfgRecoEvSel8, bool, false, "require sel8 for reconstruction events") + O2_DEFINE_CONFIGURABLE(cfgRecoEvkIsGoodITSLayersAll, bool, false, "require kIsGoodITSLayersAll for reconstruction events") + O2_DEFINE_CONFIGURABLE(cfgRecoEvkNoSameBunchPileup, bool, false, "require kNoSameBunchPileup for reconstruction events") Configurable> cfgTrackDensityP0{"cfgTrackDensityP0", std::vector{0.6003720411, 0.6152630970, 0.6288860646, 0.6360694031, 0.6409494798, 0.6450540203, 0.6482117301, 0.6512592056, 0.6640008690, 0.6862631416, 0.7005738691, 0.7106567432, 0.7170728333}, "parameter 0 for track density efficiency correction"}; Configurable> cfgTrackDensityP1{"cfgTrackDensityP1", std::vector{-1.007592e-05, -8.932635e-06, -9.114538e-06, -1.054818e-05, -1.220212e-05, -1.312304e-05, -1.376433e-05, -1.412813e-05, -1.289562e-05, -1.050065e-05, -8.635725e-06, -7.380821e-06, -6.201250e-06}, "parameter 1 for track density efficiency correction"}; float maxEta = 0.8; @@ -81,6 +98,22 @@ struct FlowMc { 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}, "pt axis"}; + // Filter for MCcollisions + Filter mccollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; + using FilteredMcCollisions = 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 reco tracks + Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); + using FilteredTracks = soa::Filtered>; + + // using FilteredTracks = soa::Join; + + // Additional filters for tracks + TrackSelection myTrackSel; + TF1* fPtDepDCAxy = nullptr; + // Cent vs IP TH1D* mCentVsIPTruth = nullptr; bool centVsIPTruthLoaded = false; @@ -98,7 +131,6 @@ struct FlowMc { // 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://alice-ccdb.cern.ch", "url of the ccdb repository"}; OutputObj fWeights{GFWWeights("weights")}; @@ -110,10 +142,22 @@ struct FlowMc { std::vector corrconfigsTruth; std::vector corrconfigsReco; TRandom3* fRndm = new TRandom3(0); + double epsilon = 1e-6; void init(InitContext&) { + ccdb->setURL(ccdbUrl.value); + ccdb->setCaching(true); + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); + + const AxisSpec axisVertex{20, -10, 10, "Vtxz (cm)"}; + const AxisSpec axisEta{20, -1., 1., "#eta"}; + const AxisSpec axisCounter{1, 0, +1, ""}; // QA histograms + histos.add("mcEventCounter", "Monte Carlo Truth EventCounter", HistType::kTH1F, {axisCounter}); + histos.add("numberOfRecoCollisions", "numberOfRecoCollisions", HistType::kTH1F, {{10, -0.5f, 9.5f}}); + histos.add("RecoEventCounter", "Reconstruction EventCounter", HistType::kTH1F, {axisCounter}); histos.add("hnTPCClu", "Number of found TPC clusters", HistType::kTH1D, {{100, 40, 180}}); histos.add("hnITSClu", "Number of found ITS clusters", HistType::kTH1D, {{100, 0, 20}}); // pT histograms @@ -156,7 +200,9 @@ struct FlowMc { histos.add("hPtNchGeneratedLambda", "Reco production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); histos.add("hPtNchGlobalLambda", "Global production; pT (GeV/c); multiplicity", HistType::kTH2D, {axisPt, axisNch}); histos.add("hPtMCGen", "Monte Carlo Truth; pT (GeV/c);", {HistType::kTH1D, {axisPt}}); + histos.add("hEtaPtVtxzMCGen", "Monte Carlo Truth; #eta; p_{T} (GeV/c); V_{z} (cm);", {HistType::kTH3D, {axisEta, axisPt, axisVertex}}); histos.add("hPtMCGlobal", "Monte Carlo Global; pT (GeV/c);", {HistType::kTH1D, {axisPt}}); + histos.add("hEtaPtVtxzMCGlobal", "Monte Carlo Global; #eta; p_{T} (GeV/c); V_{z} (cm);", {HistType::kTH3D, {axisEta, axisPt, axisVertex}}); histos.add("hPhiWeightedTrDen", "corrected #phi distribution, considering track density", {HistType::kTH1D, {axisPhi}}); o2::framework::AxisSpec axis = axisPt; @@ -212,6 +258,28 @@ struct FlowMc { fGFWReco->CreateRegions(); } + if (cfgEnableITSCuts) { + if (cfgTrkSelRun3ITSMatch) { + myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + } else { + myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + } + } + if (cfgCutDCAxy != 0.0) { + myTrackSel.SetMaxDcaXY(cfgCutDCAxy); + } else { + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgDCAxyFunction->c_str()), 0.001, 100); + fPtDepDCAxy->SetParameter(0, cfgDCAxyNSigma); + LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgDCAxyFunction->c_str())); + myTrackSel.SetMaxDcaXYPtDep([fPtDepDCAxy = this->fPtDepDCAxy](float pt) { return fPtDepDCAxy->Eval(pt); }); + } + myTrackSel.SetMinNClustersTPC(cfgCutTPCclu); + myTrackSel.SetMinNCrossedRowsTPC(cfgCutTPCcrossedrows); + if (cfgEnableITSCuts) + myTrackSel.SetMinNClustersITS(cfgCutITSclu); + if (!cfgCutDCAzPtDepEnabled) + myTrackSel.SetMaxDcaZ(cfgCutDCAz); + if (cfgTrackDensityCorrUse) { 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]); @@ -318,9 +386,38 @@ struct FlowMc { } } - using RecoTracks = soa::Join; + template + bool eventSelected(TCollision collision) + { + if (std::fabs(collision.posZ()) > cfgCutVertex) { + return 0; + } + if (cfgRecoEvSel8 && !collision.sel8()) { + return 0; + } + if (cfgRecoEvkNoSameBunchPileup && !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 (cfgRecoEvkIsGoodITSLayersAll && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + // from Jan 9 2025 AOT meeting + // cut time intervals with dead ITS staves + return 0; + } + return 1; + } + + template + bool trackSelected(TTrack track) + { + if (cfgCutDCAzPtDepEnabled && (track.dcaZ() > (0.004f + 0.013f / track.pt()))) { + return false; + } + return myTrackSel.IsSelected(track); + } - void process(aod::McCollision const& mcCollision, aod::BCsWithTimestamps const&, soa::Join const& mcParticles, RecoTracks const&) + void process(FilteredMcCollisions::iterator const& mcCollision, aod::BCsWithTimestamps const&, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracks const&) { float imp = mcCollision.impactParameter(); @@ -337,6 +434,21 @@ struct FlowMc { auto bc = mcCollision.bc_as(); loadCorrections(bc.timestamp()); + if (collisions.size() > -1) { + histos.fill(HIST("mcEventCounter"), 0.5); + histos.fill(HIST("numberOfRecoCollisions"), collisions.size()); // number of times coll was reco-ed + if (cfgRecoEvRejectMC) { + if (collisions.size() != 1) { // only pass those have one reconstruction event + return; + } + for (auto const& collision : collisions) { + if (!eventSelected(collision)) + return; + } + } + histos.fill(HIST("RecoEventCounter"), 0.5); + } + if (imp > minB && imp < maxB) { // event within range histos.fill(HIST("hImpactParameter"), imp); @@ -363,9 +475,9 @@ struct FlowMc { if (std::fabs(mcParticle.eta()) > maxEta) // main acceptance continue; if (mcParticle.has_tracks()) { - auto const& tracks = mcParticle.tracks_as(); + auto const& tracks = mcParticle.tracks_as(); for (auto const& track : tracks) { - if (!((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu))) { + if (!trackSelected(track)) { continue; } if (cfgIsGlobalTrack && track.isGlobalTrack()) { @@ -418,6 +530,7 @@ struct FlowMc { histos.fill(HIST("hBVsPtVsPhiGenerated"), imp, deltaPhi, mcParticle.pt()); histos.fill(HIST("hPtNchGenerated"), mcParticle.pt(), nChGlobal); histos.fill(HIST("hPtMCGen"), mcParticle.pt()); + histos.fill(HIST("hEtaPtVtxzMCGen"), mcParticle.eta(), mcParticle.pt(), vtxz); if (pdgCode == PDG_t::kPiPlus) histos.fill(HIST("hPtNchGeneratedPion"), mcParticle.pt(), nChGlobal); if (pdgCode == PDG_t::kKPlus) @@ -437,9 +550,9 @@ struct FlowMc { bool validITSTrack = false; bool validITSABTrack = false; if (mcParticle.has_tracks()) { - auto const& tracks = mcParticle.tracks_as(); + auto const& tracks = mcParticle.tracks_as(); for (auto const& track : tracks) { - if (!((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu))) { + if (!trackSelected(track)) { continue; } histos.fill(HIST("hnTPCClu"), track.tpcNClsFound()); @@ -456,10 +569,10 @@ struct FlowMc { if (track.hasTPC()) { validTPCTrack = true; } - if (track.hasITS() && track.itsChi2NCl() > -1e-6) { + if (track.hasITS() && track.itsChi2NCl() > -1. * epsilon) { validITSTrack = true; } - if (track.hasITS() && track.itsChi2NCl() < -1e-6) { + if (track.hasITS() && track.itsChi2NCl() < -1. * epsilon) { validITSABTrack = true; } } @@ -519,6 +632,7 @@ struct FlowMc { histos.fill(HIST("hBVsPtVsPhiGlobal"), imp, deltaPhi, mcParticle.pt(), wacc * weff); histos.fill(HIST("hPtNchGlobal"), mcParticle.pt(), nChGlobal); histos.fill(HIST("hPtMCGlobal"), mcParticle.pt()); + histos.fill(HIST("hEtaPtVtxzMCGlobal"), mcParticle.eta(), mcParticle.pt(), vtxz); if (pdgCode == PDG_t::kPiPlus) histos.fill(HIST("hPtNchGlobalPion"), mcParticle.pt(), nChGlobal); if (pdgCode == PDG_t::kKPlus) diff --git a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx index dfcf5fb42fc..c022cad77c2 100644 --- a/PWGCF/Flow/Tasks/flowPbpbPikp.cxx +++ b/PWGCF/Flow/Tasks/flowPbpbPikp.cxx @@ -13,47 +13,46 @@ /// \brief PID flow using the generic framework /// \author Preet Bhanjan Pati -#include -#include -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/StepTHn.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Multiplicity.h" -#include "CommonConstants/PhysicsConstants.h" - -#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" +#include "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" +#include "PWGCF/GenericFramework/Core/GFWConfig.h" #include "PWGCF/GenericFramework/Core/GFWCumulant.h" -#include "PWGCF/GenericFramework/Core/FlowContainer.h" +#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "PWGCF/GenericFramework/Core/GFWWeightsList.h" -#include "PWGCF/GenericFramework/Core/GFWConfig.h" -#include "ReconstructionDataFormats/Track.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/PIDResponseITS.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 "Math/Vector4D.h" +#include #include #include -#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -71,6 +70,7 @@ GFWCorrConfigs configs; using namespace o2::analysis::genericframework; struct FlowPbpbPikp { + o2::aod::ITSResponse itsResponse; Service ccdb; Configurable noLaterThan{"noLaterThan", 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"}; @@ -82,13 +82,14 @@ struct FlowPbpbPikp { 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(cfgTpcCluster, int, 70, "Number of TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgTpcCrossRows, int, 70, "Number of TPC clusters") O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, true, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgOutputRunByRun, bool, true, "Fill and output NUA weights 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(cfgTpcNsigmaCut, float, 2.0f, "TPC N-sigma cut for pions, kaons, protons") + O2_DEFINE_CONFIGURABLE(cfgTpcCut, float, 2.0f, "TPC N-sigma cut for pions, kaons, protons") O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 2.0f, "DCAxy range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz range for tracks") @@ -97,19 +98,22 @@ struct FlowPbpbPikp { O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMax, int, 2000, "Maximum occupancy cut") O2_DEFINE_CONFIGURABLE(cfgUseGlobalTrack, bool, true, "use Global track") O2_DEFINE_CONFIGURABLE(cfgITScluster, int, 5, "Number of ITS cluster") - O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, true, "Use track density efficiency correction") + O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, false, "Use track density efficiency correction") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiEtaVtxz, bool, false, "Use Phi, Eta, VertexZ dependent NUA weights") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiPtCent, bool, false, "Use Phi, Pt, Centrality dependent NUA weights") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiEtaPt, bool, true, "Use Phi, Eta, Pt dependent NUA weights") O2_DEFINE_CONFIGURABLE(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") + O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts") + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") 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> cfgTofNsigmaCut{"cfgTofNsigmaCut", std::vector{1.5, 1.5, 1.5}, "TOF n-sigma cut for pions, kaons, protons"}; - Configurable> cfgItsNsigmaCut{"cfgItsNsigmaCut", std::vector{3, 2.5, 2}, "ITS n-sigma cut for pions, kaons, protons"}; - Configurable> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0}, "Switch for various event cuts [kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; + Configurable> cfgTofNsigmaCut{"cfgTofNsigmaCut", std::vector{1.5, 1.5, 1.5, -1.5, -1.5, -1.5}, "TOF n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; + Configurable> cfgItsNsigmaCut{"cfgItsNsigmaCut", std::vector{3, 3, 3, -3, -3, -3}, "ITS n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; + Configurable> cfgTpcNsigmaCut{"cfgTpcNsigmaCut", std::vector{10, 10, 10, -10, -10, -10}, "TOF n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; + Configurable> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, "Switch for various event cuts [Filtered Events, Sel8, kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; Configurable cfgRegions{"cfgRegions", {{"refN08", "refP08", "full", "poiN", "olN", "poiP", "olP", "poi", "ol", "poiNpi", "olNpi", "poiPpi", "olPpi", "poifullpi", "olfullpi", "poiNka", "olNka", "poiPka", "olPka", "poifullka", "olfullka", "poiNpr", "olNpr", "poiPpr", "olPpr", "poifullpr", "olfullpr"}, {-0.8, 0.4, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8, -0.8, -0.8, 0.4, 0.4, -0.8, -0.8}, {-0.4, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8, -0.4, -0.4, 0.8, 0.8, 0.8, 0.8}, {0, 0, 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, 128, 256, 128, 256, 128, 256, 2, 16, 2, 16, 2, 16, 4, 32, 4, 32, 4, 32, 8, 64, 8, 64, 8, 64}}, "Configurations for GFW regions"}; Configurable cfgCorrConfig{"cfgCorrConfig", {{"full {2 -2}", "full {2 -2}", "full {2 -2}", "full {2 -2}", "refN08 {2} refP08 {-2}", "refN08 {2} refP08 {-2}", "refN08 {2} refP08 {-2}", "refN08 {2} refP08 {-2}", "refP08 {-2} refN08 {2}", "refP08 {-2} refN08 {2}", "refP08 {-2} refN08 {2}", "refP08 {-2} refN08 {2}", "full {2 2 -2 -2}", "full {2 2 -2 -2}", "full {2 2 -2 -2}", "full {2 2 -2 -2}", "poi full | ol {2 -2}", "poifullpi full | olfullpi {2 -2}", "poifullka full | olfullka {2 -2}", "poifullpr full | olfullpr {2 -2}", "poiN refN08 | olN {2} refP08 {-2}", "poiNpi refN08 | olNpi {2} refP08 {-2}", "poiNka refN08 | olNka {2} refP08 {-2}", "poiNpr refN08 | olNpr {2} refP08 {-2}", "poiP refP08 | olP {2} refN08 {-2}", "poiPpi refP08 | olPpi {2} refN08 {-2}", "poiPka refP08 | olPka {2} refN08 {-2}", "poiPpr refP08 | olPpr {2} refN08 {-2}", "poi full | ol {2 2 -2 -2}", "poifullpi full | olfullpi {2 2 -2 -2}", "poifullka full | olfullka {2 2 -2 -2}", "poifullpr full | olfullpr {2 2 -2 -2}", "refN08 {2 2} refP08 {-2 -2}", "refP08 {-2 -2} refN08 {2 2}", "poiNka refN08 | olNka {2 2} refP08 {-2 -2}", "poiPka refP08 | olPka {2 2} refN08 {-2 -2}"}, {"ChFull22", "PiFull22", "KaFull22", "PrFull22", "Ch08FGap22", "Pi08FGap22", "Ka08FGap22", "Pr08FGap22", "Ch08BGap22", "Pi08BGap22", "Ka08BGap22", "Pr08BGap22", "ChFull24", "PiFull24", "KaFull24", "PrFull24", "ChFull22", "PiFull22", "KaFull22", "PrFull22", "Ch08FGap22", "Pi08FGap22", "Ka08FGap22", "Pr08FGap22", "Ch08BGap22", "Pi08BGap22", "Ka08BGap22", "Pr08BGap22", "ChFull24", "PiFull24", "KaFull24", "PrFull24", "Ka08FGap24", "Ka08BGap24", "Ka08FGap24", "Ka08BGap24"}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1}, {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, 0, 0, 0}}, "Configurations for each correlation to calculate"}; @@ -121,11 +125,15 @@ struct FlowPbpbPikp { ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90}, "centrality axis for histograms"}; ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; + ConfigurableAxis axisNsigmaITS{"axisNsigmaITS", {80, -5, 5}, "nsigmaITS axis"}; ConfigurableAxis axisParticles{"axisParticles", {3, 0, 3}, "axis for different hadrons"}; ConfigurableAxis axisTPCsignal{"axisTPCsignal", {10000, 0, 1000}, "axis for TPC signal"}; + ConfigurableAxis axisTOFbeta{"axisTOFbeta", {200, 0, 2}, "axis for TOF beta"}; - std::vector tofNsigmaCut = cfgTofNsigmaCut; - std::vector itsNsigmaCut = cfgItsNsigmaCut; + std::vector tofNsigmaCut; + std::vector itsNsigmaCut; + std::vector tpcNsigmaCut; + std::vector eventCuts; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); @@ -152,23 +160,35 @@ struct FlowPbpbPikp { }; enum EventCutTypes { - useNoTimeFrameBorder = 0, - useNoITSROFrameBorder, - useNoSameBunchPileup, - useGoodZvtxFT0vsPV, - useNoCollInTimeRangeStandard, - useGoodITSLayersAll, - useNoCollInRofStandard, - useNoHighMultCollInPrevRof, - useOccupancy, - useMultCorrCut, - useT0AV0ACut, - useVertexITSTPC, - useTVXinTRD + kFilteredEvents = 0, + kAfterSel8, + kUseNoTimeFrameBorder, + kUseNoITSROFrameBorder, + kUseNoSameBunchPileup, + kUseGoodZvtxFT0vsPV, + kUseNoCollInTimeRangeStandard, + kUseGoodITSLayersAll, + kUseNoCollInRofStandard, + kUseNoHighMultCollInPrevRof, + kUseOccupancy, + kUseMultCorrCut, + kUseT0AV0ACut, + kUseVertexITSTPC, + kUseTVXinTRD }; - std::vector fintEvCuts = cfgUseEventCuts; - std::vector eventCuts; + enum TrackCutTypes { + kFilteredTracks = 0, + kUseGlobalTracks, + kUsePvContributor, + kItsClustersCut, + kHasTpcSignal, + kTpcClustersCut, + kTpcCrossedRowsCut, + kNumPions, + kNumKaons, + kNumProtons + }; int lastRunNumer = -1; std::vector runNumbers; @@ -193,15 +213,12 @@ struct FlowPbpbPikp { void init(InitContext const&) { + eventCuts = cfgUseEventCuts; + ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); ccdb->setCreatedNotAfter(noLaterThan.value); - // Transforming event cuts from int to bool - for (int i = 0; i < static_cast(fintEvCuts.size()); i++) { - eventCuts.push_back(static_cast(fintEvCuts[i])); - } - LOGF(info, "flowGenericFramework::init()"); regions.SetNames(cfgRegions->GetNames()); regions.SetEtaMin(cfgRegions->GetEtaMin()); @@ -238,26 +255,48 @@ struct FlowPbpbPikp { histos.add("c24_full_pi", "", {HistType::kTProfile, {axisMultiplicity}}); histos.add("c24_full_ka", "", {HistType::kTProfile, {axisMultiplicity}}); histos.add("c24_full_pr", "", {HistType::kTProfile, {axisMultiplicity}}); + + histos.add("TpcdEdx", "", {HistType::kTH2D, {axisPt, axisTPCsignal}}); + histos.add("TofBeta", "", {HistType::kTH2D, {axisPt, axisTOFbeta}}); + histos.add("TofTpcNsigma_before", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); - histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); + if (!cfgUseItsPID) + histos.add("TofTpcNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaTPC, axisNsigmaTOF, axisPt}}}); + + histos.add("TofItsNsigma_before", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaITS, axisNsigmaTOF, axisPt}}}); + if (cfgUseItsPID) + histos.add("TofItsNsigma_after", "", {HistType::kTHnSparseD, {{axisParticles, axisNsigmaITS, axisNsigmaTOF, axisPt}}}); + histos.add("partCount", "", {HistType::kTHnSparseD, {{axisParticles, axisMultiplicity, axisPt}}}); - histos.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{15, 0, 15}}}); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "After sel8"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "kNoTimeFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "kIsGoodITSLayersAll"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(9, "kNoCollInRofStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(10, "kNoHighMultCollInPrevRof"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(11, "Occupancy Cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(12, "Multiplicity correlation Cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(13, "T0AV0A cut"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(14, "kIsVertexITSTPC"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(15, "kTVXinTRD"); + histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, -0.5, 14.5}}}); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kFilteredEvents + 1, "Filtered event"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kAfterSel8 + 1, "After sel8"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoSameBunchPileup + 1, "kNoSameBunchPileup"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInTimeRangeStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInRofStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseOccupancy + 1, "Occupancy Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseMultCorrCut + 1, "Multiplicity correlation Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseT0AV0ACut + 1, "T0AV0A cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseVertexITSTPC + 1, "kIsVertexITSTPC"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseTVXinTRD + 1, "kTVXinTRD"); + + histos.add("hTrackCount", "Number of Tracks;; Count", {HistType::kTH1D, {{10, -0.5, 9.5}}}); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kFilteredTracks + 1, "Filtered track"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUseGlobalTracks + 1, "Global tracks"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUsePvContributor + 1, "PV contributor"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kItsClustersCut + 1, "ITS clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kHasTpcSignal + 1, "TPC signal"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcClustersCut + 1, "TPC clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcCrossedRowsCut + 1, "TPC crossed rows"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kNumPions + 1, "Pions"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kNumKaons + 1, "Kaons"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kNumProtons + 1, "Protons"); if (cfgOutputNUAWeights && !cfgOutputRunByRun) { histos.add("NUA/hPhiEtaVtxz_ref", ";#varphi;#eta;v_{z}", {HistType::kTH3D, {axisPhi, axisEta, axisVertex}}); @@ -324,7 +363,7 @@ struct FlowPbpbPikp { fFC->Initialize(oba, axisMultiplicity, cfgNbootstrap); delete oba; - if (eventCuts[useMultCorrCut]) { + if (eventCuts[kUseMultCorrCut]) { 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); @@ -335,7 +374,7 @@ struct FlowPbpbPikp { 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); } - if (eventCuts[useT0AV0ACut]) { + if (eventCuts[kUseT0AV0ACut]) { 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); @@ -360,7 +399,11 @@ struct FlowPbpbPikp { funcV4 = new TF1("funcV4", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); funcV4->SetParameters(0.008845, 0.000259668, -3.24435e-06, 4.54837e-08, -6.01825e-10); } - } + + tofNsigmaCut = cfgTofNsigmaCut; + itsNsigmaCut = cfgItsNsigmaCut; + tpcNsigmaCut = cfgTpcNsigmaCut; + } // End of init() enum Particles { PIONS, @@ -386,13 +429,38 @@ struct FlowPbpbPikp { template bool selectionTrack(const TTrack& track) { - if (cfgUseGlobalTrack && !(track.isGlobalTrack() && track.isPVContributor() && track.itsNCls() > cfgITScluster && track.tpcNClsFound() > cfgTpcCluster && track.hasTPC())) { - return false; + histos.fill(HIST("hTrackCount"), kFilteredTracks); // Filtered tracks + if (cfgUseGlobalTrack && !(track.isGlobalTrack())) { + return 0; + } + if (cfgUseGlobalTrack) + histos.fill(HIST("hTrackCount"), kUseGlobalTracks); // After global track selection + + if (!(track.isPVContributor())) { + return 0; + } + histos.fill(HIST("hTrackCount"), kUsePvContributor); // After PV contributor selection + + if (!(track.itsNCls() > cfgITScluster)) { + return 0; + } + histos.fill(HIST("hTrackCount"), kItsClustersCut); // After ITS cluster selection + + if (!(track.hasTPC())) { + return 0; + } + histos.fill(HIST("hTrackCount"), kHasTpcSignal); // If track has TPC signal + + if (!(track.tpcNClsFound() > cfgTpcCluster)) { + return 0; } - if (!cfgUseGlobalTrack && !(track.isPVContributor() && track.itsNCls() > cfgITScluster && track.hasTPC())) { - return false; + histos.fill(HIST("hTrackCount"), kTpcClustersCut); // After TPC cluster selection + + if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) { + return 0; } - return true; + histos.fill(HIST("hTrackCount"), kTpcCrossedRowsCut); // After TPC crossed rows selection + return 1; } template @@ -401,7 +469,11 @@ struct FlowPbpbPikp { histos.fill(HIST("partCount"), pidIndex - 1, collision.centFT0C(), track.pt()); switch (pidIndex) { case 1: - histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); + if (!cfgUseItsPID) + histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt()); + if (cfgUseItsPID) + histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaPi(), track.pt()); + histos.fill(HIST("hTrackCount"), kNumPions); // Pion count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pi_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // pion weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -410,7 +482,11 @@ struct FlowPbpbPikp { histos.fill(HIST("PhiCorrected/hPhiEtaPt_pi_corrd"), track.phi(), track.eta(), track.pt(), wacc); break; case 2: - histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); + if (!cfgUseItsPID) + histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaKa(), track.tofNSigmaKa(), track.pt()); + if (cfgUseItsPID) + histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaKa(), track.pt()); + histos.fill(HIST("hTrackCount"), kNumKaons); // Kaon count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_ka_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // kaon weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -419,7 +495,11 @@ struct FlowPbpbPikp { histos.fill(HIST("PhiCorrected/hPhiEtaPt_ka_corrd"), track.phi(), track.eta(), track.pt(), wacc); break; case 3: - histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + if (!cfgUseItsPID) + histos.fill(HIST("TofTpcNsigma_after"), pidIndex - 1, track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); + if (cfgUseItsPID) + histos.fill(HIST("TofItsNsigma_after"), pidIndex - 1, itsResponse.nSigmaITS(track), track.tofNSigmaPr(), track.pt()); + histos.fill(HIST("hTrackCount"), kNumProtons); // Proton count if (!cfgAcceptance.value.empty() && cfgUseWeightPhiEtaVtxz) histos.fill(HIST("PhiCorrected/hPhiEtaVtxz_pr_corrd"), track.phi(), track.eta(), collision.posZ(), wacc); // proton weights if (!cfgAcceptance.value.empty() && cfgUseWeightPhiPtCent) @@ -437,12 +517,12 @@ struct FlowPbpbPikp { std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; std::array nSigmaCombined = {std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()), std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())}; int pid = -1; - float nsigma = cfgTpcNsigmaCut; + float nsigma = cfgTpcCut; // Choose which nSigma to use std::array nSigmaToUse = (track.pt() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; if (track.pt() > cfgTofPtCut && !track.hasTOF()) - return -1; + return 0; const int numSpecies = 3; int pidCount = 0; @@ -450,7 +530,7 @@ struct FlowPbpbPikp { for (int i = 0; i < numSpecies; ++i) { if (std::abs(nSigmaToUse[i]) < nsigma) { if (pidCount > 0 && cfgUseStrictPID) - return -1; // more than one particle with low nsigma + return 0; // more than one particle with low nsigma pidCount++; pid = i; @@ -461,6 +541,56 @@ struct FlowPbpbPikp { 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 = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::vector detectorNsigmaCut = 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() > cfgTofPtCut && !track.hasTOF()) { + return 0; + } 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 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 void fillProfile(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const double& cent) { @@ -645,70 +775,70 @@ struct FlowPbpbPikp { template bool selectionEvent(TCollision collision, const int mult, const float cent) { - histos.fill(HIST("hEventCount"), 0.5); + histos.fill(HIST("hEventCount"), kFilteredEvents); if (!collision.sel8()) { return 0; } - histos.fill(HIST("hEventCount"), 1.5); + histos.fill(HIST("hEventCount"), kAfterSel8); - if (eventCuts[useNoTimeFrameBorder] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + if (eventCuts[kUseNoTimeFrameBorder] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { return 0; } - if (eventCuts[useNoTimeFrameBorder]) - histos.fill(HIST("hEventCount"), 2.5); + if (eventCuts[kUseNoTimeFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoTimeFrameBorder); - if (eventCuts[useNoITSROFrameBorder] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + if (eventCuts[kUseNoITSROFrameBorder] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { return 0; } - if (eventCuts[useNoITSROFrameBorder]) - histos.fill(HIST("hEventCount"), 3.5); + if (eventCuts[kUseNoITSROFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoITSROFrameBorder); - if (eventCuts[useNoSameBunchPileup] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (eventCuts[kUseNoSameBunchPileup] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return 0; } - if (eventCuts[useNoSameBunchPileup]) - histos.fill(HIST("hEventCount"), 4.5); + if (eventCuts[kUseNoSameBunchPileup]) + histos.fill(HIST("hEventCount"), kUseNoSameBunchPileup); - if (eventCuts[useGoodZvtxFT0vsPV] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (eventCuts[kUseGoodZvtxFT0vsPV] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { return 0; } - if (eventCuts[useGoodZvtxFT0vsPV]) - histos.fill(HIST("hEventCount"), 5.5); + if (eventCuts[kUseGoodZvtxFT0vsPV]) + histos.fill(HIST("hEventCount"), kUseGoodZvtxFT0vsPV); - if (eventCuts[useNoCollInTimeRangeStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + if (eventCuts[kUseNoCollInTimeRangeStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return 0; } - if (eventCuts[useNoCollInTimeRangeStandard]) - histos.fill(HIST("hEventCount"), 6.5); + if (eventCuts[kUseNoCollInTimeRangeStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInTimeRangeStandard); - if (eventCuts[useGoodITSLayersAll] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (eventCuts[kUseGoodITSLayersAll] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { return 0; } - if (eventCuts[useGoodITSLayersAll]) - histos.fill(HIST("hEventCount"), 7.5); + if (eventCuts[kUseGoodITSLayersAll]) + histos.fill(HIST("hEventCount"), kUseGoodITSLayersAll); - if (eventCuts[useNoCollInRofStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + if (eventCuts[kUseNoCollInRofStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return 0; } - if (eventCuts[useNoCollInRofStandard]) - histos.fill(HIST("hEventCount"), 8.5); + if (eventCuts[kUseNoCollInRofStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInRofStandard); - if (eventCuts[useNoHighMultCollInPrevRof] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + if (eventCuts[kUseNoHighMultCollInPrevRof] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { return 0; } - if (eventCuts[useNoHighMultCollInPrevRof]) - histos.fill(HIST("hEventCount"), 9.5); + if (eventCuts[kUseNoHighMultCollInPrevRof]) + histos.fill(HIST("hEventCount"), kUseNoHighMultCollInPrevRof); auto multNTracksPV = collision.multNTracksPV(); auto occupancy = collision.trackOccupancyInTimeRange(); - if (eventCuts[useOccupancy] && (occupancy < cfgCutOccupancyMin || occupancy > cfgCutOccupancyMax)) { + if (eventCuts[kUseOccupancy] && (occupancy < cfgCutOccupancyMin || occupancy > cfgCutOccupancyMax)) { return 0; } - if (eventCuts[useOccupancy]) - histos.fill(HIST("hEventCount"), 10.5); + if (eventCuts[kUseOccupancy]) + histos.fill(HIST("hEventCount"), kUseOccupancy); - if (eventCuts[useMultCorrCut]) { + if (eventCuts[kUseMultCorrCut]) { if (multNTracksPV < fMultPVCutLow->Eval(cent)) return 0; if (multNTracksPV > fMultPVCutHigh->Eval(cent)) @@ -718,25 +848,25 @@ struct FlowPbpbPikp { if (mult > fMultCutHigh->Eval(cent)) return 0; } - if (eventCuts[useMultCorrCut]) - histos.fill(HIST("hEventCount"), 11.5); + if (eventCuts[kUseMultCorrCut]) + histos.fill(HIST("hEventCount"), kUseMultCorrCut); // V0A T0A 5 sigma cut - if (eventCuts[useT0AV0ACut] && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > cfgV0AT0Acut * fT0AV0ASigma->Eval(collision.multFT0A()))) + if (eventCuts[kUseT0AV0ACut] && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > cfgV0AT0Acut * fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; - if (eventCuts[useT0AV0ACut]) - histos.fill(HIST("hEventCount"), 12.5); + if (eventCuts[kUseT0AV0ACut]) + histos.fill(HIST("hEventCount"), kUseT0AV0ACut); - if (eventCuts[useVertexITSTPC] && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + if (eventCuts[kUseVertexITSTPC] && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) return 0; - if (eventCuts[useVertexITSTPC]) - histos.fill(HIST("hEventCount"), 13.5); + if (eventCuts[kUseVertexITSTPC]) + histos.fill(HIST("hEventCount"), kUseVertexITSTPC); - if (eventCuts[useTVXinTRD] && collision.alias_bit(kTVXinTRD)) { + if (eventCuts[kUseTVXinTRD] && collision.alias_bit(kTVXinTRD)) { return 0; } - if (eventCuts[useTVXinTRD]) - histos.fill(HIST("hEventCount"), 14.5); + if (eventCuts[kUseTVXinTRD]) + histos.fill(HIST("hEventCount"), kUseTVXinTRD); return 1; } @@ -814,14 +944,21 @@ struct FlowPbpbPikp { histos.fill(HIST("hEta"), track.eta()); histos.fill(HIST("hPt"), pt); + histos.fill(HIST("TpcdEdx"), pt, track.tpcSignal()); + histos.fill(HIST("TofBeta"), pt, track.beta()); + histos.fill(HIST("TofTpcNsigma_before"), PIONS, track.tpcNSigmaPi(), track.tofNSigmaPi(), pt); histos.fill(HIST("TofTpcNsigma_before"), KAONS, track.tpcNSigmaKa(), track.tofNSigmaKa(), pt); histos.fill(HIST("TofTpcNsigma_before"), PROTONS, track.tpcNSigmaPr(), track.tofNSigmaPr(), pt); + histos.fill(HIST("TofItsNsigma_before"), PIONS, itsResponse.nSigmaITS(track), track.tofNSigmaPi(), pt); + histos.fill(HIST("TofItsNsigma_before"), KAONS, itsResponse.nSigmaITS(track), track.tofNSigmaKa(), pt); + histos.fill(HIST("TofItsNsigma_before"), PROTONS, itsResponse.nSigmaITS(track), track.tofNSigmaPr(), pt); + bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); // within RF pT range - pidIndex = getNsigmaPIDTpcTof(track); + pidIndex = cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPIDTpcTof(track); weff = 1; // Initializing weff for each track // NUA weights diff --git a/PWGCF/Flow/Tasks/flowPtEfficiency.cxx b/PWGCF/Flow/Tasks/flowPtEfficiency.cxx index 78dbc0fc731..27657e0f435 100644 --- a/PWGCF/Flow/Tasks/flowPtEfficiency.cxx +++ b/PWGCF/Flow/Tasks/flowPtEfficiency.cxx @@ -14,29 +14,32 @@ /// \since Jun/08/2023 /// \brief a task to calculate the pt efficiency -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" +#include "FlowContainer.h" +#include "GFW.h" +#include "GFWCumulant.h" +#include "GFWPowerArray.h" +#include "GFWWeights.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "GFWPowerArray.h" -#include "GFW.h" -#include "GFWCumulant.h" -#include "GFWWeights.h" -#include "FlowContainer.h" +#include "Framework/ASoAHelpers.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; @@ -57,9 +60,12 @@ struct FlowPtEfficiency { O2_DEFINE_CONFIGURABLE(cfgCutITSclu, float, 5.0f, "minimum ITS clusters") O2_DEFINE_CONFIGURABLE(cfgCutTPCcrossedrows, float, 70.0f, "minimum TPC crossed rows") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 0.2f, "DCAxy cut for tracks") + O2_DEFINE_CONFIGURABLE(cfgDCAxyNSigma, float, 7, "Cut on number of sigma deviations from expected DCA in the transverse direction"); + O2_DEFINE_CONFIGURABLE(cfgDCAxyFunction, std::string, "(0.0015+0.005/(x^1.1))", "Functional form of pt-dependent DCAxy cut"); O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz cut for tracks") 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(cfgEnableITSCuts, bool, true, "switch of enabling ITS based track selection cuts") O2_DEFINE_CONFIGURABLE(cfgSelRunNumberEnabled, bool, false, "switch of run number selection") O2_DEFINE_CONFIGURABLE(cfgFlowEnabled, bool, false, "switch of calculating flow") O2_DEFINE_CONFIGURABLE(cfgFlowNbootstrap, int, 30, "Number of subsamples") @@ -127,6 +133,7 @@ struct FlowPtEfficiency { std::vector corrconfigsTruth; std::vector corrconfigsReco; TRandom3* fRndm = new TRandom3(0); + TF1* fPtDepDCAxy = nullptr; bool isStable(int pdg) { @@ -219,19 +226,29 @@ struct FlowPtEfficiency { fGFWReco->CreateRegions(); } - if (cfgTrkSelRun3ITSMatch) { - myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, TrackSelection::GlobalTrackRun3DCAxyCut::Default); - } else { - myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + if (cfgEnableITSCuts) { + if (cfgTrkSelRun3ITSMatch) { + myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSall7Layers, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + } else { + myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); + } } if (cfgCutDCAxyppPass3Enabled) { myTrackSel.SetMaxDcaXYPtDep([](float pt) { return 0.004f + 0.013f / pt; }); } else { - myTrackSel.SetMaxDcaXY(cfgCutDCAxy); + if (cfgCutDCAxy != 0.0) { + myTrackSel.SetMaxDcaXY(cfgCutDCAxy); + } else { + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgDCAxyFunction->c_str()), 0.001, 100); + fPtDepDCAxy->SetParameter(0, cfgDCAxyNSigma); + LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgDCAxyFunction->c_str())); + myTrackSel.SetMaxDcaXYPtDep([fPtDepDCAxy = this->fPtDepDCAxy](float pt) { return fPtDepDCAxy->Eval(pt); }); + } } myTrackSel.SetMinNClustersTPC(cfgCutTPCclu); - myTrackSel.SetMinNClustersITS(cfgCutITSclu); myTrackSel.SetMinNCrossedRowsTPC(cfgCutTPCcrossedrows); + if (cfgEnableITSCuts) + myTrackSel.SetMinNClustersITS(cfgCutITSclu); if (!cfgCutDCAzPtDepEnabled) myTrackSel.SetMaxDcaZ(cfgCutDCAz); } @@ -358,10 +375,12 @@ struct FlowPtEfficiency { template bool trackSelected(TTrack track) { - if (cfgkIsTrackGlobal && !track.isGlobalTrack()) + if (cfgkIsTrackGlobal && !track.isGlobalTrack()) { return false; - if (cfgCutDCAzPtDepEnabled && (track.dcaZ() > (0.004f + 0.013f / track.pt()))) + } + if (cfgCutDCAzPtDepEnabled && (track.dcaZ() > (0.004f + 0.013f / track.pt()))) { return false; + } return myTrackSel.IsSelected(track); } @@ -378,7 +397,6 @@ struct FlowPtEfficiency { if (!std::count(cfgRunNumberList.value.begin(), cfgRunNumberList.value.end(), runNumber)) return; } - float imp = 0; bool impFetched = false; float evPhi = 0; @@ -393,7 +411,6 @@ struct FlowPtEfficiency { fGFWReco->Clear(); } - for (const auto& track : tracks) { if (!trackSelected(track)) continue; diff --git a/PWGCF/Flow/Tasks/flowRunbyRun.cxx b/PWGCF/Flow/Tasks/flowRunbyRun.cxx index 620063e1d5d..9259eb8be9e 100644 --- a/PWGCF/Flow/Tasks/flowRunbyRun.cxx +++ b/PWGCF/Flow/Tasks/flowRunbyRun.cxx @@ -68,6 +68,7 @@ struct FlowRunbyRun { O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "max DCA to vertex z") O2_DEFINE_CONFIGURABLE(cfgCutDCAzPtDepEnabled, bool, false, "switch of DCAz pt dependent cut") O2_DEFINE_CONFIGURABLE(cfgUseAdditionalEventCut, bool, false, "Use additional event cut on mult correlations") + O2_DEFINE_CONFIGURABLE(cfgOutputCorrelationQA, bool, false, "Fill correlation QA histograms") 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") @@ -101,6 +102,10 @@ struct FlowRunbyRun { ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta 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}"}; + ConfigurableAxis axisCentForQA{"axisCentForQA", {100, 0, 100}, "centrality (%)"}; + ConfigurableAxis axisT0C{"axisT0C", {70, 0, 70000}, "N_{ch} (T0C)"}; + ConfigurableAxis axisT0A{"axisT0A", {200, 0, 200000}, "N_{ch} (T0A)"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; 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); @@ -113,7 +118,6 @@ struct FlowRunbyRun { // 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://alice-ccdb.cern.ch", "url of the ccdb repository"}; // Define output @@ -129,6 +133,7 @@ struct FlowRunbyRun { int lastRunNumer = -1; std::vector runNumbers; // vector of run numbers std::map>> th1sList; // map of histograms for all runs + std::map>> th2sList; // map of TH2 histograms for all runs std::map>> th3sList; // map of TH3 histograms for all runs std::map>> profilesList; // map of profiles for all runs enum OutputTH1Names { @@ -142,6 +147,14 @@ struct FlowRunbyRun { hEventCountSpecific, kCount_TH1Names }; + enum OutputTH2Names { + // here are TH2 histograms + hglobalTracks_centT0C = 0, + hglobalTracks_PVTracks, + hglobalTracks_multV0A, + hcentFV0A_centFT0C, + kCount_TH2Names + }; enum OutputTH3Names { hPhiEtaVtxz = 0, kCount_TH3Names @@ -170,14 +183,15 @@ struct FlowRunbyRun { TF1* fT0AV0AMean = nullptr; TF1* fT0AV0ASigma = nullptr; - using AodCollisions = soa::Filtered>; + using AodCollisions = soa::Filtered>; using AodTracks = soa::Filtered>; void init(InitContext const&) { ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); - ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); // Add output histograms to the registry runNumbers = cfgRunNumbers; @@ -358,6 +372,15 @@ struct FlowRunbyRun { histos[hEventCountSpecific]->GetXaxis()->SetBinLabel(10, "cfgEvSelV0AT0ACut"); th1sList.insert(std::make_pair(runNumber, histos)); + if (cfgOutputCorrelationQA) { + std::vector> th2s(kCount_TH2Names); + th2s[hglobalTracks_centT0C] = registry.add(Form("%d/globalTracks_centT0C", runNumber), "after cut;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); + th2s[hglobalTracks_PVTracks] = registry.add(Form("%d/globalTracks_PVTracks", runNumber), "after cut;mulplicity PV tracks;mulplicity global tracks", {HistType::kTH2D, {axisNch, axisNch}}); + th2s[hglobalTracks_multV0A] = registry.add(Form("%d/globalTracks_multV0A", runNumber), "after cut;mulplicity V0A;mulplicity global tracks", {HistType::kTH2D, {axisT0A, axisNch}}); + th2s[hcentFV0A_centFT0C] = registry.add(Form("%d/centFV0A_centFT0C", runNumber), "after cut;Centrality T0C;Centrality V0A", {HistType::kTH2D, {axisCentForQA, axisCentForQA}}); + th2sList.insert(std::make_pair(runNumber, th2s)); + } + std::vector> profiles(kCount_TProfileNames); profiles[c22] = registry.add(Form("%d/c22", runNumber), "", {HistType::kTProfile, {axisIndependent}}); profiles[c22_gap10] = registry.add(Form("%d/c22_gap10", runNumber), "", {HistType::kTProfile, {axisIndependent}}); @@ -455,7 +478,8 @@ struct FlowRunbyRun { th1sList[runNumber][hEventCountSpecific]->Fill(8.5); // V0A T0A 5 sigma cut - if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > 5 * fT0AV0ASigma->Eval(collision.multFT0A()))) + float nSigma = 5.; // 5 sigma cut + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > nSigma * fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; if (cfgEvSelV0AT0ACut) th1sList[runNumber][hEventCountSpecific]->Fill(9.5); @@ -511,6 +535,12 @@ struct FlowRunbyRun { th1sList[runNumber][hVtxZ]->Fill(collision.posZ()); th1sList[runNumber][hMult]->Fill(tracks.size()); th1sList[runNumber][hCent]->Fill(collision.centFT0C()); + if (cfgOutputCorrelationQA) { + th2sList[runNumber][hglobalTracks_centT0C]->Fill(collision.centFT0C(), tracks.size()); + th2sList[runNumber][hglobalTracks_PVTracks]->Fill(collision.multNTracksPV(), tracks.size()); + th2sList[runNumber][hglobalTracks_multV0A]->Fill(collision.multFV0A(), tracks.size()); + th2sList[runNumber][hcentFV0A_centFT0C]->Fill(collision.centFT0C(), collision.centFV0A()); + } loadCorrections(bc.timestamp(), runNumber); diff --git a/PWGCF/Flow/Tasks/flowSP.cxx b/PWGCF/Flow/Tasks/flowSP.cxx index db8bb0df404..1442509bba0 100644 --- a/PWGCF/Flow/Tasks/flowSP.cxx +++ b/PWGCF/Flow/Tasks/flowSP.cxx @@ -14,35 +14,39 @@ /// \since 01/12/2024 /// \brief task to evaluate flow with respect to spectator plane. -#include -#include -#include -#include -#include -#include -#include -#include +#include "GFWWeights.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "PWGCF/DataModel/SPTableZDC.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" -#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPLHCIFData.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" -#include "PWGCF/DataModel/SPTableZDC.h" -#include "GFWWeights.h" #include "TF1.h" #include "TPDGCode.h" +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -52,18 +56,18 @@ using namespace o2::framework::expressions; struct FlowSP { // QA Plots - O2_DEFINE_CONFIGURABLE(cfgFillEventQA, bool, true, "Fill histograms for event QA"); - O2_DEFINE_CONFIGURABLE(cfgFillTrackQA, bool, true, "Fill histograms for track QA"); - O2_DEFINE_CONFIGURABLE(cfgFillPIDQA, bool, true, "Fill histograms for PID QA"); - O2_DEFINE_CONFIGURABLE(cfgFillEventPlaneQA, bool, true, "Fill histograms for Event Plane QA"); - O2_DEFINE_CONFIGURABLE(cfgFillGeneralV1Histos, bool, true, "Fill histograms for vn analysis"); - O2_DEFINE_CONFIGURABLE(cfgFillQABefore, bool, true, "Fill QA histograms before cuts, only for processData"); + O2_DEFINE_CONFIGURABLE(cfgFillEventQA, bool, false, "Fill histograms for event QA"); + O2_DEFINE_CONFIGURABLE(cfgFillTrackQA, bool, false, "Fill histograms for track QA"); + 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"); // 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"); - O2_DEFINE_CONFIGURABLE(cfgFillEventPlane, bool, true, "Flag to make and fill histos with Event Plane"); - O2_DEFINE_CONFIGURABLE(cfgFillXandYterms, bool, true, "Flag to make and fill histos for with separate x and y terms for SPM"); + O2_DEFINE_CONFIGURABLE(cfgFillEventPlane, bool, false, "Flag to make and fill histos with Event Plane"); + O2_DEFINE_CONFIGURABLE(cfgFillXandYterms, bool, false, "Flag to make and fill histos for with separate x and y terms for SPM"); O2_DEFINE_CONFIGURABLE(cfgFillChargeDependence, bool, true, "Flag to make and fill histos for charge dependent flow"); - O2_DEFINE_CONFIGURABLE(cfgFillPID, bool, true, "Flag to make and fill histos for PID flow"); + O2_DEFINE_CONFIGURABLE(cfgFillPID, bool, false, "Flag to make and fill histos for PID flow"); // Centrality Estimators -> standard is FT0C O2_DEFINE_CONFIGURABLE(cfgCentFT0Cvariant1, bool, false, "Set centrality estimator to cfgCentFT0Cvariant1"); O2_DEFINE_CONFIGURABLE(cfgCentFT0M, bool, false, "Set centrality estimator to cfgCentFT0M"); @@ -85,18 +89,17 @@ 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)"); // 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(cfgTrackSelsPIDNsigma, float, 2.0, "nSigma cut for PID"); + O2_DEFINE_CONFIGURABLE(cfgTrackSelDoTrackQAvsCent, bool, true, "Do track selection QA plots as function of centrality"); // Additional event selections O2_DEFINE_CONFIGURABLE(cfgEvSelsUseAdditionalEventCut, bool, true, "Bool to enable Additional Event Cut"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsnSigmaMultCuts, int, 3, "Sigma cut on Additional event cut: 1, 2 or 3 (default) sigma available"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsManualEventParameters, bool, false, "Use manual event parameters for the pile up fits. Needed for Cent estimaters other than FT0C"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsMultPv, std::vector, {}, "Multiplicity cuts for PV first 5 parameters cutLOW last 5 cutHIGH"); - O2_DEFINE_CONFIGURABLE(cfgEvSelsMult, std::vector, {}, "Multiplicity cuts for T0C first 5 parameters cutLOW last 5 cutHIGH"); O2_DEFINE_CONFIGURABLE(cfgEvSelsMaxOccupancy, int, 10000, "Maximum occupancy of selected events"); O2_DEFINE_CONFIGURABLE(cfgEvSelsNoSameBunchPileupCut, bool, true, "kNoSameBunchPileupCut"); O2_DEFINE_CONFIGURABLE(cfgEvSelsIsGoodZvtxFT0vsPV, bool, true, "kIsGoodZvtxFT0vsPV"); @@ -110,13 +113,18 @@ struct FlowSP { O2_DEFINE_CONFIGURABLE(cfgHarmMixed1, int, 2, "Flow harmonic n for ux and uy in mixed harmonics (MH): (Cos(n*phi), Sin(n*phi))"); O2_DEFINE_CONFIGURABLE(cfgHarmMixed2, int, 3, "Flow harmonic n for ux and uy in mixed harmonics (MH): (Cos(n*phi), Sin(n*phi))"); // settings for CCDB data - O2_DEFINE_CONFIGURABLE(cfgCCDBdir_QQ, std::string, "", "ccdb dir for average QQ values in 1% centrality bins"); + O2_DEFINE_CONFIGURABLE(cfgCCDBdir_QQ, std::string, "Users/c/ckoster/ZDC/LHC23_PbPb_pass4/meanQQ/Default", "ccdb dir for average QQ values in 1% centrality bins"); O2_DEFINE_CONFIGURABLE(cfgCCDBdir_SP, std::string, "", "ccdb dir for average event plane resolution in 1% centrality bins"); - O2_DEFINE_CONFIGURABLE(cfgCCDB_NUA, std::string, "", "ccdb dir for NUA corrections"); - O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE, std::string, "", "ccdb dir for NUE corrections"); + O2_DEFINE_CONFIGURABLE(cfgCCDB_NUA, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass4/Default", "ccdb dir for NUA corrections"); + O2_DEFINE_CONFIGURABLE(cfgCCDB_NUE, std::string, "Users/c/ckoster/flowSP/LHC23_PbPb_pass4/NUE/Default", "ccdb dir for NUE corrections"); O2_DEFINE_CONFIGURABLE(cfgCCDBdir_centrality, std::string, "", "ccdb dir for Centrality corrections"); // Confogirable axis ConfigurableAxis axisCentrality{"axisCentrality", {10, 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{2389.99, -83.8483, 1.11062, -0.00672263, 1.54725e-05, 4067.4, -145.485, 2.27273, -0.0186308, 6.5501e-05}, "Multiplicity cuts (PV) first 5 parameters cutLOW last 5 cutHIGH (Default is +-3sigma pass4) "}; + Configurable> cfgEvSelsMult{"cfgEvSelsMult", std::vector{1048.48, -31.4568, 0.287794, -0.00046847, -3.5909e-06, 2610.98, -83.3983, 1.0893, -0.00735094, 2.26929e-05}, "Multiplicity cuts (Global) first 5 parameters cutLOW last 5 cutHIGH (Default is +-3sigma pass4) "}; 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; @@ -145,6 +153,7 @@ struct FlowSP { struct Config { std::vector mEfficiency = {}; std::vector mAcceptance = {}; + std::vector mAcceptance2D = {}; bool correctionsLoaded = false; int lastRunNumber = 0; @@ -160,10 +169,10 @@ struct FlowSP { } cfg; - // define output objects OutputObj fWeights{GFWWeights("weights")}; OutputObj fWeightsPOS{GFWWeights("weights_positive")}; OutputObj fWeightsNEG{GFWWeights("weights_negative")}; + HistogramRegistry registry{"registry"}; // Event selection cuts - Alex @@ -246,18 +255,16 @@ struct FlowSP { AxisSpec axisDCAxy = {100, -.5, .5, "DCA_{xy} (cm)"}; AxisSpec axisPhiMod = {100, 0, constants::math::PI / 9, "fmod(#varphi,#pi/9)"}; AxisSpec axisPhi = {60, 0, constants::math::TwoPI, "#varphi"}; - AxisSpec axisEta = {64, -1.8, 1.8, "#eta"}; + AxisSpec axisEta = {64, -1.6, 1.6, "#eta"}; AxisSpec axisEtaVn = {8, -.8, .8, "#eta"}; AxisSpec axisVx = {40, -0.01, 0.01, "v_{x}"}; AxisSpec axisVy = {40, -0.01, 0.01, "v_{y}"}; AxisSpec axisVz = {40, -10, 10, "v_{z}"}; AxisSpec axisCent = {90, 0, 90, "Centrality(%)"}; AxisSpec axisPhiPlane = {100, -constants::math::PI, constants::math::PI, "#Psi"}; - AxisSpec axisNch = {40, 0, 40000, "N_{ch}"}; AxisSpec axisT0c = {70, 0, 100000, "N_{ch} (T0C)"}; AxisSpec axisT0a = {70, 0, 200000, "N_{ch} (T0A)"}; AxisSpec axisV0a = {70, 0, 200000, "N_{ch} (V0A)"}; - AxisSpec axisMultpv = {40, 0, 4000, "N_{ch} (PV)"}; AxisSpec axisShCl = {40, 0, 1, "Fraction shared cl. TPC"}; AxisSpec axisCl = {80, 0, 160, "Number of cl. TPC"}; AxisSpec axisNsigma = {100, -10, 10, "Nsigma for TPC and TOF"}; @@ -278,7 +285,7 @@ struct FlowSP { 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_MultCuts + 1, "Mult cuts (Alex)"); + registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_MultCuts + 1, "Multiplicity cuts"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_kIsGoodITSLayersAll + 1, "kkIsGoodITSLayersAll"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_isSelectedZDC + 1, "isSelected"); registry.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(evSel_CentCuts + 1, "Cenrality range"); @@ -296,14 +303,21 @@ struct FlowSP { registry.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(trackSel_ParticleWeights + 1, "Apply weights"); if (cfgFillWeights) { - fWeights->setPtBins(ptbins, &ptbinning[0]); - fWeights->init(true, false); + if (cfguseNUA2D) { + registry.add("weights/hPhi_Eta_vz", "", kTH3D, {axisPhi, axisEta, axisVz}); + registry.add("weights/hPhi_Eta_vz_positive", "", kTH3D, {axisPhi, axisEta, axisVz}); + registry.add("weights/hPhi_Eta_vz_negative", "", kTH3D, {axisPhi, axisEta, axisVz}); + } else { + // define output objects + fWeights->setPtBins(ptbins, &ptbinning[0]); + fWeights->init(true, false); - fWeightsPOS->setPtBins(ptbins, &ptbinning[0]); - fWeightsPOS->init(true, false); + fWeightsPOS->setPtBins(ptbins, &ptbinning[0]); + fWeightsPOS->init(true, false); - fWeightsNEG->setPtBins(ptbins, &ptbinning[0]); - fWeightsNEG->init(true, false); + fWeightsNEG->setPtBins(ptbins, &ptbinning[0]); + fWeightsNEG->init(true, false); + } } if (cfgFillEventQA) { @@ -312,9 +326,7 @@ struct FlowSP { registry.add("QA/after/hCentFV0A", "; Cent FV0A (%); ", {HistType::kTH1D, {axisCent}}); registry.add("QA/after/hCentNGlobal", "; Cent NGlobal (%); ", {HistType::kTH1D, {axisCent}}); registry.add("QA/after/globalTracks_centT0C", "", {HistType::kTH2D, {axisCent, axisNch}}); - registry.add("QA/after/globalTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisNch}}); registry.add("QA/after/PVTracks_centT0C", "", {HistType::kTH2D, {axisCent, axisMultpv}}); - registry.add("QA/after/PVTracks_centNGlobal", "", {HistType::kTH2D, {axisCent, axisMultpv}}); registry.add("QA/after/globalTracks_PVTracks", "", {HistType::kTH2D, {axisMultpv, axisNch}}); registry.add("QA/after/globalTracks_multT0A", "", {HistType::kTH2D, {axisT0a, axisNch}}); registry.add("QA/after/globalTracks_multV0A", "", {HistType::kTH2D, {axisV0a, axisNch}}); @@ -343,8 +355,10 @@ struct FlowSP { if (cfgFillTrackQA) { registry.add("incl/pion/QA/after/hPt", "", kTH1D, {axisPt}); registry.add("incl/pion/QA/after/hPhi", "", kTH1D, {axisPhi}); + registry.add("incl/pion/QA/after/hPhi_uncorrected", "", kTH1D, {axisPhi}); registry.add("incl/pion/QA/after/hEta", "", kTH1D, {axisEta}); registry.add("incl/pion/QA/after/hPhi_Eta_vz", "", kTH3D, {axisPhi, axisEta, axisVz}); + registry.add("incl/pion/QA/after/hPhi_Eta_vz_corrected", "", kTH3D, {axisPhi, axisEta, axisVz}); registry.add("incl/pion/QA/after/hDCAxy_pt", "", kTH2D, {axisPt, axisDCAxy}); registry.add("incl/pion/QA/after/hDCAz_pt", "", kTH2D, {axisPt, axisDCAz}); registry.add("incl/pion/QA/after/hSharedClusters_pt", "", {HistType::kTH2D, {axisPt, axisShCl}}); @@ -354,20 +368,42 @@ struct FlowSP { if (cfgFillQABefore) registry.addClone("incl/pion/QA/after/", "incl/pion/QA/before/"); } + if (cfgFillTrackQA) { registry.add("QA/after/pt_phi", "", {HistType::kTH2D, {axisPt, axisPhiMod}}); - registry.add("incl/QA/after/hPt", "", kTH1D, {axisPt}); - registry.add("incl/QA/after/hPhi", "", kTH1D, {axisPhi}); - registry.add("incl/QA/after/hEta", "", kTH1D, {axisEta}); registry.add("incl/QA/after/hPhi_Eta_vz", "", kTH3D, {axisPhi, axisEta, axisVz}); + registry.add("incl/QA/after/hPhi_Eta_vz_corrected", "", kTH3D, {axisPhi, axisEta, axisVz}); registry.add("incl/QA/after/hDCAxy_pt", "", kTH2D, {axisPt, axisDCAxy}); registry.add("incl/QA/after/hDCAz_pt", "", kTH2D, {axisPt, axisDCAz}); registry.add("incl/QA/after/hSharedClusters_pt", "", {HistType::kTH2D, {axisPt, axisShCl}}); registry.add("incl/QA/after/hCrossedRows_pt", "", {HistType::kTH2D, {axisPt, axisCl}}); registry.add("incl/QA/after/hCrossedRows_vs_SharedClusters", "", {HistType::kTH2D, {axisCl, axisShCl}}); + + if (cfgTrackSelDoTrackQAvsCent) { + registry.add("incl/QA/after/hPt", "", kTH2D, {axisPt, axisCent}); + registry.add("incl/QA/after/hPt_forward", "", kTH2D, {axisPt, axisCent}); + registry.add("incl/QA/after/hPt_forward_uncorrected", "", kTH2D, {axisPt, axisCent}); + registry.add("incl/QA/after/hPt_backward", "", kTH2D, {axisPt, axisCent}); + registry.add("incl/QA/after/hPt_backward_uncorrected", "", kTH2D, {axisPt, axisCent}); + registry.add("incl/QA/after/hPhi", "", kTH2D, {axisPhi, axisCent}); + registry.add("incl/QA/after/hPhi_uncorrected", "", kTH2D, {axisPhi, axisCent}); + registry.add("incl/QA/after/hEta", "", kTH2D, {axisEta, axisCent}); + registry.add("incl/QA/after/hEta_uncorrected", "", kTH2D, {axisEta, axisCent}); + } else { + registry.add("incl/QA/after/hPt", "", kTH1D, {axisPt}); + registry.add("incl/QA/after/hPt_forward", "", kTH1D, {axisPt}); + registry.add("incl/QA/after/hPt_forward_uncorrected", "", kTH1D, {axisPt}); + registry.add("incl/QA/after/hPt_backward", "", kTH1D, {axisPt}); + registry.add("incl/QA/after/hPt_backward_uncorrected", "", kTH1D, {axisPt}); + registry.add("incl/QA/after/hPhi", "", kTH1D, {axisPhi}); + registry.add("incl/QA/after/hPhi_uncorrected", "", kTH1D, {axisPhi}); + registry.add("incl/QA/after/hEta", "", kTH1D, {axisEta}); + registry.add("incl/QA/after/hEta_uncorrected", "", kTH1D, {axisEta}); + } + + if (cfgFillQABefore) + registry.addClone("incl/QA/after/", "incl/QA/before/"); } - if (cfgFillQABefore && (cfgFillTrackQA || cfgFillPIDQA)) - registry.addClone("incl/QA/after/", "incl/QA/before/"); if (doprocessMCReco) { registry.add("trackMCReco/after/hIsPhysicalPrimary", "", {HistType::kTH1D, {{2, 0, 2}}}); @@ -536,111 +572,26 @@ struct FlowSP { } if (cfgEvSelsUseAdditionalEventCut) { - - int twoSigma = 2; - int threeSigma = 3; - // Fitted for LHC23zzh_pass4 fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - - // Variables from fitting distribution with mean+1sigma - double fitParamLowPV1 = 2942.55; - double fitParamLowPV2 = -103.111; - double fitParamLowPV3 = 1.4397; - double fitParamLowPV4 = -0.00974862; - double fitParamLowPV5 = 2.71433e-05; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamLowPV1 = 2665.68; - fitParamLowPV2 = -93.3784; - fitParamLowPV3 = 1.27137; - fitParamLowPV4 = -0.00818936; - fitParamLowPV5 = 2.115e-05; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamLowPV1 = 2389.99; - fitParamLowPV2 = -83.8483; - fitParamLowPV3 = 1.11062; - fitParamLowPV4 = -0.00672263; - fitParamLowPV5 = 1.54725e-05; - } - - fMultPVCutLow->SetParameters(fitParamLowPV1, fitParamLowPV2, fitParamLowPV3, fitParamLowPV4, fitParamLowPV5); - fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - - // Variables from fitting distribution with mean+1sigma - double fitParamHighPV1 = 3508.13; - double fitParamHighPV2 = -124.831; - double fitParamHighPV3 = 1.87871; - double fitParamHighPV4 = -0.0145343; - double fitParamHighPV5 = 4.80688e-05; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamHighPV1 = 3787.93; - fitParamHighPV2 = -135.184; - fitParamHighPV3 = 2.07683; - fitParamHighPV4 = -0.0165997; - fitParamHighPV5 = 5.68725e-05; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamHighPV1 = 4067.4; - fitParamHighPV2 = -145.485; - fitParamHighPV3 = 2.27273; - fitParamHighPV4 = -0.0186308; - fitParamHighPV5 = 6.5501e-05; - } - fMultPVCutHigh->SetParameters(fitParamHighPV1, fitParamHighPV2, fitParamHighPV3, fitParamHighPV4, fitParamHighPV5); - fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - - double fitParamLow1 = 1566.5; - double fitParamLow2 = -48.2114; - double fitParamLow3 = 0.529522; - double fitParamLow4 = -0.00235284; - double fitParamLow5 = 3.01132e-06; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamLow1 = 1307.92; - fitParamLow2 = -39.9168; - fitParamLow3 = 0.412675; - fitParamLow4 = -0.00148081; - fitParamLow5 = 1.10868e-07; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamLow1 = 1048.48; - fitParamLow2 = -31.4568; - fitParamLow3 = 0.287794; - fitParamLow4 = -0.00046847; - fitParamLow5 = -3.5909e-06; - } - fMultCutLow->SetParameters(fitParamLow1, fitParamLow2, fitParamLow3, fitParamLow4, fitParamLow5); - fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); - double fitParamHigh1 = 2089.73; - double fitParamHigh2 = -65.9772; - double fitParamHigh3 = 0.816781; - double fitParamHigh4 = -0.00496563; - double fitParamHigh5 = 1.34314e-05; - - if (cfgEvSelsnSigmaMultCuts == twoSigma) { - fitParamHigh1 = 2350.39; - fitParamHigh2 = -74.6939; - fitParamHigh3 = 0.953287; - fitParamHigh4 = -0.006162; - fitParamHigh5 = 1.80808e-05; - } else if (cfgEvSelsnSigmaMultCuts == threeSigma) { - fitParamHigh1 = 2610.98; - fitParamHigh2 = -83.3983; - fitParamHigh3 = 1.0893; - fitParamHigh4 = -0.00735094; - fitParamHigh5 = 2.26929e-05; - } + std::vector paramsMultPVCut = cfgEvSelsMultPv; + std::vector paramsMultCut = cfgEvSelsMult; - fMultCutHigh->SetParameters(fitParamHigh1, fitParamHigh2, fitParamHigh3, fitParamHigh4, fitParamHigh5); + // number of parameters required in cfgEvSelsMultPv and cfgEvSelsMult. (5 Low + 5 High) + uint64_t nParams = 10; - if (cfgEvSelsManualEventParameters) { - fMultPVCutLow->SetParameters((cfgEvSelsMultPv.value)[0], (cfgEvSelsMultPv.value)[1], (cfgEvSelsMultPv.value)[2], (cfgEvSelsMultPv.value)[3], (cfgEvSelsMultPv.value)[4]); - fMultPVCutHigh->SetParameters((cfgEvSelsMultPv.value)[5], (cfgEvSelsMultPv.value)[6], (cfgEvSelsMultPv.value)[7], (cfgEvSelsMultPv.value)[8], (cfgEvSelsMultPv.value)[9]); - fMultCutLow->SetParameters((cfgEvSelsMult.value)[0], (cfgEvSelsMult.value)[1], (cfgEvSelsMult.value)[2], (cfgEvSelsMult.value)[3], (cfgEvSelsMult.value)[4]); - fMultCutHigh->SetParameters((cfgEvSelsMult.value)[5], (cfgEvSelsMult.value)[6], (cfgEvSelsMult.value)[7], (cfgEvSelsMult.value)[8], (cfgEvSelsMult.value)[9]); + if (paramsMultPVCut.size() < nParams) { + LOGF(fatal, "cfgEvSelsMultPv not set properly.. size = %d (should be 10) --> Check your config files!", paramsMultPVCut.size()); + } else if (paramsMultCut.size() < nParams) { + LOGF(fatal, "cfgEvSelsMult not set properly.. size = %d (should be 10) --> Check your config files!", paramsMultCut.size()); + } else { + fMultPVCutLow->SetParameters(paramsMultPVCut[0], paramsMultPVCut[1], paramsMultPVCut[2], paramsMultPVCut[3], paramsMultPVCut[4]); + fMultPVCutHigh->SetParameters(paramsMultPVCut[5], paramsMultPVCut[6], paramsMultPVCut[7], paramsMultPVCut[8], paramsMultPVCut[9]); + fMultCutLow->SetParameters(paramsMultCut[0], paramsMultCut[1], paramsMultCut[2], paramsMultCut[3], paramsMultCut[4]); + fMultCutHigh->SetParameters(paramsMultCut[5], paramsMultCut[6], paramsMultCut[7], paramsMultCut[8], paramsMultCut[9]); } } @@ -650,6 +601,17 @@ struct FlowSP { } } // end of init + float getNUA2D(TH3D* hNUA, float eta, float phi, float vtxz) + { + int xind = hNUA->GetXaxis()->FindBin(phi); + int etaind = hNUA->GetYaxis()->FindBin(eta); + int vzind = hNUA->GetZaxis()->FindBin(vtxz); + float weight = hNUA->GetBinContent(xind, etaind, vzind); + if (weight != 0) + return 1. / weight; + return 1; + } + template int getTrackPID(TrackObject track) { @@ -687,12 +649,10 @@ struct FlowSP { } if (nIdentified == 0) { - // LOGF(warning, "No PID match found for |nSigma| < %.2f", cfgTrackSelsPIDNsigma); return kUnidentified; // No PID match found } else if (nIdentified == 1) { return valPID; } else { - // LOGF(warning, "Track identified as %i particles for |nSigma| < %.2f", nIdentified, cfgTrackSelsPIDNsigma); return kUnidentified; // Multiple PID matches found } @@ -702,10 +662,8 @@ struct FlowSP { 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); @@ -716,6 +674,19 @@ struct FlowSP { return grpo->getNominalL3Field(); } + std::pair getCrossingAngleCCDB(uint64_t timestamp) + { + // TODO done only once (and not per run). Will be replaced by CCDBConfigurable + auto grpo = ccdb->getForTimeStamp("GLO/Config/GRPLHCIF", timestamp); + if (grpo == nullptr) { + LOGF(fatal, "GRP object for Crossing Angle not found for timestamp %llu", timestamp); + return {0, 0}; + } + float crossingAngle = grpo->getCrossingAngle(); + uint16_t crossingAngleTime = grpo->getCrossingAngleTime(); + return {crossingAngle, crossingAngleTime}; + } + // From Generic Framework void loadCorrections(uint64_t timestamp) { @@ -725,19 +696,34 @@ struct FlowSP { int nWeights = 3; - if (cfgCCDB_NUA.value.empty() == false) { - TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUA, timestamp); - cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights"))); - cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_positive"))); - cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_negative"))); - int sizeAcc = cfg.mAcceptance.size(); - if (sizeAcc < nWeights) - LOGF(warning, "Could not load acceptance weights from %s", cfgCCDB_NUA.value.c_str()); - else - LOGF(info, "Loaded acceptance weights from %s", cfgCCDB_NUA.value.c_str()); - } else { - LOGF(info, "cfgCCDB_NUA empty! No corrections loaded"); + if (cfguseNUA1D) { + if (cfgCCDB_NUA.value.empty() == false) { + TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUA, timestamp); + cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights"))); + cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_positive"))); + cfg.mAcceptance.push_back(reinterpret_cast(listCorrections->FindObject("weights_negative"))); + int sizeAcc = cfg.mAcceptance.size(); + if (sizeAcc < nWeights) + LOGF(fatal, "Could not load acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + else + LOGF(info, "Loaded acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + } else { + LOGF(info, "cfgCCDB_NUA empty! No corrections loaded"); + } + } else if (cfguseNUA2D) { + if (cfgCCDB_NUA.value.empty() == false) { + TH3D* hNUA2D = ccdb->getForTimeStamp(cfgCCDB_NUA, timestamp); + if (!hNUA2D) { + LOGF(fatal, "Could not load acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + } else { + LOGF(info, "Loaded acceptance weights from %s", cfgCCDB_NUA.value.c_str()); + cfg.mAcceptance2D.push_back(hNUA2D); + } + } else { + LOGF(info, "cfgCCDB_NUA empty! No corrections loaded"); + } } + // Get Efficiency correction if (cfgCCDB_NUE.value.empty() == false) { TList* listCorrections = ccdb->getForTimeStamp(cfgCCDB_NUE, timestamp); cfg.mEfficiency.push_back(reinterpret_cast(listCorrections->FindObject("Efficiency"))); @@ -766,11 +752,21 @@ struct FlowSP { if (eff == 0) return false; weight_nue = 1. / eff; - int sizeAcc = cfg.mAcceptance.size(); - if (sizeAcc > pID) - weight_nua = cfg.mAcceptance[pID]->getNUA(phi, eta, vtxz); - else - weight_nua = 1; + + if (cfguseNUA1D) { + int sizeAcc = cfg.mAcceptance.size(); + if (sizeAcc > pID) { + weight_nua = cfg.mAcceptance[pID]->getNUA(phi, eta, vtxz); + } else { + weight_nua = 1; + } + } else if (cfguseNUA2D) { + if (cfg.mAcceptance2D.size() > 0) { + weight_nua = getNUA2D(cfg.mAcceptance2D[0], eta, phi, vtxz); + } else { + weight_nua = 1; + } + } return true; } @@ -895,8 +891,6 @@ struct FlowSP { registry.fill(HIST("hTrackCount"), trackSel_DCAz); - // registry.fill(HIST("hTrackCount"), trackSel_GlobalTracks); - if (track.tpcNClsFound() < cfgTrackSelsNcls) return false; registry.fill(HIST("hTrackCount"), trackSel_NCls); @@ -953,7 +947,7 @@ struct FlowSP { registry.fill(HIST("QA/") + HIST(Time[ft]) + HIST("/CentFT0C_vs_CentNGlobal"), collision.centFT0C(), collision.centNGlobal(), centWeight); if (cfgFillEventPlaneQA) { - if constexpr (framework::has_type_v) { + if constexpr (o2::framework::has_type_v) { double psiA = 1.0 * std::atan2(collision.qyA(), collision.qxA()); double psiC = 1.0 * std::atan2(collision.qyC(), collision.qxC()); double psiFull = 1.0 * std::atan2(collision.qyA() + collision.qyC(), collision.qxA() + collision.qxC()); @@ -1089,10 +1083,50 @@ struct FlowSP { return; static constexpr std::string_view Time[] = {"before/", "after/"}; + // NOTE: species[kUnidentified] = "" (when no PID) registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt"), track.pt(), wacc * weff); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi"), track.phi(), wacc * weff); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hEta"), track.eta(), wacc * weff); - registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz"), track.phi(), track.eta(), vz, wacc * weff); + if (track.eta() > 0) { + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_forward"), track.pt(), wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_forward_uncorrected"), track.pt()); + } else { + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_backward"), track.pt(), wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_backward_uncorrected"), track.pt()); + } + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi"), track.phi(), wacc); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_uncorrected"), track.phi()); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hEta"), track.eta(), wacc); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hEta_uncorrected"), track.eta()); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz"), track.phi(), track.eta(), vz); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz_corrected"), track.phi(), track.eta(), vz, wacc); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAxy_pt"), track.pt(), track.dcaXY(), wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAz_pt"), track.pt(), track.dcaZ(), wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hSharedClusters_pt"), track.pt(), track.tpcFractionSharedCls(), wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hCrossedRows_pt"), track.pt(), track.tpcNClsFound(), wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hCrossedRows_vs_SharedClusters"), track.tpcNClsFound(), track.tpcFractionSharedCls(), wacc * weff); + } + + template + inline void fillTrackQA(TrackObject track, double vz, double centrality, float wacc = 1, float weff = 1) + { + if (!cfgFillTrackQA) + return; + + static constexpr std::string_view Time[] = {"before/", "after/"}; + // NOTE: species[kUnidentified] = "" (when no PID) + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt"), track.pt(), centrality, wacc * weff); + if (track.eta() > 0) { + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_forward"), track.pt(), centrality, wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_forward_uncorrected"), track.pt(), centrality); + } else { + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_backward"), track.pt(), centrality, wacc * weff); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPt_backward_uncorrected"), track.pt(), centrality); + } + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi"), track.phi(), centrality, wacc); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_uncorrected"), track.phi(), centrality); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hEta"), track.eta(), centrality, wacc); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hEta_uncorrected"), track.eta(), centrality); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz"), track.phi(), track.eta(), vz); + registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hPhi_Eta_vz_corrected"), track.phi(), track.eta(), vz, wacc); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAxy_pt"), track.pt(), track.dcaXY(), wacc * weff); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hDCAz_pt"), track.pt(), track.dcaZ(), wacc * weff); registry.fill(HIST(Charge[ct]) + HIST(Species[pt]) + HIST("QA/") + HIST(Time[ft]) + HIST("hSharedClusters_pt"), track.pt(), track.tpcFractionSharedCls(), wacc * weff); @@ -1167,15 +1201,27 @@ struct FlowSP { } template - void fillAllQA(TrackObject track, double vtxz, bool pos) + void fillAllQA(TrackObject track, double vtxz, double centrality, bool pos, float wacc = 1, float weff = 1, float waccP = 1, float weffP = 1, float waccN = 1, float weffN = 1) { - fillTrackQA(track, vtxz); + if (!cfgTrackSelDoTrackQAvsCent) { + fillTrackQA(track, vtxz, wacc, weff); + } else { + fillTrackQA(track, vtxz, centrality, wacc, weff); + } fillPIDQA(track); if (pos) { - fillTrackQA(track, vtxz); + if (!cfgTrackSelDoTrackQAvsCent) { + fillTrackQA(track, vtxz, waccP, weffP); + } else { + fillTrackQA(track, vtxz, centrality, waccP, weffP); + } fillPIDQA(track); } else { - fillTrackQA(track, vtxz); + if (!cfgTrackSelDoTrackQAvsCent) { + fillTrackQA(track, vtxz, waccN, weffN); + } else { + fillTrackQA(track, vtxz, centrality, waccN, weffN); + } fillPIDQA(track); } } @@ -1188,10 +1234,11 @@ struct FlowSP { auto field = (cfgMagField == standardMagField) ? getMagneticField(bc.timestamp()) : cfgMagField; if (bc.runNumber() != cfg.lastRunNumber) { - // load corrections again for new run! 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) @@ -1316,16 +1363,16 @@ struct FlowSP { if (cfgFillQABefore) { switch (trackPID) { case kUnidentified: - fillAllQA(track, vtxz, pos); + fillAllQA(track, vtxz, centrality, pos); break; case kPion: - fillAllQA(track, vtxz, pos); + fillAllQA(track, vtxz, centrality, pos); break; case kKaon: - fillAllQA(track, vtxz, pos); + fillAllQA(track, vtxz, centrality, pos); break; case kProton: - fillAllQA(track, vtxz, pos); + fillAllQA(track, vtxz, centrality, pos); break; } } @@ -1333,46 +1380,55 @@ struct FlowSP { if (!trackSelected(track, field)) continue; - switch (trackPID) { - case kUnidentified: - fillAllQA(track, vtxz, pos); - break; - case kPion: - fillAllQA(track, vtxz, pos); - break; - case kKaon: - fillAllQA(track, vtxz, pos); - break; - case kProton: - fillAllQA(track, vtxz, pos); - break; + // constrain angle to 0 -> [0,0+2pi] + auto phi = RecoDecay::constrainAngle(track.phi(), 0); + + if (cfguseNUA2D && cfgFillWeights) { + registry.fill(HIST("weights/hPhi_Eta_vz"), phi, track.eta(), vtxz, 1); + if (pos) { + registry.fill(HIST("weights/hPhi_Eta_vz_positive"), phi, track.eta(), vtxz, 1); + } else { + registry.fill(HIST("weights/hPhi_Eta_vz_negative"), phi, track.eta(), vtxz, 1); + } } - // Fill NUA weights + // Fill NUA weights (last 0 is for Data see GFWWeights class (not a weight)) if (cfgFillWeights) { - fWeights->fill(track.phi(), track.eta(), vtxz, track.pt(), centrality, 0); + fWeights->fill(phi, track.eta(), vtxz, track.pt(), centrality, 0); } if (cfgFillWeightsPOS) { if (pos) - fWeightsPOS->fill(track.phi(), track.eta(), vtxz, track.pt(), centrality, 0); + fWeightsPOS->fill(phi, track.eta(), vtxz, track.pt(), centrality, 0); } if (cfgFillWeightsNEG) { if (!pos) - fWeightsNEG->fill(track.phi(), track.eta(), vtxz, track.pt(), centrality, 0); + fWeightsNEG->fill(phi, track.eta(), vtxz, track.pt(), centrality, 0); } - // Set weff and wacc for inclusice, negative and positive hadrons - if (!setCurrentParticleWeights(kInclusive, weff, wacc, track.phi(), track.eta(), track.pt(), vtxz)) + // Set weff and wacc for inclusive, negative and positive hadrons + if (!setCurrentParticleWeights(kInclusive, weff, wacc, phi, track.eta(), track.pt(), vtxz)) continue; - if (pos && !setCurrentParticleWeights(kPositive, weffP, waccP, track.phi(), track.eta(), track.pt(), vtxz)) + if (pos && !setCurrentParticleWeights(kPositive, weffP, waccP, phi, track.eta(), track.pt(), vtxz)) continue; - if (!pos && !setCurrentParticleWeights(kNegative, weffN, waccN, track.phi(), track.eta(), track.pt(), vtxz)) + if (!pos && !setCurrentParticleWeights(kNegative, weffN, waccN, phi, track.eta(), track.pt(), vtxz)) continue; registry.fill(HIST("hTrackCount"), trackSel_ParticleWeights); - // constrain angle to 0 -> [0,0+2pi] - auto phi = RecoDecay::constrainAngle(track.phi(), 0); + switch (trackPID) { + case kUnidentified: + fillAllQA(track, vtxz, centrality, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + case kPion: + fillAllQA(track, vtxz, centrality, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + case kKaon: + fillAllQA(track, vtxz, centrality, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + case kProton: + fillAllQA(track, vtxz, centrality, pos, wacc, weff, waccP, weffP, waccN, weffN); + break; + } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - auto ux = std::cos(cfgHarm * phi); @@ -1390,15 +1446,11 @@ struct FlowSP { double vnFull = std::cos(cfgHarm * (phi - psiFull)) / evPlaneRes; fillHistograms(track, wacc, weff, centWeight, ux, uy, uxMH, uyMH, uxMH2, uyMH2, qxA, qyA, qxC, qyC, corrQQx, corrQQy, corrQQ, vnA, vnC, vnFull, centrality); - fillTrackQA(track, vtxz, wacc, weff); - if (cfgFillChargeDependence) { if (pos) { fillHistograms(track, waccP, weffP, centWeight, ux, uy, uxMH, uyMH, uxMH2, uyMH2, qxA, qyA, qxC, qyC, corrQQx, corrQQy, corrQQ, vnA, vnC, vnFull, centrality); - fillTrackQA(track, vtxz, waccP, weffP); } else { fillHistograms(track, waccN, weffN, centWeight, ux, uy, uxMH, uyMH, uxMH2, uyMH2, qxA, qyA, qxC, qyC, corrQQx, corrQQy, corrQQ, vnA, vnC, vnFull, centrality); - fillTrackQA(track, vtxz, waccN, weffN); } } } // end of track loop @@ -1442,7 +1494,6 @@ struct FlowSP { fillEventQA(collision, tracks); - // LOGF(info, "Size of tracks: %i", tracks.size()); registry.fill(HIST("trackMCReco/hTrackSize_unFiltered"), tracks.size()); registry.fill(HIST("trackMCReco/hTrackSize_Filtered"), filteredTracks.size()); @@ -1467,10 +1518,8 @@ struct FlowSP { } PROCESS_SWITCH(FlowSP, processMCReco, "Process analysis for MC reconstructed events", false); - // Filter mcCollFilter = nabs(aod::mccollision::posZ) < cfgEvSelsVtxZ; void processMCGen(aod::McCollisions const& mcCollisions, CCs const& collisions, TCs const& tracks, FilteredTCs const& filteredTracks, MCs const& McParts) { - // LOGF(info, "Size of mccollisions: %i", mcCollisions.size()); for (const auto& mcCollision : mcCollisions) { float centrality = -1; diff --git a/PWGCF/Flow/Tasks/flowTask.cxx b/PWGCF/Flow/Tasks/flowTask.cxx index 5431a84bd47..9f27ffa0005 100644 --- a/PWGCF/Flow/Tasks/flowTask.cxx +++ b/PWGCF/Flow/Tasks/flowTask.cxx @@ -14,36 +14,40 @@ /// \since Dec/10/2023 /// \brief jira: PWGCF-254, task to measure flow observables with cumulant method -#include -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" +#include "FlowContainer.h" +#include "FlowPtContainer.h" +#include "GFW.h" +#include "GFWConfig.h" +#include "GFWCumulant.h" +#include "GFWPowerArray.h" +#include "GFWWeights.h" -#include "Common/DataModel/EventSelection.h" +#include "Common/CCDB/ctpRateFetcher.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/CCDB/ctpRateFetcher.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 "GFWPowerArray.h" -#include "GFW.h" -#include "GFWCumulant.h" -#include "GFWWeights.h" -#include "FlowContainer.h" #include "TList.h" +#include +#include #include #include -#include -#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -53,6 +57,7 @@ using namespace o2::framework::expressions; struct FlowTask { + // Basic event&track selections O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") 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") @@ -64,16 +69,17 @@ struct FlowTask { O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "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(cfgEtaPtPt, float, 0.4, "eta cut for pt-pt correlations"); O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5f, "max chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgCutTPCclu, float, 70.0f, "minimum 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(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") + // Additional events selection flags 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(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") @@ -85,24 +91,57 @@ struct FlowTask { 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(cfgEvSelOccupancy, bool, true, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyHigh, int, 500, "High cut on TPC occupancy") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") + // User configuration for ananlysis 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") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeightsRefPt, bool, false, "NUA weights are filled in ref pt bins") 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(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(cfgCutOccupancyLow, int, 0, "Low cut on TPC occupancy") 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)") + O2_DEFINE_CONFIGURABLE(cfgMpar, int, 4, "Highest order of pt-pt correlations") 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"}; - 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"}; + struct : ConfigurableGroup { + 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"}; + 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; 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"}; @@ -127,23 +166,25 @@ struct FlowTask { // Corrections TH1D* mEfficiency = nullptr; GFWWeights* mAcceptance = nullptr; - TObjArray* mAcceptanceList = nullptr; bool correctionsLoaded = false; // 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://alice-ccdb.cern.ch", "url of the ccdb repository"}; // Define output OutputObj fFC{FlowContainer("FlowContainer")}; OutputObj fFCgen{FlowContainer("FlowContainer_gen")}; + OutputObj fFCpt{FlowPtContainer("FlowPtContainer")}; + OutputObj fFCptgen{FlowPtContainer("FlowPtContainer_gen")}; OutputObj fWeights{GFWWeights("weights")}; HistogramRegistry registry{"registry"}; // define global variables GFW* fGFW = new GFW(); std::vector corrconfigs; + GFWCorrConfigs gfwConfigs; + std::vector corrconfigsPtVn; TAxis* fPtAxis; TRandom3* fRndm = new TRandom3(0); enum CentEstimators { @@ -172,19 +213,6 @@ struct FlowTask { TF1* funcV3; TF1* funcV4; - // Track selection - TrackSelection myTrackSel; - TF1* fPhiCutLow = nullptr; - TF1* fPhiCutHigh = nullptr; - // Additional Event selection cuts - Copy from flowGenericFramework.cxx - TF1* fMultPVCutLow = nullptr; - TF1* fMultPVCutHigh = nullptr; - TF1* fMultCutLow = nullptr; - TF1* fMultCutHigh = nullptr; - TF1* fMultMultPVCut = nullptr; - TF1* fT0AV0AMean = nullptr; - TF1* fT0AV0ASigma = nullptr; - void init(InitContext const&) { const AxisSpec axisVertex{40, -20, 20, "Vtxz (cm)"}; @@ -196,7 +224,8 @@ struct FlowTask { ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); - ccdb->setCreatedNotAfter(ccdbNoLaterThan.value); + auto now = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + ccdb->setCreatedNotAfter(now); // Add some output objects to the histogram registry // Event QA @@ -206,38 +235,27 @@ struct FlowTask { 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.add("hEventCountSpecific", "Number of Event;; Count", {HistType::kTH1D, {{10, 0, 10}}}); + 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, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); - 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"); - } + 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"); 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("hCent", hCentTitle.c_str(), {HistType::kTH1D, {{90, 0, 90}}}); + registry.add("hCent", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); if (doprocessMCGen) { registry.add("MCGen/MChVtxZ", "Vexter Z distribution", {HistType::kTH1D, {axisVertex}}); registry.add("MCGen/MChMult", "Multiplicity distribution", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); - registry.add("MCGen/MChCent", hCentTitle.c_str(), {HistType::kTH1D, {{90, 0, 90}}}); + registry.add("MCGen/MChCent", hCentTitle.c_str(), {HistType::kTH1D, {{100, 0, 100}}}); } if (!cfgUseSmallMemory) { registry.add("BeforeSel8_globalTracks_centT0C", "before sel8;Centrality T0C;mulplicity global tracks", {HistType::kTH2D, {axisCentForQA, axisNch}}); @@ -437,23 +455,50 @@ struct FlowTask { corrconfigs.push_back(fGFW->GetCorrelatorConfig(userDefineGFWCorr.at(i).c_str(), userDefineGFWName.at(i).c_str(), kFALSE)); } } - fGFW->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); + gfwConfigs.SetCorrs(cfgUserPtVnCorrConfig->GetCorrs()); + gfwConfigs.SetHeads(cfgUserPtVnCorrConfig->GetHeads()); + gfwConfigs.SetpTDifs(cfgUserPtVnCorrConfig->GetpTDifs()); + // Mask 1: vn-[pT], 2: vn-[pT^2], 4: vn-[pT^3] + gfwConfigs.SetpTCorrMasks(cfgUserPtVnCorrConfig->GetpTCorrMasks()); + gfwConfigs.Print(); + fFCpt->setUseCentralMoments(cfgUseCentralMoments); + fFCpt->setUseGapMethod(true); + fFCpt->initialise(axisIndependent, cfgMpar, gfwConfigs, cfgNbootstrap); + for (auto i = 0; i < gfwConfigs.GetSize(); ++i) { + corrconfigsPtVn.push_back(fGFW->GetCorrelatorConfig(gfwConfigs.GetCorrs()[i], gfwConfigs.GetHeads()[i], gfwConfigs.GetpTDifs()[i])); + } + fGFW->CreateRegions(); - 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 (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 (cfgTrackDensityCorrUse) { @@ -461,8 +506,8 @@ struct FlowTask { 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; + std::vector f1p0 = cfgFuncParas.cfgTrackDensityP0; + std::vector f1p1 = cfgFuncParas.cfgTrackDensityP1; for (uint ifunc = 0; ifunc < pTEffBins.size() - 1; ifunc++) { funcEff[ifunc] = new TF1(Form("funcEff%i", ifunc), "[0]+[1]*x", 0, 3000); funcEff[ifunc]->SetParameters(f1p0[ifunc], f1p1[ifunc]); @@ -474,12 +519,6 @@ struct FlowTask { funcV4 = new TF1("funcV4", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); funcV4->SetParameters(0.008845, 0.000259668, -3.24435e-06, 4.54837e-08, -6.01825e-10); } - - myTrackSel = getGlobalTrackSelectionRun3ITSMatch(TrackSelection::GlobalTrackRun3ITSMatching::Run3ITSibAny, TrackSelection::GlobalTrackRun3DCAxyCut::Default); - myTrackSel.SetMinNClustersTPC(cfgCutTPCclu); - myTrackSel.SetMinNClustersITS(cfgCutITSclu); - if (cfgCutDCAxyppPass3Enabled) - myTrackSel.SetMaxDcaXYPtDep([](float pt) { return 0.004f + 0.013f / pt; }); // Tuned on the LHC22f anchored MC LHC23d1d on primary pions. 7 Sigmas of the resolution } template @@ -524,30 +563,46 @@ struct FlowTask { return; } - void loadCorrections(uint64_t timestamp, int runNumber) + template + inline void fillPtSums(TTrack track, float weff) + { + if (std::abs(track.eta()) < cfgEtaPtPt) { + (dt == kGen) ? fFCptgen->fill(1., track.pt()) : fFCpt->fill(weff, track.pt()); + } + } + + template + void fillPtContainers(const float& centmult, const double& rndm) + { + (dt == kGen) ? fFCptgen->calculateCorrelations() : fFCpt->calculateCorrelations(); + (dt == kGen) ? fFCptgen->fillPtProfiles(centmult, rndm) : fFCpt->fillPtProfiles(centmult, rndm); + (dt == kGen) ? fFCptgen->fillCMProfiles(centmult, rndm) : fFCpt->fillCMProfiles(centmult, rndm); + for (uint l_ind = 0; l_ind < corrconfigsPtVn.size(); ++l_ind) { + if (!corrconfigsPtVn.at(l_ind).pTDif) { + auto dnx = fGFW->Calculate(corrconfigsPtVn.at(l_ind), 0, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigsPtVn.at(l_ind), 0, kFALSE).real() / dnx; + if (std::abs(val) < 1) { + (dt == kGen) ? fFCptgen->fillVnPtProfiles(centmult, val, dnx, rndm, gfwConfigs.GetpTCorrMasks()[l_ind]) : fFCpt->fillVnPtProfiles(centmult, val, dnx, rndm, gfwConfigs.GetpTCorrMasks()[l_ind]); + } + continue; + } + } + return; + } + + void loadCorrections(uint64_t timestamp) { if (correctionsLoaded) return; - if (!cfgAcceptanceListEnabled && cfgAcceptance.value.empty() == false) { + if (cfgAcceptance.value.empty() == false) { mAcceptance = ccdb->getForTimeStamp(cfgAcceptance, timestamp); if (mAcceptance) LOGF(info, "Loaded acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance); else LOGF(warning, "Could not load acceptance weights from %s (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance); } - if (cfgAcceptanceListEnabled && cfgAcceptanceList.value.empty() == false) { - mAcceptanceList = ccdb->getForTimeStamp(cfgAcceptanceList, timestamp); - if (mAcceptanceList == nullptr) { - LOGF(fatal, "Could not load acceptance weights list from %s", cfgAcceptanceList.value.c_str()); - } - LOGF(info, "Loaded acceptance weights list from %s (%p)", cfgAcceptanceList.value.c_str(), (void*)mAcceptanceList); - - mAcceptance = static_cast(mAcceptanceList->FindObject(Form("%d", runNumber))); - if (mAcceptance == nullptr) { - LOGF(fatal, "Could not find acceptance weights for run %d in acceptance list", runNumber); - } - LOGF(info, "Loaded acceptance weights (%p) for run %d from list (%p)", (void*)mAcceptance, runNumber, (void*)mAcceptanceList); - } if (cfgEfficiency.value.empty() == false) { mEfficiency = ccdb->getForTimeStamp(cfgEfficiency, timestamp); if (mEfficiency == nullptr) { @@ -587,107 +642,98 @@ struct FlowTask { } if (cfgEvSelkNoSameBunchPileup) registry.fill(HIST("hEventCountSpecific"), 1.5); + if (cfgEvSelkNoITSROFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return 0; + } + if (cfgEvSelkNoITSROFrameBorder) + registry.fill(HIST("hEventCountSpecific"), 2.5); + if (cfgEvSelkNoTimeFrameBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return 0; + } + if (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 (cfgEvSelkIsGoodZvtxFT0vsPV) - registry.fill(HIST("hEventCountSpecific"), 2.5); + registry.fill(HIST("hEventCountSpecific"), 4.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); + 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 (cfgEvSelkIsGoodITSLayersAll) - registry.fill(HIST("hEventCountSpecific"), 4.5); + 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 (cfgEvSelkNoCollInRofStandard) - registry.fill(HIST("hEventCountSpecific"), 5.5); + 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 (cfgEvSelkNoHighMultCollInPrevRof) - registry.fill(HIST("hEventCountSpecific"), 6.5); + registry.fill(HIST("hEventCountSpecific"), 8.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); + registry.fill(HIST("hEventCountSpecific"), 9.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 (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; + } } if (cfgEvSelMultCorrelation) - registry.fill(HIST("hEventCountSpecific"), 8.5); + registry.fill(HIST("hEventCountSpecific"), 10.5); // V0A T0A 5 sigma cut float sigma = 5.0; - if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > sigma * fT0AV0ASigma->Eval(collision.multFT0A()))) + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - cfgFuncParas.fT0AV0AMean->Eval(collision.multFT0A())) > sigma * cfgFuncParas.fT0AV0ASigma->Eval(collision.multFT0A()))) return 0; if (cfgEvSelV0AT0ACut) - registry.fill(HIST("hEventCountSpecific"), 9.5); + registry.fill(HIST("hEventCountSpecific"), 11.5); 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); - float sigma = 5.0; - if (!(std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > sigma * fT0AV0ASigma->Eval(collision.multFT0A()))) - registry.fill(HIST("hEventCountTentative"), 9.5); - } - template bool trackSelected(TTrack track) { - if (cfgCutDCAzPtDepEnabled && (std::fabs(track.dcaZ()) > (0.004f + 0.013f / track.pt()))) - return false; - - if (cfgTrkSelSwitch) { - return myTrackSel.IsSelected(track); - } else { - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu)); - } + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); } void initHadronicRate(aod::BCsWithTimestamps::iterator const& bc) @@ -730,7 +776,7 @@ struct FlowTask { return cent; } - void process(FilteredCollisions::iterator const& collision, aod::BCsWithTimestamps const&, FilteredTracks const& tracks) + void processData(FilteredCollisions::iterator const& collision, aod::BCsWithTimestamps const&, FilteredTracks const& tracks) { registry.fill(HIST("hEventCount"), 0.5); if (!cfgUseSmallMemory && tracks.size() >= 1) { @@ -760,8 +806,6 @@ struct FlowTask { } float cent = getCentrality(collision); - if (cfgUseTentativeEventCounter) - eventCounterQA(collision, tracks.size(), cent); if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent)) return; registry.fill(HIST("hEventCount"), 3.5); @@ -771,6 +815,7 @@ struct FlowTask { registry.fill(HIST("hMult"), tracks.size()); registry.fill(HIST("hCent"), cent); fGFW->Clear(); + fFCpt->clearVector(); if (cfgGetInteractionRate) { initHadronicRate(bc); double hadronicRate = mRateFetcher.fetch(ccdb.service, bc.timestamp(), mRunNumber, "ZNC hadronic") * 1.e-3; // @@ -779,7 +824,7 @@ struct FlowTask { return; gCurrentHadronicRate->Fill(seconds, hadronicRate); } - loadCorrections(bc.timestamp(), currentRunNumber); + loadCorrections(bc.timestamp()); registry.fill(HIST("hEventCount"), 4.5); // fill event QA @@ -879,6 +924,10 @@ struct FlowTask { fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 2); if (withinPtPOI && withinPtRef) fGFW->Fill(track.eta(), fPtAxis->FindBin(track.pt()) - 1, track.phi(), wacc * weff, 4); + if (cfgUsePtRef && withinPtRef) + fillPtSums(track, weff); + if (!cfgUsePtRef && withinPtPOI) + fillPtSums(track, weff); } registry.fill(HIST("hTrackCorrection2d"), tracks.size(), nTracksCorrected); @@ -886,7 +935,10 @@ struct FlowTask { for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { fillFC(corrconfigs.at(l_ind), independent, lRandom); } + // Filling pt Container + fillPtContainers(independent, lRandom); } + PROCESS_SWITCH(FlowTask, processData, "Process analysis for non-derived data", true); void processMCGen(FilteredMcCollisions::iterator const& mcCollision, FilteredSmallGroupMcCollisions const& collisions, FilteredMcParticles const& mcParticles) { @@ -908,6 +960,7 @@ struct FlowTask { independent = static_cast(mcParticles.size()); fGFW->Clear(); + fFCptgen->clearVector(); for (const auto& mcParticle : mcParticles) { if (!mcParticle.isPhysicalPrimary()) @@ -926,12 +979,18 @@ struct FlowTask { fGFW->Fill(mcParticle.eta(), fPtAxis->FindBin(mcParticle.pt()) - 1, mcParticle.phi(), 1., 2); if (withinPtPOI && withinPtRef) fGFW->Fill(mcParticle.eta(), fPtAxis->FindBin(mcParticle.pt()) - 1, mcParticle.phi(), 1., 4); + if (cfgUsePtRef && withinPtRef) + fillPtSums(mcParticle, 1.); + if (!cfgUsePtRef && withinPtPOI) + fillPtSums(mcParticle, 1.); } // Filling Flow Container for (uint l_ind = 0; l_ind < corrconfigs.size(); l_ind++) { fillFC(corrconfigs.at(l_ind), independent, lRandom); } + // Filling pt Container + fillPtContainers(independent, lRandom); } PROCESS_SWITCH(FlowTask, processMCGen, "Process analysis for MC generated events", false); }; diff --git a/PWGCF/Flow/Tasks/flowZdcTask.cxx b/PWGCF/Flow/Tasks/flowZdcTask.cxx index 3bad6691449..80844482e83 100644 --- a/PWGCF/Flow/Tasks/flowZdcTask.cxx +++ b/PWGCF/Flow/Tasks/flowZdcTask.cxx @@ -14,34 +14,40 @@ /// \since 10/01/2024 /// \brief task to evaluate flow and neutron skin with information from ZDC -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "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 -#include -#include + +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod::mult; +using namespace o2::constants::math; using namespace o2::aod::evsel; #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -50,29 +56,16 @@ struct FlowZdcTask { SliceCache cache; O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMin, float, 0.2f, "Minimal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutPtMax, float, 10.0f, "Maximal pT for ref tracks") - O2_DEFINE_CONFIGURABLE(cfgCutEta, float, 0.8f, "Eta range for tracks") - O2_DEFINE_CONFIGURABLE(cfgCutChi2prTPCcls, float, 2.5, "Chi2 per TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgUseNch, bool, false, "Use Nch for flow observables") - O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") - O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2, "DCA Z cut") - O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 0.2f, "DCA XY cut") - - Configurable nBinsPt{"nBinsPt", 500, "N bins in pT histo"}; + Configurable eventSelection{"eventSelection", 1, "event selection"}; - Configurable maxZp{"maxZp", 3099.5, "Max ZP signal"}; - Configurable minTpcNcrossedRows{"minTpcNcrossedRows", 20, "minTpcNcrossedRows"}; + 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 nBinsFT0Amp{"nBinsFT0Amp", 250000, "nbinsAmp"}; - Configurable maxZn{"maxZn", 4099.5, "Max ZN signal"}; + Configurable nBinsCent{"nBinsCent", 90, "nBinsCent"}; + Configurable maxZn{"maxZn", 125.5, "Max ZN signal"}; Configurable vtxRange{"vtxRange", 10.0f, "Vertex Z range to consider"}; Configurable etaRange{"etaRange", 1.0f, "Eta range to consider"}; - Configurable npvTracksCut{"npvTracksCut", 1.0f, "Apply extra NPVtracks cut"}; // configs for process QA Configurable nBinsNch{"nBinsNch", 2501, "N bins Nch (|eta|<0.8)"}; Configurable nBinsAmpFT0{"nBinsAmpFT0", 100, "N bins FT0 amp"}; @@ -80,9 +73,11 @@ struct FlowZdcTask { Configurable nBinsAmpFV0{"nBinsAmpFV0", 100, "N bins FV0 amp"}; Configurable maxAmpFV0{"maxAmpFV0", 2000, "Max FV0 amp"}; Configurable nBinsZDC{"nBinsZDC", 400, "nBinsZDC"}; - Configurable nBinsZEM{"nBinsZEM", 100, "nBinsZEM"}; + Configurable nBinsZN{"nBinsZN", 400, "N bins ZN"}; + Configurable nBinsZP{"nBinsZP", 160, "N bins ZP"}; Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; Configurable maxNch{"maxNch", 2500, "Max Nch (|eta|<0.8)"}; + Configurable oneNeutron{"oneNeutron", 1.0, "one neutron, energy or integer"}; Configurable nBinsTDC{"nBinsTDC", 150, "nbinsTDC"}; Configurable minTdc{"minTdc", -15.0, "minimum TDC"}; Configurable maxTdc{"maxTdc", 15.0, "maximum TDC"}; @@ -97,38 +92,44 @@ struct FlowZdcTask { Configurable isOccupancyCut{"isOccupancyCut", true, "Occupancy cut?"}; Configurable isApplyFT0CbasedOccupancy{"isApplyFT0CbasedOccupancy", false, "T0C Occu cut?"}; Configurable isTDCcut{"isTDCcut", false, "Use TDC cut?"}; - Configurable isZEMcut{"isZEMcut", true, "Use ZEM cut?"}; - + Configurable isZEMcut{"isZEMcut", false, "Use ZEM cut?"}; + Configurable useMidRapNchSel{"useMidRapNchSel", false, "Use mid-rapidity Nch selection"}; + Configurable applyEff{"applyEff", true, "Apply track-by-track efficiency correction"}; + Configurable applyFD{"applyFD", false, "Apply track-by-track feed down correction"}; + Configurable correctNch{"correctNch", true, "Correct also Nch"}; + Configurable isOneNeutronFound{"isOneNeutronFound", true, "Require at least 1 neutron in ZNA/ZNC to fill ZPA/ZPC"}; + + Configurable nSigmaNchCut{"nSigmaNchCut", 1., "nSigma Nch selection"}; Configurable minNchSel{"minNchSel", 5., "min Nch Selection"}; Configurable znBasedCut{"znBasedCut", 100, "ZN-based cut"}; Configurable zemCut{"zemCut", 1000., "ZEM cut"}; Configurable tdcCut{"tdcCut", 1., "TDC cut"}; Configurable minOccCut{"minOccCut", 0, "min Occu cut"}; Configurable maxOccCut{"maxOccCut", 500, "max Occu cut"}; - Configurable minITSnCls{"minITSnCls", 5, "min ITSnCls"}; + Configurable minPt{"minPt", 0.1, "minimum pt of the tracks"}; + Configurable maxPt{"maxPt", 3., "maximum pt of the tracks"}; + Configurable maxPtSpectra{"maxPtSpectra", 50., "maximum pt of the tracks"}; // axis configs - ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisPhi{"axisPhi", {60, 0.0, constants::math::TwoPI}, "phi axis for histograms"}; - ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.2, 0.25, 0.30, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.20, 2.40, 2.60, 2.80, 3.00}, "pt axis for histograms"}; ConfigurableAxis axisMultiplicity{"axisMultiplicity", {3500, 0, 3500}, "centrality axis for histograms"}; - ConfigurableAxis axisEnergy{"axisEnergy", {100, 0, 700}, "energy axis for zdc histos"}; - ConfigurableAxis axisMultTpc{"axisMultTpc", {2000, -0.5f, 2999.5f}, "TPCmultiplicity"}; ConfigurableAxis axisZN{"axisZN", {5000, 0, 500}, "axisZN"}; ConfigurableAxis axisZP{"axisZP", {5000, 0, 500}, "axisZP"}; ConfigurableAxis axisFT0CAmp{"axisFT0CAmp", {5000, 0, 5000}, "axisFT0CAmp"}; ConfigurableAxis axisFT0AAmp{"axisFT0AAmp", {5000, 0, 5000}, "axisFT0AAmp"}; ConfigurableAxis axisFT0MAmp{"axisFT0MAmp", {10000, 0, 10000}, "axisFT0MAmp"}; - ConfigurableAxis ft0cMultHistBin{"ft0cMultHistBin", {501, -0.5, 500.5}, ""}; ConfigurableAxis multHistBin{"multHistBin", {501, -0.5, 500.5}, ""}; ConfigurableAxis axisCent{"axisCent", {10, 0, 100}, "axisCent"}; + ConfigurableAxis ft0cMultHistBin{"ft0cMultHistBin", {501, -0.5, 500.5}, ""}; + 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"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; - Filter trackFilter = (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtMin) && (aod::track::pt < cfgCutPtMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::dcaXY) < cfgCutDCAxy); - using ColEvSels = soa::Join; + Filter trackFilter = ((aod::track::eta > minEta) && (aod::track::eta < maxEta)); + using ColEvSels = soa::Join; using AodCollisions = soa::Filtered>; using AodTracks = soa::Filtered>; Partition tracksIUWithTPC = (aod::track::tpcNClsFindable > (uint8_t)0); @@ -138,9 +139,14 @@ struct FlowZdcTask { using CollisionDataTable = soa::Join; using TrackDataTable = soa::Join; using FilTrackDataTable = soa::Filtered; - std::complex qTPC; // init q TPC - std::complex qZNA{0, 0}; // init qZNA - std::complex qZNC{0, 0}; // init qZNC + using TheFilteredTracks = soa::Filtered; + + // CCDB paths + Configurable paTH{"paTH", "Users/s/sahernan/test", "base path to the ccdb object"}; + Configurable paTHmeanNch{"paTHmeanNch", "Users/s/shernan/test", "base path to the ccdb object"}; + Configurable paTHsigmaNch{"paTHsigmaNch", "Users/s/shernan/testSigma", "base path to the ccdb object"}; + Configurable paTHEff{"paTHEff", "Users/s/shernan/TrackingEff", "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"}; enum EvCutLabel { All = 1, @@ -164,8 +170,7 @@ struct FlowZdcTask { // Begin Histogram Registry HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - OutputObj pCosPsiDifferences{TProfile("pCosPsiDifferences", "Differences in cos(psi) vs Centrality;Centrality;Mean cos(psi) Difference", 200, 0, 100, -1, 1)}; - OutputObj pSinPsiDifferences{TProfile("pSinPsiDifferences", "Differences in sin(psi) vs Centrality;Centrality;Mean sin(psi) Difference", 200, 0, 100, -1, 1)}; + Service ccdb; OutputObj pZNvsFT0Ccent{TProfile("pZNvsFT0Ccent", "ZN Energy vs FT0C Centrality", 100, 0, 100, 0, 500)}; OutputObj pZPvsFT0Ccent{TProfile("pZPvsFT0Ccent", "ZP Energy vs FT0C Centrality", 100, 0, 100, 0, 500)}; OutputObj pZNratiovscent{TProfile("pZNratiovscent", "Ratio ZNC/ZNA vs FT0C Centrality", 100, 0, 100, 0, 5)}; @@ -175,12 +180,10 @@ struct FlowZdcTask { { // define axes const AxisSpec axisCounter{1, 0, +1, ""}; - const AxisSpec axisQ{100, -1, 1, "Q"}; - const AxisSpec axisQZNA{100, -1, 1, "Q"}; - const AxisSpec axisREQ{100, -1, 1, "real Q"}; - const AxisSpec axisIMQ{100, -1, 1, "imag Q"}; const AxisSpec axisEvent{18, 0.5, 18.5, ""}; 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"}; AxisSpec axisMult = {multHistBin, "Mult", "MultAxis"}; @@ -189,33 +192,12 @@ struct FlowZdcTask { // create histograms histos.add("hEventCounter", "Event counter", kTH1F, {axisEvent}); histos.add("zPos", ";;Entries;", kTH1F, {axisZpos}); - histos.add("etaHistogram", "etaHistogram", kTH1F, {axisEta}); - histos.add("ptHistogram", "ptHistogram", kTH1F, {axisPt}); histos.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); - histos.add("centHistogram", "centHistogram", kTH1F, {axisCent}); - histos.add("multHistogram", "multHistogram", kTH1F, {axisMultiplicity}); - histos.add("multvsCent", "centrality vs multiplicity", kTH2F, {axisCent, axisMultiplicity}); - histos.add("phiHistogram", "phiHistogram", kTH1F, {axisPhi}); - histos.add("TPCmultiplicity", "TPCmultiplicity", kTH1F, {axisMultTpc}); - - histos.add("REqHistogram", "REqHistogram", kTH1F, {axisQ}); - histos.add("IMqHistogram", "IMqHistogram", kTH1F, {axisQ}); - - histos.add("REqHistogramZNA", "REqHistogramZNA", kTH1F, {axisQZNA}); - histos.add("IMqHistogramZNA", "IMqHistogramZNA", kTH1F, {axisQZNA}); - - histos.add("REqHistogramZNC", "REqHistogramZNC", kTH1F, {axisQZNA}); - histos.add("IMqHistogramZNC", "IMqHistogramZNC", kTH1F, {axisQZNA}); - - histos.add("EnergyZNA", "ZNA Sector Energy", kTH1F, {axisEnergy}); - histos.add("EnergyZNC", "ZNC Sector Energy", kTH1F, {axisEnergy}); - histos.add("hCentFT0C", "FT0C Centrality Distribution", kTH1F, {{100, 0, 105}}); histos.add("hZNvsFT0Ccent", "ZN Energy vs FT0C Centrality", kTH2F, {axisCent, axisZN}); - histos.add("hZPvsFT0Ccent", "ZP Energy vs FT0C Centrality;Centrality [%];ZP Energy", kTH2F, @@ -223,9 +205,20 @@ struct FlowZdcTask { histos.add("hNchvsNPV", ";NPVTracks (|#eta|<1);N_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsNch, -0.5, maxNch}, {nBinsNch, -0.5, maxNch}}}); - histos.add("revsimag", "revsimag", kTH2F, {axisREQ, axisIMQ}); // for q vector recentering - histos.add("hYield", "Nch vs pT", kTH2F, {axisMultiplicity, axisPt}); - histos.add("hGlobalTracks", "hGlobalTracks", kTH1F, {axisMultiplicity}); + 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, {{nBinsZN, -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("NchVsOneParCorr", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(1)}]#GT (GeV/#it{c})", kTProfile, {{nBinsNch, minNch, maxNch}}); + histos.add("EtaVsPhi", ";#eta;#varphi", kTH2F, {{{axisEta}, {100, -0.1 * PI, +2.1 * PI}}}); + histos.add("ZposVsEta", "", kTProfile, {axisZpos}); + histos.add("sigma1Pt", ";;#sigma(p_{T})/p_{T};", kTProfile, {axisPt}); + histos.add("dcaXYvspT", ";DCA_{xy} (cm);;", kTH2F, {{{50, -1., 1.}, {axisPt}}}); + histos.add("GlobalMult_vs_FT0C", "GlobalMult_vs_FT0C", kTH2F, {axisMult, axisFT0CMult}); + histos.add("VtxZHist", "VtxZHist", kTH1D, {axisVtxZ}); + // event selection steps histos.add("eventSelectionSteps", "eventSelectionSteps", kTH1D, {axisEvent}); auto hstat = histos.get(HIST("eventSelectionSteps")); @@ -248,41 +241,23 @@ struct FlowZdcTask { xAxis->SetBinLabel(16, "Within TDC cut?"); xAxis->SetBinLabel(17, "Within ZEM cut?"); - histos.add("GlobalMult_vs_FT0C", "GlobalMult_vs_FT0C", kTH2F, {axisMult, axisFT0CMult}); - histos.add("VtxZHist", "VtxZHist", kTH1D, {axisVtxZ}); - 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("RealQHistogramZNA", "RealQHistogramZNA", kTH1F, {axisQZNA}); - histos.add("ImagQHistogramZNA", "ImagQHistogramZNA", kTH1F, {axisQZNA}); - histos.add("RealQHistogramZNC", "RealQHistogramZNC", kTH1F, {axisQZNA}); - histos.add("ImagQHistogramZNC", "ImagQHistogramZNC", kTH1F, {axisQZNA}); - - histos.add("Acorrelations", "Acorrelations", kTH2F, {{axisQZNA}, {axisQZNA}}); - histos.add("SPAngleZNA", "Spectator Plane Angle ZNA;Angle (radians);Entries", {HistType::kTH1F, {{100, -o2::constants::math::PI, o2::constants::math::PI}}}); - histos.add("SPAngleZNC", "Spectator Plane Angle ZNC;Angle (radians);Entries", {HistType::kTH1F, {{100, -o2::constants::math::PI, o2::constants::math::PI}}}); - - histos.add("RunningAverageCosPsiDiff", "Running Average of cos(psi) Differences;Running Average;Entries", {HistType::kTH1F, {{100, -1, 1}}}); - - histos.add("CosPsiDifferences", "Differences in cos(psi);cos(psiZNC) - cos(psiZNA);Entries", {HistType::kTH1F, {{100, -2, 2}}}); - histos.add("hSinDifferences", "Differences in sin(psi);sin(psiZNC) - sin(psiZNA);Entries", {HistType::kTH1F, {{100, -2, 2}}}); 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", "ZN energy side c", kTH1F, {axisEnergy}); - histos.add("ZNAenergy", "ZN energy side a", kTH1F, {axisEnergy}); - histos.add("ZPCenergy", "ZP energy side c", kTH1F, {axisEnergy}); - histos.add("ZPAenergy", "ZP energy side a", kTH1F, {axisEnergy}); - histos.add("ZNenergy", "common zn (a + c sides) energy", kTH1F, {axisEnergy}); - histos.add("ZPenergy", "common zp energy (a + c sides)", kTH1F, {axisEnergy}); - histos.add("hFT0CAmp", ";Amplitude;counts", kTH1F, {axisFT0CAmp}); - histos.add("hFT0AAmp", ";Amplitude;counts", kTH1F, {axisFT0AAmp}); - histos.add("hFT0MAmp", ";Amplitude;counts", kTH1F, {axisFT0MAmp}); + 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, {axisFT0CAmp, axisZN}); histos.add("hZPvsFT0CAmp", "ZP Energy vs FT0C Amplitude", kTH2F, {axisFT0CAmp, axisZP}); histos.add("hZNvsMult", "ZN Energy vs Multiplicity", kTH2F, {axisMultiplicity, axisZN}); @@ -290,17 +265,18 @@ struct FlowZdcTask { } if (doprocessQA) { - histos.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); - histos.add("ZNVsFT0A", ";T0A (#times 1/100);ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNVsFT0C", ";T0C (#times 1/100);ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZDC, -0.5, maxZn}}}); histos.add("ZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0, 0., 3000.}, {nBinsZDC, -0.5, maxZn}}}); - histos.add("ZN", ";ZNA+ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ZNA", ";ZNA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ZPA", ";ZPA;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); - histos.add("ZNC", ";ZNC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); - histos.add("ZPC", ";ZPC;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); + histos.add("ZNA", ";ZNA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); + histos.add("ZPA", ";ZPA Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); + histos.add("ZNC", ";ZNC Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); + histos.add("ZPC", ";ZPC Amplitude;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); + histos.add("ZNACommon", ";ZNA Common Energy;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); + histos.add("ZPACommon", ";ZPA Common Energy;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); + histos.add("ZNCCommon", ";ZNC Common Energy;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZn}}); + histos.add("ZPCCommon", ";ZPC Common Energy;Entries;", kTH1F, {{nBinsZDC, -0.5, maxZp}}); histos.add("ZNAVsZNC", ";ZNC;ZNA", kTH2F, {{{30, -0.5, maxZn}, {30, -0.5, maxZn}}}); histos.add("ZPAVsZPC", ";ZPC;ZPA;", kTH2F, {{{100, -0.5, maxZp}, {100, -0.5, maxZp}}}); histos.add("ZNAVsZPA", ";ZPA;ZNA;", kTH2F, {{{20, -0.5, maxZp}, {30, -0.5, maxZn}}}); @@ -322,7 +298,7 @@ struct FlowZdcTask { histos.add("ZEM2Vstdc", ";t_{ZEM2};ZEM2;", kTH2F, {{{30, -15., 15.}, {30, -0.5, 2000.5}}}); histos.add("debunch", ";t_{ZDC}-t_{ZDA};t_{ZDC}+t_{ZDA}", kTH2F, {{{nBinsTDC, minTdc, maxTdc}, {nBinsTDC, minTdc, maxTdc}}}); - histos.add("Nch", "Nch", kTH1F, {{nBinsNch, minNch, maxNch}}); + histos.add("GlbTracks", "Nch", kTH1F, {{nBinsNch, minNch, maxNch}}); histos.add("NchVsFT0C", ";T0C (#times 1/100, -3.3 < #eta < -2.1);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFT0, 0., 950.}, {nBinsNch, minNch, maxNch}}}); histos.add("NchVsFT0M", ";T0A+T0C (#times 1/100, -3.3 < #eta < -2.1 and 3.5 < #eta < 4.9);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFT0, 0., 3000.}, {nBinsNch, minNch, maxNch}}}); histos.add("NchVsFT0A", ";T0A (#times 1/100, 3.5 < #eta < 4.9);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsNch, minNch, maxNch}}}); @@ -336,7 +312,22 @@ struct FlowZdcTask { histos.add("ZNAVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZDC, minNch, maxZn}}}); 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("pZPAvsFT0Ccent", ";FT0C centrality;ZPA Amplitude", kTProfile, {{nBinsCent, minT0CcentCut, maxT0CcentCut}}); + histos.add("pZPCvsFT0Ccent", ";FT0C centrality;ZPC Amplitude", kTProfile, {{nBinsCent, minT0CcentCut, maxT0CcentCut}}); + histos.add("pZPAvsGlbTrack", ";Global Tracks (ITS + TPC);ZPA Amplitude", kTProfile, {{nBinsNch, minNch, maxNch}}); + histos.add("pZPCvsGlbTrack", ";Global Tracks (ITS + TPC);ZPC Amplitude", kTProfile, {{nBinsNch, minNch, maxNch}}); } + + ccdb->setURL("http://alice-ccdb.cern.ch"); + // Enabling object caching, otherwise each call goes to the CCDB server + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + // 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); } template bool isEventSelected(EventCuts const& col) @@ -422,9 +413,10 @@ struct FlowZdcTask { return true; } - void processQA(ColEvSels::iterator const& collision, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::FV0As const& /*fv0as*/, aod::FT0s const& /*ft0s*/, AodTracks const& tracks) + 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; } @@ -459,6 +451,21 @@ struct FlowZdcTask { float tZPC{zdc.timeZPC()}; float tZDCdif{tZNC + tZPC - tZNA - tZPA}; float tZDCsum{tZNC + tZPC + tZNA + tZPA}; + 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; + 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}; // TDC cut if (isTDCcut) { @@ -468,10 +475,6 @@ struct FlowZdcTask { histos.fill(HIST("hEventCounter"), EvCutLabel::Tdc); } - float aZEM1{zdc.amplitudeZEM1()}; - float aZEM2{zdc.amplitudeZEM2()}; - float sumZEMs{aZEM1 + aZEM2}; - // ZEM cut if (isZEMcut) { if (sumZEMs < zemCut) { @@ -480,68 +483,130 @@ struct FlowZdcTask { histos.fill(HIST("hEventCounter"), EvCutLabel::Zem); } - float znA = zdc.amplitudeZNA() / cfgCollisionEnergy; - float znC = zdc.amplitudeZNC() / cfgCollisionEnergy; - float zpA = zdc.amplitudeZPA() / cfgCollisionEnergy; - float zpC = zdc.amplitudeZPC() / cfgCollisionEnergy; - - 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]; float sumZNA = (zdc.energySectorZNA())[0] + (zdc.energySectorZNA())[1] + (zdc.energySectorZNA())[2] + (zdc.energySectorZNA())[3]; float sumZPC = (zdc.energySectorZPC())[0] + (zdc.energySectorZPC())[1] + (zdc.energySectorZPC())[2] + (zdc.energySectorZPC())[3]; float sumZPA = (zdc.energySectorZPA())[0] + (zdc.energySectorZPA())[1] + (zdc.energySectorZPA())[2] + (zdc.energySectorZPA())[3]; - int itsTracks = 0, glbTracks = 0; float et = 0., meanpt = 0.; + int itsTracks = 0, glbTracks = 0; for (const auto& track : tracks) { - if (track.hasITS() && track.itsNCls() >= minITSnCls) { + if (track.hasITS()) { itsTracks++; } // Track Selection - if (track.isGlobalTrack()) { + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { continue; } 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("ExcludedEvtVsNch"), glbTracks); + } else { + skipEvent = true; + } + } else { + skipEvent = true; + } + if (!skipEvent) { + return; + } + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + 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()); + et += std::sqrt(std::pow(track.pt(), 2.) + std::pow(o2::constants::physics::MassPionCharged, 2.)); + meanpt += track.pt(); + } histos.fill(HIST("zPos"), collision.posZ()); histos.fill(HIST("T0Ccent"), collision.centFT0C()); - histos.fill(HIST("ZNCcvsZNCsum"), sumZNC / cfgCollisionEnergy, zdc.energyCommonZNC() / cfgCollisionEnergy); histos.fill(HIST("ZNAcvsZNAsum"), sumZNA / cfgCollisionEnergy, zdc.energyCommonZNA() / cfgCollisionEnergy); histos.fill(HIST("ZPCcvsZPCsum"), sumZPC / cfgCollisionEnergy, zdc.energyCommonZPC() / cfgCollisionEnergy); histos.fill(HIST("ZPAcvsZPAsum"), sumZPA / cfgCollisionEnergy, zdc.energyCommonZPA() / cfgCollisionEnergy); + histos.fill(HIST("GlbTracks"), glbTracks); - histos.fill(HIST("Nch"), glbTracks); + // Neutron ZDC histos.fill(HIST("ZNA"), znA); histos.fill(HIST("ZNC"), znC); - histos.fill(HIST("ZPA"), zpA); - histos.fill(HIST("ZPC"), zpC); + histos.fill(HIST("ZNACommon"), commonSumZna); + histos.fill(HIST("ZNCCommon"), commonSumZnc); histos.fill(HIST("ZNASector"), sumZNA / cfgCollisionEnergy); histos.fill(HIST("ZNCSector"), sumZNC / cfgCollisionEnergy); - histos.fill(HIST("ZPASector"), sumZPA / cfgCollisionEnergy); - histos.fill(HIST("ZPCSector"), sumZPC / cfgCollisionEnergy); histos.fill(HIST("ZN"), znA + znC); - 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("ZNVsZEM"), sumZEMs, sumZNs); histos.fill(HIST("ZNCVstdc"), tZNC, znC); histos.fill(HIST("ZNAVstdc"), tZNA, znA); histos.fill(HIST("ZPCVstdc"), tZPC, zpC); - histos.fill(HIST("ZPAVstdc"), tZPA, zpA); - histos.fill(HIST("ZEM1Vstdc"), tZEM1, aZEM1); - histos.fill(HIST("ZEM2Vstdc"), tZEM2, aZEM2); - histos.fill(HIST("debunch"), tZDCdif, tZDCsum); - histos.fill(HIST("ZNVsFT0A"), aT0A / 100., sumZNs); histos.fill(HIST("ZNVsFT0C"), aT0C / 100., sumZNs); histos.fill(HIST("ZNVsFT0M"), (aT0A + aT0C) / 100., sumZNs); + // Proton ZDC + if (!isOneNeutronFound || znA >= oneNeutron) { + histos.fill(HIST("ZPA"), zpA); + histos.fill(HIST("ZPACommon"), commonSumZpa); + histos.fill(HIST("ZPASector"), sumZPA / cfgCollisionEnergy); + histos.fill(HIST("ZPAVstdc"), tZPA, zpA); + histos.fill(HIST("ZPAvsCent"), cent, zpA); + if (std::isfinite(zpA) && !std::isnan(zpA) && + cent >= minT0CcentCut && cent < maxT0CcentCut && glbTracks >= minNch && glbTracks < maxNch) { + histos.fill(HIST("pZPAvsFT0Ccent"), cent, zpA); + histos.fill(HIST("pZPAvsGlbTrack"), glbTracks, zpA); + } + } + if (!isOneNeutronFound || znC >= oneNeutron) { + histos.fill(HIST("ZPC"), zpC); + histos.fill(HIST("ZPCCommon"), commonSumZpc); + histos.fill(HIST("ZPCSector"), sumZPC / cfgCollisionEnergy); + histos.fill(HIST("ZPCvsCent"), cent, zpC); + if (std::isfinite(zpC) && !std::isnan(zpC) && + cent >= minT0CcentCut && cent < maxT0CcentCut && glbTracks >= minNch && glbTracks < maxNch) { + histos.fill(HIST("pZPCvsFT0Ccent"), cent, zpC); + histos.fill(HIST("pZPCvsGlbTrack"), glbTracks, zpC); + } + } + + // ZDC Correlations + 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("ZEM1Vstdc"), tZEM1, aZEM1); + histos.fill(HIST("ZEM2Vstdc"), tZEM2, aZEM2); + histos.fill(HIST("debunch"), tZDCdif, tZDCsum); + if (sumZNs > znBasedCut) { return; } @@ -561,55 +626,6 @@ struct FlowZdcTask { } } - void processQVector(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracks const& tracks, BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcsData*/, aod::ZDCMults const& /*zdcMults*/) - { - if (!isEventSelected(collision)) { - return; - } - histos.fill(HIST("eventCounter"), 0.5); - histos.fill(HIST("centHistogram"), collision.centFT0C()); - const auto& tracksGrouped = tracksIUWithTPC->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - const int multTPC = tracksGrouped.size(); - const auto cent = collision.centFT0C(); - int globalTracks = tracks.size(); - if (globalTracks < 1) - return; - // this is the q vector for the TPC data. it is a complex function - double qTpcReal = 0.0; // Initialize qTPC_real - double qTpcIm = 0.0; // init qTPC_imaginary - std::complex qTPC(0, 0); // Starting with a q-vector of zero - int nTot{0}; // Tracks are already filtered with GlobalTrack || GlobalTrackSDD - for (const auto& track : tracks) { - double phi = track.phi(); - nTot++; - histos.fill(HIST("etaHistogram"), track.eta()); - histos.fill(HIST("phiHistogram"), track.phi()); - histos.fill(HIST("ptHistogram"), track.pt()); - qTPC += std::complex(std::cos(2.0 * phi), std::sin(2.0 * phi)); - } // end track loop 1 - double pT{0}; - for (const auto& track : tracks) { - if (track.tpcNClsCrossedRows() < minTpcNcrossedRows) - continue; - if (std::fabs(track.dcaXY()) > cfgCutDCAxy) - continue; - pT = track.pt(); - pT++; - } // end track loop 2 - histos.fill(HIST("multvsCent"), cent, nTot); - histos.fill(HIST("hYield"), nTot, pT); - histos.fill(HIST("multHistogram"), nTot); - qTpcReal = qTPC.real() / nTot; // normalize these vectors by the total number of particles - qTpcIm = qTPC.imag() / nTot; - - histos.fill(HIST("REqHistogram"), qTpcReal); - histos.fill(HIST("IMqHistogram"), qTpcIm); - - histos.fill(HIST("TPCmultiplicity"), multTPC); - histos.fill(HIST("hGlobalTracks"), globalTracks); - - histos.fill(HIST("revsimag"), qTpcReal, qTpcIm); - } void processZdcCollAssoc( AodCollisions::iterator const& collision, AodTracks const& tracks, @@ -620,10 +636,13 @@ struct FlowZdcTask { 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; - const auto& foundBC = collision.foundBC_as(); if (collision.has_foundFT0()) { auto ft0 = collision.foundFT0(); for (const auto& amplitude : ft0.amplitudeA()) { @@ -633,66 +652,168 @@ struct FlowZdcTask { ft0cAmp += amplitude; } } - histos.fill(HIST("hFT0AAmp"), ft0aAmp); - histos.fill(HIST("hFT0CAmp"), ft0cAmp); - double ft0mAmp = ft0aAmp + ft0cAmp; - histos.fill(HIST("hFT0MAmp"), ft0mAmp); - if (foundBC.has_zdc()) { - const auto& zdcread = foundBC.zdc(); - const auto cent = collision.centFT0C(); - - // ZDC data and histogram filling - histos.get(HIST("ZNAcoll"))->Fill(zdcread.amplitudeZNA()); - histos.get(HIST("ZNCcoll"))->Fill(zdcread.amplitudeZNC()); - 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()); - - float sumZNC = (zdcread.energySectorZNC())[0] + (zdcread.energySectorZNC())[1] + (zdcread.energySectorZNC())[2] + (zdcread.energySectorZNC())[3]; - float sumZNA = (zdcread.energySectorZNA())[0] + (zdcread.energySectorZNA())[1] + (zdcread.energySectorZNA())[2] + (zdcread.energySectorZNA())[3]; - float sumZPC = (zdcread.energySectorZPC())[0] + (zdcread.energySectorZPC())[1] + (zdcread.energySectorZPC())[2] + (zdcread.energySectorZPC())[3]; - float sumZPA = (zdcread.energySectorZPA())[0] + (zdcread.energySectorZPA())[1] + (zdcread.energySectorZPA())[2] + (zdcread.energySectorZPA())[3]; - float sumZDC = sumZPA + sumZPC + sumZNA + sumZNC; - float sumZEM = zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(); - // ZEM cut - if (isZEMcut) { - if (sumZEM < zemCut) { - return; - } - } - // common energies - float commonSumZnc = (zdcread.energyCommonZNC()); - float commonSumZna = (zdcread.energyCommonZNA()); - float commonSumZpc = (zdcread.energyCommonZPC()); - float commonSumZpa = (zdcread.energyCommonZPA()); - float sumZN = (sumZNC) + (sumZNA); - float sumZP = (sumZPC) + (sumZPA); - - 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("hNchvsNPV"), collision.multNTracksPVeta1(), nTot); - - float ratioZN = sumZNC / sumZNA; - float ratioZP = sumZPC / sumZPA; - pZNratiovscent->Fill(cent, ratioZN); - pZPratiovscent->Fill(cent, ratioZP); - pZNvsFT0Ccent->Fill(cent, sumZN); - pZPvsFT0Ccent->Fill(cent, sumZP); - - histos.get(HIST("ZDC_energy_vs_ZEM"))->Fill(sumZEM, sumZDC); + 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(); + float znC = zdcread.amplitudeZNC(); + float zpA = zdcread.amplitudeZPA(); + float zpC = zdcread.amplitudeZPC(); + 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]; + float sumZNA = (zdcread.energySectorZNA())[0] + (zdcread.energySectorZNA())[1] + (zdcread.energySectorZNA())[2] + (zdcread.energySectorZNA())[3]; + float sumZPC = (zdcread.energySectorZPC())[0] + (zdcread.energySectorZPC())[1] + (zdcread.energySectorZPC())[2] + (zdcread.energySectorZPC())[3]; + float sumZPA = (zdcread.energySectorZPA())[0] + (zdcread.energySectorZPA())[1] + (zdcread.energySectorZPA())[2] + (zdcread.energySectorZPA())[3]; + float sumZDC = sumZPA + sumZPC + sumZNA + sumZNC; + float sumZEM = zdcread.amplitudeZEM1() + zdcread.amplitudeZEM2(); + znA /= cfgCollisionEnergy; + znC /= cfgCollisionEnergy; + zpA /= cfgCollisionEnergy; + zpC /= cfgCollisionEnergy; + 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); + } + // ZEM cut + if (isZEMcut) { + if (sumZEM < zemCut) { + return; + } + } + // common energies + float commonSumZnc = (zdcread.energyCommonZNC()); + float commonSumZna = (zdcread.energyCommonZNA()); + float commonSumZpc = (zdcread.energyCommonZPC()); + float commonSumZpa = (zdcread.energyCommonZPA()); + 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); + } 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); + } + } + + 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("hNchvsNPV"), collision.multNTracksPVeta1(), nTot); + 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); + + float ratioZN = sumZNC / sumZNA; + float ratioZP = sumZPC / sumZPA; + pZNratiovscent->Fill(cent, ratioZN); + pZPratiovscent->Fill(cent, ratioZP); + pZNvsFT0Ccent->Fill(cent, sumZN); + pZPvsFT0Ccent->Fill(cent, sumZP); + histos.get(HIST("ZDC_energy_vs_ZEM"))->Fill(sumZEM, sumZDC); } void processCorrelation(CollisionDataTable::iterator const& collision, FilTrackDataTable const& tracks) @@ -714,9 +835,8 @@ struct FlowZdcTask { histos.fill(HIST("GlobalMult_vs_FT0C"), nchTracks, collision.multFT0C()); } - PROCESS_SWITCH(FlowZdcTask, processZdcCollAssoc, "Processing ZDC w. collision association", true); + PROCESS_SWITCH(FlowZdcTask, processZdcCollAssoc, "Processing ZDC w. collision association", false); PROCESS_SWITCH(FlowZdcTask, processQA, "Process QA", true); - PROCESS_SWITCH(FlowZdcTask, processQVector, "Process before recentering", true); PROCESS_SWITCH(FlowZdcTask, processCorrelation, "Process correlations", true); }; // end of struct function diff --git a/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx b/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx index 8f6db97fde8..de9c43aeb88 100644 --- a/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx +++ b/PWGCF/Flow/Tasks/resonancesGfwFlow.cxx @@ -13,50 +13,49 @@ /// \brief PID flow for resonances using the generic framework /// \author Preet Bhanjan Pati -#include -#include -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/StepTHn.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" - -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" +#include "PWGCF/GenericFramework/Core/FlowContainer.h" #include "PWGCF/GenericFramework/Core/GFW.h" +#include "PWGCF/GenericFramework/Core/GFWConfig.h" #include "PWGCF/GenericFramework/Core/GFWCumulant.h" -#include "PWGCF/GenericFramework/Core/FlowContainer.h" +#include "PWGCF/GenericFramework/Core/GFWPowerArray.h" #include "PWGCF/GenericFramework/Core/GFWWeights.h" #include "PWGCF/GenericFramework/Core/GFWWeightsList.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "ReconstructionDataFormats/Track.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/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.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 "Math/Vector4D.h" +#include #include #include -#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -65,37 +64,120 @@ using namespace std; namespace { -std::shared_ptr refC22Boot[10]; -std::shared_ptr refC24Boot[10]; - -std::shared_ptr phiD22FPtBoot[10]; -std::shared_ptr phiD22BPtBoot[10]; -std::shared_ptr phiD24FPtBoot[10]; -std::shared_ptr phiD24BPtBoot[10]; - -std::shared_ptr k0D22FPtBoot[10]; -std::shared_ptr k0D22BPtBoot[10]; -std::shared_ptr k0D24FPtBoot[10]; -std::shared_ptr k0D24BPtBoot[10]; - -std::shared_ptr lambdaD22FPtBoot[10]; -std::shared_ptr lambdaD22BPtBoot[10]; -std::shared_ptr lambdaD24FPtBoot[10]; -std::shared_ptr lambdaD24BPtBoot[10]; - -std::shared_ptr anLambdaD22FPtBoot[10]; -std::shared_ptr anLambdaD22BPtBoot[10]; -std::shared_ptr anLambdaD24FPtBoot[10]; -std::shared_ptr anLambdaD24BPtBoot[10]; +std::vector> refV2; +std::vector> phiV2; +std::vector> lsPhiV2; +std::vector> k0V2; +std::vector> lambdaV2; + +std::vector>> refBoot; +std::vector>> phiBoot; +std::vector>> lsPhiBoot; +std::vector>> k0Boot; +std::vector>> lambdaBoot; } // namespace #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; +namespace o2::analysis::genericframework +{ +GFWRegions regions; +GFWCorrConfigs configs; +} // namespace o2::analysis::genericframework + +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; +} + +using namespace o2::analysis::genericframework; + +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 ResonancesGfwFlow { + o2::aod::ITSResponse itsResponse; Service ccdb; - Configurable noLaterThan{"noLaterThan", 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"}; + enum OutputSpecies { + K0 = 0, + LAMBDA = 1, + PHI = 2, + ANLAMBDA = 3, + REF = 4, + kCount_OutputSpecies + }; + enum Particles { + PIONS, + KAONS, + PROTONS + }; + enum ParticleCuts { + kCosPA = 0, + kMassMin, + kMassMax, + kPosTrackPt, + kNegTrackPt, + kDCAPosToPVMin, + kDCANegToPVMin, + kLifeTime, + kRadiusMin, + kRadiusMax, + kRapidity + }; + enum ParticleSwitches { + kUseParticle = 0, + kUseCosPA, + kMassBins, + kDCABetDaug, + kUseProperLifetime, + kUseV0Radius + }; + enum EventCutTypes { + kFilteredEvents = 0, + kAfterSel8, + kUseNoTimeFrameBorder, + kUseNoITSROFrameBorder, + kUseNoSameBunchPileup, + kUseGoodZvtxFT0vsPV, + kUseNoCollInTimeRangeStandard, + kUseGoodITSLayersAll, + kUseNoCollInRofStandard, + kUseNoHighMultCollInPrevRof, + kUseOccupancy, + kUseMultCorrCut, + kUseT0AV0ACut, + kUseVertexITSTPC, + kUseTVXinTRD + }; + enum TrackCutTypes { + kFilteredTracks = 0, + kUseGlobalTracks, + kUsePvContributor, + kItsClustersCut, + kHasTpcSignal, + kTpcClustersCut, + kTpcCrossedRowsCut + }; + O2_DEFINE_CONFIGURABLE(cfgCutVertex, float, 10.0f, "Accepted z-vertex range") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMin, float, 0.2f, "Minimal pT for poi tracks") O2_DEFINE_CONFIGURABLE(cfgCutPtPOIMax, float, 10.0f, "Maximal pT for poi tracks") @@ -103,32 +185,17 @@ struct ResonancesGfwFlow { 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(cfgTpcCluster, int, 70, "Number of TPC clusters") - O2_DEFINE_CONFIGURABLE(cfgTpcNsigmaCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") - O2_DEFINE_CONFIGURABLE(cfgTofNsigmaCut, float, 3.0f, "TOF N-sigma cut for pions, kaons, protons") + O2_DEFINE_CONFIGURABLE(cfgTpcCluster, int, 50, "Number of TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgTpcCrossRows, int, 70, "Number of TPC clusters") + O2_DEFINE_CONFIGURABLE(cfgTpcCut, float, 3.0f, "TPC N-sigma cut for pions, kaons, protons") O2_DEFINE_CONFIGURABLE(cfgTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") - O2_DEFINE_CONFIGURABLE(cfgITScluster, int, 0, "Number of ITS cluster") - O2_DEFINE_CONFIGURABLE(cfgCutOccupancy, int, 3000, "Occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgITScluster, int, 5, "Number of ITS cluster") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMin, int, 0, "Minimum occupancy cut") + O2_DEFINE_CONFIGURABLE(cfgCutOccupancyMax, int, 2000, "Maximum occupancy cut") O2_DEFINE_CONFIGURABLE(cfgUseGlobalTrack, bool, true, "use Global track") O2_DEFINE_CONFIGURABLE(cfgFakeKaonCut, float, 0.1f, "Maximum difference in measured momentum and TPC inner ring momentum of particle") - O2_DEFINE_CONFIGURABLE(cfgRapidityCut, float, 0.5, "Rapidity cut for the reconstructed particles") - O2_DEFINE_CONFIGURABLE(cfgUseCosPA, bool, false, "Use Pointing angle for resonances") - O2_DEFINE_CONFIGURABLE(cfgUseV0Radius, bool, true, "Use V0 radius for particle identification") - O2_DEFINE_CONFIGURABLE(cfgLambdaRadiusMin, float, 0.5f, "Minimum Lambda radius in cm") - O2_DEFINE_CONFIGURABLE(cfgLambdaRadiusMax, float, 200.0f, "Maximum Lambda radius in cm") - O2_DEFINE_CONFIGURABLE(cfgK0RadiusMin, float, 0.5f, "Minimum K0 radius in cm") - O2_DEFINE_CONFIGURABLE(cfgK0RadiusMax, float, 200.0f, "Maximum K0 radius in cm") - O2_DEFINE_CONFIGURABLE(cfgUseProperLifetime, bool, false, "Use proper lifetime for particle identification") - O2_DEFINE_CONFIGURABLE(cfgK0LifeTime, float, 20.0f, "Maximum lifetime for K0 in cm") - O2_DEFINE_CONFIGURABLE(cfgLambdaLifeTime, float, 30.0f, "Maximum lifetime for Lambda in cm") O2_DEFINE_CONFIGURABLE(cfgCutDCAxy, float, 2.0f, "DCAxy range for tracks") O2_DEFINE_CONFIGURABLE(cfgCutDCAz, float, 2.0f, "DCAz range for tracks") - O2_DEFINE_CONFIGURABLE(cfgDCALambdaPosToPVMin, float, 0.1f, "minimum DCA to PV for Lambda positive track") - O2_DEFINE_CONFIGURABLE(cfgDCALambdaNegToPVMin, float, 0.25f, "minimum DCA to PV for Lambda negative track") - O2_DEFINE_CONFIGURABLE(cfgDCAK0PosToPVMin, float, 0.06f, "minimum DCA to PV for K0 positive track") - O2_DEFINE_CONFIGURABLE(cfgDCAK0NegToPVMin, float, 0.06f, "minimum DCA to PV for K0 negative track") - O2_DEFINE_CONFIGURABLE(cfgUseMCCLambda, bool, false, "Use mass cross check for lambda") - O2_DEFINE_CONFIGURABLE(cfgUseMCCK0, bool, false, "Use mass cross check for K0") O2_DEFINE_CONFIGURABLE(cfgOutputNUAWeights, bool, true, "Fill and output NUA weights") O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") O2_DEFINE_CONFIGURABLE(cfgUseWeightPhiEtaVtxz, bool, true, "Use Phi, Eta, VertexZ dependent NUA weights") @@ -137,42 +204,22 @@ struct ResonancesGfwFlow { O2_DEFINE_CONFIGURABLE(cfgNbootstrap, int, 10, "Number of subsamples") O2_DEFINE_CONFIGURABLE(cfgUseBootStrap, bool, true, "Use bootstrap for error estimation") O2_DEFINE_CONFIGURABLE(cfgTrackDensityCorrUse, bool, true, "Use track density efficiency correction") - O2_DEFINE_CONFIGURABLE(cfgUsePhi, bool, true, "Analyze Phi") - O2_DEFINE_CONFIGURABLE(cfgUseK0, bool, true, "Analyze K0") - O2_DEFINE_CONFIGURABLE(cfgUseLambda, bool, true, "Analyze Lambda") - - enum OutputSpecies { - Ref = 0, - K0 = 1, - Lambda = 2, - AnLambda = 3, - Phi = 4, - kCount_OutputSpecies - }; - - struct : ConfigurableGroup { - Configurable> cfgCosPAs{"cfgCosPAs", std::vector{0.97f, 0.995f, 0.04f}, "Minimum Pointing angle for resonances [K0, Lambda, Phi]"}; - Configurable> cfgDCABetDaug{"cfgDCABetDaug", std::vector{1, 1, 1}, "Maximum DCA between resonance daughters [K0, Lambda, Phi]"}; - Configurable> cfgMassMin{"cfgMassMin", std::vector{0.44f, 1.1f, 0.99f}, "Minimum mass for resonances [K0, Lambda, Phi]"}; - Configurable> cfgMassMax{"cfgMassMax", std::vector{0.56f, 1.16f, 1.06f}, "Maximum mass for resonances [K0, Lambda, Phi]"}; - Configurable> cfgNMassBins{"cfgNMassBins", std::vector{70, 70, 70}, "Invariant mass bins for resonances [K0, Lambda, Phi]"}; - Configurable> cfgMccCut{"cfgMccCut", std::vector{0.005f, 0.01f, 0.0f}, "MCC cut for resonances [K0, Lambda, Phi]"}; - Configurable> cfgPosTrackPt{"cfgPosTrackPt", std::vector{0.15f, 0.15f, 0.15f}, "Pt cut for positive track of resonances [K0, Lambda, Phi]"}; - Configurable> cfgNegTrackPt{"cfgNegTrackPt", std::vector{0.15f, 0.15f, 0.15f}, "Pt cut for negative track of resonances [K0, Lambda, Phi]"}; - } resoCuts; + O2_DEFINE_CONFIGURABLE(cfgV0AT0Acut, int, 5, "V0AT0A cut") + 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(cfgUseStrictPID, bool, true, "Use strict PID cuts for TPC") + O2_DEFINE_CONFIGURABLE(cfgUseAsymmetricPID, bool, false, "Use asymmetric PID cuts") + O2_DEFINE_CONFIGURABLE(cfgUseItsPID, bool, true, "Use ITS PID for particle identification") 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> cfgUseEventCuts{"cfgUseEventCuts", std::vector{1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0}, "Switch for various event cuts [Filtered Events, Sel8, kNoTimeFrameBorder, kNoITSROFrameBorder, kNoSameBunchPileup, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kIsGoodITSLayersAll, kNoCollInRofStandard, kNoHighMultCollInPrevRof, Occupancy, Multiplicity correlation, T0AV0A 3 sigma cut, kIsVertexITSTPC, kTVXinTRD]"}; + 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"}; - // Reading in the configurables - std::vector vMassMin = resoCuts.cfgMassMin; - std::vector vMassMax = resoCuts.cfgMassMax; - std::vector vMassBins = resoCuts.cfgNMassBins; - std::vector vCosPAs = resoCuts.cfgCosPAs; - std::vector vDCABetDaug = resoCuts.cfgDCABetDaug; - std::vector vMccCut = resoCuts.cfgMccCut; - std::vector vPosTrackPt = resoCuts.cfgPosTrackPt; - std::vector vNegTrackPt = resoCuts.cfgNegTrackPt; + Configurable cfgRegions{"cfgRegions", {{"refN08", "refP08", "refFull", "poiNphi", "poiPphi", "poifullphi", "olNphi", "olPphi", "olfullphi", "poiNk0", "poiPk0", "poifullk0", "olNk0", "olPk0", "olfullk0", "poiNlam", "poiPlam", "poifulllam", "olNlam", "olPlam", "olfulllam", "poiNantilam", "poiPantilam", "poifullantilam", "olNantilam", "olPantilam", "olfullantilam"}, {-0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8, -0.8, 0.4, -0.8}, {-0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8, -0.4, 0.8, 0.8}, {0, 0, 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, 2, 2, 2, 32, 32, 32, 4, 4, 4, 64, 64, 64, 8, 8, 8, 128, 128, 128, 16, 16, 16, 256, 256, 256}}, "Configurations for GFW regions"}; + Configurable cfgCorrConfig{"cfgCorrConfig", {{"refN08 {2} refP08 {-2}", "refN08 {2 2} refP08 {-2 -2}", "poiNphi refN08 | olNphi {2} refP08 {-2}", "poiNphi refN08 | olNphi {2 2} refP08 {-2 -2}", "poiPphi refP08 | olPphi {2} refN08 {-2}", "poiPphi refP08 | olPphi {2 2} refN08 {-2 -2}", "poiNk0 refN08 | olNk0 {2} refP08 {-2}", "poiNk0 refN08 | olNk0 {2 2} refP08 {-2 -2}", "poiPk0 refP08 | olPk0 {2} refN08 {-2}", "poiPk0 refP08 | olPk0 {2 2} refN08 {-2 -2}", "poiNlam refN08 | olNlam {2} refP08 {-2}", "poiNlam refN08 | olNlam {2 2} refP08 {-2 -2}", "poiPlam refP08 | olPlam {2} refN08 {-2}", "poiPlam refP08 | olPlam {2 2} refN08 {-2 -2}", "poiNantilam refN08 | olNantilam {2} refP08 {-2}", "poiNantilam refN08 | olNantilam {2 2} refP08 {-2 -2}", "poiPantilam refP08 | olPantilam {2} refN08 {-2}", "poiPantilam refP08 | olPantilam {2 2} refN08 {-2 -2}"}, {"Ref08Gap22", "Ref08Gap24", "PhiF08Gap22", "PhiF08Gap24", "PhiB08Gap22", "PhiB08Gap24", "K0F08Gap22", "K0F08Gap24", "K0B08Gap22", "K0B08Gap24", "LamF08Gap22", "LamF08Gap24", "LamB08Gap22", "LamB08Gap24", "AnLamF08Gap22", "AnLamF08Gap24", "AnLamB08Gap22", "AnLamB08Gap24"}, {0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, "Configurations for each correlation to calculate"}; // Defining configurable axis ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for histograms"}; @@ -183,11 +230,6 @@ struct ResonancesGfwFlow { ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {80, -5, 5}, "nsigmaTPC axis"}; ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {80, -5, 5}, "nsigmaTOF axis"}; ConfigurableAxis axisParticles{"axisParticles", {3, 0, 3}, "axis for different hadrons"}; - ConfigurableAxis axisPhiMass{"axisPhiMass", {vMassBins[Phi - 2], vMassMin[Phi - 2], vMassMax[Phi - 2]}, "axis for invariant mass distibution for Phi"}; - ConfigurableAxis axisK0Mass{"axisK0Mass", {vMassBins[K0 - 1], vMassMin[K0 - 1], vMassMax[K0 - 1]}, "axis for invariant mass distibution for K0"}; - ConfigurableAxis axisLambdaMass{"axisLambdaMass", {vMassBins[Lambda - 1], vMassMin[Lambda - 1], vMassMax[Lambda - 1]}, "axis for invariant mass distibution for Lambda"}; - ConfigurableAxis axisTPCsignal{"axisTPCsignal", {10000, 0, 1000}, "axis for TPC signal"}; - ConfigurableAxis axisTOFsignal{"axisTOFsignal", {10000, 0, 1000}, "axis for TOF signal"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter trackFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz) && (nabs(aod::track::eta) < cfgCutEta) && (aod::track::pt > cfgCutPtPOIMin) && (aod::track::pt < cfgCutPtPOIMax) && ((requireGlobalTrackInFilter()) || (aod::track::isGlobalTrackSDD == (uint8_t) true)) && (aod::track::tpcChi2NCl < cfgCutChi2prTPCcls); @@ -202,6 +244,13 @@ struct ResonancesGfwFlow { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + std::array, 3> resoCutVals; + std::array, 3> resoSwitchVals; + std::array tofNsigmaCut; + std::array itsNsigmaCut; + std::array tpcNsigmaCut; + std::vector eventCuts; + GFW* fGFW = new GFW(); std::vector corrconfigs; TAxis* fPtAxis; @@ -220,52 +269,135 @@ struct ResonancesGfwFlow { TF1* funcV3; TF1* funcV4; + // Additional Event selection cuts - Copy from flowGenericFramework.cxx + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fMultMultPVCut = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + void init(InitContext const&) { + int64_t noLaterThan = std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(); + // Initilizing ccdb ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); - ccdb->setCreatedNotAfter(noLaterThan.value); + ccdb->setCreatedNotAfter(noLaterThan); + + LOGF(info, "flowGenericFramework::init()"); + regions.SetNames(cfgRegions->GetNames()); + regions.SetEtaMin(cfgRegions->GetEtaMin()); + regions.SetEtaMax(cfgRegions->GetEtaMax()); + regions.SetpTDifs(cfgRegions->GetpTDifs()); + regions.SetBitmasks(cfgRegions->GetBitmasks()); + configs.SetCorrs(cfgCorrConfig->GetCorrs()); + configs.SetHeads(cfgCorrConfig->GetHeads()); + configs.SetpTDifs(cfgCorrConfig->GetpTDifs()); + configs.SetpTCorrMasks(cfgCorrConfig->GetpTCorrMasks()); + regions.Print(); + configs.Print(); + + projectMatrix(nSigmas->getData(), tpcNsigmaCut, tofNsigmaCut, itsNsigmaCut); + readMatrix(resonanceCuts->getData(), resoCutVals); + readMatrix(resonanceSwitches->getData(), resoSwitchVals); + eventCuts = cfgUseEventCuts; AxisSpec singleCount = {1, 0, 1}; + AxisSpec axisK0Mass = {resoSwitchVals[K0][kMassBins], resoCutVals[K0][kMassMin], resoCutVals[K0][kMassMax]}; + AxisSpec axisLambdaMass = {resoSwitchVals[LAMBDA][kMassBins], resoCutVals[LAMBDA][kMassMin], resoCutVals[LAMBDA][kMassMax]}; + AxisSpec axisPhiMass = {resoSwitchVals[PHI][kMassBins], resoCutVals[PHI][kMassMin], resoCutVals[PHI][kMassMax]}; histos.add("hVtxZ", "", {HistType::kTH1D, {axisVertex}}); histos.add("hMult", "", {HistType::kTH1D, {{3000, 0.5, 3000.5}}}); histos.add("hCent", "", {HistType::kTH1D, {{90, 0, 90}}}); - histos.add("Refc22", "", {HistType::kTProfile, {axisMultiplicity}}); - histos.add("Refc24", "", {HistType::kTProfile, {axisMultiplicity}}); + refBoot.resize(cfgNbootstrap); + phiBoot.resize(cfgNbootstrap); + lsPhiBoot.resize(cfgNbootstrap); + k0Boot.resize(cfgNbootstrap); + lambdaBoot.resize(cfgNbootstrap); + + // Defining histograms to store correlations + for (auto i = 0; i < configs.GetSize(); ++i) { + if (resoSwitchVals[PHI][kUseParticle] && configs.GetHeads()[i].starts_with("Phi")) { + phiV2.push_back(histos.add(Form("h%spt", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + phiBoot[j].push_back(histos.add(Form("BootStrap/h%spt_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of phi loop + + if (cfgUseLsPhi && configs.GetHeads()[i].starts_with("LsPhi")) { + lsPhiV2.push_back(histos.add(Form("h%spt", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + phiBoot[j].push_back(histos.add(Form("BootStrap/h%spt_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}})); + } + } // end of bootstrap condition + } + if (resoSwitchVals[K0][kUseParticle] && configs.GetHeads()[i].starts_with("K0")) { + k0V2.push_back(histos.add(Form("h%spt", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + k0Boot[j].push_back(histos.add(Form("BootStrap/h%spt_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of K0 loop + + if (resoSwitchVals[LAMBDA][kUseParticle] && (configs.GetHeads()[i].starts_with("Lam") || configs.GetHeads()[i].starts_with("AnLam"))) { + lambdaV2.push_back(histos.add(Form("h%spt", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + lambdaBoot[j].push_back(histos.add(Form("BootStrap/h%spt_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of lambda loop + + if (configs.GetHeads()[i].starts_with("Ref")) { + refV2.push_back(histos.add(Form("h%s", configs.GetHeads()[i].c_str()), "", {HistType::kTProfile, {axisMultiplicity}})); + if (cfgUseBootStrap) { + for (int j = 0; j < cfgNbootstrap; ++j) { + refBoot[j].push_back(histos.add(Form("BootStrap/h%s_boot_%d", configs.GetHeads()[i].c_str(), j), "", {HistType::kTProfile, {axisMultiplicity}})); + } + } // end of bootstrap condition + } // end of ref loop + + } // end of configs loop - if (cfgUsePhi) { - histos.add("KaplusTPC", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("KaminusTPC", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("KaplusTOF", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("KaminusTOF", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + if (cfgUseLsPhi) { + histos.add("hLsPhiMass_sparse", "", {HistType::kTHnSparseD, {{axisPhiMass, axisPt, axisMultiplicity}}}); + } + + if (resoSwitchVals[PHI][kUseParticle]) { + histos.add("KaPlusTPC", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("KaMinusTPC", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("KaPlusTOF", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("KaMinusTOF", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hPhiPhi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hPhiEta", "", {HistType::kTH1D, {axisEta}}); histos.add("hPhiMass_sparse", "", {HistType::kTHnSparseD, {{axisPhiMass, axisPt, axisMultiplicity}}}); - histos.add("hPhimassSparse_RD", "", {HistType::kTHnSparseD, {{axisPhiMass, axisPt, axisMultiplicity}}}); - histos.add("Phid22Fpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - histos.add("Phid24Fpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - histos.add("Phid22Bpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - histos.add("Phid24Bpt", "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); + histos.add("hPhiCount", "Number of Phi;; Count", {HistType::kTH1D, {{5, 0, 5}}}); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(1, "Phi candidates"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(2, "Daughter track selection"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(3, "Fake Kaon"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(4, "CosPA"); + histos.get(HIST("hPhiCount"))->GetXaxis()->SetBinLabel(5, "Rapidity cut"); } - if (cfgUseK0) { - histos.add("PlusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("MinusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("PlusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("MinusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + if (resoSwitchVals[K0][kUseParticle]) { + histos.add("PiPlusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiPlusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_K0", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hK0Phi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hK0Eta", "", {HistType::kTH1D, {axisEta}}); histos.add("hK0Mass_sparse", "", {HistType::kTHnSparseF, {{axisK0Mass, axisPt, axisMultiplicity}}}); histos.add("hK0s", "", {HistType::kTH1D, {singleCount}}); - histos.add("K0d22Fpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("K0d24Fpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("K0d22Bpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("K0d24Bpt", "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - histos.add("hK0Count", "Number of K0;; Count", {HistType::kTH1D, {{10, 0, 10}}}); histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(1, "K0 candidates"); histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); @@ -278,33 +410,23 @@ struct ResonancesGfwFlow { histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(9, "Proper lifetime"); histos.get(HIST("hK0Count"))->GetXaxis()->SetBinLabel(10, "Daughter track selection"); } - if (cfgUseLambda) { - histos.add("PlusTPC_L", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("MinusTPC_L", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("PlusTOF_L", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("MinusTOF_L", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + if (resoSwitchVals[LAMBDA][kUseParticle]) { + histos.add("PrPlusTPC_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiMinusTPC_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PrPlusTOF_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("PiMinusTOF_L", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hLambdaPhi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hLambdaEta", "", {HistType::kTH1D, {axisEta}}); histos.add("hLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, axisPt, axisMultiplicity}}}); - histos.add("PlusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("MinusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisTPCsignal}}}); - histos.add("PlusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); - histos.add("MinusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisTOFsignal}}}); + histos.add("PiPlusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PrMinusTPC_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTPC}}}); + histos.add("PiPlusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); + histos.add("PrMinusTOF_AL", "", {HistType::kTH2D, {{axisPt, axisNsigmaTOF}}}); histos.add("hAntiLambdaPhi", "", {HistType::kTH1D, {axisPhi}}); histos.add("hAntiLambdaEta", "", {HistType::kTH1D, {axisEta}}); histos.add("hAntiLambdaMass_sparse", "", {HistType::kTHnSparseF, {{axisLambdaMass, axisPt, axisMultiplicity}}}); histos.add("hLambdas", "", {HistType::kTH1D, {singleCount}}); - histos.add("Lambdad22Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("Lambdad24Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("Lambdad22Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("Lambdad24Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - - histos.add("AnLambdad22Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("AnLambdad24Fpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("AnLambdad22Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("AnLambdad24Bpt", "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - histos.add("hLambdaCount", "Number of Lambda;; Count", {HistType::kTH1D, {{10, 0, 10}}}); histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(1, "Lambda candidates"); histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(2, "Daughter pt"); @@ -318,15 +440,31 @@ struct ResonancesGfwFlow { histos.get(HIST("hLambdaCount"))->GetXaxis()->SetBinLabel(10, "Daughter track selection"); } - histos.add("hEventCount", "Number of Event;; Count", {HistType::kTH1D, {{8, 0, 8}}}); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(1, "Filtered event"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(2, "After sel8"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(3, "kNoTimeFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(5, "kNoSameBunchPileup"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(6, "kIsGoodZvtxFT0vsPV"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(7, "kNoCollInTimeRangeStandard"); - histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(8, "After Occupancy"); + histos.add("hEventCount", "Number of Events;; Count", {HistType::kTH1D, {{15, -0.5, 14.5}}}); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kFilteredEvents + 1, "Filtered event"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kAfterSel8 + 1, "After sel8"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoTimeFrameBorder + 1, "kNoTimeFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoITSROFrameBorder + 1, "kNoITSROFrameBorder"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoSameBunchPileup + 1, "kNoSameBunchPileup"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodZvtxFT0vsPV + 1, "kIsGoodZvtxFT0vsPV"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInTimeRangeStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseGoodITSLayersAll + 1, "kIsGoodITSLayersAll"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoCollInRofStandard + 1, "kNoCollInRofStandard"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseNoHighMultCollInPrevRof + 1, "kNoHighMultCollInPrevRof"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseOccupancy + 1, "Occupancy Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseMultCorrCut + 1, "Multiplicity correlation Cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseT0AV0ACut + 1, "T0AV0A cut"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseVertexITSTPC + 1, "kIsVertexITSTPC"); + histos.get(HIST("hEventCount"))->GetXaxis()->SetBinLabel(kUseTVXinTRD + 1, "kTVXinTRD"); + + histos.add("hTrackCount", "Number of Tracks;; Count", {HistType::kTH1D, {{7, -0.5, 6.5}}}); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kFilteredTracks + 1, "Filtered track"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUseGlobalTracks + 1, "Global tracks"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kUsePvContributor + 1, "PV contributor"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kItsClustersCut + 1, "ITS clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kHasTpcSignal + 1, "TPC signal"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcClustersCut + 1, "TPC clusters"); + histos.get(HIST("hTrackCount"))->GetXaxis()->SetBinLabel(kTpcCrossedRowsCut + 1, "TPC crossed rows"); if (cfgOutputNUAWeights) { histos.add("NUA/hPhiEtaVtxz_ref", ";#varphi;#eta;v_{z}", {HistType::kTH3D, {axisPhi, {64, -1.6, 1.6}, {40, -10, 10}}}); @@ -348,115 +486,62 @@ struct ResonancesGfwFlow { histos.add("NUA/hPhiEtaPt_phi", ";#varphi;#eta;p_{T}", {HistType::kTH3D, {axisPhi, {64, -1.6, 1.6}, axisPt}}); } - if (cfgUseBootStrap) { - for (int i = 0; i < cfgNbootstrap; i++) { - refC22Boot[i] = histos.add(Form("BootStrap/Refc22_bootstrap_%d", i), "", {HistType::kTProfile, {axisMultiplicity}}); - refC24Boot[i] = histos.add(Form("BootStrap/Refc24_bootstrap_%d", i), "", {HistType::kTProfile, {axisMultiplicity}}); - if (cfgUsePhi) { - phiD22FPtBoot[i] = histos.add(Form("BootStrap/phid22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - phiD24FPtBoot[i] = histos.add(Form("BootStrap/phid24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - phiD22BPtBoot[i] = histos.add(Form("BootStrap/phid22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - phiD24BPtBoot[i] = histos.add(Form("BootStrap/phid24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisPhiMass, axisMultiplicity}}); - } - if (cfgUseK0) { - k0D22FPtBoot[i] = histos.add(Form("BootStrap/k0d22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - k0D24FPtBoot[i] = histos.add(Form("BootStrap/k0d24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - k0D22BPtBoot[i] = histos.add(Form("BootStrap/k0d22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - k0D24BPtBoot[i] = histos.add(Form("BootStrap/k0d24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisK0Mass, axisMultiplicity}}); - } - if (cfgUseLambda) { - lambdaD22FPtBoot[i] = histos.add(Form("BootStrap/lambdad22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - lambdaD24FPtBoot[i] = histos.add(Form("BootStrap/lambdad24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - lambdaD22BPtBoot[i] = histos.add(Form("BootStrap/lambdad22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - lambdaD24BPtBoot[i] = histos.add(Form("BootStrap/lambdad24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - - anLambdaD22FPtBoot[i] = histos.add(Form("BootStrap/anlambdad22Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - anLambdaD24FPtBoot[i] = histos.add(Form("BootStrap/anlambdad24Fpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - anLambdaD22BPtBoot[i] = histos.add(Form("BootStrap/anlambdad22Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - anLambdaD24BPtBoot[i] = histos.add(Form("BootStrap/anlambdad24Bpt_bootstrap_%d", i), "", {HistType::kTProfile3D, {axisPt, axisLambdaMass, axisMultiplicity}}); - } - } // end of bootstrap loop - } // end of bootstrap condition - o2::framework::AxisSpec axis = axisPt; int nPtBins = axis.binEdges.size() - 1; double* ptBins = &(axis.binEdges)[0]; fPtAxis = new TAxis(nPtBins, ptBins); - fPhiMassAxis = new TAxis(vMassBins[Phi - 2], vMassMin[Phi - 2], vMassMax[Phi - 2]); - fK0MassAxis = new TAxis(vMassBins[K0 - 1], vMassMin[K0 - 1], vMassMax[K0 - 1]); - fLambdaMassAxis = new TAxis(vMassBins[Lambda - 1], vMassMin[Lambda - 1], vMassMax[Lambda - 1]); + fPhiMassAxis = new TAxis(resoSwitchVals[PHI][kMassBins], resoCutVals[PHI][kMassMin], resoCutVals[PHI][kMassMax]); + fK0MassAxis = new TAxis(resoSwitchVals[K0][kMassBins], resoCutVals[K0][kMassMin], resoCutVals[K0][kMassMax]); + fLambdaMassAxis = new TAxis(resoSwitchVals[LAMBDA][kMassBins], resoCutVals[LAMBDA][kMassMin], resoCutVals[LAMBDA][kMassMax]); - int nPhisPtMassBins = nPtBins * vMassBins[Phi - 2]; - int nK0sPtMassBins = nPtBins * vMassBins[K0 - 1]; - int nLambdasPtMassBins = nPtBins * vMassBins[Lambda - 1]; + int nPhisPtMassBins = nPtBins * resoSwitchVals[PHI][kMassBins]; + int nK0sPtMassBins = nPtBins * resoSwitchVals[K0][kMassBins]; + int nLambdasPtMassBins = nPtBins * resoSwitchVals[LAMBDA][kMassBins]; + int nPtMassBins; //********** Defining the regions ********** - // reference particles - fGFW->AddRegion("refN08", -0.8, -0.4, 1, 1); - fGFW->AddRegion("refP08", 0.4, 0.8, 1, 1); - - // phi - fGFW->AddRegion("poiNphi", -0.8, -0.4, 1 + nPhisPtMassBins, 2); - fGFW->AddRegion("poiPphi", -0.8, -0.4, 1 + nPhisPtMassBins, 2); - fGFW->AddRegion("olNphi", -0.8, -0.4, 1 + nPhisPtMassBins, 32); - fGFW->AddRegion("olPphi", -0.8, -0.4, 1 + nPhisPtMassBins, 32); - - // kshort - fGFW->AddRegion("poiNk0", -0.8, -0.4, 1 + nK0sPtMassBins, 4); - fGFW->AddRegion("poiPk0", -0.8, -0.4, 1 + nK0sPtMassBins, 4); - fGFW->AddRegion("olNk0", -0.8, -0.4, 1 + nK0sPtMassBins, 64); - fGFW->AddRegion("olPk0", -0.8, -0.4, 1 + nK0sPtMassBins, 64); - - // lambda - fGFW->AddRegion("poiNlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 8); - fGFW->AddRegion("poiPlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 8); - fGFW->AddRegion("olNlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 128); - fGFW->AddRegion("olPlam", -0.8, -0.4, 1 + nLambdasPtMassBins, 128); - - // antilambda - fGFW->AddRegion("poiNantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 16); - fGFW->AddRegion("poiPantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 16); - fGFW->AddRegion("olNantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 256); - fGFW->AddRegion("olPantilam", -0.8, -0.4, 1 + nLambdasPtMassBins, 256); + for (auto i(0); i < regions.GetSize(); ++i) { + if (regions.GetNames()[i].ends_with("phi")) { + nPtMassBins = nPhisPtMassBins; + } else if (regions.GetNames()[i].ends_with("k0")) { + nPtMassBins = nK0sPtMassBins; + } else if (regions.GetNames()[i].ends_with("lam") || regions.GetNames()[i].ends_with("antilam")) { + nPtMassBins = nLambdasPtMassBins; + } else { + nPtMassBins = nPtBins; + } + fGFW->AddRegion(regions.GetNames()[i], regions.GetEtaMin()[i], regions.GetEtaMax()[i], (regions.GetpTDifs()[i]) ? nPtMassBins + 1 : 1, regions.GetBitmasks()[i]); + } //********** Defining the correlations ************ - // NAMING CONVENTION: - // F: Forward --> REF from negative eta + POI from negative eta correlated to REF from positive eta - // B: Backward --> REF from negative eta correlated to REF from positive eta + POI from positive eta - - //--------- reference particles - // Forward and Backward correlations are the same for reference particles - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN08 {2} refP08 {-2}", "Ref08Gap22", kFALSE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("refN08 {2 2} refP08 {-2 -2}", "Ref08Gap24", kFALSE)); - - //--------- pt differential pois - // Phi - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNphi refN08 | olNphi {2} refP08 {-2}", "PhiF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNphi refN08 | olNphi {2 2} refP08 {-2 -2}", "PhiF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPphi refP08 | olPphi {2} refN08 {-2}", "PhiB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPphi refP08 | olPphi {2 2} refN08 {-2 -2}", "PhiB08Gap24", kTRUE)); - - // K0 - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNk0 refN08 | olNk0 {2} refP08 {-2}", "KsF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNk0 refN08 | olNk0 {2 2} refP08 {-2 -2}", "KsF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPk0 refP08 | olPk0 {2} refN08 {-2}", "KsB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPk0 refP08 | olPk0 {2 2} refN08 {-2 -2}", "KsB08Gap24", kTRUE)); - - // Lambda - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNlam refN08 | olNlam {2} refP08 {-2}", "LamF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNlam refN08 | olNlam {2 2} refP08 {-2 -2}", "LamF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPlam refP08 | olPlam {2} refN08 {-2}", "LamB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPlam refP08 | olPlam {2 2} refN08 {-2 -2}", "LamB08Gap24", kTRUE)); - - // Antilambda - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNantilam refN08 | olNantilam {2} refP08 {-2}", "AnLamF08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiNantilam refN08 | olNantilam {2 2} refP08 {-2 -2}", "AnLamF08Gap24", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPantilam refP08 | olPantilam {2} refN08 {-2}", "AnLamB08Gap22", kTRUE)); - corrconfigs.push_back(fGFW->GetCorrelatorConfig("poiPantilam refP08 | olPantilam {2 2} refN08 {-2 -2}", "AnLamB08Gap24", kTRUE)); - + for (auto i = 0; i < configs.GetSize(); ++i) { + corrconfigs.push_back(fGFW->GetCorrelatorConfig(configs.GetCorrs()[i], configs.GetHeads()[i], configs.GetpTDifs()[i])); + } + if (corrconfigs.empty()) + LOGF(error, "Configuration contains vectors of different size - check the GFWCorrConfig configurable"); fGFW->CreateRegions(); + // Multiplicity correlation cuts + if (eventCuts[kUseMultCorrCut]) { + 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); + } + if (eventCuts[kUseT0AV0ACut]) { + 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); + } + + // Track density correction if (cfgTrackDensityCorrUse) { 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]); @@ -477,30 +562,17 @@ struct ResonancesGfwFlow { } } - template - void fillResoProfile(const GFW::CorrConfig& corrconf, const ConstStr& tarName, const double cent, TAxis* partaxis) + template + int findComponent(std::vector>& ptr, const std::string& name) { - double dnx, val; - if (!corrconf.pTDif) { - dnx = fGFW->Calculate(corrconf, 0, kTRUE).real(); - if (dnx == 0) - return; - val = fGFW->Calculate(corrconf, 0, kFALSE).real() / dnx; - if (std::fabs(val) < 1) - histos.fill(tarName, cent, val, dnx); - return; - } - for (int i = 1; i <= fPtAxis->GetNbins(); i++) { - for (int j = 1; j <= partaxis->GetNbins(); j++) { - dnx = fGFW->Calculate(corrconf, ((i - 1) * partaxis->GetNbins()) + (j - 1), kTRUE).real(); - if (dnx == 0) - continue; - val = fGFW->Calculate(corrconf, ((i - 1) * partaxis->GetNbins()) + (j - 1), kFALSE).real() / dnx; - if (std::fabs(val) < 1) - histos.fill(tarName, fPtAxis->GetBinCenter(i), partaxis->GetBinCenter(j), cent, val, dnx); + int nIndex = -1; + for (int i = 0; i < static_cast(ptr.size()); i++) { + if (ptr[i]->GetName() == name) { + nIndex = i; } } - return; + + return nIndex; } void fillProfileBoot(const GFW::CorrConfig& corrconf, std::shared_ptr profile, const double& cent) @@ -533,9 +605,10 @@ struct ResonancesGfwFlow { } return; } + // Cosine pointing angle cut template - bool selectionPair(const TTrack1& track1, const TTrack2& track2) + double cosinePointingAngle(const TTrack1& track1, const TTrack2& track2) { double pt1, pt2, pz1, pz2, p1, p2, angle; pt1 = track1.pt(); @@ -545,10 +618,8 @@ struct ResonancesGfwFlow { p1 = track1.p(); p2 = track2.p(); angle = std::acos((pt1 * pt2 + pz1 * pz2) / (p1 * p2)); - if (cfgUseCosPA && angle < vCosPAs[Phi - 2]) { - return false; - } - return true; + + return angle; } template @@ -563,39 +634,120 @@ struct ResonancesGfwFlow { } template - bool selectionTrack(const TTrack& track) + bool isGoodTrack(const TTrack& track) { - if (cfgUseGlobalTrack && !(track.isGlobalTrack() && track.isPVContributor() && track.itsNCls() > cfgITScluster && track.tpcNClsFound() > cfgTpcCluster && track.hasTPC())) { - return false; + histos.fill(HIST("hTrackCount"), kFilteredTracks); // Filtered tracks + + if (cfgUseGlobalTrack && !(track.isGlobalTrack())) { + return 0; } - if (!cfgUseGlobalTrack && !(track.isPVContributor() && track.itsNCls() > cfgITScluster && track.hasTPC())) { - return false; + histos.fill(HIST("hTrackCount"), kUseGlobalTracks); // After global track selection + + if (!(track.isPVContributor())) { + return 0; } - return true; + histos.fill(HIST("hTrackCount"), kUsePvContributor); // After PV contributor selection + + if (!(track.itsNCls() > cfgITScluster)) { + return 0; + } + histos.fill(HIST("hTrackCount"), kItsClustersCut); // After ITS cluster selection + + if (!(track.hasTPC())) { + return 0; + } + histos.fill(HIST("hTrackCount"), kHasTpcSignal); // If track has TPC signal + + if (!(track.tpcNClsFound() > cfgTpcCluster)) { + return 0; + } + histos.fill(HIST("hTrackCount"), kTpcClustersCut); // After TPC cluster selection + + if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) { + return 0; + } + histos.fill(HIST("hTrackCount"), kTpcCrossedRowsCut); // After TPC crossed rows selection + + return 1; } template - int getNsigmaPID(TTrack track) + int getNsigmaPIDTpcTof(TTrack track) { // Computing Nsigma arrays for pion, kaon, and protons std::array nSigmaTPC = {track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr()}; std::array nSigmaCombined = {std::hypot(track.tpcNSigmaPi(), track.tofNSigmaPi()), std::hypot(track.tpcNSigmaKa(), track.tofNSigmaKa()), std::hypot(track.tpcNSigmaPr(), track.tofNSigmaPr())}; int pid = -1; - float nsigma = cfgTpcNsigmaCut; + float nsigma = cfgTpcCut; // 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() > cfgTofPtCut && track.hasTOF()) ? nSigmaCombined : nSigmaTPC; + if (track.pt() > cfgTofPtCut && !track.hasTOF()) + return 0; const int numSpecies = 3; + int pidCount = 0; // Select particle with the lowest nsigma for (int i = 0; i < numSpecies; ++i) { if (std::abs(nSigmaToUse[i]) < nsigma) { + if (pidCount > 0 && cfgUseStrictPID) + return 0; // more than one particle with low nsigma + + pidCount++; pid = i; - nsigma = std::abs(nSigmaToUse[i]); + if (!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 = cfgUseItsPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::array detectorNsigmaCut = 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() > cfgTofPtCut && !track.hasTOF()) { + return 0; + } 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 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 } @@ -609,35 +761,35 @@ struct ResonancesGfwFlow { mAcceptance.clear(); mAcceptance.resize(kCount_OutputSpecies); - mAcceptance[Ref] = ccdb->getForTimeStamp(cfgAcceptance.value + "_ref", timestamp); - if (mAcceptance[Ref]) - LOGF(info, "Loaded acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Ref]); - else - LOGF(fatal, "Could not load acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Ref]); - mAcceptance[K0] = ccdb->getForTimeStamp(cfgAcceptance.value + "_k0", timestamp); if (mAcceptance[K0]) LOGF(info, "Loaded acceptance weights from %s_k0 (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[K0]); else LOGF(fatal, "Could not load acceptance weights from %s_k0 (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[K0]); - mAcceptance[Lambda] = ccdb->getForTimeStamp(cfgAcceptance.value + "_lambda", timestamp); - if (mAcceptance[Lambda]) - LOGF(info, "Loaded acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Lambda]); + mAcceptance[LAMBDA] = ccdb->getForTimeStamp(cfgAcceptance.value + "_lambda", timestamp); + if (mAcceptance[LAMBDA]) + LOGF(info, "Loaded acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[LAMBDA]); + else + LOGF(fatal, "Could not load acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[LAMBDA]); + + mAcceptance[PHI] = ccdb->getForTimeStamp(cfgAcceptance.value + "_phi", timestamp); + if (mAcceptance[PHI]) + LOGF(info, "Loaded acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[PHI]); else - LOGF(fatal, "Could not load acceptance weights from %s_lambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Lambda]); + LOGF(fatal, "Could not load acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[PHI]); - mAcceptance[AnLambda] = ccdb->getForTimeStamp(cfgAcceptance.value + "_AnLambda", timestamp); - if (mAcceptance[AnLambda]) - LOGF(info, "Loaded acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[AnLambda]); + mAcceptance[ANLAMBDA] = ccdb->getForTimeStamp(cfgAcceptance.value + "_anlambda", timestamp); + if (mAcceptance[ANLAMBDA]) + LOGF(info, "Loaded acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[ANLAMBDA]); else - LOGF(fatal, "Could not load acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[AnLambda]); + LOGF(fatal, "Could not load acceptance weights from %s_anlambda (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[ANLAMBDA]); - mAcceptance[Phi] = ccdb->getForTimeStamp(cfgAcceptance.value + "_phi", timestamp); - if (mAcceptance[Phi]) - LOGF(info, "Loaded acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Phi]); + mAcceptance[REF] = ccdb->getForTimeStamp(cfgAcceptance.value + "_ref", timestamp); + if (mAcceptance[REF]) + LOGF(info, "Loaded acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[REF]); else - LOGF(fatal, "Could not load acceptance weights from %s_phi (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[Phi]); + LOGF(fatal, "Could not load acceptance weights from %s_ref (%p)", cfgAcceptance.value.c_str(), (void*)mAcceptance[REF]); } correctionsLoaded = true; @@ -645,7 +797,7 @@ struct ResonancesGfwFlow { template double getAcceptance(TTrack track, const TCollision collision, int pid_index_reso) - { // 0 = ref, 1 = k0, 2 = lambda, 3 = anti-lambda, 4 = phi + { // 0 = k0, 1 = lambda, 2 = phi, 3 = anti-lambda, 4 = ref if (pid_index_reso < 0 || pid_index_reso >= kCount_OutputSpecies) { return 1; } @@ -674,7 +826,7 @@ struct ResonancesGfwFlow { template double getAcceptancePhi(vector mom, const TCollision collision, int pid_index_reso) - { // 0 = ref, 1 = k0, 2 = lambda, 3 = anti-lambda, 4 = phi + { // 0 = k0, 1 = lambda, 2 = phi, 3 = anti-lambda, 4 = ref if (pid_index_reso < 0 || pid_index_reso >= kCount_OutputSpecies) { return 1; } @@ -712,7 +864,7 @@ struct ResonancesGfwFlow { bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); // within RF pT range - if (withinPtRef && !pid_index_reso) { + if (withinPtRef && pid_index_reso == REF) { histos.fill(HIST("NUA/hPhiEtaVtxz_ref"), track.phi(), track.eta(), vtxz); // pt-subset of charged particles for ref flow histos.fill(HIST("NUA/hPhiPtCent_ref"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_ref"), track.phi(), track.eta(), track.pt()); @@ -725,12 +877,12 @@ struct ResonancesGfwFlow { histos.fill(HIST("NUA/hPhiPtCent_k0"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_k0"), track.phi(), track.eta(), track.pt()); break; - case Lambda: + case LAMBDA: histos.fill(HIST("NUA/hPhiEtaVtxz_lambda"), track.phi(), track.eta(), vtxz); // Lambda weights histos.fill(HIST("NUA/hPhiPtCent_lambda"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_lambda"), track.phi(), track.eta(), track.pt()); break; - case AnLambda: + case ANLAMBDA: histos.fill(HIST("NUA/hPhiEtaVtxz_anlambda"), track.phi(), track.eta(), vtxz); // Anti-Lambda weights histos.fill(HIST("NUA/hPhiPtCent_anlambda"), track.phi(), track.pt(), cent); histos.fill(HIST("NUA/hPhiEtaPt_anlambda"), track.phi(), track.eta(), track.pt()); @@ -740,33 +892,56 @@ struct ResonancesGfwFlow { } } + template + bool selectionV0Daughter(TTrack const& track, int pid) + { + if (!(track.itsNCls() > cfgITScluster)) + return 0; + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < cfgTpcCluster) + return false; + if (!(track.tpcNClsCrossedRows() > cfgTpcCrossRows)) + return 0; + + if (cfgUseOnlyTPC) { + if (pid == PIONS && std::abs(track.tpcNSigmaPi()) > cfgTpcCut) + return false; + if (pid == KAONS && std::abs(track.tpcNSigmaKa()) > cfgTpcCut) + return false; + if (pid == PROTONS && std::abs(track.tpcNSigmaPr()) > cfgTpcCut) + return false; + } else { + int partIndex = cfgUseAsymmetricPID ? getNsigmaPIDAssymmetric(track) : getNsigmaPIDTpcTof(track); + int pidIndex = partIndex - 1; // 0 = pion, 1 = kaon, 2 = proton + if (pidIndex != pid) + return false; + } + + return true; + } + template void resurrectPhi(TTrack trackplus, TTrack trackminus, const TCollision collision, vector plusdaug, vector minusdaug, vector mom, double plusmass, const ConstStr& hist) { - const int nKaon = 2; for (auto const& [partplus, partminus] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(trackplus, trackminus))) { - if (getNsigmaPID(partplus) != nKaon) - continue; - if (getNsigmaPID(partminus) != nKaon) + histos.fill(HIST("hPhiCount"), 0.5); + if (!selectionV0Daughter(partplus, KAONS) || !selectionV0Daughter(partminus, KAONS)) // 0 = pion, 1 = kaon, 2 = proton continue; + histos.fill(HIST("hPhiCount"), 1.5); + if (isFakeKaon(partplus) || isFakeKaon(partminus)) continue; - if (!selectionPair(partplus, partminus)) - continue; - if (!selectionTrack(partplus) || !selectionTrack(partminus)) - continue; + histos.fill(HIST("hPhiCount"), 2.5); - histos.fill(HIST("KaplusTPC"), partplus.pt(), partplus.tpcNSigmaKa()); - histos.fill(HIST("KaplusTOF"), partplus.pt(), partplus.tofNSigmaKa()); - histos.fill(HIST("KaminusTPC"), partminus.pt(), partminus.tpcNSigmaKa()); - histos.fill(HIST("KaminusTOF"), partminus.pt(), partminus.tofNSigmaKa()); - - std::array, 2> ptarr = {{{partplus.px(), partplus.py(), partplus.pz()}, {partminus.px(), partminus.py(), partminus.pz()}}}; - std::array massarr = {plusmass, plusmass}; + if (resoSwitchVals[PHI][kUseCosPA] && cosinePointingAngle(partplus, partminus) < resoCutVals[PHI][kCosPA]) + continue; + histos.fill(HIST("hPhiCount"), 3.5); - // Calculation using RecoDecay - double invMassRD = RecoDecay::m2(ptarr, massarr); - double ptRD = std::sqrt(RecoDecay::sumOfSquares(partplus.pt(), partminus.pt())); + histos.fill(HIST("KaPlusTPC"), partplus.pt(), partplus.tpcNSigmaKa()); + histos.fill(HIST("KaPlusTOF"), partplus.pt(), partplus.tofNSigmaKa()); + histos.fill(HIST("KaMinusTPC"), partminus.pt(), partminus.tpcNSigmaKa()); + histos.fill(HIST("KaMinusTOF"), partminus.pt(), partminus.tofNSigmaKa()); // Calculation using ROOT vectors plusdaug = ROOT::Math::PxPyPzMVector(partplus.px(), partplus.py(), partplus.pz(), plusmass); @@ -781,11 +956,12 @@ struct ResonancesGfwFlow { phi = RecoDecay::constrainAngle(phi, 0.0, 1); // constrain azimuthal angle to [0,2pi] - if (std::abs(mom.Rapidity()) < cfgRapidityCut) { + if (std::abs(mom.Rapidity()) < resoCutVals[PHI][kRapidity]) { + histos.fill(HIST("hPhiCount"), 4.5); + histos.fill(hist, invMass, pt, collision.centFT0C()); histos.fill(HIST("hPhiPhi"), phi); histos.fill(HIST("hPhiEta"), mom.Eta()); - histos.fill(HIST("hPhimassSparse_RD"), invMassRD, ptRD, collision.centFT0C()); // fill RecoDecay mass and pt // Fill Phi weights if (cfgOutputNUAWeights && withinPtPOI) { @@ -794,30 +970,53 @@ struct ResonancesGfwFlow { histos.fill(HIST("NUA/hPhiEtaPt_phi"), phi, mom.Eta(), pt); } double weff = 1; - double waccPOI = getAcceptancePhi(mom, collision, Phi); + double waccPOI = getAcceptancePhi(mom, collision, PHI); if (withinPtPOI) fGFW->Fill(mom.Eta(), ((fPtAxis->FindBin(pt) - 1) * fPhiMassAxis->GetNbins()) + (fPhiMassAxis->FindBin(invMass) - 1), phi, weff * waccPOI, 2); if (withinPtPOI && withinPtRef) fGFW->Fill(mom.Eta(), ((fPtAxis->FindBin(pt) - 1) * fPhiMassAxis->GetNbins()) + (fPhiMassAxis->FindBin(invMass) - 1), phi, weff * waccPOI, 32); } - } + } // end of combinations loop return; } - template - bool selectionV0Daughter(TTrack const& track, int pid) // pid 1: proton, pid 0: pion + template + void likeSignPhi(TTrack track, const TCollision collision, double plusmass, const ConstStr& hist) { - if (track.tpcNClsFound() < cfgTpcCluster) - return false; - if (!track.hasTPC()) - return false; - if (pid == 1 && std::abs(track.tpcNSigmaPr()) > cfgTpcNsigmaCut) - return false; - if (pid == 0 && std::abs(track.tpcNSigmaPi()) > cfgTpcNsigmaCut) - return false; + ROOT::Math::PxPyPzMVector daug1, daug2, mom; + for (auto const& [part1, part2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(track, track))) { - return true; + if (!selectionV0Daughter(part1, KAONS) || !selectionV0Daughter(part2, KAONS)) // 0 = pion, 1 = kaon, 2 = proton + continue; + if (isFakeKaon(part1) || isFakeKaon(part2)) + continue; + + // Calculation using ROOT vectors + daug1 = ROOT::Math::PxPyPzMVector(part1.px(), part1.py(), part1.pz(), plusmass); + daug2 = ROOT::Math::PxPyPzMVector(part2.px(), part2.py(), part2.pz(), plusmass); + mom = daug1 + daug2; + + double pt = mom.Pt(); + double invMass = mom.M(); + double phi = mom.Phi(); + bool withinPtPOI = (cfgCutPtPOIMin < pt) && (pt < cfgCutPtPOIMax); // within POI pT range + bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); + + phi = RecoDecay::constrainAngle(phi, 0.0, 1); // constrain azimuthal angle to [0,2pi] + + if (std::abs(mom.Rapidity()) < resoCutVals[PHI][kRapidity]) { + histos.fill(hist, invMass, pt, collision.centFT0C()); + double weff = 1; + double waccPOI = 1; + + if (withinPtPOI) + fGFW->Fill(mom.Eta(), ((fPtAxis->FindBin(pt) - 1) * fPhiMassAxis->GetNbins()) + (fPhiMassAxis->FindBin(invMass) - 1), phi, weff * waccPOI, 512); + if (withinPtPOI && withinPtRef) + fGFW->Fill(mom.Eta(), ((fPtAxis->FindBin(pt) - 1) * fPhiMassAxis->GetNbins()) + (fPhiMassAxis->FindBin(invMass) - 1), phi, weff * waccPOI, 1024); + } + } // end of positive combinations loop + return; } template @@ -834,13 +1033,13 @@ struct ResonancesGfwFlow { auto negtrack = candidate.template negTrack_as(); histos.fill(HIST("hLambdaCount"), 0.5); - if (postrack.pt() < vPosTrackPt[Lambda - 1] || negtrack.pt() < vNegTrackPt[Lambda - 1]) + if (postrack.pt() < resoCutVals[LAMBDA][kPosTrackPt] || negtrack.pt() < resoCutVals[LAMBDA][kNegTrackPt]) return false; histos.fill(HIST("hLambdaCount"), 1.5); - if (mlambda > vMassMin[Lambda - 1] && mlambda < vMassMax[Lambda - 1]) + if (mlambda > resoCutVals[LAMBDA][kMassMin] && mlambda < resoCutVals[LAMBDA][kMassMax]) isL = true; - if (mantilambda > vMassMin[Lambda - 1] && mantilambda < vMassMax[Lambda - 1]) + if (mantilambda > resoCutVals[LAMBDA][kMassMin] && mantilambda < resoCutVals[LAMBDA][kMassMax]) isAL = true; if (!isL && !isAL) { @@ -849,40 +1048,40 @@ struct ResonancesGfwFlow { histos.fill(HIST("hLambdaCount"), 2.5); // Rapidity correction - if (candidate.yLambda() > cfgRapidityCut) + if (candidate.yLambda() > resoCutVals[LAMBDA][kRapidity]) return false; histos.fill(HIST("hLambdaCount"), 3.5); // DCA cuts for lambda and antilambda if (isL) { - if (std::abs(candidate.dcapostopv()) < cfgDCALambdaPosToPVMin || std::abs(candidate.dcanegtopv()) < cfgDCALambdaNegToPVMin) + if (std::abs(candidate.dcapostopv()) < resoCutVals[LAMBDA][kDCAPosToPVMin] || std::abs(candidate.dcanegtopv()) < resoCutVals[LAMBDA][kDCANegToPVMin]) return false; } if (isAL) { - if (std::abs(candidate.dcapostopv()) < cfgDCALambdaNegToPVMin || std::abs(candidate.dcanegtopv()) < cfgDCALambdaPosToPVMin) + if (std::abs(candidate.dcapostopv()) < resoCutVals[LAMBDA][kDCANegToPVMin] || std::abs(candidate.dcanegtopv()) < resoCutVals[LAMBDA][kDCAPosToPVMin]) return false; } histos.fill(HIST("hLambdaCount"), 4.5); - if (std::abs(candidate.dcaV0daughters()) > vDCABetDaug[Lambda - 1]) + if (std::abs(candidate.dcaV0daughters()) > resoSwitchVals[LAMBDA][kDCABetDaug]) return false; histos.fill(HIST("hLambdaCount"), 5.5); // v0 radius cuts - if (cfgUseV0Radius && (candidate.v0radius() < cfgLambdaRadiusMin || candidate.v0radius() > cfgLambdaRadiusMax)) + if (resoSwitchVals[LAMBDA][kUseV0Radius] && (candidate.v0radius() < resoCutVals[LAMBDA][kRadiusMin] || candidate.v0radius() > resoCutVals[LAMBDA][kRadiusMax])) return false; histos.fill(HIST("hLambdaCount"), 6.5); // cosine pointing angle cuts - if (candidate.v0cosPA() < vCosPAs[Lambda - 1]) + if (candidate.v0cosPA() < resoCutVals[LAMBDA][kCosPA]) return false; histos.fill(HIST("hLambdaCount"), 7.5); // Proper lifetime - if (cfgUseProperLifetime && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > cfgLambdaLifeTime) + if (resoSwitchVals[LAMBDA][kUseProperLifetime] && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > resoCutVals[LAMBDA][kLifeTime]) return false; histos.fill(HIST("hLambdaCount"), 8.5); if (isL) { - if (!selectionV0Daughter(postrack, 1) || !selectionV0Daughter(negtrack, 0)) + if (!selectionV0Daughter(postrack, PROTONS) || !selectionV0Daughter(negtrack, PIONS)) return false; } if (isAL) { - if (!selectionV0Daughter(postrack, 0) || !selectionV0Daughter(negtrack, 1)) + if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PROTONS)) return false; } histos.fill(HIST("hLambdaCount"), 9.5); @@ -893,9 +1092,9 @@ struct ResonancesGfwFlow { if (isL) { if (cfgOutputNUAWeights) - fillWeights(candidate, collision, Lambda); + fillWeights(candidate, collision, LAMBDA); - double waccPOI = getAcceptance(candidate, collision, Lambda); + double waccPOI = getAcceptance(candidate, collision, LAMBDA); if (withinPtPOI) fGFW->Fill(candidate.eta(), ((fPtAxis->FindBin(candidate.pt()) - 1) * fLambdaMassAxis->GetNbins()) + (fLambdaMassAxis->FindBin(mlambda) - 1), candidate.phi(), waccPOI * weff, 8); if (withinPtPOI && withinPtRef) @@ -904,16 +1103,16 @@ struct ResonancesGfwFlow { histos.fill(HIST("hLambdaMass_sparse"), mlambda, candidate.pt(), collision.centFT0C()); histos.fill(HIST("hLambdaPhi"), candidate.phi()); histos.fill(HIST("hLambdaEta"), candidate.eta()); - histos.fill(HIST("PlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); - histos.fill(HIST("PlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); - histos.fill(HIST("MinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); - histos.fill(HIST("MinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); + histos.fill(HIST("PrPlusTPC_L"), postrack.pt(), postrack.tpcNSigmaKa()); + histos.fill(HIST("PrPlusTOF_L"), postrack.pt(), postrack.tofNSigmaKa()); + histos.fill(HIST("PiMinusTPC_L"), negtrack.pt(), negtrack.tpcNSigmaKa()); + histos.fill(HIST("PiMinusTOF_L"), negtrack.pt(), negtrack.tofNSigmaKa()); } if (isAL) { if (cfgOutputNUAWeights) - fillWeights(candidate, collision, AnLambda); + fillWeights(candidate, collision, ANLAMBDA); - double waccPOI = getAcceptance(candidate, collision, AnLambda); + double waccPOI = getAcceptance(candidate, collision, ANLAMBDA); if (withinPtPOI) fGFW->Fill(candidate.eta(), ((fPtAxis->FindBin(candidate.pt()) - 1) * fLambdaMassAxis->GetNbins()) + (fLambdaMassAxis->FindBin(mantilambda) - 1), candidate.phi(), waccPOI * weff, 16); if (withinPtPOI && withinPtRef) @@ -922,10 +1121,10 @@ struct ResonancesGfwFlow { histos.fill(HIST("hAntiLambdaMass_sparse"), mantilambda, candidate.pt(), collision.centFT0C()); histos.fill(HIST("hAntiLambdaPhi"), candidate.phi()); histos.fill(HIST("hAntiLambdaEta"), candidate.eta()); - histos.fill(HIST("PlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); - histos.fill(HIST("PlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); - histos.fill(HIST("MinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); - histos.fill(HIST("MinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); + histos.fill(HIST("PiPlusTPC_AL"), postrack.pt(), postrack.tpcNSigmaKa()); + histos.fill(HIST("PiPlusTOF_AL"), postrack.pt(), postrack.tofNSigmaKa()); + histos.fill(HIST("PrMinusTPC_AL"), negtrack.pt(), negtrack.tpcNSigmaKa()); + histos.fill(HIST("PrMinusTOF_AL"), negtrack.pt(), negtrack.tofNSigmaKa()); } return true; } @@ -940,36 +1139,36 @@ struct ResonancesGfwFlow { auto negtrack = candidate.template negTrack_as(); histos.fill(HIST("hK0Count"), 0.5); - if (postrack.pt() < vPosTrackPt[K0 - 1] || negtrack.pt() < vNegTrackPt[K0 - 1]) + if (postrack.pt() < resoCutVals[K0][kPosTrackPt] || negtrack.pt() < resoCutVals[K0][kNegTrackPt]) return false; histos.fill(HIST("hK0Count"), 1.5); - if (mk0 < vMassMin[K0 - 1] && mk0 > vMassMax[K0 - 1]) + if (mk0 < resoCutVals[K0][kMassMin] && mk0 > resoCutVals[K0][kMassMax]) return false; histos.fill(HIST("hK0Count"), 2.5); // Rapidity correction - if (candidate.yK0Short() > cfgRapidityCut) + if (candidate.yK0Short() > resoCutVals[K0][kRapidity]) return false; histos.fill(HIST("hK0Count"), 3.5); // DCA cuts for K0short - if (std::abs(candidate.dcapostopv()) < cfgDCAK0PosToPVMin || std::abs(candidate.dcanegtopv()) < cfgDCAK0NegToPVMin) + if (std::abs(candidate.dcapostopv()) < resoCutVals[K0][kDCAPosToPVMin] || std::abs(candidate.dcanegtopv()) < resoCutVals[K0][kDCANegToPVMin]) return false; histos.fill(HIST("hK0Count"), 4.5); - if (std::abs(candidate.dcaV0daughters()) > vDCABetDaug[K0 - 1]) + if (std::abs(candidate.dcaV0daughters()) > resoSwitchVals[K0][kDCABetDaug]) return false; histos.fill(HIST("hK0Count"), 5.5); // v0 radius cuts - if (cfgUseV0Radius && (candidate.v0radius() < cfgK0RadiusMin || candidate.v0radius() > cfgK0RadiusMax)) + if (resoSwitchVals[K0][kUseV0Radius] && (candidate.v0radius() < resoCutVals[K0][kRadiusMin] || candidate.v0radius() > resoCutVals[K0][kRadiusMax])) return false; histos.fill(HIST("hK0Count"), 6.5); // cosine pointing angle cuts - if (candidate.v0cosPA() < vCosPAs[K0 - 1]) + if (candidate.v0cosPA() < resoCutVals[K0][kCosPA]) return false; histos.fill(HIST("hK0Count"), 7.5); // Proper lifetime - if (cfgUseProperLifetime && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > cfgK0LifeTime) + if (resoSwitchVals[K0][kUseProperLifetime] && candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0Short > resoCutVals[K0][kLifeTime]) return false; histos.fill(HIST("hK0Count"), 8.5); - if (!selectionV0Daughter(postrack, 0) || !selectionV0Daughter(negtrack, 0)) + if (!selectionV0Daughter(postrack, PIONS) || !selectionV0Daughter(negtrack, PIONS)) return false; histos.fill(HIST("hK0Count"), 9.5); bool withinPtPOI = (cfgCutPtPOIMin < candidate.pt()) && (candidate.pt() < cfgCutPtPOIMax); // within POI pT range @@ -989,15 +1188,114 @@ struct ResonancesGfwFlow { histos.fill(HIST("hK0Mass_sparse"), mk0, candidate.pt(), collision.centFT0C()); histos.fill(HIST("hK0Phi"), candidate.phi()); histos.fill(HIST("hK0Eta"), candidate.eta()); - histos.fill(HIST("PlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); - histos.fill(HIST("PlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); - histos.fill(HIST("MinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); - histos.fill(HIST("MinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); + histos.fill(HIST("PiPlusTPC_K0"), postrack.pt(), postrack.tpcNSigmaKa()); + histos.fill(HIST("PiPlusTOF_K0"), postrack.pt(), postrack.tofNSigmaKa()); + histos.fill(HIST("PiMinusTPC_K0"), negtrack.pt(), negtrack.tpcNSigmaKa()); + histos.fill(HIST("PiMinusTOF_K0"), negtrack.pt(), negtrack.tofNSigmaKa()); return true; } - using BinningTypeVertexContributor = ColumnBinningPolicy; + template + bool selectionEvent(TCollision collision, const int mult, const float cent) + { + histos.fill(HIST("hEventCount"), kFilteredEvents); + if (!collision.sel8()) { + return 0; + } + histos.fill(HIST("hEventCount"), kAfterSel8); + + if (eventCuts[kUseNoTimeFrameBorder] && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return 0; + } + if (eventCuts[kUseNoTimeFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoTimeFrameBorder); + + if (eventCuts[kUseNoITSROFrameBorder] && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return 0; + } + if (eventCuts[kUseNoITSROFrameBorder]) + histos.fill(HIST("hEventCount"), kUseNoITSROFrameBorder); + + if (eventCuts[kUseNoSameBunchPileup] && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return 0; + } + if (eventCuts[kUseNoSameBunchPileup]) + histos.fill(HIST("hEventCount"), kUseNoSameBunchPileup); + + if (eventCuts[kUseGoodZvtxFT0vsPV] && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return 0; + } + if (eventCuts[kUseGoodZvtxFT0vsPV]) + histos.fill(HIST("hEventCount"), kUseGoodZvtxFT0vsPV); + + if (eventCuts[kUseNoCollInTimeRangeStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return 0; + } + if (eventCuts[kUseNoCollInTimeRangeStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInTimeRangeStandard); + + if (eventCuts[kUseGoodITSLayersAll] && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return 0; + } + if (eventCuts[kUseGoodITSLayersAll]) + histos.fill(HIST("hEventCount"), kUseGoodITSLayersAll); + + if (eventCuts[kUseNoCollInRofStandard] && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return 0; + } + if (eventCuts[kUseNoCollInRofStandard]) + histos.fill(HIST("hEventCount"), kUseNoCollInRofStandard); + + if (eventCuts[kUseNoHighMultCollInPrevRof] && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { + return 0; + } + if (eventCuts[kUseNoHighMultCollInPrevRof]) + histos.fill(HIST("hEventCount"), kUseNoHighMultCollInPrevRof); + + auto multNTracksPV = collision.multNTracksPV(); + auto occupancy = collision.trackOccupancyInTimeRange(); + + if (eventCuts[kUseOccupancy] && (occupancy < cfgCutOccupancyMin || occupancy > cfgCutOccupancyMax)) { + return 0; + } + if (eventCuts[kUseOccupancy]) + histos.fill(HIST("hEventCount"), kUseOccupancy); + + if (eventCuts[kUseMultCorrCut]) { + if (multNTracksPV < fMultPVCutLow->Eval(cent)) + return 0; + if (multNTracksPV > fMultPVCutHigh->Eval(cent)) + return 0; + if (mult < fMultCutLow->Eval(cent)) + return 0; + if (mult > fMultCutHigh->Eval(cent)) + return 0; + } + if (eventCuts[kUseMultCorrCut]) + histos.fill(HIST("hEventCount"), kUseMultCorrCut); + + // V0A T0A 5 sigma cut + if (eventCuts[kUseT0AV0ACut] && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > cfgV0AT0Acut * fT0AV0ASigma->Eval(collision.multFT0A()))) + return 0; + if (eventCuts[kUseT0AV0ACut]) + histos.fill(HIST("hEventCount"), kUseT0AV0ACut); + + if (eventCuts[kUseVertexITSTPC] && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return 0; + if (eventCuts[kUseVertexITSTPC]) + histos.fill(HIST("hEventCount"), kUseVertexITSTPC); + + if (eventCuts[kUseTVXinTRD] && collision.alias_bit(kTVXinTRD)) { + return 0; + } + if (eventCuts[kUseTVXinTRD]) + histos.fill(HIST("hEventCount"), kUseTVXinTRD); + + return 1; + } + + // using BinningTypeVertexContributor = ColumnBinningPolicy; ROOT::Math::PxPyPzMVector phiMom, kaonPlus, kaonMinus; double massKaPlus = o2::constants::physics::MassKPlus; double massLambda = o2::constants::physics::MassLambda; @@ -1005,42 +1303,16 @@ struct ResonancesGfwFlow { void process(AodCollisions::iterator const& collision, aod::BCsWithTimestamps const&, AodTracksWithoutBayes const& tracks, aod::V0Datas const& V0s) { - histos.fill(HIST("hEventCount"), 0.5); int nTot = tracks.size(); if (nTot < 1) return; - if (!collision.sel8()) - return; - histos.fill(HIST("hEventCount"), 1.5); - - if (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) - return; - histos.fill(HIST("hEventCount"), 2.5); - - if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) - return; - histos.fill(HIST("hEventCount"), 3.5); - - if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) - return; - histos.fill(HIST("hEventCount"), 4.5); - - if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) - return; - histos.fill(HIST("hEventCount"), 5.5); - - if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) - return; - histos.fill(HIST("hEventCount"), 6.5); + float vtxz = collision.posZ(); + const auto cent = collision.centFT0C(); - int occupancy = collision.trackOccupancyInTimeRange(); - if (occupancy > cfgCutOccupancy) + if (!selectionEvent(collision, nTot, cent)) return; - histos.fill(HIST("hEventCount"), 7.5); - const auto cent = collision.centFT0C(); - float vtxz = collision.posZ(); auto bc = collision.bc_as(); histos.fill(HIST("hVtxZ"), vtxz); @@ -1083,8 +1355,9 @@ struct ResonancesGfwFlow { // Actual track loop for (auto const& track : tracks) { - if (!selectionTrack(track)) + if (!isGoodTrack(track)) continue; + double pt = track.pt(); bool withinPtRef = (cfgCutPtMin < pt) && (pt < cfgCutPtMax); @@ -1092,9 +1365,9 @@ struct ResonancesGfwFlow { if (withinPtRef) if (cfgOutputNUAWeights) - fillWeights(track, collision, Ref); + fillWeights(track, collision, REF); - double waccRef = getAcceptance(track, collision, 0); + double waccRef = getAcceptance(track, collision, REF); if (cfgTrackDensityCorrUse && withinPtRef) { double fphi = v2 * std::cos(2 * (track.phi() - psi2Est)) + v3 * std::cos(3 * (track.phi() - psi3Est)) + v4 * std::cos(4 * (track.phi() - psi4Est)); @@ -1115,80 +1388,78 @@ struct ResonancesGfwFlow { auto posSlicedTracks = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto negSlicedTracks = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - if (cfgUsePhi) { + if (resoSwitchVals[PHI][kUseParticle]) { resurrectPhi(posSlicedTracks, negSlicedTracks, collision, kaonPlus, kaonMinus, phiMom, massKaPlus, HIST("hPhiMass_sparse")); } + if (cfgUseLsPhi) { + likeSignPhi(posSlicedTracks, collision, massKaPlus, HIST("hLsPhiMass_sparse")); + likeSignPhi(negSlicedTracks, collision, massKaPlus, HIST("hLsPhiMass_sparse")); + } + + // ---------------------- Analyzing the V0s for (auto const& v0s : V0s) { - if (cfgUseK0) { + if (resoSwitchVals[K0][kUseParticle]) { if (selectionK0(collision, v0s) == true) histos.fill(HIST("hK0s"), 1); } - if (cfgUseLambda) { + if (resoSwitchVals[LAMBDA][kUseParticle]) { if (selectionLambda(collision, v0s) == true) histos.fill(HIST("hLambdas"), 1); } } // End of v0 loop - fillResoProfile(corrconfigs.at(0), HIST("Refc22"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(1), HIST("Refc24"), cent, fPhiMassAxis); - if (cfgUsePhi) { - fillResoProfile(corrconfigs.at(2), HIST("Phid22Fpt"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(3), HIST("Phid24Fpt"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(4), HIST("Phid22Bpt"), cent, fPhiMassAxis); - fillResoProfile(corrconfigs.at(5), HIST("Phid24Bpt"), cent, fPhiMassAxis); - } - if (cfgUseK0) { - fillResoProfile(corrconfigs.at(6), HIST("K0d22Fpt"), cent, fK0MassAxis); - fillResoProfile(corrconfigs.at(7), HIST("K0d24Fpt"), cent, fK0MassAxis); - fillResoProfile(corrconfigs.at(8), HIST("K0d22Bpt"), cent, fK0MassAxis); - fillResoProfile(corrconfigs.at(9), HIST("K0d24Bpt"), cent, fK0MassAxis); - } - if (cfgUseLambda) { - fillResoProfile(corrconfigs.at(10), HIST("Lambdad22Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(11), HIST("Lambdad24Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(12), HIST("Lambdad22Bpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(13), HIST("Lambdad24Bpt"), cent, fLambdaMassAxis); - - fillResoProfile(corrconfigs.at(14), HIST("AnLambdad22Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(15), HIST("AnLambdad24Fpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(16), HIST("AnLambdad22Bpt"), cent, fLambdaMassAxis); - fillResoProfile(corrconfigs.at(17), HIST("AnLambdad24Bpt"), cent, fLambdaMassAxis); - } + // Filling the cumulant profiles + double r = fRndm->Rndm(); + int bootId = static_cast(r * 10); - // bootstraping - if (cfgUseBootStrap) { - double r = fRndm->Rndm(); - int bootId = static_cast(r * 10); + for (auto i = 0; i < static_cast(corrconfigs.size()); ++i) { + if (resoSwitchVals[PHI][kUseParticle] && corrconfigs.at(i).Head.starts_with("Phi")) { + int pIndex = findComponent(phiV2, Form("h%spt", corrconfigs.at(i).Head.c_str())); + fillProfileBoot3D(corrconfigs.at(i), phiV2[pIndex], cent, fPhiMassAxis); - fillProfileBoot(corrconfigs.at(0), refC22Boot[bootId], cent); - fillProfileBoot(corrconfigs.at(1), refC24Boot[bootId], cent); + if (cfgUseBootStrap) { + fillProfileBoot3D(corrconfigs.at(i), phiBoot[bootId][pIndex], cent, fPhiMassAxis); + } + } // end of phi condition - if (cfgUsePhi) { - fillProfileBoot3D(corrconfigs.at(2), phiD22FPtBoot[bootId], cent, fPhiMassAxis); - fillProfileBoot3D(corrconfigs.at(3), phiD24FPtBoot[bootId], cent, fPhiMassAxis); - fillProfileBoot3D(corrconfigs.at(4), phiD22BPtBoot[bootId], cent, fPhiMassAxis); - fillProfileBoot3D(corrconfigs.at(5), phiD24BPtBoot[bootId], cent, fPhiMassAxis); - } - if (cfgUseK0) { - fillProfileBoot3D(corrconfigs.at(6), k0D22FPtBoot[bootId], cent, fK0MassAxis); - fillProfileBoot3D(corrconfigs.at(7), k0D24FPtBoot[bootId], cent, fK0MassAxis); - fillProfileBoot3D(corrconfigs.at(8), k0D22BPtBoot[bootId], cent, fK0MassAxis); - fillProfileBoot3D(corrconfigs.at(9), k0D24BPtBoot[bootId], cent, fK0MassAxis); - } - if (cfgUseLambda) { - fillProfileBoot3D(corrconfigs.at(10), lambdaD22FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(11), lambdaD24FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(12), lambdaD22BPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(13), lambdaD24BPtBoot[bootId], cent, fLambdaMassAxis); - - fillProfileBoot3D(corrconfigs.at(14), anLambdaD22FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(15), anLambdaD24FPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(16), anLambdaD22BPtBoot[bootId], cent, fLambdaMassAxis); - fillProfileBoot3D(corrconfigs.at(17), anLambdaD24BPtBoot[bootId], cent, fLambdaMassAxis); - } - } // end of bootstrap condition - } // end of process + if (cfgUseLsPhi && corrconfigs.at(i).Head.starts_with("LsPhi")) { + int pIndex = findComponent(lsPhiV2, Form("h%spt", corrconfigs.at(i).Head.c_str())); + fillProfileBoot3D(corrconfigs.at(i), lsPhiV2[pIndex], cent, fPhiMassAxis); + + if (cfgUseBootStrap) { + fillProfileBoot3D(corrconfigs.at(i), phiBoot[bootId][pIndex], cent, fPhiMassAxis); + } + } // end of LikeSign phi condition + + if (resoSwitchVals[K0][kUseParticle] && corrconfigs.at(i).Head.starts_with("K0")) { + int pIndex = findComponent(k0V2, Form("h%spt", corrconfigs.at(i).Head.c_str())); + fillProfileBoot3D(corrconfigs.at(i), k0V2[pIndex], cent, fK0MassAxis); + + if (cfgUseBootStrap) { + fillProfileBoot3D(corrconfigs.at(i), k0Boot[bootId][pIndex], cent, fK0MassAxis); + } + } // end of K0 condition + + if (resoSwitchVals[LAMBDA][kUseParticle] && (corrconfigs.at(i).Head.starts_with("Lam") || corrconfigs.at(i).Head.starts_with("AnLam"))) { + int pIndex = findComponent(lambdaV2, Form("h%spt", corrconfigs.at(i).Head.c_str())); + fillProfileBoot3D(corrconfigs.at(i), lambdaV2[pIndex], cent, fLambdaMassAxis); + + if (cfgUseBootStrap) { + fillProfileBoot3D(corrconfigs.at(i), lambdaBoot[bootId][pIndex], cent, fLambdaMassAxis); + } + } // end of lambda condition + + if (configs.GetHeads()[i].starts_with("Ref")) { + int pIndex = findComponent(refV2, Form("h%s", corrconfigs.at(i).Head.c_str())); + fillProfileBoot(corrconfigs.at(i), refV2[pIndex], cent); + + if (cfgUseBootStrap) { + fillProfileBoot(corrconfigs.at(i), refBoot[bootId][pIndex], cent); + } + } // end of ref condition + } // end of loop over correlation configurations + } // end of processReso }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/GenericFramework/Core/BootstrapProfile.h b/PWGCF/GenericFramework/Core/BootstrapProfile.h index a0dfde08509..829c58cc11a 100644 --- a/PWGCF/GenericFramework/Core/BootstrapProfile.h +++ b/PWGCF/GenericFramework/Core/BootstrapProfile.h @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file BootstrapProfile.h/.cxx +/// \brief Derived class from TProfile that stores extra TProfiles for bootstrap samples +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_BOOTSTRAPPROFILE_H_ #define PWGCF_GENERICFRAMEWORK_CORE_BOOTSTRAPPROFILE_H_ diff --git a/PWGCF/GenericFramework/Core/FlowContainer.h b/PWGCF/GenericFramework/Core/FlowContainer.h index 40a379e01a8..bb330c049b6 100644 --- a/PWGCF/GenericFramework/Core/FlowContainer.h +++ b/PWGCF/GenericFramework/Core/FlowContainer.h @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file GFW.h/.cxx +/// \brief Container to store correlations and compute common cumulants +/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_FLOWCONTAINER_H_ #define PWGCF_GENERICFRAMEWORK_CORE_FLOWCONTAINER_H_ #include diff --git a/PWGCF/GenericFramework/Core/GFW.cxx b/PWGCF/GenericFramework/Core/GFW.cxx index 1541aaf8993..350fe752156 100644 --- a/PWGCF/GenericFramework/Core/GFW.cxx +++ b/PWGCF/GenericFramework/Core/GFW.cxx @@ -9,16 +9,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -Class steers the initialization and calculation of n-particle correlations. Uses recursive function, all terms are calculated only once. -Latest version includes the calculation of any number of gaps and any combination of harmonics (including eg symmetric cumulants, etc.) -If used, modified, or distributed, please aknowledge the author of this code. -*/ - #include "GFW.h" +#include +#include +#include +#include + using std::complex; using std::pair; using std::string; diff --git a/PWGCF/GenericFramework/Core/GFW.h b/PWGCF/GenericFramework/Core/GFW.h index 629731bea85..8ec2b78d095 100644 --- a/PWGCF/GenericFramework/Core/GFW.h +++ b/PWGCF/GenericFramework/Core/GFW.h @@ -9,23 +9,22 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -Class steers the initialization and calculation of n-particle correlations. Uses recursive function, all terms are calculated only once. -Latest version includes the calculation of any number of gaps and any combination of harmonics (including eg symmetric cumulants, etc.) -If used, modified, or distributed, please aknowledge the author of this code. -*/ +/// \file GFW.h/.cxx +/// \brief Class steers the initialization and calculation of n-particle correlations. Uses recursive function, all terms are calculated only once. +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_GFW_H_ #define PWGCF_GENERICFRAMEWORK_CORE_GFW_H_ #include "GFWCumulant.h" #include "GFWPowerArray.h" -#include -#include -#include + #include #include +#include +#include +#include +#include class GFW { diff --git a/PWGCF/GenericFramework/Core/GFWCumulant.cxx b/PWGCF/GenericFramework/Core/GFWCumulant.cxx index a82e3bcd08b..f27da24bd27 100644 --- a/PWGCF/GenericFramework/Core/GFWCumulant.cxx +++ b/PWGCF/GenericFramework/Core/GFWCumulant.cxx @@ -9,16 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -A part of -A container to store Q vectors for one subevent with an extra layer to recursively calculate particle correlations. -If used, modified, or distributed, please aknowledge the author of this code. -*/ - #include "GFWCumulant.h" +#include + using std::complex; using std::vector; diff --git a/PWGCF/GenericFramework/Core/GFWCumulant.h b/PWGCF/GenericFramework/Core/GFWCumulant.h index f8cf6624542..2567a2e9c4a 100644 --- a/PWGCF/GenericFramework/Core/GFWCumulant.h +++ b/PWGCF/GenericFramework/Core/GFWCumulant.h @@ -9,13 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/* -Author: Vytautas Vislavicius -Extention of Generic Flow (https://arxiv.org/abs/1312.3572 by A. Bilandzic et al.) -A part of -A container to store Q vectors for one subevent with an extra layer to recursively calculate particle correlations. -If used, modified, or distributed, please aknowledge the author of this code. -*/ +/// \file GFWCumulant.h/.cxx +/// \brief A container to store Q vectors for one subevent with an extra layer to recursively calculate particle correlations. +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_GFWCUMULANT_H_ #define PWGCF_GENERICFRAMEWORK_CORE_GFWCUMULANT_H_ diff --git a/PWGCF/GenericFramework/Core/GFWPowerArray.h b/PWGCF/GenericFramework/Core/GFWPowerArray.h index 82314374e00..ba38f2fcc54 100644 --- a/PWGCF/GenericFramework/Core/GFWPowerArray.h +++ b/PWGCF/GenericFramework/Core/GFWPowerArray.h @@ -9,6 +9,10 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file GFWPowerArray.h/.cxx +/// \brief Class to compute necessary powers of Q-vectors based on input correlations +/// \author Emil Gorm Nielsen, NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_GFWPOWERARRAY_H_ #define PWGCF_GENERICFRAMEWORK_CORE_GFWPOWERARRAY_H_ diff --git a/PWGCF/GenericFramework/Core/ProfileSubset.h b/PWGCF/GenericFramework/Core/ProfileSubset.h index 3d749e06b0e..fc920b898c4 100644 --- a/PWGCF/GenericFramework/Core/ProfileSubset.h +++ b/PWGCF/GenericFramework/Core/ProfileSubset.h @@ -9,9 +9,13 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file ProfileSubset.h/.cxx +/// \brief // Helper class to select a subrange of a TProfile +/// \author Emil Gorm Nielsen (ack. V. Vislavicius), NBI, emil.gorm.nielsen@cern.ch + #ifndef PWGCF_GENERICFRAMEWORK_CORE_PROFILESUBSET_H_ #define PWGCF_GENERICFRAMEWORK_CORE_PROFILESUBSET_H_ -// Helper function to select a subrange of a TProfile + #include "TProfile.h" #include "TProfile2D.h" #include "TError.h" diff --git a/PWGCF/GenericFramework/Tasks/CMakeLists.txt b/PWGCF/GenericFramework/Tasks/CMakeLists.txt index ee71394c4cb..338f173aa73 100644 --- a/PWGCF/GenericFramework/Tasks/CMakeLists.txt +++ b/PWGCF/GenericFramework/Tasks/CMakeLists.txt @@ -13,3 +13,8 @@ o2physics_add_dpl_workflow(flow-generic-framework SOURCES flowGenericFramework.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(flow-gfw-light-ions + SOURCES flowGfwLightIons.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::GFWCore + COMPONENT_NAME Analysis) diff --git a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx index c7d268057e4..79e56fbcff6 100644 --- a/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx +++ b/PWGCF/GenericFramework/Tasks/flowGenericFramework.cxx @@ -97,6 +97,7 @@ struct FlowGenericFramework { 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"); @@ -298,7 +299,8 @@ struct FlowGenericFramework { registry.add("MCGen/before/pt_gen", "", {HistType::kTH1D, {ptAxis}}); registry.add("MCGen/before/phi_eta_vtxZ_gen", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); registry.addClone("MCGen/before/", "MCGen/after/"); - registry.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); + if (doprocessOnTheFly) + registry.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); } if (doprocessMCReco || doprocessData || doprocessRun2) { registry.add("trackQA/before/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); @@ -386,16 +388,6 @@ struct FlowGenericFramework { fMultCutLow->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); fMultCutHigh = new TF1("fMultCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); fMultCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); - /* - 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); */ } 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}; @@ -630,7 +622,7 @@ struct FlowGenericFramework { { if (cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > cfgDCAxyNSigma / 7. * (0.0105f + 0.0035f / track.pt()))) return false; - return ((track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); + return ((track.tpcNClsCrossedRows() >= cfgNTPCXrows) && (track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); } enum DataType { kReco, @@ -1100,7 +1092,7 @@ struct FlowGenericFramework { } 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(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks, aod::McParticles const&) { auto bc = collision.bc_as(); int run = bc.runNumber(); @@ -1141,10 +1133,9 @@ struct FlowGenericFramework { void processOnTheFly(soa::Filtered::iterator const& mcCollision, aod::McParticles const& mcParticles) { - float centrality = -1; int run = 0; registry.fill(HIST("MCGen/impactParameter"), mcCollision.impactParameter(), mcParticles.size()); - processCollision(mcCollision, mcParticles, centrality, run); + processCollision(mcCollision, mcParticles, mcCollision.impactParameter(), run); } PROCESS_SWITCH(FlowGenericFramework, processOnTheFly, "Process analysis for MC on-the-fly generated events", false); diff --git a/PWGCF/GenericFramework/Tasks/flowGfwLightIons.cxx b/PWGCF/GenericFramework/Tasks/flowGfwLightIons.cxx new file mode 100644 index 00000000000..7a74223e5ac --- /dev/null +++ b/PWGCF/GenericFramework/Tasks/flowGfwLightIons.cxx @@ -0,0 +1,1295 @@ +// 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 flowGfwLightIons.cxx +/// \brief Dedicated GFW task to analyse angular correlations in light-ion collision systems +/// \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 "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 "Framework/ASoAHelpers.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 +#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}; + +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; +GFWRegions regions; +GFWCorrConfigs configs; +std::vector multGlobalCorrCutPars; +std::vector multPVCorrCutPars; +std::vector multGlobalPVCorrCutPars; +std::vector multGlobalV0ACutPars; +std::vector multGlobalT0ACutPars; +std::vector firstRunsOfFill; +} // namespace o2::analysis::gfw + +struct FlowGfwLightIons { + + 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(cfgUseNch, bool, false, "Do correlations as function of Nch") + 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(cfgFillFlowRunByRun, bool, false, "Fill flow profile run-by-run (only for v22)") + O2_DEFINE_CONFIGURABLE(cfgTimeDependent, bool, false, "Fill output as function of time (for contamination studies)") + O2_DEFINE_CONFIGURABLE(cfgFirstRunsOfFill, std::vector, {}, "First runs of a fill for time dependent analysis") + 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(cfgUseCentralMoments, bool, true, "Use central moments in vn-pt calculations") + O2_DEFINE_CONFIGURABLE(cfgEfficiency, std::string, "", "CCDB path to efficiency object") + O2_DEFINE_CONFIGURABLE(cfgAcceptance, std::string, "", "CCDB path to acceptance object") + O2_DEFINE_CONFIGURABLE(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(cfgEta, float, 0.8, "eta cut"); + O2_DEFINE_CONFIGURABLE(cfgEtaPtPt, float, 0.4, "eta cut for pt-pt correlations"); + O2_DEFINE_CONFIGURABLE(cfgVtxZ, float, 10, "vertex cut (cm)"); + 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(cfgFixedMultMin, int, 1, "Minimum for fixed nch range"); + O2_DEFINE_CONFIGURABLE(cfgFixedMultMax, int, 3000, "Maximum for fixed nch range"); + O2_DEFINE_CONFIGURABLE(cfgUseMultiplicityFlowWeights, bool, true, "Enable or disable the use of multiplicity-based event weighting"); + 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"); + 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 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"); + 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; + + 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"}; + + // Connect to ccdb + Service ccdb; + + struct Config { + TH1D* mEfficiency = nullptr; + GFWWeights* mAcceptance; + bool correctionsLoaded = false; + } cfg; + + // Define output + OutputObj fFC{FlowContainer("FlowContainer")}; + OutputObj fFCpt{FlowPtContainer("FlowPtContainer")}; + OutputObj fFCgen{FlowContainer("FlowContainer_gen")}; + OutputObj fFCptgen{FlowPtContainer("FlowPtContainer_gen")}; + HistogramRegistry registry{"registry"}; + + // QA outputs + std::map>> th1sList; + std::map>> tpfsList; + std::map>> th3sList; + enum OutputTH1Names { + hPhi = 0, + hEta, + hVtxZ, + hMult, + hCent, + hEventSel, + kCount_TH1Names + }; + enum OutputTProfileNames { + pfCorr22 = 0, + kCount_TProfileNames + }; + // NUA outputs + enum OutputTH3Names { + hNUAref = 0, + kCount_TH3Names + }; + enum CentEstimators { + kCentFT0C = 0, + kCentFT0CVariant1, + kCentFT0M, + kCentFV0A, + kCentNTPV, + kCentNGlobal, + kCentMFT + }; + enum EventSelFlags { + kFilteredEvent = 1, + kSel8, + kOccupancy, + kTVXTRD, + kNoSamebunchPU, + kZVtxFT0PV, + kNoCollTRStd, + kVtxITSTPC, + kGoodITSLayers, + kMultCuts, + kTrackCent + }; + + // Define global variables + // Generic Framework + GFW* fGFW = new GFW(); + std::vector corrconfigs; + + TRandom3* fRndm = new TRandom3(0); + TAxis* fSecondAxis; + int lastRun = -1; + std::vector::iterator firstRunOfCurrentFill; + std::vector runNumbers; + + // Density dependent eff correction + std::vector funcEff; + TH1D* hFindPtBin; + TF1* funcV2; + TF1* funcV3; + TF1* funcV4; + struct DensityCorr { + double psi2Est; + double psi3Est; + double psi4Est; + double v2; + double v3; + double v4; + int density; + DensityCorr() : psi2Est(0.), psi3Est(0.), psi4Est(0.), v2(0.), v3(0.), v4(0.), density(0) {} + }; + + // region indices for consistency flag + int posRegionIndex = -1; + int negRegionIndex = -1; + int fullRegionIndex = -1; + int midRegionIndex = -1; + + // 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; + + 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; + + Preslice perCollision = aod::track::collisionId; + o2::framework::expressions::Filter mcCollFilter = nabs(aod::mccollision::posZ) < cfgVtxZ; + o2::framework::expressions::Filter mcParticlesFilter = (aod::mcparticle::eta > o2::analysis::gfw::etalow && aod::mcparticle::eta < o2::analysis::gfw::etaup && aod::mcparticle::pt > o2::analysis::gfw::ptlow && aod::mcparticle::pt < o2::analysis::gfw::ptup); + + using GFWTracks = soa::Filtered>; + + void init(InitContext const&) + { + LOGF(info, "flowGfwLightIons::init()"); + 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 = cfgPtmin; + o2::analysis::gfw::ptup = 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 = cfgMultGlobalCutPars; + o2::analysis::gfw::multPVCorrCutPars = cfgMultPVCutPars; + o2::analysis::gfw::multGlobalPVCorrCutPars = cfgMultGlobalPVCutPars; + o2::analysis::gfw::multGlobalV0ACutPars = cfgGlobalAsideCorrCuts.cfgMultGlobalV0ACutPars; + o2::analysis::gfw::multGlobalT0ACutPars = cfgGlobalAsideCorrCuts.cfgMultGlobalT0ACutPars; + o2::analysis::gfw::firstRunsOfFill = cfgFirstRunsOfFill; + if (cfgTimeDependent && !std::is_sorted(o2::analysis::gfw::firstRunsOfFill.begin(), o2::analysis::gfw::firstRunsOfFill.end())) { + std::sort(o2::analysis::gfw::firstRunsOfFill.begin(), o2::analysis::gfw::firstRunsOfFill.end()); + } + firstRunOfCurrentFill = o2::analysis::gfw::firstRunsOfFill.begin(); + + AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + 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; + case kCentNGlobal: + sCentralityEstimator = "NGlobals"; + break; + case kCentMFT: + sCentralityEstimator = "MFT"; + break; + default: + sCentralityEstimator = "FT0C"; + break; + } + sCentralityEstimator += " 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}"}; + std::vector bbinning(201); + std::generate(bbinning.begin(), bbinning.end(), [n = -0.1, step = 0.1]() mutable { + n += step; + return n; + }); + AxisSpec bAxis = {bbinning, "#it{b}"}; + 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)"}; + std::vector timebinning(289); + std::generate(timebinning.begin(), timebinning.end(), [n = -24 / 288., step = 24 / 288.]() mutable { + n += step; + return n; + }); + AxisSpec timeAxis = {timebinning, "time (hrs)"}; + + AxisSpec multAxis = (cfgTimeDependent) ? timeAxis : (doprocessOnTheFly && !cfgUseNch) ? bAxis + : (cfgUseNch) ? nchAxis + : 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 = (cfgTimeDependent) ? new TAxis(timeAxis.binEdges.size() - 1, &(timeAxis.binEdges[0])) : new TAxis(ptbins, &o2::analysis::gfw::ptbinning[0]); + + if (doprocessMCGen || doprocessOnTheFly) { + registry.add("MCGen/trackQA/nch_pt", "#it{p}_{T} vs multiplicity; N_{ch}; #it{p}_{T}", {HistType::kTH2D, {nchAxis, ptAxis}}); + registry.add("MCGen/trackQA/phi_eta_vtxZ", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + registry.add("MCGen/trackQA/pt_ref", "Reference #it{p}_{T}; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptreflow, o2::analysis::gfw::ptrefup}}}); + registry.add("MCGen/trackQA/pt_poi", "POI #it{p}_{T}; #it{p}_{T}; Counts", {HistType::kTH1D, {{100, o2::analysis::gfw::ptpoilow, o2::analysis::gfw::ptpoiup}}}); + if (doprocessOnTheFly) + registry.add("MCGen/impactParameter", "", {HistType::kTH2D, {{bAxis, nchAxis}}}); + + registry.add("MCGen/eventQA/multiplicity", "", {HistType::kTH1D, {nchAxis}}); + if (doprocessMCGen) + registry.add("MCGen/eventQA/centrality", "", {HistType::kTH1D, {centAxis}}); + } + if (doprocessMCReco || doprocessData) { + 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/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("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/multiplicity", "", {HistType::kTH1D, {nchAxis}}); + if (cfgTimeDependent) { + registry.add("eventQA/before/multiplicity_time", "Multiplicity vs time; time (hrs); N_{ch}", {HistType::kTH2D, {timeAxis, nchAxis}}); + registry.add("eventQA/before/multT0C_time", "T0C Multiplicity vs time; time (hrs); N_{ch} (T0C)", {HistType::kTH2D, {timeAxis, t0cAxis}}); + registry.add("eventQA/before/multT0A_time", "T0A Multiplicity vs time; time (hrs); N_{ch} (T0A)", {HistType::kTH2D, {timeAxis, t0aAxis}}); + registry.add("eventQA/before/multV0A_time", "V0A Multiplicity vs time; time (hrs); N_{ch} (V0A)", {HistType::kTH2D, {timeAxis, v0aAxis}}); + registry.add("eventQA/before/multPV_time", "PV Multiplicity vs time; time (hrs); N_{ch} (PV)", {HistType::kTH2D, {timeAxis, 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, {v0aAxis, nchAxis}}); + registry.add("eventQA/before/multV0A_multT0A", "", {HistType::kTH2D, {t0aAxis, v0aAxis}}); + + if (doprocessData || doprocessMCReco) { + registry.add("eventQA/before/centrality", "", {HistType::kTH1D, {centAxis}}); + 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.addClone("eventQA/before/", "eventQA/after/"); + registry.add("eventQA/eventSel", "Number of Events;; Counts", {HistType::kTH1D, {{11, 0.5, 11.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(kTVXTRD, "kTVXinTRD"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoSamebunchPU, "kNoSameBunchPileup"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kZVtxFT0PV, "kIsGoodZvtxFT0vsPV"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kNoCollTRStd, "kNoCollInTimeRangeStandard"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kVtxITSTPC, "kIsVertexITSTPC"); + registry.get(HIST("eventQA/eventSel"))->GetXaxis()->SetBinLabel(kGoodITSLayers, "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 (!cfgRunByRun && cfgFillWeights) { + registry.add("phi_eta_vtxz_ref", "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + } + } + + 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); + if (doprocessData || doprocessMCReco) { + fFC->SetName("FlowContainer"); + fFC->SetXAxis(fSecondAxis); + fFC->Initialize(oba, multAxis, cfgNbootstrap); + } + if (doprocessMCGen || doprocessOnTheFly) { + fFCgen->SetName("FlowContainer_gen"); + fFCgen->SetXAxis(fSecondAxis); + fFCgen->Initialize(oba, multAxis, cfgNbootstrap); + } + delete oba; + fFCpt->setUseCentralMoments(cfgUseCentralMoments); + fFCpt->setUseGapMethod(true); + fFCpt->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); + fFCptgen->setUseCentralMoments(cfgUseCentralMoments); + fFCptgen->setUseGapMethod(true); + fFCptgen->initialise(multAxis, cfgMpar, o2::analysis::gfw::configs, cfgNbootstrap); + + fPtDepDCAxy = new TF1("ptDepDCAxy", Form("[0]*%s", cfgDCAxy->c_str()), 0.001, 100); + fPtDepDCAxy->SetParameter(0, cfgDCAxyNSigma); + LOGF(info, "DCAxy pt-dependence function: %s", Form("[0]*%s", cfgDCAxy->c_str())); + if (cfgUseAdditionalEventCut) { + fMultPVCutLow = new TF1("fMultPVCutLow", cfgMultCorrLowCutFunction->c_str(), 0, 100); + fMultPVCutLow->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); + fMultPVCutHigh = new TF1("fMultPVCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultPVCutHigh->SetParameters(&(o2::analysis::gfw::multPVCorrCutPars[0])); + fMultCutLow = new TF1("fMultCutLow", cfgMultCorrLowCutFunction->c_str(), 0, 100); + fMultCutLow->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); + fMultCutHigh = new TF1("fMultCutHigh", cfgMultCorrHighCutFunction->c_str(), 0, 100); + fMultCutHigh->SetParameters(&(o2::analysis::gfw::multGlobalCorrCutPars[0])); + fMultPVGlobalCutHigh = new TF1("fMultPVGlobalCutHigh", 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 (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]); + funcEff.resize(pTEffBins.size() - 1); + // LHC24g3 Eff + std::vector f1p0 = cfgTrackDensityP0; + std::vector f1p1 = cfgTrackDensityP1; + for (uint ifunc = 0; ifunc < pTEffBins.size() - 1; ifunc++) { + funcEff[ifunc] = new TF1(Form("funcEff%i", ifunc), "[0]+[1]*x", 0, 3000); + funcEff[ifunc]->SetParameters(f1p0[ifunc], f1p1[ifunc]); + } + funcV2 = new TF1("funcV2", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); + funcV2->SetParameters(0.0186111, 0.00351907, -4.38264e-05, 1.35383e-07, -3.96266e-10); + funcV3 = new TF1("funcV3", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); + funcV3->SetParameters(0.0174056, 0.000703329, -1.45044e-05, 1.91991e-07, -1.62137e-09); + funcV4 = new TF1("funcV4", "[0]+[1]*x+[2]*x*x+[3]*x*x*x+[4]*x*x*x*x", 0, 100); + funcV4->SetParameters(0.008845, 0.000259668, -3.24435e-06, 4.54837e-08, -6.01825e-10); + } + 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; + }(); + } + } + + 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())); + } + } + } + + int getMagneticField(uint64_t timestamp) + { + 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(); + } + + void loadCorrections(aod::BCsWithTimestamps::iterator const& bc) + { + uint64_t timestamp = bc.timestamp(); + if (!cfgRunByRun && cfg.correctionsLoaded) + return; + if (!cfgAcceptance.value.empty()) { + std::string runstr = (cfgRunByRun) ? "RunByRun/" : ""; + cfg.mAcceptance = ccdb->getForTimeStamp(cfgAcceptance.value + runstr, timestamp); + } + 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()); + } + LOGF(info, "Loaded efficiency histogram from %s (%p)", cfgEfficiency.value.c_str(), (void*)cfg.mEfficiency); + } + cfg.correctionsLoaded = true; + } + + 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) + { + double eff = 1.; + if (cfg.mEfficiency) + eff = cfg.mEfficiency->GetBinContent(cfg.mEfficiency->FindBin(track.pt())); + if (eff == 0) + return -1.; + else + return 1. / eff; + } + + template + bool eventSelected(TCollision collision, const int& multTrk, const float& centrality, const int& run) + { + if (cfgTVXinTRD) { + if (collision.alias_bit(kTVXinTRD)) { + // TRD triggered + // "CMTVX-B-NOPF-TRD,minbias_TVX" + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kTVXTRD); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kTVXTRD); + } + 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"), kNoSamebunchPU); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kNoSamebunchPU); + } + if (cfgIsGoodZvtxFT0vsPV) { + if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference + // use this cut at low multiplicities with caution + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kZVtxFT0PV); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kZVtxFT0PV); + } + 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"), kNoCollTRStd); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kNoCollTRStd); + } + + 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"), kVtxITSTPC); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kVtxITSTPC); + } + + if (cfgIsGoodITSLayersAll) { + if (!collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return 0; + } + registry.fill(HIST("eventQA/eventSel"), kGoodITSLayers); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kGoodITSLayers); + } + + 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; + + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFV0A()) < fMultGlobalV0ACutLow->Eval(multTrk)) + return 0; + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFV0A()) > fMultGlobalV0ACutHigh->Eval(multTrk)) + return 0; + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFT0A()) < fMultGlobalT0ACutLow->Eval(multTrk)) + return 0; + if (!(cfgGlobalAsideCorrCuts.cfgMultGlobalASideCorrCutFunction->empty()) && static_cast(collision.multFT0A()) > fMultGlobalT0ACutHigh->Eval(multTrk)) + return 0; + registry.fill(HIST("eventQA/eventSel"), kMultCuts); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kMultCuts); + } + return 1; + } + + template + bool trackSelected(TTrack track) + { + if (cfgDCAxyNSigma && (std::fabs(track.dcaXY()) > fPtDepDCAxy->Eval(track.pt()))) + return false; + return ((track.tpcNClsCrossedRows() >= cfgNTPCXrows) && (track.tpcNClsFound() >= cfgNTPCCls) && (track.itsNCls() >= cfgMinNITSCls)); + } + + enum DataType { + kReco, + kGen + }; + + template + void fillWeights(const TTrack track, const double vtxz, const int& run) + { + if (cfgRunByRun) + th3sList[run][hNUAref]->Fill(track.phi(), track.eta(), vtxz); + else + registry.fill(HIST("phi_eta_vtxz_ref"), track.phi(), track.eta(), vtxz); + return; + } + + void createRunByRunHistograms(const int& run) + { + AxisSpec phiAxis = {o2::analysis::gfw::phibins, o2::analysis::gfw::philow, o2::analysis::gfw::phiup, "#phi"}; + 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 (%)"}; + 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}}); + histos[hVtxZ] = registry.add(Form("%d/vtxz", run), "", {HistType::kTH1D, {vtxAxis}}); + histos[hMult] = registry.add(Form("%d/mult", run), "", {HistType::kTH1D, {nchAxis}}); + histos[hCent] = registry.add(Form("%d/cent", run), "", {HistType::kTH1D, {centAxis}}); + if (cfgFillFlowRunByRun) { + std::vector> profiles(kCount_TProfileNames); + profiles[pfCorr22] = registry.add(Form("%d/corr22", run), "", {HistType::kTProfile, {(cfgUseNch) ? nchAxis : centAxis}}); + tpfsList.insert(std::make_pair(run, profiles)); + } + histos[hEventSel] = registry.add(Form("%d/eventSel", run), "Number of Events;; Counts", {HistType::kTH1D, {{11, 0.5, 11.5}}}); + histos[hEventSel]->GetXaxis()->SetBinLabel(kFilteredEvent, "Filtered event"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kSel8, "sel8"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kOccupancy, "occupancy"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kTVXTRD, "kTVXinTRD"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kNoSamebunchPU, "kNoSameBunchPileup"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kZVtxFT0PV, "kIsGoodZvtxFT0vsPV"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kNoCollTRStd, "kNoCollInTimeRangeStandard"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kVtxITSTPC, "kIsVertexITSTPC"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kGoodITSLayers, "kIsGoodITSLayersAll"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kMultCuts, "after Mult cuts"); + histos[hEventSel]->GetXaxis()->SetBinLabel(kTrackCent, "has track + within cent"); + th1sList.insert(std::make_pair(run, histos)); + std::vector> histos3d(kCount_TH3Names); + histos3d[hNUAref] = registry.add(Form("%d/phi_eta_vtxz_ref", run), "", {HistType::kTH3D, {phiAxis, etaAxis, vtxAxis}}); + th3sList.insert(std::make_pair(run, histos3d)); + return; + } + + template + void fillOutputContainers(const float& centmult, const double& rndm, const int& run = 0) + { + (dt == kGen) ? fFCptgen->calculateCorrelations() : fFCpt->calculateCorrelations(); + (dt == kGen) ? fFCptgen->fillPtProfiles(centmult, rndm) : fFCpt->fillPtProfiles(centmult, rndm); + (dt == kGen) ? fFCptgen->fillCMProfiles(centmult, rndm) : fFCpt->fillCMProfiles(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(); + if (dnx == 0) + continue; + 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, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm) : fFC->FillProfile(corrconfigs.at(l_ind).Head.c_str(), centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm); + (dt == kGen) ? fFCptgen->fillVnPtProfiles(centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]) : fFCpt->fillVnPtProfiles(centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm, o2::analysis::gfw::configs.GetpTCorrMasks()[l_ind]); + if (cfgRunByRun && cfgFillFlowRunByRun && dt != kGen && l_ind == 0) { + tpfsList[run][pfCorr22]->Fill(centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0); + } + } + continue; + } + for (int i = 1; i <= fSecondAxis->GetNbins(); i++) { + auto dnx = fGFW->Calculate(corrconfigs.at(l_ind), i - 1, kTRUE).real(); + if (dnx == 0) + continue; + auto val = fGFW->Calculate(corrconfigs.at(l_ind), i - 1, kFALSE).real() / dnx; + if (std::abs(val) < 1) + (dt == kGen) ? fFCgen->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm) : fFC->FillProfile(Form("%s_pt_%i", corrconfigs.at(l_ind).Head.c_str(), i), centmult, val, (cfgUseMultiplicityFlowWeights) ? dnx : 1.0, rndm); + } + } + 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) + { + if (tracks.size() < 1) + return; + if (dt != kGen && 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; + if (dt != kGen) { + registry.fill(HIST("eventQA/eventSel"), kTrackCent); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kTrackCent); + } + if (xaxis.centrality >= 0) + registry.fill(HIST("eventQA/after/centrality"), xaxis.centrality); + registry.fill(HIST("eventQA/after/multiplicity"), xaxis.multiplicity); + float vtxz = collision.posZ(); + if (dt != kGen && cfgRunByRun) { + th1sList[run][hVtxZ]->Fill(vtxz); + th1sList[run][hMult]->Fill(xaxis.multiplicity); + th1sList[run][hCent]->Fill(xaxis.centrality); + } + fGFW->Clear(); + (dt == kGen) ? fFCptgen->clearVector() : fFCpt->clearVector(); + + float lRandom = fRndm->Rndm(); + + // be cautious, this only works for Pb-Pb + // esimate the Event plane and vn for this event + DensityCorr densitycorrections; + if (cfgUseDensityDependentCorrection) { + double psi2Est = 0, psi3Est = 0, psi4Est = 0; + double v2 = 0, v3 = 0, v4 = 0; + double q2x = 0, q2y = 0; + double q3x = 0, q3y = 0; + double q4x = 0, q4y = 0; + for (const auto& track : tracks) { + bool withinPtRef = (o2::analysis::gfw::ptreflow < track.pt()) && (track.pt() < o2::analysis::gfw::ptrefup); // within RF pT rang + if (withinPtRef) { + q2x += std::cos(2 * track.phi()); + q2y += std::sin(2 * track.phi()); + q3x += std::cos(3 * track.phi()); + q3y += std::sin(3 * track.phi()); + q4x += std::cos(4 * track.phi()); + q4y += std::sin(4 * track.phi()); + } + } + psi2Est = std::atan2(q2y, q2x) / 2.; + psi3Est = std::atan2(q3y, q3x) / 3.; + psi4Est = std::atan2(q4y, q4x) / 4.; + v2 = funcV2->Eval(xaxis.centrality); + v3 = funcV3->Eval(xaxis.centrality); + v4 = funcV4->Eval(xaxis.centrality); + densitycorrections.psi2Est = psi2Est; + densitycorrections.psi3Est = psi3Est; + densitycorrections.psi4Est = psi4Est; + densitycorrections.v2 = v2; + densitycorrections.v3 = v3; + densitycorrections.v4 = v4; + densitycorrections.density = tracks.size(); + } + AcceptedTracks acceptedTracks{0, 0, 0, 0}; + for (const auto& track : tracks) { + processTrack(track, vtxz, xaxis.multiplicity, run, densitycorrections, acceptedTracks); + 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; + } + if (!cfgFillWeights) + fillOutputContainers
((cfgTimeDependent) ? xaxis.time : (cfgUseNch) ? xaxis.multiplicity + : xaxis.centrality, + lRandom, run); + } + + bool isStable(int pdg) + { + if (std::abs(pdg) == PDG_t::kPiPlus) + return true; + if (std::abs(pdg) == PDG_t::kKPlus) + return true; + if (std::abs(pdg) == PDG_t::kProton) + return true; + if (std::abs(pdg) == PDG_t::kElectron) + return true; + if (std::abs(pdg) == PDG_t::kMuonMinus) + return true; + return false; + } + + 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 + inline void processTrack(TTrack const& track, const float& vtxz, const int& multiplicity, const int& run, DensityCorr densitycorrections, AcceptedTracks& acceptedTracks) + { + if constexpr (framework::has_type_v) { + if (track.mcParticleId() < 0 || !(track.has_mcParticle())) + return; + + auto mcParticle = track.mcParticle(); + if (!mcParticle.isPhysicalPrimary()) + return; + if (!isStable(mcParticle.pdgCode())) + return; + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/before/nch_pt"), multiplicity, track.pt()); + } + if (!trackSelected(track)) + return; + + if (cfgFillWeights) { + fillWeights(track, vtxz, run); + } else { + fillPtSums(track); + fillGFW(track, vtxz, densitycorrections); + fillAcceptedTracks(track, acceptedTracks); + } + + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/after/nch_pt"), multiplicity, track.pt()); + if (cfgRunByRun) { + th1sList[run][hPhi]->Fill(track.phi()); + th1sList[run][hEta]->Fill(track.eta()); + } + } + + } else if constexpr (framework::has_type_v) { + if (!track.isPhysicalPrimary() || !isStable(track.pdgCode())) + return; + + fillPtSums(track); + fillGFW(track, vtxz, densitycorrections); + fillAcceptedTracks(track, acceptedTracks); + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("MCGen/trackQA/nch_pt"), multiplicity, track.pt()); + } + } else { + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/before/nch_pt"), multiplicity, track.pt()); + } + if (!trackSelected(track)) + return; + + if (cfgFillWeights) { + fillWeights(track, vtxz, run); + } else { + fillPtSums(track); + fillGFW(track, vtxz, densitycorrections); + fillAcceptedTracks(track, acceptedTracks); + } + if (cfgFillQA) { + fillTrackQA(track, vtxz); + registry.fill(HIST("trackQA/after/nch_pt"), multiplicity, track.pt()); + if (cfgRunByRun) { + th1sList[run][hPhi]->Fill(track.phi()); + th1sList[run][hEta]->Fill(track.eta()); + th3sList[run][hNUAref]->Fill(track.phi(), track.eta(), vtxz, getAcceptance(track, vtxz)); + } + } + } + return; + } + + template + inline void fillGFW(TTrack track, const double& vtxz, DensityCorr densitycorrections) + { + 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 = (dt == kGen) ? 1. : getEfficiency(track); + if (weff < 0) + return; + if (cfgUseDensityDependentCorrection && withinPtRef && dt != kGen) { + double fphi = densitycorrections.v2 * std::cos(2 * (track.phi() - densitycorrections.psi2Est)) + densitycorrections.v3 * std::cos(3 * (track.phi() - densitycorrections.psi3Est)) + densitycorrections.v4 * std::cos(4 * (track.phi() - densitycorrections.psi4Est)); + fphi = (1 + 2 * fphi); + int pTBinForEff = hFindPtBin->FindBin(track.pt()); + if (pTBinForEff >= 1 && pTBinForEff <= hFindPtBin->GetNbinsX()) { + float wEPeff = funcEff[pTBinForEff - 1]->Eval(fphi * densitycorrections.density); + if (wEPeff > 0.) { + wEPeff = 1. / wEPeff; + weff *= wEPeff; + } + } + } + double wacc = (dt == kGen) ? 1. : getAcceptance(track, vtxz); + if (withinPtRef) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 1); + if (withinPtPOI) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 2); + if (withinPtRef && withinPtPOI) + fGFW->Fill(track.eta(), fSecondAxis->FindBin(track.pt()) - 1, track.phi(), weff * wacc, 4); + return; + } + + template + inline void fillPtSums(TTrack track) + { + double weff = (dt == kGen) ? 1. : getEfficiency(track); + if (weff < 0) + return; + if (std::abs(track.eta()) < cfgEtaPtPt && track.pt() > o2::analysis::gfw::ptreflow && track.pt() < o2::analysis::gfw::ptrefup) { + (dt == kGen) ? fFCptgen->fill(1., track.pt()) : fFCpt->fill(weff, track.pt()); + } + } + + template + inline void fillTrackQA(TTrack track, const float vtxz) + { + if constexpr (dt == kGen) { + registry.fill(HIST("MCGen/trackQA/phi_eta_vtxZ"), track.phi(), track.eta(), vtxz); + registry.fill(HIST("MCGen/trackQA/pt_ref"), track.pt()); + registry.fill(HIST("MCGen/trackQA/pt_poi"), track.pt()); + } else { + 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()); + } + } + } + + 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(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()); + if (cfgTimeDependent) { + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multiplicity_time"), xaxis.time, xaxis.multiplicity); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multT0C_time"), xaxis.time, collision.multFT0C()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multT0A_time"), xaxis.time, collision.multFT0A()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multV0A_time"), xaxis.time, collision.multFV0A()); + registry.fill(HIST("eventQA/") + HIST(FillTimeName[ft]) + HIST("multPV_time"), xaxis.time, collision.multNTracksPV()); + } + return; + } + + double getTimeSinceStartOfFill(uint64_t timestamp, int firstRun) + { + auto runDuration = ccdb->getRunDuration(firstRun); + uint64_t tsSOF = runDuration.first; + uint64_t diff = timestamp - tsSOF; + return static_cast(diff) / 3600000.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); + if (cfgRunByRun) { + if (std::find(runNumbers.begin(), runNumbers.end(), run) == runNumbers.end()) { + LOGF(info, "Creating histograms for run %d", run); + createRunByRunHistograms(run); + runNumbers.push_back(run); + } else { + LOGF(info, "run %d already in runNumbers", run); + } + if (!cfgFillWeights) + loadCorrections(bc); + } + } + if (!cfgFillWeights && !cfgRunByRun) + loadCorrections(bc); + registry.fill(HIST("eventQA/eventSel"), kFilteredEvent); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kFilteredEvent); + if (!collision.sel8()) + return; + registry.fill(HIST("eventQA/eventSel"), kSel8); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kSel8); + if (cfgDoOccupancySel) { + int occupancy = collision.trackOccupancyInTimeRange(); + if (occupancy < 0 || occupancy > cfgOccupancySelection) + return; + } + registry.fill(HIST("eventQA/eventSel"), kOccupancy); + if (cfgRunByRun) + th1sList[run][hEventSel]->Fill(kOccupancy); + + const XAxis xaxis{getCentrality(collision), tracks.size(), (cfgTimeDependent) ? getTimeSinceStartOfFill(bc.timestamp(), *firstRunOfCurrentFill) : -1.0}; + if (cfgTimeDependent && run == *firstRunOfCurrentFill && firstRunOfCurrentFill != o2::analysis::gfw::firstRunsOfFill.end() - 1) + ++firstRunOfCurrentFill; + + 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, run)) + return; + if (cfgFillQA) + fillEventQA(collision, xaxis); + processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwLightIons, 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&) + { + auto bc = collision.bc_as(); + int run = bc.runNumber(); + if (run != lastRun) { + lastRun = run; + if (cfgRunByRun) + createRunByRunHistograms(run); + } + if (!collision.sel8()) + return; + + const XAxis xaxis{getCentrality(collision), tracks.size(), (cfgTimeDependent) ? getTimeSinceStartOfFill(bc.timestamp(), *firstRunOfCurrentFill) : -1.0}; + if (cfgTimeDependent && run == *firstRunOfCurrentFill && firstRunOfCurrentFill != o2::analysis::gfw::firstRunsOfFill.end() - 1) + ++firstRunOfCurrentFill; + + 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, run)) + return; + if (cfgFillQA) + fillEventQA(collision, xaxis); + if (!cfgFillWeights) + loadCorrections(bc); + processCollision(collision, tracks, xaxis, run); + } + PROCESS_SWITCH(FlowGfwLightIons, processMCReco, "Process analysis for MC reconstructed events", false); + + void processMCGen(soa::Filtered::iterator const& mcCollision, soa::SmallGroups> const& collisions, aod::McParticles const& particles, GFWTracks const& tracks) + { + if (collisions.size() != 1) + return; + float centrality = -1; + for (const auto& collision : collisions) { + centrality = getCentrality(collision); + } + + std::vector numberOfTracks; + for (auto const& collision : collisions) { + auto groupedTracks = tracks.sliceBy(perCollision, collision.globalIndex()); + numberOfTracks.emplace_back(groupedTracks.size()); + } + + const XAxis xaxis{centrality, numberOfTracks[0], -1.0}; + int run = 0; + processCollision(mcCollision, particles, xaxis, run); + } + PROCESS_SWITCH(FlowGfwLightIons, processMCGen, "Process analysis for MC generated events", false); + + void processOnTheFly(soa::Filtered::iterator const& mcCollision, aod::McParticles const& mcParticles) + { + int run = 0; + registry.fill(HIST("MCGen/impactParameter"), mcCollision.impactParameter(), mcParticles.size()); + const XAxis xaxis{mcCollision.impactParameter(), mcParticles.size(), -1.0}; + processCollision(mcCollision, mcParticles, xaxis, run); + } + PROCESS_SWITCH(FlowGfwLightIons, processOnTheFly, "Process analysis for MC on-the-fly generated events", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGCF/JCorran/Core/JFFlucAnalysis.cxx b/PWGCF/JCorran/Core/JFFlucAnalysis.cxx index 9dc4189a810..4c3b01adeca 100644 --- a/PWGCF/JCorran/Core/JFFlucAnalysis.cxx +++ b/PWGCF/JCorran/Core/JFFlucAnalysis.cxx @@ -12,10 +12,12 @@ /// \author Jasper Parkkila (jparkkil@cern.ch) /// \since Sep 2022 -#include +#include "JFFlucAnalysis.h" + #include +#include + #include -#include "JFFlucAnalysis.h" JFFlucAnalysis::JFFlucAnalysis() : TNamed(), fVertex(0), diff --git a/PWGCF/JCorran/Core/JFFlucAnalysis.h b/PWGCF/JCorran/Core/JFFlucAnalysis.h index 01589a09849..b728c809173 100644 --- a/PWGCF/JCorran/Core/JFFlucAnalysis.h +++ b/PWGCF/JCorran/Core/JFFlucAnalysis.h @@ -15,13 +15,16 @@ #ifndef PWGCF_JCORRAN_CORE_JFFLUCANALYSIS_H_ #define PWGCF_JCORRAN_CORE_JFFLUCANALYSIS_H_ -#include #include "JQVectors.h" + #include -#include #include #include #include +#include + +#include +#include class JFFlucAnalysis : public TNamed { @@ -61,7 +64,6 @@ class JFFlucAnalysis : public TNamed enum HIST_THN { HIST_THN_PHIETAZ, HIST_THN_PTETA, - HIST_THN_PHIETA, HIST_THN_SC_with_QC_4corr, HIST_THN_SC_with_QC_2corr, HIST_THN_SC_with_QC_2corr_gap, @@ -98,6 +100,7 @@ class JFFlucAnalysis : public TNamed enum HIST_THN_SPARSE { HIST_THN_SPARSE_VN, HIST_THN_SPARSE_VN_VN, + HIST_THN_SPARSE_MULTCORR, HIST_THN_SPARSE_COUNT }; enum { @@ -144,29 +147,42 @@ class JFFlucAnalysis : public TNamed using hasWeightEff = decltype(std::declval().weightEff()); template using hasSign = decltype(std::declval().sign()); + template + using hasMultSet = decltype(std::declval().multiplicities()); template inline void FillQA(JInputClass& inputInst, UInt_t type = 0u) { - ph1[HIST_TH1_CENTRALITY]->Fill(fCent); - ph1[HIST_TH1_IMPACTPARAM]->Fill(fImpactParameter); + if (type == 0u) { + ph1[HIST_TH1_CENTRALITY]->Fill(fCent); + ph1[HIST_TH1_ZVERTEX]->Fill(fVertex); + ph1[HIST_TH1_IMPACTPARAM]->Fill(fImpactParameter); + } for (auto& track : inputInst) { Double_t corrInv = 1.0; using JInputClassIter = typename JInputClass::iterator; if constexpr (std::experimental::is_detected::value) - corrInv /= track.weightEff(); + corrInv *= track.weightEff(); if constexpr (std::experimental::is_detected::value) pht[HIST_THN_PTETA]->Fill(fCent, track.pt(), track.eta(), track.sign(), corrInv); else pht[HIST_THN_PTETA]->Fill(fCent, track.pt(), track.eta(), 0.0, corrInv); if constexpr (std::experimental::is_detected::value) corrInv /= track.weightNUA(); - pht[HIST_THN_PHIETA]->Fill(fCent, track.phi(), track.eta(), corrInv); pht[HIST_THN_PHIETAZ]->Fill(fCent, static_cast(type), track.phi(), track.eta(), fVertex, corrInv); } + } - ph1[HIST_TH1_ZVERTEX]->Fill(fVertex); + template + inline void FillMultSet(JEventClass& event) + { + // + if constexpr (std::experimental::is_detected::value) { + // need to convert to vec of doubles since THnSparse has no way to fill vec of floats directly + std::vector v(event.multiplicities().begin(), event.multiplicities().end()); + phs[HIST_THN_SPARSE_MULTCORR]->Fill(v.data()); + } } #define kcNH kH4 // max second dimension + 1 diff --git a/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx b/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx index b3419ff7dc8..502a14c6b28 100644 --- a/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx +++ b/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.cxx @@ -12,24 +12,41 @@ /// \since Sep 2024 #include "JFFlucAnalysisO2Hist.h" -#include -#include + +#include "PWGCF/DataModel/CorrelationsDerived.h" + #include "CommonConstants/MathConstants.h" +#include +#include + using namespace o2; -JFFlucAnalysisO2Hist::JFFlucAnalysisO2Hist(HistogramRegistry& registry, AxisSpec& axisMultiplicity, AxisSpec& phiAxis, AxisSpec& etaAxis, AxisSpec& zvtAxis, AxisSpec& ptAxis, AxisSpec& massAxis, const TString& folder) : JFFlucAnalysis() +JFFlucAnalysisO2Hist::JFFlucAnalysisO2Hist(HistogramRegistry& registry, AxisSpec& axisMultiplicity, AxisSpec& phiAxis, AxisSpec& etaAxis, AxisSpec& zvtAxis, AxisSpec& ptAxis, AxisSpec& massAxis, uint16_t multCorrMask, const TString& folder) : JFFlucAnalysis() { ph1[HIST_TH1_CENTRALITY] = std::get>(registry.add(Form("%s/h_cent", folder.Data()), "multiplicity/centrality", {HistType::kTH1F, {axisMultiplicity}})).get(); ph1[HIST_TH1_IMPACTPARAM] = std::get>(registry.add(Form("%s/h_IP", folder.Data()), "impact parameter", {HistType::kTH1F, {{400, -2.0, 20.0}}})).get(); ph1[HIST_TH1_ZVERTEX] = std::get>(registry.add(Form("%s/h_vertex", folder.Data()), "z vertex", {HistType::kTH1F, {{100, -20.0, 20.0}}})).get(); + if (multCorrMask != 0) { + std::vector multAxes; + if (multCorrMask & aod::cfmultset::CentFT0C) + multAxes.emplace_back(100, 0, 100, "FT0C centrality"); + if (multCorrMask & aod::cfmultset::MultFV0A) + multAxes.emplace_back(100, 0, 100000, "V0A multiplicity"); + if (multCorrMask & aod::cfmultset::MultNTracksPV) + multAxes.emplace_back(100, 0, 1000, "Nch PV"); + if (multCorrMask & aod::cfmultset::MultNTracksGlobal) + multAxes.emplace_back(100, 0, 1000, "Nch Global"); + registry.add("multCorrelations", "Multiplicity correlations", {HistType::kTHnSparseF, multAxes}); + phs[HIST_THN_SPARSE_MULTCORR] = std::get>(registry.add(Form("%s/h_multcorr", folder.Data()), "multiplicity/centrality correlations", {HistType::kTHnSparseF, multAxes})).get(); + } + AxisSpec chgAxis = {3, -1.5, 1.5, "charge"}; AxisSpec typeAxis = {2, -0.5, 1.5, "type"}; - pht[HIST_THN_PHIETAZ] = std::get>(registry.add(Form("%s/h_phietaz", folder.Data()), "multiplicity/centrality, type, phi, eta, z", {HistType::kTHnSparseF, {axisMultiplicity, typeAxis, phiAxis, etaAxis, zvtAxis}})).get(); + pht[HIST_THN_PHIETAZ] = std::get>(registry.add(Form("%s/h_phietaz", folder.Data()), "(corrected) multiplicity/centrality, type, phi, eta, z", {HistType::kTHnSparseF, {axisMultiplicity, typeAxis, phiAxis, etaAxis, zvtAxis}})).get(); pht[HIST_THN_PTETA] = std::get>(registry.add(Form("%s/h_pteta", folder.Data()), "(corrected) multiplicity/centrality, pT, eta, charge", {HistType::kTHnSparseF, {axisMultiplicity, ptAxis, etaAxis, chgAxis}})).get(); - pht[HIST_THN_PHIETA] = std::get>(registry.add(Form("%s/h_phieta", folder.Data()), "(corrected) multiplicity/centrality, phi, eta", {HistType::kTHnSparseF, {axisMultiplicity, phiAxis, etaAxis}})).get(); AxisSpec hAxis = {kNH, -0.5, static_cast(kNH - 1) + 0.5, "#it{n}"}; AxisSpec kAxis = {nKL, -0.5, static_cast(nKL - 1) + 0.5, "#it{k}"}; AxisSpec vnAxis = {2048, -0.1, 0.1, "#it{V}_#it{n}"}; diff --git a/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.h b/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.h index a9de2fd7864..8821c64a225 100644 --- a/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.h +++ b/PWGCF/JCorran/Core/JFFlucAnalysisO2Hist.h @@ -15,6 +15,7 @@ #define PWGCF_JCORRAN_CORE_JFFLUCANALYSISO2HIST_H_ #include "JFFlucAnalysis.h" + #include "Framework/HistogramRegistry.h" using namespace o2; @@ -23,7 +24,7 @@ using namespace o2::framework; class JFFlucAnalysisO2Hist : public JFFlucAnalysis { public: - JFFlucAnalysisO2Hist(HistogramRegistry&, AxisSpec&, AxisSpec&, AxisSpec&, AxisSpec&, AxisSpec&, AxisSpec&, const TString&); + JFFlucAnalysisO2Hist(HistogramRegistry&, AxisSpec&, AxisSpec&, AxisSpec&, AxisSpec&, AxisSpec&, AxisSpec&, uint16_t, const TString&); ~JFFlucAnalysisO2Hist(); }; diff --git a/PWGCF/JCorran/Core/JQVectors.h b/PWGCF/JCorran/Core/JQVectors.h index c96aac454b7..01693ae6073 100644 --- a/PWGCF/JCorran/Core/JQVectors.h +++ b/PWGCF/JCorran/Core/JQVectors.h @@ -84,7 +84,7 @@ class JQVectors : public std::conditional_t, JQ if constexpr (std::experimental::is_detected::value) tf /= track.weightNUA(); if constexpr (std::experimental::is_detected::value) - tf /= track.weightEff(); + tf *= track.weightEff(); } } } diff --git a/PWGCF/JCorran/Tasks/jFlucEfficiencyTask.cxx b/PWGCF/JCorran/Tasks/jFlucEfficiencyTask.cxx index 59ca8b18903..4ca33837d1e 100644 --- a/PWGCF/JCorran/Tasks/jFlucEfficiencyTask.cxx +++ b/PWGCF/JCorran/Tasks/jFlucEfficiencyTask.cxx @@ -49,6 +49,8 @@ struct JFlucEfficiencyTask { 170.0, 180.0, 190.0, 200.0, 210.0, 220.0, 230.0, 240.0, 250.0, 260.0, 270.0, 280.0, 290.0, 300.0}; + static constexpr double kChargeThreshold = 3.0; // PDG charge units: 3 = |e| + // Update the axisPt configuration with proper vector initialization ConfigurableAxis axisPt{"axisPt", std::vector(PttJacek.begin(), PttJacek.end()), "pT axis"}; @@ -105,6 +107,8 @@ struct JFlucEfficiencyTask { Configurable cfgMaxbDCAzToPVcut{"cfgMaxbDCAzToPVcut", 1.0, "Track DCAz cut to PV Maximum"}; } TrackCuts; + Configurable applyMCStudy{"applyMCStudy", false, "Apply MC study"}; + // Configurable for track selection Configurable trackSelection{"trackSelection", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; @@ -175,8 +179,16 @@ struct JFlucEfficiencyTask { o2::framework::HistType::kTH2F, {AxisSpec(100, -1, 1), AxisSpec(axisMultiplicity)}); registry.add("hPtGenPos", "Generated p_{T} (positive);p_{T} (GeV/c);Centrality (%);Counts", o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtGenPos_Pos", "Generated p_{T} (positive) in TPC positive side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtGenPos_Neg", "Generated p_{T} (positive) in TPC negative side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); registry.add("hPtGenNeg", "Generated p_{T} (negative);p_{T} (GeV/c);Centrality (%);Counts", o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtGenNeg_Pos", "Generated p_{T} (negative) in TPC positive side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtGenNeg_Neg", "Generated p_{T} (negative) in TPC negative side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); } registry.add("hPtRec", "Reconstructed p_{T} (all);p_{T} (GeV/c);Centrality (%);Counts", o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); @@ -184,8 +196,33 @@ struct JFlucEfficiencyTask { o2::framework::HistType::kTH2F, {AxisSpec(100, -1, 1), AxisSpec(axisMultiplicity)}); registry.add("hPtRecPos", "Reconstructed p_{T} (positive);p_{T} (GeV/c);Centrality (%);Counts", o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtRecPos_Pos", "Reconstructed p_{T} (positive) in TPC positive side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtRecPos_Neg", "Reconstructed p_{T} (positive) in TPC negative side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); registry.add("hPtRecNeg", "Reconstructed p_{T} (negative);p_{T} (GeV/c);Centrality (%);Counts", o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtRecNeg_Pos", "Reconstructed p_{T} (negative) in TPC positive side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + registry.add("hPtRecNeg_Neg", "Reconstructed p_{T} (negative) in TPC negative side;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}); + if (applyMCStudy) { + registry.add("hChargeSignMismatch", "Charge-Sign mismatch cases", {HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}}); + registry.add("hChargeSignMismatchPos", "MC charge + but track sign -", {HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}}); + registry.add("hChargeSignMismatchNeg", "MC charge - but track sign +", {HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}}); + registry.add("hChargeSignMatch", "Charge-Sign match cases", {HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}}); + registry.add("hChargeSignMatchPos", "MC charge + and track sign +", {HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}}); + registry.add("hChargeSignMatchNeg", "MC charge - and track sign -", {HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}}); + registry.add("hChargeSignRatio", "Ratio of mismatch to total", {HistType::kTH2F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity)}}); + + // pT resolution + registry.add("hPtResolution", "p_{T} resolution;p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH3F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity), AxisSpec(60, -3, 3)}); + registry.add("hPtResolutionPos", "p_{T} resolution (positive);p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH3F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity), AxisSpec(60, -3, 3)}); + registry.add("hPtResolutionNeg", "p_{T} resolution (negative);p_{T} (GeV/c);Centrality (%);Counts", + o2::framework::HistType::kTH3F, {AxisSpec(axisPt), AxisSpec(axisMultiplicity), AxisSpec(60, -3, 3)}); + } if (doprocessEfficiency) { registry.add("hPtGenData", "Generated p_{T} from data events (all);p_{T} (GeV/c);Centrality (%);Counts", @@ -239,7 +276,7 @@ struct JFlucEfficiencyTask { if (p != nullptr) { charge = p->Charge(); } - return std::abs(charge) >= 3.; + return std::abs(charge) >= kChargeThreshold; } // Track selection template @@ -380,10 +417,25 @@ struct JFlucEfficiencyTask { } registry.fill(HIST("hPtGen"), particle.pt(), centrality); registry.fill(HIST("hEtaGen"), particle.eta(), centrality); + if (particle.eta() > 0) { + registry.fill(HIST("hPtGenPos_Pos"), particle.pt(), centrality); + } else if (particle.eta() < 0) { + registry.fill(HIST("hPtGenNeg_Neg"), particle.pt(), centrality); + } if (charge > 0) { // Positive particles registry.fill(HIST("hPtGenPos"), particle.pt(), centrality); + if (particle.eta() > 0) { + registry.fill(HIST("hPtGenPos_Pos"), particle.pt(), centrality); + } else if (particle.eta() < 0) { + registry.fill(HIST("hPtGenPos_Neg"), particle.pt(), centrality); + } } else if (charge < 0) { // Negative particles registry.fill(HIST("hPtGenNeg"), particle.pt(), centrality); + if (particle.eta() > 0) { + registry.fill(HIST("hPtGenNeg_Pos"), particle.pt(), centrality); + } else if (particle.eta() < 0) { + registry.fill(HIST("hPtGenNeg_Neg"), particle.pt(), centrality); + } } } // Reconstruct tracks from MC particles @@ -402,12 +454,56 @@ struct JFlucEfficiencyTask { if (!mcPart.isPhysicalPrimary() || !isChargedParticle(mcPart.pdgCode())) { continue; } + if (applyMCStudy) { + // Check charge-sign consistency + auto mcCharge = getCharge(mcPart); + auto trackSign = track.sign(); + + if (mcCharge > 0 && trackSign > 0) { + // MC charge + and track sign + + registry.fill(HIST("hChargeSignMatchPos"), track.pt(), centrality); + registry.fill(HIST("hChargeSignMatch"), track.pt(), centrality); + } else if (mcCharge < 0 && trackSign < 0) { + // MC charge - and track sign - + registry.fill(HIST("hChargeSignMatchNeg"), track.pt(), centrality); + registry.fill(HIST("hChargeSignMatch"), track.pt(), centrality); + } else if (mcCharge > 0 && trackSign < 0) { + // MC charge + but track sign - + registry.fill(HIST("hChargeSignMismatchPos"), track.pt(), centrality); + registry.fill(HIST("hChargeSignMismatch"), track.pt(), centrality); + } else if (mcCharge < 0 && trackSign > 0) { + // MC charge - but track sign + + registry.fill(HIST("hChargeSignMismatchNeg"), track.pt(), centrality); + registry.fill(HIST("hChargeSignMismatch"), track.pt(), centrality); + } + + // pT resolution + auto ptRec = track.pt(); + auto ptGen = mcPart.pt(); + auto ptResolution = (ptRec - ptGen); + registry.fill(HIST("hPtResolution"), ptRec, centrality, ptResolution); + if (track.sign() > 0) { + registry.fill(HIST("hPtResolutionPos"), ptRec, centrality, ptResolution); + } else if (track.sign() < 0) { + registry.fill(HIST("hPtResolutionNeg"), ptRec, centrality, ptResolution); + } + } registry.fill(HIST("hPtRec"), track.pt(), centrality); registry.fill(HIST("hEtaRec"), track.eta(), centrality); if (track.sign() > 0) { // Positive tracks registry.fill(HIST("hPtRecPos"), track.pt(), centrality); + if (track.eta() > 0) { + registry.fill(HIST("hPtRecPos_Pos"), track.pt(), centrality); + } else if (track.eta() < 0) { + registry.fill(HIST("hPtRecPos_Neg"), track.pt(), centrality); + } } else if (track.sign() < 0) { // Negative tracks registry.fill(HIST("hPtRecNeg"), track.pt(), centrality); + if (track.eta() > 0) { + registry.fill(HIST("hPtRecNeg_Pos"), track.pt(), centrality); + } else if (track.eta() < 0) { + registry.fill(HIST("hPtRecNeg_Neg"), track.pt(), centrality); + } } } } @@ -481,6 +577,11 @@ struct JFlucEfficiencyTask { registry.fill(HIST("hPtRecPos"), track.pt(), centrality); } else if (track.sign() < 0) { // Negative tracks registry.fill(HIST("hPtRecNeg"), track.pt(), centrality); + if (track.eta() > 0) { + registry.fill(HIST("hPtRecNeg_Pos"), track.pt(), centrality); + } else if (track.eta() < 0) { + registry.fill(HIST("hPtRecNeg_Neg"), track.pt(), centrality); + } } } } @@ -508,8 +609,18 @@ struct JFlucEfficiencyTask { registry.fill(HIST("hEtaRec"), track.eta(), centrality); if (track.sign() > 0) { // Positive tracks registry.fill(HIST("hPtRecPos"), track.pt(), centrality); + if (track.eta() > 0) { + registry.fill(HIST("hPtRecPos_Pos"), track.pt(), centrality); + } else if (track.eta() < 0) { + registry.fill(HIST("hPtRecPos_Neg"), track.pt(), centrality); + } } else if (track.sign() < 0) { // Negative tracks registry.fill(HIST("hPtRecNeg"), track.pt(), centrality); + if (track.eta() > 0) { + registry.fill(HIST("hPtRecPos_Pos"), track.pt(), centrality); + } else if (track.eta() < 0) { + registry.fill(HIST("hPtRecPos_Neg"), track.pt(), centrality); + } } } } @@ -535,6 +646,11 @@ struct JFlucEfficiencyTask { registry.fill(HIST("hPtRecPos"), track.pt(), centrality); } else if (track.sign() < 0) { // Negative tracks registry.fill(HIST("hPtRecNeg"), track.pt(), centrality); + if (track.eta() > 0) { + registry.fill(HIST("hPtRecNeg_Pos"), track.pt(), centrality); + } else if (track.eta() < 0) { + registry.fill(HIST("hPtRecNeg_Neg"), track.pt(), centrality); + } } } } diff --git a/PWGCF/JCorran/Tasks/jflucAnalysisTask.cxx b/PWGCF/JCorran/Tasks/jflucAnalysisTask.cxx index 6e0ba68d2df..8f1244661c7 100644 --- a/PWGCF/JCorran/Tasks/jflucAnalysisTask.cxx +++ b/PWGCF/JCorran/Tasks/jflucAnalysisTask.cxx @@ -12,25 +12,27 @@ /// \author Dong Jo Kim (djkim@jyu.fi) /// \since Sep 2022 -#include +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" +#include "Framework/RunningWorkflowInfo.h" #include "ReconstructionDataFormats/V0.h" +#include + // #include "CCDB/BasicCCDBManager.h" -#include "PWGCF/JCorran/DataModel/JCatalyst.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" #include "JFFlucAnalysis.h" #include "JFFlucAnalysisO2Hist.h" + +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGCF/JCorran/DataModel/JCatalyst.h" + #include "Framework/runDataProcessing.h" using namespace o2; @@ -52,6 +54,8 @@ struct jflucAnalysisTask { O2_DEFINE_CONFIGURABLE(etamax, float, 0.8, "Maximum eta for tracks"); O2_DEFINE_CONFIGURABLE(ptmin, float, 0.2, "Minimum pt for tracks"); O2_DEFINE_CONFIGURABLE(ptmax, float, 5.0, "Maximum pt for tracks"); + O2_DEFINE_CONFIGURABLE(cfgCentBinsForMC, int, 0, "0 = OFF and 1 = ON for data like multiplicity/centrality bins for MC process"); + O2_DEFINE_CONFIGURABLE(cfgMultCorrelationsMask, uint16_t, 0, "Selection bitmask for the multiplicity correlations. This should match the filter selection cfgEstimatorBitMask.") ConfigurableAxis axisMultiplicity{"axisMultiplicity", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 100.1}, "multiplicity / centrality axis for histograms"}; ConfigurableAxis phiAxis{"axisPhi", {50, 0.0, o2::constants::math::TwoPI}, "phi axis for histograms"}; @@ -60,8 +64,9 @@ struct jflucAnalysisTask { ConfigurableAxis ptAxis{"axisPt", {60, 0.0, 300.0}, "pt axis for histograms"}; ConfigurableAxis massAxis{"axisMass", {1, 0.0, 10.0}, "mass axis for histograms"}; - Filter jtrackFilter = (aod::jtrack::pt > ptmin) && (aod::jtrack::pt < ptmax); // eta cuts done by jfluc - Filter cftrackFilter = (aod::cftrack::pt > ptmin) && (aod::cftrack::pt < ptmax); // eta cuts done by jfluc + Filter jtrackFilter = (aod::jtrack::pt > ptmin) && (aod::jtrack::pt < ptmax); // eta cuts done by jfluc + Filter cftrackFilter = (aod::cftrack::pt > ptmin) && (aod::cftrack::pt < ptmax); // eta cuts done by jfluc + Filter cfmcparticleFilter = (aod::cfmcparticle::pt > ptmin) && (aod::cfmcparticle::pt < ptmax) && (aod::cfmcparticle::sign != 0); // eta cuts done by jfluc Filter cf2pFilter = (aod::cf2prongtrack::pt > ptmin) && (aod::cf2prongtrack::pt < ptmax); HistogramRegistry registry{"registry"}; @@ -74,15 +79,15 @@ struct jflucAnalysisTask { auto axisSpecZvt = AxisSpec(zvtAxis); auto axisSpecPt = AxisSpec(ptAxis); auto axisSpecMass = AxisSpec(massAxis); - if (doprocessJDerived || doprocessJDerivedCorrected || doprocessCFDerived || doprocessCFDerivedCorrected) { - pcf = new JFFlucAnalysisO2Hist(registry, axisSpecMult, axisSpecPhi, axisSpecEta, axisSpecZvt, axisSpecPt, axisSpecMass, "jfluc"); + if (doprocessJDerived || doprocessJDerivedCorrected || doprocessCFDerived || doprocessCFDerivedCorrected || doprocessCFDerivedMultSet || doprocessCFDerivedMultSetCorrected || doprocessMCCFDerived) { + pcf = new JFFlucAnalysisO2Hist(registry, axisSpecMult, axisSpecPhi, axisSpecEta, axisSpecZvt, axisSpecPt, axisSpecMass, cfgMultCorrelationsMask, "jfluc"); pcf->AddFlags(JFFlucAnalysis::kFlucEbEWeighting); pcf->UserCreateOutputObjects(); } else { pcf = 0; } if (doprocessCF2ProngDerived || doprocessCF2ProngDerivedCorrected) { - pcf2Prong = new JFFlucAnalysisO2Hist(registry, axisSpecMult, axisSpecPhi, axisSpecEta, axisSpecZvt, axisSpecPt, axisSpecMass, "jfluc2prong"); + pcf2Prong = new JFFlucAnalysisO2Hist(registry, axisSpecMult, axisSpecPhi, axisSpecEta, axisSpecZvt, axisSpecPt, axisSpecMass, cfgMultCorrelationsMask, "jfluc2prong"); pcf2Prong->AddFlags(JFFlucAnalysis::kFlucEbEWeighting); pcf2Prong->UserCreateOutputObjects(); @@ -91,6 +96,8 @@ struct jflucAnalysisTask { } else { pcf2Prong = 0; } + if ((doprocessCFDerivedMultSet || doprocessCFDerivedMultSetCorrected) && cfgMultCorrelationsMask == 0) + LOGF(fatal, "cfgMultCorrelationsMask can not be 0 when MultSet process functions are in use."); } template @@ -103,6 +110,7 @@ struct jflucAnalysisTask { pcf->SetEventCentrality(collision.multiplicity()); pcf->SetEventVertex(collision.posZ()); pcf->FillQA(tracks); + pcf->FillMultSet(collision); qvecs.Calculate(tracks, etamin, etamax); pcf->SetJQVectors(&qvecs); pcf->UserExec(""); @@ -154,6 +162,22 @@ struct jflucAnalysisTask { } PROCESS_SWITCH(jflucAnalysisTask, processCFDerivedCorrected, "Process CF derived data with corrections", true); + void processCFDerivedMultSet(soa::Join::iterator const& collision, soa::Filtered const& tracks) + { + if (std::popcount(cfgMultCorrelationsMask.value) != static_cast(collision.multiplicities().size())) + LOGF(fatal, "Multiplicity selections (cfgMultCorrelationsMask = 0x%x) do not match the size of the table column (%ld). The histogram filling relies on the preservation of order.", cfgMultCorrelationsMask.value, collision.multiplicities().size()); + analyze(collision, tracks); + } + PROCESS_SWITCH(jflucAnalysisTask, processCFDerivedMultSet, "Process CF derived data with multiplicity sets", false); + + void processCFDerivedMultSetCorrected(soa::Join::iterator const& collision, soa::Filtered> const& tracks) + { + if (std::popcount(cfgMultCorrelationsMask.value) != static_cast(collision.multiplicities().size())) + LOGF(fatal, "Multiplicity selections (cfgMultCorrelationsMask = 0x%x) do not match the size of the table column (%ld). The histogram filling relies on the preservation of order.", cfgMultCorrelationsMask.value, collision.multiplicities().size()); + analyze(collision, tracks); + } + PROCESS_SWITCH(jflucAnalysisTask, processCFDerivedMultSetCorrected, "Process CF derived data with corrections and multiplicity sets", false); + void processCF2ProngDerived(aod::CFCollision const& collision, soa::Filtered const& tracks, soa::Filtered const& p2tracks) { analyze(collision, p2tracks, tracks); @@ -166,6 +190,27 @@ struct jflucAnalysisTask { } PROCESS_SWITCH(jflucAnalysisTask, processCF2ProngDerivedCorrected, "Process CF derived data with 2-prongs as POI and charged particles as REF with corrections.", false); + void processMCCFDerived(aod::CFMcCollision const& mcCollision, soa::Filtered const& particles, soa::SmallGroups const& collisions) + { + auto multiplicity = mcCollision.multiplicity(); + if (cfgCentBinsForMC > 0) { + if (collisions.size() == 0) { + return; + } + for (const auto& collision : collisions) { + multiplicity = collision.multiplicity(); + } + } + pcf->Init(); + pcf->SetEventCentrality(multiplicity); + pcf->SetEventVertex(mcCollision.posZ()); + pcf->FillQA(particles); + qvecs.Calculate(particles, etamin, etamax); + pcf->SetJQVectors(&qvecs); + pcf->UserExec(""); + } + PROCESS_SWITCH(jflucAnalysisTask, processMCCFDerived, "Process CF derived MC data", false); + JFFlucAnalysis::JQVectorsT qvecs; JFFlucAnalysis::JQVectorsT qvecsRef; JFFlucAnalysisO2Hist* pcf; diff --git a/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx b/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx index 244035fd310..7d15d9b2a6d 100644 --- a/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx +++ b/PWGCF/JCorran/Tasks/jflucWeightsLoader.cxx @@ -12,27 +12,27 @@ /// \since May 2024 // o2-linter: disable='doc/file' -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/HistogramRegistry.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGCF/JCorran/DataModel/JCatalyst.h" -#include "Common/DataModel/EventSelection.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" -#include "ReconstructionDataFormats/V0.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" - -#include "PWGCF/JCorran/DataModel/JCatalyst.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/RunningWorkflowInfo.h" #include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/V0.h" + +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; @@ -50,7 +50,7 @@ struct JflucWeightsLoader { THnF* ph = 0; TFile* pf = 0; - THnD* pheff = 0; + THnF* pheff = 0; TFile* pfeff = 0; int runNumber = 0; int timestamp = 0; @@ -108,7 +108,6 @@ struct JflucWeightsLoader { useCCDB = false; } else { LOGF(info, "Didn't find \"local://\" or \"ccdb\" for non-uniform acceptance corrections."); - return; } if (cfgPathEffWeights.value.substr(0, 8) == "local://") { @@ -118,16 +117,13 @@ struct JflucWeightsLoader { delete pfeff; pfeff = 0; LOGF(fatal, "Efficiency correction weights file not found: %s", cfgPathEffWeights.value.substr(8).c_str()); - } - // - if (!(pheff = pfeff->Get("ccdb_object"))) { + } else if (!(pheff = pfeff->Get("ccdb_object"))) { LOGF(warning, "Efficiency correction histogram not found."); } else { LOGF(info, "Loaded efficiency correction histogram locally."); } } else { LOGF(info, "Didn't find \"local://\" or \"ccdb\" for efficiency corrections."); - return; } } diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h index 95d24fa9a47..c1274b6788c 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h @@ -17,8 +17,8 @@ #define PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_CONFIGURABLES_H_ // ... -#include #include +#include // *) Task configuration: struct : ConfigurableGroup { @@ -46,6 +46,7 @@ struct : ConfigurableGroup { Configurable cfUseSetBinLabel{"cfUseSetBinLabel", false, "until hist->SetBinLabel(...) large memory consumption is resolved, for each histogram dump all that info in the y-axis title. See also local executable PostprocessLabels.C, where I do the final bin labeling offline"}; Configurable cfUseClone{"cfUseClone", false, "until hist->Clone(...) large memory consumption is resolved, do not use cloning. See ROOT Forum thread."}; Configurable cfUseFormula{"cfUseFormula", false, "until TFormula large memory consumption is resolved, do not use this class. See ROOT Forum thread."}; + Configurable cfUseDatabasePDG{"cfUseDatabasePDG", false, "When enabled, there is a standard memory blow-up."}; } cf_tc; // *) QA: @@ -77,7 +78,7 @@ struct : ConfigurableGroup { // *) Event cuts: struct : ConfigurableGroup { - Configurable> cfUseEventCuts{"cfUseEventCuts", {"1-NumberOfEvents", "1-TotalMultiplicity", "1-Multiplicity", "1-ReferenceMultiplicity", "1-Centrality", "1-VertexX", "1-VertexY", "1-VertexZ", "1-NContributors", "1-ImpactParameter", "0-EventPlaneAngle", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "0-MultMCNParticlesEta08", "0-Trigger", "0-Sel7", "1-Sel8", "1-MultiplicityEstimator", "1-ReferenceMultiplicityEstimator", "1-CentralityEstimator", "1-SelectedEvents", "1-NoSameBunchPileup", "1-IsGoodZvtxFT0vsPV", "1-IsVertexITSTPC", "1-IsVertexTOFmatched", "1-IsVertexTRDmatched", "0-NoCollInTimeRangeStrict", "0-NoCollInTimeRangeStandard", "0-NoCollInRofStrict", "0-NoCollInRofStandard", "0-NoHighMultCollInPrevRof", "0-IsGoodITSLayer3", "0-IsGoodITSLayer0123", "0-IsGoodITSLayersAll", "1-OccupancyEstimator", "1-MinVertexDistanceFromIP", "0-NoPileupTPC", "0-NoPileupFromSPD", "0-NoSPDOnVsOfPileup", "1-RefMultVsNContrUp", "1-RefMultVsNContrLow", "1-CentralityCorrelationsCut", "1-CentralityWeights"}, "use (1) or do not use (0) event cuts"}; + Configurable> cfUseEventCuts{"cfUseEventCuts", {"1-NumberOfEvents", "1-TotalMultiplicity", "1-Multiplicity", "1-ReferenceMultiplicity", "1-Centrality", "1-VertexX", "1-VertexY", "1-VertexZ", "1-NContributors", "1-ImpactParameter", "0-EventPlaneAngle", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "0-MultMCNParticlesEta08", "0-Trigger", "0-Sel7", "1-Sel8", "1-MultiplicityEstimator", "1-ReferenceMultiplicityEstimator", "1-CentralityEstimator", "1-SelectedEvents", "1-NoSameBunchPileup", "1-IsGoodZvtxFT0vsPV", "1-IsVertexITSTPC", "1-IsVertexTOFmatched", "1-IsVertexTRDmatched", "0-NoCollInTimeRangeStrict", "0-NoCollInTimeRangeStandard", "0-NoCollInRofStrict", "0-NoCollInRofStandard", "0-NoHighMultCollInPrevRof", "0-IsGoodITSLayer3", "0-IsGoodITSLayer0123", "0-IsGoodITSLayersAll", "1-OccupancyEstimator", "1-MinVertexDistanceFromIP", "0-NoPileupTPC", "0-NoPileupFromSPD", "0-NoSPDOnVsOfPileup", "1-RefMultVsNContrUp", "1-RefMultVsNContrLow", "1-CentralityCorrelationsCut", "0-FT0Bad", "0-ITSBad", "0-ITSLimAccMCRepr", "0-TPCBadTracking", "0-TPCLimAccMCRepr", "0-TPCBadPID", "1-CentralityWeights"}, "use (1) or do not use (0) event cuts"}; Configurable cfUseEventCutCounterAbsolute{"cfUseEventCutCounterAbsolute", false, "profile and save how many times each event cut counter triggered (absolute). Use with care, as this is computationally heavy"}; Configurable cfUseEventCutCounterSequential{"cfUseEventCutCounterSequential", false, "profile and save how many times each event cut counter triggered (sequential). Use with care, as this is computationally heavy"}; Configurable cfPrintCutCounterContent{"cfPrintCutCounterContent", false, "if true, prints on the screen after each event the content of fEventCutCounterHist[*][*] (all which were booked)"}; @@ -128,7 +129,12 @@ struct : ConfigurableGroup { Configurable cfCentralityCorrelationsCut{"cfCentralityCorrelationsCut", "CentFT0C_CentFT0M", "Indicate two centrality estimators for the calculation of centrality correlation cut"}; Configurable cfCentralityCorrelationsCutTreshold{"cfCentralityCorrelationsCutTreshold", 10.0, "set the treshold for centrality correlation cut"}; Configurable cfCentralityCorrelationsCutVersion{"cfCentralityCorrelationsCutVersion", "Absolute", "set the version of centrality correlation cut. Supported: \"Relative\" and \"Absolute\""}; - + Configurable cfUseFT0Bad{"cfUseFT0Bad", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseITSBad{"cfUseITSBad", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseITSLimAccMCRepr{"cfUseITSLimAccMCRepr", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseTPCBadTracking{"cfUseTPCBadTracking", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseTPCLimAccMCRepr{"cfUseTPCLimAccMCRepr", false, "TBI 20250516 explanation (or see enum)"}; + Configurable cfUseTPCBadPID{"cfUseTPCBadPID", false, "TBI 20250516 explanation (or see enum)"}; } cf_ec; // *) Particle histograms: @@ -185,29 +191,24 @@ struct : ConfigurableGroup { // *) Multiparticle correlations: struct : ConfigurableGroup { Configurable cfCalculateCorrelations{"cfCalculateCorrelations", false, "calculate or not multiparticle correlations"}; - Configurable cfCalculateCorrelationsAsFunctionOfIntegrated{"cfCalculateCorrelationsAsFunctionOfIntegrated", true, "calculate or not correlations as a function of integrated"}; - Configurable cfCalculateCorrelationsAsFunctionOfMultiplicity{"cfCalculateCorrelationsAsFunctionOfMultiplicity", true, "calculate or not correlations as a function of multiplicity"}; - Configurable cfCalculateCorrelationsAsFunctionOfCentrality{"cfCalculateCorrelationsAsFunctionOfCentrality", true, "calculate or not correlations as a function of centrality"}; - Configurable cfCalculateCorrelationsAsFunctionOfPt{"cfCalculateCorrelationsAsFunctionOfPt", false, "calculate or not correlations as a function of pt"}; - Configurable cfCalculateCorrelationsAsFunctionOfEta{"cfCalculateCorrelationsAsFunctionOfEta", false, "calculate or not correlations as a function of eta"}; - Configurable cfCalculateCorrelationsAsFunctionOfOccupancy{"cfCalculateCorrelationsAsFunctionOfOccupancy", true, "calculate or not correlations as a function of occupancy"}; - Configurable cfCalculateCorrelationsAsFunctionOfInteractionRate{"cfCalculateCorrelationsAsFunctionOfInteractionRate", true, "calculate or not correlations as a function of interaction rate"}; - Configurable cfCalculateCorrelationsAsFunctionOfCurrentRunDuration{"cfCalculateCorrelationsAsFunctionOfCurrentRunDuration", true, "calculate or not correlations as a function of current run duration (i.e. vs. seconds since start of run)"}; - Configurable cfCalculateCorrelationsAsFunctionOfVz{"cfCalculateCorrelationsAsFunctionOfVz", true, "calculate or not correlations as a function of vertex z position"}; + Configurable> cfCalculateCorrelationsAsFunctionOf{"cfCalculateCorrelationsAsFunctionOf", {"1-Integrated", "1-Multiplicity", "1-Centrality", "0-Pt", "0-Eta", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "1-Vz", "0-Charge"}, "calculate or not correlations as a function of specified variable"}; } cf_mupa; // *) Test0: struct : ConfigurableGroup { + + // 1D: Configurable cfCalculateTest0{"cfCalculateTest0", false, "calculate or not Test0"}; - Configurable cfCalculateTest0AsFunctionOfIntegrated{"cfCalculateTest0AsFunctionOfIntegrated", false, "calculate or not Test0 as a function of integrated"}; - Configurable cfCalculateTest0AsFunctionOfMultiplicity{"cfCalculateTest0AsFunctionOfMultiplicity", false, "calculate or not Test0 as a function of multiplicity"}; - Configurable cfCalculateTest0AsFunctionOfCentrality{"cfCalculateTest0AsFunctionOfCentrality", false, "calculate or not Test0 as a function of centrality"}; - Configurable cfCalculateTest0AsFunctionOfPt{"cfCalculateTest0AsFunctionOfPt", false, "calculate or not Test0 as a function of pt"}; - Configurable cfCalculateTest0AsFunctionOfEta{"cfCalculateTest0AsFunctionOfEta", false, "calculate or not Test0 as a function of eta"}; - Configurable cfCalculateTest0AsFunctionOfOccupancy{"cfCalculateTest0AsFunctionOfOccupancy", false, "calculate or not Test0 as a function of occupancy"}; - Configurable cfCalculateTest0AsFunctionOfInteractionRate{"cfCalculateTest0AsFunctionOfInteractionRate", false, "calculate or not Test0 as a function of interaction rate"}; - Configurable cfCalculateTest0AsFunctionOfCurrentRunDuration{"cfCalculateTest0AsFunctionOfCurrentRunDuration", false, "calculate or not Test0 as a function of current run duration (i.e. vs. seconds since start of run)"}; - Configurable cfCalculateTest0AsFunctionOfVz{"cfCalculateTest0AsFunctionOfVz", false, "calculate or not Test0 as a function of vertex z position"}; + Configurable> cfCalculateTest0AsFunctionOf{"cfCalculateTest0AsFunctionOf", {"1-Integrated", "1-Multiplicity", "1-Centrality", "1-Pt", "1-Eta", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "1-Vz", "1-Charge"}, "calculate or not correlations as a function of specified variable"}; + + // 2D: + Configurable cfCalculate2DTest0{"cfCalculate2DTest0", false, "calculate or not 2D Test0 using TProfile2D"}; + Configurable> cfCalculate2DTest0AsFunctionOf{"cfCalculate2DTest0AsFunctionOf", {"1-Centrality_Pt", "1-Centrality_Eta", "1-Centrality_Charge", "1-Centrality_Vz", "1-Pt_Eta", "1-Pt_Charge", "1-Eta_Charge"}, "calculate or not correlations in 2D as a function of two specified variables."}; + + // 3D: + Configurable cfCalculate3DTest0{"cfCalculate3DTest0", false, "calculate or not 3D Test0 using TProfile3D"}; + Configurable> cfCalculate3DTest0AsFunctionOf{"cfCalculate3DTest0AsFunctionOf", {"1-Centrality_Pt_Eta", "1-Centrality_Pt_Charge", "1-Centrality_Pt_Vz", "1-Centrality_Eta_Vz", "1-Centrality_Eta_Charge", "1-Centrality_Vz_Charge", "1-Pt_Eta_Charge"}, "calculate or not correlations in 3D as a function of three specified variables."}; + Configurable cfFileWithLabels{"cfFileWithLabels", "/home/abilandz/DatasetsO2/labels.root", "path to external ROOT file which specifies all labels"}; // for AliEn file prepend "/alice/cern.ch/", for CCDB prepend "/alice-ccdb.cern.ch" Configurable cfUseDefaultLabels{"cfUseDefaultLabels", false, "use default internally hardwired labels, only for testing purposes"}; Configurable cfWhichDefaultLabels{"cfWhichDefaultLabels", "standard", "only for testing purposes, select one set of default labels, see GetDefaultObjArrayWithLabels for supported options"}; @@ -216,15 +217,7 @@ struct : ConfigurableGroup { // *) Eta separation: struct : ConfigurableGroup { Configurable cfCalculateEtaSeparations{"cfCalculateEtaSeparations", false, "calculate or not 2p corr. vs. eta separations"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfIntegrated{"cfCalculateEtaSeparationsAsFunctionOfIntegrated", false, "calculate or not 2p corr. vs. eta separations ..."}; - Configurable cfCalculateEtaSeparationsAsFunctionOfMultiplicity{"cfCalculateEtaSeparationsAsFunctionOfMultiplicity", false, "calculate or not 2p corr. vs. eta separations as a function of multiplicity"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfCentrality{"cfCalculateEtaSeparationsAsFunctionOfCentrality", false, "calculate or not 2p corr. vs. eta separations as a function of centrality"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfPt{"cfCalculateEtaSeparationsAsFunctionOfPt", false, "calculate or not 2p corr. vs. eta separations as a function of pt"}; - // Configurable cfCalculateEtaSeparationsAsFunctionOfEta{"cfCalculateEtaSeparationsAsFunctionOfEta", false, "this one doesn't make sense in this context"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfOccupancy{"cfCalculateEtaSeparationsAsFunctionOfOccupancy", false, "calculate or not 2p corr. vs. eta separations as a function of occupancy"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfInteractionRate{"cfCalculateEtaSeparationsAsFunctionOfInteractionRate", false, "calculate or not 2p corr. vs. eta separations as a function of interaction rate"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfCurrentRunDuration{"cfCalculateEtaSeparationsAsFunctionOfCurrentRunDuration", false, "calculate or not 2p corr. vs. eta separations as a function of current run duration (i.e. vs. seconds since start of run)"}; - Configurable cfCalculateEtaSeparationsAsFunctionOfVz{"cfCalculateEtaSeparationsAsFunctionOfVz", false, "calculate or not 2p corr. vs. eta separations as a function of vertex z position"}; + Configurable> cfCalculateEtaSeparationsAsFunctionOf{"cfCalculateEtaSeparationsAsFunctionOf", {"1-Integrated", "1-Multiplicity", "1-Centrality", "1-Pt", "0-Eta", "1-Occupancy", "1-InteractionRate", "1-CurrentRunDuration", "1-Vz", "1-Charge"}, "calculate or not correlations as a function of specified variable"}; Configurable> cfEtaSeparationsValues{"cfEtaSeparationsValues", {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8}, "Eta separation between interval A (-eta) and B (+eta)"}; Configurable> cfEtaSeparationsSkipHarmonics{"cfEtaSeparationsSkipHarmonics", {"0-v1", "0-v2", "0-v3", "0-v4", "1-v5", "1-v6", "1-v7", "1-v8", "1-v9"}, "For calculation of 2p correlation with eta separation these harmonics will be skipped (if first flag = \"0-v1\", v1 will be NOT be skipped in the calculus of 2p correlations with eta separations, etc.)"}; } cf_es; @@ -237,8 +230,8 @@ 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", {"1-wPt"}, "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", {"1-wEta"}, "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-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 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; @@ -271,6 +264,7 @@ struct : ConfigurableGroup { 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 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."}; Configurable> cfInternalValidationPlanes{"cfInternalValidationPlanes", {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, "{Psi1, Psi2, Psi3, Psi4, ...} + has an effect only in combination with cfHarmonicsOptionInternalValidation = \"constant\". Max number of Psin's is gMaxHarmonic."}; Configurable> cfMultRangeInternalValidation{"cfMultRangeInternalValidation", {1000, 1001}, "{min, max}, with convention: min <= M < max"}; @@ -281,32 +275,32 @@ struct : ConfigurableGroup { Configurable cfSaveResultsHistograms{"cfSaveResultsHistograms", false, "save or not results histograms"}; // Fixed-length binning (default): - Configurable> cfFixedLengthMultBins{"cfFixedLengthMultBins", {2000, 0., 20000.}, "nMultBins, multMin, multMax (only for results histograms)"}; - Configurable> cfFixedLengthCentBins{"cfFixedLengthCentBins", {110, 0., 110.}, "nCentBins, centMin, centMax (only for results histograms)"}; - Configurable> cfFixedLengthPtBins{"cfFixedLengthPtBins", {1000, 0., 10.}, "nPtBins, ptMin, ptMax (only for results histograms)"}; - Configurable> cfFixedLengthEtaBins{"cfFixedLengthEtaBins", {80, -2., 2.}, "nEtaBins, etaMin, etaMax (only for results histograms)"}; - Configurable> cfFixedLengthOccuBins{"cfFixedLengthOccuBins", {200, 0., 60000.}, "nOccuBins, occuMin, occuMax (only for results histograms)"}; - Configurable> cfFixedLengthIRBins{"cfFixedLengthIRBins", {1000, 0., 100.}, "nirBins, irMin, irMax (only for results histograms)"}; - Configurable> cfFixedLengthCRDBins{"cfFixedLengthCRDBins", {100000, 0., 100000.}, "ncrdBins, crdMin, crdMax (only for results histograms)"}; - Configurable> cfFixedLengthVzBins{"cfFixedLengthVzBins", {400, -20., 20.}, "nvzBins, vzMin, vzMax (only for results histograms)"}; + Configurable> cfFixedLengthMultBins{"cfFixedLengthMultBins", {2000, 0., 20000.}, "nMultBins, multMin, multMax (only for results histograms)"}; + Configurable> cfFixedLengthCentBins{"cfFixedLengthCentBins", {110, 0., 110.}, "nCentBins, centMin, centMax (only for results histograms)"}; + Configurable> cfFixedLengthPtBins{"cfFixedLengthPtBins", {1000, 0., 10.}, "nPtBins, ptMin, ptMax (only for results histograms)"}; + Configurable> cfFixedLengthEtaBins{"cfFixedLengthEtaBins", {80, -2., 2.}, "nEtaBins, etaMin, etaMax (only for results histograms)"}; + Configurable> cfFixedLengthOccuBins{"cfFixedLengthOccuBins", {200, 0., 60000.}, "nOccuBins, occuMin, occuMax (only for results histograms)"}; + Configurable> cfFixedLengthIRBins{"cfFixedLengthIRBins", {1000, 0., 100.}, "nirBins, irMin, irMax (only for results histograms)"}; + Configurable> cfFixedLengthCRDBins{"cfFixedLengthCRDBins", {100000, 0., 100000.}, "ncrdBins, crdMin, crdMax (only for results histograms)"}; + Configurable> cfFixedLengthVzBins{"cfFixedLengthVzBins", {400, -20., 20.}, "nvzBins, vzMin, vzMax (only for results histograms)"}; // Variable-length binning (per request): Configurable cfUseVariableLengthMultBins{"cfUseVariableLengthMultBins", false, "use or not variable-length multiplicity bins"}; - Configurable> cfVariableLengthMultBins{"cfVariableLengthMultBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length multiplicity bins"}; + Configurable> cfVariableLengthMultBins{"cfVariableLengthMultBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length multiplicity bins"}; Configurable cfUseVariableLengthCentBins{"cfUseVariableLengthCentBins", false, "use or not variable-length centrality bins"}; - Configurable> cfVariableLengthCentBins{"cfVariableLengthCentBins", {0., 10., 50., 100.}, "variable-length centrality bins"}; + Configurable> cfVariableLengthCentBins{"cfVariableLengthCentBins", {0., 10., 50., 100.}, "variable-length centrality bins"}; Configurable cfUseVariableLengthPtBins{"cfUseVariableLengthPtBins", true, "use or not variable-length pt bins"}; - Configurable> cfVariableLengthPtBins{"cfVariableLengthPtBins", {0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.80, 1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00, 4.00, 5.00}, "variable-length pt bins"}; + Configurable> cfVariableLengthPtBins{"cfVariableLengthPtBins", {0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.80, 1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00, 4.00, 5.00}, "variable-length pt bins"}; Configurable cfUseVariableLengthEtaBins{"cfUseVariableLengthEtaBins", true, "use or not variable-length eta bins"}; - Configurable> cfVariableLengthEtaBins{"cfVariableLengthEtaBins", {-0.8, -0.6, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.6, 0.8}, "variable-length eta bins"}; + Configurable> cfVariableLengthEtaBins{"cfVariableLengthEtaBins", {-0.8, -0.6, -0.4, -0.3, -0.2, -0.1, 0.0, 0.1, 0.2, 0.3, 0.4, 0.6, 0.8}, "variable-length eta bins"}; Configurable cfUseVariableLengthOccuBins{"cfUseVariableLengthOccuBins", false, "use or not variable-length occupancy bins"}; - Configurable> cfVariableLengthOccuBins{"cfVariableLengthOccuBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length occupancy bins"}; + Configurable> cfVariableLengthOccuBins{"cfVariableLengthOccuBins", {0., 5., 6., 7., 8., 9., 100., 200., 500., 1000., 10000.}, "variable-length occupancy bins"}; Configurable cfUseVariableLengthIRBins{"cfUseVariableLengthIRBins", false, "use or not variable-length interaction rate bins"}; - Configurable> cfVariableLengthIRBins{"cfVariableLengthIRBins", {0., 5., 10., 50., 100., 200.}, "variable-length ineraction rate bins"}; + Configurable> cfVariableLengthIRBins{"cfVariableLengthIRBins", {0., 5., 10., 50., 100., 200.}, "variable-length ineraction rate bins"}; Configurable cfUseVariableLengthCRDBins{"cfUseVariableLengthCRDBins", false, "use or not variable-length current run duration bins"}; - Configurable> cfVariableLengthCRDBins{"cfVariableLengthCRDBins", {0., 5., 10., 50., 100., 500.}, "variable-length current run duration bins"}; + Configurable> cfVariableLengthCRDBins{"cfVariableLengthCRDBins", {0., 5., 10., 50., 100., 500.}, "variable-length current run duration bins"}; Configurable cfUseVariableLengthVzBins{"cfUseVariableLengthVzBins", false, "use or not variable-length vertex z bins"}; - Configurable> cfVariableLengthVzBins{"cfVariableLengthVzBins", {-10., -8., -6., -4, -2., -1., 0., 1., 2., 4., 6., 8., 10.}, "variable-length vertex z bins"}; + Configurable> cfVariableLengthVzBins{"cfVariableLengthVzBins", {-10., -8., -6., -4, -2., -1., 0., 1., 2., 4., 6., 8., 10.}, "variable-length vertex z bins"}; } cf_res; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h index a603d614a24..fff7cd5fdee 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-DataMembers.h @@ -16,6 +16,8 @@ #ifndef PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_DATAMEMBERS_H_ #define PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_DATAMEMBERS_H_ +#include + // General remarks: // 0. Starting with C++11, it's possible to initialize data members at declaration, so I do it here // 1. Use //!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: @@ -254,20 +260,34 @@ 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 - TComplex fqvector[eqvectorKine_N][gMaxNoBinsKine][gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] = {{{{TComplex(0., 0.)}}}}; //! "differenttial" q-vector [kine var.][binNo][fMaxHarmonic*fMaxCorrelator+1][fMaxCorrelator+1] = [6*12+1][12+1] - int fqVectorEntries[eqvectorKine_N][gMaxNoBinsKine] = {{0}}; // count number of entries in each differential q-vector - TComplex fQabVector[2][gMaxHarmonic][gMaxNumberEtaSeparations] = {{{TComplex(0., 0.)}}}; //! integrated [-eta or +eta][harmonic][eta separation] - float fMab[2][gMaxNumberEtaSeparations] = {{0.}}; //! multiplicities in 2 eta separated intervals - TH1F* fMabDist[2][2][2][gMaxNumberEtaSeparations] = {{{{NULL}}}}; // multiplicity distributions in A and B, for each eta separation [ A or B ] [rec or sim] [ before or after cuts ] [ eta separation value ] - TComplex fqabVector[2][gMaxNoBinsKine][gMaxHarmonic][gMaxNumberEtaSeparations] = {{{{TComplex(0., 0.)}}}}; //! differential in pt [-eta or +eta][binNo][harmonic][eta separation] - float fmab[2][gMaxNoBinsKine][gMaxNumberEtaSeparations] = {{{0.}}}; //! multiplicities vs pt in 2 eta separated intervals -} qv; // "qv" is a common label for objects in this struct + 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 + + 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. + bool fCalculateqvectorsKine[eqvectorKine_N] = {false}; // same as above, just specifically for each enum eqvectorKine + applies only to Correlations and Test0 + bool fCalculateqvectorsKineEtaSeparations[eqvectorKine_N] = {false}; // same as above, just specifically for each enum eqvectorKine + applies only to EtaSeparations + + 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 + + // q-vectors for eta separations: + TComplex fQabVector[2][gMaxHarmonic][gMaxNumberEtaSeparations] = {{{TComplex(0., 0.)}}}; //! integrated [-eta or +eta][harmonic][eta separation] + float fMab[2][gMaxNumberEtaSeparations] = {{0.}}; //! multiplicities in 2 eta separated intervals + TH1F* fMabDist[2][2][2][gMaxNumberEtaSeparations] = {{{{NULL}}}}; // multiplicity distributions in A and B, for each eta separation [ A or B ] [rec or sim] [ before or after cuts ] [ eta separation value ] + std::vector>>>>> fqabVector; // dynamically allocated differential q-vector. + // dimensions: [-eta or +eta][eqvectorKine_N][global binNo][harmonic][eta separation] + // Remark: Unlike fqvector above, here I support only 2-p correlations, + // therefore no need for "[gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1]", etc. + std::vector>>> fmab; //! multiplicities vs kine in 2 eta separated intervals + // [-eta or +eta][eqvectorKine_N][global binNo][eta separation] +} qv; // "qv" is a common label for objects in this struct // *) Multiparticle correlations (standard, isotropic, same harmonic): struct MultiparticleCorrelations { @@ -326,7 +346,7 @@ struct NestedLoops { //! [2p=0,4p=1,6p=2,8p=3][n=1,n=2,...,n=gMaxHarmonic][0=integrated,1=vs. //! multiplicity,2=vs. centrality,3=pT,4=eta] TArrayD* ftaNestedLoops[2] = {NULL}; //! e-b-e container for nested loops [0=angles;1=product of all weights] - TArrayD* ftaNestedLoopsKine[eqvectorKine_N][gMaxNoBinsKine][2] = {{{NULL}}}; //! e-b-e container for nested loops // [0=pT,1=eta][kine bin][0=angles;1=product of all weights] + TArrayD* ftaNestedLoopsKine[eqvectorKine_N][gMaxNoBinsKine][2] = {{{NULL}}}; //! e-b-e container for nested loops // [0=pT,1=eta,2=...][kine bin][0=angles;1=product of all weights] } nl; // "nl" labels an instance of this group of histograms // *) Toy NUA (can be applied both in real data analysis and in analysis 'on-the-fly', e.g. when running internal validation): @@ -354,22 +374,29 @@ struct InternalValidation { 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 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, ... } int fMultRangeInternalValidation[2] = {0, 0}; // min and max values for uniform multiplicity distribution in on-the-fly analysis (convention: min <= M < max) } iv; // *) Test0: struct Test0 { - TList* fTest0List = NULL; // list to hold all objects for Test0 - TProfile* fTest0FlagsPro = NULL; // store all flags for Test0 - bool fCalculateTest0 = false; // calculate or not Test0 - TProfile* fTest0Pro[gMaxCorrelator][gMaxIndex][eAsFunctionOf_N] = {{{NULL}}}; //! [order][index][0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta] - TString* fTest0Labels[gMaxCorrelator][gMaxIndex] = {{NULL}}; // all labels: k-p'th order is stored in k-1'th index. So yes, I also store 1-p - bool fCalculateTest0AsFunctionOf[eAsFunctionOf_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] - TString fFileWithLabels = ""; // path to external ROOT file which specifies all labels of interest - bool fUseDefaultLabels = false; // use default labels hardwired in GetDefaultObjArrayWithLabels(), the choice is made with cfWhichDefaultLabels - TString fWhichDefaultLabels = ""; // only for testing purposes, select one set of default labels, see GetDefaultObjArrayWithLabels for supported options -} t0; // "t0" labels an instance of this group of histograms + TList* fTest0List = NULL; // list to hold all objects for Test0 + TProfile* fTest0FlagsPro = NULL; // store all flags for Test0 + bool fCalculateTest0 = false; // calculate or not Test0 + TProfile* fTest0Pro[gMaxCorrelator][gMaxIndex][eAsFunctionOf_N] = {{{NULL}}}; //! [order][index][0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta] + bool fCalculate2DTest0 = false; // calculate or not 2D Test0 + TProfile2D* fTest0Pro2D[gMaxCorrelator][gMaxIndex][eAsFunctionOf2D_N] = {{{NULL}}}; //! [order][index][0=cent vs pt, ..., see enum eAsFunctionOf2D] + bool fCalculate3DTest0 = false; // calculate or not 2D Test0 + TProfile3D* fTest0Pro3D[gMaxCorrelator][gMaxIndex][eAsFunctionOf3D_N] = {{{NULL}}}; //! [order][index][0=cent vs pt vs eta, ..., see enum eAsFunctionOf3D] + TString* fTest0Labels[gMaxCorrelator][gMaxIndex] = {{NULL}}; // all labels: k-p'th order is stored in k-1'th index. So yes, I also store 1-p + bool fCalculateTest0AsFunctionOf[eAsFunctionOf_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] + bool fCalculate2DTest0AsFunctionOf[eAsFunctionOf2D_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] + bool fCalculate3DTest0AsFunctionOf[eAsFunctionOf3D_N] = {false}; //! [0=integrated,1=vs. multiplicity,2=vs. centrality,3=pT,4=eta,5=vs. occupancy, ...] + TString fFileWithLabels = ""; // path to external ROOT file which specifies all labels of interest + bool fUseDefaultLabels = false; // use default labels hardwired in GetDefaultObjArrayWithLabels(), the choice is made with cfWhichDefaultLabels + TString fWhichDefaultLabels = ""; // only for testing purposes, select one set of default labels, see GetDefaultObjArrayWithLabels for supported options +} t0; // "t0" labels an instance of this group of histograms // *) Eta separations: struct EtaSeparations { @@ -385,28 +412,31 @@ struct EtaSeparations { // *) Global cosmetics: struct GlobalCosmetics { - TString srs[2] = {"rec", "sim"}; // used in the histogram name as index when saved to the file - TString srs_long[2] = {"reconstructed", "simulated"}; // used in the histogram title - TString sba[2] = {"before", "after"}; // used in the histogram name as index when saved to the file - TString sba_long[2] = {"before cuts", "after cuts"}; // used in the histogram title - TString scc[eCutCounter_N] = {"abs", "seq"}; // used in the histogram name as index when saved to the file - TString scc_long[eCutCounter_N] = {"absolute", "sequential"}; // used in the histogram title + TString srs[2] = {"rec", "sim"}; // used in the histogram name as index when saved to the file + TString srsLong[2] = {"reconstructed", "simulated"}; // used in the histogram title + TString sba[2] = {"before", "after"}; // used in the histogram name as index when saved to the file + TString sbaLong[2] = {"before cuts", "after cuts"}; // used in the histogram title + TString scc[eCutCounter_N] = {"abs", "seq"}; // used in the histogram name as index when saved to the file + TString sccLong[eCutCounter_N] = {"absolute", "sequential"}; // used in the histogram title } gc; // *) Results: -struct Results { // This is in addition also sort of "abstract" interface, which defines common binning, etc., for other groups of histograms. - TList* fResultsList = NULL; //!Clone() eUseFormula, // Use or not class TFormula + eUseDatabasePDG, // Use or not class TDatabasePDG eConfiguration_N }; @@ -92,11 +93,13 @@ enum eDefaultColors { eColor = kBlack, enum eWeights { wPHI = 0, wPT = 1, wETA = 2, + wCHARGE = 3, eWeights_N }; enum eDiffWeights { // TBI 20250215 this is now obsolete, superseeded with more general implementation, see enums eDiffWeightCategory, eDiffPhiWeights, etc. wPHIPT = 0, wPHIETA, + wPHICHARGE, eDiffWeights_N }; @@ -120,13 +123,15 @@ enum eDiffPhiWeights { enum eDiffPtWeights { wPtPtAxis = 0, - // ... TBI 20250222 add all other axes on which differential pt weight could have non-trivial dependence, in the same spirit I did it above for phi weights in enum eDiffPhiWeights + wPtChargeAxis, + wPtCentralityAxis, eDiffPtWeights_N }; enum eDiffEtaWeights { wEtaEtaAxis = 0, - // ... TBI 20250222 add all other axes on which differential eta weight could have non-trivial dependence, in the same spirit I did it above for phi weights in enum eDiffPhiWeights + wEtaChargeAxis, + wEtaCentralityAxis, eDiffEtaWeights_N }; @@ -195,6 +200,18 @@ enum eEventCuts { eRefMultVsNContrUp, // formula for upper boundary cut in eReferenceMultiplicity_vs_NContributors (remember that I use naming convention "x_vs_y") eRefMultVsNContrLow, // formula for lower boundary cut in eReferenceMultiplicity_vs_NContributors (remember that I use naming convention "x_vs_y") eCentralityCorrelationsCut, // port of void SetCentralityCorrelationsCuts(...) from MuPa class. Example format: "CentFT0C_CentFT0M", so IFS is "_", until proven otherwise + + // RCT flags, see https://indico.cern.ch/event/1545907/ + up-to-date code in Common/CCDB/RCTSelectionFlags.h + // Remark 1: For the time being, I support here differentially 6 flags used to define the combined "CBT" flag, see if (label == "CBT") in Common/CCDB/RCTSelectionFlags.h + // Remark 2: If I want to use directly the combined "CBT" flag, see how it can be done using RCTFlagsChecker in + // https://github.com/AliceO2Group/O2Physics/blob/master/DPG/Tasks/AOTEvent/timeDependentQa.cxx#L115 + // But check before the memory status after RCTFlagsChecker is used. + eFT0Bad, + eITSBad, + eITSLimAccMCRepr, + eTPCBadTracking, + eTPCLimAccMCRepr, + eTPCBadPID, // ... eCentralityWeights, // used for centrality flattening. Remember that this event cut must be implemented very last, // therefore I have it separately implemented for Run 3,2,1 in EventCuts() at the very end in each case. @@ -296,7 +313,8 @@ enum eParticleCuts { eParticleCuts_N }; -enum eAsFunctionOf { +enum eAsFunctionOf { // this is a specific enum only for 1D dependence + // 1D: AFO_INTEGRATED = 0, AFO_MULTIPLICITY, // vs. default multiplicity, which is (at the moment) fSelectedTracks, i.e. number of tracks in Q-vector AFO_CENTRALITY, // vs. default centrality estimator, see how it's calculated in DetermineCentrality(...) @@ -306,9 +324,37 @@ enum eAsFunctionOf { AFO_INTERACTIONRATE, // vs. "interation rate" AFO_CURRENTRUNDURATION, // vs. "current run duration", i.e. vs "seconds since start of run" AFO_VZ, // vs. "vertex z position" + AFO_CHARGE, // vs. "particle charge" + // ... eAsFunctionOf_N }; // prefix is needed, to avoid conflict with enum eKinematics +enum eAsFunctionOf2D { // this is a specific enum only for 2D dependence + // 2D: + AFO_CENTRALITY_PT = 0, + AFO_CENTRALITY_ETA, + AFO_CENTRALITY_CHARGE, + AFO_CENTRALITY_VZ, + AFO_PT_ETA, + AFO_PT_CHARGE, + AFO_ETA_CHARGE, + // ... + eAsFunctionOf2D_N +}; + +enum eAsFunctionOf3D { // this is a specific enum only for 3D dependence + // 3D: + AFO_CENTRALITY_PT_ETA = 0, + AFO_CENTRALITY_PT_CHARGE, + AFO_CENTRALITY_PT_VZ, + AFO_CENTRALITY_ETA_VZ, + AFO_CENTRALITY_ETA_CHARGE, + AFO_CENTRALITY_VZ_CHARGE, + AFO_PT_ETA_CHARGE, + // ... + eAsFunctionOf3D_N +}; + enum eNUAPDF { ePhiNUAPDF = 0, ePtNUAPDF, @@ -317,8 +363,21 @@ enum eNUAPDF { }; enum eqvectorKine { // Here "kine" originally meant "kinematic", i.e. vs. pt or vs. eta, now it's general. + // 1D: PTq = 0, ETAq, + CHARGEq, + // ... + + // 2D: // Yes, I linearize 2D case, in an analogy with "global bin" structure for multidimensional histograms. + PT_ETAq, + PT_CHARGEq, + ETA_CHARGEq, + // ... + + // 3D: // Yes, I linearize 3D case, in an analogy with "global bin" structure for multidimensional histograms. + PT_ETA_CHARGEq, + // ... eqvectorKine_N }; diff --git a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h index dc244873b37..bd4bca81735 100644 --- a/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h +++ b/PWGCF/MultiparticleCorrelations/Core/MuPa-MemberFunctions.h @@ -17,12 +17,12 @@ #define PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_MEMBERFUNCTIONS_H_ // ... -#include #include +#include //============================================================ -void BookBaseList() +void bookBaseList() { // Book base TList and store task configuration. @@ -125,6 +125,9 @@ void BookBaseList() fBasePro->GetXaxis()->SetBinLabel(eUseFormula, "fUseFormula"); fBasePro->Fill(eUseFormula, static_cast(tc.fUseFormula)); + fBasePro->GetXaxis()->SetBinLabel(eUseDatabasePDG, "fUseDatabasePDG"); + fBasePro->Fill(eUseDatabasePDG, static_cast(tc.fUseDatabasePDG)); + } else { // d) Define bin labels indirectly by storing them in y-axis title + local executable PostprocessLabels.C. @@ -199,6 +202,9 @@ void BookBaseList() yAxisTitle += TString::Format("%d:fUseFormula; ", static_cast(eUseFormula)); fBasePro->Fill(eUseFormula, static_cast(tc.fUseFormula)); + yAxisTitle += TString::Format("%d:fUseDatabasePDG; ", static_cast(eUseDatabasePDG)); + fBasePro->Fill(eUseDatabasePDG, static_cast(tc.fUseDatabasePDG)); + // ... // *) Insanity check on the number of fields in this specially crafted y-axis title: @@ -223,11 +229,11 @@ void BookBaseList() ExitFunction(__FUNCTION__); } -} // void BookBaseList() +} // void bookBaseList() //============================================================ -void DefaultConfiguration() +void defaultConfiguration() { // Default task configuration. // a) Default values are hardcoded as Configurables in the file MuPa-Configurables.h @@ -350,6 +356,7 @@ void DefaultConfiguration() tc.fUseSetBinLabel = cf_tc.cfUseSetBinLabel; tc.fUseClone = cf_tc.cfUseClone; tc.fUseFormula = cf_tc.cfUseFormula; + tc.fUseDatabasePDG = cf_tc.cfUseDatabasePDG; // *) Event histograms (for QA see below): eh.fEventHistogramsName[eNumberOfEvents] = "NumberOfEvents"; @@ -423,6 +430,12 @@ void DefaultConfiguration() ec.fEventCutName[eRefMultVsNContrUp] = "RefMultVsNContrUp"; ec.fEventCutName[eRefMultVsNContrLow] = "RefMultVsNContrLow"; ec.fEventCutName[eCentralityCorrelationsCut] = "CentralityCorrelationsCut"; + ec.fEventCutName[eFT0Bad] = "FT0Bad"; + ec.fEventCutName[eITSBad] = "ITSBad"; + ec.fEventCutName[eITSLimAccMCRepr] = "ITSLimAccMCRepr"; + ec.fEventCutName[eTPCBadTracking] = "TPCBadTracking"; + ec.fEventCutName[eTPCLimAccMCRepr] = "TPCLimAccMCRepr"; + ec.fEventCutName[eTPCBadPID] = "TPCBadPID"; ec.fEventCutName[eCentralityWeights] = "CentralityWeights"; for (int t = 0; t < eEventCuts_N; t++) { if (ec.fEventCutName[t].EqualTo("")) { @@ -507,29 +520,106 @@ void DefaultConfiguration() // *) Multiparticle correlations: mupa.fCalculateCorrelations = cf_mupa.cfCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED] = cf_mupa.cfCalculateCorrelationsAsFunctionOfIntegrated && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY] = cf_mupa.cfCalculateCorrelationsAsFunctionOfMultiplicity && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY] = cf_mupa.cfCalculateCorrelationsAsFunctionOfCentrality && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] = cf_mupa.cfCalculateCorrelationsAsFunctionOfPt && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] = cf_mupa.cfCalculateCorrelationsAsFunctionOfEta && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY] = cf_mupa.cfCalculateCorrelationsAsFunctionOfOccupancy && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE] = cf_mupa.cfCalculateCorrelationsAsFunctionOfInteractionRate && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION] = cf_mupa.cfCalculateCorrelationsAsFunctionOfCurrentRunDuration && mupa.fCalculateCorrelations; - mupa.fCalculateCorrelationsAsFunctionOf[AFO_VZ] = cf_mupa.cfCalculateCorrelationsAsFunctionOfVz && mupa.fCalculateCorrelations; + + // *) Use configurable array cfCalculateCorrelationsAsFunctionOf, to specify vs which observable correlations will be calculated (flags 1 or 0). + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf. + auto lCalculateCorrelationsAsFunctionOf = cf_mupa.cfCalculateCorrelationsAsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculateCorrelationsAsFunctionOf.size() != eAsFunctionOf_N) { + LOGF(info, "\033[1;31m lCalculateCorrelationsAsFunctionOf.size() = %d\033[0m", lCalculateCorrelationsAsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf_N) = %d\033[0m", static_cast(eAsFunctionOf_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculateCorrelationsAsFunctionOf, and number of entries in enum eAsFunctionOf_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& mupa.fCalculateCorrelations" below, to switch off calculation of all correlations with one common flag: + mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_PT]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_ETA]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_VZ] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_VZ]) && mupa.fCalculateCorrelations; + mupa.fCalculateCorrelationsAsFunctionOf[AFO_CHARGE] = Alright(lCalculateCorrelationsAsFunctionOf[AFO_CHARGE]) && mupa.fCalculateCorrelations; + // ... // *) Test0: + // 1D: t0.fCalculateTest0 = cf_t0.cfCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_INTEGRATED] = cf_t0.cfCalculateTest0AsFunctionOfIntegrated && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_MULTIPLICITY] = cf_t0.cfCalculateTest0AsFunctionOfMultiplicity && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_CENTRALITY] = cf_t0.cfCalculateTest0AsFunctionOfCentrality && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_PT] = cf_t0.cfCalculateTest0AsFunctionOfPt && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_ETA] = cf_t0.cfCalculateTest0AsFunctionOfEta && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_OCCUPANCY] = cf_t0.cfCalculateTest0AsFunctionOfOccupancy && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_INTERACTIONRATE] = cf_t0.cfCalculateTest0AsFunctionOfInteractionRate && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION] = cf_t0.cfCalculateTest0AsFunctionOfCurrentRunDuration && t0.fCalculateTest0; - t0.fCalculateTest0AsFunctionOf[AFO_VZ] = cf_t0.cfCalculateTest0AsFunctionOfVz && t0.fCalculateTest0; - if (t0.fCalculateTest0) { + // *) Use configurable array cfCalculateTest0AsFunctionOf, to specify vs which observable Test0 will be calculated (flags 1 or 0). + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf. + auto lCalculateTest0AsFunctionOf = cf_t0.cfCalculateTest0AsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculateTest0AsFunctionOf.size() != eAsFunctionOf_N) { + LOGF(info, "\033[1;31m lCalculateTest0AsFunctionOf.size() = %d\033[0m", lCalculateTest0AsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf_N) = %d\033[0m", static_cast(eAsFunctionOf_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculateTest0AsFunctionOf, and number of entries in enum eAsFunctionOf_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& t0.fCalculateTest0" below, to switch off calculation of all Test0 with one common flag: + t0.fCalculateTest0AsFunctionOf[AFO_INTEGRATED] = Alright(lCalculateTest0AsFunctionOf[AFO_INTEGRATED]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_MULTIPLICITY] = Alright(lCalculateTest0AsFunctionOf[AFO_MULTIPLICITY]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_CENTRALITY] = Alright(lCalculateTest0AsFunctionOf[AFO_CENTRALITY]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_PT] = Alright(lCalculateTest0AsFunctionOf[AFO_PT]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_ETA] = Alright(lCalculateTest0AsFunctionOf[AFO_ETA]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_OCCUPANCY] = Alright(lCalculateTest0AsFunctionOf[AFO_OCCUPANCY]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_INTERACTIONRATE] = Alright(lCalculateTest0AsFunctionOf[AFO_INTERACTIONRATE]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION] = Alright(lCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_VZ] = Alright(lCalculateTest0AsFunctionOf[AFO_VZ]) && t0.fCalculateTest0; + t0.fCalculateTest0AsFunctionOf[AFO_CHARGE] = Alright(lCalculateTest0AsFunctionOf[AFO_CHARGE]) && t0.fCalculateTest0; + // ... + + // 2D: + t0.fCalculate2DTest0 = cf_t0.cfCalculate2DTest0; + + // *) Use configurable array cfCalculate2DTest0AsFunctionOf, to specify vs which two observables Test0 will be calculated (flags 1 or 0). + // Supported format: "0-someName1_someName_2" and "1-someName1_someName_2", where both "-" and "_" are IFS, but with different meaning. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf2D_N. + auto lCalculate2DTest0AsFunctionOf = cf_t0.cfCalculate2DTest0AsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculate2DTest0AsFunctionOf.size() != eAsFunctionOf2D_N) { + LOGF(info, "\033[1;31m lCalculate2DTest0AsFunctionOf.size() = %d\033[0m", lCalculate2DTest0AsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf2D_N) = %d\033[0m", static_cast(eAsFunctionOf2D_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculate2DTest0AsFunctionOf, and number of entries in enum eAsFunctionOf2D_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& t0.fCalculate2DTest0" below, to switch off calculation of all Test0 with one common flag: + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_VZ] = Alright(lCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_VZ]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] = Alright(lCalculate2DTest0AsFunctionOf[AFO_PT_ETA]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE] = Alright(lCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE]) && t0.fCalculate2DTest0; + t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] = Alright(lCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE]) && t0.fCalculate2DTest0; + + // ... + + // 3D: + t0.fCalculate3DTest0 = cf_t0.cfCalculate3DTest0; + + // *) Use configurable array cfCalculate3DTest0AsFunctionOf, to specify vs which two observables Test0 will be calculated (flags 1 or 0). + // Supported format: "0-someName1_someName_2" and "1-someName1_someName_2", where both "-" and "_" are IFS, but with different meaning. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf3D_N. + auto lCalculate3DTest0AsFunctionOf = cf_t0.cfCalculate3DTest0AsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculate3DTest0AsFunctionOf.size() != eAsFunctionOf3D_N) { + LOGF(info, "\033[1;31m lCalculate3DTest0AsFunctionOf.size() = %d\033[0m", lCalculate3DTest0AsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf3D_N) = %d\033[0m", static_cast(eAsFunctionOf3D_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculate3DTest0AsFunctionOf, and number of entries in enum eAsFunctionOf3D_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& t0.fCalculate3DTest0" below, to switch off calculation of all Test0 with one common flag: + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE]) && t0.fCalculate3DTest0; + t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE] = Alright(lCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) && t0.fCalculate3DTest0; + + // ... + + if (t0.fCalculateTest0 || t0.fCalculate2DTest0 || t0.fCalculate3DTest0) { t0.fFileWithLabels = TString(cf_t0.cfFileWithLabels); t0.fUseDefaultLabels = cf_t0.cfUseDefaultLabels; t0.fWhichDefaultLabels = TString(cf_t0.cfWhichDefaultLabels); @@ -577,7 +667,11 @@ 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 { // ... TBI 20250222 add support for other dimensions of differential pt weights, in the same spirit i did it for differential phi weights + } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCharge")) { + pw.fUseDiffPtWeights[wPtChargeAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; + } else if (TString(lWhichDiffPtWeights[dpw]).Contains("wCentrality")) { + pw.fUseDiffPtWeights[wPtCentralityAxis] = Alright(lWhichDiffPtWeights[dpw]) && pw.fUseDiffPtWeights[wPtPtAxis]; + } else { LOGF(fatal, "\033[1;31m%s at line %d : The setting %s in configurable cfWhichDiffPtWeights is not supported yet. See enum eDiffPtWeights . \n \033[0m", __FUNCTION__, __LINE__, TString(lWhichDiffPtWeights[dpw]).Data()); } } @@ -592,7 +686,11 @@ 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 { // ... TBI 20250222 add support for other dimensions of differential eta weights, in the same spirit i did it for differential phi weights + } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCharge")) { + pw.fUseDiffEtaWeights[wEtaChargeAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; + } else if (TString(lWhichDiffEtaWeights[dpw]).Contains("wCentrality")) { + pw.fUseDiffEtaWeights[wEtaCentralityAxis] = Alright(lWhichDiffEtaWeights[dpw]) && pw.fUseDiffEtaWeights[wEtaEtaAxis]; + } else { LOGF(fatal, "\033[1;31m%s at line %d : The setting %s in configurable cfWhichDiffEtaWeights is not supported yet. See enum eDiffEtaWeights . \n \033[0m", __FUNCTION__, __LINE__, TString(lWhichDiffEtaWeights[dpw]).Data()); } } @@ -688,11 +786,23 @@ void DefaultConfiguration() iv.fInternalValidationForceBailout = cf_iv.cfInternalValidationForceBailout; iv.fnEventsInternalValidation = cf_iv.cfnEventsInternalValidation; iv.fRescaleWithTheoreticalInput = cf_iv.cfRescaleWithTheoreticalInput; + iv.fRandomizeReactionPlane = cf_iv.cfRandomizeReactionPlane; iv.fHarmonicsOptionInternalValidation = new TString(cf_iv.cfHarmonicsOptionInternalValidation); // *) Results histograms: - // Define axis titles: - // Remark: keep ordering in sync with enum eAsFunctionOf + // **) Fixed-length or variable-length binning: + // Remark: keep ordering in sync with enum eAsFunctionOf: + cf_res.cfUseVariableLengthMultBins ? res.fUseResultsProVariableLengthBins[AFO_MULTIPLICITY] = true : res.fUseResultsProVariableLengthBins[AFO_MULTIPLICITY] = false; + cf_res.cfUseVariableLengthCentBins ? res.fUseResultsProVariableLengthBins[AFO_CENTRALITY] = true : res.fUseResultsProVariableLengthBins[AFO_CENTRALITY] = false; + cf_res.cfUseVariableLengthPtBins ? res.fUseResultsProVariableLengthBins[AFO_PT] = true : res.fUseResultsProVariableLengthBins[AFO_PT] = false; + cf_res.cfUseVariableLengthEtaBins ? res.fUseResultsProVariableLengthBins[AFO_ETA] = true : res.fUseResultsProVariableLengthBins[AFO_ETA] = false; + cf_res.cfUseVariableLengthOccuBins ? res.fUseResultsProVariableLengthBins[AFO_OCCUPANCY] = true : res.fUseResultsProVariableLengthBins[AFO_OCCUPANCY] = false; + cf_res.cfUseVariableLengthCRDBins ? res.fUseResultsProVariableLengthBins[AFO_CURRENTRUNDURATION] = true : res.fUseResultsProVariableLengthBins[AFO_CURRENTRUNDURATION] = false; + cf_res.cfUseVariableLengthVzBins ? res.fUseResultsProVariableLengthBins[AFO_VZ] = true : res.fUseResultsProVariableLengthBins[AFO_VZ] = false; + + // **) Define axis titles: + // Remark: keep ordering in sync with enum eAsFunctionOf + // 1D: res.fResultsProXaxisTitle[AFO_INTEGRATED] = "integrated"; res.fResultsProRawName[AFO_INTEGRATED] = "int"; // this is how it appears simplified in the hist name when saved to the file res.fResultsProXaxisTitle[AFO_MULTIPLICITY] = "multiplicity"; @@ -711,6 +821,16 @@ void DefaultConfiguration() res.fResultsProRawName[AFO_CURRENTRUNDURATION] = "crd"; res.fResultsProXaxisTitle[AFO_VZ] = "vertex z position"; res.fResultsProRawName[AFO_VZ] = "vz"; + res.fResultsProXaxisTitle[AFO_CHARGE] = "particle charge"; + res.fResultsProRawName[AFO_CHARGE] = "charge"; + // ... + + // 2D: + // Remark: I re-use the above definitions for 1D. + + // 3D: + // Remark: I re-use the above definitions for 1D. + res.fSaveResultsHistograms = cf_res.cfSaveResultsHistograms; // *) QA: @@ -742,7 +862,7 @@ void DefaultConfiguration() qa.fOccupancyEstimatorName[eFT0COccupancyInTimeRange] = "FT0COccupancyInTimeRange"; // **) Names of QA 2D event histograms: - // Remark: Do NOT use FancyFormatting here, only later in BookQAHistograms() for axis titles! + // Remark: Do NOT use FancyFormatting here, only later in bookQAHistograms() for axis titles! qa.fEventHistogramsName2D[eMultiplicity_vs_ReferenceMultiplicity] = Form("%s_vs_%s", eh.fEventHistogramsName[eMultiplicity].Data(), eh.fEventHistogramsName[eReferenceMultiplicity].Data()); qa.fEventHistogramsName2D[eMultiplicity_vs_NContributors] = Form("%s_vs_%s", eh.fEventHistogramsName[eMultiplicity].Data(), eh.fEventHistogramsName[eNContributors].Data()); qa.fEventHistogramsName2D[eMultiplicity_vs_Centrality] = Form("%s_vs_%s", eh.fEventHistogramsName[eMultiplicity].Data(), eh.fEventHistogramsName[eCentrality].Data()); @@ -882,15 +1002,29 @@ void DefaultConfiguration() // ** Eta separations: es.fCalculateEtaSeparations = cf_es.cfCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED] = cf_es.cfCalculateEtaSeparationsAsFunctionOfIntegrated && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY] = cf_es.cfCalculateEtaSeparationsAsFunctionOfMultiplicity && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY] = cf_es.cfCalculateEtaSeparationsAsFunctionOfCentrality && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT] = cf_es.cfCalculateEtaSeparationsAsFunctionOfPt && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_ETA] = false; // this one doesn't make sense in this context, obviously - es.fCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY] = cf_es.cfCalculateEtaSeparationsAsFunctionOfOccupancy && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE] = cf_es.cfCalculateEtaSeparationsAsFunctionOfInteractionRate && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION] = cf_es.cfCalculateEtaSeparationsAsFunctionOfCurrentRunDuration && es.fCalculateEtaSeparations; - es.fCalculateEtaSeparationsAsFunctionOf[AFO_VZ] = cf_es.cfCalculateEtaSeparationsAsFunctionOfVz && es.fCalculateEtaSeparations; + + // *) Use configurable array cfCalculateEtaSeparationsAsFunctionOf, to specify vs which observable EtaSeparations will be calculated (flags 1 or 0). + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. + // Ordering of the flags in that array is interpreted through ordering of enums in enum eAsFunctionOf. + auto lCalculateEtaSeparationsAsFunctionOf = cf_es.cfCalculateEtaSeparationsAsFunctionOf.value; // this is now the local version of that string array from configurable. + if (lCalculateEtaSeparationsAsFunctionOf.size() != eAsFunctionOf_N) { + LOGF(info, "\033[1;31m lCalculateEtaSeparationsAsFunctionOf.size() = %d\033[0m", lCalculateEtaSeparationsAsFunctionOf.size()); + LOGF(info, "\033[1;31m eAsFunctionOf_N) = %d\033[0m", static_cast(eAsFunctionOf_N)); + LOGF(fatal, "\033[1;31m%s at line %d : Mismatch in the number of flags in configurable cfCalculateEtaSeparationsAsFunctionOf, and number of entries in enum eAsFunctionOf_N \n \033[0m", __FUNCTION__, __LINE__); + } + + // I append "&& es.fCalculateEtaSeparations" below, to switch off calculation of all correlations with one common flag: + es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_PT]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_ETA] = false; // yes, in this context this one doesn't make sense + es.fCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_VZ] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_VZ]) && es.fCalculateEtaSeparations; + es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE] = Alright(lCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) && es.fCalculateEtaSeparations; + // ... if (es.fCalculateEtaSeparations) { auto lEtaSeparationsValues = cf_es.cfEtaSeparationsValues.value; @@ -918,11 +1052,62 @@ void DefaultConfiguration() } // if(es.fCalculateEtaSeparations) { + // Set the flags qv.fCalculateqvectorsKineAny, fCalculateqvectorsKine[eqvectorKine_N] and fCalculateqvectorsKineEtaSeparations[eqvectorKine_N]: + // TBI 20250601 I have to do it without loop, until I provide support for 2D and 3D to Correlations and EtaSeparations + + // Test0 and Correlations: + if (mupa.fCalculateCorrelationsAsFunctionOf[AfoKineMap1D(PTq)] || t0.fCalculateTest0AsFunctionOf[AfoKineMap1D(PTq)]) { + qv.fCalculateqvectorsKine[PTq] = true; + } + if (mupa.fCalculateCorrelationsAsFunctionOf[AfoKineMap1D(ETAq)] || t0.fCalculateTest0AsFunctionOf[AfoKineMap1D(ETAq)]) { + qv.fCalculateqvectorsKine[ETAq] = true; + } + if (mupa.fCalculateCorrelationsAsFunctionOf[AfoKineMap1D(CHARGEq)] || t0.fCalculateTest0AsFunctionOf[AfoKineMap1D(CHARGEq)]) { + qv.fCalculateqvectorsKine[CHARGEq] = true; + } + if (t0.fCalculate2DTest0AsFunctionOf[AfoKineMap2D(PT_ETAq)]) { + qv.fCalculateqvectorsKine[PT_ETAq] = true; + } + if (t0.fCalculate2DTest0AsFunctionOf[AfoKineMap2D(PT_CHARGEq)]) { + qv.fCalculateqvectorsKine[PT_CHARGEq] = true; + } + if (t0.fCalculate2DTest0AsFunctionOf[AfoKineMap2D(ETA_CHARGEq)]) { + qv.fCalculateqvectorsKine[ETA_CHARGEq] = true; + } + if (t0.fCalculate3DTest0AsFunctionOf[AfoKineMap3D(PT_ETA_CHARGEq)]) { + qv.fCalculateqvectorsKine[PT_ETA_CHARGEq] = true; + } + + // Eta separations: + if (es.fCalculateEtaSeparationsAsFunctionOf[AfoKineMap1D(PTq)]) { + qv.fCalculateqvectorsKineEtaSeparations[PTq] = true; + } + qv.fCalculateqvectorsKineEtaSeparations[ETAq] = false; // yes, this one is alwas set explicitly to false + if (es.fCalculateEtaSeparationsAsFunctionOf[AfoKineMap1D(CHARGEq)]) { + qv.fCalculateqvectorsKineEtaSeparations[CHARGEq] = true; + } + qv.fCalculateqvectorsKineEtaSeparations[PT_ETAq] = false; // yes, this one is alwas set explicitly to false + + // TBI 20250617 comment in this branch, when i implement support for 2D eta separations. + // if (es.fCalculate2DEtaSeparationsAsFunctionOf[AfoKineMap2D(PT_CHARGEq)]) { + // qv.fCalculateqvectorsKineEtaSeparations[PT_CHARGEq] = true; + // } + + qv.fCalculateqvectorsKineEtaSeparations[ETA_CHARGEq] = false; // yes, this one is alwas set explicitly to false + qv.fCalculateqvectorsKineEtaSeparations[PT_ETA_CHARGEq] = false; // yes, this one is alwas set explicitly to false + + for (int qKine = 0; qKine < eqvectorKine_N; qKine++) { + if (qv.fCalculateqvectorsKine[qKine] || qv.fCalculateqvectorsKineEtaSeparations[qKine]) { + qv.fCalculateqvectorsKineAny = true; + break; // yes, I need at least one kine calculus, to set this flag to true + } + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } -} // void DefaultConfiguration() +} // void defaultConfiguration() //============================================================ @@ -947,7 +1132,7 @@ bool Alright(TString s) } int nEntries = oa->GetEntries(); if (2 != nEntries) { - LOGF(fatal, "\033[1;31m%s at line %d : string expected in this function must be formatted as \"someName-0\" or \"someName-1\" => s = %s\033[0m", __FUNCTION__, __LINE__, s.Data()); + LOGF(fatal, "\033[1;31m%s at line %d : string expected in this function must be formatted as \"0-someName\" or \"1-someName\" => s = %s\033[0m", __FUNCTION__, __LINE__, s.Data()); } // b) Do the thing: @@ -972,7 +1157,7 @@ bool Alright(TString s) //============================================================ -void DefaultBooking() +void defaultBooking() { // Set here which histograms are booked by default. @@ -993,7 +1178,7 @@ void DefaultBooking() // *) By default all event histograms are booked. If you do not want particular event histogram to be booked, // use configurable array cfBookEventHistograms, where you can specify name of the histogram accompanied with flags 1 (book) or 0 (do not book). - // Supported format: "someName-0" and "someName-1", where "-" is a field separator. + // Supported format: "0-someName" and "1-someName", where "-" is a field separator. // Ordering of the flags in that array is interpreted through ordering of enums in enum eEventHistograms. auto lBookEventHistograms = cf_eh.cfBookEventHistograms.value; // this is now the local version of that string array from configurable. if (lBookEventHistograms.size() != eEventHistograms_N) { @@ -1354,16 +1539,16 @@ void DefaultBooking() ExitFunction(__FUNCTION__); } -} // void DefaultBooking() +} // void defaultBooking() //============================================================ -void DefaultBinning() +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(). + // 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. // a) Default binning for event histograms; @@ -1524,81 +1709,98 @@ void DefaultBinning() ph.fParticleHistogramsBins2D[ePhiEta][eY][2] = ph.fParticleHistogramsBins[eEta][2]; // d) Default binning for results histograms: - // Remark: These bins apply to following categories fCorrelationsPro, fNestedLoopsPro, fTest0Pro, and fResultsPro. - // *) For integrated resullts, binning is always the same: - res.fResultsProFixedLengthBins[AFO_INTEGRATED][0] = 1; - res.fResultsProFixedLengthBins[AFO_INTEGRATED][1] = 0.; - res.fResultsProFixedLengthBins[AFO_INTEGRATED][2] = 1.; - // *) Fixed-length binning vs. multiplicity: - this->InitializeFixedLengthBins(AFO_MULTIPLICITY); - // *) Fixed-length binning vs. centrality: - this->InitializeFixedLengthBins(AFO_CENTRALITY); - // *) Fixed-length binning vs. pt: - this->InitializeFixedLengthBins(AFO_PT); - // *) Fixed-length binning vs. eta: - this->InitializeFixedLengthBins(AFO_ETA); - // *) Fixed-length binning vs. occupancy: - this->InitializeFixedLengthBins(AFO_OCCUPANCY); - // *) Fixed-length binning vs. interaction rate: - this->InitializeFixedLengthBins(AFO_INTERACTIONRATE); - // *) Fixed-length binning vs. run duration: - this->InitializeFixedLengthBins(AFO_CURRENTRUNDURATION); - // *) Vertex z position: - this->InitializeFixedLengthBins(AFO_VZ); - - // e) Variable-length binning set via MuPa-Configurables.h: - // *) Variable-length binning vs. multiplicity: - if (cf_res.cfUseVariableLengthMultBins) { + // Remark: These bins apply to following categories fCorrelationsPro, fNestedLoopsPro, fTest0Pro, fResultsPro, and all 2D and 3D variants. + // 1D: + // *) For integrated results, binning is always the same nBins = 1 in (0.,1.): + res.fResultsProBinEdges[AFO_INTEGRATED] = new TArrayD(2); + res.fResultsProBinEdges[AFO_INTEGRATED]->AddAt(0., 0); + res.fResultsProBinEdges[AFO_INTEGRATED]->AddAt(1., 1); + + // *) Binning vs. multiplicity: + if (res.fUseResultsProVariableLengthBins[AFO_MULTIPLICITY]) { this->InitializeVariableLengthBins(AFO_MULTIPLICITY); + } else { + this->InitializeFixedLengthBins(AFO_MULTIPLICITY); } - // *) Variable-length binning vs. centrality: - if (cf_res.cfUseVariableLengthCentBins) { + + // *) Binning vs. centrality: + if (res.fUseResultsProVariableLengthBins[AFO_CENTRALITY]) { this->InitializeVariableLengthBins(AFO_CENTRALITY); + } else { + this->InitializeFixedLengthBins(AFO_CENTRALITY); } - // *) Variable-length binning vs. pt: - if (cf_res.cfUseVariableLengthPtBins) { + + // *) Binning vs. pt: + if (res.fUseResultsProVariableLengthBins[AFO_PT]) { this->InitializeVariableLengthBins(AFO_PT); + } else { + this->InitializeFixedLengthBins(AFO_PT); } - // *) Variable-length binning vs. eta: - if (cf_res.cfUseVariableLengthEtaBins) { + + // *) Binning vs. eta: + if (res.fUseResultsProVariableLengthBins[AFO_ETA]) { this->InitializeVariableLengthBins(AFO_ETA); + } else { + this->InitializeFixedLengthBins(AFO_ETA); } - // *) Variable-length binning vs. occupancy: - if (cf_res.cfUseVariableLengthOccuBins) { + + // *) Binning vs. occupancy: + if (res.fUseResultsProVariableLengthBins[AFO_OCCUPANCY]) { this->InitializeVariableLengthBins(AFO_OCCUPANCY); + } else { + this->InitializeFixedLengthBins(AFO_OCCUPANCY); } - // *) Variable-length binning vs. interaction rate: - if (cf_res.cfUseVariableLengthIRBins) { + + // *) Binning vs. interaction rate: + if (res.fUseResultsProVariableLengthBins[AFO_INTERACTIONRATE]) { this->InitializeVariableLengthBins(AFO_INTERACTIONRATE); + } else { + this->InitializeFixedLengthBins(AFO_INTERACTIONRATE); } - // *) Variable-length binning vs. run duration: - if (cf_res.cfUseVariableLengthCRDBins) { + + // *) Binning vs. current run duration: + if (res.fUseResultsProVariableLengthBins[AFO_CURRENTRUNDURATION]) { this->InitializeVariableLengthBins(AFO_CURRENTRUNDURATION); + } else { + this->InitializeFixedLengthBins(AFO_CURRENTRUNDURATION); } - // *) Variable-length binning vs. vertex z position: - if (cf_res.cfUseVariableLengthVzBins) { + + // *) Binning vs. vertex z position: + if (res.fUseResultsProVariableLengthBins[AFO_VZ]) { this->InitializeVariableLengthBins(AFO_VZ); + } else { + this->InitializeFixedLengthBins(AFO_VZ); } + // *) 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"). + res.fResultsProBinEdges[AFO_CHARGE] = new TArrayD(3); + res.fResultsProBinEdges[AFO_CHARGE]->AddAt(-2., 0); + res.fResultsProBinEdges[AFO_CHARGE]->AddAt(0., 1); + res.fResultsProBinEdges[AFO_CHARGE]->AddAt(2., 2); + + // ... + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } -} // void DefaultBinning() +} // void defaultBinning() //============================================================ void InitializeFixedLengthBins(eAsFunctionOf AFO) { - // This is a helper function to suppress code bloat in DefaultBinning(). + // This is a helper function to suppress code bloat in defaultBinning(). // It merely initalizes res.fResultsProFixedLengthBins[...] from corresponding configurables + a few other minor thingies. + // I do not have here AFO_INTEGRATED and AFO_CHARGE, because for them binning is always the same, i.e. no need for configurable. if (tc.fVerbose) { StartFunction(__FUNCTION__); } // Common local vector for all fixed-length bins: - std::vector lFixedLength_bins; + std::vector lFixedLength_bins; switch (AFO) { case AFO_MULTIPLICITY: { @@ -1644,15 +1846,10 @@ void InitializeFixedLengthBins(eAsFunctionOf AFO) if (lFixedLength_bins.size() != 3) { LOGF(fatal, "in function \033[1;31m%s at line %d => The array cfFixedLength_bins must have have 3 entries: {nBins, min, max} \n \033[0m", __FUNCTION__, __LINE__); } - res.fResultsProFixedLengthBins[AFO][0] = lFixedLength_bins[0]; - res.fResultsProFixedLengthBins[AFO][1] = lFixedLength_bins[1]; - res.fResultsProFixedLengthBins[AFO][2] = lFixedLength_bins[2]; + + res.fResultsProBinEdges[AFO] = ArrayWithBinEdges(lFixedLength_bins[0], lFixedLength_bins[1], lFixedLength_bins[2]); if (tc.fVerbose) { - LOGF(info, "\033[1;32m %s : fixed-length %s bins \033[0m", __FUNCTION__, res.fResultsProXaxisTitle[AFO].Data()); - LOGF(info, "\033[1;32m [0] : %f \033[0m", res.fResultsProFixedLengthBins[AFO][0]); - LOGF(info, "\033[1;32m [1] : %f \033[0m", res.fResultsProFixedLengthBins[AFO][1]); - LOGF(info, "\033[1;32m [2] : %f \033[0m", res.fResultsProFixedLengthBins[AFO][2]); ExitFunction(__FUNCTION__); } @@ -1662,7 +1859,7 @@ void InitializeFixedLengthBins(eAsFunctionOf AFO) void InitializeVariableLengthBins(eAsFunctionOf AFO) { - // This is a helper function to suppress code bloat in DefaultBinning(). + // This is a helper function to suppress code bloat in defaultBinning(). // It merely initalizes res.fResultsProVariableLengthBins[...] from corresponding configurables + a few other minor thingies. if (tc.fVerbose) { @@ -1670,7 +1867,7 @@ void InitializeVariableLengthBins(eAsFunctionOf AFO) } // Common local vector for all variable-length bins: - std::vector lVariableLength_bins; + std::vector lVariableLength_bins; switch (AFO) { case AFO_MULTIPLICITY: { @@ -1713,15 +1910,14 @@ void InitializeVariableLengthBins(eAsFunctionOf AFO) } // switch(AFO) // From this point onward, the code is the same for any AFO variable: - res.fUseResultsProVariableLengthBins[AFO] = true; if (lVariableLength_bins.size() < 2) { LOGF(fatal, "in function \033[1;31m%s at line %d => The array cfVariableLength_bins must have at least 2 entries \n \033[0m", __FUNCTION__, __LINE__); } - res.fResultsProVariableLengthBins[AFO] = new TArrayF(lVariableLength_bins.size(), lVariableLength_bins.data()); + res.fResultsProBinEdges[AFO] = new TArrayD(lVariableLength_bins.size(), lVariableLength_bins.data()); if (tc.fVerbose) { LOGF(info, "\033[1;32m %s : variable-length %s bins \033[0m", __FUNCTION__, res.fResultsProXaxisTitle[AFO].Data()); - for (int i = 0; i < res.fResultsProVariableLengthBins[AFO]->GetSize(); i++) { - LOGF(info, "\033[1;32m [%d] : %f \033[0m", i, res.fResultsProVariableLengthBins[AFO]->GetAt(i)); + for (int i = 0; i < res.fResultsProBinEdges[AFO]->GetSize(); i++) { + LOGF(info, "\033[1;32m [%d] : %f \033[0m", i, res.fResultsProBinEdges[AFO]->GetAt(i)); } } @@ -1772,7 +1968,7 @@ void CastStringIntoArray(int AFO) //============================================================ -void DefaultCuts() +void defaultCuts() { // Define default cuts. Default cuts are hardwired in MuPa-Configurables.h. @@ -1849,6 +2045,12 @@ void DefaultCuts() ec.fUseEventCuts[eRefMultVsNContrUp] = Alright(lUseEventCuts[eRefMultVsNContrUp]); ec.fUseEventCuts[eRefMultVsNContrLow] = Alright(lUseEventCuts[eRefMultVsNContrLow]); ec.fUseEventCuts[eCentralityCorrelationsCut] = Alright(lUseEventCuts[eCentralityCorrelationsCut]); + ec.fUseEventCuts[eFT0Bad] = Alright(lUseEventCuts[eFT0Bad]); + ec.fUseEventCuts[eITSBad] = Alright(lUseEventCuts[eITSBad]); + ec.fUseEventCuts[eITSLimAccMCRepr] = Alright(lUseEventCuts[eITSLimAccMCRepr]); + ec.fUseEventCuts[eTPCBadTracking] = Alright(lUseEventCuts[eTPCBadTracking]); + ec.fUseEventCuts[eTPCLimAccMCRepr] = Alright(lUseEventCuts[eTPCLimAccMCRepr]); + ec.fUseEventCuts[eTPCBadPID] = Alright(lUseEventCuts[eTPCBadPID]); ec.fUseEventCuts[eCentralityWeights] = Alright(lUseEventCuts[eCentralityWeights]); // **) event cuts defined via booleans: @@ -1870,6 +2072,12 @@ void DefaultCuts() ec.fUseEventCuts[eNoPileupTPC] = ec.fUseEventCuts[eNoPileupTPC] && cf_ec.cfUseNoPileupTPC; ec.fUseEventCuts[eNoPileupFromSPD] = ec.fUseEventCuts[eNoPileupFromSPD] && cf_ec.cfUseNoPileupFromSPD; ec.fUseEventCuts[eNoSPDOnVsOfPileup] = ec.fUseEventCuts[eNoSPDOnVsOfPileup] && cf_ec.cfUseNoSPDOnVsOfPileup; + ec.fUseEventCuts[eFT0Bad] = ec.fUseEventCuts[eFT0Bad] && cf_ec.cfUseFT0Bad; + ec.fUseEventCuts[eITSBad] = ec.fUseEventCuts[eITSBad] && cf_ec.cfUseITSBad; + ec.fUseEventCuts[eITSLimAccMCRepr] = ec.fUseEventCuts[eITSLimAccMCRepr] && cf_ec.cfUseITSLimAccMCRepr; + ec.fUseEventCuts[eTPCBadTracking] = ec.fUseEventCuts[eTPCBadTracking] && cf_ec.cfUseTPCBadTracking; + ec.fUseEventCuts[eTPCLimAccMCRepr] = ec.fUseEventCuts[eTPCLimAccMCRepr] && cf_ec.cfUseTPCLimAccMCRepr; + ec.fUseEventCuts[eTPCBadPID] = ec.fUseEventCuts[eTPCBadPID] && cf_ec.cfUseTPCBadPID; ec.fUseEventCuts[eCentralityWeights] = ec.fUseEventCuts[eCentralityWeights] && cf_cw.cfUseCentralityWeights; // **) event cuts defined via [min, max): @@ -2101,13 +2309,13 @@ void DefaultCuts() ExitFunction(__FUNCTION__); } -} // void DefaultCuts() +} // void defaultCuts() //============================================================ -void SpecificCuts(TString whichSpecificCuts) +void specificCuts(TString whichSpecificCuts) { - // After default cuts are applied, on top of them apply analysis-specific cuts. Has to be called after DefaultBinning() and DefaultCuts(). + // After default cuts are applied, on top of them apply analysis-specific cuts. Has to be called after defaultBinning() and defaultCuts(). // Here I hardwire defalt cuts and settings for a given period which will overwrite whatever is set in configurables. // When I do systematic checks, this option shall NOT be used, because values for some cuts which I plan to vary, are also hardwired here. // Both event and particle cuts are hardwired here. As well as some other settings. @@ -2138,10 +2346,10 @@ void SpecificCuts(TString whichSpecificCuts) } // b) Implementation of analysis-specific cuts: - // Remark #1: Whichever cuts start to repeat below across different case statements, promote them into DefaultCuts(), i.e. hardwire those values in configurables. + // Remark #1: Whichever cuts start to repeat below across different case statements, promote them into defaultCuts(), i.e. hardwire those values in configurables. // The idea is to keep here cuts only which are specific for particular analysis, and which are unlikely ever to change as a default cut for that particular analysis. // Remark #2: Remember that the values for the cuts hardwired here overwrite the ones set as default values in configurables. - // If you want to reconfigure all cuts below manually via configurables, simply do not call SpecificCuts, i.e. set in JSON "cfUseSpecificCuts": "false" + // If you want to reconfigure all cuts below manually via configurables, simply do not call specificCuts, i.e. set in JSON "cfUseSpecificCuts": "false" // Therefore, if I want to vary some of these cuts via configurables as a part of systematics, I must set in JSON "cfUseSpecificCuts": "false" // Remark #3: Most up-to-date documentation of each cut is in enum file. switch (specificCuts) { @@ -2164,7 +2372,7 @@ void SpecificCuts(TString whichSpecificCuts) ec.fUseEventCuts[eNoPileupFromSPD] = false; // Run 2 ec.fUseEventCuts[eNoSPDOnVsOfPileup] = false; // Run 2 - ec.fUseEventCuts[eInteractionRate] = true; + ec.fUseEventCuts[eInteractionRate] = false; // I set it to false by default, to prevent having the standard memory blow-up by default ec.fdEventCuts[eInteractionRate][eMin] = 0.1; // there are some pathological non-physical events with IR = 0. See eCorrelationsVsInteractionRate_vs_ReferenceMultiplicity ec.fdEventCuts[eInteractionRate][eMax] = 1000000000.; @@ -2247,7 +2455,7 @@ void SpecificCuts(TString whichSpecificCuts) ec.fUseEventCuts[eNoPileupFromSPD] = false; // Run 2 ec.fUseEventCuts[eNoSPDOnVsOfPileup] = false; // Run 2 - ec.fUseEventCuts[eInteractionRate] = true; + ec.fUseEventCuts[eInteractionRate] = false; // I set it to false by default, to prevent having the standard memory blow-up by default ec.fdEventCuts[eInteractionRate][eMin] = 0.1; // there are some pathological non-physical events with IR = 0. See eCorrelationsVsInteractionRate_vs_ReferenceMultiplicity ec.fdEventCuts[eInteractionRate][eMax] = 1000000000.; @@ -2331,7 +2539,12 @@ void SpecificCuts(TString whichSpecificCuts) ec.fUseEventCuts[eIsGoodITSLayer3] = false; ec.fUseEventCuts[eIsGoodITSLayer0123] = false; ec.fUseEventCuts[eIsGoodITSLayersAll] = false; - + ec.fUseEventCuts[eFT0Bad] = false; + ec.fUseEventCuts[eITSBad] = false; + ec.fUseEventCuts[eITSLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadTracking] = false; + ec.fUseEventCuts[eTPCLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadPID] = false; ec.fUseEventCuts[eTrigger] = true; ec.fsEventCuts[eTrigger] = "kINT7"; // TBI 20250115 remember that it cannot be used when i procees in "Rec" some converted Run 2 MC, see enum @@ -2346,8 +2559,8 @@ void SpecificCuts(TString whichSpecificCuts) // TBI 20250331 fine-tune this cut in the same spirit for other ref. mult. estimators } - ec.fUseEventCuts[eCentralityCorrelationsCut] = true; - ec.fsEventCuts[eCentralityCorrelationsCut] = "CentRun2V0M_vs_CentRun2SPDTracklets"; + ec.fUseEventCuts[eCentralityCorrelationsCut] = false; + ec.fsEventCuts[eCentralityCorrelationsCut] = "CentRun2V0M_CentRun2SPDTracklets"; ec.fCentralityCorrelationsCutTreshold = 10.0; ec.fCentralityCorrelationsCutVersion = "Absolute"; @@ -2359,8 +2572,6 @@ void SpecificCuts(TString whichSpecificCuts) pc.fUseParticleCuts[etrackCutFlagFb2] = false; // only for Run 3 pc.fUseParticleCuts[eisPVContributor] = false; // only for Run 3 - // ... - // The rest: mupa.fCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY] = false; mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE] = false; @@ -2425,6 +2636,12 @@ void SpecificCuts(TString whichSpecificCuts) ec.fUseEventCuts[eIsGoodITSLayer3] = false; ec.fUseEventCuts[eIsGoodITSLayer0123] = false; ec.fUseEventCuts[eIsGoodITSLayersAll] = false; + ec.fUseEventCuts[eFT0Bad] = false; + ec.fUseEventCuts[eITSBad] = false; + ec.fUseEventCuts[eITSLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadTracking] = false; + ec.fUseEventCuts[eTPCLimAccMCRepr] = false; + ec.fUseEventCuts[eTPCBadPID] = false; // ec.fUseEventCuts[eTrigger] = true; // ec.fsEventCuts[eTrigger] = "kINT7"; // TBI 20250115 cannot be used when i procees in "Rec" some converted Run 2 MC, see enum @@ -2467,11 +2684,11 @@ void SpecificCuts(TString whichSpecificCuts) ExitFunction(__FUNCTION__); } -} // void SpecificCuts(const char* specificCutsName) +} // void specificCuts(const char* specificCutsName) //============================================================ -void InsanityChecksOnDefinitionsOfConfigurables() +void insanityChecksOnDefinitionsOfConfigurables() { // Do insanity checks on values obtained from configurables before using them in the remaining function. // This is really important, because one misconfigured configurable (e.g. boolean set to string), causes the whole json config to die silently, and @@ -2559,15 +2776,15 @@ void InsanityChecksOnDefinitionsOfConfigurables() ExitFunction(__FUNCTION__); } -} // InsanityChecksOnDefinitionsOfConfigurables() +} // insanityChecksOnDefinitionsOfConfigurables() //============================================================ -void InsanityChecksBeforeBooking() +void insanityChecksBeforeBooking() { - // Do insanity checks on configuration, binning and cuts. Values obtained from configurables are checked before being used in InsanityChecksOnDefinitionsOfConfigurables(). + // Do insanity checks on configuration, binning and cuts. Values obtained from configurables are checked before being used in insanityChecksOnDefinitionsOfConfigurables(). // Remember that here I cannot do insanity checks on local histograms, etc., because they are not booked yet. - // For those additional checks, use InsanityChecksAfterBooking(). + // For those additional checks, use insanityChecksAfterBooking(). // a) Insanity checks on configuration; // b) Ensure that Run 1/2 specific cuts and flags are used only in Run 1/2 (both data and sim); @@ -2680,21 +2897,20 @@ void InsanityChecksBeforeBooking() } // **) Enforce the usage of particular trigger for this dataset: - if (tc.fProcess[eProcessRec_Run2]) { - // TBI 20250115 Not really sure I need this - if I want to run only "Rec" over Monte Carlo, then obviously the condition below is pointless. - // Also here I need to be able automaticaly to determine whether I am processing real data or Monte Carlo, from the dataset itself. - // TBI 20240517 for the time being, here I am enforcing that "kINT7" is mandatory for Run 2 - // TBI 20241209 I still have to validate it for Run 1 converted real data => then expand if(...) statement above - - /* commented out temporariy, see TBI 20250115 above - if (!(ec.fUseEventCuts[eTrigger] && ec.fsEventCuts[eTrigger].EqualTo("kINT7"))) { - LOGF(fatal, "\033[1;31m%s at line %d : trigger \"%s\" is not internally validated/supported yet. Add it to the list of supported triggers, if you really want to use that one.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); - } else { - LOGF(info, "\033[1;32m%s at line %d : WARNING => trigger \"%s\" can be used only on real converted Run 2 and Run 1 data. For MC converted Run 2 and Run 1 data, this trigger shouldn't be used.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); - // TBI 20240517 I need here programmatic access to "event-selection-task" flags "isMC and "isRunMC" . Then I can directly bail out. - } - */ - } + // if (tc.fProcess[eProcessRec_Run2]) { + // TBI 20250115 Not really sure I need this - if I want to run only "Rec" over Monte Carlo, then obviously the condition below is pointless. + // Also here I need to be able automaticaly to determine whether I am processing real data or Monte Carlo, from the dataset itself. + // TBI 20240517 for the time being, here I am enforcing that "kINT7" is mandatory for Run 2 + // TBI 20241209 I still have to validate it for Run 1 converted real data => then expand if(...) statement above + + // commented out temporariy, see TBI 20250115 above + // if (!(ec.fUseEventCuts[eTrigger] && ec.fsEventCuts[eTrigger].EqualTo("kINT7"))) { + // LOGF(fatal, "\033[1;31m%s at line %d : trigger \"%s\" is not internally validated/supported yet. Add it to the list of supported triggers, if you really want to use that one.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); + // } else { + // LOGF(info, "\033[1;32m%s at line %d : WARNING => trigger \"%s\" can be used only on real converted Run 2 and Run 1 data. For MC converted Run 2 and Run 1 data, this trigger shouldn't be used.\033[0m", __FUNCTION__, __LINE__, ec.fsEventCuts[eTrigger].Data()); + // // TBI 20240517 I need here programmatic access to "event-selection-task" flags "isMC and "isRunMC" . Then I can directly bail out. + // } + // } // **) Ensure that fFloatingPointPrecision makes sense: if (!(tc.fFloatingPointPrecision > 0.)) { @@ -2717,6 +2933,15 @@ void InsanityChecksBeforeBooking() 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); } + // ** 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) { + LOGF(fatal, "\033[1;31m%s at line %d : For simulated data when fDatabasePDG is NOT used, I have to disable cut on charge, since that info is not available.\033[0m", __FUNCTION__, __LINE__); + } + // ** Make sure I am using fDatabasePDG only over Monte Carlo data: + if (tc.fUseDatabasePDG && !(tc.fProcess[eGenericRecSim] || tc.fProcess[eGenericSim])) { + LOGF(fatal, "\033[1;31m%s at line %d : Use fDatabasePDG only over Monte Carlo datasets.\033[0m", __FUNCTION__, __LINE__); + } + // b) Ensure that Run 1/2 specific cuts and flags are used only in Run 1/2 (both data and sim): // **) Ensure that eSel7 is used only for converted Run 2 and Run 1 (both data and sim): if (ec.fUseEventCuts[eSel7]) { @@ -2878,6 +3103,12 @@ void InsanityChecksBeforeBooking() } } + if (ec.fUseEventCuts[eFT0Bad] || ec.fUseEventCuts[eITSBad] || ec.fUseEventCuts[eITSLimAccMCRepr] || ec.fUseEventCuts[eTPCBadTracking] || ec.fUseEventCuts[eTPCLimAccMCRepr] || ec.fUseEventCuts[eTPCBadPID]) { + if (!(tc.fProcess[eProcessRec] || tc.fProcess[eProcessRecSim] || tc.fProcess[eProcessSim] || tc.fProcess[eProcessQA])) { + LOGF(fatal, "\033[1;31m%s at line %d : use eFT0Bad, eITSBad, eITSLimAccMCRepr, eTPCBadTracking, eTPCLimAccMCRepr, eTPCBadPID only for Run 3 data and MC\033[0m", __FUNCTION__, __LINE__); + } + } + // **) Supported reference multiplicity estimators for Run 3 are enlisted here: if (tc.fProcess[eProcessRec] || tc.fProcess[eProcessRecSim] || tc.fProcess[eProcessQA]) { if (!(ec.fsEventCuts[eReferenceMultiplicityEstimator].EqualTo("MultTPC", TString::kIgnoreCase) || @@ -2966,8 +3197,8 @@ void InsanityChecksBeforeBooking() // ... // g) Insanity checks on internal validation: - // Remark: I check here only in the settings I could define in DefaultConfiguration(). - // The other insanity checks are in BookInternalValidationHistograms() or in InsanityChecksAfterBooking() + // Remark: I check here only in the settings I could define in defaultConfiguration(). + // The other insanity checks are in bookInternalValidationHistograms() or in insanityChecksAfterBooking() if (iv.fUseInternalValidation) { if (iv.fnEventsInternalValidation <= 0) { LOGF(fatal, "\033[1;31m%s at line %d : iv.fnEventsInternalValidation <= 0 => Set number of events to positive integer\033[0m", __FUNCTION__, __LINE__); @@ -3007,14 +3238,14 @@ void InsanityChecksBeforeBooking() ExitFunction(__FUNCTION__); } -} // void InsanityChecksBeforeBooking() +} // void insanityChecksBeforeBooking() //============================================================ -void InsanityChecksAfterBooking() +void insanityChecksAfterBooking() { // Do insanity checks on all booked histograms, etc., - // Configuration, binning and cuts are checked already before booking in InsanityChecksBeforeBooking(). + // Configuration, binning and cuts are checked already before booking in insanityChecksBeforeBooking(). // a) Insanity checks on booking; // b) Insanity checks on internal validation; @@ -3060,7 +3291,47 @@ void InsanityChecksAfterBooking() ExitFunction(__FUNCTION__); } -} // void InsanityChecksAfterBooking() +} // void insanityChecksAfterBooking() + +//============================================================ + +void purgeAfterBooking() +{ + // I can purge a few objects used for common consistent booking across different group of histograms. + + // TBI 20250518 I now automatically purge only 2D and 3D objects, I can refine further an purge also the lighte objects, if necessary + + // a) Purge results histograms and related objects; + // ... + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + return; // TBI 20250625 the code below is not ready yet, because I still use these 2D and 3D histos in in FillqvectorNdim(...) + + // a) Purge results histograms and related objects: + if (!res.fSaveResultsHistograms) { + for (int v = 0; v < eAsFunctionOf2D_N; v++) { + if (res.fResultsPro2D[v]) { + delete res.fResultsPro2D[v]; + res.fResultsPro2D[v] = NULL; + } + } + + for (int v = 0; v < eAsFunctionOf3D_N; v++) { + if (res.fResultsPro3D[v]) { + delete res.fResultsPro3D[v]; + res.fResultsPro3D[v] = NULL; + } + } + } // if(!res.fSaveResultsHistograms) + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void purgeAfterBooking() //============================================================ @@ -3099,7 +3370,7 @@ bool Skip(int recOrSim) //============================================================ -void BookAndNestAllLists() +void bookAndNestAllLists() { // *) QA; // **) QA event histograms; @@ -3258,11 +3529,11 @@ void BookAndNestAllLists() ExitFunction(__FUNCTION__); } -} // void BookAndNestAllLists() +} // void bookAndNestAllLists() -//============================================================ +//========================================================== -void BookQAHistograms() +void bookQAHistograms() { // Book all QA histograms and other related objects. @@ -3281,13 +3552,14 @@ void BookQAHistograms() } // *) Print the warning message, because with too many 2D histograms with double precision, the code crashes in terminate, due to: - /* - [1450742:multiparticle-correlations-a-b]: [13:30:27][STATE] Exiting FairMQ state machine - [1450742:multiparticle-correlations-a-b]: [13:30:27][FATAL] error while setting up workflow in o2-analysis-cf-multiparticle-correlations-ab: shmem: could not create a message of size 1282720912, alignment: 64, free memory: 1358639296 - [1450742:multiparticle-correlations-a-b]: terminate called after throwing an instance of 'o2::framework::RuntimeErrorRef' - [1450742:multiparticle-correlations-a-b]: *** Program crashed (Aborted) - [1450742:multiparticle-correlations-a-b]: Backtrace by DPL: - */ + // + // [1450742:multiparticle-correlations-a-b]: [13:30:27][STATE] Exiting FairMQ state machine + // [1450742:multiparticle-correlations-a-b]: [13:30:27][FATAL] error while setting up workflow in o2-analysis-cf-multiparticle-correlations-ab: shmem: could not create a message of size 1282720912, alignment: 64, free memory: 1358639296 + // [1450742:multiparticle-correlations-a-b]: terminate called after throwing an instance of 'o2::framework::RuntimeErrorRef' + // [1450742:multiparticle-correlations-a-b]: *** Program crashed (Aborted) + // [1450742:multiparticle-correlations-a-b]: Backtrace by DPL: + // + if (tc.fVerbose) { LOGF(info, "\033[1;33m%s: !!!! WARNING !!!! With too many 2D histograms with double precision, the code will crash in terminate (\"... shmem: could not create a message of size ...\") . Locally, you can circumvent this while testing by calling Bailout() explicitly. !!!! WARNING !!!! \033[0m", __FUNCTION__); } @@ -3767,7 +4039,7 @@ void BookQAHistograms() // valgrind --tool=massif => ~9.8 MiB (Last check: 20250315) qa.fQAEventHistograms2D[t][rs][ba] = new TH2F( TString::Format("fQAEventHistograms2D[%s][%s][%s]", qa.fEventHistogramsName2D[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) nBins_x_Event[t], min_x_Event[t], max_x_Event[t], nBins_y_Event[t], min_y_Event[t], max_y_Event[t]); qa.fQAEventHistograms2D[t][rs][ba]->GetXaxis()->SetTitle(title_x_Event[t].Data()); qa.fQAEventHistograms2D[t][rs][ba]->GetYaxis()->SetTitle(title_y_Event[t].Data()); @@ -3832,7 +4104,7 @@ void BookQAHistograms() // valgrind --tool=massif => ~30.6 MiB (Last check: 20250315) qa.fQAParticleHistograms2D[t][rs][ba] = new TH2F( TString::Format("fQAParticleHistograms2D[%s][%s][%s]", qa.fParticleHistogramsName2D[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) nBins_x_Particle[t], min_x_Particle[t], max_x_Particle[t], nBins_y_Particle[t], min_y_Particle[t], max_y_Particle[t]); qa.fQAParticleHistograms2D[t][rs][ba]->GetXaxis()->SetTitle(title_x_Particle[t].Data()); @@ -3993,7 +4265,7 @@ void BookQAHistograms() // valgrind --tool=massif => ~70.2 MiB (Last check: 20250315) qa.fQAParticleEventHistograms2D[t][rs][ba] = new TH2F( TString::Format("fQAParticleEventHistograms2D[%s][%s][%s]", qa.fQAParticleEventHistogramsName2D[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) nBins_x_ParticleEvent[t], min_x_ParticleEvent[t], max_x_ParticleEvent[t], nBins_y_ParticleEvent[t], min_y_ParticleEvent[t], max_y_ParticleEvent[t]); qa.fQAParticleEventHistograms2D[t][rs][ba]->GetXaxis()->SetTitle(title_x_ParticleEvent[t].Data()); @@ -4023,7 +4295,7 @@ void BookQAHistograms() qa.fQAParticleEventProEbyE[rs][ba] = new TProfile( TString::Format("fParticleEventProEbyE[%s][%s]", gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), + TString::Format("%s, %s", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), eQAParticleEventProEbyE_N, 0., eQAParticleEventProEbyE_N); } // for (int ba = 0; ba < 2; ba++) // before/after cuts } // for (int rs = 0; rs < 2; rs++) // reco/sim @@ -4198,7 +4470,7 @@ void BookQAHistograms() // valgrind --tool=massif => ~58.7 MiB (Last check: 20250315) qa.fQACorrelationsVsHistograms2D[t][h][rs] = new TH2F( TString::Format("fQACorrelationsVsHistograms2D[%s][%d][%s]", qa.fQACorrelationsVsHistogramsName2D[t].Data(), h, gc.srs[rs].Data()), - TString::Format("%s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) + TString::Format("%s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) nBins_x_CorrelationsVs, min_x_CorrelationsVs, max_x_CorrelationsVs, nBins_y_CorrelationsVs[t], min_y_CorrelationsVs[t], max_y_CorrelationsVs[t]); qa.fQACorrelationsVsHistograms2D[t][h][rs]->GetXaxis()->SetTitle(TString::Format("%s (harmonic = %d)", title_x_CorrelationsVs.Data(), h + 1)); @@ -4323,7 +4595,7 @@ void BookQAHistograms() // TBI 20250317 documet here the output of profiling using valgrind --tool=massif qa.fQACorrVsIRVsProfiles2D[t][h][rs] = new TProfile2D( TString::Format("fQACorrVsIRVsProfiles2D[%s][%d][%s]", qa.fQACorrelationsVsInteractionRateVsProfilesName2D[t].Data(), h, gc.srs[rs].Data()), - TString::Format("%s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) + TString::Format("%s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) nBins_x_CorrelationsVsInteractionRateVs, min_x_CorrelationsVsInteractionRateVs, max_x_CorrelationsVsInteractionRateVs, nBins_y_CorrelationsVsInteractionRateVs[t], min_y_CorrelationsVsInteractionRateVs[t], max_y_CorrelationsVsInteractionRateVs[t]); TString tmp = qa.fQACorrVsIRVsProfiles2D[t][h][rs]->GetTitle(); // translating e.g. "544114, reconstructed" into "<<2>> (harmonic = 2), 544114, reconstructed" @@ -4346,11 +4618,11 @@ void BookQAHistograms() ExitFunction(__FUNCTION__); } -} // void BookQAHistograms() +} // void bookQAHistograms() //============================================================ -void BookEventHistograms() +void bookEventHistograms() { // Book all event histograms. @@ -4425,7 +4697,7 @@ void BookEventHistograms() } eh.fEventHistograms[t][rs][ba] = new TH1F( TString::Format("fEventHistograms[%s][%s][%s]", eh.fEventHistogramsName[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), // __RUN_NUMBER__ is handled in PropagateRunNumber(...) static_cast(eh.fEventHistogramsBins[t][0]), eh.fEventHistogramsBins[t][1], eh.fEventHistogramsBins[t][2]); eh.fEventHistograms[t][rs][ba]->GetXaxis()->SetTitle(FancyFormatting(eh.fEventHistogramsName[t].Data())); @@ -4440,11 +4712,11 @@ void BookEventHistograms() ExitFunction(__FUNCTION__); } -} // void BookEventHistograms() +} // void bookEventHistograms() //============================================================ -void BookEventCutsHistograms() +void bookEventCutsHistograms() { // Book all event cuts objects. @@ -4528,7 +4800,7 @@ void BookEventCutsHistograms() continue; } - ec.fEventCutCounterHist[rs][cc] = new TH1F(TString::Format("fEventCutCounterHist[%s][%s]", gc.srs[rs].Data(), gc.scc[cc].Data()), TString::Format("%s, %s, event cut counter (%s)", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.scc_long[cc].Data()), eEventCuts_N, 0.5, static_cast(eEventCuts_N) + 0.5); // I cast in double the last argument, because that's what this particular TH1I constructor expects. And yes, +0.5, because eEventCuts kicks off from 0 + ec.fEventCutCounterHist[rs][cc] = new TH1F(TString::Format("fEventCutCounterHist[%s][%s]", gc.srs[rs].Data(), gc.scc[cc].Data()), TString::Format("%s, %s, event cut counter (%s)", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sccLong[cc].Data()), eEventCuts_N, 0.5, static_cast(eEventCuts_N) + 0.5); // I cast in double the last argument, because that's what this particular TH1I constructor expects. And yes, +0.5, because eEventCuts kicks off from 0 ec.fEventCutCounterHist[rs][cc]->SetStats(false); ec.fEventCutCounterHist[rs][cc]->SetLineColor(eColor); ec.fEventCutCounterHist[rs][cc]->SetFillColor(eFillColor); @@ -4591,7 +4863,7 @@ void BookEventCutsHistograms() ExitFunction(__FUNCTION__); } -} // void BookEventCutsHistograms() +} // void bookEventCutsHistograms() //============================================================ @@ -4668,7 +4940,7 @@ float RefMultVsNContr(const float& refMult, eEventCutsFormulas whichCutFormula) //============================================================ -void BookParticleHistograms() +void bookParticleHistograms() { // Book all particle histograms. @@ -4745,7 +5017,7 @@ void BookParticleHistograms() for (int ba = 0; ba < 2; ba++) // before/after cuts { ph.fParticleHistograms[t][rs][ba] = new TH1F(TString::Format("fParticleHistograms[%s][%s][%s]", ph.fParticleHistogramsName[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), static_cast(ph.fParticleHistogramsBins[t][0]), ph.fParticleHistogramsBins[t][1], ph.fParticleHistogramsBins[t][2]); ph.fParticleHistograms[t][rs][ba]->SetLineColor(ec.fBeforeAfterColor[ba]); ph.fParticleHistograms[t][rs][ba]->SetFillColor(ec.fBeforeAfterColor[ba] - 10); @@ -4800,14 +5072,14 @@ void BookParticleHistograms() // *) variable-length binning for phi vs pt, but only in pt axis: ph.fParticleHistograms2D[t][rs][ba] = new TH2D(TString::Format("fParticleHistograms2D[%s][%s][%s]", ph.fParticleHistogramsName2D[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), static_cast(ph.fParticleHistogramsBins2D[t][eX][0]), ph.fParticleHistogramsBins2D[t][eX][1], ph.fParticleHistogramsBins2D[t][eX][2], res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray()); // yes, x-axis of "results vs pt" hist is y-axis here for 2D. } else if (ph.fParticleHistogramsName2D[t].EqualTo("Phi_vs_Eta") && res.fUseResultsProVariableLengthBins[AFO_ETA]) { // *) variable-length binning for phi vs eta, but only in eta axis: ph.fParticleHistograms2D[t][rs][ba] = new TH2D(TString::Format("fParticleHistograms2D[%s][%s][%s]", ph.fParticleHistogramsName2D[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), static_cast(ph.fParticleHistogramsBins2D[t][eX][0]), ph.fParticleHistogramsBins2D[t][eX][1], ph.fParticleHistogramsBins2D[t][eX][2], res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray()); // yes, x-axis of "results vs pt" hist is y-axis here for 2D } else { @@ -4815,7 +5087,7 @@ void BookParticleHistograms() // Remark: Remember that I cannot use here GetXaxis()->GetXbins()->GetArray() as for variable-width case, because for fixed-width case, this is always 0 // See https://root-forum.cern.ch/t/get-bin-array/7276/9 ph.fParticleHistograms2D[t][rs][ba] = new TH2D(TString::Format("fParticleHistograms2D[%s][%s][%s]", ph.fParticleHistogramsName2D[t].Data(), gc.srs[rs].Data(), gc.sba[ba].Data()), - TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), + TString::Format("%s, %s, %s", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), static_cast(ph.fParticleHistogramsBins2D[t][eX][0]), ph.fParticleHistogramsBins2D[t][eX][1], ph.fParticleHistogramsBins2D[t][eX][2], static_cast(ph.fParticleHistogramsBins2D[t][eY][0]), ph.fParticleHistogramsBins2D[t][eY][1], ph.fParticleHistogramsBins2D[t][eY][2]); } @@ -4831,7 +5103,7 @@ void BookParticleHistograms() // 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. + // Therefore, I can do all this only after bookResultsHistograms() was already called. // 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. @@ -4855,7 +5127,10 @@ void BookParticleHistograms() delete lAxis; ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPhiAxis] = FancyFormatting("Phi"); - // ***) pt-axis for diff phi weights: I re-use binning from results histograms + // ***) 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(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiPtAxis]); @@ -4866,7 +5141,10 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiPtAxis] = FancyFormatting("Pt"); - // ***) eta-axis for diff phi weights: I re-use binning from results histograms + // ***) 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(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiEtaAxis]); @@ -4877,9 +5155,12 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiEtaAxis] = FancyFormatting("Eta"); - // ***) charge-axis for diff phi weights: I support only fixed-length binning, nothing really to ever change here: - ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis] = 2; - lAxis = new TAxis(ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiChargeAxis], -1.5, 1.5); + // ***) 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(); 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); @@ -4888,7 +5169,10 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) ph.fParticleSparseHistogramsAxisTitle[eDWPhi][wPhiChargeAxis] = FancyFormatting("Charge"); - // ***) centrality-axis for diff phi weights: I re-use binning from results histograms + // ***) 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(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiCentralityAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiCentralityAxis]); @@ -4899,7 +5183,10 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) 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 + // ***) 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(); ph.fParticleSparseHistogramsBinEdges[eDWPhi][wPhiVertexZAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPhi][wPhiVertexZAxis]); @@ -4914,7 +5201,10 @@ void BookParticleHistograms() // **) eDiffWeightCategory = eDWPt: - // ***) pt-axis for diff pt weights: I re-use binning from results histograms + // ***) 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(); ph.fParticleSparseHistogramsBinEdges[eDWPt][wPtPtAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWPt][wPtPtAxis]); @@ -4925,11 +5215,42 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) 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__); + } + ph.fParticleSparseHistogramsNBins[eDWPt][wPtChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); + lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + 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(...) + 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(); + 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(...) + 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 + // ***) 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(); ph.fParticleSparseHistogramsBinEdges[eDWEta][wEtaEtaAxis] = new TArrayD(1 + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaEtaAxis]); @@ -4940,6 +5261,34 @@ void BookParticleHistograms() // delete lAxis; // I do not need to delete here, only when new TAxis(...) 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__); + } + ph.fParticleSparseHistogramsNBins[eDWEta][wEtaChargeAxis] = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); + lAxis = res.fResultsPro[AFO_CHARGE]->GetXaxis(); + 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(...) + 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(); + 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(...) + 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. + // ... // e) Book specific particle sparse histograms (n-dimensions): @@ -4959,13 +5308,13 @@ void BookParticleHistograms() ExitFunction(__FUNCTION__); } -} // void BookParticleHistograms() +} // void bookParticleHistograms() //============================================================ void BookParticleSparseHistograms(eDiffWeightCategory dwc) { - // This is a helper function for BookParticleHistograms(), merely to reduce code bloat. + // This is a helper function for bookParticleHistograms(), merely to reduce code bloat. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -5005,7 +5354,7 @@ void BookParticleSparseHistograms(eDiffWeightCategory dwc) 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.srs_long[rs].Data(), ph.fParticleSparseHistogramsTitle[dwc].Data()), nDimensions, nBins->GetArray(), NULL, NULL); + 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++) { @@ -5028,7 +5377,7 @@ void BookParticleSparseHistograms(eDiffWeightCategory dwc) //============================================================ -void BookParticleCutsHistograms() +void bookParticleCutsHistograms() { // Book all particle cuts objects. @@ -5110,7 +5459,7 @@ void BookParticleCutsHistograms() continue; } - pc.fParticleCutCounterHist[rs][cc] = new TH1F(TString::Format("fParticleCutCounterHist[%s][%s]", gc.srs[rs].Data(), gc.scc[cc].Data()), TString::Format("%s, %s, particle cut counter (%s)", "__RUN_NUMBER__", gc.srs_long[rs].Data(), gc.scc_long[cc].Data()), eParticleCuts_N, 0.5, static_cast(eParticleCuts_N) + 0.5); + pc.fParticleCutCounterHist[rs][cc] = new TH1F(TString::Format("fParticleCutCounterHist[%s][%s]", gc.srs[rs].Data(), gc.scc[cc].Data()), TString::Format("%s, %s, particle cut counter (%s)", "__RUN_NUMBER__", gc.srsLong[rs].Data(), gc.sccLong[cc].Data()), eParticleCuts_N, 0.5, static_cast(eParticleCuts_N) + 0.5); // I cast in double the last argument, because that's what this particular TH1I constructor expects // Yes, +0.5, because eParticleCuts kicks off from 0 pc.fParticleCutCounterHist[rs][cc]->SetStats(false); @@ -5140,17 +5489,18 @@ void BookParticleCutsHistograms() ExitFunction(__FUNCTION__); } -} // void BookParticleCutsHistograms() +} // void bookParticleCutsHistograms() //============================================================ -void BookQvectorHistograms() +void bookQvectorHistograms() { // Book all Q-vector histograms. // a) Book the profile holding flags; - // b) Book multiplicity distributions in A and B, for each eta separation; - // c) ... + // b) Differential q-vectors booked dynamically: + // c) Book multiplicity distributions in A and B, for each eta separation; + // d) ... if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -5206,10 +5556,115 @@ void BookQvectorHistograms() qv.fQvectorList->Add(qv.fQvectorFlagsPro); - // b) Book multiplicity distributions in A and B, for each eta separation: + // b) Differential q-vectors booked dynamically: + // Remark: Here I am slighthly generalizing the great example provided at https://cplusplus.com/forum/articles/7459/ + + // b1) book qv.fqvector and qv.fqvectorEntries : + // dimensions: [eqvectorKine_N][gMaxNoBinsKine][gMaxHarmonic * gMaxCorrelator + 1][gMaxCorrelator + 1] => keep in sync with the documentation in the header + // here I am calculating for each dimensions how many entries I need in a given analysis + if (qv.fCalculateqvectorsKineAny) { + qv.fNumberOfKineBins.resize(eqvectorKine_N); // this is the light object, so I can hardwire here eqvectorKine_N + // then, in NumberOfKineVectors() i will store bins ONLY for qvectorKine which were requested. + // Therefore, final ordering in will correspond to the ordering in enum eqvectorKine ONLY if all kine vectors were requested. + // Otherwise, I fill here bins only for kine vectors which were requested, in consequtive order, starting from 0. + + int dim1 = eqvectorKine_N; + // int dim2 = number of kine bins => I calculate this one dynamically for each qVectorKine, see the loop below + NumberOfKineBins(); // here I calculate and fill qv.fNumberOfKineBins[ ... ] + int dim3 = gMaxHarmonic * gMaxCorrelator + 1; // TBI 20250601 I could dinamically allocate this one as well, but this will trigger another major re-design, and it's not rally a big deal + int dim4 = gMaxCorrelator + 1; // TBI 20250601 I could dinamically allocate this one as well, but this will trigger another major re-design, and it's not really a big deal + + qv.fqvector.resize(dim1); + qv.fqvectorEntries.resize(dim1); + + for (int i = 0; i < dim1; ++i) { // here I am looping over entries in enum eqvectorKine + if (qv.fCalculateqvectorsKine[i]) { + qv.fqvector[i].resize(qv.fNumberOfKineBins[i]); // yes, qv.fNumberOfKineBins[i] => for each qvectorkine I calculate and dynamically allocate only necessary bins + qv.fqvectorEntries[i].resize(qv.fNumberOfKineBins[i]); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqvector[i].resize(0); + qv.fqvectorEntries[i].resize(0); + } + + for (int j = 0; j < qv.fNumberOfKineBins[i]; ++j) { + if (qv.fCalculateqvectorsKine[i]) { + qv.fqvector[i][j].resize(dim3); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqvector[i][j].resize(0); + } + + for (int k = 0; k < dim3; ++k) { + if (qv.fCalculateqvectorsKine[i]) { + qv.fqvector[i][j][k].resize(dim4); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqvector[i][j][k].resize(0); + } + } + } + } // for (int i = 0; i < dim1; ++i) + + // b2) book qv.fqabVector and qv.fmab (differential q-vectors with eta separations): + // dimensions: [-eta or +eta][eqvectorKine_N][global binNo][harmonic][eta separation] => keep in sync with the documentation in the header + // here I am calculating for each dimensions how many entries I need in a given analysis + + if (es.fCalculateEtaSeparations) { + int dim1 = 2; // -eta or eta + int dim2 = eqvectorKine_N; + // int dim3 = number of kine bins => I calculated this one dynamically for each qVectorKine, see the loop below + // NumberOfKineBins(); // here I calculate and fill qv.fNumberOfKineBins[ ... ] => I did it already above for qv.fqvector + int dim4 = gMaxHarmonic; + int dim5 = gMaxNumberEtaSeparations; + qv.fqabVector.resize(dim1); + qv.fmab.resize(dim1); + + for (int i = 0; i < dim1; ++i) { // here I am looping over -eta or eta + qv.fqabVector[i].resize(dim2); + qv.fmab[i].resize(dim2); + + for (int j = 0; j < dim2; ++j) { // here I am looping over entries in enum eqvectorKine + + if (qv.fCalculateqvectorsKineEtaSeparations[j]) { + qv.fqabVector[i][j].resize(qv.fNumberOfKineBins[j]); // yes, qv.fNumberOfKineBins[j] => for each qvectorkine I calculate and dynamically allocate only necessary bins + qv.fmab[i][j].resize(qv.fNumberOfKineBins[j]); + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + qv.fqabVector[i][j].resize(0); + qv.fmab[i][j].resize(0); + } + + for (int k = 0; k < qv.fNumberOfKineBins[j]; ++k) { + if (qv.fCalculateqvectorsKineEtaSeparations[j]) { + qv.fqabVector[i][j][k].resize(dim4); + qv.fmab[i][j][k].resize(dim5); // yes, directly dim5, because this one doesn't depend on harmonics + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + // I have already in the previous loop ironed out for qv.fCalculateqvectorsKineEtaSeparations[j] = false, so no need to do it here again + // TBI 20250620 validate what happens here + } + + for (int l = 0; l < dim4; ++l) { // loop over harmonics + if (qv.fCalculateqvectorsKineEtaSeparations[j] && !es.fEtaSeparationsSkipHarmonics[l]) { + qv.fqabVector[i][j][k][l].resize(dim5); + // no need to resize qv.fmab here, because this one doesn't depend on harmonics + } else { + // calculus for this kine variable is not needed, I am ironing out this dimension + // I have already in the previous loop ironed out for qv.fCalculateqvectorsKineEtaSeparations[j] = false, so no need to do it here again + // TBI 20250620 validate what happens here + } + } // for (int l = 0; l < dim4; ++l) + } // for (int k = 0; k < qv.fNumberOfKineBins[j]; ++k) + } // for (int j = 0; j < dim2; ++j) + } // for (int i = 0; i < dim1; ++i) + } // if(es.fCalculateEtaSeparations) + } // if(qv.fCalculateqvectorsKineAny) + + // c) Book multiplicity distributions in A and B, for each eta separation: if (es.fCalculateEtaSeparations) { TString sEtaSep[2] = {"A", "B"}; // A <=> -eta , B <=> + eta - TString sEtaSep_long[2] = {TString::Format("%.2f < #eta <", pc.fdParticleCuts[eEta][eMin]), TString::Format("< #eta < %.2f", pc.fdParticleCuts[eEta][eMax])}; + TString sEtaSepLong[2] = {TString::Format("%.2f < #eta <", pc.fdParticleCuts[eEta][eMin]), TString::Format("< #eta < %.2f", pc.fdParticleCuts[eEta][eMax])}; // yes, here I define first the part of intervals as etaCutMin < eta < "subevent boundary", and "subevent" boundary < eta < etaCutMax // Then below in the loop, I inject for "subevent boundary" the corresponding fEtaSeparationsValues (divided by 2, becaus it's symmetric round 0) for (int ab = 0; ab < 2; ab++) { // ab = 0 <=> -eta , ab = 1 <=> + eta @@ -5224,7 +5679,7 @@ void BookQvectorHistograms() for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation qv.fMabDist[ab][rs][ba][e] = new TH1F(Form("fMabDist[%s][%s][%s][%d]", sEtaSep[ab].Data(), gc.srs[rs].Data(), gc.sba[ba].Data(), e), Form("%s, %s, %s, %s", "__RUN_NUMBER__", - 0 == ab ? Form("%s -%.2f", sEtaSep_long[ab].Data(), es.fEtaSeparationsValues[e] / 2.) : Form("%.2f %s", es.fEtaSeparationsValues[e] / 2., sEtaSep_long[ab].Data()), gc.srs_long[rs].Data(), gc.sba_long[ba].Data()), + 0 == ab ? Form("%s -%.2f", sEtaSepLong[ab].Data(), es.fEtaSeparationsValues[e] / 2.) : Form("%.2f %s", es.fEtaSeparationsValues[e] / 2., sEtaSepLong[ab].Data()), gc.srsLong[rs].Data(), gc.sbaLong[ba].Data()), static_cast(eh.fEventHistogramsBins[eMultiplicity][0]), eh.fEventHistogramsBins[eMultiplicity][1], eh.fEventHistogramsBins[eMultiplicity][2]); // TBI 20241207 I have hardwired in this constructor "0 == ab", this can backfire... qv.fMabDist[ab][rs][ba][e]->SetLineColor(ec.fBeforeAfterColor[ba]); qv.fMabDist[ab][rs][ba][e]->SetFillColor(ec.fBeforeAfterColor[ba] - 10); @@ -5247,11 +5702,58 @@ void BookQvectorHistograms() ExitFunction(__FUNCTION__); } -} // void BookQvectorHistograms() +} // void bookQvectorHistograms() + +//============================================================ + +void NumberOfKineBins() +{ + // Helper function called only in void bookQvectorHistograms(), if kine analysis was requested. + // I calculate for each requested kine vector the number of kine bins => this is stored in dynamically allocated array qv.fNumberOfKineBins. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // 1D kine: + if (qv.fCalculateqvectorsKine[PTq]) { + qv.fNumberOfKineBins[PTq] = res.fResultsPro[AFO_PT]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[ETAq]) { + qv.fNumberOfKineBins[ETAq] = res.fResultsPro[AFO_ETA]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[CHARGEq]) { + qv.fNumberOfKineBins[CHARGEq] = res.fResultsPro[AFO_CHARGE]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + // ... + + // 2D kine: + if (qv.fCalculateqvectorsKine[PT_ETAq]) { + qv.fNumberOfKineBins[PT_ETAq] = (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[PT_CHARGEq]) { + qv.fNumberOfKineBins[PT_CHARGEq] = (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + if (qv.fCalculateqvectorsKine[ETA_CHARGEq]) { + qv.fNumberOfKineBins[ETA_CHARGEq] = (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + // ... + + // 3D kine: + if (qv.fCalculateqvectorsKine[PT_ETA_CHARGEq]) { + qv.fNumberOfKineBins[PT_ETA_CHARGEq] = (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsY() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + // ... + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void NumberOfKineBins() //============================================================ -void BookCorrelationsHistograms() +void bookCorrelationsHistograms() { // Book all correlations histograms. @@ -5323,50 +5825,19 @@ void BookCorrelationsHistograms() for (int v = 0; v < eAsFunctionOf_N; v++) { // decide what is booked, then later valid pointer to fCorrelationsPro[k][n][v] is used as a boolean, in the standard way: - if (AFO_INTEGRATED == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTEGRATED]) { - continue; - } - if (AFO_MULTIPLICITY == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_MULTIPLICITY]) { - continue; - } - if (AFO_CENTRALITY == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_CENTRALITY]) { - continue; - } - if (AFO_PT == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT]) { - continue; - } - if (AFO_ETA == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA]) { - continue; - } - if (AFO_OCCUPANCY == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_OCCUPANCY]) { - continue; - } - if (AFO_INTERACTIONRATE == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_INTERACTIONRATE]) { - continue; - } - if (AFO_CURRENTRUNDURATION == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_CURRENTRUNDURATION]) { - continue; - } - if (AFO_VZ == v && !mupa.fCalculateCorrelationsAsFunctionOf[AFO_VZ]) { + if (!mupa.fCalculateCorrelationsAsFunctionOf[v]) { continue; } if (!res.fResultsPro[v]) { - LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + LOGF(fatal, "\033[1;31m%s at line %d : fResultsPro[%d] is NULL, this shall never happen, but apparently it happened... \033[0m", __FUNCTION__, __LINE__, v); } if (tc.fUseClone) { mupa.fCorrelationsPro[k][n][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()))); // yes } else { - // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - mupa.fCorrelationsPro[k][n][v] = new TProfile(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - mupa.fCorrelationsPro[k][n][v] = new TProfile(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else - } // else + mupa.fCorrelationsPro[k][n][v] = new TProfile(Form("fCorrelationsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); + } mupa.fCorrelationsPro[k][n][v]->SetStats(false); mupa.fCorrelationsPro[k][n][v]->Sumw2(); @@ -5389,11 +5860,11 @@ void BookCorrelationsHistograms() ExitFunction(__FUNCTION__); } -} // BookCorrelationsHistograms() +} // bookCorrelationsHistograms() //============================================================ -void BookWeightsHistograms() +void bookWeightsHistograms() { // Book all objects for particle weights. @@ -5515,10 +5986,22 @@ void BookWeightsHistograms() if (pw.fUseDiffPtWeights[wPtPtAxis]) { pw.fWeightsFlagsPro->Fill(11.5, 1.); } + if (pw.fUseDiffPhiWeights[wPtChargeAxis]) { + pw.fWeightsFlagsPro->Fill(12.5, 1.); + } + if (pw.fUseDiffPhiWeights[wPtCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(13.5, 1.); + } // **) differential eta weights using sparse: if (pw.fUseDiffEtaWeights[wEtaEtaAxis]) { - pw.fWeightsFlagsPro->Fill(12.5, 1.); + pw.fWeightsFlagsPro->Fill(14.5, 1.); + } + if (pw.fUseDiffPhiWeights[wEtaChargeAxis]) { + pw.fWeightsFlagsPro->Fill(15.5, 1.); + } + if (pw.fUseDiffPhiWeights[wEtaCentralityAxis]) { + pw.fWeightsFlagsPro->Fill(16.5, 1.); } pw.fWeightsList->Add(pw.fWeightsFlagsPro); @@ -5538,11 +6021,11 @@ void BookWeightsHistograms() ExitFunction(__FUNCTION__); } -} // void BookWeightsHistograms() +} // void bookWeightsHistograms() //============================================================ -void BookCentralityWeightsHistograms() +void bookCentralityWeightsHistograms() { // Book all objects for centrality weights. @@ -5601,16 +6084,16 @@ void BookCentralityWeightsHistograms() ExitFunction(__FUNCTION__); } -} // void BookCentralityWeightsHistograms() +} // void bookCentralityWeightsHistograms() //============================================================ -void BookNestedLoopsHistograms() +void bookNestedLoopsHistograms() { // Book all nested loops histograms. // a) Book the profile holding flags; - // b) Common local labels (keep 'em in sync with BookCorrelationsHistograms()); + // b) Common local labels (keep 'em in sync with bookCorrelationsHistograms()); // c) Book what needs to be booked; // d) Few quick insanity checks on booking. @@ -5685,18 +6168,87 @@ void BookNestedLoopsHistograms() // *) Book containers for differential nested loops: if (nl.fCalculateKineCustomNestedLoops) { - const int iMaxSize = 2e4; - for (int b = 0; b < res.fResultsPro[AFO_PT]->GetNbinsX(); b++) { + + const int iMaxSize = 2e4; // this is roughly number of particles per bin, it shouldn't exceed this threshold + int nBins = -1; + + // 1D kine: + // **) vs. pt: + nBins = res.fResultsPro[AFO_PT]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip later + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[PTq][b][0] = new TArrayD(iMaxSize); nl.ftaNestedLoopsKine[PTq][b][1] = new TArrayD(iMaxSize); } - for (int b = 0; b < res.fResultsPro[AFO_ETA]->GetNbinsX(); b++) { + + // **) vs. eta: + nBins = res.fResultsPro[AFO_ETA]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it later + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[ETAq][b][0] = new TArrayD(iMaxSize); nl.ftaNestedLoopsKine[ETAq][b][1] = new TArrayD(iMaxSize); } - } - // b) Common local labels (keep 'em in sync with BookCorrelationsHistograms()) + // **) vs. charge: + nBins = res.fResultsPro[AFO_CHARGE]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it later + for (int b = 0; b < nBins; b++) { + nl.ftaNestedLoopsKine[CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[CHARGEq][b][1] = new TArrayD(iMaxSize); + } + + // ... + + // 2D kine: + // **) vs. (pt,eta): + if (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]) { + // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsY() + 2); + // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETAq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[PT_ETAq][b][1] = new TArrayD(iMaxSize); + } + } + + // **) vs. (pt,charge): + if (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]) { + // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsY() + 2); + // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[PT_CHARGEq][b][1] = new TArrayD(iMaxSize); + } + } + + // **) vs. (eta,charge): + if (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]) { + // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsY() + 2); + // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][1] = new TArrayD(iMaxSize); + } + } + + // ... + + // 3D kine: + // **) vs. (pt,eta,charge): + if (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]) { + // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsY() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsZ() + 2); + // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][0] = new TArrayD(iMaxSize); + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][1] = new TArrayD(iMaxSize); + } + } + + // ... + + } // if (nl.fCalculateKineCustomNestedLoops) + + // b) Common local labels (keep 'em in sync with bookCorrelationsHistograms()) TString oVariable[4] = { "#varphi_{1}-#varphi_{2}", "#varphi_{1}+#varphi_{2}-#varphi_{3}-#varphi_{4}", @@ -5723,30 +6275,17 @@ void BookNestedLoopsHistograms() if (tc.fUseClone) { nl.fNestedLoopsPro[k][n][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fNestedLoopsPro[%d][%d][%d]", k, n, v))); // yes } else { - // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - nl.fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - nl.fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else - } // else + nl.fNestedLoopsPro[k][n][v] = new TProfile(Form("fNestedLoopsPro[%d][%d][%s]", k, n, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); + } nl.fNestedLoopsPro[k][n][v]->SetTitle(Form("#LT#LTcos[%s(%s)]#GT#GT", 1 == n + 1 ? "" : Form("%d", n + 1), oVariable[k].Data())); nl.fNestedLoopsPro[k][n][v]->SetStats(false); nl.fNestedLoopsPro[k][n][v]->Sumw2(); nl.fNestedLoopsPro[k][n][v]->GetXaxis()->SetTitle(res.fResultsProXaxisTitle[v].Data()); - /* - if(fUseFixedNumberOfRandomlySelectedTracks && 1==v) // just a warning - for the meaning of multiplicity in this special case - { - nl.fNestedLoopsPro[k][n][1]->GetXaxis()->SetTitle("WARNING: for each - multiplicity, fFixedNumberOfRandomlySelectedTracks is selected randomly - in Q-vector"); + if (tc.fFixedNumberOfRandomlySelectedTracks > 0 && AFO_MULTIPLICITY == v) { // just a warning for the meaning of multiplicity in this special case + nl.fNestedLoopsPro[k][n][v]->GetXaxis()->SetTitle("WARNING: for each multiplicity, fFixedNumberOfRandomlySelectedTracks is selected randomly in Q-vector"); } - */ nl.fNestedLoopsList->Add(nl.fNestedLoopsPro[k][n][v]); } // for(int v=0;v<5;v++) // variable [0=integrated,1=vs. @@ -5768,11 +6307,11 @@ void BookNestedLoopsHistograms() ExitFunction(__FUNCTION__); } -} // void BookNestedLoopsHistograms() +} // void bookNestedLoopsHistograms() //============================================================ -void BookNUAHistograms() +void bookNUAHistograms() { // Book all objects for Toy NUA. @@ -5943,11 +6482,11 @@ void BookNUAHistograms() ExitFunction(__FUNCTION__); } -} // void BookNUAHistograms() +} // void bookNUAHistograms() //============================================================ -void BookInternalValidationHistograms() +void bookInternalValidationHistograms() { // Book all internal validation histograms. @@ -5961,7 +6500,7 @@ void BookInternalValidationHistograms() } // a) Book the profile holding flags: - iv.fInternalValidationFlagsPro = new TProfile("fInternalValidationFlagsPro", "flags for internal validation", 4, 0., 4.); + iv.fInternalValidationFlagsPro = new TProfile("fInternalValidationFlagsPro", "flags for internal validation", 5, 0., 5.); iv.fInternalValidationFlagsPro->SetStats(false); iv.fInternalValidationFlagsPro->SetLineColor(eColor); iv.fInternalValidationFlagsPro->SetFillColor(eFillColor); @@ -5975,7 +6514,9 @@ void BookInternalValidationHistograms() iv.fInternalValidationFlagsPro->Fill(1.5, iv.fnEventsInternalValidation); iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(3, "fRescaleWithTheoreticalInput"); iv.fInternalValidationFlagsPro->Fill(2.5, iv.fRescaleWithTheoreticalInput); - iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(4, TString::Format("option = %s", iv.fHarmonicsOptionInternalValidation->Data())); + iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(4, "fRandomizeReactionPlane"); + iv.fInternalValidationFlagsPro->Fill(3.5, iv.fRandomizeReactionPlane); + iv.fInternalValidationFlagsPro->GetXaxis()->SetBinLabel(5, TString::Format("option = %s", iv.fHarmonicsOptionInternalValidation->Data())); } else { // Workaround for SetBinLabel() large memory consumption: @@ -5990,7 +6531,10 @@ void BookInternalValidationHistograms() yAxisTitle += TString::Format("%d:fRescaleWithTheoreticalInput; ", 3); iv.fInternalValidationFlagsPro->Fill(2.5, static_cast(iv.fRescaleWithTheoreticalInput)); - yAxisTitle += TString::Format("%d:option = %s; ", 4, iv.fHarmonicsOptionInternalValidation->Data()); + yAxisTitle += TString::Format("%d:fRandomizeReactionPlane; ", 4); + iv.fInternalValidationFlagsPro->Fill(3.5, static_cast(iv.fRandomizeReactionPlane)); + + yAxisTitle += TString::Format("%d:option = %s; ", 5, iv.fHarmonicsOptionInternalValidation->Data()); // ... @@ -6054,7 +6598,7 @@ void BookInternalValidationHistograms() ExitFunction(__FUNCTION__); } -} // BookInternalValidationHistograms() +} // bookInternalValidationHistograms() //============================================================ @@ -6139,6 +6683,7 @@ void InternalValidation() GetParticleWeights(); pw.fParticleWeightsAreFetched = true; } + // differential phi weights: if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // Yes, I check only the first flag. This way, I can 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. @@ -6146,13 +6691,30 @@ void InternalValidation() GetParticleWeights(); pw.fParticleWeightsAreFetched = true; } - } // if (!pw.fParticleWeightsAreFetched) { - // a) Fourier like p.d.f. for azimuthal angles and flow amplitudes: - TF1* fPhiPDF = NULL; - TF3* fvnPDF = NULL; + // 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..." + GetParticleWeights(); + pw.fParticleWeightsAreFetched = true; + } - if (iv.fHarmonicsOptionInternalValidation->EqualTo("constant")) { + // 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. + // 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; + } + + } // if (!pw.fParticleWeightsAreFetched) { + + // a) Fourier like p.d.f. for azimuthal angles and flow amplitudes: + TF1* fPhiPDF = NULL; + TF3* fvnPDF = NULL; + + 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 // Keep also in sync with const int gMaxHarmonic = 9; in *GlobalConstants.h @@ -6245,7 +6807,12 @@ void InternalValidation() // b1) Determine multiplicity, centrality, reaction plane and configure p.d.f. for azimuthal angles if harmonics are not constant e-by-e: int nMult = static_cast(gRandom->Uniform(iv.fMultRangeInternalValidation[eMin], iv.fMultRangeInternalValidation[eMax])); - double fReactionPlane = gRandom->Uniform(0., o2::constants::math::TwoPI); // no cast is needed, since Uniform(...) returns double + double fReactionPlane = 0.; + if (iv.fRandomizeReactionPlane) { + fReactionPlane = gRandom->Uniform(0., o2::constants::math::TwoPI); // no cast is needed, since Uniform(...) returns double + } else { + LOGF(info, "\033[1;33m%s at line %d : Reaction plane was not randomized for this collision.\033[0m", __FUNCTION__, __LINE__); + } if (iv.fHarmonicsOptionInternalValidation->EqualTo("constant")) { fPhiPDF->SetParameter(18, fReactionPlane); } else if (iv.fHarmonicsOptionInternalValidation->EqualTo("correlated")) { @@ -6254,13 +6821,13 @@ void InternalValidation() 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 - ebye.fInteractionRate = static_cast(gRandom->Uniform(0., 10000.)); // this is perfectly fine for this exercise + ebye.fInteractionRate = static_cast(gRandom->Uniform(0., 1000.)); // this is perfectly fine for this exercise ebye.fCurrentRunDuration = static_cast(gRandom->Uniform(0., 86400.)); // this is perfectly fine for this exercise ebye.fVz = static_cast(gRandom->Uniform(-20., 20.)); // this is perfectly fine for this exercise ebye.fFT0CAmplitudeOnFoundBC = static_cast(gRandom->Uniform(0., 100000.)); // this is perfectly fine for this exercise ebye.fImpactParameter = static_cast(gRandom->Uniform(0., 20.)); // this is perfectly fine for this exercise - // b2) Fill event histograms before cuts: + // b2) Fill event histograms before cuts: if (eh.fFillEventHistograms) { !eh.fEventHistograms[eNumberOfEvents][eSim][eBefore] ? true : eh.fEventHistograms[eNumberOfEvents][eSim][eBefore]->Fill(0.5); !eh.fEventHistograms[eTotalMultiplicity][eSim][eBefore] ? true : eh.fEventHistograms[eTotalMultiplicity][eSim][eBefore]->Fill(nMult); @@ -6310,6 +6877,7 @@ void InternalValidation() 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 @@ -6321,16 +6889,32 @@ void InternalValidation() // Particle angle: dPhi = fPhiPDF->GetRandom(); - // *) To increase performance, sample pt or eta only if requested: - if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_PT] || t0.fCalculateTest0AsFunctionOf[AFO_PT] || es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { + // *) 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); } - if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA] || es.fCalculateEtaSeparations) { + if (mupa.fCalculateCorrelationsAsFunctionOf[AFO_ETA] || t0.fCalculateTest0AsFunctionOf[AFO_ETA] || es.fCalculateEtaSeparations || + t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA] || t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA] || t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE] || + 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); } + 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); + } + } + // *) 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) { @@ -6338,6 +6922,7 @@ void InternalValidation() !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); // 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); @@ -6362,6 +6947,7 @@ void InternalValidation() !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); // 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); @@ -6373,20 +6959,74 @@ void InternalValidation() this->FillQvector(dPhi, dPt, dEta); // all 3 arguments are passed by reference } - // *) Differential q-vectors: - // **) pt-dependence: + // *) 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: - this->Fillqvector(dPhi, dPt, PTq); // first 2 arguments are passed by reference, 3rd argument is enum + 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: - // Remark: Within Fillqvector() I check again all the relevant flags. - this->Fillqvector(dPhi, dPt, PTq, dEta); // first 2 arguments and the last one are passed by reference, 3rd argument is enum. "kine" variable is the 2nd argument + double kineArr[1] = {dPt}; + this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); } - // **) eta-dependence: + + // ***) 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. - this->Fillqvector(dPhi, dEta, ETAq); // first 2 arguments are passed by reference, 3rd argument is enum + 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); + } + + // ... + + // ** 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); } // *) Fill nested loops containers: @@ -6432,7 +7072,7 @@ void InternalValidation() ResetEventByEventQuantities(); // *) Print info on the current event number (within current real event): - LOGF(info, " Event # %d/%d (within current real event) ....", e + 1, static_cast(iv.fnEventsInternalValidation)); + LOGF(info, " Event # %d/%d (within current real event, running internal validation) ....", e + 1, static_cast(iv.fnEventsInternalValidation)); // *) Determine all event counters: DetermineEventCounters(); @@ -6515,26 +7155,30 @@ bool Accept(const double& value, int var) //============================================================ -void BookTest0Histograms() +void bookTest0Histograms() { // Book all Test0 histograms. // a) Book the profile holding flags; // b) Book placeholder and make sure all labels are stored in the placeholder; - // c) Book what needs to be booked; - // d) Few quick insanity checks on booking. + // c) Book what needs to be booked for 1D; + // d) Book what needs to be booked for 2D; + // e) Book what needs to be booked for 3D; + // f) Few quick insanity checks on booking (cherry-picking). if (tc.fVerbose) { StartFunction(__FUNCTION__); } // a) Book the profile holding flags: - t0.fTest0FlagsPro = new TProfile("fTest0FlagsPro", "flags for Test0", 1, 0., 1.); + t0.fTest0FlagsPro = new TProfile("fTest0FlagsPro", "flags for Test0", 3, 0., 3.); t0.fTest0FlagsPro->SetStats(false); t0.fTest0FlagsPro->GetXaxis()->SetLabelSize(0.04); if (tc.fUseSetBinLabel) { t0.fTest0FlagsPro->GetXaxis()->SetBinLabel(1, "fCalculateTest0"); + t0.fTest0FlagsPro->GetXaxis()->SetBinLabel(2, "fCalculate2DTest0"); + t0.fTest0FlagsPro->GetXaxis()->SetBinLabel(3, "fCalculate3DTest0"); // ... @@ -6543,7 +7187,8 @@ void BookTest0Histograms() TString yAxisTitle = ""; yAxisTitle += TString::Format("%d:fCalculateTest0; ", 1); - t0.fTest0FlagsPro->Fill(0.5, static_cast(t0.fCalculateTest0)); + yAxisTitle += TString::Format("%d:fCalculate2DTest0; ", 2); + yAxisTitle += TString::Format("%d:fCalculate3DTest0; ", 3); // ... @@ -6563,98 +7208,182 @@ void BookTest0Histograms() } // else - t0.fTest0FlagsPro->Fill(0.5, t0.fCalculateTest0); + t0.fTest0FlagsPro->Fill(0.5, static_cast(t0.fCalculateTest0)); + t0.fTest0FlagsPro->Fill(1.5, static_cast(t0.fCalculate2DTest0)); + t0.fTest0FlagsPro->Fill(2.5, static_cast(t0.fCalculate3DTest0)); + // ... t0.fTest0List->Add(t0.fTest0FlagsPro); - if (!t0.fCalculateTest0) { + if (!(t0.fCalculateTest0 || t0.fCalculate2DTest0 || t0.fCalculate3DTest0)) { return; } // b) Book placeholder and make sure all labels are stored in the placeholder: this->StoreLabelsInPlaceholder(); - // c) Book what needs to be booked: - for (int mo = 0; mo < gMaxCorrelator; mo++) { - for (int mi = 0; mi < gMaxIndex; mi++) { - if (!t0.fTest0Labels[mo][mi]) { - continue; - } - { + // c) Book what needs to be booked for 1D: + if (t0.fCalculateTest0) { + for (int mo = 0; mo < gMaxCorrelator; mo++) { + for (int mi = 0; mi < gMaxIndex; mi++) { + if (!t0.fTest0Labels[mo][mi]) { + continue; + } for (int v = 0; v < eAsFunctionOf_N; v++) { - // decide what is booked, then later valid pointer to fCorrelationsPro[k][n][v] is used as a boolean, in the standard way: - if (AFO_INTEGRATED == v && !t0.fCalculateTest0AsFunctionOf[AFO_INTEGRATED]) { - continue; - } - if (AFO_MULTIPLICITY == v && !t0.fCalculateTest0AsFunctionOf[AFO_MULTIPLICITY]) { - continue; - } - if (AFO_CENTRALITY == v && !t0.fCalculateTest0AsFunctionOf[AFO_CENTRALITY]) { + + // decide what is booked, then later valid pointer to fTest0Pro[k][n][v] is used as a boolean, in the standard way: + if (!t0.fCalculateTest0AsFunctionOf[v]) { continue; } - if (AFO_PT == v && !t0.fCalculateTest0AsFunctionOf[AFO_PT]) { - continue; + + if (!res.fResultsPro[v]) { + LOGF(fatal, "\033[1;31m%s at line %d : fResultsPro[%d] is NULL, this shall never happen, but apparently it happened... \033[0m", __FUNCTION__, __LINE__, v); } - if (AFO_ETA == v && !t0.fCalculateTest0AsFunctionOf[AFO_ETA]) { - continue; + + if (tc.fUseClone) { + t0.fTest0Pro[mo][mi][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()))); // yes + } else { + t0.fTest0Pro[mo][mi][v] = new TProfile(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); } - if (AFO_OCCUPANCY == v && !t0.fCalculateTest0AsFunctionOf[AFO_OCCUPANCY]) { - continue; + + t0.fTest0Pro[mo][mi][v]->SetStats(false); + t0.fTest0Pro[mo][mi][v]->Sumw2(); + t0.fTest0Pro[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); + t0.fTest0Pro[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsProXaxisTitle[v].Data())); + t0.fTest0List->Add(t0.fTest0Pro[mo][mi][v]); // yes, this has to be here + + } // for(int v=0;vGetName(); + TObjArray* oa = rawName.Tokenize("[]"); + if (oa->GetEntries() != 2) { + LOGF(fatal, "\033[1;31m%s at line %d : oa->GetEntries() = %d \033[0m", __FUNCTION__, __LINE__, oa->GetEntries()); } - if (AFO_CURRENTRUNDURATION == v && !t0.fCalculateTest0AsFunctionOf[AFO_CURRENTRUNDURATION]) { - continue; + rawName = oa->At(1)->GetName(); // basically: fResultsPro2D[cent_pt] => cent_pt + delete oa; + if (rawName.EqualTo("")) { + LOGF(fatal, "\033[1;31m%s at line %d : rawName is empty string \033[0m", __FUNCTION__, __LINE__); } - if (AFO_VZ == v && !t0.fCalculateTest0AsFunctionOf[AFO_VZ]) { - continue; + + if (tc.fUseClone) { + t0.fTest0Pro2D[mo][mi][v] = reinterpret_cast(res.fResultsPro2D[v]->Clone(Form("fTest0Pro2D[%d][%d][%s]", mo, mi, rawName.Data()))); + } else { + // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved + t0.fTest0Pro2D[mo][mi][v] = new TProfile2D(Form("fTest0Pro2D[%d][%d][%s]", mo, mi, rawName.Data()), "", + res.fResultsPro2D[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro2D[v]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro2D[v]->GetYaxis()->GetXbins()->GetSize() - 1, res.fResultsPro2D[v]->GetYaxis()->GetXbins()->GetArray()); // yes, GetYaxis()->GetXbins() + } // else + + t0.fTest0Pro2D[mo][mi][v]->SetStats(false); + t0.fTest0Pro2D[mo][mi][v]->Sumw2(); + t0.fTest0Pro2D[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); + t0.fTest0Pro2D[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsPro2D[v]->GetXaxis()->GetTitle())); + t0.fTest0Pro2D[mo][mi][v]->GetYaxis()->SetTitle(FancyFormatting(res.fResultsPro2D[v]->GetYaxis()->GetTitle())); + t0.fTest0List->Add(t0.fTest0Pro2D[mo][mi][v]); // yes, this has to be here + + } // for(int v=0;vGetName(); + TObjArray* oa = rawName.Tokenize("[]"); + if (oa->GetEntries() != 2) { + LOGF(fatal, "\033[1;31m%s at line %d : oa->GetEntries() = %d \033[0m", __FUNCTION__, __LINE__, oa->GetEntries()); + } + rawName = oa->At(1)->GetName(); // basically: fResultsPro2D[cent_pt_eta] => cent_pt_eta + delete oa; + if (rawName.EqualTo("")) { + LOGF(fatal, "\033[1;31m%s at line %d : rawName is empty string \033[0m", __FUNCTION__, __LINE__); } if (tc.fUseClone) { - t0.fTest0Pro[mo][mi][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()))); // yes + t0.fTest0Pro3D[mo][mi][v] = reinterpret_cast(res.fResultsPro3D[v]->Clone(Form("fTest0Pro3D[%d][%d][%s]", mo, mi, rawName.Data()))); } else { // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - t0.fTest0Pro[mo][mi][v] = new TProfile(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - t0.fTest0Pro[mo][mi][v] = new TProfile(Form("fTest0Pro[%d][%d][%s]", mo, mi, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else + t0.fTest0Pro3D[mo][mi][v] = new TProfile3D(Form("fTest0Pro3D[%d][%d][%s]", mo, mi, rawName.Data()), "", + res.fResultsPro3D[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro3D[v]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro3D[v]->GetYaxis()->GetXbins()->GetSize() - 1, res.fResultsPro3D[v]->GetYaxis()->GetXbins()->GetArray(), // yes, GetYaxis()->GetXbins() + res.fResultsPro3D[v]->GetZaxis()->GetXbins()->GetSize() - 1, res.fResultsPro3D[v]->GetZaxis()->GetXbins()->GetArray()); // yes, GetZaxis()->GetXbins() } // else - t0.fTest0Pro[mo][mi][v]->SetStats(false); - t0.fTest0Pro[mo][mi][v]->Sumw2(); - t0.fTest0Pro[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); - t0.fTest0Pro[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsProXaxisTitle[v].Data())); - t0.fTest0List->Add(t0.fTest0Pro[mo][mi][v]); // yes, this has to be here + t0.fTest0Pro3D[mo][mi][v]->SetStats(false); + t0.fTest0Pro3D[mo][mi][v]->Sumw2(); + t0.fTest0Pro3D[mo][mi][v]->SetTitle(t0.fTest0Labels[mo][mi]->Data()); + t0.fTest0Pro3D[mo][mi][v]->GetXaxis()->SetTitle(FancyFormatting(res.fResultsPro3D[v]->GetXaxis()->GetTitle())); + t0.fTest0Pro3D[mo][mi][v]->GetYaxis()->SetTitle(FancyFormatting(res.fResultsPro3D[v]->GetYaxis()->GetTitle())); + t0.fTest0Pro3D[mo][mi][v]->GetZaxis()->SetTitle(FancyFormatting(res.fResultsPro3D[v]->GetZaxis()->GetTitle())); + t0.fTest0List->Add(t0.fTest0Pro3D[mo][mi][v]); // yes, this has to be here } // for(int v=0;vGetXaxis()->GetTitle()).EqualTo("integrated")) { LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] } if (t0.fTest0Pro[0][0][AFO_PT] && !TString(t0.fTest0Pro[0][0][AFO_PT]->GetXaxis()->GetTitle()).EqualTo("p_{T}")) { - LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] + LOGF(fatal, "\033[1;31m%s at line %d : x-axis title = %s\033[0m", __FUNCTION__, __LINE__, t0.fTest0Pro[0][0][AFO_PT]->GetXaxis()->GetTitle()); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] + } + + // 2D: + if (t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT] && !(TString(t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetXaxis()->GetTitle()).Contains("centrality", TString::kIgnoreCase) && TString(t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetYaxis()->GetTitle()).EqualTo("p_{T}"))) { + LOGF(fatal, "\033[1;31m%s at line %d : x-axis title = %s, y-axis title = %s\033[0m", __FUNCTION__, __LINE__, t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetXaxis()->GetTitle(), t0.fTest0Pro2D[0][0][AFO_CENTRALITY_PT]->GetYaxis()->GetTitle()); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] + } + + // 3D: + if (t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA] && !(TString(t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetXaxis()->GetTitle()).Contains("centrality", TString::kIgnoreCase) && TString(t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetYaxis()->GetTitle()).EqualTo("p_{T}") && TString(t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetZaxis()->GetTitle()).EqualTo("#eta"))) { + LOGF(fatal, "\033[1;31m%s at line %d : x-axis title = %s, y-axis title = %s, z-axis title = %s\033[0m", __FUNCTION__, __LINE__, t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetXaxis()->GetTitle(), t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetYaxis()->GetTitle(), t0.fTest0Pro3D[0][0][AFO_CENTRALITY_PT_ETA]->GetZaxis()->GetTitle()); // ordering in enum eAsFunctionOf is not the same as in TString fResultsProXaxisTitle[eAsFunctionOf_N] } if (tc.fVerbose) { ExitFunction(__FUNCTION__); } -} // void BookTest0Histograms() +} // void bookTest0Histograms() //============================================================ -void BookEtaSeparationsHistograms() +void bookEtaSeparationsHistograms() { // Book all eta separations histograms. @@ -6716,51 +7445,21 @@ void BookEtaSeparationsHistograms() } for (int e = 0; e < gMaxNumberEtaSeparations; e++) { for (int v = 0; v < eAsFunctionOf_N; v++) { + // decide what is booked, then later valid pointer to es.fEtaSeparationsPro[h][e][v] is used as a boolean, in the standard way: - if (AFO_INTEGRATED == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTEGRATED]) { - continue; - } - if (AFO_MULTIPLICITY == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_MULTIPLICITY]) { - continue; - } - if (AFO_CENTRALITY == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_CENTRALITY]) { - continue; - } - if (AFO_PT == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { - continue; - } - if (AFO_ETA == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_ETA]) { - continue; - } - if (AFO_OCCUPANCY == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_OCCUPANCY]) { - continue; - } - if (AFO_INTERACTIONRATE == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_INTERACTIONRATE]) { - continue; - } - if (AFO_CURRENTRUNDURATION == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_CURRENTRUNDURATION]) { - continue; - } - if (AFO_VZ == v && !es.fCalculateEtaSeparationsAsFunctionOf[AFO_VZ]) { + if (!es.fCalculateEtaSeparationsAsFunctionOf[v]) { continue; } if (!res.fResultsPro[v]) { - LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + LOGF(fatal, "\033[1;31m%s at line %d : fResultsPro[%d] is NULL, this shall never happen, but apparently it happened... \033[0m", __FUNCTION__, __LINE__, v); } if (tc.fUseClone) { es.fEtaSeparationsPro[h][e][v] = reinterpret_cast(res.fResultsPro[v]->Clone(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()))); // yes } else { - // TBI 20250412 this branch is temporary workaround until hist->Clone(...) large memory consumption is resolved - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - es.fEtaSeparationsPro[h][e][v] = new TProfile(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()), "", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - es.fEtaSeparationsPro[h][e][v] = new TProfile(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()), "", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } // else - } // else + es.fEtaSeparationsPro[h][e][v] = new TProfile(Form("fEtaSeparationsPro[%d][%d][%s]", h, e, res.fResultsProRawName[v].Data()), "", res.fResultsPro[v]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[v]->GetXaxis()->GetXbins()->GetArray()); + } es.fEtaSeparationsPro[h][e][v]->SetStats(false); es.fEtaSeparationsPro[h][e][v]->Sumw2(); @@ -6783,16 +7482,19 @@ void BookEtaSeparationsHistograms() ExitFunction(__FUNCTION__); } -} // void BookEtaSeparationsHistograms() +} // void bookEtaSeparationsHistograms() //============================================================ -void BookResultsHistograms() +void bookResultsHistograms() { // Book all results histograms. + // These results histograms in addition act as a sort of "abstract" interface, which defines common binning, etc., for other groups of histograms. // a) Book the profile holding flags; - // b) Book results histograms, which in addition act as a sort of "abstract" interface, which defines common binning, etc., for other groups of histograms. + // b) Book (and optionaly save) results histograms 1D; + // c) Book (and optionaly save) results histograms 2D; + // d) Book (and optionaly save) results histograms 3D. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -6834,35 +7536,255 @@ void BookResultsHistograms() } res.fResultsList->Add(res.fResultsFlagsPro); - // b) Book results histograms, which in addition act as a sort of "abstract" interface, which defines common binning, etc., for other groups of histograms: + // b) Book (and optionaly save) results histograms 1D: for (int v = 0; v < eAsFunctionOf_N; v++) { - if (res.fUseResultsProVariableLengthBins[v]) { - // per demand, variable-length binning: - res.fResultsPro[v] = new TProfile(Form("fResultsPro[%s]", res.fResultsProRawName[v].Data()), "...", res.fResultsProVariableLengthBins[v]->GetSize() - 1, res.fResultsProVariableLengthBins[v]->GetArray()); - } else { - // the default fixed-length binning: - res.fResultsPro[v] = new TProfile(Form("fResultsPro[%s]", res.fResultsProRawName[v].Data()), "...", static_cast(res.fResultsProFixedLengthBins[v][0]), res.fResultsProFixedLengthBins[v][1], res.fResultsProFixedLengthBins[v][2]); - } - // Optionally, save these histograms. Or just use them as an "abstract" interface for the booking of other group of histograms: + // 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])) { + // // TBI 20250518 do I need here also some check for the nested loops? + // continue; + // } + + res.fResultsPro[v] = new TProfile(Form("fResultsPro[%s]", res.fResultsProRawName[v].Data()), "...", res.fResultsProBinEdges[v]->GetSize() - 1, res.fResultsProBinEdges[v]->GetArray()); + res.fResultsPro[v]->GetXaxis()->SetTitle(res.fResultsProXaxisTitle[v].Data()); + res.fResultsPro[v]->SetStats(false); + + delete res.fResultsProBinEdges[v]; // yes, it served the purpose. Now this info is carried permanently with res.fResultsPro[v], and I can always retrieve it later with e.g. + // res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins() (which gives pointer to TArrayD, yes I need double, because TProfile ctor takes double) + + // Optionally, save these histograms - I need this mostly to check/validate the binning. if (res.fSaveResultsHistograms) { res.fResultsList->Add(res.fResultsPro[v]); } - } // for (int v = 0; v < eAsFunctionOf_N; v++) { + } // for (int v = 0; v < eAsFunctionOf_N; v++) + + // c) Book (and optionaly save) results histograms 2D: + // Remark 1: Here I cannot loop, because for each axis I re-use binning from 1D cases. + // Remark 2: I have deleted above res.fResultsProBinEdges[...], that info is now only in the axis of res.fResultsPro[...] + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_PT]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data()); // raw name is e.g. "[cent_pt]" in the file + res.fResultsPro2D[AFO_CENTRALITY_PT] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_CENTRALITY_PT]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_PT]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_PT]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_ETA]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_ETA].Data()); + res.fResultsPro2D[AFO_CENTRALITY_ETA] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_CENTRALITY_ETA]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_ETA]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_ETA]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_CHARGE]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro2D[AFO_CENTRALITY_CHARGE] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + + res.fResultsPro2D[AFO_CENTRALITY_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_CHARGE]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_CENTRALITY_VZ]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_VZ].Data()); + res.fResultsPro2D[AFO_CENTRALITY_VZ] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_CENTRALITY_VZ]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_VZ]->GetYaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_CENTRALITY_VZ]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_ETA]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_ETA].Data()); + res.fResultsPro2D[AFO_PT_ETA] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_PT_ETA]->GetXaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_ETA]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_ETA]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_PT_CHARGE]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro2D[AFO_PT_CHARGE] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_PT_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_PT_CHARGE]->SetStats(false); + } + + if (t0.fCalculate2DTest0AsFunctionOf[AFO_ETA_CHARGE]) { + TString rawName = TString::Format("%s_%s", res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro2D[AFO_ETA_CHARGE] = new TProfile2D(Form("fResultsPro2D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro2D[AFO_ETA_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_ETA_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro2D[AFO_ETA_CHARGE]->SetStats(false); + } + + // ... + + // Optionally, save 2D results histograms - I need this mostly to check/validate the binning: + for (int v = 0; v < eAsFunctionOf2D_N; v++) { + if (res.fSaveResultsHistograms && res.fResultsPro2D[v]) { + res.fResultsList->Add(res.fResultsPro2D[v]); + } + } + + // d) Book (and optionaly save) results histograms 3D: + // Remark 1: Here I cannot loop, because for each axis I re-use binning from 1D cases. + // Remark 2: I have deleted above res.fResultsProBinEdges[...], that info is now only in the axis of res.fResultsPro[...] + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_ETA]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_ETA].Data()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->GetZaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_ETA]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_CHARGE]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_PT_VZ]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_VZ].Data()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->GetYaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->GetZaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_PT_VZ]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_VZ]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_VZ].Data()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->GetZaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_VZ]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_ETA_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_ETA_CHARGE]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_CENTRALITY_VZ_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_CENTRALITY].Data(), res.fResultsProRawName[AFO_VZ].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_VZ]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_CENTRALITY]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_VZ]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_CENTRALITY_VZ_CHARGE]->SetStats(false); + } + + if (t0.fCalculate3DTest0AsFunctionOf[AFO_PT_ETA_CHARGE]) { + TString rawName = TString::Format("%s_%s_%s", res.fResultsProRawName[AFO_PT].Data(), res.fResultsProRawName[AFO_ETA].Data(), res.fResultsProRawName[AFO_CHARGE].Data()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE] = new TProfile3D(Form("fResultsPro3D[%s]", rawName.Data()), "...", + res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_PT]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_ETA]->GetXaxis()->GetXbins()->GetArray(), + res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetSize() - 1, res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetXbins()->GetArray()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->GetXaxis()->SetTitle(res.fResultsPro[AFO_PT]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->GetYaxis()->SetTitle(res.fResultsPro[AFO_ETA]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->GetZaxis()->SetTitle(res.fResultsPro[AFO_CHARGE]->GetXaxis()->GetTitle()); + res.fResultsPro3D[AFO_PT_ETA_CHARGE]->SetStats(false); + } + + // Optionally, save 3D results histograms - I need this mostly to check/validate the binning: + for (int v = 0; v < eAsFunctionOf3D_N; v++) { + + if (res.fSaveResultsHistograms && res.fResultsPro3D[v]) { + res.fResultsList->Add(res.fResultsPro3D[v]); + } + } + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void bookResultsHistograms() + +//============================================================ + +TArrayD* ArrayWithBinEdges(int nBins, float min, float max) +{ + // Helper function to determine concrete bin edges, when the fixed-size binning was specified with nBins in (min, max). + + // a) Insanity checks on arguments; + // b) Okay, do the thing. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // a) Insanity check on arguments: + if (nBins <= 0 || max < min || std::abs(max - min) < tc.fFloatingPointPrecision) { + LOGF(fatal, "\033[1;31m%s at line %d : Insane arguments for fixed-length binning: nBins = %d , min = %f, max = %f \033[0m", __FUNCTION__, __LINE__, nBins, min, max); + } + + // b) Okay, do the thing: + float binWidth = (max - min) / (1. * nBins); + + TArrayD* binEdges = new TArrayD(nBins + 1); + for (int b = 1; b <= nBins + 1; b++) { + binEdges->AddAt(min + (b - 1) * binWidth, b - 1); + } if (tc.fVerbose) { ExitFunction(__FUNCTION__); } -} // void BookResultsHistograms() + return binEdges; + +} // TArrayD *ArrayWithBinEdges(int nBins, float min, float max) //============================================================ -void BookTheRest() +void bookTheRest() { // Here I book everything not sorted (yes) in specific functions above. // a) Book the timer; + // b) Book TDatabasePDG; // *) ... if (tc.fVerbose) { @@ -6876,11 +7798,16 @@ void BookTheRest() tc.fTimer[eLocal] = new TStopwatch(); } + // b) Book TDatabasePDG: + if (tc.fUseDatabasePDG) { + tc.fDatabasePDG = new TDatabasePDG(); // there is a standard memory blow-up here + } + if (tc.fVerbose) { ExitFunction(__FUNCTION__); } -} // void BookTheRest() +} // void bookTheRest() //============================================================ @@ -7389,19 +8316,23 @@ void ResetEventByEventQuantities() qv.fQvector[h][wp] = TComplex(0., 0.); } } + } // if (qv.fCalculateQvectors) + + if (qv.fCalculateqvectorsKineAny) { + ResetQ(); // TBI 20250601 do I really need this one here. It doesn't hurt, though... + // Remark: It's important to validate this reset with nested loops e-by-e and for all events. + for (int i = 0; i < static_cast(qv.fqvector.size()); ++i) { + for (int j = 0; j < static_cast(qv.fqvector[i].size()); ++j) { + qv.fqvectorEntries[i][j] = 0; + for (int k = 0; k < static_cast(qv.fqvector[i][j].size()); ++k) { + for (int l = 0; l < static_cast(qv.fqvector[i][j][k].size()); ++l) { + qv.fqvector[i][j][k][l] = {0., 0.}; // yes, this is the right notation for complex numbers + } + } + } + } - // b2) diff. Q-vector: - for (int bin = 1; bin <= gMaxNoBinsKine; bin++) { - qv.fqVectorEntries[PTq][bin - 1] = 0; // TBI 20240214 shall I loop also over enum's PTq and ETAq? If yes, fix it also below for qv.fqvector[PTq][bin - 1][... - qv.fqVectorEntries[ETAq][bin - 1] = 0; - for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - qv.fqvector[PTq][bin - 1][h][wp] = TComplex(0., 0.); - qv.fqvector[ETAq][bin - 1][h][wp] = TComplex(0., 0.); - } // for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - } // for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - } // for (int b = 0; b < gMaxNoBinsKine; b++ ) { - } // if(qv.fCalculateQvectors) + } // if (qv.fCalculateqvectorsKineAny) // b3) integrated Q-vector needed for calculations with eta separations: if (es.fCalculateEtaSeparations) { @@ -7422,29 +8353,36 @@ void ResetEventByEventQuantities() } } - // b4) diff. q-vector in pt needed for calculations with eta separations: - if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { // yes, for the time being, only as a function of pt makes sense if eta separation is used - for (int ab = 0; ab < 2; ab++) { // ab = 0 <=> -eta , ab = 1 <=> + eta - for (int bin = 1; bin <= gMaxNoBinsKine; bin++) { - for (int h = 0; h < gMaxHarmonic; h++) { - if (es.fEtaSeparationsSkipHarmonics[h]) { - continue; - } - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - qv.fqabVector[ab][bin - 1][h][e] = TComplex(0., 0.); // yes, bin - 1 here + // b4) diff. q-vector needed for calculations with eta separations: + if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { // _444 check this conditions + // [-eta or +eta][eqvectorKine_N][global binNo][harmonic][eta separation] + for (int i = 0; i < static_cast(qv.fqabVector.size()); ++i) { + for (int j = 0; j < static_cast(qv.fqabVector[i].size()); ++j) { + for (int k = 0; k < static_cast(qv.fqabVector[i][j].size()); ++k) { + for (int l = 0; l < static_cast(qv.fqabVector[i][j][k].size()); ++l) { // yes, this dimension is for harmonics at the moment + if (es.fEtaSeparationsSkipHarmonics[l]) { + continue; + } + for (int m = 0; m < static_cast(qv.fqabVector[i][j][k][l].size()); ++m) { + qv.fqabVector[i][j][k][l][m] = {0., 0.}; // yes, this is the right notation for complex numbers + } } } } } - for (int ab = 0; ab < 2; ab++) { // ab = 0 <=> -eta , ab = 1 <=> + eta - for (int bin = 1; bin <= gMaxNoBinsKine; bin++) { - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - qv.fmab[ab][bin - 1][e] = 0.; // yes, bin - 1 here + // [-eta or +eta][eqvectorKine_N][global binNo][eta separation] + for (int i = 0; i < static_cast(qv.fmab.size()); ++i) { + for (int j = 0; j < static_cast(qv.fmab[i].size()); ++j) { + for (int k = 0; k < static_cast(qv.fmab[i][j].size()); ++k) { + for (int l = 0; l < static_cast(qv.fmab[i][j][k].size()); ++l) { + qv.fmab[i][j][k][l] = 0.; + } } } } - } + + } // if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) // c) Reset ebe containers for nested loops: if (nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) { @@ -7458,14 +8396,74 @@ void ResetEventByEventQuantities() } // if(nl.fCalculateNestedLoops || nl.fCalculateCustomNestedLoops) if (nl.fCalculateKineCustomNestedLoops) { - for (int b = 0; b < res.fResultsPro[AFO_PT]->GetNbinsX(); b++) { + int nBins = -1; + + // 1D kine: + // **) vs. pt: + nBins = res.fResultsPro[AFO_PT]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[PTq][b][0]->Reset(); nl.ftaNestedLoopsKine[PTq][b][1]->Reset(); } - for (int b = 0; b < res.fResultsPro[AFO_ETA]->GetNbinsX(); b++) { + + // **) vs. eta: + nBins = res.fResultsPro[AFO_ETA]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { nl.ftaNestedLoopsKine[ETAq][b][0]->Reset(); nl.ftaNestedLoopsKine[ETAq][b][1]->Reset(); } + + // **) vs. charge: + nBins = res.fResultsPro[AFO_CHARGE]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { + nl.ftaNestedLoopsKine[CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[CHARGEq][b][1]->Reset(); + } + + // ... + + // 2D kine: + // **) vs. (pt,eta): + if (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_ETAq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETAq][b][0]->Reset(); + nl.ftaNestedLoopsKine[PT_ETAq][b][1]->Reset(); + } + } + + // **) vs. (pt,charge): + if (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(PT_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[PT_CHARGEq][b][1]->Reset(); + } + } + + // **) vs. (eta,charge): + if (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro2D[AfoKineMap2D(ETA_CHARGEq)]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[ETA_CHARGEq][b][1]->Reset(); + } + } + + // ... + + // 3D kine: + // **) vs. (pt,eta,charge): + if (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]) { // this is safe, because this one shall be booked if any of Correlations, Test0, EtaSeparations, etc., was requested + nBins = (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsX() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsY() + 2) * (res.fResultsPro3D[AfoKineMap3D(PT_ETA_CHARGEq)]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + for (int b = 0; b < nBins; b++) { // loop over lineralized global bins + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][0]->Reset(); + nl.ftaNestedLoopsKine[PT_ETA_CHARGEq][b][1]->Reset(); + } + } + + // ... + } // if(nl.fCalculateKineCustomNestedLoops) { // d) Fisher-Yates algorithm: @@ -8114,6 +9112,72 @@ bool EventCuts(T1 const& collision, T2 const& tracks, eCutModus cutModus) } } + // *) FT0Bad: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eFT0Bad]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eFT0Bad, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kFT0Bad)) { + if (!EventCut(eRec, eFT0Bad, cutModus)) { + return false; + } + } + } + + // *) ITSBad: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eITSBad]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eITSBad, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kITSBad)) { + if (!EventCut(eRec, eITSBad, cutModus)) { + return false; + } + } + } + + // *) ITSLimAccMCRepr: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eITSLimAccMCRepr]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eITSLimAccMCRepr, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kITSLimAccMCRepr)) { + if (!EventCut(eRec, eITSLimAccMCRepr, cutModus)) { + return false; + } + } + } + + // *) TPCBadTracking: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eTPCBadTracking]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eTPCBadTracking, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kTPCBadTracking)) { + if (!EventCut(eRec, eTPCBadTracking, cutModus)) { + return false; + } + } + } + + // *) TPCLimAccMCRepr: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eTPCLimAccMCRepr]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eTPCLimAccMCRepr, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kTPCLimAccMCRepr)) { + if (!EventCut(eRec, eTPCLimAccMCRepr, cutModus)) { + return false; + } + } + } + + // *) TPCBadPID: // see O2Physics/Common/CCDB/RCTSelectionFlags.h + if (ec.fUseEventCuts[eTPCBadPID]) { + if (cutModus == eCutCounterBinning) { + EventCut(eRec, eTPCBadPID, eCutCounterBinning); + } else if (collision.rct_bit(o2::aod::rctsel::kTPCBadPID)) { + if (!EventCut(eRec, eTPCBadPID, cutModus)) { + return false; + } + } + } + // ... // *) Centrality weights (flattening): @@ -8588,7 +9652,7 @@ void FillEventHistograms(T1 const& collision, T2 const& tracks, eBeforeAfter ba) !eh.fEventHistograms[eImpactParameter][eSim][ba] ? true : eh.fEventHistograms[eImpactParameter][eSim][ba]->Fill(collision.impactParameter()); // yes, because in this branch 'collision' is always aod::McCollision !eh.fEventHistograms[eEventPlaneAngle][eSim][ba] ? true : eh.fEventHistograms[eEventPlaneAngle][eSim][ba]->Fill(collision.eventPlaneAngle()); // yes, because in this branch 'collision' is always aod::McCollision !eh.fEventHistograms[eMultiplicity][eSim][ba] ? true : eh.fEventHistograms[eMultiplicity][eSim][ba]->Fill(ebye.fMultiplicity); - !eh.fEventHistograms[eCentrality][eSim][ba] ? true : eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // ebye.fCentrality = ebye.fCentralitySim in any case in this branh + !eh.fEventHistograms[eCentrality][eSim][ba] ? true : eh.fEventHistograms[eCentrality][eSim][ba]->Fill(ebye.fCentrality); // ebye.fCentrality = ebye.fCentralitySim in any case in this branch // eh.fEventHistograms[eReferenceMultiplicity][eSim][ba]->Fill(ebye.fReferenceMultiplicity); // TBI 20241123 this case is still not supported in DetermineReferenceMultiplicity() // eh.fEventHistograms[eTotalMultiplicity][eSim][ba]->Fill(tracks.size()); // TBI 20231030 check further how to use the same thing for 'sim' } @@ -8788,6 +9852,10 @@ void CheckUnderflowAndOverflow() { // Check and bail out if in event and particle histograms there are entries which went to underflow or overflow bins. + // TBI 20250527 I have reinvented the wheel here, there are already member functions TH1::IsBinUnderflow() and TH1::IsBinOverflow(), + // which I have use also for 2D and 3D cases with "global bin". + // Reimplemented this function using those member functions eventually. + // a) Event histograms 1D; // b) Event histograms 2D; // c) Particle histograms 1D; @@ -9592,36 +10660,35 @@ bool ParticleCuts(T const& track, eCutModus cutModus) LOGF(warning, "No MC particle for this track, skip..."); return false; // TBI 20231107 re-think. I shouldn't probably get to this point, if MC truth info doesn't exist for this track } - // auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle + // auto mcParticle = track.mcParticle(); // corresponding MC truth simulated particle - // In this branch I can cut additionally and directly on corresponding MC truth simulated, e.g. on mcparticle.pt() + // In this branch I can cut additionally and directly on corresponding MC truth simulated, e.g. on mcParticle.pt() // In case I implement something here, remember to switch from eRec to eSim when calling e.g. ParticleCut(...) - /* - // *) Phi: TBI 2024-511 re-think if i really cut directly on MC truth kine and other info and keep it in sync with what I did in AliPhysics - if (pc.fUseParticleCuts[ePhi]) { - if (cutModus == eCutCounterBinning) { - ParticleCut(eSim, ePhi, eCutCounterBinning); - } else if (mcparticle.phi() < pc.fdParticleCuts[ePhi][eMin] || mcparticle.phi() > pc.fdParticleCuts[ePhi][eMax]) { - if (!ParticleCut(eSim, ePhi, cutModus)) { - return false; - } - } - } - */ - // *) Charge: TBI 20240511 mcparticle.sign() doesn't exist, here most likely i need to cut on the signature of mcparticle.pdg() but check further, because e is negative charge, but PDG is 11, etc. - /* - if (pc.fUseParticleCuts[eCharge]) { - if (cutModus == eCutCounterBinning) { - ParticleCut(eSim, eCharge, eCutCounterBinning); - } else if (0 == mcparticle.sign() || mcparticle.sign() < pc.fdParticleCuts[eCharge][eMin] || mcparticle.sign() > pc.fdParticleCuts[eCharge][eMax]) { - // TBI 20240511 with first condition, I always throw away neutral particles, so for the time being that is hardcoded - if (!ParticleCut(eSim, eCharge, cutModus)) { - return false; - } - } - } - */ + // // *) Phi: TBI 2024-511 re-think if i really cut directly on MC truth kine and other info and keep it in sync with what I did in AliPhysics + // if (pc.fUseParticleCuts[ePhi]) { + // if (cutModus == eCutCounterBinning) { + // ParticleCut(eSim, ePhi, eCutCounterBinning); + // } else if (mcParticle.phi() < pc.fdParticleCuts[ePhi][eMin] || mcParticle.phi() > pc.fdParticleCuts[ePhi][eMax]) { + // if (!ParticleCut(eSim, ePhi, cutModus)) { + // return false; + // } + // } + // } + + // *) Charge: TBI 20240511 mcParticle.sign() doesn't exist, get charge from tc.fDatabasePDG instead using PDG code , as I did it below + + // if (pc.fUseParticleCuts[eCharge]) { + // if (cutModus == eCutCounterBinning) { + // ParticleCut(eSim, eCharge, eCutCounterBinning); + // } else if (0 == mcParticle.sign() || mcParticle.sign() < pc.fdParticleCuts[eCharge][eMin] || mcParticle.sign() > pc.fdParticleCuts[eCharge][eMax]) { + // // TBI 20240511 with first condition, I always throw away neutral particles, so for the time being that is hardcoded + // if (!ParticleCut(eSim, eCharge, cutModus)) { + // return false; + // } + // } + // } + // TBI 20240511 add cut on PDG // ... @@ -9673,17 +10740,39 @@ bool ParticleCuts(T const& track, eCutModus cutModus) /* // *) Charge: if (pc.fUseParticleCuts[eCharge]) { + double charge = -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 + charge = tc.fDatabasePDG->GetParticle(track.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + if (tc.fVerboseForEachParticle) { + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! There is a large memory blow-up when using TDatabasePDG !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + } + } if (cutModus == eCutCounterBinning) { ParticleCut(eSim, eCharge, eCutCounterBinning); - } else if (0 == track.sign() || track.sign() < pc.fdParticleCuts[eCharge][eMin] || track.sign() > pc.fdParticleCuts[eCharge][eMax]) { - // TBI 20240511 with first condition, I always throw away neutral particles, so for the time being that is hardcoded + } else if (0 == static_cast(charge) || charge < pc.fdParticleCuts[eCharge][eMin] || charge > pc.fdParticleCuts[eCharge][eMax]) { + // TBI 20250611 with first condition, I always throw away neutral particles when O2DatabasePDG is used. + // However due to initialization charge = 0. that way I throw all particles when O2DatabasePDG is NOT used. + // Therefore, when O2DatabasePDG is NOT used, I have to disable cut on charge, since that info is not available. if (!ParticleCut(eSim, eCharge, cutModus)) { return false; } } } + */ - // TBI 20240511 add cut on PDG + + // *) PDG code: + if (pc.fUseParticleCuts[ePDG]) { + if (cutModus == eCutCounterBinning) { + ParticleCut(eSim, ePDG, eCutCounterBinning); + } else if (track.pdgCode() < pc.fdParticleCuts[ePDG][eMin] || track.pdgCode() > pc.fdParticleCuts[ePDG][eMax]) { + // TBI 20250611 I need to generalize this, e.g. add support to process more that one PDG code (e.g. 2212 and -2212, etc.) + if (!ParticleCut(eSim, ePDG, cutModus)) { + return false; + } + } + } // ... @@ -9704,7 +10793,7 @@ bool ParticleCuts(T const& track, eCutModus cutModus) LOGF(warning, "No MC particle for this track, skip..."); return false; // TBI 20231107 re-think. I shouldn't probably get to this point, if MC truth info doesn't exist for this track } - // auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle + // auto mcParticle = track.mcParticle(); // corresponding MC truth simulated particle // ... @@ -9741,7 +10830,7 @@ bool ParticleCuts(T const& track, eCutModus cutModus) LOGF(warning, "No MC particle for this track, skip..."); return false; // TBI 20231107 re-think. I shouldn't probably get to this point, if MC truth info doesn't exist for this track } - // auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle + // auto mcParticle = track.mcParticle(); // corresponding MC truth simulated particle // ... @@ -9840,10 +10929,10 @@ bool ParticleCuts(T const& track, eCutModus cutModus) LOGF(warning, "No MC particle for this track, skip..."); return false; // TBI 20231107 re-think. I shouldn't probably get to this point, if MC truth info doesn't exist for this particle } - auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle - dPhi = mcparticle.phi(); - dPt = mcparticle.pt(); - dEta = mcparticle.eta(); + auto mcParticle = track.mcParticle(); // corresponding MC truth simulated particle + dPhi = mcParticle.phi(); + dPt = mcParticle.pt(); + dEta = mcParticle.eta(); // Apply NUA on these kine variables: if (nua.fApplyNUAPDF[ePhiNUAPDF] && !Accept(dPhi, ePhiNUAPDF)) { @@ -9969,36 +11058,17 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // 1D: if (ph.fFillParticleHistograms) { - // From o2::aod::Tracks - - // memStatus ~120 + // From o2::aod::Tracks !ph.fParticleHistograms[ePhi][eRec][ba] ? true : ph.fParticleHistograms[ePhi][eRec][ba]->Fill(track.phi(), weight); - - // memStatus ~125 - !ph.fParticleHistograms[ePt][eRec][ba] ? true : ph.fParticleHistograms[ePt][eRec][ba]->Fill(track.pt(), weight); - - // memStatus ~127 - !ph.fParticleHistograms[eEta][eRec][ba] ? true : ph.fParticleHistograms[eEta][eRec][ba]->Fill(track.eta(), weight); - - // memStatus ~133 - !ph.fParticleHistograms[eCharge][eRec][ba] ? true : ph.fParticleHistograms[eCharge][eRec][ba]->Fill(track.sign(), weight); - // memStatus ~139 - // From o2::aod::TracksExtra_001 !ph.fParticleHistograms[etpcNClsFindable][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFindable][eRec][ba]->Fill(track.tpcNClsFindable(), weight); !ph.fParticleHistograms[etpcNClsShared][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsShared][eRec][ba]->Fill(track.tpcNClsShared(), weight); - - // memStatus ~140 - !ph.fParticleHistograms[eitsChi2NCl][eRec][ba] ? true : ph.fParticleHistograms[eitsChi2NCl][eRec][ba]->Fill(track.itsChi2NCl(), weight); - - // memStatus ~146 - !ph.fParticleHistograms[etpcNClsFound][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsFound][eRec][ba]->Fill(track.tpcNClsFound(), weight); !ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba] ? true : ph.fParticleHistograms[etpcNClsCrossedRows][eRec][ba]->Fill(track.tpcNClsCrossedRows(), weight); !ph.fParticleHistograms[eitsNCls][eRec][ba] ? true : ph.fParticleHistograms[eitsNCls][eRec][ba]->Fill(track.itsNCls(), weight); @@ -10031,13 +11101,13 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // **) 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()}; + double vector[eDiffPtWeights_N] = {track.pt(), static_cast(track.sign()), ebye.fCentrality}; ph.fParticleSparseHistograms[eDWPt][eRec]->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()}; + double vector[eDiffEtaWeights_N] = {track.eta(), static_cast(track.sign()), ebye.fCentrality}; ph.fParticleSparseHistograms[eDWEta][eRec]->Fill(vector, weight); } } // if (ba == eAfter) { @@ -10138,21 +11208,28 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) LOGF(warning, " No MC particle for this track, skip..."); return; } - auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle + auto mcParticle = track.mcParticle(); // corresponding MC truth simulated particle // 1D: if (ph.fFillParticleHistograms) { - !ph.fParticleHistograms[ePhi][eSim][ba] ? true : ph.fParticleHistograms[ePhi][eSim][ba]->Fill(mcparticle.phi(), weight); - !ph.fParticleHistograms[ePt][eSim][ba] ? true : ph.fParticleHistograms[ePt][eSim][ba]->Fill(mcparticle.pt(), weight); - !ph.fParticleHistograms[eEta][eSim][ba] ? true : ph.fParticleHistograms[eEta][eSim][ba]->Fill(mcparticle.eta(), weight); - // !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill( ... ); // TBI 20240511 there is no mcparticle.sign()) - !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(mcparticle.pdgCode(), weight); // TBI 20240512 this one gets filles correctly, deduce from it charge signature + !ph.fParticleHistograms[ePhi][eSim][ba] ? true : ph.fParticleHistograms[ePhi][eSim][ba]->Fill(mcParticle.phi(), weight); + !ph.fParticleHistograms[ePt][eSim][ba] ? true : ph.fParticleHistograms[ePt][eSim][ba]->Fill(mcParticle.pt(), weight); + !ph.fParticleHistograms[eEta][eSim][ba] ? true : ph.fParticleHistograms[eEta][eSim][ba]->Fill(mcParticle.eta(), weight); + + // 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 + } + !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill(charge); + !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(mcParticle.pdgCode(), weight); } // 2D: if (ph.fFillParticleHistograms2D) { - !ph.fParticleHistograms2D[ePhiPt][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][ba]->Fill(mcparticle.phi(), mcparticle.pt(), weight); - !ph.fParticleHistograms2D[ePhiEta][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][ba]->Fill(mcparticle.phi(), mcparticle.eta(), weight); + !ph.fParticleHistograms2D[ePhiPt][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiPt][eSim][ba]->Fill(mcParticle.phi(), mcParticle.pt(), weight); + !ph.fParticleHistograms2D[ePhiEta][eSim][ba] ? true : ph.fParticleHistograms2D[ePhiEta][eSim][ba]->Fill(mcParticle.phi(), mcParticle.eta(), weight); } // if(ph.fFillParticleHistograms2D) { // nD (THnSparse): @@ -10160,22 +11237,41 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) // **) 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] = {mcparticle.phi(), mcparticle.pt(), mcparticle.eta(), 0., 0., 0.}; - // TBI 20250223 I do not have access to particle charge signature here => I set it to 0 temporarily. - // Then, I did not calculate and store centrality for "sim" => I set it to 0 temporarily. - // Same for vertex z, I could trivially extend ebye.fVz also for "sim" dimension => I set it to 0 temporarily here, until that's done. + + // 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[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); } // **) 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] = {mcparticle.pt()}; + + // 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[eDiffPtWeights_N] = {mcParticle.pt(), charge, ebye.fCentralitySim}; ph.fParticleSparseHistograms[eDWPt][eSim]->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] = {mcparticle.eta()}; + + // 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[eDiffEtaWeights_N] = {mcParticle.eta(), charge, ebye.fCentralitySim}; ph.fParticleSparseHistograms[eDWEta][eSim]->Fill(vector, weight); } } // if (ba == eAfter) { @@ -10194,7 +11290,14 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) !ph.fParticleHistograms[ePhi][eSim][ba] ? true : ph.fParticleHistograms[ePhi][eSim][ba]->Fill(track.phi(), weight); !ph.fParticleHistograms[ePt][eSim][ba] ? true : ph.fParticleHistograms[ePt][eSim][ba]->Fill(track.pt(), weight); !ph.fParticleHistograms[eEta][eSim][ba] ? true : ph.fParticleHistograms[eEta][eSim][ba]->Fill(track.eta(), weight); - // !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill( ... ); // TBI 20240511 there is no mcparticle.sign()) + + // 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(track.pdgCode())) { + // Yes, I have to check the 2nd condition, because e.g. for PDG code 1000010020 (deuteron), GetParticle(...) returns NULL + charge = tc.fDatabasePDG->GetParticle(track.pdgCode())->Charge() / 3.; // yes, divided by 3. Fundamental unit of charge is associated with quarks + } + !ph.fParticleHistograms[eCharge][eSim][ba] ? true : ph.fParticleHistograms[eCharge][eSim][ba]->Fill(charge); !ph.fParticleHistograms[ePDG][eSim][ba] ? true : ph.fParticleHistograms[ePDG][eSim][ba]->Fill(track.pdgCode(), weight); } // if(ph.fFillParticleHistograms) { @@ -10222,7 +11325,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) return; } - // auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle + // auto mcParticle = track.mcParticle(); // corresponding MC truth simulated particle // ... @@ -10257,7 +11360,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) return; } - // auto mcparticle = track.mcParticle(); // corresponding MC truth simulated particle + // auto mcParticle = track.mcParticle(); // corresponding MC truth simulated particle // ... @@ -10302,8 +11405,7 @@ void FillParticleHistograms(T const& track, eBeforeAfter ba, int weight = 1) void CalculateCorrelations() { // Calculate analytically multiparticle correlations from Q-vectors. - // In this method, only isotropic correlations for which all harmonics are the - // same are evaluated. + // In this method, only isotropic correlations for which all harmonics are the same are evaluated. // a) Flush 'n' fill the generic Q-vectors; // b) Calculate correlations; @@ -10352,7 +11454,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(twoC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as twoC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, twoC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 2-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 2-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10421,7 +11523,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(fourC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as fourC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, fourC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 4-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 4-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10492,7 +11594,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(sixC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as sixC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, sixC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 6-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 6-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10565,7 +11667,7 @@ void CalculateCorrelations() if (std::abs(nestedLoopValue) > 0. && std::abs(eightC - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as eightC = %f\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, eightC); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 8-p, harmonic %d\033[0m", h); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for isotropic 8-p, harmonic %d\033[0m", h); } delete harmonics; harmonics = NULL; @@ -10640,6 +11742,11 @@ void CalculateKineCorrelations(eAsFunctionOf AFO_variable) // nBins = res.fResultsPro[AFO_ETA]->GetNbinsX(); // TBI 20241111 temporarily commented out just to suppress warnings break; } + case AFO_CHARGE: { + qvKine = CHARGEq; + // nBins = res.fResultsPro[AFO_ETA]->GetNbinsX(); // TBI 20241111 temporarily commented out just to suppress warnings + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); break; @@ -10836,7 +11943,7 @@ void CalculateTest0() } else if (std::abs(nestedLoopValue) > 0. && std::abs(correlation / weight - nestedLoopValue) > tc.fFloatingPointPrecision) { LOGF(fatal, "\033[1;31m%s at line %d : nestedLoopValue = %f is not the same as correlation/weight = %f, for correlator %s\033[0m", __FUNCTION__, __LINE__, nestedLoopValue, correlation / weight, t0.fTest0Labels[mo][mi]->Data()); } else { - LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for %d-p Test0 corr. %s\033[0m", mo + 1, t0.fTest0Labels[mo][mi]->Data()); + LOGF(info, "\033[1;32m ebye check (integrated) with CustomNestedLoops is OK for %d-p Test0 corr. %s\033[0m", mo + 1, t0.fTest0Labels[mo][mi]->Data()); } delete harmonics; harmonics = NULL; @@ -10858,6 +11965,8 @@ void CalculateTest0() } // if(fUseInternalValidation && fRescaleWithTheoreticalInput) // Finally, fill: + + // 1D: // integrated: if (t0.fTest0Pro[mo][mi][AFO_INTEGRATED]) { t0.fTest0Pro[mo][mi][AFO_INTEGRATED]->Fill(0.5, correlation / weight, weight); @@ -10886,6 +11995,21 @@ void CalculateTest0() if (t0.fTest0Pro[mo][mi][AFO_VZ]) { t0.fTest0Pro[mo][mi][AFO_VZ]->Fill(ebye.fVz, correlation / weight, weight); } + + // ... + + // 2D: + // vs. centrality vs. vertex z position: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_VZ]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_VZ]->Fill(ebye.fCentrality, ebye.fVz, correlation / weight, weight); + } + + // ... + + // 3D: + + // ... + } // if(t0.fTest0Labels[mo][mi]) } // for(int mi=0;miGetNbinsX(); break; } + case AFO_CHARGE: { + qvKine = CHARGEq; + nBins = res.fResultsPro[AFO_CHARGE]->GetNbinsX(); + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); break; @@ -10935,11 +12068,11 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); } - // *) Uniform loop over bin for all kine variables: + // *) Uniform loop over bins for all kine variables: for (int b = 0; b < nBins; b++) { // *) 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 ((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)); } @@ -10949,7 +12082,7 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) // After that, I can call all standard Q-vector functions again: for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - qv.fQ[h][wp] = qv.fqvector[qvKine][b][h][wp]; + // qv.fQ[h][wp] = qv.fqvector[qvKine][b][h][wp]; TBI 20250616 I cannot use this any longer, after I added one more dimension to qv.fqvector } } @@ -10973,7 +12106,7 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) delete oa; // yes, otherwise it's a memory leak } - if (qv.fqVectorEntries[qvKine][b] < mo + 1) { + if (qv.fqvectorEntries[qvKine][b] < mo + 1) { continue; } @@ -11091,15 +12224,39 @@ void CalculateKineTest0(eAsFunctionOf AFO_variable) LOGF(info, "\n\033[1;33m t0.fTest0Pro[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro[mo][mi][AFO_variable]->GetTitle()); LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_variable)); LOGF(info, "\n\033[1;33m ebye.fSelectedTracks = %d \033[0m\n", ebye.fSelectedTracks); - LOGF(info, "\n\033[1;33m qv.fqVectorEntries[qvKine][b] = %d \033[0m\n", qv.fqVectorEntries[qvKine][b]); + LOGF(info, "\n\033[1;33m qv.fqvectorEntries[qvKine][b] = %d \033[0m\n", qv.fqvectorEntries[qvKine][b]); LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } // Finally, fill: + + // 1D: if (t0.fTest0Pro[mo][mi][AFO_variable]) { t0.fTest0Pro[mo][mi][AFO_variable]->Fill(t0.fTest0Pro[mo][mi][AFO_variable]->GetXaxis()->GetBinCenter(b + 1), correlation / weight, weight); } // fill in the bin center + // 2D: + if (t0.fCalculate2DTest0) { + + // vs. centrality vs. pt: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT] && AFO_variable == AFO_PT) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->GetYaxis()->GetBinCenter(b + 1), correlation / weight, weight); + } + + // vs. centrality vs. eta: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA] && AFO_variable == AFO_ETA) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->GetYaxis()->GetBinCenter(b + 1), correlation / weight, weight); + } + + // vs. centrality vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE] && AFO_variable == AFO_CHARGE) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->GetYaxis()->GetBinCenter(b + 1), correlation / weight, weight); + } + + // ... + + } // if(t0.fCalculate2DTest0) + } // if(fTest0Labels[mo][mi]) } // for(int mi=0;mi(kineVarChoice), StringKineMap(kineVarChoice).Data(), Ndim); } - // Calculate 2-p correlations with 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++) { - if (es.fEtaSeparationsSkipHarmonics[h]) { - continue; - } - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (!(qv.fQabVector[0][h][e].Rho() > 0. && qv.fQabVector[1][h][e].Rho() > 0.)) { - continue; - } - if (!(qv.fMab[0][e] > 0. && qv.fMab[1][e] > 0.)) { - continue; - } - - // calculate correlation and weights with particular eta separation: - correlation = TComplex(qv.fQabVector[0][h][e] * TComplex::Conjugate(qv.fQabVector[1][h][e])).Re(); - weight = qv.fMab[0][e] * qv.fMab[1][e]; - - // for on-the-fly and internal validation, rescale results with theoretical value: - if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { - correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); - } - - // integrated: - if (es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]) { - es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]->Fill(0.5, correlation / weight, weight); - } + int nBins = -1; - // vs. multiplicity: - if (es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]) { - es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]->Fill(ebye.fMultiplicity + 0.5, correlation / weight, weight); - } + switch (Ndim) { - // vs. centrality: - if (es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]) { - es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]->Fill(ebye.fCentrality, correlation / weight, weight); + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + if (res.fResultsPro[AFO_var]) { + nBins = res.fResultsPro[AFO_var]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below. + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s nBins = %d, kineVarChoice = %d (%s), Ndim = %d \033[0m", __FUNCTION__, nBins, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), Ndim); + } } - // vs. occupancy: - if (es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]) { - es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]->Fill(ebye.fOccupancy, correlation / weight, weight); - } + break; + } - // vs. interaction rate: - if (es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]) { - es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]->Fill(ebye.fInteractionRate, correlation / weight, weight); + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + if (res.fResultsPro2D[AFO_var]) { + nBins = (res.fResultsPro2D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro2D[AFO_var]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s nBins = %d, kineVarChoice = %d (%s), Ndim = %d \033[0m", __FUNCTION__, nBins, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), Ndim); + } } - // vs. current run duration: - if (es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]) { - es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]->Fill(ebye.fCurrentRunDuration, correlation / weight, weight); - } + break; + } - // vs. vertex z position: - if (es.fEtaSeparationsPro[h][e][AFO_VZ]) { - es.fEtaSeparationsPro[h][e][AFO_VZ]->Fill(ebye.fVz, correlation / weight, weight); + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + if (res.fResultsPro3D[AFO_var]) { + nBins = (res.fResultsPro3D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsY() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + if (tc.fVerbose) { + LOGF(info, "\033[1;31m%s nBins = %d, kineVarChoice = %d (%s), Ndim = %d \033[0m", __FUNCTION__, nBins, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), Ndim); + } } - - } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - } // for (int h = 0; h < gMaxHarmonic; h++) { - - if (tc.fVerbose) { - ExitFunction(__FUNCTION__); - } - -} // void CalculateEtaSeparations() - -//============================================================ - -void CalculateKineEtaSeparations(eAsFunctionOf AFO_variable) -{ - // Calculate differential correlations with pseudorapidity separations. - - if (tc.fVerbose) { - StartFunction(__FUNCTION__); - } - - // *) ... - eqvectorKine qvKine = eqvectorKine_N; // which eqvectorKine enum - int nBins = -1; - - switch (AFO_variable) { - case AFO_PT: { - qvKine = PTq; - nBins = res.fResultsPro[AFO_PT]->GetNbinsX(); break; } - case AFO_ETA: { - LOGF(fatal, "\033[1;31m%s at line %d : It doesn't make sense (i.e. AFO_ETA cannot be used here). \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); - break; // obsolete, but it supresses the warning - } + + // ... + default: { - LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); break; } - } // switch(AFO_variable) - // *) Insanity checks on above settings: - if (qvKine == eqvectorKine_N) { - LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); - } + } // switch (Ndim) - // *) Uniform loop over bin for all kine variables: - for (int b = 0; b < nBins; b++) { + // *) 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 + if (tc.fVerbose) { // TBI 20250701 temporary check, remove eventually + LOGF(info, "\033[1;31m%s b = %d \033[0m", __FUNCTION__, b); + Trace(__FUNCTION__, __LINE__); + } - // *) 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)); - } - } + // *) Check if this bin is overflow or underflow: + // 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) { + LOGF(info, "\033[1;31m%s no entries in bin = %d, for kineVarChoice = %d (%s). Just skipping this bin (this is most likely underflow or overflow global bin)\033[0m", __FUNCTION__, b, static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data()); + } + 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)) { + 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]); + } + } */ - // Calculate differential 2-p correlations with 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++) { - if (es.fEtaSeparationsSkipHarmonics[h]) { - continue; + // *) Re-initialize Q-vector to be q-vector in this bin: + // After that, I can call all standard Q-vector functions again: + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { + qv.fQ[h][wp] = TComplex(qv.fqvector[kineVarChoice][b][h][wp].real(), qv.fqvector[kineVarChoice][b][h][wp].imag()); // TBI 20250601 check if there is a simpler way to initialize ROOT TComplex with C++ type 'complex' } + } - for (int e = 0; e < gMaxNumberEtaSeparations; e++) { - if (!(qv.fqabVector[0][b][h][e].Rho() > 0. && qv.fqabVector[1][b][h][e].Rho() > 0.)) { - continue; - } - if (!(qv.fmab[0][b][e] > 0. && qv.fmab[1][b][e] > 0.)) { - continue; - } + if (tc.fVerbose) { // TBI 20250701 temporary check, remove eventually + Trace(__FUNCTION__, __LINE__); + } - // calculate correlation and weights with particular eta separation: - correlation = TComplex(qv.fqabVector[0][b][h][e] * TComplex::Conjugate(qv.fqabVector[1][b][h][e])).Re(); - weight = qv.fmab[0][b][e] * qv.fmab[1][b][e]; + // *) Okay, let's do transparently the differential calculus, whether it's 1D, 2D, 3D, ...: + double correlation = 0.; + double weight = 0.; + int n[gMaxCorrelator] = {0}; // array holding harmonics - // for on-the-fly and internal validation, rescale results with theoretical value: - if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { - correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); - } + for (int mo = 0; mo < gMaxCorrelator; mo++) { + for (int mi = 0; mi < gMaxIndex; mi++) { + // TBI 20240221 I do not have to loop each time all the way up to gMaxCorrelator and gMaxIndex, but nevermind now, it's not a big efficiency loss. + if (t0.fTest0Labels[mo][mi]) { + // Extract harmonics from TString, FS is " ": + for (int h = 0; h <= mo; h++) { + // cout<At(h)->GetName()).Atoi(); + delete oa; // yes, otherwise it's a memory leak + } - // finally, fill: - if (es.fEtaSeparationsPro[h][e][AFO_variable]) { - es.fEtaSeparationsPro[h][e][AFO_variable]->Fill(es.fEtaSeparationsPro[h][e][AFO_variable]->GetXaxis()->GetBinCenter(b + 1), correlation / weight, weight); - } - } - } - } // for (int b = 0; b < nBins; b++) { + if (qv.fqvectorEntries[kineVarChoice][b] < mo + 1) { + continue; + } - if (tc.fVerbose) { - ExitFunction(__FUNCTION__); - } + switch (mo + 1) // which order? yes, mo+1 + { + case 1: + correlation = One(n[0]).Re(); + weight = One(0).Re(); + break; -} // void CalculateKineEtaSeparations() + case 2: + correlation = Two(n[0], n[1]).Re(); + weight = Two(0, 0).Re(); + break; -//============================================================ + case 3: + correlation = Three(n[0], n[1], n[2]).Re(); + weight = Three(0, 0, 0).Re(); + break; -void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, const double& dPt, const double& dEta) -{ - // Fill into the nested loop containers the current particle. + case 4: + correlation = Four(n[0], n[1], n[2], n[3]).Re(); + weight = Four(0, 0, 0, 0).Re(); + break; - if (tc.fVerbose) { - StartFunction(__FUNCTION__); - } + case 5: + correlation = Five(n[0], n[1], n[2], n[3], n[4]).Re(); + weight = Five(0, 0, 0, 0, 0).Re(); + break; - if (tc.fInsanityCheckForEachParticle) { + case 6: + correlation = Six(n[0], n[1], n[2], n[3], n[4], n[5]).Re(); + weight = Six(0, 0, 0, 0, 0, 0).Re(); + break; + + case 7: + correlation = Seven(n[0], n[1], n[2], n[3], n[4], n[5], n[6]).Re(); + weight = Seven(0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 8: + correlation = Eight(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]).Re(); + weight = Eight(0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 9: + correlation = Nine(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8]).Re(); + weight = Nine(0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 10: + correlation = Ten(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9]).Re(); + weight = Ten(0, 0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 11: + correlation = Eleven(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10]).Re(); + weight = Eleven(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + case 12: + correlation = Twelve(n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9], n[10], n[11]).Re(); + weight = Twelve(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0).Re(); + break; + + default: + LOGF(fatal, "\033[1;31m%s at line %d : not supported yet: %s \n\n\033[0m", __FUNCTION__, __LINE__, t0.fTest0Labels[mo][mi]->Data()); + } // switch(mo+1) + + // *) e-b-e sanity check: + if (nl.fCalculateKineCustomNestedLoops) { + TArrayI* harmonics = new TArrayI(mo + 1); + for (int i = 0; i < mo + 1; i++) { + harmonics->SetAt(n[i], i); + } + if (!(weight > 0.)) { + LOGF(fatal, "\033[1;31m%s at line %d : is perhaps order of some requested correlator bigger than the number of particles? Correlator = %s \033[0m", __FUNCTION__, __LINE__, t0.fTest0Labels[mo][mi]->Data()); + } + double nestedLoopValue = this->CalculateKineCustomNestedLoops(harmonics, kineVarChoice, b); + PrintBinEdgesKine(kineVarChoice, b); + if (!(std::abs(nestedLoopValue) > 0.)) { + LOGF(info, " e-b-e check with CalculateKineCustomNestedLoops was NOT calculated for %d-p Test0 corr. %s, kineVarChoice (eqvectorKine) = %d (%s), bin = %d", mo + 1, t0.fTest0Labels[mo][mi]->Data(), static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), b); + } else if (std::abs(nestedLoopValue) > 0. && std::abs(correlation / weight - nestedLoopValue) > tc.fFloatingPointPrecision) { + LOGF(fatal, "\033[1;31m%s at line %d : correlator: %s \n correlation: %f \n custom loop: %f \033[0m", __FUNCTION__, __LINE__, t0.fTest0Labels[mo][mi]->Data(), correlation / weight, nestedLoopValue); + } else { + LOGF(info, "\033[1;32m ebye check (differential) with CalculateKineCustomNestedLoops is OK for %d-p Test0 corr. %s, kineVarChoice (eqvectorKine) = %d (%s), bin = %d, nParticles in this bin = %d\033[0m", mo + 1, t0.fTest0Labels[mo][mi]->Data(), static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), b, qv.fqvectorEntries[kineVarChoice][b]); + } + delete harmonics; + harmonics = NULL; + } // if(nl.fCalculateKineCustomNestedLoops) + + if (tc.fVerbose) { // TBI 20250701 temporary check, remove eventually + Trace(__FUNCTION__, __LINE__); + } + + // To ease comparison, rescale with theoretical value. Now all Test0 results shall be at 1: + if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && iv.fInternalValidationVnPsin[ePsin]) { + TArrayI* harmonics = new TArrayI(mo + 1); + for (int i = 0; i < mo + 1; i++) { + harmonics->SetAt(n[i], i); + } + TComplex theoreticalValue = TheoreticalValue(harmonics, iv.fInternalValidationVnPsin[eVn], iv.fInternalValidationVnPsin[ePsin]); + if (std::abs(theoreticalValue.Re()) > 0.) { + correlation /= theoreticalValue.Re(); + } + // TBI 20240424 for the time being, I do not do anything with imaginary part, but I could eventually... + delete harmonics; + harmonics = NULL; + } // if(fUseInternalValidation && fRescaleWithTheoreticalInput) + + if (tc.fVerbose) { // TBI 20250701 temporary check, remove eventually + Trace(__FUNCTION__, __LINE__); + } + + // Insanity check for the event weight: + if (!(weight > 0.)) { + // If it's negative, that means that sum of particle weights is smaller than "number of particles - 1" + // In that case, you can simply rescale all particle weights, so that each of them is > 1, basically recalculate weights.root files with such a rescaling. + LOGF(info, "\n\033[1;33m b = %d \033[0m\n", b); + LOGF(info, "\n\033[1;33m kineVarChoice = %d \033[0m\n", static_cast(kineVarChoice)); + LOGF(info, "\n\033[1;33m event weight = %e \033[0m\n", weight); + LOGF(info, "\n\033[1;33m sum of particle weights = %e \033[0m\n", One(0).Re()); + LOGF(info, "\n\033[1;33m correlation = %f \033[0m\n", correlation); + + switch (Ndim) { + + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + LOGF(info, "\n\033[1;33m t0.fTest0Pro[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro[mo][mi][AFO_var]->GetTitle()); + LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_var)); + break; + } + + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + LOGF(info, "\n\033[1;33m t0.fTest0Pro2D[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro2D[mo][mi][AFO_var]->GetTitle()); + LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_var)); + break; + } + + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + LOGF(info, "\n\033[1;33m t0.fTest0Pro3D[mo][mi][AFO_variable]->GetTitle() = %s \033[0m\n", t0.fTest0Pro3D[mo][mi][AFO_var]->GetTitle()); + LOGF(info, "\n\033[1;33m [mo][mi][AFO_variable] = [%d][%d][%d] \033[0m\n", mo, mi, static_cast(AFO_var)); + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (Ndim) + + LOGF(info, "\n\033[1;33m ebye.fSelectedTracks = %d \033[0m\n", ebye.fSelectedTracks); + LOGF(info, "\n\033[1;33m qv.fqvectorEntries[kineVarChoice][b] = %d \033[0m\n", qv.fqvectorEntries[kineVarChoice][b]); + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + + // Finally, fill: + switch (Ndim) { + + case 1: { + + // *) cases for which 1D vs. pt calculus is needed: + if (kineVarChoice == PTq) { + // **) vs. pt: + if (t0.fTest0Pro[mo][mi][AFO_PT]) { + t0.fTest0Pro[mo][mi][AFO_PT]->Fill(t0.fTest0Pro[mo][mi][AFO_PT]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. pt: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_PT]->GetYaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. pt vs. vz: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_VZ]) { + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_VZ]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_VZ]->GetYaxis()->GetBinCenter(b), ebye.fVz, correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // ... + + } // if (kineVarChoice == PTq) { + + // *) cases for which 1D vs. eta calculus is needed: + if (kineVarChoice == ETAq) { + // **) vs. eta: + if (t0.fTest0Pro[mo][mi][AFO_ETA]) { + t0.fTest0Pro[mo][mi][AFO_ETA]->Fill(t0.fTest0Pro[mo][mi][AFO_ETA]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. eta: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_ETA]->GetYaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. eta vs. vz: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_VZ]) { + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_VZ]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_VZ]->GetYaxis()->GetBinCenter(b), ebye.fVz, correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // ... + + } // if (kineVarChoice == ETAq) { + + // *) cases for which 1D vs. charge calculus is needed: + if (kineVarChoice == CHARGEq) { + // **) vs. charge: + if (t0.fTest0Pro[mo][mi][AFO_CHARGE]) { + t0.fTest0Pro[mo][mi][AFO_CHARGE]->Fill(t0.fTest0Pro[mo][mi][AFO_CHARGE]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + // **) vs. centrality vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]) { + t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro2D[mo][mi][AFO_CENTRALITY_CHARGE]->GetYaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // **) vs. centrality vs. vz vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_VZ_CHARGE]) { + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_VZ_CHARGE]->Fill(ebye.fCentrality, ebye.fVz, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_VZ_CHARGE]->GetZaxis()->GetBinCenter(b), correlation / weight, weight); // only for 1D kine case, I can use direcly b, because "linearized global bin" is the same as ordinary bin + } + + // ... + + } // if (kineVarChoice == CHARGEq) { + + // ... + + break; + } + + case 2: { + + // *) cases for which 2D vs. (pt,eta) calculus is needed: + if (kineVarChoice == PT_ETAq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. pt vs. eta: + if (t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]) { + t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->Fill(t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->GetXaxis()->GetBinCenter(binX), t0.fTest0Pro2D[mo][mi][AFO_PT_ETA]->GetYaxis()->GetBinCenter(binY), correlation / weight, weight); + } + + // **) vs. centrality vs. pt vs. eta: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]) { + // Remark: I have to re-use binX, binY, binZ obtained from t0.fTest0Pro2D[mo][mi][AFO_PT_ETA] above, because I am looping for "case 2:" here over global bin number of + // t0.fTest0Pro2D[mo][mi][AFO_PT_ETA], not of t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA] + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]->GetYaxis()->GetBinCenter(binX), t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_ETA]->GetZaxis()->GetBinCenter(binY), correlation / weight, weight); // yes, y-axis of this histogram is x-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_ETA], and similarly z-axis here is y-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_ETA] + } + + // ... + + } // if (kineVarChoice == PT_ETAq) + + // *) cases for which 2D vs. (pt,charge) calculus is needed: + if (kineVarChoice == PT_CHARGEq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. pt vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]) { + t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->Fill(t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->GetXaxis()->GetBinCenter(binX), t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE]->GetYaxis()->GetBinCenter(binY), correlation / weight, weight); + } + // **) vs. centrality vs. pt vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]) { + // Remark: I have to re-use binX, binY, binZ obtained from t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE] above, because I am looping for "case 2:" here over global bin number of + // t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE], not of t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE] + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]->GetYaxis()->GetBinCenter(binX), t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_PT_CHARGE]->GetZaxis()->GetBinCenter(binY), correlation / weight, weight); // yes, y-axis of this histogram is x-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE], and similarly z-axis here is y-axis of t0.fTest0Pro2D[mo][mi][AFO_PT_CHARGE] + } + + // ... + + } // if (kineVarChoice == PT_CHARGEq) + + // *) cases for which 2D vs. (eta,charge) calculus is needed: + if (kineVarChoice == ETA_CHARGEq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. eta vs. charge: + if (t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]) { + t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->Fill(t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->GetXaxis()->GetBinCenter(binX), t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE]->GetYaxis()->GetBinCenter(binY), correlation / weight, weight); + } + // **) vs. centrality vs. eta vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]) { + // Remark: I have to re-use binX, binY, binZ obtained from t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE] above, because I am looping for "case 2:" here over global bin number of + // t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE], not of t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE] + t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]->Fill(ebye.fCentrality, t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]->GetYaxis()->GetBinCenter(binX), t0.fTest0Pro3D[mo][mi][AFO_CENTRALITY_ETA_CHARGE]->GetZaxis()->GetBinCenter(binY), correlation / weight, weight); // yes, y-axis of this histogram is x-axis of t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE], and similarly z-axis here is y-axis of t0.fTest0Pro2D[mo][mi][AFO_ETA_CHARGE] + } + + // ... + + } // if (kineVarChoice == ETA_CHARGEq) + + // ... + + break; + } + + case 3: { + + // *) cases for which 3D vs. (pt,eta,charge) calculus is needed: + if (kineVarChoice == PT_ETA_CHARGEq) { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetBinXYZ(b, binX, binY, binZ); + + // **) vs. pt vs. eta vs. charge: + if (t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]) { + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->Fill(t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetXaxis()->GetBinCenter(binX), + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetYaxis()->GetBinCenter(binY), + t0.fTest0Pro3D[mo][mi][AFO_PT_ETA_CHARGE]->GetZaxis()->GetBinCenter(binZ), + correlation / weight, weight); + } + } + + // ... + + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (Ndim) + + } // if(fTest0Labels[mo][mi]) + } // for(int mi=0;mi kineVarChoice (eqvectorKine) = %d, global (ordinary) bin %d <=> (%f, %f)", static_cast(kineVarChoice), bin, res.fResultsPro[AfoKineMap1D(kineVarChoice)]->GetBinLowEdge(bin), res.fResultsPro[AfoKineMap1D(kineVarChoice)]->GetBinLowEdge(bin + 1)); + + break; + } + + // 2D: + case PT_ETAq: + case PT_CHARGEq: + case ETA_CHARGEq: { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; // dummy for 2D case + res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetBinXYZ(bin, binX, binY, binZ); + + LOGF(info, " => kineVarChoice (eqvectorKine) = %d, global bin %d = (%d, %d) <=> (%f, %f) x (%f, %f)", static_cast(kineVarChoice), bin, binX, binY, res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX), res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX + 1), res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY), res.fResultsPro2D[AfoKineMap2D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY + 1)); + + break; + } + + // 3D: + case PT_ETA_CHARGEq: { + + // transfer global bin b into (binX, binY, binZ): + int binX = -1; + int binY = -1; + int binZ = -1; + res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetBinXYZ(bin, binX, binY, binZ); + + LOGF(info, " => kineVarChoice (eqvectorKine) = %d, global bin %d = (%d, %d, %d) <=> (%f, %f) x (%f, %f) x (%f, %f)", static_cast(kineVarChoice), bin, binX, binY, binZ, res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetXaxis()->GetBinLowEdge(binX + 1), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetYaxis()->GetBinLowEdge(binY + 1), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetZaxis()->GetBinLowEdge(binZ), res.fResultsPro3D[AfoKineMap3D(kineVarChoice)]->GetZaxis()->GetBinLowEdge(binZ + 1)); + + 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)); + break; + } + + } // switch(AFO_variable) + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void PrintBinEdgesKine() + +//============================================================ + +void CalculateEtaSeparations() +{ + // Calculate correlations with pseudorapidity separations. + + // Remark: this is a port and generalization of void AliFlowAnalysisWithMultiparticleCorrelations::CalculateEtaGaps(AliFlowEventSimple *anEvent) + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // Calculate 2-p correlations with 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++) { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (!(qv.fQabVector[0][h][e].Rho() > 0. && qv.fQabVector[1][h][e].Rho() > 0.)) { + continue; + } + if (!(qv.fMab[0][e] > 0. && qv.fMab[1][e] > 0.)) { + continue; + } + + // calculate correlation and weights with particular eta separation: + correlation = TComplex(qv.fQabVector[0][h][e] * TComplex::Conjugate(qv.fQabVector[1][h][e])).Re(); + weight = qv.fMab[0][e] * qv.fMab[1][e]; + + // for on-the-fly and internal validation, rescale results with theoretical value: + if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { + correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); + } + + // integrated: + if (es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]) { + es.fEtaSeparationsPro[h][e][AFO_INTEGRATED]->Fill(0.5, correlation / weight, weight); + } + + // vs. multiplicity: + if (es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]) { + es.fEtaSeparationsPro[h][e][AFO_MULTIPLICITY]->Fill(ebye.fMultiplicity + 0.5, correlation / weight, weight); + } + + // vs. centrality: + if (es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]) { + es.fEtaSeparationsPro[h][e][AFO_CENTRALITY]->Fill(ebye.fCentrality, correlation / weight, weight); + } + + // vs. occupancy: + if (es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]) { + es.fEtaSeparationsPro[h][e][AFO_OCCUPANCY]->Fill(ebye.fOccupancy, correlation / weight, weight); + } + + // vs. interaction rate: + if (es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]) { + es.fEtaSeparationsPro[h][e][AFO_INTERACTIONRATE]->Fill(ebye.fInteractionRate, correlation / weight, weight); + } + + // vs. current run duration: + if (es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]) { + es.fEtaSeparationsPro[h][e][AFO_CURRENTRUNDURATION]->Fill(ebye.fCurrentRunDuration, correlation / weight, weight); + } + + // vs. vertex z position: + if (es.fEtaSeparationsPro[h][e][AFO_VZ]) { + es.fEtaSeparationsPro[h][e][AFO_VZ]->Fill(ebye.fVz, correlation / weight, weight); + } + + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + } // for (int h = 0; h < gMaxHarmonic; h++) { + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void CalculateEtaSeparations() + +//============================================================ + +void CalculateKineEtaSeparationsNdim(eqvectorKine kineVarChoice, int Ndim) +{ + // Calculate analytically N-dimensional kine eta separations from differential q-vectors. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // This is a replacement for the legacy function CalculateKineEtaSeparations(...), which is as of 20250620 deemed obsolete. + // Remember that here I changed design, and pass enum eqvectorKine as an argument, not any longer enum eAsFunctionOf. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + int nBins = -1; + + switch (Ndim) { + + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + if (res.fResultsPro[AFO_var]) { + nBins = res.fResultsPro[AFO_var]->GetNbinsX() + 2; // + 2 means that I take into account overflow and underflow, then skip it in the loop below. + } + + break; + } + + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + if (res.fResultsPro2D[AFO_var]) { + nBins = (res.fResultsPro2D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro2D[AFO_var]->GetNbinsY() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + + break; + } + + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + if (res.fResultsPro3D[AFO_var]) { + nBins = (res.fResultsPro3D[AFO_var]->GetNbinsX() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsY() + 2) * (res.fResultsPro3D[AFO_var]->GetNbinsZ() + 2); // + 2 means that I take into account overflow and underflow, then skip it in the loop below + } + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (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: + double correlation = 0.; + double weight = 0.; + for (int h = 0; h < gMaxHarmonic; h++) { + if (es.fEtaSeparationsSkipHarmonics[h]) { + continue; + } + + 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.)) { + continue; + } + if (!(qv.fmab[0][kineVarChoice][b][e] > 0. && qv.fmab[1][kineVarChoice][b][e] > 0.)) { + continue; + } + + // calculate correlation and weights with particular eta separation: + correlation = (qv.fqabVector[0][kineVarChoice][b][h][e] * std::conj(qv.fqabVector[1][kineVarChoice][b][h][e])).real(); + // Remark: this was the legacy code, just in case I would still need it: + // correlation = TComplex(qv.fqabVector[0][kineVarChoice][b][h][e] * TComplex::Conjugate(qv.fqabVector[1][kineVarChoice][b][h][e])).Re(); + weight = qv.fmab[0][kineVarChoice][b][e] * qv.fmab[1][kineVarChoice][b][e]; + + // for on-the-fly and internal validation, rescale results with theoretical value: + if (iv.fUseInternalValidation && iv.fRescaleWithTheoreticalInput && iv.fInternalValidationVnPsin[eVn] && std::abs(iv.fInternalValidationVnPsin[eVn]->GetAt(h)) > 0.) { + correlation /= std::pow(iv.fInternalValidationVnPsin[eVn]->GetAt(h), 2.); + } + + // finally, fill 1D case: + if (es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]) { + es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->Fill(es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->GetXaxis()->GetBinCenter(b), correlation / weight, weight); + } + + // TBI 20250620 I need to add support eventually also for 2D and 3D cases. + } + } + } // for (int b = 0; b < nBins; b++) + + // *) Quick insanity check: I shall never have any entry in underflow (bin = 0) or overflow (bin = nBins -1) in es.fEtaSeparationsPro, otherwise some cuts were bypassed: + if (tc.fDoAdditionalInsanityChecks) { + for (int h = 0; h < gMaxHarmonic; h++) { + for (int e = 0; e < gMaxNumberEtaSeparations; e++) { + if (es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)] && std::abs(es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->GetBinContent(0)) > 0.) { + LOGF(fatal, "\033[1;31m%s at line %d : underflow is not empty \033[0m", __FUNCTION__, __LINE__); + } + if (es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)] && std::abs(es.fEtaSeparationsPro[h][e][AfoKineMap1D(kineVarChoice)]->GetBinContent(nBins - 1)) > 0.) { + LOGF(fatal, "\033[1;31m%s at line %d : overflow is not empty \033[0m", __FUNCTION__, __LINE__); + } + } + } + } // if (tc.fDoAdditionalInsanityChecks) + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void CalculateKineEtaSeparationsNdim(eqvectorKine kineVarChoice, int Ndim) + +//============================================================ + +void FillNestedLoopsContainers(const int& particleIndex, const double& dPhi, const double& dPt, const double& dEta) +{ + // Fill into the nested loop containers the current particle. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + if (tc.fInsanityCheckForEachParticle) { if (particleIndex < 0) { LOGF(fatal, "\033[1;31m%s at line %d : particleIndex = %d\033[0m", __FUNCTION__, __LINE__, particleIndex); } @@ -11349,19 +13092,6 @@ void CalculateNestedLoops() LOGF(info, " ebye.fSelectedTracks = %d", ebye.fSelectedTracks); int nParticles = ebye.fSelectedTracks; - /* TBI 20220823 enable the lines below eventually - if(fUseFixedNumberOfRandomlySelectedTracks) - { - nParticles = 0; - for(int i=0;iGetSize();i++) - { - if(std::abs(ftaNestedLoops[0]->GetAt(i)) > 0. && - std::abs(ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} - } - } - cout<<"nParticles = "<GetNbinsX(); nBinsNL = nl.fNestedLoopsPro[0][0][v]->GetNbinsX(); @@ -12085,33 +13815,28 @@ void SetDiffWeightsSparse(THnSparseF* const sparse, eDiffWeightCategory dwc) // Finally, add to corresponding TList: pw.fWeightsList->Add(pw.fDiffWeightsSparse[dwc]); - /* - -TBI-today - - // 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__); - } - - */ + // 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__); + // } } // void SetDiffWeightsSparse(THnSparseF* const sparse) @@ -12678,52 +14403,50 @@ THnSparseF* GetSparseHistogramWithWeights(const char* filePath, const char* runN // hist->SetTitle(Form("%s, %.2f < %s < %.2f", filePath, min, lVariableName, max)); - /* - // *) insanity check for differential weights => check if boundaries of current bin are the same as bin boundaries for which these weights were calculated. - // This way I ensure that weights correspond to same kinematic cuts and binning as in current analysis. - // Current example format which was set in MakeWeights.C: someString(s), min < kinematic-variable-name < max - // Algorithm: IFS is " " and I take (N-1)th and (N-5)th entry: - TObjArray* oa = TString(hist->GetTitle()).Tokenize(" "); - if (!oa) { - LOGF(fatal, "in function \033[1;31m%s at line %d \n hist->GetTitle() = %s\033[0m", __FUNCTION__, __LINE__, hist->GetTitle()); - } - int nEntries = oa->GetEntries(); - - // I need to figure out corresponding variable from results histograms and its formatting: - eAsFunctionOf AFO = eAsFunctionOf_N; - const char* lVariableName = ""; - if (TString(variable).EqualTo("phipt")) { - AFO = AFO_PT; - lVariableName = FancyFormatting("Pt"); - } else if (TString(variable).EqualTo("phieta")) { - AFO = AFO_ETA; - lVariableName = FancyFormatting("Eta"); - } else { - LOGF(fatal, "\033[1;31m%s at line %d : name = %s is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(variable)); - } - - // Get min and max value for bin, stored locally: - float min = res.fResultsPro[AFO]->GetBinLowEdge(bin + 1); - float max = res.fResultsPro[AFO]->GetBinLowEdge(bin + 2); - if (min > max) { - LOGF(fatal, "\033[1;33m min = %f, max = %f, res.fResultsPro[AFO]->GetName() = %s\033[0m", min, max, res.fResultsPro[AFO]->GetName()); - } - - // Compare with min and max value stored in external weights.root file using MakeWeights.C: - if (!(std::abs(TString(oa->At(nEntries - 1)->GetName()).Atof() - max) < tc.fFloatingPointPrecision)) { - LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); - LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in upper bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 1)->GetName()).Atof(), max); - } - if (!(std::abs(TString(oa->At(nEntries - 5)->GetName()).Atof() - min) < tc.fFloatingPointPrecision)) { - LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); - LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in lower bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 5)->GetName()).Atof(), min); - } - delete oa; // yes, otherwise it's a memory leak - - // *) final settings and cosmetics: - hist->SetDirectory(0); - - */ + // TBI 20250530 check this code snippet - do I need it? + // // *) insanity check for differential weights => check if boundaries of current bin are the same as bin boundaries for which these weights were calculated. + // // This way I ensure that weights correspond to same kinematic cuts and binning as in current analysis. + // // Current example format which was set in MakeWeights.C: someString(s), min < kinematic-variable-name < max + // // Algorithm: IFS is " " and I take (N-1)th and (N-5)th entry: + // TObjArray* oa = TString(hist->GetTitle()).Tokenize(" "); + // if (!oa) { + // LOGF(fatal, "in function \033[1;31m%s at line %d \n hist->GetTitle() = %s\033[0m", __FUNCTION__, __LINE__, hist->GetTitle()); + // } + // int nEntries = oa->GetEntries(); + // + // // I need to figure out corresponding variable from results histograms and its formatting: + // eAsFunctionOf AFO = eAsFunctionOf_N; + // const char* lVariableName = ""; + // if (TString(variable).EqualTo("phipt")) { + // AFO = AFO_PT; + // lVariableName = FancyFormatting("Pt"); + // } else if (TString(variable).EqualTo("phieta")) { + // AFO = AFO_ETA; + // lVariableName = FancyFormatting("Eta"); + // } else { + // LOGF(fatal, "\033[1;31m%s at line %d : name = %s is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(variable)); + // } + // + // // Get min and max value for bin, stored locally: + // float min = res.fResultsPro[AFO]->GetBinLowEdge(bin + 1); + // float max = res.fResultsPro[AFO]->GetBinLowEdge(bin + 2); + // if (min > max) { + // LOGF(fatal, "\033[1;33m min = %f, max = %f, res.fResultsPro[AFO]->GetName() = %s\033[0m", min, max, res.fResultsPro[AFO]->GetName()); + // } + // + // // Compare with min and max value stored in external weights.root file using MakeWeights.C: + // if (!(std::abs(TString(oa->At(nEntries - 1)->GetName()).Atof() - max) < tc.fFloatingPointPrecision)) { + // LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); + // LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in upper bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 1)->GetName()).Atof(), max); + // } + // if (!(std::abs(TString(oa->At(nEntries - 5)->GetName()).Atof() - min) < tc.fFloatingPointPrecision)) { + // LOGF(info, "\033[1;33m hist->GetTitle() = %s, res.fResultsPro[AFO]->GetName() = %s\033[0m", hist->GetTitle(), res.fResultsPro[AFO]->GetName()); + // LOGF(fatal, "in function \033[1;31m%s at line %d : mismatch in lower bin boundaries \n from title = %f , local = %f\033[0m", __FUNCTION__, __LINE__, TString(oa->At(nEntries - 5)->GetName()).Atof(), min); + // } + // delete oa; // yes, otherwise it's a memory leak + // + // // *) final settings and cosmetics: + // hist->SetDirectory(0); // 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)); @@ -12873,20 +14596,6 @@ TH1D* GetHistogramWithCentralityWeights(const char* filePath, const char* runNum LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } - /* - // xxxxxxxxxxxx TBI 20241124 remove this code - - hist = reinterpret_cast(centralityWeightsFile->Get("FT0C_Default list name")); // TBI 20241122 temporary workaround - if (!hist) { - Exit(); - } - hist->SetDirectory(0); - hist->SetTitle(Form("%s, %s", filePath, runNumber)); // I have to do it here, because only here I have "filePath" available - return hist; - - // xxxxxxxxxxxx - */ - centralityWeightsFile->GetObject("ccdb_object", baseList); // TBI 20231008 for simplicity, hardwired name // of base TList is "ccdb_object" also for // local case, see if I need to change this @@ -12985,6 +14694,13 @@ TObjArray* GetDefaultObjArrayWithLabels(const char* whichDefaultLabels) TObjString* objstr = new TObjString(labels[l].Data()); arr->Add(objstr); } + } else if (TString(whichDefaultLabels).EqualTo("mixedEventsStudy")) { + const int nLabels = 3; + TString labels[nLabels] = {"2", "-2", "2 -2"}; + for (int l = 0; l < nLabels; l++) { + TObjString* objstr = new TObjString(labels[l].Data()); + arr->Add(objstr); + } } else if (TString(whichDefaultLabels).EqualTo("scan2p")) { const int nLabels = 6; TString labels[nLabels] = {"1 -1", "2 -2", "3 -3", "4 -4", "5 -5", "6 -6"}; @@ -12992,6 +14708,13 @@ TObjArray* GetDefaultObjArrayWithLabels(const char* whichDefaultLabels) TObjString* objstr = new TObjString(labels[l].Data()); arr->Add(objstr); } + } else if (TString(whichDefaultLabels).EqualTo("projections")) { // use this set to test projections when calculating multi-dimensional weights + const int nLabels = 10; + TString labels[nLabels] = {"1", "2", "3", "1 -1", "2 -2", "3 -3", "3 -1 -2", "1 1 -1 -1", "2 2 -2 -2", "3 3 -3 -3"}; + for (int l = 0; l < nLabels; l++) { + TObjString* objstr = new TObjString(labels[l].Data()); + arr->Add(objstr); + } } else if (TString(whichDefaultLabels).EqualTo("standard")) { const int nLabels = 7; TString labels[nLabels] = {"1 -1", "2 -2", "3 -3", "2 1 -1 -2", "3 1 -1 -3", "3 2 -2 -3", "3 2 1 -1 -2 -3"}; @@ -13798,6 +15521,19 @@ double WeightFromSparse(const double& dPhi, const double& dPt, const double& dEt // 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), // 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 + // 1,0 => 1 + // 2,0 => 2 + // 3,0 => 3 + // 0,1 => 4 + // 1,1 => 5 + // ... + // 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. + double weight = pw.fDiffWeightsSparse[dwc]->GetBinContent(bin); if (tc.fVerbose) { @@ -13814,6 +15550,8 @@ double DiffWeight(const double& valueY, const double& valueX, eqvectorKine varia { // Determine differential particle weight y(x). For the time being, "y = phi" always, but this can be generalized. + // TBI 20250520 This function is now obsolete, use WeightFromSparse(...) instead. + if (tc.fVerbose) { StartFunction(__FUNCTION__); } @@ -14392,16 +16130,6 @@ double CalculateCustomNestedLoops(TArrayI* harmonics) } int nParticles = ebye.fSelectedTracks; - /* TBI 20231108 enable eventually - if(fUseFixedNumberOfRandomlySelectedParticles) - { - nParticles = 0; - for(int i=0;iGetSize();i++) - { - if(std::abs(nl.ftaNestedLoops[0]->GetAt(i)) > 0. && std::abs(nl.ftaNestedLoops[1]->GetAt(i)) > 0.){nParticles++;} - } - } - */ // a) Determine the order of correlator; int order = harmonics->GetSize(); @@ -14590,6 +16318,10 @@ double CalculateCustomNestedLoops(TArrayI* harmonics) double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_variable, int bin) { + // !!! OBSOLETE FUNCTION !!! + + LOGF(info, "\033[1;33m%s at line %d: !!!! WARNING !!!! As of 20250529, this is an obsolete function, use double CalculateKineCustomNestedLoops(TArrayI* harmonics, eqvectorKine kineVarChoice, int bin) instead !!!! WARNING !!!! \033[0m", __FUNCTION__, __LINE__); + // For the specified harmonics, kine variable, and bin, get the correlation from nested loops. // Order of correlator is the number of harmonics, i.e. the number of elements in an array. @@ -14619,37 +16351,265 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari kineVarName = "eta"; break; } + case AFO_CHARGE: { + qvKine = CHARGEq; + kineVarName = "charge"; + break; + } default: { LOGF(fatal, "\033[1;31m%s at line %d : This AFO_variable = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable)); break; } } // switch(AFO_variable) - // *) Insanity checks on above settings: - if (qvKine == eqvectorKine_N) { - LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + // *) Insanity checks on above settings: + if (qvKine == eqvectorKine_N) { + LOGF(fatal, "\033[1;31m%s at line %d : qvKine == eqvectorKine_N => add some more entries to the case statement \033[0m", __FUNCTION__, __LINE__); + } + + if (0 > bin || res.fResultsPro[AFO_variable]->GetNbinsX() < bin) { // this 'bin' starts from 0, i.e. this is an array 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 => AFO_variable = %d, bin = %d\033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + } + + // Get the number of particles in this kine bin: + int nParticles = 0; + for (int i = 0; i < nl.ftaNestedLoopsKine[qvKine][bin][0]->GetSize(); i++) { + if (std::abs(nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i)) > 0.) { + nParticles++; + } + } + + // 'qvKine' is enum eqvectorKine: + if (!res.fResultsPro[AFO_variable]) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_variable = %d, bin = %d \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + } + + LOGF(info, " Processing qvKine = %d (vs. %s), nParticles in this kine bin = %d, bin range = [%f,%f) ....", static_cast(qvKine), kineVarName.Data(), nParticles, res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 1), res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 2)); + + // a) Determine the order of correlator; + int order = harmonics->GetSize(); + if (0 == order || order > gMaxCorrelator) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); + } + if (order > nParticles) { + LOGF(info, " There is no enough particles in this bin to calculate the requested correlator"); + return 0.; // TBI 20240405 Is this really safe here? Re-think... + } + if (nl.fMaxNestedLoop > 0 && nl.fMaxNestedLoop < order) { + LOGF(info, " nl.fMaxNestedLoop > 0 && nl.fMaxNestedLoop < order, where nl.fMaxNestedLoop = %d, order = %d", nl.fMaxNestedLoop, order); + return 0.; // TBI 20240405 Is this really safe here? Re-think... + } + + // b) Custom nested loop: + TProfile* profile = new TProfile("profile", "", 1, 0., 1.); // helper profile to get all averages automatically + // profile->Sumw2(); + double value = 0.; // cos of current multiplet + double weight = 1.; // weight of current multiplet + for (int i1 = 0; i1 < nParticles; i1++) { + double dPhi1 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i1); + double dW1 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i1); + if (1 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1); + weight = dW1; + profile->Fill(0.5, value, weight); + continue; + } + for (int i2 = 0; i2 < nParticles; i2++) { + if (i2 == i1) { + continue; + } + double dPhi2 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i2); + double dW2 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i2); + if (2 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2); + weight = dW1 * dW2; + profile->Fill(0.5, value, weight); + continue; + } + for (int i3 = 0; i3 < nParticles; i3++) { + if (i3 == i1 || i3 == i2) { + continue; + } + double dPhi3 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i3); + double dW3 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i3); + if (3 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3); + weight = dW1 * dW2 * dW3; + profile->Fill(0.5, value, weight); + continue; + } + for (int i4 = 0; i4 < nParticles; i4++) { + if (i4 == i1 || i4 == i2 || i4 == i3) { + continue; + } + double dPhi4 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i4); + double dW4 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i4); + if (4 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4); + weight = dW1 * dW2 * dW3 * dW4; + profile->Fill(0.5, value, weight); + continue; + } + for (int i5 = 0; i5 < nParticles; i5++) { + if (i5 == i1 || i5 == i2 || i5 == i3 || i5 == i4) { + continue; + } + double dPhi5 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i5); + double dW5 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i5); + if (5 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5); + weight = dW1 * dW2 * dW3 * dW4 * dW5; + profile->Fill(0.5, value, weight); + continue; + } + for (int i6 = 0; i6 < nParticles; i6++) { + if (i6 == i1 || i6 == i2 || i6 == i3 || i6 == i4 || i6 == i5) { + continue; + } + double dPhi6 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i6); + double dW6 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i6); + if (6 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6; + profile->Fill(0.5, value, weight); + continue; + } + for (int i7 = 0; i7 < nParticles; i7++) { + if (i7 == i1 || i7 == i2 || i7 == i3 || i7 == i4 || i7 == i5 || i7 == i6) { + continue; + } + double dPhi7 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i7); + double dW7 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i7); + if (7 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7; + profile->Fill(0.5, value, weight); + continue; + } + for (int i8 = 0; i8 < nParticles; i8++) { + if (i8 == i1 || i8 == i2 || i8 == i3 || i8 == i4 || i8 == i5 || i8 == i6 || i8 == i7) { + continue; + } + double dPhi8 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i8); + double dW8 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i8); + if (8 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8; + profile->Fill(0.5, value, weight); + continue; + } + for (int i9 = 0; i9 < nParticles; i9++) { + if (i9 == i1 || i9 == i2 || i9 == i3 || i9 == i4 || i9 == i5 || i9 == i6 || i9 == i7 || i9 == i8) { + continue; + } + double dPhi9 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i9); + double dW9 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i9); + if (9 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9; + profile->Fill(0.5, value, weight); + continue; + } + for (int i10 = 0; i10 < nParticles; i10++) { + if (i10 == i1 || i10 == i2 || i10 == i3 || i10 == i4 || i10 == i5 || i10 == i6 || i10 == i7 || i10 == i8 || i10 == i9) { + continue; + } + double dPhi10 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i10); + double dW10 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i10); + if (10 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10; + profile->Fill(0.5, value, weight); + continue; + } + for (int i11 = 0; i11 < nParticles; i11++) { + if (i11 == i1 || i11 == i2 || i11 == i3 || i11 == i4 || i11 == i5 || i11 == i6 || i11 == i7 || i11 == i8 || i11 == i9 || i11 == i10) { + continue; + } + double dPhi11 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i11); + double dW11 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i11); + if (11 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11; + profile->Fill(0.5, value, weight); + continue; + } + for (int i12 = 0; i12 < nParticles; i12++) { + if (i12 == i1 || i12 == i2 || i12 == i3 || i12 == i4 || i12 == i5 || i12 == i6 || i12 == i7 || i12 == i8 || i12 == i9 || i12 == i10 || i12 == i11) { + continue; + } + double dPhi12 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i12); + double dW12 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i12); + if (12 == order) { + value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11 + harmonics->GetAt(11) * dPhi12); + weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11 * dW12; + profile->Fill(0.5, value, weight); + continue; + } + + // ... it's easy to continue the above pattern here + + } // for(int i12=0; i12GetBinContent(1); + delete profile; + profile = NULL; + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + return finalValue; + +} // double CalculateKineCustomNestedLoops(TArrayI *harmonics, eAsFunctionOf AFO_variable, int bin) + +//============================================================ + +double CalculateKineCustomNestedLoops(TArrayI* harmonics, eqvectorKine kineVarChoice, int bin) +{ + // For the specified harmonics, kine variable, and bin, get the correlation from nested loops. + // Order of correlator is the number of harmonics, i.e. the number of elements in an array. + + // a) Determine the order of correlator; + // b) Custom nested loop; + // c) Return value. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); } - if (0 > bin || res.fResultsPro[AFO_variable]->GetNbinsX() < bin) { // this 'bin' starts from 0, i.e. this is an array 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 => AFO_variable = %d, bin = %d\033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + if (!harmonics) { + LOGF(fatal, "\033[1;31m%s at line %d\033[0m", __FUNCTION__, __LINE__); } + // TBI 20250529 add protection for b in underflow or overflow + // Get the number of particles in this kine bin: int nParticles = 0; - for (int i = 0; i < nl.ftaNestedLoopsKine[qvKine][bin][0]->GetSize(); i++) { - if (std::abs(nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i)) > 0.) { + for (int i = 0; i < nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetSize(); i++) { + if (std::abs(nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i)) > 0.) { nParticles++; } } - // 'qvKine' is enum eqvectorKine: - if (!res.fResultsPro[AFO_variable]) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_variable = %d, bin = %d \033[0m", __FUNCTION__, __LINE__, static_cast(AFO_variable), bin); + // It doesn't hurt to do here insanity check on the number of particles, in case I have already calculated it independently when calculating diff. q-vectors: + if (qv.fCalculateqvectorsKineAny && qv.fqvectorEntries[kineVarChoice][bin] > 0) { // TBI 20250602 I think this chained condition is ok, but re-think nevertheless + if (!(nParticles == qv.fqvectorEntries[kineVarChoice][bin])) { + LOGF(fatal, "\033[1;31m%s at line %d : nParticles = %d, qv.fqvectorEntries[kineVarChoice][bin] = %d, kineVarChoices = %d (%s), bin = %d\033[0m", __FUNCTION__, __LINE__, nParticles, qv.fqvectorEntries[kineVarChoice][bin], static_cast(kineVarChoice), StringKineMap(kineVarChoice).Data(), bin); + } } - LOGF(info, " Processing qvKine = %d (vs. %s), nParticles in this kine bin = %d, bin range = [%f,%f) ....", static_cast(qvKine), kineVarName.Data(), nParticles, res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 1), res.fResultsPro[AFO_variable]->GetBinLowEdge(bin + 2)); - // a) Determine the order of correlator; int order = harmonics->GetSize(); if (0 == order || order > gMaxCorrelator) { @@ -14670,8 +16630,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari double value = 0.; // cos of current multiplet double weight = 1.; // weight of current multiplet for (int i1 = 0; i1 < nParticles; i1++) { - double dPhi1 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i1); - double dW1 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i1); + double dPhi1 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i1); + double dW1 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i1); if (1 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1); weight = dW1; @@ -14682,8 +16642,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i2 == i1) { continue; } - double dPhi2 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i2); - double dW2 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i2); + double dPhi2 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i2); + double dW2 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i2); if (2 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2); weight = dW1 * dW2; @@ -14694,8 +16654,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i3 == i1 || i3 == i2) { continue; } - double dPhi3 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i3); - double dW3 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i3); + double dPhi3 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i3); + double dW3 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i3); if (3 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3); weight = dW1 * dW2 * dW3; @@ -14706,8 +16666,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i4 == i1 || i4 == i2 || i4 == i3) { continue; } - double dPhi4 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i4); - double dW4 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i4); + double dPhi4 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i4); + double dW4 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i4); if (4 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4); weight = dW1 * dW2 * dW3 * dW4; @@ -14718,8 +16678,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i5 == i1 || i5 == i2 || i5 == i3 || i5 == i4) { continue; } - double dPhi5 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i5); - double dW5 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i5); + double dPhi5 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i5); + double dW5 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i5); if (5 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5); weight = dW1 * dW2 * dW3 * dW4 * dW5; @@ -14730,8 +16690,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i6 == i1 || i6 == i2 || i6 == i3 || i6 == i4 || i6 == i5) { continue; } - double dPhi6 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i6); - double dW6 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i6); + double dPhi6 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i6); + double dW6 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i6); if (6 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6; @@ -14742,8 +16702,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i7 == i1 || i7 == i2 || i7 == i3 || i7 == i4 || i7 == i5 || i7 == i6) { continue; } - double dPhi7 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i7); - double dW7 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i7); + double dPhi7 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i7); + double dW7 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i7); if (7 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7; @@ -14754,8 +16714,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i8 == i1 || i8 == i2 || i8 == i3 || i8 == i4 || i8 == i5 || i8 == i6 || i8 == i7) { continue; } - double dPhi8 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i8); - double dW8 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i8); + double dPhi8 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i8); + double dW8 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i8); if (8 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8; @@ -14766,8 +16726,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i9 == i1 || i9 == i2 || i9 == i3 || i9 == i4 || i9 == i5 || i9 == i6 || i9 == i7 || i9 == i8) { continue; } - double dPhi9 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i9); - double dW9 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i9); + double dPhi9 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i9); + double dW9 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i9); if (9 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9; @@ -14778,8 +16738,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i10 == i1 || i10 == i2 || i10 == i3 || i10 == i4 || i10 == i5 || i10 == i6 || i10 == i7 || i10 == i8 || i10 == i9) { continue; } - double dPhi10 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i10); - double dW10 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i10); + double dPhi10 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i10); + double dW10 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i10); if (10 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10; @@ -14790,8 +16750,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i11 == i1 || i11 == i2 || i11 == i3 || i11 == i4 || i11 == i5 || i11 == i6 || i11 == i7 || i11 == i8 || i11 == i9 || i11 == i10) { continue; } - double dPhi11 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i11); - double dW11 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i11); + double dPhi11 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i11); + double dW11 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i11); if (11 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11; @@ -14802,8 +16762,8 @@ double CalculateKineCustomNestedLoops(TArrayI* harmonics, eAsFunctionOf AFO_vari if (i12 == i1 || i12 == i2 || i12 == i3 || i12 == i4 || i12 == i5 || i12 == i6 || i12 == i7 || i12 == i8 || i12 == i9 || i12 == i10 || i12 == i11) { continue; } - double dPhi12 = nl.ftaNestedLoopsKine[qvKine][bin][0]->GetAt(i12); - double dW12 = nl.ftaNestedLoopsKine[qvKine][bin][1]->GetAt(i12); + double dPhi12 = nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->GetAt(i12); + double dW12 = nl.ftaNestedLoopsKine[kineVarChoice][bin][1]->GetAt(i12); if (12 == order) { value = std::cos(harmonics->GetAt(0) * dPhi1 + harmonics->GetAt(1) * dPhi2 + harmonics->GetAt(2) * dPhi3 + harmonics->GetAt(3) * dPhi4 + harmonics->GetAt(4) * dPhi5 + harmonics->GetAt(5) * dPhi6 + harmonics->GetAt(6) * dPhi7 + harmonics->GetAt(7) * dPhi8 + harmonics->GetAt(8) * dPhi9 + harmonics->GetAt(9) * dPhi10 + harmonics->GetAt(10) * dPhi11 + harmonics->GetAt(11) * dPhi12); weight = dW1 * dW2 * dW3 * dW4 * dW5 * dW6 * dW7 * dW8 * dW9 * dW10 * dW11 * dW12; @@ -15556,226 +17516,520 @@ void PrintCutCounterContent() } LOGF(info, "bin = %d => %s : %d", bin, ec.fEventCutCounterHist[rs][cc]->GetXaxis()->GetBinLabel(bin), static_cast(ec.fEventCutCounterHist[rs][cc]->GetBinContent(bin))); } - } // for (int cc = 0; cc < eCutCounter_N; cc++) // enum eCutCounter - } // for (int rs = 0; rs < 2; rs++) // reco/sim + } // for (int cc = 0; cc < eCutCounter_N; cc++) // enum eCutCounter + } // for (int rs = 0; rs < 2; rs++) // reco/sim + + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + +} // void PrintCutCounterContent() + +//============================================================ + +void Trace(const char* functionName, int lineNumber) +{ + // A simple utility wrapper. Use only during debugging, sprinkle calls to this function here and there, as follows + // Trace(__FUNCTION__, __LINE__); + + LOGF(info, "\033[1;32m%s .... line %d\033[0m", functionName, lineNumber); + +} // void Trace(const char* functionName, int lineNumber) + +//============================================================ + +void Exit() +{ + // A simple utility wrapper. Used only during debugging. + // Use directly as: Exit(); + // Line number, function name, formatting, etc, are determinad automatically. + + LOGF(info, "\n\n\n\n\n\n\n\n\n\n"); + exit(1); + +} // void Exit() + +//============================================================ + +void StartFunction(const char* functionName) +{ + // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function starts. + + LOGF(info, "\033[1;32mStart %s\033[0m", functionName); // prints in green + +} // void StartFunction(const char* functionName) + +//============================================================ + +void ExitFunction(const char* functionName) +{ + // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function exits. + + LOGF(info, "\033[1;32mExit %s\033[0m", functionName); // prints in green + +} // void ExitFunction(const char* functionName) + +//============================================================ + +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. + // If fSequentialBailout > 0, bail out is performed each fSequentialBailout events, each time in a new local ROOT file. + // For sequential bailout, the naming scheme of ROOT files is AnalysisResultsBailOut_eh.fEventCounter[eProcessed].root . + // If ROOT file with the same name already exists, BailOut is not performed, since the argument is that + // it's pointless to perform Bailout for same eh.fEventCounter[eProcessed], even if eh.fEventCounter[eTotal] changed. + // Only if finalBailout = true, I will overwrite the existing file with the same name. + + if (tc.fVerbose) { + StartFunction(__FUNCTION__); + } + + // *) Local variables: TBI 20240130 shall I promote 'em to data members + add support for configurables? + TString sBailOutFile = "AnalysisResultsBailOut.root"; + TString sDirectoryFile = "multiparticle-correlations-a-b"; + + // *) For sequential bailout, I need to adapt the ROOT file name each time this function is called: + if (tc.fSequentialBailout > 0) { + sBailOutFile.ReplaceAll(".root", Form("_%d.root", eh.fEventCounter[eProcessed])); // replaces in-place + // basically, at 1st call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_1*eh.fEventCounter[eProcessed].root", + // at 2nd call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_2*eh.fEventCounter[eProcessed].root", etc. + if (!finalBailout && !gSystem->AccessPathName(sBailOutFile.Data(), kFileExists)) { // only for finalBailout = true, I will overwrite the existing file with the same name. + LOGF(info, "\033[1;33m\nsBailOutFile = %s already exits, that means that eh.fEventCounter[eProcessed] is the same as in the previous call of BailOut.\nJust skipping and waiting more events to pass selection criteria... \033[0m", sBailOutFile.Data()); + return; + } + } + + // *) Info message: + if (eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]) { + LOGF(info, "\033[1;32m=> Per request, bailing out after %d selected events in the local file %s .\n\033[0m", static_cast(eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]->GetBinContent(1)), sBailOutFile.Data()); + } + + // *) Okay, let's bail out intentionally: + TFile* f = new TFile(sBailOutFile.Data(), "recreate"); + TDirectoryFile* dirFile = new TDirectoryFile(sDirectoryFile.Data(), sDirectoryFile.Data()); + // TBI 20240130 I cannot add here fBaseList directly, since that one is declared as OutputObj + // Therefore, adding one-by-one nested TList's I want to bail out. + // Keep in sync with bookAndNestAllLists(). + TList* bailOutList = new TList(); // this is sort of 'fake' fBaseList + bailOutList->SetOwner(false); // yes, beacause for sequential bailout, with SetOwner(true) the code is crashing after 1st sequential bailout is done + bailOutList->SetName(sBaseListName.Data()); + bailOutList->Add(fBasePro); // yes, this one needs a special treatment + bailOutList->Add(qa.fQAList); + bailOutList->Add(ec.fEventCutsList); + bailOutList->Add(eh.fEventHistogramsList); + bailOutList->Add(pc.fParticleCutsList); + bailOutList->Add(ph.fParticleHistogramsList); + bailOutList->Add(qv.fQvectorList); + bailOutList->Add(mupa.fCorrelationsList); + bailOutList->Add(pw.fWeightsList); + bailOutList->Add(cw.fCentralityWeightsList); + bailOutList->Add(nl.fNestedLoopsList); + bailOutList->Add(nua.fNUAList); + bailOutList->Add(iv.fInternalValidationList); + bailOutList->Add(t0.fTest0List); + bailOutList->Add(es.fEtaSeparationsList); + bailOutList->Add(res.fResultsList); + + // *) Add list with nested list to TDirectoryFile: + dirFile->Add(bailOutList, true); + dirFile->Write(dirFile->GetName(), TObject::kSingleKey + TObject::kOverwrite); + + delete dirFile; + dirFile = NULL; + f->Close(); + + if (tc.fVerbose && !(tc.fSequentialBailout > 0)) { // then it will be called only once, for the only and permanent bailout + ExitFunction(__FUNCTION__); + } + + // *) Hasta la vista: + if (finalBailout) { + LOGF(fatal, "\033[1;31mHasta la vista - bailed out permanently in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); + } else { + LOGF(info, "\033[1;32mBailed out sequentially in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); + if (tc.fVerbose) { + ExitFunction(__FUNCTION__); + } + } + +} // void BailOut(bool finalBailout = false) + +//============================================================ + +void FillQvector(const double& dPhi, const double& dPt, const double& dEta) +{ + // 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); + LOGF(info, "\033[1;32m dPt = %f\033[0m", dPt); + LOGF(info, "\033[1;32m dEta = %f\033[0m", dEta); + } + + // Particle weights: + double wPhi = 1.; // integrated phi weight + double wPt = 1.; // integrated pt weight + double wEta = 1.; // integrated eta weight + double wToPowerP = 1.; // weight raised to power p + + if (pw.fUseWeights[wPHI]) { + wPhi = Weight(dPhi, wPHI); + if (!(wPhi > 0.)) { + LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); + LOGF(fatal, "dPhi = %f\nwPhi = %f", dPhi, wPhi); + } + } // if(pw.fUseWeights[wPHI]) + + if (pw.fUseWeights[wPT]) { + wPt = Weight(dPt, wPT); // corresponding pt weight + if (!(wPt > 0.)) { + LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); + LOGF(fatal, "dPt = %f\nwPt = %f", dPt, wPt); + } + } // if(pw.fUseWeights[wPT]) + + if (pw.fUseWeights[wETA]) { + wEta = Weight(dEta, wETA); // corresponding eta weight + if (!(wEta > 0.)) { + LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); + LOGF(fatal, "dEta = %f\nwEta = %f", dEta, wEta); + } + } // if(pw.fUseWeights[wETA]) + + if (qv.fCalculateQvectors) { + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + 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 + } else { + qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights + } + } // for(int wp=0;wp 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; + 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)); + } + } // for (int h = 0; h < gMaxHarmonic; h++) { + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation + } + } + } // if(es.fCalculateEtaSeparations) { - if (tc.fVerbose) { + if (tc.fVerboseForEachParticle) { ExitFunction(__FUNCTION__); } -} // void PrintCutCounterContent() +} // void FillQvector(const double& dPhi, const double& dPt, const double& dEta) //============================================================ -void Trace(const char* functionName, int lineNumber) +void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) { - // A simple utility wrapper. Use only during debugging, sprinkle calls to this function here and there, as follows - // Trace(__FUNCTION__, __LINE__); + // Fill integrated Q-vector using sparse histograms. - LOGF(info, "\033[1;32m%s .... line %d\033[0m", functionName, lineNumber); + // Remark: I pass by reference particle quantities, while event quantities (centrality, vertex z, ...) I fetch from data members (or from global variables in a macro). -} // void Trace(const char* functionName, int lineNumber) + // To do: + // 20250224 do I need to switch to this function also in InternalValidation()? I still use simple FillQvector() there. + // That would really make sense only after I add support for usage of particle weights in InternalValidation() -//============================================================ + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + LOGF(info, "\033[1;32m dPhi = %f\033[0m", dPhi); + LOGF(info, "\033[1;32m dPt = %f\033[0m", dPt); + LOGF(info, "\033[1;32m dEta = %f\033[0m", dEta); + LOGF(info, "\033[1;32m dCharge = %f\033[0m", dCharge); + } -void Exit() -{ - // A simple utility wrapper. Used only during debugging. - // Use directly as: Exit(); - // Line number, function name, formatting, etc, are determinad automatically. + // Particle weights from sparse histograms: + 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 - LOGF(info, "\n\n\n\n\n\n\n\n\n\n"); - exit(1); + // *) Multidimensional phi weights: + if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a comon boolean for this category + wPhi = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWPhi); + // 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 (!(wPhi > 0.)) { + LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); + LOGF(error, "dPhi = %f", dPhi); + if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { + LOGF(fatal, "dPt = %f", dPt); + } + if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { + LOGF(fatal, "dEta = %f", dEta); + } + if (pw.fUseDiffPhiWeights[wPhiChargeAxis]) { + LOGF(fatal, "dCharge = %f", dCharge); + } + if (pw.fUseDiffPhiWeights[wPhiCentralityAxis]) { + LOGF(fatal, "ebye.Centrality = %f", ebye.fCentrality); + } + if (pw.fUseDiffPhiWeights[wPhiVertexZAxis]) { + LOGF(fatal, "ebye.Vz = %f", ebye.fVz); + } + LOGF(fatal, "Multidimensional weight for enabled dimensions is wPhi = %f", wPhi); + } + } // if(pw.fUseDiffPhiWeights[wPhiPhiAxis]) -} // void Exit() + // *) 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 (!(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(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 (!(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(fatal, "Multidimensional weight for enabled dimensions is wEta = %f", wEta); + } + } // if(pw.fUseDiffEtaWeights[wEtaEtaAxis]) -void StartFunction(const char* functionName) -{ - // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function starts. + 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 + } else { + qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights + } + } // for(int wp=0;wp 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; + 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)); + } + } // for (int h = 0; h < gMaxHarmonic; h++) { + } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation + } + } + } // if(es.fCalculateEtaSeparations) { -} // void StartFunction(const char* functionName) + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + +} // void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) //============================================================ -void ExitFunction(const char* functionName) +void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice, const double& dEta = 0.) { - // A simple utility wrapper, used when tc.fVerbose = true. It merely ensures uniform formatting of notification when the function exits. - - LOGF(info, "\033[1;32mExit %s\033[0m", functionName); // prints in green + // !!! OBSOLETE FUNCTION (as of 20250527) !!! -} // void ExitFunction(const char* functionName) + 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__); -//============================================================ + // 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 + // Example usage #2: this->Fillqvector(dPhi, dPt, PTq, dEta); // differential q-vectors with using eta separations (I need dEta of particle to decide whether particle is added to qa or qb) -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. - // If fSequentialBailout > 0, bail out is performed each fSequentialBailout events, each time in a new local ROOT file. - // For sequential bailout, the naming scheme of ROOT files is AnalysisResultsBailOut_eh.fEventCounter[eProcessed].root . - // If ROOT file with the same name already exists, BailOut is not performed, since the argument is that - // it's pointless to perform Bailout for same eh.fEventCounter[eProcessed], even if eh.fEventCounter[eTotal] changed. - // Only if finalBailout = true, I will overwrite the existing file with the same name. + // 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) - if (tc.fVerbose) { + if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); } - // *) Local variables: TBI 20240130 shall I promote 'em to data members + add support for configurables? - TString sBailOutFile = "AnalysisResultsBailOut.root"; - TString sDirectoryFile = "multiparticle-correlations-a-b"; - - // *) For sequential bailout, I need to adapt the ROOT file name each time this function is called: - if (tc.fSequentialBailout > 0) { - sBailOutFile.ReplaceAll(".root", Form("_%d.root", eh.fEventCounter[eProcessed])); // replaces in-place - // basically, at 1st call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_1*eh.fEventCounter[eProcessed].root", - // at 2nd call "AnalysisResultsBailOut.root" => "AnalysisResultsBailOut_2*eh.fEventCounter[eProcessed].root", etc. - if (!finalBailout && !gSystem->AccessPathName(sBailOutFile.Data(), kFileExists)) { // only for finalBailout = true, I will overwrite the existing file with the same name. - LOGF(info, "\033[1;33m\nsBailOutFile = %s already exits, that means that eh.fEventCounter[eProcessed] is the same as in the previous call of BailOut.\nJust skipping and waiting more events to pass selection criteria... \033[0m", sBailOutFile.Data()); - return; + // *) 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" + 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 + break; } - } - - // *) Info message: - if (eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]) { - LOGF(info, "\033[1;32m=> Per request, bailing out after %d selected events in the local file %s .\n\033[0m", static_cast(eh.fEventHistograms[eNumberOfEvents][eRec][eAfter]->GetBinContent(1)), sBailOutFile.Data()); - } - - // *) Okay, let's bail out intentionally: - TFile* f = new TFile(sBailOutFile.Data(), "recreate"); - TDirectoryFile* dirFile = new TDirectoryFile(sDirectoryFile.Data(), sDirectoryFile.Data()); - // TBI 20240130 I cannot add here fBaseList directly, since that one is declared as OutputObj - // Therefore, adding one-by-one nested TList's I want to bail out. - // Keep in sync with BookAndNestAllLists(). - TList* bailOutList = new TList(); // this is sort of 'fake' fBaseList - bailOutList->SetOwner(false); // yes, beacause for sequential bailout, with SetOwner(true) the code is crashing after 1st sequential bailout is done - bailOutList->SetName(sBaseListName.Data()); - bailOutList->Add(fBasePro); // yes, this one needs a special treatment - bailOutList->Add(qa.fQAList); - bailOutList->Add(ec.fEventCutsList); - bailOutList->Add(eh.fEventHistogramsList); - bailOutList->Add(pc.fParticleCutsList); - bailOutList->Add(ph.fParticleHistogramsList); - bailOutList->Add(qv.fQvectorList); - bailOutList->Add(mupa.fCorrelationsList); - bailOutList->Add(pw.fWeightsList); - bailOutList->Add(cw.fCentralityWeightsList); - bailOutList->Add(nl.fNestedLoopsList); - bailOutList->Add(nua.fNUAList); - bailOutList->Add(iv.fInternalValidationList); - bailOutList->Add(t0.fTest0List); - bailOutList->Add(es.fEtaSeparationsList); - bailOutList->Add(res.fResultsList); - - // *) Add list with nested list to TDirectoryFile: - dirFile->Add(bailOutList, true); - dirFile->Write(dirFile->GetName(), TObject::kSingleKey + TObject::kOverwrite); - delete dirFile; - dirFile = NULL; - f->Close(); + case ETAq: { + AFO_var = AFO_ETA; + AFO_weight = wETA; + AFO_diffWeight = wPHIETA; // TBI 20250215 this is now obsolete, see the comment in enum + break; + } + case CHARGEq: { + AFO_var = AFO_CHARGE; + AFO_weight = wCHARGE; + AFO_diffWeight = wPHICHARGE; // TBI 20250215 this is now obsolete, see the comment in enum + 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)); + break; + } + } // switch(kineVarChoice) - if (tc.fVerbose && !(tc.fSequentialBailout > 0)) { // then it will be called only once, for the only and permanent bailout - ExitFunction(__FUNCTION__); + // *) 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__); + } + 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 (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__); } - // *) Hasta la vista: - if (finalBailout) { - LOGF(fatal, "\033[1;31mHasta la vista - bailed out permanently in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); - } else { - LOGF(info, "\033[1;32mBailed out sequentially in function %s at line %d\n The output file is: %s\n\n\033[0m", __FUNCTION__, __LINE__, sBailOutFile.Data()); - if (tc.fVerbose) { - ExitFunction(__FUNCTION__); + // *) 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); } } -} // void BailOut(bool finalBailout = false) - -//============================================================ + // *) 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]) { -void FillQvector(const double& dPhi, const double& dPt, const double& dEta) -{ - // Fill integrated Q-vector. - // Example usage: this->FillQvector(dPhi, dPt, dEta); + // *) 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]) { - // 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... + // *) Finally, fill differential q-vector in that bin: + for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { + for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power + if (pw.fUseWeights[AFO_weight] || pw.fUseDiffWeights[AFO_diffWeight]) { + // TBI 20240212 supported at the moment: e.g. q-vector vs pt can be weighted only with diff. phi(pt) and integrated pt weights. + // It cannot be weighted in addition with eta weights, since in any case I anticipate I will do always 1-D analysis, by integrating out all other dependencies + wToPowerP = std::pow(diffPhiWeightsForThisKineVar * kineVarWeight, wp); + qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // q-vector with weights + } else { + qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare q-vector without weights + } + } // for(int wp=0;wpAddAt(dPhi, qv.fqvectorEntries[kineVarChoice][bin - 1]); + nl.ftaNestedLoopsKine[kineVarChoice][bin - 1][1]->AddAt(diffPhiWeightsForThisKineVar * kineVarWeight, qv.fqvectorEntries[kineVarChoice][bin - 1]); } - // Particle weights: - double wPhi = 1.; // integrated phi weight - double wPt = 1.; // integrated pt weight - double wEta = 1.; // integrated eta weight - double wToPowerP = 1.; // weight raised to power p - - if (pw.fUseWeights[wPHI]) { - wPhi = Weight(dPhi, wPHI); - if (!(wPhi > 0.)) { - LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); - LOGF(fatal, "dPhi = %f\nwPhi = %f", dPhi, wPhi); - } - } // if(pw.fUseWeights[wPHI]) + // *) Multiplicity counter in this bin: + qv.fqvectorEntries[kineVarChoice][bin - 1]++; // count number of particles in this pt bin in this event - if (pw.fUseWeights[wPT]) { - wPt = Weight(dPt, wPT); // corresponding pt weight - if (!(wPt > 0.)) { - LOGF(error, "\033[1;33m%s wPt is not positive\033[0m", __FUNCTION__); - LOGF(fatal, "dPt = %f\nwPt = %f", dPt, wPt); - } - } // if(pw.fUseWeights[wPT]) + // *) Usage of eta separations in differential correlations: + if (es.fCalculateEtaSeparations && es.fCalculateEtaSeparationsAsFunctionOf[AFO_var]) { // yes, I can decouple this one from if (qv.fCalculateQvectors) - if (pw.fUseWeights[wETA]) { - wEta = Weight(dEta, wETA); // corresponding eta weight - if (!(wEta > 0.)) { - LOGF(error, "\033[1;33m%s wEta is not positive\033[0m", __FUNCTION__); - LOGF(fatal, "dEta = %f\nwEta = %f", dEta, wEta); + if (AFO_var == AFO_ETA) { + LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == AFO_ETA . This doesn't make any sense in this context. \033[0m", __FUNCTION__, __LINE__); } - } // if(pw.fUseWeights[wETA]) - - if (qv.fCalculateQvectors) { - for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - 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 - } else { - qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights - } - } // for(int wp=0;wp 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; + // qv.fmab[1][bin - 1][e] += diffPhiWeightsForThisKineVar * kineVarWeight; // Remark: I can hardwire linear weight like this only for 2-p correlation + // TBI 20250616 I cannot use this any longer, after i added one more dimension 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][bin - 1][h][e] += TComplex(diffPhiWeightsForThisKineVar * kineVarWeight * std::cos((h + 1) * dPhi), diffPhiWeightsForThisKineVar * kineVarWeight * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation // TBI 20250616 I cannot use this any longer, after I added one more dimension to qv.fqabVector } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation @@ -15787,289 +18041,436 @@ void FillQvector(const double& dPhi, const double& dPt, const double& dEta) ExitFunction(__FUNCTION__); } -} // void FillQvector(const double& dPhi, const double& dPt, const double& dEta) +} // void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice) //============================================================ -void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) +eAsFunctionOf AfoKineMap1D(eqvectorKine kineVarChoice) { - // Fill integrated Q-vector using sparse histograms. + // Simple utility function to map for the 1-dimensional case eqvectorKine into eAsFunctionOf. - // Remark: I pass by reference particle quantities, while event quantities (centrality, vertex z, ...) I fetch from data members (or from global variables in a macro). + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + } - // To do: - // 20250224 do I need to switch to this function also in InternalValidation()? I still use simple FillQvector() there. - // That would really make sense only after I add support for usage of particle weights in InternalValidation() + eAsFunctionOf AFO_var = eAsFunctionOf_N; + + switch (kineVarChoice) { + + case PTq: { + AFO_var = AFO_PT; + break; + } + + case ETAq: { + AFO_var = AFO_ETA; + break; + } + + case CHARGEq: { + AFO_var = AFO_CHARGE; + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet for 1D case. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + + } // switch(kineVarChoice) + + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + + return AFO_var; + +} // eAsFunctionOf AfoKineMap1D(eqvectorKine kineVarChoice) + +//============================================================ + +eAsFunctionOf2D AfoKineMap2D(eqvectorKine kineVarChoice) +{ + // Simple utility function to map for the 2-dimensional case eqvectorKine into eAsFunctionOf2D. if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); - LOGF(info, "\033[1;32m dPhi = %f\033[0m", dPhi); - LOGF(info, "\033[1;32m dPt = %f\033[0m", dPt); - LOGF(info, "\033[1;32m dEta = %f\033[0m", dEta); - LOGF(info, "\033[1;32m dCharge = %f\033[0m", dCharge); } - // Particle weights from sparse histograms: - 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 + eAsFunctionOf2D AFO_var = eAsFunctionOf2D_N; - // *) Multidimensional phi weights: - if (pw.fUseDiffPhiWeights[wPhiPhiAxis]) { // yes, 0th axis serves as a comon boolean for this category - wPhi = WeightFromSparse(dPhi, dPt, dEta, dCharge, eDWPhi); - // 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 (!(wPhi > 0.)) { - LOGF(error, "\033[1;33m%s wPhi is not positive\033[0m", __FUNCTION__); - LOGF(error, "dPhi = %f", dPhi); - if (pw.fUseDiffPhiWeights[wPhiPtAxis]) { - LOGF(fatal, "dPt = %f", dPt); - } - if (pw.fUseDiffPhiWeights[wPhiEtaAxis]) { - LOGF(fatal, "dEta = %f", dEta); - } - if (pw.fUseDiffPhiWeights[wPhiChargeAxis]) { - LOGF(fatal, "dCharge = %f", dCharge); - } - if (pw.fUseDiffPhiWeights[wPhiCentralityAxis]) { - LOGF(fatal, "ebye.Centrality = %f", ebye.fCentrality); - } - if (pw.fUseDiffPhiWeights[wPhiVertexZAxis]) { - LOGF(fatal, "ebye.Vz = %f", ebye.fVz); - } - LOGF(fatal, "Multidimensional weight for enabled dimensions is wPhi = %f", wPhi); + switch (kineVarChoice) { + + case PT_ETAq: { + AFO_var = AFO_PT_ETA; + break; } - } // 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 (!(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(fatal, "Multidimensional weight for enabled dimensions is wPt = %f", wPt); + case PT_CHARGEq: { + AFO_var = AFO_PT_CHARGE; + break; } - } // 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 (!(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(fatal, "Multidimensional weight for enabled dimensions is wEta = %f", wEta); + case ETA_CHARGEq: { + AFO_var = AFO_ETA_CHARGE; + break; + } + + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet for 2D case. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; + } + + } // switch(kineVarChoice) + + if (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); + } + + return AFO_var; + +} // eAsFunctionOf2D AfoKineMap2D(eqvectorKine kineVarChoice) + +//============================================================ + +eAsFunctionOf3D AfoKineMap3D(eqvectorKine kineVarChoice) +{ + // Simple utility function to map for the 3-dimensional case eqvectorKine into eAsFunctionOf3D. + + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); + } + + eAsFunctionOf3D AFO_var = eAsFunctionOf3D_N; + + switch (kineVarChoice) { + + case PT_ETA_CHARGEq: { + AFO_var = AFO_PT_ETA_CHARGE; + break; } - } // if(pw.fUseDiffEtaWeights[wEtaEtaAxis]) - 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 - } else { - qv.fQvector[h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare Q-vector without weights - } - } // for(int wp=0;wp 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; - 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)); - } - } // for (int h = 0; h < gMaxHarmonic; h++) { - } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation - } + default: { + LOGF(fatal, "\033[1;31m%s at line %d : this kineVarChoice = %d is not supported yet for 3D case. \033[0m", __FUNCTION__, __LINE__, static_cast(kineVarChoice)); + break; } - } // if(es.fCalculateEtaSeparations) { + + } // switch(kineVarChoice) if (tc.fVerboseForEachParticle) { ExitFunction(__FUNCTION__); } -} // void FillQvectorFromSparse(const double& dPhi, const double& dPt, const double& dEta, const double& dCharge) + return AFO_var; + +} // eAsFunctionOf3D AfoKineMap3D(eqvectorKine kineVarChoice) //============================================================ -void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice, const double& dEta = 0.) +TString StringKineMap(eqvectorKine kineVarChoice) { - // 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 - // Example usage #2: this->Fillqvector(dPhi, dPt, PTq, dEta); // differential q-vectors with using eta separations (I need dEta of particle to decide whether particle is added to qa or qb) + // Simple utility function to map eqvectorKine into string. + + // Example: StringKineMap(PTq).Data() => prints "vs. pt" if (tc.fVerboseForEachParticle) { StartFunction(__FUNCTION__); } - // *) 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" + TString s = ""; + switch (kineVarChoice) { + case PTq: { - AFO_var = AFO_PT; - AFO_weight = wPT; - AFO_diffWeight = wPHIPT; + s = "vs. pt"; break; } + case ETAq: { - AFO_var = AFO_ETA; - AFO_weight = wETA; - AFO_diffWeight = wPHIETA; + s = "vs. eta"; + break; + } + + case CHARGEq: { + s = "vs. charge"; + break; + } + + case PT_ETAq: { + s = "vs. pt vs. eta"; + break; + } + + case PT_CHARGEq: { + s = "vs. pt vs. charge"; + break; + } + + case ETA_CHARGEq: { + s = "vs. eta vs. charge"; + break; + } + + case PT_ETA_CHARGEq: { + s = "vs. pt vs. eta vs. charge"; 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)); 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__); - } - 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 (tc.fVerboseForEachParticle) { + ExitFunction(__FUNCTION__); } - 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__); + + return s; + +} // 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. + // 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" + + // Example - the standard 1D case: + // double kineArr[1] = {dPt}; + // this->FillqvectorNdim(dPhi, kineArr, 1, PTq); // differential q-vector vs. pt + + // Example - the 2D case: + // double kineArr[2] = {dPt, dEta}; + // this->FillqvectorNdim(dPhi, kineArr, 2, PT_ETAq); // differential q-vector vs. (pt, eta) + + // Example - the 3D case: + // double kineArr[3] = {dPt, dEta, dCharge}; + // this->FillqvectorNdim(dPhi, kineArr, 3, PT_ETA_CHARGEq); // differential q-vector vs. (pt, eta, charge) + + // Example - the 1D case, pt dependence with eta separations: + // double kineArr[1] = {dPt}; + // this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); // differential q-vectors with using eta separations (I need dEta of particle to decide whether particle is added to qa or qb) + + if (tc.fVerboseForEachParticle) { + StartFunction(__FUNCTION__); } - // *) Get the desired bin number: + // This is the linearized global bin, the 2nd index of fqvector[...][gMaxNoBinsKine][...][...], it shall work transparently for 1D, 2D, 3D, etc... + // Yes, it is also the 3rd index of fqabVector[...][...][gMaxNoBinsKine][...][...] 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); + + switch (Ndim) { + + case 1: { + eAsFunctionOf AFO_var = AfoKineMap1D(kineVarChoice); + 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. + 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); + } + } + 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? + case 2: { + eAsFunctionOf2D AFO_var = AfoKineMap2D(kineVarChoice); + 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. + 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); + } + } + break; } - } // 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? + case 3: { + eAsFunctionOf3D AFO_var = AfoKineMap3D(kineVarChoice); + 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. + 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); + } + } + break; } - } // if(pw.fUseDiffWeights[AFO_diffWeight]) { - // *) Finally, fill differential q-vector in that bin: - for (int h = 0; h < gMaxHarmonic * gMaxCorrelator + 1; h++) { - for (int wp = 0; wp < gMaxCorrelator + 1; wp++) { // weight power - if (pw.fUseWeights[AFO_weight] || pw.fUseDiffWeights[AFO_diffWeight]) { - // TBI 20240212 supported at the moment: e.g. q-vector vs pt can be weighted only with diff. phi(pt) and integrated pt weights. - // It cannot be weighted in addition with eta weights, since in any case I anticipate I will do always 1-D analysis, by integrating out all other dependencies - wToPowerP = std::pow(diffPhiWeightsForThisKineVar * kineVarWeight, wp); - qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(wToPowerP * std::cos(h * dPhi), wToPowerP * std::sin(h * dPhi)); // q-vector with weights - } else { - qv.fqvector[kineVarChoice][bin - 1][h][wp] += TComplex(std::cos(h * dPhi), std::sin(h * dPhi)); // bare q-vector without weights + // ... + + default: { + LOGF(fatal, "\033[1;31m%s at line %d : Ndim = %d is not supported yet. \033[0m", __FUNCTION__, __LINE__, Ndim); + break; + } + + } // switch (Ndim) + + // zzzzzzzzzzzzzzzzzzzzzz + + /* + + // *) 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" + 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 + break; + } + case ETAq: { + AFO_var = AFO_ETA; + AFO_weight = wETA; + AFO_diffWeight = wPHIETA; // TBI 20250215 this is now obsolete, see the comment in enum + break; + } + case CHARGEq: { + AFO_var = AFO_CHARGE; + AFO_weight = wCHARGE; + AFO_diffWeight = wPHICHARGE; // TBI 20250215 this is now obsolete, see the comment in enum + 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)); + 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__); + } + 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 (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__); + } + + // *) 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); + } + } + */ + + /* + // *) 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]) { + + */ + + // *) 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;wpAddAt(dPhi, qv.fqVectorEntries[kineVarChoice][bin - 1]); - nl.ftaNestedLoopsKine[kineVarChoice][bin - 1][1]->AddAt(diffPhiWeightsForThisKineVar * kineVarWeight, qv.fqVectorEntries[kineVarChoice][bin - 1]); + nl.ftaNestedLoopsKine[kineVarChoice][bin][0]->AddAt(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 } // *) Multiplicity counter in this bin: - qv.fqVectorEntries[kineVarChoice][bin - 1]++; // count number of particles in this pt bin in this event + 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 && es.fCalculateEtaSeparationsAsFunctionOf[AFO_var]) { // yes, I can decouple this one from if (qv.fCalculateQvectors) + if (es.fCalculateEtaSeparations && qv.fCalculateqvectorsKineEtaSeparations[kineVarChoice]) { // yes, I have decoupled this one from if (qv.fCalculateQvectors) - if (AFO_var == AFO_ETA) { - LOGF(fatal, "\033[1;31m%s at line %d : AFO_var == AFO_ETA . This doesn't make any sense in this context. \033[0m", __FUNCTION__, __LINE__); + 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 } 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][bin - 1][e] += 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] += 1.; // diffPhiWeightsForThisKineVar * kineVarWeight; // 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][bin - 1][h][e] += TComplex(diffPhiWeightsForThisKineVar * kineVarWeight * std::cos((h + 1) * dPhi), diffPhiWeightsForThisKineVar * kineVarWeight * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation + 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 } } // 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][bin - 1][e] += 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] += 1.; // diffPhiWeightsForThisKineVar * kineVarWeight; // 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][bin - 1][h][e] += TComplex(diffPhiWeightsForThisKineVar * kineVarWeight * std::cos((h + 1) * dPhi), diffPhiWeightsForThisKineVar * kineVarWeight * std::sin((h + 1) * dPhi)); // Remark: I can hardwire linear weight like this only for 2-p correlation + 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 } } // for (int h = 0; h < gMaxHarmonic; h++) { } // for (int e = 0; e < gMaxNumberEtaSeparations; e++) { // eta separation } } - } // if(es.fCalculateEtaSeparations) { + } // if(es.fCalculateEtaSeparations) if (tc.fVerboseForEachParticle) { ExitFunction(__FUNCTION__); } -} // void Fillqvector(const double& dPhi, const double& kineVarValue, eqvectorKine kineVarChoice) +} // void FillqvectorNdim(const double& dPhi, double* kineVarValues, int Ndim, eqvectorKine kineVarChoice, const double& dEta = 0.) //============================================================ void CalculateEverything() { // Calculate everything for selected events and particles. - // Remark: Data members for Q-vectors, containers for nested loops, etc., must all be filled when this function is called. + // Remark: Data members for Q-vectors (both integrated and differential), containers for nested loops, etc., must all be filled when this function is called. if (tc.fVerbose) { StartFunction(__FUNCTION__); @@ -16095,14 +18496,45 @@ void CalculateEverything() this->CalculateTest0(); } - // *) Calculate kine Test0: TBI 20240110 name convention - // Remark: vs. pt, vs. eta, etc., are all calculated here - if (qv.fCalculateQvectors && t0.fCalculateTest0AsFunctionOf[AFO_PT]) { - this->CalculateKineTest0(AFO_PT); + // *) Calculate kine Test0: + + // **) 1D kine: + // ***) cases for which 1D vs. pt calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PTq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PTq, 1); + } + + // ***) cases for which 1D vs. eta calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[ETAq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(ETAq, 1); + } + // ***) cases for which 1D vs. charge calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(CHARGEq, 1); + } + // ... + + // **) 2D kine: + // ***) cases for which 2D vs. (pt,eta) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PT_ETAq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PT_ETAq, 2); + } + // ***) cases for which 2D vs. (pt,charge) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PT_CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PT_CHARGEq, 2); + } + // ***) cases for which 2D vs. (eta,charge) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[ETA_CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(ETA_CHARGEq, 2); } - if (qv.fCalculateQvectors && t0.fCalculateTest0AsFunctionOf[AFO_ETA]) { - this->CalculateKineTest0(AFO_ETA); + // ... + + // **) 3D kine: + // ***) cases for which 3D vs. (pt,eta,charge) calculus is needed: + if (qv.fCalculateQvectors && qv.fCalculateqvectorsKine[PT_ETA_CHARGEq]) { // TBI 20250601 do I really need here qv.fCalculateQvectors + this->CalculateKineTest0Ndim(PT_ETA_CHARGEq, 3); } + // ... // *) Calculate nested loops: if (nl.fCalculateNestedLoops) { @@ -16118,7 +18550,10 @@ void CalculateEverything() if (es.fCalculateEtaSeparations) { this->CalculateEtaSeparations(); if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_PT]) { - this->CalculateKineEtaSeparations(AFO_PT); // The implementation of CalculateKineEtaSeparations( ... ) is generic and can be used for any other "kine" variable, for which it makes sense + this->CalculateKineEtaSeparationsNdim(PTq, 1); + } + if (es.fCalculateEtaSeparationsAsFunctionOf[AFO_CHARGE]) { + this->CalculateKineEtaSeparationsNdim(CHARGEq, 1); } } @@ -16191,9 +18626,10 @@ void MainLoopOverParticles(T const& tracks) } // *) Declare local kinematic variables: - double dPhi = 0.; // azimuthal angle - double dPt = 0.; // transverse momentum - double dEta = 0.; // pseudorapidity + 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) { @@ -16230,41 +18666,31 @@ void MainLoopOverParticles(T const& tracks) continue; } - // memStatus ~120 (with 'continue') - // *) Fill particle histograms before particle cuts: if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D || qa.fFillQAParticleHistograms2D) { FillParticleHistograms(track, eBefore); } - - // memStatus ~163 (with 'continue') - // *) Particle cuts counters (use only during QA, as this is computationally heavy): if (pc.fUseParticleCutCounterAbsolute || pc.fUseParticleCutCounterSequential) { ParticleCutsCounters(track); } - // memStatus ~164 (with 'continue') - // *) Particle cuts: if (!ParticleCuts(track, eCut)) { // Main call for event cuts. continue; // not return!! } - // memStatus ~162 (with 'continue') - // *) Fill particle histograms after particle cuts: if (ph.fFillParticleHistograms || ph.fFillParticleHistograms2D || qa.fFillQAParticleHistograms2D) { FillParticleHistograms(track, eAfter); } - // memStatus ~164 (with 'continue') - // *) Intitialize local kinematic variables: // Remark: for "eRecSim" processing, kinematics is taken from "reconstructed". dPhi = track.phi(); dPt = track.pt(); dEta = track.eta(); + dCharge = track.sign(); // Remark: Keep in sync all calls and flags below with the ones in InternalValidation(). // *) Integrated Q-vectors: @@ -16274,29 +18700,87 @@ void MainLoopOverParticles(T const& tracks) 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, track.sign()); // 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->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, ...) } } - // *) Differential q-vectors: - // **) pt-dependence: + // *) 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: - this->Fillqvector(dPhi, dPt, PTq); // first 2 arguments are passed by reference, 3rd argument is enum + 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: - // Remark: Within Fillqvector() I check again all the relevant flags. - this->Fillqvector(dPhi, dPt, PTq, dEta); // first 2 arguments and the last one are passed by reference, 3rd argument is enum. "kine" variable is the 2nd argument + double kineArr[1] = {dPt}; + this->FillqvectorNdim(dPhi, kineArr, 1, PTq, dEta); } - // **) eta-dependence: + + // ***) 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. - this->Fillqvector(dPhi, dEta, ETAq); // first 2 arguments are passed by reference, 3rd argument is enum + double kineArr[1] = {dEta}; + this->FillqvectorNdim(dPhi, kineArr, 1, ETAq); } - // *) Fill nested loops containers: + // ***) 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); + } + + // ... + + // ** 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); + } + + // *) 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 } @@ -16344,6 +18828,8 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) StartFunction(__FUNCTION__); } + // memStatus: ~50K (without differential q-vectors and eta separations) + // *) Dry run: if (tc.fDryRun) { EventCounterForDryRun(eFill); @@ -16352,6 +18838,8 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) return; } + // memStatus: ~50K (without differential q-vectors and eta separations) + // *) Reset event-by-event quantities: TBI 20240430 I do not need this call also here really, but it doesn't hurt either... ResetEventByEventQuantities(); @@ -16392,22 +18880,20 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) // *) Determine vertex z position: DetermineVertexZ(collision); + // memStatus: ~50K (without differential q-vectors and eta separations) + // *) Determine additional QA thingies: if (qa.fFillQAEventHistograms2D || qa.fFillQAParticleHistograms2D || qa.fFillQAParticleEventHistograms2D || qa.fFillQACorrelationsVsHistograms2D || qa.fFillQACorrelationsVsInteractionRateVsProfiles2D) { // Remark: I implement ideally here only the getters for which the subscription to additional non-standard tables was needed for QA purposes. DetermineQAThingies(collision, bcs); } - // memStatus: ~116 - // *) 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 FillEventHistograms(collision, tracks, eBefore); } - // memStatus: ~117 - // *) Print info on the current event number (total, before cuts): if (tc.fVerboseEventCounter) { PrintEventCounter(eBefore); @@ -16418,19 +18904,17 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) EventCutsCounters(collision, tracks); } - // memStatus: ~117 - // *) Event cuts: if (!EventCuts(collision, tracks, eCut)) { // Main call for event cuts return; } - // memStatus: ~117 + // memStatus: ~50K (without differential q-vectors and eta separations) // *) Main loop over particles: - MainLoopOverParticles(tracks); + MainLoopOverParticles(tracks); // memStatus: so here I invest ~20K, as of 20250530 - // memStatus: ~162 (all particle histograms), ~133 (only phi, pt, eta) + // memStatus: ~70K (without differential q-vectors and eta separations) // *) Determine multiplicity of this event, for all "vs. mult" results: DetermineMultiplicity(); @@ -16457,6 +18941,8 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) // *) Calculate everything for selected events and particles: CalculateEverything(); + // memStatus: ~72K (without differential q-vectors and eta separations) + // *) Reset event-by-event quantities: ResetEventByEventQuantities(); @@ -16481,12 +18967,20 @@ void Steer(T1 const& collision, T2 const& bcs, T3 const& tracks) tc.fTimer[eGlobal]->Continue(); // yes } - // memStatus: ~160 +- 5 - if (tc.fVerbose) { ExitFunction(__FUNCTION__); } + // memStatus (summary): Last update: 20250602 + // Remark: disable sequential bailout before doing this test (yes!) + all of UseSetBinLabel, ... UseDatabasetPDG + // ~46K (skeleton - literally) + // ~50K (dry run with 1D objects booked) + // ~70K (all object declaration besides kine objects (diff. q-vectors and eta separations) + all calculus and 1D histograms filled, trivial labels) + // ~70K (all object declaration + 1D kine objects (diff. q-vectors in coarse kine bins) + all calculus and 1D histograms filled, standard labels) + // ~80K (all object declaration + 1D + 2D kine objects (diff. q-vectors in fine kine bins) + all calculus and 1D histograms filled, standard labels) + // ~110K (all object declaration + 1D + 2D + 3D kine objects (diff. q-vectors in fine kine bins) + all calculus and 1D histograms filled, standard labels) + // ~125K (all object declaration + 1D + 2D + 3D kine objects (diff. q-vectors in fine kine bins) + all calculus and 1D histograms filled, Set_0 labels) + } // template void Steer(T1 const* collision, T2 const* tracks) #endif // PWGCF_MULTIPARTICLECORRELATIONS_CORE_MUPA_MEMBERFUNCTIONS_H_ diff --git a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx index 344c45a7330..3f7953f5f11 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/multiparticle-correlations-ab.cxx @@ -14,16 +14,18 @@ /// \author Ante.Bilandzic@cern.ch // O2: -#include #include "Common/CCDB/ctpRateFetcher.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/DataTypes.h" -#include "Common/DataModel/TrackSelectionTables.h" // needed for aod::TracksDCA table +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/TrackSelectionTables.h" // needed for aod::TracksDCA table + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" +#include using namespace o2; using namespace o2::framework; @@ -73,21 +75,27 @@ using Collision_QA = CollisionRec; // if I would need additional tables for QA, using TracksRec_QA = TracksRec; // if I would need additional tables for QA, just join 'em here with TracksRec // *) ROOT: -#include -#include -#include -#include -#include -#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 std; // *) Enums: @@ -104,6 +112,12 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to Service ccdb; ctpRateFetcher mRateFetcher; // see email from MP on 20240508 and example usage in O2Physics/PWGLF/TableProducer/Common/zdcSP.cxx + // *) O2DatabsePDG service shared service between different tasks (do not use TDatabasePDG directly, because it's not shared) + // See also Tutorials/src/usingPDGCervice.cxx + // TBI 20250625 enable the line below and switch to O2DatabsePDG when memory consumption with O2DatabsePDG is resolved, and then replace in all functions + // tc.fDatabasePDG->GetParticle(track.pdgCode()) with pdg->GetParticle(track.pdgCode()) + same for mcParticle + remove TDatabasePDG.h + // Service pdg; + // *) Configurables (cuts): #include "PWGCF/MultiparticleCorrelations/Core/MuPa-Configurables.h" @@ -132,50 +146,54 @@ struct MultiparticleCorrelationsAB // this name is used in lower-case format to TH1::AddDirectory(kFALSE); // *) 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 - DefaultBooking(); // here I decide only which histograms are booked, not details like binning, etc. - DefaultBinning(); // here default values for bins are either hardwired, or values for bins provided via configurables are taken into account - DefaultCuts(); // here default values for cuts are either hardwired, or defined through default binning to ease bookeeping, + 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 + defaultBooking(); // here I decide only which histograms are booked, not details like binning, etc. + defaultBinning(); // here default values for bins are either hardwired, or values for bins provided via configurables are taken into account + defaultCuts(); // here default values for cuts are either hardwired, or defined through default binning to ease bookeeping, // or values for cuts provided via configurables are taken into account - // Remark: DefaultCuts() has to be called after DefaultBinning() + // Remark: defaultCuts() has to be called after defaultBinning() // *) Specific cuts: if (tc.fUseSpecificCuts) { - SpecificCuts(tc.fWhichSpecificCuts); // after default cuts are applied, on top of them apply analysis-specific cuts. Has to be called after DefaultBinning() and DefaultCuts() + specificCuts(tc.fWhichSpecificCuts); // after default cuts are applied, on top of them apply analysis-specific cuts. Has to be called after defaultBinning() and defaultCuts() } // *) Insanity checks before booking: - InsanityChecksBeforeBooking(); // check only hardwired values and the ones obtained from configurables + insanityChecksBeforeBooking(); // check only hardwired values and the ones obtained from configurables // *) Book random generator: delete gRandom; gRandom = new TRandom3(tc.fRandomSeed); // if uiSeed is 0, the seed is determined uniquely in space and time via TUUID // *) Book base list: - BookBaseList(); + bookBaseList(); // *) Book all remaining objects; - BookAndNestAllLists(); - BookResultsHistograms(); // yes, this one has to be booked first, because it defines the common binning for other groups of histograms TBI 20250412 this is true only if I can use Clone() - BookQAHistograms(); - BookEventHistograms(); - BookEventCutsHistograms(); - BookParticleHistograms(); - BookParticleCutsHistograms(); - BookQvectorHistograms(); - BookCorrelationsHistograms(); - BookWeightsHistograms(); - BookCentralityWeightsHistograms(); - BookNestedLoopsHistograms(); - BookNUAHistograms(); - BookInternalValidationHistograms(); - BookTest0Histograms(); - BookEtaSeparationsHistograms(); - BookTheRest(); // I book everything that was not sorted (yet) in the specific functions above + bookAndNestAllLists(); + bookResultsHistograms(); // yes, this one has to be booked first, because it defines the common binning for other groups of histograms, w/ or w/o clonning + bookQAHistograms(); + bookEventHistograms(); + bookEventCutsHistograms(); + bookParticleHistograms(); + bookParticleCutsHistograms(); // memStatus: 50913 + bookQvectorHistograms(); // memStatus: 50913 (without differential q-vectors and eta separations) + bookCorrelationsHistograms(); + bookWeightsHistograms(); + bookCentralityWeightsHistograms(); + bookNestedLoopsHistograms(); + bookNUAHistograms(); + bookInternalValidationHistograms(); + bookTest0Histograms(); + bookEtaSeparationsHistograms(); + bookTheRest(); // I book everything that was not sorted (yet) in the specific functions above + // memStatus: 50913 (without differential q-vectors and eta separations) + + // *) I can purge a few objects used for common consistent booking across different groups of histograms: + purgeAfterBooking(); // *) Insanity checks after booking: - InsanityChecksAfterBooking(); // pointers of all local histograms, etc., are available, so I can do insanity checks directly on all booked objects + insanityChecksAfterBooking(); // pointers of all local histograms, etc., are available, so I can do insanity checks directly on all booked objects // *) Trick to avoid name clashes, part 2: TH1::AddDirectory(oldHistAddStatus); diff --git a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx index 2d35169f9e8..1a50269aa9b 100644 --- a/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx +++ b/PWGCF/MultiparticleCorrelations/Tasks/threeParticleCorrelations.cxx @@ -37,20 +37,30 @@ struct ThreeParticleCorrelations { // Analysis parameters float centMin = 0.0, centMax = 90.0; - float zvtxMax = 7.0; + float zvtxMax = 10.0; float v0PtMin = 0.6, v0PtMax = 12.0; float v0EtaMax = 0.72; float trackPtMin = 0.2, trackPtMax = 3.0; float trackEtaMax = 0.8; + // Track PID parameters double pionID = 0.0, kaonID = 1.0, protonID = 2.0; - float nSigma0 = 0.0, nSigma2 = 2.0, nSigma4 = 4.0; + float nSigma0 = 0.0, nSigma2 = 2.0, nSigma4 = 4.0, nSigma5 = 5.0; + // V0 filter parameters + float tpcNCrossedRowsMin = 70.0; + float decayRMin = 1.2, ctauMax = 30.0; + float cosPAMin = 0.995; + float dcaProtonMin = 0.05, dcaPionMin = 0.2; + int dcaV0DauMax = 1; + + // Track filter parameters float pionPtMin = 0.3, pionPtMax = 2.3, kaonPtMin = 0.5, kaonPtMax = 2.5, protonPtMin = 0.5, protonPtMax = 2.5; float pionPtMid = 1.5, kaonPtMid1 = 1.5, kaonPtMid2 = 2.0, protonPtMid = 0.7; - float dEtaMax = 0.05, dEtaMin = 0.022; - float dPhiStarMinOS = 0.075, dPhiStarMinSS = 0.12; + // RD filter parameters + float dEtaMax = 0.05, dEtaMin = 0.023; + float dPhiStarMinOS = 0.09, dPhiStarMinSS = 0.095; float rMin = 0.8, rMax = 2.5; // Lambda invariant mass fit @@ -112,7 +122,7 @@ struct ThreeParticleCorrelations { PresliceUnsorted perMCCol = aod::mccollisionlabel::mcCollisionId; ConfigurableAxis confCentBins{"confCentBins", {VARIABLE_WIDTH, 0.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f, 90.0f}, "ME Centrality binning"}; - ConfigurableAxis confZvtxBins{"confZvtxBins", {VARIABLE_WIDTH, -7.0f, -5.0f, -3.0f, -1.0f, 0.0f, 1.0f, 3.0f, 5.0f, 7.0f}, "ME Zvtx binning"}; + ConfigurableAxis confZvtxBins{"confZvtxBins", {VARIABLE_WIDTH, -10.0f, -8.0f, -6.0f, -4.0f, -2.0, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f}, "ME Zvtx binning"}; using BinningType = ColumnBinningPolicy; using BinningTypeMC = ColumnBinningPolicy; @@ -129,9 +139,11 @@ struct ThreeParticleCorrelations { TH3D** hEffPions = new TH3D*[2]; TH3D** hEffKaons = new TH3D*[2]; TH3D** hEffProtons = new TH3D*[2]; + TH3D** hEffLambdas = new TH3D*[2]; // Correlation variables int triggSign, assocSign; + double v0Efficiency; double candMass; double* assocPID; @@ -156,8 +168,8 @@ struct ThreeParticleCorrelations { // QA & PID rQARegistry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{3, 0, 3}}}); rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "All"); - rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "kNoSameBunchPileup"); - rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); + rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "kIsGoodZvtxFT0vsPV"); + rQARegistry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "kNoSameBunchPileup"); rQARegistry.add("hEventCentrality", "hEventCentrality", {HistType::kTH1D, {{centralityAxis}}}); rQARegistry.add("hEventCentrality_MC", "hEventCentrality_MC", {HistType::kTH1D, {{centralityAxis}}}); @@ -165,15 +177,20 @@ struct ThreeParticleCorrelations { rQARegistry.add("hTrackPt", "hTrackPt", {HistType::kTH1D, {{100, 0, 4}}}); rQARegistry.add("hTrackEta", "hTrackEta", {HistType::kTH1D, {{100, -1, 1}}}); rQARegistry.add("hTrackPhi", "hTrackPhi", {HistType::kTH1D, {{100, (-1. / 2) * constants::math::PI, (5. / 2) * constants::math::PI}}}); - - rQARegistry.add("hPtPion", "hPtPion", {HistType::kTH2D, {{trackPtAxis}, {centralityAxis}}}); - rQARegistry.add("hPtKaon", "hPtKaon", {HistType::kTH2D, {{trackPtAxis}, {centralityAxis}}}); - rQARegistry.add("hPtProton", "hPtProton", {HistType::kTH2D, {{trackPtAxis}, {centralityAxis}}}); - rQARegistry.add("hPtV0", "hPtV0", {HistType::kTH2D, {{v0PtAxis}, {centralityAxis}}}); - rQARegistry.add("hPtPion_MC", "hPtPion_MC", {HistType::kTH2D, {{trackPtAxis}, {centralityAxis}}}); - rQARegistry.add("hPtKaon_MC", "hPtKaon_MC", {HistType::kTH2D, {{trackPtAxis}, {centralityAxis}}}); - rQARegistry.add("hPtProton_MC", "hPtProton_MC", {HistType::kTH2D, {{trackPtAxis}, {centralityAxis}}}); - rQARegistry.add("hPtV0_MC", "hPtV0_MC", {HistType::kTH2D, {{v0PtAxis}, {centralityAxis}}}); + rQARegistry.add("hTrackNSharedClusters", "hTrackNSharedClusters", {HistType::kTH1D, {{200, 0, 200}}}); + + rQARegistry.add("hPtPion_Uncorrected", "hPtPion_Uncorrected", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtKaon_Uncorrected", "hPtKaon_Uncorrected", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtProton_Uncorrected", "hPtProton_Uncorrected", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtV0_Uncorrected", "hPtV0_Uncorrected", {HistType::kTH3D, {{v0PtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtPion_Corrected", "hPtPion_Corrected", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtKaon_Corrected", "hPtKaon_Corrected", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtProton_Corrected", "hPtProton_Corrected", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtV0_Corrected", "hPtV0_Corrected", {HistType::kTH3D, {{v0PtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtPion_MC", "hPtPion_MC", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtKaon_MC", "hPtKaon_MC", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtProton_MC", "hPtProton_MC", {HistType::kTH3D, {{trackPtAxis}, {centralityAxis}, {2, -2, 2}}}); + rQARegistry.add("hPtV0_MC", "hPtV0_MC", {HistType::kTH3D, {{v0PtAxis}, {centralityAxis}, {2, -2, 2}}}); rQARegistry.add("hdEdx", "hdEdx", {HistType::kTH2D, {{56, 0.2, 3.0}, {180, 20, 200}}}); rQARegistry.add("hdEdxPion", "hdEdxPion", {HistType::kTH2D, {{56, 0.2, 3.0}, {180, 20, 200}}}); @@ -184,12 +201,12 @@ struct ThreeParticleCorrelations { rQARegistry.add("hBetaKaon", "hBetaKaon", {HistType::kTH2D, {{56, 0.2, 3.0}, {70, 0.4, 1.1}}}); rQARegistry.add("hBetaProton", "hBetaProton", {HistType::kTH2D, {{56, 0.2, 3.0}, {70, 0.4, 1.1}}}); - rQARegistry.add("hTPCPion", "hTPCPion", {HistType::kTH2D, {{trackPtAxis}, {241, -6, 6}}}); - rQARegistry.add("hTPCKaon", "hTPCKaon", {HistType::kTH2D, {{trackPtAxis}, {241, -6, 6}}}); - rQARegistry.add("hTPCProton", "hTPCProton", {HistType::kTH2D, {{trackPtAxis}, {241, -6, 6}}}); - rQARegistry.add("hTOFPion", "hTOFPion", {HistType::kTH2D, {{trackPtAxis}, {1000, -50, 50}}}); - rQARegistry.add("hTOFKaon", "hTOFKaon", {HistType::kTH2D, {{trackPtAxis}, {1000, -50, 50}}}); - rQARegistry.add("hTOFProton", "hTOFProton", {HistType::kTH2D, {{trackPtAxis}, {1000, -50, 50}}}); + rQARegistry.add("hTPCPion", "hTPCPion", {HistType::kTH2D, {{trackPtAxis}, {1001, -50.05, 50.05}}}); + rQARegistry.add("hTPCKaon", "hTPCKaon", {HistType::kTH2D, {{trackPtAxis}, {1001, -50.05, 50.05}}}); + rQARegistry.add("hTPCProton", "hTPCProton", {HistType::kTH2D, {{trackPtAxis}, {1001, -50.05, 50.05}}}); + rQARegistry.add("hTOFPion", "hTOFPion", {HistType::kTH2D, {{trackPtAxis}, {1001, -50.05, 50.05}}}); + rQARegistry.add("hTOFKaon", "hTOFKaon", {HistType::kTH2D, {{trackPtAxis}, {1001, -50.05, 50.05}}}); + rQARegistry.add("hTOFProton", "hTOFProton", {HistType::kTH2D, {{trackPtAxis}, {1001, -50.05, 50.05}}}); rQARegistry.add("hInvMassLambda", "hInvMassLambda", {HistType::kTH3D, {{lambdaInvMassAxis}, {v0PtAxis}, {centralityAxis}}}); rQARegistry.add("hInvMassAntiLambda", "hInvMassAntiLambda", {HistType::kTH3D, {{lambdaInvMassAxis}, {v0PtAxis}, {centralityAxis}}}); @@ -198,27 +215,19 @@ struct ThreeParticleCorrelations { rQARegistry.add("hInvMassAntiLambda_MC", "hInvMassAntiLambda_MC", {HistType::kTH3D, {{lambdaInvMassAxis}, {v0PtAxis}, {centralityAxis}}}); // PhiStar - rPhiStarRegistry.add("hSEProtonPreCut_OS", "hSEProtonPreCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPreCut_SS", "hSEProtonPreCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPreCut_SSP", "hSEProtonPreCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPreCut_SSN", "hSEProtonPreCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_OS", "hSEProtonPostCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_SS", "hSEProtonPostCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_SSP", "hSEProtonPostCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hSEProtonPostCut_SSN", "hSEProtonPostCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_OS", "hSEPhiStarIR_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_SS", "hSEPhiStarIR_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_SSP", "hSEPhiStarIR_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hSEPhiStarIR_SSN", "hSEPhiStarIR_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hSEPhiStarMean_OS", "hSEPhiStarMean_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); 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("hMEProtonPreCut_OS", "hMEProtonPreCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPreCut_SS", "hMEProtonPreCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPreCut_SSP", "hMEProtonPreCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPreCut_SSN", "hMEProtonPreCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_OS", "hMEProtonPostCut_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_SS", "hMEProtonPostCut_SS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_SSP", "hMEProtonPostCut_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); - rPhiStarRegistry.add("hMEProtonPostCut_SSN", "hMEProtonPostCut_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + 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}}}); + rPhiStarRegistry.add("hMEPhiStarIR_SSP", "hMEPhiStarIR_SSP", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); + rPhiStarRegistry.add("hMEPhiStarIR_SSN", "hMEPhiStarIR_SSN", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); rPhiStarRegistry.add("hMEPhiStarMean_OS", "hMEPhiStarMean_OS", {HistType::kTH2D, {{121, -0.3025, 0.3025}, {101, -0.0505, 0.0505}}}); 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}}}); @@ -250,10 +259,6 @@ struct ThreeParticleCorrelations { rMCRegistry.add("hPIDKaonN", "hPIDKaonN", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); rMCRegistry.add("hPIDProtonP", "hPIDProtonP", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); rMCRegistry.add("hPIDProtonN", "hPIDProtonN", {HistType::kTH3D, {{trackPtAxis}, {trackEtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaP_SGNL", "hPIDLambdaP_SGNL", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaP_SB", "hPIDLambdaP_SB", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaN_SGNL", "hPIDLambdaN_SGNL", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); - rMCRegistry.add("hPIDLambdaN_SB", "hPIDLambdaN_SB", {HistType::kTH3D, {{v0PtAxis}, {v0EtaAxis}, {centralityAxis}}}); // Purity rMCRegistry.add("hSelectPionP", "hSelectPionP", {HistType::kTH1D, {trackPtAxis}}); @@ -306,13 +311,16 @@ struct ThreeParticleCorrelations { ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); - TList* efficiencyList = ccdb->getForTimeStamp("Users/j/jstaa/Efficiency/ChargedParticles", 1); - hEffPions[0] = static_cast(efficiencyList->FindObject("hEfficiencyPionP")); - hEffPions[1] = static_cast(efficiencyList->FindObject("hEfficiencyPionN")); - hEffKaons[0] = static_cast(efficiencyList->FindObject("hEfficiencyKaonP")); - hEffKaons[1] = static_cast(efficiencyList->FindObject("hEfficiencyKaonN")); - hEffProtons[0] = static_cast(efficiencyList->FindObject("hEfficiencyProtonP")); - hEffProtons[1] = static_cast(efficiencyList->FindObject("hEfficiencyProtonN")); + TList* effListChargedParticles = ccdb->getForTimeStamp("Users/j/jstaa/Efficiency/ChargedParticles", 1); + TList* effListLambdas = ccdb->getForTimeStamp("Users/j/jstaa/Efficiency/Lambdas", 1); + hEffPions[0] = static_cast(effListChargedParticles->FindObject("hEfficiencyPionP")); + hEffPions[1] = static_cast(effListChargedParticles->FindObject("hEfficiencyPionN")); + hEffKaons[0] = static_cast(effListChargedParticles->FindObject("hEfficiencyKaonP")); + hEffKaons[1] = static_cast(effListChargedParticles->FindObject("hEfficiencyKaonN")); + hEffProtons[0] = static_cast(effListChargedParticles->FindObject("hEfficiencyProtonP")); + hEffProtons[1] = static_cast(effListChargedParticles->FindObject("hEfficiencyProtonN")); + hEffLambdas[0] = static_cast(effListLambdas->FindObject("hEfficiencyLambdaP")); + hEffLambdas[1] = static_cast(effListLambdas->FindObject("hEfficiencyLambdaN")); } //========================================================================================================================================================================================================================================================================== @@ -345,18 +353,22 @@ struct ThreeParticleCorrelations { rQARegistry.fill(HIST("hTrackPt"), track.pt()); rQARegistry.fill(HIST("hTrackEta"), track.eta()); rQARegistry.fill(HIST("hTrackPhi"), track.phi()); + rQARegistry.fill(HIST("hTrackNSharedClusters"), track.tpcNClsShared()); rQARegistry.fill(HIST("hdEdx"), track.pt(), track.tpcSignal()); rQARegistry.fill(HIST("hBeta"), track.pt(), track.beta()); if (assocPID[0] == pionID) { // Pions - rQARegistry.fill(HIST("hPtPion"), track.pt(), collision.centFT0C(), 1. / trackEff(hEffPions, track, collision.centFT0C())); + rQARegistry.fill(HIST("hPtPion_Uncorrected"), track.pt(), collision.centFT0C(), track.sign()); + rQARegistry.fill(HIST("hPtPion_Corrected"), track.pt(), collision.centFT0C(), track.sign(), 1. / trackEff(hEffPions, track, collision.centFT0C())); rQARegistry.fill(HIST("hdEdxPion"), track.pt(), track.tpcSignal()); rQARegistry.fill(HIST("hBetaPion"), track.pt(), track.beta()); } else if (assocPID[0] == kaonID) { // Kaons - rQARegistry.fill(HIST("hPtKaon"), track.pt(), collision.centFT0C(), 1. / trackEff(hEffKaons, track, collision.centFT0C())); + rQARegistry.fill(HIST("hPtKaon_Uncorrected"), track.pt(), collision.centFT0C(), track.sign()); + rQARegistry.fill(HIST("hPtKaon_Corrected"), track.pt(), collision.centFT0C(), track.sign(), 1. / trackEff(hEffKaons, track, collision.centFT0C())); rQARegistry.fill(HIST("hdEdxKaon"), track.pt(), track.tpcSignal()); rQARegistry.fill(HIST("hBetaKaon"), track.pt(), track.beta()); } else if (assocPID[0] == protonID) { // Protons - rQARegistry.fill(HIST("hPtProton"), track.pt(), collision.centFT0C(), 1. / trackEff(hEffProtons, track, collision.centFT0C())); + rQARegistry.fill(HIST("hPtProton_Uncorrected"), track.pt(), collision.centFT0C(), track.sign()); + rQARegistry.fill(HIST("hPtProton_Corrected"), track.pt(), collision.centFT0C(), track.sign(), 1. / trackEff(hEffProtons, track, collision.centFT0C())); rQARegistry.fill(HIST("hdEdxProton"), track.pt(), track.tpcSignal()); rQARegistry.fill(HIST("hBetaProton"), track.pt(), track.beta()); } @@ -366,16 +378,19 @@ struct ThreeParticleCorrelations { // Start of the Same-Event correlations for (const auto& trigger : v0s) { - if (v0Filters(trigger, false)) { + if (v0Filters(collision, trigger, tracks)) { - rQARegistry.fill(HIST("hPtV0"), trigger.pt(), collision.centFT0C()); triggSign = v0Sign(trigger); + v0Efficiency = v0Eff(hEffLambdas, trigger, collision.centFT0C()); + + rQARegistry.fill(HIST("hPtV0_Uncorrected"), trigger.pt(), collision.centFT0C(), triggSign); + rQARegistry.fill(HIST("hPtV0_Corrected"), trigger.pt(), collision.centFT0C(), triggSign, 1. / v0Efficiency); if (triggSign == 1) { candMass = trigger.mLambda(); - rQARegistry.fill(HIST("hInvMassLambda"), trigger.mLambda(), trigger.pt(), collision.centFT0C()); + rQARegistry.fill(HIST("hInvMassLambda"), trigger.mLambda(), trigger.pt(), collision.centFT0C(), 1. / v0Efficiency); } else if (triggSign == -1) { candMass = trigger.mAntiLambda(); - rQARegistry.fill(HIST("hInvMassAntiLambda"), trigger.mAntiLambda(), trigger.pt(), collision.centFT0C()); + rQARegistry.fill(HIST("hInvMassAntiLambda"), trigger.mAntiLambda(), trigger.pt(), collision.centFT0C(), 1. / v0Efficiency); } for (const auto& associate : tracks) { @@ -388,36 +403,36 @@ struct ThreeParticleCorrelations { if (candMass >= MassLambda0 - 4 * dGaussSigma && candMass <= MassLambda0 + 4 * dGaussSigma) { if (assocPID[0] == pionID) { // Pions - rSECorrRegistry.fill(HIST("hSameLambdaPion_SGNL"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaPion_SGNL"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, collision.centFT0C()) * v0Efficiency)); } else if (assocPID[0] == kaonID) { // Kaons - rSECorrRegistry.fill(HIST("hSameLambdaKaon_SGNL"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaKaon_SGNL"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, collision.centFT0C()) * v0Efficiency)); } else if (assocPID[0] == protonID) { // Protons - rSECorrRegistry.fill(HIST("hSameLambdaProton_SGNL"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaProton_SGNL"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, collision.centFT0C()) * v0Efficiency)); } } else if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { if (assocPID[0] == pionID) { // Pions - rSECorrRegistry.fill(HIST("hSameLambdaPion_SB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaPion_SB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, collision.centFT0C()) * v0Efficiency)); if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass < MassLambda0 - 4 * dGaussSigma) { - rSECorrRegistry.fill(HIST("hSameLambdaPion_leftSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaPion_leftSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, collision.centFT0C()) * v0Efficiency)); } else if (candMass > MassLambda0 + 4 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rSECorrRegistry.fill(HIST("hSameLambdaPion_rightSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaPion_rightSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, collision.centFT0C()) * v0Efficiency)); } } else if (assocPID[0] == kaonID) { // Kaons - rSECorrRegistry.fill(HIST("hSameLambdaKaon_SB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaKaon_SB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, collision.centFT0C()) * v0Efficiency)); if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass < MassLambda0 - 4 * dGaussSigma) { - rSECorrRegistry.fill(HIST("hSameLambdaKaon_leftSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaKaon_leftSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, collision.centFT0C()) * v0Efficiency)); } else if (candMass > MassLambda0 + 4 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rSECorrRegistry.fill(HIST("hSameLambdaKaon_rightSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaKaon_rightSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, collision.centFT0C()) * v0Efficiency)); } } else if (assocPID[0] == protonID) { // Protons - rSECorrRegistry.fill(HIST("hSameLambdaProton_SB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaProton_SB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, collision.centFT0C()) * v0Efficiency)); if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass < MassLambda0 - 4 * dGaussSigma) { - rSECorrRegistry.fill(HIST("hSameLambdaProton_leftSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaProton_leftSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, collision.centFT0C()) * v0Efficiency)); } else if (candMass > MassLambda0 + 4 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rSECorrRegistry.fill(HIST("hSameLambdaProton_rightSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, collision.centFT0C())); + rSECorrRegistry.fill(HIST("hSameLambdaProton_rightSB"), deltaPhi, deltaEta, collision.centFT0C(), collision.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, collision.centFT0C()) * v0Efficiency)); } } } @@ -429,7 +444,7 @@ struct ThreeParticleCorrelations { // End of the Same-Event correlations } - void processMixed(MyFilteredCollisions const&, aod::V0Datas const&, MyFilteredTracks const&, aod::BCsWithTimestamps const&) + void processMixed(MyFilteredCollisions const&, aod::V0Datas const&, MyFilteredTracks const& tracks, aod::BCsWithTimestamps const&) { // Start of the Mixed-Event correlations @@ -441,10 +456,12 @@ struct ThreeParticleCorrelations { auto bc = coll_1.bc_as(); auto bField = getMagneticField(bc.timestamp()); for (const auto& [trigger, associate] : soa::combinations(soa::CombinationsFullIndexPolicy(v0_1, track_2))) { - if (v0Filters(trigger, false) && trackFilters(associate)) { + if (v0Filters(coll_1, trigger, tracks) && trackFilters(associate)) { if (radialDistanceFilter(trigger, associate, bField, true) && fakeV0Filter(trigger, associate)) { triggSign = v0Sign(trigger); + v0Efficiency = v0Eff(hEffLambdas, trigger, coll_1.centFT0C()); + if (triggSign == 1) { candMass = trigger.mLambda(); } else if (triggSign == -1) { @@ -457,36 +474,36 @@ struct ThreeParticleCorrelations { if (candMass >= MassLambda0 - 4 * dGaussSigma && candMass <= MassLambda0 + 4 * dGaussSigma) { if (assocPID[0] == pionID) { // Pions - rMECorrRegistry.fill(HIST("hMixLambdaPion_SGNL"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaPion_SGNL"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, coll_1.centFT0C()) * v0Efficiency)); } else if (assocPID[0] == kaonID) { // Kaons - rMECorrRegistry.fill(HIST("hMixLambdaKaon_SGNL"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaKaon_SGNL"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, coll_1.centFT0C()) * v0Efficiency)); } else if (assocPID[0] == protonID) { // Protons - rMECorrRegistry.fill(HIST("hMixLambdaProton_SGNL"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaProton_SGNL"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, coll_1.centFT0C()) * v0Efficiency)); } } else if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { if (assocPID[0] == pionID) { // Pions - rMECorrRegistry.fill(HIST("hMixLambdaPion_SB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaPion_SB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, coll_1.centFT0C()) * v0Efficiency)); if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass < MassLambda0 - 4 * dGaussSigma) { - rMECorrRegistry.fill(HIST("hMixLambdaPion_leftSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaPion_leftSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, coll_1.centFT0C()) * v0Efficiency)); } else if (candMass > MassLambda0 + 4 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rMECorrRegistry.fill(HIST("hMixLambdaPion_rightSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffPions, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaPion_rightSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffPions, associate, coll_1.centFT0C()) * v0Efficiency)); } } else if (assocPID[0] == kaonID) { // Kaons - rMECorrRegistry.fill(HIST("hMixLambdaKaon_SB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaKaon_SB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, coll_1.centFT0C()) * v0Efficiency)); if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass < MassLambda0 - 4 * dGaussSigma) { - rMECorrRegistry.fill(HIST("hMixLambdaKaon_leftSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaKaon_leftSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, coll_1.centFT0C()) * v0Efficiency)); } else if (candMass > MassLambda0 + 4 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rMECorrRegistry.fill(HIST("hMixLambdaKaon_rightSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffKaons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaKaon_rightSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffKaons, associate, coll_1.centFT0C()) * v0Efficiency)); } } else if (assocPID[0] == protonID) { // Protons - rMECorrRegistry.fill(HIST("hMixLambdaProton_SB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaProton_SB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, coll_1.centFT0C()) * v0Efficiency)); if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass < MassLambda0 - 4 * dGaussSigma) { - rMECorrRegistry.fill(HIST("hMixLambdaProton_leftSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaProton_leftSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, coll_1.centFT0C()) * v0Efficiency)); } else if (candMass > MassLambda0 + 4 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rMECorrRegistry.fill(HIST("hMixLambdaProton_rightSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / trackEff(hEffProtons, associate, coll_1.centFT0C())); + rMECorrRegistry.fill(HIST("hMixLambdaProton_rightSB"), deltaPhi, deltaEta, coll_1.centFT0C(), coll_1.posZ(), triggSign, associate.sign(), 1. / (trackEff(hEffProtons, associate, coll_1.centFT0C()) * v0Efficiency)); } } } @@ -516,12 +533,18 @@ struct ThreeParticleCorrelations { for (const auto& track : groupMCAssociates) { if (track.isPhysicalPrimary()) { + if (track.pdgCode() > 0) { + assocSign = 1; + } else if (track.pdgCode() < 0) { + assocSign = -1; + } + if (std::abs(track.pdgCode()) == kPiPlus) { // Pions - rQARegistry.fill(HIST("hPtPion_MC"), track.pt(), collision.bestCollisionCentFT0C()); + rQARegistry.fill(HIST("hPtPion_MC"), track.pt(), collision.bestCollisionCentFT0C(), assocSign); } else if (std::abs(track.pdgCode()) == kKPlus) { // Kaons - rQARegistry.fill(HIST("hPtKaon_MC"), track.pt(), collision.bestCollisionCentFT0C()); + rQARegistry.fill(HIST("hPtKaon_MC"), track.pt(), collision.bestCollisionCentFT0C(), assocSign); } else if (std::abs(track.pdgCode()) == kProton) { // Protons - rQARegistry.fill(HIST("hPtProton_MC"), track.pt(), collision.bestCollisionCentFT0C()); + rQARegistry.fill(HIST("hPtProton_MC"), track.pt(), collision.bestCollisionCentFT0C(), assocSign); } } } @@ -531,12 +554,12 @@ struct ThreeParticleCorrelations { for (const auto& trigger : groupMCTriggers) { if (trigger.isPhysicalPrimary()) { - rQARegistry.fill(HIST("hPtV0_MC"), trigger.pt(), collision.bestCollisionCentFT0C()); if (trigger.pdgCode() > 0) { triggSign = 1; } else if (trigger.pdgCode() < 0) { triggSign = -1; } + rQARegistry.fill(HIST("hPtV0_MC"), trigger.pt(), collision.bestCollisionCentFT0C(), triggSign); rQARegistry.fill(HIST("hNLambdas"), triggSign, trigger.pt(), collision.bestCollisionCentFT0C()); for (const auto& associate : groupMCAssociates) { @@ -758,42 +781,24 @@ struct ThreeParticleCorrelations { for (const auto& v0 : v0s) { - if (!v0.has_mcParticle() || v0.pt() < v0PtMin || v0.pt() > v0PtMax || std::abs(v0.eta()) > v0EtaMax) { + if (!v0.has_mcParticle()) { continue; } - auto particle = v0.mcParticle(); - if (particle.isPhysicalPrimary()) { + if (v0Filters(collision, v0, tracks)) { + + v0Efficiency = v0Eff(hEffLambdas, v0, collision.centFT0C()); // V0 efficiency - Reconstructed - if (particle.pdgCode() == kLambda0) { // Lambdas + if (v0Sign(v0) == 1) { // Lambdas + candMass = v0.mLambda(); + rQARegistry.fill(HIST("hInvMassLambda_MC"), v0.mLambda(), v0.pt(), collision.centFT0C(), 1. / v0Efficiency); rMCRegistry.fill(HIST("hRecLambdaP"), v0.pt(), v0.eta(), collision.centFT0C()); - } else if (particle.pdgCode() == kLambda0Bar) { // AntiLambdas + } else if (v0Sign(v0) == -1) { // AntiLambdas + candMass = v0.mAntiLambda(); + rQARegistry.fill(HIST("hInvMassAntiLambda_MC"), v0.mAntiLambda(), v0.pt(), collision.centFT0C(), 1. / v0Efficiency); rMCRegistry.fill(HIST("hRecLambdaN"), v0.pt(), v0.eta(), collision.centFT0C()); } - - if (v0Filters(v0, true)) { - - // V0 efficiency - Reconstructed - if (v0Sign(v0) == 1) { // Lambdas - candMass = v0.mLambda(); - rQARegistry.fill(HIST("hInvMassLambda_MC"), v0.mLambda(), v0.pt(), collision.centFT0C()); - if (candMass >= MassLambda0 - 4 * dGaussSigma && candMass <= MassLambda0 + 4 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaP_SGNL"), v0.pt(), v0.eta(), collision.centFT0C()); - } else if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaP_SB"), v0.pt(), v0.eta(), collision.centFT0C()); - } - - } else if (v0Sign(v0) == -1) { // AntiLambdas - candMass = v0.mAntiLambda(); - rQARegistry.fill(HIST("hInvMassAntiLambda_MC"), v0.mAntiLambda(), v0.pt(), collision.centFT0C()); - if (candMass >= MassLambda0 - 4 * dGaussSigma && candMass <= MassLambda0 + 4 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaN_SGNL"), v0.pt(), v0.eta(), collision.centFT0C()); - } else if (candMass >= MassLambda0 - 8 * dGaussSigma && candMass <= MassLambda0 + 8 * dGaussSigma) { - rMCRegistry.fill(HIST("hPIDLambdaN_SB"), v0.pt(), v0.eta(), collision.centFT0C()); - } - } - } } } // End of the Monte-Carlo reconstructed QA @@ -823,6 +828,25 @@ struct ThreeParticleCorrelations { return 0.1 * (grpo->getNominalL3Field()); // 1 T = 10 kG } + template + double v0Eff(TH3D** efficiencies, const V0Cand& v0, double centrality) + { + + int index = -999; + if (v0Sign(v0) > 0) { + index = 0; + } else if (v0Sign(v0) < 0) { + index = 1; + } + + double efficiency = efficiencies[index]->GetBinContent(efficiencies[index]->FindBin(v0.pt(), v0.eta(), centrality)); + if (efficiency > 0) { + return efficiency; + } else { + return 1.0; + } + } + template double trackEff(TH3D** efficiencies, const TrackCand& track, double centrality) { @@ -887,67 +911,81 @@ struct ThreeParticleCorrelations { //========================================================================================================================================================================================================================================================================== - template - bool acceptEvent(const CollCand& collision, bool FillHist) // Event filter + template + bool acceptEvent(const Col& col, bool FillHist) // Event filter { if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 0.5); } - if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { // kNoSameBunchPileup - return kFALSE; + if (!col.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { // kIsGoodZvtxFT0vsPV + return false; } if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 1.5); } - if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { // kIsGoodZvtxFT0vsPV - return kFALSE; + if (!col.selection_bit(aod::evsel::kNoSameBunchPileup)) { // kNoSameBunchPileup + return false; } if (FillHist) { rQARegistry.fill(HIST("hNEvents"), 2.5); } - return kTRUE; + return true; } - template - bool v0Filters(const V0Cand& v0, bool MCRec) // V0 filter + template + bool v0Filters(const Col& col, const V0Cand& v0, T const&) // V0 filter { - if (v0.pt() < v0PtMin || v0.pt() > v0PtMax) - return kFALSE; - if (std::abs(v0.eta()) > v0EtaMax) - return kFALSE; + // Kinematic cuts + if (v0.pt() <= v0PtMin || v0.pt() >= v0PtMax || std::abs(v0.eta()) >= v0EtaMax) { + return false; + } - if (!MCRec) { // Data - if (v0Sign(v0) == 1) { - const auto& posDaughter = v0.template posTrack_as(); - if (std::abs(posDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } - } else if (v0Sign(v0) == -1) { - const auto& negDaughter = v0.template negTrack_as(); - if (std::abs(negDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } + // Daughter cuts + auto posDaughter = v0.template posTrack_as(); + auto negDaughter = v0.template negTrack_as(); + if (std::abs(posDaughter.eta()) >= trackEtaMax || std::abs(negDaughter.eta()) >= trackEtaMax) { + return false; + } + if (posDaughter.tpcNClsCrossedRows() <= tpcNCrossedRowsMin || negDaughter.tpcNClsCrossedRows() <= tpcNCrossedRowsMin) { + return false; + } + if (v0Sign(v0) == 1) { + if (std::abs(posDaughter.tpcNSigmaPr()) >= nSigma5 || std::abs(negDaughter.tpcNSigmaPi()) >= nSigma5) { + return false; } - } else { // MC Reconstructed - if (v0Sign(v0) == 1) { - const auto& posDaughter = v0.template posTrack_as(); - if (std::abs(posDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } - } else if (v0Sign(v0) == -1) { - const auto& negDaughter = v0.template negTrack_as(); - if (std::abs(negDaughter.tpcNSigmaPr()) > nSigma4) { - return kFALSE; - } + if (std::abs(v0.dcapostopv()) <= dcaProtonMin || std::abs(v0.dcanegtopv()) <= dcaPionMin) { + return false; + } + } else if (v0Sign(v0) == -1) { + if (std::abs(posDaughter.tpcNSigmaPi()) >= nSigma5 || std::abs(negDaughter.tpcNSigmaPr()) >= nSigma5) { + return false; + } + if (std::abs(v0.dcapostopv()) <= dcaPionMin || std::abs(v0.dcanegtopv()) <= dcaProtonMin) { + return false; } } - return kTRUE; + // Topological cuts + float ctau = v0.distovertotmom(col.posX(), col.posY(), col.posZ()) * MassLambda0; + if (v0.v0radius() <= decayRMin) { + return false; + } + if (ctau >= ctauMax) { + return false; + } + if (v0.v0cosPA() <= cosPAMin) { + return false; + } + if (v0.dcaV0daughters() >= dcaV0DauMax) { + return false; + } + + return true; } template @@ -955,71 +993,71 @@ struct ThreeParticleCorrelations { { if (!track.hasTOF()) { - return kFALSE; + return false; } if (trackPID(track)[0] == pionID) { // Pions - if (std::abs(track.tpcNSigmaPi()) > nSigma4) { - return kFALSE; + if (std::abs(track.tpcNSigmaPi()) >= nSigma4) { + return false; } if (track.pt() < pionPtMin) { - return kFALSE; + return false; } else if (track.pt() > pionPtMin && track.pt() < pionPtMid) { - if (std::abs(track.tofNSigmaPi()) > nSigma4) { - return kFALSE; + if (std::abs(track.tofNSigmaPi()) >= nSigma4) { + return false; } } else if (track.pt() > pionPtMid && track.pt() < pionPtMax) { - if (track.tofNSigmaPi() < -nSigma4 || track.tofNSigmaPi() > nSigma0) { - return kFALSE; + if (track.tofNSigmaPi() <= -nSigma4 || track.tofNSigmaPi() >= nSigma0) { + return false; } } else if (track.pt() > pionPtMax) { - return kFALSE; + return false; } } else if (trackPID(track)[0] == kaonID) { // Kaons - if (std::abs(track.tpcNSigmaKa()) > nSigma4) { - return kFALSE; + if (std::abs(track.tpcNSigmaKa()) >= nSigma4) { + return false; } if (track.pt() < kaonPtMin) { - return kFALSE; + return false; } else if (track.pt() > kaonPtMin && track.pt() < kaonPtMid1) { - if (std::abs(track.tofNSigmaKa()) > nSigma4) { - return kFALSE; + if (std::abs(track.tofNSigmaKa()) >= nSigma4) { + return false; } } else if (track.pt() > kaonPtMid1 && track.pt() < kaonPtMid2) { - if (track.tofNSigmaKa() < -nSigma2 || track.tofNSigmaKa() > nSigma4) { - return kFALSE; + if (track.tofNSigmaKa() <= -nSigma2 || track.tofNSigmaKa() >= nSigma4) { + return false; } } else if (track.pt() > kaonPtMid2 && track.pt() < kaonPtMax) { - if (track.tofNSigmaKa() < nSigma0 || track.tofNSigmaKa() > nSigma4) { - return kFALSE; + if (track.tofNSigmaKa() <= nSigma0 || track.tofNSigmaKa() >= nSigma4) { + return false; } } else if (track.pt() > kaonPtMax) { - return kFALSE; + return false; } } else if (trackPID(track)[0] == protonID) { // Protons - if (std::abs(track.tpcNSigmaPr()) > nSigma4) { - return kFALSE; + if (std::abs(track.tpcNSigmaPr()) >= nSigma4) { + return false; } if (track.pt() < protonPtMin) { - return kFALSE; + return false; } else if (track.pt() > protonPtMin && track.pt() < protonPtMid) { - if (track.tofNSigmaPr() < -nSigma2 || track.tofNSigmaPr() > nSigma4) { - return kFALSE; + if (track.tofNSigmaPr() <= -nSigma2 || track.tofNSigmaPr() >= nSigma4) { + return false; } } else if (track.pt() > protonPtMid && track.pt() < protonPtMax) { - if (std::abs(track.tofNSigmaPr()) > nSigma4) { - return kFALSE; + if (std::abs(track.tofNSigmaPr()) >= nSigma4) { + return false; } } else if (track.pt() > protonPtMax) { - if (track.tofNSigmaPr() < -nSigma2 || track.tofNSigmaPr() > nSigma4) { - return kFALSE; + if (track.tofNSigmaPr() <= -nSigma2 || track.tofNSigmaPr() >= nSigma4) { + return false; } } } - return kTRUE; + return true; } template @@ -1027,10 +1065,10 @@ struct ThreeParticleCorrelations { { if (track.globalIndex() == v0.posTrackId() || track.globalIndex() == v0.negTrackId()) { - return kFALSE; + return false; } - return kTRUE; + return true; } template @@ -1040,7 +1078,7 @@ struct ThreeParticleCorrelations { if (confFakeV0Switch) { if (trackPID(track)[0] == kaonID) { // Kaons - return kTRUE; + return true; } std::array massArray; @@ -1070,11 +1108,11 @@ struct ThreeParticleCorrelations { double invMass = RecoDecay::m(std::array{dMomArray, aMomArray}, massArray); if (invMass >= MassLambda0 - 4 * dGaussSigma && invMass <= MassLambda0 + 4 * dGaussSigma) { - return kFALSE; + return false; } } - return kTRUE; + return true; } template @@ -1108,69 +1146,36 @@ struct ThreeParticleCorrelations { if (r == rMin) { if (!Mix) { // Same-event if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_OS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_OS"), dPhiStar, dEta); } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_SS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_SS"), dPhiStar, dEta); if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_SSP"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_SSP"), dPhiStar, dEta); } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hSEProtonPreCut_SSN"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hSEPhiStarIR_SSN"), dPhiStar, dEta); } } } else { // Mixed-event if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_OS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_OS"), dPhiStar, dEta); } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_SS"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_SS"), dPhiStar, dEta); if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_SSP"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_SSP"), dPhiStar, dEta); } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hMEProtonPreCut_SSN"), dPhiStar, dEta); + rPhiStarRegistry.fill(HIST("hMEPhiStarIR_SSN"), dPhiStar, dEta); } } } - } - if (std::abs(dEta) < dEtaMin) { if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - if (std::abs(dPhiStar) < dPhiStarMinOS) { - pass = false; - } - } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - if (std::abs(dPhiStar) < dPhiStarMinSS) { + if (std::abs(dEta) < dEtaMin && std::abs(dPhiStar) < dPhiStarMinOS) { pass = false; } } } - if (r == rMin && pass) { - if (!Mix) { // Same-event - if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_OS"), dPhiStar, dEta); - } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_SS"), dPhiStar, dEta); - if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_SSP"), dPhiStar, dEta); - } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hSEProtonPostCut_SSN"), dPhiStar, dEta); - } - } - - } else { // Mixed-event - if (proton.sign() * track.sign() == -1) { // OS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_OS"), dPhiStar, dEta); - } else if (proton.sign() * track.sign() == 1) { // SS (Electric charge) - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_SS"), dPhiStar, dEta); - if (proton.sign() == 1) { // Positive - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_SSP"), dPhiStar, dEta); - } else if (proton.sign() == -1) { // Negative - rPhiStarRegistry.fill(HIST("hMEProtonPostCut_SSN"), dPhiStar, dEta); - } - } - } - } - dPhiStarMean += (dPhiStar / 170); } // End of the TPC radius loop @@ -1199,6 +1204,12 @@ struct ThreeParticleCorrelations { } } } + + if (proton.sign() * track.sign() == 1) { // SS (Electric charge) + if (std::abs(dEta) < dEtaMin && std::abs(dPhiStarMean) < dPhiStarMinSS) { + pass = false; + } + } } return pass; diff --git a/PWGCF/TableProducer/filter2Prong.cxx b/PWGCF/TableProducer/filter2Prong.cxx index 25bee387660..00f7bb58827 100644 --- a/PWGCF/TableProducer/filter2Prong.cxx +++ b/PWGCF/TableProducer/filter2Prong.cxx @@ -11,31 +11,36 @@ /// \author Jasper Parkkila -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "MathUtils/detail/TypeTruncation.h" - #include "PWGCF/DataModel/CorrelationsDerived.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/DataModel/PIDResponseITS.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "MathUtils/detail/TypeTruncation.h" + #include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::math_utils::detail; +enum LambdaPid { kLambda = 0, + kAntiLambda +}; + // #define FLOAT_PRECISION 0xFFFFFFF0 #define O2_DEFINE_CONFIGURABLE(NAME, TYPE, DEFAULT, HELP) Configurable NAME{#NAME, DEFAULT, HELP}; @@ -46,10 +51,58 @@ struct Filter2Prong { O2_DEFINE_CONFIGURABLE(cfgImPart2Mass, float, o2::constants::physics::MassKMinus, "Daughter particle 2 mass in GeV") O2_DEFINE_CONFIGURABLE(cfgImPart1PID, int, o2::track::PID::Kaon, "PID of daughter particle 1 (O2 PID ID)") O2_DEFINE_CONFIGURABLE(cfgImPart2PID, int, o2::track::PID::Kaon, "PID of daughter particle 2 (O2 PID ID)") + O2_DEFINE_CONFIGURABLE(cfgMomDepPID, bool, 1, "Use mommentum dependent PID for Phi meson") O2_DEFINE_CONFIGURABLE(cfgImCutPt, float, 0.2f, "Minimal pT for candidates") - O2_DEFINE_CONFIGURABLE(cfgImMinInvMass, float, 0.95f, "Minimum invariant mass (GeV)") - O2_DEFINE_CONFIGURABLE(cfgImMaxInvMass, float, 1.07f, "Maximum invariant mass (GeV)") - O2_DEFINE_CONFIGURABLE(cfgImSigmaFormula, std::string, "(z < 0.5 && x < 3.0) || (z >= 0.5 && x < 2.5 && y < 3.0)", "pT dependent daughter track sigma pass condition (x = TPC sigma, y = TOF sigma, z = pT)") + O2_DEFINE_CONFIGURABLE(cfgImMinInvMass, float, 0.95f, "Minimum invariant mass for generic 2 prong") + O2_DEFINE_CONFIGURABLE(cfgImMaxInvMass, float, 1.07f, "Maximum invariant mass for generic 2 prong") + O2_DEFINE_CONFIGURABLE(cfgImSigmaFormula, std::string, "(([p] < 0.5 || [hasTOF] <= 0.0) && abs([sTPC]) < 3.0) || ([p] >= 0.5 && abs([sTPC]) < 2.5 && abs([sTOF]) < 3.0)", "pT dependent daughter track sigma pass condition. Parameters: [p] momentum, [sTPC] sigma TPC, [sTOF] sigma TOF, [hasTOF] has TOF.") + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(tpcNClsCrossedRowsTrackMin, float, 70, "Minimum number of crossed rows in TPC"); + O2_DEFINE_CONFIGURABLE(etaTrackMax, float, 0.8, "Maximum pseudorapidity"); + O2_DEFINE_CONFIGURABLE(ptTrackMin, float, 0.1, "Minimum transverse momentum"); + O2_DEFINE_CONFIGURABLE(minV0DCAPr, float, 0.1, "Min V0 proton DCA"); + O2_DEFINE_CONFIGURABLE(minV0DCAPiLambda, float, 0.1, "Min V0 pion DCA for lambda"); + O2_DEFINE_CONFIGURABLE(minV0DCAPiK0s, float, 0.1, "Min V0 pion DCA for K0s"); + O2_DEFINE_CONFIGURABLE(daughPIDCuts, float, 4.0, "PID nsigma for V0s"); + O2_DEFINE_CONFIGURABLE(massK0Min, float, 0.4, "Minimum mass for K0"); + O2_DEFINE_CONFIGURABLE(massK0Max, float, 0.6, "Maximum mass for K0"); + O2_DEFINE_CONFIGURABLE(massLambdaMin, float, 1.0, "Minimum mass for lambda"); + O2_DEFINE_CONFIGURABLE(massLambdaMax, float, 1.3, "Maximum mass for lambda"); + O2_DEFINE_CONFIGURABLE(radiusMaxLambda, float, 2.3, "Maximum decay radius (cm) for lambda"); + O2_DEFINE_CONFIGURABLE(radiusMinLambda, float, 0.0, "Minimum decay radius (cm) for lambda"); + O2_DEFINE_CONFIGURABLE(radiusMaxK0s, float, 2.3, "Maximum decay radius (cm) for K0s"); + O2_DEFINE_CONFIGURABLE(radiusMinK0s, float, 0.0, "Minimum decay radius (cm) for K0s"); + O2_DEFINE_CONFIGURABLE(cosPaMinLambda, float, 0.98, "Minimum cosine of pointing angle for lambda"); + O2_DEFINE_CONFIGURABLE(cosPaMinK0s, float, 0.98, "Minimum cosine of pointing angle for K0s"); + O2_DEFINE_CONFIGURABLE(dcaV0DaughtersMaxLambda, float, 0.2, "Maximum DCA among the V0 daughters (cm) for lambda"); + O2_DEFINE_CONFIGURABLE(dcaV0DaughtersMaxK0s, float, 0.2, "Maximum DCA among the V0 daughters (cm) for K0s"); + O2_DEFINE_CONFIGURABLE(qtArmenterosMinForK0s, float, 0.12, "Minimum Armenteros' qt for K0s"); + O2_DEFINE_CONFIGURABLE(maxLambdaLifeTime, float, 30, "Maximum lambda lifetime (in cm)"); + O2_DEFINE_CONFIGURABLE(maxK0sLifeTime, float, 30, "Maximum K0s lifetime (in cm)"); + } grpV0; + + struct : ConfigurableGroup { + O2_DEFINE_CONFIGURABLE(ImMinInvMassPhiMeson, float, 0.98f, "Minimum invariant mass Phi meson (GeV)"); + O2_DEFINE_CONFIGURABLE(ImMaxInvMassPhiMeson, float, 1.07f, "Maximum invariant mass Phi meson (GeV)"); + O2_DEFINE_CONFIGURABLE(ITSPIDSelection, bool, true, "PID ITS"); + O2_DEFINE_CONFIGURABLE(ITSPIDPthreshold, float, 1.0, "Momentum threshold for ITS PID (GeV/c) (only used if ITSPIDSelection is true)"); + O2_DEFINE_CONFIGURABLE(lowITSPIDNsigma, float, 3.0, "lower cut on PID nsigma for ITS"); + O2_DEFINE_CONFIGURABLE(highITSPIDNsigma, float, 3.0, "higher cut on PID nsigma for ITS"); + O2_DEFINE_CONFIGURABLE(ITSclusterPhiMeson, int, 5, "Minimum number of ITS cluster for phi meson track"); + O2_DEFINE_CONFIGURABLE(TPCCrossedRowsPhiMeson, int, 80, "Minimum number of TPC Crossed Rows for phi meson track"); + O2_DEFINE_CONFIGURABLE(cutDCAxyPhiMeson, float, 0.1, "Maximum DCAxy for phi meson track"); + O2_DEFINE_CONFIGURABLE(cutDCAzPhiMeson, float, 0.1, "Maximum DCAz for phi meson track"); + O2_DEFINE_CONFIGURABLE(cutEtaPhiMeson, float, 0.8, "Maximum eta for phi meson track"); + O2_DEFINE_CONFIGURABLE(cutPTPhiMeson, float, 0.15, "Maximum pt for phi meson track"); + O2_DEFINE_CONFIGURABLE(isDeepAngle, bool, true, "Flag for applying deep angle"); + O2_DEFINE_CONFIGURABLE(deepAngle, float, 0.04, "Deep angle cut"); + O2_DEFINE_CONFIGURABLE(nsigmaCutTPC, float, 2.5, "nsigma tpc"); + O2_DEFINE_CONFIGURABLE(nsigmaCutTOF, float, 2.5, "nsigma tof"); + O2_DEFINE_CONFIGURABLE(cutTOFBeta, float, 0.5, "TOF beta"); + O2_DEFINE_CONFIGURABLE(confFakeKaonCut, float, 0.15, "Cut based on track from momentum difference"); + O2_DEFINE_CONFIGURABLE(removefaketrack, bool, true, "Flag to remove fake kaon"); + } grpPhi; HfHelper hfHelper; Produces output2ProngTracks; @@ -62,16 +115,36 @@ struct Filter2Prong { using HFCandidates = soa::Join; using HFCandidatesML = soa::Join; + using HFCandidatesMCRecoML = soa::Join; template using HasMLProb = decltype(std::declval().mlProbD0()); + template + using HasFlagMcMatchRec = decltype(std::declval().flagMcMatchRec()); + + using PIDTrack = soa::Join; + using ResoV0s = aod::V0Datas; std::unique_ptr sigmaFormula; + std::array sigmaFormulaParamIndex; void init(InitContext&) { - if (doprocessDataInvMass) + if (doprocessDataInvMass) { sigmaFormula = std::make_unique("sigmaFormula", cfgImSigmaFormula.value.c_str()); + if (static_cast(sigmaFormula->GetNpar()) > std::size(sigmaFormulaParamIndex)) + LOGF(fatal, "Number of parameters in cfgImSigmaFormula can not be larger than %d.", std::size(sigmaFormulaParamIndex)); + // could do SetParameter(name,value) directly, but pre-lookup of the names will result in faster process + std::array pars = {"p", "sTPC", "sTOF", "hasTOF"}; + std::fill_n(sigmaFormulaParamIndex.begin(), std::size(sigmaFormulaParamIndex), ~0u); + for (uint i = 0, n = sigmaFormula->GetNpar(); i < n; ++i) { + auto m = std::find(pars.begin(), pars.end(), sigmaFormula->GetParName(i)); + if (m != pars.end()) + sigmaFormulaParamIndex[std::distance(pars.begin(), m)] = i; + else + LOGF(warning, "Unrecognized cfgImSigmaFormula parameter %s.", sigmaFormula->GetParName(i)); + } + } } template @@ -100,6 +173,10 @@ struct Filter2Prong { continue; if (cfgYMax >= 0.0f && std::abs(hfHelper.yD0(c)) > cfgYMax) continue; + if constexpr (std::experimental::is_detected::value) { + if (std::abs(c.flagMcMatchRec()) != o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) + continue; + } if (c.isSelD0() > 0) { output2ProngTracks(cfcollisions.begin().globalIndex(), @@ -143,13 +220,20 @@ struct Filter2Prong { } PROCESS_SWITCH(Filter2Prong, processData, "Process data D0 candidates", true); - void processMC(aod::McCollisions::iterator const&, aod::CFMcParticleRefs const& cfmcparticles, aod::McParticles const& mcparticles) + void processMCRecoML(aod::Collisions::iterator const& col, aod::BCsWithTimestamps const& bcs, aod::CFCollRefs const& cfcollisions, aod::CFTrackRefs const& cftracks, HFCandidatesMCRecoML const& candidates) + { + processDataT(col, bcs, cfcollisions, cftracks, candidates); + } + PROCESS_SWITCH(Filter2Prong, processMCRecoML, "Process data D0 candidates together with reco information and ML", false); + + using HFMCTrack = soa::Join; + void processMC(aod::McCollisions::iterator const&, aod::CFMcParticleRefs const& cfmcparticles, [[maybe_unused]] HFMCTrack const& mcparticles) { // The main filter outputs the primary MC particles. Here we just resolve the daughter indices that are needed for the efficiency matching. for (const auto& r : cfmcparticles) { - const auto& mcParticle = mcparticles.iteratorAt(r.mcParticleId()); - if (mcParticle.daughtersIds().size() != 2) { - output2ProngMcParts(-1, -1); + const auto& mcParticle = r.mcParticle_as(); + if ((std::abs(mcParticle.flagMcMatchGen()) != o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || mcParticle.daughtersIds().size() != 2) { + output2ProngMcParts(-1, -1, aod::cf2prongtrack::Generic2Prong); continue; } int prongCFId[2] = {-1, -1}; @@ -161,14 +245,195 @@ struct Filter2Prong { } } } - output2ProngMcParts(prongCFId[0], prongCFId[1]); + output2ProngMcParts(prongCFId[0], prongCFId[1], + (mcParticle.pdgCode() >= 0 ? aod::cf2prongtrack::D0ToPiK : aod::cf2prongtrack::D0barToKPi) | ((mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) ? aod::cf2prongmcpart::Prompt : 0)); } } PROCESS_SWITCH(Filter2Prong, processMC, "Process MC 2-prong daughters", false); + void processMCGeneric(aod::McCollisions::iterator const&, aod::CFMcParticleRefs const& cfmcparticles, [[maybe_unused]] aod::McParticles const& mcparticles) + { + // The main filter outputs the primary MC particles. Here we just resolve the daughter indices that are needed for the efficiency matching. + for (const auto& r : cfmcparticles) { + const auto& mcParticle = r.mcParticle(); + if (mcParticle.daughtersIds().size() != 2) { + output2ProngMcParts(-1, -1, aod::cf2prongtrack::Generic2Prong); // not a 2-prong + continue; + } + int prongCFId[2] = {-1, -1}; + for (uint i = 0; i < 2; ++i) { + for (const auto& cfmcpart : cfmcparticles) { + if (mcParticle.daughtersIds()[i] == cfmcpart.mcParticleId()) { + prongCFId[i] = cfmcpart.globalIndex(); + break; + } + } + } + output2ProngMcParts(prongCFId[0], prongCFId[1], aod::cf2prongtrack::Generic2Prong); // the 2-prong Phi, for example, can be checked through its daughters + } + } + PROCESS_SWITCH(Filter2Prong, processMCGeneric, "Process generic MC 2-prong daughters", false); + + template + bool selectionTrack(const T& candidate) + { + if (candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() >= grpPhi.ITSclusterPhiMeson && candidate.tpcNClsCrossedRows() > grpPhi.TPCCrossedRowsPhiMeson && std::abs(candidate.dcaXY()) <= grpPhi.cutDCAxyPhiMeson && std::abs(candidate.dcaZ()) <= grpPhi.cutDCAzPhiMeson && std::abs(candidate.eta()) <= grpPhi.cutEtaPhiMeson && candidate.pt() >= grpPhi.cutPTPhiMeson) { + return true; + } + return false; + } + + template + bool selectionPair(const T1& candidate1, const T2& candidate2) + { + double pt1, pt2, pz1, pz2, p1, p2, angle; + pt1 = candidate1.pt(); + pt2 = candidate2.pt(); + pz1 = candidate1.pz(); + pz2 = candidate2.pz(); + p1 = candidate1.p(); + p2 = candidate2.p(); + angle = TMath::ACos((pt1 * pt2 + pz1 * pz2) / (p1 * p2)); + if (grpPhi.isDeepAngle && angle < grpPhi.deepAngle) { + return false; + } + return true; + } + + template + bool isFakeTrack(T const& track) + { + const auto pglobal = track.p(); + const auto ptpc = track.tpcInnerParam(); + if (TMath::Abs(pglobal - ptpc) > grpPhi.confFakeKaonCut) { + return true; + } + return false; + } + + template + bool isSelectedV0AsK0s(Collision const& collision, const V0Cand& v0) + { + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + + float CtauK0s = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0; + + if (v0.mK0Short() < grpV0.massK0Min || v0.mK0Short() > grpV0.massK0Max) { + return false; + } + if ((v0.qtarm() / std::abs(v0.alpha())) < grpV0.qtArmenterosMinForK0s) { + return false; + } + if (v0.v0radius() > grpV0.radiusMaxK0s || v0.v0radius() < grpV0.radiusMinK0s) { + return false; + } + if (v0.v0cosPA() < grpV0.cosPaMinK0s) { + return false; + } + if (v0.dcaV0daughters() > grpV0.dcaV0DaughtersMaxK0s) { + return false; + } + if (std::abs(CtauK0s) > grpV0.maxK0sLifeTime) { + return false; + } + if (((std::abs(posTrack.tpcNSigmaPi()) > grpV0.daughPIDCuts) || (std::abs(negTrack.tpcNSigmaPi()) > grpV0.daughPIDCuts))) { + return false; + } + if ((TMath::Abs(v0.dcapostopv()) < grpV0.minV0DCAPiK0s || TMath::Abs(v0.dcanegtopv()) < grpV0.minV0DCAPiK0s)) { + return false; + } + return true; + } + + template + bool isSelectedV0AsLambda(Collision const& collision, const V0Cand& v0) + { + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + + float CtauLambda = v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda; + + if ((v0.mLambda() < grpV0.massLambdaMin || v0.mLambda() > grpV0.massLambdaMax) && + (v0.mAntiLambda() < grpV0.massLambdaMin || v0.mAntiLambda() > grpV0.massLambdaMax)) { + return false; + } + if (v0.v0radius() > grpV0.radiusMaxLambda || v0.v0radius() < grpV0.radiusMinLambda) { + return false; + } + if (v0.v0cosPA() < grpV0.cosPaMinLambda) { + return false; + } + if (v0.dcaV0daughters() > grpV0.dcaV0DaughtersMaxLambda) { + return false; + } + if (pid == LambdaPid::kLambda && (TMath::Abs(v0.dcapostopv()) < grpV0.minV0DCAPr || TMath::Abs(v0.dcanegtopv()) < grpV0.minV0DCAPiLambda)) { + return false; + } + if (pid == LambdaPid::kAntiLambda && (TMath::Abs(v0.dcapostopv()) < grpV0.minV0DCAPiLambda || TMath::Abs(v0.dcanegtopv()) < grpV0.minV0DCAPr)) { + return false; + } + if (pid == LambdaPid::kLambda && ((std::abs(posTrack.tpcNSigmaPr()) > grpV0.daughPIDCuts) || (std::abs(negTrack.tpcNSigmaPi()) > grpV0.daughPIDCuts))) { + return false; + } + if (pid == LambdaPid::kAntiLambda && ((std::abs(posTrack.tpcNSigmaPi()) > grpV0.daughPIDCuts) || (std::abs(negTrack.tpcNSigmaPr()) > grpV0.daughPIDCuts))) { + return false; + } + if (std::abs(CtauLambda) > grpV0.maxLambdaLifeTime) { + return false; + } + return true; + } + + template + bool isV0TrackSelected(const T1& v0) + { + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + + if (!posTrack.hasTPC() || !negTrack.hasTPC()) { + return false; + } + if (posTrack.tpcNClsCrossedRows() < grpV0.tpcNClsCrossedRowsTrackMin || negTrack.tpcNClsCrossedRows() < grpV0.tpcNClsCrossedRowsTrackMin) { + return false; + } + if (posTrack.tpcCrossedRowsOverFindableCls() < 0.8 || negTrack.tpcCrossedRowsOverFindableCls() < 0.8) { + return false; + } + if (std::abs(v0.positiveeta()) > grpV0.etaTrackMax || std::abs(v0.negativeeta()) > grpV0.etaTrackMax) { + return false; + } + if (v0.positivept() < grpV0.ptTrackMin || v0.negativept() < grpV0.ptTrackMin) { + return false; + } + return true; + } + + template + bool selectionPID(const T& candidate) + { + if (cfgMomDepPID) { + if (candidate.p() < 0.5) { + if (!candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaKa()) < grpPhi.nsigmaCutTPC) { + return true; + } else if (candidate.hasTOF() && TMath::Sqrt(candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) < grpPhi.nsigmaCutTOF && candidate.beta() > grpPhi.cutTOFBeta) { + return true; + } + } else if (candidate.hasTOF() && TMath::Sqrt(candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) < grpPhi.nsigmaCutTOF && candidate.beta() > grpPhi.cutTOFBeta) { + return true; + } + } else { + if (!candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaKa()) < grpPhi.nsigmaCutTPC) { + return true; + } else if (candidate.hasTOF() && TMath::Sqrt(candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) < grpPhi.nsigmaCutTOF && candidate.beta() > grpPhi.cutTOFBeta) { + return true; + } + } + return false; + } + // Generic 2-prong invariant mass method candidate finder. Only works for non-identical daughters of opposite charge for now. - using PIDTrack = soa::Join; - void processDataInvMass(aod::Collisions::iterator const&, aod::BCsWithTimestamps const&, aod::CFCollRefs const& cfcollisions, aod::CFTrackRefs const& cftracks, PIDTrack const& tracks) + void processDataInvMass(aod::Collisions::iterator const&, aod::BCsWithTimestamps const&, aod::CFCollRefs const& cfcollisions, aod::CFTrackRefs const& cftracks, Filter2Prong::PIDTrack const& tracks) { if (cfcollisions.size() <= 0 || cftracks.size() <= 0) return; // rejected collision @@ -176,7 +441,11 @@ struct Filter2Prong { const auto& p1 = tracks.iteratorAt(cftrack1.trackId() - tracks.begin().globalIndex()); if (p1.sign() != 1) continue; - if (sigmaFormula->Eval(o2::aod::pidutils::tpcNSigma(cfgImPart1PID, p1), o2::aod::pidutils::tofNSigma(cfgImPart1PID, p1)) <= 0.0f) + sigmaFormula->SetParameter(sigmaFormulaParamIndex[0], p1.p()); + sigmaFormula->SetParameter(sigmaFormulaParamIndex[1], o2::aod::pidutils::tpcNSigma(cfgImPart1PID, p1)); + sigmaFormula->SetParameter(sigmaFormulaParamIndex[2], o2::aod::pidutils::tofNSigma(cfgImPart1PID, p1)); + sigmaFormula->SetParameter(sigmaFormulaParamIndex[3], static_cast(p1.hasTOF())); + if (sigmaFormula->Eval() <= 0.0f) continue; for (const auto& cftrack2 : cftracks) { if (cftrack2.globalIndex() == cftrack1.globalIndex()) @@ -184,7 +453,11 @@ struct Filter2Prong { const auto& p2 = tracks.iteratorAt(cftrack2.trackId() - tracks.begin().globalIndex()); if (p2.sign() != -1) continue; - if (sigmaFormula->Eval(o2::aod::pidutils::tpcNSigma(cfgImPart2PID, p2), o2::aod::pidutils::tofNSigma(cfgImPart2PID, p2)) <= 0.0f) + sigmaFormula->SetParameter(sigmaFormulaParamIndex[0], p2.p()); + sigmaFormula->SetParameter(sigmaFormulaParamIndex[1], o2::aod::pidutils::tpcNSigma(cfgImPart1PID, p2)); + sigmaFormula->SetParameter(sigmaFormulaParamIndex[2], o2::aod::pidutils::tofNSigma(cfgImPart1PID, p2)); + sigmaFormula->SetParameter(sigmaFormulaParamIndex[3], static_cast(p2.hasTOF())); + if (sigmaFormula->Eval() <= 0.0f) continue; ROOT::Math::PtEtaPhiMVector vec1(p1.pt(), p1.eta(), p1.phi(), cfgImPart1Mass); ROOT::Math::PtEtaPhiMVector vec2(p2.pt(), p2.eta(), p2.phi(), cfgImPart2Mass); @@ -199,6 +472,214 @@ struct Filter2Prong { } } PROCESS_SWITCH(Filter2Prong, processDataInvMass, "Process data generic 2-prong candidates with invariant mass method", false); + + // Phi and V0s invariant mass method candidate finder. Only works for non-identical daughters of opposite charge for now. + void processDataPhiV0(aod::Collisions::iterator const& collision, aod::BCsWithTimestamps const&, aod::CFCollRefs const& cfcollisions, aod::CFTrackRefs const& cftracks, Filter2Prong::PIDTrack const& tracks, aod::V0Datas const& V0s) + { + if (cfcollisions.size() <= 0) + return; // rejected collision + + // V0 + for (const auto& v0 : V0s) { // Loop over V0 candidates + if (!isV0TrackSelected(v0)) { // Quality selection for V0 prongs + continue; + } + + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + double massV0 = 0.0; + + // K0s + if (isSelectedV0AsK0s(collision, v0)) { // candidate is K0s + output2ProngTracks(cfcollisions.begin().globalIndex(), + posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::cf2prongtrack::K0stoPiPi); + } + + // Lambda and Anti-Lambda + bool LambdaTag = isSelectedV0AsLambda(collision, v0); + bool aLambdaTag = isSelectedV0AsLambda(collision, v0); + + // Note: candidate compatible with Lambda and Anti-Lambda hypothesis are counted twice (once for each hypothesis) + if (LambdaTag) { // candidate is Lambda + massV0 = v0.mLambda(); + output2ProngTracks(cfcollisions.begin().globalIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::cf2prongtrack::LambdatoPPi); + } + if (aLambdaTag) { // candidate is Anti-lambda + massV0 = v0.mAntiLambda(); + output2ProngTracks(cfcollisions.begin().globalIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::cf2prongtrack::AntiLambdatoPiP); + } // end of Lambda and Anti-Lambda processing + } // end of loop over V0 candidates + + // Phi + if (cftracks.size() <= 0) + return; // rejected collision + + o2::aod::ITSResponse itsResponse; + + for (const auto& cftrack1 : cftracks) { // Loop over first track + const auto& p1 = tracks.iteratorAt(cftrack1.trackId() - tracks.begin().globalIndex()); + if (p1.sign() != 1) { + continue; + } + if (!selectionTrack(p1)) { + continue; + } + if (grpPhi.ITSPIDSelection && p1.p() < grpPhi.ITSPIDPthreshold.value && !(itsResponse.nSigmaITS(p1) > grpPhi.lowITSPIDNsigma.value && itsResponse.nSigmaITS(p1) < grpPhi.highITSPIDNsigma.value)) { // Check ITS PID condition + continue; + } + if (!selectionPID(p1)) { + continue; + } + if (grpPhi.removefaketrack && isFakeTrack(p1)) { // Check if the track is a fake kaon + continue; + } + + for (const auto& cftrack2 : cftracks) { // Loop over second track + if (cftrack2.globalIndex() == cftrack1.globalIndex()) // Skip if it's the same track as the first one + continue; + + const auto& p2 = tracks.iteratorAt(cftrack2.trackId() - tracks.begin().globalIndex()); + if (p2.sign() != -1) { + continue; + } + if (!selectionTrack(p2)) { + continue; + } + if (!selectionPID(p2)) { + continue; + } + if (grpPhi.ITSPIDSelection && p2.p() < grpPhi.ITSPIDPthreshold.value && !(itsResponse.nSigmaITS(p2) > grpPhi.lowITSPIDNsigma.value && itsResponse.nSigmaITS(p2) < grpPhi.highITSPIDNsigma.value)) { // Check ITS PID condition + continue; + } + if (grpPhi.removefaketrack && isFakeTrack(p2)) { // Check if the track is a fake kaon + continue; + } + if (!selectionPair(p1, p2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector vec1(p1.pt(), p1.eta(), p1.phi(), cfgImPart1Mass); + ROOT::Math::PtEtaPhiMVector vec2(p2.pt(), p2.eta(), p2.phi(), cfgImPart2Mass); + ROOT::Math::PtEtaPhiMVector s = vec1 + vec2; + if (s.M() < grpPhi.ImMinInvMassPhiMeson || s.M() > grpPhi.ImMaxInvMassPhiMeson) { + continue; + } + float phi = RecoDecay::constrainAngle(s.Phi(), 0.0f); + output2ProngTracks(cfcollisions.begin().globalIndex(), + cftrack1.globalIndex(), cftrack2.globalIndex(), s.pt(), s.eta(), phi, s.M(), aod::cf2prongtrack::PhiToKK); + } // end of loop over second track + } // end of loop over first track + } + PROCESS_SWITCH(Filter2Prong, processDataPhiV0, "Process data Phi and V0 candidates with invariant mass method", false); + + // Phi and V0s invariant mass method candidate finder. Only works for non-identical daughters of opposite charge for now. + void processDataV0(aod::Collisions::iterator const& collision, aod::BCsWithTimestamps const&, aod::CFCollRefs const& cfcollisions, aod::CFTrackRefs const& cftracks, Filter2Prong::PIDTrack const&, aod::V0Datas const& V0s) + { + if (cfcollisions.size() <= 0 || cftracks.size() <= 0) + return; // rejected collision + + for (const auto& v0 : V0s) { // Loop over V0 candidates + if (!isV0TrackSelected(v0)) { // Quality selection for V0 prongs + continue; + } + + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + double massV0 = 0.0; + + // K0s + if (isSelectedV0AsK0s(collision, v0)) { // candidate is K0s + output2ProngTracks(cfcollisions.begin().globalIndex(), + posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), v0.mK0Short(), aod::cf2prongtrack::K0stoPiPi); + } + + // Lambda and Anti-Lambda + bool LambdaTag = isSelectedV0AsLambda(collision, v0); + bool aLambdaTag = isSelectedV0AsLambda(collision, v0); + + // Note: candidate compatible with Lambda and Anti-Lambda hypothesis are counted twice (once for each hypothesis) + if (LambdaTag) { // candidate is Lambda + massV0 = v0.mLambda(); + output2ProngTracks(cfcollisions.begin().globalIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::cf2prongtrack::LambdatoPPi); + } + if (aLambdaTag) { // candidate is Anti-lambda + massV0 = v0.mAntiLambda(); + output2ProngTracks(cfcollisions.begin().globalIndex(), posTrack.globalIndex(), negTrack.globalIndex(), + v0.pt(), v0.eta(), v0.phi(), massV0, aod::cf2prongtrack::AntiLambdatoPiP); + } // end of Lambda and Anti-Lambda processing + } // end of loop over V0 candidates + } + PROCESS_SWITCH(Filter2Prong, processDataV0, "Process data V0 candidates with invariant mass method", false); + + // Phi and V0s invariant mass method candidate finder. Only works for non-identical daughters of opposite charge for now. + void processDataPhi(aod::Collisions::iterator const&, aod::BCsWithTimestamps const&, aod::CFCollRefs const& cfcollisions, aod::CFTrackRefs const& cftracks, Filter2Prong::PIDTrack const& tracks) + { + if (cfcollisions.size() <= 0 || cftracks.size() <= 0) + return; // rejected collision + + o2::aod::ITSResponse itsResponse; + + for (const auto& cftrack1 : cftracks) { // Loop over first track + const auto& p1 = tracks.iteratorAt(cftrack1.trackId() - tracks.begin().globalIndex()); + if (p1.sign() != 1) { + continue; + } + if (!selectionTrack(p1)) { + continue; + } + if (grpPhi.ITSPIDSelection && p1.p() < grpPhi.ITSPIDPthreshold.value && !(itsResponse.nSigmaITS(p1) > grpPhi.lowITSPIDNsigma.value && itsResponse.nSigmaITS(p1) < grpPhi.highITSPIDNsigma.value)) { // Check ITS PID condition + continue; + } + if (!selectionPID(p1)) { + continue; + } + if (grpPhi.removefaketrack && isFakeTrack(p1)) { // Check if the track is a fake kaon + continue; + } + + for (const auto& cftrack2 : cftracks) { // Loop over second track + if (cftrack2.globalIndex() == cftrack1.globalIndex()) // Skip if it's the same track as the first one + continue; + + const auto& p2 = tracks.iteratorAt(cftrack2.trackId() - tracks.begin().globalIndex()); + if (p2.sign() != -1) { + continue; + } + if (!selectionTrack(p2)) { + continue; + } + if (!selectionPID(p2)) { + continue; + } + if (grpPhi.ITSPIDSelection && p2.p() < grpPhi.ITSPIDPthreshold.value && !(itsResponse.nSigmaITS(p2) > grpPhi.lowITSPIDNsigma.value && itsResponse.nSigmaITS(p2) < grpPhi.highITSPIDNsigma.value)) { // Check ITS PID condition + continue; + } + if (grpPhi.removefaketrack && isFakeTrack(p2)) { // Check if the track is a fake kaon + continue; + } + if (!selectionPair(p1, p2)) { + continue; + } + + ROOT::Math::PtEtaPhiMVector vec1(p1.pt(), p1.eta(), p1.phi(), cfgImPart1Mass); + ROOT::Math::PtEtaPhiMVector vec2(p2.pt(), p2.eta(), p2.phi(), cfgImPart2Mass); + ROOT::Math::PtEtaPhiMVector s = vec1 + vec2; + if (s.M() < grpPhi.ImMinInvMassPhiMeson || s.M() > grpPhi.ImMaxInvMassPhiMeson) { + continue; + } + float phi = RecoDecay::constrainAngle(s.Phi(), 0.0f); + output2ProngTracks(cfcollisions.begin().globalIndex(), + cftrack1.globalIndex(), cftrack2.globalIndex(), s.pt(), s.eta(), phi, s.M(), aod::cf2prongtrack::PhiToKK); + } // end of loop over second track + } // end of loop over first track + } + PROCESS_SWITCH(Filter2Prong, processDataPhi, "Process data Phi candidates with invariant mass method", false); + }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/TableProducer/filterCorrelations.cxx b/PWGCF/TableProducer/filterCorrelations.cxx index 7d5e0b17c38..70a009346c4 100644 --- a/PWGCF/TableProducer/filterCorrelations.cxx +++ b/PWGCF/TableProducer/filterCorrelations.cxx @@ -8,23 +8,27 @@ // In applying this license CERN does 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 "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" - +#include "Framework/runDataProcessing.h" #include "MathUtils/detail/TypeTruncation.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" - #include +#include // required for is_detected +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -47,10 +51,17 @@ using CFMultiplicity = CFMultiplicities::iterator; struct FilterCF { Service pdg; - enum TrackSelectionCuts : uint8_t { + enum TrackSelectionCuts1 : uint8_t { kTrackSelected = BIT(0), kITS5Clusters = BIT(1), - kTPC90CrossedRows = BIT(2) + kTPCCrossedRows = BIT(2), + kTPCClusters = BIT(3), + kchi2perTPC = BIT(4), + kchi2perITS = BIT(5), + }; + + enum TrackSelectionCuts2 : uint8_t { + kPIDProton = BIT(1) }; // Configuration @@ -60,14 +71,26 @@ struct FilterCF { O2_DEFINE_CONFIGURABLE(cfgCutMCPt, float, 0.5f, "Minimal pT for particles") O2_DEFINE_CONFIGURABLE(cfgCutMCEta, float, 0.8f, "Eta range for particles") O2_DEFINE_CONFIGURABLE(cfgVerbosity, int, 1, "Verbosity level (0 = major, 1 = per collision)") - O2_DEFINE_CONFIGURABLE(cfgTrigger, int, 7, "Trigger choice: (0 = none, 7 = sel7, 8 = sel8, 9 = sel8 + kNoSameBunchPileup + kIsGoodZvtxFT0vsPV, 10 = sel8 before April, 2024, 11 = sel8 for MC, 12 = sel8 with low occupancy cut)") + O2_DEFINE_CONFIGURABLE(cfgTrigger, int, 7, "Trigger choice: (0 = none, 7 = sel7, 8 = sel8, 9 = sel8 + kNoSameBunchPileup + kIsGoodZvtxFT0vsPV, 10 = sel8 before April, 2024, 11 = sel8 for MC, 12 = sel8 with low occupancy cut, 13 = sel8 + kNoSameBunchPileup + kIsGoodITSLayersAll -- for OO/NeNe) ") O2_DEFINE_CONFIGURABLE(cfgMinOcc, int, 0, "minimum occupancy selection") O2_DEFINE_CONFIGURABLE(cfgMaxOcc, int, 3000, "maximum occupancy selection") O2_DEFINE_CONFIGURABLE(cfgCollisionFlags, uint16_t, aod::collision::CollisionFlagsRun2::Run2VertexerTracks, "Request collision flags if non-zero (0 = off, 1 = Run2VertexerTracks)") O2_DEFINE_CONFIGURABLE(cfgTransientTables, bool, false, "Output transient tables for collision and track IDs to enable successive filtering tasks") - O2_DEFINE_CONFIGURABLE(cfgTrackSelection, int, 0, "Type of track selection (0 = Run 2/3 without systematics | 1 = Run 3 with systematics)") + O2_DEFINE_CONFIGURABLE(cfgTrackSelection, int, 0, "Type of track selection (0 = Run 2/3 without systematics | 1 = Run 3 with systematics | 2 = Run 3 with proton pid selection)") O2_DEFINE_CONFIGURABLE(cfgMinMultiplicity, float, -1, "Minimum multiplicity considered for filtering (if value positive)") O2_DEFINE_CONFIGURABLE(cfgMcSpecialPDGs, std::vector, {}, "Special MC PDG codes to include in the MC primary particle output (additional to charged particles). Empty = charged particles only.") // needed for some neutral particles + O2_DEFINE_CONFIGURABLE(nsigmaCutTPCProton, float, 3, "proton nsigma TPC") + O2_DEFINE_CONFIGURABLE(nsigmaCutTOFProton, float, 3, "proton nsigma TOF") + O2_DEFINE_CONFIGURABLE(ITSProtonselection, bool, false, "flag for ITS proton nsigma selection") + 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(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") + O2_DEFINE_CONFIGURABLE(chi2pertpccluster, float, 2.5, "maximum Chi2 / cluster for the TPC track segment") + O2_DEFINE_CONFIGURABLE(chi2peritscluster, float, 36, "maximum Chi2 / cluster for the ITS track segment") + O2_DEFINE_CONFIGURABLE(cfgEstimatorBitMask, uint16_t, 0, "BitMask for multiplicity estimators to be included in the CFMultSet tables."); // Filters and input definitions Filter collisionZVtxFilter = nabs(aod::collision::posZ) < cfgCutVertex; @@ -95,6 +118,9 @@ struct FilterCF { Produces outputTrackRefs; Produces outputMcParticleRefs; + Produces outputMultSets; + std::vector multiplicities{}; + // persistent caches std::vector mcReconstructedCache; std::vector mcParticleLabelsCache; @@ -124,12 +150,55 @@ 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); + } + return false; + } + + using TrackType = soa::Filtered>; + + template + bool selectionPIDProton(const T& candidate) + { + o2::aod::ITSResponse itsResponse; + + if (ITSProtonselection && candidate.pt() <= 0.6 && !(itsResponse.nSigmaITS(candidate) > nsigmaCutITSProton)) { + return false; + } + if (ITSProtonselection && candidate.pt() > 0.6 && candidate.pt() <= 0.8 && !(itsResponse.nSigmaITS(candidate) > nsigmaCutITSProton)) { + return false; + } + + if (candidate.hasTOF()) { + if (candidate.pt() < 0.7 && std::abs(candidate.tpcNSigmaPr()) < nsigmaCutTPCProton) { + return true; + } + if (candidate.p() >= 0.7 && std::abs(candidate.tpcNSigmaPr()) < nsigmaCutTPCProton && std::abs(candidate.tofNSigmaPr()) < nsigmaCutTOFProton) { + return true; + } + } else { + if (std::abs(candidate.tpcNSigmaPr()) < nsigmaCutTPCProton) { + return true; + } } return false; } - template - uint8_t getTrackType(TTrack& track) + template + struct HasProtonPID : std::false_type { + }; + + template + struct HasProtonPID().tpcNSigmaPr()), + decltype(std::declval().tofNSigmaPr()), + decltype(std::declval().hasTOF())>> + : std::true_type { + }; + + template + uint8_t getTrackType(const TTrack& track) { if (cfgTrackSelection == 0) { if (track.isGlobalTrack()) { @@ -142,20 +211,45 @@ struct FilterCF { uint8_t trackType = 0; if (track.isGlobalTrack()) { trackType |= kTrackSelected; - if (track.itsNCls() >= 5) { + if (track.itsNCls() >= itsnclusters) { trackType |= kITS5Clusters; } - if (track.tpcNClsCrossedRows() >= 90) { - trackType |= kTPC90CrossedRows; + if (track.tpcNClsCrossedRows() >= tpcncrossedrows) { + trackType |= kTPCCrossedRows; + } + if (track.tpcNClsFound() >= tpcnclusters) { + trackType |= kTPCClusters; + } + if (track.tpcChi2NCl() <= chi2pertpccluster) { + trackType |= kchi2perTPC; + } + if (track.itsChi2NCl() <= chi2peritscluster) { + trackType |= kchi2perITS; + } + } + return trackType; + } else if (cfgTrackSelection == 2) { + uint8_t trackType = 0; + if constexpr (HasProtonPID::value) { + if (track.isGlobalTrack() && (track.itsNCls() >= itsnclusters) && (track.tpcNClsCrossedRows() >= tpcncrossedrows) && selectionPIDProton(track)) { + trackType |= kPIDProton; } } return trackType; } + LOGF(fatal, "Invalid setting for cfgTrackSelection: %d", cfgTrackSelection.value); return 0; } - void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks) + template + using HasMultTables = decltype(std::declval().multNTracksPV()); + + /// \brief Templetized process data for a given collision and its associated tracks + /// \param collision The collision object containing information about the collision + /// \param tracks The collection of tracks associated with the collision + template + void processDataT(const C1& collision, const T1& tracks) { if (cfgVerbosity > 0) { LOGF(info, "processData: Tracks for collision: %d | Vertex: %.1f (%d) | INT7: %d | Multiplicity: %.1f", tracks.size(), collision.posZ(), collision.flags(), collision.sel7(), collision.multiplicity()); @@ -165,13 +259,29 @@ struct FilterCF { return; } - auto bc = collision.bc_as(); + auto bc = collision.template bc_as(); outputCollisions(bc.runNumber(), collision.posZ(), collision.multiplicity(), bc.timestamp()); + if constexpr (std::experimental::is_detected::value) { + multiplicities.clear(); + if (cfgEstimatorBitMask & aod::cfmultset::CentFT0C) + multiplicities.push_back(collision.centFT0C()); + if (cfgEstimatorBitMask & aod::cfmultset::MultFV0A) + multiplicities.push_back(collision.multFV0A()); + if (cfgEstimatorBitMask & aod::cfmultset::MultNTracksPV) + multiplicities.push_back(collision.multNTracksPV()); + if (cfgEstimatorBitMask & aod::cfmultset::MultNTracksGlobal) + multiplicities.push_back(collision.multNTracksGlobal()); + outputMultSets(multiplicities); + } + if (cfgTransientTables) outputCollRefs(collision.globalIndex()); - for (auto& track : tracks) { + if ((std::abs(track.dcaXY()) > dcaxymax) || (std::abs(track.dcaZ()) > dcazmax)) { + continue; + } + outputTracks(outputCollisions.lastIndex(), track.pt(), track.eta(), track.phi(), track.sign(), getTrackType(track)); if (cfgTransientTables) outputTrackRefs(collision.globalIndex(), track.globalIndex()); @@ -180,15 +290,37 @@ struct FilterCF { etaphi->Fill(collision.multiplicity(), track.eta(), track.phi()); } } + + void processData(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks) + { + processDataT(collision, tracks); + } PROCESS_SWITCH(FilterCF, processData, "Process data", true); - // NOTE not filtering collisions here because in that case there can be tracks referring to MC particles which are not part of the selected MC collisions - Preslice perMcCollision = aod::mcparticle::mcCollisionId; - Preslice perCollision = aod::track::collisionId; - void processMC(aod::McCollisions const& mcCollisions, aod::McParticles const& allParticles, - soa::Join const& allCollisions, - soa::Filtered> const& tracks, - aod::BCsWithTimestamps const&) + void processDataPid(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks) + { + processDataT(collision, tracks); + } + PROCESS_SWITCH(FilterCF, processDataPid, "Process data with PID", false); + + void processDataMults(soa::Filtered>::iterator const& collision, aod::BCsWithTimestamps const&, soa::Filtered> const& tracks) + { + processDataT(collision, tracks); + } + PROCESS_SWITCH(FilterCF, processDataMults, "Process data with multiplicity sets", 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 + /// \param allCollisions The collection of all collisions, joined with MC collision labels and + /// event selections + /// \param tracks The collection of tracks, filtered by selection criteria + /// \param bcs The collection of bunch crossings with timestamps + template + void processMCT(aod::McCollisions const& mcCollisions, aod::McParticles const& allParticles, + soa::Join const& allCollisions, + T1 const& tracks, + aod::BCsWithTimestamps const&) { mcReconstructedCache.reserve(allParticles.size()); mcParticleLabelsCache.reserve(allParticles.size()); @@ -286,8 +418,7 @@ struct FilterCF { LOGP(fatal, "processMC: Track {} is referring to a MC particle which we do not store {} {} (reco flag {})", track.index(), track.mcParticleId(), mcParticleId, static_cast(mcReconstructedCache[track.mcParticleId()])); } } - outputTracks(outputCollisions.lastIndex(), - truncateFloatFraction(track.pt()), truncateFloatFraction(track.eta()), truncateFloatFraction(track.phi()), track.sign(), getTrackType(track)); + outputTracks(outputCollisions.lastIndex(), truncateFloatFraction(track.pt()), truncateFloatFraction(track.eta()), truncateFloatFraction(track.phi()), track.sign(), getTrackType(track)); outputTrackLabels(mcParticleId); if (cfgTransientTables) outputTrackRefs(collision.globalIndex(), track.globalIndex()); @@ -297,8 +428,29 @@ struct FilterCF { } } } + + // NOTE not filtering collisions here because in that case there can be tracks referring to MC particles which are not part of the selected MC collisions + Preslice perMcCollision = aod::mcparticle::mcCollisionId; + Preslice perCollision = aod::track::collisionId; + void processMC(aod::McCollisions const& mcCollisions, aod::McParticles const& allParticles, + soa::Join const& allCollisions, + soa::Filtered> const& tracks, + aod::BCsWithTimestamps const& bcs) + { + processMCT(mcCollisions, allParticles, allCollisions, tracks, bcs); + } PROCESS_SWITCH(FilterCF, processMC, "Process MC", false); + // NOTE not filtering collisions here because in that case there can be tracks referring to MC particles which are not part of the selected MC collisions + void processMCPid(aod::McCollisions const& mcCollisions, aod::McParticles const& allParticles, + soa::Join const& allCollisions, + soa::Filtered> const& tracks, + aod::BCsWithTimestamps const& bcs) + { + processMCT(mcCollisions, allParticles, allCollisions, tracks, bcs); + } + PROCESS_SWITCH(FilterCF, processMCPid, "Process MC with PID", false); + void processMCGen(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& particles) { float multiplicity = 0.0f; diff --git a/PWGCF/Tasks/correlations.cxx b/PWGCF/Tasks/correlations.cxx index 7461cc4b671..0fdbb0499df 100644 --- a/PWGCF/Tasks/correlations.cxx +++ b/PWGCF/Tasks/correlations.cxx @@ -13,36 +13,39 @@ /// \brief task for the correlation calculations with CF-filtered tracks for O2 analysis /// \author Jan Fiete Grosse-Oetringhaus , Jasper Parkkila -#include -#include -#include +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" -#include -#include -#include -#include -#include -#include +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "CCDB/BasicCCDBManager.h" -#include "Framework/StepTHn.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 "CommonConstants/MathConstants.h" -#include "Common/Core/RecoDecay.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -74,7 +77,7 @@ struct CorrelationTask { 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; 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(cfgCorrelationMethod, int, 0, "Correlation method, 0 = all, 1 = dd, 2 = ddbar"); @@ -82,7 +85,8 @@ struct CorrelationTask { 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, uint8_t, 0, "BitMask for track selection systematics; refer to the enum TrackSelectionCuts in filtering task"); + 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.") // Suggested values: Photon: 0.004; K0 and Lambda: 0.005 Configurable> cfgPairCut{"cfgPairCut", {kCfgPairCutDefaults[0], 5, {"Photon", "K0", "Lambda", "Phi", "Rho"}}, "Pair cuts on various particles"}; @@ -94,6 +98,7 @@ struct CorrelationTask { O2_DEFINE_CONFIGURABLE(cfgVerbosity, int, 1, "Verbosity level (0 = major, 1 = per collision)") O2_DEFINE_CONFIGURABLE(cfgDecayParticleMask, int, 0, "Selection bitmask for the decay particles: 0 = no selection") + O2_DEFINE_CONFIGURABLE(cfgV0RapidityMax, float, 0.8, "Maximum rapidity for the decay particles (0 = no selection)") O2_DEFINE_CONFIGURABLE(cfgMassAxis, int, 0, "Use invariant mass axis (0 = OFF, 1 = ON)") O2_DEFINE_CONFIGURABLE(cfgMcTriggerPDGs, std::vector, {}, "MC PDG codes to use exclusively as trigger particles and exclude from associated particles. Empty = no selection.") @@ -111,8 +116,7 @@ struct CorrelationTask { 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 axisInvMass{"axisInvMass", {VARIABLE_WIDTH, 0, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2.0, 5.0}, "invariant mass axis for histograms"}; - ConfigurableAxis axisInvMassHistogram{"axisInvMassHistogram", {1000, 1.0, 3.0}, "invariant mass histogram binning"}; + ConfigurableAxis axisInvMass{"axisInvMass", {VARIABLE_WIDTH, 1.7, 1.75, 1.8, 1.85, 1.9, 1.95, 2.0, 5.0}, "invariant mass axis for histograms"}; // This filter is applied to AOD and derived data (column names are identical) Filter collisionZVtxFilter = nabs(aod::collision::posZ) < cfgCutVertex; @@ -125,7 +129,7 @@ struct CorrelationTask { // MC filters Filter cfMCCollisionFilter = nabs(aod::mccollision::posZ) < cfgCutVertex; - Filter cfMCParticleFilter = (nabs(aod::cfmcparticle::eta) < cfgCutEta) && (aod::cfmcparticle::pt > cfgCutPt) && (aod::cfmcparticle::sign != 0); + Filter cfMCParticleFilter = (nabs(aod::cfmcparticle::eta) < cfgCutEta) && (aod::cfmcparticle::pt > cfgCutPt); // && (aod::cfmcparticle::sign != 0); //check the sign manually, some specials may be neutral // HF filters Filter track2pFilter = (nabs(aod::cf2prongtrack::eta) < cfgCutEta) && (aod::cf2prongtrack::pt > cfgCutPt); @@ -158,22 +162,44 @@ 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."); 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) { + if (doprocessSame2ProngDerived || doprocessSame2ProngDerivedML || doprocessSame2Prong2Prong || doprocessSame2Prong2ProngML || doprocessMCSameDerived2Prong) { registry.add("yieldsTrigger", "multiplicity/centrality vs pT vs eta (triggers)", {HistType::kTH3F, {{100, 0, 100, "/multiplicity/centrality"}, {40, 0, 20, "p_{T}"}, {100, -2, 2, "#eta"}}}); registry.add("etaphiTrigger", "multiplicity/centrality vs eta vs phi (triggers)", {HistType::kTH3F, {{100, 0, 100, "multiplicity/centrality"}, {100, -2, 2, "#eta"}, {200, 0, o2::constants::math::TwoPI, "#varphi"}}}); - registry.add("invMass", "2-prong invariant mass (GeV/c^2)", {HistType::kTH3F, {axisInvMassHistogram, axisPtTrigger, axisMultiplicity}}); + const AxisSpec& a = AxisSpec(axisInvMass); + AxisSpec axisSpecMass = {1000, a.binEdges[0], a.binEdges[a.getNbins()]}; + registry.add("invMass", "2-prong invariant mass (GeV/c^2)", {HistType::kTH3F, {axisSpecMass, axisPtTrigger, axisMultiplicity}}); if (doprocessSame2Prong2Prong || doprocessSame2Prong2ProngML) { - registry.add("invMassTwoPart", "2D 2-prong invariant mass (GeV/c^2)", {HistType::kTHnSparseF, {axisInvMassHistogram, axisInvMassHistogram, axisPtTrigger, axisPtAssoc, axisMultiplicity}}); - registry.add("invMassTwoPartDPhi", "2D 2-prong invariant mass (GeV/c^2)", {HistType::kTHnSparseF, {axisInvMassHistogram, axisInvMassHistogram, axisPtTrigger, axisPtAssoc, axisDeltaPhi}}); + registry.add("invMassTwoPart", "2D 2-prong invariant mass (GeV/c^2)", {HistType::kTHnSparseF, {axisSpecMass, axisSpecMass, axisPtTrigger, axisPtAssoc, axisMultiplicity}}); + registry.add("invMassTwoPartDPhi", "2D 2-prong invariant mass (GeV/c^2)", {HistType::kTHnSparseF, {axisSpecMass, axisSpecMass, axisPtTrigger, axisPtAssoc, axisDeltaPhi}}); } } + 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(100, 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); @@ -221,7 +247,7 @@ struct CorrelationTask { if (!cfgEfficiencyAssociated.value.empty()) efficiencyAssociatedCache.reserve(512); - if (doprocessMCEfficiency2Prong) { + if (doprocessMCEfficiency2Prong || doprocessMCEfficiency2ProngML) { 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); @@ -262,10 +288,20 @@ struct CorrelationTask { return !((track.decay() == 0 && track.mlProbD0()[0] > cfgPtCentDepMLbkgSel->at(idx)) || (track.decay() == 1 && track.mlProbD0bar()[0] > cfgPtCentDepMLbkgSel->at(idx))); } + template + using HasMultSet = decltype(std::declval().multiplicities()); + template - void fillQA(const TCollision& /*collision*/, float multiplicity, const TTracks& tracks) + void fillQA(const TCollision& collision, float multiplicity, const TTracks& tracks) { registry.fill(HIST("multiplicity"), multiplicity); + if constexpr (std::experimental::is_detected::value) { + if (std::popcount(cfgMultCorrelationsMask.value) != static_cast(collision.multiplicities().size())) + LOGF(fatal, "Multiplicity selections (cfgMultCorrelationsMask = 0x%x) do not match the size of the table column (%ld). The histogram filling relies on the preservation of order.", cfgMultCorrelationsMask.value, collision.multiplicities().size()); + // need to convert to vec of doubles since THnSparse has no way to fill vec of floats directly + std::vector v(collision.multiplicities().begin(), collision.multiplicities().end()); + registry.get(HIST("multCorrelations")).get()->Fill(v.data()); + } for (const auto& track1 : tracks) { registry.fill(HIST("yields"), multiplicity, track1.pt(), track1.eta()); registry.fill(HIST("etaphi"), multiplicity, track1.eta(), track1.phi()); @@ -336,7 +372,7 @@ struct CorrelationTask { } } if constexpr (std::experimental::is_detected::value) { - if (!cfgMcTriggerPDGs->empty() && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), track1->pdgCode()) == cfgMcTriggerPDGs->end()) + if (!cfgMcTriggerPDGs->empty() && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), track1.pdgCode()) == cfgMcTriggerPDGs->end()) continue; } registry.fill(HIST("yieldsTrigger"), multiplicity, track1.pt(), track1.eta()); @@ -378,11 +414,49 @@ struct CorrelationTask { template using HasDecay = decltype(std::declval().decay()); template + using HasMcDecay = decltype(std::declval().mcDecay()); + template using HasProng0Id = decltype(std::declval().cfTrackProng0Id()); template using HasProng1Id = decltype(std::declval().cfTrackProng1Id()); template using HasMlProbD0 = decltype(std::declval().mlProbD0()); + template + using HasPartDaugh0Id = decltype(std::declval().cfParticleDaugh0Id()); + template + using HasPartDaugh1Id = decltype(std::declval().cfParticleDaugh1Id()); + + template + std::tuple getV0Rapidity(const T& track) + { + if constexpr (!std::experimental::is_detected::value) + return {false, 0.0f}; // no decay type, return dummy rapidity + const auto decayType = track.decay(); + float mass = 0.f; + + if (decayType == aod::cf2prongtrack::K0stoPiPi) { + mass = o2::constants::physics::MassK0Short; + } else if (decayType == aod::cf2prongtrack::LambdatoPPi || decayType == aod::cf2prongtrack::AntiLambdatoPiP) { + mass = o2::constants::physics::MassLambda; + } else if (decayType == aod::cf2prongtrack::PhiToKK) { + mass = o2::constants::physics::MassPhi; + } else { + return {false, 0.0f}; // unsupported decay type, return dummy rapidity + } + + const float pt = track.pt(); + const float eta = track.eta(); + const float phi = track.phi(); + + const float px = pt * std::cos(phi); + const float py = pt * std::sin(phi); + const float pz = pt * std::sinh(eta); + + const float p2 = px * px + py * py + pz * pz; + + const float E = std::sqrt(p2 + mass * mass); + return {true, 0.5f * std::log((E + pz) / (E - pz))}; + } template void fillCorrelations(TTarget target, TTracks1& tracks1, TTracks2& tracks2, float multiplicity, float posZ, int magField, float eventWeight) @@ -401,28 +475,57 @@ struct CorrelationTask { 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 constexpr (step <= CorrelationContainer::kCFStepTracked && !std::experimental::is_detected::value) { if (!checkObject(track1)) { continue; } } - if constexpr (std::experimental::is_detected::value) { - if (cfgDecayParticleMask != 0 && (cfgDecayParticleMask & (1u << static_cast(track1.decay()))) == 0u) - continue; - } - + // sign check and PDG code special cases if constexpr (std::experimental::is_detected::value) { - if (!cfgMcTriggerPDGs->empty() && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), track1.pdgCode()) == cfgMcTriggerPDGs->end()) + // If the MC trigger particle is on the trigger PDG code list, we will accept them regardless of their charge. + if (!cfgMcTriggerPDGs->empty()) { + if (std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), track1.pdgCode()) == cfgMcTriggerPDGs->end()) + continue; + } else { // otherwise check the sign against the configuration + if (cfgTriggerCharge != 0) { + if (cfgTriggerCharge * track1.sign() < 0) + continue; + } else if (track1.sign() == 0) { + continue; // reject neutral MC particles + } + } + } else if constexpr (std::experimental::is_detected::value) { + // Check reco objects that have the sign attribute. There are no neutrals to deal with. + if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.sign() < 0) continue; } - if constexpr (std::experimental::is_detected::value) { - if (cfgTriggerCharge != 0 && cfgTriggerCharge * track1.sign() < 0) { + if constexpr (std::experimental::is_detected::value) { + if (((track1.mcDecay() != aod::cf2prongtrack::D0ToPiK) && (track1.mcDecay() != aod::cf2prongtrack::D0barToKPi)) || (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) { + continue; // skip particles that do not match the decay mask } + if (cfgV0RapidityMax > 0) { + auto [t, y] = getV0Rapidity(track1); + if (t && std::abs(y) > cfgV0RapidityMax) + continue; // V0s are not allowed to be outside the rapidity range + registry.fill(HIST("yvspt"), y, track1.pt()); + } + } + + if constexpr (std::experimental::is_detected::value) { + if (track1.cfParticleDaugh0Id() < 0 && track1.cfParticleDaugh1Id() < 0) + continue; // these we could not match } + if constexpr (std::experimental::is_detected::value) { + if (!passMLScore(track1)) + continue; + } // ML selection + float triggerWeight = eventWeight; if constexpr (step == CorrelationContainer::kCFStepCorrected) { if (cfg.mEfficiencyTrigger) { @@ -430,16 +533,16 @@ struct CorrelationTask { } } - if constexpr (std::experimental::is_detected::value) { - if ((doprocessSame2ProngDerivedML || doprocessSame2Prong2ProngML || doprocessMixed2ProngDerivedML || doprocessMixed2Prong2ProngML) && !passMLScore(track1)) - continue; - } // ML selection - if (cfgMassAxis) { if constexpr (std::experimental::is_detected::value) target->getTriggerHist()->Fill(step, track1.pt(), multiplicity, posZ, track1.invMass(), triggerWeight); - else + else if constexpr (std::experimental::is_detected::value) { + // TParticlePDG *p = pdg->GetParticle(track1.pdgCode()); + // target->getTriggerHist()->Fill(step, track1.pt(), multiplicity, posZ, p->Mass(), triggerWeight); + target->getTriggerHist()->Fill(step, track1.pt(), multiplicity, posZ, 1.8, triggerWeight); + } else { LOGF(fatal, "Can not fill mass axis without invMass column. Disable cfgMassAxis."); + } } else { target->getTriggerHist()->Fill(step, track1.pt(), multiplicity, posZ, triggerWeight); } @@ -451,11 +554,12 @@ struct CorrelationTask { continue; } } - if constexpr (std::experimental::is_detected::value) { + if constexpr (std::experimental::is_detected::value) { // skip those that are specifically chosen to be triggers if (!cfgMcTriggerPDGs->empty() && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), track2.pdgCode()) != cfgMcTriggerPDGs->end()) - continue; + continue; // TODO: fix cases like MC D0-D0 } + // Daughter track and particle checks if constexpr (std::experimental::is_detected::value) { if (track2.globalIndex() == track1.cfTrackProng0Id()) // do not correlate daughter tracks of the same event continue; @@ -464,16 +568,34 @@ struct CorrelationTask { if (track2.globalIndex() == track1.cfTrackProng1Id()) // do not correlate daughter tracks of the same event continue; } + if constexpr (std::experimental::is_detected::value) { + if (track2.globalIndex() == track1.cfParticleDaugh0Id()) // do not correlate daughter particles of the same event + continue; + } + if constexpr (std::experimental::is_detected::value) { + if (track2.globalIndex() == track1.cfParticleDaugh1Id()) // do not correlate daughter particles of the same event + continue; + } - if constexpr (step <= CorrelationContainer::kCFStepTracked) { + if constexpr (step <= CorrelationContainer::kCFStepTracked && !std::experimental::is_detected::value) { if (!checkObject(track2)) { continue; } } - if constexpr (std::experimental::is_detected::value) { - if (cfgDecayParticleMask != 0 && (cfgDecayParticleMask & (1u << static_cast(track2.decay()))) == 0u) + // 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) continue; + } else if constexpr (std::experimental::is_detected::value) { + if (cfgDecayParticleMask != 0 && (cfgDecayParticleMask & (1u << static_cast(track2.decay()))) == 0u) { + continue; // skip particles that do not match the decay mask + } + if (cfgV0RapidityMax > 0) { + auto [t, y] = getV0Rapidity(track1); + if (t && std::abs(y) > cfgV0RapidityMax) + continue; // V0s are not allowed to be outside the rapidity range + } } if constexpr (std::experimental::is_detected::value && std::experimental::is_detected::value) { @@ -508,13 +630,18 @@ struct CorrelationTask { } } } // no shared prong for two mothers + // TODO MC daughters check ^^ if (cfgPtOrder != 0 && track2.pt() >= track1.pt()) { continue; } if constexpr (std::experimental::is_detected::value) { - if (cfgAssociatedCharge != 0 && cfgAssociatedCharge * track2.sign() < 0) { + // TODO: support for MC D0-D0 case + if (cfgAssociatedCharge != 0) { + if (cfgAssociatedCharge * track2.sign() < 0) + continue; + } else if (track2.sign() == 0) { // mc particles come in neutrals, need to check explicitly continue; } } @@ -548,7 +675,7 @@ struct CorrelationTask { float deltaPhi = RecoDecay::constrainAngle(track1.phi() - track2.phi(), -o2::constants::math::PIHalf); if constexpr (std::experimental::is_detected::value) { - if ((doprocessSame2ProngDerivedML || doprocessSame2Prong2ProngML || doprocessMixed2ProngDerivedML || doprocessMixed2Prong2ProngML) && !passMLScore(track2)) + if (!passMLScore(track2)) continue; } // ML selection @@ -561,8 +688,12 @@ struct CorrelationTask { } else if (cfgMassAxis) { if constexpr (std::experimental::is_detected::value) target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, track1.invMass(), associatedWeight); - else + else if constexpr (std::experimental::is_detected::value) { + // TParticlePDG *p = pdg->GetParticle(track1.pdgCode()); //TODO: get the mass for the PDG properly + target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, 1.8, associatedWeight); // p->Mass() + } else { LOGF(fatal, "Can not fill mass axis without invMass column. Disable cfgMassAxis."); + } } else { target->getPairHist()->Fill(step, track1.eta() - track2.eta(), track2.pt(), track1.pt(), multiplicity, deltaPhi, posZ, associatedWeight); } @@ -636,11 +767,12 @@ struct CorrelationTask { } PROCESS_SWITCH(CorrelationTask, processSameAOD, "Process same event on AOD", true); - void processSameDerived(DerivedCollisions::iterator const& collision, soa::Filtered const& tracks) + template + void processSameDerivedT(CollType const& collision, TTracks1 const& tracks1, TTracks2 const& tracks2) { 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, "processSameDerived: Tracks for collision: %d | Vertex: %.1f | Multiplicity/Centrality: %.1f", tracks.size(), collision.posZ(), collision.multiplicity()); + LOGF(info, "processSameDerivedT: Tracks for collision: %d/%d | Vertex: %.1f | Multiplicity/Centrality: %.1f", tracks1.size(), tracks2.size(), collision.posZ(), collision.multiplicity()); } loadEfficiency(collision.timestamp()); @@ -652,87 +784,54 @@ struct CorrelationTask { int bin = configurableBinningDerived.getBin({collision.posZ(), collision.multiplicity()}); registry.fill(HIST("eventcount_same"), bin); - fillQA(collision, multiplicity, tracks); + registry.fill(HIST("trackcount_same"), bin, tracks1.size()); + if constexpr (std::experimental::is_detected::value) + fillQA(collision, multiplicity, tracks1, tracks2); + else + fillQA(collision, multiplicity, tracks1); same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(same, tracks, tracks, multiplicity, collision.posZ(), field, 1.0f); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); - fillCorrelations(same, tracks, tracks, multiplicity, collision.posZ(), field, 1.0f); + fillCorrelations(same, tracks1, tracks2, multiplicity, collision.posZ(), field, 1.0f); } } - PROCESS_SWITCH(CorrelationTask, processSameDerived, "Process same event on derived data", false); - template - void processSame2ProngDerivedT(DerivedCollisions::iterator const& collision, soa::Filtered const& tracks, p2type const& p2tracks) + void processSameDerived(DerivedCollisions::iterator const& collision, soa::Filtered const& tracks) { - 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, "processSame2ProngDerived: Tracks for collision: %d | 2-prong candidates: %d | Vertex: %.1f | Multiplicity/Centrality: %.1f", tracks.size(), p2tracks.size(), collision.posZ(), collision.multiplicity()); - } - loadEfficiency(collision.timestamp()); - - const auto multiplicity = collision.multiplicity(); - - int bin = configurableBinningDerived.getBin({collision.posZ(), collision.multiplicity()}); - registry.fill(HIST("eventcount_same"), bin); - fillQA(collision, multiplicity, p2tracks, tracks); - - same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(same, p2tracks, tracks, multiplicity, collision.posZ(), 0, 1.0f); + processSameDerivedT(collision, tracks, tracks); + } + PROCESS_SWITCH(CorrelationTask, processSameDerived, "Process same event on derived data", false); - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { - same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); - fillCorrelations(same, p2tracks, tracks, multiplicity, collision.posZ(), 0, 1.0f); - } + void processSameDerivedMultSet(soa::Filtered>::iterator const& collision, soa::Filtered const& tracks) + { + processSameDerivedT(collision, tracks, tracks); } + PROCESS_SWITCH(CorrelationTask, processSameDerivedMultSet, "Process same event on derived data with multiplicity sets", false); void processSame2ProngDerived(DerivedCollisions::iterator const& collision, soa::Filtered const& tracks, soa::Filtered const& p2tracks) { - processSame2ProngDerivedT(collision, tracks, p2tracks); + processSameDerivedT(collision, p2tracks, tracks); } PROCESS_SWITCH(CorrelationTask, processSame2ProngDerived, "Process same event on derived data", false); void processSame2ProngDerivedML(DerivedCollisions::iterator const& collision, soa::Filtered const& tracks, soa::Filtered> const& p2tracks) { - processSame2ProngDerivedT(collision, tracks, p2tracks); + processSameDerivedT(collision, p2tracks, tracks); } PROCESS_SWITCH(CorrelationTask, processSame2ProngDerivedML, "Process same event on derived data with ML scores", false); - template - void processSame2Prong2ProngT(DerivedCollisions::iterator const& collision, p2type const& p2tracks) - { - 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, "processSame2ProngDerived: 2-prong candidates: %d | Vertex: %.1f | Multiplicity/Centrality: %.1f", p2tracks.size(), collision.posZ(), collision.multiplicity()); - } - loadEfficiency(collision.timestamp()); - - const auto multiplicity = collision.multiplicity(); - - int bin = configurableBinningDerived.getBin({collision.posZ(), collision.multiplicity()}); - registry.fill(HIST("eventcount_same"), bin); - fillQA(collision, multiplicity, p2tracks, p2tracks); - - same->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(same, p2tracks, p2tracks, multiplicity, collision.posZ(), 0, 1.0f); - - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { - same->fillEvent(multiplicity, CorrelationContainer::kCFStepCorrected); - fillCorrelations(same, p2tracks, p2tracks, multiplicity, collision.posZ(), 0, 1.0f); - } - } - void processSame2Prong2Prong(DerivedCollisions::iterator const& collision, soa::Filtered const& p2tracks) { - processSame2Prong2ProngT(collision, p2tracks); + processSameDerivedT(collision, p2tracks, p2tracks); } PROCESS_SWITCH(CorrelationTask, processSame2Prong2Prong, "Process same event on derived data", false); void processSame2Prong2ProngML(DerivedCollisions::iterator const& collision, soa::Filtered> const& p2tracks) { - processSame2Prong2ProngT(collision, p2tracks); + processSameDerivedT(collision, p2tracks, p2tracks); } PROCESS_SWITCH(CorrelationTask, processSame2Prong2ProngML, "Process same event on derived data with ML scores", false); @@ -780,12 +879,16 @@ struct CorrelationTask { PROCESS_SWITCH(CorrelationTask, processMixedAOD, "Process mixed events on AOD", false); using BinningTypeDerived = ColumnBinningPolicy; - void processMixedDerived(DerivedCollisions const& collisions, DerivedTracks const& tracks) + + template + void processMixedDerivedT(DerivedCollisions const& collisions, TrackTypes&&... tracks) { BinningTypeDerived configurableBinningDerived{{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(tracks); - SameKindPair pairs{configurableBinningDerived, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + 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; @@ -809,6 +912,7 @@ struct CorrelationTask { // 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 (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { @@ -819,107 +923,34 @@ struct CorrelationTask { } } } - PROCESS_SWITCH(CorrelationTask, processMixedDerived, "Process mixed events on derived data", false); - template - void processMixed2ProngDerivedT(DerivedCollisions const& collisions, DerivedTracks const& tracks, p2type const& p2tracks) + void processMixedDerived(DerivedCollisions const& collisions, DerivedTracks const& tracks) { - BinningTypeDerived configurableBinningDerived{{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(p2tracks, tracks); - 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; - int bin = configurableBinningDerived.getBin({collision1.posZ(), collision1.multiplicity()}); - float eventWeight = 1.0f / it.currentWindowNeighbours(); - int field = 0; - if (cfgTwoTrackCut > 0) { - field = getMagneticField(collision1.timestamp()); - } - - if (cfgVerbosity > 0) { - LOGF(info, "processMixed2ProngDerived: 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(collision1.multiplicity(), CorrelationContainer::kCFStepReconstructed); - } - - registry.fill(HIST("eventcount_mixed"), bin); - fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); - - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { - if (it.isNewWindow()) { - mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepCorrected); - } - fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); - } - } + processMixedDerivedT(collisions, tracks); } + PROCESS_SWITCH(CorrelationTask, processMixedDerived, "Process mixed events on derived data", false); void processMixed2ProngDerived(DerivedCollisions const& collisions, DerivedTracks const& tracks, soa::Filtered const& p2tracks) { - processMixed2ProngDerivedT(collisions, tracks, p2tracks); + processMixedDerivedT(collisions, p2tracks, tracks); } PROCESS_SWITCH(CorrelationTask, processMixed2ProngDerived, "Process mixed events on derived data", false); void processMixed2ProngDerivedML(DerivedCollisions const& collisions, DerivedTracks const& tracks, soa::Filtered> const& p2tracks) { - processMixed2ProngDerivedT(collisions, tracks, p2tracks); + processMixedDerivedT(collisions, p2tracks, tracks); } PROCESS_SWITCH(CorrelationTask, processMixed2ProngDerivedML, "Process mixed events on derived data with ML scores", false); - template - void processMixed2Prong2ProngT(DerivedCollisions const& collisions, p2type const& p2tracks) - { - BinningTypeDerived configurableBinningDerived{{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(p2tracks); - SameKindPair 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; - int bin = configurableBinningDerived.getBin({collision1.posZ(), collision1.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(collision1.multiplicity(), CorrelationContainer::kCFStepReconstructed); - } - - // LOGF(info, "Tracks: %d and %d entries", tracks1.size(), tracks2.size()); - - registry.fill(HIST("eventcount_mixed"), bin); - fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); - if (cfg.mEfficiencyAssociated || cfg.mEfficiencyTrigger) { - if (it.isNewWindow()) { - mixed->fillEvent(collision1.multiplicity(), CorrelationContainer::kCFStepCorrected); - } - fillCorrelations(mixed, tracks1, tracks2, collision1.multiplicity(), collision1.posZ(), field, eventWeight); - } - } - } - void processMixed2Prong2Prong(DerivedCollisions const& collisions, soa::Filtered const& p2tracks) { - processMixed2Prong2ProngT(collisions, p2tracks); + processMixedDerivedT(collisions, p2tracks); } PROCESS_SWITCH(CorrelationTask, processMixed2Prong2Prong, "Process mixed events on derived data", false); void processMixed2Prong2ProngML(DerivedCollisions const& collisions, soa::Filtered> const& p2tracks) { - processMixed2Prong2ProngT(collisions, p2tracks); + processMixedDerivedT(collisions, p2tracks); } PROCESS_SWITCH(CorrelationTask, processMixed2Prong2ProngML, "Process mixed events on derived data with ML scores", false); @@ -986,9 +1017,11 @@ struct CorrelationTask { case 2212: // proton case -2212: return 2; - default: // NOTE. The efficiency histogram is hardcoded to contain 4 species. Anything special will have the last slot. - return 3; } + if (std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), pdgCode) != cfgMcTriggerPDGs->end()) + return 4; // NOTE - if changed, the number in processMCEfficiency2Prong needs to be changed too since we skip the getSpecies call + else // The efficiency histogram is hardcoded to contain 5 species. Anything special will have the 4th slot. + return 3; } // NOTE SmallGroups includes soa::Filtered always @@ -1010,7 +1043,7 @@ struct CorrelationTask { } // Primaries for (const auto& mcParticle : mcParticles) { - if (mcParticle.isPhysicalPrimary() && mcParticle.sign() != 0) { + if (mcParticle.isPhysicalPrimary() && mcParticle.sign() != 0 && !((doprocessMCEfficiency2Prong || doprocessMCEfficiency2ProngML) && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), mcParticle.pdgCode()) != cfgMcTriggerPDGs->end())) { same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); } } @@ -1024,6 +1057,8 @@ struct CorrelationTask { for (const auto& track : groupedTracks) { if (track.has_cfMCParticle()) { const auto& mcParticle = track.cfMCParticle(); + if ((doprocessMCEfficiency2Prong || doprocessMCEfficiency2ProngML) && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), mcParticle.pdgCode()) != cfgMcTriggerPDGs->end()) + continue; // properly booked by the 2Prong efficiency function, ignore here if (mcParticle.isPhysicalPrimary()) { same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); } @@ -1038,8 +1073,8 @@ struct CorrelationTask { } PROCESS_SWITCH(CorrelationTask, processMCEfficiency, "MC: Extract efficiencies", false); - Preslice perCollision2Prong = aod::cftrack::cfCollisionId; - void processMCEfficiency2Prong(soa::Filtered::iterator const& mcCollision, soa::Join const& mcParticles, soa::SmallGroups const& collisions, aod::CFTracksWithLabel const&, aod::CF2ProngTracks const& p2tracks) + 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(); if (cfgCentBinsForMC > 0) { @@ -1053,10 +1088,12 @@ struct CorrelationTask { // Primaries p2indexCache.clear(); for (const auto& mcParticle : mcParticles) { - if (mcParticle.isPhysicalPrimary() && std::find(cfgMcTriggerPDGs->begin(), cfgMcTriggerPDGs->end(), mcParticle.pdgCode()) != cfgMcTriggerPDGs->end()) { - same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), getSpecies(mcParticle.pdgCode()), multiplicity, mcCollision.posZ()); - if (mcParticle.cfParticleDaugh0Id() < 0 || mcParticle.cfParticleDaugh1Id() < 0) - continue; + 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) + continue; // wrong decay channel + if (mcParticle.cfParticleDaugh0Id() < 0 && mcParticle.cfParticleDaugh1Id() < 0) + continue; // daughters not found + same->getTrackHistEfficiency()->Fill(CorrelationContainer::MC, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); p2indexCache.push_back(mcParticle.globalIndex()); } } @@ -1064,36 +1101,67 @@ 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; // Check if the mc particles of the prongs are found. - const auto& p0 = p2track.cfTrackProng0_as(); - const auto& p1 = p2track.cfTrackProng1_as(); - if (p0.has_cfMCParticle() && p1.has_cfMCParticle()) { - // find the 2-prong MC particle by the daughter MC particle IDs + if constexpr (std::experimental::is_detected::value) { + if (!passMLScore(p2track)) + continue; + } + auto fillMC2p = [&](const aod::CFTracksWithLabel::iterator& p) -> bool { + if (!p.has_cfMCParticle()) + return false; auto m = std::find_if(p2indexCache.begin(), p2indexCache.end(), [&](const auto& t) -> bool { - const auto& mcParticle = mcParticles.iteratorAt(t); - return p0.cfMCParticleId() == mcParticle.cfParticleDaugh0Id() && p1.cfMCParticleId() == mcParticle.cfParticleDaugh1Id(); + const auto& mcParticle = mcParticles.iteratorAt(t - mcParticles.begin().globalIndex()); + return (p.cfMCParticleId() == mcParticle.cfParticleDaugh0Id() || p.cfMCParticleId() == mcParticle.cfParticleDaugh1Id()); }); 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()); + same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, mcParticle.eta(), mcParticle.pt(), 4, multiplicity, mcCollision.posZ()); + return true; + }; + if (p2track.has_cfTrackProng0()) { + // + if (const auto& p0 = p2track.template cfTrackProng0_as(); fillMC2p(p0)) + continue; + } + if (p2track.has_cfTrackProng1()) { + if (const auto& p1 = p2track.template cfTrackProng1_as(); fillMC2p(p1)) continue; - const auto& mcParticle = mcParticles.iteratorAt(*m); - 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()); - } else { - // fake track - same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 0, multiplicity, mcCollision.posZ()); } + + // alternatively, book the reco pTs directly + // same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoPrimaries, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); + // same->getTrackHistEfficiency()->Fill(CorrelationContainer::RecoAll, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); + // continue; + + // fake track + same->getTrackHistEfficiency()->Fill(CorrelationContainer::Fake, p2track.eta(), p2track.pt(), 4, multiplicity, mcCollision.posZ()); } } } + + 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); + } PROCESS_SWITCH(CorrelationTask, processMCEfficiency2Prong, "MC: Extract efficiencies for 2-prong particles", false); - // NOTE SmallGroups includes soa::Filtered always - void processMCSameDerived(soa::Filtered::iterator const& mcCollision, soa::Filtered const& mcParticles, soa::SmallGroups const& collisions) + 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); + } + PROCESS_SWITCH(CorrelationTask, processMCEfficiency2ProngML, "MC: Extract efficiencies 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) { if (cfgVerbosity > 0) { - LOGF(info, "processMCSameDerived. MC collision: %d, particles: %d, collisions: %d", mcCollision.globalIndex(), mcParticles.size(), collisions.size()); + LOGF(info, "processMCSameDerivedT. MC collision: %d, particles1: %d, particles2: %d, collisions: %d", mcCollision.globalIndex(), mcParticles1.size(), mcParticles2.size(), collisions.size()); } auto multiplicity = mcCollision.multiplicity(); @@ -1104,36 +1172,55 @@ struct CorrelationTask { for (const auto& collision : collisions) { multiplicity = collision.multiplicity(); } - if (cfgVerbosity > 0) { - LOGF(info, " Data multiplicity: %f", multiplicity); - } } - fillQA(mcCollision, multiplicity, mcParticles); + if (!(doprocessSameDerived || doprocessSameDerivedMultSet || doprocessSame2ProngDerived || doprocessSame2ProngDerivedML || doprocessSame2Prong2Prong || doprocessSame2Prong2ProngML)) { + if constexpr (std::experimental::is_detected::value) + fillQA(mcCollision, multiplicity, mcParticles1, mcParticles2); + else + fillQA(mcCollision, multiplicity, mcParticles1); + } same->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); - fillCorrelations(same, mcParticles, mcParticles, multiplicity, mcCollision.posZ(), 0, 1.0f); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); if (collisions.size() == 0) { return; } same->fillEvent(multiplicity, CorrelationContainer::kCFStepVertex); - fillCorrelations(same, mcParticles, mcParticles, multiplicity, mcCollision.posZ(), 0, 1.0f); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); same->fillEvent(multiplicity, CorrelationContainer::kCFStepTrackedOnlyPrim); - fillCorrelations(same, mcParticles, mcParticles, multiplicity, mcCollision.posZ(), 0, 1.0f); + fillCorrelations(same, mcParticles1, mcParticles2, multiplicity, mcCollision.posZ(), 0, 1.0f); same->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); - fillCorrelations(same, mcParticles, mcParticles, multiplicity, mcCollision.posZ(), 0, 1.0f); + 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(CorrelationTask, processMCSameDerived, "Process MC same event on derived data", false); + void processMCSameDerived2Prong(soa::Filtered::iterator const& mcCollision, soa::Filtered> const& mcParticles2Prong, soa::Filtered const& mcParticles, soa::SmallGroups const& collisions) + { + // Subscribe to the MC particles table twice, once joined with the 2prongs and another time without. + // This is to avoid triggering any 2p-2p specific cases in the templated fillCorrelations(). + processMCSameDerivedT(mcCollision, mcParticles2Prong, mcParticles, collisions); + } + PROCESS_SWITCH(CorrelationTask, processMCSameDerived2Prong, "Process MC same event on derived data", false); + + // TODO: add MC 2Prong2Prong functions when needed + PresliceUnsorted collisionPerMCCollision = aod::cfcollision::cfMcCollisionId; - void processMCMixedDerived(soa::Filtered const& mcCollisions, soa::Filtered const& mcParticles, soa::Filtered const& collisions) + template + void processMCMixedDerivedT(soa::Filtered const& mcCollisions, soa::Filtered const& collisions, ParticleTypes&&... particles) { bool useMCMultiplicity = (cfgCentBinsForMC == 0); auto getMultiplicity = @@ -1150,8 +1237,10 @@ struct CorrelationTask { 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(mcParticles); - SameKindPair, soa::Filtered, BinningTypeMCDerived> pairs{configurableBinning, cfgNoMixedEvents, -1, mcCollisions, tuple, &cache}; // -1 is the number of the bin to skip + 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; @@ -1191,7 +1280,20 @@ struct CorrelationTask { // 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(CorrelationTask, processMCMixedDerived, "Process MC mixed events on derived data", false); + + void processMCMixedDerived2Prong(soa::Filtered const& mcCollisions, soa::Filtered> const& mcParticles2Prong, soa::Filtered const& mcParticles, soa::Filtered const& collisions) + { + // Subscribe to the MC particles table twice, once joined with the 2prongs and another time without. + // This is to avoid triggering any 2p-2p specific cases in the templated fillCorrelations(). + processMCMixedDerivedT(mcCollisions, collisions, mcParticles2Prong, mcParticles); + } + PROCESS_SWITCH(CorrelationTask, processMCMixedDerived2Prong, "Process MC mixed events on derived data", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt index 83526365550..0b61a13fbb5 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt +++ b/PWGCF/TwoParticleCorrelations/Tasks/CMakeLists.txt @@ -40,7 +40,7 @@ o2physics_add_dpl_workflow(dpt-dpt-efficiency-and-qc o2physics_add_dpl_workflow(dpt-dpt-per-run-qc SOURCES dptDptPerRunQc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2::DataFormatsITSMFT COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(dpt-dpt-per-run-extra-qc @@ -63,6 +63,11 @@ o2physics_add_dpl_workflow(di-hadron-cor PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2Physics::GFWCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(pid-di-hadron + SOURCES pidDiHadron.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore O2Physics::AnalysisCCDB O2Physics::GFWCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(longrange-correlation SOURCES longrangeCorrelation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGCFCore diff --git a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx index 4a944a4fff0..7ccd59ed178 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/diHadronCor.cxx @@ -14,39 +14,41 @@ /// \author Zhiyong Lu (zhiyong.lu@cern.ch) /// \since May/03/2025 -#include -#include "TRandom3.h" -#include "TF1.h" -#include -#include - -#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/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/PIDResponse.h" #include "PWGCF/Core/CorrelationContainer.h" #include "PWGCF/Core/PairCuts.h" -#include "PWGCF/GenericFramework/Core/GFWPowerArray.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 "DataFormatsParameters/GRPObject.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/PIDResponse.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; @@ -62,7 +64,8 @@ struct DiHadronCor { 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, 70.0f, "minimum 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") @@ -78,8 +81,9 @@ struct DiHadronCor { 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(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(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") @@ -91,8 +95,42 @@ struct DiHadronCor { 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") + 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; @@ -134,6 +172,7 @@ struct DiHadronCor { // Corrections TH3D* mEfficiency = nullptr; + TH1D* mCentralityWeight = nullptr; bool correctionsLoaded = false; // Define the outputs @@ -159,15 +198,6 @@ struct DiHadronCor { // persistent caches std::vector efficiencyAssociatedCache; - // Additional Event selection cuts - Copy from flowGenericFramework.cxx - TF1* fMultPVCutLow = nullptr; - TF1* fMultPVCutHigh = nullptr; - TF1* fMultCutLow = nullptr; - TF1* fMultCutHigh = nullptr; - TF1* fMultMultPVCut = nullptr; - TF1* fT0AV0AMean = nullptr; - TF1* fT0AV0ASigma = nullptr; - void init(InitContext&) { if (cfgCentTableUnavailable && !cfgSelCollByNch) { @@ -184,65 +214,72 @@ struct DiHadronCor { LOGF(info, "Starting init"); // Event Counter - 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"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(4, "kNoCollInTimeRangeStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(5, "kIsGoodITSLayersAll"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(6, "kNoCollInRofStandard"); - registry.get(HIST("hEventCountSpecific"))->GetXaxis()->SetBinLabel(7, "kNoHighMultCollInPrevRof"); - 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 (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 (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"); } - // 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("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 - std::string hCentTitle = "Centrality distribution, Estimator " + std::to_string(cfgCentEstimator); - registry.add("Centrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); - registry.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); // 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 (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); + } - registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisSample, axisVertex, axisPtTrigger}}}); + 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, {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("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, axisPtTrigger}}}); + } 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) { @@ -252,7 +289,11 @@ struct DiHadronCor { LOGF(fatal, "Full simulation and on-the-fly processing of mixed event not supported"); } if (doprocessMCSame || doprocessOntheflySame) { - registry.add("MCTrue/MCeventcount", "MCeventcount", {HistType::kTH1F, {{4, 0, 4, "bin"}}}); // histogram to see how many events are in the same and mixed event + 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}}); @@ -263,7 +304,16 @@ struct DiHadronCor { 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)"}, {axisPtTrigger, "p_{T} (GeV/c)"}, @@ -279,6 +329,8 @@ struct DiHadronCor { 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) @@ -322,7 +374,7 @@ struct DiHadronCor { template bool trackSelected(TTrack track) { - return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.itsNCls() >= cfgCutITSclu)); + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); } template @@ -343,7 +395,7 @@ struct DiHadronCor { return true; } - void loadEfficiency(uint64_t timestamp) + void loadCorrection(uint64_t timestamp) { if (correctionsLoaded) { return; @@ -360,6 +412,13 @@ struct DiHadronCor { } 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; } @@ -380,6 +439,19 @@ struct DiHadronCor { 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. @@ -424,7 +496,7 @@ struct DiHadronCor { } template - void fillCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system, int magneticField, float cent) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + 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) { @@ -455,7 +527,7 @@ struct DiHadronCor { if (!getEfficiencyCorrection(triggerWeight, track1.eta(), track1.pt(), posZ)) continue; if (system == SameEvent) { - registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); } for (auto const& track2 : tracks2) { @@ -466,8 +538,12 @@ struct DiHadronCor { associatedWeight = efficiencyAssociatedCache[track2.filteredIndex()]; } - if (track1.pt() <= track2.pt()) - continue; // skip if the trigger pt is less than the associate pt + 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(); @@ -497,18 +573,18 @@ struct DiHadronCor { // fill the right sparse and histograms if (system == SameEvent) { - same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); - registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), 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.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); - registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } } } } template - void fillMCCorrelations(TTracks tracks1, TTracksAssoc tracks2, float posZ, int system) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms + 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); @@ -522,7 +598,7 @@ struct DiHadronCor { continue; if (system == SameEvent && (doprocessMCSame || doprocessOntheflySame)) - registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.pt(), triggerWeight); + registry.fill(HIST("MCTrue/MCTrig_hist"), fSampleIndex, posZ, track1.pt(), eventWeight * triggerWeight); for (auto const& track2 : tracks2) { @@ -531,21 +607,25 @@ struct DiHadronCor { if (doprocessOntheflyMixed && !genTrackSelected(track2)) continue; - if (track1.pt() <= track2.pt()) - continue; // skip if the trigger pt is less than the associate pt + 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.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); if (doprocessMCSame || doprocessOntheflySame) - registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_same"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } else if (system == MixedEvent) { - mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, triggerWeight * associatedWeight); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); if (doprocessMCMixed || doprocessOntheflyMixed) - registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, triggerWeight * associatedWeight); + registry.fill(HIST("MCTrue/MCdeltaEta_deltaPhi_mixed"), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); } } } @@ -562,64 +642,90 @@ struct DiHadronCor { } 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"), 2.5); + 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"), 3.5); + 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"), 4.5); + 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"), 5.5); + 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"), 6.5); + 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"), 7.5); + registry.fill(HIST("hEventCountSpecific"), 9.5); auto multNTracksPV = collision.multNTracksPV(); 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 (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"), 8.5); + registry.fill(HIST("hEventCountSpecific"), 10.5); // V0A T0A 5 sigma cut float sigma = 5.0; - if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > sigma * fT0AV0ASigma->Eval(collision.multFT0A()))) + 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"), 9.5); + registry.fill(HIST("hEventCountSpecific"), 11.5); return 1; } @@ -630,13 +736,18 @@ struct DiHadronCor { return; auto bc = collision.bc_as(); float cent = -1.; - if (!cfgCentTableUnavailable) + float weightCent = 1.0f; + if (!cfgCentTableUnavailable) { cent = getCentrality(collision); + } if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) return; - - if (!cfgCentTableUnavailable) + 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()); @@ -647,12 +758,11 @@ struct DiHadronCor { return; } - loadEfficiency(bc.timestamp()); 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); - fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent); + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent, weightCent); } PROCESS_SWITCH(DiHadronCor, processSame, "Process same event", true); @@ -671,8 +781,9 @@ struct DiHadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(tracks, tracks); - Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + 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; @@ -701,9 +812,16 @@ struct DiHadronCor { registry.fill(HIST("eventcount"), MixedEvent); // fill the mixed event in the 3 bin auto bc = collision1.bc_as(); - loadEfficiency(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); - fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1); + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1, eventWeight * weightCent); } } @@ -723,14 +841,16 @@ struct DiHadronCor { } } - void processMCEfficiency(FilteredMcCollisions::iterator const& mcCollision, aod::BCsWithTimestamps const&, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracksWithMCLabels const& tracks) + void processMCEfficiency(FilteredMcCollisions::iterator const& mcCollision, soa::SmallGroups> const& collisions, FilteredMcParticles const& mcParticles, FilteredTracksWithMCLabels const& tracks) { - if (cfgSelCollByNch && (tracks.size() < cfgCutMultMin || tracks.size() >= cfgCutMultMax)) { + 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()); } } @@ -743,13 +863,16 @@ struct DiHadronCor { for (const auto& track : groupedTracks) { if (track.has_mcParticle()) { - const auto& mcParticle = track.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()); } } @@ -791,14 +914,15 @@ struct DiHadronCor { } same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + 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); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); } PROCESS_SWITCH(DiHadronCor, processMCSame, "Process MC same event", false); @@ -815,8 +939,9 @@ struct DiHadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + 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; @@ -839,14 +964,19 @@ struct DiHadronCor { 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); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); if (groupedCollisions.size() == 0) { continue; } - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + registry.fill(HIST("MCTrue/MCeventcount"), 4.5); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); } } PROCESS_SWITCH(DiHadronCor, processMCMixed, "Process MC mixed events", false); @@ -873,10 +1003,10 @@ struct DiHadronCor { } same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepAll); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); same->fillEvent(mcParticles.size(), CorrelationContainer::kCFStepTrackedOnlyPrim); - fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent); + fillMCCorrelations(mcParticles, mcParticles, mcCollision.posZ(), SameEvent, 1.0f); } PROCESS_SWITCH(DiHadronCor, processOntheflySame, "Process on-the-fly same event", false); @@ -893,8 +1023,9 @@ struct DiHadronCor { MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxMix, axisMultMix}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pair{binningOnVtxAndMult, cfgMixEventNumMin, -1, mcCollisions, tracksTuple, &cache}; // -1 is the number of the bin to skip - for (auto const& [collision1, tracks1, collision2, tracks2] : pair) { + 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; @@ -903,10 +1034,14 @@ struct DiHadronCor { 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); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); - fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); + fillMCCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, eventWeight); } } PROCESS_SWITCH(DiHadronCor, processOntheflyMixed, "Process on-the-fly mixed events", false); diff --git a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx index 9a299ed8950..ba34f15f58d 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/lambdaR2Correlation.cxx @@ -13,22 +13,26 @@ /// \brief R2 correlation of Lambda baryons. /// \author Yash Patley -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Framework/AnalysisTask.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/mcCentrality.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/RecoDecay.h" -#include "CCDB/BasicCCDBManager.h" + #include "TPDGCode.h" +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -40,9 +44,11 @@ namespace o2::aod namespace lambdacollision { DECLARE_SOA_COLUMN(Cent, cent, float); -} +DECLARE_SOA_COLUMN(Mult, mult, float); +} // namespace lambdacollision DECLARE_SOA_TABLE(LambdaCollisions, "AOD", "LAMBDACOLS", o2::soa::Index<>, lambdacollision::Cent, + lambdacollision::Mult, aod::collision::PosX, aod::collision::PosY, aod::collision::PosZ); @@ -53,6 +59,7 @@ namespace lambdamcgencollision } DECLARE_SOA_TABLE(LambdaMcGenCollisions, "AOD", "LMCGENCOLS", o2::soa::Index<>, lambdacollision::Cent, + lambdacollision::Mult, o2::aod::mccollision::PosX, o2::aod::mccollision::PosY, o2::aod::mccollision::PosZ); @@ -152,8 +159,8 @@ enum TrackLabels { kPassV0KinCuts, kPassV0TopoSel, kAllSelPassed, - kNotPrimaryLambda, - kNotSecondaryLambda, + kPrimaryLambda, + kSecondaryLambda, kLambdaDauNotMcParticle, kLambdaNotPrPiMinus, kAntiLambdaNotAntiPrPiPlus, @@ -169,6 +176,11 @@ enum TrackLabels { kGenLambdaToPrPi }; +enum CentEstType { + kCentFT0M = 0, + kCentFV0A +}; + enum RunType { kRun3 = 0, kRun2 @@ -226,6 +238,7 @@ struct LambdaTableProducer { 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"}; @@ -242,14 +255,15 @@ struct LambdaTableProducer { Configurable cIsGoodITSLayers{"cIsGoodITSLayers", false, "Good ITS Layers All"}; // Tracks - Configurable cTrackMinPt{"cTrackMinPt", 0.16, "p_{T} minimum"}; - Configurable cTrackMaxPt{"cTrackMaxPt", 999.0, "p_{T} minimum"}; + 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", 80, "TPC Min Crossed Rows"}; + 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", 5.0, "TPC NSigma Selection Cut"}; + 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"}; @@ -314,9 +328,8 @@ struct LambdaTableProducer { {"hPrimFracVsPtEtaCentLambda", "hPrimFracVsPtEtaCentAntiLambda"}}; // Initialize Global Variables - float cent = 0.; + float cent = 0., mult = 0.; float pt = 0., eta = 0., rap = 0., phi = 0.; - bool bSecondaryLambdaFlag = false; void init(InitContext const&) { @@ -339,7 +352,7 @@ struct LambdaTableProducer { const AxisSpec axisV0Phi(36, 0., TwoPI, "#phi (rad)"); const AxisSpec axisRadius(2000, 0, 200, "r(cm)"); - const AxisSpec axisCosPA(500, 0.995, 1.0, "cos(#theta_{PA})"); + 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)"); @@ -404,13 +417,11 @@ struct LambdaTableProducer { histos.addClone("McRec/Lambda/", "McRec/AntiLambda/"); // MC Generated Histograms - if (doprocessMCRun3 || doprocessMCRun2) { + 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_from_sigma", "PIDs", kTH2F, {axisPID, axisV0Pt}); - histos.add("Tracks/h2f_lambda_from_cascade", "PIDs", kTH2F, {axisPID, axisV0Pt}); - histos.add("Tracks/h2f_lambda_from_omega", "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}); @@ -436,8 +447,8 @@ struct LambdaTableProducer { 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::kNotPrimaryLambda, "kNotPrimaryLambda"); - histos.get(HIST("Tracks/h1f_tracks_info"))->GetXaxis()->SetBinLabel(TrackLabels::kNotSecondaryLambda, "kNotSecondaryLambda"); + 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"); @@ -477,7 +488,12 @@ struct LambdaTableProducer { } if constexpr (run == kRun3) { // Run3 Min-Bias Trigger - cent = col.centFT0M(); + // select centrality estimator + if (cCentEstimator == kCentFT0M) { + cent = col.centFT0M(); + } else if (cCentEstimator == kCentFV0A) { + cent = col.centFV0A(); + } if (cSel8Trig && !col.sel8()) { return false; } @@ -491,7 +507,7 @@ struct LambdaTableProducer { } } - if (cent <= cMinMult || cent >= cMaxMult) { // select centrality + if (cent <= cMinMult || cent >= cMaxMult) { // select centrality percentile class return false; } @@ -523,6 +539,9 @@ struct LambdaTableProducer { return false; } + // Set Multiplicity + mult = col.multNTracksPV(); + return true; } @@ -736,6 +755,30 @@ struct LambdaTableProducer { 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) { @@ -743,12 +786,11 @@ struct LambdaTableProducer { // check for secondary lambda if (!mcpart.isPhysicalPrimary()) { - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotPrimaryLambda); - bSecondaryLambdaFlag = true; + histos.fill(HIST("Tracks/h1f_tracks_info"), kSecondaryLambda); return kSecondary; } - histos.fill(HIST("Tracks/h1f_tracks_info"), kNotSecondaryLambda); + histos.fill(HIST("Tracks/h1f_tracks_info"), kPrimaryLambda); return kPrimary; } @@ -789,18 +831,6 @@ struct LambdaTableProducer { } } - // get information about secondary lambdas - if (bSecondaryLambdaFlag) { - auto lambdaMothers = mcpart.template mothers_as(); - if (std::abs(lambdaMothers[0].pdgCode()) == kSigmaMinus || std::abs(lambdaMothers[0].pdgCode()) == kSigma0 || std::abs(lambdaMothers[0].pdgCode()) == kSigmaPlus) { - histos.fill(HIST("Tracks/h2f_lambda_from_sigma"), mcpart.pdgCode(), mcpart.pt()); - } else if (std::abs(lambdaMothers[0].pdgCode()) == kXiMinus || std::abs(lambdaMothers[0].pdgCode()) == kXi0) { - histos.fill(HIST("Tracks/h2f_lambda_from_cascade"), mcpart.pdgCode(), mcpart.pt()); - } else if (std::abs(lambdaMothers[0].pdgCode()) == kOmegaMinus) { - histos.fill(HIST("Tracks/h2f_lambda_from_omega"), mcpart.pdgCode(), mcpart.pt()); - } - } - return true; } @@ -865,6 +895,14 @@ struct LambdaTableProducer { 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&) { @@ -945,7 +983,7 @@ struct LambdaTableProducer { histos.fill(HIST("Events/h1f_collision_posZ"), collision.posZ()); // Fill Collision Table - lambdaCollisionTable(cent, collision.posX(), collision.posY(), collision.posZ()); + lambdaCollisionTable(cent, mult, collision.posX(), collision.posY(), collision.posZ()); // initialize v0track objects ParticleType v0Type = kLambda; @@ -977,6 +1015,13 @@ struct LambdaTableProducer { // 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(); @@ -988,13 +1033,21 @@ struct LambdaTableProducer { if constexpr (dmc == kMC) { histos.fill(HIST("Tracks/h2f_tracks_pid_before_sel"), v0.mcParticle().pdgCode(), v0.pt()); - if (cSelMCPSV0) { // Get Primary/Secondary Lambda + // Get Primary/Secondary Lambda + if (cSelMCPSV0) { v0PrmScdType = isPrimaryV0(v0); } - if (cSelectTrueLambda && !selTrueMcRecLambda(v0, tracks)) { // check for true Lambda/Anti-Lambda + + // 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()); @@ -1040,7 +1093,7 @@ struct LambdaTableProducer { void fillLambdaMcGenTables(C const& mcCollision, M const& mcParticles) { // Fill McGen Collision Table - lambdaMCGenCollisionTable(cent, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); + lambdaMCGenCollisionTable(cent, mult, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ()); // initialize track objects ParticleType v0Type = kLambda; @@ -1170,11 +1223,13 @@ struct LambdaTableProducer { SliceCache cache; Preslice> perCollision = aod::v0data::collisionId; - using CollisionsRun3 = soa::Join; - using CollisionsRun2 = soa::Join; - using Tracks = soa::Join; - using McV0Tracks = soa::Join; + 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) { @@ -1183,13 +1238,37 @@ struct LambdaTableProducer { PROCESS_SWITCH(LambdaTableProducer, processDataRun3, "Process for Run3 DATA", true); - void processDataRun2(CollisionsRun2::iterator const& collision, aod::V0Datas const& V0s, Tracks const& tracks) + 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, @@ -1202,7 +1281,7 @@ struct LambdaTableProducer { void processMCRun2(aod::McCollisions::iterator const& mcCollision, soa::SmallGroups> const& collisions, - McV0Tracks const& V0s, TracksMC const& tracks, + McV0Tracks const& V0s, TracksMCRun2 const& tracks, aod::McParticles const& mcParticles) { analyzeMcRecoGen(mcCollision, collisions, V0s, tracks, mcParticles); @@ -1426,6 +1505,7 @@ struct LambdaR2Correlation { 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})"); @@ -1439,8 +1519,9 @@ struct LambdaR2Correlation { // 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/h1i_lambda_mult", "#Lambda - Multiplicity", kTH1I, {axisMult}); - histos.add("Event/Reco/h1i_antilambda_mult", "#bar{#Lambda} - Multiplicity", kTH1I, {axisMult}); + histos.add("Event/Reco/h2f_Mult_vs_Centrality", "N_{TPC} 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 @@ -1453,6 +1534,8 @@ struct LambdaR2Correlation { // Single and Two Particle Densities // 1D Histograms + histos.add("Reco/Primary/h2f_n1_mass_LaP", "#rho_{1}^{#Lambda}", kTH2F, {axisCent, axisMass}); + histos.add("Reco/Primary/h2f_n1_mass_LaM", "#rho_{1}^{#bar{#Lambda}}", kTH2F, {axisCent, axisMass}); 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}); @@ -1565,6 +1648,7 @@ struct LambdaR2Correlation { 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("h2f_n1_mass_") + HIST(SubDirHist[part]), cent, track.mass()); 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()); @@ -1580,9 +1664,9 @@ struct LambdaR2Correlation { // fill multiplicity histograms if (ntrk != 0) { if (part == kLambda) { - histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h1i_lambda_mult"), ntrk); + histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h2f_lambda_mult"), cent, ntrk); } else { - histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h1i_antilambda_mult"), ntrk); + histos.fill(HIST("Event/") + HIST(SubDirRecGen[rec_gen]) + HIST("h2f_antilambda_mult"), cent, ntrk); } } } @@ -1614,6 +1698,7 @@ struct LambdaR2Correlation { { 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(); @@ -1666,6 +1751,7 @@ struct LambdaR2Correlation { { 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(); diff --git a/PWGCF/TwoParticleCorrelations/Tasks/longrangeCorrelation.cxx b/PWGCF/TwoParticleCorrelations/Tasks/longrangeCorrelation.cxx index 5fb1bc8e1c8..f9839d9e502 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/longrangeCorrelation.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/longrangeCorrelation.cxx @@ -12,50 +12,54 @@ /// \file longrangeCorrelation.cxx /// /// \brief task for long range correlation analysis -/// \author Abhi Modak (abhi.modak@cern.ch) and Debojit sarkar (debojit.sarkar@cern.ch) +/// \author Abhi Modak (abhi.modak@cern.ch) and Debojit Sarkar (debojit.sarkar@cern.ch) /// \since April 22, 2025 -#include -#include -#include -#include -#include -#include -#include +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGCF/Core/PairCuts.h" +#include "PWGCF/DataModel/CorrelationsDerived.h" +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/CollisionAssociationTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" #include "Common/DataModel/FT0Corrected.h" -#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "CommonConstants/MathConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DetectorsCommonDataFormats/AlignParam.h" #include "FT0Base/Geometry.h" #include "FV0Base/Geometry.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" -#include "DetectorsCommonDataFormats/AlignParam.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; +using namespace o2::aod::fwdtrack; using namespace o2::aod::evsel; using namespace o2::constants::math; @@ -71,9 +75,10 @@ static constexpr TrackSelectionFlags::flagtype TrackSelectionDca = static constexpr TrackSelectionFlags::flagtype TrackSelectionDcaxyOnly = TrackSelectionFlags::kDCAxy; +static constexpr std::string_view kCorrType[] = {"Ft0aGlobal/", "Ft0cGlobal/", "Fv0Global/", "MftGlobal/", "Fv0Mft/"}; +static constexpr std::string_view kEvntType[] = {"SE/", "ME/"}; + AxisSpec axisEvent{10, 0.5, 9.5, "#Event", "EventAxis"}; -AxisSpec amplitudeFT0{5000, 0, 10000, "FT0 amplitude"}; -AxisSpec channelFT0Axis{96, 0.0, 96.0, "FT0 channel"}; struct LongrangeCorrelation { @@ -86,6 +91,7 @@ struct LongrangeCorrelation { Service ccdb; o2::ccdb::CcdbApi ccdbApi; std::vector* offsetFT0; + std::vector* offsetFV0; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable cfgVtxCut{"cfgVtxCut", 10.0f, "Vertex Z range to consider"}; Configurable cfgEtaCut{"cfgEtaCut", 1.0f, "Eta range to consider"}; @@ -95,7 +101,12 @@ struct LongrangeCorrelation { Configurable mixingParameter{"mixingParameter", 5, "how many events are mixed"}; Configurable cfgMinMult{"cfgMinMult", 0, "Minimum multiplicity for collision"}; Configurable cfgMaxMult{"cfgMaxMult", 10, "Maximum multiplicity for collision"}; + Configurable cfigMftEtaMax{"cfigMftEtaMax", -2.5f, "Maximum MFT eta cut"}; + Configurable cfigMftEtaMin{"cfigMftEtaMin", -3.6f, "Minimum MFT eta cut"}; + Configurable cfigMftDcaxy{"cfigMftDcaxy", 2.0f, "cut on DCA xy for MFT tracks"}; + Configurable cfigMftCluster{"cfigMftCluster", 5, "cut on MFT Cluster"}; Configurable cfgSampleSize{"cfgSampleSize", 10, "Sample size for mixed event"}; + Configurable isApplySameBunchPileup{"isApplySameBunchPileup", false, "Enable SameBunchPileup cut"}; ConfigurableAxis axisDeltaPhi{"axisDeltaPhi", {72, -PIHalf, PIHalf * 3}, "delta phi axis for histograms"}; ConfigurableAxis axisDeltaEta{"axisDeltaEta", {40, -6, -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"}; @@ -111,13 +122,45 @@ struct LongrangeCorrelation { ConfigurableAxis axisEtaAssoc{"axisEtaAssoc", {96, 3.5, 4.9}, "#eta assoc axis"}; ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample 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"}; + ConfigurableAxis amplitudeFt0a{"amplitudeFt0a", {5000, 0, 10000}, "FT0A amplitude"}; + ConfigurableAxis channelFt0aAxis{"channelFt0aAxis", {96, 0.0, 96.0}, "FT0A channel"}; using CollTable = soa::Join; using TrksTable = soa::Filtered>; - Preslice perCollision = aod::track::collisionId; - - OutputObj same{Form("sameEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; - OutputObj mixed{Form("mixedEvent_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + using MftTrkTable = soa::Filtered; + Preslice perColGlobal = aod::track::collisionId; + Preslice perColMft = aod::fwdtrack::collisionId; + + o2::ft0::Geometry ft0Det; + o2::fv0::Geometry* fv0Det; + + OutputObj sameFt0aGlobal{Form("sameEventFt0aGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj mixedFt0aGlobal{Form("mixedEventFt0aGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj sameFt0cGlobal{Form("sameEventFt0cGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj mixedFt0cGlobal{Form("mixedEventFt0cGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj sameMftGlobal{Form("sameEventMftGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj mixedMftGlobal{Form("mixedEventMftGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj sameFv0Global{Form("sameEventFv0Global_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj mixedFv0Global{Form("mixedEventFv0Global_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj sameFv0Mft{Form("sameEventFv0Mft_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + OutputObj mixedFv0Mft{Form("mixedEventFv0Mft_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult))}; + + template + void addHistos() + { + histos.add(Form("%s%shMult", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH1D, {axisMultiplicity}); + histos.add(Form("%s%sTrig_etavsphi", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH2D, {axisPhi, axisEtaTrig}); + histos.add(Form("%s%sTrig_eta", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH1D, {axisEtaTrig}); + histos.add(Form("%s%sTrig_phi", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH1D, {axisPhi}); + histos.add(Form("%s%sTrig_pt", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH1D, {axisPtTrigger}); + histos.add(Form("%s%shMult_used", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH1F, {axisMultiplicity}); + histos.add(Form("%s%sTrig_hist", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTHnSparseF, {axisSample, axisVtxZ, axisPtTrigger}); + histos.add(Form("%s%sAssoc_amp", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH2D, {channelFt0aAxis, amplitudeFt0a}); + histos.add(Form("%s%sAssoc_eta", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH1D, {axisEtaAssoc}); + histos.add(Form("%s%sAssoc_phi", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH1D, {axisPhi}); + histos.add(Form("%s%sAssoc_etavsphi", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH2D, {axisPhi, axisEtaAssoc}); + histos.add(Form("%s%sdeltaEta_deltaPhi", kCorrType[corrType].data(), kEvntType[evntType].data()), "", kTH2D, {axisDeltaPhi, axisDeltaEta}); + } void init(InitContext const&) { @@ -128,45 +171,11 @@ struct LongrangeCorrelation { ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); LOGF(info, "Getting alignment offsets from the CCDB..."); offsetFT0 = ccdb->getForTimeStamp>("FT0/Calib/Align", cfgCcdbParam.noLaterThan.value); + offsetFV0 = ccdb->getForTimeStamp>("FV0/Calib/Align", cfgCcdbParam.noLaterThan.value); 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()); - - // QA histos - histos.add("QA/EventHist", "events", kTH1F, {axisEvent}, false); - histos.add("QA/VtxZHist", "v_{z} (cm)", kTH1F, {axisVtxZ}, false); - histos.add("QA/hMEpvz1", ";pvz;Entries", kTH1F, {{30, -15, 15}}); - histos.add("QA/hMEpvz2", ";pvz;Entries", kTH1F, {{30, -15, 15}}); - histos.add("QA/hMixingQA", "events", kTH1F, {axisEvent}, false); - - auto hstat = histos.get(HIST("QA/EventHist")); - auto* x = hstat->GetXaxis(); - x->SetBinLabel(1, "All events"); - x->SetBinLabel(2, "sel8"); - x->SetBinLabel(3, "|vz|<10"); - - histos.add("SE/hMult", "event multiplicity", kTH1D, {axisMultiplicity}); - histos.add("SE/Trig_etavsphi", ";#eta;#phi", kTH2D, {axisPhi, axisEtaTrig}); - histos.add("SE/Trig_eta", "#eta", kTH1D, {axisEtaTrig}); - histos.add("SE/Trig_phi", "#eta", kTH1D, {axisPhi}); - histos.add("SE/Trig_pt", "p_{T}", kTH1D, {axisPtTrigger}); - histos.add("SE/hMult_used", "event multiplicity", kTH1F, {axisMultiplicity}); - histos.add("SE/Trig_hist", "trig hist", kTHnSparseF, {axisSample, axisVtxZ, axisPtTrigger}); - histos.add("SE/FT0Amp", "ftoamult", kTH2D, {channelFT0Axis, amplitudeFT0}); - histos.add("SE/FT0Aeta", "ft0a;#eta", kTH1D, {axisEtaAssoc}); - histos.add("SE/FT0Aphi", "ft0a;#phi", kTH1D, {axisPhi}); - histos.add("SE/FT0Aetavsphi", ";ft0a;#eta;#phi", kTH2D, {axisPhi, axisEtaAssoc}); - histos.add("SE/deltaEta_deltaPhi", ";#delta#eta;#delta#phi", kTH2D, {axisDeltaPhi, axisDeltaEta}); - - histos.add("ME/hMult", "event multiplicity", kTH1D, {axisMultiplicity}); - histos.add("ME/Trig_etavsphi", ";#eta;#phi", kTH2D, {axisPhi, axisEtaTrig}); - histos.add("ME/Trig_eta", "#eta", kTH1D, {axisEtaTrig}); - histos.add("ME/Trig_phi", "#eta", kTH1D, {axisPhi}); - histos.add("ME/Trig_pt", "p_{T}", kTH1D, {axisPtTrigger}); - histos.add("ME/FT0Amp", "ftoamult", kTH2D, {channelFT0Axis, amplitudeFT0}); - histos.add("ME/FT0Aeta", "ft0a;#eta", kTH1D, {axisEtaAssoc}); - histos.add("ME/FT0Aphi", "ft0a;#phi", kTH1D, {axisPhi}); - histos.add("ME/FT0Aetavsphi", ";ft0a;#eta;#phi", kTH2D, {axisPhi, axisEtaAssoc}); - histos.add("ME/deltaEta_deltaPhi", ";#delta#eta;#delta#phi", kTH2D, {axisDeltaPhi, axisDeltaEta}); + 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()); std::vector corrAxis = {{axisSample, "Sample"}, {axisVtxZ, "z-vtx (cm)"}, @@ -180,145 +189,487 @@ struct LongrangeCorrelation { 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)); + fv0Det = o2::fv0::Geometry::instance(o2::fv0::Geometry::eUninitialized); + + if (doprocessEventStat) { + histos.add("QA/EventHist", "events", kTH1F, {axisEvent}, false); + histos.add("QA/VtxZHist", "v_{z} (cm)", kTH1F, {axisVtxZ}, false); + + auto hstat = histos.get(HIST("QA/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, "|vz|<10"); + } + + if (doprocessFt0aGlobalSE || doprocessFt0aGlobalME) { + addHistos<0, 0>(); + addHistos<0, 1>(); + sameFt0aGlobal.setObject(new CorrelationContainer(Form("sameEventFt0aGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("sameEventFt0aGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + mixedFt0aGlobal.setObject(new CorrelationContainer(Form("mixedEventFt0aGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("mixedEventFt0aGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + } + + if (doprocessFt0cGlobalSE || doprocessFt0cGlobalME) { + addHistos<1, 0>(); + addHistos<1, 1>(); + sameFt0cGlobal.setObject(new CorrelationContainer(Form("sameEventFt0cGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("sameEventFt0cGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + mixedFt0cGlobal.setObject(new CorrelationContainer(Form("mixedEventFt0cGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("mixedEventFt0cGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + } + + if (doprocessFv0GlobalSE || doprocessFv0GlobalME) { + addHistos<2, 0>(); + addHistos<2, 1>(); + sameFv0Global.setObject(new CorrelationContainer(Form("sameEventFv0Global_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("sameEventFv0Global_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + mixedFv0Global.setObject(new CorrelationContainer(Form("mixedEventFv0Global_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("mixedEventFv0Global_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + } + + if (doprocessMftGlobalSE || doprocessMftGlobalME) { + addHistos<3, 0>(); + addHistos<3, 1>(); + sameMftGlobal.setObject(new CorrelationContainer(Form("sameEventMftGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("sameEventMftGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + mixedMftGlobal.setObject(new CorrelationContainer(Form("mixedEventMftGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("mixedEventMftGlobal_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + } + + if (doprocessFv0MftSE || doprocessFv0MftME) { + addHistos<4, 0>(); + addHistos<4, 1>(); + sameFv0Mft.setObject(new CorrelationContainer(Form("sameEventFv0Mft_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("sameEventFv0Mft_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + mixedFv0Mft.setObject(new CorrelationContainer(Form("mixedEventFv0Mft_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), Form("mixedEventFv0Mft_%i_%i", static_cast(cfgMinMult), static_cast(cfgMaxMult)), corrAxis, effAxis, userAxis)); + } } - double getPhiFT0(int chno, double offsetX, double offsetY) + Filter fTrackSelectionITS = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && + ncheckbit(aod::track::trackCutFlag, TrackSelectionIts); + Filter fTrackSelectionTPC = ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC), + ncheckbit(aod::track::trackCutFlag, TrackSelectionTpc), true); + Filter fTrackSelectionDCA = ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, TrackSelectionDcaxyOnly), + ncheckbit(aod::track::trackCutFlag, TrackSelectionDca)); + Filter fTracksEta = nabs(aod::track::eta) < cfgEtaCut; + Filter fTracksPt = (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax); + + Filter fMftTrackEta = (aod::fwdtrack::eta < cfigMftEtaMax) && (aod::fwdtrack::eta > cfigMftEtaMin); + Filter fMftTrackColID = (aod::fwdtrack::bestCollisionId >= 0); + Filter fMftTrackDca = (nabs(aod::fwdtrack::bestDCAXY) < cfigMftDcaxy); + + double getPhiFT0(int chno, int i) { - o2::ft0::Geometry ft0Det; ft0Det.calculateChannelCenter(); auto chPos = ft0Det.getChannelCenter(chno); - return RecoDecay::phi(chPos.X() + offsetX, chPos.Y() + offsetY); + return RecoDecay::phi(chPos.X() + (*offsetFT0)[i].getX(), chPos.Y() + (*offsetFT0)[i].getY()); } - double getEtaFT0(int chno, double offsetX, double offsetY, double offsetZ) + double getPhiFV0(int chno) + { + int 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 isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + float offsetX, offsetY; + if (isChnoInLeft) { + offsetX = (*offsetFV0)[0].getX(); + offsetY = (*offsetFV0)[0].getY(); + } else { + offsetX = (*offsetFV0)[1].getX(); + offsetY = (*offsetFV0)[1].getY(); + } + + auto chPos = fv0Det->getReadoutCenter(chno); + return RecoDecay::phi(chPos.x + offsetX, chPos.y + offsetY); + } + + double getEtaFT0(int chno, int i) { - o2::ft0::Geometry ft0Det; ft0Det.calculateChannelCenter(); auto chPos = ft0Det.getChannelCenter(chno); - auto x = chPos.X() + offsetX; - auto y = chPos.Y() + offsetY; - auto z = chPos.Z() + offsetZ; + auto x = chPos.X() + (*offsetFT0)[i].getX(); + auto y = chPos.Y() + (*offsetFT0)[i].getY(); + auto z = chPos.Z() + (*offsetFT0)[i].getZ(); auto r = std::sqrt(x * x + y * y); auto theta = std::atan2(r, z); return -std::log(std::tan(0.5 * theta)); } - Filter fTrackSelectionITS = ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) && - ncheckbit(aod::track::trackCutFlag, TrackSelectionIts); - Filter fTrackSelectionTPC = ifnode(ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC), - ncheckbit(aod::track::trackCutFlag, TrackSelectionTpc), true); - Filter fTrackSelectionDCA = ifnode(dcaZ.node() > 0.f, nabs(aod::track::dcaZ) <= dcaZ && ncheckbit(aod::track::trackCutFlag, TrackSelectionDcaxyOnly), - ncheckbit(aod::track::trackCutFlag, TrackSelectionDca)); - Filter fTracksEta = nabs(aod::track::eta) < cfgEtaCut; - Filter fTracksPt = (aod::track::pt > cfgPtCutMin) && (aod::track::pt < cfgPtCutMax); + double getEtaFV0(int chno) + { + int 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 isChnoInLeft = std::find(std::begin(cellsInLeft), std::end(cellsInLeft), chno) != std::end(cellsInLeft); + 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 chPos = fv0Det->getReadoutCenter(chno); + 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)); + } template bool isEventSelected(CheckCol const& col) { - histos.fill(HIST("QA/EventHist"), 1); if (!col.sel8()) { return false; } - histos.fill(HIST("QA/EventHist"), 2); + if (isApplySameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } if (std::abs(col.posZ()) >= cfgVtxCut) { return false; } - histos.fill(HIST("QA/EventHist"), 3); - histos.fill(HIST("QA/VtxZHist"), col.posZ()); return true; } - template - void fillYield(TTracks tracks, bool mixing) + template + bool isMftTrackSelected(CheckMftTrack const& track) { - if (mixing) { - histos.fill(HIST("ME/hMult"), tracks.size()); - for (auto const& triggerTrack : tracks) { - histos.fill(HIST("ME/Trig_etavsphi"), triggerTrack.phi(), triggerTrack.eta()); - histos.fill(HIST("ME/Trig_eta"), triggerTrack.eta()); - histos.fill(HIST("ME/Trig_phi"), triggerTrack.phi()); - histos.fill(HIST("ME/Trig_pt"), triggerTrack.pt()); + if (track.nClusters() < cfigMftCluster) { + return false; + } + return true; + } + + template + void fillYield(TTracks tracks) + { + if (evntType == 1) { + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("hMult"), tracks.size()); + for (auto const& iTrk : tracks) { + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_etavsphi"), iTrk.phi(), iTrk.eta()); + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_eta"), iTrk.eta()); + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_phi"), iTrk.phi()); + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_pt"), iTrk.pt()); } } else { - histos.fill(HIST("SE/hMult"), tracks.size()); - for (auto const& triggerTrack : tracks) { - histos.fill(HIST("SE/Trig_etavsphi"), triggerTrack.phi(), triggerTrack.eta()); - histos.fill(HIST("SE/Trig_eta"), triggerTrack.eta()); - histos.fill(HIST("SE/Trig_phi"), triggerTrack.phi()); - histos.fill(HIST("SE/Trig_pt"), triggerTrack.pt()); + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("hMult"), tracks.size()); + for (auto const& iTrk : tracks) { + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_etavsphi"), iTrk.phi(), iTrk.eta()); + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_eta"), iTrk.eta()); + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_phi"), iTrk.phi()); + histos.fill(HIST(kCorrType[corrType]) + HIST(kEvntType[evntType]) + HIST("Trig_pt"), iTrk.pt()); } } } template - void fillCorrelation(TTarget target, TTriggers const& triggers, TFT0s const& ft0, bool mixing, float vz) + void fillCorrFt0aGlobal(TTarget target, TTriggers const& triggers, TFT0s const& ft0, bool mixing, float vz) { int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); if (!mixing) - histos.fill(HIST("SE/hMult_used"), triggers.size()); + histos.fill(HIST("Ft0aGlobal/SE/hMult_used"), triggers.size()); for (auto const& triggerTrack : triggers) { if (!mixing) - histos.fill(HIST("SE/Trig_hist"), fSampleIndex, vz, triggerTrack.pt()); - - auto offsetFT0Ax = (*offsetFT0)[0].getX(); - auto offsetFT0Ay = (*offsetFT0)[0].getY(); - auto offsetFT0Az = (*offsetFT0)[0].getZ(); - for (std::size_t iChA = 0; iChA < ft0.channelA().size(); iChA++) { - auto chanelid = ft0.channelA()[iChA]; - float ampl = ft0.amplitudeA()[iChA]; + histos.fill(HIST("Ft0aGlobal/SE/Trig_hist"), fSampleIndex, vz, triggerTrack.pt()); + + for (std::size_t iCh = 0; iCh < ft0.channelA().size(); iCh++) { + auto chanelid = ft0.channelA()[iCh]; + float ampl = ft0.amplitudeA()[iCh]; if (ampl <= 0) continue; if (mixing) - histos.fill(HIST("ME/FT0Amp"), chanelid, ampl); + histos.fill(HIST("Ft0aGlobal/ME/Assoc_amp"), chanelid, ampl); else - histos.fill(HIST("SE/FT0Amp"), chanelid, ampl); + histos.fill(HIST("Ft0aGlobal/SE/Assoc_amp"), chanelid, ampl); - auto phiA = getPhiFT0(chanelid, offsetFT0Ax, offsetFT0Ay); - auto etaA = getEtaFT0(chanelid, offsetFT0Ax, offsetFT0Ay, offsetFT0Az); + auto phi = getPhiFT0(chanelid, 0); + auto eta = getEtaFT0(chanelid, 0); if (mixing) { - histos.fill(HIST("ME/FT0Aeta"), etaA); - histos.fill(HIST("ME/FT0Aphi"), phiA); - histos.fill(HIST("ME/FT0Aetavsphi"), phiA, etaA); + histos.fill(HIST("Ft0aGlobal/ME/Assoc_eta"), eta); + histos.fill(HIST("Ft0aGlobal/ME/Assoc_phi"), phi); + histos.fill(HIST("Ft0aGlobal/ME/Assoc_etavsphi"), phi, eta); } else { - histos.fill(HIST("SE/FT0Aeta"), etaA); - histos.fill(HIST("SE/FT0Aphi"), phiA); - histos.fill(HIST("SE/FT0Aetavsphi"), phiA, etaA); + histos.fill(HIST("Ft0aGlobal/SE/Assoc_eta"), eta); + histos.fill(HIST("Ft0aGlobal/SE/Assoc_phi"), phi); + histos.fill(HIST("Ft0aGlobal/SE/Assoc_etavsphi"), phi, eta); } - float deltaPhi = RecoDecay::constrainAngle(triggerTrack.phi() - phiA, -PIHalf); - float deltaEta = triggerTrack.eta() - etaA; + float deltaPhi = RecoDecay::constrainAngle(triggerTrack.phi() - phi, -PIHalf); + float deltaEta = triggerTrack.eta() - eta; if (mixing) - histos.fill(HIST("ME/deltaEta_deltaPhi"), deltaPhi, deltaEta); + histos.fill(HIST("Ft0aGlobal/ME/deltaEta_deltaPhi"), deltaPhi, deltaEta); else - histos.fill(HIST("SE/deltaEta_deltaPhi"), deltaPhi, deltaEta); + histos.fill(HIST("Ft0aGlobal/SE/deltaEta_deltaPhi"), deltaPhi, deltaEta); target->getPairHist()->Fill(step, fSampleIndex, vz, triggerTrack.pt(), triggerTrack.pt(), deltaPhi, deltaEta); } // associated ft0 tracks } // trigger tracks - } // fillCorrelation + } // fillCorrFt0aGlobal - void processSE(CollTable::iterator const& col, aod::FT0s const&, TrksTable const& tracks) + template + void fillCorrFt0cGlobal(TTarget target, TTriggers const& triggers, TFT0s const& ft0, bool mixing, float vz) + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + if (!mixing) + histos.fill(HIST("Ft0cGlobal/SE/hMult_used"), triggers.size()); + for (auto const& triggerTrack : triggers) { + if (!mixing) + histos.fill(HIST("Ft0cGlobal/SE/Trig_hist"), fSampleIndex, vz, triggerTrack.pt()); + + for (std::size_t iCh = 0; iCh < ft0.channelC().size(); iCh++) { + auto chanelid = ft0.channelC()[iCh]; + float ampl = ft0.amplitudeC()[iCh]; + if (ampl <= 0) + continue; + if (mixing) + histos.fill(HIST("Ft0cGlobal/ME/Assoc_amp"), chanelid, ampl); + else + histos.fill(HIST("Ft0cGlobal/SE/Assoc_amp"), chanelid, ampl); + + auto phi = getPhiFT0(chanelid, 1); + auto eta = getEtaFT0(chanelid, 1); + + if (mixing) { + histos.fill(HIST("Ft0cGlobal/ME/Assoc_eta"), eta); + histos.fill(HIST("Ft0cGlobal/ME/Assoc_phi"), phi); + histos.fill(HIST("Ft0cGlobal/ME/Assoc_etavsphi"), phi, eta); + } else { + histos.fill(HIST("Ft0cGlobal/SE/Assoc_eta"), eta); + histos.fill(HIST("Ft0cGlobal/SE/Assoc_phi"), phi); + histos.fill(HIST("Ft0cGlobal/SE/Assoc_etavsphi"), phi, eta); + } + float deltaPhi = RecoDecay::constrainAngle(triggerTrack.phi() - phi, -PIHalf); + float deltaEta = triggerTrack.eta() - eta; + if (mixing) + histos.fill(HIST("Ft0cGlobal/ME/deltaEta_deltaPhi"), deltaPhi, deltaEta); + else + histos.fill(HIST("Ft0cGlobal/SE/deltaEta_deltaPhi"), deltaPhi, deltaEta); + target->getPairHist()->Fill(step, fSampleIndex, vz, triggerTrack.pt(), triggerTrack.pt(), deltaPhi, deltaEta); + } // associated ft0 tracks + } // trigger tracks + } // fillCorrFt0cGlobal + + template + void fillCorrMftGlobal(TTarget target, TTriggers const& triggers, TMFTs const& mft, bool mixing, float vz) + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + if (!mixing) + histos.fill(HIST("MftGlobal/SE/hMult_used"), triggers.size()); + for (auto const& triggerTrack : triggers) { + if (!mixing) + histos.fill(HIST("MftGlobal/SE/Trig_hist"), fSampleIndex, vz, triggerTrack.pt()); + + for (auto const& assoTrack : mft) { + if (!isMftTrackSelected(assoTrack)) { + continue; + } + auto phi = assoTrack.phi(); + o2::math_utils::bringTo02Pi(phi); + if (mixing) { + histos.fill(HIST("MftGlobal/ME/Assoc_eta"), assoTrack.eta()); + histos.fill(HIST("MftGlobal/ME/Assoc_phi"), phi); + histos.fill(HIST("MftGlobal/ME/Assoc_etavsphi"), phi, assoTrack.eta()); + } else { + histos.fill(HIST("MftGlobal/SE/Assoc_eta"), assoTrack.eta()); + histos.fill(HIST("MftGlobal/SE/Assoc_phi"), phi); + histos.fill(HIST("MftGlobal/SE/Assoc_etavsphi"), phi, assoTrack.eta()); + } + float deltaPhi = RecoDecay::constrainAngle(triggerTrack.phi() - phi, -PIHalf); + float deltaEta = triggerTrack.eta() - assoTrack.eta(); + if (mixing) + histos.fill(HIST("MftGlobal/ME/deltaEta_deltaPhi"), deltaPhi, deltaEta); + else + histos.fill(HIST("MftGlobal/SE/deltaEta_deltaPhi"), deltaPhi, deltaEta); + target->getPairHist()->Fill(step, fSampleIndex, vz, triggerTrack.pt(), assoTrack.pt(), deltaPhi, deltaEta); + } // associated mft tracks + } // trigger tracks + } // fillCorrMftGlobal + + template + void fillCorrFv0Global(TTarget target, TTriggers const& triggers, TFV0s const& fv0, bool mixing, float vz) + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + if (!mixing) + histos.fill(HIST("Fv0Global/SE/hMult_used"), triggers.size()); + for (auto const& triggerTrack : triggers) { + if (!mixing) + histos.fill(HIST("Fv0Global/SE/Trig_hist"), fSampleIndex, vz, triggerTrack.pt()); + + for (std::size_t iCh = 0; iCh < fv0.channel().size(); iCh++) { + auto chanelid = fv0.channel()[iCh]; + float ampl = fv0.amplitude()[iCh]; + if (ampl <= 0) + continue; + if (mixing) + histos.fill(HIST("Fv0Global/ME/Assoc_amp"), chanelid, ampl); + else + histos.fill(HIST("Fv0Global/SE/Assoc_amp"), chanelid, ampl); + + auto phi = getPhiFV0(chanelid); + auto eta = getEtaFV0(chanelid); + + if (mixing) { + histos.fill(HIST("Fv0Global/ME/Assoc_eta"), eta); + histos.fill(HIST("Fv0Global/ME/Assoc_phi"), phi); + histos.fill(HIST("Fv0Global/ME/Assoc_etavsphi"), phi, eta); + } else { + histos.fill(HIST("Fv0Global/SE/Assoc_eta"), eta); + histos.fill(HIST("Fv0Global/SE/Assoc_phi"), phi); + histos.fill(HIST("Fv0Global/SE/Assoc_etavsphi"), phi, eta); + } + float deltaPhi = RecoDecay::constrainAngle(triggerTrack.phi() - phi, -PIHalf); + float deltaEta = triggerTrack.eta() - eta; + if (mixing) + histos.fill(HIST("Fv0Global/ME/deltaEta_deltaPhi"), deltaPhi, deltaEta); + else + histos.fill(HIST("Fv0Global/SE/deltaEta_deltaPhi"), deltaPhi, deltaEta); + target->getPairHist()->Fill(step, fSampleIndex, vz, triggerTrack.pt(), triggerTrack.pt(), deltaPhi, deltaEta); + } // associated fv0 tracks + } // trigger tracks + } // fillCorrFv0Global + + template + void fillCorrFv0Mft(TTarget target, TTracks const& tracks, TTriggers const& triggers, TFV0s const& fv0, bool mixing, float vz) + { + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + if (!mixing) + histos.fill(HIST("Fv0Mft/SE/hMult_used"), tracks.size()); + for (auto const& triggerTrack : triggers) { + if (!isMftTrackSelected(triggerTrack)) { + continue; + } + if (!mixing) + histos.fill(HIST("Fv0Mft/SE/Trig_hist"), fSampleIndex, vz, triggerTrack.pt()); + + auto trigphi = triggerTrack.phi(); + o2::math_utils::bringTo02Pi(trigphi); + + for (std::size_t iCh = 0; iCh < fv0.channel().size(); iCh++) { + auto chanelid = fv0.channel()[iCh]; + float ampl = fv0.amplitude()[iCh]; + if (ampl <= 0) + continue; + if (mixing) + histos.fill(HIST("Fv0Mft/ME/Assoc_amp"), chanelid, ampl); + else + histos.fill(HIST("Fv0Mft/SE/Assoc_amp"), chanelid, ampl); + + auto phi = getPhiFV0(chanelid); + auto eta = getEtaFV0(chanelid); + + if (mixing) { + histos.fill(HIST("Fv0Mft/ME/Assoc_eta"), eta); + histos.fill(HIST("Fv0Mft/ME/Assoc_phi"), phi); + histos.fill(HIST("Fv0Mft/ME/Assoc_etavsphi"), phi, eta); + } else { + histos.fill(HIST("Fv0Mft/SE/Assoc_eta"), eta); + histos.fill(HIST("Fv0Mft/SE/Assoc_phi"), phi); + histos.fill(HIST("Fv0Mft/SE/Assoc_etavsphi"), phi, eta); + } + + float deltaPhi = RecoDecay::constrainAngle(trigphi - phi, -PIHalf); + float deltaEta = triggerTrack.eta() - eta; + if (mixing) + histos.fill(HIST("Fv0Mft/ME/deltaEta_deltaPhi"), deltaPhi, deltaEta); + else + histos.fill(HIST("Fv0Mft/SE/deltaEta_deltaPhi"), deltaPhi, deltaEta); + target->getPairHist()->Fill(step, fSampleIndex, vz, triggerTrack.pt(), triggerTrack.pt(), deltaPhi, deltaEta); + } // associated fv0 tracks + } // trigger tracks + } // fillCorrFv0Mft + + void processEventStat(CollTable::iterator const& col) + { + histos.fill(HIST("QA/EventHist"), 1); + if (!col.sel8()) { + return; + } + histos.fill(HIST("QA/EventHist"), 2); + if (isApplySameBunchPileup && !col.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return; + } + histos.fill(HIST("QA/EventHist"), 3); + if (std::abs(col.posZ()) >= cfgVtxCut) { + return; + } + histos.fill(HIST("QA/EventHist"), 4); + histos.fill(HIST("QA/VtxZHist"), col.posZ()); + } + + void processFt0aGlobalSE(CollTable::iterator const& col, aod::FT0s const&, TrksTable const& tracks) { if (!isEventSelected(col)) { return; } if (col.has_foundFT0()) { - fillYield(tracks, false); + fillYield<0, 0>(tracks); const auto& ft0 = col.foundFT0(); if (tracks.size() < cfgMinMult || tracks.size() >= cfgMaxMult) { return; } - fillCorrelation(same, tracks, ft0, false, col.posZ()); + fillCorrFt0aGlobal(sameFt0aGlobal, tracks, ft0, false, col.posZ()); + } + } // same event + + void processFt0cGlobalSE(CollTable::iterator const& col, aod::FT0s const&, TrksTable const& tracks) + { + if (!isEventSelected(col)) { + return; + } + if (col.has_foundFT0()) { + fillYield<1, 0>(tracks); + const auto& ft0 = col.foundFT0(); + if (tracks.size() < cfgMinMult || tracks.size() >= cfgMaxMult) { + return; + } + fillCorrFt0cGlobal(sameFt0cGlobal, tracks, ft0, false, col.posZ()); + } + } // same event + + void processMftGlobalSE(CollTable::iterator const& col, MftTrkTable const& mfttracks, TrksTable const& tracks) + { + if (!isEventSelected(col)) { + return; + } + fillYield<3, 0>(tracks); + if (tracks.size() < cfgMinMult || tracks.size() >= cfgMaxMult) { + return; + } + fillCorrMftGlobal(sameMftGlobal, tracks, mfttracks, false, col.posZ()); + } // same event + + void processFv0GlobalSE(CollTable::iterator const& col, aod::FV0As const&, TrksTable const& tracks) + { + if (!isEventSelected(col)) { + return; + } + if (col.has_foundFV0()) { + fillYield<2, 0>(tracks); + const auto& fv0 = col.foundFV0(); + if (tracks.size() < cfgMinMult || tracks.size() >= cfgMaxMult) { + return; + } + fillCorrFv0Global(sameFv0Global, tracks, fv0, false, col.posZ()); + } + } // same event + + void processFv0MftSE(CollTable::iterator const& col, aod::FV0As const&, TrksTable const& tracks, MftTrkTable const& mfttracks) + { + if (!isEventSelected(col)) { + return; + } + if (col.has_foundFV0()) { + fillYield<4, 0>(mfttracks); + const auto& fv0 = col.foundFV0(); + if (tracks.size() < cfgMinMult || tracks.size() >= cfgMaxMult) { + return; + } + fillCorrFv0Mft(sameFv0Mft, tracks, mfttracks, fv0, false, col.posZ()); } } // same event - void processME(CollTable const& col, aod::FT0s const&, TrksTable const& tracks) + void processFt0aGlobalME(CollTable const& col, aod::FT0s const&, TrksTable const& tracks) { auto getTracksSize = [&tracks, this](CollTable::iterator const& collision) { auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); return associatedTracks.size(); }; + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxZME, axisMultME}, true}; for (auto const& [col1, col2] : soa::selfCombinations(binningOnVtxAndMult, mixingParameter, -1, col, col)) { @@ -326,25 +677,138 @@ struct LongrangeCorrelation { continue; } if (col1.globalIndex() == col2.globalIndex()) { - histos.fill(HIST("QA/hMixingQA"), 1.0); // same-collision pair counting continue; } if (col1.has_foundFT0() && col2.has_foundFT0()) { - histos.fill(HIST("QA/hMEpvz1"), col1.posZ()); - histos.fill(HIST("QA/hMEpvz2"), col2.posZ()); - auto slicedTriggerTracks = tracks.sliceBy(perCollision, col1.globalIndex()); - fillYield(slicedTriggerTracks, true); + auto slicedTriggerTracks = tracks.sliceBy(perColGlobal, col1.globalIndex()); + fillYield<0, 1>(slicedTriggerTracks); const auto& ft0 = col2.foundFT0(); if (slicedTriggerTracks.size() < cfgMinMult || slicedTriggerTracks.size() >= cfgMaxMult) { continue; } - fillCorrelation(mixed, slicedTriggerTracks, ft0, true, col1.posZ()); + fillCorrFt0aGlobal(mixedFt0aGlobal, slicedTriggerTracks, ft0, true, col1.posZ()); + } + } + } // mixed event + + void processFt0cGlobalME(CollTable const& col, aod::FT0s const&, TrksTable const& tracks) + { + auto getTracksSize = [&tracks, this](CollTable::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + return associatedTracks.size(); + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxZME, axisMultME}, true}; + for (auto const& [col1, col2] : soa::selfCombinations(binningOnVtxAndMult, mixingParameter, -1, col, col)) { + if (!isEventSelected(col1) || !isEventSelected(col2)) { + continue; + } + if (col1.globalIndex() == col2.globalIndex()) { + continue; + } + if (col1.has_foundFT0() && col2.has_foundFT0()) { + auto slicedTriggerTracks = tracks.sliceBy(perColGlobal, col1.globalIndex()); + fillYield<1, 1>(slicedTriggerTracks); + const auto& ft0 = col2.foundFT0(); + if (slicedTriggerTracks.size() < cfgMinMult || slicedTriggerTracks.size() >= cfgMaxMult) { + continue; + } + fillCorrFt0cGlobal(mixedFt0cGlobal, slicedTriggerTracks, ft0, true, col1.posZ()); + } + } + } // mixed event + + void processMftGlobalME(CollTable const& col, MftTrkTable const& mfttracks, TrksTable const& tracks) + { + auto getTracksSize = [&tracks, this](CollTable::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + return associatedTracks.size(); + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxZME, axisMultME}, true}; + auto tracksTuple = std::make_tuple(tracks, mfttracks); + Pair pairs{binningOnVtxAndMult, mixingParameter, -1, col, tracksTuple, &cache}; + for (auto const& [col1, tracks1, col2, tracks2] : pairs) { + if (!isEventSelected(col1) || !isEventSelected(col2)) { + continue; + } + if ((tracks1.size() < cfgMinMult || tracks1.size() >= cfgMaxMult)) { + continue; + } + fillCorrMftGlobal(mixedMftGlobal, tracks1, tracks2, true, col1.posZ()); + } + } // mixed event + + void processFv0GlobalME(CollTable const& col, aod::FV0As const&, TrksTable const& tracks) + { + auto getTracksSize = [&tracks, this](CollTable::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + return associatedTracks.size(); + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxZME, axisMultME}, true}; + for (auto const& [col1, col2] : soa::selfCombinations(binningOnVtxAndMult, mixingParameter, -1, col, col)) { + if (!isEventSelected(col1) || !isEventSelected(col2)) { + continue; + } + if (col1.globalIndex() == col2.globalIndex()) { + continue; + } + if (col1.has_foundFV0() && col2.has_foundFV0()) { + auto slicedTriggerTracks = tracks.sliceBy(perColGlobal, col1.globalIndex()); + fillYield<2, 1>(slicedTriggerTracks); + const auto& fv0 = col2.foundFV0(); + if (slicedTriggerTracks.size() < cfgMinMult || slicedTriggerTracks.size() >= cfgMaxMult) { + continue; + } + fillCorrFv0Global(mixedFv0Global, slicedTriggerTracks, fv0, true, col1.posZ()); + } + } + } // mixed event + + void processFv0MftME(CollTable const& col, aod::FV0As const&, TrksTable const& tracks, MftTrkTable const& mfttracks) + { + auto getTracksSize = [&tracks, this](CollTable::iterator const& collision) { + auto associatedTracks = tracks.sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), this->cache); + return associatedTracks.size(); + }; + + using MixedBinning = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getTracksSize)>; + MixedBinning binningOnVtxAndMult{{getTracksSize}, {axisVtxZME, axisMultME}, true}; + for (auto const& [col1, col2] : soa::selfCombinations(binningOnVtxAndMult, mixingParameter, -1, col, col)) { + if (!isEventSelected(col1) || !isEventSelected(col2)) { + continue; + } + if (col1.globalIndex() == col2.globalIndex()) { + continue; + } + if (col1.has_foundFV0() && col2.has_foundFV0()) { + auto slicedGlobalTracks = tracks.sliceBy(perColGlobal, col1.globalIndex()); + auto slicedTriggerMftTracks = mfttracks.sliceBy(perColMft, col1.globalIndex()); + fillYield<4, 1>(slicedTriggerMftTracks); + const auto& fv0 = col2.foundFV0(); + if (slicedGlobalTracks.size() < cfgMinMult || slicedGlobalTracks.size() >= cfgMaxMult) { + continue; + } + fillCorrFv0Mft(mixedFv0Mft, slicedGlobalTracks, slicedTriggerMftTracks, fv0, true, col1.posZ()); } } } // mixed event - PROCESS_SWITCH(LongrangeCorrelation, processSE, "process same event", false); - PROCESS_SWITCH(LongrangeCorrelation, processME, "process mixed event", false); + PROCESS_SWITCH(LongrangeCorrelation, processEventStat, "event stat", false); + PROCESS_SWITCH(LongrangeCorrelation, processFt0aGlobalSE, "same event FT0a vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processFt0aGlobalME, "mixed event FT0a vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processFt0cGlobalSE, "same event FT0c vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processFt0cGlobalME, "mixed event FT0c vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processMftGlobalSE, "same event MFT vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processMftGlobalME, "mixed event MFT vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processFv0GlobalSE, "same event FV0 vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processFv0GlobalME, "mixed event FV0 vs global", false); + PROCESS_SWITCH(LongrangeCorrelation, processFv0MftSE, "same event FV0 vs MFT", false); + PROCESS_SWITCH(LongrangeCorrelation, processFv0MftME, "mixed event FV0 vs MFT", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGCF/TwoParticleCorrelations/Tasks/neutronProtonCorrZdc.cxx b/PWGCF/TwoParticleCorrelations/Tasks/neutronProtonCorrZdc.cxx index 1870c66da80..772d7c9d288 100644 --- a/PWGCF/TwoParticleCorrelations/Tasks/neutronProtonCorrZdc.cxx +++ b/PWGCF/TwoParticleCorrelations/Tasks/neutronProtonCorrZdc.cxx @@ -56,7 +56,10 @@ struct NeutronProtonCorrZdc { Configurable cfgZNmin{"cfgZNmin", -10, "Minimum value for ZN signal"}; Configurable cfgZNmax{"cfgZNmax", 350, "Maximum value for ZN signal"}; Configurable cfgZPmin{"cfgZPmin", -10, "Minimum value for ZP signal"}; - Configurable cfgZPmax{"cfgZPmax", 200, "Maximum value for ZP signal"}; + Configurable cfgZPmax{"cfgZPmax", 150, "Maximum value for ZP signal"}; + Configurable cfgAmplMin{"cfgAmplMin", -50, "Minimum value for sector amplitude"}; + Configurable cfgAmplMax{"cfgAmplMax", 300, "Maximum value for sector amplitude"}; + Configurable cfgNBinsAmpl{"cfgNBinsAmpl", 100, "Number of bins for sector amplitude histograms"}; Configurable cfgDiffZmin{"cfgDiffZmin", -30, "Minimum value for the diffZ signal"}; Configurable cfgDiffZmax{"cfgDiffZmax", 50, "Maximum value for the diffZ signal"}; Configurable cfgNBinsAlpha{"cfgNBinsAlpha", 100, "Number of bins for ZDC asymmetry"}; @@ -87,6 +90,9 @@ struct NeutronProtonCorrZdc { const AxisSpec axisZPCSignal{cfgNBinsZP, cfgZPmin, cfgZPmax, "ZPC (a.u.)"}; const AxisSpec axisZNSignal{2 * cfgNBinsZN, cfgZNmin, 1.5 * cfgZNmax, "ZN (a.u.)"}; const AxisSpec axisZPSignal{2 * cfgNBinsZP, cfgZPmin, 1.5 * cfgZPmax, "ZP (a.u.)"}; + const AxisSpec axisZNAmplitude{cfgNBinsAmpl, cfgAmplMin, cfgAmplMax, "Ampl (a.u.)"}; + const AxisSpec axisZPAmplitude{cfgNBinsAmpl, cfgAmplMin * 0.3, cfgAmplMax * 0.3, "Ampl (a.u.)"}; + const AxisSpec axisTotalAmplitude{cfgNBinsAmpl, 4.0 * cfgAmplMin, 4.0 * cfgAmplMax, "Ampl (a.u.)"}; const AxisSpec axisAlphaZ{cfgNBinsAlpha, cfgAlphaZmin, cfgAlphaZmax, "#alpha_{spec}"}; const AxisSpec axisZDiffSignal{cfgNBinsZN, cfgDiffZmin, cfgDiffZmax, "#Delta E"}; const AxisSpec axisMultiplicityF0A{cfgNBinsMultiplicity, 0, 200000, "F0A"}; @@ -99,6 +105,10 @@ struct NeutronProtonCorrZdc { HistogramConfigSpec defaultTimingHistogram({HistType::kTH2F, {cfgAxisCent, axisZDCTiming}}); HistogramConfigSpec defaultZNSectorHist({HistType::kTH2F, {cfgAxisCent, axisZNSectorSignal}}); HistogramConfigSpec defaultZPSectorHist({HistType::kTH2F, {cfgAxisCent, axisZPSectorSignal}}); + HistogramConfigSpec defaultZNAmplSectorHist({HistType::kTH2F, {cfgAxisCent, axisZNAmplitude}}); + HistogramConfigSpec defaultZPAmplSectorHist({HistType::kTH2F, {cfgAxisCent, axisZPAmplitude}}); + HistogramConfigSpec defaultEnergyZNAmplSectorHist({HistType::kTH2F, {axisZNSignal, axisZNAmplitude}}); + HistogramConfigSpec defaultEnergyZPAmplSectorHist({HistType::kTH2F, {axisZPSignal, axisZPAmplitude}}); HistogramConfigSpec defaultZDCDiffHist({HistType::kTH2F, {cfgAxisCent, axisZDiffSignal}}); // create histograms @@ -132,6 +142,13 @@ struct NeutronProtonCorrZdc { histos.add("ASide/CentvsdiffZNSignal", "CentvsdiffZNSignal", defaultZDCDiffHist); histos.add("ASide/CentvsdiffZPSignal", "CentvsdiffZPSignal", defaultZDCDiffHist); + histos.add("ASide/CentvsZNAmplitude", "CentvsZNAmplitude", defaultZNAmplSectorHist); + histos.add("ASide/CentvsZPAmplitude", "CentvsZPAmplitude", defaultZPAmplSectorHist); + histos.add("ASide/ZNSignalvsZNAmplitudeSum", "ZNSignalvsZNAmplitudeSum", defaultEnergyZNAmplSectorHist); + histos.add("ASide/ZNSignalvsZNAmplitudeCommon", "ZNSignalvsZNAmplitudeCommon", defaultEnergyZNAmplSectorHist); + histos.add("ASide/ZPSignalvsZPAmplitudeSum", "ZPSignalvsZPAmplitudeSum", defaultEnergyZPAmplSectorHist); + histos.add("ASide/ZPSignalvsZPAmplitudeCommon", "ZPSignalvsZPAmplitudeCommon", defaultEnergyZPAmplSectorHist); + // Cloning the folder histos.addClone("ASide/", "CSide/"); @@ -143,6 +160,8 @@ struct NeutronProtonCorrZdc { histos.add("CentvsAlphaZP", "CentvsAlphaZP", kTH2F, {cfgAxisCent, axisAlphaZ}); histos.add("CentvsAlphaZNcommon", "CentvsAlphaZNcommon", kTH2F, {cfgAxisCent, axisAlphaZ}); histos.add("CentvsAlphaZPcommon", "CentvsAlphaZPcommon", kTH2F, {cfgAxisCent, axisAlphaZ}); + histos.add("CentvsAlphaZNAmplitude", "CentvsAlphaZNAmplitude", kTH2F, {cfgAxisCent, axisAlphaZ}); + histos.add("CentvsAlphaZPAmplitude", "CentvsAlphaZPAmplitude", kTH2F, {cfgAxisCent, axisAlphaZ}); histos.add("CentvsDiffZNSignal", "CentvsDiffZNSignal", defaultZDCDiffHist); histos.add("CentvsDiffZPSignal", "CentvsDiffZPSignal", defaultZDCDiffHist); histos.add("CentvsZNAvsZNC", "CentvsZNAvsZNC", kTH3F, {cfgAxisCent, axisZNASignal, axisZNCSignal}); @@ -238,6 +257,8 @@ struct NeutronProtonCorrZdc { std::array, 2> zpEnergyResponse = {zdc.energySectorZPA(), zdc.energySectorZPC()}; std::array znEnergyResponseCommon = {zdc.energyCommonZNA(), zdc.energyCommonZNC()}; std::array zpEnergyResponseCommon = {zdc.energyCommonZPA(), zdc.energyCommonZPC()}; + std::array znAmplitudeResponse = {zdc.amplitudeZNA(), zdc.amplitudeZNC()}; + std::array zpAmplitudeResponse = {zdc.amplitudeZPA(), zdc.amplitudeZPC()}; float sumZN = znEnergyResponse[side][0] + znEnergyResponse[side][1] + znEnergyResponse[side][2] + znEnergyResponse[side][3]; float sumZP = zpEnergyResponse[side][0] + zpEnergyResponse[side][1] + zpEnergyResponse[side][2] + zpEnergyResponse[side][3]; @@ -248,6 +269,13 @@ struct NeutronProtonCorrZdc { histos.fill(HIST(SubDir[side]) + HIST("CentvsZPSignalSum"), centr, sumZP); histos.fill(HIST(SubDir[side]) + HIST("CentvsZPSignalCommon"), centr, zpEnergyResponseCommon[side]); histos.fill(HIST(SubDir[side]) + HIST("CentvsdiffZPSignal"), centr, sumZP - zpEnergyResponseCommon[side]); + histos.fill(HIST(SubDir[side]) + HIST("CentvsZNAmplitude"), centr, znAmplitudeResponse[side]); + histos.fill(HIST(SubDir[side]) + HIST("CentvsZPAmplitude"), centr, zpAmplitudeResponse[side]); + + histos.fill(HIST(SubDir[side]) + HIST("ZNSignalvsZNAmplitudeSum"), sumZN, znAmplitudeResponse[side]); + histos.fill(HIST(SubDir[side]) + HIST("ZNSignalvsZNAmplitudeCommon"), znEnergyResponseCommon[side], znAmplitudeResponse[side]); + histos.fill(HIST(SubDir[side]) + HIST("ZPSignalvsZPAmplitudeSum"), sumZP, zpAmplitudeResponse[side]); + histos.fill(HIST(SubDir[side]) + HIST("ZPSignalvsZPAmplitudeCommon"), zpEnergyResponseCommon[side], zpAmplitudeResponse[side]); } template @@ -332,6 +360,9 @@ struct NeutronProtonCorrZdc { float alphaZN = (sumZNA - sumZNC) / (sumZNA + sumZNC); float alphaZP = (sumZPA - sumZPC) / (sumZPA + sumZPC); + float alphaZNAmplitude = (zdcread.amplitudeZNA() - zdcread.amplitudeZNC()) / (zdcread.amplitudeZNA() + zdcread.amplitudeZNC()); + float alphaZPAmplitude = (zdcread.amplitudeZPA() - zdcread.amplitudeZPC()) / (zdcread.amplitudeZPA() + zdcread.amplitudeZPC()); + histos.fill(HIST("CentvsDiffZNSignal"), cent, (sumZNA + sumZNC) - (zdcread.energyCommonZNA() + zdcread.energyCommonZNC())); histos.fill(HIST("CentvsDiffZPSignal"), cent, (sumZPA + sumZPC) - (zdcread.energyCommonZPA() + zdcread.energyCommonZPC())); histos.fill(HIST("CentvsZNSignalSum"), cent, sumZNA + sumZNC); @@ -342,6 +373,8 @@ struct NeutronProtonCorrZdc { histos.fill(HIST("CentvsAlphaZP"), cent, alphaZP); histos.fill(HIST("CentvsAlphaZNcommon"), cent, (zdcread.energyCommonZNA() - zdcread.energyCommonZNC()) / (zdcread.energyCommonZNA() + zdcread.energyCommonZNC())); histos.fill(HIST("CentvsAlphaZPcommon"), cent, (zdcread.energyCommonZPA() - zdcread.energyCommonZPC()) / (zdcread.energyCommonZPA() + zdcread.energyCommonZPC())); + histos.fill(HIST("CentvsAlphaZNAmplitude"), cent, alphaZNAmplitude); + histos.fill(HIST("CentvsAlphaZPAmplitude"), cent, alphaZPAmplitude); histos.fill(HIST("CentvsZNAvsZNC"), cent, sumZNA, sumZNC); histos.fill(HIST("CentvsZNAvsZPA"), cent, sumZNA, sumZPA); diff --git a/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.cxx new file mode 100644 index 00000000000..b5190b2927c --- /dev/null +++ b/PWGCF/TwoParticleCorrelations/Tasks/pidDiHadron.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 pidDiHadron.cxx +/// \brief di-hadron correlation of PID for O-O, Pb-Pb collisions +/// \author Preet Bhanjan Pati (preet.bhanjan.pati@cern.ch), Zhiyong Lu (zhiyong.lu@cern.ch) +/// \since July/29/2025 + +#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/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.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 "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.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 PidDiHadron { + 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(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, false, "enable trigger pT < associated pT cut") + O2_DEFINE_CONFIGURABLE(cfgUsePtOrderInMixEvent, bool, false, "enable trigger pT < associated pT cut in mixed event") + O2_DEFINE_CONFIGURABLE(cfgPIDUseITSPID, bool, true, "Use ITS PID for particle identification") + O2_DEFINE_CONFIGURABLE(cfgPIDTofPtCut, float, 0.5f, "Minimum pt to use TOF N-sigma") + O2_DEFINE_CONFIGURABLE(cfgPIDParticle, int, 0, "1 = pion, 2 = kaon, 3 = proton, 0 for no PID") + + 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 axisPtTrigger{"axisPtTrigger", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt trigger axis for histograms"}; + ConfigurableAxis axisPtAssoc{"axisPtAssoc", {VARIABLE_WIDTH, 0.2, 0.5, 1, 1.5, 2, 3, 4, 6, 10}, "pt 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"}; + Configurable> pidTofNsigmaCut{"pidTofNsigmaCut", std::vector{1.5, 1.5, 1.5, -1.5, -1.5, -1.5}, "TOF n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; + Configurable> pidItsNsigmaCut{"pidItsNsigmaCut", std::vector{3, 3, 3, -3, -3, -3}, "ITS n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; + Configurable> pidTpcNsigmaCut{"pidTpcNsigmaCut", std::vector{10, 10, 10, -10, -10, -10}, "TOF n-sigma cut for pions_posNsigma, kaons_posNsigma, protons_posNsigma, pions_negNsigma, kaons_negNsigma, protons_negNsigma"}; + + 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>; + + Preslice perCollision = aod::track::collisionId; + + // Corrections + TH3D* mEfficiency = 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 + }; + std::vector tofNsigmaCut; + std::vector itsNsigmaCut; + std::vector tpcNsigmaCut; + o2::aod::ITSResponse itsResponse; + enum Particles { + PIONS, + KAONS, + PROTONS + }; + + // persistent caches + std::vector efficiencyAssociatedCache; + + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + TF1* fMultCutLow = nullptr; + TF1* fMultCutHigh = nullptr; + TF1* fMultMultPVCut = nullptr; + TF1* fT0AV0AMean = nullptr; + TF1* fT0AV0ASigma = nullptr; + + 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 (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); + } + + 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, {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("Centrality", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); + registry.add("Centrality_used", hCentTitle.c_str(), {HistType::kTH1D, {axisCentrality}}); // 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, axisPtTrigger}}}); + } + + 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 corrAxis = {{axisSample, "Sample"}, + {axisVertex, "z-vtx (cm)"}, + {axisPtTrigger, "p_{T} (GeV/c)"}, + {axisPtAssoc, "p_{T} (GeV/c)"}, + {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)); + + tofNsigmaCut = pidTofNsigmaCut; + itsNsigmaCut = pidItsNsigmaCut; + tpcNsigmaCut = pidTpcNsigmaCut; + + 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) + { + if (cfgPIDParticle && getNsigmaPID(track) != cfgPIDParticle) { + return false; + } + return ((track.tpcNClsFound() >= cfgCutTPCclu) && (track.tpcNClsCrossedRows() >= cfgCutTPCCrossedRows) && (track.itsNCls() >= cfgCutITSclu)); + } + + void loadEfficiency(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); + } + 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; + } + + // 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.pt(), 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.pt(), track2.pt(), 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.pt(), track2.pt(), deltaPhi, deltaEta, eventWeight * triggerWeight * associatedWeight); + registry.fill(HIST("deltaEta_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 (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 (fillCounter && cfgEvSelMultCorrelation) + registry.fill(HIST("hEventCountSpecific"), 10.5); + + // V0A T0A 5 sigma cut + float sigma = 5.0; + if (cfgEvSelV0AT0ACut && (std::fabs(collision.multFV0A() - fT0AV0AMean->Eval(collision.multFT0A())) > sigma * fT0AV0ASigma->Eval(collision.multFT0A()))) + return 0; + if (fillCounter && cfgEvSelV0AT0ACut) + registry.fill(HIST("hEventCountSpecific"), 11.5); + + return 1; + } + + void processSame(FilteredCollisions::iterator const& collision, FilteredTracks const& tracks, aod::BCsWithTimestamps const&) + { + if (!collision.sel8()) + return; + auto bc = collision.bc_as(); + float cent = -1.; + if (!cfgCentTableUnavailable) + cent = getCentrality(collision); + if (cfgUseAdditionalEventCut && !eventSelected(collision, tracks.size(), cent, true)) + return; + + if (!cfgCentTableUnavailable) + registry.fill(HIST("Centrality"), cent); + 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; + } + + loadEfficiency(bc.timestamp()); + 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); + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, getMagneticField(bc.timestamp()), cent, 1.0f); + } + PROCESS_SWITCH(PidDiHadron, 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(); + loadEfficiency(bc.timestamp()); + float eventWeight = 1.0f; + if (cfgUseEventWeights) { + eventWeight = 1.0f / it.currentWindowNeighbours(); + } + + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent, getMagneticField(bc.timestamp()), cent1, eventWeight); + } + } + PROCESS_SWITCH(PidDiHadron, processMixed, "Process mixed events", true); + + 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; + + std::array nSigmaToUse = cfgPIDUseITSPID ? nSigmaITS : nSigmaTPC; // Choose which nSigma to use: TPC or ITS + std::vector detectorNsigmaCut = cfgPIDUseITSPID ? 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() > cfgPIDTofPtCut && !track.hasTOF()) { + return 0; + } else if (track.pt() > cfgPIDTofPtCut && 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 + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGDQ/Core/CMakeLists.txt b/PWGDQ/Core/CMakeLists.txt index d19a66a68e6..41ceb661bf9 100644 --- a/PWGDQ/Core/CMakeLists.txt +++ b/PWGDQ/Core/CMakeLists.txt @@ -21,7 +21,7 @@ o2physics_add_library(PWGDQCore AnalysisCompositeCut.cxx MCProng.cxx MCSignal.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2::GlobalTracking O2Physics::AnalysisCore KFParticle::KFParticle) + PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2::GlobalTracking O2Physics::AnalysisCore KFParticle::KFParticle O2Physics::MLCore) o2physics_target_root_dictionary(PWGDQCore HEADERS AnalysisCut.h diff --git a/PWGDQ/Core/CutsLibrary.cxx b/PWGDQ/Core/CutsLibrary.cxx index 1feb6d88b0d..14d8b6aa256 100644 --- a/PWGDQ/Core/CutsLibrary.cxx +++ b/PWGDQ/Core/CutsLibrary.cxx @@ -12,14 +12,19 @@ // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // #include "PWGDQ/Core/CutsLibrary.h" -#include -#include -#include -#include -#include + #include "AnalysisCompositeCut.h" #include "VarManager.h" +#include + +#include + +#include +#include +#include +#include + using std::cout; using std::endl; @@ -203,6 +208,7 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) if (!nameStr.compare("MuonForEMu")) { cut->AddCut(GetAnalysisCut("muonLowPt5")); cut->AddCut(GetAnalysisCut("muonQualityCuts")); + cut->AddCut(GetAnalysisCut("MCHMID")); return cut; } // /////////////////////////////////////////////// @@ -1121,6 +1127,13 @@ AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName) return cut; } + if (!nameStr.compare("Jpsi_TPCPost_calib_debug10")) { + cut->AddCut(GetAnalysisCut("jpsiKineSkimmed")); + cut->AddCut(GetAnalysisCut("jpsi_trackCut_debug6")); + cut->AddCut(GetAnalysisCut("jpsi_TPCPID_debug10")); + return cut; + } + if (!nameStr.compare("LMee_TPCPost_calib_debug1")) { cut->AddCut(GetAnalysisCut("lmee_trackCut_debug")); cut->AddCut(GetAnalysisCut("lmee_TPCPID_debug1")); @@ -3827,9 +3840,9 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) cut->AddCut(VarManager::kIsGoodZvtxFT0vsPV, 0.5, 1.5); cut->AddCut(VarManager::kCentFT0C, 0.0, 90.0); cut->AddCut(VarManager::kTrackOccupancyInTimeRange, 0., 1000); - return cut; } + if (!nameStr.compare("eventStandardSel8PbPbQualityFirmTrackOccupancy")) { cut->AddCut(VarManager::kVtxZ, -10.0, 10.0); cut->AddCut(VarManager::kIsSel8, 0.5, 1.5); @@ -4400,6 +4413,15 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("jpsi_trackCut_debug6")) { + cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); + cut->AddCut(VarManager::kTPCncls, 120., 159); + cut->AddCut(VarManager::kTPCnclsCR, 140., 159); + cut->AddCut(VarManager::kIsITSibAny, 0.5, 1.5); + cut->AddCut(VarManager::kIsSPDfirst, 0.5, 1.5); + return cut; + } + if (!nameStr.compare("lmee_trackCut_debug")) { cut->AddCut(VarManager::kEta, -0.9, 0.9); cut->AddCut(VarManager::kTPCchi2, 0.0, 4.0); @@ -5030,6 +5052,13 @@ AnalysisCut* o2::aod::dqcuts::GetAnalysisCut(const char* cutName) return cut; } + if (!nameStr.compare("jpsi_TPCPID_debug10")) { + cut->AddCut(VarManager::kTPCnSigmaEl, -1.5, 2.0); + cut->AddCut(VarManager::kTPCnSigmaPi, 4.0, 999); + cut->AddCut(VarManager::kTPCnSigmaPr, 3.5, 999); + return cut; + } + if (!nameStr.compare("pidCut_lowP_Corr")) { cut->AddCut(VarManager::kTPCnSigmaEl_Corr, -3.0, 3.0, false, VarManager::kP, 0.0, 5.0); cut->AddCut(VarManager::kTPCnSigmaPi_Corr, 3.0, 999, false, VarManager::kP, 0.0, 5.0); @@ -7076,3 +7105,230 @@ AnalysisCompositeCut* o2::aod::dqcuts::ParseJSONAnalysisCompositeCut(T cut, cons return retCut; } + +//________________________________________________________________________________________________ +o2::aod::dqmlcuts::BdtScoreConfig o2::aod::dqmlcuts::GetBdtScoreCutsAndConfigFromJSON(const char* json) +{ + LOG(info) << "========================================== interpreting JSON for ML analysis cuts"; + if (!json) { + LOG(fatal) << "JSON config string is null!"; + return {}; + } + LOG(info) << "JSON string: " << json; + + rapidjson::Document document; + + // Check that the json is parsed correctly + rapidjson::ParseResult ok = document.Parse(json); + if (!ok) { + LOG(fatal) << "JSON parse error: " << rapidjson::GetParseErrorFunc(ok.Code()) << " (" << ok.Offset() << ")"; + return {}; + } + + for (auto it = document.MemberBegin(); it != document.MemberEnd(); ++it) { + const auto& obj = it->value; + + // Classification type + if (!obj.HasMember("type")) { + LOG(fatal) << "Missing type (Binary/MultiClass)"; + return {}; + } + TString typeStr = obj["type"].GetString(); + if (typeStr != "Binary" && typeStr != "MultiClass") { + LOG(fatal) << "Unsupported classification type: " << typeStr; + return {}; + } + + // Input features + if (!obj.HasMember("inputFeatures") || !obj["inputFeatures"].IsArray()) { + LOG(fatal) << "Missing inputFeatures member or array"; + return {}; + } + std::vector namesInputFeatures; + for (const auto& feature : obj["inputFeatures"].GetArray()) { + namesInputFeatures.emplace_back(feature.GetString()); + LOG(debug) << "Input features: " << feature.GetString(); + } + + // Model files + if (!obj.HasMember("modelFiles") || !obj["modelFiles"].IsArray()) { + LOG(fatal) << "Missing modelFiles member or array"; + return {}; + } + std::vector onnxFileNames; + for (const auto& model : obj["modelFiles"].GetArray()) { + onnxFileNames.emplace_back(model.GetString()); + LOG(debug) << "Model Files: " << model.GetString() << " "; + } + + // Centrality estimation type + if (!obj.HasMember("cent") || !obj["cent"].IsString()) { + LOG(fatal) << "Missing cent member"; + return {}; + } + std::string cent = obj["cent"].GetString(); + LOG(debug) << "Centrality type: " << cent; + if (cent != "kCentFT0C" && cent != "kCentFT0A" && cent != "kCentFT0M") { + LOG(fatal) << "Unsupported centrality type: " << cent; + return {}; + } + + // Cut storage + std::vector> centBins; + std::vector> ptBins; + std::vector> cutsMl; + std::vector cutDirs; + std::vector labelsFlatBin; + bool cutDirsFilled = false; + + for (auto centMember = obj.MemberBegin(); centMember != obj.MemberEnd(); ++centMember) { + TString centKey = centMember->name.GetString(); + if (!centKey.Contains("AddCentCut")) + continue; + + const auto& centCut = centMember->value; + + // Centrality info + if (!centCut.HasMember("centMin") || !centCut.HasMember("centMax")) { + LOG(fatal) << "Missing centMin/centMax in " << centKey; + return {}; + } + double centMin = centCut["centMin"].GetDouble(); + double centMax = centCut["centMax"].GetDouble(); + + for (auto ptMember = centCut.MemberBegin(); ptMember != centCut.MemberEnd(); ++ptMember) { + TString ptKey = ptMember->name.GetString(); + if (!ptKey.Contains("AddPtCut")) + continue; + + const auto& ptCut = ptMember->value; + + // Pt info + if (!ptCut.HasMember("pTMin") || !ptCut.HasMember("pTMax")) { + LOG(fatal) << "Missing pTMin/pTMax in " << ptKey; + return {}; + } + + double ptMin = ptCut["pTMin"].GetDouble(); + double ptMax = ptCut["pTMax"].GetDouble(); + + std::vector binCuts; + bool exclude = false; + + for (auto mlMember = ptCut.MemberBegin(); mlMember != ptCut.MemberEnd(); ++mlMember) { + TString mlKey = mlMember->name.GetString(); + if (!mlKey.Contains("AddMLCut")) + continue; + + const auto& mlcut = mlMember->value; + + if (!mlcut.HasMember("cut")) { + LOG(fatal) << "Missing cut (score) in " << mlKey; + return {}; + } + + double cutVal = mlcut["cut"].GetDouble(); + exclude = mlcut.HasMember("exclude") ? mlcut["exclude"].GetBool() : false; + + binCuts.push_back(cutVal); + + if (!cutDirsFilled) { + cutDirs.push_back(exclude ? 0 : 1); + } + } + + if (!cutDirsFilled) { + cutDirsFilled = true; + } + + centBins.emplace_back(centMin, centMax); + ptBins.emplace_back(ptMin, ptMax); + cutsMl.push_back(binCuts); + labelsFlatBin.push_back(Form("%s_cent%.0f_%.0f_pt%.1f_%.1f", cent.c_str(), centMin, centMax, ptMin, ptMax)); + LOG(info) << "Added cut for " << Form("%s_cent%.0f_%.0f_pt%.1f_%.1f", cent.c_str(), centMin, centMax, ptMin, ptMax) << " with cuts: ["; + for (size_t i = 0; i < binCuts.size(); ++i) { + std::cout << binCuts[i]; + if (i != binCuts.size() - 1) + std::cout << ", "; + } + std::cout << "] and direction: " << (exclude ? "CutGreater" : "CutSmaller") << std::endl; + } + } + + if (cutDirs.size() != cutsMl[0].size()) { + LOG(fatal) << "Mismatch the cut size and direction size: cutsMl[0].size() = " << cutsMl[0].size() + << ", cutsMl[0].size() = " << cutDirs.size(); + return {}; + } + + std::vector labelsClass; + for (size_t j = 0; j < cutsMl[0].size(); ++j) { + labelsClass.push_back(Form("score class %d", static_cast(j))); + } + + size_t nFlatBins = cutsMl.size(); + std::vector binsMl(nFlatBins + 1); + std::iota(binsMl.begin(), binsMl.end(), 0); + + // Binary + if (typeStr == "Binary") { + dqmlcuts::BinaryBdtScoreConfig binaryCfg; + binaryCfg.inputFeatures = namesInputFeatures; + binaryCfg.onnxFiles = onnxFileNames; + binaryCfg.binsCent = centBins; + binaryCfg.binsPt = ptBins; + binaryCfg.binsMl = binsMl; + binaryCfg.cutDirs = cutDirs; + binaryCfg.centType = cent; + binaryCfg.cutsMl = makeLabeledCutsMl(cutsMl, labelsFlatBin, labelsClass); + + return binaryCfg; + + // MultiClass + } else if (typeStr == "MultiClass") { + dqmlcuts::MultiClassBdtScoreConfig multiCfg; + multiCfg.inputFeatures = namesInputFeatures; + multiCfg.onnxFiles = onnxFileNames; + multiCfg.binsCent = centBins; + multiCfg.binsPt = ptBins; + multiCfg.binsMl = binsMl; + multiCfg.cutDirs = cutDirs; + multiCfg.centType = cent; + multiCfg.cutsMl = makeLabeledCutsMl(cutsMl, labelsFlatBin, labelsClass); + + return multiCfg; + } + } + + return {}; +} + +o2::framework::LabeledArray o2::aod::dqmlcuts::makeLabeledCutsMl(const std::vector>& cuts, + const std::vector& labelsflatBin, + const std::vector& labelsClass) +{ + const size_t nRows = cuts.size(); + const size_t nCols = cuts.empty() ? 0 : cuts[0].size(); + std::vector flat; + + for (const auto& row : cuts) { + flat.insert(flat.end(), row.begin(), row.end()); + } + + o2::framework::Array2D arr(flat.data(), nRows, nCols); + return o2::framework::LabeledArray(arr, labelsflatBin, labelsClass); +} + +int o2::aod::dqmlcuts::getMlBinIndex(double cent, double pt, + const std::vector>& binsCent, + const std::vector>& binsPt) +{ + LOG(debug) << "Searching for Ml bin index for cent: " << cent << ", pt: " << pt; + for (size_t i = 0; i < binsCent.size(); ++i) { + if (cent >= binsCent[i].first && cent < binsCent[i].second && pt >= binsPt[i].first && pt < binsPt[i].second) { + LOG(debug) << " - Found at index: " << i; + return static_cast(i); + } + } + return -1; // not found +} diff --git a/PWGDQ/Core/CutsLibrary.h b/PWGDQ/Core/CutsLibrary.h index c6ad4caded2..b38577f3c2b 100644 --- a/PWGDQ/Core/CutsLibrary.h +++ b/PWGDQ/Core/CutsLibrary.h @@ -15,12 +15,13 @@ #ifndef PWGDQ_CORE_CUTSLIBRARY_H_ #define PWGDQ_CORE_CUTSLIBRARY_H_ -#include -#include -#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/AnalysisCompositeCut.h" +#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/VarManager.h" +#include +#include + // /////////////////////////////////////////////// // These are the Cuts used in the CEFP Task // // to select tracks in the event selection // @@ -119,6 +120,41 @@ bool ValidateJSONAnalysisCompositeCut(T cut); template AnalysisCompositeCut* ParseJSONAnalysisCompositeCut(T key, const char* cutName); } // namespace dqcuts +namespace dqmlcuts +{ +struct BinaryBdtScoreConfig { + std::vector inputFeatures; + std::vector onnxFiles; + std::vector> binsCent; // bins for centrality + std::vector> binsPt; // bins for pT + std::vector binsMl; // bins for flattened binning + std::string centType; + o2::framework::LabeledArray cutsMl; // BDT score cuts for each bin + std::vector cutDirs; // direction of the cuts on the BDT score +}; + +struct MultiClassBdtScoreConfig { + std::vector inputFeatures; + std::vector onnxFiles; + std::vector> binsCent; + std::vector> binsPt; + std::vector binsMl; + std::string centType; + o2::framework::LabeledArray cutsMl; + std::vector cutDirs; +}; + +using BdtScoreConfig = std::variant; + +BdtScoreConfig GetBdtScoreCutsAndConfigFromJSON(const char* json); + +o2::framework::LabeledArray makeLabeledCutsMl(const std::vector>& cuts, + const std::vector& labelsPt, + const std::vector& labelsClass); +int getMlBinIndex(double cent, double pt, + const std::vector>& binsCent, + const std::vector>& binsPt); +} // namespace dqmlcuts } // namespace o2::aod AnalysisCompositeCut* o2::aod::dqcuts::GetCompositeCut(const char* cutName); diff --git a/PWGDQ/Core/DQMlResponse.h b/PWGDQ/Core/DQMlResponse.h new file mode 100644 index 00000000000..64bfe233cc7 --- /dev/null +++ b/PWGDQ/Core/DQMlResponse.h @@ -0,0 +1,239 @@ +// 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: jseo@cern.ch +// +// Class to compute the ML response for DQ-analysis selections +// + +#ifndef PWGDQ_CORE_DQMLRESPONSE_H_ +#define PWGDQ_CORE_DQMLRESPONSE_H_ + +#include "Tools/ML/MlResponse.h" + +#include +#include +#include +#include + +namespace o2::analysis +{ + +enum class InputFeatures : uint8_t { // refer to DielectronsAll, TODO: add more features if needed + kMass = 0, + kPt, + kEta, + kPhi, + kPt1, + kITSChi2NCl1, + kTPCNClsCR1, + kTPCNClsFound1, + kTPCChi2NCl1, + kDcaXY1, + kDcaZ1, + kTPCNSigmaEl1, + kTPCNSigmaPi1, + kTPCNSigmaPr1, + kTOFNSigmaEl1, + kTOFNSigmaPi1, + kTOFNSigmaPr1, + kPt2, + kITSChi2NCl2, + kTPCNClsCR2, + kTPCNClsFound2, + kTPCChi2NCl2, + kDcaXY2, + kDcaZ2, + kTPCNSigmaEl2, + kTPCNSigmaPi2, + kTPCNSigmaPr2, + kTOFNSigmaEl2, + kTOFNSigmaPi2, + kTOFNSigmaPr2 +}; + +static const std::map gFeatureNameMap = { + {InputFeatures::kMass, "kMass"}, + {InputFeatures::kPt, "kPt"}, + {InputFeatures::kEta, "kEta"}, + {InputFeatures::kPhi, "kPhi"}, + {InputFeatures::kPt1, "kPt1"}, + {InputFeatures::kITSChi2NCl1, "kITSChi2NCl1"}, + {InputFeatures::kTPCNClsCR1, "kTPCNClsCR1"}, + {InputFeatures::kTPCNClsFound1, "kTPCNClsFound1"}, + {InputFeatures::kTPCChi2NCl1, "kTPCChi2NCl1"}, + {InputFeatures::kDcaXY1, "kDcaXY1"}, + {InputFeatures::kDcaZ1, "kDcaZ1"}, + {InputFeatures::kTPCNSigmaEl1, "kTPCNSigmaEl1"}, + {InputFeatures::kTPCNSigmaPi1, "kTPCNSigmaPi1"}, + {InputFeatures::kTPCNSigmaPr1, "kTPCNSigmaPr1"}, + {InputFeatures::kTOFNSigmaEl1, "kTOFNSigmaEl1"}, + {InputFeatures::kTOFNSigmaPi1, "kTOFNSigmaPi1"}, + {InputFeatures::kTOFNSigmaPr1, "kTOFNSigmaPr1"}, + {InputFeatures::kPt2, "kPt2"}, + {InputFeatures::kITSChi2NCl2, "kITSChi2NCl2"}, + {InputFeatures::kTPCNClsCR2, "kTPCNClsCR2"}, + {InputFeatures::kTPCNClsFound2, "kTPCNClsFound2"}, + {InputFeatures::kTPCChi2NCl2, "kTPCChi2NCl2"}, + {InputFeatures::kDcaXY2, "kDcaXY2"}, + {InputFeatures::kDcaZ2, "kDcaZ2"}, + {InputFeatures::kTPCNSigmaEl2, "kTPCNSigmaEl2"}, + {InputFeatures::kTPCNSigmaPi2, "kTPCNSigmaPi2"}, + {InputFeatures::kTPCNSigmaPr2, "kTPCNSigmaPr2"}, + {InputFeatures::kTOFNSigmaEl2, "kTOFNSigmaEl2"}, + {InputFeatures::kTOFNSigmaPi2, "kTOFNSigmaPi2"}, + {InputFeatures::kTOFNSigmaPr2, "kTOFNSigmaPr2"}}; + +template +class DQMlResponse : public MlResponse +{ + public: + DQMlResponse() = default; + virtual ~DQMlResponse() = default; + + void setBinsCent(const std::vector>& bins) { binsCent = bins; } + void setBinsPt(const std::vector>& bins) { binsPt = bins; } + void setCentType(std::string& type) { centType = type; } + + const std::vector>& getBinsCent() const { return binsCent; } + const std::vector>& getBinsPt() const { return binsPt; } + const std::string& getCentType() const { return centType; } + + /// Method to get the input features vector needed for ML inference + /// \return inputFeatures vector + template + std::vector getInputFeatures(const T1& t1, + const T2& t2, + const TValues& fg) const + { + std::vector dqInputFeatures; + dqInputFeatures.reserve(MlResponse::mCachedIndices.size()); + + for (auto idx : MlResponse::mCachedIndices) { + auto enumIdx = static_cast(idx); + auto mapIdx = gFeatureNameMap.find(enumIdx); + if (mapIdx == gFeatureNameMap.end()) { + LOG(fatal) << "Unknown InputFeatures index: " << static_cast(enumIdx); + } + + const auto& name = mapIdx->second; + if (name == "kMass") { + dqInputFeatures.push_back(fg[VarManager::fgVarNamesMap["kMass"]]); + } else if (name == "kPt") { + dqInputFeatures.push_back(fg[VarManager::fgVarNamesMap["kPt"]]); + } else if (name == "kEta") { + dqInputFeatures.push_back(fg[VarManager::fgVarNamesMap["kEta"]]); + } else if (name == "kPhi") { + dqInputFeatures.push_back(fg[VarManager::fgVarNamesMap["kPhi"]]); + } else if (name == "kPt1") { + dqInputFeatures.push_back(t1.pt()); + } else if (name == "kITSChi2NCl1") { + dqInputFeatures.push_back(t1.itsChi2NCl()); + } else if (name == "kTPCNClsCR1") { + dqInputFeatures.push_back(t1.tpcNClsCrossedRows()); + } else if (name == "kTPCNClsFound1") { + dqInputFeatures.push_back(t1.tpcNClsFound()); + } else if (name == "kTPCChi2NCl1") { + dqInputFeatures.push_back(t1.tpcChi2NCl()); + } else if (name == "kDcaXY1") { + dqInputFeatures.push_back(t1.dcaXY()); + } else if (name == "kDcaZ1") { + dqInputFeatures.push_back(t1.dcaZ()); + } else if (name == "kTPCNSigmaEl1") { + dqInputFeatures.push_back(t1.tpcNSigmaEl()); + } else if (name == "kTPCNSigmaPi1") { + dqInputFeatures.push_back(t1.tpcNSigmaPi()); + } else if (name == "kTPCNSigmaPr1") { + dqInputFeatures.push_back(t1.tpcNSigmaPr()); + } else if (name == "kTOFNSigmaEl1") { + dqInputFeatures.push_back(t1.tofNSigmaEl()); + } else if (name == "kTOFNSigmaPi1") { + dqInputFeatures.push_back(t1.tofNSigmaPi()); + } else if (name == "kTOFNSigmaPr1") { + dqInputFeatures.push_back(t1.tofNSigmaPr()); + } else if (name == "kPt2") { + dqInputFeatures.push_back(t2.pt()); + } else if (name == "kITSChi2NCl2") { + dqInputFeatures.push_back(t2.itsChi2NCl()); + } else if (name == "kTPCNClsCR2") { + dqInputFeatures.push_back(t2.tpcNClsCrossedRows()); + } else if (name == "kTPCNClsFound2") { + dqInputFeatures.push_back(t2.tpcNClsFound()); + } else if (name == "kTPCChi2NCl2") { + dqInputFeatures.push_back(t2.tpcChi2NCl()); + } else if (name == "kDcaXY2") { + dqInputFeatures.push_back(t2.dcaXY()); + } else if (name == "kDcaZ2") { + dqInputFeatures.push_back(t2.dcaZ()); + } else if (name == "kTPCNSigmaEl2") { + dqInputFeatures.push_back(t2.tpcNSigmaEl()); + } else if (name == "kTPCNSigmaPi2") { + dqInputFeatures.push_back(t2.tpcNSigmaPi()); + } else if (name == "kTPCNSigmaPr2") { + dqInputFeatures.push_back(t2.tpcNSigmaPr()); + } else if (name == "kTOFNSigmaEl2") { + dqInputFeatures.push_back(t2.tofNSigmaEl()); + } else if (name == "kTOFNSigmaPi2") { + dqInputFeatures.push_back(t2.tofNSigmaPi()); + } else if (name == "kTOFNSigmaPr2") { + dqInputFeatures.push_back(t2.tofNSigmaPr()); + } else { + LOG(fatal) << "Missing accessor for feature: " << name; + } + } + LOG(debug) << "Total features collected: " << dqInputFeatures.size(); + return dqInputFeatures; + } + + protected: + std::vector> binsCent; + std::vector> binsPt; + std::string centType; + + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + {"kMass", static_cast(InputFeatures::kMass)}, + {"kPt", static_cast(InputFeatures::kPt)}, + {"kEta", static_cast(InputFeatures::kEta)}, + {"kPhi", static_cast(InputFeatures::kPhi)}, + {"kPt1", static_cast(InputFeatures::kPt1)}, + {"kITSChi2NCl1", static_cast(InputFeatures::kITSChi2NCl1)}, + {"kTPCNClsCR1", static_cast(InputFeatures::kTPCNClsCR1)}, + {"kTPCNClsFound1", static_cast(InputFeatures::kTPCNClsFound1)}, + {"kTPCChi2NCl1", static_cast(InputFeatures::kTPCChi2NCl1)}, + {"kDcaXY1", static_cast(InputFeatures::kDcaXY1)}, + {"kDcaZ1", static_cast(InputFeatures::kDcaZ1)}, + {"kTPCNSigmaEl1", static_cast(InputFeatures::kTPCNSigmaEl1)}, + {"kTPCNSigmaPi1", static_cast(InputFeatures::kTPCNSigmaPi1)}, + {"kTPCNSigmaPr1", static_cast(InputFeatures::kTPCNSigmaPr1)}, + {"kTOFNSigmaEl1", static_cast(InputFeatures::kTOFNSigmaEl1)}, + {"kTOFNSigmaPi1", static_cast(InputFeatures::kTOFNSigmaPi1)}, + {"kTOFNSigmaPr1", static_cast(InputFeatures::kTOFNSigmaPr1)}, + {"kPt2", static_cast(InputFeatures::kPt2)}, + {"kITSChi2NCl2", static_cast(InputFeatures::kITSChi2NCl2)}, + {"kTPCNClsCR2", static_cast(InputFeatures::kTPCNClsCR2)}, + {"kTPCNClsFound2", static_cast(InputFeatures::kTPCNClsFound2)}, + {"kTPCChi2NCl2", static_cast(InputFeatures::kTPCChi2NCl2)}, + {"kDcaXY2", static_cast(InputFeatures::kDcaXY2)}, + {"kDcaZ2", static_cast(InputFeatures::kDcaZ2)}, + {"kTPCNSigmaEl2", static_cast(InputFeatures::kTPCNSigmaEl2)}, + {"kTPCNSigmaPi2", static_cast(InputFeatures::kTPCNSigmaPi2)}, + {"kTPCNSigmaPr2", static_cast(InputFeatures::kTPCNSigmaPr2)}, + {"kTOFNSigmaEl2", static_cast(InputFeatures::kTOFNSigmaEl2)}, + {"kTOFNSigmaPi2", static_cast(InputFeatures::kTOFNSigmaPi2)}, + {"kTOFNSigmaPr2", static_cast(InputFeatures::kTOFNSigmaPr2)}}; + } +}; + +} // namespace o2::analysis + +#endif // PWGDQ_CORE_DQMLRESPONSE_H_ diff --git a/PWGDQ/Core/HistogramsLibrary.cxx b/PWGDQ/Core/HistogramsLibrary.cxx index 9fdb5b0cae5..b9618a4c64e 100644 --- a/PWGDQ/Core/HistogramsLibrary.cxx +++ b/PWGDQ/Core/HistogramsLibrary.cxx @@ -84,11 +84,11 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h if (subGroupStr.Contains("mult")) { if (subGroupStr.Contains("pp")) { hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 250, 0.0, 500.0, VarManager::kMultTPC); - hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 250, 0.0, 500.0, VarManager::kMultFV0A); - hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 300, 0.0, 300.0, VarManager::kMultFT0A); - hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 300, 0.0, 300.0, VarManager::kMultFT0C); - hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 300, 0.0, 300.0, VarManager::kMultFDDA); - hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 50, 0.0, 50.0, VarManager::kMultFDDC); + hm->AddHistogram(histClass, "MultFV0A", "MultFV0A", false, 1000, 0.0, 25000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "MultFT0A", "MultFT0A", false, 1000, 0.0, 25000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "MultFT0C", "MultFT0C", false, 1000, 0.0, 25000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "MultFDDA", "MultFDDA", false, 1000, 0.0, 25000.0, VarManager::kMultFDDA); + hm->AddHistogram(histClass, "MultFDDC", "MultFDDC", false, 1000, 0.0, 25000.0, VarManager::kMultFDDC); hm->AddHistogram(histClass, "MultTracklets", "MultTracklets", false, 250, 0.0, 250.0, VarManager::kMultTracklets); hm->AddHistogram(histClass, "VtxNContribReal", "Vtx n contributors", false, 150, 0.0, 150.0, VarManager::kVtxNcontribReal); hm->AddHistogram(histClass, "VtxNContrib", "Vtx n contributors", false, 100, 0.0, 100.0, VarManager::kVtxNcontrib); @@ -115,6 +115,11 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "VtxZ_VtxNcontribReal", "VtxZ vs VtxNcontribReal", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kVtxNcontribReal); hm->AddHistogram(histClass, "VtxZ_MultNTracksPVeta1", "VtxZ vs MultNTracksPVeta1", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kMultNTracksPVeta1); hm->AddHistogram(histClass, "VtxZ_MultNTracksPVetaHalf", "VtxZ vs MultNTracksPVetaHalf", false, 100, -10.0, 10.0, VarManager::kVtxZ, 150, 0, 150.0, VarManager::kMultNTracksPVetaHalf); + hm->AddHistogram(histClass, "VtxZ_MultFV0A", "VtxZ vs MultFV0A", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "VtxZ_MultFT0A", "VtxZ vs MultFT0A", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "VtxZ_MultFT0C", "VtxZ vs MultFT0C", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFT0C); + hm->AddHistogram(histClass, "VtxZ_MultFDDA", "VtxZ vs MultFDDA", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFDDA); + hm->AddHistogram(histClass, "VtxZ_MultFDDC", "VtxZ vs MultFDDC", false, 20, -10.0, 10.0, VarManager::kVtxZ, 200, 0, 25000.0, VarManager::kMultFDDC); } else { hm->AddHistogram(histClass, "MultTPC", "MultTPC", false, 200, 0.0, 50000.0, VarManager::kMultTPC); @@ -189,6 +194,18 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h if (subGroupStr.Contains("occupancy")) { hm->AddHistogram(histClass, "ITStrackOccupancy", "ITStrackOccupancy", false, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange); hm->AddHistogram(histClass, "Ft0cOccupancy", "Ft0cOccupancy", false, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange); + if (subGroupStr.Contains("qvector")) { + hm->AddHistogram(histClass, "Psi2A_ITStrackOccupancy", "", false, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2A); + hm->AddHistogram(histClass, "Psi2B_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2B); + hm->AddHistogram(histClass, "Psi2C_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2C); + hm->AddHistogram(histClass, "Psi2APOS_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2APOS); + hm->AddHistogram(histClass, "Psi2ANEG_ITStrackOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kTrackOccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2ANEG); + hm->AddHistogram(histClass, "Psi2A_Ft0cOccupancy", "", false, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2A); + hm->AddHistogram(histClass, "Psi2B_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2B); + hm->AddHistogram(histClass, "Psi2C_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2C); + hm->AddHistogram(histClass, "Psi2APOS_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2APOS); + hm->AddHistogram(histClass, "Psi2ANEG_Ft0cOccupancy", "", true, 200, 0.0, 20000.0, VarManager::kFT0COccupancyInTimeRange, 100, -TMath::Pi() / 2, TMath::Pi() / 2, VarManager::kPsi2ANEG); + } } if (subGroupStr.Contains("mc")) { hm->AddHistogram(histClass, "MCVtxX_VtxX", "Vtx X (MC vs rec)", false, 100, -0.5, 0.5, VarManager::kVtxX, 100, -0.5, 0.5, VarManager::kMCVtxX); @@ -237,6 +254,10 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Q2X0A", "", false, 500, -10.0, 10.0, VarManager::kQ2X0A); hm->AddHistogram(histClass, "Q2Y0A", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0A); + hm->AddHistogram(histClass, "Q2X0APOS", "", false, 500, -10.0, 10.0, VarManager::kQ2X0APOS); + hm->AddHistogram(histClass, "Q2Y0APOS", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0APOS); + hm->AddHistogram(histClass, "Q2X0ANEG", "", false, 500, -10.0, 10.0, VarManager::kQ2X0ANEG); + hm->AddHistogram(histClass, "Q2Y0ANEG", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0ANEG); hm->AddHistogram(histClass, "Q2X0B", "", false, 500, -10.0, 10.0, VarManager::kQ2X0B); hm->AddHistogram(histClass, "Q2Y0B", "", false, 500, -10.0, 10.0, VarManager::kQ2Y0B); hm->AddHistogram(histClass, "Q2X0C", "", false, 500, -10.0, 10.0, VarManager::kQ2X0C); @@ -253,6 +274,9 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Q2Y0B_Cent", "", true, 18, 0.0, 90.0, VarManager::kCentVZERO, 500, -10.0, 10.0, VarManager::kQ2Y0B); hm->AddHistogram(histClass, "Q2X0C_Cent", "", true, 18, 0.0, 90.0, VarManager::kCentVZERO, 500, -10.0, 10.0, VarManager::kQ2X0C); hm->AddHistogram(histClass, "Q2Y0C_Cent", "", true, 18, 0.0, 90.0, VarManager::kCentVZERO, 500, -10.0, 10.0, VarManager::kQ2Y0C); + hm->AddHistogram(histClass, "Q2X0A_Q2Y0A_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -10.0, 10.0, VarManager::kQ2X0A, 500, -10.0, 10.0, VarManager::kQ2Y0A); + hm->AddHistogram(histClass, "Q2X0B_Q2Y0B_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -10.0, 10.0, VarManager::kQ2X0B, 500, -10.0, 10.0, VarManager::kQ2Y0B); + hm->AddHistogram(histClass, "Q2X0C_Q2Y0C_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -10.0, 10.0, VarManager::kQ2X0C, 500, -10.0, 10.0, VarManager::kQ2Y0C); hm->AddHistogram(histClass, "Q3X0A", "", false, 500, -10.0, 10.0, VarManager::kQ3X0A); hm->AddHistogram(histClass, "Q3Y0A", "", false, 500, -10.0, 10.0, VarManager::kQ3Y0A); hm->AddHistogram(histClass, "Q3X0B", "", false, 500, -10.0, 10.0, VarManager::kQ3X0B); @@ -280,6 +304,8 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Q3X0A_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -10.0, 10.0, VarManager::kQ3X0A); hm->AddHistogram(histClass, "Q3Y0A_CentFT0C", "", false, 18, 0.0, 90.0, VarManager::kCentFT0C, 500, -10.0, 10.0, VarManager::kQ3Y0A); hm->AddHistogram(histClass, "Psi2A", "", false, 100, -2.0, 2.0, VarManager::kPsi2A); + hm->AddHistogram(histClass, "Psi2APOS", "", false, 100, -2.0, 2.0, VarManager::kPsi2APOS); + hm->AddHistogram(histClass, "Psi2ANEG", "", false, 100, -2.0, 2.0, VarManager::kPsi2ANEG); hm->AddHistogram(histClass, "Psi2B", "", false, 100, -2.0, 2.0, VarManager::kPsi2B); hm->AddHistogram(histClass, "Psi2C", "", false, 100, -2.0, 2.0, VarManager::kPsi2C); hm->AddHistogram(histClass, "Psi2A_CentFT0C", "", false, 90, 0.0, 90.0, VarManager::kCentFT0C, 100, -2.0, 2.0, VarManager::kPsi2A); @@ -930,6 +956,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h 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::kCentFT0C); } if (!groupStr.CompareTo("pair")) { @@ -944,6 +971,13 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_MultNTracksPVetaHalf", "Mass vs MultNTracksPVetaHalf", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kMultNTracksPVetaHalf); hm->AddHistogram(histClass, "Mass_MultNTracksPVeta1", "Mass vs MultNTracksPVeta1", false, 200, 2.0, 5.0, VarManager::kMass, 150, 0, 150.0, VarManager::kMultNTracksPVeta1); } + if (subGroupStr.Contains("dimuon_fwdmult")) { + hm->AddHistogram(histClass, "Mass_MultFV0A", "Mass vs MultFV0A", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFV0A); + hm->AddHistogram(histClass, "Mass_MultFT0A", "Mass vs MultFT0A", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFT0A); + hm->AddHistogram(histClass, "Mass_MultFT0C", "Mass vs MultFT0C", false, 200, 2.0, 5.0, VarManager::kMass, 1000, 0, 25000.0, VarManager::kMultFT0C); + 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("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); @@ -1005,6 +1039,11 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Pt_CosThetaRM", "", false, 200, 1.0, 5.0, VarManager::kMass, 40, 0.0, 20.0, VarManager::kPt, 20, -1., 1., VarManager::kCosThetaRM); } } + if (subGroupStr.Contains("globalpolarization")) { + hm->AddHistogram(histClass, "CosThetaStarTPC", "", false, 100, -1.0, 1.0, VarManager::kCosThetaStarTPC); + hm->AddHistogram(histClass, "CosThetaStarFT0A", "", false, 100, -1.0, 1.0, VarManager::kCosThetaStarFT0A); + hm->AddHistogram(histClass, "CosThetaStarFT0C", "", false, 100, -1.0, 1.0, VarManager::kCosThetaStarFT0C); + } if (subGroupStr.Contains("upsilon")) { hm->AddHistogram(histClass, "MassUpsilon_Pt", "", false, 500, 7.0, 12.0, VarManager::kMass, 400, 0.0, 40.0, VarManager::kPt); } @@ -1036,6 +1075,22 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "CosPointingAngle", "", false, 200, -1.0, 1.0, VarManager::kCosPointingAngle); hm->AddHistogram(histClass, "VtxingChi2PCA", "", false, 100, 0.0, 10.0, VarManager::kVertexingChi2PCA); } + if (subGroupStr.Contains("tauxy-midy-pol-he")) { + int varspTHE[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaHE, VarManager::kVertexingTauxyProjectedPoleJPsiMass}; + int binspT[4] = {50, 10, 20, 1000}; + double xminpT[4] = {2., 0., -1., -0.03}; + double xmaxpT[4] = {4., 20., 1., 0.03}; + hm->AddHistogram(histClass, "Tauxy_Mass_Pt_CosthetaHE", "", 4, varspTHE, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + } + + if (subGroupStr.Contains("tauxy-midy-pol-rand")) { + int varspTRand[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaRM, VarManager::kVertexingTauxyProjectedPoleJPsiMass}; + + int binspT[4] = {50, 10, 20, 1000}; + double xminpT[4] = {2., 0., -1., -0.03}; + double xmaxpT[4] = {4., 20., 1., 0.03}; + hm->AddHistogram(histClass, "Tauxy_Mass_Pt_CosthetaRand", "", 4, varspTRand, binspT, xminpT, xmaxpT, 0, -1, kFALSE); + } if (subGroupStr.Contains("kalman-filter")) { hm->AddHistogram(histClass, "LxyErr", "", false, 100, 0.0, 10.0, VarManager::kVertexingLxyErr); @@ -1119,6 +1174,10 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Pt", "", false, 750, 0.0, 15.0, VarManager::kMass, 120, 0.0, 30.0, VarManager::kPt); hm->AddHistogram(histClass, "Mass_Rapidity", "", false, 750, 0.0, 15.0, VarManager::kMass, 150, 2.5, 4.0, VarManager::kRap); hm->AddHistogram(histClass, "Mass_Phi", "", false, 750, 0.0, 15.0, VarManager::kMass, 180, constants::math::PI, 2 * constants::math::PI, VarManager::kPhi); + if (subGroupStr.Contains("dimuon-tag-and-probe")) { + hm->AddHistogram(histClass, "Mass_PtProbe", "mass vs probe pT", false, 750, 0.0, 15.0, VarManager::kMass, 120, 0.0, 30.0, VarManager::kPt2); // Warning: in the tag-and-probe task t2 is always the probe + hm->AddHistogram(histClass, "Mass_EtaProbe", "mass vs probe eta", false, 750, 0.0, 15.0, VarManager::kMass, 120, 0.0, 30.0, VarManager::kEta2); // Warning: in the tag-and-probe task t2 is always the probe + } if (subGroupStr.Contains("dimuon-multi-diff")) { int varsKine[3] = {VarManager::kMass, VarManager::kPt, VarManager::kRap}; int binsKine[3] = {250, 120, 60}; @@ -1220,39 +1279,24 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } if (subGroupStr.Contains("dimuon-polarization-he")) { int varspTHE[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaHE, VarManager::kPhiHE}; - int varsrapHE[4] = {VarManager::kMass, VarManager::kRap, VarManager::kCosThetaHE, VarManager::kPhiHE}; int binspT[4] = {100, 40, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {5., 4.0, 1., +3.14}; 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("dimuon-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, 40, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {5., 4.0, 1., +3.14}; 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-pp")) { int varspTPP[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaPP, VarManager::kPhiPP}; - int varsrapPP[4] = {VarManager::kMass, VarManager::kRap, VarManager::kCosThetaPP, VarManager::kPhiPP}; int binspT[4] = {100, 40, 20, 20}; - int binsy[4] = {100, 10, 20, 20}; double xminpT[4] = {1., 0., -1., -3.14}; double xmaxpT[4] = {5., 20., 1., +3.14}; - double xminy[4] = {1., 2.5, -1., -3.14}; - double xmaxy[4] = {5., 4.0, 1., +3.14}; hm->AddHistogram(histClass, "Mass_Pt_cosThetaPP_phiPP", "", 4, varspTPP, binspT, xminpT, xmaxpT, 0, -1, kFALSE); - hm->AddHistogram(histClass, "Mass_y_cosThetaPP_phiPP", "", 4, varsrapPP, binsy, xminy, xmaxy, 0, -1, kFALSE); } if (subGroupStr.Contains("dimuon-polarization-lowmass-pp")) { int varspTPP[4] = {VarManager::kMass, VarManager::kPt, VarManager::kCosThetaPP, VarManager::kPhiPP}; @@ -1854,7 +1898,7 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h } } if (!groupStr.CompareTo("dilepton-dihadron")) { - if (subGroupStr.EqualTo("xtojpsipipi")) { + if (subGroupStr.Contains("xtojpsipipi") || subGroupStr.Contains("psi2stojpsipipi")) { hm->AddHistogram(histClass, "hMass_X3872", "", false, 1000, 3.0, 5.0, VarManager::kQuadMass); hm->AddHistogram(histClass, "hMass_defaultDileptonMass_X3872", "", false, 1000, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass); hm->AddHistogram(histClass, "hPt_X3872", "", false, 150, 0.0, 15.0, VarManager::kQuadPt); @@ -1863,12 +1907,12 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "hCostheta_Jpsi_Dihadron", "", false, 100, -1.0, 1.0, VarManager::kCosthetaDileptonDitrack); hm->AddHistogram(histClass, "hPtDilepton_PtDihadron", "", false, 150, 0, 15.0, VarManager::kPairPt, 100, 0, 10, VarManager::kDitrackPt); hm->AddHistogram(histClass, "hPtDilepton_MassDihadron", "", false, 150, 0, 15.0, VarManager::kPairPt, 150, 0.0, 3.0, VarManager::kDitrackMass); - hm->AddHistogram(histClass, "hQ_X3872", "", false, 150, 0.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hQ_X3872", "", false, 300, -3.0, 3.0, VarManager::kQ); hm->AddHistogram(histClass, "hDeltaR1_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR1); hm->AddHistogram(histClass, "hDeltaR2_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR2); hm->AddHistogram(histClass, "hDeltaR_X3872", "", false, 100, 0.0, 10.0, VarManager::kDeltaR); - hm->AddHistogram(histClass, "hMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 150, 0.0, 3.0, VarManager::kQ); - hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 150, 0.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 300, -3.0, 3.0, VarManager::kQ); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Q_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 300, -3.0, 3.0, VarManager::kQ); hm->AddHistogram(histClass, "hMass_DeltaR1_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kDeltaR1); hm->AddHistogram(histClass, "hMass_defaultDileptonMass_DeltaR1_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, 0.0, 10.0, VarManager::kDeltaR1); hm->AddHistogram(histClass, "hMass_DeltaR2_X3872", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kDeltaR2); @@ -1888,6 +1932,30 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "hMass_defaultDileptonMass_PtTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 100, 0.0, 10.0, VarManager::kPt); hm->AddHistogram(histClass, "hMass_PtTrack1", "", false, 100, 3.0, 5.0, VarManager::kQuadMass, 100, 0.0, 10.0, VarManager::kPt); } + if (subGroupStr.Contains("vertexing")) { + hm->AddHistogram(histClass, "UsedKF", "", false, 2, -0.5, 1.5, VarManager::kUsedKF); + hm->AddHistogram(histClass, "KFMass", "", false, 750, 0.0, 30.0, VarManager::kKFMass); + hm->AddHistogram(histClass, "Lz", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLz); + hm->AddHistogram(histClass, "Lxy", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxy); + hm->AddHistogram(histClass, "Lxyz", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxyz); + hm->AddHistogram(histClass, "Tauz", "", false, 4000, -0.01, 0.01, VarManager::kVertexingTauz); + hm->AddHistogram(histClass, "Tauxy", "", false, 4000, -0.01, 0.01, VarManager::kVertexingTauxy); + hm->AddHistogram(histClass, "LxyzErr", "", false, 100, 0.0, 0.2, VarManager::kVertexingLxyzErr); + hm->AddHistogram(histClass, "LzErr", "", false, 100, 0.0, 0.2, VarManager::kVertexingLzErr); + hm->AddHistogram(histClass, "TauzErr", "", false, 100, 0.0, 0.2, VarManager::kVertexingTauzErr); + hm->AddHistogram(histClass, "VtxingProcCode", "", false, 10, 0.0, 10.0, VarManager::kVertexingProcCode); + hm->AddHistogram(histClass, "VtxingChi2PCA", "", false, 100, 0.0, 10.0, VarManager::kVertexingChi2PCA); + hm->AddHistogram(histClass, "LzProj", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLzProjected); + hm->AddHistogram(histClass, "LxyProj", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxyProjected); + hm->AddHistogram(histClass, "LxyzProj", "", false, 1000, -0.2, 0.2, VarManager::kVertexingLxyzProjected); + hm->AddHistogram(histClass, "TauzProj", "", false, 4000, -0.5, 0.5, VarManager::kVertexingTauzProjected); + hm->AddHistogram(histClass, "TauxyProj", "", false, 4000, -0.5, 0.5, VarManager::kVertexingTauxyProjected); + hm->AddHistogram(histClass, "CosPointingAngle", "", false, 100, 0.0, 1.0, VarManager::kCosPointingAngle); + hm->AddHistogram(histClass, "DCAxyzBetweenProngs", "", false, 100, 0.0, 1.0, VarManager::kKFDCAxyzBetweenProngs); + hm->AddHistogram(histClass, "KFChi2OverNDFGeo", "", false, 150, -5, 10, VarManager::kKFChi2OverNDFGeo); + hm->AddHistogram(histClass, "hMass_Chi2OverNDFGeo", "", false, 1000, 3.0, 5.0, VarManager::kQuadMass, 150, -5, 10., VarManager::kKFChi2OverNDFGeo); + hm->AddHistogram(histClass, "hMass_defaultDileptonMass_Chi2OverNDFGeo", "", false, 1000, 3.0, 5.0, VarManager::kQuadDefaultDileptonMass, 150, -5, 10., VarManager::kKFChi2OverNDFGeo); + } } if (!groupStr.CompareTo("dilepton-photon-mass")) { hm->AddHistogram(histClass, "Mass_Dilepton", "", false, 500, 0.0, 5.0, VarManager::kPairMassDau); @@ -1918,6 +1986,13 @@ void o2::aod::dqhistograms::DefineHistograms(HistogramManager* hm, const char* h hm->AddHistogram(histClass, "Mass_Pt", "", false, 500, 0.0, 5.0, VarManager::kMassDau, 200, 0.0, 20.0, VarManager::kPt); hm->AddHistogram(histClass, "Rapidity", "", false, 400, -4.0, 4.0, VarManager::kRap); } + + if (subGroupStr.Contains("DY-dimuon")) { + hm->AddHistogram(histClass, "DY_mass", "", false, 5000, 0.0, 50.0, VarManager::kMass); // 10 MeV mass res + hm->AddHistogram(histClass, "DY_pT", "", false, 2000, 0.0, 100.0, VarManager::kPt); // 50 MeV pT res + hm->AddHistogram(histClass, "DY_y", "", false, 20, 2.0, 4.0, VarManager::kRap); + hm->AddHistogram(histClass, "DY_phi", "", false, 180, constants::math::PI, 2 * constants::math::PI, VarManager::kPhi); + } } //__________________________________________________________________ diff --git a/PWGDQ/Core/MCSignalLibrary.cxx b/PWGDQ/Core/MCSignalLibrary.cxx index 4486a7c8ea9..5e4f2ada1bb 100644 --- a/PWGDQ/Core/MCSignalLibrary.cxx +++ b/PWGDQ/Core/MCSignalLibrary.cxx @@ -174,7 +174,7 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) return signal; } if (!nameStr.compare("promptPsi2S")) { - MCProng prong(2, {100443, 503}, {true, true}, {false, true}, {0, 0}, {0, 0}, {false, false}); + MCProng prong(1, {100443}, {true}, {false}, {0}, {0}, {false}, false, {503}, {true}); signal = new MCSignal(name, "Prompt psi2s (not from beauty)", {prong}, {-1}); return signal; } @@ -868,11 +868,29 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "ee pairs from non-prompt j/psi decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } + if (!nameStr.compare("mumuFromPhi")) { + MCProng prong(2, {13, 333}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "mumu pairs from phi decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } if (!nameStr.compare("mumuFromJpsi")) { MCProng prong(2, {13, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); signal = new MCSignal(name, "mumu pairs from j/psi decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } + if (!nameStr.compare("mumuFromPromptJpsi")) { + MCProng prong(2, {13, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {503}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "mumu pairs from prompt j/psi decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } + if (!nameStr.compare("mumuFromNonPromptJpsi")) { + MCProng prong(2, {13, 443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {503}, {false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "mumu pairs from non-prompt j/psi decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } if (!nameStr.compare("eeFromPsi2S")) { MCProng prong(2, {11, 100443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); prong.SetSourceBit(0, MCProng::kPhysicalPrimary); @@ -884,6 +902,18 @@ MCSignal* o2::aod::dqmcsignals::GetMCSignal(const char* name) signal = new MCSignal(name, "mumu pairs from psi2s decays", {prong, prong}, {1, 1}); // signal at pair level return signal; } + if (!nameStr.compare("mumuFromPromptPsi2S")) { + MCProng prong(2, {13, 100443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {503}, {true}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "mumu pairs from prompt psi2s decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } + if (!nameStr.compare("mumuFromNonPromptPsi2S")) { + MCProng prong(2, {13, 100443}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}, false, {503}, {false}); + prong.SetSourceBit(0, MCProng::kPhysicalPrimary); + signal = new MCSignal(name, "mumu pairs from non-prompt psi2s decays", {prong, prong}, {1, 1}); // signal at pair level + return signal; + } if (!nameStr.compare("mumuFromUpsilon1S")) { MCProng prong(2, {13, 553}, {true, true}, {false, false}, {0, 0}, {0, 0}, {false, false}); signal = new MCSignal(name, "mumu pairs from upsilon1s decays", {prong, prong}, {1, 1}); // signal at pair level diff --git a/PWGDQ/Core/VarManager.cxx b/PWGDQ/Core/VarManager.cxx index 503101d303f..4bb8c419ad7 100644 --- a/PWGDQ/Core/VarManager.cxx +++ b/PWGDQ/Core/VarManager.cxx @@ -28,8 +28,6 @@ bool VarManager::fgUsedVars[VarManager::kNVars] = {false}; bool VarManager::fgUsedKF = false; float VarManager::fgMagField = 0.5; float VarManager::fgValues[VarManager::kNVars] = {0.0f}; -float VarManager::fgCenterOfMassEnergy = 13600; // GeV -float VarManager::fgMassofCollidingParticle = 9.382720; // GeV float VarManager::fgTPCInterSectorBoundary = 1.0; // cm int VarManager::fgITSROFbias = 0; int VarManager::fgITSROFlength = 100; @@ -37,8 +35,11 @@ int VarManager::fgITSROFBorderMarginLow = 0; int VarManager::fgITSROFBorderMarginHigh = 0; uint64_t VarManager::fgSOR = 0; uint64_t VarManager::fgEOR = 0; +ROOT::Math::PxPyPzEVector VarManager::fgBeamA(0, 0, 6799.99, 6800); // GeV, beam from A-side 4-momentum vector +ROOT::Math::PxPyPzEVector VarManager::fgBeamC(0, 0, -6799.99, 6800); // GeV, beam from C-side 4-momentum vector o2::vertexing::DCAFitterN<2> VarManager::fgFitterTwoProngBarrel; o2::vertexing::DCAFitterN<3> VarManager::fgFitterThreeProngBarrel; +o2::vertexing::DCAFitterN<4> VarManager::fgFitterFourProngBarrel; o2::vertexing::FwdDCAFitterN<2> VarManager::fgFitterTwoProngFwd; o2::vertexing::FwdDCAFitterN<3> VarManager::fgFitterThreeProngFwd; o2::globaltracking::MatchGlobalFwd VarManager::mMatching; @@ -113,15 +114,75 @@ void VarManager::SetCollisionSystem(TString system, float energy) // // Set the collision system and the center of mass energy // - fgCenterOfMassEnergy = energy; - - if (system.Contains("PbPb")) { - fgMassofCollidingParticle = MassProton * 208; - } - if (system.Contains("pp")) { - fgMassofCollidingParticle = MassProton; + int NumberOfNucleonsA = 1; // default value for pp collisions + int NumberOfNucleonsC = 1; // default value for pp collisions + int NumberOfProtonsA = 1; // default value for pp collisions + int NumberOfProtonsC = 1; // default value for pp collisions + if (system.EqualTo("PbPb")) { + NumberOfNucleonsA = 208; + NumberOfNucleonsC = 208; + NumberOfProtonsA = 82; // Pb has 82 protons + NumberOfProtonsC = 82; // Pb has 82 protons + } else if (system.EqualTo("pp")) { + NumberOfNucleonsA = 1; + NumberOfNucleonsC = 1; + NumberOfProtonsA = 1; // proton has 1 proton + NumberOfProtonsC = 1; // proton has 1 proton + } else if (system.EqualTo("XeXe")) { + NumberOfNucleonsA = 129; + NumberOfNucleonsC = 129; + NumberOfProtonsA = 54; // Xe has 54 protons + NumberOfProtonsC = 54; // Xe has 54 protons + } else if (system.EqualTo("pPb")) { + NumberOfNucleonsA = 1; + NumberOfNucleonsC = 208; + NumberOfProtonsA = 1; // proton has 1 proton + NumberOfProtonsC = 82; // Pb has 82 protons + } else if (system.EqualTo("Pbp")) { + NumberOfNucleonsA = 208; + NumberOfNucleonsC = 1; + NumberOfProtonsA = 82; // Pb has 82 protons + NumberOfProtonsC = 1; // proton has 1 proton + } else if (system.EqualTo("OO")) { + NumberOfNucleonsA = 16; + NumberOfNucleonsC = 16; + NumberOfProtonsA = 8; // O has 8 protons + NumberOfProtonsC = 8; // O has 8 protons + } else if (system.EqualTo("pO")) { + NumberOfNucleonsA = 1; + NumberOfNucleonsC = 16; + NumberOfProtonsA = 1; // proton has 1 proton + NumberOfProtonsC = 8; // O has 8 protons + } else if (system.EqualTo("NeNe")) { + NumberOfNucleonsA = 20; + NumberOfNucleonsC = 20; + NumberOfProtonsA = 10; // Ne has 5 protons + NumberOfProtonsC = 10; // Ne has 5 protons } // TO Do: add more systems + + // set the beam 4-momentum vectors + float beamAEnergy = energy / 2.0 * sqrt(NumberOfProtonsA * NumberOfProtonsC / NumberOfProtonsC / NumberOfProtonsA); // GeV + float beamCEnergy = energy / 2.0 * sqrt(NumberOfProtonsC * NumberOfProtonsA / NumberOfProtonsA / NumberOfProtonsC); // GeV + float beamAMomentum = std::sqrt(beamAEnergy * beamAEnergy - NumberOfNucleonsA * NumberOfNucleonsA * MassProton * MassProton); + float beamCMomentum = std::sqrt(beamCEnergy * beamCEnergy - NumberOfNucleonsC * NumberOfNucleonsC * MassProton * MassProton); + fgBeamA.SetPxPyPzE(0, 0, beamAMomentum, beamAEnergy); + fgBeamC.SetPxPyPzE(0, 0, -beamCMomentum, beamCEnergy); +} + +//__________________________________________________________________ +void VarManager::SetCollisionSystem(o2::parameters::GRPLHCIFData* grplhcif) +{ + // + // Set the collision system and the center of mass energy from the GRP information + double beamAEnergy = grplhcif->getBeamEnergyPerNucleonInGeV(o2::constants::lhc::BeamDirection::BeamA); + double beamCEnergy = grplhcif->getBeamEnergyPerNucleonInGeV(o2::constants::lhc::BeamDirection::BeamC); + double beamANucleons = grplhcif->getBeamA(o2::constants::lhc::BeamDirection::BeamA); + double beamCNucleons = grplhcif->getBeamA(o2::constants::lhc::BeamDirection::BeamC); + double beamAMomentum = std::sqrt(beamAEnergy * beamAEnergy - beamANucleons * beamANucleons * MassProton * MassProton); + double beamCMomentum = std::sqrt(beamCEnergy * beamCEnergy - beamCNucleons * beamCNucleons * MassProton * MassProton); + fgBeamA.SetPxPyPzE(0, 0, beamAMomentum, beamAEnergy); + fgBeamC.SetPxPyPzE(0, 0, -beamCMomentum, beamCEnergy); } //__________________________________________________________________ @@ -201,6 +262,10 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kCentVZERO] = "%"; fgVariableNames[kCentFT0C] = "Centrality FT0C"; fgVariableUnits[kCentFT0C] = "%"; + fgVariableNames[kCentFT0A] = "Centrality FT0A"; + fgVariableUnits[kCentFT0A] = "%"; + fgVariableNames[kCentFT0M] = "Centrality FT0M"; + fgVariableUnits[kCentFT0M] = "%"; fgVariableNames[kMultTPC] = "Multiplicity TPC"; fgVariableUnits[kMultTPC] = ""; fgVariableNames[kMultFV0A] = "Multiplicity FV0A"; @@ -962,6 +1027,12 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kPhiTildePP] = "rad."; fgVariableNames[kCosThetaRM] = "cos#it{#theta}_{RM}"; fgVariableUnits[kCosThetaRM] = ""; + fgVariableNames[kCosThetaStarTPC] = "cos#it{#theta}^{*}_{TPC}"; + fgVariableUnits[kCosThetaStarTPC] = ""; + fgVariableNames[kCosThetaStarFT0A] = "cos#it{#theta}^{*}_{FT0A}"; + fgVariableUnits[kCosThetaStarFT0A] = ""; + fgVariableNames[kCosThetaStarFT0C] = "cos#it{#theta}^{*}_{FT0C}"; + fgVariableUnits[kCosThetaStarFT0C] = ""; fgVariableNames[kCosPhiVP] = "cos#it{#varphi}_{VP}"; fgVariableUnits[kCosPhiVP] = ""; fgVariableNames[kPhiVP] = "#varphi_{VP} - #Psi_{2}"; @@ -1060,6 +1131,12 @@ void VarManager::SetDefaultVarNames() fgVariableUnits[kS13] = "GeV^{2}/c^{4}"; fgVariableNames[kS23] = "m_{23}^{2}"; fgVariableUnits[kS23] = "GeV^{2}/c^{4}"; + fgVariableNames[kBdtBackground] = "kBdtBackground"; + fgVariableUnits[kBdtBackground] = " "; + fgVariableNames[kBdtPrompt] = "kBdtPrompt"; + fgVariableUnits[kBdtPrompt] = " "; + fgVariableNames[kBdtNonprompt] = "kBdtNonprompt"; + fgVariableUnits[kBdtNonprompt] = " "; // Set the variables short names map. This is needed for dynamic configuration via JSON files fgVarNamesMap["kNothing"] = kNothing; @@ -1108,6 +1185,8 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kVtxChi2"] = kVtxChi2; fgVarNamesMap["kCentVZERO"] = kCentVZERO; fgVarNamesMap["kCentFT0C"] = kCentFT0C; + fgVarNamesMap["kCentFT0A"] = kCentFT0A; + fgVarNamesMap["kCentFT0M"] = kCentFT0M; fgVarNamesMap["kMultTPC"] = kMultTPC; fgVarNamesMap["kMultFV0A"] = kMultFV0A; fgVarNamesMap["kMultFV0C"] = kMultFV0C; @@ -1525,6 +1604,9 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kPhiPP"] = kPhiPP; fgVarNamesMap["kPhiTildePP"] = kPhiTildePP; fgVarNamesMap["kCosThetaRM"] = kCosThetaRM; + fgVarNamesMap["kCosThetaStarTPC"] = kCosThetaStarTPC; + fgVarNamesMap["kCosThetaStarFT0A"] = kCosThetaStarFT0A; + fgVarNamesMap["kCosThetaStarFT0C"] = kCosThetaStarFT0C; fgVarNamesMap["kCosPhiVP"] = kCosPhiVP; fgVarNamesMap["kPhiVP"] = kPhiVP; fgVarNamesMap["kDeltaPhiPair2"] = kDeltaPhiPair2; @@ -1694,4 +1776,7 @@ void VarManager::SetDefaultVarNames() fgVarNamesMap["kV24ME"] = kV24ME; fgVarNamesMap["kWV22ME"] = kWV22ME; fgVarNamesMap["kWV24ME"] = kWV24ME; + fgVarNamesMap["kBdtBackground"] = kBdtBackground; + fgVarNamesMap["kBdtPrompt"] = kBdtPrompt; + fgVarNamesMap["kBdtNonprompt"] = kBdtNonprompt; } diff --git a/PWGDQ/Core/VarManager.h b/PWGDQ/Core/VarManager.h index 31c1f69a275..d49e71677da 100644 --- a/PWGDQ/Core/VarManager.h +++ b/PWGDQ/Core/VarManager.h @@ -24,49 +24,49 @@ #define HomogeneousField #endif -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include "TRandom.h" -#include "TH3F.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/GenVector/Boost.h" -#include "Math/VectorUtil.h" - -#include "Framework/DataTypes.h" -#include "TGeoGlobalMagField.h" -#include "Field/MagneticField.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/Vertex.h" -#include "DCAFitter/DCAFitterN.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" -#include "ReconstructionDataFormats/DCA.h" -#include "DetectorsBase/Propagator.h" +#include "Common/Core/CollisionTypeHelper.h" +#include "Common/Core/EventPlaneHelper.h" #include "Common/Core/trackUtilities.h" -#include "Math/SMatrix.h" -#include "ReconstructionDataFormats/TrackFwd.h" +#include "CommonConstants/LHCConstants.h" +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" #include "DCAFitter/FwdDCAFitterN.h" +#include "DetectorsBase/Propagator.h" +#include "Field/MagneticField.h" +#include "Framework/DataTypes.h" #include "GlobalTracking/MatchGlobalFwd.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CommonConstants/LHCConstants.h" +#include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Track.h" +#include "ReconstructionDataFormats/TrackFwd.h" +#include "ReconstructionDataFormats/Vertex.h" + +#include "Math/GenVector/Boost.h" +#include "Math/SMatrix.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/VectorUtil.h" +#include "TGeoGlobalMagField.h" +#include "TH3F.h" +#include "TRandom.h" +#include +#include -#include "KFParticle.h" #include "KFPTrack.h" #include "KFPVertex.h" +#include "KFParticle.h" #include "KFParticleBase.h" #include "KFVertex.h" -#include "Common/Core/EventPlaneHelper.h" +#include +#include +#include +#include +#include +#include +#include using std::complex; using std::cout; @@ -146,6 +146,7 @@ class VarManager : public TObject kBtoJpsiEEK, // e.g. B+ -> e+ e- K+ kJpsiEEProton, // e.g. Jpsi-proton correlation, Jpsi to e+e- kXtoJpsiPiPi, // e.g. X(3872) -> J/psi pi+ pi- + kPsi2StoJpsiPiPi, // e.g. Psi(2S) -> J/psi pi+ pi- kChictoJpsiEE, // e.g. Chi_c1 -> J/psi e+ e- kDstarToD0KPiPi, // e.g. D*+ -> D0 pi+ -> K- pi+ pi+ kTripleCandidateToEEPhoton, // e.g. chi_c -> e+ e- photon or pi0 -> e+ e- photon @@ -222,6 +223,8 @@ class VarManager : public TObject kVtxChi2, kCentVZERO, kCentFT0C, + kCentFT0A, + kCentFT0M, kMultTPC, kMultFV0A, kMultFV0C, @@ -667,6 +670,9 @@ class VarManager : public TObject kPhiPP, kPhiTildePP, kCosThetaRM, + kCosThetaStarTPC, + kCosThetaStarFT0A, + kCosThetaStarFT0C, kCosPhiVP, kPhiVP, kDeltaPhiPair2, @@ -849,6 +855,11 @@ class VarManager : public TObject // deltaMass_jpsi = kPairMass - kPairMassDau +3.096900 kDeltaMass_jpsi, + // BDT score + kBdtBackground, + kBdtPrompt, + kBdtNonprompt, + kNVars }; // end of Variables enumeration @@ -921,6 +932,7 @@ class VarManager : public TObject // Setup the collision system static void SetCollisionSystem(TString system, float energy); + static void SetCollisionSystem(o2::parameters::GRPLHCIFData* grplhcif); static void SetMagneticField(float magField) { @@ -998,6 +1010,25 @@ class VarManager : public TObject fgUsedKF = false; } + // Setup the 4 prong KFParticle + static void SetupFourProngKFParticle(float magField) + { + KFParticle::SetField(magField); + fgUsedKF = true; + } + + // Setup the 4 prong DCAFitterN + static void SetupFourProngDCAFitter(float magField, bool propagateToPCA, float maxR, float /*maxDZIni*/, float minParamChange, float minRelChi2Change, bool useAbsDCA) + { + fgFitterFourProngBarrel.setBz(magField); + fgFitterFourProngBarrel.setPropagateToPCA(propagateToPCA); + fgFitterFourProngBarrel.setMaxR(maxR); + fgFitterFourProngBarrel.setMinParamChange(minParamChange); + fgFitterFourProngBarrel.setMinRelChi2Change(minRelChi2Change); + fgFitterFourProngBarrel.setUseAbsDCA(useAbsDCA); + fgUsedKF = false; + } + static auto getEventPlane(int harm, float qnxa, float qnya) { // Compute event plane angle from qn vector components for the sub-event A @@ -1068,7 +1099,7 @@ class VarManager : public TObject template static void FillTripleMC(T1 const& t1, T2 const& t2, T3 const& t3, float* values = nullptr, PairCandidateType pairType = kTripleCandidateToEEPhoton); template - static void FillQaudMC(T1 const& t1, T2 const& t2, T2 const& t3, float* values = nullptr); + 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 @@ -1097,8 +1128,12 @@ class VarManager : public TObject static void FillPairVn(T1 const& t1, T2 const& t2, float* values = nullptr); template static void FillDileptonTrackTrack(T1 const& dilepton, T2 const& hadron1, T3 const& hadron2, float* values = nullptr); + template + static void FillDileptonTrackTrackVertexing(C const& collision, T1 const& lepton1, T1 const& lepton2, T1 const& track1, T1 const& track2, float* values); template static void FillZDC(const T& zdc, float* values = nullptr); + template + static void FillBdtScore(const T& bdtScore, float* values = nullptr); static void SetCalibrationObject(CalibObjects calib, TObject* obj) { @@ -1170,6 +1205,8 @@ class VarManager : public TObject static int fgITSROFBorderMarginHigh; // ITS ROF border high margin static uint64_t fgSOR; // Timestamp for start of run static uint64_t fgEOR; // Timestamp for end of run + static ROOT::Math::PxPyPzEVector fgBeamA; // beam from A-side 4-momentum vector + static ROOT::Math::PxPyPzEVector fgBeamC; // beam from C-side 4-momentum vector // static void FillEventDerived(float* values = nullptr); static void FillTrackDerived(float* values = nullptr); @@ -1187,6 +1224,7 @@ class VarManager : public TObject static o2::vertexing::DCAFitterN<2> fgFitterTwoProngBarrel; static o2::vertexing::DCAFitterN<3> fgFitterThreeProngBarrel; + static o2::vertexing::DCAFitterN<4> fgFitterFourProngBarrel; static o2::vertexing::FwdDCAFitterN<2> fgFitterTwoProngFwd; static o2::vertexing::FwdDCAFitterN<3> fgFitterThreeProngFwd; static o2::globaltracking::MatchGlobalFwd mMatching; @@ -1551,6 +1589,8 @@ void VarManager::FillEvent(T const& event, float* values) if constexpr ((fillMap & CollisionCent) > 0 || (fillMap & ReducedEventExtended) > 0) { values[kCentFT0C] = event.centFT0C(); + values[kCentFT0A] = event.centFT0A(); + values[kCentFT0M] = event.centFT0M(); } if constexpr ((fillMap & CollisionMult) > 0 || (fillMap & ReducedEventExtended) > 0) { @@ -2777,21 +2817,12 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) double Ptot2 = TMath::Sqrt(v2.Px() * v2.Px() + v2.Py() * v2.Py() + v2.Pz() * v2.Pz()); values[kDeltaPtotTracks] = Ptot1 - Ptot2; - if (t1.sign() > 0) { - values[kPt1] = t1.pt(); - values[kEta1] = t1.eta(); - values[kPhi1] = t1.phi(); - values[kPt2] = t2.pt(); - values[kEta2] = t2.eta(); - values[kPhi2] = t2.phi(); - } else { - values[kPt1] = t2.pt(); - values[kEta1] = t2.eta(); - values[kPhi1] = t2.phi(); - values[kPt2] = t1.pt(); - values[kEta2] = t1.eta(); - values[kPhi2] = t1.phi(); - } + 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(); @@ -2836,16 +2867,11 @@ void VarManager::FillPair(T1 const& t1, T2 const& t2, float* values) bool useRM = fgUsedVars[kCosThetaRM]; // Random frame if (useHE || useCS || usePP || useRM) { - // TO DO: get the correct values from CCDB - double BeamMomentum = TMath::Sqrt(fgCenterOfMassEnergy * fgCenterOfMassEnergy / 4 - fgMassofCollidingParticle * fgMassofCollidingParticle); // GeV - ROOT::Math::PxPyPzEVector Beam1(0., 0., -BeamMomentum, fgCenterOfMassEnergy / 2); - ROOT::Math::PxPyPzEVector Beam2(0., 0., BeamMomentum, fgCenterOfMassEnergy / 2); - ROOT::Math::Boost boostv12{v12.BoostToCM()}; ROOT::Math::XYZVectorF v1_CM{(boostv12(v1).Vect()).Unit()}; ROOT::Math::XYZVectorF v2_CM{(boostv12(v2).Vect()).Unit()}; - ROOT::Math::XYZVectorF Beam1_CM{(boostv12(Beam1).Vect()).Unit()}; - ROOT::Math::XYZVectorF Beam2_CM{(boostv12(Beam2).Vect()).Unit()}; + 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); @@ -3351,16 +3377,11 @@ void VarManager::FillPairMC(T1 const& t1, T2 const& t2, float* values) bool useRM = fgUsedVars[kMCCosThetaRM]; // Random frame if (useHE || useCS || usePP || useRM) { - // TO DO: get the correct values from CCDB - double BeamMomentum = TMath::Sqrt(fgCenterOfMassEnergy * fgCenterOfMassEnergy / 4 - fgMassofCollidingParticle * fgMassofCollidingParticle); // GeV - ROOT::Math::PxPyPzEVector Beam1(0., 0., -BeamMomentum, fgCenterOfMassEnergy / 2); - ROOT::Math::PxPyPzEVector Beam2(0., 0., BeamMomentum, fgCenterOfMassEnergy / 2); - ROOT::Math::Boost boostv12{v12.BoostToCM()}; ROOT::Math::XYZVectorF v1_CM{(boostv12(v1).Vect()).Unit()}; ROOT::Math::XYZVectorF v2_CM{(boostv12(v2).Vect()).Unit()}; - ROOT::Math::XYZVectorF Beam1_CM{(boostv12(Beam1).Vect()).Unit()}; - ROOT::Math::XYZVectorF Beam2_CM{(boostv12(Beam2).Vect()).Unit()}; + 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.pdgCode() > 0 ? v1_CM : v2_CM); @@ -4815,6 +4836,26 @@ void VarManager::FillPairVn(T1 const& t1, T2 const& t2, float* values) values[kR3EP] = -999.; } + // global polarization parameters + bool useGlobalPolarizatiobSpinOne = fgUsedVars[kCosThetaStarTPC] || fgUsedVars[kCosThetaStarFT0A] || fgUsedVars[kCosThetaStarFT0C]; + if (useGlobalPolarizatiobSpinOne) { + ROOT::Math::Boost boostv12{v12.BoostToCM()}; + ROOT::Math::XYZVectorF v1_CM{(boostv12(v1).Vect()).Unit()}; + ROOT::Math::XYZVectorF v2_CM{(boostv12(v2).Vect()).Unit()}; + + // using positive sign convention for the first track + ROOT::Math::XYZVectorF v_CM = (t1.sign() > 0 ? v1_CM : v2_CM); + + ROOT::Math::XYZVector zaxisTPC = ROOT::Math::XYZVector(TMath::Cos(Psi2A), TMath::Sin(Psi2A), 0).Unit(); + values[kCosThetaStarTPC] = v_CM.Dot(zaxisTPC); + + ROOT::Math::XYZVector zaxisFT0A = ROOT::Math::XYZVector(TMath::Cos(Psi2B), TMath::Sin(Psi2B), 0).Unit(); + values[kCosThetaStarFT0A] = v_CM.Dot(zaxisFT0A); + + ROOT::Math::XYZVector zaxisFT0C = ROOT::Math::XYZVector(TMath::Cos(Psi2C), TMath::Sin(Psi2C), 0).Unit(); + values[kCosThetaStarFT0C] = v_CM.Dot(zaxisFT0C); + } + // kV4, kC4POI, kC4REF etc. if constexpr ((fillMap & ReducedEventQvectorExtra) > 0) { complex Q21(values[kQ2X0A] * values[kS11A], values[kQ2Y0A] * values[kS11A]); @@ -5080,9 +5121,269 @@ void VarManager::FillDileptonTrackTrack(T1 const& dilepton, T2 const& hadron1, T } } +//__________________________________________________________________ +template +void VarManager::FillDileptonTrackTrackVertexing(C const& collision, T1 const& lepton1, T1 const& lepton2, T1 const& track1, T1 const& track2, float* values) +{ + constexpr bool eventHasVtxCov = ((collFillMap & Collision) > 0 || (collFillMap & ReducedEventVtxCov) > 0); + constexpr bool trackHasCov = ((fillMap & TrackCov) > 0 || (fillMap & ReducedTrackBarrelCov) > 0); + + if (!eventHasVtxCov || !trackHasCov) { + return; + } + + if (!values) { + values = fgValues; + } + + float mtrack1, mtrack2; + float mlepton1, mlepton2; + + if constexpr (candidateType == kXtoJpsiPiPi || candidateType == kPsi2StoJpsiPiPi) { + mlepton1 = o2::constants::physics::MassElectron; + mlepton2 = o2::constants::physics::MassElectron; + mtrack1 = o2::constants::physics::MassPionCharged; + mtrack2 = o2::constants::physics::MassPionCharged; + } + + ROOT::Math::PtEtaPhiMVector v1(lepton1.pt(), lepton1.eta(), lepton1.phi(), mlepton1); + ROOT::Math::PtEtaPhiMVector v2(lepton2.pt(), lepton2.eta(), lepton2.phi(), mlepton2); + ROOT::Math::PtEtaPhiMVector v3(track1.pt(), track1.eta(), track1.phi(), mtrack1); + ROOT::Math::PtEtaPhiMVector v4(track2.pt(), track2.eta(), track2.phi(), mtrack2); + ROOT::Math::PtEtaPhiMVector v1234 = v1 + v2 + v3 + v4; + + int procCodeDilepton = 0; + int procCodeDileptonTrackTrack = 0; + + values[kUsedKF] = fgUsedKF; + if (!fgUsedKF) { + // create covariance matrix + std::array lepton1pars = {lepton1.y(), lepton1.z(), lepton1.snp(), lepton1.tgl(), lepton1.signed1Pt()}; + std::array lepton1covs = {lepton1.cYY(), lepton1.cZY(), lepton1.cZZ(), lepton1.cSnpY(), lepton1.cSnpZ(), + lepton1.cSnpSnp(), lepton1.cTglY(), lepton1.cTglZ(), lepton1.cTglSnp(), lepton1.cTglTgl(), + lepton1.c1PtY(), lepton1.c1PtZ(), lepton1.c1PtSnp(), lepton1.c1PtTgl(), lepton1.c1Pt21Pt2()}; + o2::track::TrackParCov pars1{lepton1.x(), lepton1.alpha(), lepton1pars, lepton1covs}; + std::array lepton2pars = {lepton2.y(), lepton2.z(), lepton2.snp(), lepton2.tgl(), lepton2.signed1Pt()}; + std::array lepton2covs = {lepton2.cYY(), lepton2.cZY(), lepton2.cZZ(), lepton2.cSnpY(), lepton2.cSnpZ(), + lepton2.cSnpSnp(), lepton2.cTglY(), lepton2.cTglZ(), lepton2.cTglSnp(), lepton2.cTglTgl(), + lepton2.c1PtY(), lepton2.c1PtZ(), lepton2.c1PtSnp(), lepton2.c1PtTgl(), lepton2.c1Pt21Pt2()}; + o2::track::TrackParCov pars2{lepton2.x(), lepton2.alpha(), lepton2pars, lepton2covs}; + std::array track1pars = {track1.y(), track1.z(), track1.snp(), track1.tgl(), track1.signed1Pt()}; + std::array track1covs = {track1.cYY(), track1.cZY(), track1.cZZ(), track1.cSnpY(), track1.cSnpZ(), + track1.cSnpSnp(), track1.cTglY(), track1.cTglZ(), track1.cTglSnp(), track1.cTglTgl(), + track1.c1PtY(), track1.c1PtZ(), track1.c1PtSnp(), track1.c1PtTgl(), track1.c1Pt21Pt2()}; + o2::track::TrackParCov pars3{track1.x(), track1.alpha(), track1pars, track1covs}; + std::array track2pars = {track2.y(), track2.z(), track2.snp(), track2.tgl(), track2.signed1Pt()}; + std::array track2covs = {track2.cYY(), track2.cZY(), track2.cZZ(), track2.cSnpY(), track2.cSnpZ(), + track2.cSnpSnp(), track2.cTglY(), track2.cTglZ(), track2.cTglSnp(), track2.cTglTgl(), + track2.c1PtY(), track2.c1PtZ(), track2.c1PtSnp(), track2.c1PtTgl(), track2.c1Pt21Pt2()}; + o2::track::TrackParCov pars4{track2.x(), track2.alpha(), track2pars, track2covs}; + + procCodeDilepton = VarManager::fgFitterTwoProngBarrel.process(pars1, pars2); + // create dilepton track + // o2::track::TrackParCov parsDilepton = VarManager::fgFitterTwoProngBarrel.createParentTrackParCov(0); + // procCodeDileptonTrackTrack = VarManager::fgFitterThreeProngBarrel.process(parsDilepton, pars3, pars4); + procCodeDileptonTrackTrack = VarManager::fgFitterFourProngBarrel.process(pars1, pars2, pars3, pars4); + + // fill values + if (procCodeDilepton == 0 && procCodeDileptonTrackTrack == 0) { + // TODO: set the other variables to appropriate values and return + values[kVertexingLxy] = -999.; + values[kVertexingLxyz] = -999.; + values[kVertexingLz] = -999.; + values[kVertexingLxyErr] = -999.; + values[kVertexingLxyzErr] = -999.; + values[kVertexingLzErr] = -999.; + values[kVertexingTauxy] = -999.; + values[kVertexingTauxyErr] = -999.; + values[kVertexingTauz] = -999.; + values[kVertexingTauzErr] = -999.; + values[kVertexingLzProjected] = -999.; + values[kVertexingLxyProjected] = -999.; + values[kVertexingLxyzProjected] = -999.; + values[kVertexingTauzProjected] = -999.; + values[kVertexingTauxyProjected] = -999.; + values[kVertexingTauxyzProjected] = -999.; + return; + } else { + Vec3D secondaryVertex; + std::array covMatrixPCA; + secondaryVertex = fgFitterFourProngBarrel.getPCACandidate(); + covMatrixPCA = fgFitterFourProngBarrel.calcPCACovMatrixFlat(); + + o2::math_utils::Point3D vtxXYZ(collision.posX(), collision.posY(), collision.posZ()); + std::array vtxCov{collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}; + o2::dataformats::VertexBase primaryVertex = {std::move(vtxXYZ), std::move(vtxCov)}; + auto covMatrixPV = primaryVertex.getCov(); + + double phi = std::atan2(secondaryVertex[1] - collision.posY(), secondaryVertex[0] - collision.posX()); + double theta = std::atan2(secondaryVertex[2] - collision.posZ(), + std::sqrt((secondaryVertex[0] - collision.posX()) * (secondaryVertex[0] - collision.posX()) + + (secondaryVertex[1] - collision.posY()) * (secondaryVertex[1] - collision.posY()))); + + values[kVertexingLxy] = (collision.posX() - secondaryVertex[0]) * (collision.posX() - secondaryVertex[0]) + + (collision.posY() - secondaryVertex[1]) * (collision.posY() - secondaryVertex[1]); + values[kVertexingLz] = (collision.posZ() - secondaryVertex[2]) * (collision.posZ() - secondaryVertex[2]); + values[kVertexingLxyz] = values[kVertexingLxy] + values[kVertexingLz]; + values[kVertexingLxy] = std::sqrt(values[kVertexingLxy]); + values[kVertexingLz] = std::sqrt(values[kVertexingLz]); + values[kVertexingLxyz] = std::sqrt(values[kVertexingLxyz]); + + values[kVertexingLxyzErr] = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, theta) + getRotatedCovMatrixXX(covMatrixPCA, phi, theta)); + values[kVertexingLxyErr] = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + values[kVertexingLzErr] = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, 0, theta) + getRotatedCovMatrixXX(covMatrixPCA, 0, theta)); + + values[kVertexingTauz] = (collision.posZ() - secondaryVertex[2]) * v1234.M() / (TMath::Abs(v1234.Pz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauxy] = values[kVertexingLxy] * v1234.M() / (v1234.Pt() * o2::constants::physics::LightSpeedCm2NS); + + values[kVertexingTauzErr] = values[kVertexingLzErr] * v1234.M() / (TMath::Abs(v1234.Pz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauxyErr] = values[kVertexingLxyErr] * v1234.M() / (v1234.Pt() * o2::constants::physics::LightSpeedCm2NS); + + values[kCosPointingAngle] = ((collision.posX() - secondaryVertex[0]) * v1234.Px() + + (collision.posY() - secondaryVertex[1]) * v1234.Py() + + (collision.posZ() - secondaryVertex[2]) * v1234.Pz()) / + (v1234.P() * values[VarManager::kVertexingLxyz]); + // // run 2 definitions: Decay length projected onto the momentum vector of the candidate + values[kVertexingLzProjected] = (secondaryVertex[2] - collision.posZ()) * v1234.Pz(); + values[kVertexingLzProjected] = values[kVertexingLzProjected] / TMath::Sqrt(v1234.Pz() * v1234.Pz()); + values[kVertexingLxyProjected] = ((secondaryVertex[0] - collision.posX()) * v1234.Px()) + ((secondaryVertex[1] - collision.posY()) * v1234.Py()); + values[kVertexingLxyProjected] = values[kVertexingLxyProjected] / TMath::Sqrt((v1234.Px() * v1234.Px()) + (v1234.Py() * v1234.Py())); + values[kVertexingLxyzProjected] = ((secondaryVertex[0] - collision.posX()) * v1234.Px()) + ((secondaryVertex[1] - collision.posY()) * v1234.Py()) + ((secondaryVertex[2] - collision.posZ()) * v1234.Pz()); + values[kVertexingLxyzProjected] = values[kVertexingLxyzProjected] / TMath::Sqrt((v1234.Px() * v1234.Px()) + (v1234.Py() * v1234.Py()) + (v1234.Pz() * v1234.Pz())); + + values[kVertexingTauzProjected] = values[kVertexingLzProjected] * v1234.M() / TMath::Abs(v1234.Pz()); + values[kVertexingTauxyProjected] = values[kVertexingLxyProjected] * v1234.M() / (v1234.Pt()); + values[kVertexingTauxyzProjected] = values[kVertexingLxyzProjected] * v1234.M() / (v1234.P()); + } + } else if (fgUsedKF) { + KFParticle lepton1KF; // lepton1 + KFParticle lepton2KF; // lepton2 + KFParticle KFGeoTwoLeptons; + KFParticle trk1KF; // track1 + KFParticle trk2KF; // track2 + KFParticle KFGeoTwoTracks; + KFParticle KFGeoFourProng; + if constexpr (candidateType == kXtoJpsiPiPi) { + KFPTrack kfpTrack0 = createKFPTrackFromTrack(lepton1); + lepton1KF = KFParticle(kfpTrack0, -11 * lepton1.sign()); + KFPTrack kfpTrack1 = createKFPTrackFromTrack(lepton2); + lepton2KF = KFParticle(kfpTrack1, -11 * lepton2.sign()); + KFPTrack kfpTrack2 = createKFPTrackFromTrack(track1); + trk1KF = KFParticle(kfpTrack2, 211 * track1.sign()); + KFPTrack kfpTrack3 = createKFPTrackFromTrack(track2); + trk2KF = KFParticle(kfpTrack3, 211 * track2.sign()); + + KFGeoTwoLeptons.SetConstructMethod(2); + KFGeoTwoLeptons.AddDaughter(lepton1KF); + KFGeoTwoLeptons.AddDaughter(lepton2KF); + + if (fgUsedVars[kPairMass] || fgUsedVars[kPairPt]) { + values[VarManager::kPairMass] = KFGeoTwoLeptons.GetMass(); + values[VarManager::kPairPt] = KFGeoTwoLeptons.GetPt(); + } + + KFGeoTwoTracks.SetConstructMethod(2); + KFGeoTwoTracks.AddDaughter(trk1KF); + KFGeoTwoTracks.AddDaughter(trk2KF); + + if (fgUsedVars[kDitrackMass] || fgUsedVars[kDitrackPt]) { + values[VarManager::kDitrackMass] = KFGeoTwoTracks.GetMass(); + values[VarManager::kDitrackPt] = KFGeoTwoTracks.GetPt(); + } + + KFGeoFourProng.SetConstructMethod(2); + KFGeoFourProng.AddDaughter(KFGeoTwoLeptons); + KFGeoFourProng.AddDaughter(KFGeoTwoTracks); + } + + if constexpr (candidateType == kPsi2StoJpsiPiPi) { + KFPTrack kfpTrack0 = createKFPTrackFromTrack(lepton1); + lepton1KF = KFParticle(kfpTrack0, -11 * lepton1.sign()); + KFPTrack kfpTrack1 = createKFPTrackFromTrack(lepton2); + lepton2KF = KFParticle(kfpTrack1, -11 * lepton2.sign()); + KFPTrack kfpTrack2 = createKFPTrackFromTrack(track1); + trk1KF = KFParticle(kfpTrack2, 211 * track1.sign()); + KFPTrack kfpTrack3 = createKFPTrackFromTrack(track2); + trk2KF = KFParticle(kfpTrack3, 211 * track2.sign()); + + KFGeoTwoLeptons.SetConstructMethod(2); + KFGeoTwoLeptons.AddDaughter(lepton1KF); + KFGeoTwoLeptons.AddDaughter(lepton2KF); + + if (fgUsedVars[kPairMass] || fgUsedVars[kPairPt]) { + values[VarManager::kPairMass] = KFGeoTwoLeptons.GetMass(); + values[VarManager::kPairPt] = KFGeoTwoLeptons.GetPt(); + } + + KFGeoFourProng.SetConstructMethod(2); + KFGeoFourProng.AddDaughter(KFGeoTwoLeptons); + KFGeoFourProng.AddDaughter(trk1KF); + KFGeoFourProng.AddDaughter(trk2KF); + } + + if (fgUsedVars[kKFMass]) { + float mass = 0., massErr = 0.; + if (!KFGeoFourProng.GetMass(mass, massErr)) + values[kKFMass] = mass; + else + values[kKFMass] = -999.; + } + + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + values[kKFNContributorsPV] = kfpVertex.GetNContributors(); + KFParticle KFPV(kfpVertex); + double dxQuadlet2PV = KFGeoFourProng.GetX() - KFPV.GetX(); + double dyQuadlet2PV = KFGeoFourProng.GetY() - KFPV.GetY(); + double dzQuadlet2PV = KFGeoFourProng.GetZ() - KFPV.GetZ(); + + values[kVertexingLxy] = std::sqrt(dxQuadlet2PV * dxQuadlet2PV + dyQuadlet2PV * dyQuadlet2PV); + values[kVertexingLz] = std::sqrt(dzQuadlet2PV * dzQuadlet2PV); + values[kVertexingLxyz] = std::sqrt(dxQuadlet2PV * dxQuadlet2PV + dyQuadlet2PV * dyQuadlet2PV + dzQuadlet2PV * dzQuadlet2PV); + + values[kVertexingLxyErr] = (KFPV.GetCovariance(0) + KFGeoFourProng.GetCovariance(0)) * dxQuadlet2PV * dxQuadlet2PV + (KFPV.GetCovariance(2) + KFGeoFourProng.GetCovariance(2)) * dyQuadlet2PV * dyQuadlet2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoFourProng.GetCovariance(1)) * dxQuadlet2PV * dyQuadlet2PV); + values[kVertexingLzErr] = (KFPV.GetCovariance(5) + KFGeoFourProng.GetCovariance(5)) * dzQuadlet2PV * dzQuadlet2PV; + values[kVertexingLxyzErr] = (KFPV.GetCovariance(0) + KFGeoFourProng.GetCovariance(0)) * dxQuadlet2PV * dxQuadlet2PV + (KFPV.GetCovariance(2) + KFGeoFourProng.GetCovariance(2)) * dyQuadlet2PV * dyQuadlet2PV + (KFPV.GetCovariance(5) + KFGeoFourProng.GetCovariance(5)) * dzQuadlet2PV * dzQuadlet2PV + 2 * ((KFPV.GetCovariance(1) + KFGeoFourProng.GetCovariance(1)) * dxQuadlet2PV * dyQuadlet2PV + (KFPV.GetCovariance(3) + KFGeoFourProng.GetCovariance(3)) * dxQuadlet2PV * dzQuadlet2PV + (KFPV.GetCovariance(4) + KFGeoFourProng.GetCovariance(4)) * dyQuadlet2PV * dzQuadlet2PV); + + if (fabs(values[kVertexingLxy]) < 1.e-8f) + values[kVertexingLxy] = 1.e-8f; + values[kVertexingLxyErr] = values[kVertexingLxyErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLxyErr]) / values[kVertexingLxy]; + if (fabs(values[kVertexingLz]) < 1.e-8f) + values[kVertexingLz] = 1.e-8f; + values[kVertexingLzErr] = values[kVertexingLzErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLzErr]) / values[kVertexingLz]; + if (fabs(values[kVertexingLxyz]) < 1.e-8f) + values[kVertexingLxyz] = 1.e-8f; + values[kVertexingLxyzErr] = values[kVertexingLxyzErr] < 0. ? 1.e8f : std::sqrt(values[kVertexingLxyzErr]) / values[kVertexingLxyz]; + + values[kVertexingTauxy] = KFGeoFourProng.GetPseudoProperDecayTime(KFPV, KFGeoFourProng.GetMass()) / (o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauz] = -1 * dzQuadlet2PV * KFGeoFourProng.GetMass() / (TMath::Abs(KFGeoFourProng.GetPz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingPz] = TMath::Abs(KFGeoFourProng.GetPz()); + values[kVertexingSV] = KFGeoFourProng.GetZ(); + + values[kVertexingTauxyErr] = values[kVertexingLxyErr] * KFGeoFourProng.GetMass() / (KFGeoFourProng.GetPt() * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingTauzErr] = values[kVertexingLzErr] * KFGeoFourProng.GetMass() / (TMath::Abs(KFGeoFourProng.GetPz()) * o2::constants::physics::LightSpeedCm2NS); + values[kVertexingChi2PCA] = KFGeoFourProng.GetChi2(); + values[kCosPointingAngle] = (std::sqrt(dxQuadlet2PV * dxQuadlet2PV) * v1234.Px() + + std::sqrt(dyQuadlet2PV * dyQuadlet2PV) * v1234.Py() + + std::sqrt(dzQuadlet2PV * dzQuadlet2PV) * v1234.Pz()) / + (v1234.P() * values[VarManager::kVertexingLxyz]); + // // run 2 definitions: Decay length projected onto the momentum vector of the candidate + values[kVertexingLzProjected] = (dzQuadlet2PV * KFGeoFourProng.GetPz()) / TMath::Sqrt(KFGeoFourProng.GetPz() * KFGeoFourProng.GetPz()); + values[kVertexingLxyProjected] = (dxQuadlet2PV * KFGeoFourProng.GetPx()) + (dyQuadlet2PV * KFGeoFourProng.GetPy()); + values[kVertexingLxyProjected] = values[kVertexingLxyProjected] / TMath::Sqrt((KFGeoFourProng.GetPx() * KFGeoFourProng.GetPx()) + (KFGeoFourProng.GetPy() * KFGeoFourProng.GetPy())); + values[kVertexingLxyzProjected] = (dxQuadlet2PV * KFGeoFourProng.GetPx()) + (dyQuadlet2PV * KFGeoFourProng.GetPy()) + (dzQuadlet2PV * KFGeoFourProng.GetPz()); + values[kVertexingLxyzProjected] = values[kVertexingLxyzProjected] / TMath::Sqrt((KFGeoFourProng.GetPx() * KFGeoFourProng.GetPx()) + (KFGeoFourProng.GetPy() * KFGeoFourProng.GetPy()) + (KFGeoFourProng.GetPz() * KFGeoFourProng.GetPz())); + values[kVertexingTauxyProjected] = values[kVertexingLxyProjected] * KFGeoFourProng.GetMass() / (KFGeoFourProng.GetPt()); + values[kVertexingTauxyProjectedNs] = values[kVertexingTauxyProjected] / o2::constants::physics::LightSpeedCm2NS; + values[kVertexingTauzProjected] = values[kVertexingLzProjected] * KFGeoFourProng.GetMass() / TMath::Abs(KFGeoFourProng.GetPz()); + values[kKFChi2OverNDFGeo] = KFGeoFourProng.GetChi2() / KFGeoFourProng.GetNDF(); + } else { + return; + } +} + //__________________________________________________________________ template -void VarManager::FillQaudMC(T1 const& dilepton, T2 const& track1, T2 const& track2, float* values) +void VarManager::FillQuadMC(T1 const& dilepton, T2 const& track1, T2 const& track2, float* values) { if (!values) { values = fgValues; @@ -5230,4 +5531,24 @@ float VarManager::calculatePhiV(T1 const& t1, T2 const& t2) return pairPhiV; } +/// Fill BDT score values. +/// Supports binary (1 output) and multiclass (3 outputs) models. +template +void VarManager::FillBdtScore(T1 const& bdtScore, float* values) +{ + if (!values) { + values = fgValues; + } + + if (bdtScore.size() == 1) { + values[kBdtBackground] = bdtScore[0]; + } else if (bdtScore.size() == 3) { + values[kBdtBackground] = bdtScore[0]; + values[kBdtPrompt] = bdtScore[1]; + values[kBdtNonprompt] = bdtScore[2]; + } else { + LOG(warning) << "Unexpected number of BDT outputs: " << bdtScore.size(); + } +} + #endif // PWGDQ_CORE_VARMANAGER_H_ diff --git a/PWGDQ/DataModel/ReducedInfoTables.h b/PWGDQ/DataModel/ReducedInfoTables.h index dcf27f9ac9c..ae5fd853bf9 100644 --- a/PWGDQ/DataModel/ReducedInfoTables.h +++ b/PWGDQ/DataModel/ReducedInfoTables.h @@ -15,31 +15,33 @@ #ifndef PWGDQ_DATAMODEL_REDUCEDINFOTABLES_H_ #define PWGDQ_DATAMODEL_REDUCEDINFOTABLES_H_ -#include -#include -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGHF/Utils/utilsPid.h" + #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Qvectors.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" #include "MathUtils/Utils.h" -#include "PWGHF/Utils/utilsPid.h" +#include +#include namespace o2::aod { namespace dqppfilter { -DECLARE_SOA_COLUMN(EventFilter, eventFilter, uint64_t); //! Bit-field used for the high level event triggering +DECLARE_SOA_COLUMN(EventFilter, eventFilter, uint64_t); //! Bit-field used for the high level event triggering DECLARE_SOA_COLUMN(NewBcMultFT0A, newBcMultFT0A, float); //! sum of amplitudes on A side of FT0 DECLARE_SOA_COLUMN(NewBcMultFT0C, newBcMultFT0C, float); //! sum of amplitudes on C side of FT0 DECLARE_SOA_COLUMN(NewBcMultFDDA, newBcMultFDDA, float); //! sum of amplitudes on A side of FDD DECLARE_SOA_COLUMN(NewBcMultFDDC, newBcMultFDDC, float); //! sum of amplitudes on C side of FDD DECLARE_SOA_COLUMN(NewBcMultFV0A, newBcMultFV0A, float); //! sum of amplitudes on A side of FDD -} +} // namespace dqppfilter DECLARE_SOA_TABLE(DQEventFilter, "AOD", "EVENTFILTER", //! Store event-level decisions (DQ high level triggers) dqppfilter::EventFilter); @@ -64,11 +66,11 @@ 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_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) @@ -93,51 +95,51 @@ DECLARE_SOA_COLUMN(NTrkBPos, nTrkBPos, int); DECLARE_SOA_COLUMN(NTrkBNeg, nTrkBNeg, int); DECLARE_SOA_COLUMN(NTrkBAll, nTrkBAll, int); -DECLARE_SOA_COLUMN(Q1ZNAX, q1znax, float); //! Q-vector x component, evaluated with ZNA (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1ZNAY, q1znay, float); //! Q-vector y component, evaluated with ZNA (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1ZNCX, q1zncx, float); //! Q-vector x component, evaluated with ZNC (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1ZNCY, q1zncy, float); //! Q-vector y component, evaluated with ZNC (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1X0A, q1x0a, float); //! Q-vector x component, with event eta gap A (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1Y0A, q1y0a, float); //! Q-vector y component, with event eta gap A (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1X0B, q1x0b, float); //! Q-vector x component, with event eta gap B (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1Y0B, q1y0b, float); //! Q-vector y component, with event eta gap B (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1X0C, q1x0c, float); //! Q-vector x component, with event eta gap C (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q1Y0C, q1y0c, float); //! Q-vector y component, with event eta gap C (harmonic 1 and power 1) -DECLARE_SOA_COLUMN(Q2X0A, q2x0a, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2Y0A, q2y0a, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2X0B, q2x0b, float); //! Q-vector x component, with event eta gap B (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2Y0B, q2y0b, float); //! Q-vector y component, with event eta gap B (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2X0C, q2x0c, float); //! Q-vector x component, with event eta gap C (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(Q2Y0C, q2y0c, float); //! Q-vector y component, with event eta gap C (harmonic 2 and power 1) -DECLARE_SOA_COLUMN(MultA, multa, float); //! Event multiplicity eta gap A -DECLARE_SOA_COLUMN(MultB, multb, float); //! Event multiplicity eta gap B -DECLARE_SOA_COLUMN(MultC, multc, float); //! Event multiplicity eta gap C -DECLARE_SOA_COLUMN(Q3X0A, q3x0a, float); //! Q-vector x component, with event eta gap A (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3Y0A, q3y0a, float); //! Q-vector y component, with event eta gap A (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3X0B, q3x0b, float); //! Q-vector x component, with event eta gap B (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3Y0B, q3y0b, float); //! Q-vector y component, with event eta gap B (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3X0C, q3x0c, float); //! Q-vector x component, with event eta gap C (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q3Y0C, q3y0c, float); //! Q-vector y component, with event eta gap C (harmonic 3 and power 1) -DECLARE_SOA_COLUMN(Q4X0A, q4x0a, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4Y0A, q4y0a, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4X0B, q4x0b, float); //! Q-vector x component, with event eta gap B (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4Y0B, q4y0b, float); //! Q-vector y component, with event eta gap B (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4X0C, q4x0c, float); //! Q-vector x component, with event eta gap C (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q4Y0C, q4y0c, float); //! Q-vector y component, with event eta gap C (harmonic 4 and power 1) -DECLARE_SOA_COLUMN(Q42XA, q42xa, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 2) -DECLARE_SOA_COLUMN(Q42YA, q42ya, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 2) -DECLARE_SOA_COLUMN(Q23XA, q23xa, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 3) -DECLARE_SOA_COLUMN(Q23YA, q23ya, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 3) -DECLARE_SOA_COLUMN(S11A, s11a, float); //! Weighted multiplicity (p = 1, k = 1) -DECLARE_SOA_COLUMN(S12A, s12a, float); //! Weighted multiplicity (p = 1, k = 2) -DECLARE_SOA_COLUMN(S13A, s13a, float); //! Weighted multiplicity (p = 1, k = 3) -DECLARE_SOA_COLUMN(S31A, s31a, float); //! Weighted multiplicity (p = 3, k = 1) -DECLARE_SOA_COLUMN(CORR2REF, corr2ref, float); //! Ref Flow correlator <2> +DECLARE_SOA_COLUMN(Q1ZNAX, q1znax, float); //! Q-vector x component, evaluated with ZNA (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1ZNAY, q1znay, float); //! Q-vector y component, evaluated with ZNA (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1ZNCX, q1zncx, float); //! Q-vector x component, evaluated with ZNC (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1ZNCY, q1zncy, float); //! Q-vector y component, evaluated with ZNC (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1X0A, q1x0a, float); //! Q-vector x component, with event eta gap A (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1Y0A, q1y0a, float); //! Q-vector y component, with event eta gap A (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1X0B, q1x0b, float); //! Q-vector x component, with event eta gap B (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1Y0B, q1y0b, float); //! Q-vector y component, with event eta gap B (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1X0C, q1x0c, float); //! Q-vector x component, with event eta gap C (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q1Y0C, q1y0c, float); //! Q-vector y component, with event eta gap C (harmonic 1 and power 1) +DECLARE_SOA_COLUMN(Q2X0A, q2x0a, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2Y0A, q2y0a, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2X0B, q2x0b, float); //! Q-vector x component, with event eta gap B (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2Y0B, q2y0b, float); //! Q-vector y component, with event eta gap B (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2X0C, q2x0c, float); //! Q-vector x component, with event eta gap C (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(Q2Y0C, q2y0c, float); //! Q-vector y component, with event eta gap C (harmonic 2 and power 1) +DECLARE_SOA_COLUMN(MultA, multa, float); //! Event multiplicity eta gap A +DECLARE_SOA_COLUMN(MultB, multb, float); //! Event multiplicity eta gap B +DECLARE_SOA_COLUMN(MultC, multc, float); //! Event multiplicity eta gap C +DECLARE_SOA_COLUMN(Q3X0A, q3x0a, float); //! Q-vector x component, with event eta gap A (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3Y0A, q3y0a, float); //! Q-vector y component, with event eta gap A (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3X0B, q3x0b, float); //! Q-vector x component, with event eta gap B (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3Y0B, q3y0b, float); //! Q-vector y component, with event eta gap B (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3X0C, q3x0c, float); //! Q-vector x component, with event eta gap C (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q3Y0C, q3y0c, float); //! Q-vector y component, with event eta gap C (harmonic 3 and power 1) +DECLARE_SOA_COLUMN(Q4X0A, q4x0a, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4Y0A, q4y0a, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4X0B, q4x0b, float); //! Q-vector x component, with event eta gap B (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4Y0B, q4y0b, float); //! Q-vector y component, with event eta gap B (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4X0C, q4x0c, float); //! Q-vector x component, with event eta gap C (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q4Y0C, q4y0c, float); //! Q-vector y component, with event eta gap C (harmonic 4 and power 1) +DECLARE_SOA_COLUMN(Q42XA, q42xa, float); //! Q-vector x component, with event eta gap A (harmonic 4 and power 2) +DECLARE_SOA_COLUMN(Q42YA, q42ya, float); //! Q-vector y component, with event eta gap A (harmonic 4 and power 2) +DECLARE_SOA_COLUMN(Q23XA, q23xa, float); //! Q-vector x component, with event eta gap A (harmonic 2 and power 3) +DECLARE_SOA_COLUMN(Q23YA, q23ya, float); //! Q-vector y component, with event eta gap A (harmonic 2 and power 3) +DECLARE_SOA_COLUMN(S11A, s11a, float); //! Weighted multiplicity (p = 1, k = 1) +DECLARE_SOA_COLUMN(S12A, s12a, float); //! Weighted multiplicity (p = 1, k = 2) +DECLARE_SOA_COLUMN(S13A, s13a, float); //! Weighted multiplicity (p = 1, k = 3) +DECLARE_SOA_COLUMN(S31A, s31a, float); //! Weighted multiplicity (p = 3, k = 1) +DECLARE_SOA_COLUMN(CORR2REF, corr2ref, float); //! Ref Flow correlator <2> DECLARE_SOA_COLUMN(CORR2REFetagap, corr2refetagap, float); //! Ref Flow correlator <2> -DECLARE_SOA_COLUMN(CORR4REF, corr4ref, float); //! Ref Flow correlator <4> -DECLARE_SOA_COLUMN(M11REF, m11ref, float); //! Weighted multiplicity of <<2>> for reference flow -DECLARE_SOA_COLUMN(M1111REF, m1111ref, float); //! Weighted multiplicity of <<4>> for reference flow -DECLARE_SOA_COLUMN(M11REFetagap, m11refetagap, float); //! Weighted multiplicity of <<2>> etagap for reference flow +DECLARE_SOA_COLUMN(CORR4REF, corr4ref, float); //! Ref Flow correlator <4> +DECLARE_SOA_COLUMN(M11REF, m11ref, float); //! Weighted multiplicity of <<2>> for reference flow +DECLARE_SOA_COLUMN(M1111REF, m1111ref, float); //! Weighted multiplicity of <<4>> for reference flow +DECLARE_SOA_COLUMN(M11REFetagap, m11refetagap, float); //! Weighted multiplicity of <<2>> etagap for reference flow } // namespace reducedevent DECLARE_SOA_TABLE_STAGED(ReducedEvents, "REDUCEDEVENT", //! Main event information table @@ -146,12 +148,20 @@ DECLARE_SOA_TABLE_STAGED(ReducedEvents, "REDUCEDEVENT", //! Main event informa collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, collision::CollisionTime, collision::CollisionTimeRes); -DECLARE_SOA_TABLE(ReducedEventsExtended, "AOD", "REEXTENDED", //! Extended event information +DECLARE_SOA_TABLE(ReducedEventsExtended_000, "AOD", "REEXTENDED", //! Extended event information bc::GlobalBC, evsel::Alias, evsel::Selection, timestamp::Timestamp, cent::CentRun2V0M, mult::MultTPC, mult::MultFV0A, mult::MultFV0C, mult::MultFT0A, mult::MultFT0C, mult::MultFDDA, mult::MultFDDC, mult::MultZNA, mult::MultZNC, mult::MultTracklets, mult::MultNTracksPV, cent::CentFT0C); +DECLARE_SOA_TABLE_VERSIONED(ReducedEventsExtended_001, "AOD", "REEXTENDED", 1, //! Extended event information + bc::GlobalBC, evsel::Alias, evsel::Selection, timestamp::Timestamp, cent::CentRun2V0M, + mult::MultTPC, mult::MultFV0A, mult::MultFV0C, mult::MultFT0A, mult::MultFT0C, + mult::MultFDDA, mult::MultFDDC, mult::MultZNA, mult::MultZNC, mult::MultTracklets, mult::MultNTracksPV, + cent::CentFT0C, cent::CentFT0A, cent::CentFT0M); + +using ReducedEventsExtended = ReducedEventsExtended_001; + DECLARE_SOA_TABLE(ReducedEventsMultPV_000, "AOD", "REMULTPV", //! Multiplicity information for primary vertex mult::MultNTracksHasITS, mult::MultNTracksHasTPC, mult::MultNTracksHasTOF, mult::MultNTracksHasTRD, mult::MultNTracksITSOnly, mult::MultNTracksTPCOnly, mult::MultNTracksITSTPC, @@ -614,42 +624,42 @@ DECLARE_SOA_COLUMN(Vt2, vt2, float); //! Production vertex time DECLARE_SOA_COLUMN(IsAmbig1, isAmbig1, int); //! DECLARE_SOA_COLUMN(IsAmbig2, isAmbig2, int); //! -DECLARE_SOA_COLUMN(FwdDcaX1, fwdDcaX1, float); //! X component of forward DCA -DECLARE_SOA_COLUMN(FwdDcaY1, fwdDcaY1, float); //! Y component of forward DCA -DECLARE_SOA_COLUMN(FwdDcaX2, fwdDcaX2, float); //! X component of forward DCA -DECLARE_SOA_COLUMN(FwdDcaY2, fwdDcaY2, float); //! Y component of forward DCA -DECLARE_SOA_COLUMN(ITSNCls1, itsNCls1, int); //! Number of ITS clusters +DECLARE_SOA_COLUMN(FwdDcaX1, fwdDcaX1, float); //! X component of forward DCA +DECLARE_SOA_COLUMN(FwdDcaY1, fwdDcaY1, float); //! Y component of forward DCA +DECLARE_SOA_COLUMN(FwdDcaX2, fwdDcaX2, float); //! X component of forward DCA +DECLARE_SOA_COLUMN(FwdDcaY2, fwdDcaY2, float); //! Y component of forward DCA +DECLARE_SOA_COLUMN(ITSNCls1, itsNCls1, int); //! Number of ITS clusters DECLARE_SOA_COLUMN(ITSClusterMap1, itsClusterMap1, uint8_t); //! ITS clusters map DECLARE_SOA_COLUMN(ITSChi2NCl1, itsChi2NCl1, float); //! ITS chi2/Ncls -DECLARE_SOA_COLUMN(TPCNClsFound1, tpcNClsFound1, float); //! Number of TPC clusters found -DECLARE_SOA_COLUMN(TPCNClsCR1, tpcNClsCR1, float); //! Number of TPC crossed rows -DECLARE_SOA_COLUMN(TPCChi2NCl1, tpcChi2NCl1, float); //! TPC chi2/Ncls -DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); //! DCA in XY plane -DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); //! DCA in Z -DECLARE_SOA_COLUMN(TPCSignal1, tpcSignal1, float); //! TPC dE/dx signal -DECLARE_SOA_COLUMN(TPCNSigmaEl1, tpcNSigmaEl1, float); //! TPC nSigma electron -DECLARE_SOA_COLUMN(TPCNSigmaPi1, tpcNSigmaPi1, float); //! TPC nSigma pion -DECLARE_SOA_COLUMN(TPCNSigmaPr1, tpcNSigmaPr1, float); //! TPC nSigma proton -DECLARE_SOA_COLUMN(TOFBeta1, tofBeta1, float); //! TOF beta -DECLARE_SOA_COLUMN(TOFNSigmaEl1, tofNSigmaEl1, float); //! TOF nSigma electron -DECLARE_SOA_COLUMN(TOFNSigmaPi1, tofNSigmaPi1, float); //! TOF nSigma pion -DECLARE_SOA_COLUMN(TOFNSigmaPr1, tofNSigmaPr1, float); //! TOF nSigma proton -DECLARE_SOA_COLUMN(ITSNCls2, itsNCls2, int); //! Number of ITS clusters +DECLARE_SOA_COLUMN(TPCNClsFound1, tpcNClsFound1, float); //! Number of TPC clusters found +DECLARE_SOA_COLUMN(TPCNClsCR1, tpcNClsCR1, float); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(TPCChi2NCl1, tpcChi2NCl1, float); //! TPC chi2/Ncls +DECLARE_SOA_COLUMN(DcaXY1, dcaXY1, float); //! DCA in XY plane +DECLARE_SOA_COLUMN(DcaZ1, dcaZ1, float); //! DCA in Z +DECLARE_SOA_COLUMN(TPCSignal1, tpcSignal1, float); //! TPC dE/dx signal +DECLARE_SOA_COLUMN(TPCNSigmaEl1, tpcNSigmaEl1, float); //! TPC nSigma electron +DECLARE_SOA_COLUMN(TPCNSigmaPi1, tpcNSigmaPi1, float); //! TPC nSigma pion +DECLARE_SOA_COLUMN(TPCNSigmaPr1, tpcNSigmaPr1, float); //! TPC nSigma proton +DECLARE_SOA_COLUMN(TOFBeta1, tofBeta1, float); //! TOF beta +DECLARE_SOA_COLUMN(TOFNSigmaEl1, tofNSigmaEl1, float); //! TOF nSigma electron +DECLARE_SOA_COLUMN(TOFNSigmaPi1, tofNSigmaPi1, float); //! TOF nSigma pion +DECLARE_SOA_COLUMN(TOFNSigmaPr1, tofNSigmaPr1, float); //! TOF nSigma proton +DECLARE_SOA_COLUMN(ITSNCls2, itsNCls2, int); //! Number of ITS clusters DECLARE_SOA_COLUMN(ITSClusterMap2, itsClusterMap2, uint8_t); //! ITS clusters map DECLARE_SOA_COLUMN(ITSChi2NCl2, itsChi2NCl2, float); //! ITS chi2/Ncls -DECLARE_SOA_COLUMN(TPCNClsFound2, tpcNClsFound2, float); //! Number of TPC clusters found -DECLARE_SOA_COLUMN(TPCNClsCR2, tpcNClsCR2, float); //! Number of TPC crossed rows -DECLARE_SOA_COLUMN(TPCChi2NCl2, tpcChi2NCl2, float); //! TPC chi2/Ncls -DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); //! DCA in XY plane -DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); //! DCA in Z -DECLARE_SOA_COLUMN(TPCSignal2, tpcSignal2, float); //! TPC dE/dx signal -DECLARE_SOA_COLUMN(TPCNSigmaEl2, tpcNSigmaEl2, float); //! TPC nSigma electron -DECLARE_SOA_COLUMN(TPCNSigmaPi2, tpcNSigmaPi2, float); //! TPC nSigma pion -DECLARE_SOA_COLUMN(TPCNSigmaPr2, tpcNSigmaPr2, float); //! TPC nSigma proton -DECLARE_SOA_COLUMN(TOFBeta2, tofBeta2, float); //! TOF beta -DECLARE_SOA_COLUMN(TOFNSigmaEl2, tofNSigmaEl2, float); //! TOF nSigma electron -DECLARE_SOA_COLUMN(TOFNSigmaPi2, tofNSigmaPi2, float); //! TOF nSigma pion -DECLARE_SOA_COLUMN(TOFNSigmaPr2, tofNSigmaPr2, float); //! TOF nSigma proton +DECLARE_SOA_COLUMN(TPCNClsFound2, tpcNClsFound2, float); //! Number of TPC clusters found +DECLARE_SOA_COLUMN(TPCNClsCR2, tpcNClsCR2, float); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(TPCChi2NCl2, tpcChi2NCl2, float); //! TPC chi2/Ncls +DECLARE_SOA_COLUMN(DcaXY2, dcaXY2, float); //! DCA in XY plane +DECLARE_SOA_COLUMN(DcaZ2, dcaZ2, float); //! DCA in Z +DECLARE_SOA_COLUMN(TPCSignal2, tpcSignal2, float); //! TPC dE/dx signal +DECLARE_SOA_COLUMN(TPCNSigmaEl2, tpcNSigmaEl2, float); //! TPC nSigma electron +DECLARE_SOA_COLUMN(TPCNSigmaPi2, tpcNSigmaPi2, float); //! TPC nSigma pion +DECLARE_SOA_COLUMN(TPCNSigmaPr2, tpcNSigmaPr2, float); //! TPC nSigma proton +DECLARE_SOA_COLUMN(TOFBeta2, tofBeta2, float); //! TOF beta +DECLARE_SOA_COLUMN(TOFNSigmaEl2, tofNSigmaEl2, float); //! TOF nSigma electron +DECLARE_SOA_COLUMN(TOFNSigmaPi2, tofNSigmaPi2, float); //! TOF nSigma pion +DECLARE_SOA_COLUMN(TOFNSigmaPr2, tofNSigmaPr2, float); //! TOF nSigma proton DECLARE_SOA_COLUMN(DCAxyzTrk0KF, dcaxyztrk0KF, float); //! 3D DCA to primary vertex of the first track DECLARE_SOA_COLUMN(DCAxyzTrk1KF, dcaxyztrk1KF, float); //! 3D DCA to primary vertex of the second track @@ -665,58 +675,58 @@ DECLARE_SOA_COLUMN(DeviationxyTrk1KF, deviationxyTrk1KF, float); //! 2D chi2 dev // pair information namespace reducedpair { -DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); //! -DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, ReducedTracks, "_0"); //! Index to first prong -DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, ReducedTracks, "_1"); //! Index to second prong -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, Tracks, "_0"); //! Index of first prong in Tracks table -DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, Tracks, "_1"); //! Index of second prong in Tracks table -DECLARE_SOA_BITMAP_COLUMN(EventSelection, evSelection, 8); //! Event selection bits (ambiguity, splitting candidate) -DECLARE_SOA_COLUMN(Mass, mass, float); //! -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_BITMAP_COLUMN(FilterMap, filterMap, 32); //! -DECLARE_SOA_BITMAP_COLUMN(PairFilterMap, pairFilterMap, 32); //! -DECLARE_SOA_BITMAP_COLUMN(CommonFilterMap, commonFilterMap, 32); //! -DECLARE_SOA_COLUMN(McDecision, mcDecision, uint32_t); //! -DECLARE_SOA_COLUMN(Tauz, tauz, float); //! Longitudinal pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(TauzErr, tauzErr, float); //! Error on longitudinal pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(VertexPz, vertexPz, float); //! Longitudinal projection of impulsion -DECLARE_SOA_COLUMN(SVertex, sVertex, float); //! Secondary vertex of lepton pair -DECLARE_SOA_COLUMN(Tauxy, tauxy, float); //! Transverse pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(TauxyErr, tauxyErr, float); //! Error on transverse pseudo-proper time of lepton pair (in ns) -DECLARE_SOA_COLUMN(Lz, lz, float); //! Longitudinal projection of decay length -DECLARE_SOA_COLUMN(Lxy, lxy, float); //! Transverse projection of decay length -DECLARE_SOA_COLUMN(Chi2pca, chi2pca, float); //! Chi2 for PCA of the dilepton -DECLARE_SOA_COLUMN(CosPointingAngle, cosPointingAngle, float); //! Cosine of the pointing angle -DECLARE_SOA_COLUMN(U2Q2, u2q2, float); //! Scalar product between unitary vector with event flow vector (harmonic 2) -DECLARE_SOA_COLUMN(U3Q3, u3q3, float); //! Scalar product between unitary vector with event flow vector (harmonic 3) -DECLARE_SOA_COLUMN(Cos2DeltaPhi, cos2deltaphi, float); //! Cosinus term using event plane angle (harmonic 2) -DECLARE_SOA_COLUMN(Cos3DeltaPhi, cos3deltaphi, float); //! Cosinus term using event plane angle (harmonic 3) -DECLARE_SOA_COLUMN(R2SP_AB, r2spab, float); //! Event plane resolution for SP method n=2 (A,B) TPC-FT0A -DECLARE_SOA_COLUMN(R2SP_AC, r2spac, float); //! Event plane resolution for SP method n=2 (A,C) TPC-FT0C -DECLARE_SOA_COLUMN(R2SP_BC, r2spbc, float); //! Event plane resolution for SP method n=2 (B,C) FT0A-FT0C -DECLARE_SOA_COLUMN(R3SP, r3sp, float); //! Event plane resolution for SP method n=3 -DECLARE_SOA_COLUMN(R2EP, r2ep, float); //! Event plane resolution for EP method n=2 -DECLARE_SOA_COLUMN(R2EP_AB, r2epab, float); //! Event plane resolution for EP method n=2 (A,B) TPC-FT0A -DECLARE_SOA_COLUMN(R2EP_AC, r2epac, float); //! Event plane resolution for EP method n=2 (A,C) TPC-FT0C -DECLARE_SOA_COLUMN(R2EP_BC, r2epbc, float); //! Event plane resolution for EP method n=2 (B,C) FT0A-FT0C -DECLARE_SOA_COLUMN(R3EP, r3ep, float); //! Event plane resolution for EP method n=3 -DECLARE_SOA_COLUMN(CORR2POI, corr2poi, float); //! POI FLOW CORRELATOR <2'> -DECLARE_SOA_COLUMN(CORR4POI, corr4poi, float); //! POI FLOW CORRELATOR <4'> -DECLARE_SOA_COLUMN(M01POI, m01poi, float); //! POI event weight for <2'> -DECLARE_SOA_COLUMN(M0111POI, m0111poi, float); //! POI event weight for <4'> -DECLARE_SOA_COLUMN(MultDimuons, multdimuons, int); //! Dimuon multiplicity -DECLARE_SOA_COLUMN(CentFT0C, centft0c, float); //! Centrality information from FT0C -DECLARE_SOA_COLUMN(CollisionId, collisionId, int32_t); //! -DECLARE_SOA_COLUMN(IsFirst, isfirst, int); //! Flag for the first dilepton in the collision -DECLARE_SOA_COLUMN(DCAxyzBetweenTrksKF, dcaxyzbetweentrksKF, float); //! DCAxyz between the two tracks -DECLARE_SOA_COLUMN(DCAxyBetweenTrksKF, dcaxybetweentrksKF, float); //! DCAxy between the two tracks -DECLARE_SOA_COLUMN(MassKFGeo, massKFGeo, float); //! Pair mass from KFParticle -DECLARE_SOA_COLUMN(CosPAKFGeo, cosPAKFGeo, float); //! Cosine of the pointing angle from KFParticle -DECLARE_SOA_COLUMN(Chi2OverNDFKFGeo, chi2overndfKFGeo, float); //! Chi2 over NDF from KFParticle -DECLARE_SOA_COLUMN(DecayLengthKFGeo, decaylengthKFGeo, float); //! Decay length from KFParticle +DECLARE_SOA_INDEX_COLUMN(ReducedEvent, reducedevent); //! +DECLARE_SOA_INDEX_COLUMN_FULL(Index0, index0, int, ReducedTracks, "_0"); //! Index to first prong +DECLARE_SOA_INDEX_COLUMN_FULL(Index1, index1, int, ReducedTracks, "_1"); //! Index to second prong +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, Tracks, "_0"); //! Index of first prong in Tracks table +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, Tracks, "_1"); //! Index of second prong in Tracks table +DECLARE_SOA_BITMAP_COLUMN(EventSelection, evSelection, 8); //! Event selection bits (ambiguity, splitting candidate) +DECLARE_SOA_COLUMN(Mass, mass, float); //! +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_BITMAP_COLUMN(FilterMap, filterMap, 32); //! +DECLARE_SOA_BITMAP_COLUMN(PairFilterMap, pairFilterMap, 32); //! +DECLARE_SOA_BITMAP_COLUMN(CommonFilterMap, commonFilterMap, 32); //! +DECLARE_SOA_COLUMN(McDecision, mcDecision, uint32_t); //! +DECLARE_SOA_COLUMN(Tauz, tauz, float); //! Longitudinal pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(TauzErr, tauzErr, float); //! Error on longitudinal pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(VertexPz, vertexPz, float); //! Longitudinal projection of impulsion +DECLARE_SOA_COLUMN(SVertex, sVertex, float); //! Secondary vertex of lepton pair +DECLARE_SOA_COLUMN(Tauxy, tauxy, float); //! Transverse pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(TauxyErr, tauxyErr, float); //! Error on transverse pseudo-proper time of lepton pair (in ns) +DECLARE_SOA_COLUMN(Lz, lz, float); //! Longitudinal projection of decay length +DECLARE_SOA_COLUMN(Lxy, lxy, float); //! Transverse projection of decay length +DECLARE_SOA_COLUMN(Chi2pca, chi2pca, float); //! Chi2 for PCA of the dilepton +DECLARE_SOA_COLUMN(CosPointingAngle, cosPointingAngle, float); //! Cosine of the pointing angle +DECLARE_SOA_COLUMN(U2Q2, u2q2, float); //! Scalar product between unitary vector with event flow vector (harmonic 2) +DECLARE_SOA_COLUMN(U3Q3, u3q3, float); //! Scalar product between unitary vector with event flow vector (harmonic 3) +DECLARE_SOA_COLUMN(Cos2DeltaPhi, cos2deltaphi, float); //! Cosinus term using event plane angle (harmonic 2) +DECLARE_SOA_COLUMN(Cos3DeltaPhi, cos3deltaphi, float); //! Cosinus term using event plane angle (harmonic 3) +DECLARE_SOA_COLUMN(R2SP_AB, r2spab, float); //! Event plane resolution for SP method n=2 (A,B) TPC-FT0A +DECLARE_SOA_COLUMN(R2SP_AC, r2spac, float); //! Event plane resolution for SP method n=2 (A,C) TPC-FT0C +DECLARE_SOA_COLUMN(R2SP_BC, r2spbc, float); //! Event plane resolution for SP method n=2 (B,C) FT0A-FT0C +DECLARE_SOA_COLUMN(R3SP, r3sp, float); //! Event plane resolution for SP method n=3 +DECLARE_SOA_COLUMN(R2EP, r2ep, float); //! Event plane resolution for EP method n=2 +DECLARE_SOA_COLUMN(R2EP_AB, r2epab, float); //! Event plane resolution for EP method n=2 (A,B) TPC-FT0A +DECLARE_SOA_COLUMN(R2EP_AC, r2epac, float); //! Event plane resolution for EP method n=2 (A,C) TPC-FT0C +DECLARE_SOA_COLUMN(R2EP_BC, r2epbc, float); //! Event plane resolution for EP method n=2 (B,C) FT0A-FT0C +DECLARE_SOA_COLUMN(R3EP, r3ep, float); //! Event plane resolution for EP method n=3 +DECLARE_SOA_COLUMN(CORR2POI, corr2poi, float); //! POI FLOW CORRELATOR <2'> +DECLARE_SOA_COLUMN(CORR4POI, corr4poi, float); //! POI FLOW CORRELATOR <4'> +DECLARE_SOA_COLUMN(M01POI, m01poi, float); //! POI event weight for <2'> +DECLARE_SOA_COLUMN(M0111POI, m0111poi, float); //! POI event weight for <4'> +DECLARE_SOA_COLUMN(MultDimuons, multdimuons, int); //! Dimuon multiplicity +DECLARE_SOA_COLUMN(CentFT0C, centft0c, float); //! Centrality information from FT0C +DECLARE_SOA_COLUMN(CollisionId, collisionId, int32_t); //! +DECLARE_SOA_COLUMN(IsFirst, isfirst, int); //! Flag for the first dilepton in the collision +DECLARE_SOA_COLUMN(DCAxyzBetweenTrksKF, dcaxyzbetweentrksKF, float); //! DCAxyz between the two tracks +DECLARE_SOA_COLUMN(DCAxyBetweenTrksKF, dcaxybetweentrksKF, float); //! DCAxy between the two tracks +DECLARE_SOA_COLUMN(MassKFGeo, massKFGeo, float); //! Pair mass from KFParticle +DECLARE_SOA_COLUMN(CosPAKFGeo, cosPAKFGeo, float); //! Cosine of the pointing angle from KFParticle +DECLARE_SOA_COLUMN(Chi2OverNDFKFGeo, chi2overndfKFGeo, float); //! Chi2 over NDF from KFParticle +DECLARE_SOA_COLUMN(DecayLengthKFGeo, decaylengthKFGeo, float); //! Decay length from KFParticle DECLARE_SOA_COLUMN(DecayLengthOverErrKFGeo, decaylengthovererrKFGeo, float); //! Decay length over error from KFParticle DECLARE_SOA_COLUMN(DecayLengthXYKFGeo, decaylengthxyKFGeo, float); //! Decay length XY from KFParticle DECLARE_SOA_COLUMN(DecayLengthXYOverErrKFGeo, decaylengthxyovererrKFGeo, float); //! Decay length XY over error from KFParticle @@ -729,6 +739,19 @@ DECLARE_SOA_COLUMN(PairDCAxy, pairDCAxy, float); DECLARE_SOA_COLUMN(DeviationPairKF, deviationPairKF, float); //! Pair chi2 deviation to PV from KFParticle DECLARE_SOA_COLUMN(DeviationxyPairKF, deviationxyPairKF, float); //! Pair chi2 deviation to PV in XY from KFParticle // DECLARE_SOA_INDEX_COLUMN(ReducedMuon, reducedmuon2); //! +DECLARE_SOA_COLUMN(CosThetaHE, costhetaHE, float); //! Cosine in the helicity frame +DECLARE_SOA_COLUMN(PhiHE, phiHe, float); //! Phi in the helicity frame +DECLARE_SOA_COLUMN(PhiTildeHE, phiTildeHe, float); //! Tilde Phi in the helicity frame +DECLARE_SOA_COLUMN(CosThetaCS, costhetaCS, float); //! Cosine in the Collins-Soper frame +DECLARE_SOA_COLUMN(PhiCS, phiCS, float); //! Phi in the Collins-Soper frame +DECLARE_SOA_COLUMN(PhiTildeCS, phiTildeCS, float); //! Tilde Phi in the Collins-Soper frame +DECLARE_SOA_COLUMN(CosThetaPP, costhetaPP, float); //! Cosine in the Production Plane frame +DECLARE_SOA_COLUMN(PhiPP, phiPP, float); //! Phi in the Production Plane frame +DECLARE_SOA_COLUMN(PhiTildePP, phiTildePP, float); //! Tilde Phi in the Production Plane frame +DECLARE_SOA_COLUMN(CosThetaRM, costhetaRM, float); //! Cosine in the Random frame +DECLARE_SOA_COLUMN(CosThetaStarTPC, costhetaStarTPC, float); //! global polarization, event plane reconstructed from TPC tracks +DECLARE_SOA_COLUMN(CosThetaStarFT0A, costhetaStarFT0A, float); //! global polarization, event plane reconstructed from FT0A tracks +DECLARE_SOA_COLUMN(CosThetaStarFT0C, costhetaStarFT0C, float); //! global polarization, event plane reconstructed from FT0C tracks DECLARE_SOA_DYNAMIC_COLUMN(Px, px, //! [](float pt, float phi) -> float { return pt * std::cos(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, //! @@ -865,6 +888,13 @@ DECLARE_SOA_TABLE(DileptonsMiniTreeRec, "AOD", "RTDILMTREEREC", //! dilepton_track_index::Pt1, dilepton_track_index::Eta1, dilepton_track_index::Phi1, dilepton_track_index::Pt2, dilepton_track_index::Eta2, dilepton_track_index::Phi2); +DECLARE_SOA_TABLE(DileptonsPolarization, "AOD", "RTDILPOLAR", //! + reducedpair::CosThetaHE, reducedpair::PhiHE, reducedpair::PhiTildeHE, + reducedpair::CosThetaCS, reducedpair::PhiCS, reducedpair::PhiTildeCS, + reducedpair::CosThetaPP, reducedpair::PhiPP, reducedpair::PhiTildePP, + reducedpair::CosThetaRM, + reducedpair::CosThetaStarTPC, reducedpair::CosThetaStarFT0A, reducedpair::CosThetaStarFT0C); + using Dielectron = Dielectrons::iterator; using StoredDielectron = StoredDielectrons::iterator; using Dimuon = Dimuons::iterator; @@ -878,6 +908,7 @@ using DimuonAll = DimuonsAll::iterator; using DileptonMiniTree = DileptonsMiniTree::iterator; using DileptonMiniTreeGen = DileptonsMiniTreeGen::iterator; using DileptonMiniTreeRec = DileptonsMiniTreeRec::iterator; +using DileptonPolarization = DileptonsPolarization::iterator; // Tables for using analysis-dilepton-track with analysis-asymmetric-pairing DECLARE_SOA_TABLE(Ditracks, "AOD", "RTDITRACK", //! @@ -946,30 +977,65 @@ using DileptonTrackCandidate = DileptonTrackCandidates::iterator; namespace dileptonTrackTrackCandidate { // infotmation about the dilepton-track-track -DECLARE_SOA_COLUMN(Mass, mass, 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(DeltaQ, deltaQ, float); //! -DECLARE_SOA_COLUMN(R1, r1, float); //! distance between the dilepton and the track1 in theta-phi plane -DECLARE_SOA_COLUMN(R2, r2, float); //! distance between the dilepton and the track2 in theta-phi plane -DECLARE_SOA_COLUMN(R, r, float); //! -DECLARE_SOA_COLUMN(DileptonMass, dileptonMass, float); //! -DECLARE_SOA_COLUMN(DileptonPt, dileptonPt, float); //! -DECLARE_SOA_COLUMN(DileptonEta, dileptonEta, float); //! -DECLARE_SOA_COLUMN(DileptonPhi, dileptonPhi, float); //! -DECLARE_SOA_COLUMN(DileptonSign, dileptonSign, int); //! -DECLARE_SOA_COLUMN(DiTracksMass, diTracksMass, float); //! -DECLARE_SOA_COLUMN(DiTracksPt, diTracksPt, float); //! -DECLARE_SOA_COLUMN(TrackPt1, trackPt1, float); //! -DECLARE_SOA_COLUMN(TrackPt2, trackPt2, float); //! -DECLARE_SOA_COLUMN(TrackEta1, trackEta1, float); //! -DECLARE_SOA_COLUMN(TrackEta2, trackEta2, float); //! -DECLARE_SOA_COLUMN(TrackPhi1, trackPhi1, float); //! -DECLARE_SOA_COLUMN(TrackPhi2, trackPhi2, float); //! -DECLARE_SOA_COLUMN(TrackSign1, trackSign1, int); //! -DECLARE_SOA_COLUMN(TrackSign2, trackSign2, int); //! +DECLARE_SOA_COLUMN(Mass, mass, 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(DeltaQ, deltaQ, float); //! +DECLARE_SOA_COLUMN(R1, r1, float); //! distance between the dilepton and the track1 in theta-phi plane +DECLARE_SOA_COLUMN(R2, r2, float); //! distance between the dilepton and the track2 in theta-phi plane +DECLARE_SOA_COLUMN(R, r, float); //! +DECLARE_SOA_COLUMN(DileptonMass, dileptonMass, float); //! +DECLARE_SOA_COLUMN(DileptonPt, dileptonPt, float); //! +DECLARE_SOA_COLUMN(DileptonEta, dileptonEta, float); //! +DECLARE_SOA_COLUMN(DileptonPhi, dileptonPhi, float); //! +DECLARE_SOA_COLUMN(DileptonSign, dileptonSign, int); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaEl1, dileptonTPCnSigmaEl1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPi1, dileptonTPCnSigmaPi1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPr1, dileptonTPCnSigmaPr1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnCls1, dileptonTPCnCls1, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaEl2, dileptonTPCnSigmaEl2, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPi2, dileptonTPCnSigmaPi2, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnSigmaPr2, dileptonTPCnSigmaPr2, float); //! +DECLARE_SOA_COLUMN(DileptonTPCnCls2, dileptonTPCnCls2, float); //! +DECLARE_SOA_COLUMN(DiTracksMass, diTracksMass, float); //! +DECLARE_SOA_COLUMN(DiTracksPt, diTracksPt, float); //! +DECLARE_SOA_COLUMN(TrackPt1, trackPt1, float); //! +DECLARE_SOA_COLUMN(TrackPt2, trackPt2, float); //! +DECLARE_SOA_COLUMN(TrackEta1, trackEta1, float); //! +DECLARE_SOA_COLUMN(TrackEta2, trackEta2, float); //! +DECLARE_SOA_COLUMN(TrackPhi1, trackPhi1, float); //! +DECLARE_SOA_COLUMN(TrackPhi2, trackPhi2, float); //! +DECLARE_SOA_COLUMN(TrackSign1, trackSign1, int); //! +DECLARE_SOA_COLUMN(TrackSign2, trackSign2, int); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPi1, trackTPCNSigmaPi1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPi2, trackTPCNSigmaPi2, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaKa1, trackTPCNSigmaKa1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaKa2, trackTPCNSigmaKa2, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPr1, trackTPCNSigmaPr1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNSigmaPr2, trackTPCNSigmaPr2, float); //! +DECLARE_SOA_COLUMN(TrackTPCNCls1, trackTPCNCls1, float); //! +DECLARE_SOA_COLUMN(TrackTPCNCls2, trackTPCNCls2, float); //! +DECLARE_SOA_COLUMN(KFMass, kfMass, float); //! +DECLARE_SOA_COLUMN(VertexingProcCode, vertexingProcCode, float); //! +DECLARE_SOA_COLUMN(VertexingChi2PCA, vertexingChi2PCA, float); //! +DECLARE_SOA_COLUMN(CosPointingAngle, cosPointingAngle, float); //! +DECLARE_SOA_COLUMN(KFDCAxyzBetweenProngs, kfDCAxyzBetweenProngs, float); //! +DECLARE_SOA_COLUMN(KFChi2OverNDFGeo, kfChi2OverNDFGeo, float); //! +DECLARE_SOA_COLUMN(VertexingLz, vertexingLz, float); //! +DECLARE_SOA_COLUMN(VertexingLxy, vertexingLxy, float); //! +DECLARE_SOA_COLUMN(VertexingLxyz, vertexingLxyz, float); //! +DECLARE_SOA_COLUMN(VertexingTauz, vertexingTauz, float); //! +DECLARE_SOA_COLUMN(VertexingTauxy, vertexingTauxy, float); //! +DECLARE_SOA_COLUMN(VertexingLzErr, vertexingLzErr, float); //! +DECLARE_SOA_COLUMN(VertexingLxyzErr, vertexingLxyzErr, float); //! +DECLARE_SOA_COLUMN(VertexingTauzErr, vertexingTauzErr, float); //! +DECLARE_SOA_COLUMN(VertexingLzProjected, vertexingLzProjected, float); //! +DECLARE_SOA_COLUMN(VertexingLxyProjected, vertexingLxyProjected, float); //! +DECLARE_SOA_COLUMN(VertexingLxyzProjected, vertexingLxyzProjected, float); //! +DECLARE_SOA_COLUMN(VertexingTauzProjected, vertexingTauzProjected, float); //! +DECLARE_SOA_COLUMN(VertexingTauxyProjected, vertexingTauxyProjected, float); //! } // namespace dileptonTrackTrackCandidate DECLARE_SOA_TABLE(DileptonTrackTrackCandidates, "AOD", "RTDQUADPLET", //! @@ -987,6 +1053,14 @@ DECLARE_SOA_TABLE(DileptonTrackTrackCandidates, "AOD", "RTDQUADPLET", //! dileptonTrackTrackCandidate::DileptonEta, dileptonTrackTrackCandidate::DileptonPhi, dileptonTrackTrackCandidate::DileptonSign, + dileptonTrackTrackCandidate::DileptonTPCnSigmaEl1, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPi1, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPr1, + dileptonTrackTrackCandidate::DileptonTPCnCls1, + dileptonTrackTrackCandidate::DileptonTPCnSigmaEl2, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPi2, + dileptonTrackTrackCandidate::DileptonTPCnSigmaPr2, + dileptonTrackTrackCandidate::DileptonTPCnCls2, dileptonTrackTrackCandidate::DiTracksMass, dileptonTrackTrackCandidate::DiTracksPt, dileptonTrackTrackCandidate::TrackPt1, @@ -996,7 +1070,34 @@ DECLARE_SOA_TABLE(DileptonTrackTrackCandidates, "AOD", "RTDQUADPLET", //! dileptonTrackTrackCandidate::TrackPhi1, dileptonTrackTrackCandidate::TrackPhi2, dileptonTrackTrackCandidate::TrackSign1, - dileptonTrackTrackCandidate::TrackSign2); + dileptonTrackTrackCandidate::TrackSign2, + dileptonTrackTrackCandidate::TrackTPCNSigmaPi1, + dileptonTrackTrackCandidate::TrackTPCNSigmaPi2, + dileptonTrackTrackCandidate::TrackTPCNSigmaKa1, + dileptonTrackTrackCandidate::TrackTPCNSigmaKa2, + dileptonTrackTrackCandidate::TrackTPCNSigmaPr1, + dileptonTrackTrackCandidate::TrackTPCNSigmaPr2, + dileptonTrackTrackCandidate::TrackTPCNCls1, + dileptonTrackTrackCandidate::TrackTPCNCls2, + dileptonTrackTrackCandidate::KFMass, + dileptonTrackTrackCandidate::VertexingProcCode, + dileptonTrackTrackCandidate::VertexingChi2PCA, + dileptonTrackTrackCandidate::CosPointingAngle, + dileptonTrackTrackCandidate::KFDCAxyzBetweenProngs, + dileptonTrackTrackCandidate::KFChi2OverNDFGeo, + dileptonTrackTrackCandidate::VertexingLz, + dileptonTrackTrackCandidate::VertexingLxy, + dileptonTrackTrackCandidate::VertexingLxyz, + dileptonTrackTrackCandidate::VertexingTauz, + dileptonTrackTrackCandidate::VertexingTauxy, + dileptonTrackTrackCandidate::VertexingLzErr, + dileptonTrackTrackCandidate::VertexingLxyzErr, + dileptonTrackTrackCandidate::VertexingTauzErr, + dileptonTrackTrackCandidate::VertexingLzProjected, + dileptonTrackTrackCandidate::VertexingLxyProjected, + dileptonTrackTrackCandidate::VertexingLxyzProjected, + dileptonTrackTrackCandidate::VertexingTauzProjected, + dileptonTrackTrackCandidate::VertexingTauxyProjected); using DileptonTrackTrackCandidate = DileptonTrackTrackCandidates::iterator; diff --git a/PWGDQ/Macros/Prompt-np-Seprataion.zip b/PWGDQ/Macros/Prompt-np-Seprataion.zip new file mode 100644 index 00000000000..06471293445 Binary files /dev/null and b/PWGDQ/Macros/Prompt-np-Seprataion.zip differ diff --git a/PWGDQ/Macros/bdtCut.json b/PWGDQ/Macros/bdtCut.json new file mode 100644 index 00000000000..2e015fa8618 --- /dev/null +++ b/PWGDQ/Macros/bdtCut.json @@ -0,0 +1,89 @@ +{ + "TestCut": { + "type": "Binary", + "title": "MyBDTModel", + "inputFeatures": [ + "kMass", + "kPt", + "kEta", + "kPhi", + "kPt1", + "kITSChi2NCl1", + "kTPCNClsCR1", + "kTPCNClsFound1", + "kTPCChi2NCl1", + "kDcaXY1", + "kDcaZ1", + "kTPCNSigmaEl1", + "kTPCNSigmaPi1", + "kTPCNSigmaPr1", + "kTOFNSigmaEl1", + "kTOFNSigmaPi1", + "kTOFNSigmaPr1", + "kPt2", + "kITSChi2NCl2", + "kTPCNClsCR2", + "kTPCNClsFound2", + "kTPCChi2NCl2", + "kDcaXY2", + "kDcaZ2", + "kTPCNSigmaEl2", + "kTPCNSigmaPi2", + "kTPCNSigmaPr2", + "kTOFNSigmaEl2", + "kTOFNSigmaPi2", + "kTOFNSigmaPr2" + ], + "modelFiles": [ + "cent_10_30_pt0_2_onnx.onnx", + "cent_10_30_pt2_20_onnx.onnx", + "cent_30_50_pt0_2_onnx.onnx", + "cent_30_50_pt2_20_onnx.onnx" + ], + "cent": "kCentFT0C", + "AddCentCut-Cent1030": { + "centMin": 10, + "centMax": 30, + "AddPtCut-pTBin1": { + "pTMin": 0, + "pTMax": 2, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.5, + "exclude": false + } + }, + "AddPtCut-pTBin2": { + "pTMin": 2, + "pTMax": 20, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.5, + "exclude": false + } + } + }, + "AddCentCut-Cent3050": { + "centMin": 30, + "centMax": 50, + "AddPtCut-pTBin1": { + "pTMin": 0, + "pTMax": 2, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.5, + "exclude": false + } + }, + "AddPtCut-pTBin2": { + "pTMin": 2, + "pTMax": 20, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.5, + "exclude": false + } + } + } + } +} diff --git a/PWGDQ/Macros/bdtCutMulti.json b/PWGDQ/Macros/bdtCutMulti.json new file mode 100644 index 00000000000..ba687e36200 --- /dev/null +++ b/PWGDQ/Macros/bdtCutMulti.json @@ -0,0 +1,129 @@ +{ + "TestCut": { + "type": "MultiClass", + "title": "MyBDTModel", + "inputFeatures": [ + "kMass", + "kPt", + "kEta", + "kPhi", + "kPt1", + "kITSChi2NCl1", + "kTPCNClsCR1", + "kTPCNClsFound1", + "kTPCChi2NCl1", + "kDcaXY1", + "kDcaZ1", + "kTPCNSigmaEl1", + "kTPCNSigmaPi1", + "kTPCNSigmaPr1", + "kTOFNSigmaEl1", + "kTOFNSigmaPi1", + "kTOFNSigmaPr1", + "kPt2", + "kITSChi2NCl2", + "kTPCNClsCR2", + "kTPCNClsFound2", + "kTPCChi2NCl2", + "kDcaXY2", + "kDcaZ2", + "kTPCNSigmaEl2", + "kTPCNSigmaPi2", + "kTPCNSigmaPr2", + "kTOFNSigmaEl2", + "kTOFNSigmaPi2", + "kTOFNSigmaPr2" + ], + "modelFiles": [ + "cent_10_30_pt_1_2_onnx.onnx", + "cent_10_30_pt_2_20_onnx.onnx", + "cent_30_50_pt_1_2_onnx.onnx", + "cent_30_50_pt_2_20_onnx.onnx" + ], + "cent": "kCentFT0C", + "AddCentCut-Cent1030": { + "centMin": 10, + "centMax": 30, + "AddPtCut-pTBin1": { + "pTMin": 1, + "pTMax": 2, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-prompt": { + "var": "kBdtPrompt", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-nonprompt": { + "var": "kBdtNonprompt", + "cut": 0.5, + "exclude": false + } + }, + "AddPtCut-pTBin2": { + "pTMin": 2, + "pTMax": 20, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-prompt": { + "var": "kBdtPrompt", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-nonprompt": { + "var": "kBdtNonprompt", + "cut": 0.5, + "exclude": false + } + } + }, + "AddCentCut-Cent3050": { + "centMin": 30, + "centMax": 50, + "AddPtCut-pTBin1": { + "pTMin": 1, + "pTMax": 2, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-prompt": { + "var": "kBdtPrompt", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-nonprompt": { + "var": "kBdtNonprompt", + "cut": 0.5, + "exclude": false + } + }, + "AddPtCut-pTBin2": { + "pTMin": 2, + "pTMax": 20, + "AddMLCut-background": { + "var": "kBdtBackground", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-prompt": { + "var": "kBdtPrompt", + "cut": 0.1, + "exclude": true + }, + "AddMLCut-nonprompt": { + "var": "kBdtNonprompt", + "cut": 0.5, + "exclude": false + } + } + } + } +} diff --git a/PWGDQ/TableProducer/tableMaker.cxx b/PWGDQ/TableProducer/tableMaker.cxx index 6792ba67932..7ebb5876bf5 100644 --- a/PWGDQ/TableProducer/tableMaker.cxx +++ b/PWGDQ/TableProducer/tableMaker.cxx @@ -24,45 +24,48 @@ #include #include // other includes -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.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/CCDB/TriggerAliases.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/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/MftmchMatchingML.h" -#include "Common/DataModel/FwdTrackReAlignTables.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/CutsLibrary.h" -#include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" -#include "DetectorsVertexing/VertexTrackMatcher.h" -#include "ReconstructionDataFormats/PrimaryVertex.h" -#include "ReconstructionDataFormats/VtxTrackIndex.h" -#include "ReconstructionDataFormats/VtxTrackRef.h" -#include "DataFormatsITSMFT/ROFRecord.h" +#include "EventFiltering/Zorro.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonDataFormat/InteractionRecord.h" -#include "DetectorsVertexing/PVertexerParams.h" -#include "MathUtils/Primitive2D.h" #include "DataFormatsGlobalTracking/RecoContainer.h" -#include "Common/DataModel/CollisionAssociationTables.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" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "EventFiltering/Zorro.h" using std::cout; using std::endl; @@ -113,8 +116,8 @@ using MyEvents = soa::Join; using MyEventsWithMults = soa::Join; using MyEventsWithFilter = soa::Join; using MyEventsWithMultsAndFilter = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; using MyMuons = soa::Join; using MyMuonsWithCov = soa::Join; using MyMuonsColl = soa::Join; @@ -191,15 +194,15 @@ struct TableMaker { 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 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"}; } useZorro; struct : ConfigurableGroup { - Configurable fConfigCcdbUrl{"useCCDBConfigurations.ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"useCCDBConfigurations.ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; - Configurable fConfigCcdbPathZorro{"useCCDBConfigurations.ccdb-path-zorro", "/Users/m/mpuccio/EventFiltering/OTS/", "base path to the ccdb object for zorro"}; + Configurable fConfigCcdbUrl{"useCCDBConfigurations.ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"useCCDBConfigurations.ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbPathZorro{"useCCDBConfigurations.ccdb-path-zorro", "/Users/m/mpuccio/EventFiltering/OTS/", "base path to the ccdb object for zorro"}; } useCCDBConfigurations; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; @@ -481,17 +484,17 @@ struct TableMaker { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); @@ -953,17 +956,17 @@ struct TableMaker { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); diff --git a/PWGDQ/TableProducer/tableMakerMC.cxx b/PWGDQ/TableProducer/tableMakerMC.cxx index e8408b3e046..1d43d196f9d 100644 --- a/PWGDQ/TableProducer/tableMakerMC.cxx +++ b/PWGDQ/TableProducer/tableMakerMC.cxx @@ -87,8 +87,8 @@ using MyMftTracks = soa::Join; using MyEvents = soa::Join; using MyEventsWithMults = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; constexpr static uint32_t gkEventFillMap = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision; constexpr static uint32_t gkEventFillMapWithMults = VarManager::ObjTypes::BC | VarManager::ObjTypes::Collision | VarManager::ObjTypes::CollisionMult; @@ -444,17 +444,17 @@ struct TableMakerMC { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); @@ -1079,17 +1079,17 @@ struct TableMakerMC { eventExtended(collision.bc().globalBC(), collision.bc().triggerMask(), 0, triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - collision.centFT0C()); + collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionMult) > 0) { eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], collision.multTPC(), collision.multFV0A(), collision.multFV0C(), collision.multFT0A(), collision.multFT0C(), collision.multFDDA(), collision.multFDDC(), collision.multZNA(), collision.multZNC(), collision.multTracklets(), collision.multNTracksPV(), - -1); + -1, -1, -1); } else if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C()); + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, collision.centFT0C(), collision.centFT0A(), collision.centFT0M()); } else { - eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); + eventExtended(bc.globalBC(), bc.triggerMask(), bc.timestamp(), triggerAliases, VarManager::fgValues[VarManager::kCentVZERO], -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1); } eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); diff --git a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx index 484ec4873d5..ad48874301e 100644 --- a/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMakerMC_withAssoc.cxx @@ -90,8 +90,8 @@ using MyMuonsRealignWithCov = soa::Join; using MyEventsWithMults = soa::Join; using MyEventsWithMultsAndRapidityGapFilter = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; using MFTTrackLabeled = soa::Join; // Declare bit maps containing information on the table joins content (used as argument in templated functions) @@ -547,6 +547,8 @@ struct TableMakerMC { int multTracklets = -1.0; int multTracksPV = -1.0; float centFT0C = -1.0; + float centFT0A = -1.0; + float centFT0M = -1.0; // Loop over collisions for (const auto& collision : collisions) { @@ -641,9 +643,11 @@ struct TableMakerMC { } if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { centFT0C = collision.centFT0C(); + centFT0A = collision.centFT0A(); + centFT0M = collision.centFT0M(); } eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C); + multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C, centFT0A, centFT0M); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventMClabels(collision.mcCollisionId(), collision.mcMask()); eventInfo(collision.globalIndex()); @@ -1108,7 +1112,7 @@ struct TableMakerMC { VarManager::SetupMuonMagField(); } } - std::map metadataRCT, header; + 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()); diff --git a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx index 9c269de06d3..60670abfac6 100644 --- a/PWGDQ/TableProducer/tableMaker_withAssoc.cxx +++ b/PWGDQ/TableProducer/tableMaker_withAssoc.cxx @@ -23,46 +23,49 @@ #include #include // other includes -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.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/CCDB/TriggerAliases.h" +#include "Common/Core/TableHelper.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/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/MftmchMatchingML.h" -#include "Common/DataModel/FwdTrackReAlignTables.h" -#include "Common/Core/TableHelper.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/CutsLibrary.h" -#include "DataFormatsGlobalTracking/RecoContainerCreateTracksVariadic.h" -#include "DetectorsVertexing/VertexTrackMatcher.h" -#include "ReconstructionDataFormats/PrimaryVertex.h" -#include "ReconstructionDataFormats/VtxTrackIndex.h" -#include "ReconstructionDataFormats/VtxTrackRef.h" -#include "DataFormatsITSMFT/ROFRecord.h" +#include "EventFiltering/Zorro.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonDataFormat/InteractionRecord.h" -#include "DetectorsVertexing/PVertexerParams.h" -#include "MathUtils/Primitive2D.h" #include "DataFormatsGlobalTracking/RecoContainer.h" -#include "Common/DataModel/CollisionAssociationTables.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" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "EventFiltering/Zorro.h" using namespace o2; using namespace o2::framework; @@ -104,8 +107,8 @@ using MyEventsWithMults = soa::Join; using MyEventsWithFilter = soa::Join; using MyEventsWithMultsAndFilter = soa::Join; using MyEventsWithMultsAndRapidityGapFilter = soa::Join; -using MyEventsWithCent = soa::Join; -using MyEventsWithCentAndMults = soa::Join; +using MyEventsWithCent = soa::Join; +using MyEventsWithCentAndMults = soa::Join; using MyEventsWithMultsExtra = soa::Join; using MyMuons = soa::Join; using MyMuonsWithCov = soa::Join; @@ -225,9 +228,9 @@ struct TableMaker { // 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 fConfigCcdbPathZorro{"ccdb-path-zorro", "/Users/m/mpuccio/EventFiltering/OTS/Chunked/", "base path to the ccdb object for zorro"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbPathZorro{"ccdb-path-zorro", "/Users/m/mpuccio/EventFiltering/OTS/Chunked/", "base path to the ccdb object for zorro"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigGeoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable fConfigGrpMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; @@ -770,6 +773,8 @@ struct TableMaker { int multTracklets = -1.0; int multTracksPV = -1.0; float centFT0C = -1.0; + float centFT0A = -1.0; + float centFT0M = -1.0; for (const auto& collision : collisions) { @@ -898,9 +903,11 @@ struct TableMaker { } if constexpr ((TEventFillMap & VarManager::ObjTypes::CollisionCent) > 0) { centFT0C = collision.centFT0C(); + centFT0A = collision.centFT0A(); + centFT0M = collision.centFT0M(); } eventExtended(bc.globalBC(), collision.alias_raw(), collision.selection_raw(), bc.timestamp(), VarManager::fgValues[VarManager::kCentVZERO], - multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C); + multTPC, multFV0A, multFV0C, multFT0A, multFT0C, multFDDA, multFDDC, multZNA, multZNC, multTracklets, multTracksPV, centFT0C, centFT0A, centFT0M); eventVtxCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventInfo(collision.globalIndex()); if constexpr ((TEventFillMap & VarManager::ObjTypes::Zdc) > 0) { @@ -1313,7 +1320,7 @@ struct TableMaker { VarManager::SetupMuonMagField(); } } - std::map metadataRCT, header; + 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()); diff --git a/PWGDQ/Tasks/CMakeLists.txt b/PWGDQ/Tasks/CMakeLists.txt index a10d6bb117d..c3bb38bf955 100644 --- a/PWGDQ/Tasks/CMakeLists.txt +++ b/PWGDQ/Tasks/CMakeLists.txt @@ -11,12 +11,12 @@ o2physics_add_dpl_workflow(table-reader SOURCES tableReader.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGDQCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(table-reader-with-assoc SOURCES tableReader_withAssoc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(efficiency @@ -118,3 +118,13 @@ o2physics_add_dpl_workflow(model-converter-mult-pv SOURCES ModelConverterMultPv.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(model-converter-event-extended + SOURCES ModelConverterEventExtended.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGDQCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(tag-and-probe + SOURCES TagAndProbe.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGDQCore + COMPONENT_NAME Analysis) diff --git a/PWGDQ/Tasks/ModelConverterEventExtended.cxx b/PWGDQ/Tasks/ModelConverterEventExtended.cxx new file mode 100644 index 00000000000..ec0a6a0c4be --- /dev/null +++ b/PWGDQ/Tasks/ModelConverterEventExtended.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. +// +// Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no +// +// 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 + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; + +struct eventExtendedConverter000_001 { + Produces eventExtended_001; + + void process(aod::ReducedEventsExtended_000 const& events) + { + for (const auto& event : events) { + eventExtended_001(event.globalBC(), event.alias_raw(), event.selection_raw(), event.timestamp(), event.centRun2V0M(), + event.multTPC(), event.multFV0A(), event.multFV0C(), event.multFT0A(), event.multFT0C(), + event.multFDDA(), event.multFDDC(), event.multZNA(), event.multZNC(), event.multTracklets(), event.multNTracksPV(), + event.centFT0C(), -1.0f, -1.0f); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGDQ/Tasks/TagAndProbe.cxx b/PWGDQ/Tasks/TagAndProbe.cxx new file mode 100644 index 00000000000..2a35b33b87e --- /dev/null +++ b/PWGDQ/Tasks/TagAndProbe.cxx @@ -0,0 +1,442 @@ +// 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 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 + +using std::cout; +using std::endl; +using std::string; + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod; + +// Some definitions +namespace o2::aod +{ +namespace dqanalysisflags +{ +DECLARE_SOA_BITMAP_COLUMN(IsEventSelected, isEventSelected, 8); //! Event decision +DECLARE_SOA_BITMAP_COLUMN(IsMuonSelected, isMuonSelected, 32); //! Muon track decisions (joinable to ReducedMuonsAssoc) +} // namespace dqanalysisflags + +DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTSA", dqanalysisflags::IsEventSelected); //! joinable to ReducedEvents +DECLARE_SOA_TABLE(MuonTrackCuts, "AOD", "DQANAMUONCUTSA", dqanalysisflags::IsMuonSelected); //! joinable to ReducedMuonsAssoc //! joinable to ReducedTracksAssoc +} // namespace o2::aod + +// Declarations of various short names +using MyEvents = soa::Join; +using MyEventsVtxCov = soa::Join; + +using MyMuonTracksWithCov = soa::Join; + +// bit maps used for the Fill functions of the VarManager +constexpr static uint32_t gkEventFillMapWithCov = VarManager::ObjTypes::ReducedEvent | VarManager::ObjTypes::ReducedEventExtended | VarManager::ObjTypes::ReducedEventVtxCov; + +constexpr static uint32_t gkMuonFillMapWithCov = VarManager::ObjTypes::ReducedMuon | VarManager::ObjTypes::ReducedMuonExtra | VarManager::ObjTypes::ReducedMuonCov; + +// 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"); + } +} + +// Run the AnalysisTagAndProbe +// This task assumes that both legs of the resonance fulfill the same cuts (symmetric decay channel) +// Runs combinatorics for muon-muon combinations +struct AnalysisTagAndProbe { + + o2::base::MatLayerCylSet* fLUT = nullptr; + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + + OutputObj fOutputList{"output"}; + + struct : ConfigurableGroup { + Configurable muon{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; + // TODO: Add pair cuts via JSON + } fConfigCuts; + + Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigQA{"cfgQA", true, "If true, fill output histograms"}; + + 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; + + struct : ConfigurableGroup { + 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 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 propTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; + } fConfigOptions; + + Service fCCDB; + o2::ccdb::CcdbApi fCCDBApi; + + HistogramManager* fHistMan; + + // keep histogram class names in maps, so we don't have to buld their names in the pair loops + std::map> fMuonHistNames; + + uint32_t fMuonFilterMask; // mask for the muon cuts required in this task to be applied on the muon cuts produced upstream + int fNCutsMuon; + + bool fEnableMuonHistos; + + Preslice muonAssocsPerCollision = aod::reducedtrack_association::reducedeventId; + + void init(o2::framework::InitContext& context) + { + fEnableMuonHistos = context.mOptions.get("processMuonTagAndProbe"); + + if (context.mOptions.get("processDummy")) { + if (fEnableMuonHistos) { + LOG(fatal) << "No other processing tasks should be enabled if the processDummy is enabled!!"; + } + return; + } + VarManager::SetDefaultVarNames(); + + // Keep track of all the histogram class names to avoid composing strings in the pairing loop + TString histNames = ""; + std::vector names; + + // get the list of cuts for muons + // and make a mask for active cuts (muon selection tasks may run more cuts, needed for other analyses) + TString muonCutsStr = fConfigCuts.muon.value; + TObjArray* objArrayMuonCuts = nullptr; + if (!muonCutsStr.IsNull()) { + objArrayMuonCuts = muonCutsStr.Tokenize(","); + } + + // get the muon track selection cuts + TString tempCutsStr = fConfigCuts.muon.value; + + if (!muonCutsStr.IsNull()) { + 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) { + fMuonFilterMask |= (static_cast(1) << icut); + + if (fEnableMuonHistos) { + // no pair cuts + names = { + Form("PairsMuonSEPM_%s", objArray->At(icut)->GetName()), + Form("PairsMuonSEPM_%s_PassingProbes", objArray->At(icut)->GetName()), + Form("PairsMuonSEPM_%s_FailingProbes", objArray->At(icut)->GetName())}; + histNames += Form("%s;%s;%s;", names[0].Data(), names[1].Data(), names[2].Data()); + fMuonHistNames[icut] = names; + } + } + } + } + + fCurrentRun = 0; + + fCCDB->setURL(fConfigCCDB.url.value); + fCCDB->setCaching(true); + fCCDB->setLocalObjectValidityChecking(); + fCCDBApi.init(fConfigCCDB.url.value); + + 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); + } + + if (fConfigQA) { + 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()); + } + } + + void initParamsFromCCDB(uint64_t timestamp, int runNumber, bool withTwoProngFitter = true) + { + + if (fConfigOptions.useRemoteField.value) { + o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(fConfigCCDB.grpMagPath, timestamp); + float magField = 0.0; + if (grpmag != nullptr) { + magField = grpmag->getNominalL3Field(); + } 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 + } + } + + std::map metadataRCT, header; + header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", runNumber), metadataRCT, -1); + uint64_t sor = std::atol(header["SOR"].c_str()); + uint64_t eor = std::atol(header["EOR"].c_str()); + VarManager::SetSORandEOR(sor, eor); + } + + // Template function to run run Tag And Probe (muon-muon) + template + void runTagAndProbe(TEvents const& events, Preslice& preslice, TTrackAssocs const& assocs, TTracks const& /*tracks*/) + { + if (events.size() > 0) { // Additional protection to avoid crashing of events.begin().runNumber() + if (fCurrentRun != events.begin().runNumber()) { + initParamsFromCCDB(events.begin().timestamp(), events.begin().runNumber(), TTwoProngFitter); + fCurrentRun = events.begin().runNumber(); + } + } + + TString cutNames = fConfigCuts.muon.value; + std::map> histNames = fMuonHistNames; + int ncuts = fNCutsMuon; + int sign1 = 0; + int sign2 = 0; + + if (events.size() > 0) { + for (auto& event : events) { + // Reset the fValues array + VarManager::ResetValues(0, VarManager::kNVars); + // VarManager::FillEvent(event, VarManager::fgValues); + 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::kDecayToMuMu) { + + auto t1 = a1.template reducedmuon_as(); + auto t2 = a2.template reducedmuon_as(); + if (t1.matchMCHTrackId() == t2.matchMCHTrackId() && t1.matchMCHTrackId() >= 0) + continue; + if (t1.matchMFTTrackId() == t2.matchMFTTrackId() && t1.matchMFTTrackId() >= 0) + continue; + sign1 = t1.sign(); + sign2 = t2.sign(); + + VarManager::FillPair(t1, t2); + + for (int icut = 0; icut < ncuts; icut++) { + if (sign1 * sign2 < 0) { + fHistMan->FillHistClass(histNames[icut][0].Data(), VarManager::fgValues); + + if (static_cast(t1.trackType()) == 3) { // t1 is the tag (track MCHMID) + if (static_cast(t2.trackType()) == 3) { // t2 is the passing probe (track MCHMID) + fHistMan->FillHistClass(histNames[icut][1].Data(), VarManager::fgValues); + } else if (static_cast(t2.trackType()) == 4) { // t2 is the failing probe (MCHStandalone) + fHistMan->FillHistClass(histNames[icut][2].Data(), VarManager::fgValues); + } else { + continue; + } + } + } + } // end loop (cuts) + } // end if (kDecayToMuMu) + } // end loop over pairs of track associations + } // end loop over events + } // end if (events.size() > 0) + + } // end runTagAndProbe + + void processMuonTagAndProbe(MyEventsVtxCov const& events, + aod::ReducedMuonsAssoc const& muonAssocs, MyMuonTracksWithCov const& muons) + { + runTagAndProbe(events, muonAssocsPerCollision, muonAssocs, muons); + } + + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisTagAndProbe, processMuonTagAndProbe, "Run muon - pairing & TagAndProbe", false); + PROCESS_SWITCH(AnalysisTagAndProbe, processDummy, "Dummy function, enabled only if none of the others are enabled", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + 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("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("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")) { + 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("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"); + } + } // end loop over histogram classes +} diff --git a/PWGDQ/Tasks/dqCorrelation.cxx b/PWGDQ/Tasks/dqCorrelation.cxx index 950e82364cb..ec240fa66fe 100644 --- a/PWGDQ/Tasks/dqCorrelation.cxx +++ b/PWGDQ/Tasks/dqCorrelation.cxx @@ -11,44 +11,45 @@ /// @author Victor Valencia // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "PWGCF/GenericFramework/Core/FlowContainer.h" -#include "PWGCF/GenericFramework/Core/GFWCumulant.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/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/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 "Field/MagneticField.h" -#include "TGeoGlobalMagField.h" -#include "DetectorsBase/Propagator.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 "PWGCF/GenericFramework/Core/GFWPowerArray.h" +#include "TGeoGlobalMagField.h" #include "TProfile.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include using std::cout; using std::endl; @@ -118,7 +119,7 @@ struct DqCumulantFlow { ConfigurableAxis axisMass{"axisMass", {40, 2, 4}, "mass axis for histograms"}; Configurable fConfigNPow{"cfgNPow", 0, "Power of weights for Q vector"}; // Configurables for the reference flow - Configurable fConfigTrackCuts{"cfgLeptonCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable fConfigTrackCuts{"cfgLeptonCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; Configurable fConfigCutPtMin{"cfgCutPtMin", 1.0f, "Minimal pT for tracks"}; Configurable fConfigCutPtMax{"cfgCutPtMax", 12.0f, "Maximal pT for tracks"}; Configurable fConfigCutEtaMin{"cfgCutEtaMin", -0.8f, "Eta min range for tracks"}; diff --git a/PWGDQ/Tasks/dqEfficiency.cxx b/PWGDQ/Tasks/dqEfficiency.cxx index e898e4c4f19..bcbaa4fe1bf 100644 --- a/PWGDQ/Tasks/dqEfficiency.cxx +++ b/PWGDQ/Tasks/dqEfficiency.cxx @@ -13,30 +13,33 @@ // // Analysis task for processing O2::DQ MC skimmed AODs // -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.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 "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 using std::cout; using std::endl; @@ -308,8 +311,8 @@ struct AnalysisTrackSelection { fHistMan->FillHistClass(fHistNamesMCMatched[j][i].Data(), VarManager::fgValues); } } // end loop over cuts - } // end loop over MC signals - } // end loop over tracks + } // end loop over MC signals + } // end loop over tracks } void processSkimmed(MyEventsSelected::iterator const& event, MyBarrelTracks const& tracks, ReducedMCEvents const& eventsMC, ReducedMCTracks const& tracksMC) @@ -481,8 +484,8 @@ struct AnalysisMuonSelection { fHistMan->FillHistClass(fHistNamesMCMatched[j][i].Data(), VarManager::fgValues); } } // end loop over cuts - } // end loop over MC signals - } // end loop over muons + } // end loop over MC signals + } // end loop over muons } void processSkimmed(MyEventsSelected::iterator const& event, MyMuonTracks const& muons, ReducedMCEvents const& eventsMC, ReducedMCTracks const& tracksMC) @@ -622,8 +625,8 @@ struct AnalysisSameEventPairing { } fBarrelHistNamesMCmatched.push_back(mcSigClasses); } // end loop over cuts - } // end if(cutNames.IsNull()) - } // end if processBarrel + } // end if(cutNames.IsNull()) + } // end if processBarrel if (enableMuonHistos) { TString cutNames = fConfigMuonCuts.value; @@ -650,8 +653,8 @@ struct AnalysisSameEventPairing { } fMuonHistNamesMCmatched.push_back(mcSigClasses); } // end loop over cuts - } // end if(cutNames.IsNull()) - } // end if processMuon + } // end if(cutNames.IsNull()) + } // end if processMuon // NOTE: For the electron-muon pairing, the policy is that the user specifies n track and n muon cuts via configurables // So for each barrel cut there is a corresponding muon cut @@ -897,7 +900,7 @@ struct AnalysisSameEventPairing { } } } // end loop over barrel track pairs - } // end runPairing + } // end runPairing template void runMCGen(TTracksMC& groupedMCTracks) @@ -947,7 +950,7 @@ struct AnalysisSameEventPairing { } } } // end of true pairing loop - } // end runMCGen + } // end runMCGen // Preslice perReducedMcEvent = aod::reducedtrackMC::reducedMCeventId; PresliceUnsorted perReducedMcEvent = aod::reducedtrackMC::reducedMCeventId; @@ -1040,9 +1043,18 @@ struct AnalysisSameEventPairing { struct AnalysisDileptonTrack { Produces dileptontrackcandidatesList; OutputObj fOutputList{"output"}; + Service ccdb; + o2::base::MatLayerCylSet* lut = nullptr; + // TODO: For now this is only used to determine the position in the filter bit map for the hadron cut - Configurable fConfigTrackCuts{"cfgLeptonCuts", "", "Comma separated list of barrel track cuts"}; + Configurable fConfigTrackCuts{"cfgLeptonCuts", "", "Comma separated list of barrel track cuts"}; Configurable fConfigFillCandidateTable{"cfgFillCandidateTable", false, "Produce a single flat tables with all relevant information dilepton-track candidates"}; + Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fCorrFullGeo{"cfgCorrFullGeo", false, "Use full geometry to correct for MCS effects in track propagation"}; + Configurable fNoCorr{"cfgNoCorrFwdProp", false, "Do not correct for MCS effects in track propagation"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Filter eventFilter = aod::dqanalysisflags::isEventSelected == 1; // Filter dileptonFilter = aod::reducedpair::mass > 2.92f && aod::reducedpair::mass < 3.16f && aod::reducedpair::sign == 0; // Filter dileptonFilter = aod::reducedpair::mass > 2.6f && aod::reducedpair::mass < 3.5f && aod::reducedpair::sign == 0; @@ -1075,6 +1087,21 @@ struct AnalysisDileptonTrack { return; } + ccdb->setURL(ccdburl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + + if (fNoCorr) { + VarManager::SetupFwdDCAFitterNoCorr(); + } else if (fCorrFullGeo) { + if (!o2::base::GeometryManager::isGeometryLoaded()) { + ccdb->get(geoPath); + } + } else { + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + VarManager::SetupMatLUTFwdDCAFitter(lut); + } + TString sigNamesStr = fConfigMCRecSignals.value; std::unique_ptr objRecSigArray(sigNamesStr.Tokenize(",")); TString histNames; @@ -1320,6 +1347,8 @@ struct AnalysisDileptonTrackTrack { Configurable fConfigMCRecSignals{"cfgBarrelMCRecSignals", "", "Comma separated list of MC signals (reconstructed)"}; Configurable fConfigMCGenSignals{"cfgBarrelMCGenSignals", "", "Comma separated list of MC signals (generated)"}; Configurable fConfigDileptonMCRecSignal{"cfgDileptonMCRecSignal", "", "Comma separated list of MC signals (reconstructed)"}; + Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigUseDCAVertexing{"cfgUseDCAVertexing", false, "Use DCA for secondary vertex reconstruction (DCAFitter is used by default)"}; Produces DileptonTrackTrackTable; HistogramManager* fHistMan; @@ -1410,7 +1439,7 @@ struct AnalysisDileptonTrackTrack { if (sig->GetNProngs() == 4) { fRecMCSignals.push_back(*sig); fRecMCSignalsNames.push_back(sig->GetName()); - histNames += Form("MCTruthRecQaud_%s_%s;", fQuadrupletCutNames[icut].Data(), sig->GetName()); + histNames += Form("MCTruthRecQuad_%s_%s;", fQuadrupletCutNames[icut].Data(), sig->GetName()); } } } @@ -1426,7 +1455,7 @@ struct AnalysisDileptonTrackTrack { if (sig) { if (sig->GetNProngs() == 1) { // NOTE: 1-prong signals required fGenMCSignals.push_back(*sig); - histNames += Form("MCTruthGenQaud_%s;", sig->GetName()); // TODO: Add these names to a std::vector to avoid using Form in the process function + histNames += Form("MCTruthGenQuad_%s;", sig->GetName()); // TODO: Add these names to a std::vector to avoid using Form in the process function } } } @@ -1455,6 +1484,15 @@ struct AnalysisDileptonTrackTrack { VarManager::ResetValues(0, VarManager::kNVars, fValuesQuadruplet); VarManager::FillEvent(event, fValuesQuadruplet); + // set up KF or DCAfitter + if (fConfigUseDCAVertexing) { + VarManager::SetupTwoProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + // VarManager::SetupThreeProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } else if (fConfigUseKFVertexing) { + VarManager::SetupFourProngKFParticle(5.0f); + } + // LOGF(info, "Number of dileptons: %d", dileptons.size()); int indexOffset = -999; std::vector trackGlobalIndexes; @@ -1506,6 +1544,10 @@ struct AnalysisDileptonTrackTrack { // Fill the Histograms VarManager::FillDileptonTrackTrack(dilepton, t1, t2, fValuesQuadruplet); + // reconstruct the secondary vertex + if (fConfigUseDCAVertexing || fConfigUseKFVertexing) { + VarManager::FillDileptonTrackTrackVertexing(event, lepton1, lepton2, t1, t2, fValuesQuadruplet); + } uint32_t CutDecision = 0; uint32_t mcDecision = 0; int iCut = 0; @@ -1539,7 +1581,7 @@ struct AnalysisDileptonTrackTrack { } for (unsigned int isig = 0; isig < fRecMCSignals.size(); isig++) { if (mcDecision & (static_cast(1) << isig)) { - fHistMan->FillHistClass(Form("MCTruthRecQaud_%s_%s", fQuadrupletCutNames[iCut].Data(), fRecMCSignalsNames[isig].Data()), fValuesQuadruplet); + fHistMan->FillHistClass(Form("MCTruthRecQuad_%s_%s", fQuadrupletCutNames[iCut].Data(), fRecMCSignalsNames[isig].Data()), fValuesQuadruplet); } } } @@ -1554,7 +1596,12 @@ struct AnalysisDileptonTrackTrack { DileptonTrackTrackTable(fValuesQuadruplet[VarManager::kQuadMass], fValuesQuadruplet[VarManager::kQuadPt], fValuesQuadruplet[VarManager::kQuadEta], fValuesQuadruplet[VarManager::kQuadPhi], fValuesQuadruplet[VarManager::kRap], fValuesQuadruplet[VarManager::kQ], fValuesQuadruplet[VarManager::kDeltaR1], fValuesQuadruplet[VarManager::kDeltaR2], fValuesQuadruplet[VarManager::kDeltaR], dilepton.mass(), dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.sign(), - fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign()); + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton1.tpcNClsFound(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), lepton2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign(), t1.tpcNSigmaPi(), t2.tpcNSigmaPi(), t1.tpcNSigmaKa(), t2.tpcNSigmaKa(), t1.tpcNSigmaPr(), t1.tpcNSigmaPr(), t1.tpcNClsFound(), t2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kKFMass], fValuesQuadruplet[VarManager::kVertexingProcCode], fValuesQuadruplet[VarManager::kVertexingChi2PCA], fValuesQuadruplet[VarManager::kCosPointingAngle], fValuesQuadruplet[VarManager::kKFDCAxyzBetweenProngs], fValuesQuadruplet[VarManager::kKFChi2OverNDFGeo], + fValuesQuadruplet[VarManager::kVertexingLz], fValuesQuadruplet[VarManager::kVertexingLxy], fValuesQuadruplet[VarManager::kVertexingLxyz], fValuesQuadruplet[VarManager::kVertexingTauz], fValuesQuadruplet[VarManager::kVertexingTauxy], fValuesQuadruplet[VarManager::kVertexingLzErr], fValuesQuadruplet[VarManager::kVertexingLxyzErr], + fValuesQuadruplet[VarManager::kVertexingTauzErr], fValuesQuadruplet[VarManager::kVertexingLzProjected], fValuesQuadruplet[VarManager::kVertexingLxyProjected], fValuesQuadruplet[VarManager::kVertexingLxyzProjected], fValuesQuadruplet[VarManager::kVertexingTauzProjected], fValuesQuadruplet[VarManager::kVertexingTauxyProjected]); } // end loop over track - track combinations } // end loop over dileptons }; @@ -1574,9 +1621,9 @@ struct AnalysisDileptonTrackTrack { auto dilepton = mcTracks.rawIteratorAt(daughterIdFirst); auto track1 = mcTracks.rawIteratorAt(daughterIdFirst + 1); auto track2 = mcTracks.rawIteratorAt(daughterIdFirst + 2); - VarManager::FillQaudMC(dilepton, track1, track2); + VarManager::FillQuadMC(dilepton, track1, track2); } - fHistMan->FillHistClass(Form("MCTruthGenQaud_%s", sig.GetName()), VarManager::fgValues); + fHistMan->FillHistClass(Form("MCTruthGenQuad_%s", sig.GetName()), VarManager::fgValues); } } } @@ -1654,7 +1701,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) // histMan->AddHistogram(objArray->At(iclass)->GetName(), "Rapidity", "MC generator y distribution", false, 150, 2.5, 4.0, VarManager::kMCY); histMan->AddHistogram(objArray->At(iclass)->GetName(), "Phi", "MC generator #varphi distribution", false, 50, 0.0, 2. * TMath::Pi(), VarManager::kMCPhi); } - if (classStr.Contains("MCTruthGenQaud")) { + if (classStr.Contains("MCTruthGenQuad")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "mctruth_quad"); } if (classStr.Contains("MCTruthGen")) { @@ -1673,7 +1720,7 @@ void DefineHistograms(HistogramManager* histMan, TString histClasses) if (classStr.Contains("DileptonTrackInvMass")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-hadron-mass"); } - if (classStr.Contains("Quadruplet") || classStr.Contains("MCTruthRecQaud")) { + if (classStr.Contains("Quadruplet") || classStr.Contains("MCTruthRecQuad")) { dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-dihadron", "xtojpsipipi"); } diff --git a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx index cb44ae1d935..6351a49157f 100644 --- a/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx +++ b/PWGDQ/Tasks/dqEfficiency_withAssoc.cxx @@ -12,43 +12,47 @@ // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // Configurable workflow for running several DQ or other PWG analyses -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisHelpers.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/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" -#include "PWGDQ/Core/MixingLibrary.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/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 "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "Common/Core/TableHelper.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include using std::cout; using std::endl; @@ -84,7 +88,42 @@ DECLARE_SOA_COLUMN(TauxyBcandidate, tauxyBcandidate, float); DECLARE_SOA_COLUMN(TauzBcandidate, tauzBcandidate, float); DECLARE_SOA_COLUMN(CosPBcandidate, cosPBcandidate, float); DECLARE_SOA_COLUMN(Chi2Bcandidate, chi2Bcandidate, float); -DECLARE_SOA_COLUMN(DCAxyzBetweenProngs, dcaxyzBetweenProngs, float); +DECLARE_SOA_COLUMN(PINassoc, pINassoc, float); +DECLARE_SOA_COLUMN(Etaassoc, etaassoc, float); +DECLARE_SOA_COLUMN(Ptpair, ptpair, float); +DECLARE_SOA_COLUMN(Etapair, etapair, float); +DECLARE_SOA_COLUMN(PINleg1, pINleg1, float); +DECLARE_SOA_COLUMN(Etaleg1, etaleg1, float); +DECLARE_SOA_COLUMN(PINleg2, pINleg2, float); +DECLARE_SOA_COLUMN(Etaleg2, etaleg2, 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(DCAXYassoc, dcaXYassoc, float); +DECLARE_SOA_COLUMN(DCAZassoc, dcaZassoc, float); +DECLARE_SOA_COLUMN(DCAXYleg1, dcaXYleg1, float); +DECLARE_SOA_COLUMN(DCAZleg1, dcaZleg1, float); +DECLARE_SOA_COLUMN(DCAXYleg2, dcaXYleg2, float); +DECLARE_SOA_COLUMN(DCAZleg2, dcaZleg2, 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_COLUMN(McFlag, mcFlag, int8_t); DECLARE_SOA_BITMAP_COLUMN(IsJpsiFromBSelected, isJpsiFromBSelected, 32); // Candidate columns for prompt-non-prompt JPsi separation @@ -107,8 +146,17 @@ DECLARE_SOA_TABLE(Prefilter, "AOD", "DQPREFILTER", dqanalysisflags::IsBarrelSele DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONS", dqanalysisflags::massBcandidate, dqanalysisflags::MassDileptonCandidate, dqanalysisflags::deltaMassBcandidate, dqanalysisflags::pTBcandidate, dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LzBcandidate, - dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::DCAxyzBetweenProngs, - dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate, + dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate, + 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::DCAXYassoc, dqanalysisflags::DCAZassoc, dqanalysisflags::DCAXYleg1, dqanalysisflags::DCAZleg1, dqanalysisflags::DCAXYleg2, dqanalysisflags::DCAZleg2, + 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, dqanalysisflags::McFlag); DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs, dqanalysisflags::Corrassoc); } // namespace o2::aod @@ -166,8 +214,8 @@ struct AnalysisEventSelection { Produces eventSel; OutputObj fOutputList{"output"}; - Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; - Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified 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 fConfigAddEventMCHistogram{"cfgAddEventMCHistogram", "generator", "Comma separated list of histograms"}; @@ -177,7 +225,7 @@ struct AnalysisEventSelection { Configurable fConfigSplitCollisionsDeltaBC{"splitCollisionsDeltaBC", 100, "maximum delta-BC between two collisions to consider them as split candidates; do not apply if value is negative"}; Configurable fConfigCheckSplitCollisions{"checkSplitCollisions", false, "If true, run the split collision check and fill histograms"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + 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"}; HistogramManager* fHistMan = nullptr; @@ -386,14 +434,14 @@ struct AnalysisTrackSelection { Produces trackAmbiguities; OutputObj fOutputList{"output"}; - Configurable fConfigCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + 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 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 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"}; @@ -490,7 +538,7 @@ struct AnalysisTrackSelection { 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 + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } @@ -711,13 +759,13 @@ struct AnalysisMuonSelection { Produces muonAmbiguities; OutputObj fOutputList{"output"}; - Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; + Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; Configurable fConfigCutsJSON{"cfgMuonCutsJSON", "", "Additional list of muon cuts in JSON format"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigAddMuonHistogram{"cfgAddMuonHistogram", "", "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 fConfigCcdbUrl{"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 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"}; @@ -812,9 +860,9 @@ struct AnalysisMuonSelection { histClasses += "Muon_AmbiguityInBunch;Muon_AmbiguityOutOfBunch;"; } - DefineHistograms(fHistMan, histClasses.Data(), fConfigAddMuonHistogram.value.data()); // define all histograms + DefineHistograms(fHistMan, histClasses.Data(), fConfigAddMuonHistogram.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 + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } @@ -1216,9 +1264,9 @@ struct AnalysisSameEventPairing { OutputObj fOutputList{"output"}; 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 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"}; // TODO: Add pair cuts via JSON } fConfigCuts; @@ -1227,7 +1275,7 @@ struct AnalysisSameEventPairing { Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; struct : ConfigurableGroup { - Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + 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"}; @@ -1594,9 +1642,9 @@ struct AnalysisSameEventPairing { 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 + 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 + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } @@ -1883,6 +1931,24 @@ struct AnalysisSameEventPairing { float dileptonMass = VarManager::fgValues[VarManager::kMass]; if (dileptonMass > useMiniTree.fConfigMiniTreeMinMass && dileptonMass < useMiniTree.fConfigMiniTreeMaxMass) { + // In the miniTree the positive daughter is positioned as first + if (t1.sign() > 0) { + dileptonMiniTreeRec(mcDecision, + VarManager::fgValues[VarManager::kMass], + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kCentFT0C], + t1.reducedMCTrack().pt(), t1.reducedMCTrack().eta(), t1.reducedMCTrack().phi(), + t2.reducedMCTrack().pt(), t2.reducedMCTrack().eta(), t2.reducedMCTrack().phi(), + t1.pt(), t1.eta(), t1.phi(), + t2.pt(), t2.eta(), t2.phi()); + } else { + dileptonMiniTreeRec(mcDecision, + VarManager::fgValues[VarManager::kMass], + VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kCentFT0C], + t2.reducedMCTrack().pt(), t2.reducedMCTrack().eta(), t2.reducedMCTrack().phi(), + t1.reducedMCTrack().pt(), t1.reducedMCTrack().eta(), t1.reducedMCTrack().phi(), + t2.pt(), t2.eta(), t2.phi(), + t2.pt(), t2.eta(), t2.phi()); + } dileptonMiniTreeRec(mcDecision, VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], VarManager::fgValues[VarManager::kCentFT0C], @@ -2115,11 +2181,16 @@ struct AnalysisSameEventPairing { continue; } - auto groupedMCTracks = mcTracks.sliceBy(perReducedMcGenEvent, event.reducedMCeventId()); - groupedMCTracks.bindInternalIndicesTo(&mcTracks); - for (auto& track : groupedMCTracks) { + // auto groupedMCTracks = mcTracks.sliceBy(perReducedMcGenEvent, event.reducedMCeventId()); + // groupedMCTracks.bindInternalIndicesTo(&mcTracks); + // for (auto& track : groupedMCTracks) { + for (auto& track : mcTracks) { + if (track.reducedMCeventId() != event.reducedMCeventId()) { + continue; + } VarManager::FillTrackMC(mcTracks, track); - auto track_raw = groupedMCTracks.rawIteratorAt(track.globalIndex()); + auto track_raw = mcTracks.rawIteratorAt(track.globalIndex()); + // auto track_raw = groupedMCTracks.rawIteratorAt(track.globalIndex()); for (auto& sig : fGenMCSignals) { if (sig->CheckSignal(true, track_raw)) { fHistMan->FillHistClass(Form("MCTruthGenSel_%s", sig->GetName()), VarManager::fgValues); @@ -2173,13 +2244,13 @@ struct AnalysisAsymmetricPairing { OutputObj fOutputList{"output"}; // Configurables - Configurable fConfigLegCuts{"cfgLegCuts", "", ":[:],[:[:],...]"}; + 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 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"}; @@ -2189,7 +2260,7 @@ struct AnalysisAsymmetricPairing { Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable fConfigGRPMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable fConfigUseRemoteField{"cfgUseRemoteField", false, "Choose whether to fetch the magnetic field from ccdb or set it manually"}; Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; @@ -2593,7 +2664,7 @@ struct AnalysisAsymmetricPairing { VarManager::SetupMatLUTFwdDCAFitter(fLUT); 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 + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } @@ -2753,7 +2824,7 @@ struct AnalysisAsymmetricPairing { 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 + 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); @@ -3172,7 +3243,7 @@ struct AnalysisDileptonTrack { Produces BmesonsTable; OutputObj fOutputList{"output"}; - Configurable fConfigTrackCuts{"cfgTrackCuts", "kaonPID", "Comma separated list of track cuts to be correlated with the dileptons"}; + 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 fConfigDileptonpTCut{"cfgDileptonpTCut", 0.0, "pT cut for dileptons used in the triplet vertexing"}; @@ -3630,6 +3701,21 @@ struct AnalysisDileptonTrack { mcDecision |= (static_cast(1) << isig); } } + // table to be written out for ML analysis + BmesonsTable(fValuesHadron[VarManager::kPairMass], dilepton.mass(), fValuesHadron[VarManager::kDeltaMass], fValuesHadron[VarManager::kPairPt], + fValuesHadron[VarManager::kVertexingLxy], fValuesHadron[VarManager::kVertexingLxyz], fValuesHadron[VarManager::kVertexingLz], + fValuesHadron[VarManager::kVertexingTauxy], fValuesHadron[VarManager::kVertexingTauz], fValuesHadron[VarManager::kCosPointingAngle], + fValuesHadron[VarManager::kVertexingChi2PCA], + track.tpcInnerParam(), track.eta(), dilepton.pt(), dilepton.eta(), lepton1.tpcInnerParam(), lepton1.eta(), lepton2.tpcInnerParam(), lepton2.eta(), + track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tpcNSigmaPr(), track.tofNSigmaKa(), + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), + track.dcaXY(), track.dcaZ(), lepton1.dcaXY(), lepton1.dcaZ(), lepton2.dcaXY(), lepton2.dcaZ(), + track.itsClusterMap(), lepton1.itsClusterMap(), lepton2.itsClusterMap(), + track.itsChi2NCl(), lepton1.itsChi2NCl(), lepton2.itsChi2NCl(), + track.tpcNClsFound(), lepton1.tpcNClsFound(), lepton2.tpcNClsFound(), + track.tpcChi2NCl(), lepton1.tpcChi2NCl(), lepton2.tpcChi2NCl(), + dilepton.filterMap_raw(), trackSelection, mcDecision); } if constexpr (TCandidateType == VarManager::kDstarToD0KPiPi) { @@ -3739,11 +3825,6 @@ struct AnalysisDileptonTrack { } } // end loop over track cuts } // end loop over dilepton cuts - // table to be written out for ML analysis - BmesonsTable(fValuesHadron[VarManager::kPairMass], dilepton.mass(), fValuesHadron[VarManager::kDeltaMass], fValuesHadron[VarManager::kPairPt], - fValuesHadron[VarManager::kVertexingLxy], fValuesHadron[VarManager::kVertexingLxyz], fValuesHadron[VarManager::kVertexingLz], - fValuesHadron[VarManager::kVertexingTauxy], fValuesHadron[VarManager::kVertexingTauz], fValuesHadron[VarManager::kKFDCAxyzBetweenProngs], - fValuesHadron[VarManager::kCosPointingAngle], fValuesHadron[VarManager::kVertexingChi2PCA], dilepton.filterMap_raw(), trackSelection, mcDecision); } // end loop over associations } // end loop over dileptons } diff --git a/PWGDQ/Tasks/dqFlow.cxx b/PWGDQ/Tasks/dqFlow.cxx index cdbee28a8a0..52e3ca8c29c 100644 --- a/PWGDQ/Tasks/dqFlow.cxx +++ b/PWGDQ/Tasks/dqFlow.cxx @@ -66,7 +66,7 @@ using MyBcs = soa::Join; using MyEvents = soa::Join; using MyEventsWithCent = soa::Join; -using MyEventsWithCentRun3 = soa::Join; +using MyEventsWithCentRun3 = soa::Join; // using MyEventsWithCentQvectRun3 = soa::Join; // using MyEventsWithCentQvectRun3 = soa::Join; using MyEventsWithCentQvectRun3 = soa::Join; diff --git a/PWGDQ/Tasks/filterPP.cxx b/PWGDQ/Tasks/filterPP.cxx index c9239f8366d..4f3527f07ca 100644 --- a/PWGDQ/Tasks/filterPP.cxx +++ b/PWGDQ/Tasks/filterPP.cxx @@ -11,35 +11,39 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.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/CCDB/TriggerAliases.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/filterTables.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/CutsLibrary.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 using std::cout; using std::endl; @@ -179,8 +183,8 @@ struct DQBarrelTrackSelection { Configurable fConfigCuts{"cfgBarrelTrackCuts", "jpsiPID1", "Comma separated list of barrel track cuts"}; Configurable fConfigQA{"cfgWithQA", false, "If true, fill QA histograms"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "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"}; diff --git a/PWGDQ/Tasks/filterPPwithAssociation.cxx b/PWGDQ/Tasks/filterPPwithAssociation.cxx index 532482e641b..90d1e4942b4 100644 --- a/PWGDQ/Tasks/filterPPwithAssociation.cxx +++ b/PWGDQ/Tasks/filterPPwithAssociation.cxx @@ -11,44 +11,48 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.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/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/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/filterTables.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/CutsLibrary.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/LHCConstants.h" -#include "Common/Core/CollisionAssociation.h" -#include "Common/DataModel/CollisionAssociationTables.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 "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include using std::cout; using std::endl; @@ -83,9 +87,9 @@ DECLARE_SOA_COLUMN(IsDQBarrelSelected, isDQBarrelSelected, uint32_t); DECLARE_SOA_COLUMN(IsDQMuonSelected, isDQMuonSelected, uint32_t); DECLARE_SOA_COLUMN(IsDQEMuBarrelSelected, isDQEMuBarrelSelected, uint32_t); // for electron-muon pair DECLARE_SOA_COLUMN(IsDQEMuMuonSelected, isDQEMuMuonSelected, uint32_t); // for electron-muon pair -DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! Collision index -DECLARE_SOA_INDEX_COLUMN(Track, track); //! Track index -DECLARE_SOA_INDEX_COLUMN(FwdTrack, fwdtrack); //! FwdTrack index +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! Collision index +DECLARE_SOA_INDEX_COLUMN(Track, track); //! Track index +DECLARE_SOA_INDEX_COLUMN(FwdTrack, fwdtrack); //! FwdTrack index } // namespace dqppfilter DECLARE_SOA_TABLE(DQEventCuts, "AOD", "DQEVENTCUTS", dqppfilter::IsDQEventSelected); @@ -160,7 +164,7 @@ struct DQEventSelectionTask { fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); DefineHistograms(fHistMan, "Event_BeforeCuts;Event_AfterCuts;", fConfigHistClasses.value); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } } @@ -210,8 +214,8 @@ struct DQBarrelTrackSelection { Configurable fConfigQA{"cfgWithQA", false, "If true, fill QA histograms"}; Configurable fConfigHistClasses{"cfgHistClasses", "its,tpcpid,dca", "If true, fill QA histograms"}; Configurable fPropTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/i/iarsene/Calib/TPCpostCalib", "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"}; @@ -266,7 +270,7 @@ struct DQBarrelTrackSelection { } DefineHistograms(fHistMan, cutNames.Data(), fConfigHistClasses.value); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); // CCDB configuration @@ -384,7 +388,7 @@ struct DQMuonsSelection { Configurable fConfigQA{"cfgWithQA", false, "If true, fill QA histograms"}; Configurable fConfigHistClasses{"cfgHistClasses", "muon", "If true, fill QA histograms"}; Configurable fPropMuon{"cfgPropMuon", false, "Propgate muon tracks through absorber"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; @@ -441,7 +445,7 @@ struct DQMuonsSelection { } DefineHistograms(fHistMan, cutNames.Data(), fConfigHistClasses.value); // define all histograms - VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); } } @@ -530,7 +534,7 @@ struct DQFilterPPTask { Configurable fConfigFilterLsMuonsPairs{"cfgWithMuonLS", "false", "Comma separated list of booleans for each trigger, If true, also select like sign (--/++) muon pairs"}; Configurable fConfigFilterLsElectronMuonsPairs{"cfgWithElectronMuonLS", "false", "Comma separated list of booleans for each trigger, If true, also select like sign (--/++) muon pairs"}; Configurable fPropMuon{"cfgPropMuon", false, "Propgate muon tracks through absorber"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; @@ -539,21 +543,21 @@ struct DQFilterPPTask { int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. - int fNBarrelCuts; // number of barrel selections - int fNMuonCuts; // number of muon selections - int fNElectronMuonCuts; // number of electron-muon selections - std::vector fBarrelRunPairing; // bit map on whether the selections require pairing (barrel) - std::vector fMuonRunPairing; // bit map on whether the selections require pairing (muon) - std::vector fElectronMuonRunPairing; // bit map on whether the selections require pairing (e-mu) - std::vector fBarrelNreqObjs; // minimal number of tracks/pairs required (barrel) - std::vector fMuonNreqObjs; // minimal number of tracks/pairs required (muon) - std::vector fElectronMuonNreqObjs; // minimal number of electron-muon pairs required - std::map fBarrelPairCuts; // map of barrel pair cuts - std::map fMuonPairCuts; // map of muon pair cuts + int fNBarrelCuts; // number of barrel selections + int fNMuonCuts; // number of muon selections + int fNElectronMuonCuts; // number of electron-muon selections + std::vector fBarrelRunPairing; // bit map on whether the selections require pairing (barrel) + std::vector fMuonRunPairing; // bit map on whether the selections require pairing (muon) + std::vector fElectronMuonRunPairing; // bit map on whether the selections require pairing (e-mu) + std::vector fBarrelNreqObjs; // minimal number of tracks/pairs required (barrel) + std::vector fMuonNreqObjs; // minimal number of tracks/pairs required (muon) + std::vector fElectronMuonNreqObjs; // minimal number of electron-muon pairs required + std::map fBarrelPairCuts; // map of barrel pair cuts + std::map fMuonPairCuts; // map of muon pair cuts std::map fElectronMuonPairCuts; // map of electron-muon pair cuts - std::map fBarrelPairHistNames; // map with names of the barrel pairing histogram directories - std::map fMuonPairHistNames; // map with names of the muon pairing histogram directories - std::map fElectronMuonPairHistNames; // map with names of the electron-muon pairing histogram directories + std::map fBarrelPairHistNames; // map with names of the barrel pairing histogram directories + std::map fMuonPairHistNames; // map with names of the muon pairing histogram directories + std::map fElectronMuonPairHistNames; // map with names of the electron-muon pairing histogram directories std::map fFiltersMap; // map of filters for events that passed at least one filter std::map> fCEFPfilters; // map of CEFP filters for events that passed at least one filter @@ -771,7 +775,7 @@ struct DQFilterPPTask { if (objCountersBarrel[i] > 1) { // pairing has to be enabled and at least two tracks are needed pairingMask |= (static_cast(1) << i); } - objCountersBarrel[i] = 0; // reset counters for selections where pairing is needed (count pairs instead) + objCountersBarrel[i] = 0; // reset counters for selections where pairing is needed (count pairs instead) taggedCollisions[i].clear(); // empty the list of tagged collisions if pairing is needed (so we count just events with pairs or containing selected pair legs) } } @@ -848,7 +852,7 @@ struct DQFilterPPTask { if (objCountersMuon[i] > 1) { pairingMask |= (static_cast(1) << i); } - objCountersMuon[i] = 0; // reset counters for selections where pairing is needed (count pairs instead) + objCountersMuon[i] = 0; // reset counters for selections where pairing is needed (count pairs instead) taggedCollisions[i + fNBarrelCuts].clear(); // empty the list of tagged collisions if pairing is needed (so we count just events with pairs or containing selected pair legs) } } diff --git a/PWGDQ/Tasks/mchAlignRecord.cxx b/PWGDQ/Tasks/mchAlignRecord.cxx index 2f612493b6e..c3dbce0865f 100644 --- a/PWGDQ/Tasks/mchAlignRecord.cxx +++ b/PWGDQ/Tasks/mchAlignRecord.cxx @@ -14,63 +14,61 @@ /// /// \author Chi ZHANG, CEA-Saclay, chi.zhang@cern.ch -#include -#include -#include -#include -#include -#include -#include +#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 "CommonConstants/LHCConstants.h" -#include "CommonUtils/NameConf.h" -#include "Common/DataModel/EventSelection.h" -#include "PWGDQ/Core/VarManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DetectorsBase/GeometryManager.h" -#include "DetectorsBase/GRPGeomHelper.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/Logger.h" -#include "Framework/CallbackService.h" -#include "CCDB/BasicCCDBManager.h" - -#include "MCHGeometryTransformer/Transformations.h" -#include "DataFormatsMCH/Cluster.h" -#include "DataFormatsMCH/TrackMCH.h" -#include "MCHTracking/Track.h" -#include "MCHTracking/TrackExtrap.h" -#include "MCHTracking/TrackParam.h" -#include "MCHTracking/TrackFitter.h" -#include "MCHBase/TrackerParam.h" -#include "ReconstructionDataFormats/TrackMCHMID.h" -#include "MCHAlign/Aligner.h" -#include "DetectorsCommonDataFormats/AlignParam.h" -#include "DetectorsCommonDataFormats/DetID.h" -#include "DetectorsCommonDataFormats/DetectorNameConf.h" +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -105,13 +103,13 @@ struct mchAlignRecordTask { map transformNew; mch::geo::TransformationCreator transformation; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable fFixChamber{"fix-chamber", "", "Fixing chamber"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable fFixChamber{"fix-chamber", "", "Fixing chamber"}; Configurable fDoNewGeo{"do-realign", false, "Transform to a given new geometry"}; Configurable fDoEvaluation{"do-evaluation", false, "Enable storage of residuals"}; - Configurable fConfigNewGeoFile{"new-geo", "o2sim_geometry-aligned.root", "New geometry for transformation"}; + Configurable fConfigNewGeoFile{"new-geo", "o2sim_geometry-aligned.root", "New geometry for transformation"}; Configurable fAllowedVarX{"variation-x", 2.0, "Allowed variation for x axis in cm"}; Configurable fAllowedVarY{"variation-y", 0.3, "Allowed variation for y axis in cm"}; Configurable fAllowedVarPhi{"variation-phi", 0.002, "Allowed variation for phi axis in rad"}; diff --git a/PWGDQ/Tasks/muonDCA.cxx b/PWGDQ/Tasks/muonDCA.cxx index b2031418d5c..897ed273322 100644 --- a/PWGDQ/Tasks/muonDCA.cxx +++ b/PWGDQ/Tasks/muonDCA.cxx @@ -13,14 +13,15 @@ /// \brief Task to compute and evaluate DCA quantities /// \author Nicolas Bizé , SUBATECH // -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "GlobalTracking/MatchGlobalFwd.h" +#include "PWGDQ/Core/VarManager.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" + #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGDQ/Core/VarManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "GlobalTracking/MatchGlobalFwd.h" using namespace o2; using namespace o2::framework; @@ -44,7 +45,7 @@ struct muonExtrap { Produces dcaTable; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Service fCCDB; o2::parameters::GRPMagField* grpmag = nullptr; // for run 3, we access GRPMagField from GLO/Config/GRPMagField diff --git a/PWGDQ/Tasks/tableReader.cxx b/PWGDQ/Tasks/tableReader.cxx index eb5d6dae897..102eb26100f 100644 --- a/PWGDQ/Tasks/tableReader.cxx +++ b/PWGDQ/Tasks/tableReader.cxx @@ -11,39 +11,44 @@ // // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGDQ/Core/VarManager.h" -#include "PWGDQ/Core/HistogramManager.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/AnalysisCompositeCut.h" -#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/CutsLibrary.h" +#include "PWGDQ/Core/DQMlResponse.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 "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" -#include "Field/MagneticField.h" -#include "TGeoGlobalMagField.h" -#include "DetectorsBase/Propagator.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 "Common/CCDB/EventSelectionParams.h" + +#include "TGeoGlobalMagField.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include using std::cout; using std::endl; @@ -157,14 +162,14 @@ struct AnalysisEventSelection { Produces hash; OutputObj fOutputList{"output"}; // TODO: Provide the mixing variables and binning directly via configurables (e.g. vectors of float) - Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; - Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; + Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro [WARNING: under debug, do not enable!]"}; Configurable fConfigITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; Configurable fConfigITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; HistogramManager* fHistMan = nullptr; MixingHandler* fMixHandler = nullptr; @@ -218,11 +223,12 @@ struct AnalysisEventSelection { void runEventSelection(TEvent const& event) { if (event.runNumber() != fLastRun) { - auto alppar = fCCDB->getForTimeStamp>("ITS/Config/AlpideParam", event.timestamp()); - EventSelectionParams* par = fCCDB->getForTimeStamp("EventSelection/EventSelectionParams", event.timestamp()); - int itsROFrameStartBorderMargin = fConfigITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : fConfigITSROFrameStartBorderMargin; - int itsROFrameEndBorderMargin = fConfigITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : fConfigITSROFrameEndBorderMargin; - VarManager::SetITSROFBorderselection(alppar->roFrameBiasInBC, alppar->roFrameLengthInBC, itsROFrameStartBorderMargin, itsROFrameEndBorderMargin); + // Part temporary removed to study the issue to run on derived data on hyperloop + // auto alppar = fCCDB->getForTimeStamp>("ITS/Config/AlpideParam", event.timestamp()); + // EventSelectionParams* par = fCCDB->getForTimeStamp("EventSelection/EventSelectionParams", event.timestamp()); + // int itsROFrameStartBorderMargin = fConfigITSROFrameStartBorderMargin < 0 ? par->fITSROFrameStartBorderMargin : fConfigITSROFrameStartBorderMargin; + // int itsROFrameEndBorderMargin = fConfigITSROFrameEndBorderMargin < 0 ? par->fITSROFrameEndBorderMargin : fConfigITSROFrameEndBorderMargin; + // VarManager::SetITSROFBorderselection(alppar->roFrameBiasInBC, alppar->roFrameLengthInBC, itsROFrameStartBorderMargin, itsROFrameEndBorderMargin); fLastRun = event.runNumber(); } @@ -317,12 +323,12 @@ struct AnalysisTrackSelection { // for candidate electron selection (+ eventual prefilter cuts) and other needs like quarkonium - hadron correlations // The user must ensure using them properly in the tasks downstream // NOTE: For now, the candidate electron cuts must be provided first, then followed by any other needed selections - Configurable fConfigCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable fConfigCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; - Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; Configurable fConfigPrefilterCutId{"cfgPrefilterCutId", 32, "Id of the Prefilter track cut (starting at 0)"}; // In order to create another column prefilter (should be temporary before improving cut selection in configurables, then displaced to AnalysisPrefilterSelection) - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; Configurable fConfigRunPeriods{"cfgRunPeriods", "LHC22f", "run periods for used data"}; @@ -452,7 +458,7 @@ struct AnalysisTrackSelection { struct AnalysisMuonSelection { Produces muonSel; OutputObj fOutputList{"output"}; - Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; + Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigAddMuonHistogram{"cfgAddMuonHistogram", "", "Comma separated list of histograms"}; @@ -672,14 +678,14 @@ struct AnalysisEventMixing { // single particle selection tasks to preserve the correspondence between the track cut name and its // bit position in the cuts bitmap // TODO: Create a configurable to specify exactly on which of the bits one should run the event mixing - Configurable fConfigTrackCuts{"cfgTrackCuts", "", "Comma separated list of barrel track cuts"}; - Configurable fConfigMuonCuts{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; + Configurable fConfigTrackCuts{"cfgTrackCuts", "", "Comma separated list of barrel track cuts"}; + Configurable fConfigMuonCuts{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; Configurable fConfigMixingDepth{"cfgMixingDepth", 100, "Number of Events stored for event mixing"}; Configurable fConfigAddEventMixingHistogram{"cfgAddEventMixingHistogram", "", "Comma separated list of histograms"}; Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable fConfigAmbiguousHist{"cfgAmbiHist", false, "Enable Ambiguous histograms for time association studies"}; - Configurable ccdbPathFlow{"ccdb-path-flow", "Users/c/chizh/FlowResolution", "path to the ccdb object for flow resolution factors"}; + Configurable ccdbPathFlow{"ccdb-path-flow", "Users/c/chizh/FlowResolution", "path to the ccdb object for flow resolution factors"}; Configurable fConfigFlowReso{"cfgFlowReso", false, "Enable loading of flow resolution factors from CCDB"}; Configurable fConfigSingleMuCumulants{"cfgSingleMuCumulants", false, "Enable loading of flow resolution factors from CCDB"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; @@ -1022,12 +1028,12 @@ struct AnalysisSameEventPairing { int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. OutputObj fOutputList{"output"}; - Configurable fConfigTrackCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; - Configurable fConfigMuonCuts{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; - Configurable fConfigPairCuts{"cfgPairCuts", "", "Comma separated list of pair cuts"}; - Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable ccdbPath{"ccdb-path", "Users/lm", "base path to the ccdb object"}; - Configurable ccdbPathFlow{"ccdb-path-flow", "Users/c/chizh/FlowResolution", "path to the ccdb object for flow resolution factors"}; + Configurable fConfigTrackCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable fConfigMuonCuts{"cfgMuonCuts", "", "Comma separated list of muon cuts"}; + Configurable fConfigPairCuts{"cfgPairCuts", "", "Comma separated list of pair cuts"}; + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPath{"ccdb-path", "Users/lm", "base path to the ccdb object"}; + Configurable ccdbPathFlow{"ccdb-path-flow", "Users/c/chizh/FlowResolution", "path to the ccdb object for flow resolution factors"}; Configurable fConfigFlowReso{"cfgFlowReso", false, "Enable loading of flow resolution factors from 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 fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; @@ -1049,6 +1055,12 @@ struct AnalysisSameEventPairing { Configurable fCenterMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; Configurable fConfigCumulants{"cfgCumulants", false, "If true, fill Cumulants with Weights different than 0"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; + // ML inference + Configurable applyBDT{"applyBDT", false, "Flag to apply ML selections"}; + Configurable fConfigBdtCutsJSON{"fConfigBdtCutsJSON", "", "Additional list of BDT cuts in JSON format"}; + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"Users/j/jseo/ML/PbPbPsi/default/"}, "Paths of models on CCDB"}; + 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"}; // Configurables to create output tree (flat tables or minitree) struct : ConfigurableGroup { @@ -1066,6 +1078,10 @@ struct AnalysisSameEventPairing { HistogramManager* fHistMan; + o2::analysis::DQMlResponse fDQMlResponse; + std::vector fOutputMlPsi2ee = {}; // TODO: check this is needed or not + o2::ccdb::CcdbApi ccdbApi; + // NOTE: The track filter produced by the barrel track selection contain a number of electron cut decisions and one last cut for hadrons used in the // dilepton - hadron task downstream. So the bit mask is required to select pairs just based on the electron cuts // TODO: provide as Configurable the list and names of the cuts which should be used in pairing @@ -1116,6 +1132,54 @@ struct AnalysisSameEventPairing { } } + if (applyBDT) { + // BDT cuts via JSON + std::vector binsMl; + o2::framework::LabeledArray cutsMl; + std::vector cutDirMl; + int nClassesMl = 1; + std::vector namesInputFeatures; + std::vector onnxFileNames; + + auto config = o2::aod::dqmlcuts::GetBdtScoreCutsAndConfigFromJSON(fConfigBdtCutsJSON.value.c_str()); + + if (std::holds_alternative(config)) { + auto& cfg = std::get(config); + binsMl = cfg.binsMl; + nClassesMl = 1; + cutsMl = cfg.cutsMl; + cutDirMl = cfg.cutDirs; + namesInputFeatures = cfg.inputFeatures; + onnxFileNames = cfg.onnxFiles; + fDQMlResponse.setBinsCent(cfg.binsCent); + fDQMlResponse.setBinsPt(cfg.binsPt); + fDQMlResponse.setCentType(cfg.centType); + LOG(info) << "Using BDT cuts for binary classification"; + } else { + auto& cfg = std::get(config); + binsMl = cfg.binsMl; + nClassesMl = 3; + cutsMl = cfg.cutsMl; + cutDirMl = cfg.cutDirs; + namesInputFeatures = cfg.inputFeatures; + onnxFileNames = cfg.onnxFiles; + fDQMlResponse.setBinsCent(cfg.binsCent); + fDQMlResponse.setBinsPt(cfg.binsPt); + fDQMlResponse.setCentType(cfg.centType); + LOG(info) << "Using BDT cuts for multiclass classification"; + } + + fDQMlResponse.configure(binsMl, cutsMl, cutDirMl, nClassesMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdburl); + fDQMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + fDQMlResponse.setModelPathsLocal(onnxFileNames); + } + fDQMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + fDQMlResponse.init(); + } + if (context.mOptions.get("processDecayToEESkimmed") || context.mOptions.get("processDecayToEESkimmedNoTwoProngFitter") || context.mOptions.get("processDecayToEESkimmedWithCov") || context.mOptions.get("processDecayToEESkimmedWithCovNoTwoProngFitter") || context.mOptions.get("processDecayToEEVertexingSkimmed") || context.mOptions.get("processVnDecayToEESkimmed") || context.mOptions.get("processDecayToEEPrefilterSkimmed") || context.mOptions.get("processDecayToEEPrefilterSkimmedNoTwoProngFitter") || context.mOptions.get("processDecayToEESkimmedWithColl") || context.mOptions.get("processDecayToEESkimmedWithCollNoTwoProngFitter") || context.mOptions.get("processDecayToPiPiSkimmed") || context.mOptions.get("processAllSkimmed")) { TString cutNames = fConfigTrackCuts.value; if (!cutNames.IsNull()) { // if track cuts @@ -1312,6 +1376,8 @@ struct AnalysisSameEventPairing { dileptonMiniTree.reserve(1); } + bool isSelectedBDT = false; + if (fConfigMultDimuons.value) { uint32_t mult_dimuons = 0; @@ -1390,6 +1456,43 @@ struct AnalysisSameEventPairing { } } if constexpr ((TPairType == pairTypeEE) && (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { + if (applyBDT) { + std::vector dqInputFeatures = fDQMlResponse.getInputFeatures(t1, t2, VarManager::fgValues); + + if (dqInputFeatures.empty()) { + LOG(fatal) << "Input features for ML selection are empty! Please check your configuration."; + return; + } + + int modelIndex = -1; + const auto& binsCent = fDQMlResponse.getBinsCent(); + const auto& binsPt = fDQMlResponse.getBinsPt(); + const std::string& centType = fDQMlResponse.getCentType(); + + if ("kCentFT0C" == centType) { + modelIndex = o2::aod::dqmlcuts::getMlBinIndex(VarManager::fgValues[VarManager::kCentFT0C], VarManager::fgValues[VarManager::kPt], binsCent, binsPt); + } else if ("kCentFT0A" == centType) { + modelIndex = o2::aod::dqmlcuts::getMlBinIndex(VarManager::fgValues[VarManager::kCentFT0A], VarManager::fgValues[VarManager::kPt], binsCent, binsPt); + } else if ("kCentFT0M" == centType) { + modelIndex = o2::aod::dqmlcuts::getMlBinIndex(VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kPt], binsCent, binsPt); + } else { + LOG(fatal) << "Unknown centrality estimation type: " << centType; + return; + } + + if (modelIndex < 0) { + LOG(debug) << "Ml index is negative! This means that the centrality/pt is not in the range of the model bins."; + continue; + } + + LOG(debug) << "Model index: " << modelIndex << ", pT: " << VarManager::fgValues[VarManager::kPt] << ", centrality (kCentFT0C): " << VarManager::fgValues[VarManager::kCentFT0C]; + isSelectedBDT = fDQMlResponse.isSelectedMl(dqInputFeatures, modelIndex, fOutputMlPsi2ee); + VarManager::FillBdtScore(fOutputMlPsi2ee); // TODO: check if this is needed or not + } + + if (applyBDT && !isSelectedBDT) + continue; + if (fConfigFlatTables.value) { dielectronAllList(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], t1.sign() + t2.sign(), dileptonFilterMap, dileptonMcDecision, t1.pt(), t1.eta(), t1.phi(), t1.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(), @@ -1463,6 +1566,9 @@ struct AnalysisSameEventPairing { } } + if (applyBDT && !isSelectedBDT) + continue; + int iCut = 0; for (int icut = 0; icut < ncuts; icut++) { if (twoTrackFilter & (static_cast(1) << icut)) { @@ -1475,17 +1581,16 @@ struct AnalysisSameEventPairing { // By default (kPt1, kEta1, kPhi1) are for the positive charge float dileptonMass = VarManager::fgValues[VarManager::kMass]; if (dileptonMass > useMiniTree.fConfigMiniTreeMinMass && dileptonMass < useMiniTree.fConfigMiniTreeMaxMass) { - dileptonMiniTree(VarManager::fgValues[VarManager::kMass], - VarManager::fgValues[VarManager::kPt], - VarManager::fgValues[VarManager::kRap], - VarManager::fgValues[VarManager::kCentFT0C], - VarManager::fgValues[VarManager::kCos2DeltaPhi], - VarManager::fgValues[VarManager::kPt1], - VarManager::fgValues[VarManager::kEta1], - VarManager::fgValues[VarManager::kPhi1], - VarManager::fgValues[VarManager::kPt2], - VarManager::fgValues[VarManager::kEta2], - VarManager::fgValues[VarManager::kPhi2]); + // In the miniTree the positive daughter is positioned as first + if (t1.sign() > 0) { + dileptonMiniTree(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kRap], + VarManager::fgValues[VarManager::kCentFT0C], VarManager::fgValues[VarManager::kCos2DeltaPhi], + t1.pt(), t1.eta(), t1.phi(), t2.pt(), t2.eta(), t2.phi()); + } else { + dileptonMiniTree(VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kRap], + VarManager::fgValues[VarManager::kCentFT0C], VarManager::fgValues[VarManager::kCos2DeltaPhi], + t2.pt(), t2.eta(), t2.phi(), t1.pt(), t1.eta(), t1.phi()); + } } } } else { @@ -1738,7 +1843,7 @@ struct AnalysisDileptonHadron { OutputObj fOutputList{"output"}; // TODO: For now this is only used to determine the position in the filter bit map for the hadron cut - Configurable fConfigTrackCuts{"cfgLeptonCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable fConfigTrackCuts{"cfgLeptonCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; // comment: add list of subgroups (must define subgroups under ) Configurable fConfigAddDileptonHadHistogram{"cfgAddDileptonHadHistogram", "", "Comma separated list of histograms"}; Configurable fConfigMixingDepth{"cfgMixingDepth", 5, "Event mixing pool depth"}; @@ -1959,6 +2064,8 @@ struct AnalysisDileptonTrackTrack { Configurable fConfigQuadrupletCuts{"cfgQuadrupletCuts", "pairX3872Cut1", "Comma separated list of Dilepton-Track-Track cut"}; Configurable fConfigAddDileptonHistogram{"cfgAddDileptonHistogram", "barrel", "Comma separated list of histograms"}; Configurable fConfigAddQuadrupletHistogram{"cfgAddQuadrupletHistogram", "xtojpsipipi", "Comma separated list of histograms"}; + Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigUseDCAVertexing{"cfgUseDCAVertexing", false, "Use DCA for secondary vertex reconstruction (DCAFitter is used by default)"}; Produces DileptonTrackTrackTable; @@ -1969,7 +2076,6 @@ struct AnalysisDileptonTrackTrack { constexpr static uint32_t fgDileptonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::Pair; // fill map // use some values array to avoid mixing up the quantities - float* fValuesDitrack; float* fValuesQuadruplet; HistogramManager* fHistMan; @@ -2010,7 +2116,7 @@ struct AnalysisDileptonTrackTrack { } if (!context.mOptions.get("processDummy")) { - DefineHistograms(fHistMan, Form("Dileptons_%s", configDileptonCutNamesStr.Data()), fConfigAddDileptonHistogram); + DefineHistograms(fHistMan, Form("Pairs_%s", configDileptonCutNamesStr.Data()), fConfigAddDileptonHistogram); if (!configQuadruletCutNamesStr.IsNull()) { for (std::size_t icut = 0; icut < fQuadrupletCutNames.size(); ++icut) { if (fIsSameTrackCut) { @@ -2037,6 +2143,25 @@ struct AnalysisDileptonTrackTrack { // LOGF(info, "Number of dileptons: %d", dileptons.size()); + // set up KF or DCAfitter + if (fConfigUseDCAVertexing) { + VarManager::SetupTwoProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + // VarManager::SetupThreeProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(5.0f, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } else if (fConfigUseKFVertexing) { + VarManager::SetupFourProngKFParticle(5.0f); + } + + int indexOffset = -999; + std::vector trackGlobalIndexes; + + if (dileptons.size() > 0) { + for (auto track : tracks) { + trackGlobalIndexes.push_back(track.globalIndex()); + // std::cout << track.index() << " " << track.globalIndex() << std::endl; + } + } + // loop over dileptons for (auto dilepton : dileptons) { VarManager::FillTrack(dilepton, fValuesQuadruplet); @@ -2045,12 +2170,20 @@ struct AnalysisDileptonTrackTrack { if (!fDileptonCut.IsSelected(fValuesQuadruplet)) continue; - fHistMan->FillHistClass(Form("Dileptons_%s", fDileptonCut.GetName()), fValuesQuadruplet); + fHistMan->FillHistClass(Form("Pairs_%s", fDileptonCut.GetName()), fValuesQuadruplet); // get the index of the electron legs int indexLepton1 = dilepton.index0Id(); int indexLepton2 = dilepton.index1Id(); + if (indexOffset == -999) { + indexOffset = trackGlobalIndexes.at(0); + } + trackGlobalIndexes.clear(); + + auto lepton1 = tracks.iteratorAt(indexLepton1 - indexOffset); + auto lepton2 = tracks.iteratorAt(indexLepton2 - indexOffset); + // loop over hadrons pairs for (auto& [t1, t2] : combinations(tracks, tracks)) { // avoid self-combinations @@ -2070,6 +2203,10 @@ struct AnalysisDileptonTrackTrack { // fill variables VarManager::FillDileptonTrackTrack(dilepton, t1, t2, fValuesQuadruplet); + // reconstruct the secondary vertex + if (fConfigUseDCAVertexing || fConfigUseKFVertexing) { + VarManager::FillDileptonTrackTrackVertexing(event, lepton1, lepton2, t1, t2, fValuesQuadruplet); + } int iCut = 0; uint32_t CutDecision = 0; @@ -2102,22 +2239,33 @@ struct AnalysisDileptonTrackTrack { DileptonTrackTrackTable(fValuesQuadruplet[VarManager::kQuadMass], fValuesQuadruplet[VarManager::kQuadPt], fValuesQuadruplet[VarManager::kQuadEta], fValuesQuadruplet[VarManager::kQuadPhi], fValuesQuadruplet[VarManager::kRap], fValuesQuadruplet[VarManager::kQ], fValuesQuadruplet[VarManager::kDeltaR1], fValuesQuadruplet[VarManager::kDeltaR2], fValuesQuadruplet[VarManager::kDeltaR], dilepton.mass(), dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.sign(), - fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign()); + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton1.tpcNClsFound(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), lepton2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], t1.pt(), t2.pt(), t1.eta(), t2.eta(), t1.phi(), t2.phi(), t1.sign(), t2.sign(), t1.tpcNSigmaPi(), t2.tpcNSigmaPi(), t1.tpcNSigmaKa(), t2.tpcNSigmaKa(), t1.tpcNSigmaPr(), t1.tpcNSigmaPr(), t1.tpcNClsFound(), t2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kKFMass], fValuesQuadruplet[VarManager::kVertexingProcCode], fValuesQuadruplet[VarManager::kVertexingChi2PCA], fValuesQuadruplet[VarManager::kCosPointingAngle], fValuesQuadruplet[VarManager::kKFDCAxyzBetweenProngs], fValuesQuadruplet[VarManager::kKFChi2OverNDFGeo], + fValuesQuadruplet[VarManager::kVertexingLz], fValuesQuadruplet[VarManager::kVertexingLxy], fValuesQuadruplet[VarManager::kVertexingLxyz], fValuesQuadruplet[VarManager::kVertexingTauz], fValuesQuadruplet[VarManager::kVertexingTauxy], fValuesQuadruplet[VarManager::kVertexingLzErr], fValuesQuadruplet[VarManager::kVertexingLxyzErr], + fValuesQuadruplet[VarManager::kVertexingTauzErr], fValuesQuadruplet[VarManager::kVertexingLzProjected], fValuesQuadruplet[VarManager::kVertexingLxyProjected], fValuesQuadruplet[VarManager::kVertexingLxyzProjected], fValuesQuadruplet[VarManager::kVertexingTauzProjected], fValuesQuadruplet[VarManager::kVertexingTauxyProjected]); } // end loop over track-track pairs } // end loop over dileptons } - void processJpsiPiPi(soa::Filtered::iterator const& event, MyBarrelTracksSelectedWithCov const& tracks, soa::Filtered const& dileptons) + void processChicToJpsiPiPi(soa::Filtered::iterator const& event, MyBarrelTracksSelectedWithCov const& tracks, soa::Filtered const& dileptons) { runDileptonTrackTrack(event, tracks, dileptons); } + void processPsi2SToJpsiPiPi(soa::Filtered::iterator const& event, MyBarrelTracksSelectedWithCov const& tracks, soa::Filtered const& dileptons) + { + runDileptonTrackTrack(event, tracks, dileptons); + } + void processDummy(MyEvents&) { // do nothing } - PROCESS_SWITCH(AnalysisDileptonTrackTrack, processJpsiPiPi, "Run dilepton-dihadron pairing to study X(3872), using skimmed data", false); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processChicToJpsiPiPi, "Run dilepton-dihadron pairing to study X(3872), using skimmed data", false); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processPsi2SToJpsiPiPi, "Run dilepton-dihadron pairing to study Psi(2S), using skimmed data", false); PROCESS_SWITCH(AnalysisDileptonTrackTrack, processDummy, "Dummy function", false); }; diff --git a/PWGDQ/Tasks/tableReader_withAssoc.cxx b/PWGDQ/Tasks/tableReader_withAssoc.cxx index c17a0b3d24c..ae6c450ac3e 100644 --- a/PWGDQ/Tasks/tableReader_withAssoc.cxx +++ b/PWGDQ/Tasks/tableReader_withAssoc.cxx @@ -12,51 +12,55 @@ // 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/DQMlResponse.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 "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/Configurable.h" -#include "Framework/OutputObjHeader.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGDQ/Core/VarManager.h" -#include "PWGDQ/Core/HistogramManager.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/AnalysisCut.h" -#include "PWGDQ/Core/AnalysisCompositeCut.h" -#include "PWGDQ/Core/HistogramsLibrary.h" -#include "PWGDQ/Core/CutsLibrary.h" -#include "PWGDQ/Core/MixingLibrary.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "Field/MagneticField.h" -#include "TGeoGlobalMagField.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "Common/Core/TableHelper.h" -#include "ITSMFTBase/DPLAlpideParam.h" -#include "Common/CCDB/EventSelectionParams.h" +#include using std::cout; using std::endl; @@ -95,12 +99,13 @@ DECLARE_SOA_COLUMN(TauzBcandidate, tauzBcandidate, float); DECLARE_SOA_COLUMN(CosPBcandidate, cosPBcandidate, float); DECLARE_SOA_COLUMN(Chi2Bcandidate, chi2Bcandidate, float); DECLARE_SOA_COLUMN(Ptassoc, ptassoc, float); +DECLARE_SOA_COLUMN(PINassoc, pINassoc, float); DECLARE_SOA_COLUMN(Etaassoc, etaassoc, 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(Ptleg2, ptleg2, float); +DECLARE_SOA_COLUMN(PINleg2, pINleg2, float); DECLARE_SOA_COLUMN(Etaleg2, etaleg2, float); DECLARE_SOA_COLUMN(TPCnsigmaKaassoc, tpcnsigmaKaassoc, float); DECLARE_SOA_COLUMN(TPCnsigmaPiassoc, tpcnsigmaPiassoc, float); @@ -139,6 +144,9 @@ DECLARE_SOA_COLUMN(LxyeePoleMass, lxyJPsi2eePoleMass, float); DECLARE_SOA_COLUMN(Lzee, lzJPsi2ee, float); DECLARE_SOA_COLUMN(AmbiguousInBunchPairs, AmbiguousJpsiPairsInBunch, bool); DECLARE_SOA_COLUMN(AmbiguousOutOfBunchPairs, AmbiguousJpsiPairsOutOfBunch, bool); +// Candidate columns for JPsi/muon correlations +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); } // namespace dqanalysisflags DECLARE_SOA_TABLE(EventCuts, "AOD", "DQANAEVCUTSA", dqanalysisflags::IsEventSelected); //! joinable to ReducedEvents @@ -152,8 +160,8 @@ DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONSA", dqanalysisflags::massBcandidate, dqanalysisflags::MassDileptonCandidate, dqanalysisflags::deltamassBcandidate, dqanalysisflags::pTBcandidate, dqanalysisflags::EtaBcandidate, dqanalysisflags::LxyBcandidate, dqanalysisflags::LxyzBcandidate, dqanalysisflags::LzBcandidate, dqanalysisflags::TauxyBcandidate, dqanalysisflags::TauzBcandidate, dqanalysisflags::CosPBcandidate, dqanalysisflags::Chi2Bcandidate, - dqanalysisflags::Ptassoc, dqanalysisflags::Etaassoc, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, - dqanalysisflags::Ptleg1, dqanalysisflags::Etaleg1, dqanalysisflags::Ptleg2, dqanalysisflags::Etaleg2, + 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, @@ -163,12 +171,16 @@ DECLARE_SOA_TABLE(BmesonCandidates, "AOD", "DQBMESONSA", dqanalysisflags::TPCNclsassoc, dqanalysisflags::TPCNclsleg1, dqanalysisflags::TPCNclsleg2, dqanalysisflags::TPCChi2assoc, dqanalysisflags::TPCChi2leg1, dqanalysisflags::TPCChi2leg2, dqanalysisflags::IsJpsiFromBSelected, dqanalysisflags::IsBarrelSelected); +DECLARE_SOA_TABLE(JPsiMuonCandidates, "AOD", "DQJPSIMUONA", + dqanalysisflags::DeltaEta, dqanalysisflags::DeltaPhi, + dqanalysisflags::MassDileptonCandidate, dqanalysisflags::Ptpair, dqanalysisflags::Etapair, dqanalysisflags::Ptassoc, dqanalysisflags::Etaassoc); DECLARE_SOA_TABLE(JPsieeCandidates, "AOD", "DQPSEUDOPROPER", dqanalysisflags::Massee, dqanalysisflags::Ptee, dqanalysisflags::Lxyee, dqanalysisflags::LxyeePoleMass, dqanalysisflags::Lzee, dqanalysisflags::AmbiguousInBunchPairs, dqanalysisflags::AmbiguousOutOfBunchPairs); } // namespace o2::aod // Declarations of various short names using MyEvents = soa::Join; using MyEventsMultExtra = soa::Join; +using MyEventsMultExtraQVector = soa::Join; using MyEventsZdc = soa::Join; using MyEventsMultExtraZdc = soa::Join; using MyEventsSelected = soa::Join; @@ -177,11 +189,14 @@ using MyEventsVtxCovSelectedMultExtra = soa::Join; using MyEventsVtxCov = soa::Join; using MyEventsVtxCovSelected = soa::Join; -using MyEventsVtxCovSelectedQvector = soa::Join; +using MyEventsVtxCovSelectedQvector = soa::Join; +using MyEventsVtxCovSelectedQvectorWithHash = soa::Join; using MyEventsVtxCovZdcSelected = soa::Join; using MyEventsVtxCovZdcSelectedMultExtra = soa::Join; using MyEventsQvector = soa::Join; using MyEventsHashSelectedQvector = soa::Join; +using MyEventsQvectorCentr = soa::Join; +using MyEventsQvectorCentrSelected = soa::Join; using MyBarrelTracks = soa::Join; using MyBarrelTracksWithAmbiguities = soa::Join; @@ -200,10 +215,14 @@ using MyMuonTracksSelectedWithColl = soa::Join 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 fConfigEventCuts{"cfgEventCuts", "eventStandard", "Event selection"}; - Configurable fConfigEventCutsJSON{"cfgEventCutsJSON", "", "Additional event cuts specified in JSON format"}; + 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 fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Add event histograms defined via JSON formatting (see HistogramsLibrary)"}; Configurable fConfigQA{"cfgQA", true, "If true, QA histograms will be created and filled"}; @@ -252,7 +271,7 @@ struct AnalysisEventSelection { Configurable fConfigCheckSplitCollisions{"cfgCheckSplitCollisions", false, "If true, run the split collision check and fill histograms"}; Configurable fConfigRunZorro{"cfgRunZorro", false, "Enable event selection with zorro [WARNING: under debug, do not enable!]"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable 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"}; HistogramManager* fHistMan = nullptr; @@ -270,7 +289,7 @@ struct AnalysisEventSelection { { LOG(info) << "Starting initialization of AnalysisEventSelection (idstoreh)"; - bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc"); + bool isAnyProcessEnabled = context.mOptions.get("processSkimmed") || context.mOptions.get("processSkimmedWithZdc") || context.mOptions.get("processSkimmedWithMultExtra") || context.mOptions.get("processSkimmedWithMultExtraZdc") || context.mOptions.get("processSkimmedWithQvectorCentr"); bool isDummyEnabled = context.mOptions.get("processDummy"); if (isDummyEnabled) { @@ -341,7 +360,7 @@ struct AnalysisEventSelection { void runEventSelection(TEvents const& events) { if (events.size() > 0 && events.begin().runNumber() != fCurrentRun) { - std::map metadataRCT, header; + std::map metadataRCT, header; header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", events.begin().runNumber()), metadataRCT, -1); uint64_t sor = std::atol(header["SOR"].c_str()); uint64_t eor = std::atol(header["EOR"].c_str()); @@ -507,6 +526,11 @@ struct AnalysisEventSelection { runEventSelection(events); publishSelections(events); } + void processSkimmedWithQvectorCentr(MyEventsQvectorCentr const& events) + { + runEventSelection(events); + publishSelections(events); + } void processDummy(MyEvents&) { // do nothing @@ -516,6 +540,7 @@ struct AnalysisEventSelection { 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); + PROCESS_SWITCH(AnalysisEventSelection, processSkimmedWithQvectorCentr, "Run event selection on DQ skimmed events, with Q-vector", false); PROCESS_SWITCH(AnalysisEventSelection, processDummy, "Dummy function", false); }; @@ -526,15 +551,15 @@ struct AnalysisTrackSelection { Produces trackAmbiguities; OutputObj fOutputList{"output"}; - Configurable fConfigCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; + Configurable fConfigCuts{"cfgTrackCuts", "jpsiO2MCdebugCuts2", "Comma separated list of barrel track cuts"}; Configurable fConfigCutsJSON{"cfgBarrelTrackCutsJSON", "", "Additional list of barrel track cuts in JSON format"}; - Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; 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 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"}; @@ -632,7 +657,7 @@ struct AnalysisTrackSelection { LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", events.begin().timestamp()); } - std::map metadataRCT, header; + std::map metadataRCT, header; header = fCCDBApi.retrieveHeaders(Form("RCT/Info/RunInformation/%i", events.begin().runNumber()), metadataRCT, -1); uint64_t sor = std::atol(header["SOR"].c_str()); uint64_t eor = std::atol(header["EOR"].c_str()); @@ -778,14 +803,14 @@ struct AnalysisMuonSelection { Produces muonAmbiguities; OutputObj fOutputList{"output"}; - Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; + Configurable fConfigCuts{"cfgMuonCuts", "muonQualityCuts", "Comma separated list of muon cuts"}; Configurable fConfigCutsJSON{"cfgMuonCutsJSON", "", "Additional list of muon cuts in JSON format"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigAddMuonHistogram{"cfgAddMuonHistogram", "", "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 fConfigCcdbUrl{"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 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"}; @@ -1183,6 +1208,7 @@ struct AnalysisSameEventPairing { Produces dileptonFlowList; Produces dileptonInfoList; Produces PromptNonPromptSepTable; + Produces dileptonPolarList; o2::base::MatLayerCylSet* fLUT = nullptr; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. @@ -1190,9 +1216,9 @@ struct AnalysisSameEventPairing { OutputObj fOutputList{"output"}; 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"}; + 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"}; Configurable event{"cfgRemoveCollSplittingCandidates", false, "If true, remove collision splitting candidates as determined by the event selection task upstream"}; // TODO: Add pair cuts via JSON } fConfigCuts; @@ -1204,16 +1230,18 @@ struct AnalysisSameEventPairing { Configurable fConfigQA{"cfgQA", true, "If true, fill output histograms"}; struct : ConfigurableGroup { - Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + 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"}; + Configurable GrpLhcIfPath{"grplhcif", "GLO/Config/GRPLHCIF", "Path on the CCDB for the GRPLHCIF object"}; } fConfigCCDB; struct : ConfigurableGroup { 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"}; @@ -1222,7 +1250,16 @@ struct AnalysisSameEventPairing { Configurable collisionSystem{"syst", "pp", "Collision system, pp or PbPb"}; Configurable centerMassEnergy{"energy", 13600, "Center of mass energy in GeV"}; Configurable propTrack{"cfgPropTrack", true, "Propgate tracks to associated collision to recalculate DCA and momentum vector"}; + Configurable useRemoteCollisionInfo{"cfgUseRemoteCollisionInfo", false, "Use remote collision information from CCDB"}; } fConfigOptions; + struct : ConfigurableGroup { + Configurable applyBDT{"applyBDT", false, "Flag to apply ML selections"}; + Configurable fConfigBdtCutsJSON{"fConfigBdtCutsJSON", "", "Additional list of BDT cuts in JSON format"}; + + Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{"Users/j/jseo/ML/PbPbPsi/default/"}, "Paths of models on CCDB"}; + 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"}; + } fConfigML; Service fCCDB; o2::ccdb::CcdbApi fCCDBApi; @@ -1231,6 +1268,9 @@ struct AnalysisSameEventPairing { HistogramManager* fHistMan; + o2::analysis::DQMlResponse fDQMlResponse; + std::vector fOutputMlPsi2ee = {}; // TODO: check this is needed or not + // 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; @@ -1258,8 +1298,8 @@ struct AnalysisSameEventPairing { void init(o2::framework::InitContext& context) { LOG(info) << "Starting initialization of AnalysisSameEventPairing (idstoreh)"; - fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed") || context.mOptions.get("processBarrelOnlySkimmedNoCov") || context.mOptions.get("processBarrelOnlySkimmedNoCovWithMultExtra"); - fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingBarrelSkimmed"); + fEnableBarrelHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processBarrelOnlySkimmed") || context.mOptions.get("processBarrelOnlyWithCollSkimmed") || context.mOptions.get("processBarrelOnlySkimmedNoCov") || context.mOptions.get("processBarrelOnlySkimmedNoCovWithMultExtra") || context.mOptions.get("processBarrelOnlyWithQvectorCentrSkimmedNoCov"); + fEnableBarrelMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingBarrelSkimmed") || context.mOptions.get("processMixingBarrelSkimmedFlow"); fEnableMuonHistos = context.mOptions.get("processAllSkimmed") || context.mOptions.get("processMuonOnlySkimmed") || context.mOptions.get("processMuonOnlySkimmedMultExtra") || context.mOptions.get("processMixingMuonSkimmed"); fEnableMuonMixingHistos = context.mOptions.get("processMixingAllSkimmed") || context.mOptions.get("processMixingMuonSkimmed"); @@ -1298,6 +1338,54 @@ struct AnalysisSameEventPairing { objArrayMuonCuts = muonCutsStr.Tokenize(","); } + if (fConfigML.applyBDT) { + // BDT cuts via JSON + std::vector binsMl; + o2::framework::LabeledArray cutsMl; + std::vector cutDirMl; + int nClassesMl = 1; + std::vector namesInputFeatures; + std::vector onnxFileNames; + + auto config = o2::aod::dqmlcuts::GetBdtScoreCutsAndConfigFromJSON(fConfigML.fConfigBdtCutsJSON.value.c_str()); + + if (std::holds_alternative(config)) { + auto& cfg = std::get(config); + binsMl = cfg.binsMl; + nClassesMl = 1; + cutsMl = cfg.cutsMl; + cutDirMl = cfg.cutDirs; + namesInputFeatures = cfg.inputFeatures; + onnxFileNames = cfg.onnxFiles; + fDQMlResponse.setBinsCent(cfg.binsCent); + fDQMlResponse.setBinsPt(cfg.binsPt); + fDQMlResponse.setCentType(cfg.centType); + LOG(info) << "Using BDT cuts for binary classification"; + } else { + auto& cfg = std::get(config); + binsMl = cfg.binsMl; + nClassesMl = 3; + cutsMl = cfg.cutsMl; + cutDirMl = cfg.cutDirs; + namesInputFeatures = cfg.inputFeatures; + onnxFileNames = cfg.onnxFiles; + fDQMlResponse.setBinsCent(cfg.binsCent); + fDQMlResponse.setBinsPt(cfg.binsPt); + fDQMlResponse.setCentType(cfg.centType); + LOG(info) << "Using BDT cuts for multiclass classification"; + } + + fDQMlResponse.configure(binsMl, cutsMl, cutDirMl, nClassesMl); + if (fConfigML.loadModelsFromCCDB) { + fCCDBApi.init(fConfigCCDB.url); + fDQMlResponse.setModelPathsCCDB(onnxFileNames, fCCDBApi, fConfigML.modelPathsCCDB, fConfigML.timestampCCDB); + } else { + fDQMlResponse.setModelPathsLocal(onnxFileNames); + } + fDQMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + fDQMlResponse.init(); + } + // get the barrel track selection cuts string tempCuts; getTaskOptionValue(context, "analysis-track-selection", "cfgTrackCuts", tempCuts, false); @@ -1542,6 +1630,11 @@ struct AnalysisSameEventPairing { uint64_t sor = std::atol(header["SOR"].c_str()); uint64_t eor = std::atol(header["EOR"].c_str()); VarManager::SetSORandEOR(sor, eor); + + if (fConfigOptions.useRemoteCollisionInfo) { + o2::parameters::GRPLHCIFData* grpo = fCCDB->getForTimeStamp(fConfigCCDB.GrpLhcIfPath, timestamp); + VarManager::SetCollisionSystem(grpo); + } } // Template function to run same event pairing (barrel-barrel, muon-muon, barrel-muon) @@ -1592,10 +1685,14 @@ struct AnalysisSameEventPairing { dielectronAllList.reserve(1); dimuonAllList.reserve(1); } + if (fConfigOptions.polarTables.value) { + dileptonPolarList.reserve(1); + } fAmbiguousPairs.clear(); constexpr bool eventHasQvector = ((TEventFillMap & VarManager::ObjTypes::ReducedEventQvector) > 0); constexpr bool eventHasQvectorCentr = ((TEventFillMap & VarManager::ObjTypes::CollisionQvect) > 0); constexpr bool trackHasCov = ((TTrackFillMap & VarManager::ObjTypes::TrackCov) > 0 || (TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelCov) > 0); + bool isSelectedBDT = false; for (auto& event : events) { if (!event.isEventSelected_bit(0)) { @@ -1654,6 +1751,9 @@ struct AnalysisSameEventPairing { if constexpr (eventHasQvector) { VarManager::FillPairVn(t1, t2); } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } dielectronList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], @@ -1663,9 +1763,53 @@ struct AnalysisSameEventPairing { dielectronInfoList(t1.collisionId(), t1.trackId(), t2.trackId()); dileptonInfoList(t1.collisionId(), event.posX(), event.posY(), event.posZ()); } + if (fConfigOptions.polarTables.value) { + 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]); + } if constexpr (trackHasCov && TTwoProngFitter) { dielectronsExtraList(t1.globalIndex(), t2.globalIndex(), VarManager::fgValues[VarManager::kVertexingTauzProjected], VarManager::fgValues[VarManager::kVertexingLzProjected], VarManager::fgValues[VarManager::kVertexingLxyProjected]); if constexpr ((TTrackFillMap & VarManager::ObjTypes::ReducedTrackBarrelPID) > 0) { + if (fConfigML.applyBDT) { + std::vector dqInputFeatures = fDQMlResponse.getInputFeatures(t1, t2, VarManager::fgValues); + + if (dqInputFeatures.empty()) { + LOG(fatal) << "Input features for ML selection are empty! Please check your configuration."; + return; + } + + int modelIndex = -1; + const auto& binsCent = fDQMlResponse.getBinsCent(); + const auto& binsPt = fDQMlResponse.getBinsPt(); + const std::string& centType = fDQMlResponse.getCentType(); + + if ("kCentFT0C" == centType) { + modelIndex = o2::aod::dqmlcuts::getMlBinIndex(VarManager::fgValues[VarManager::kCentFT0C], VarManager::fgValues[VarManager::kPt], binsCent, binsPt); + } else if ("kCentFT0A" == centType) { + modelIndex = o2::aod::dqmlcuts::getMlBinIndex(VarManager::fgValues[VarManager::kCentFT0A], VarManager::fgValues[VarManager::kPt], binsCent, binsPt); + } else if ("kCentFT0M" == centType) { + modelIndex = o2::aod::dqmlcuts::getMlBinIndex(VarManager::fgValues[VarManager::kCentFT0M], VarManager::fgValues[VarManager::kPt], binsCent, binsPt); + } else { + LOG(fatal) << "Unknown centrality estimation type: " << centType; + return; + } + + if (modelIndex < 0) { + LOG(info) << "Ml index is negative! This means that the centrality/pt is not in the range of the model bins."; + continue; + } + + LOG(debug) << "Model index: " << modelIndex << ", pT: " << VarManager::fgValues[VarManager::kPt] << ", centrality (kCentFT0C): " << VarManager::fgValues[VarManager::kCentFT0C]; + isSelectedBDT = fDQMlResponse.isSelectedMl(dqInputFeatures, modelIndex, fOutputMlPsi2ee); + VarManager::FillBdtScore(fOutputMlPsi2ee); // TODO: check if this is needed or not + } + + if (fConfigML.applyBDT && !isSelectedBDT) + continue; + 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, dileptonMcDecision, 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(), @@ -1719,6 +1863,9 @@ struct AnalysisSameEventPairing { if constexpr (eventHasQvector) { VarManager::FillPairVn(t1, t2); } + if constexpr (eventHasQvectorCentr) { + VarManager::FillPairVn(t1, t2); + } dimuonList(event.globalIndex(), VarManager::fgValues[VarManager::kMass], VarManager::fgValues[VarManager::kPt], VarManager::fgValues[VarManager::kEta], VarManager::fgValues[VarManager::kPhi], @@ -1787,6 +1934,10 @@ struct AnalysisSameEventPairing { bool isLeg1Ambi = false; bool isLeg2Ambi = false; bool isAmbiExtra = false; + + if (fConfigML.applyBDT && !isSelectedBDT) + continue; + for (int icut = 0; icut < ncuts; icut++) { if (twoTrackFilter & (static_cast(1) << icut)) { isAmbiInBunch = (twoTrackFilter & (static_cast(1) << 28)) || (twoTrackFilter & (static_cast(1) << 29)); @@ -2080,6 +2231,13 @@ struct AnalysisSameEventPairing { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); } + void processBarrelOnlySkimmedFlow(MyEventsVtxCovSelectedQvector const& events, + soa::Join const& barrelAssocs, + MyBarrelTracksWithAmbiguities const& barrelTracks) + { + runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); + } + void processBarrelOnlySkimmedNoCov(MyEventsSelected const& events, soa::Join const& barrelAssocs, MyBarrelTracksWithAmbiguities const& barrelTracks) @@ -2101,6 +2259,13 @@ struct AnalysisSameEventPairing { runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); } + void processBarrelOnlyWithQvectorCentrSkimmedNoCov(MyEventsQvectorCentrSelected const& events, + soa::Join const& barrelAssocs, + MyBarrelTracksWithAmbiguities const& barrelTracks) + { + runSameEventPairing(events, trackAssocsPerCollision, barrelAssocs, barrelTracks); + } + void processMuonOnlySkimmed(MyEventsVtxCovSelected const& events, soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) { @@ -2127,6 +2292,12 @@ struct AnalysisSameEventPairing { runSameSideMixing(events, trackAssocs, tracks, trackAssocsPerCollision); } + void processMixingBarrelSkimmedFlow(soa::Filtered& events, + soa::Join const& trackAssocs, aod::ReducedTracks const& tracks) + { + runSameSideMixing(events, trackAssocs, tracks, trackAssocsPerCollision); + } + void processMixingMuonSkimmed(soa::Filtered& events, soa::Join const& muonAssocs, MyMuonTracksWithCovWithAmbiguities const& muons) { @@ -2143,10 +2314,13 @@ struct AnalysisSameEventPairing { PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlyWithCollSkimmed, "Run barrel only pairing, with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmedNoCov, "Run barrel only pairing (no covariances), with skimmed tracks and with collision information", false); PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmedNoCovWithMultExtra, "Run barrel only pairing (no covariances), with skimmed tracks, with collision information, with MultsExtra", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlyWithQvectorCentrSkimmedNoCov, "Run barrel only pairing (no covariances), with skimmed tracks, with Qvector from central framework", false); + PROCESS_SWITCH(AnalysisSameEventPairing, processBarrelOnlySkimmedFlow, "Run barrel only pairing, with skimmed tracks and with flow", false); 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, 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); PROCESS_SWITCH(AnalysisSameEventPairing, processMixingMuonSkimmed, "Run muon type mixing pairing, with skimmed muons", false); PROCESS_SWITCH(AnalysisSameEventPairing, processDummy, "Dummy function, enabled only if none of the others are enabled", false); }; @@ -2164,13 +2338,13 @@ struct AnalysisAsymmetricPairing { OutputObj fOutputList{"output"}; // Configurables - Configurable fConfigLegCuts{"cfgLegCuts", "", ":[:],[:[:],...]"}; + Configurable fConfigLegCuts{"cfgLegCuts", "", ":[:],[:[:],...]"}; Configurable fConfigLegAFilterMask{"cfgLegAFilterMask", 0, "Filter mask corresponding to cuts in track-selection"}; Configurable fConfigLegBFilterMask{"cfgLegBFilterMask", 0, "Filter mask corresponding to cuts in track-selection"}; Configurable fConfigLegCFilterMask{"cfgLegCFilterMask", 0, "Filter mask corresponding to cuts in track-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 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"}; @@ -2179,7 +2353,7 @@ struct AnalysisAsymmetricPairing { Configurable fConfigReflectedHistograms{"cfgReflectedHistograms", false, "Include separate histograms for pairs which are reflections of previously counted pairs"}; Configurable fConfigAddJSONHistograms{"cfgAddJSONHistograms", "", "Histograms in JSON format"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable fConfigGRPMagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; Configurable fConfigUseRemoteField{"cfgUseRemoteField", false, "Choose whether to fetch the magnetic field from ccdb or set it manually"}; Configurable fConfigMagField{"cfgMagField", 5.0f, "Manually set magnetic field"}; @@ -2456,7 +2630,7 @@ struct AnalysisAsymmetricPairing { VarManager::SetupMatLUTFwdDCAFitter(fLUT); 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 + VarManager::SetUseVars(fHistMan->GetUsedVars()); // provide the list of required variables so that VarManager knows what to fill fOutputList.setObject(fHistMan->GetMainHistogramList()); LOG(info) << "Initialization of AnalysisAsymmetricPairing finished (idstoreh)"; } @@ -2886,9 +3060,10 @@ struct AnalysisAsymmetricPairing { // tracks passing the fConfigTrackCut cut. The dileptons cuts from the same-event pairing task are auto-detected struct AnalysisDileptonTrack { Produces BmesonsTable; + Produces DileptonTrackTable; OutputObj fOutputList{"output"}; - Configurable fConfigTrackCuts{"cfgTrackCuts", "kaonPID", "Comma separated list of cuts for the track to be correlated with the dileptons"}; + Configurable fConfigTrackCuts{"cfgTrackCuts", "kaonPID", "Comma separated list of cuts for the track 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 fConfigDileptonpTCut{"cfgDileptonpTCut", 0.0, "pT cut for dileptons used in the triplet vertexing"}; @@ -2903,14 +3078,14 @@ struct AnalysisDileptonTrack { 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 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"}; int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. int fNCuts; // number of dilepton leg cuts int fNLegCuts; - int fNPairCuts; // number of pair cuts + int fNPairCuts; // number of pair cuts int fNCommonTrackCuts; std::map fCommonTrackCutMap; uint32_t fTrackCutBitMap; // track cut bit mask to be used in the selection of tracks associated with dileptons @@ -3268,7 +3443,7 @@ struct AnalysisDileptonTrack { fValuesHadron[VarManager::kVertexingLxy], fValuesHadron[VarManager::kVertexingLxyz], fValuesHadron[VarManager::kVertexingLz], fValuesHadron[VarManager::kVertexingTauxy], fValuesHadron[VarManager::kVertexingTauz], fValuesHadron[VarManager::kCosPointingAngle], fValuesHadron[VarManager::kVertexingChi2PCA], - track.pt(), track.eta(), dilepton.pt(), dilepton.eta(), lepton1.pt(), lepton1.eta(), lepton2.pt(), lepton2.eta(), + track.tpcInnerParam(), track.eta(), dilepton.pt(), dilepton.eta(), lepton1.tpcInnerParam(), lepton1.eta(), lepton2.tpcInnerParam(), lepton2.eta(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tpcNSigmaPr(), track.tofNSigmaKa(), lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), @@ -3307,6 +3482,8 @@ struct AnalysisDileptonTrack { VarManager::FillDileptonHadron(dilepton, track, fValuesHadron); VarManager::FillDileptonTrackVertexing(event, lepton1, lepton2, track, fValuesHadron); + // Fill table for correlation analysis + DileptonTrackTable(fValuesHadron[VarManager::kDeltaEta], fValuesHadron[VarManager::kDeltaPhi], dilepton.mass(), dilepton.pt(), dilepton.eta(), track.pt(), track.eta()); } // Fill histograms for the triplets @@ -3528,6 +3705,257 @@ struct AnalysisDileptonTrack { PROCESS_SWITCH(AnalysisDileptonTrack, processDummy, "Dummy function", false); }; +struct AnalysisDileptonTrackTrack { + OutputObj fOutputList{"output"}; + + Configurable fConfigTrackCut1{"cfgTrackCut1", "pionPIDCut1", "track1 cut"}; // used for select the tracks from SelectedTracks + Configurable fConfigTrackCut2{"cfgTrackCut2", "pionPIDCut2", "track2 cut"}; // used for select the tracks from SelectedTracks + Configurable fConfigDileptonCut{"cfgDiLeptonCut", "pairJpsi2", "Dilepton cut"}; + Configurable fConfigQuadrupletCuts{"cfgQuadrupletCuts", "pairX3872Cut1", "Comma separated list of Dilepton-Track-Track cut"}; + Configurable fConfigAddDileptonHistogram{"cfgAddDileptonHistogram", "barrel", "Comma separated list of histograms"}; + Configurable fConfigAddQuadrupletHistogram{"cfgAddQuadrupletHistogram", "xtojpsipipi", "Comma separated list of histograms"}; + + Configurable fConfigSetupFourProngFitter{"cfgSetupFourProngFitter", false, "Use DCA for secondary vertex reconstruction (DCAFitter is used by default)"}; + Configurable fConfigUseKFVertexing{"cfgUseKFVertexing", false, "Use KF Particle for secondary vertex reconstruction (DCAFitter is used by default)"}; + 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"}; + + Produces DileptonTrackTrackTable; + + int fCurrentRun; // needed to detect if the run changed and trigger update of calibrations etc. + // uint32_t fTrackCutBitMap; // track cut bit mask to be used in the selection of tracks associated with dileptons + // cut name setting + TString fTrackCutName1; + TString fTrackCutName2; + bool fIsSameTrackCut = false; + AnalysisCompositeCut fDileptonCut; + std::vector fQuadrupletCutNames; + std::vector fQuadrupletCuts; + + Service fCCDB; + + Filter eventFilter = aod::dqanalysisflags::isEventSelected > static_cast(0); + Filter dileptonFilter = aod::reducedpair::sign == 0; + Filter filterBarrelTrackSelected = aod::dqanalysisflags::isBarrelSelected > static_cast(0); + + constexpr static uint32_t fgDileptonFillMap = VarManager::ObjTypes::ReducedTrack | VarManager::ObjTypes::Pair; // fill map + + // use some values array to avoid mixing up the quantities + float* fValuesQuadruplet; + HistogramManager* fHistMan; + + void init(o2::framework::InitContext& context) + { + // bool isBarrel = context.mOptions.get("processJpsiPiPi"); + + if (context.mOptions.get("processDummy")) { + return; + } + + fCurrentRun = 0; + + fValuesQuadruplet = new float[VarManager::kNVars]; + VarManager::SetDefaultVarNames(); + fHistMan = new HistogramManager("analysisHistos", "aa", VarManager::kNVars); + fHistMan->SetUseDefaultVariableNames(kTRUE); + fHistMan->SetDefaultVarNames(VarManager::fgVariableNames, VarManager::fgVariableUnits); + + // define cuts + fTrackCutName1 = fConfigTrackCut1.value; + fTrackCutName2 = fConfigTrackCut2.value; + if (fTrackCutName1 == fTrackCutName2) { + fIsSameTrackCut = true; + } + TString configDileptonCutNamesStr = fConfigDileptonCut.value; + fDileptonCut = *dqcuts::GetCompositeCut(configDileptonCutNamesStr.Data()); + TString configQuadruletCutNamesStr = fConfigQuadrupletCuts.value; + std::unique_ptr objArray(configQuadruletCutNamesStr.Tokenize(",")); + for (Int_t icut = 0; icut < objArray->GetEntries(); ++icut) { + TString cutName = objArray->At(icut)->GetName(); + fQuadrupletCutNames.push_back(cutName); + fQuadrupletCuts.push_back(*dqcuts::GetCompositeCut(cutName.Data())); + } + + if (!context.mOptions.get("processDummy")) { + DefineHistograms(fHistMan, Form("Pairs_%s", configDileptonCutNamesStr.Data()), fConfigAddDileptonHistogram.value.data()); + if (!configQuadruletCutNamesStr.IsNull()) { + for (std::size_t icut = 0; icut < fQuadrupletCutNames.size(); ++icut) { + if (fIsSameTrackCut) { + DefineHistograms(fHistMan, Form("QuadrupletSEPM_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + } else { + DefineHistograms(fHistMan, Form("QuadrupletSEPM_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + DefineHistograms(fHistMan, Form("QuadrupletSEMP_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + } + DefineHistograms(fHistMan, Form("QuadrupletSEPP_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + DefineHistograms(fHistMan, Form("QuadrupletSEMM_%s", fQuadrupletCutNames[icut].Data()), fConfigAddQuadrupletHistogram.value.data()); + } + } + } + + VarManager::SetUseVars(fHistMan->GetUsedVars()); + fOutputList.setObject(fHistMan->GetMainHistogramList()); + } + + // init parameters from CCDB + void initParamsFromCCDB(uint64_t timestamp) + { + if (fConfigUseRemoteField.value) { + o2::parameters::GRPMagField* grpmag = fCCDB->getForTimeStamp(fConfigGRPmagPath.value, timestamp); + float magField = 0.0; + if (grpmag != nullptr) { + magField = grpmag->getNominalL3Field(); + } else { + LOGF(fatal, "GRP object is not available in CCDB at timestamp=%llu", timestamp); + } + if (fConfigUseKFVertexing.value) { + VarManager::SetupTwoProngKFParticle(magField); + VarManager::SetupFourProngKFParticle(magField); + } else if (fConfigSetupFourProngFitter.value) { + VarManager::SetupTwoProngDCAFitter(magField, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(magField, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } + } else { + if (fConfigUseKFVertexing.value) { + VarManager::SetupTwoProngKFParticle(fConfigMagField.value); + VarManager::SetupFourProngKFParticle(fConfigMagField.value); + } else if (fConfigSetupFourProngFitter.value) { + LOGP(info, "Setting up DCA fitter for two and four prong candidates"); + VarManager::SetupTwoProngDCAFitter(fConfigMagField.value, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + VarManager::SetupFourProngDCAFitter(fConfigMagField.value, true, 200.0f, 4.0f, 1.0e-3f, 0.9f, false); // TODO: get these parameters from Configurables + } + } + } + + // Template function to run pair - hadron combinations + template + void runDileptonTrackTrack(TEvent const& event, TTrackAssocs const& assocs, TTracks const& tracks, TDileptons const& dileptons) + { + VarManager::ResetValues(0, VarManager::kNVars, fValuesQuadruplet); + VarManager::FillEvent(event, fValuesQuadruplet); + // int indexOffset = -999; + // std::vector trackGlobalIndexes; + + for (auto dilepton : dileptons) { + // get full track info of tracks based on the index + + int indexLepton1 = dilepton.index0Id(); + int indexLepton2 = dilepton.index1Id(); + auto lepton1 = tracks.rawIteratorAt(dilepton.index0Id()); + auto lepton2 = tracks.rawIteratorAt(dilepton.index1Id()); + // Check that the dilepton has zero charge + if (dilepton.sign() != 0) { + continue; + } + VarManager::FillTrack(dilepton, fValuesQuadruplet); + // LOGP(info, "is dilepton selected: {}", fDileptonCut.IsSelected(fValuesQuadruplet)); + + // apply the dilepton cut + if (!fDileptonCut.IsSelected(fValuesQuadruplet)) + continue; + + fHistMan->FillHistClass(Form("Pairs_%s", fDileptonCut.GetName()), fValuesQuadruplet); + + // loop over hadrons pairs + for (auto& [a1, a2] : o2::soa::combinations(assocs, assocs)) { + uint32_t trackSelection = 0; + if (fIsSameTrackCut) { + trackSelection = ((a1.isBarrelSelected_raw() & (static_cast(1) << 1)) || (a2.isBarrelSelected_raw() & (static_cast(1) << 1))); + } else { + trackSelection = ((a1.isBarrelSelected_raw() & (static_cast(1) << 1)) && (a2.isBarrelSelected_raw() & (static_cast(1) << 2))); + } + // LOGP(info, "trackSelection: {}, a1: {}, a2: {}", trackSelection, a1.isBarrelSelected_raw(), a2.isBarrelSelected_raw()); + if (!trackSelection) { + continue; + } + + // get the track from this association + auto track1 = a1.template reducedtrack_as(); + auto track2 = a2.template reducedtrack_as(); + // avoid self combinations + if (track1.globalIndex() == indexLepton1 || track1.globalIndex() == indexLepton2 || track2.globalIndex() == indexLepton1 || track2.globalIndex() == indexLepton2) { + continue; + } + + // fill variables + VarManager::FillDileptonTrackTrack(dilepton, track1, track2, fValuesQuadruplet); + if (fConfigSetupFourProngFitter || fConfigUseKFVertexing) { + // LOGP(info, "Using KF or DCA fitter for secondary vertexing"); + VarManager::FillDileptonTrackTrackVertexing(event, lepton1, lepton2, track1, track2, fValuesQuadruplet); + } + + int iCut = 0; + uint32_t CutDecision = 0; + for (auto cutname = fQuadrupletCutNames.begin(); cutname != fQuadrupletCutNames.end(); cutname++, iCut++) { + // apply dilepton-track-track cut + if (fQuadrupletCuts[iCut].IsSelected(fValuesQuadruplet)) { + CutDecision |= (1 << iCut); + if (fIsSameTrackCut) { + if (track1.sign() * track2.sign() < 0) { + fHistMan->FillHistClass(Form("QuadrupletSEPM_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } + } else { + if ((track1.sign() < 0) && (track2.sign() > 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEMP_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } else if ((track1.sign() > 0) && (track2.sign() < 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEPM_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } + } + if ((track1.sign() > 0) && (track2.sign() > 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEPP_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } else if ((track1.sign() < 0) && (track2.sign() < 0)) { + fHistMan->FillHistClass(Form("QuadrupletSEMM_%s", fQuadrupletCutNames[iCut].Data()), fValuesQuadruplet); + } + } + } // loop over dilepton-track-track cuts + + // fill table + if (!CutDecision) + continue; + DileptonTrackTrackTable(fValuesQuadruplet[VarManager::kQuadMass], fValuesQuadruplet[VarManager::kQuadPt], fValuesQuadruplet[VarManager::kQuadEta], fValuesQuadruplet[VarManager::kQuadPhi], fValuesQuadruplet[VarManager::kRap], + fValuesQuadruplet[VarManager::kQ], fValuesQuadruplet[VarManager::kDeltaR1], fValuesQuadruplet[VarManager::kDeltaR2], fValuesQuadruplet[VarManager::kDeltaR], + dilepton.mass(), dilepton.pt(), dilepton.eta(), dilepton.phi(), dilepton.sign(), + lepton1.tpcNSigmaEl(), lepton1.tpcNSigmaPi(), lepton1.tpcNSigmaPr(), lepton1.tpcNClsFound(), + lepton2.tpcNSigmaEl(), lepton2.tpcNSigmaPi(), lepton2.tpcNSigmaPr(), lepton2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kDitrackMass], fValuesQuadruplet[VarManager::kDitrackPt], track1.pt(), track2.pt(), track1.eta(), track2.eta(), track1.phi(), track2.phi(), track1.sign(), track2.sign(), track1.tpcNSigmaPi(), track2.tpcNSigmaPi(), track1.tpcNSigmaKa(), track2.tpcNSigmaKa(), track1.tpcNSigmaPr(), track1.tpcNSigmaPr(), track1.tpcNClsFound(), track2.tpcNClsFound(), + fValuesQuadruplet[VarManager::kKFMass], fValuesQuadruplet[VarManager::kVertexingProcCode], fValuesQuadruplet[VarManager::kVertexingChi2PCA], fValuesQuadruplet[VarManager::kCosPointingAngle], fValuesQuadruplet[VarManager::kKFDCAxyzBetweenProngs], fValuesQuadruplet[VarManager::kKFChi2OverNDFGeo], + fValuesQuadruplet[VarManager::kVertexingLz], fValuesQuadruplet[VarManager::kVertexingLxy], fValuesQuadruplet[VarManager::kVertexingLxyz], fValuesQuadruplet[VarManager::kVertexingTauz], fValuesQuadruplet[VarManager::kVertexingTauxy], fValuesQuadruplet[VarManager::kVertexingLzErr], fValuesQuadruplet[VarManager::kVertexingLxyzErr], + fValuesQuadruplet[VarManager::kVertexingTauzErr], fValuesQuadruplet[VarManager::kVertexingLzProjected], fValuesQuadruplet[VarManager::kVertexingLxyProjected], fValuesQuadruplet[VarManager::kVertexingLxyzProjected], fValuesQuadruplet[VarManager::kVertexingTauzProjected], fValuesQuadruplet[VarManager::kVertexingTauxyProjected]); + } + } + } + + Preslice trackAssocsPerCollision = aod::reducedtrack_association::reducedeventId; + Preslice dielectronsPerCollision = aod::reducedpair::reducedeventId; + Preslice ditracksPerCollision = aod::reducedpair::reducedeventId; + + void processJpsiPiPi(soa::Filtered const& events, + soa::Filtered> const& assocs, + MyBarrelTracksWithCov const& tracks, soa::Filtered const& dileptons) + { + if (events.size() == 0) { + return; + } + if (fCurrentRun != events.begin().runNumber()) { // start: runNumber + initParamsFromCCDB(events.begin().timestamp()); + fCurrentRun = events.begin().runNumber(); + } // end: runNumber + for (auto& event : events) { + auto groupedBarrelAssocs = assocs.sliceBy(trackAssocsPerCollision, event.globalIndex()); + auto groupedDielectrons = dileptons.sliceBy(dielectronsPerCollision, event.globalIndex()); + runDileptonTrackTrack(event, groupedBarrelAssocs, tracks, groupedDielectrons); + } + } + + void processDummy(MyEvents&) + { + // do nothing + } + + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processJpsiPiPi, "Run barrel pairing of J/psi with pion candidate", false); + PROCESS_SWITCH(AnalysisDileptonTrackTrack, processDummy, "Dummy function", true); +}; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ @@ -3537,7 +3965,8 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; } void DefineHistograms(HistogramManager* histMan, TString histClasses, const char* histGroups) @@ -3614,5 +4043,9 @@ 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("Quadruplet")) { + dqhistograms::DefineHistograms(histMan, objArray->At(iclass)->GetName(), "dilepton-dihadron", histName); + } } // end loop over histogram classes } diff --git a/PWGDQ/Tasks/taskJpsiHf.cxx b/PWGDQ/Tasks/taskJpsiHf.cxx index 79d9348940a..ef415259a02 100644 --- a/PWGDQ/Tasks/taskJpsiHf.cxx +++ b/PWGDQ/Tasks/taskJpsiHf.cxx @@ -97,15 +97,16 @@ struct taskJPsiHf { float deltaRap = -999; float deltaPhi = -999; - for (auto& dilepton : dileptons) { + for (auto const& dilepton : dileptons) { ptDilepton = RecoDecay::pt(dilepton.px(), dilepton.py()); rapDilepton = RecoDecay::y(std::array{dilepton.px(), dilepton.py(), dilepton.pz()}, constants::physics::MassJPsi); phiDilepton = RecoDecay::phi(dilepton.px(), dilepton.py()); - for (auto& dmeson : dmesons) { + for (auto const& dmeson : dmesons) { ptDmeson = RecoDecay::pt(dmeson.px(), dmeson.py()); phiDmeson = RecoDecay::phi(dmeson.px(), dmeson.py()); - deltaPhi = RecoDecay::constrainAngle(phiDilepton - phiDmeson, -o2::constants::math::PIHalf); + float absDeltaPhiRaw = std::abs(phiDilepton - phiDmeson); + deltaPhi = (absDeltaPhiRaw < o2::constants::math::PI) ? absDeltaPhiRaw : o2::constants::math::TwoPI - absDeltaPhiRaw; auto ptBinDmesForBdt = findBin(binsPtDmesForBdt, ptDmeson); if (ptBinDmesForBdt == -1) { diff --git a/PWGEM/Dilepton/Core/CMakeLists.txt b/PWGEM/Dilepton/Core/CMakeLists.txt index 92d06924294..97501004c4a 100644 --- a/PWGEM/Dilepton/Core/CMakeLists.txt +++ b/PWGEM/Dilepton/Core/CMakeLists.txt @@ -13,10 +13,12 @@ o2physics_add_library(PWGEMDileptonCore SOURCES EMEventCut.cxx DielectronCut.cxx DimuonCut.cxx + EMTrackCut.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore) o2physics_target_root_dictionary(PWGEMDileptonCore HEADERS EMEventCut.h DielectronCut.h DimuonCut.h + EMTrackCut.h LINKDEF PWGEMDileptonCoreLinkDef.h) diff --git a/PWGEM/Dilepton/Core/DielectronCut.cxx b/PWGEM/Dilepton/Core/DielectronCut.cxx index cd0ae3f5078..7f86c7babbe 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.cxx +++ b/PWGEM/Dilepton/Core/DielectronCut.cxx @@ -13,11 +13,12 @@ // Class for dielectron Cut // -#include -#include +#include "PWGEM/Dilepton/Core/DielectronCut.h" #include "Framework/Logger.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" + +#include +#include ClassImp(DielectronCut); @@ -66,12 +67,13 @@ void DielectronCut::SelectPhotonConversion(bool flag) mSelectPC = flag; LOG(info) << "Dielectron Cut, select photon conversion: " << mSelectPC; } -void DielectronCut::SetMindEtadPhi(bool flag, float min_deta, float min_dphi) +void DielectronCut::SetMindEtadPhi(bool flag1, bool flag2, float min_deta, float min_dphi) { - mApplydEtadPhi = flag; + mApplydEtadPhi = flag1; + mApplydEtadPhiPosition = flag2; mMinDeltaEta = min_deta; mMinDeltaPhi = min_dphi; - LOG(info) << "Dielectron Cut, set apply deta-dphi cut: " << mApplydEtadPhi << " min_deta: " << mMinDeltaEta << " min_dphi: " << mMinDeltaPhi; + LOG(info) << "Dielectron Cut, set apply deta-dphi cut: " << mApplydEtadPhi << " apply deta-dphi* cut: " << mApplydEtadPhiPosition << " min_deta: " << mMinDeltaEta << " min_dphi: " << mMinDeltaPhi; } void DielectronCut::SetRequireDifferentSides(bool flag) { @@ -90,11 +92,13 @@ void DielectronCut::SetTrackEtaRange(float minEta, float maxEta) mMaxTrackEta = maxEta; LOG(info) << "Dielectron Cut, set track eta range: " << mMinTrackEta << " - " << mMaxTrackEta; } -void DielectronCut::SetTrackPhiRange(float minPhi, float maxPhi) +void DielectronCut::SetTrackPhiRange(float minPhi, float maxPhi, bool mirror, bool reject) { mMinTrackPhi = minPhi; mMaxTrackPhi = maxPhi; - LOG(info) << "Dielectron Cut, set track phi range (rad.): " << mMinTrackPhi << " - " << mMaxTrackPhi; + mMirrorTrackPhi = mirror; + mRejectTrackPhi = reject; + LOG(info) << "Dielectron Cut, set track phi range (rad.): " << mMinTrackPhi << " - " << mMaxTrackPhi << " with mirror: " << mMirrorTrackPhi << " and rejection: " << mRejectTrackPhi; } void DielectronCut::SetMinNClustersTPC(int minNClustersTPC) { @@ -141,12 +145,12 @@ void DielectronCut::SetChi2PerClusterITS(float min, float max) mMaxChi2PerClusterITS = max; LOG(info) << "Dielectron Cut, set chi2 per cluster ITS range: " << mMinChi2PerClusterITS << " - " << mMaxChi2PerClusterITS; } -void DielectronCut::SetMeanClusterSizeITS(float min, float max, float minP, float maxP) +void DielectronCut::SetMeanClusterSizeITS(float min, float max) { mMinMeanClusterSizeITS = min; mMaxMeanClusterSizeITS = max; - mMinP_ITSClusterSize = minP; - mMaxP_ITSClusterSize = maxP; + // mMinP_ITSClusterSize = minP; + // mMaxP_ITSClusterSize = maxP; LOG(info) << "Dielectron Cut, set mean cluster size ITS range: " << mMinMeanClusterSizeITS << " - " << mMaxMeanClusterSizeITS; } void DielectronCut::SetChi2TOF(float min, float max) @@ -219,12 +223,12 @@ void DielectronCut::SetTPCNsigmaElRange(float min, float max) mMaxTPCNsigmaEl = max; LOG(info) << "Dielectron Cut, set TPC n sigma El range: " << mMinTPCNsigmaEl << " - " << mMaxTPCNsigmaEl; } -void DielectronCut::SetTPCNsigmaMuRange(float min, float max) -{ - mMinTPCNsigmaMu = min; - mMaxTPCNsigmaMu = max; - LOG(info) << "Dielectron Cut, set TPC n sigma Mu range: " << mMinTPCNsigmaMu << " - " << mMaxTPCNsigmaMu; -} +// void DielectronCut::SetTPCNsigmaMuRange(float min, float max) +// { +// mMinTPCNsigmaMu = min; +// mMaxTPCNsigmaMu = max; +// LOG(info) << "Dielectron Cut, set TPC n sigma Mu range: " << mMinTPCNsigmaMu << " - " << mMaxTPCNsigmaMu; +// } void DielectronCut::SetTPCNsigmaPiRange(float min, float max) { mMinTPCNsigmaPi = min; @@ -250,12 +254,12 @@ void DielectronCut::SetTOFNsigmaElRange(float min, float max) mMaxTOFNsigmaEl = max; LOG(info) << "Dielectron Cut, set TOF n sigma El range: " << mMinTOFNsigmaEl << " - " << mMaxTOFNsigmaEl; } -void DielectronCut::SetTOFNsigmaMuRange(float min, float max) -{ - mMinTOFNsigmaMu = min; - mMaxTOFNsigmaMu = max; - LOG(info) << "Dielectron Cut, set TOF n sigma Mu range: " << mMinTOFNsigmaMu << " - " << mMaxTOFNsigmaMu; -} +// void DielectronCut::SetTOFNsigmaMuRange(float min, float max) +// { +// mMinTOFNsigmaMu = min; +// mMaxTOFNsigmaMu = max; +// LOG(info) << "Dielectron Cut, set TOF n sigma Mu range: " << mMinTOFNsigmaMu << " - " << mMaxTOFNsigmaMu; +// } void DielectronCut::SetTOFNsigmaPiRange(float min, float max) { mMinTOFNsigmaPi = min; @@ -275,50 +279,50 @@ void DielectronCut::SetTOFNsigmaPrRange(float min, float max) LOG(info) << "Dielectron Cut, set TOF n sigma Pr range: " << mMinTOFNsigmaPr << " - " << mMaxTOFNsigmaPr; } -void DielectronCut::SetITSNsigmaElRange(float min, float max) -{ - mMinITSNsigmaEl = min; - mMaxITSNsigmaEl = max; - LOG(info) << "Dielectron Cut, set ITS n sigma El range: " << mMinITSNsigmaEl << " - " << mMaxITSNsigmaEl; -} -void DielectronCut::SetITSNsigmaMuRange(float min, float max) -{ - mMinITSNsigmaMu = min; - mMaxITSNsigmaMu = max; - LOG(info) << "Dielectron Cut, set ITS n sigma Mu range: " << mMinITSNsigmaMu << " - " << mMaxITSNsigmaMu; -} -void DielectronCut::SetITSNsigmaPiRange(float min, float max) -{ - mMinITSNsigmaPi = min; - mMaxITSNsigmaPi = max; - LOG(info) << "Dielectron Cut, set ITS n sigma Pi range: " << mMinITSNsigmaPi << " - " << mMaxITSNsigmaPi; -} -void DielectronCut::SetITSNsigmaKaRange(float min, float max) -{ - mMinITSNsigmaKa = min; - mMaxITSNsigmaKa = max; - LOG(info) << "Dielectron Cut, set ITS n sigma Ka range: " << mMinITSNsigmaKa << " - " << mMaxITSNsigmaKa; -} -void DielectronCut::SetITSNsigmaPrRange(float min, float max) -{ - mMinITSNsigmaPr = min; - mMaxITSNsigmaPr = max; - LOG(info) << "Dielectron Cut, set ITS n sigma Pr range: " << mMinITSNsigmaPr << " - " << mMaxITSNsigmaPr; -} - -void DielectronCut::SetPRangeForITSNsigmaKa(float min, float max) -{ - mMinP_ITSNsigmaKa = min; - mMaxP_ITSNsigmaKa = max; - LOG(info) << "Dielectron Cut, set p range for ITS n sigma Ka: " << mMinP_ITSNsigmaKa << " - " << mMaxP_ITSNsigmaKa; -} - -void DielectronCut::SetPRangeForITSNsigmaPr(float min, float max) -{ - mMinP_ITSNsigmaPr = min; - mMaxP_ITSNsigmaPr = max; - LOG(info) << "Dielectron Cut, set p range for ITS n sigma Pr: " << mMinP_ITSNsigmaPr << " - " << mMaxP_ITSNsigmaPr; -} +// void DielectronCut::SetITSNsigmaElRange(float min, float max) +// { +// mMinITSNsigmaEl = min; +// mMaxITSNsigmaEl = max; +// LOG(info) << "Dielectron Cut, set ITS n sigma El range: " << mMinITSNsigmaEl << " - " << mMaxITSNsigmaEl; +// } +// void DielectronCut::SetITSNsigmaMuRange(float min, float max) +// { +// mMinITSNsigmaMu = min; +// mMaxITSNsigmaMu = max; +// LOG(info) << "Dielectron Cut, set ITS n sigma Mu range: " << mMinITSNsigmaMu << " - " << mMaxITSNsigmaMu; +// } +// void DielectronCut::SetITSNsigmaPiRange(float min, float max) +// { +// mMinITSNsigmaPi = min; +// mMaxITSNsigmaPi = max; +// LOG(info) << "Dielectron Cut, set ITS n sigma Pi range: " << mMinITSNsigmaPi << " - " << mMaxITSNsigmaPi; +// } +// void DielectronCut::SetITSNsigmaKaRange(float min, float max) +// { +// mMinITSNsigmaKa = min; +// mMaxITSNsigmaKa = max; +// LOG(info) << "Dielectron Cut, set ITS n sigma Ka range: " << mMinITSNsigmaKa << " - " << mMaxITSNsigmaKa; +// } +// void DielectronCut::SetITSNsigmaPrRange(float min, float max) +// { +// mMinITSNsigmaPr = min; +// mMaxITSNsigmaPr = max; +// LOG(info) << "Dielectron Cut, set ITS n sigma Pr range: " << mMinITSNsigmaPr << " - " << mMaxITSNsigmaPr; +// } +// +// void DielectronCut::SetPRangeForITSNsigmaKa(float min, float max) +// { +// mMinP_ITSNsigmaKa = min; +// mMaxP_ITSNsigmaKa = max; +// LOG(info) << "Dielectron Cut, set p range for ITS n sigma Ka: " << mMinP_ITSNsigmaKa << " - " << mMaxP_ITSNsigmaKa; +// } +// +// void DielectronCut::SetPRangeForITSNsigmaPr(float min, float max) +// { +// mMinP_ITSNsigmaPr = min; +// mMaxP_ITSNsigmaPr = max; +// LOG(info) << "Dielectron Cut, set p range for ITS n sigma Pr: " << mMinP_ITSNsigmaPr << " - " << mMaxP_ITSNsigmaPr; +// } void DielectronCut::SetMaxPinMuonTPConly(float max) { @@ -341,3 +345,9 @@ void DielectronCut::RequireITSib1st(bool flag) mRequireITSib1st = flag; LOG(info) << "Dielectron Cut, require ITS ib 1st: " << mRequireITSib1st; } +void DielectronCut::IncludeITSsa(bool flag, float max) +{ + mIncludeITSsa = flag; + mMaxPtITSsa = max; + LOG(info) << "Dielectron Cut, include ITSsa tracks: " << mIncludeITSsa << ", mMaxPtITSsa = " << mMaxPtITSsa; +} diff --git a/PWGEM/Dilepton/Core/DielectronCut.h b/PWGEM/Dilepton/Core/DielectronCut.h index 9ad54af870c..0dc108b05c5 100644 --- a/PWGEM/Dilepton/Core/DielectronCut.h +++ b/PWGEM/Dilepton/Core/DielectronCut.h @@ -16,21 +16,22 @@ #ifndef PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ #define PWGEM_DILEPTON_CORE_DIELECTRONCUT_H_ -#include -#include -#include -#include -#include -#include "TNamed.h" -#include "Math/Vector4D.h" - +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" #include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" + +#include "Math/Vector4D.h" +#include "TNamed.h" + +#include +#include +#include +#include +#include using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using namespace o2::aod::pwgem::dilepton::utils::pairutil; @@ -64,7 +65,7 @@ class DielectronCut : public TNamed kDCAz, kITSNCls, kITSChi2NDF, - kITSClusterSize, + // kITSClusterSize, kPrefilter, kNCuts }; @@ -100,7 +101,7 @@ class DielectronCut : public TNamed } template - bool IsSelectedPair(TTrack1 const& t1, TTrack2 const& t2, const float bz) const + bool IsSelectedPair(TTrack1 const& t1, TTrack2 const& t2, const float bz, const float refR) const { ROOT::Math::PtEtaPhiMVector v1(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassElectron); @@ -136,6 +137,10 @@ class DielectronCut : public TNamed return false; } + if (mApplydEtadPhi && mApplydEtadPhiPosition) { // applying both cuts is not allowed. + return false; + } + float deta = v1.Eta() - v2.Eta(); float dphi = v1.Phi() - v2.Phi(); o2::math_utils::bringToPMPi(dphi); @@ -143,13 +148,24 @@ class DielectronCut : public TNamed return false; } + float phiPosition1 = t1.phi() + std::asin(t1.sign() * 0.30282 * (bz * 0.1) * refR / (2.f * t1.pt())); + float phiPosition2 = t2.phi() + std::asin(t2.sign() * 0.30282 * (bz * 0.1) * refR / (2.f * t2.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = phiPosition1 - phiPosition2; + o2::math_utils::bringToPMPi(dphiPosition); + if (mApplydEtadPhiPosition && std::pow(deta / mMinDeltaEta, 2) + std::pow(dphiPosition / mMinDeltaPhi, 2) < 1.f) { + return false; + } + return true; } template bool IsSelectedTrack(TTrack const& track, TCollision const& collision = 0) const { - if (!track.hasITS() || !track.hasTPC()) { // track has to be ITS-TPC matched track + if (!track.hasITS()) { return false; } @@ -182,9 +198,10 @@ class DielectronCut : public TNamed if (!IsSelectedTrack(track, DielectronCuts::kITSChi2NDF)) { return false; } - if (!IsSelectedTrack(track, DielectronCuts::kITSClusterSize)) { - return false; - } + + // if (!IsSelectedTrack(track, DielectronCuts::kITSClusterSize)) { + // 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); }); @@ -200,24 +217,34 @@ class DielectronCut : public TNamed } } - // TPC cuts - if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { + if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track return false; } - if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { - return false; - } - if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { + + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa return false; } - if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { - return false; + + // TPC cuts + if (track.hasTPC()) { + if (!IsSelectedTrack(track, DielectronCuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCFracSharedClusters)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kRelDiffPin)) { + return false; + } + if (!IsSelectedTrack(track, DielectronCuts::kTPCChi2NDF)) { + return false; + } } if (mApplyPF && !IsSelectedTrack(track, DielectronCuts::kPrefilter)) { @@ -230,8 +257,15 @@ class DielectronCut : public TNamed return false; } } else { - if (!PassPID(track)) { - return false; + if (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) { // ITSsa + float meanClusterSizeITS = track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())); + if (meanClusterSizeITS < mMinMeanClusterSizeITS || mMaxMeanClusterSizeITS < meanClusterSizeITS) { + return false; + } + } else { // not ITSsa + if (!PassPID(track)) { + return false; + } } } @@ -239,14 +273,15 @@ class DielectronCut : public TNamed } template - bool PassPIDML(TTrack const& track, TCollision const& collision) const + bool PassPIDML(TTrack const&, TCollision const&) const { + return false; /*if (!PassTOFif(track)) { // Allows for pre-selection. But potentially dangerous if analyzers are not aware of it return false; }*/ - std::vector inputFeatures = mPIDMlResponse->getInputFeatures(track, collision); - float binningFeature = mPIDMlResponse->getBinningFeature(track, collision); - return mPIDMlResponse->isSelectedMl(inputFeatures, binningFeature); + // std::vector inputFeatures = mPIDMlResponse->getInputFeatures(track, collision); + // float binningFeature = mPIDMlResponse->getBinningFeature(track, collision); + // return mPIDMlResponse->isSelectedMl(inputFeatures, binningFeature); } template @@ -291,9 +326,9 @@ class DielectronCut : public TNamed bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; bool is_pi_excluded_TPC = (track.tpcInnerParam() > mMinPinForPionRejectionTPC && track.tpcInnerParam() < mMaxPinForPionRejectionTPC) ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_el_included_TOF = (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) && (track.hasTOF() && track.tofChi2() < mMaxChi2TOF); - bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; - return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF && is_ka_excluded_ITS && is_pr_excluded_ITS; + // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; + // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; + return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; } template @@ -302,45 +337,45 @@ class DielectronCut : public TNamed bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_el_included_TOF = (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl) && (track.hasTOF() && track.tofChi2() < mMaxChi2TOF); - bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; - return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF && is_ka_excluded_ITS && is_pr_excluded_ITS; + // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; + // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; + return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; } template bool PassTPChadrej(T const& track) const { bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; + // bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); bool is_el_included_TOF = track.hasTOF() ? (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl && track.tofChi2() < mMaxChi2TOF) : true; - bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; - return is_el_included_TPC && is_mu_excluded_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC && is_el_included_TOF && is_ka_excluded_ITS && is_pr_excluded_ITS; + // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; + // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; + return is_el_included_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC && is_el_included_TOF; } template bool PassTPConly(T const& track) const { bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; - return is_el_included_TPC && is_ka_excluded_ITS && is_pr_excluded_ITS; + // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; + // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; + return is_el_included_TPC; } template bool PassTPConlyhadrej(T const& track) const { bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; - bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; + // bool is_mu_excluded_TPC = mMuonExclusionTPC ? track.tpcNSigmaMu() < mMinTPCNsigmaMu || mMaxTPCNsigmaMu < track.tpcNSigmaMu() : true; bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_ka_excluded_TPC = track.tpcNSigmaKa() < mMinTPCNsigmaKa || mMaxTPCNsigmaKa < track.tpcNSigmaKa(); bool is_pr_excluded_TPC = track.tpcNSigmaPr() < mMinTPCNsigmaPr || mMaxTPCNsigmaPr < track.tpcNSigmaPr(); - bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; - return is_el_included_TPC && is_mu_excluded_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC && is_ka_excluded_ITS && is_pr_excluded_ITS; + // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; + // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; + return is_el_included_TPC && is_pi_excluded_TPC && is_ka_excluded_TPC && is_pr_excluded_TPC; } template @@ -349,9 +384,9 @@ class DielectronCut : public TNamed bool is_el_included_TPC = mMinTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; bool is_pi_excluded_TPC = track.tpcInnerParam() < mMaxPinForPionRejectionTPC ? (track.tpcNSigmaPi() < mMinTPCNsigmaPi || mMaxTPCNsigmaPi < track.tpcNSigmaPi()) : true; bool is_el_included_TOF = track.hasTOF() ? (mMinTOFNsigmaEl < track.tofNSigmaEl() && track.tofNSigmaEl() < mMaxTOFNsigmaEl && track.tofChi2() < mMaxChi2TOF) : true; - bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; - bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; - return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF && is_ka_excluded_ITS && is_pr_excluded_ITS; + // bool is_ka_excluded_ITS = (mMinP_ITSNsigmaKa < track.p() && track.p() < mMaxP_ITSNsigmaKa) ? (track.itsNSigmaKa() < mMinITSNsigmaKa || mMaxITSNsigmaKa < track.itsNSigmaKa()) : true; + // bool is_pr_excluded_ITS = (mMinP_ITSNsigmaPr < track.p() && track.p() < mMaxP_ITSNsigmaPr) ? (track.itsNSigmaPr() < mMinITSNsigmaPr || mMaxITSNsigmaPr < track.itsNSigmaPr()) : true; + return is_el_included_TPC && is_pi_excluded_TPC && is_el_included_TOF; } template @@ -359,13 +394,21 @@ class DielectronCut : public TNamed { switch (cut) { case DielectronCuts::kTrackPtRange: - return track.pt() >= mMinTrackPt && track.pt() <= mMaxTrackPt; + return track.pt() > mMinTrackPt && track.pt() < mMaxTrackPt; case DielectronCuts::kTrackEtaRange: - return track.eta() >= mMinTrackEta && track.eta() <= mMaxTrackEta; + return track.eta() > mMinTrackEta && track.eta() < mMaxTrackEta; case DielectronCuts::kTrackPhiRange: - return track.phi() >= mMinTrackPhi && track.phi() <= mMaxTrackPhi; + if (!mMirrorTrackPhi) { + bool is_in_phi_range = track.phi() > mMinTrackPhi && track.phi() < mMaxTrackPhi; + return mRejectTrackPhi ? !is_in_phi_range : is_in_phi_range; + } else { + double minTrackPhiMirror = mMinTrackPhi + TMath::Pi(); + double maxTrackPhiMirror = mMaxTrackPhi + TMath::Pi(); + bool is_in_phi_range = (track.phi() > mMinTrackPhi && track.phi() < mMaxTrackPhi) || (track.phi() > minTrackPhiMirror && track.phi() < maxTrackPhiMirror); + return mRejectTrackPhi ? !is_in_phi_range : is_in_phi_range; + } case DielectronCuts::kTPCNCls: return track.tpcNClsFound() >= mMinNClustersTPC; @@ -374,10 +417,10 @@ class DielectronCut : public TNamed return track.tpcNClsCrossedRows() >= mMinNCrossedRowsTPC; case DielectronCuts::kTPCCrossedRowsOverNCls: - return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; + return track.tpcCrossedRowsOverFindableCls() > mMinNCrossedRowsOverFindableClustersTPC; case DielectronCuts::kTPCFracSharedClusters: - return track.tpcFractionSharedCls() <= mMaxFracSharedClustersTPC; + return track.tpcFractionSharedCls() < mMaxFracSharedClustersTPC; case DielectronCuts::kRelDiffPin: return mMinRelDiffPin < (track.tpcInnerParam() - track.p()) / track.p() && (track.tpcInnerParam() - track.p()) / track.p() < mMaxRelDiffPin; @@ -386,13 +429,13 @@ 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 < dca3DinSigma(track) && dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg case DielectronCuts::kDCAxy: - return std::fabs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); case DielectronCuts::kDCAz: - return std::fabs(track.dcaZ()) <= mMaxDcaZ; + return std::fabs(track.dcaZ()) < mMaxDcaZ; case DielectronCuts::kITSNCls: return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; @@ -400,9 +443,6 @@ class DielectronCut : public TNamed case DielectronCuts::kITSChi2NDF: return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; - case DielectronCuts::kITSClusterSize: - return ((mMinP_ITSClusterSize < track.p() && track.p() < mMaxP_ITSClusterSize) ? (mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS) : true); - case DielectronCuts::kPrefilter: return track.pfb() <= 0; @@ -419,12 +459,12 @@ class DielectronCut : public TNamed void SetPairOpAng(float minOpAng = 0.f, float maxOpAng = 1e10f); void SetMaxMeePhiVDep(std::function phivDepCut, float min_phiv, float max_phiv); void SelectPhotonConversion(bool flag); - void SetMindEtadPhi(bool flag, float min_deta, float min_dphi); + void SetMindEtadPhi(bool applydEtadPhi, bool applydEtadPhiPosition, float min_deta, float min_dphi); void SetRequireDifferentSides(bool flag); void SetTrackPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetTrackEtaRange(float minEta = -1e10f, float maxEta = 1e10f); - void SetTrackPhiRange(float minPhi = 0.f, float maxPhi = 2.f * M_PI); + void SetTrackPhiRange(float minPhi = 0.f, float maxPhi = 2.f * M_PI, bool mirror = false, bool reject = false); void SetMinNClustersTPC(int minNClustersTPC); void SetMinNCrossedRowsTPC(int minNCrossedRowsTPC); void SetMinNCrossedRowsOverFindableClustersTPC(float minNCrossedRowsOverFindableClustersTPC); @@ -433,7 +473,7 @@ class DielectronCut : public TNamed void SetChi2PerClusterTPC(float min, float max); void SetNClustersITS(int min, int max); void SetChi2PerClusterITS(float min, float max); - void SetMeanClusterSizeITS(float min, float max, float minP = 0.f, float maxP = 0.f); + void SetMeanClusterSizeITS(float min, float max); void SetChi2TOF(float min, float max); void SetPIDScheme(int scheme); @@ -441,23 +481,23 @@ class DielectronCut : public TNamed void SetMuonExclusionTPC(bool flag); void SetTOFbetaRange(float min, float max); void SetTPCNsigmaElRange(float min, float max); - void SetTPCNsigmaMuRange(float min, float max); + // void SetTPCNsigmaMuRange(float min, float max); void SetTPCNsigmaPiRange(float min, float max); void SetTPCNsigmaKaRange(float min, float max); void SetTPCNsigmaPrRange(float min, float max); void SetTOFNsigmaElRange(float min, float max); - void SetTOFNsigmaMuRange(float min, float max); + // void SetTOFNsigmaMuRange(float min, float max); void SetTOFNsigmaPiRange(float min, float max); void SetTOFNsigmaKaRange(float min, float max); void SetTOFNsigmaPrRange(float min, float max); - void SetITSNsigmaElRange(float min, float max); - void SetITSNsigmaMuRange(float min, float max); - void SetITSNsigmaPiRange(float min, float max); - void SetITSNsigmaKaRange(float min, float max); - void SetITSNsigmaPrRange(float min, float max); + // void SetITSNsigmaElRange(float min, float max); + // void SetITSNsigmaMuRange(float min, float max); + // void SetITSNsigmaPiRange(float min, float max); + // void SetITSNsigmaKaRange(float min, float max); + // void SetITSNsigmaPrRange(float min, float max); - void SetPRangeForITSNsigmaKa(float min, float max); - void SetPRangeForITSNsigmaPr(float min, float max); + // void SetPRangeForITSNsigmaKa(float min, float max); + // void SetPRangeForITSNsigmaPr(float min, float max); void SetMaxPinMuonTPConly(float max); void SetPinRangeForPionRejectionTPC(float min, float max); @@ -470,6 +510,7 @@ class DielectronCut : public TNamed void SetTrackMaxDcaXYPtDep(std::function ptDepCut); void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); + void IncludeITSsa(bool flag, float maxpt); void SetPIDMlResponse(o2::analysis::MlResponseDielectronSingleTrack* mlResponse) { @@ -491,15 +532,17 @@ class DielectronCut : public TNamed std::function mMaxMeePhiVDep{}; // max mee as a function of phiv bool mSelectPC{false}; // flag to select photon conversion used in mMaxPhivPairMeeDep bool mApplydEtadPhi{false}; // flag to apply deta, dphi cut between 2 tracks + bool mApplydEtadPhiPosition{false}; // flag to apply deta, dphi cut between 2 tracks float mMinDeltaEta{0.f}; float mMinDeltaPhi{0.f}; float mMinOpAng{0.f}, mMaxOpAng{1e10f}; bool mRequireDiffSides{false}; // flag to require 2 tracks to be from different sides. (A-C combination). If one wants 2 tracks to be in the same side (A-A or C-C), one can simply use track eta cut. // kinematic cuts - float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT - float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta - float mMinTrackPhi{0.f}, mMaxTrackPhi{2.f * M_PI}; // range in phi + float mMinTrackPt{0.f}, mMaxTrackPt{1e10f}; // range in pT + float mMinTrackEta{-1e10f}, mMaxTrackEta{1e10f}; // range in eta + float mMinTrackPhi{0.f}, mMaxTrackPhi{2.f * M_PI}; // range in phi + bool mMirrorTrackPhi{false}, mRejectTrackPhi{false}; // phi cut mirror by Pi, rejected/accepted // track quality cuts int mMinNClustersTPC{0}; // min number of TPC clusters @@ -523,8 +566,10 @@ class DielectronCut : public TNamed std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mApplyPhiV{true}; bool mApplyPF{false}; - float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // max x cos(Lmabda) - float mMinP_ITSClusterSize{0.0}, mMaxP_ITSClusterSize{0.0}; + 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}; // pid cuts int mPIDScheme{-1}; @@ -532,24 +577,24 @@ class DielectronCut : public TNamed bool mMuonExclusionTPC{false}; // flag to reject muon in TPC for low B float mMinTOFbeta{-999}, mMaxTOFbeta{999}; float mMinTPCNsigmaEl{-1e+10}, mMaxTPCNsigmaEl{+1e+10}; - float mMinTPCNsigmaMu{-1e+10}, mMaxTPCNsigmaMu{+1e+10}; + // float mMinTPCNsigmaMu{-1e+10}, mMaxTPCNsigmaMu{+1e+10}; float mMinTPCNsigmaPi{-1e+10}, mMaxTPCNsigmaPi{+1e+10}; float mMinTPCNsigmaKa{-1e+10}, mMaxTPCNsigmaKa{+1e+10}; float mMinTPCNsigmaPr{-1e+10}, mMaxTPCNsigmaPr{+1e+10}; float mMinTOFNsigmaEl{-1e+10}, mMaxTOFNsigmaEl{+1e+10}; - float mMinTOFNsigmaMu{-1e+10}, mMaxTOFNsigmaMu{+1e+10}; + // float mMinTOFNsigmaMu{-1e+10}, mMaxTOFNsigmaMu{+1e+10}; float mMinTOFNsigmaPi{-1e+10}, mMaxTOFNsigmaPi{+1e+10}; float mMinTOFNsigmaKa{-1e+10}, mMaxTOFNsigmaKa{+1e+10}; float mMinTOFNsigmaPr{-1e+10}, mMaxTOFNsigmaPr{+1e+10}; - float mMinITSNsigmaEl{-1e+10}, mMaxITSNsigmaEl{+1e+10}; - float mMinITSNsigmaMu{-1e+10}, mMaxITSNsigmaMu{+1e+10}; - float mMinITSNsigmaPi{-1e+10}, mMaxITSNsigmaPi{+1e+10}; - float mMinITSNsigmaKa{-1e+10}, mMaxITSNsigmaKa{+1e+10}; - float mMinITSNsigmaPr{-1e+10}, mMaxITSNsigmaPr{+1e+10}; - float mMinP_ITSNsigmaKa{0.0}, mMaxP_ITSNsigmaKa{0.0}; - float mMinP_ITSNsigmaPr{0.0}, mMaxP_ITSNsigmaPr{0.0}; + // float mMinITSNsigmaEl{-1e+10}, mMaxITSNsigmaEl{+1e+10}; + // float mMinITSNsigmaMu{-1e+10}, mMaxITSNsigmaMu{+1e+10}; + // float mMinITSNsigmaPi{-1e+10}, mMaxITSNsigmaPi{+1e+10}; + // float mMinITSNsigmaKa{-1e+10}, mMaxITSNsigmaKa{+1e+10}; + // float mMinITSNsigmaPr{-1e+10}, mMaxITSNsigmaPr{+1e+10}; + // float mMinP_ITSNsigmaKa{0.0}, mMaxP_ITSNsigmaKa{0.0}; + // float mMinP_ITSNsigmaPr{0.0}, mMaxP_ITSNsigmaPr{0.0}; o2::analysis::MlResponseDielectronSingleTrack* mPIDMlResponse{nullptr}; diff --git a/PWGEM/Dilepton/Core/Dilepton.h b/PWGEM/Dilepton/Core/Dilepton.h index 95bd4a0b6f8..2ded13ca237 100644 --- a/PWGEM/Dilepton/Core/Dilepton.h +++ b/PWGEM/Dilepton/Core/Dilepton.h @@ -17,47 +17,48 @@ #ifndef PWGEM_DILEPTON_CORE_DILEPTON_H_ #define PWGEM_DILEPTON_CORE_DILEPTON_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include "TH1D.h" -#include "TString.h" -#include "Math/Vector4D.h" +#include "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/EMFwdTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.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/GRPLHCIFData.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 "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "Math/Vector4D.h" +#include "TH1D.h" +#include "TString.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" -#include "PWGEM/Dilepton/Core/DimuonCut.h" -#include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EMFwdTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -74,7 +75,7 @@ using MyCollision = MyCollisions::iterator; using MyCollisionsWithSWT = soa::Join; using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; -using MyElectrons = soa::Join; +using MyElectrons = soa::Join; using MyElectron = MyElectrons::iterator; using FilteredMyElectrons = soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; @@ -84,7 +85,7 @@ using MyMuon = MyMuons::iterator; using FilteredMyMuons = soa::Filtered; using FilteredMyMuon = FilteredMyMuons::iterator; -using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrackWithCov>; +using MyEMH_electron = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; using MyEMH_muon = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMFwdTrack>; template @@ -109,7 +110,7 @@ struct Dilepton { Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; Configurable cfgDoMix{"cfgDoMix", true, "flag for event mixing"}; Configurable ndepth{"ndepth", 100, "depth for event mixing"}; - Configurable ndiff_bc_mix{"ndiff_bc_mix", 5, "difference in global BC required in mixed events"}; + 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"}; @@ -139,7 +140,8 @@ struct Dilepton { 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 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"}; @@ -155,7 +157,7 @@ struct Dilepton { 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_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + 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; @@ -176,7 +178,8 @@ struct Dilepton { 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"}; + 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_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; @@ -195,6 +198,8 @@ struct Dilepton { 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"}; @@ -208,16 +213,15 @@ struct Dilepton { 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_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; 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]"}; 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_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"}; @@ -228,15 +232,17 @@ struct Dilepton { 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 cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; - Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; - Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; - Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; - Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; - Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; + // Configurable cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; + // Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; + // Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; + // Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; + // Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; + // Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; 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)"}; @@ -281,6 +287,11 @@ struct Dilepton { 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::aod::rctsel::RCTFlagsChecker rctChecker; @@ -454,7 +465,7 @@ struct Dilepton { 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"; + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kG"; } else { grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); if (!grpmag) { @@ -463,7 +474,7 @@ struct Dilepton { 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"; + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kG"; } mRunNumber = collision.runNumber(); @@ -539,6 +550,8 @@ struct Dilepton { if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonAnalysisType::kQC)) { fRegistry.add("Pair/same/uls/hs", "dilepton", kTHnSparseD, {axis_mass, axis_pt, axis_dca}, true); 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/hDeltaEtaDeltaPhiPosition", "#Delta#eta-#Delta#varphi^{*} between 2 tracks;#Delta#varphi^{*} (rad.);#Delta#eta;", 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); @@ -637,6 +650,7 @@ struct Dilepton { 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); @@ -660,14 +674,14 @@ struct Dilepton { 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, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); + fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, dielectroncuts.cfg_apply_detadphiposition, 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); + 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); @@ -675,38 +689,39 @@ struct Dilepton { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + 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, 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.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); - fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); - fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); - fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); - fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); + // fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); + // fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); + // fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); + // fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + 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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; @@ -749,6 +764,8 @@ struct Dilepton { 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 @@ -842,7 +859,7 @@ struct Dilepton { } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - if (!cut.IsSelectedPair(t1, t2, d_bz)) { + if (!cut.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { return false; } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { @@ -894,12 +911,21 @@ struct Dilepton { float dphi = t1.sign() * v1.Pt() > t2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); o2::math_utils::bringToPMPi(dphi); + float phiPosition1 = t1.phi() + std::asin(t1.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * t1.pt())); + float phiPosition2 = t2.phi() + std::asin(t2.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * t2.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = t1.sign() * v1.Pt() > t2.sign() * v2.Pt() ? phiPosition1 - phiPosition2 : phiPosition2 - phiPosition1; + o2::math_utils::bringToPMPi(dphiPosition); + 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 opAng = o2::aod::pwgem::dilepton::utils::pairutil::getOpeningAngle(t1.px(), t1.py(), t1.pz(), t2.px(), t2.py(), t2.pz()); if (t1.sign() * t2.sign() < 0) { // ULS fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDeltaEtaDeltaPhi"), dphi, deta, weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta, weight); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("uls/hMvsOpAng"), opAng, v12.M(), weight); @@ -912,6 +938,7 @@ struct Dilepton { } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDeltaEtaDeltaPhi"), dphi, deta, weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta, weight); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hMvsOpAng"), opAng, v12.M(), weight); @@ -924,6 +951,7 @@ 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, weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDeltaEtaDeltaPhi"), dphi, deta, weight); + fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta, weight); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsPhiV"), phiv, v12.M(), weight); fRegistry.fill(HIST("Pair/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hMvsOpAng"), opAng, v12.M(), weight); @@ -1054,13 +1082,9 @@ struct Dilepton { used_trackIds.emplace_back(pair_tmp_id1); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, - t1.x(), t1.y(), t1.z(), t1.alpha(), t1.snp(), t1.tgl(), t1.cYY(), t1.cZY(), t1.cZZ(), - t1.cSnpY(), t1.cSnpZ(), t1.cSnpSnp(), t1.cTglY(), t1.cTglZ(), t1.cTglSnp(), t1.cTglTgl(), t1.c1PtY(), t1.c1PtZ(), t1.c1PtSnp(), t1.c1PtTgl(), t1.c1Pt21Pt2())); + emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, t1.cYY(), t1.cZY(), t1.cZZ())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, - t1.x(), t1.y(), t1.z(), t1.alpha(), t1.snp(), t1.tgl(), t1.cYY(), t1.cZY(), t1.cZZ(), - t1.cSnpY(), t1.cSnpZ(), t1.cSnpSnp(), t1.cTglY(), t1.cTglZ(), t1.cTglSnp(), t1.cTglTgl(), t1.c1PtY(), t1.c1PtZ(), t1.c1PtSnp(), t1.c1PtTgl(), t1.c1Pt21Pt2())); + emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, t1.cYY(), t1.cZY(), t1.cZZ())); } } } @@ -1068,13 +1092,9 @@ struct Dilepton { used_trackIds.emplace_back(pair_tmp_id2); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, - t2.x(), t2.y(), t2.z(), t2.alpha(), t2.snp(), t2.tgl(), t2.cYY(), t2.cZY(), t2.cZZ(), - t2.cSnpY(), t2.cSnpZ(), t2.cSnpSnp(), t2.cTglY(), t2.cTglZ(), t2.cTglSnp(), t2.cTglTgl(), t2.c1PtY(), t2.c1PtZ(), t2.c1PtSnp(), t2.c1PtTgl(), t2.c1Pt21Pt2())); + emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, t2.cYY(), t2.cZY(), t2.cZZ())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMTrackWithCov(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, - t2.x(), t2.y(), t2.z(), t2.alpha(), t2.snp(), t2.tgl(), t2.cYY(), t2.cZY(), t2.cZZ(), - t2.cSnpY(), t2.cSnpZ(), t2.cSnpSnp(), t2.cTglY(), t2.cTglZ(), t2.cTglSnp(), t2.cTglTgl(), t2.c1PtY(), t2.c1PtZ(), t2.c1PtSnp(), t2.c1PtTgl(), t2.c1Pt21Pt2())); + emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, t2.cYY(), t2.cZY(), t2.cZZ())); } } } @@ -1086,10 +1106,10 @@ struct Dilepton { used_trackIds.emplace_back(pair_tmp_id1); if (cfgDoMix) { if (t1.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); } } @@ -1098,10 +1118,10 @@ struct Dilepton { used_trackIds.emplace_back(pair_tmp_id2); if (cfgDoMix) { if (t2.sign() > 0) { - emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); } else { - emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); } } @@ -1119,8 +1139,7 @@ struct Dilepton { SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; - Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + 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) && @@ -1140,7 +1159,7 @@ struct Dilepton { 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 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); @@ -1325,25 +1344,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, tracks); + fillPairInfo<1>(collision, pos, neg, cut, nullptr); } } 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, tracks); + fillPairInfo<1>(collision, neg, pos, cut, nullptr); } } 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, tracks); + fillPairInfo<1>(collision, pos1, pos2, cut, nullptr); } } 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, tracks); + fillPairInfo<1>(collision, neg1, neg2, cut, nullptr); } } } // end of loop over mixed event pool @@ -1385,7 +1404,7 @@ struct Dilepton { } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - if (!cut.IsSelectedPair(t1, t2, d_bz)) { + if (!cut.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { return false; } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { diff --git a/PWGEM/Dilepton/Core/DileptonHadronMPC.h b/PWGEM/Dilepton/Core/DileptonHadronMPC.h new file mode 100644 index 00000000000..9efb785a21a --- /dev/null +++ b/PWGEM/Dilepton/Core/DileptonHadronMPC.h @@ -0,0 +1,1436 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over leptons. +// Please write to: daiki.sekihata@cern.ch + +#ifndef PWGEM_DILEPTON_CORE_DILEPTONHADRONMPC_H_ +#define PWGEM_DILEPTON_CORE_DILEPTONHADRONMPC_H_ + +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Core/EMTrackCut.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/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/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 "TH1D.h" +#include "TString.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::dilepton::utils; +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 MyCollisionsWithSWT = soa::Join; +using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; + +using MyElectrons = soa::Join; +using MyElectron = MyElectrons::iterator; +using FilteredMyElectrons = soa::Filtered; +using FilteredMyElectron = FilteredMyElectrons::iterator; + +using MyMuons = soa::Join; +using MyMuon = MyMuons::iterator; +using FilteredMyMuons = soa::Filtered; +using FilteredMyMuon = FilteredMyMuons::iterator; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::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 + +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, 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"}; + Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; // 1 trigger name per 1 task. fHighTrackMult, fHighFt0Mult + // Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; + // Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; + Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; + Configurable 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.20, 0.30, 0.40, 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"}; + + // 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 ConfRapidityBins{"ConfRapidityBins", {20, -1, 1}, "rapidity bins for output histograms"}; + ConfigurableAxis ConfDEtaBins{"ConfDEtaBins", {60, -3, 3}, "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"}; + + 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", 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 "}; + // 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_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_1 : 2, kElFromPi0_2 : 4, kElFromPi0_3 : 8] 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"}; + + // 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_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"}; + 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"}; + } dimuoncuts; + + 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; + 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}; + 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 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*/) + { + 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); + + 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]); + } + } + + 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]); + } + } + + emh_pos = new TEMH(ndepth_lepton); + emh_neg = new TEMH(ndepth_lepton); + emh_ref = new MyEMH_track(ndepth_hadron); // for reference flow + + DefineEMEventCut(); + DefineEMTrackCut(); + addhistograms(); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + DefineDielectronCut(); + leptonM1 = o2::constants::physics::MassElectron; + leptonM2 = o2::constants::physics::MassElectron; + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + DefineDimuonCut(); + leptonM1 = o2::constants::physics::MassMuon; + leptonM2 = o2::constants::physics::MassMuon; + } + + if (doprocessTriggerAnalysis) { + fRegistry.add("Event/hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + } + } + + template + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + // In case override, don't proceed, please - no CCDB access required + if (d_bz_input > -990) { + d_bz = d_bz_input; + o2::parameters::GRPMagField grpmag; + if (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 << " 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(); + + 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()); + } + } + + ~DileptonHadronMPC() + { + delete emh_pos; + emh_pos = 0x0; + delete emh_neg; + emh_neg = 0x0; + delete emh_ref; + emh_ref = 0x0; + + used_trackIds.clear(); + used_trackIds.shrink_to_fit(); + used_refTrackIds.clear(); + used_refTrackIds.shrink_to_fit(); + } + + void addhistograms() + { + // event info + o2::aod::pwgem::dilepton::utils::eventhistogram::addEventHistograms<-1>(&fRegistry); + + std::string mass_axis_title = "m_{ll} (GeV/c^{2})"; + std::string pair_pt_axis_title = "p_{T,ll}^{trg} (GeV/c)"; + std::string pair_dca_axis_title = "DCA_{ll} (#sigma)"; + std::string pair_rapidity_axis_title = "y_{ll}"; + std::string deta_axis_title = "#Delta#eta = #eta_{ll} - #eta_{h}"; + std::string dphi_axis_title = "#Delta#varphi = #varphi_{ll} - #varphi_{h} (rad.)"; + std::string cosndphi_axis_title = std::format("cos({0:d}(#varphi_{{ll}} - #varphi_{{h}}))", cfgNmod.value); + + 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_rapidity_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)"; + } + deta_axis_title = "#Delta#eta = #eta_{ee} - #eta_{h}"; + dphi_axis_title = "#Delta#varphi = #varphi_{ee} - #varphi_{h} (rad.)"; + cosndphi_axis_title = std::format("cos({0:d}(#varphi_{{ee}} - #varphi_{{h}}))", cfgNmod.value); + } 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_rapidity_axis_title = "y_{#mu#mu}"; + pair_dca_axis_title = "DCA_{#mu#mu}^{XY} (#sigma)"; + deta_axis_title = "#Delta#eta = #eta_{#mu#mu} - #eta_{h}"; + dphi_axis_title = "#Delta#varphi = #varphi_{#mu#mu} - #varphi_{h} (rad.)"; + cosndphi_axis_title = std::format("cos({0:d}(#varphi_{{#mu#mu}} - #varphi_{{h}}))", cfgNmod.value); + } + + // 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{ConfRapidityBins, pair_rapidity_axis_title}; + + // dilepton-hadron info + const 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 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}, true); + fRegistry.add("Dilepton/same/uls/hs", "dilepton", 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}; + // 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.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_dphi_hh{cfgNbinsDPhi, -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); + 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); + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kCumulant)) { + const 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.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}}^{{trg}} - #varphi_{{h}}^{{ref}}))", cfgNmod.value)}; + fRegistry.add("HadronHadron/same/hDEtaCosNDPhi", "hadron-hadron 2PC", 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); + } + + 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); + } + + o2::analysis::MlResponseDielectronSingleTrack mlResponseSingleTrack; + 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, dielectroncuts.cfg_apply_detadphiposition, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); + fDielectronCut.SetPairOpAng(0.f, 6.3); + fDielectronCut.SetRequireDifferentSides(false); + + // 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, false, false); + 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(0.f, 16.f); + 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, dielectroncuts.cfg_max_chi2tof); + fDielectronCut.SetRelDiffPin(-1e+10, +1e+10); + fDielectronCut.IncludeITSsa(false, 0.15); + + // for eID + fDielectronCut.SetPIDScheme(dielectroncuts.cfg_pid_scheme); + fDielectronCut.SetTPCNsigmaElRange(dielectroncuts.cfg_min_TPCNsigmaEl, dielectroncuts.cfg_max_TPCNsigmaEl); + 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 + 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 + } + + 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); + 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, 16); + fDimuonCut.SetChi2(0.f, dimuoncuts.cfg_max_chi2); + fDimuonCut.SetMatchingChi2MCHMFT(0.f, dimuoncuts.cfg_max_matching_chi2_mftmch); + fDimuonCut.SetMatchingChi2MCHMID(0.f, dimuoncuts.cfg_max_matching_chi2_mchmid); + fDimuonCut.SetDCAxy(0.f, dimuoncuts.cfg_max_dcaxy); + fDimuonCut.SetRabs(dimuoncuts.cfg_min_rabs, dimuoncuts.cfg_max_rabs); + fDimuonCut.SetMaxPDCARabsDep([&](float rabs) { return (rabs < 26.5 ? 594.f : 324.f); }); + 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); + } + + 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); + } + + template + bool fillDilepton(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks) + { + if constexpr (ev_id == 1) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto v1ambIds = t1.ambiguousElectronsIds(); + auto v2ambIds = t2.ambiguousElectronsIds(); + + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto v1ambIds = t1.ambiguousMuonsIds(); + auto v2ambIds = t2.ambiguousMuonsIds(); + + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } + } + + if constexpr (ev_id == 0) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(t1, collision) || !cut.template IsSelectedTrack(t2, collision)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + + if (!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.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.IsSelectedPair(t1, t2)) { + return false; + } + } + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; + } + if (ev_id == 1) { + weight = 1.f; + } + + 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)); + } + + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("Dilepton/") + 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("Dilepton/") + 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("Dilepton/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), weight); + } + + // store tracks for event mixing without double counting + if constexpr (ev_id == 0) { + std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); + std::pair pair_tmp_id1 = std::make_pair(ndf, t1.globalIndex()); + std::pair pair_tmp_id2 = std::make_pair(ndf, t2.globalIndex()); + + std::vector possibleIds1; + std::vector possibleIds2; + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + std::copy(t1.ambiguousElectronsIds().begin(), t1.ambiguousElectronsIds().end(), std::back_inserter(possibleIds1)); + std::copy(t2.ambiguousElectronsIds().begin(), t2.ambiguousElectronsIds().end(), std::back_inserter(possibleIds2)); + + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id1) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id1); + if (cfgDoMix) { + if (t1.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, t1.cYY(), t1.cZY(), t1.cZZ())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), leptonM1, t1.sign(), t1.dcaXY(), t1.dcaZ(), possibleIds1, t1.cYY(), t1.cZY(), t1.cZZ())); + } + } + } + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id2) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id2); + if (cfgDoMix) { + if (t2.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, t2.cYY(), t2.cZY(), t2.cZZ())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), leptonM2, t2.sign(), t2.dcaXY(), t2.dcaZ(), possibleIds2, t2.cYY(), t2.cZY(), t2.cZZ())); + } + } + } + } else if (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + std::copy(t1.ambiguousMuonsIds().begin(), t1.ambiguousMuonsIds().end(), std::back_inserter(possibleIds1)); + std::copy(t2.ambiguousMuonsIds().begin(), t2.ambiguousMuonsIds().end(), std::back_inserter(possibleIds2)); + + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id1) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id1); + if (cfgDoMix) { + if (t1.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, + t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.fwdtrackId(), t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassMuon, t1.sign(), t1.fwdDcaX(), t1.fwdDcaY(), possibleIds1, + t1.cXXatDCA(), t1.cXYatDCA(), t1.cYYatDCA())); + } + } + } + if (std::find(used_trackIds.begin(), used_trackIds.end(), pair_tmp_id2) == used_trackIds.end()) { + used_trackIds.emplace_back(pair_tmp_id2); + if (cfgDoMix) { + if (t2.sign() > 0) { + emh_pos->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, + t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + } else { + emh_neg->AddTrackToEventPool(key_df_collision, EMFwdTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.fwdtrackId(), t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassMuon, t2.sign(), t2.fwdDcaX(), t2.fwdDcaY(), possibleIds2, + t2.cXXatDCA(), t2.cXYatDCA(), t2.cYYatDCA())); + } + } + } + } + } + return true; + } + + template + bool fillDileptonHadron(TCollision const& collision, TTrack1 const& t1, TTrack2 const& t2, TCut const& cut, TAllTracks const& tracks, TRefTrack const& t3) + { + // this function must be called, if dilepton passes the cut. + if constexpr (ev_id == 1) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + // bool is_found1 = std::find(t2.ambiguousElectronsIds.begin(), t2.ambiguousElectronsIds.end(), t1.globalIndex()) != t2.ambiguousElectronsIds.end(); // this does not work. + // bool is_found2 = std::find(t1.ambiguousElectronsIds.begin(), t1.ambiguousElectronsIds.end(), t2.globalIndex()) != t1.ambiguousElectronsIds.end(); // this does not work. + auto v1ambIds = t1.ambiguousElectronsIds(); + auto v2ambIds = t2.ambiguousElectronsIds(); + + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + // bool is_found1 = std::find(t2.ambiguousMuonsIds.begin(), t2.ambiguousMuonsIds.end(), t1.globalIndex()) != t2.ambiguousMuonsIds.end(); // this does not work. + // bool is_found2 = std::find(t1.ambiguousMuonsIds.begin(), t1.ambiguousMuonsIds.end(), t2.globalIndex()) != t1.ambiguousMuonsIds.end(); // this does not work. + auto v1ambIds = t1.ambiguousMuonsIds(); + auto v2ambIds = t2.ambiguousMuonsIds(); + + if ((t1.dfId() == t2.dfId()) && std::find(v2ambIds.begin(), v2ambIds.end(), t1.globalIndex()) != v2ambIds.end() && std::find(v1ambIds.begin(), v1ambIds.end(), t2.globalIndex()) != v1ambIds.end()) { + return false; // this is protection against pairing 2 identical tracks. This happens, when TTCA is used. TTCA can assign a track to several possible collisions. + } + } + } + + if constexpr (ev_id == 0) { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { + if (!cut.template IsSelectedTrack(t1, collision) || !cut.template IsSelectedTrack(t2, collision)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + 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)) { + return false; + } + if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(t2, cut, tracks)) { + return false; + } + } + + if (!fEMTrackCut.IsSelected(t3)) { // for charged track + return false; + } + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (!cut.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.IsSelectedPair(t1, t2)) { + return false; + } + } + + float weight = 1.f; + if (cfgApplyWeightTTCA) { + weight = map_weight[std::make_pair(t1.globalIndex(), t2.globalIndex())]; + } + if (ev_id == 1) { + weight = 1.f; + } + + 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; + + ROOT::Math::PtEtaPhiMVector v3(t3.pt(), t3.eta(), t3.phi(), 0.139); // mass of hadron does not matter. + float deta = v12.Eta() - v3.Eta(); + float dphi = v12.Phi() - v3.Phi(); + + 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)); + } + + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation)) { + dphi = RecoDecay::constrainAngle(dphi, -M_PI / 2, 1U); + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("DileptonHadron/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), deta, dphi, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("DileptonHadron/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), deta, dphi, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("DileptonHadron/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), deta, dphi, weight); + } + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kCumulant)) { + o2::math_utils::bringTo02Pi(dphi); + float cosndphi = std::cos(cfgNmod * dphi); + if (t1.sign() * t2.sign() < 0) { // ULS + fRegistry.fill(HIST("DileptonHadron/") + HIST(event_pair_types[ev_id]) + HIST("uls/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), deta, cosndphi, weight); + } else if (t1.sign() > 0 && t2.sign() > 0) { // LS++ + fRegistry.fill(HIST("DileptonHadron/") + HIST(event_pair_types[ev_id]) + HIST("lspp/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), deta, cosndphi, weight); + } else if (t1.sign() < 0 && t2.sign() < 0) { // LS-- + fRegistry.fill(HIST("DileptonHadron/") + HIST(event_pair_types[ev_id]) + HIST("lsmm/hs"), v12.M(), v12.Pt(), pair_dca, v12.Rapidity(), deta, cosndphi, weight); + } + } + + return true; + } + + template + bool fillHadronHadron(TCollision const& collision, TRefTrack const& t1, TRefTrack const& t2, TLeptons const& posLeptons, TLeptons const& negLeptons) + { + if constexpr (ev_id == 0) { + if (!fEMTrackCut.IsSelected(t1) || !fEMTrackCut.IsSelected(t2)) { // for charged track + return false; + } + + // 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 (t1.trackId() == pos.trackId() || t2.trackId() == pos.trackId()) { + return false; + } + } + for (const auto& neg : negLeptons) { // leptons per collision + if (t1.trackId() == neg.trackId() || t2.trackId() == neg.trackId()) { + return false; + } + } + } + } + + if constexpr (ev_id == 1) { + if (t1.dfId() == t2.dfId() && t1.globalIndex() == t2.globalIndex()) { + return false; // this never happens. only for protection. + } + } + + float weight = 1.f; + float deta = t1.eta() - t2.eta(); // t1 is trigger, t2 is associated + float dphi = t1.phi() - t2.phi(); // t1 is trigger, t2 is associated + + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation)) { + dphi = RecoDecay::constrainAngle(dphi, -M_PI / 2, 1U); + fRegistry.fill(HIST("HadronHadron/") + HIST(event_pair_types[ev_id]) + HIST("hDEtaDPhi"), dphi, deta, weight); + } else if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kCumulant)) { + o2::math_utils::bringTo02Pi(dphi); + float cosndphi = std::cos(cfgNmod * dphi); + fRegistry.fill(HIST("HadronHadron/") + HIST(event_pair_types[ev_id]) + HIST("hDEtaCosNDPhi"), cosndphi, deta, weight); + } + + // store ref tracks for mixed event in case of kAzimuthalCorrelation + if constexpr (ev_id == 0) { + if (cfgDoMix && cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation)) { + std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); + std::pair pair_tmp_id1 = std::make_pair(ndf, t1.globalIndex()); + std::pair pair_tmp_id2 = std::make_pair(ndf, t2.globalIndex()); + if (std::find(used_refTrackIds.begin(), used_refTrackIds.end(), pair_tmp_id1) == used_refTrackIds.end()) { + used_refTrackIds.emplace_back(pair_tmp_id1); + emh_ref->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t1.globalIndex(), collision.globalIndex(), t1.trackId(), t1.pt(), t1.eta(), t1.phi(), 0.139)); + } // store t1 + if (std::find(used_refTrackIds.begin(), used_refTrackIds.end(), pair_tmp_id2) == used_refTrackIds.end()) { + used_refTrackIds.emplace_back(pair_tmp_id2); + emh_ref->AddTrackToEventPool(key_df_collision, EMTrack(ndf, t2.globalIndex(), collision.globalIndex(), t2.trackId(), t2.pt(), t2.eta(), t2.phi(), 0.139)); + } // store t2 + } + } + + 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_1))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_1))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_2))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_2))) <= static_cast(0), true) && + ifnode((dielectroncuts.cfg_prefilter_bits.node() & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_3))) > static_cast(0), (o2::aod::emprimaryelectron::pfb & static_cast(1 << int(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPi0_3))) <= 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_track = aod::emprimarytrack::emeventId; + + 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); + + TEMH* emh_pos = nullptr; + TEMH* emh_neg = nullptr; + MyEMH_track* emh_ref = nullptr; // for reference flow + std::map, uint64_t> map_mixed_eventId_to_globalBC; + + std::vector> used_trackIds; + std::vector> used_refTrackIds; + 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) + { + 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]) { + continue; + } + + if constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + } + + o2::aod::pwgem::dilepton::utils::eventhistogram::fillEventInfo<0, -1>(&fRegistry, collision); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + 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 refTracks_per_coll = refTracks.sliceBy(perCollision_track, collision.globalIndex()); + + auto posTracks_per_coll = posTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + auto negTracks_per_coll = negTracks.sliceByCached(perCollision, collision.globalIndex(), cache); + + 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); + if (is_pair_ok) { + nuls++; + for (const auto& refTrack : refTracks_per_coll) { + fillDileptonHadron<0>(collision, pos, neg, cut, tracks, 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); + if (is_pair_ok) { + nlspp++; + for (const auto& refTrack : refTracks_per_coll) { + fillDileptonHadron<0>(collision, pos1, pos2, cut, tracks, 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); + if (is_pair_ok) { + nlsmm++; + for (const auto& refTrack : refTracks_per_coll) { + fillDileptonHadron<0>(collision, neg1, neg2, cut, tracks, refTrack); + } + } + } + + if (nuls > 0 || nlspp > 0 || nlsmm > 0) { // at least 1 pair exists. + for (const auto& track : refTracks_per_coll) { + if (fEMTrackCut.IsSelected(track)) { + fRegistry.fill(HIST("Hadron/hs"), track.pt(), track.eta(), track.phi()); + } + } + for (const auto& [trg, ref] : combinations(CombinationsStrictlyUpperIndexPolicy(refTracks_per_coll, refTracks_per_coll))) { + fillHadronHadron<0>(collision, trg, ref, posTracks_per_coll, negTracks_per_coll); + } + } + + if (!cfgDoMix || !(nuls > 0 || nlspp > 0 || nlsmm > 0)) { + continue; + } + + // event mixing + int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; + if (zbin < 0) { + zbin = 0; + } else if (static_cast(zvtx_bin_edges.size()) - 2 < zbin) { + zbin = static_cast(zvtx_bin_edges.size()) - 2; + } + + int centbin = lower_bound(cent_bin_edges.begin(), cent_bin_edges.end(), centrality) - cent_bin_edges.begin() - 1; + if (centbin < 0) { + centbin = 0; + } else if (static_cast(cent_bin_edges.size()) - 2 < centbin) { + centbin = static_cast(cent_bin_edges.size()) - 2; + } + + int epbin = 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; + } + + std::tuple key_bin = std::make_tuple(zbin, centbin, epbin, occbin); + std::pair key_df_collision = std::make_pair(ndf, collision.globalIndex()); + + // make a vector of selected electrons in this collision. + auto selected_posTracks_in_this_event = emh_pos->GetTracksPerCollision(key_df_collision); + auto selected_negTracks_in_this_event = emh_neg->GetTracksPerCollision(key_df_collision); + + auto collisionIds_in_mixing_pool = emh_pos->GetCollisionIdsFromEventPool(key_bin); // pos/neg does not matter. + + // LOGF(info, "selected_posTracks_in_this_event.size() = %d, selected_negTracks_in_this_event.size() = %d, collisionIds_in_mixing_pool.size() = %d", selected_posTracks_in_this_event.size(), selected_negTracks_in_this_event.size(), collisionIds_in_mixing_pool.size()); + + // perform event mixing, only if at least 1 dilepton exists. + + for (const auto& mix_dfId_collisionId : collisionIds_in_mixing_pool) { + int mix_dfId = mix_dfId_collisionId.first; + int mix_collisionId = mix_dfId_collisionId.second; + if (collision.globalIndex() == mix_collisionId && ndf == mix_dfId) { // this never happens. only protection. + continue; + } + + auto globalBC_mix = map_mixed_eventId_to_globalBC[mix_dfId_collisionId]; + uint64_t diffBC = std::max(collision.globalBC(), globalBC_mix) - std::min(collision.globalBC(), globalBC_mix); + fRegistry.fill(HIST("Dilepton/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto posTracks_from_event_pool = emh_pos->GetTracksPerCollision(mix_dfId_collisionId); + auto negTracks_from_event_pool = emh_neg->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "posTracks_from_event_pool.size() = %d, negTracks_from_event_pool.size() = %d", posTracks_from_event_pool.size(), negTracks_from_event_pool.size()); + + 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); + } + } + + 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); + } + } + + 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); + } + } + + 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); + } + } + } // end of loop over mixed event pool for lepton-lepton + + if (cfgAnalysisType == static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonHadronAnalysisType::kAzimuthalCorrelation)) { + auto selected_refTracks_in_this_event = emh_ref->GetTracksPerCollision(key_df_collision); + auto collisionIds_in_mixing_pool_hadron = emh_ref->GetCollisionIdsFromEventPool(key_bin); + // LOGF(info, "selected_refTracks_in_this_event.size() = %d, collisionIds_in_mixing_pool_hadron.size() = %d", selected_refTracks_in_this_event.size(), collisionIds_in_mixing_pool_hadron.size()); + + 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("HadronHadron/mix/hDiffBC"), diffBC); + if (diffBC < ndiff_bc_mix) { + continue; + } + + auto refTracks_from_event_pool = emh_ref->GetTracksPerCollision(mix_dfId_collisionId); + // LOGF(info, "refTracks_from_event_pool.size() = %d", refTracks_from_event_pool.size()); + for (const auto& ref1 : selected_refTracks_in_this_event) { // ref-ref mix + for (const auto& ref2 : refTracks_from_event_pool) { + fillHadronHadron<1>(collision, ref1, ref2, nullptr, nullptr); + } + } + } // end of loop over mixed event pool for lepton-lepton + } + + if (nuls > 0 || nlspp > 0 || nlsmm > 0) { + map_mixed_eventId_to_globalBC[key_df_collision] = collision.globalBC(); + emh_pos->AddCollisionIdAtLast(key_bin, key_df_collision); + emh_neg->AddCollisionIdAtLast(key_bin, key_df_collision); + emh_ref->AddCollisionIdAtLast(key_bin, key_df_collision); + } + + } // end of collision loop + + } // end of DF + + template + bool isPairOK(TCollision const& collision, 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, collision) || !cut.template IsSelectedTrack(t2, collision)) { + return false; + } + } else { // cut-based + if (!cut.template IsSelectedTrack(t1) || !cut.template IsSelectedTrack(t2)) { + return false; + } + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.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)) { + return false; + } + } + + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + if (!cut.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { + return false; + } + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + if (!cut.IsSelectedPair(t1, t2)) { + return false; + } + } + return true; + } + + std::map, float> map_weight; // -> float + template + void fillPairWeightMap(TCollisions const& collisions, TLeptons const& posTracks, TLeptons const& negTracks, TPresilce const& perCollision, TCut const& cut, TAllTracks const& tracks) + { + std::vector> passed_pairIds; + passed_pairIds.reserve(posTracks.size() * negTracks.size()); + + for (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 constexpr (isTriggerAnalysis) { + if (!collision.swtalias_bit(o2::aod::pwgem::dilepton::swt::aliasLabels.at(cfg_swt_name.value))) { + continue; + } + } + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + if (eventcuts.cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + 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 + if (isPairOK(collision, 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++ + if (isPairOK(collision, 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-- + if (isPairOK(collision, 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)); + + 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(); + } + + void processAnalysis(FilteredMyCollisions const& collisions, MyTracks const& refTracks, Types const&... args) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto electrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); + } + run2PC(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons, refTracks); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto muons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); + } + run2PC(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons, refTracks); + } + map_weight.clear(); + ndf++; + } + PROCESS_SWITCH(DileptonHadronMPC, processAnalysis, "run dilepton analysis", true); + + using FilteredMyCollisionsWithSWT = soa::Filtered; + void processTriggerAnalysis(FilteredMyCollisionsWithSWT const& collisions, MyTracks const& refTracks, Types const&... args) + { + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + auto electrons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons); + } + run2PC(collisions, positive_electrons, negative_electrons, o2::aod::emprimaryelectron::emeventId, fDielectronCut, electrons, refTracks); + } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { + auto muons = std::get<0>(std::tie(args...)); + if (cfgApplyWeightTTCA) { + fillPairWeightMap(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons); + } + run2PC(collisions, positive_muons, negative_muons, o2::aod::emprimarymuon::emeventId, fDimuonCut, muons, refTracks); + } + map_weight.clear(); + ndf++; + } + PROCESS_SWITCH(DileptonHadronMPC, processTriggerAnalysis, "run dilepton analysis on triggered data", false); + + void processDummy(MyCollisions const&) {} + PROCESS_SWITCH(DileptonHadronMPC, processDummy, "Dummy function", false); +}; + +#endif // PWGEM_DILEPTON_CORE_DILEPTONHADRONMPC_H_ diff --git a/PWGEM/Dilepton/Core/DileptonMC.h b/PWGEM/Dilepton/Core/DileptonMC.h index 769c6b72ec3..46e7ecbe9be 100644 --- a/PWGEM/Dilepton/Core/DileptonMC.h +++ b/PWGEM/Dilepton/Core/DileptonMC.h @@ -17,40 +17,40 @@ #ifndef PWGEM_DILEPTON_CORE_DILEPTONMC_H_ #define PWGEM_DILEPTON_CORE_DILEPTONMC_H_ -#include -#include -#include -#include +#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/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.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/GRPLHCIFData.h" #include "DataFormatsParameters/GRPECSObject.h" - -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsParameters/GRPLHCIFData.h" #include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.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 "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" +#include "Math/Vector4D.h" +#include "TString.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" -#include "PWGEM/Dilepton/Core/DimuonCut.h" -#include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -67,12 +67,12 @@ using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyMCElectrons = soa::Join; +using MyMCElectrons = soa::Join; using MyMCElectron = MyMCElectrons::iterator; using FilteredMyMCElectrons = soa::Filtered; using FilteredMyMCElectron = FilteredMyMCElectrons::iterator; -using MyMCMuons = soa::Join; +using MyMCMuons = soa::Join; using MyMCMuon = MyMCMuons::iterator; using FilteredMyMCMuons = soa::Filtered; using FilteredMyMCMuon = FilteredMyMCMuons::iterator; @@ -109,6 +109,10 @@ struct DileptonMC { 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", {VARIABLE_WIDTH, -10.f, +10.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. @@ -126,12 +130,13 @@ struct DileptonMC { 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", 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 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"}; @@ -147,7 +152,7 @@ struct DileptonMC { 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_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + 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; @@ -168,7 +173,8 @@ struct DileptonMC { 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"}; + 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_min_opang{"cfg_min_opang", 0.0, "min opening angle"}; @@ -183,10 +189,12 @@ struct DileptonMC { 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, "max eta 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, "max phi 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"}; @@ -200,16 +208,15 @@ struct DileptonMC { 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_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; 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]"}; 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_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"}; @@ -220,15 +227,17 @@ struct DileptonMC { 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 cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; - Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; - Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; - Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; - Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; - Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; + // Configurable cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; + // Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; + // Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; + // Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; + // Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; + // Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; 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)"}; @@ -273,6 +282,12 @@ struct DileptonMC { 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; @@ -332,6 +347,11 @@ struct DileptonMC { const AxisSpec axis_pt_meson{ConfPtllBins, "p_{T} (GeV/c)"}; // for omega, phi meson pT spectra const AxisSpec axis_y_meson{ConfYllBins, "y"}; // rapidity of meson + 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 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_cs{cfg_nbin_cos_theta_cs, 0.f, 1.f, "|cos(#theta_{CS})|"}; // for kPolarization, kUPC @@ -419,6 +439,12 @@ struct DileptonMC { fRegistry.add("Pair/sm/Photon/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/PromptPi0/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/NonPromptPi0/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/PromptPi0/hDeltaPtvsDCA", "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add("Pair/sm/NonPromptPi0/hDeltaPtvsDCA", "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add("Pair/sm/PromptJPsi/hDeltaPtvsDCA", "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add("Pair/sm/NonPromptJPsi/hDeltaPtvsDCA", "#Delta p_{T,1}^{gen-rec} + #Delta p_{T,2}^{gen-rec} vs. DCA_{ee}", kTH2F, {axis_dca_narrow, axis_dpt}, true); + fRegistry.add("Pair/sm/PromptPi0/hDCAz1vsDCAz2", "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); + fRegistry.add("Pair/sm/PromptJPsi/hDCAz1vsDCAz2", "DCA_{z,1} vs DCA_{z,2}", kTH2F, {axis_dca_track1, axis_dca_track2}, true); } fRegistry.add("Pair/ccbar/c2l_c2l/hadron_hadron/hs", "hs pair", kTHnSparseD, {axis_mass, axis_pt, axis_y, axis_dphi_ee, axis_deta_ee, axis_cos_theta_cs, axis_phi_cs, axis_aco, axis_asym_pt, axis_dphi_e_ee, axis_dca}, true); @@ -559,7 +585,7 @@ struct DileptonMC { 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"; + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kG"; } else { grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); if (!grpmag) { @@ -568,7 +594,7 @@ struct DileptonMC { 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"; + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kG"; } mRunNumber = collision.runNumber(); @@ -603,6 +629,7 @@ struct DileptonMC { 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); @@ -626,14 +653,14 @@ struct DileptonMC { 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, dielectroncuts.cfg_min_deta, dielectroncuts.cfg_min_dphi); + fDielectronCut.SetMindEtadPhi(dielectroncuts.cfg_apply_detadphi, dielectroncuts.cfg_apply_detadphiposition, 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_max_eta_track, +dielectroncuts.cfg_max_eta_track); - fDielectronCut.SetTrackPhiRange(-dielectroncuts.cfg_max_phi_track, +dielectroncuts.cfg_max_phi_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); @@ -641,38 +668,39 @@ struct DileptonMC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + 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.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); - fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); - fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); - fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); - fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); + // fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); + // fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); + // fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); + // fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + 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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; @@ -715,6 +743,8 @@ struct DileptonMC { 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 @@ -800,7 +830,7 @@ struct DileptonMC { return false; } } - if (!cut.IsSelectedPair(t1, t2, d_bz)) { + if (!cut.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { return false; } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { @@ -814,6 +844,14 @@ struct DileptonMC { 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; @@ -963,16 +1001,21 @@ struct DileptonMC { 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 fRegistry.fill(HIST("Pair/sm/PromptPi0/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/sm/PromptPi0/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); fRegistry.fill(HIST("Pair/sm/PromptPi0/hMvsPhiV"), phiv, v12.M()); + fRegistry.fill(HIST("Pair/sm/PromptPi0/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); } } else { // non-prompt pi0 fRegistry.fill(HIST("Pair/sm/NonPromptPi0/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/sm/NonPromptPi0/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); fRegistry.fill(HIST("Pair/sm/NonPromptPi0/hMvsPhiV"), phiv, v12.M()); } } @@ -1001,8 +1044,15 @@ struct DileptonMC { case 443: { if (IsFromBeauty(mcmother, mcparticles) > 0) { fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/sm/NonPromptJPsi/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + } } else { fRegistry.fill(HIST("Pair/sm/PromptJPsi/hs"), v12.M(), v12.Pt(), v12.Rapidity(), dphi, deta, std::fabs(cos_thetaCS), std::fabs(phiCS), aco, asym, std::fabs(dphi_e_ee), pair_dca, weight); + if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { + fRegistry.fill(HIST("Pair/sm/PromptJPsi/hDeltaPtvsDCA"), pair_dca, deltaPt1 + deltaPt2); + fRegistry.fill(HIST("Pair/sm/PromptJPsi/hDCAz1vsDCAz2"), dcaZinSigma(t1), dcaZinSigma(t2)); + } } break; } @@ -1183,8 +1233,7 @@ struct DileptonMC { SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; - Filter pidFilter_electron = dielectroncuts.cfg_min_TPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < dielectroncuts.cfg_max_TPCNsigmaEl; + 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) && @@ -1201,7 +1250,7 @@ struct DileptonMC { o2::aod::emprimaryelectron::pfb >= static_cast(0)); 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 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); @@ -1848,7 +1897,7 @@ struct DileptonMC { } if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDielectron) { - if (!cut.template IsSelectedPair(t1, t2, d_bz)) { + if (!cut.template IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { return false; } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { diff --git a/PWGEM/Dilepton/Core/DimuonCut.cxx b/PWGEM/Dilepton/Core/DimuonCut.cxx index ee18a8e4232..ef5e44123aa 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.cxx +++ b/PWGEM/Dilepton/Core/DimuonCut.cxx @@ -13,9 +13,12 @@ // Class for dimuon Cut // -#include "Framework/Logger.h" #include "PWGEM/Dilepton/Core/DimuonCut.h" +#include "Framework/Logger.h" + +#include + ClassImp(DimuonCut); void DimuonCut::SetMassRange(float min, float max) @@ -119,3 +122,22 @@ void DimuonCut::SetMaxPDCARabsDep(std::function RabsDepCut) mMaxPDCARabsDep = RabsDepCut; LOG(info) << "Dimuon Cut, set max pDCA as a function of Rabs: " << mMaxPDCARabsDep(10.0); } +void DimuonCut::SetMFTHitMap(bool flag, std::vector hitMap) +{ + mApplyMFTHitMap = flag; + mRequiredMFTDisks = hitMap; + if (mApplyMFTHitMap) { + for (const auto& iDisk : mRequiredMFTDisks) { + LOG(info) << "Dimuon Cut, require MFT hit on Disk: " << iDisk; + } + } +} +void DimuonCut::SetMaxdPtdEtadPhiwrtMCHMID(float reldPtMax, float dEtaMax, float dPhiMax) +{ + mMaxReldPtwrtMCHMID = reldPtMax; + mMaxdEtawrtMCHMID = dEtaMax; + mMaxdPhiwrtMCHMID = dPhiMax; + LOG(info) << "Dimuon Cut, set max rel. dpt between MFT-MCH-MID and associated MCH-MID: " << mMaxReldPtwrtMCHMID; + LOG(info) << "Dimuon Cut, set max deta between MFT-MCH-MID and associated MCH-MID: " << mMaxdEtawrtMCHMID; + LOG(info) << "Dimuon Cut, set max dphi between MFT-MCH-MID and associated MCH-MID: " << mMaxdPhiwrtMCHMID; +} diff --git a/PWGEM/Dilepton/Core/DimuonCut.h b/PWGEM/Dilepton/Core/DimuonCut.h index 4bb854c6b73..2895c95f311 100644 --- a/PWGEM/Dilepton/Core/DimuonCut.h +++ b/PWGEM/Dilepton/Core/DimuonCut.h @@ -16,19 +16,21 @@ #ifndef PWGEM_DILEPTON_CORE_DIMUONCUT_H_ #define PWGEM_DILEPTON_CORE_DIMUONCUT_H_ +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" +#include "MathUtils/Utils.h" + +#include "Math/Vector4D.h" +#include "TNamed.h" + #include #include -#include -#include #include -#include "TNamed.h" -#include "Math/Vector4D.h" - -#include "MathUtils/Utils.h" -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" -#include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include +#include using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; @@ -59,6 +61,8 @@ class DimuonCut : public TNamed kMatchingChi2MCHMID, kRabs, kPDCA, + kMFTHitMap, + kDPtDEtaDPhiwrtMCHMID, kNCuts }; @@ -154,6 +158,12 @@ class DimuonCut : public TNamed if (!IsSelectedTrack(track, DimuonCuts::kRabs)) { return false; } + if (mApplyMFTHitMap && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kMFTHitMap)) { + return false; + } + if (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && !IsSelectedTrack(track, DimuonCuts::kDPtDEtaDPhiwrtMCHMID)) { + return false; + } return true; } @@ -184,7 +194,7 @@ class DimuonCut : public TNamed return track.nClusters() >= mMinNClustersMCHMID; case DimuonCuts::kChi2: - return track.chi2() < mMaxChi2; + return (track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) ? track.chi2() / (2.f * (track.nClusters() + track.nClustersMFT()) - 5.f) : track.chi2()) < mMaxChi2; case DimuonCuts::kMatchingChi2MCHMFT: return track.chi2MatchMCHMFT() < mMaxMatchingChi2MCHMFT; @@ -198,6 +208,19 @@ class DimuonCut : public TNamed case DimuonCuts::kRabs: return mMinRabs < track.rAtAbsorberEnd() && track.rAtAbsorberEnd() < mMaxRabs; + 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)}; + for (const auto& iDisk : mRequiredMFTDisks) { + if (!mftHitMap[iDisk]) { + return false; + } + } + return true; + } + + case DimuonCuts::kDPtDEtaDPhiwrtMCHMID: + return std::fabs(track.ptMatchedMCHMID() - track.pt()) / track.pt() < mMaxReldPtwrtMCHMID && std::sqrt(std::pow((track.etaMatchedMCHMID() - track.eta()) / mMaxdEtawrtMCHMID, 2) + std::pow((track.phiMatchedMCHMID() - track.phi()) / mMaxdPhiwrtMCHMID, 2)) < 1.f; + default: return false; } @@ -222,6 +245,8 @@ class DimuonCut : public TNamed void SetDCAxy(float min, float max); // in cm void SetRabs(float min, float max); // in cm 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 private: // pair cuts @@ -249,6 +274,9 @@ class DimuonCut : public TNamed float mMinRabs{17.6}, mMaxRabs{89.5}; float mMinDcaXY{0.0f}, mMaxDcaXY{1e10f}; + float mMaxReldPtwrtMCHMID{1e10f}, mMaxdEtawrtMCHMID{1e10f}, mMaxdPhiwrtMCHMID{1e10f}; + bool mApplyMFTHitMap{false}; + std::vector mRequiredMFTDisks{}; ClassDef(DimuonCut, 1); }; diff --git a/PWGEM/Dilepton/Core/EMEventCut.cxx b/PWGEM/Dilepton/Core/EMEventCut.cxx index a8f085f2646..58e3c5be4e8 100644 --- a/PWGEM/Dilepton/Core/EMEventCut.cxx +++ b/PWGEM/Dilepton/Core/EMEventCut.cxx @@ -13,9 +13,10 @@ // Class for em event selection // -#include "Framework/Logger.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "Framework/Logger.h" + ClassImp(EMEventCut); void EMEventCut::SetRequireSel8(bool flag) @@ -61,6 +62,12 @@ void EMEventCut::SetRequireVertexITSTPC(bool flag) LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC matched track: " << mRequireVertexITSTPC; } +void EMEventCut::SetRequireVertexTOFmatched(bool flag) +{ + mRequireVertexTOFmatched = flag; + LOG(info) << "EM Event Cut, require vertex reconstructed by ITS-TPC-TOF matched track: " << mRequireVertexTOFmatched; +} + void EMEventCut::SetRequireGoodZvtxFT0vsPV(bool flag) { mRequireGoodZvtxFT0vsPV = flag; diff --git a/PWGEM/Dilepton/Core/EMEventCut.h b/PWGEM/Dilepton/Core/EMEventCut.h index 7434b6e3f72..8dc1b7ef961 100644 --- a/PWGEM/Dilepton/Core/EMEventCut.h +++ b/PWGEM/Dilepton/Core/EMEventCut.h @@ -16,10 +16,11 @@ #ifndef PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ #define PWGEM_DILEPTON_CORE_EMEVENTCUT_H_ -#include "TNamed.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" +#include "TNamed.h" + using namespace std; class EMEventCut : public TNamed @@ -37,6 +38,7 @@ class EMEventCut : public TNamed kNoITSROFB, // no ITS read out frame border kNoSameBunchPileup, kIsVertexITSTPC, + kIsVertexTOFmatched, kIsGoodZvtxFT0vsPV, kNoCollInTimeRangeStandard, kNoCollInTimeRangeStrict, @@ -73,6 +75,9 @@ class EMEventCut : public TNamed if (mRequireVertexITSTPC && !IsSelected(collision, EMEventCuts::kIsVertexITSTPC)) { return false; } + if (mRequireVertexTOFmatched && !IsSelected(collision, EMEventCuts::kIsVertexTOFmatched)) { + return false; + } if (mRequireGoodZvtxFT0vsPV && !IsSelected(collision, EMEventCuts::kIsGoodZvtxFT0vsPV)) { return false; } @@ -128,6 +133,9 @@ class EMEventCut : public TNamed case EMEventCuts::kIsVertexITSTPC: return collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC); + case EMEventCuts::kIsVertexTOFmatched: + return collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched); + case EMEventCuts::kIsGoodZvtxFT0vsPV: return collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV); @@ -168,6 +176,7 @@ class EMEventCut : public TNamed 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); @@ -186,6 +195,7 @@ class EMEventCut : public TNamed bool mRequireNoITSROFB{false}; bool mRequireNoSameBunchPileup{false}; bool mRequireVertexITSTPC{false}; + bool mRequireVertexTOFmatched{false}; bool mRequireGoodZvtxFT0vsPV{false}; bool mRequireNoCollInTimeRangeStandard{false}; bool mRequireNoCollInTimeRangeStrict{false}; diff --git a/PWGEM/Dilepton/Core/EMTrackCut.cxx b/PWGEM/Dilepton/Core/EMTrackCut.cxx new file mode 100644 index 00000000000..2ea7934a30b --- /dev/null +++ b/PWGEM/Dilepton/Core/EMTrackCut.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. + +// +// Class for track Cut +// + +#include "PWGEM/Dilepton/Core/EMTrackCut.h" + +#include "Framework/Logger.h" + +#include +#include + +ClassImp(EMTrackCut); + +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. + +void EMTrackCut::SetTrackPtRange(float minPt, float maxPt) +{ + mMinTrackPt = minPt; + mMaxTrackPt = maxPt; + LOG(info) << "EMTrack Cut, set track pt range: " << mMinTrackPt << " - " << mMaxTrackPt; +} +void EMTrackCut::SetTrackEtaRange(float minEta, float maxEta) +{ + mMinTrackEta = minEta; + mMaxTrackEta = maxEta; + LOG(info) << "EMTrack Cut, set track eta range: " << mMinTrackEta << " - " << mMaxTrackEta; +} +void EMTrackCut::SetTrackPhiRange(float minPhi, float maxPhi) +{ + mMinTrackPhi = minPhi; + 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) +{ + mTrackBit = bit; + LOG(info) << "EMTrack Cut, require track bits: " << mTrackBit; +} diff --git a/PWGEM/Dilepton/Core/EMTrackCut.h b/PWGEM/Dilepton/Core/EMTrackCut.h new file mode 100644 index 00000000000..d70a009aaac --- /dev/null +++ b/PWGEM/Dilepton/Core/EMTrackCut.h @@ -0,0 +1,234 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// +// Class for track selection +// + +#ifndef PWGEM_DILEPTON_CORE_EMTRACKCUT_H_ +#define PWGEM_DILEPTON_CORE_EMTRACKCUT_H_ + +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" + +#include "Math/Vector4D.h" +#include "TNamed.h" + +#include +#include +#include +#include +#include + +using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; + +class EMTrackCut : public TNamed +{ + public: + EMTrackCut() = default; + EMTrackCut(const char* name, const char* title) : TNamed(name, title) {} + ~EMTrackCut() {} + + enum class EMTrackCuts : int { + // track cut + kTrackPtRange, + kTrackEtaRange, + kTrackPhiRange, + // kDCAxy, + // kDCAz, + // kTPCNCls, + // kTPCCrossedRows, + // kTPCCrossedRowsOverNCls, + // kTPCFracSharedClusters, + // kTPCChi2NDF, + // kITSNCls, + // kITSChi2NDF, + kTrackBit, + kNCuts + }; + + 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; + } + + template + bool IsSelectedTrack(T const& track, const EMTrackCuts& cut) const + { + switch (cut) { + case EMTrackCuts::kTrackPtRange: + return track.pt() > mMinTrackPt && track.pt() < mMaxTrackPt; + + case EMTrackCuts::kTrackEtaRange: + return track.eta() > mMinTrackEta && track.eta() < mMaxTrackEta; + + 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; + 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; + } + } + + // Setters + 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); +}; + +#endif // PWGEM_DILEPTON_CORE_EMTRACKCUT_H_ diff --git a/PWGEM/Dilepton/Core/PWGEMDileptonCoreLinkDef.h b/PWGEM/Dilepton/Core/PWGEMDileptonCoreLinkDef.h index c1af31aa27b..fe78534478e 100644 --- a/PWGEM/Dilepton/Core/PWGEMDileptonCoreLinkDef.h +++ b/PWGEM/Dilepton/Core/PWGEMDileptonCoreLinkDef.h @@ -19,5 +19,6 @@ #pragma link C++ class EMEventCut + ; #pragma link C++ class DielectronCut + ; #pragma link C++ class DimuonCut + ; +#pragma link C++ class EMTrackCut + ; #endif // PWGEM_DILEPTON_CORE_PWGEMDILEPTONCORELINKDEF_H_ diff --git a/PWGEM/Dilepton/Core/PhotonHBT.h b/PWGEM/Dilepton/Core/PhotonHBT.h index cc8251fb0cd..678c3e800f3 100644 --- a/PWGEM/Dilepton/Core/PhotonHBT.h +++ b/PWGEM/Dilepton/Core/PhotonHBT.h @@ -17,40 +17,41 @@ #ifndef PWGEM_DILEPTON_CORE_PHOTONHBT_H_ #define PWGEM_DILEPTON_CORE_PHOTONHBT_H_ +#include "PWGEM/Dilepton/Core/DielectronCut.h" +#include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Tools/ML/MlResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.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 "TString.h" + #include #include #include #include +#include #include -#include #include +#include #include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/GenVector/Boost.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" - -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" namespace o2::aod::pwgem::dilepton::core::photonhbt { @@ -79,7 +80,7 @@ using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; using FilteredMyTracks = soa::Filtered; using FilteredMyTrack = FilteredMyTracks::iterator; @@ -160,7 +161,6 @@ struct PhotonHBT { 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_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_disable_itsonly_track{"cfg_disable_itsonly_track", false, "flag to disable ITSonly tracks"}; @@ -208,18 +208,17 @@ struct PhotonHBT { Configurable cfg_max_dcaz{"cfg_max_dcaz", 0.2, "max dca Z for single track in cm"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_min_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; 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_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]"}; 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_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -3.0, "min. TPC n sigma for pion exclusion"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +3.0, "max. TPC n sigma for pion exclusion"}; Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; @@ -230,15 +229,17 @@ struct PhotonHBT { 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", 0.5, "max. pin for pion rejection in TPC"}; - Configurable cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; - Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; - Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; - Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; - Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; - Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; + // Configurable cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; + // Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; + // Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; + // Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; + // Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; + // Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; 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)"}; @@ -534,7 +535,6 @@ struct PhotonHBT { fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); fV0PhotonCut.SetRequireITSonly(pcmcuts.cfg_require_v0_with_itsonly); fV0PhotonCut.SetRequireTPConly(pcmcuts.cfg_require_v0_with_tpconly); @@ -567,36 +567,37 @@ struct PhotonHBT { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + 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.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.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); - fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); - fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); - fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); - fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); + // fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); + // fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); + // fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); + // fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + 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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; @@ -847,7 +848,7 @@ struct PhotonHBT { continue; } } - if (!cut1.IsSelectedPair(pos1, ele1, d_bz)) { + if (!cut1.IsSelectedPair(pos1, ele1, d_bz, dielectroncuts.cfgRefR)) { continue; } @@ -875,7 +876,7 @@ struct PhotonHBT { continue; } } - if (!cut2.IsSelectedPair(pos2, ele2, d_bz)) { + if (!cut2.IsSelectedPair(pos2, ele2, d_bz, dielectroncuts.cfgRefR)) { continue; } @@ -993,7 +994,7 @@ struct PhotonHBT { continue; } } - if (!cut2.IsSelectedPair(pos2, ele2, d_bz)) { + if (!cut2.IsSelectedPair(pos2, ele2, d_bz, dielectroncuts.cfgRefR)) { continue; } @@ -1361,7 +1362,7 @@ struct PhotonHBT { continue; } } - if (!cut.IsSelectedPair(pos, ele, d_bz)) { + if (!cut.IsSelectedPair(pos, ele, d_bz, dielectroncuts.cfgRefR)) { continue; } passed_pairIds.emplace_back(std::make_pair(pos.globalIndex(), ele.globalIndex())); diff --git a/PWGEM/Dilepton/Core/SingleTrackQC.h b/PWGEM/Dilepton/Core/SingleTrackQC.h index f5f8be20518..ae41d2dd210 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQC.h @@ -17,32 +17,33 @@ #ifndef PWGEM_DILEPTON_CORE_SINGLETRACKQC_H_ #define PWGEM_DILEPTON_CORE_SINGLETRACKQC_H_ -#include -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.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 "Tools/ML/MlResponse.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 +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -57,7 +58,7 @@ using MyCollision = MyCollisions::iterator; using MyCollisionsWithSWT = soa::Join; using MyCollisionWithSWT = MyCollisionsWithSWT::iterator; -using MyElectrons = soa::Join; +using MyElectrons = soa::Join; using MyElectron = MyElectrons::iterator; using FilteredMyElectrons = soa::Filtered; using FilteredMyElectron = FilteredMyElectrons::iterator; @@ -80,10 +81,11 @@ struct SingleTrackQC { // 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"}; 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 ConfDCABins{"ConfDCABins", {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}, "DCA bins for output histograms"}; + ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {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}, "DCA3d bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 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}, "DCAxy bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 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}, "DCAz bins in sigma for output histograms"}; EMEventCut fEMEventCut; struct : ConfigurableGroup { @@ -95,7 +97,8 @@ struct SingleTrackQC { 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 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"}; @@ -111,7 +114,7 @@ struct SingleTrackQC { 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_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + 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; @@ -122,10 +125,12 @@ struct SingleTrackQC { 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, "max eta 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, "max phi 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"}; @@ -139,16 +144,14 @@ struct SingleTrackQC { 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_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; 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_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_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"}; @@ -159,15 +162,17 @@ struct SingleTrackQC { 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 cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; - Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; - Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; - Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; - Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; - Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; + // Configurable cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; + // Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; + // Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; + // Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; + // Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; + // Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; 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)"}; @@ -201,6 +206,11 @@ struct SingleTrackQC { 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::aod::rctsel::RCTFlagsChecker rctChecker; @@ -221,24 +231,20 @@ struct SingleTrackQC { const AxisSpec axis_pt{ConfPtlBins, "p_{T,e} (GeV/c)"}; const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; - std::string dca_axis_title = "DCA_{e}^{3D} (#sigma)"; - if (cfgDCAType == 1) { - dca_axis_title = "DCA_{e}^{XY} (#sigma)"; - } else if (cfgDCAType == 2) { - dca_axis_title = "DCA_{e}^{Z} (#sigma)"; - } - const AxisSpec axis_dca{ConfDCABins, dca_axis_title}; + 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)"}; // track info - fRegistry.add("Track/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca}, true); + 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/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{2000, -5, 5}}, false); - fRegistry.add("Track/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {700, -3.5f, 3.5f}}, 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., 400}}, 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", "number of TPC clusters;TPC N_{cls}", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/positive/hNcrTPC", "number of TPC crossed rows;TPC N_{CR}", kTH1F, {{161, -0.5, 160.5}}, 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_{pv} (GeV/c);(p_{in} - p_{pv})/p_{pv}", 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); @@ -251,37 +257,38 @@ struct SingleTrackQC { 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/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/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/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/hITSNsigmaEl", "ITS n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hITSNsigmaMu", "ITS n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hITSNsigmaPi", "ITS n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hITSNsigmaKa", "ITS n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hITSNsigmaPr", "ITS n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hITSNsigmaEl", "ITS n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hITSNsigmaMu", "ITS n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hITSNsigmaPi", "ITS n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hITSNsigmaKa", "ITS n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hITSNsigmaPr", "ITS n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.addClone("Track/positive/", "Track/negative/"); } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; const AxisSpec axis_eta{50, -6, -1, "#eta_{#mu}"}; const AxisSpec axis_phi{36, 0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; - const AxisSpec axis_dca{ConfDCABins, "DCA_{#mu}^{XY} (#sigma)"}; + const 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/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/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); fRegistry.add("Track/positive/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); fRegistry.add("Track/positive/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, false); @@ -292,7 +299,7 @@ struct SingleTrackQC { 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", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/positive/hChi2", "chi2;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); @@ -358,6 +365,7 @@ struct SingleTrackQC { 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); @@ -377,7 +385,7 @@ struct SingleTrackQC { // 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); + 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); @@ -385,38 +393,39 @@ struct SingleTrackQC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + 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.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); - fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); - fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); - fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); - fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); + // fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); + // fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); + // fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); + // fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + 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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; @@ -452,6 +461,8 @@ struct SingleTrackQC { 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 @@ -462,24 +473,21 @@ struct SingleTrackQC { weight = map_weight[track.globalIndex()]; } - float dca = dca3DinSigma(track); - if (cfgDCAType == 1) { - dca = dcaXYinSigma(track); - } else if (cfgDCAType == 2) { - dca = dcaZinSigma(track); - } + float dca3D = dca3DinSigma(track); + float dcaXY = dcaXYinSigma(track); + float dcaZ = dcaZinSigma(track); if (track.sign() > 0) { - fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca, weight); + fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, weight); fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/positive/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + 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/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/positive/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/positive/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/positive/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/positive/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/positive/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -495,31 +503,31 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITSob"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/positive/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + // fRegistry.fill(HIST("Track/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/positive/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/positive/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/positive/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); fRegistry.fill(HIST("Track/positive/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); - fRegistry.fill(HIST("Track/positive/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); - fRegistry.fill(HIST("Track/positive/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); - fRegistry.fill(HIST("Track/positive/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); - fRegistry.fill(HIST("Track/positive/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); - fRegistry.fill(HIST("Track/positive/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + // fRegistry.fill(HIST("Track/positive/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); + // fRegistry.fill(HIST("Track/positive/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); + // fRegistry.fill(HIST("Track/positive/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); + // fRegistry.fill(HIST("Track/positive/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); + // fRegistry.fill(HIST("Track/positive/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); } else { - fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca, weight); + fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, weight); fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/negative/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + 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/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/negative/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/negative/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/negative/hNclsTPC_Pt"), track.pt(), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/negative/hNcrTPC_Pt"), track.pt(), track.tpcNClsCrossedRows()); fRegistry.fill(HIST("Track/negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/negative/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -535,20 +543,20 @@ struct SingleTrackQC { fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITSob"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/negative/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + // fRegistry.fill(HIST("Track/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/negative/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/negative/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/negative/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); fRegistry.fill(HIST("Track/negative/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); - fRegistry.fill(HIST("Track/negative/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); - fRegistry.fill(HIST("Track/negative/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); - fRegistry.fill(HIST("Track/negative/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); - fRegistry.fill(HIST("Track/negative/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); - fRegistry.fill(HIST("Track/negative/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + // fRegistry.fill(HIST("Track/negative/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); + // fRegistry.fill(HIST("Track/negative/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); + // fRegistry.fill(HIST("Track/negative/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); + // fRegistry.fill(HIST("Track/negative/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); + // fRegistry.fill(HIST("Track/negative/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); } } @@ -560,9 +568,15 @@ struct SingleTrackQC { weight = map_weight[track.globalIndex()]; } float dca_xy = fwdDcaXYinSigma(track); + + float deta = track.etaMatchedMCHMID() - track.eta(); + float dphi = track.phiMatchedMCHMID() - track.phi(); + o2::math_utils::bringToPMPi(dphi); + if (track.sign() > 0) { fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); fRegistry.fill(HIST("Track/positive/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/positive/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/positive/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/positive/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); @@ -573,13 +587,14 @@ struct SingleTrackQC { 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.chi2()); + 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/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); fRegistry.fill(HIST("Track/positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/positive/hMFTClusterMap"), track.mftClusterMap()); } else { fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, weight); fRegistry.fill(HIST("Track/negative/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/negative/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/negative/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/negative/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); @@ -590,7 +605,7 @@ struct SingleTrackQC { 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.chi2()); + 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/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); fRegistry.fill(HIST("Track/negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/negative/hMFTClusterMap"), track.mftClusterMap()); @@ -738,7 +753,7 @@ struct SingleTrackQC { SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = dielectroncuts.cfg_min_pt_track < o2::aod::track::pt && dielectroncuts.cfg_min_eta_track < o2::aod::track::eta && o2::aod::track::eta < dielectroncuts.cfg_max_eta_track && dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter 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); diff --git a/PWGEM/Dilepton/Core/SingleTrackQCMC.h b/PWGEM/Dilepton/Core/SingleTrackQCMC.h index f400b617f1f..6410f8e4134 100644 --- a/PWGEM/Dilepton/Core/SingleTrackQCMC.h +++ b/PWGEM/Dilepton/Core/SingleTrackQCMC.h @@ -17,33 +17,34 @@ #ifndef PWGEM_DILEPTON_CORE_SINGLETRACKQCMC_H_ #define PWGEM_DILEPTON_CORE_SINGLETRACKQCMC_H_ -#include -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Tools/ML/MlResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/DimuonCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.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 "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -59,11 +60,11 @@ using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyMCElectrons = soa::Join; +using MyMCElectrons = soa::Join; using MyMCElectron = MyMCElectrons::iterator; using FilteredMyMCElectrons = soa::Filtered; -using MyMCMuons = soa::Join; +using MyMCMuons = soa::Join; using MyMCMuon = MyMCMuons::iterator; using FilteredMyMCMuons = soa::Filtered; @@ -87,23 +88,25 @@ struct SingleTrackQCMC { // Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", static_cast(1e+9), "max. multNTracksPV"}; Configurable cfgFillQA{"cfgFillQA", false, "flag to fill QA histograms"}; Configurable cfgApplyWeightTTCA{"cfgApplyWeightTTCA", false, "flag to apply weighting by 1/N"}; - Configurable cfgDCAType{"cfgDCAType", 0, "type of DCA for output. 0:3D, 1:XY, 2:Z, else:3D"}; 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 ConfDCABins{"ConfDCABins", {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}, "DCA bins for output histograms"}; + ConfigurableAxis ConfDCA3DBins{"ConfDCA3DBins", {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}, "DCA3d bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAXYBins{"ConfDCAXYBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 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}, "DCAxy bins in sigma for output histograms"}; + ConfigurableAxis ConfDCAZBins{"ConfDCAZBins", {VARIABLE_WIDTH, -10.0, -9.0, -8.0, -7.0, -6.0, -5.0, -4.5, -4.0, -3.5, -3.0, -2.5, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3, -1.2, -1.1, -1.0, -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, 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}, "DCAz bins in sigma for output histograms"}; 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", 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"}; + 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 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"}; @@ -119,7 +122,7 @@ struct SingleTrackQCMC { 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_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + 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; @@ -129,10 +132,12 @@ struct SingleTrackQCMC { 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, "max eta 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, "max phi 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"}; @@ -146,16 +151,14 @@ struct SingleTrackQCMC { 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_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; 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_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_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"}; @@ -166,15 +169,17 @@ struct SingleTrackQCMC { 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 cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; - Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; - Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; - Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; - Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; - Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; - Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; + // Configurable cfg_min_ITSNsigmaKa{"cfg_min_ITSNsigmaKa", -1.0, "min. ITS n sigma for kaon exclusion"}; + // Configurable cfg_max_ITSNsigmaKa{"cfg_max_ITSNsigmaKa", 1e+10, "max. ITS n sigma for kaon exclusion"}; + // Configurable cfg_min_ITSNsigmaPr{"cfg_min_ITSNsigmaPr", -1.0, "min. ITS n sigma for proton exclusion"}; + // Configurable cfg_max_ITSNsigmaPr{"cfg_max_ITSNsigmaPr", 1e+10, "max. ITS n sigma for proton exclusion"}; + // Configurable cfg_min_p_ITSNsigmaKa{"cfg_min_p_ITSNsigmaKa", 0.0, "min p for kaon exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaKa{"cfg_max_p_ITSNsigmaKa", 0.0, "max p for kaon exclusion in ITS"}; + // Configurable cfg_min_p_ITSNsigmaPr{"cfg_min_p_ITSNsigmaPr", 0.0, "min p for proton exclusion in ITS"}; + // Configurable cfg_max_p_ITSNsigmaPr{"cfg_max_p_ITSNsigmaPr", 0.0, "max p for proton exclusion in ITS"}; 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)"}; @@ -207,6 +212,12 @@ struct SingleTrackQCMC { 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; @@ -240,13 +251,9 @@ struct SingleTrackQCMC { const AxisSpec axis_eta{20, -1.0, +1.0, "#eta_{e}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{e} (rad.)"}; const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; - std::string dca_axis_title = "DCA_{e}^{3D} (#sigma)"; - if (cfgDCAType == 1) { - dca_axis_title = "DCA_{e}^{XY} (#sigma)"; - } else if (cfgDCAType == 2) { - dca_axis_title = "DCA_{e}^{Z} (#sigma)"; - } - const AxisSpec axis_dca{ConfDCABins, dca_axis_title}; + 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)"}; // generated info fRegistry.add("Generated/lf/hs", "gen. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_charge_gen}, true); @@ -260,16 +267,19 @@ struct SingleTrackQCMC { fRegistry.addClone("Generated/lf/", "Generated/b2c2l/"); // track info - fRegistry.add("Track/lf/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + fRegistry.add("Track/lf/positive/hs", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); + if (fillGenValuesForRec) { + fRegistry.add("Track/lf/positive/hsGenRec", "rec. single electron", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca3D, axis_dcaXY, axis_dcaZ, axis_charge_gen}, true); + } if (cfgFillQA) { fRegistry.add("Track/lf/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/lf/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {700, -3.5f, 3.5f}}, false); + fRegistry.add("Track/lf/positive/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.f, 1.f}}, false); fRegistry.add("Track/lf/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/lf/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/lf/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/lf/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/lf/positive/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/lf/positive/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/lf/positive/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/lf/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/lf/positive/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/lf/positive/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/lf/positive/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); @@ -297,31 +307,31 @@ struct SingleTrackQCMC { 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/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/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/PID/positive/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/PID/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/PID/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.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/hITSNsigmaEl", "ITS n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/PID/positive/hITSNsigmaMu", "ITS n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/PID/positive/hITSNsigmaPi", "ITS n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/PID/positive/hITSNsigmaKa", "ITS n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/PID/positive/hITSNsigmaPr", "ITS n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hITSNsigmaEl", "ITS n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hITSNsigmaMu", "ITS n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hITSNsigmaPi", "ITS n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hITSNsigmaKa", "ITS n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/PID/positive/hITSNsigmaPr", "ITS n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.addClone("Track/PID/positive/", "Track/PID/negative/"); } } else if constexpr (pairtype == o2::aod::pwgem::dilepton::utils::pairutil::DileptonPairType::kDimuon) { const AxisSpec axis_pt{ConfPtlBins, "p_{T,#mu} (GeV/c)"}; const AxisSpec axis_eta{50, -6, -1, "#eta_{#mu}"}; const AxisSpec axis_phi{36, 0.0, 2 * M_PI, "#varphi_{#mu} (rad.)"}; - const AxisSpec axis_dca{ConfDCABins, "DCA_{#mu}^{XY} (#sigma)"}; + const AxisSpec axis_dca{ConfDCAXYBins, "DCA_{#mu}^{XY} (#sigma)"}; const AxisSpec axis_charge_gen{3, -1.5, +1.5, "true charge"}; // generated info @@ -337,8 +347,12 @@ struct SingleTrackQCMC { // track info fRegistry.add("Track/lf/positive/hs", "rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + if (fillGenValuesForRec) { + fRegistry.add("Track/lf/positive/hsGenRec", "gen. info of rec. single muon", kTHnSparseD, {axis_pt, axis_eta, axis_phi, axis_dca, axis_charge_gen}, true); + } if (cfgFillQA) { fRegistry.add("Track/lf/positive/hEtaPhi_MatchMCHMID", "#eta vs. #varphi of matched MCHMID", kTH2F, {{180, 0, 2.f * M_PI}, {100, -6, -1}}, false); + fRegistry.add("Track/lf/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/lf/positive/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); fRegistry.add("Track/lf/positive/hTrackType", "track type", kTH1F, {{6, -0.5f, 5.5}}, false); fRegistry.add("Track/lf/positive/hDCAxy", "DCA x vs. y;DCA_{x} (cm);DCA_{y} (cm)", kTH2F, {{200, -0.5f, 0.5f}, {200, -0.5f, 0.5f}}, false); @@ -349,7 +363,7 @@ struct SingleTrackQCMC { fRegistry.add("Track/lf/positive/hNclsMCH", "number of MCH clusters", kTH1F, {{21, -0.5, 20.5}}, false); fRegistry.add("Track/lf/positive/hNclsMFT", "number of MFT clusters", kTH1F, {{11, -0.5, 10.5}}, false); fRegistry.add("Track/lf/positive/hPDCA", "pDCA;R at absorber (cm);p #times DCA (GeV/c #upoint cm)", kTH2F, {{100, 0, 100}, {100, 0.0f, 1000}}, false); - fRegistry.add("Track/lf/positive/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, false); + fRegistry.add("Track/lf/positive/hChi2", "chi2;chi2/ndf", kTH1F, {{100, 0.0f, 10}}, false); fRegistry.add("Track/lf/positive/hChi2MatchMCHMID", "chi2 match MCH-MID;chi2", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("Track/lf/positive/hChi2MatchMCHMFT", "chi2 match MCH-MFT;chi2", kTH1F, {{100, 0.0f, 100}}, false); fRegistry.add("Track/lf/positive/hMFTClusterMap", "MFT cluster map", kTH1F, {{1024, -0.5, 1023.5}}, false); @@ -370,12 +384,16 @@ struct SingleTrackQCMC { } } + bool fillGenValuesForRec = false; int pdg_lepton = 0; void init(InitContext&) { if (doprocessQCMC && doprocessQCMC_Smeared) { LOGF(fatal, "Cannot enable processQCMC and processQCMC_Smeared at the same time. Please choose one."); } + if (doprocessQCMC) { + fillGenValuesForRec = true; + } ccdb->setURL(ccdburl); ccdb->setCaching(true); @@ -417,6 +435,7 @@ struct SingleTrackQCMC { 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); @@ -436,7 +455,7 @@ struct SingleTrackQCMC { // 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); + 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); @@ -444,38 +463,39 @@ struct SingleTrackQCMC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + 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.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); - fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); - fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); - fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); - fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); + // fDielectronCut.SetITSNsigmaKaRange(dielectroncuts.cfg_min_ITSNsigmaKa, dielectroncuts.cfg_max_ITSNsigmaKa); + // fDielectronCut.SetITSNsigmaPrRange(dielectroncuts.cfg_min_ITSNsigmaPr, dielectroncuts.cfg_max_ITSNsigmaPr); + // fDielectronCut.SetPRangeForITSNsigmaKa(dielectroncuts.cfg_min_p_ITSNsigmaKa, dielectroncuts.cfg_max_p_ITSNsigmaKa); + // fDielectronCut.SetPRangeForITSNsigmaPr(dielectroncuts.cfg_min_p_ITSNsigmaPr, dielectroncuts.cfg_max_p_ITSNsigmaPr); if (dielectroncuts.cfg_pid_scheme == static_cast(DielectronCut::PIDSchemes::kPIDML)) { // please call this at the end of DefineDileptonCut static constexpr int nClassesMl = 2; - const std::vector cutDirMl = {o2::cuts_ml::CutSmaller, o2::cuts_ml::CutNot}; - const std::vector labelsClasses = {"Signal", "Background"}; + 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] = dielectroncuts.cutsMl.value[i]; - cutsMlArr[i][1] = 0.; + cutsMlArr[i][0] = 0.; + cutsMlArr[i][1] = dielectroncuts.cutsMl.value[i]; } o2::framework::LabeledArray cutsMl = {cutsMlArr[0], nBinsMl, nClassesMl, labelsBins, labelsClasses}; @@ -511,6 +531,8 @@ struct SingleTrackQCMC { 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 @@ -559,12 +581,9 @@ struct SingleTrackQCMC { void fillElectronInfo(TTrack const& track) { auto mctrack = track.template emmcparticle_as(); - float dca = dca3DinSigma(track); - if (cfgDCAType == 1) { - dca = dcaXYinSigma(track); - } else if (cfgDCAType == 2) { - dca = dcaZinSigma(track); - } + float dca3D = dca3DinSigma(track); + float dcaXY = dcaXYinSigma(track); + float dcaZ = dcaZinSigma(track); float weight = 1.f; if (cfgApplyWeightTTCA) { @@ -573,17 +592,20 @@ struct SingleTrackQCMC { // LOGF(info, "map_weight[%d] = %f", track.globalIndex(), weight); if (track.sign() > 0) { - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca, -mctrack.pdgCode() / pdg_lepton, weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, -mctrack.pdgCode() / pdg_lepton, weight); + if (fillGenValuesForRec) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hsGenRec"), mctrack.pt(), mctrack.eta(), mctrack.phi(), dca3D, dcaXY, dcaZ, -mctrack.pdgCode() / pdg_lepton, weight); + } if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + 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/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/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()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -602,33 +624,36 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/PID/positive/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/PID/positive/hMeanClusterSizeITSob"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + // fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/PID/positive/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); - fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); - fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); - fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); - fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); - fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); + // fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + // fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + // fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + // fRegistry.fill(HIST("Track/PID/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + // fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); + // fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); + // fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); + // fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); + // fRegistry.fill(HIST("Track/PID/positive/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); } } else { - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca, -mctrack.pdgCode() / pdg_lepton, weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca3D, dcaXY, dcaZ, -mctrack.pdgCode() / pdg_lepton, weight); + if (fillGenValuesForRec) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hsGenRec"), mctrack.pt(), mctrack.eta(), mctrack.phi(), dca3D, dcaXY, dcaZ, -mctrack.pdgCode() / pdg_lepton, weight); + } if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + 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/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/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()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); @@ -647,20 +672,20 @@ struct SingleTrackQCMC { fRegistry.fill(HIST("Track/PID/negative/hMeanClusterSizeITSib"), track.p(), track.meanClusterSizeITSib() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/PID/negative/hMeanClusterSizeITSob"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + // fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/PID/negative/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); - fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); - fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); - fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); - fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); - fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); + // fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + // fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + // fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + // fRegistry.fill(HIST("Track/PID/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + // fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); + // fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); + // fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); + // fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); + // fRegistry.fill(HIST("Track/PID/negative/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); } } } @@ -670,6 +695,9 @@ struct SingleTrackQCMC { { auto mctrack = track.template emmcparticle_as(); float dca_xy = fwdDcaXYinSigma(track); + float deta = track.etaMatchedMCHMID() - track.eta(); + float dphi = track.phiMatchedMCHMID() - track.phi(); + o2::math_utils::bringToPMPi(dphi); float weight = 1.f; if (cfgApplyWeightTTCA) { @@ -679,8 +707,12 @@ struct SingleTrackQCMC { if (track.sign() > 0) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hs"), track.pt(), track.eta(), track.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); + if (fillGenValuesForRec) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hsGenRec"), mctrack.pt(), mctrack.eta(), mctrack.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); + } if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); @@ -691,7 +723,7 @@ struct SingleTrackQCMC { 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.chi2()); + 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/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("positive/hMFTClusterMap"), track.mftClusterMap()); @@ -701,8 +733,12 @@ struct SingleTrackQCMC { } } else { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hs"), track.pt(), track.eta(), track.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); + if (fillGenValuesForRec) { + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hsGenRec"), mctrack.pt(), mctrack.eta(), mctrack.phi(), dca_xy, -mctrack.pdgCode() / pdg_lepton, weight); + } if (cfgFillQA) { fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hEtaPhi_MatchMCHMID"), track.phiMatchedMCHMID(), track.etaMatchedMCHMID(), weight); + fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hdEtadPhi"), dphi, deta, weight); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hQoverPt"), track.sign() / track.pt()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hTrackType"), track.trackType()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hDCAxy"), track.fwdDcaX(), track.fwdDcaY()); @@ -713,7 +749,7 @@ struct SingleTrackQCMC { 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.chi2()); + 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/hChi2MatchMCHMID"), track.chi2MatchMCHMID()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hChi2MatchMCHMFT"), track.chi2MatchMCHMFT()); fRegistry.fill(HIST("Track/") + HIST(lepton_source_types[lepton_source_id]) + HIST("negative/hMFTClusterMap"), track.mftClusterMap()); @@ -785,6 +821,9 @@ struct SingleTrackQCMC { if (!o2::aod::pwgem::dilepton::utils::emtrackutil::isBestMatch(track, cut, tracks)) { continue; } + if (dimuoncuts.rejectWrongMatch && track.trackType() == static_cast(o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) && track.emmcparticleId() != track.emmftmcparticleId()) { + continue; + } } auto mcmother = mcparticles.iteratorAt(mctrack.mothersIds()[0]); @@ -818,7 +857,9 @@ struct SingleTrackQCMC { fillTrackInfo<7, TMCParticles>(track); } } else { - fillTrackInfo<2, TMCParticles>(track); + if (pdg_mother == 22) { // photon conversion + fillTrackInfo<2, TMCParticles>(track); + } } } // end of track loop @@ -1021,7 +1062,7 @@ struct SingleTrackQCMC { SliceCache cache; Preslice perCollision_electron = aod::emprimaryelectron::emeventId; - Filter trackFilter_electron = dielectroncuts.cfg_min_phi_track < o2::aod::track::phi && o2::aod::track::phi < dielectroncuts.cfg_max_phi_track && o2::aod::track::tpcChi2NCl < dielectroncuts.cfg_max_chi2tpc && o2::aod::track::itsChi2NCl < dielectroncuts.cfg_max_chi2its && nabs(o2::aod::track::dcaXY) < dielectroncuts.cfg_max_dcaxy && nabs(o2::aod::track::dcaZ) < dielectroncuts.cfg_max_dcaz; + Filter 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); diff --git a/PWGEM/Dilepton/DataModel/dileptonTables.h b/PWGEM/Dilepton/DataModel/dileptonTables.h index 244d5ada6cc..f290ac8548b 100644 --- a/PWGEM/Dilepton/DataModel/dileptonTables.h +++ b/PWGEM/Dilepton/DataModel/dileptonTables.h @@ -9,17 +9,19 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include #include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisDataModel.h" + +#include +#include +#include #ifndef PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ #define PWGEM_DILEPTON_DATAMODEL_DILEPTONTABLES_H_ @@ -39,6 +41,7 @@ enum class swtAliases : int { // software trigger aliases for EM kSingleMuLow, kSingleMuHigh, kDiMuon, + kHighFt0cFv0Mult, kNaliases }; @@ -52,6 +55,7 @@ const std::unordered_map aliasLabels = { {"fSingleMuLow", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kSingleMuLow)}, {"fSingleMuHigh", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kSingleMuHigh)}, {"fDiMuon", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kDiMuon)}, + {"fHighFt0cFv0Mult", static_cast(o2::aod::pwgem::dilepton::swt::swtAliases::kHighFt0cFv0Mult)}, }; } // namespace pwgem::dilepton::swt @@ -120,6 +124,8 @@ DECLARE_SOA_COLUMN(SpherocityPtUnWeighted, spherocity_ptunweighted, float); //! 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_DYNAMIC_COLUMN(PosZ, posZ, [](int16_t posZint16) -> float { return static_cast(posZint16) * 0.1f; }); @@ -154,9 +160,17 @@ DECLARE_SOA_TABLE_VERSIONED(EMEvents_002, "AOD", "EMEVENT", 2, //! Main event collision::PosX, collision::PosY, collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emevent::Sel8); -using EMEvents = EMEvents_002; +DECLARE_SOA_TABLE_VERSIONED(EMEvents_003, "AOD", "EMEVENT", 3, //! Main event information table + o2::soa::Index<>, emevent::CollisionId, bc::RunNumber, bc::GlobalBC, evsel::Alias, evsel::Selection, evsel::Rct, timestamp::Timestamp, + collision::PosZ, + collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, emevent::Sel8); + +using EMEvents = EMEvents_003; using EMEvent = EMEvents::iterator; +DECLARE_SOA_TABLE(EMEventsXY, "AOD", "EMEVENTXY", emevent::PosX, emevent::PosY); // joinable to EMEvents, only for treeCreatetorML.cxx +using EMEventXY = EMEventsXY::iterator; + DECLARE_SOA_TABLE(EMEventsCov, "AOD", "EMEVENTCOV", //! joinable to EMEvents collision::CovXX, collision::CovXY, collision::CovXZ, collision::CovYY, collision::CovYZ, collision::CovZZ, collision::Chi2, o2::soa::Marker<1>); using EMEventCov = EMEventsCov::iterator; @@ -375,6 +389,18 @@ DECLARE_SOA_TABLE(EMPrimaryMuonMCLabels, "AOD", "EMPRMMUMCLABEL", //! emprimarymuonmclabel::EMMCParticleId, emprimarymuonmclabel::McMask); using EMPrimaryMuonMCLabel = EMPrimaryMuonMCLabels::iterator; +namespace emmftmclabel +{ +// DECLARE_SOA_INDEX_COLUMN_FULL(EMMCParticle, emmcparticle); +DECLARE_SOA_INDEX_COLUMN_FULL(EMMFTMCParticle, emmftmcparticle, int, EMMCParticles, "_MFT"); +DECLARE_SOA_COLUMN(McMask, mcMask, uint16_t); +} // namespace emmftmclabel + +// NOTE: MC labels. This table has one entry for each reconstructed track (joinable with EMPrimaryMuons table) +DECLARE_SOA_TABLE(EMMFTMCLabels, "AOD", "EMMFTMCLABEL", //! + emmftmclabel::EMMFTMCParticleId, emmftmclabel::McMask); +using EMMFTMCLabel = EMMFTMCLabels::iterator; + namespace emprimaryelectron { DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! @@ -382,20 +408,25 @@ DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! DECLARE_SOA_COLUMN(TrackId, trackId, int); //! DECLARE_SOA_SELF_ARRAY_INDEX_COLUMN(AmbiguousElectrons, ambiguousElectrons); DECLARE_SOA_COLUMN(IsAssociatedToMPC, isAssociatedToMPC, bool); //! is associated to most probable collision +DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); //! is ambiguous DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! DECLARE_SOA_COLUMN(PrefilterBit, pfb, uint8_t); //! DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! -DECLARE_SOA_COLUMN(ITSNSigmaEl, itsNSigmaEl, float); //! -DECLARE_SOA_COLUMN(ITSNSigmaMu, itsNSigmaMu, float); //! -DECLARE_SOA_COLUMN(ITSNSigmaPi, itsNSigmaPi, float); //! -DECLARE_SOA_COLUMN(ITSNSigmaKa, itsNSigmaKa, float); //! -DECLARE_SOA_COLUMN(ITSNSigmaPr, itsNSigmaPr, float); //! +DECLARE_SOA_COLUMN(ProbElBDT, probElBDT, float); //! + +DECLARE_SOA_COLUMN(ITSNSigmaEl, itsNSigmaEl, float); //! +DECLARE_SOA_COLUMN(ITSNSigmaMu, itsNSigmaMu, float); //! +DECLARE_SOA_COLUMN(ITSNSigmaPi, itsNSigmaPi, float); //! +DECLARE_SOA_COLUMN(ITSNSigmaKa, itsNSigmaKa, float); //! +DECLARE_SOA_COLUMN(ITSNSigmaPr, itsNSigmaPr, float); //! + DECLARE_SOA_DYNAMIC_COLUMN(Signed1Pt, signed1Pt, [](float pt, int8_t sign) -> float { return sign * 1. / pt; }); DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(Px, px, [](float pt, float phi) -> float { return pt * std::cos(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, [](float pt, float phi) -> float { return pt * std::sin(phi); }); DECLARE_SOA_DYNAMIC_COLUMN(Pz, pz, [](float pt, float eta) -> float { return pt * std::sinh(eta); }); DECLARE_SOA_DYNAMIC_COLUMN(Theta, theta, [](float tgl) -> float { return M_PI_2 - std::atan(tgl); }); +DECLARE_SOA_DYNAMIC_COLUMN(Tgl, tgl, [](float eta) -> float { return std::tan(M_PI_2 - 2 * std::atan(std::exp(-eta))); }); DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITS, meanClusterSizeITS, [](uint32_t itsClusterSizes) -> float { int total_cluster_size = 0, nl = 0; for (unsigned int layer = 0; layer < 7; layer++) { @@ -502,11 +533,75 @@ DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_002, "AOD", "EMPRIMARYEL", 2, //! emprimaryelectron::MeanClusterSizeITSib, emprimaryelectron::MeanClusterSizeITSob); -using EMPrimaryElectrons = EMPrimaryElectrons_002; +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectrons_003, "AOD", "EMPRIMARYEL", 3, //! + o2::soa::Index<>, emprimaryelectron::CollisionId, + emprimaryelectron::TrackId, emprimaryelectron::Sign, + track::Pt, track::Eta, track::Phi, track::DcaXY, track::DcaZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, + track::TPCChi2NCl, track::TPCInnerParam, + track::TPCSignal, pidtpc::TPCNSigmaEl, /*pidtpc::TPCNSigmaMu,*/ pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtofbeta::Beta, pidtof::TOFNSigmaEl, /*pidtof::TOFNSigmaMu,*/ pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, + track::ITSClusterSizes, + // emprimaryelectron::ITSNSigmaEl, emprimaryelectron::ITSNSigmaMu, emprimaryelectron::ITSNSigmaPi, emprimaryelectron::ITSNSigmaKa, emprimaryelectron::ITSNSigmaPr, + track::ITSChi2NCl, track::TOFChi2, track::DetectorMap, + track::X, track::Alpha, track::Y, track::Z, track::Snp, track::Tgl, emprimaryelectron::IsAssociatedToMPC, + mcpidtpc::DeDxTunedMc, + + // dynamic column + track::TPCNClsFound, + 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, + emprimaryelectron::Signed1Pt, + emprimaryelectron::P, + emprimaryelectron::Px, + emprimaryelectron::Py, + emprimaryelectron::Pz, + emprimaryelectron::Theta, + emprimaryelectron::MeanClusterSizeITS, + emprimaryelectron::MeanClusterSizeITSib, + emprimaryelectron::MeanClusterSizeITSob); + +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::TPCNClsFindable, track::TPCNClsFindableMinusFound, 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, + mcpidtpc::DeDxTunedMc, + + // dynamic column + track::TPCNClsFound, + 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, + + emprimaryelectron::Signed1Pt, + emprimaryelectron::P, + emprimaryelectron::Px, + emprimaryelectron::Py, + emprimaryelectron::Pz, + emprimaryelectron::Tgl, + emprimaryelectron::MeanClusterSizeITS, + emprimaryelectron::MeanClusterSizeITSib, + emprimaryelectron::MeanClusterSizeITSob); + +using EMPrimaryElectrons = EMPrimaryElectrons_004; // iterators using EMPrimaryElectron = EMPrimaryElectrons::iterator; -DECLARE_SOA_TABLE(EMPrimaryElectronsCov, "AOD", "EMPRIMARYELCOV", //! +DECLARE_SOA_TABLE(EMPrimaryElectronsCov_000, "AOD", "EMPRIMARYELCOV", //! aod::track::CYY, aod::track::CZY, aod::track::CZZ, @@ -522,9 +617,35 @@ DECLARE_SOA_TABLE(EMPrimaryElectronsCov, "AOD", "EMPRIMARYELCOV", //! aod::track::C1PtSnp, aod::track::C1PtTgl, 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. + +using EMPrimaryElectronsCov = EMPrimaryElectronsCov_001; // iterators using EMPrimaryElectronCov = EMPrimaryElectronsCov::iterator; +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectronsDeDxMC_000, "AOD", "EMPRMELDEDXMC", 0, mcpidtpc::DeDxTunedMc, o2::soa::Marker<1>); +using EMPrimaryElectronsDeDxMC = EMPrimaryElectronsDeDxMC_000; +// iterators +using EMPrimaryElectronDeDxMC = EMPrimaryElectronsDeDxMC::iterator; + DECLARE_SOA_TABLE(EMPrimaryElectronEMEventIds, "AOD", "PRMELMEVENTID", emprimaryelectron::EMEventId); // To be joined with EMPrimaryElectrons table at analysis level. // iterators using EMPrimaryElectronEMEventId = EMPrimaryElectronEMEventIds::iterator; @@ -641,6 +762,37 @@ DECLARE_SOA_TABLE(EMGlobalMuonSelfIds, "AOD", "EMGLMUSELFID", emprimarymuon::Glo // iterators using EMGlobalMuonSelfId = EMGlobalMuonSelfIds::iterator; +namespace emprimarytrack +{ +DECLARE_SOA_INDEX_COLUMN(EMEvent, emevent); //! +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(TrackId, trackId, int); //! +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! +DECLARE_SOA_COLUMN(TrackBit, trackBit, uint16_t); //! +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float signed1Pt) -> float { return 1.f / std::fabs(signed1Pt); }); +} // namespace emprimarytrack + +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryTracks_000, "AOD", "EMPRIMARYTRACK", 0, //! primary charged track table for 2PC + o2::soa::Index<>, emprimarytrack::CollisionId, emprimarytrack::TrackId, emprimarytrack::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, + track::Signed1Pt, track::Eta, track::Phi, emprimarytrack::TrackBit, + // dynamic column + track::Sign, emprimarytrack::Pt); + +using EMPrimaryTracks = EMPrimaryTracks_001; +// iterators +using EMPrimaryTrack = EMPrimaryTracks::iterator; + +DECLARE_SOA_TABLE(EMPrimaryTrackEMEventIds, "AOD", "PRMTRKEMEVENTID", emprimarytrack::EMEventId); // To be joined with EMPrimaryTracks table at analysis level. +// iterators +using EMPrimaryTrackEMEventId = EMPrimaryTrackEMEventIds::iterator; + +DECLARE_SOA_TABLE(EMPrimaryTrackEMEventIdsTMP, "AOD", "PRMTRKEVIDTMP", track::CollisionId); // To be joined with EMPrimaryTracks in associateDileptonToEMEvent +// iterators +using EMPrimaryTrackEMEventIdTMP = EMPrimaryTrackEMEventIdsTMP::iterator; + // Dummy data for MC namespace emdummydata { diff --git a/PWGEM/Dilepton/DataModel/lmeeMLTables.h b/PWGEM/Dilepton/DataModel/lmeeMLTables.h index 8e0104daf90..f2000b0f4a4 100644 --- a/PWGEM/Dilepton/DataModel/lmeeMLTables.h +++ b/PWGEM/Dilepton/DataModel/lmeeMLTables.h @@ -9,13 +9,15 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisDataModel.h" + +#include #ifndef PWGEM_DILEPTON_DATAMODEL_LMEEMLTABLES_H_ #define PWGEM_DILEPTON_DATAMODEL_LMEEMLTABLES_H_ @@ -23,10 +25,9 @@ namespace o2::aod { -namespace pwgem::dilepton +namespace pwgem::dilepton::ml { -enum class PID_Label : int { - kUnDef = -1, +enum class PID_Label : uint8_t { kElectron = 0, kMuon = 1, kPion = 2, @@ -34,22 +35,24 @@ enum class PID_Label : int { kProton = 4, }; // this can be used for eID. -enum class Track_Type : int { +enum class Track_Type : uint8_t { kPrimary = 0, kSecondary = 1, }; // this can be used for selecting electron from primary or photon conversion. -} // namespace pwgem::dilepton +} // namespace pwgem::dilepton::ml -namespace emprimarytrack +namespace emmltrack { -DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! -DECLARE_SOA_COLUMN(PIDLabel, pidlabel, int); //! -DECLARE_SOA_COLUMN(TrackType, tracktype, int); //! -DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, int); //! -DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, int); //! -DECLARE_SOA_COLUMN(IsForValidation, isForValidation, bool); //! -DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float pt, float eta) -> float { return pt * std::cosh(eta); }); +DECLARE_SOA_COLUMN(CollisionId, collisionId, int); //! +DECLARE_SOA_COLUMN(PIDLabel, pidlabel, uint8_t); //! +DECLARE_SOA_COLUMN(TrackType, tracktype, uint8_t); //! +DECLARE_SOA_COLUMN(TPCNClsFound, tpcNClsFound, uint8_t); //! +DECLARE_SOA_COLUMN(TPCNClsCrossedRows, tpcNClsCrossedRows, uint8_t); //! +DECLARE_SOA_COLUMN(IsForValidation, isForValidation, bool); //! +DECLARE_SOA_COLUMN(Sign, sign, short); //! +DECLARE_SOA_COLUMN(P, p, 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; for (unsigned int layer = 0; layer < 7; layer++) { @@ -80,26 +83,24 @@ DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32 return 0; } }); -} // namespace emprimarytrack +} // namespace emmltrack // reconstructed track information -DECLARE_SOA_TABLE(EMPrimaryTracks, "AOD", "EMPTRACK", //! - o2::soa::Index<>, emprimarytrack::CollisionId, collision::PosZ, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, - track::Pt, track::Eta, track::Phi, track::Tgl, track::Signed1Pt, - track::DcaXY, track::DcaZ, track::CYY, track::CZZ, track::CZY, - track::TPCNClsFindable, emprimarytrack::TPCNClsFound, emprimarytrack::TPCNClsCrossedRows, +DECLARE_SOA_TABLE(EMTracksForMLPID, "AOD", "EMTRACKMLPID", //! + o2::soa::Index<>, collision::NumContrib, evsel::NumTracksInTimeRange, evsel::SumAmpFT0CInTimeRange, + emmltrack::P, track::Tgl, emmltrack::Sign, + track::TPCNClsFindable, emmltrack::TPCNClsFound, emmltrack::TPCNClsCrossedRows, track::TPCChi2NCl, track::TPCInnerParam, - track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, - pidtofbeta::Beta, pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, - track::ITSClusterSizes, track::ITSChi2NCl, track::TOFChi2, track::DetectorMap, emprimarytrack::PIDLabel, emprimarytrack::TrackType, emprimarytrack::IsForValidation, + 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, emmltrack::PIDLabel, // dynamic column - emprimarytrack::P, - emprimarytrack::MeanClusterSizeITS, - emprimarytrack::MeanClusterSizeITSob); + emmltrack::MeanClusterSizeITS, + emmltrack::MeanClusterSizeITSob); // iterators -using EMPrimaryTrack = EMPrimaryTracks::iterator; +using EMTrackForMLPID = EMTracksForMLPID::iterator; } // namespace o2::aod diff --git a/PWGEM/Dilepton/TableProducer/CMakeLists.txt b/PWGEM/Dilepton/TableProducer/CMakeLists.txt index c95928b3eb1..d234ee0d2b4 100644 --- a/PWGEM/Dilepton/TableProducer/CMakeLists.txt +++ b/PWGEM/Dilepton/TableProducer/CMakeLists.txt @@ -22,7 +22,7 @@ o2physics_add_dpl_workflow(tree-creator-electron-ml-dda o2physics_add_dpl_workflow(skimmer-primary-electron SOURCES skimmerPrimaryElectron.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(skimmer-primary-muon @@ -30,8 +30,8 @@ o2physics_add_dpl_workflow(skimmer-primary-muon PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(skimmer-secondary-electron - SOURCES skimmerSecondaryElectron.cxx +o2physics_add_dpl_workflow(skimmer-primary-track + SOURCES skimmerPrimaryTrack.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -50,11 +50,6 @@ o2physics_add_dpl_workflow(associate-mc-info-dilepton PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(filter-dielectron-event - SOURCES filterDielectronEvent.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(event-selection SOURCES eventSelection.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore diff --git a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx index bdca5c93802..52867a7609d 100644 --- a/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/associateMCinfoDilepton.cxx @@ -14,19 +14,21 @@ // This code produces reduced events for photon analyses. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Common/Core/TableHelper.h" -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "Common/Core/TableHelper.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -43,6 +45,7 @@ struct AssociateMCInfoDilepton { using MyCollisionsMC = soa::Join; using TracksMC = soa::Join; using FwdTracksMC = soa::Join; + using MFTTracksMC = soa::Join; Produces mcevents; Produces mceventlabels; @@ -51,6 +54,7 @@ struct AssociateMCInfoDilepton { Produces v0legmclabels; Produces emprimaryelectronmclabels; Produces emprimarymuonmclabels; + Produces emmftmclabels; Produces emdummydata; Configurable n_dummy_loop{"n_dummy_loop", 0, "for loop runs over n times"}; @@ -135,8 +139,8 @@ struct AssociateMCInfoDilepton { Partition mcmuons = nabs(o2::aod::mcparticle::pdgCode) == 13 && min_eta_gen_primary_fwd < o2::aod::mcparticle::eta && o2::aod::mcparticle::eta < max_eta_gen_primary_fwd; Partition mcvectormesons = o2::aod::mcparticle::pdgCode == 223 || o2::aod::mcparticle::pdgCode == 333; - template - void skimmingMC(MyCollisionsMC const& collisions, aod::BCs const&, aod::McCollisions const& mcCollisions, aod::McParticles const& mcTracks, TTracks const& o2tracks, TFwdTracks const& o2fwdtracks, TPCMs const& v0photons, TPCMLegs const& /*v0legs*/, TEMPrimaryElectrons const& emprimaryelectrons, TEMPrimaryMuons const& emprimarymuons) + 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) { // temporary variables used for the indexing of the skimmed MC stack std::map fNewLabels; @@ -358,8 +362,8 @@ struct AssociateMCInfoDilepton { continue; } - auto ele = v0.template negTrack_as(); - auto pos = v0.template posTrack_as(); + 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()); @@ -521,6 +525,54 @@ struct AssociateMCInfoDilepton { } } // end of mother chain loop + // mc label for tracks registered in MFT in global muons + if (o2track.matchMFTTrackId() > -1) { + const auto& o2mfttrack = o2track.template matchMFTTrack_as(); + if (!o2mfttrack.has_mcParticle()) { + emmftmclabels(-1, 0); + break; + } + + const auto& mco2mfttrack = o2mfttrack.template mcParticle_as(); + if (!(fNewLabels.find(mco2mfttrack.globalIndex()) != fNewLabels.end())) { + fNewLabels[mco2mfttrack.globalIndex()] = fCounters[0]; + fNewLabelsReversed[fCounters[0]] = mco2mfttrack.globalIndex(); + // fMCFlags[mco2mfttrack.globalIndex()] = mcflags; + fEventIdx[mco2mfttrack.globalIndex()] = fEventLabels.find(mco2mfttrack.mcCollisionId())->second; + fCounters[0]++; + } + emmftmclabels(fNewLabels.find(mco2mfttrack.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 + } else { + emmftmclabels(-1, 0); + } } // end of em primary muon loop } @@ -612,36 +664,36 @@ struct AssociateMCInfoDilepton { void processMC_Electron(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, aod::EMPrimaryElectrons const& emprimaryelectrons) { const uint8_t sysflag = kElectron; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, nullptr, emprimaryelectrons, nullptr); + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, nullptr, nullptr, emprimaryelectrons, nullptr); } - void processMC_FwdMuon(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, FwdTracksMC const& o2fwdtracks, aod::EMPrimaryMuons const& emprimarymuons) + void processMC_FwdMuon(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, FwdTracksMC const& o2fwdtracks, MFTTracksMC const& o2mfttracks, aod::EMPrimaryMuons const& emprimarymuons) { const uint8_t sysflag = kFwdMuon; - skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, o2fwdtracks, nullptr, nullptr, nullptr, emprimarymuons); + skimmingMC(collisions, bcs, mccollisions, mcTracks, nullptr, o2fwdtracks, o2mfttracks, nullptr, nullptr, nullptr, emprimarymuons); } - void processMC_Electron_FwdMuon(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, FwdTracksMC const& o2fwdtracks, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) + void processMC_Electron_FwdMuon(MyCollisionsMC const& collisions, aod::BCs const& bcs, aod::McCollisions const& mccollisions, aod::McParticles const& mcTracks, TracksMC const& o2tracks, FwdTracksMC const& o2fwdtracks, MFTTracksMC const& o2mfttracks, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& emprimarymuons) { const uint8_t sysflag = kElectron | kFwdMuon; - skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, o2fwdtracks, nullptr, nullptr, emprimaryelectrons, emprimarymuons); + 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, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, aod::EMPrimaryElectrons const& emprimaryelectrons, aod::EMPrimaryMuons const& 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, v0photons, v0legs, emprimaryelectrons, emprimarymuons); + 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, v0photons, v0legs, emprimaryelectrons, nullptr); + 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, v0photons, v0legs, nullptr, nullptr); + skimmingMC(collisions, bcs, mccollisions, mcTracks, o2tracks, nullptr, nullptr, v0photons, v0legs, nullptr, nullptr); } void processGenDummy(MyCollisionsMC const&) diff --git a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx index 253da4de3a6..b8575494195 100644 --- a/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx +++ b/PWGEM/Dilepton/TableProducer/createEMEventDilepton.cxx @@ -14,24 +14,25 @@ // This code produces reduced events for photon analyses. // Please write to: daiki.sekihata@cern.ch -#include +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.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 "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" -#include "Common/Core/TableHelper.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include using namespace o2; +using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; @@ -54,6 +55,7 @@ using MyCollisionsMC_Cent_Qvec = soa::Join; struct CreateEMEventDilepton { Produces embc; Produces event; + Produces eventXY; // Produces eventcov; Produces event_mult; Produces event_cent; @@ -188,9 +190,11 @@ struct CreateEMEventDilepton { registry.fill(HIST("hEventCounter"), 2); event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), bc.timestamp(), - collision.posX(), collision.posY(), collision.posZ(), + collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + eventXY(collision.posX(), collision.posY()); + // 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()); @@ -298,10 +302,13 @@ 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; void init(o2::framework::InitContext&) {} @@ -336,11 +343,18 @@ 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) + { + fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); + } + void processDummy(aod::EMEvents const&) {} - PROCESS_SWITCH(AssociateDileptonToEMEvent, processPCM, "process pcm-event indexing", false); - PROCESS_SWITCH(AssociateDileptonToEMEvent, processElectron, "process dalitzee-event indexing", false); - PROCESS_SWITCH(AssociateDileptonToEMEvent, processFwdMuon, "process forward muon indexing", false); + PROCESS_SWITCH(AssociateDileptonToEMEvent, 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); PROCESS_SWITCH(AssociateDileptonToEMEvent, processDummy, "process dummy", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/Dilepton/TableProducer/eventSelection.cxx b/PWGEM/Dilepton/TableProducer/eventSelection.cxx index 65eb1a93d53..d4d33e83cc5 100644 --- a/PWGEM/Dilepton/TableProducer/eventSelection.cxx +++ b/PWGEM/Dilepton/TableProducer/eventSelection.cxx @@ -43,7 +43,7 @@ struct EMEventSelection { // for RCT Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + 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"}; diff --git a/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx b/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx deleted file mode 100644 index b0332194b55..00000000000 --- a/PWGEM/Dilepton/TableProducer/filterDielectronEvent.cxx +++ /dev/null @@ -1,1719 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \brief write relevant information about primary electrons. -/// \author daiki.sekihata@cern.ch - -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/TableHelper.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" - -using namespace o2; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::constants::physics; - -using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; - -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; -using MyTracksMC = soa::Join; -using MyTrackMC = MyTracksMC::iterator; - -struct filterDielectronEvent { - using MyCollisions = soa::Join; - using MyCollisionsWithSWT = soa::Join; - - SliceCache cache; - Preslice perCol = o2::aod::track::collisionId; - Produces emprimaryelectrons; - Produces emprimaryelectronscov; - Produces filter; - - // Configurables - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - - // Operation and minimisation criteria - Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 80, "min. crossed rows"}; - Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; - Configurable max_pin_for_pion_rejection{"max_pin_for_pion_rejection", 1e+10, "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 min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; - Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; - Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; - Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt{"minpt", 0.15, "min pt for track"}; - Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; - Configurable dca_xy_max{"dca_xy_max", 0.1f, "max DCAxy in cm"}; - Configurable dca_z_max{"dca_z_max", 0.1f, "max DCAz in cm"}; - Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1.5, "max DCA 3D in sigma"}; - Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.5, "min. TPC n sigma for electron inclusion"}; - Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.5, "max. TPC n sigma for electron inclusion"}; - Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", 3.5, "max. TOF n sigma for electron inclusion"}; - Configurable minTPCNsigmaPi{"minTPCNsigmaPi", -1e+10, "min. TPC n sigma for pion exclusion"}; - Configurable maxTPCNsigmaPi{"maxTPCNsigmaPi", 2.0, "max. TPC n sigma for pion exclusion"}; - Configurable minTPCNsigmaKa{"minTPCNsigmaKa", -3.0, "min. TPC n sigma for kaon exclusion"}; - Configurable maxTPCNsigmaKa{"maxTPCNsigmaKa", +3.0, "max. TPC n sigma for kaon exclusion"}; - Configurable minTPCNsigmaPr{"minTPCNsigmaPr", -3.0, "min. TPC n sigma for proton exclusion"}; - Configurable maxTPCNsigmaPr{"maxTPCNsigmaPr", +3.0, "max. TPC n sigma for proton exclusion"}; - Configurable maxMee{"maxMee", 1e+10, "max mee for virtual photon selection"}; - - Configurable apply_phiv{"apply_phiv", true, "flag to apply phiv cut"}; - Configurable slope{"slope", 0.0181, "slope for mee vs. phiv"}; - Configurable intercept{"intercept", -0.0370, "intercept for mee vs. phiv"}; - - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - - int mRunNumber; - float d_bz; - Service ccdb; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - void init(InitContext&) - { - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - if (fillQAHistogram) { - fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/hRelSigma1Pt", "relative p_{T} resolution;p_{T} (GeV/c);#sigma_{1/p_{T}} #times p_{T}", kTH2F, {{1000, 0, 10}, {100, 0, 0.1}}, false); - fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {20, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); - fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFbeta", "TOF beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); - fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/hTPCNclsShared", "TPC Ncls/Nfindable;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); - fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); - fRegistry.add("Pair/before/hMvsPt", "m_{ee} vs. p_{T,ee};m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {{400, 0, 4}, {100, 0, 10}}, false); - fRegistry.add("Pair/before/hMvsPhiV", "mee vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0, 0.1}}, false); - fRegistry.addClone("Pair/before/", "Pair/after/"); - fRegistry.add("Pair/uls/hM", "m_{ee};m_{ee} (GeV/c^{2})", kTH1F, {{100, 0, 0.1}}, false); - fRegistry.add("Pair/lspp/hM", "m_{ee};m_{ee} (GeV/c^{2})", kTH1F, {{100, 0, 0.1}}, false); - fRegistry.add("Pair/lsmm/hM", "m_{ee};m_{ee} (GeV/c^{2})", kTH1F, {{100, 0, 0.1}}, false); - } - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (std::fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - o2::base::Propagator::initFieldFromGRP(&grpmag); - mRunNumber = bc.runNumber(); - return; - } - - auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = bc.runNumber(); - } - - template - bool checkTrack(TCollision const& collision, TTrack const& track) - { - if constexpr (isMC) { - if (!track.has_mcParticle()) { - return false; - } - } - - if (track.tpcChi2NCl() > maxchi2tpc) { - return false; - } - - if (track.itsChi2NCl() > maxchi2its) { - return false; - } - - if (!track.hasITS() || !track.hasTPC()) { - return false; - } - if (track.itsNCls() < min_ncluster_its) { - return false; - } - if (track.itsNClsInnerBarrel() < min_ncluster_itsib) { - 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; - } - - std::array dcaInfo; - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); - // std::array pVec_recalc = {0, 0, 0}; // px, py, pz - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); - // getPxPyPz(track_par_cov_recalc, pVec_recalc); - float dcaXY = dcaInfo[0]; - float dcaZ = dcaInfo[1]; - - if (std::fabs(dcaXY) > dca_xy_max || std::fabs(dcaZ) > dca_z_max) { - return false; - } - - if (track_par_cov_recalc.getPt() < minpt || std::fabs(track_par_cov_recalc.getEta()) > maxeta) { - return false; - } - - float dca_3d = 999.f; - float det = track_par_cov_recalc.getSigmaY2() * track_par_cov_recalc.getSigmaZ2() - track_par_cov_recalc.getSigmaZY() * track_par_cov_recalc.getSigmaZY(); - if (det < 0) { - dca_3d = 999.f; - } else { - float chi2 = (dcaXY * dcaXY * track_par_cov_recalc.getSigmaZ2() + dcaZ * dcaZ * track_par_cov_recalc.getSigmaY2() - 2. * dcaXY * dcaZ * track_par_cov_recalc.getSigmaZY()) / det; - dca_3d = std::sqrt(std::fabs(chi2) / 2.); - } - if (dca_3d > dca_3d_sigma_max) { - return false; - } - - return true; - } - - template - bool isElectron(TTrack const& track) - { - return isElectron_TPChadrej(track) || isElectron_TOFreq(track); - } - - template - bool isElectron_TPChadrej(TTrack const& track) - { - 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(track.tofNSigmaEl()))) { - return false; - } - return true; - } - - template - bool isElectron_TOFreq(TTrack const& track) - { - if (minTPCNsigmaPi < track.tpcNSigmaPi() && track.tpcNSigmaPi() < maxTPCNsigmaPi && track.tpcInnerParam() < max_pin_for_pion_rejection) { - return false; - } - return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && std::fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl; - } - - 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()) { - std::array dcaInfo; - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); - // std::array pVec_recalc = {0, 0, 0}; // px, py, pz - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); - // getPxPyPz(track_par_cov_recalc, pVec_recalc); - float dcaXY = dcaInfo[0]; - float dcaZ = dcaInfo[1]; - - float pt_recalc = track_par_cov_recalc.getPt(); - float eta_recalc = track_par_cov_recalc.getEta(); - float phi_recalc = track_par_cov_recalc.getPhi(); - - bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); - - emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), - pt_recalc, eta_recalc, phi_recalc, dcaXY, dcaZ, - track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), - track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.itsClusterSizes(), 0, 0, 0, 0, 0, - track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), - track_par_cov_recalc.getX(), track_par_cov_recalc.getAlpha(), track_par_cov_recalc.getY(), track_par_cov_recalc.getZ(), track_par_cov_recalc.getSnp(), track_par_cov_recalc.getTgl(), isAssociatedToMPC); - - emprimaryelectronscov( - track_par_cov_recalc.getSigmaY2(), - track_par_cov_recalc.getSigmaZY(), - track_par_cov_recalc.getSigmaZ2(), - track_par_cov_recalc.getSigmaSnpY(), - track_par_cov_recalc.getSigmaSnpZ(), - track_par_cov_recalc.getSigmaSnp2(), - track_par_cov_recalc.getSigmaTglY(), - track_par_cov_recalc.getSigmaTglZ(), - track_par_cov_recalc.getSigmaTglSnp(), - track_par_cov_recalc.getSigmaTgl2(), - track_par_cov_recalc.getSigma1PtY(), - track_par_cov_recalc.getSigma1PtZ(), - track_par_cov_recalc.getSigma1PtSnp(), - track_par_cov_recalc.getSigma1PtTgl(), - track_par_cov_recalc.getSigma1Pt2()); - - stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); - - if (fillQAHistogram) { - uint32_t itsClusterSizes = track.itsClusterSizes(); - int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 0; layer < 7; layer++) { - int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; - if (cluster_size_per_layer > 0) { - nl++; - } - total_cluster_size += cluster_size_per_layer; - } - - fRegistry.fill(HIST("Track/hPt"), pt_recalc); - fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt_recalc); - fRegistry.fill(HIST("Track/hRelSigma1Pt"), pt_recalc, std::sqrt(track_par_cov_recalc.getSigma1Pt2()) * pt_recalc); - fRegistry.fill(HIST("Track/hEtaPhi"), phi_recalc, eta_recalc); - fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / std::sqrt(track_par_cov_recalc.getSigmaY2()), dcaZ / std::sqrt(track_par_cov_recalc.getSigmaZ2())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, std::sqrt(track_par_cov_recalc.getSigmaY2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, std::sqrt(track_par_cov_recalc.getSigmaZ2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); - fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); - fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); - fRegistry.fill(HIST("Track/hTPCNclsShared"), track.pt(), track.tpcFractionSharedCls()); - fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); - fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); - fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); - fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); - fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); - fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); - } - } - } - - template - o2::track::TrackParCov propagateTrack(TCollision const& collision, TTrack const& track) - { - std::array dcaInfo; - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); - // std::array pVec_recalc = {0, 0, 0}; // px, py, pz - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); - // getPxPyPz(track_par_cov_recalc, pVec_recalc); - return track_par_cov_recalc; - } - - std::vector> stored_trackIds; - // std::vector> stored_pairIds; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; - Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; - using MyFilteredTracks = soa::Filtered; - - Partition posTracks = o2::aod::track::signed1Pt > 0.f; - Partition negTracks = o2::aod::track::signed1Pt < 0.f; - - // ---------- for data ---------- - - void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&) - { - stored_trackIds.reserve(posTracks.size() + negTracks.size()); - - for (auto& collision : collisions) { - auto bc = collision.template foundBC_as(); - initCCDB(bc); - - if (!collision.isSelected()) { - filter(0, 0, 0); - continue; - } - - int nee_uls = 0; - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { - if (!checkTrack(collision, pos) || !checkTrack(collision, ele)) { - continue; - } - if (!isElectron(pos) || !isElectron(ele)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); - - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); - fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); - } - if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { - fillTrackTable(collision, pos); - fillTrackTable(collision, ele); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); - } - nee_uls++; - } - - } // end of pairing loop - - if (fillQAHistogram) { - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { - if (!checkTrack(collision, pos1) || !checkTrack(collision, pos2)) { - continue; - } - if (!isElectron(pos1) || !isElectron(pos2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); - } // end of pairing loop - - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { - if (!checkTrack(collision, ele1) || !checkTrack(collision, ele2)) { - continue; - } - if (!isElectron(ele1) || !isElectron(ele2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); - } // end of pairing loop - } - - if (nee_uls < 1) { - filter(nee_uls, 0, 0); - continue; - } - filter(nee_uls, 0, 0); - - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - // stored_pairIds.clear(); - // stored_pairIds.shrink_to_fit(); - } - PROCESS_SWITCH(filterDielectronEvent, processRec_SA, "process reconstructed info only", true); // standalone - - Preslice trackIndicesPerCollision = aod::track_association::collisionId; - void processRec_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) - { - stored_trackIds.reserve(tracks.size() * 2); - - for (auto& collision : collisions) { - auto bc = collision.template foundBC_as(); - initCCDB(bc); - - if (!collision.isSelected()) { - filter(0, 0, 0); - continue; - } - - int nee_uls = 0; - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); - std::vector posTracks_per_coll; - std::vector negTracks_per_coll; - posTracks_per_coll.reserve(trackIdsThisCollision.size()); - negTracks_per_coll.reserve(trackIdsThisCollision.size()); - - for (auto& trackId : trackIdsThisCollision) { - auto track = trackId.template track_as(); - if (!checkTrack(collision, track) || !isElectron(track)) { - continue; - } - - if (track.sign() > 0) { - posTracks_per_coll.emplace_back(track); - } else { - negTracks_per_coll.emplace_back(track); - } - } // end of track loop - - for (auto& pos : posTracks_per_coll) { - for (auto& ele : negTracks_per_coll) { - - auto pos_prop = propagateTrack(collision, pos); - auto ele_prop = propagateTrack(collision, ele); - - std::array pVec_pos = {0, 0, 0}; // px, py, pz - getPxPyPz(pos_prop, pVec_pos); - std::array pVec_ele = {0, 0, 0}; // px, py, pz - getPxPyPz(ele_prop, pVec_ele); - - ROOT::Math::PtEtaPhiMVector v1(pos_prop.getPt(), pos_prop.getEta(), pos_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele_prop.getPt(), ele_prop.getEta(), ele_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_pos[0], pVec_pos[1], pVec_pos[2], pVec_ele[0], pVec_ele[1], pVec_ele[2], pos.sign(), ele.sign(), d_bz); - - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); - fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); - } - if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { - fillTrackTable(collision, pos); - fillTrackTable(collision, ele); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); - } - nee_uls++; - } - - } // end of negative track loop - } // end of postive track loop - - if (fillQAHistogram) { - for (auto& pos1 : posTracks_per_coll) { - for (auto& pos2 : posTracks_per_coll) { - if (pos1.globalIndex() == pos2.globalIndex()) { - continue; - } - - auto pos1_prop = propagateTrack(collision, pos1); - auto pos2_prop = propagateTrack(collision, pos2); - - std::array pVec_pos1 = {0, 0, 0}; // px, py, pz - getPxPyPz(pos1_prop, pVec_pos1); - std::array pVec_pos2 = {0, 0, 0}; // px, py, pz - getPxPyPz(pos2_prop, pVec_pos2); - - ROOT::Math::PtEtaPhiMVector v1(pos1_prop.getPt(), pos1_prop.getEta(), pos1_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos2_prop.getPt(), pos2_prop.getEta(), pos2_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); - } // end of positive track loop - } // end of postive track loop - - for (auto& ele1 : negTracks_per_coll) { - for (auto& ele2 : negTracks_per_coll) { - if (ele1.globalIndex() == ele2.globalIndex()) { - continue; - } - - auto ele1_prop = propagateTrack(collision, ele1); - auto ele2_prop = propagateTrack(collision, ele2); - - std::array pVec_ele1 = {0, 0, 0}; // px, py, pz - getPxPyPz(ele1_prop, pVec_ele1); - std::array pVec_ele2 = {0, 0, 0}; // px, py, pz - getPxPyPz(ele2_prop, pVec_ele2); - - ROOT::Math::PtEtaPhiMVector v1(ele1_prop.getPt(), ele1_prop.getEta(), ele1_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele2_prop.getPt(), ele2_prop.getEta(), ele2_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); - } // end of negative track loop - } // end of negative track loop - } - - if (nee_uls < 1) { - filter(nee_uls, 0, 0); - continue; - } - - filter(nee_uls, 0, 0); - - posTracks_per_coll.clear(); - negTracks_per_coll.clear(); - posTracks_per_coll.shrink_to_fit(); - negTracks_per_coll.shrink_to_fit(); - - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - // stored_pairIds.clear(); - // stored_pairIds.shrink_to_fit(); - } - PROCESS_SWITCH(filterDielectronEvent, processRec_TTCA, "process reconstructed info only", false); // with TTCA - - // ---------- for data ---------- - - void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&) - { - stored_trackIds.reserve(posTracks.size() + negTracks.size()); - - for (auto& collision : collisions) { - auto bc = collision.template foundBC_as(); - initCCDB(bc); - - if (!collision.isSelected()) { - filter(0, 0, 0); - continue; - } - if (collision.swtaliastmp_raw() == 0) { - filter(0, 0, 0); - continue; - } - - int nee_uls = 0; - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { - if (!checkTrack(collision, pos) || !checkTrack(collision, ele)) { - continue; - } - if (!isElectron(pos) || !isElectron(ele)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); - - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); - fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); - } - if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { - fillTrackTable(collision, pos); - fillTrackTable(collision, ele); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); - } - nee_uls++; - } - - } // end of pairing loop - - if (fillQAHistogram) { - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { - if (!checkTrack(collision, pos1) || !checkTrack(collision, pos2)) { - continue; - } - if (!isElectron(pos1) || !isElectron(pos2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); - } // end of pairing loop - - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { - if (!checkTrack(collision, ele1) || !checkTrack(collision, ele2)) { - continue; - } - if (!isElectron(ele1) || !isElectron(ele2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); - } // end of pairing loop - } - - if (nee_uls < 1) { - filter(nee_uls, 0, 0); - continue; - } - filter(nee_uls, 0, 0); - - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - // stored_pairIds.clear(); - // stored_pairIds.shrink_to_fit(); - } - PROCESS_SWITCH(filterDielectronEvent, processRec_SA_SWT, "process reconstructed info only", false); // standalone - - void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) - { - stored_trackIds.reserve(tracks.size() * 2); - - for (auto& collision : collisions) { - auto bc = collision.template foundBC_as(); - initCCDB(bc); - - if (!collision.isSelected()) { - filter(0, 0, 0); - continue; - } - if (collision.swtaliastmp_raw() == 0) { - filter(0, 0, 0); - continue; - } - - int nee_uls = 0; - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); - std::vector posTracks_per_coll; - std::vector negTracks_per_coll; - posTracks_per_coll.reserve(trackIdsThisCollision.size()); - negTracks_per_coll.reserve(trackIdsThisCollision.size()); - - for (auto& trackId : trackIdsThisCollision) { - auto track = trackId.template track_as(); - if (!checkTrack(collision, track) || !isElectron(track)) { - continue; - } - - if (track.sign() > 0) { - posTracks_per_coll.emplace_back(track); - } else { - negTracks_per_coll.emplace_back(track); - } - } // end of track loop - - for (auto& pos : posTracks_per_coll) { - for (auto& ele : negTracks_per_coll) { - - auto pos_prop = propagateTrack(collision, pos); - auto ele_prop = propagateTrack(collision, ele); - - std::array pVec_pos = {0, 0, 0}; // px, py, pz - getPxPyPz(pos_prop, pVec_pos); - std::array pVec_ele = {0, 0, 0}; // px, py, pz - getPxPyPz(ele_prop, pVec_ele); - - ROOT::Math::PtEtaPhiMVector v1(pos_prop.getPt(), pos_prop.getEta(), pos_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele_prop.getPt(), ele_prop.getEta(), ele_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_pos[0], pVec_pos[1], pVec_pos[2], pVec_ele[0], pVec_ele[1], pVec_ele[2], pos.sign(), ele.sign(), d_bz); - - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); - fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); - } - if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { - fillTrackTable(collision, pos); - fillTrackTable(collision, ele); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); - } - nee_uls++; - } - - } // end of negative track loop - } // end of postive track loop - - if (fillQAHistogram) { - for (auto& pos1 : posTracks_per_coll) { - for (auto& pos2 : posTracks_per_coll) { - if (pos1.globalIndex() == pos2.globalIndex()) { - continue; - } - - auto pos1_prop = propagateTrack(collision, pos1); - auto pos2_prop = propagateTrack(collision, pos2); - - std::array pVec_pos1 = {0, 0, 0}; // px, py, pz - getPxPyPz(pos1_prop, pVec_pos1); - std::array pVec_pos2 = {0, 0, 0}; // px, py, pz - getPxPyPz(pos2_prop, pVec_pos2); - - ROOT::Math::PtEtaPhiMVector v1(pos1_prop.getPt(), pos1_prop.getEta(), pos1_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos2_prop.getPt(), pos2_prop.getEta(), pos2_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); - } // end of positive track loop - } // end of postive track loop - - for (auto& ele1 : negTracks_per_coll) { - for (auto& ele2 : negTracks_per_coll) { - if (ele1.globalIndex() == ele2.globalIndex()) { - continue; - } - - auto ele1_prop = propagateTrack(collision, ele1); - auto ele2_prop = propagateTrack(collision, ele2); - - std::array pVec_ele1 = {0, 0, 0}; // px, py, pz - getPxPyPz(ele1_prop, pVec_ele1); - std::array pVec_ele2 = {0, 0, 0}; // px, py, pz - getPxPyPz(ele2_prop, pVec_ele2); - - ROOT::Math::PtEtaPhiMVector v1(ele1_prop.getPt(), ele1_prop.getEta(), ele1_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele2_prop.getPt(), ele2_prop.getEta(), ele2_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); - } // end of negative track loop - } // end of negative track loop - } - - if (nee_uls < 1) { - filter(nee_uls, 0, 0); - continue; - } - - filter(nee_uls, 0, 0); - - posTracks_per_coll.clear(); - negTracks_per_coll.clear(); - posTracks_per_coll.shrink_to_fit(); - negTracks_per_coll.shrink_to_fit(); - - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - // stored_pairIds.clear(); - // stored_pairIds.shrink_to_fit(); - } - PROCESS_SWITCH(filterDielectronEvent, processRec_TTCA_SWT, "process reconstructed info only", false); // with TTCA - - // ---------- for MC ---------- - - using MyFilteredTracksMC = soa::Filtered; - Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; - Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; - void processMC_SA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) - { - stored_trackIds.reserve(tracks.size()); - - for (auto& collision : collisions) { - if (!collision.has_mcCollision()) { - continue; - } - auto bc = collision.template foundBC_as(); - initCCDB(bc); - - if (!collision.isSelected()) { - filter(0, 0, 0); - continue; - } - - int nee_uls = 0; - auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - - for (auto& [pos, ele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { - if (!checkTrack(collision, pos) || !checkTrack(collision, ele)) { - continue; - } - if (!isElectron(pos) || !isElectron(ele)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); - fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); - } - if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { - fillTrackTable(collision, pos); - fillTrackTable(collision, ele); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); - } - nee_uls++; - } - - } // end of pairing loop - - if (fillQAHistogram) { - for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { - if (!checkTrack(collision, pos1) || !checkTrack(collision, pos2)) { - continue; - } - if (!isElectron(pos1) || !isElectron(pos2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos1.pt(), pos1.eta(), pos1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos2.pt(), pos2.eta(), pos2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); - } // end of pairing loop - - for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { - if (!checkTrack(collision, ele1) || !checkTrack(collision, ele2)) { - continue; - } - if (!isElectron(ele1) || !isElectron(ele2)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(ele1.pt(), ele1.eta(), ele1.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele2.pt(), ele2.eta(), ele2.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); - } // end of pairing loop - } - - if (nee_uls < 1) { - filter(nee_uls, 0, 0); - continue; - } - filter(nee_uls, 0, 0); - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - // stored_pairIds.clear(); - // stored_pairIds.shrink_to_fit(); - } - PROCESS_SWITCH(filterDielectronEvent, processMC_SA, "process reconstructed and MC info ", false); - - void processMC_TTCA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, aod::TrackAssoc const& trackIndices) - { - stored_trackIds.reserve(tracks.size() * 2); - - for (auto& collision : collisions) { - if (!collision.has_mcCollision()) { - continue; - } - auto bc = collision.template foundBC_as(); - initCCDB(bc); - - if (!collision.isSelected()) { - filter(0, 0, 0); - continue; - } - - int nee_uls = 0; - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); - std::vector posTracks_per_coll; - std::vector negTracks_per_coll; - posTracks_per_coll.reserve(trackIdsThisCollision.size()); - negTracks_per_coll.reserve(trackIdsThisCollision.size()); - - for (auto& trackId : trackIdsThisCollision) { - auto track = trackId.template track_as(); - if (!checkTrack(collision, track) || !isElectron(track)) { - continue; - } - - if (track.sign() > 0) { - posTracks_per_coll.emplace_back(track); - } else { - negTracks_per_coll.emplace_back(track); - } - } // end of track loop - - for (auto& pos : posTracks_per_coll) { - for (auto& ele : negTracks_per_coll) { - auto pos_prop = propagateTrack(collision, pos); - auto ele_prop = propagateTrack(collision, ele); - std::array pVec_pos = {0, 0, 0}; // px, py, pz - getPxPyPz(pos_prop, pVec_pos); - std::array pVec_ele = {0, 0, 0}; // px, py, pz - getPxPyPz(ele_prop, pVec_ele); - - ROOT::Math::PtEtaPhiMVector v1(pos_prop.getPt(), pos_prop.getEta(), pos_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele_prop.getPt(), ele_prop.getEta(), ele_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_pos[0], pVec_pos[1], pVec_pos[2], pVec_ele[0], pVec_ele[1], pVec_ele[2], pos.sign(), ele.sign(), d_bz); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/uls/hM"), v12.M()); - fRegistry.fill(HIST("Pair/before/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/before/hMvsPhiV"), phiv, v12.M()); - } - if (apply_phiv ? (v12.M() < maxMee && slope * phiv + intercept < v12.M()) : (v12.M() < maxMee)) { - fillTrackTable(collision, pos); - fillTrackTable(collision, ele); - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/after/hMvsPt"), v12.M(), v12.Pt()); - fRegistry.fill(HIST("Pair/after/hMvsPhiV"), phiv, v12.M()); - } - nee_uls++; - } - - } // end of negative track loop - } // end of postive track loop - - if (fillQAHistogram) { - for (auto& pos1 : posTracks_per_coll) { - for (auto& pos2 : posTracks_per_coll) { - if (pos1.globalIndex() == pos2.globalIndex()) { - continue; - } - - auto pos1_prop = propagateTrack(collision, pos1); - auto pos2_prop = propagateTrack(collision, pos2); - - std::array pVec_pos1 = {0, 0, 0}; // px, py, pz - getPxPyPz(pos1_prop, pVec_pos1); - std::array pVec_pos2 = {0, 0, 0}; // px, py, pz - getPxPyPz(pos2_prop, pVec_pos2); - - ROOT::Math::PtEtaPhiMVector v1(pos1_prop.getPt(), pos1_prop.getEta(), pos1_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos2_prop.getPt(), pos2_prop.getEta(), pos2_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lspp/hM"), v12.M()); - } // end of positive track loop - } // end of postive track loop - - for (auto& ele1 : negTracks_per_coll) { - for (auto& ele2 : negTracks_per_coll) { - if (ele1.globalIndex() == ele2.globalIndex()) { - continue; - } - - auto ele1_prop = propagateTrack(collision, ele1); - auto ele2_prop = propagateTrack(collision, ele2); - - std::array pVec_ele1 = {0, 0, 0}; // px, py, pz - getPxPyPz(ele1_prop, pVec_ele1); - std::array pVec_ele2 = {0, 0, 0}; // px, py, pz - getPxPyPz(ele2_prop, pVec_ele2); - - ROOT::Math::PtEtaPhiMVector v1(ele1_prop.getPt(), ele1_prop.getEta(), ele1_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(ele2_prop.getPt(), ele2_prop.getEta(), ele2_prop.getPhi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - fRegistry.fill(HIST("Pair/lsmm/hM"), v12.M()); - } // end of negative track loop - } // end of negative track loop - } - - if (nee_uls < 1) { - filter(nee_uls, 0, 0); - continue; - } - filter(nee_uls, 0, 0); - - posTracks_per_coll.clear(); - negTracks_per_coll.clear(); - posTracks_per_coll.shrink_to_fit(); - negTracks_per_coll.shrink_to_fit(); - - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - // stored_pairIds.clear(); - // stored_pairIds.shrink_to_fit(); - } - PROCESS_SWITCH(filterDielectronEvent, processMC_TTCA, "process reconstructed info only", false); // with TTCA -}; -struct prefilterPrimaryElectron { - using MyCollisions = soa::Join; - using MyCollisionsWithSWT = soa::Join; - - Produces ele_pfb; - - SliceCache cache; - Preslice perCol_track = o2::aod::track::collisionId; - PresliceUnsorted perCol_ele = o2::aod::emprimaryelectron::collisionId; - - // CCDB options - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - - // Operation and minimisation criteria - Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; - - Configurable max_dcaxy{"max_dcaxy", 0.3, "DCAxy To PV for loose track sample"}; - Configurable max_dcaz{"max_dcaz", 0.3, "DCAz To PV for loose track sample"}; - Configurable minpt{"minpt", 0.1, "min pt for track for loose track sample"}; - 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 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", 6.0, "max chi2/NclsITS"}; - Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; - Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; - Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -3.0, "min. TPC n sigma for electron inclusion"}; - Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.0, "max. TPC n sigma for electron inclusion"}; - Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; - Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; - - Configurable> max_mee_vec{"max_mee_vec", std::vector{0.08, 0.10, 0.12}, "vector fo max mee for prefilter in ULS. Please sort this by increasing order."}; // currently, 3 thoresholds are allowed. - - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - - int mRunNumber; - float d_bz; - Service ccdb; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - void init(InitContext&) - { - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - if (!doprocessDummy) { - addHistograms(); - } - } - - 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, {{180, 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("Pair/before/uls/hMvsPt", "mass vs. pT;m_{ee} (GeV/c^{2});p_{T,ee} (GeV/c)", kTH2F, {{400, 0, 4}, {100, 0, 10}}); - 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, 1.f}}); - fRegistry.addClone("Pair/before/uls/", "Pair/before/lspp/"); - fRegistry.addClone("Pair/before/uls/", "Pair/before/lsmm/"); - fRegistry.addClone("Pair/before/", "Pair/after/"); - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (std::fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - o2::base::Propagator::initFieldFromGRP(&grpmag); - mRunNumber = bc.runNumber(); - return; - } - - auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = bc.runNumber(); - } - - o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - template - bool checkTrack(TCollision const& collision, TTrack const& track) - { - if (!track.hasITS()) { - return false; - } - if (track.itsChi2NCl() > maxchi2its) { - return false; - } - if (track.itsNCls() < min_ncluster_its) { - return false; - } - if (track.itsNClsInnerBarrel() < min_ncluster_itsib) { - return false; - } - - if (!track.hasTPC()) { - return false; - } - 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() > maxchi2its) { - return false; - } - - std::array dcaInfo; - auto track_par_cov_recalc = getTrackParCov(track); - // std::array pVec_recalc = {0, 0, 0}; // px, py, pz - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); - // getPxPyPz(track_par_cov_recalc, pVec_recalc); - - if (std::fabs(dcaInfo[0]) > max_dcaxy || std::fabs(dcaInfo[1]) > max_dcaz) { - return false; - } - - if (track_par_cov_recalc.getPt() < minpt || std::fabs(track_par_cov_recalc.getEta()) > maxeta) { - return false; - } - - return true; - } - - Preslice trackIndicesPerCollision = aod::track_association::collisionId; - - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && 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 positrons = o2::aod::emprimaryelectron::sign > int8_t(0); - Partition electrons = o2::aod::emprimaryelectron::sign < int8_t(0); - void processSA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const&, aod::EMPrimaryElectrons const& primaryelectrons) - { - std::unordered_map pfb_map; // map track.globalIndex -> prefilter bit - - for (auto& collision : collisions) { - auto bc = collision.template foundBC_as(); - initCCDB(bc); - if (!collision.isSelected()) { - continue; - } - - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample - - auto positrons_per_coll = positrons->sliceByCachedUnsorted(o2::aod::emprimaryelectron::collisionId, collision.globalIndex(), cache); // signal sample - auto electrons_per_coll = electrons->sliceByCachedUnsorted(o2::aod::emprimaryelectron::collisionId, collision.globalIndex(), cache); // signal sample - - for (auto& pos : posTracks_per_coll) { - if (!checkTrack(collision, pos)) { // track cut is applied to loose sample - continue; - } - fRegistry.fill(HIST("Track/hPt"), pos.pt()); - fRegistry.fill(HIST("Track/hEtaPhi"), pos.phi(), pos.eta()); - } - for (auto& neg : negTracks_per_coll) { - if (!checkTrack(collision, neg)) { // track cut is applied to loose sample - continue; - } - fRegistry.fill(HIST("Track/hPt"), neg.pt()); - fRegistry.fill(HIST("Track/hEtaPhi"), neg.phi(), neg.eta()); - } - - for (auto& [ele, empos] : combinations(CombinationsFullIndexPolicy(negTracks_per_coll, positrons_per_coll))) { - // auto pos = tracks.rawIteratorAt(empos.trackId()); // use rawIterator, if the table is filtered. - if (!checkTrack(collision, ele)) { // track cut is applied to loose sample - continue; - } - if (empos.trackId() == ele.globalIndex()) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); // loose track - ROOT::Math::PtEtaPhiMVector v2(empos.pt(), empos.eta(), empos.phi(), o2::constants::physics::MassElectron); // signal track - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(empos.px(), empos.py(), empos.pz(), ele.px(), ele.py(), ele.pz(), empos.sign(), ele.sign(), d_bz); - 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)) { - 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_1) + i)); - } - } - - if (v12.M() < slope * phiv + intercept) { - pfb_map[empos.globalIndex()] |= (uint8_t(1) << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC)); - } - - } // end of ULS pairing - - for (auto& [pos, emele] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, electrons_per_coll))) { - // auto ele = tracks.rawIteratorAt(emele.trackId()); // use rawIterator, if the table is filtered. - if (!checkTrack(collision, pos)) { // track cut is applied to loose sample - continue; - } - if (emele.trackId() == pos.globalIndex()) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(emele.pt(), emele.eta(), emele.phi(), o2::constants::physics::MassElectron); // signal track - ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); // loose track - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), emele.px(), emele.py(), emele.pz(), pos.sign(), emele.sign(), d_bz); - 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)) { - 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_1) + i)); - } - } - - if (v12.M() < slope * phiv + intercept) { - pfb_map[emele.globalIndex()] |= (uint8_t(1) << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBit::kElFromPC)); - } - - } // end of ULS pairing - - for (auto& [pos, empos] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, positrons_per_coll))) { - // auto pos = tracks.rawIteratorAt(empos.trackId()); // use rawIterator, if the table is filtered. - if (!checkTrack(collision, pos)) { // track cut is applied to loose sample - continue; - } - if (empos.trackId() == pos.globalIndex()) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); // loose track - ROOT::Math::PtEtaPhiMVector v2(empos.pt(), empos.eta(), empos.phi(), o2::constants::physics::MassElectron); // signal track - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(empos.px(), empos.py(), empos.pz(), pos.px(), pos.py(), pos.pz(), empos.sign(), pos.sign(), d_bz); - fRegistry.fill(HIST("Pair/before/lspp/hMvsPhiV"), phiv, v12.M()); - fRegistry.fill(HIST("Pair/before/lspp/hMvsPt"), v12.M(), v12.Pt()); - } // end of LS++ pairing - - for (auto& [ele, emele] : combinations(CombinationsFullIndexPolicy(negTracks_per_coll, electrons_per_coll))) { - // auto ele = tracks.rawIteratorAt(emele.trackId()); // use rawIterator, if the table is filtered. - if (!checkTrack(collision, ele)) { // track cut is applied to loose sample - continue; - } - if (emele.trackId() == ele.globalIndex()) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); // loose track - ROOT::Math::PtEtaPhiMVector v2(emele.pt(), emele.eta(), emele.phi(), o2::constants::physics::MassElectron); // signal track - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(emele.px(), emele.py(), emele.pz(), ele.px(), ele.py(), ele.pz(), emele.sign(), ele.sign(), d_bz); - fRegistry.fill(HIST("Pair/before/lsmm/hMvsPhiV"), phiv, v12.M()); - fRegistry.fill(HIST("Pair/before/lsmm/hMvsPt"), v12.M(), v12.Pt()); - } // end of LS-- pairing - - } // end of collision loop - - for (auto& ele : primaryelectrons) { - ele_pfb(pfb_map[ele.globalIndex()]); - } - - // check prefilter - for (auto& collision : collisions) { - auto positrons_per_coll = positrons->sliceByCachedUnsorted(o2::aod::emprimaryelectron::collisionId, collision.globalIndex(), cache); // signal sample - auto electrons_per_coll = electrons->sliceByCachedUnsorted(o2::aod::emprimaryelectron::collisionId, collision.globalIndex(), cache); // signal sample - - for (auto& [ele, pos] : combinations(CombinationsFullIndexPolicy(electrons_per_coll, positrons_per_coll))) { - if (pfb_map[ele.globalIndex()] != 0 || pfb_map[pos.globalIndex()] != 0) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = 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); - fRegistry.fill(HIST("Pair/after/uls/hMvsPhiV"), phiv, v12.M()); - fRegistry.fill(HIST("Pair/after/uls/hMvsPt"), v12.M(), v12.Pt()); - } // end of ULS pairing - } // end of collision loop - - pfb_map.clear(); - } - PROCESS_SWITCH(prefilterPrimaryElectron, processSA, "process SA", false); - - void processDummy(aod::EMPrimaryElectrons const& primaryelectrons) - { - for (int i = 0; i < primaryelectrons.size(); i++) { - ele_pfb(0); - } - } - PROCESS_SWITCH(prefilterPrimaryElectron, processDummy, "processDummy", true); -}; -struct associateAmbiguousElectron { - Produces em_amb_ele_ids; - - SliceCache cache; - PresliceUnsorted perTrack = o2::aod::emprimaryelectron::trackId; - std::vector ambele_self_Ids; - - void process(aod::EMPrimaryElectrons const& electrons) - { - for (auto& electron : electrons) { - auto electrons_with_same_trackId = electrons.sliceBy(perTrack, electron.trackId()); - ambele_self_Ids.reserve(electrons_with_same_trackId.size()); - for (auto& amb_ele : electrons_with_same_trackId) { - if (amb_ele.globalIndex() == electron.globalIndex()) { // don't store myself. - continue; - } - ambele_self_Ids.emplace_back(amb_ele.globalIndex()); - } - em_amb_ele_ids(ambele_self_Ids); - ambele_self_Ids.clear(); - ambele_self_Ids.shrink_to_fit(); - } - } -}; -struct createEMEvent2VP { - using MyBCs = soa::Join; - using MyQvectors = soa::Join; - - using MyCollisions = soa::Join; - using MyCollisions_Cent = soa::Join; // centrality table has dependency on multiplicity table. - using MyCollisions_Cent_Qvec = soa::Join; - - using MyCollisionsWithSWT = soa::Join; - using MyCollisionsWithSWT_Cent = soa::Join; // centrality table has dependency on multiplicity table. - using MyCollisionsWithSWT_Cent_Qvec = soa::Join; - - using MyCollisionsMC = soa::Join; - using MyCollisionsMC_Cent = soa::Join; // centrality table has dependency on multiplicity table. - using MyCollisionsMC_Cent_Qvec = soa::Join; - - Produces event; - // Produces eventcov; - Produces event_mult; - Produces event_cent; - Produces event_qvec; - Produces emswtbit; - - enum class EMEventType : int { - kEvent = 0, - kEvent_Cent = 1, - kEvent_Cent_Qvec = 2, - }; - - HistogramRegistry registry{"registry"}; - void init(o2::framework::InitContext&) - { - auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{7, 0.5f, 7.5f}}); - hEventCounter->GetXaxis()->SetBinLabel(1, "all"); - hEventCounter->GetXaxis()->SetBinLabel(2, "sel8"); - - registry.add("hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); - } - - ~createEMEvent2VP() - { - swt_names.clear(); - swt_names.shrink_to_fit(); - } - - std::vector mTOIidx; - std::vector swt_names; - uint64_t mNinspectedTVX{0}; - - int mRunNumber; - - template - void skimEvent(TCollisions const& collisions, TBCs const&) - { - for (auto& collision : collisions) { - if constexpr (isMC) { - if (!collision.has_mcCollision()) { - continue; - } - } - - if constexpr (isTriggerAnalysis) { - if (collision.swtaliastmp_raw() == 0) { - continue; - } - } - - auto bc = collision.template foundBC_as(); - - if (!collision.isSelected()) { - continue; - } - - if (!(collision.neeuls() >= 1 || collision.neeuls() + collision.ngpcm() >= 2)) { - continue; - } - - if constexpr (isTriggerAnalysis) { - emswtbit(collision.swtaliastmp_raw(), collision.nInspectedTVX()); - } - - // LOGF(info, "collision.neeuls() = %d, collision.ngpcm() = %d", collision.neeuls(), collision.ngpcm()); - // LOGF(info, "collision.multNTracksPV() = %d, collision.multFT0A() = %f, collision.multFT0C() = %f", collision.multNTracksPV(), collision.multFT0A(), collision.multFT0C()); - - registry.fill(HIST("hEventCounter"), 1); - - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), bc.timestamp(), - collision.posX(), collision.posY(), collision.posZ(), - collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); - - // 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()); - - if constexpr (eventype == 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); - } else if constexpr (eventype == 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); - } else if constexpr (eventype == EMEventType::kEvent_Cent_Qvec) { - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); - float q2xft0m = 999.f, q2yft0m = 999.f, q2xft0a = 999.f, q2yft0a = 999.f, q2xft0c = 999.f, q2yft0c = 999.f, q2xbpos = 999.f, q2ybpos = 999.f, q2xbneg = 999.f, q2ybneg = 999.f, q2xbtot = 999.f, q2ybtot = 999.f; - float q3xft0m = 999.f, q3yft0m = 999.f, q3xft0a = 999.f, q3yft0a = 999.f, q3xft0c = 999.f, q3yft0c = 999.f, q3xbpos = 999.f, q3ybpos = 999.f, q3xbneg = 999.f, q3ybneg = 999.f, q3xbtot = 999.f, q3ybtot = 999.f; - - if (collision.qvecFT0CReVec().size() >= 2) { // harmonics 2,3 - q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; - q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; - q3xft0m = collision.qvecFT0MReVec()[1], q3xft0a = collision.qvecFT0AReVec()[1], q3xft0c = collision.qvecFT0CReVec()[1], q3xbpos = collision.qvecBPosReVec()[1], q3xbneg = collision.qvecBNegReVec()[1], q3xbtot = collision.qvecBTotReVec()[1]; - q3yft0m = collision.qvecFT0MImVec()[1], q3yft0a = collision.qvecFT0AImVec()[1], q3yft0c = collision.qvecFT0CImVec()[1], q3ybpos = collision.qvecBPosImVec()[1], q3ybneg = collision.qvecBNegImVec()[1], q3ybtot = collision.qvecBTotImVec()[1]; - } else if (collision.qvecFT0CReVec().size() >= 1) { // harmonics 2 - q2xft0m = collision.qvecFT0MReVec()[0], q2xft0a = collision.qvecFT0AReVec()[0], q2xft0c = collision.qvecFT0CReVec()[0], q2xbpos = collision.qvecBPosReVec()[0], q2xbneg = collision.qvecBNegReVec()[0], q2xbtot = collision.qvecBTotReVec()[0]; - q2yft0m = collision.qvecFT0MImVec()[0], q2yft0a = collision.qvecFT0AImVec()[0], q2yft0c = collision.qvecFT0CImVec()[0], q2ybpos = collision.qvecBPosImVec()[0], q2ybneg = collision.qvecBNegImVec()[0], q2ybtot = collision.qvecBTotImVec()[0]; - } - event_qvec( - q2xft0m, q2yft0m, q2xft0a, q2yft0a, q2xft0c, q2yft0c, q2xbpos, q2ybpos, q2xbneg, q2ybneg, q2xbtot, q2ybtot, - q3xft0m, q3yft0m, q3xft0a, q3yft0a, q3xft0c, q3yft0c, q3xbpos, q3ybpos, q3xbneg, q3ybneg, q3xbtot, q3ybtot); - } else { - event_cent(105.f, 105.f, 105.f); - event_qvec( - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, - 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); - } - } // end of collision loop - } // end of skimEvent - - void processEvent(MyCollisions const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEvent, "process event info", false); - - void processEvent_Cent(MyCollisions_Cent const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEvent_Cent, "process event info", false); - - void processEvent_Cent_Qvec(MyCollisions_Cent_Qvec const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEvent_Cent_Qvec, "process event info", false); - - void processEvent_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEvent_SWT, "process event info", false); - - void processEvent_SWT_Cent(MyCollisionsWithSWT_Cent const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEvent_SWT_Cent, "process event info", false); - - void processEvent_SWT_Cent_Qvec(MyCollisionsWithSWT_Cent_Qvec const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEvent_SWT_Cent_Qvec, "process event info", false); - - void processEventMC(MyCollisionsMC const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEventMC, "process event info", false); - - void processEventMC_Cent(MyCollisionsMC_Cent const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEventMC_Cent, "process event info", false); - - void processEventMC_Cent_Qvec(MyCollisionsMC_Cent_Qvec const& collisions, MyBCs const& bcs) - { - skimEvent(collisions, bcs); - } - PROCESS_SWITCH(createEMEvent2VP, processEventMC_Cent_Qvec, "process event info", false); - - void processDummy(aod::Collisions const&) {} - PROCESS_SWITCH(createEMEvent2VP, processDummy, "processDummy", true); -}; -struct AssociateDileptonToEMEvent2VP { - Produces v0kfeventid; - Produces prmeleventid; - - Preslice perCollision_pcm = aod::v0photonkf::collisionId; - PresliceUnsorted perCollision_el = aod::emprimaryelectron::collisionId; - - void init(o2::framework::InitContext&) {} - - template - void fillEventId(TCollisions const& collisions, TLeptons const& leptons, TEventIds& eventIds, TPreslice const& perCollision) - { - for (auto& collision : collisions) { - auto leptons_coll = leptons.sliceBy(perCollision, collision.collisionId()); - int nl = leptons_coll.size(); - // LOGF(info, "collision.collisionId() = %d , nl = %d", collision.collisionId(), nl); - for (int il = 0; il < nl; il++) { - eventIds(collision.globalIndex()); - } // end of photon loop - } // end of collision loop - } - - // This struct is for both data and MC. - // Note that reconstructed collisions without mc collisions are already rejected in CreateEMEventDilepton in MC. - - void processPCM(aod::EMEvents const& collisions, aod::V0PhotonsKF const& photons) - { - fillEventId(collisions, photons, v0kfeventid, perCollision_pcm); - } - - void processElectron(aod::EMEvents const& collisions, aod::EMPrimaryElectrons const& tracks) - { - fillEventId(collisions, tracks, prmeleventid, perCollision_el); - } - - void processDummy(aod::EMEvents const&) {} - - PROCESS_SWITCH(AssociateDileptonToEMEvent2VP, processPCM, "process pcm-event indexing", false); - PROCESS_SWITCH(AssociateDileptonToEMEvent2VP, processElectron, "process dalitzee-event indexing", false); - PROCESS_SWITCH(AssociateDileptonToEMEvent2VP, processDummy, "process dummy", true); -}; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"filter-dielectron-event"}), - adaptAnalysisTask(cfgc, TaskName{"prefilter-primary-electron"}), - adaptAnalysisTask(cfgc, TaskName{"associate-ambiguous-electron"}), - adaptAnalysisTask(cfgc, TaskName{"create-emevent-2vp"}), - adaptAnalysisTask(cfgc, TaskName{"associate-dilepton-to-emevent2VP"}), - }; -} diff --git a/PWGEM/Dilepton/TableProducer/filterEoI.cxx b/PWGEM/Dilepton/TableProducer/filterEoI.cxx index 9edaeb784dc..59dfbf07e0b 100644 --- a/PWGEM/Dilepton/TableProducer/filterEoI.cxx +++ b/PWGEM/Dilepton/TableProducer/filterEoI.cxx @@ -14,11 +14,13 @@ // This code filters events that are interesting for dilepton analyses. // Please write to: daiki.sekihata@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "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" using namespace o2; using namespace o2::framework; @@ -29,55 +31,86 @@ struct filterEoI { enum SubSystem { kElectron = 0x1, kFwdMuon = 0x2, + kPCM = 0x4, + kElectronFromDalitz = 0x8, }; Produces emeoi; + // Configurable minNElectrons{"minNElectrons", 1, "min number of e+ or e- at midrapidity"}; + // Configurable minNMuons{"minNMuons", 1, "min number of mu+ or mu- at forward rapidity"}; + // Configurable minNV0s{"minNV0s", 1, "min number of v0 photons at midrapidity"}; HistogramRegistry fRegistry{"output"}; void init(o2::framework::InitContext&) { - auto hEventCounter = fRegistry.add("hEventCounter", "hEventCounter", kTH1D, {{5, 0.5f, 5.5f}}); + auto hEventCounter = fRegistry.add("hEventCounter", "hEventCounter", kTH1D, {{8, 0.5f, 8.5f}}); hEventCounter->GetXaxis()->SetBinLabel(1, "all"); hEventCounter->GetXaxis()->SetBinLabel(2, "event with electron"); hEventCounter->GetXaxis()->SetBinLabel(3, "event with forward muon"); - hEventCounter->GetXaxis()->SetBinLabel(4, "event with electron or forward muon"); - hEventCounter->GetXaxis()->SetBinLabel(5, "event with electron and forward muon"); + hEventCounter->GetXaxis()->SetBinLabel(4, "event with v0"); + hEventCounter->GetXaxis()->SetBinLabel(5, "event with electron or forward muon"); + hEventCounter->GetXaxis()->SetBinLabel(6, "event with electron and forward muon"); + hEventCounter->GetXaxis()->SetBinLabel(7, "event with electron or forward muon or v0"); + hEventCounter->GetXaxis()->SetBinLabel(8, "event with v0 or electrons from dalitz"); } SliceCache cache; Preslice perCollision_el = aod::emprimaryelectron::collisionId; Preslice perCollision_mu = aod::emprimarymuon::collisionId; + Preslice perCollision_v0 = aod::v0photonkf::collisionId; + Preslice perCollision_elda = aod::emprimaryelectron::collisionId; - template - void selectEoI(TCollisions const& collisions, TElectrons const& electrons, TMuons const& muons) + template + void selectEoI(TCollisions const& collisions, TElectrons const& electrons, TMuons const& muons, TV0s const& v0s, TElectronsDA const& electronsda) { for (const auto& collision : collisions) { bool does_electron_exist = false; bool does_fwdmuon_exist = false; + bool does_pcm_exist = false; + bool does_electronda_exist = false; fRegistry.fill(HIST("hEventCounter"), 1); if constexpr (static_cast(system & kElectron)) { auto electrons_coll = electrons.sliceBy(perCollision_el, collision.globalIndex()); - if (electrons_coll.size() > 0) { + if (electrons_coll.size() >= 1) { does_electron_exist = true; fRegistry.fill(HIST("hEventCounter"), 2); } } if constexpr (static_cast(system & kFwdMuon)) { auto muons_coll = muons.sliceBy(perCollision_mu, collision.globalIndex()); - if (muons_coll.size() > 0) { + if (muons_coll.size() >= 1) { does_fwdmuon_exist = true; fRegistry.fill(HIST("hEventCounter"), 3); } } + if constexpr (static_cast(system & kPCM)) { + auto v0s_coll = v0s.sliceBy(perCollision_v0, collision.globalIndex()); + if (v0s_coll.size() >= 1) { + does_pcm_exist = true; + fRegistry.fill(HIST("hEventCounter"), 4); + } + } + if constexpr (static_cast(system & kElectronFromDalitz)) { + auto electronsda_coll = electronsda.sliceBy(perCollision_elda, collision.globalIndex()); + if (electronsda_coll.size() >= 2) { + does_electronda_exist = true; + } + } if (does_electron_exist || does_fwdmuon_exist) { - fRegistry.fill(HIST("hEventCounter"), 4); + fRegistry.fill(HIST("hEventCounter"), 5); } if (does_electron_exist && does_fwdmuon_exist) { - fRegistry.fill(HIST("hEventCounter"), 5); + fRegistry.fill(HIST("hEventCounter"), 6); + } + if (does_electron_exist || does_fwdmuon_exist || does_pcm_exist) { + fRegistry.fill(HIST("hEventCounter"), 7); + } + if (does_pcm_exist || does_electronda_exist) { + fRegistry.fill(HIST("hEventCounter"), 8); } - emeoi(does_electron_exist || does_fwdmuon_exist); + emeoi(does_electron_exist || does_fwdmuon_exist || does_pcm_exist || does_electronda_exist); } // end of collision loop @@ -86,19 +119,37 @@ struct filterEoI { void process_Electron(aod::Collisions const& collisions, aod::EMPrimaryElectrons const& electrons) { const uint8_t sysflag = kElectron; - selectEoI(collisions, electrons, nullptr); + selectEoI(collisions, electrons, nullptr, nullptr, nullptr); } void process_FwdMuon(aod::Collisions const& collisions, aod::EMPrimaryMuons const& muons) { const uint8_t sysflag = kFwdMuon; - selectEoI(collisions, nullptr, muons); + selectEoI(collisions, nullptr, muons, nullptr, nullptr); } void process_Electron_FwdMuon(aod::Collisions const& collisions, aod::EMPrimaryElectrons const& electrons, aod::EMPrimaryMuons const& muons) { const uint8_t sysflag = kElectron | kFwdMuon; - selectEoI(collisions, electrons, muons); + selectEoI(collisions, electrons, muons, nullptr, nullptr); + } + + void process_PCM(aod::Collisions const& collisions, aod::V0PhotonsKF const& v0s) + { + const uint8_t sysflag = kPCM; + selectEoI(collisions, nullptr, nullptr, v0s, nullptr); + } + + void process_Electron_FwdMuon_PCM(aod::Collisions const& collisions, aod::EMPrimaryElectrons const& electrons, aod::EMPrimaryMuons const& muons, aod::V0PhotonsKF const& v0s) + { + const uint8_t sysflag = kElectron | kFwdMuon | kPCM; + selectEoI(collisions, electrons, muons, v0s, nullptr); + } + + void process_PCM_ElectronFromDalitz(aod::Collisions const& collisions, aod::V0PhotonsKF const& v0s, aod::EMPrimaryElectronsFromDalitz const& electronsda) + { + const uint8_t sysflag = kPCM | kElectronFromDalitz; + selectEoI(collisions, nullptr, nullptr, v0s, electronsda); } void processDummy(aod::Collisions const& collisions) @@ -110,7 +161,10 @@ struct filterEoI { PROCESS_SWITCH(filterEoI, process_Electron, "create filter bit for Electron", false); PROCESS_SWITCH(filterEoI, process_FwdMuon, "create filter bit for Forward Muon", false); + PROCESS_SWITCH(filterEoI, process_PCM, "create filter bit for PCM", false); PROCESS_SWITCH(filterEoI, process_Electron_FwdMuon, "create filter bit for Electron, FwdMuon", false); + PROCESS_SWITCH(filterEoI, process_Electron_FwdMuon_PCM, "create filter bit for Electron, FwdMuon, PCM", false); + PROCESS_SWITCH(filterEoI, process_PCM_ElectronFromDalitz, "create filter bit for PCM, ElectronFromDalitz", false); PROCESS_SWITCH(filterEoI, processDummy, "processDummy", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx b/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx index 3ea6dc842d8..997f8c4e6a5 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerOTS.cxx @@ -14,16 +14,19 @@ // This code produces trigger information. OTS = offline trigger selection. // Please write to: daiki.sekihata@cern.ch -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "EventFiltering/Zorro.h" #include "Common/Core/TableHelper.h" +#include "EventFiltering/Zorro.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "CCDB/BasicCCDBManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include using namespace o2; using namespace o2::framework; @@ -100,7 +103,7 @@ struct skimmerOTS { void process(MyCollisions const& collisions, MyBCs const&) { for (auto& collision : collisions) { - auto bc = collision.template foundBC_as(); + auto bc = collision.template bc_as(); // don't use foundBC. initCCDB(bc); uint16_t trigger_bitmap = 0; diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx index a4eac761725..b40a5e11e7d 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryElectron.cxx @@ -12,30 +12,34 @@ /// \brief write relevant information about primary electrons. /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/MlResponseO2Track.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsCalibration/MeanVertexObject.h" -#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/TableHelper.h" #include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/TableHelper.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Tools/ML/MlResponse.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.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 using namespace o2; using namespace o2::soa; @@ -46,16 +50,16 @@ using namespace o2::constants::physics; using MyCollisions = soa::Join; using MyCollisionsWithSWT = soa::Join; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; -using MyTracksMC = soa::Join; +using MyTracksMC = soa::Join; using MyTrackMC = MyTracksMC::iterator; struct skimmerPrimaryElectron { SliceCache cache; - Preslice perCol = o2::aod::track::collisionId; + Preslice perCol = o2::aod::track::collisionId; Produces emprimaryelectrons; Produces emprimaryelectronscov; @@ -70,17 +74,17 @@ struct skimmerPrimaryElectron { // Operation and minimisation criteria Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - Configurable min_ncluster_tpc{"min_ncluster_tpc", 10, "min ncluster tpc"}; + Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt{"minpt", 0.15, "min pt for track"}; + Configurable minpt{"minpt", 0.15, "min pt for ITS-TPC track"}; Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; - Configurable dca_xy_max{"dca_xy_max", 0.3f, "max DCAxy in cm"}; - Configurable dca_z_max{"dca_z_max", 0.3f, "max DCAz in cm"}; + Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1e+10, "max DCA 3D in sigma"}; Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -2.5, "min. TPC n sigma for electron inclusion"}; Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.5, "max. TPC n sigma for electron inclusion"}; @@ -95,8 +99,25 @@ 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"}; + + // 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 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)"}; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + o2::analysis::MlResponseO2Track mlResponseSingleTrack; int mRunNumber; float d_bz; @@ -106,6 +127,7 @@ struct skimmerPrimaryElectron { o2::dataformats::VertexBase mVtx; const o2::dataformats::MeanVertexObject* mMeanVtx = nullptr; o2::base::MatLayerCylSet* lut = nullptr; + o2::ccdb::CcdbApi ccdbApi; void init(InitContext&) { @@ -116,6 +138,7 @@ struct skimmerPrimaryElectron { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + ccdbApi.init(ccdburl); if (fillQAHistogram) { fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); @@ -136,24 +159,47 @@ struct skimmerPrimaryElectron { fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTPCdEdxMC", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTOFbeta", "TOF beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/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/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, false); - fRegistry.add("Track/hITSNsigmaEl", "ITS n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaMu", "ITS n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaPi", "ITS n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaKa", "ITS n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaPr", "ITS n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{ITS}", 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); } + + 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); + } // end of PID ML } void initCCDB(aod::BCsWithTimestamps::iterator const& bc) @@ -220,21 +266,23 @@ struct skimmerPrimaryElectron { if (!track.has_mcParticle()) { return false; } + if (storeOnlyTrueElectronMC) { + const auto& mcParticle = track.template mcParticle_as(); + if (std::abs(mcParticle.pdgCode()) != 11) { + return false; + } + } } if (requireTOF && !(track.hasTOF() && std::fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl)) { return false; } - if (track.tpcChi2NCl() > maxchi2tpc) { - return false; - } - - if (track.itsChi2NCl() > maxchi2its) { + if (!track.hasITS()) { return false; } - if (!track.hasITS() || !track.hasTPC()) { + if (track.itsChi2NCl() < 0.f || maxchi2its < track.itsChi2NCl()) { return false; } if (track.itsNCls() < min_ncluster_its) { @@ -244,65 +292,114 @@ struct skimmerPrimaryElectron { return false; } - if (track.tpcNClsFound() < min_ncluster_tpc) { + if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } + if (track.hasTPC()) { + if (track.tpcChi2NCl() < 0.f || maxchi2tpc < track.tpcChi2NCl()) { + return false; + } - if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { - return false; - } + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } - if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { - return false; - } + if (track.tpcNClsCrossedRows() < mincrossedrows) { + return false; + } - if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(track.tofNSigmaEl()))) { - return false; + if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { + return false; + } + + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - // LOGF(info, "track_par_cov_recalc.getSigmaY2() = %.16f, mDcaInfoCov.getSigmaY2() = %.16f, track_par_cov_recalc.getSigmaZ2() = %.16f, mDcaInfoCov.getSigmaZ2() = %.16f, track_par_cov_recalc.getSigmaZY() = %.16f, mDcaInfoCov.getSigmaYZ() = %.16f", track_par_cov_recalc.getSigmaY2(), mDcaInfoCov.getSigmaY2(), track_par_cov_recalc.getSigmaZ2(), mDcaInfoCov.getSigmaZ2(), track_par_cov_recalc.getSigmaZY(), mDcaInfoCov.getSigmaYZ()); - if (std::fabs(dcaXY) > dca_xy_max || std::fabs(dcaZ) > dca_z_max) { return false; } - if (track_par_cov_recalc.getPt() < minpt || std::fabs(track_par_cov_recalc.getEta()) > maxeta) { - return false; - } - float dca_3d = 999.f; - float det = track_par_cov_recalc.getSigmaY2() * track_par_cov_recalc.getSigmaZ2() - track_par_cov_recalc.getSigmaZY() * track_par_cov_recalc.getSigmaZY(); + float det = trackParCov.getSigmaY2() * trackParCov.getSigmaZ2() - trackParCov.getSigmaZY() * trackParCov.getSigmaZY(); if (det < 0) { dca_3d = 999.f; } else { - float chi2 = (dcaXY * dcaXY * track_par_cov_recalc.getSigmaZ2() + dcaZ * dcaZ * track_par_cov_recalc.getSigmaY2() - 2. * dcaXY * dcaZ * track_par_cov_recalc.getSigmaZY()) / det; + float chi2 = (dcaXY * dcaXY * trackParCov.getSigmaZ2() + dcaZ * dcaZ * trackParCov.getSigmaY2() - 2. * dcaXY * dcaZ * trackParCov.getSigmaZY()) / det; dca_3d = std::sqrt(std::fabs(chi2) / 2.); } if (dca_3d > dca_3d_sigma_max) { return false; } + if (trackParCov.getPt() < minpt || std::fabs(trackParCov.getEta()) > maxeta) { + return false; + } + + if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && maxpt_itssa < trackParCov.getPt()) { + return false; + } + + if (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) { + 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 (maxMeanITSClusterSize < static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))) { + return false; + } + } + return true; } - template - bool isElectron(TTrack const& track) + template + bool isElectron(TCollision const& collision, TTrack const& track) { - return isElectron_TPChadrej(track) || isElectron_TOFreq(track); + if (includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } + + if (usePIDML) { + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { + return false; + } + if (track.hasTOF() && (maxTOFNsigmaEl < std::fabs(track.tofNSigmaEl()))) { + return false; + } + + // 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()); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + + std::vector inputFeatures = mlResponseSingleTrack.getInputFeatures(track, trackParCov, collision); + float binningFeature = mlResponseSingleTrack.getBinningFeature(track, trackParCov, collision); + return mlResponseSingleTrack.isSelectedMl(inputFeatures, binningFeature); + } else { + return isElectron_TPChadrej(track) || isElectron_TOFreq(track); + } } template @@ -335,73 +432,104 @@ struct skimmerPrimaryElectron { return minTPCNsigmaEl < track.tpcNSigmaEl() && track.tpcNSigmaEl() < maxTPCNsigmaEl && std::fabs(track.tofNSigmaEl()) < maxTOFNsigmaEl; } - template + 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 track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - float pt_recalc = track_par_cov_recalc.getPt(); - float eta_recalc = track_par_cov_recalc.getEta(); - float phi_recalc = track_par_cov_recalc.getPhi(); + float 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(); + } emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), - pt_recalc, eta_recalc, phi_recalc, dcaXY, dcaZ, + pt_recalc, eta_recalc, phi_recalc, + dcaXY, dcaZ, trackParCov.getSigmaY2(), trackParCov.getSigmaZY(), trackParCov.getSigmaZ2(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.itsClusterSizes(), track.itsNSigmaEl(), track.itsNSigmaMu(), track.itsNSigmaPi(), track.itsNSigmaKa(), track.itsNSigmaPr(), + 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(), - track_par_cov_recalc.getX(), track_par_cov_recalc.getAlpha(), track_par_cov_recalc.getY(), track_par_cov_recalc.getZ(), track_par_cov_recalc.getSnp(), track_par_cov_recalc.getTgl(), isAssociatedToMPC); + // trackParCov.getTgl(), + isAssociatedToMPC, false, 1.f, mcTunedTPCSignal); emprimaryelectronscov( - track_par_cov_recalc.getSigmaY2(), - track_par_cov_recalc.getSigmaZY(), - track_par_cov_recalc.getSigmaZ2(), - track_par_cov_recalc.getSigmaSnpY(), - track_par_cov_recalc.getSigmaSnpZ(), - track_par_cov_recalc.getSigmaSnp2(), - track_par_cov_recalc.getSigmaTglY(), - track_par_cov_recalc.getSigmaTglZ(), - track_par_cov_recalc.getSigmaTglSnp(), - track_par_cov_recalc.getSigmaTgl2(), - track_par_cov_recalc.getSigma1PtY(), - track_par_cov_recalc.getSigma1PtZ(), - track_par_cov_recalc.getSigma1PtSnp(), - track_par_cov_recalc.getSigma1PtTgl(), - track_par_cov_recalc.getSigma1Pt2()); + 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) { - uint32_t itsClusterSizes = track.itsClusterSizes(); + // uint32_t itsClusterSizes = track.itsClusterSizes(); int total_cluster_size = 0, nl = 0; for (unsigned int layer = 0; layer < 7; layer++) { - int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; + 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_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; + } + 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(track_par_cov_recalc.getSigmaY2()), dcaZ / std::sqrt(track_par_cov_recalc.getSigmaZ2())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, std::sqrt(track_par_cov_recalc.getSigmaY2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, std::sqrt(track_par_cov_recalc.getSigmaZ2()) * 1e+4); // convert cm to um + 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()); @@ -413,31 +541,28 @@ struct skimmerPrimaryElectron { 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/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + // fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/hTOFbeta"), trackParCov.getP(), track.beta()); fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); + // 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/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); - fRegistry.fill(HIST("Track/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); - fRegistry.fill(HIST("Track/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); - fRegistry.fill(HIST("Track/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); - fRegistry.fill(HIST("Track/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); - fRegistry.fill(HIST("Track/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); + 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()))); } } } Preslice trackIndicesPerCollision = aod::track_association::collisionId; std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; - Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; @@ -447,7 +572,6 @@ struct skimmerPrimaryElectron { void processRec_SA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) { - auto tracksWithITSPid = soa::Attach(tracks); stored_trackIds.reserve(tracks.size()); for (const auto& collision : collisions) { @@ -458,12 +582,12 @@ struct skimmerPrimaryElectron { continue; } - auto tracks_per_coll = tracksWithITSPid.sliceBy(perCol, collision.globalIndex()); + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } - fillTrackTable(collision, track); + fillTrackTable(collision, track); } } // end of collision loop @@ -475,7 +599,6 @@ struct skimmerPrimaryElectron { void processRec_TTCA(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) { - auto tracksWithITSPid = soa::Attach(tracks); stored_trackIds.reserve(tracks.size() * 2); for (const auto& collision : collisions) { @@ -489,12 +612,11 @@ struct skimmerPrimaryElectron { auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); for (const auto& trackId : trackIdsThisCollision) { - // auto track = trackId.template track_as(); - auto track = tracksWithITSPid.rawIteratorAt(trackId.trackId()); - if (!checkTrack(collision, track) || !isElectron(track)) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } - fillTrackTable(collision, track); + fillTrackTable(collision, track); } } // end of collision loop @@ -505,7 +627,6 @@ struct skimmerPrimaryElectron { void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) { - auto tracksWithITSPid = soa::Attach(tracks); stored_trackIds.reserve(tracks.size()); for (const auto& collision : collisions) { @@ -520,12 +641,12 @@ struct skimmerPrimaryElectron { continue; } - auto tracks_per_coll = tracksWithITSPid.sliceBy(perCol, collision.globalIndex()); + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } - fillTrackTable(collision, track); + fillTrackTable(collision, track); } } // end of collision loop @@ -537,7 +658,6 @@ struct skimmerPrimaryElectron { void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyTracks const& tracks, aod::TrackAssoc const& trackIndices) { - auto tracksWithITSPid = soa::Attach(tracks); stored_trackIds.reserve(tracks.size() * 2); for (const auto& collision : collisions) { @@ -554,12 +674,11 @@ struct skimmerPrimaryElectron { auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); for (const auto& trackId : trackIdsThisCollision) { - // auto track = trackId.template track_as(); - auto track = tracksWithITSPid.rawIteratorAt(trackId.trackId()); - if (!checkTrack(collision, track) || !isElectron(track)) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } - fillTrackTable(collision, track); + fillTrackTable(collision, track); } } // end of collision loop @@ -573,9 +692,8 @@ struct skimmerPrimaryElectron { using MyFilteredTracksMC = soa::Filtered; Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; - void processMC_SA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + void processMC_SA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks, aod::McParticles const&) { - auto tracksWithITSPid = soa::Attach(tracks); stored_trackIds.reserve(tracks.size()); for (const auto& collision : collisions) { @@ -589,12 +707,12 @@ struct skimmerPrimaryElectron { continue; } - auto tracks_per_coll = tracksWithITSPid.sliceBy(perCol, collision.globalIndex()); + auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); for (const auto& track : tracks_per_coll) { - if (!checkTrack(collision, track) || !isElectron(track)) { + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } - fillTrackTable(collision, track); + fillTrackTable(collision, track); } } // end of collision loop @@ -603,9 +721,8 @@ struct skimmerPrimaryElectron { } PROCESS_SWITCH(skimmerPrimaryElectron, processMC_SA, "process reconstructed and MC info ", false); - void processMC_TTCA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, aod::TrackAssoc const& trackIndices) + void processMC_TTCA(soa::Join const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyTracksMC const& tracks, aod::TrackAssoc const& trackIndices, aod::McParticles const&) { - auto tracksWithITSPid = soa::Attach(tracks); stored_trackIds.reserve(tracks.size() * 2); for (const auto& collision : collisions) { @@ -622,12 +739,11 @@ struct skimmerPrimaryElectron { auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, collision.globalIndex()); for (const auto& trackId : trackIdsThisCollision) { - // auto track = trackId.template track_as(); - auto track = tracksWithITSPid.rawIteratorAt(trackId.trackId()); - if (!checkTrack(collision, track) || !isElectron(track)) { + auto track = trackId.template track_as(); + if (!checkTrack(collision, track) || !isElectron(collision, track)) { continue; } - fillTrackTable(collision, track); + fillTrackTable(collision, track); } } // end of collision loop @@ -641,7 +757,7 @@ struct prefilterPrimaryElectron { Produces ele_pfb; SliceCache cache; - Preslice perCol_track = o2::aod::track::collisionId; + Preslice perCol_track = o2::aod::track::collisionId; PresliceUnsorted perCol_ele = o2::aod::emprimaryelectron::collisionId; // CCDB options @@ -658,7 +774,7 @@ struct prefilterPrimaryElectron { Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; Configurable max_dcaxy{"max_dcaxy", 0.3, "DCAxy To PV for loose track sample"}; Configurable max_dcaz{"max_dcaz", 0.3, "DCAz To PV for loose track sample"}; - Configurable minpt{"minpt", 0.1, "min pt for track 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 min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable mincrossedrows{"mincrossedrows", 70, "min crossed rows"}; @@ -672,6 +788,9 @@ struct prefilterPrimaryElectron { Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", 3.0, "max. TPC n sigma for electron inclusion"}; Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; + Configurable includeITSsa{"includeITSsa", false, "Flag to include ITSsa tracks"}; + Configurable maxpt_itssa{"maxpt_itssa", 0.15, "mix pt for ITSsa track"}; + Configurable maxMeanITSClusterSize{"maxMeanITSClusterSize", 16, "max x cos(lambda)"}; Configurable> max_mee_vec{"max_mee_vec", std::vector{0.06, 0.08, 0.10}, "vector fo max mee for prefilter in ULS. Please sort this by increasing order."}; // currently, 3 thoresholds are allowed. @@ -786,35 +905,38 @@ struct prefilterPrimaryElectron { return false; } - if (!track.hasTPC()) { - return false; - } - if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { - return false; - } - if (track.tpcNClsFound() < min_ncluster_tpc) { + if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { 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() > maxchi2its) { - 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; + } } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); @@ -822,10 +944,29 @@ struct prefilterPrimaryElectron { return false; } - if (track_par_cov_recalc.getPt() < minpt || std::fabs(track_par_cov_recalc.getEta()) > maxeta) { + if (trackParCov.getPt() < minpt || std::fabs(trackParCov.getEta()) > maxeta) { return false; } + if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && maxpt_itssa < trackParCov.getPt()) { + return false; + } + + if (track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) { + 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 (maxMeanITSClusterSize < static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(trackParCov.getTgl()))) { + return false; + } + } + return true; } @@ -840,21 +981,21 @@ struct prefilterPrimaryElectron { mVtx.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); if constexpr (loose_track_sign > 0) { // positive track is loose track - auto track_par_cov_recalc = getTrackParCov(pos); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(track_par_cov_recalc, pVec_recalc); + auto trackParCov = getTrackParCov(pos); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(trackParCov, pVec_recalc); ROOT::Math::PtEtaPhiMVector v1(ele.pt(), ele.eta(), ele.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v2(trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; mee = v12.M(); phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], ele.px(), ele.py(), ele.pz(), pos.sign(), ele.sign(), d_bz); } else { - auto track_par_cov_recalc = getTrackParCov(ele); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(track_par_cov_recalc, pVec_recalc); + auto trackParCov = getTrackParCov(ele); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(trackParCov, pVec_recalc); - ROOT::Math::PtEtaPhiMVector v1(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); + ROOT::Math::PtEtaPhiMVector v1(trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; mee = v12.M(); @@ -870,7 +1011,7 @@ struct prefilterPrimaryElectron { Preslice trackIndicesPerCollision = aod::track_association::collisionId; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; + Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; @@ -915,26 +1056,26 @@ struct prefilterPrimaryElectron { } for (const auto& ele : negTracks_per_coll) { - if (!checkTrack(collision, ele)) { - continue; - } + // if (!checkTrack(collision, ele)) { + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz - auto track_par_cov_recalc = getTrackParCov(ele); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + auto trackParCov = getTrackParCov(ele); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(track_par_cov_recalc, pVec_recalc); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(trackParCov, pVec_recalc); for (const auto& empos : positrons_per_coll) { if (empos.trackId() == ele.globalIndex()) { continue; } - ROOT::Math::PtEtaPhiMVector v1(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); // loose track - ROOT::Math::PtEtaPhiMVector v2(empos.pt(), empos.eta(), empos.phi(), o2::constants::physics::MassElectron); // signal track + ROOT::Math::PtEtaPhiMVector v1(trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), o2::constants::physics::MassElectron); // loose track + ROOT::Math::PtEtaPhiMVector v2(empos.pt(), empos.eta(), empos.phi(), o2::constants::physics::MassElectron); // signal track ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(empos.px(), empos.py(), empos.pz(), pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], empos.sign(), ele.sign(), d_bz); if (fillQAHistogram) { @@ -960,25 +1101,25 @@ struct prefilterPrimaryElectron { } // end of loose electron loop for (const auto& pos : posTracks_per_coll) { - if (!checkTrack(collision, pos)) { // track cut is applied to loose sample - continue; - } + // if (!checkTrack(collision, pos)) { // track cut is applied to loose sample + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz - auto track_par_cov_recalc = getTrackParCov(pos); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + auto trackParCov = getTrackParCov(pos); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(track_par_cov_recalc, pVec_recalc); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(trackParCov, pVec_recalc); for (const auto& emele : electrons_per_coll) { if (emele.trackId() == pos.globalIndex()) { continue; } - ROOT::Math::PtEtaPhiMVector v1(emele.pt(), emele.eta(), emele.phi(), o2::constants::physics::MassElectron); // signal track - ROOT::Math::PtEtaPhiMVector v2(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); // loose track + ROOT::Math::PtEtaPhiMVector v1(emele.pt(), emele.eta(), emele.phi(), o2::constants::physics::MassElectron); // signal track + ROOT::Math::PtEtaPhiMVector v2(trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), o2::constants::physics::MassElectron); // loose track ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], emele.px(), emele.py(), emele.pz(), pos.sign(), emele.sign(), d_bz); if (fillQAHistogram) { @@ -1003,25 +1144,25 @@ struct prefilterPrimaryElectron { } // end of loose positon loop for (const auto& pos : posTracks_per_coll) { - if (!checkTrack(collision, pos)) { // track cut is applied to loose sample - continue; - } + // if (!checkTrack(collision, pos)) { // track cut is applied to loose sample + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz - auto track_par_cov_recalc = getTrackParCov(pos); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + auto trackParCov = getTrackParCov(pos); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(track_par_cov_recalc, pVec_recalc); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(trackParCov, pVec_recalc); for (const auto& empos : positrons_per_coll) { if (empos.trackId() == pos.globalIndex()) { continue; } - ROOT::Math::PtEtaPhiMVector v1(empos.pt(), empos.eta(), empos.phi(), o2::constants::physics::MassElectron); // signal track - ROOT::Math::PtEtaPhiMVector v2(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); // loose track + ROOT::Math::PtEtaPhiMVector v1(empos.pt(), empos.eta(), empos.phi(), o2::constants::physics::MassElectron); // signal track + ROOT::Math::PtEtaPhiMVector v2(trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), o2::constants::physics::MassElectron); // loose track ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], empos.px(), empos.py(), empos.pz(), pos.sign(), empos.sign(), d_bz); if (fillQAHistogram) { @@ -1032,26 +1173,26 @@ struct prefilterPrimaryElectron { } // end of loose positon loop for (const auto& ele : negTracks_per_coll) { - if (!checkTrack(collision, ele)) { - continue; - } + // if (!checkTrack(collision, ele)) { + // continue; + // } o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); std::array pVec_recalc = {0, 0, 0}; // px, py, pz - auto track_par_cov_recalc = getTrackParCov(ele); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + auto trackParCov = getTrackParCov(ele); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - getPxPyPz(track_par_cov_recalc, pVec_recalc); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); + getPxPyPz(trackParCov, pVec_recalc); for (const auto& emele : electrons_per_coll) { if (emele.trackId() == ele.globalIndex()) { continue; } - ROOT::Math::PtEtaPhiMVector v1(track_par_cov_recalc.getPt(), track_par_cov_recalc.getEta(), track_par_cov_recalc.getPhi(), o2::constants::physics::MassElectron); // loose track - ROOT::Math::PtEtaPhiMVector v2(emele.pt(), emele.eta(), emele.phi(), o2::constants::physics::MassElectron); // signal track + ROOT::Math::PtEtaPhiMVector v1(trackParCov.getPt(), trackParCov.getEta(), trackParCov.getPhi(), o2::constants::physics::MassElectron); // loose track + ROOT::Math::PtEtaPhiMVector v2(emele.pt(), emele.eta(), emele.phi(), o2::constants::physics::MassElectron); // signal track ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(emele.px(), emele.py(), emele.pz(), pVec_recalc[0], pVec_recalc[1], pVec_recalc[2], emele.sign(), ele.sign(), d_bz); if (fillQAHistogram) { diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx index 2558b46cb3a..1f9456e9c96 100644 --- a/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryMuon.cxx @@ -12,36 +12,36 @@ /// \brief write relevant information for muons. /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" -#include "Math/SMatrix.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/DataModel/CollisionAssociationTables.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 "TGeoGlobalMagField.h" -#include "Field/MagneticField.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 "Common/Core/fwdtrackUtilities.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "Math/SMatrix.h" +#include "Math/Vector4D.h" +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -86,7 +86,7 @@ struct skimmerPrimaryMuon { 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", 50.f, "max. chi2 for global muon"}; + Configurable maxChi2GL{"maxChi2GL", 1e+6, "max. chi2 for global muon"}; Configurable refitGlobalMuon{"refitGlobalMuon", true, "flag to refit global muon"}; o2::ccdb::CcdbApi ccdbApi; @@ -117,7 +117,7 @@ struct skimmerPrimaryMuon { } mRunNumber = bc.runNumber(); - std::map metadata; + std::map metadata; auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, mRunNumber); auto ts = soreor.first; auto grpmag = ccdbApi.retrieveFromTFileAny(grpmagPath, metadata, ts); @@ -148,12 +148,11 @@ struct skimmerPrimaryMuon { 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", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/hChi2MFT", "chi2 MFT;chi2 MFT", kTH1F, {{100, 0.0f, 100}}, 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/hMatchScoreMCHMFT", "match score MCH-MFT;score", kTH1F, {{100, 0.0f, 100}}, false); - fRegistry.add("MFTMCHMID/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/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/hDCAxyinSigma", "DCAxy in sigma;DCA_{xy} (#sigma);", kTH1F, {{100, 0, 10}}, false); @@ -166,7 +165,7 @@ struct skimmerPrimaryMuon { 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); } - bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2, const uint8_t trackType, const float dcaXY) + 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) { if (pt < minPt || maxPt < pt) { return false; @@ -185,7 +184,7 @@ struct skimmerPrimaryMuon { if (maxDCAxy < dcaXY) { return false; } - if (chi2 < 0.f || maxChi2GL < chi2) { + if (maxChi2GL < chi2_per_ndf) { return false; } if (rAtAbsorberEnd < minRabsGL || maxRabs < rAtAbsorberEnd) { @@ -195,7 +194,7 @@ struct skimmerPrimaryMuon { if (eta < minEtaSA || maxEtaSA < eta) { return false; } - if (chi2 < 0.f || maxChi2SA < chi2) { + if (maxChi2SA < chi2_per_ndf) { return false; } } else { @@ -205,10 +204,10 @@ struct skimmerPrimaryMuon { return true; } - template - void fillFwdTrackTable(TCollision const& collision, TFwdTrack fwdtrack, TFwdTracks const&, TMFTTracks const&, const bool isAmbiguous) + template + void fillFwdTrackTable(TCollision const& collision, TFwdTrack fwdtrack, const bool isAmbiguous) { - if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && (fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT || fwdtrack.chi2() > maxChi2GL)) { + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { return; } // Users have to decide the best match between MFT and MCH-MID at analysis level. The same global muon is repeatedly stored. @@ -216,14 +215,17 @@ struct skimmerPrimaryMuon { return; } - o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, collision, propagationPoint::kToVertex); - o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(fwdtrack, collision, propagationPoint::kToDCA); + if (fwdtrack.chi2() < 0.f) { // this should never happen. only for protection. + return; + } + o2::dataformats::GlobalFwdTrack propmuonAtPV = propagateMuon(fwdtrack, collision, propagationPoint::kToVertex); float pt = propmuonAtPV.getPt(); float eta = propmuonAtPV.getEta(); float phi = propmuonAtPV.getPhi(); o2::math_utils::bringTo02Pi(phi); + o2::dataformats::GlobalFwdTrack propmuonAtDCA = propagateMuon(fwdtrack, collision, propagationPoint::kToDCA); float cXXatDCA = propmuonAtDCA.getSigma2X(); float cYYatDCA = propmuonAtDCA.getSigma2Y(); float cXYatDCA = propmuonAtDCA.getSigmaXY(); @@ -254,24 +256,44 @@ struct skimmerPrimaryMuon { // float tgl = fwdtrack.tgl(); float chi2mft = 0.f; uint64_t mftClusterSizesAndTrackFlags = 0; + int ndf_mchmft = 1; if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack) { + // apply r-absorber cut here to minimize the number of calling propagateMuon. + if (fwdtrack.rAtAbsorberEnd() < minRabsGL || maxRabs < fwdtrack.rAtAbsorberEnd()) { + return; + } + + // apply dca cut here to minimize the number of calling propagateMuon. + if (maxDCAxy < dcaXY) { + return; + } + const auto& mchtrack = fwdtrack.template matchMCHTrack_as(); // MCH-MID + const auto& mfttrack = fwdtrack.template matchMFTTrack_as(); // MFTsa + nClustersMFT = mfttrack.nClusters(); + mftClusterSizesAndTrackFlags = mfttrack.mftClusterSizesAndTrackFlags(); + ndf_mchmft = 2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f; + chi2mft = mfttrack.chi2(); + // chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); + + // apply chi2/ndf cut here to minimize the number of calling propagateMuon. + if (maxChi2GL < fwdtrack.chi2() / ndf_mchmft) { + return; + } + o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, collision, propagationPoint::kToVertex); ptMatchedMCHMID = propmuonAtPV_Matched.getPt(); etaMatchedMCHMID = propmuonAtPV_Matched.getEta(); phiMatchedMCHMID = propmuonAtPV_Matched.getPhi(); o2::math_utils::bringTo02Pi(phiMatchedMCHMID); + o2::dataformats::GlobalFwdTrack propmuonAtDCA_Matched = propagateMuon(mchtrack, collision, propagationPoint::kToDCA); 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; - const auto& mfttrack = fwdtrack.template matchMFTTrack_as(); - nClustersMFT = mfttrack.nClusters(); - mftClusterSizesAndTrackFlags = mfttrack.mftClusterSizesAndTrackFlags(); - chi2mft = mfttrack.chi2(); if (refitGlobalMuon) { eta = mfttrack.eta(); phi = mfttrack.phi(); @@ -292,7 +314,7 @@ struct skimmerPrimaryMuon { return; } - if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2(), fwdtrack.trackType(), dcaXY)) { + if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2() / ndf_mchmft, fwdtrack.trackType(), dcaXY)) { return; } @@ -340,11 +362,10 @@ struct skimmerPrimaryMuon { 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()); + fRegistry.fill(HIST("MFTMCHMID/hChi2"), fwdtrack.chi2() / ndf_mchmft); fRegistry.fill(HIST("MFTMCHMID/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); fRegistry.fill(HIST("MFTMCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); - fRegistry.fill(HIST("MFTMCHMID/hMatchScoreMCHMFT"), fwdtrack.matchScoreMCHMFT()); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MFTMCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); fRegistry.fill(HIST("MFTMCHMID/hDCAxy"), dcaXY); @@ -368,7 +389,6 @@ struct skimmerPrimaryMuon { fRegistry.fill(HIST("MCHMID/hChi2MFT"), chi2mft); fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMID"), fwdtrack.chi2MatchMCHMID()); fRegistry.fill(HIST("MCHMID/hChi2MatchMCHMFT"), fwdtrack.chi2MatchMCHMFT()); - fRegistry.fill(HIST("MCHMID/hMatchScoreMCHMFT"), fwdtrack.matchScoreMCHMFT()); fRegistry.fill(HIST("MCHMID/hDCAxy2D"), dcaX, dcaY); fRegistry.fill(HIST("MCHMID/hDCAxy2DinSigma"), dcaX / std::sqrt(cXXatDCA), dcaY / std::sqrt(cYYatDCA)); fRegistry.fill(HIST("MCHMID/hDCAxy"), dcaXY); @@ -380,15 +400,46 @@ struct skimmerPrimaryMuon { } } - SliceCache cache; + // std::map, float> mCandidates; // std::pair -> chi2MatchMCHMFT; + 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); + // mCandidates[tupleIds_at_min] = min_chi2MatchMCHMFT; + // 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 + } - PresliceUnsorted perMFTTrack = o2::aod::fwdtrack::matchMFTTrackId; + 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; - void processRec_SA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&) + void processRec_SA(MyCollisions 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); @@ -402,14 +453,24 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, false); + + 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; + } + + fillFwdTrackTable(collision, fwdtrack, false); } // end of fwdtrack loop } // end of collision loop + + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_SA, "process reconstructed info", false); - void processRec_TTCA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processRec_TTCA(MyCollisions const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) { + findBestMatchPerMCHMID(fwdtracks); + std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; for (const auto& fwdtrack : fwdtracks) { const auto& fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); @@ -431,15 +492,23 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, mapAmb[fwdtrack.globalIndex()]); + 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; + } + + fillFwdTrackTable(collision, fwdtrack, mapAmb[fwdtrack.globalIndex()]); } // end of fwdtrack loop } // end of collision loop mapAmb.clear(); + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA, "process reconstructed info", false); - void processRec_SA_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const& mfttracks, aod::BCsWithTimestamps const&) + 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); @@ -457,14 +526,22 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, false); + 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; + } + + fillFwdTrackTable(collision, fwdtrack, false); } // end of fwdtrack loop } // end of collision loop + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); } 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& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processRec_TTCA_SWT(MyCollisionsWithSWT const& collisions, MyFwdTracks const& fwdtracks, aod::MFTTracks const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) { + findBestMatchPerMCHMID(fwdtracks); + std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; for (const auto& fwdtrack : fwdtracks) { const auto& fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); @@ -488,15 +565,23 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, mapAmb[fwdtrack.globalIndex()]); + 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; + } + + fillFwdTrackTable(collision, fwdtrack, mapAmb[fwdtrack.globalIndex()]); } // end of fwdtrack loop } // end of collision loop mapAmb.clear(); + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryMuon, processRec_TTCA_SWT, "process reconstructed info", false); - void processMC_SA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const& mfttracks, aod::BCsWithTimestamps const&) + void processMC_SA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const&, aod::BCsWithTimestamps const&) { + findBestMatchPerMCHMID(fwdtracks); + for (const auto& collision : collisions) { const auto& bc = collision.template bc_as(); initCCDB(bc); @@ -515,14 +600,22 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, false); + 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; + } + + fillFwdTrackTable(collision, fwdtrack, false); } // end of fwdtrack loop } // end of collision loop + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryMuon, processMC_SA, "process reconstructed and MC info", false); - void processMC_TTCA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const& mfttracks, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) + void processMC_TTCA(soa::Join const& collisions, MyFwdTracksMC const& fwdtracks, MFTTracksMC const&, aod::BCsWithTimestamps const&, aod::FwdTrackAssoc const& fwdtrackIndices) { + findBestMatchPerMCHMID(fwdtracks); + std::unordered_map mapAmb; // fwdtrack.globalIndex() -> bool isAmb; for (const auto& fwdtrack : fwdtracks) { const auto& fwdtrackIdsPerFwdTrack = fwdtrackIndices.sliceBy(fwdtrackIndicesPerFwdTrack, fwdtrack.globalIndex()); @@ -549,10 +642,16 @@ struct skimmerPrimaryMuon { if (fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack && fwdtrack.trackType() != o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { continue; } - fillFwdTrackTable(collision, fwdtrack, fwdtracks, mfttracks, mapAmb[fwdtrack.globalIndex()]); + 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; + } + + fillFwdTrackTable(collision, fwdtrack, mapAmb[fwdtrack.globalIndex()]); } // end of fwdtrack loop } // end of collision loop mapAmb.clear(); + vec_min_chi2MatchMCHMFT.clear(); + vec_min_chi2MatchMCHMFT.shrink_to_fit(); } PROCESS_SWITCH(skimmerPrimaryMuon, processMC_TTCA, "process reconstructed and MC info", false); @@ -607,8 +706,8 @@ struct associateSameMFT { em_same_mft_ids(self_Ids); self_Ids.clear(); self_Ids.shrink_to_fit(); - } else { // for standalone muons - em_same_mft_ids(std::vector{}); // empty + } else { + em_same_mft_ids(std::vector{}); // empty for standalone muons } } // end of muon loop } diff --git a/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx new file mode 100644 index 00000000000..094065b6256 --- /dev/null +++ b/PWGEM/Dilepton/TableProducer/skimmerPrimaryTrack.cxx @@ -0,0 +1,469 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \brief write relevant information about primary tracks. +/// \author daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" + +#include "Common/Core/TableHelper.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/PIDResponse.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 +#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::pwgem::dilepton::utils::emtrackutil; + +using MyCollisions = soa::Join; +using MyCollisionsWithSWT = soa::Join; + +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; + + // Configurables + Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable mVtxPath{"mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; + + // Operation and minimisation criteria + Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; + Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; + + Configurable minpt{"minpt", 0.2, "min pt for ITS-TPC track"}; + Configurable maxpt{"maxpt", 5.0, "max pt for ITS-TPC track"}; + Configurable maxeta{"maxeta", 0.8, "eta acceptance"}; + Configurable dca_xy_max{"dca_xy_max", 1.0, "max DCAxy in cm"}; + Configurable dca_z_max{"dca_z_max", 1.0, "max DCAz in cm"}; + Configurable max_frac_shared_clusters_tpc{"max_frac_shared_clusters_tpc", 999.f, "max fraction of shared clusters in TPC"}; + + // Configurable min_ncluster_tpc{"min_ncluster_tpc", 0, "min ncluster tpc"}; + // Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; + // Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; + // Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; + // Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; + // Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; + // Configurable maxchi2its{"maxchi2its", 36.0, "max. chi2/NclsITS"}; + + HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + int mRunNumber; + float d_bz; + Service ccdb; + // o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + 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; + + void init(InitContext&) + { + mRunNumber = 0; + d_bz = 0; + + ccdb->setURL(ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + if (fillQAHistogram) { + fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); + fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{4000, -20, 20}}, 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/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); + fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); + fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); + fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); + fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); + fRegistry.add("Track/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{800, 0, 40}}, false); + fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); + fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + } + } + + 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(); + return; + } + + auto run3grp_timestamp = bc.timestamp(); + o2::parameters::GRPObject* grpo = 0x0; + o2::parameters::GRPMagField* grpmag = 0x0; + if (!skipGRPOquery) { + grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + } + if (grpo) { + o2::base::Propagator::initFieldFromGRP(grpo); + 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(); + } + + template + bool checkTrack(TCollision const& collision, TTrack const& track) + { + if constexpr (isMC) { + if (!track.has_mcParticle()) { + return false; + } + } + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + + if (track.itsChi2NCl() > 36.f) { + return false; + } + if (track.itsNCls() < 4) { + return false; + } + if (track.itsNClsInnerBarrel() < 1) { + return false; + } + + if (track.tpcChi2NCl() > 5.f) { + return false; + } + + if (track.tpcNClsFound() < 0) { + return false; + } + + if (track.tpcNClsCrossedRows() < 50) { + return false; + } + + if (track.tpcCrossedRowsOverFindableCls() < 0.8) { + return false; + } + + if (track.tpcFractionSharedCls() > max_frac_shared_clusters_tpc) { + return false; + } + + 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 (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; + } + + 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); + } + + 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); + } + + if (std::fabs(dcaZ) < 0.5) { + trackBit |= static_cast(RefTrackBit::kDCAz05cm); + } + if (std::fabs(dcaZ) < 0.3) { + trackBit |= static_cast(RefTrackBit::kDCAz03cm); + } + + if (std::fabs(dcaXY) < 0.5) { + trackBit |= static_cast(RefTrackBit::kDCAxy05cm); + } + if (std::fabs(dcaXY) < 0.3) { + trackBit |= static_cast(RefTrackBit::kDCAxy03cm); + } + + 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()); + } + } + } + + 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; + + // ---------- for data ---------- + + 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); + 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 + + 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); + + if (!collision.isSelected()) { + continue; + } + if (!collision.isEoI()) { // events with at least 1 lepton for data reduction. + 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 + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryTrack, processRec_SWT, "process reconstructed info only", false); // standalone with swt + + // ---------- for MC ---------- + + 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; + } + 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 + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryTrack, processMC, "process reconstructed and MC info ", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"skimmer-primary-track"})}; +} diff --git a/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx b/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx deleted file mode 100644 index 837fd99b3d4..00000000000 --- a/PWGEM/Dilepton/TableProducer/skimmerSecondaryElectron.cxx +++ /dev/null @@ -1,628 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -/// \brief write relevant information about primary electrons. -/// \author daiki.sekihata@cern.ch - -#include -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" - -using namespace o2; -using namespace o2::soa; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::constants::physics; - -using MyCollisions = soa::Join; -using MyCollisionsMC = soa::Join; - -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; -using MyTracksMC = soa::Join; -using MyTrackMC = MyTracksMC::iterator; - -struct skimmerSecondaryElectron { - // enum class EM_EEPairType : int { - // kULS = 0, - // kLSpp = +1, - // kLSmm = -1, - // }; - - SliceCache cache; - Preslice perCol = o2::aod::track::collisionId; - Produces emprimaryelectrons; - Produces emprimaryelectronscov; - Produces event; - Produces event_mult; - Produces event_cent; - - // Configurables - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; - - // Operation and minimisation criteria - Configurable fillQAHistogram{"fillQAHistogram", false, "flag to fill QA histograms"}; - Configurable d_bz_input{"d_bz_input", -999, "bz field in kG, -999 is automatic"}; - Configurable min_ncluster_tpc{"min_ncluster_tpc", 10, "min ncluster tpc"}; - Configurable mincrossedrows{"mincrossedrows", 70, "min. crossed rows"}; - Configurable min_tpc_cr_findable_ratio{"min_tpc_cr_findable_ratio", 0.8, "min. TPC Ncr/Nf ratio"}; - Configurable minitsncls{"minitsncls", 4, "min. number of ITS clusters"}; - Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; - Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt{"minpt", 0.15, "min pt for track"}; - Configurable maxeta{"maxeta", 0.9, "eta acceptance"}; - Configurable dca_xy_max{"dca_xy_max", 1.0f, "max DCAxy in cm"}; - Configurable dca_z_max{"dca_z_max", 1.0f, "max DCAz in cm"}; - Configurable dca_3d_sigma_max{"dca_3d_sigma_max", 1e+10, "max DCA 3D in sigma"}; - Configurable minTPCNsigmaEl{"minTPCNsigmaEl", -3.0, "min. TPC n sigma for electron inclusion"}; - Configurable maxTPCNsigmaEl{"maxTPCNsigmaEl", +4.0, "max. TPC n sigma for electron inclusion"}; - Configurable slope{"slope", 0.0185, "slope for m vs. phiv"}; - Configurable intercept{"intercept", -0.0280, "intercept for m vs. phiv"}; - Configurable mee_min{"mee_min", 0.0f, "minimum mee to distinguish photon conversion and dalitz decay"}; - - HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; - - std::pair> itsRequirement = {1, {0, 1, 2}}; // any hits on 3 ITS ib layers. - - int mRunNumber; - float d_bz; - Service ccdb; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - void init(InitContext&) - { - mRunNumber = 0; - d_bz = 0; - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - if (fillQAHistogram) { - fRegistry.add("Track/hPt", "pT;p_{T} (GeV/c)", kTH1F, {{1000, 0.0f, 10}}, false); - fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/hEtaPhi", "#eta vs. #varphi;#varphi (rad.);#eta", kTH2F, {{180, 0, 2 * M_PI}, {20, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); - fRegistry.add("Track/hDCAxyzSigma", "DCA xy vs. z;DCA_{xy} (#sigma);DCA_{z} (#sigma)", kTH2F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}}, false); - fRegistry.add("Track/hDCAxyRes_Pt", "DCA_{xy} resolution vs. pT;p_{T} (GeV/c);DCA_{xy} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/hDCAzRes_Pt", "DCA_{z} resolution vs. pT;p_{T} (GeV/c);DCA_{z} resolution (#mum)", kTH2F, {{1000, 0, 10}, {500, 0., 500}}, false); - fRegistry.add("Track/hNclsTPC", "number of TPC clusters", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/hNcrTPC", "number of TPC crossed rows", kTH1F, {{161, -0.5, 160.5}}, false); - fRegistry.add("Track/hChi2TPC", "chi2/number of TPC clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFbeta", "TOF beta;p_{in} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {600, 0, 1.2}}, false); - fRegistry.add("Track/h1overTOFbeta", "TOF beta;p_{in} (GeV/c);1/#beta", kTH2F, {{1000, 0, 10}, {1000, 0.8, 1.8}}, false); - fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTPCNcr2Nf", "TPC Ncr/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); - fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {32, 0, 16}}, false); - fRegistry.add("Pair/hMvsPhiV", "mee vs. phiv;#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2F, {{90, 0, M_PI}, {100, 0, 0.1}}, false); - } - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - o2::base::Propagator::initFieldFromGRP(&grpmag); - mRunNumber = bc.runNumber(); - return; - } - - auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = 0x0; - o2::parameters::GRPMagField* grpmag = 0x0; - if (!skipGRPOquery) - grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = bc.runNumber(); - } - - template - bool checkTrack(TTrack const& track) - { - if constexpr (isMC) { - if (!track.has_mcParticle()) { - return false; - } - } - - if (track.tpcChi2NCl() > maxchi2tpc) { - return false; - } - - if (track.itsChi2NCl() > maxchi2its) { - return false; - } - - if (!track.hasITS() || !track.hasTPC()) { - return false; - } - if (track.itsNCls() < minitsncls) { - return false; - } - - auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); - if (hits < itsRequirement.first) { - return false; - } - - if (track.tpcNClsFound() < min_ncluster_tpc) { - return false; - } - - if (track.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } - - if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { - return false; - } - - if (abs(track.dcaXY()) > dca_xy_max || abs(track.dcaZ()) > dca_z_max) { - return false; - } - - if (track.pt() < minpt || abs(track.eta()) > maxeta) { - return false; - } - - return true; - } - - template - void fillTrackTable(TCollision const& collision, TTrack const& track) - { - if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::pair{collision.globalIndex(), track.globalIndex()}) == stored_trackIds.end()) { - std::array dcaInfo; - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); - std::array pVec_recalc = {0, 0, 0}; // px, py, pz - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, track_par_cov_recalc, 2.f, matCorr, &dcaInfo); - getPxPyPz(track_par_cov_recalc, pVec_recalc); - float dcaXY = dcaInfo[0]; - float dcaZ = dcaInfo[1]; - - float pt_recalc = track_par_cov_recalc.getPt(); - float eta_recalc = track_par_cov_recalc.getEta(); - float phi_recalc = track_par_cov_recalc.getPhi(); - - bool isAssociatedToMPC = collision.globalIndex() == track.collisionId(); - - emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), - pt_recalc, eta_recalc, phi_recalc, dcaXY, dcaZ, - track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), - track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.itsClusterSizes(), 0, 0, 0, 0, 0, - track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), - track_par_cov_recalc.getX(), track_par_cov_recalc.getAlpha(), track_par_cov_recalc.getY(), track_par_cov_recalc.getZ(), track_par_cov_recalc.getSnp(), track_par_cov_recalc.getTgl(), isAssociatedToMPC); - - emprimaryelectronscov( - track_par_cov_recalc.getSigmaY2(), - track_par_cov_recalc.getSigmaZY(), - track_par_cov_recalc.getSigmaZ2(), - track_par_cov_recalc.getSigmaSnpY(), - track_par_cov_recalc.getSigmaSnpZ(), - track_par_cov_recalc.getSigmaSnp2(), - track_par_cov_recalc.getSigmaTglY(), - track_par_cov_recalc.getSigmaTglZ(), - track_par_cov_recalc.getSigmaTglSnp(), - track_par_cov_recalc.getSigmaTgl2(), - track_par_cov_recalc.getSigma1PtY(), - track_par_cov_recalc.getSigma1PtZ(), - track_par_cov_recalc.getSigma1PtSnp(), - track_par_cov_recalc.getSigma1PtTgl(), - track_par_cov_recalc.getSigma1Pt2()); - - stored_trackIds.emplace_back(std::pair{collision.globalIndex(), track.globalIndex()}); - - if (fillQAHistogram) { - uint32_t itsClusterSizes = track.itsClusterSizes(); - int total_cluster_size = 0, nl = 0; - for (unsigned int layer = 3; layer < 7; layer++) { - int cluster_size_per_layer = (itsClusterSizes >> (layer * 4)) & 0xf; - if (cluster_size_per_layer > 0) { - nl++; - } - total_cluster_size += cluster_size_per_layer; - } - - fRegistry.fill(HIST("Track/hPt"), pt_recalc); - fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / pt_recalc); - fRegistry.fill(HIST("Track/hEtaPhi"), phi_recalc, eta_recalc); - fRegistry.fill(HIST("Track/hDCAxyz"), dcaXY, dcaZ); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), dcaXY / sqrt(track_par_cov_recalc.getSigmaY2()), dcaZ / sqrt(track_par_cov_recalc.getSigmaZ2())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaY2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), pt_recalc, sqrt(track_par_cov_recalc.getSigmaZ2()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); - fRegistry.fill(HIST("Track/hTPCNcr2Nf"), track.tpcCrossedRowsOverFindableCls()); - fRegistry.fill(HIST("Track/hTPCNcls2Nf"), track.tpcFoundOverFindableCls()); - fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); - fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); - fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); - fRegistry.fill(HIST("Track/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); - fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); - fRegistry.fill(HIST("Track/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); - fRegistry.fill(HIST("Track/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.tpcInnerParam(), track.beta()); - fRegistry.fill(HIST("Track/h1overTOFbeta"), track.tpcInnerParam(), 1. / track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.tpcInnerParam(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaMu"), track.tpcInnerParam(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.tpcInnerParam(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.tpcInnerParam(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.tpcInnerParam(), track.tofNSigmaPr()); - } - } - } - - std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max; - Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; - using MyFilteredTracks = soa::Filtered; - - Partition posTracks = o2::aod::track::signed1Pt > 0.f; - Partition negTracks = o2::aod::track::signed1Pt < 0.f; - - // ---------- for data ---------- - - void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) - { - stored_trackIds.reserve(tracks.size()); - - for (auto& collision : collisions) { - auto bc = collision.bc_as(); - initCCDB(bc); - - if (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - continue; - } - - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample - - int npair = 0; - for (auto& [pos, neg] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - - if (!checkTrack(pos) || !checkTrack(neg)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float mee = v12.M(); - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), neg.px(), neg.py(), neg.pz(), pos.sign(), neg.sign(), d_bz); - - if (mee < mee_min || slope * phiv + intercept < mee) { // select phocon conversions - continue; - } - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/hMvsPhiV"), phiv, mee); - } - fillTrackTable(collision, pos); - fillTrackTable(collision, neg); - npair++; - } - - if (npair < 0.5) { - continue; - } - - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), bc.timestamp(), - collision.posX(), collision.posY(), collision.posZ(), - collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); - event_mult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - } - PROCESS_SWITCH(skimmerSecondaryElectron, processRec, "process reconstructed info only", true); // standalone - - // ---------- for MC ---------- - using MyFilteredTracksMC = soa::Filtered; - Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; - Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; - void processMC(MyCollisionsMC const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) - { - stored_trackIds.reserve(tracks.size()); - - for (auto& collision : collisions) { - if (!collision.has_mcCollision()) { - continue; - } - auto bc = collision.bc_as(); - initCCDB(bc); - - if (!collision.selection_bit(o2::aod::evsel::kIsTriggerTVX) || !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { - continue; - } - - auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample - auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); // loose track sample - - int npair = 0; - for (auto& [pos, neg] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { // ULS - if (!checkTrack(pos) || !checkTrack(neg)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float mee = v12.M(); - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), neg.px(), neg.py(), neg.pz(), pos.sign(), neg.sign(), d_bz); - - if (mee < mee_min || slope * phiv + intercept < mee) { // select phocon conversions - continue; - } - if (fillQAHistogram) { - fRegistry.fill(HIST("Pair/hMvsPhiV"), phiv, mee); - } - fillTrackTable(collision, pos); - fillTrackTable(collision, neg); - npair++; - } - - if (npair < 0.5) { - continue; - } - - event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), bc.timestamp(), - collision.posX(), collision.posY(), collision.posZ(), - collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); - event_mult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); - event_cent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); - } // end of collision loop - - stored_trackIds.clear(); - stored_trackIds.shrink_to_fit(); - } - PROCESS_SWITCH(skimmerSecondaryElectron, processMC, "process reconstructed and MC info ", false); -}; - -struct AssociateMCInfoSecondaryElectron { - Produces mcevents; - Produces mceventlabels; - Produces emmcparticles; - Produces emprimaryelectronmclabels; - - HistogramRegistry registry{"EMMCEvent"}; - void init(o2::framework::InitContext&) - { - auto hEventCounter = registry.add("hEventCounter", "hEventCounter", kTH1I, {{6, 0.5f, 6.5f}}); - hEventCounter->GetXaxis()->SetBinLabel(1, "all"); - hEventCounter->GetXaxis()->SetBinLabel(2, "has mc collision"); - } - - void processMC(MyCollisionsMC const& collisions, aod::McCollisions const&, aod::McParticles const& mcTracks, MyTracksMC const& o2tracks, aod::EMEvents const& emevents, aod::EMPrimaryElectrons const& emprimaryelectrons) - { - // temporary variables used for the indexing of the skimmed MC stack - std::map fNewLabels; - std::map fNewLabelsReversed; - // std::map fMCFlags; - std::map fEventIdx; - std::map fEventLabels; - int fCounters[2] = {0, 0}; //! [0] - particle counter, [1] - event counter - - for (auto& emevent : emevents) { - registry.fill(HIST("hEventCounter"), 1); - auto collision = collisions.iteratorAt(emevent.collisionId()); - auto mcCollision = collision.mcCollision(); - - if (!(fEventLabels.find(mcCollision.globalIndex()) != fEventLabels.end())) { - mcevents(mcCollision.globalIndex(), mcCollision.generatorsID(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.impactParameter(), mcCollision.eventPlaneAngle()); - fEventLabels[mcCollision.globalIndex()] = fCounters[1]; - fCounters[1]++; - } - - mceventlabels(fEventLabels.find(mcCollision.globalIndex())->second, collision.mcMask()); - } // end of reconstructed collision loop - - for (auto& emprimaryelectron : emprimaryelectrons) { - auto collision_from_el = collisions.iteratorAt(emprimaryelectron.collisionId()); - if (!collision_from_el.has_mcCollision()) { - continue; - } - auto mcCollision_from_el = collision_from_el.mcCollision(); - - auto o2track = o2tracks.iteratorAt(emprimaryelectron.trackId()); - if (!o2track.has_mcParticle()) { - continue; // If no MC particle is found, skip the dilepton - } - auto mctrack = o2track.template mcParticle_as(); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mctrack.globalIndex()) != fNewLabels.end())) { - fNewLabels[mctrack.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mctrack.globalIndex(); - // fMCFlags[mctrack.globalIndex()] = mcflags; - fEventIdx[mctrack.globalIndex()] = fEventLabels.find(mcCollision_from_el.globalIndex())->second; - fCounters[0]++; - } - emprimaryelectronmclabels(fNewLabels.find(mctrack.index())->second, o2track.mcMask()); - - // Next, store mother-chain of this reconstructed track. - int motherid = -999; // first mother index - if (mctrack.has_mothers()) { - motherid = mctrack.mothersIds()[0]; // first mother index - } - while (motherid > -1) { - if (motherid < mcTracks.size()) { // protect against bad mother indices. why is this needed? - auto mp = mcTracks.iteratorAt(motherid); - - // if the MC truth particle corresponding to this reconstructed track which is not already written, add it to the skimmed MC stack - if (!(fNewLabels.find(mp.globalIndex()) != fNewLabels.end())) { - fNewLabels[mp.globalIndex()] = fCounters[0]; - fNewLabelsReversed[fCounters[0]] = mp.globalIndex(); - // fMCFlags[mp.globalIndex()] = mcflags; - fEventIdx[mp.globalIndex()] = fEventLabels.find(mcCollision_from_el.globalIndex())->second; - fCounters[0]++; - } - - if (mp.has_mothers()) { - motherid = mp.mothersIds()[0]; // first mother index - } else { - motherid = -999; - } - } else { - motherid = -999; - } - } // end of mother chain loop - - } // end of em primary electron loop - - // Loop over the label map, create the mother/daughter relationships if these exist and write the skimmed MC stack - for (const auto& [newLabel, oldLabel] : fNewLabelsReversed) { - auto mctrack = mcTracks.iteratorAt(oldLabel); - // uint16_t mcflags = fMCFlags.find(oldLabel)->second; - - std::vector mothers; - if (mctrack.has_mothers()) { - for (auto& m : mctrack.mothersIds()) { - if (m < mcTracks.size()) { // protect against bad mother indices - if (fNewLabels.find(m) != fNewLabels.end()) { - mothers.push_back(fNewLabels.find(m)->second); - } - } else { - std::cout << "Mother label (" << m << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; - std::cout << " Check the MC generator" << std::endl; - } - } - } - - // Note that not all daughters from the original table are preserved in the skimmed MC stack - std::vector daughters; - if (mctrack.has_daughters()) { - // int ndau = mctrack.daughtersIds()[1] - mctrack.daughtersIds()[0] + 1; - // LOGF(info, "daughter range in original MC stack pdg = %d | %d - %d , n dau = %d", mctrack.pdgCode(), mctrack.daughtersIds()[0], mctrack.daughtersIds()[1], mctrack.daughtersIds()[1] -mctrack.daughtersIds()[0] +1); - for (int d = mctrack.daughtersIds()[0]; d <= mctrack.daughtersIds()[1]; ++d) { - // TODO: remove this check as soon as issues with MC production are fixed - if (d < mcTracks.size()) { // protect against bad daughter indices - // auto dau_tmp = mcTracks.iteratorAt(d); - // // LOGF(info, "daughter pdg = %d", dau_tmp.pdgCode()); - // if ((mctrack.pdgCode() == 223 || mctrack.pdgCode() == 333) && (mctrack.isPhysicalPrimary() || mctrack.producedByGenerator())) { - // if (fNewLabels.find(d) == fNewLabels.end() && (abs(dau_tmp.pdgCode()) == 11 || abs(dau_tmp.pdgCode()) == 13)) { - // LOGF(info, "daughter lepton is not found mctrack.globalIndex() = %d, mctrack.producedByGenerator() == %d, ndau = %d | dau_tmp.globalIndex() = %d, dau_tmp.pdgCode() = %d, dau_tmp.producedByGenerator() = %d, dau_tmp.pt() = %f, dau_tmp.eta() = %f, dau_tmp.phi() = %f", mctrack.globalIndex(), mctrack.producedByGenerator(), ndau, dau_tmp.globalIndex(), dau_tmp.pdgCode(), dau_tmp.producedByGenerator(), dau_tmp.pt(), dau_tmp.eta(), dau_tmp.phi()); - // } - // } - - if (fNewLabels.find(d) != fNewLabels.end()) { - daughters.push_back(fNewLabels.find(d)->second); - } - } else { - std::cout << "Daughter label (" << d << ") exceeds the McParticles size (" << mcTracks.size() << ")" << std::endl; - std::cout << " Check the MC generator" << std::endl; - } - } - } - - emmcparticles(fEventIdx.find(oldLabel)->second, mctrack.pdgCode(), mctrack.flags(), - mothers, daughters, - mctrack.px(), mctrack.py(), mctrack.pz(), mctrack.e(), - mctrack.vx(), mctrack.vy(), mctrack.vz()); - - mothers.clear(); - mothers.shrink_to_fit(); - daughters.clear(); - daughters.shrink_to_fit(); - } // end loop over labels - - fNewLabels.clear(); - fNewLabelsReversed.clear(); - // fMCFlags.clear(); - fEventIdx.clear(); - fEventLabels.clear(); - fCounters[0] = 0; - fCounters[1] = 0; - } - - void processDummy(MyCollisions const&) {} - - PROCESS_SWITCH(AssociateMCInfoSecondaryElectron, processMC, "create em mc event table for Electron", false); - PROCESS_SWITCH(AssociateMCInfoSecondaryElectron, processDummy, "processDummy", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"skimmer-secondary-electron"}), - adaptAnalysisTask(cfgc, TaskName{"associate-mc-info-secondary-electron"}), - }; -} diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx index 7643f79a984..51b21a6439c 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronML.cxx @@ -14,33 +14,37 @@ // This code will create data table for inputs to machine learning for electrons. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include -#include -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" + #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "DCAFitter/DCAFitterN.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.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 using namespace o2; using namespace o2::framework; @@ -96,8 +100,8 @@ DECLARE_SOA_TABLE(MyTracks, "AOD", "MYTRACK", //! track::DcaXY, track::DcaZ, mytrack::DCAresXY, mytrack::DCAresZ, track::CZY, track::TPCNClsFindable, mytrack::TPCNClsFound, mytrack::TPCNClsCrossedRows, track::TPCChi2NCl, track::TPCInnerParam, - track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaMu, pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, - pidtofbeta::Beta, pidtof::TOFNSigmaEl, pidtof::TOFNSigmaMu, pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, + track::TPCSignal, pidtpc::TPCNSigmaEl, /*pidtpc::TPCNSigmaMu,*/ pidtpc::TPCNSigmaPi, pidtpc::TPCNSigmaKa, pidtpc::TPCNSigmaPr, + pidtofbeta::Beta, pidtof::TOFNSigmaEl, /*pidtof::TOFNSigmaMu,*/ pidtof::TOFNSigmaPi, pidtof::TOFNSigmaKa, pidtof::TOFNSigmaPr, track::TOFChi2, track::ITSChi2NCl, track::ITSClusterSizes, mytrack::MCVx, mytrack::MCVy, mytrack::MCVz, mcparticle::PdgCode, mytrack::IsPhysicalPrimary, mytrack::MotherIds, mytrack::MotherPdgCodes); @@ -547,7 +551,7 @@ struct TreeCreatorElectronML { } } - template + template void doSingleTrack(TTrack& track, TMCParticle& mctrack, TMCParticles& mctracks, uint64_t collisionId, std::vector& collisions_old_labels, int& collisions_counter, bool use_downsample = true) { if (!IsSelected(track)) { @@ -580,15 +584,28 @@ struct TreeCreatorElectronML { collisions_counter++; collisions_old_labels.push_back(collisionId); } - mytrack(collisions_counter, - track.sign(), track.pt(), track.eta(), track.phi(), track.tgl(), track.dcaXY(), track.dcaZ(), sqrt(track.cYY()), sqrt(track.cZZ()), track.cZY(), - track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), - track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.tofChi2(), track.itsChi2NCl(), track.itsClusterSizes(), - mctrack.vx(), mctrack.vy(), mctrack.vz(), - mctrack.pdgCode(), mctrack.isPhysicalPrimary(), mothers_id, mothers_pdg); + + if constexpr (isDerived) { + mytrack(collisions_counter, + track.sign(), track.pt(), track.eta(), track.phi(), track.tgl(), track.dcaXY(), track.dcaZ(), sqrt(track.cYY()), sqrt(track.cZZ()), track.cZY(), + track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), /*track.tpcNSigmaMu(),*/ track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), /*track.tofNSigmaMu(),*/ 0, 0, 0, + track.tofChi2(), track.itsChi2NCl(), track.itsClusterSizes(), + mctrack.vx(), mctrack.vy(), mctrack.vz(), + mctrack.pdgCode(), mctrack.isPhysicalPrimary(), mothers_id, mothers_pdg); + } else { + mytrack(collisions_counter, + track.sign(), track.pt(), track.eta(), track.phi(), track.tgl(), track.dcaXY(), track.dcaZ(), sqrt(track.cYY()), sqrt(track.cZZ()), track.cZY(), + track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), /*track.tpcNSigmaMu(),*/ track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), /*track.tofNSigmaMu(),*/ track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.tofChi2(), track.itsChi2NCl(), track.itsClusterSizes(), + mctrack.vx(), mctrack.vy(), mctrack.vz(), + mctrack.pdgCode(), mctrack.isPhysicalPrimary(), mothers_id, mothers_pdg); + } mothers_id.shrink_to_fit(); mothers_pdg.shrink_to_fit(); @@ -634,7 +651,7 @@ struct TreeCreatorElectronML { continue; } auto mctrack = track.mcParticle_as(); - doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels, collisions_counter); + doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels, collisions_counter); } } @@ -647,7 +664,7 @@ struct TreeCreatorElectronML { } PROCESS_SWITCH(TreeCreatorElectronML, processSingleTrack, "produce ML input for single track level", false); - using MyFilteredCollisionsSkimmed = soa::Filtered>; + using MyFilteredCollisionsSkimmed = soa::Filtered>; using MyFilteredTracksMCSkimmed = soa::Filtered>; Preslice perCollisionSkimmed = aod::emprimaryelectron::emeventId; @@ -668,7 +685,7 @@ struct TreeCreatorElectronML { continue; } auto mctrack = track.emmcparticle_as(); - doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels, collisions_counter); + doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels, collisions_counter); } } @@ -732,7 +749,7 @@ struct TreeCreatorElectronML { auto track = tracks.rawIteratorAt(track_label); auto mctrack = track.mcParticle_as(); - doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels, collisions_counter, false); + doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels, collisions_counter, false); } // end of track loop @@ -804,7 +821,7 @@ struct TreeCreatorElectronML { auto track = tracks.rawIteratorAt(track_label); auto mctrack = track.emmcparticle_as(); - doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels_track, collisions_counter_track, false); + doSingleTrack(track, mctrack, mctracks, collision.globalIndex(), collisions_old_labels_track, collisions_counter_track, false); } // end of track loop diff --git a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx index a24b62374f8..81e914de7bb 100644 --- a/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx +++ b/PWGEM/Dilepton/TableProducer/treeCreatorElectronMLDDA.cxx @@ -14,36 +14,40 @@ // This code will create data table for inputs to machine learning for electrons. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include -#include -#include "Math/Vector4D.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" +#include "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/RCTSelectionFlags.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" +#include "DCAFitter/DCAFitterN.h" #include "DataFormatsCalibration/MeanVertexObject.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGEM/Dilepton/DataModel/lmeeMLTables.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.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 using namespace o2; using namespace o2::framework; @@ -54,14 +58,14 @@ using namespace o2::constants::physics; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; struct TreeCreatorElectronMLDDA { SliceCache cache; - Produces emprimarytracks; // flat table containing collision + track information + Produces emprimarytracks; // flat table containing collision + track information // Basic checks HistogramRegistry registry{ @@ -72,40 +76,34 @@ struct TreeCreatorElectronMLDDA { {"V0/hXY_Gamma", "photon conversion point in XY;X (cm);Y (cm)", {HistType::kTH2F, {{400, -100, +100}, {400, -100, +100}}}}, {"V0/hMassGamma_Rxy", "V0 mass gamma", {HistType::kTH2F, {{200, 0, 100}, {100, 0, 0.1}}}}, {"V0/hCosPA", "V0 cosine of pointing angle", {HistType::kTH1F, {{100, 0.99, 1.f}}}}, - {"V0/hPCA", "V0 distance between 2 legs", {HistType::kTH1F, {{200, 0.f, 2.f}}}}, + {"V0/hPCA", "V0 distance between 2 legs", {HistType::kTH1F, {{50, 0.f, 0.5f}}}}, {"V0/hMassGamma", "V0 mass gamma", {HistType::kTH1F, {{100, 0, 0.1}}}}, {"V0/hMassK0Short", "V0 mass K0S", {HistType::kTH1F, {{200, 0.4, 0.6}}}}, {"V0/hMassLambda", "V0 mass Lambda", {HistType::kTH1F, {{100, 1.08, 1.18}}}}, {"V0/hMassAntiLambda", "V0 mass AntiLambda", {HistType::kTH1F, {{100, 1.08, 1.18}}}}, - {"hMvsPhiV", "mee vs. phiv", {HistType::kTH2F, {{72, 0, M_PI}, {100, 0, 0.1}}}}, - {"V0/hTPCdEdx_P_El", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Mu", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Pi", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Ka", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - {"V0/hTPCdEdx_P_Pr", "TPC dEdx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, - - {"V0/hTOFbeta_P_El", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Mu", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Pi", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Ka", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, - {"V0/hTOFbeta_P_Pr", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"V0/hTPCdEdx_P_El", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTPCdEdx_P_Pi", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTPCdEdx_P_Ka", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTPCdEdx_P_Pr", "TPC dEdx vs. p;p_{in} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0, 5}, {200, 0, 200}}}}, + {"V0/hTOFbeta_P_El", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"V0/hTOFbeta_P_Pi", "TOF beta vs. p;p_{in} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0, 5}, {220, 0, 1.1}}}}, + {"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/hV0CosPA", "V0 cosine of pointing angle", {HistType::kTH1F, {{50, 0.95, 1.f}}}}, - {"Cascade/hV0PCA", "V0 distance between 2 legs", {HistType::kTH1F, {{200, 0.f, 2.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}}}}, - {"Cascade/hPCA", "cascade distance between 2 legs", {HistType::kTH1F, {{200, 0.f, 2.f}}}}, + {"Cascade/hPCA", "cascade distance between 2 legs", {HistType::kTH1F, {{50, 0.f, 0.5}}}}, {"Cascade/hMassLambda", "V0 mass Lambda in cascade", {HistType::kTH1F, {{100, 1.08, 1.18}}}}, {"Cascade/hMassXi", "cascade mass #Xi", {HistType::kTH1F, {{200, 1.2, 1.4}}}}, {"Cascade/hMassOmega", "cascade mass #Omega", {HistType::kTH1F, {{200, 1.6, 1.8}}}}, {"Cascade/hMassPt_Xi", "cascade mass #Xi^{#pm};m_{#Lambda#pi} (GeV/c^{2});p_{T,#Lambda#pi} (GeV/c)", {HistType::kTH2F, {{200, 1.2, 1.4}, {100, 0, 10}}}}, - {"Cascade/hMassPt_Xi_bachelor", "cascade mass #Xi^{#pm};m_{#Lambda#pi} (GeV/c^{2});p_{T,#pi} (GeV/c)", {HistType::kTH2F, {{200, 1.2, 1.4}, {100, 0, 10}}}}, {"Cascade/hMassPt_Omega", "cascade mass #Omega^{#pm};m_{#LambdaK} (GeV/c^{2});p_{T,#LambdaK} (GeV/c)", {HistType::kTH2F, {{200, 1.6, 1.8}, {100, 0, 10}}}}, - {"Cascade/hMassPt_Omega_bachelor", "cascade mass #Omega^{#pm};m_{#LambdaK} (GeV/c^{2});p_{T,K} (GeV/c)", {HistType::kTH2F, {{200, 1.6, 1.8}, {100, 0, 10}}}}, }, }; @@ -119,21 +117,50 @@ struct TreeCreatorElectronMLDDA { Configurable skipGRPOquery{"skipGRPOquery", true, "skip grpo query"}; // Operation and minimisation criteria Configurable d_bz_input{"d_bz_input", -999, "bz field, -999 is automatic"}; - Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; - - Configurable downscaling_electron_primary{"downscaling_electron_primary", 1.1, "down scaling factor to store primary electron for validation"}; - Configurable downscaling_electron{"downscaling_electron", 0.005, "down scaling factor to store electron"}; - Configurable downscaling_pion{"downscaling_pion", 0.001, "down scaling factor to store pion"}; - Configurable downscaling_kaon{"downscaling_kaon", 1.1, "down scaling factor to store kaon"}; - Configurable downscaling_proton{"downscaling_proton", 0.005, "down scaling factor to store proton"}; - - Configurable max_pin_for_downscaling_electron_primary{"max_pin_for_downscaling_electron_primary", 0.0, "max pin to apply down scaling factor to store primary electron for validation"}; - Configurable max_pin_for_downscaling_electron{"max_pin_for_downscaling_electron", 2.0, "max pin to apply down scaling factor to store electron"}; - Configurable max_pin_for_downscaling_pion{"max_pin_for_downscaling_pion", 2.0, "max pin to apply down scaling factor to store pion"}; - Configurable max_pin_for_downscaling_kaon{"max_pin_for_downscaling_kaon", 0.0, "max pin to apply down scaling factor to store kaon"}; - Configurable max_pin_for_downscaling_proton{"max_pin_for_downscaling_proton", 2.0, "max pin to apply down scaling factor to store proton"}; + Configurable useMatCorrType{"useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; + + Configurable downscaling_electron_highP{"downscaling_electron_highP", 1.1, "down scaling factor to store electron at high p"}; + Configurable downscaling_pion_highP{"downscaling_pion_highP", 1.1, "down scaling factor to store pion at high p"}; + Configurable downscaling_kaon_highP{"downscaling_kaon_highP", 1.1, "down scaling factor to store kaon at high p"}; + Configurable downscaling_proton_highP{"downscaling_proton_highP", 1.1, "down scaling factor to store proton at high p"}; + + Configurable downscaling_electron_lowP{"downscaling_electron_lowP", 0.01, "down scaling factor to store electron at low p"}; + Configurable downscaling_pion_lowP{"downscaling_pion_lowP", 0.01, "down scaling factor to store pion at low p"}; + Configurable downscaling_kaon_lowP{"downscaling_kaon_lowP", 1.1, "down scaling factor to store kaon at low p"}; + Configurable downscaling_proton_lowP{"downscaling_proton_lowP", 0.01, "down scaling factor to store proton at low p"}; + + Configurable max_p_for_downscaling_electron{"max_p_for_downscaling_electron", 2.0, "max p to apply down scaling factor to store electron"}; + Configurable max_p_for_downscaling_pion{"max_p_for_downscaling_pion", 2.0, "max p to apply down scaling factor to store pion"}; + 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"}; + 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 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 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 = "trackcut_group"; Configurable cfg_min_pt{"cfg_min_pt", 0.05, "min pt for v0 legs"}; @@ -144,8 +171,8 @@ struct TreeCreatorElectronMLDDA { Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 4, "min ncluster its"}; Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 1, "min ncluster itsib"}; - Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 5.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 6.0, "max chi2/NclsITS"}; + Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 5.0, "max chi2/NclsTPC"}; // comment + Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z in cm"}; } trackcuts; @@ -158,10 +185,16 @@ struct TreeCreatorElectronMLDDA { Configurable cfg_max_mass_photon{"cfg_max_mass_photon", 0.02, "max mass for photon conversion"}; Configurable cfg_min_mass_k0s{"cfg_min_mass_k0s", 0.490, "min mass for K0S"}; Configurable cfg_max_mass_k0s{"cfg_max_mass_k0s", 0.505, "max mass for K0S"}; - Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.11, "min mass for Lambda rejection"}; - Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.12, "max mass for Lambda rejection"}; - Configurable cfg_min_cospa{"cfg_min_cospa", 0.999, "min cospa for v0"}; - Configurable cfg_max_dcadau{"cfg_max_dcadau", 0.5, "max distance between 2 legs for v0"}; + Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.113, "min mass for Lambda"}; + Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.118, "max mass for Lambda"}; + + Configurable cfg_min_mass_k0s_veto{"cfg_min_mass_k0s_veto", 0.47, "min mass for K0S veto"}; + Configurable cfg_max_mass_k0s_veto{"cfg_max_mass_k0s_veto", 0.52, "max mass for K0S veto"}; + Configurable cfg_min_mass_lambda_veto{"cfg_min_mass_lambda_veto", 1.105, "min mass for Lambda veto"}; + Configurable cfg_max_mass_lambda_veto{"cfg_max_mass_lambda_veto", 1.125, "max mass for Lambda veto"}; + + Configurable cfg_min_cospa{"cfg_min_cospa", 0.9998, "min cospa for v0"}; + Configurable cfg_max_dcadau{"cfg_max_dcadau", 0.1, "max distance between 2 legs for v0"}; Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 0.8, "min. TPC Ncr/Nf ratio"}; Configurable cfg_max_frac_shared_clusters_tpc{"cfg_max_frac_shared_clusters_tpc", 0.7, "max fraction of shared clusters in TPC"}; Configurable cfg_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 70, "min ncrossed rows"}; @@ -169,26 +202,30 @@ struct TreeCreatorElectronMLDDA { Configurable cfg_min_ncluster_its{"cfg_min_ncluster_its", 2, "min ncluster its"}; Configurable cfg_min_ncluster_itsib{"cfg_min_ncluster_itsib", 0, "min ncluster itsib"}; Configurable cfg_max_chi2tpc{"cfg_max_chi2tpc", 5.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 6.0, "max chi2/NclsITS"}; - Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; - - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -4, "min n sigma e in TPC"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +4, "max n sigma e in TPC"}; - Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -4, "min n sigma pi in TPC"}; - Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +4, "max n sigma pi in TPC"}; - Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -4, "min n sigma ka in TPC"}; - Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +4, "max n sigma ka in TPC"}; - Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -4, "min n sigma pr in TPC"}; - Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +4, "max n sigma pr in TPC"}; - - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -4, "min n sigma e in TOF"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +4, "max n sigma e in TOF"}; - Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -4, "min n sigma pi in TOF"}; - Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +4, "max n sigma pi in TOF"}; - Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -4, "min n sigma ka in TOF"}; - Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +4, "max n sigma ka in TOF"}; - Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -4, "min n sigma pr in TOF"}; - Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +4, "max n sigma pr in TOF"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.0, "max chi2/NclsITS"}; + 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_qt_strangeness{"cfg_min_qt_strangeness", 0.015, "min qt for Lambda and K0S"}; + Configurable cfg_require_collinearV0{"cfg_require_collinearV0", false, "require collinear V0 for photon conversions"}; + + 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"}; + Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -5, "min n sigma pi in TPC"}; + Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +5, "max n sigma pi in TPC"}; + Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -5, "min n sigma ka in TPC"}; + Configurable cfg_max_TPCNsigmaKa{"cfg_max_TPCNsigmaKa", +5, "max n sigma ka in TPC"}; + Configurable cfg_min_TPCNsigmaPr{"cfg_min_TPCNsigmaPr", -5, "min n sigma pr in TPC"}; + Configurable cfg_max_TPCNsigmaPr{"cfg_max_TPCNsigmaPr", +5, "max n sigma pr in TPC"}; + + Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -5, "min n sigma e in TOF"}; + Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +5, "max n sigma e in TOF"}; + Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -5, "min n sigma pi in TOF"}; + Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +5, "max n sigma pi in TOF"}; + Configurable cfg_min_TOFNsigmaKa{"cfg_min_TOFNsigmaKa", -5, "min n sigma ka in TOF"}; + Configurable cfg_max_TOFNsigmaKa{"cfg_max_TOFNsigmaKa", +5, "max n sigma ka in TOF"}; + Configurable cfg_min_TOFNsigmaPr{"cfg_min_TOFNsigmaPr", -5, "min n sigma pr in TOF"}; + Configurable cfg_max_TOFNsigmaPr{"cfg_max_TOFNsigmaPr", +5, "max n sigma pr in TOF"}; Configurable cfg_min_TPCNsigmaEl_tight{"cfg_min_TPCNsigmaEl_tight", -2, "min n sigma e in TPC for pi0->eeg"}; Configurable cfg_max_TPCNsigmaEl_tight{"cfg_max_TPCNsigmaEl_tight", +2, "max n sigma e in TPC for pi0->eeg"}; @@ -210,31 +247,23 @@ struct TreeCreatorElectronMLDDA { std::string prefix = "cascadecut_group"; Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.11, "min mass for lambda in cascade"}; Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.12, "max mass for lambda in cascade"}; - Configurable cfg_min_mass_Xi{"cfg_min_mass_Xi", 1.317, "min mass for Xi"}; - Configurable cfg_max_mass_Xi{"cfg_max_mass_Xi", 1.327, "max mass for Xi"}; - Configurable cfg_min_mass_Omega{"cfg_min_mass_Omega", 1.667, "min mass for Omega"}; - Configurable cfg_max_mass_Omega{"cfg_max_mass_Omega", 1.677, "max mass for Omega"}; - Configurable cfg_min_cospa_v0{"cfg_min_cospa_v0", 0.97, "minimum V0 CosPA in cascade"}; - Configurable cfg_max_dcadau_v0{"cfg_max_dcadau_v0", 0.2, "max distance between V0 Daughters in cascade"}; - Configurable cfg_min_cospa{"cfg_min_cospa", 0.999, "minimum cascade CosPA"}; - Configurable cfg_max_dcadau{"cfg_max_dcadau", 0.4, "max distance between bachelor and V0"}; + Configurable cfg_min_mass_Xi_veto{"cfg_min_mass_Xi_veto", 1.31, "min mass for Xi veto"}; + Configurable cfg_max_mass_Xi_veto{"cfg_max_mass_Xi_veto", 1.33, "max mass for Xi veto"}; + Configurable cfg_min_mass_Omega{"cfg_min_mass_Omega", 1.669, "min mass for Omega"}; + Configurable cfg_max_mass_Omega{"cfg_max_mass_Omega", 1.675, "max mass for Omega"}; + Configurable cfg_min_cospa_v0{"cfg_min_cospa_v0", 0.995, "minimum V0 CosPA in cascade"}; + Configurable cfg_max_dcadau_v0{"cfg_max_dcadau_v0", 0.1, "max distance between V0 Daughters in cascade"}; + Configurable cfg_min_cospa{"cfg_min_cospa", 0.9998, "minimum cascade CosPA"}; + Configurable cfg_max_dcadau{"cfg_max_dcadau", 0.1, "max distance between bachelor and V0"}; Configurable cfg_min_rxy_v0{"cfg_min_rxy_v0", 1.2, "minimum V0 rxy in cascade"}; Configurable cfg_min_rxy{"cfg_min_rxy", 0.5, "minimum V0 rxy in cascade"}; Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; Configurable cfg_min_dcaxy_bachelor{"cfg_min_dcaxy_bachelor", 0.1, "min dca XY for bachelor in cm"}; } cascadecuts; - struct : ConfigurableGroup { - std::string prefix = "dalitzcut_group"; - Configurable cfg_min_mass_ee{"cfg_min_mass_ee", 0.000, "min mass for ee from pi0 dalitz decay in GeV/c2"}; - Configurable cfg_max_mass_ee{"cfg_max_mass_ee", 0.005, "max mass for ee from pi0 dalitz decay in GeV/c2"}; - Configurable cfg_min_phiv_ee{"cfg_min_phiv_ee", 0.0, "min phiv for ee from pi0 dalitz decay in rad."}; - Configurable cfg_max_phiv_ee{"cfg_max_phiv_ee", M_PI / 2, "max phiv for ee from pi0 dalitz decay in rad."}; - } dalitzcuts; - // for RCT Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_hadronPID", "select 1 [CBT, CBT_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + 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"}; @@ -355,7 +384,7 @@ struct TreeCreatorElectronMLDDA { template bool isSelectedTrack(TCollision const& collision, TTrack const& track) { - if (!track.hasITS() || !track.hasTPC()) { + if (!track.hasITS()) { return false; } @@ -369,35 +398,37 @@ struct TreeCreatorElectronMLDDA { return false; } - if (track.tpcNClsCrossedRows() < trackcuts.cfg_min_ncrossedrows_tpc) { - return false; - } - if (track.tpcNClsFound() < trackcuts.cfg_min_ncluster_tpc) { - return false; - } - if (track.tpcChi2NCl() > trackcuts.cfg_max_chi2tpc) { - return false; - } - if (track.tpcCrossedRowsOverFindableCls() < trackcuts.cfg_min_cr2findable_ratio_tpc) { + if (!v0cuts.cfg_includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcFractionSharedCls() > trackcuts.cfg_max_frac_shared_clusters_tpc) { - return false; + + if (track.hasTPC()) { + if (track.tpcNClsCrossedRows() < trackcuts.cfg_min_ncrossedrows_tpc) { + return false; + } + if (track.tpcNClsFound() < trackcuts.cfg_min_ncluster_tpc) { + return false; + } + if (track.tpcChi2NCl() > trackcuts.cfg_max_chi2tpc) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < trackcuts.cfg_min_cr2findable_ratio_tpc) { + return false; + } + if (track.tpcFractionSharedCls() > trackcuts.cfg_max_frac_shared_clusters_tpc) { + return false; + } } mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(track.pidForTracking()); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - if (std::fabs(track_par_cov_recalc.getEta()) > trackcuts.cfg_max_eta || track_par_cov_recalc.getPt() < trackcuts.cfg_min_pt) { - return false; - } - if (std::fabs(dcaXY) > trackcuts.cfg_max_dcaxy) { return false; } @@ -405,13 +436,20 @@ struct TreeCreatorElectronMLDDA { return false; } + if (std::fabs(trackParCov.getEta()) > trackcuts.cfg_max_eta || trackParCov.getPt() < trackcuts.cfg_min_pt) { + return false; + } + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && v0cuts.cfg_max_pt_itssa < trackParCov.getPt()) { + return true; + } + return true; } template bool isSelectedV0Leg(TCollision const& collision, TTrack const& track) { - if (!track.hasITS() || !track.hasTPC()) { + if (!track.hasITS()) { return false; } @@ -425,45 +463,58 @@ struct TreeCreatorElectronMLDDA { return false; } - 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) { + if (!v0cuts.cfg_includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcFractionSharedCls() > v0cuts.cfg_max_frac_shared_clusters_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; + } } mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(track.pidForTracking()); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); // float dcaZ = mDcaInfoCov.getZ(); - if (std::fabs(track_par_cov_recalc.getEta()) > v0cuts.cfg_max_eta || track_par_cov_recalc.getPt() < v0cuts.cfg_min_pt) { + if (std::fabs(dcaXY) < v0cuts.cfg_min_dcaxy_v0leg) { // this is applied in filter. return false; } - if (std::fabs(dcaXY) < v0cuts.cfg_min_dcaxy_v0leg) { // this is applied in filter. + if (std::fabs(trackParCov.getEta()) > v0cuts.cfg_max_eta || trackParCov.getPt() < v0cuts.cfg_min_pt) { return false; } + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && v0cuts.cfg_max_pt_itssa < track.pt()) { + return true; + } + return true; } template bool isElectron(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } 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 return is_El_TPC && is_El_TOF; @@ -472,6 +523,9 @@ struct TreeCreatorElectronMLDDA { template bool isPion(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } 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 return is_Pi_TPC && is_Pi_TOF; @@ -480,6 +534,9 @@ struct TreeCreatorElectronMLDDA { template bool isKaon(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } 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 return is_Ka_TPC && is_Ka_TOF; @@ -488,6 +545,9 @@ struct TreeCreatorElectronMLDDA { template bool isProton(TTrack const& track) { + if (v0cuts.cfg_includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + return true; + } 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 return is_Pr_TPC && is_Pr_TOF; @@ -497,7 +557,7 @@ struct TreeCreatorElectronMLDDA { bool isElectronTight(TTrack const& track) { bool is_El_TPC = v0cuts.cfg_min_TPCNsigmaEl_tight < track.tpcNSigmaEl() && track.tpcNSigmaEl() < v0cuts.cfg_max_TPCNsigmaEl_tight; - bool is_El_TOF = track.hasTOF() && (v0cuts.cfg_min_TOFNsigmaEl_tight < track.tofNSigmaEl() && track.tofNSigmaEl() < v0cuts.cfg_max_TOFNsigmaEl_tight); // TOFreq + bool is_El_TOF = track.hasTOF() ? v0cuts.cfg_min_TOFNsigmaEl_tight < track.tofNSigmaEl() && track.tofNSigmaEl() < v0cuts.cfg_max_TOFNsigmaEl_tight : true; // TOFif return is_El_TPC && is_El_TOF; } @@ -518,41 +578,166 @@ struct TreeCreatorElectronMLDDA { } template - void fillTrackTable(TCollision const& collision, TTrack const& track, const int pidlabel, const int tracktype, const bool isForValidation) + void fillTrackTable(TCollision const& collision, TTrack const& track, const uint8_t pidlabel) { if (store_ele_band_only && !isElectron(track)) { return; } + mDcaInfoCov.set(999, 999, 999, 999, 999); + auto trackParCov = getTrackParCov(track); + // trackParCov.setPID(track.pidForTracking()); + trackParCov.setPID(o2::track::PID::Electron); // This is for eID in the end! + 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 (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron)) { + if (trackParCov.getP() < max_p_for_downscaling_electron) { + if (dist01(engine) > downscaling_electron_lowP) { + return; + } + } else { + if (dist01(engine) > downscaling_electron_highP) { + return; + } + } + } else if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion)) { + if (trackParCov.getP() < max_p_for_downscaling_pion) { + if (dist01(engine) > downscaling_pion_lowP) { + return; + } + } else { + if (dist01(engine) > downscaling_pion_highP) { + return; + } + } + } else if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon)) { + if (trackParCov.getP() < max_p_for_downscaling_kaon) { + if (dist01(engine) > downscaling_kaon_lowP) { + return; + } + } else { + if (dist01(engine) > downscaling_kaon_highP) { + return; + } + } + } else if (pidlabel == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton)) { + if (trackParCov.getP() < max_p_for_downscaling_proton) { + if (dist01(engine) > downscaling_proton_lowP) { + return; + } + } else { + if (dist01(engine) > downscaling_proton_highP) { + return; + } + } + } if (std::find(stored_trackIds.begin(), stored_trackIds.end(), track.globalIndex()) == stored_trackIds.end()) { - mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); - float dcaXY = mDcaInfoCov.getY(); - float dcaZ = mDcaInfoCov.getZ(); - - emprimarytracks(collision.globalIndex(), collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), - track.pt(), track.eta(), track.phi(), track.tgl(), track.signed1Pt(), - dcaXY, dcaZ, track_par_cov_recalc.getSigmaY2(), track_par_cov_recalc.getSigmaZ2(), track_par_cov_recalc.getSigmaZY(), + emprimarytracks(collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange(), + trackParCov.getP(), trackParCov.getTgl(), track.sign(), track.tpcNClsFindable(), track.tpcNClsFound(), track.tpcNClsCrossedRows(), track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaMu(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), - track.beta(), track.tofNSigmaEl(), track.tofNSigmaMu(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), - track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), pidlabel, tracktype, isForValidation); + track.tpcSignal(), track.tpcNSigmaEl(), /*track.tpcNSigmaMu(),*/ track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), + track.beta(), track.tofNSigmaEl(), /*track.tofNSigmaMu(),*/ track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), + track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), pidlabel); stored_trackIds.emplace_back(track.globalIndex()); } } + 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.cfgRequireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + + if (eventcuts.cfgRequireVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + + if (eventcuts.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + + if (eventcuts.cfgRequireGoodZvtxFT0vsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + + if (eventcuts.cfgRequireNoCollInTimeRangeStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + + if (eventcuts.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; + } + + if (!(eventcuts.cfgTrackOccupancyMin <= collision.trackOccupancyInTimeRange() && collision.trackOccupancyInTimeRange() < eventcuts.cfgTrackOccupancyMax)) { + return false; + } + + if (!(eventcuts.cfgFT0COccupancyMin <= collision.ft0cOccupancyInTimeRange() && collision.ft0cOccupancyInTimeRange() < eventcuts.cfgFT0COccupancyMax)) { + return false; + } + + return true; + } + //! 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.value&& o2::aod::v0data::dcaV0daughters v0cuts.cfg_min_dcaxy_v0leg&& nabs(o2::aod::v0data::dcanegtopv) > v0cuts.cfg_min_dcaxy_v0leg; + 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; - Filter cascadeFilter = o2::aod::cascdata::dcacascdaughters < cascadecuts.cfg_max_dcadau.value && 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; + 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_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::evsel::sel8 == true; using filteredMyCollisions = soa::Filtered; @@ -560,11 +745,11 @@ struct TreeCreatorElectronMLDDA { 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 && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true; - Partition negTracks = o2::aod::track::signed1Pt < 0.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; + 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) + void processPID(filteredMyCollisions const& collisions, aod::BCsWithTimestamps const&, filteredV0s const& v0s, filteredCascades const& cascades, MyTracks const& tracks, aod::V0s const&) { stored_trackIds.reserve(tracks.size()); for (const auto& collision : collisions) { @@ -573,6 +758,10 @@ struct TreeCreatorElectronMLDDA { auto bc = collision.template foundBC_as(); initCCDB(bc); + if (!isSelectedEvent(collision)) { + continue; + } + if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { continue; } @@ -580,80 +769,94 @@ struct TreeCreatorElectronMLDDA { 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(); - if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg)) { + // 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; + } + if (v0.v0cosPA() < v0cuts.cfg_min_cospa) { continue; } if (pos.sign() * neg.sign() > 0) { continue; } - - // LOGF(info, "v0.globalIndex() = %d, v0.collisionId() = %d, v0.posTrackId() = %d, v0.negTrackId() = %d", v0.globalIndex(), v0.collisionId(), v0.posTrackId(), v0.negTrackId()); + if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg)) { + continue; + } registry.fill(HIST("V0/hPCA"), v0.dcaV0daughters()); registry.fill(HIST("V0/hCosPA"), v0.v0cosPA()); registry.fill(HIST("V0/hAP"), v0.alpha(), v0.qtarm()); - if (v0.dcaV0daughters() > v0cuts.cfg_max_dcadau) { - continue; - } - if (v0.v0cosPA() < v0cuts.cfg_min_cospa) { - continue; - } - - if (isPion(pos) && isPion(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.p(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pi"), neg.p(), neg.beta()); - registry.fill(HIST("V0/hTPCdEdx_P_Pi"), pos.p(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pi"), pos.p(), pos.beta()); - if (dist01(engine) < downscaling_pion || pos.tpcInnerParam() > max_pin_for_downscaling_pion) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + if (v0cuts.cfg_min_qt_strangeness < 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 (isPionTight(pos) && isPion(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)); + } } - if (dist01(engine) < downscaling_pion || neg.tpcInnerParam() > max_pin_for_downscaling_pion) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + if (isPion(pos) && isPionTight(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)); + } } } - } - if (isProton(pos) && isPionTight(neg)) { - registry.fill(HIST("V0/hMassLambda"), v0.mLambda()); - if (v0cuts.cfg_min_mass_lambda < v0.mLambda() && v0.mLambda() < v0cuts.cfg_max_mass_lambda) { - if (dist01(engine) < downscaling_proton || pos.tpcInnerParam() > max_pin_for_downscaling_proton) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + + if (!(v0cuts.cfg_min_mass_k0s_veto < v0.mK0Short() && v0.mK0Short() < v0cuts.cfg_max_mass_k0s_veto)) { + if (isProton(pos) && isPionTight(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)); + 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/hTPCdEdx_P_Pr"), pos.p(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pr"), pos.p(), pos.beta()); - } - } - if (isPionTight(pos) && isProton(neg)) { - registry.fill(HIST("V0/hMassAntiLambda"), v0.mAntiLambda()); - if (v0cuts.cfg_min_mass_lambda < v0.mAntiLambda() && v0.mAntiLambda() < v0cuts.cfg_max_mass_lambda) { - if (dist01(engine) < downscaling_proton || neg.tpcInnerParam() > max_pin_for_downscaling_proton) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + if (isPionTight(pos) && isProton(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)); + 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/hTPCdEdx_P_Pr"), neg.p(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Pr"), neg.p(), neg.beta()); } - } - registry.fill(HIST("V0/hMassGamma"), v0.mGamma()); - registry.fill(HIST("V0/hXY_Gamma"), v0.x(), v0.y()); - registry.fill(HIST("V0/hMassGamma_Rxy"), v0.v0radius(), v0.mGamma()); - if (isElectron(pos) && isElectron(neg)) { - if ((v0cuts.cfg_min_mass_photon < v0.mGamma() && v0.mGamma() < v0cuts.cfg_max_mass_photon)) { - if (dist01(engine) < downscaling_electron || pos.tpcInnerParam() > max_pin_for_downscaling_electron) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + } // end of stangeness + + if (!v0cuts.cfg_require_collinearV0 || o2v0.isCollinearV0()) { + if (isElectronTight(pos) && isElectron(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)); + registry.fill(HIST("V0/hTPCdEdx_P_El"), neg.tpcInnerParam(), neg.tpcSignal()); + registry.fill(HIST("V0/hTOFbeta_P_El"), neg.tpcInnerParam(), neg.beta()); } - if (dist01(engine) < downscaling_electron || neg.tpcInnerParam() > max_pin_for_downscaling_electron) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kSecondary), false); + } + + if (isElectron(pos) && isElectronTight(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)); + 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/hTPCdEdx_P_El"), neg.p(), neg.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_El"), neg.p(), neg.beta()); - registry.fill(HIST("V0/hTPCdEdx_P_El"), pos.p(), pos.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_El"), pos.p(), pos.beta()); } } + } // end of v0 loop auto cascades_coll = cascades.sliceBy(perCollision_cascade, collision.globalIndex()); @@ -662,10 +865,6 @@ struct TreeCreatorElectronMLDDA { auto bachelor = cascade.template bachelor_as(); auto pos = cascade.template posTrack_as(); auto neg = cascade.template negTrack_as(); - if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg) || !isSelectedV0Leg(collision, bachelor)) { - continue; - } - if (pos.sign() * neg.sign() > 0) { continue; } @@ -680,8 +879,7 @@ struct TreeCreatorElectronMLDDA { } } - registry.fill(HIST("Cascade/hMassLambda"), cascade.mLambda()); - if (!(v0cuts.cfg_min_mass_lambda < cascade.mLambda() && cascade.mLambda() < v0cuts.cfg_max_mass_lambda)) { + if (!(cascadecuts.cfg_min_mass_lambda < cascade.mLambda() && cascade.mLambda() < cascadecuts.cfg_max_mass_lambda)) { continue; } @@ -689,11 +887,6 @@ struct TreeCreatorElectronMLDDA { continue; } - 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())); - if (cascade.dcaV0daughters() > cascadecuts.cfg_max_dcadau_v0) { continue; } @@ -715,6 +908,16 @@ struct TreeCreatorElectronMLDDA { continue; } + if (!isSelectedV0Leg(collision, pos) || !isSelectedV0Leg(collision, neg) || !isSelectedV0Leg(collision, bachelor)) { + continue; + } + + 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 @@ -723,58 +926,22 @@ struct TreeCreatorElectronMLDDA { if (isPion(bachelor)) { registry.fill(HIST("Cascade/hMassXi"), cascade.mXi()); registry.fill(HIST("Cascade/hMassPt_Xi"), cascade.mXi(), cascade.pt()); - registry.fill(HIST("Cascade/hMassPt_Xi_bachelor"), cascade.mXi(), bachelor.p()); 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 < cascade.mXi() && cascade.mXi() < cascadecuts.cfg_max_mass_Xi) && isKaon(bachelor)) { // reject Xi candidates + 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/hMassPt_Omega_bachelor"), cascade.mOmega(), bachelor.p()); 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.p(), bachelor.tpcSignal()); - registry.fill(HIST("V0/hTOFbeta_P_Ka"), bachelor.p(), bachelor.beta()); - if (dist01(engine) < downscaling_kaon || bachelor.tpcInnerParam() > max_pin_for_downscaling_kaon) { - fillTrackTable(collision, bachelor, static_cast(o2::aod::pwgem::dilepton::PID_Label::kKaon), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary), false); - } + 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)); } } } // end of cascade loop - - // for electron sample for validation - 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, neg] : combinations(CombinationsFullIndexPolicy(posTracks_per_coll, negTracks_per_coll))) { - if (!isSelectedTrack(collision, pos) || !isSelectedTrack(collision, neg)) { - continue; - } - if (!isElectron(pos) || !isElectron(neg)) { - continue; - } - - ROOT::Math::PtEtaPhiMVector v1(neg.pt(), neg.eta(), neg.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v2(pos.pt(), pos.eta(), pos.phi(), o2::constants::physics::MassElectron); - ROOT::Math::PtEtaPhiMVector v12 = v1 + v2; - float phiv = o2::aod::pwgem::dilepton::utils::pairutil::getPhivPair(pos.px(), pos.py(), pos.pz(), neg.px(), neg.py(), neg.pz(), pos.sign(), neg.sign(), d_bz); - registry.fill(HIST("hMvsPhiV"), phiv, v12.M()); - - if ((dalitzcuts.cfg_min_mass_ee < v12.M() && v12.M() < dalitzcuts.cfg_max_mass_ee) && (dalitzcuts.cfg_min_phiv_ee < phiv && phiv < dalitzcuts.cfg_max_phiv_ee)) { // ee from pi0 dalitz decay is found. - if (isElectronTight(pos) && isElectron(neg)) { - if (dist01(engine) < downscaling_electron_primary || neg.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { - fillTrackTable(collision, neg, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary), true); // primary electron candidates - } - } - if (isElectron(pos) && isElectronTight(neg)) { - if (dist01(engine) < downscaling_electron_primary || pos.tpcInnerParam() > max_pin_for_downscaling_electron_primary) { - fillTrackTable(collision, pos, static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron), static_cast(o2::aod::pwgem::dilepton::Track_Type::kPrimary), true); // primary electron candidates - } - } - } - } // end of ULS pair loop } // end of collision loop - stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } // end of process @@ -791,61 +958,61 @@ struct MLTrackQC { HistogramRegistry registry{ "registry", { - {"hTPCdEdx_P_All", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_All", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_All", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, - {"hTPCdEdx_P_Electron", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Electron", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Electron", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, - {"hTPCdEdx_P_Pion", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Pion", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Pion", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, - {"hTPCdEdx_P_Kaon", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Kaon", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Kaon", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, - {"hTPCdEdx_P_Proton", "TPC dE/dx vs. p;p^{ITS-TPC} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, - {"hTOFbeta_P_Proton", "TOF beta vs. p;p^{ITS-TPC} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, - {"hITSClusterSize_P_Proton", "mean ITS cluster size vs. p;p^{ITS-TPC} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {64, 0.0, 16}}}}, - - {"hTPCNsigmaEl_P", "TPC n#sigma_{e} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTPCNsigmaPi_P", "TPC n#sigma_{#pi} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{#pi}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTPCNsigmaKa_P", "TPC n#sigma_{K} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{K}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTPCNsigmaPr_P", "TPC n#sigma_{p} vs. p;p^{ITS-TPC} (GeV/c);n #sigma_{p}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaEl_P", "TOF n#sigma_{e} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{e}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaPi_P", "TOF n#sigma_{#pi} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{#pi}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaKa_P", "TOF n#sigma_{K} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{K}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, - {"hTOFNsigmaPr_P", "TOF n#sigma_{p} vs. p;p^{ITS-TOF} (GeV/c);n #sigma_{p}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCdEdx_P_All", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_All", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_All", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Electron", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Electron", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Electron", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Pion", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Pion", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Pion", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Kaon", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Kaon", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Kaon", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + {"hTPCdEdx_P_Proton", "TPC dE/dx vs. p;p_{pv} (GeV/c);TPC dE/dx", {HistType::kTH2F, {{500, 0.f, 5.f}, {200, 0, 200}}}}, + {"hTOFbeta_P_Proton", "TOF beta vs. p;p_{pv} (GeV/c);TOF #beta", {HistType::kTH2F, {{500, 0.f, 5.f}, {220, 0.0, 1.1}}}}, + {"hITSobClusterSize_P_Proton", "mean ITSob cluster size vs. p;p_{pv} (GeV/c); #times cos(#lambda)", {HistType::kTH2F, {{500, 0.f, 5.f}, {150, 0.0, 15}}}}, + + {"hTPCNsigmaEl_P", "TPC n#sigma_{e} vs. p;p_{pv} (GeV/c);n #sigma_{e}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCNsigmaPi_P", "TPC n#sigma_{#pi} vs. p;p_{pv} (GeV/c);n #sigma_{#pi}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCNsigmaKa_P", "TPC n#sigma_{K} vs. p;p_{pv} (GeV/c);n #sigma_{K}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTPCNsigmaPr_P", "TPC n#sigma_{p} vs. p;p_{pv} (GeV/c);n #sigma_{p}^{TPC}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaEl_P", "TOF n#sigma_{e} vs. p;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaPi_P", "TOF n#sigma_{#pi} vs. p;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaKa_P", "TOF n#sigma_{K} vs. p;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, + {"hTOFNsigmaPr_P", "TOF n#sigma_{p} vs. p;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", {HistType::kTH2F, {{500, 0.f, 5.f}, {100, -5, +5}}}}, }, }; - void processQC(aod::EMPrimaryTracks const& tracks) + void processQC(aod::EMTracksForMLPID const& tracks) { for (const auto& track : tracks) { registry.fill(HIST("hTPCdEdx_P_All"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_All"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_All"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); - if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kElectron)) { + registry.fill(HIST("hITSobClusterSize_P_All"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); + if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kElectron)) { registry.fill(HIST("hTPCdEdx_P_Electron"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Electron"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Electron"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Electron"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaEl_P"), track.p(), track.tpcNSigmaEl()); registry.fill(HIST("hTOFNsigmaEl_P"), track.p(), track.tofNSigmaEl()); - } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kPion)) { + } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kPion)) { registry.fill(HIST("hTPCdEdx_P_Pion"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Pion"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Pion"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Pion"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaPi_P"), track.p(), track.tpcNSigmaPi()); registry.fill(HIST("hTOFNsigmaPi_P"), track.p(), track.tofNSigmaPi()); - } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kKaon)) { + } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kKaon)) { registry.fill(HIST("hTPCdEdx_P_Kaon"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Kaon"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Kaon"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Kaon"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaKa_P"), track.p(), track.tpcNSigmaKa()); registry.fill(HIST("hTOFNsigmaKa_P"), track.p(), track.tofNSigmaKa()); - } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::PID_Label::kProton)) { + } else if (track.pidlabel() == static_cast(o2::aod::pwgem::dilepton::ml::PID_Label::kProton)) { registry.fill(HIST("hTPCdEdx_P_Proton"), track.p(), track.tpcSignal()); registry.fill(HIST("hTOFbeta_P_Proton"), track.p(), track.beta()); - registry.fill(HIST("hITSClusterSize_P_Proton"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); + registry.fill(HIST("hITSobClusterSize_P_Proton"), track.p(), track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl()))); registry.fill(HIST("hTPCNsigmaPr_P"), track.p(), track.tpcNSigmaPr()); registry.fill(HIST("hTOFNsigmaPr_P"), track.p(), track.tofNSigmaPr()); } @@ -853,7 +1020,7 @@ struct MLTrackQC { } PROCESS_SWITCH(MLTrackQC, processQC, "process QC for single track level", false); - void processDummy(aod::EMPrimaryTracks const&) {} + void processDummy(aod::EMTracksForMLPID const&) {} PROCESS_SWITCH(MLTrackQC, processDummy, "process dummy", true); }; diff --git a/PWGEM/Dilepton/Tasks/CMakeLists.txt b/PWGEM/Dilepton/Tasks/CMakeLists.txt index 2eed697101d..94ccb5f2ea4 100644 --- a/PWGEM/Dilepton/Tasks/CMakeLists.txt +++ b/PWGEM/Dilepton/Tasks/CMakeLists.txt @@ -53,7 +53,7 @@ o2physics_add_dpl_workflow(bc-counter o2physics_add_dpl_workflow(event-qc SOURCES eventQC.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(single-electron-qc @@ -146,3 +146,18 @@ o2physics_add_dpl_workflow(tagging-hfe PUBLIC_LINK_LIBRARIES O2::Framework O2::DCAFitter O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(qvector-dummy-otf + SOURCES qVectorDummyOTF.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(dielectron-hadron-mpc + SOURCES dielectronHadronMPC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::MLCore O2Physics::PWGEMDileptonCore + 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 + COMPONENT_NAME Analysis) + diff --git a/PWGEM/Dilepton/Tasks/Converters/CMakeLists.txt b/PWGEM/Dilepton/Tasks/Converters/CMakeLists.txt index 503c3aee2ff..f5f41c009cd 100644 --- a/PWGEM/Dilepton/Tasks/Converters/CMakeLists.txt +++ b/PWGEM/Dilepton/Tasks/Converters/CMakeLists.txt @@ -15,8 +15,28 @@ o2physics_add_dpl_workflow(event-converter2 PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(event-converter3 + SOURCES eventConverter3.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 COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(electron-converter3 + SOURCES electronConverter3.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(electron-converter4 + SOURCES electronConverter4.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 + COMPONENT_NAME Analysis) + diff --git a/PWGEM/Dilepton/Tasks/Converters/electronConverter3.cxx b/PWGEM/Dilepton/Tasks/Converters/electronConverter3.cxx new file mode 100644 index 00000000000..f4101ab2a51 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/Converters/electronConverter3.cxx @@ -0,0 +1,85 @@ +// 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 "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct electronConverter3 { + Produces track_003; + + void process(aod::EMPrimaryElectrons_002 const& tracks) + { + for (auto& track : tracks) { + track_003(track.collisionId(), + track.trackId(), + track.sign(), + track.pt(), + track.eta(), + track.phi(), + track.dcaXY(), + track.dcaZ(), + track.tpcNClsFindable(), + track.tpcNClsFindableMinusFound(), + track.tpcNClsFindableMinusCrossedRows(), + track.tpcNClsShared(), + track.tpcChi2NCl(), + track.tpcInnerParam(), + track.tpcSignal(), + track.tpcNSigmaEl(), + // track.tpcNSigmaMu(), + track.tpcNSigmaPi(), + track.tpcNSigmaKa(), + track.tpcNSigmaPr(), + track.beta(), + track.tofNSigmaEl(), + // track.tofNSigmaMu(), + track.tofNSigmaPi(), + track.tofNSigmaKa(), + track.tofNSigmaPr(), + track.itsClusterSizes(), + // track.itsNSigmaEl(), + // track.itsNSigmaMu(), + // track.itsNSigmaPi(), + // track.itsNSigmaKa(), + // track.itsNSigmaPr(), + track.itsChi2NCl(), + track.tofChi2(), + track.detectorMap(), + track.x(), + track.alpha(), + track.y(), + track.z(), + track.snp(), + track.tgl(), + track.isAssociatedToMPC(), + -1); + } // end of track loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"electron-converter3"})}; +} diff --git a/PWGEM/Dilepton/Tasks/Converters/electronConverter4.cxx b/PWGEM/Dilepton/Tasks/Converters/electronConverter4.cxx new file mode 100644 index 00000000000..dcca6b5edc1 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/Converters/electronConverter4.cxx @@ -0,0 +1,124 @@ +// 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 "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct electronConverter4 { + Produces track_004; + + using MyElectrons002 = soa::Join; + void process002to004(MyElectrons002 const& tracks) + { + for (const auto& track : tracks) { + track_004(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.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(), + // track.tgl(), + track.isAssociatedToMPC(), + false, + 0.f, + 0.f); + } // end of track loop + } + PROCESS_SWITCH(electronConverter4, process002to004, "convert from 002 into 004", false); + + using MyElectrons003 = soa::Join; + void process003to004(MyElectrons003 const& tracks) + { + for (const auto& track : tracks) { + track_004(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.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(), + // track.tgl(), + track.isAssociatedToMPC(), + false, + 0.f, + track.mcTunedTPCSignal()); + } // end of track loop + } + PROCESS_SWITCH(electronConverter4, process003to004, "convert from 003 into 004", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"electron-converter4"})}; +} diff --git a/PWGEM/Dilepton/Tasks/Converters/eventConverter3.cxx b/PWGEM/Dilepton/Tasks/Converters/eventConverter3.cxx new file mode 100644 index 00000000000..fe22e18f859 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/Converters/eventConverter3.cxx @@ -0,0 +1,54 @@ +// 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 "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct eventConverter3 { + Produces event_003; + + void process(aod::EMEvents_002 const& collisions) + { + for (auto& collision : collisions) { + event_003( + collision.globalIndex(), + collision.runNumber(), + collision.globalBC(), + collision.alias_raw(), + 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, TaskName{"event-converter3"})}; +} diff --git a/PWGEM/Dilepton/Tasks/Converters/trackConverter1.cxx b/PWGEM/Dilepton/Tasks/Converters/trackConverter1.cxx new file mode 100644 index 00000000000..fda87265b3c --- /dev/null +++ b/PWGEM/Dilepton/Tasks/Converters/trackConverter1.cxx @@ -0,0 +1,48 @@ +// 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 "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct trackConverter1 { + Produces track_001; + + void process(aod::EMPrimaryTracks_000 const& tracks) + { + for (auto& track : tracks) { + track_001(track.collisionId(), + track.trackId(), + track.sign() / track.pt(), + track.eta(), + track.phi(), + track.trackBit()); + } // end of track loop + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"track-converter1"})}; +} diff --git a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx index c6c056b5dcb..323d82e7728 100644 --- a/PWGEM/Dilepton/Tasks/createResolutionMap.cxx +++ b/PWGEM/Dilepton/Tasks/createResolutionMap.cxx @@ -13,40 +13,41 @@ // Analysis task to produce resolution mapfor electrons/muons in dilepton analysis // Please write to: daiki.sekihata@cern.ch -#include -#include -#include -#include -#include -#include +#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/ASoA.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" +#include "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/Core/trackUtilities.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsCalibration/MeanVertexObject.h" -#include "TGeoGlobalMagField.h" -#include "Field/MagneticField.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 "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "Common/Core/fwdtrackUtilities.h" + +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -134,6 +135,9 @@ struct CreateResolutionMap { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_require_itsib_1st{"cfg_require_itsib_1st", false, "flag to require ITS ib 1st hit"}; + 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)"}; } electroncuts; struct : ConfigurableGroup { @@ -157,12 +161,12 @@ struct CreateResolutionMap { 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_min_nclusters_MFT{"cfg_min_nclusters_MFT", 5, "min nclusters MFT"}; - Configurable cfg_min_nclusters_MCH{"min_min_nclusters_MCH", 5, "min nclusters MCH"}; 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"}; } muoncuts; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -388,11 +392,7 @@ struct CreateResolutionMap { template bool isSelectedTrack(TTrack const& track) { - if (!track.hasITS() || !track.hasTPC()) { - return false; - } - - if (track.tpcChi2NCl() > electroncuts.cfg_max_chi2tpc) { + if (!track.hasITS()) { return false; } @@ -418,80 +418,67 @@ struct CreateResolutionMap { } } - if (track.tpcNClsFound() < electroncuts.cfg_min_ncluster_tpc) { + if (!electroncuts.includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcNClsCrossedRows() < electroncuts.cfg_min_ncrossedrows) { - return false; - } + if (track.hasTPC()) { + if (track.tpcChi2NCl() > electroncuts.cfg_max_chi2tpc) { + return false; + } - if (track.tpcCrossedRowsOverFindableCls() < electroncuts.cfg_min_tpc_cr_findable_ratio) { - return false; - } + if (track.tpcNClsFound() < electroncuts.cfg_min_ncluster_tpc) { + return false; + } - if (track.tpcFractionSharedCls() > electroncuts.cfg_max_frac_shared_clusters_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; + } } return true; } template - bool isSelectedTrackKine(TTrack const& track, const float pt, const float eta, const float dcaXY, const float dcaZ) + bool isSelectedTrackWithKine(TTrack const& track, const float pt, const float eta, const float tgl, const float dcaXY, const float dcaZ) { - if (!track.hasITS() || !track.hasTPC()) { + if (!isSelectedTrack(track)) { return false; } - if (track.tpcChi2NCl() > electroncuts.cfg_max_chi2tpc) { + if (std::fabs(dcaXY) > electroncuts.cfg_max_dcaxy || std::fabs(dcaZ) > electroncuts.cfg_max_dcaz) { return false; } - if (track.itsChi2NCl() > electroncuts.cfg_max_chi2its) { + if (pt < electroncuts.cfg_min_pt_track || std::fabs(eta) > electroncuts.cfg_max_eta_track) { return false; } - if (track.itsNCls() < electroncuts.cfg_min_ncluster_its) { - return false; - } - if (track.itsNClsInnerBarrel() < electroncuts.cfg_min_ncluster_itsib) { + if ((track.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) && electroncuts.maxpt_itssa < pt) { 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.hasITS() && !track.hasTPC() && !track.hasTOF() && !track.hasTRD()) { // only for ITSsa + 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 (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; + if (electroncuts.maxMeanITSClusterSize < static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(tgl))) { + return false; + } } return true; @@ -583,6 +570,15 @@ struct CreateResolutionMap { 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; + } + } + } + } else if (muon.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) { o2::dataformats::GlobalFwdTrack propmuonAtRabs = propagateMuon(muon, collision, propagationPoint::kToRabs); // this is necessary only for MuonStandaloneTrack float xAbs = propmuonAtRabs.getX(); @@ -680,6 +676,20 @@ struct CreateResolutionMap { return true; } + 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; @@ -720,20 +730,20 @@ struct CreateResolutionMap { o2::dataformats::DCA mDcaInfoCov; mDcaInfoCov.set(999, 999, 999, 999, 999); - auto track_par_cov_recalc = getTrackParCov(track); - track_par_cov_recalc.setPID(o2::track::PID::Electron); + 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, track_par_cov_recalc, 2.f, matCorr, &mDcaInfoCov); + o2::base::Propagator::Instance()->propagateToDCABxByBz(mVtx, trackParCov, 2.f, matCorr, &mDcaInfoCov); float dcaXY = mDcaInfoCov.getY(); float dcaZ = mDcaInfoCov.getZ(); - float pt = track_par_cov_recalc.getPt(); - float eta = track_par_cov_recalc.getEta(); - float phi = track_par_cov_recalc.getPhi(); + float pt = trackParCov.getPt(); + float eta = trackParCov.getEta(); + float phi = trackParCov.getPhi(); o2::math_utils::bringTo02Pi(phi); - if (!isSelectedTrackKine(track, pt, eta, dcaXY, dcaZ)) { + if (!isSelectedTrackWithKine(track, pt, eta, trackParCov.getTgl(), dcaXY, dcaZ)) { return; } diff --git a/PWGEM/Dilepton/Tasks/dielectronHadronMPC.cxx b/PWGEM/Dilepton/Tasks/dielectronHadronMPC.cxx new file mode 100644 index 00000000000..42cfa2eac28 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/dielectronHadronMPC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code is for dielectron analyses. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Core/DileptonHadronMPC.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"dielectron-hadron-2pc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/dimuonHadronMPC.cxx b/PWGEM/Dilepton/Tasks/dimuonHadronMPC.cxx new file mode 100644 index 00000000000..2e0cf5f5e59 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/dimuonHadronMPC.cxx @@ -0,0 +1,27 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code is for dimuon analyses. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/Dilepton/Core/DileptonHadronMPC.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"dimuon-hadron-mpc"})}; +} diff --git a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx index 7cc41a190d2..76b523ec64c 100644 --- a/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx +++ b/PWGEM/Dilepton/Tasks/emEfficiencyEE.cxx @@ -12,41 +12,45 @@ // // Analysis task for calculating single electron and dielectron efficiency // -#include -#include -#include -#include -#include -#include -#include -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/ASoA.h" -#include "Framework/DataTypes.h" -#include "Framework/HistogramRegistry.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 "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/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/CCDB/TriggerAliases.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 "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include +#include +#include +#include +#include + +#include +#include using std::cout; using std::endl; @@ -457,7 +461,7 @@ struct AnalysisTrackSelection { ConfigurableAxis deltaphiResBins{"deltaphiResBins", {500, -0.5f, 0.5f}, "DeltaPhi binning for resolution"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; - Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; // output lists OutputObj fOutputQA{"SingleElectronQA"}; @@ -1027,8 +1031,8 @@ struct AnalysisTrackSelection { fHistManQA->FillHistClass(fHistNamesMCMatchedQA[j][i].Data(), VarManager::fgValues); } } // end loop over cuts - } // end loop over MC signals - } // end loop over reconstructed track belonging to the events + } // end loop over MC signals + } // end loop over reconstructed track belonging to the events } template @@ -1275,8 +1279,8 @@ struct AnalysisTrackSelection { fHistManQA->FillHistClass(fHistNamesMCMatchedQA[j][i].Data(), VarManager::fgValues); } } // end loop over cuts - } // end loop over MC signals - } // end loop over reconstructed track belonging to the events + } // end loop over MC signals + } // end loop over reconstructed track belonging to the events } void processSkimmed(soa::Filtered const& events, MyBarrelTracks const& tracks, ReducedMCEvents const& eventsMC, ReducedMCTracks const& tracksMC) @@ -1601,7 +1605,7 @@ struct AnalysisSameEventPairing { runRecPair(groupedTracks, tracksMC); } } // end loop over reconstructed event - } // end loop pairing function + } // end loop pairing function template void runMCPairing(TEventMC const& /*eventMC*/, TTracksMC const& tracksMC) @@ -1716,7 +1720,7 @@ struct AnalysisSameEventPairing { } } } // end of true pairing loop - } // end runMCGen + } // end runMCGen template void runRecPair(TTracks const& tracks, TTracksMC const& /*tracksMC*/) diff --git a/PWGEM/Dilepton/Tasks/eventQC.cxx b/PWGEM/Dilepton/Tasks/eventQC.cxx index afd65dbbe7e..eb46e057ace 100644 --- a/PWGEM/Dilepton/Tasks/eventQC.cxx +++ b/PWGEM/Dilepton/Tasks/eventQC.cxx @@ -14,29 +14,32 @@ // This code is for event QC for PWG-EM. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include -#include -#include +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "TString.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Common/Core/RecoDecay.h" -#include "MathUtils/Utils.h" -#include "Framework/AnalysisDataModel.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" + #include "CCDB/BasicCCDBManager.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.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 using namespace o2; using namespace o2::aod; @@ -44,34 +47,42 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using MyBCs = soa::Join; -using MyQvectors = soa::Join; +struct eventQC { + using MyBCs = soa::Join; + using MyQvectors = soa::Join; -using MyCollisions = soa::Join; -using MyCollisions_Qvec = soa::Join; + using MyCollisions = soa::Join; + using MyCollisions_Qvec = soa::Join; -using MyTracks = soa::Join; -using MyTrack = MyTracks::iterator; + using MyTracks = soa::Join; + using MyTrack = MyTracks::iterator; -struct eventQC { // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable cfg_swt_name{"cfg_swt_name", "fHighTrackMult", "desired software trigger name"}; Configurable cfgFillEvent{"cfgFillEvent", false, "fill event histograms"}; Configurable cfgFillTrack{"cfgFillTrack", false, "fill track histograms"}; Configurable cfgFillPID{"cfgFillPID", false, "fill PID histograms"}; - Configurable cfgFillPIDITS{"cfgFillPIDITS", false, "fill PID ITS histograms"}; Configurable> cfgnMods{"cfgnMods", {2, 3}, "Modulation of interest. Please keep increasing order"}; Configurable cfgCentEstimator{"cfgCentEstimator", 2, "FT0M:0, FT0A:1, FT0C:2"}; Configurable cfgQvecEstimator{"cfgQvecEstimator", 0, "FT0M:0, FT0A:1, FT0C:2, BTot:3, BPos:4, BNeg:5"}; - Configurable cfgCentMin{"cfgCentMin", 0, "min. centrality"}; + Configurable cfgCentMin{"cfgCentMin", -1.f, "min. centrality"}; Configurable cfgCentMax{"cfgCentMax", 999.f, "max. centrality"}; + Configurable cfgNtracksPV08Min{"cfgNtracksPV08Min", -1, "min. multNTracksPV"}; + Configurable cfgNtracksPV08Max{"cfgNtracksPV08Max", 1000000000, "max. multNTracksPV"}; ConfigurableAxis ConfPtBins{"ConfPtBins", {VARIABLE_WIDTH, 0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85, 0.90, 0.95, 1.00, 1.10, 1.20, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.50, 3.00, 3.50, 4.00, 4.50, 5.00, 6.00, 7.00, 8.00, 9.00, 10.00}, "pT bins for output histograms"}; Configurable cfgNbinsEta{"cfgNbinsEta", 20, "number of eta bins for output histograms"}; Configurable cfgNbinsPhi{"cfgNbinsPhi", 36, "number of phi bins for output histograms"}; + ConfigurableAxis ConfFT0AMultBins{"ConfFT0AMultBins", {200, 0, 200e+3}, "FT0A multiplicity bins for output histograms"}; + ConfigurableAxis ConfFT0CMultBins{"ConfFT0CMultBins", {600, 0, 60e+3}, "FT0C multiplicity bins for output histograms"}; + ConfigurableAxis ConfFV0AMultBins{"ConfFV0AMultBins", {200, 0, 200e+3}, "FV0A multiplicity bins for output histograms"}; + ConfigurableAxis ConfTrackMultBins{"ConfTrackMultBins", {6001, -0.5, 6e+3 + 0.5}, "Track multiplicity bins for output histograms"}; + ConfigurableAxis ConfCentBins{"ConfCentBins", {110, 0, 110}, "centrality bins for output histograms"}; + struct : ConfigurableGroup { std::string prefix = "eventcut_group"; Configurable cfgZvtxMin{"cfgZvtxMin", -10.f, "min. Zvtx"}; @@ -80,6 +91,8 @@ struct eventQC { 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 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 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"}; @@ -122,36 +135,19 @@ struct eventQC { Configurable cfg_requireTOF{"cfg_requireTOF", false, "require TOF hit"}; } trackcuts; - struct : ConfigurableGroup { - std::string prefix = "v0cut_group"; - Configurable cfg_min_mass_photon{"cfg_min_mass_photon", 0.0, "min mass for photon rejection"}; - Configurable cfg_max_mass_photon{"cfg_max_mass_photon", 0.1, "max mass for photon rejection"}; - Configurable cfg_min_mass_k0s{"cfg_min_mass_k0s", 0.490, "min mass for K0S"}; - Configurable cfg_max_mass_k0s{"cfg_max_mass_k0s", 0.505, "max mass for K0S"}; - Configurable cfg_min_mass_lambda{"cfg_min_mass_lambda", 1.11, "min mass for Lambda rejection"}; - Configurable cfg_max_mass_lambda{"cfg_max_mass_lambda", 1.12, "max mass for Lambda rejection"}; - Configurable cfg_min_cospa_v0hadron{"cfg_min_cospa_v0hadron", 0.999, "min cospa for v0hadron"}; - Configurable cfg_max_pca_v0hadron{"cfg_max_pca_v0hadron", 0.5, "max distance between 2 legs for v0hadron"}; - Configurable cfg_min_radius_v0hadron{"cfg_min_radius_v0hadron", 1.0, "min rxy for v0hadron"}; - Configurable cfg_max_kfchi2{"cfg_max_kfchi2", 1e+10, "max kfchi2 for PCM"}; - Configurable cfg_min_cr2findable_ratio_tpc{"cfg_min_cr2findable_ratio_tpc", 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_min_ncrossedrows_tpc{"cfg_min_ncrossedrows_tpc", 40, "min ncrossed rows"}; - Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster 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", 1.0, "max chi2 for TOF"}; - Configurable cfg_min_dcaxy_v0leg{"cfg_min_dcaxy_v0leg", 0.1, "min dca XY for v0 legs in cm"}; - Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -4, "min n sigma e in TPC"}; - Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +4, "max n sigma e in TPC"}; - Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -4, "min n sigma pi in TPC"}; - Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +4, "max n sigma pi in TPC"}; - Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -2, "min n sigma el in TOF"}; - Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +2, "max n sigma el in TOF"}; - Configurable cfg_min_TOFNsigmaPi{"cfg_min_TOFNsigmaPi", -2, "min n sigma pi in TOF"}; - Configurable cfg_max_TOFNsigmaPi{"cfg_max_TOFNsigmaPi", +2, "max n sigma pi in TOF"}; - } v0cuts; + // 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::aod::rctsel::RCTFlagsChecker rctChecker; + + Zorro zorro; + std::vector mTOIidx; + uint64_t mNinspectedTVX{0}; + std::vector swt_names; + int mRunNumber; Service ccdb; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -159,22 +155,62 @@ struct eventQC { void init(InitContext&) { + mRunNumber = 0; ccdb->setURL(ccdburl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + rctChecker.init(cfgRCTLabel.value, cfgCheckZDC.value, cfgTreatLimitedAcceptanceAsBad.value); + addhistograms(); - if (doprocessEventQC_V0_PID) { - addV0histograms(); - } } ~eventQC() {} + template + void initCCDB(TBC const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + + mTOIidx = zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), cfg_swt_name.value); + for (auto& idx : mTOIidx) { + LOGF(info, "Trigger of Interest : index = %d", idx); + } + mNinspectedTVX = zorro.getInspectedTVX()->GetBinContent(1); + LOGF(info, "total inspected TVX events = %d in run number %d", mNinspectedTVX, bc.runNumber()); + fRegistry.fill(HIST("hNInspectedTVX"), bc.runNumber(), mNinspectedTVX); + + mRunNumber = bc.runNumber(); + } + void addhistograms() { - // event info + const AxisSpec axis_cent_ft0m{ConfCentBins, "centrality FT0M (%)"}; + const AxisSpec axis_cent_ft0a{ConfCentBins, "centrality FT0A (%)"}; + const AxisSpec axis_cent_ft0c{ConfCentBins, "centrality FT0C (%)"}; + + const AxisSpec axis_mult_ft0a{ConfFT0AMultBins, "FT0A multiplicity"}; + const AxisSpec axis_mult_ft0c{ConfFT0CMultBins, "FT0C multiplicity"}; + const AxisSpec axis_mult_fv0a{ConfFV0AMultBins, "FV0A multiplicity"}; + const AxisSpec axis_mult_ncontrib{ConfTrackMultBins, "N_{track} to PV"}; + const AxisSpec axis_mult_ncontrib08{ConfTrackMultBins, "N_{track} to PV in |#eta| < 0.8"}; + const AxisSpec axis_mult_global_ncontrib08{ConfTrackMultBins, "N_{track}^{global} to PV in |#eta| < 0.8"}; + const AxisSpec axis_mult_globalTrack{ConfTrackMultBins, "N_{track}^{global} in |#eta| < 0.8"}; + + if (doprocessEventQC_SWT) { + fRegistry.add("BC/hNcoll", "Number of collisions per triggered BC;N_{collision} per triggered BC", kTH1F, {{11, -0.5, +10.5}}, false); + fRegistry.add("BC/hDeltaT", "diff. in collision time per BC;#DeltaT_{coll} (ns)", kTH1F, {{500, -25, +25}}, false); + fRegistry.add("BC/hDeltaZ", "diff. in collision Z_{vtx} per BC;#DeltaZ_{vtx} (cm)", kTH1F, {{1000, -5, +5}}, false); + fRegistry.add("BC/hCorrNcontrib", "hMultNTracksPV;", kTH2F, {{axis_mult_ncontrib}, {axis_mult_ncontrib}}, false); + fRegistry.add("BC/Collision/hMultNTracksPV", "hMultNTracksPV;N_{track} to PV in |#eta| < 0.8", kTH1F, {{axis_mult_ncontrib08}}, false); + fRegistry.add("BC/Collision/hMultFT0AFT0C", "hMultFT0AFT0C;mult. FT0A;mult. FT0C", kTH2F, {{axis_mult_ft0a}, {axis_mult_ft0c}}, false); + fRegistry.add("BC/Collision/hMultFT0AFV0A", "hMultFT0AFV0A;mult. FT0A;mult. FV0A", kTH2F, {{axis_mult_ft0a}, {axis_mult_fv0a}}, false); + fRegistry.add("BC/Collision/hMultFT0CFV0A", "hMultFT0CFV0A;mult. FT0C;mult. FV0A", kTH2F, {{axis_mult_ft0c}, {axis_mult_fv0a}}, false); + } + // event info const int nbin_ev = 20; auto hCollisionCounter = fRegistry.add("Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{nbin_ev, 0.5, nbin_ev + 0.5}}, false); hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); @@ -198,31 +234,35 @@ struct eventQC { hCollisionCounter->GetXaxis()->SetBinLabel(19, "GoodITSLayersAll"); hCollisionCounter->GetXaxis()->SetBinLabel(nbin_ev, "accepted"); + fRegistry.add("hNInspectedTVX", "N inspected TVX;run number;N_{TVX}", kTProfile, {{80000, 520000.5, 600000.5}}, true); + if (cfgFillEvent) { fRegistry.add("Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); - fRegistry.add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry.add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry.add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, false); - fRegistry.add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry.add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry.add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry.add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{100, 0, 100}, {600, 0, 6000}}, false); - fRegistry.add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); - fRegistry.add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2F, {{60, 0, 60000}, {200, 0, 20000}}, false); - fRegistry.add("Event/before/hNTracksPVvsOccupancy", "hNTracksPVvsOccupancy;N_{track} to PV;N_{track} in time range", kTH2F, {{600, 0, 6000}, {200, 0, 20000}}, false); - fRegistry.add("Event/before/hNGlobalTracksvsOccupancy", "hNGlobalTracksvsOccupancy;N_{track}^{global};N_{track} in time range", kTH2F, {{600, 0, 6000}, {200, 0, 20000}}, false); - fRegistry.add("Event/before/hNGlobalTracksPVvsOccupancy", "hNGlobalTracksPVvsOccupancy;N_{track}^{global} to PV;N_{track} in time range", kTH2F, {{600, 0, 6000}, {200, 0, 20000}}, false); + fRegistry.add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV in |#eta| < 0.8", kTH1F, {{axis_mult_ncontrib08}}, false); + fRegistry.add("Event/before/hMultFT0AFT0C", "hMultFT0AFT0C;mult. FT0A;mult. FT0C", kTH2F, {{axis_mult_ft0a}, {axis_mult_ft0c}}, false); + fRegistry.add("Event/before/hMultFT0AFV0A", "hMultFT0AFV0A;mult. FT0A;mult. FV0A", kTH2F, {{axis_mult_ft0a}, {axis_mult_fv0a}}, false); + fRegistry.add("Event/before/hMultFT0CFV0A", "hMultFT0CFV0A;mult. FT0C;mult. FV0A", kTH2F, {{axis_mult_ft0c}, {axis_mult_fv0a}}, false); + fRegistry.add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{axis_cent_ft0a}}, false); + fRegistry.add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{axis_cent_ft0c}}, false); + fRegistry.add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{axis_cent_ft0m}}, false); + fRegistry.add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV in |#eta| < 0.8", kTH2F, {{axis_cent_ft0c}, {axis_mult_ncontrib08}}, false); + fRegistry.add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV in |#eta| < 0.8", kTH2F, {{axis_mult_ft0c}, {axis_mult_ncontrib08}}, false); + fRegistry.add("Event/before/hMultFT0CvsTrackOccupancy", "hMultFT0CvsTrackOccupancy;mult. FT0C;N_{track} in time range", kTH2F, {{axis_mult_ft0c}, {200, 0, 20000}}, false); + fRegistry.add("Event/before/hMultFV0AvsMultNTracksPV", "hMultFV0AvsMultNTracksPV;mult. FV0A;N_{track} to PV in |#eta| < 0.8", kTH2F, {{axis_mult_fv0a}, {axis_mult_ncontrib08}}, false); + fRegistry.add("Event/before/hNTracksPVvsTrackOccupancy", "hNTracksPVvsTrackOccupancy;N_{track} to PV in |#eta| < 0.8;N_{track} in time range", kTH2F, {{axis_mult_ncontrib08}, {200, 0, 20000}}, false); + fRegistry.add("Event/before/hNGlobalTracksvsTrackOccupancy", "hNGlobalTracksvsTrackOccupancy;N_{track}^{global} in |#eta| < 0.8;N_{track} in time range", kTH2F, {{axis_mult_globalTrack}, {200, 0, 20000}}, false); + fRegistry.add("Event/before/hNGlobalTracksPVvsTrackOccupancy", "hNGlobalTracksPVvsTrackOccupancy;N_{track}^{global} to PV in |#eta| < 0.8;N_{track} in time range", kTH2F, {{axis_mult_global_ncontrib08}, {200, 0, 20000}}, false); fRegistry.add("Event/before/hCorrOccupancy", "occupancy correlation;FT0C occupancy;track-based occupancy", kTH2F, {{200, 0, 200000}, {200, 0, 20000}}, false); } fRegistry.addClone("Event/before/", "Event/after/"); if (cfgFillEvent) { - fRegistry.add("Event/after/hMultNGlobalTracks", "hMultNGlobalTracks; N_{track}^{global}", kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry.add("Event/after/hCentFT0CvsMultNGlobalTracks", "hCentFT0CvsMultNGlobalTracks;centrality FT0C (%);N_{track}^{global}", kTH2F, {{100, 0, 100}, {600, 0, 6000}}, false); - fRegistry.add("Event/after/hMultFT0CvsMultNGlobalTracks", "hMultFT0CvsMultNGlobalTracks;mult. FT0C;N_{track}^{global}", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); - fRegistry.add("Event/after/hMultNGlobalTracksPV", "hMultNGlobalTracksPV; N_{track}^{global} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); - fRegistry.add("Event/after/hCentFT0CvsMultNGlobalTracksPV", "hCentFT0CvsMultNGlobalTracksPV;centrality FT0C (%);N_{track}^{global} to PV", kTH2F, {{100, 0, 100}, {600, 0, 6000}}, false); - fRegistry.add("Event/after/hMultFT0CvsMultNGlobalTracksPV", "hMultFT0CvsMultNGlobalTracksPV;mult. FT0C;N_{track}^{global} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); + fRegistry.add("Event/after/hMultNGlobalTracks", "hMultNGlobalTracks; N_{track}^{global} in |#eta| < 0.8", kTH1F, {{axis_mult_globalTrack}}, false); + fRegistry.add("Event/after/hCentFT0CvsMultNGlobalTracks", "hCentFT0CvsMultNGlobalTracks;centrality FT0C (%);N_{track}^{global} in |#eta| < 0.8", kTH2F, {{axis_cent_ft0c}, {axis_mult_globalTrack}}, false); + fRegistry.add("Event/after/hMultFT0CvsMultNGlobalTracks", "hMultFT0CvsMultNGlobalTracks;mult. FT0C;N_{track}^{global} in |#eta| < 0.8", kTH2F, {{axis_mult_ft0c}, {axis_mult_globalTrack}}, false); + fRegistry.add("Event/after/hMultNGlobalTracksPV", "hMultNGlobalTracksPV; N_{track}^{global} to PV in |#eta| < 0.8", kTH1F, {{axis_mult_global_ncontrib08}}, false); + fRegistry.add("Event/after/hCentFT0CvsMultNGlobalTracksPV", "hCentFT0CvsMultNGlobalTracksPV;centrality FT0C (%);N_{track}^{global} to PV in |#eta| < 0.8", kTH2F, {{axis_cent_ft0c}, {axis_mult_global_ncontrib08}}, false); + fRegistry.add("Event/after/hMultFT0CvsMultNGlobalTracksPV", "hMultFT0CvsMultNGlobalTracksPV;mult. FT0C;N_{track}^{global} to PV in |#eta| < 0.8", kTH2F, {{axis_mult_ft0c}, {axis_mult_global_ncontrib08}}, false); } std::vector tmp_ptbins; @@ -235,7 +275,7 @@ struct eventQC { const AxisSpec axis_pt_tmp{tmp_ptbins, "p_{T} (GeV/c)"}; const AxisSpec axis_pt{ConfPtBins, "p_{T} (GeV/c)"}; - const AxisSpec axis_eta{cfgNbinsEta, -1.0, +1.0, "#eta"}; + const AxisSpec axis_eta{cfgNbinsEta, -2.0, +2.0, "#eta"}; const AxisSpec axis_phi{cfgNbinsPhi, 0.0, 2 * M_PI, "#varphi (rad.)"}; const AxisSpec axis_sign{3, -1.5, +1.5, "sign"}; const AxisSpec axis_cent{20, 0, 100, "centrality FT0C (%)"}; @@ -322,9 +362,6 @@ struct eventQC { fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5.f, +5.f}}, false); fRegistry.add("Track/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5.f, +5.f}}, false); fRegistry.add("Track/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5.f, +5.f}}, false); - if (doprocessEventQC_V0_PID) { - fRegistry.add("Track/hsEID", "TPC n sigma el;p_{in} (GeV/c);#eta;n #sigma_{e}^{TPC};", kTHnSparseF, {{200, 0, 10}, {20, -1, +1}, {100, -5, +5}}, false); - } fRegistry.add("Track/hTOFbeta", "TOF #beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); @@ -332,38 +369,10 @@ struct eventQC { fRegistry.add("Track/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - if (cfgFillPIDITS) { - fRegistry.add("Track/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/hITSNsigmaEl", "ITS n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaMu", "ITS n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaPi", "ITS n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaKa", "ITS n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hITSNsigmaPr", "ITS n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{ITS}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - } + fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {150, 0, 15}}, false); } } - void addV0histograms() - { - fRegistry.add("V0/hAP", "AP plot", kTH2F, {{200, -1, +1}, {250, 0, 0.25}}, false); - fRegistry.add("V0/hPCA", "distance between 2 legs", kTH1F, {{200, 0, 2}}, false); - fRegistry.add("V0/hCosPA", "cos pointing angle", kTH1F, {{100, 0.99, 1}}, false); - fRegistry.add("V0/hRadius", "radius", kTH1F, {{200, 0, 20}}, false); - fRegistry.add("V0/K0S/pion/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("V0/K0S/pion/hsEID", "TPC n sigma el;p_{in} (GeV/c);#eta;n #sigma_{e}^{TPC};", kTHnSparseF, {{200, 0, 10}, {20, -1, +1}, {100, -5, +5}}, false); - - fRegistry.add("V0/K0S/hMass", "mass vs. p_{T} of K^{0}_{S}", kTH2F, {{200, 0.4, 0.6}, {100, 0, 10}}, false); - fRegistry.add("V0/Lambda/hMass", "mass vs. p_{T} of #Lambda", kTH2F, {{100, 1.08, 1.18}, {100, 0, 10}}, false); - fRegistry.add("V0/AntiLambda/hMass", "mass vs. p_{T} of #bar{#Lambda}", kTH2F, {{100, 1.08, 1.18}, {100, 0, 10}}, false); - fRegistry.add("V0/GammaTMP/hMass", "mass vs. p_{T} of #gamma", kTH2F, {{100, 0.0, 0.1}, {100, 0, 10}}, false); - - fRegistry.add("V0/Photon/hMass", "mass vs. p_{T}", kTH2F, {{100, 0, 0.1}, {100, 0, 10}}, false); - fRegistry.add("V0/Photon/hChi2", "radius vs. KF chi2", kTH2F, {{100, 0, 100}, {100, 0, 100}}, false); - fRegistry.add("V0/Photon/hXY", "photon conversion point;X (cm);Y(cm)", kTH2F, {{400, -100, +100}, {400, -100, 100}}, false); - fRegistry.add("V0/Photon/electron/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); - fRegistry.add("V0/Photon/electron/hsEID", "TPC n sigma el;p_{in} (GeV/c);#eta;n #sigma_{e}^{TPC};", kTHnSparseF, {{200, 0, 10}, {20, -1, +1}, {100, -5, +5}}, false); - } - template void fillTrackInfo(TTrack const& track) { @@ -402,21 +411,11 @@ struct eventQC { fRegistry.fill(HIST("Track/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); fRegistry.fill(HIST("Track/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); - if (cfgFillPIDITS) { - int nsize = 0; - for (int il = 0; il < 7; il++) { - nsize += track.itsClsSizeInLayer(il); - } - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(nsize) / static_cast(track.itsNCls()) * std::cos(std::atan(track.tgl()))); - fRegistry.fill(HIST("Track/hITSNsigmaEl"), track.p(), track.itsNSigmaEl()); - fRegistry.fill(HIST("Track/hITSNsigmaMu"), track.p(), track.itsNSigmaMu()); - fRegistry.fill(HIST("Track/hITSNsigmaPi"), track.p(), track.itsNSigmaPi()); - fRegistry.fill(HIST("Track/hITSNsigmaKa"), track.p(), track.itsNSigmaKa()); - fRegistry.fill(HIST("Track/hITSNsigmaPr"), track.p(), track.itsNSigmaPr()); + int nsize = 0; + for (int il = 0; il < 7; il++) { + nsize += track.itsClsSizeInLayer(il); } - } - if (doprocessEventQC_V0_PID) { - fRegistry.fill(HIST("Track/hsEID"), track.tpcInnerParam(), track.eta(), track.tpcNSigmaEl()); + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(nsize) / static_cast(track.itsNCls()) * std::cos(std::atan(track.tgl()))); } } @@ -481,11 +480,13 @@ struct eventQC { 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("hMultFT0AFT0C"), collision.multFT0A(), collision.multFT0C()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0AFV0A"), collision.multFT0A(), collision.multFV0A()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CFV0A"), collision.multFT0C(), collision.multFV0A()); fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange()); - fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hNTracksPVvsOccupancy"), collision.multNTracksPV(), collision.trackOccupancyInTimeRange()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFV0AvsMultNTracksPV"), collision.multFV0A(), collision.multNTracksPV()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsTrackOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange()); + fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hNTracksPVvsTrackOccupancy"), collision.multNTracksPV(), collision.trackOccupancyInTimeRange()); fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCorrOccupancy"), collision.ft0cOccupancyInTimeRange(), collision.trackOccupancyInTimeRange()); fRegistry.fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A"), collision.centFT0A()); @@ -738,40 +739,6 @@ struct eventQC { return true; } - template - bool isSelectedV0Leg(TTrack const& track) - { - if (!track.hasTPC()) { - return false; - } - - if (track.hasITS() && track.itsChi2NCl() > v0cuts.cfg_max_chi2its) { - return false; - } - - if (track.tpcChi2NCl() > v0cuts.cfg_max_chi2tpc) { - return false; - } - - if (track.tpcNClsFound() < v0cuts.cfg_min_ncluster_tpc) { - return false; - } - - if (track.tpcNClsCrossedRows() < v0cuts.cfg_min_ncrossedrows_tpc) { - 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; - } - - return true; - } - template bool isSelectedEvent(TCollision const& collision) { @@ -795,6 +762,14 @@ struct eventQC { 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.cfgRequireNoSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { return false; } @@ -846,8 +821,10 @@ struct eventQC { return true; } - Filter collisionFilter_evsel = o2::aod::evsel::sel8 == true && (eventcuts.cfgZvtxMin < o2::aod::collision::posZ && o2::aod::collision::posZ < eventcuts.cfgZvtxMax); + Filter collisionFilter_evsel = ifnode(eventcuts.cfgRequireSel8.node(), o2::aod::evsel::sel8 == true, true); + Filter collisionFilter_zvtx = eventcuts.cfgZvtxMin < o2::aod::collision::posZ && o2::aod::collision::posZ < eventcuts.cfgZvtxMax; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); + Filter collisionFilter_multiplicity = cfgNtracksPV08Min <= o2::aod::mult::multNTracksPV && o2::aod::mult::multNTracksPV < cfgNtracksPV08Max; 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; using FilteredMyCollisions = soa::Filtered; @@ -861,18 +838,57 @@ struct eventQC { SliceCache cache; Preslice perCol = o2::aod::track::collisionId; - Preslice perCol_pcm = o2::aod::v0photonkf::collisionId; - Preslice perCol_v0 = o2::aod::v0data::collisionId; - Preslice perCol_casc = o2::aod::cascdata::collisionId; + Preslice perBC = o2::aod::collision::bcId; - template - void runQC(TCollisions const& collisions, TTracks const& tracks, TV0Photons const& v0photons, TV0Legs const&, TV0StrHadrons const& v0strhadrons) + template + void runQC(TBCs const& bcs, TCollisions const& collisions, TTracks const& tracks) { - for (auto& collision : collisions) { + if constexpr (isTriggerAnalysis) { + for (const auto& bc : bcs) { + initCCDB(bc); + if (!zorro.isSelected(bc.globalBC())) { // triggered BC + continue; + } + + // if (!bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + // continue; + // } + + const auto& collisions_per_bc = collisions.sliceBy(perBC, bc.globalIndex()); + fRegistry.fill(HIST("BC/hNcoll"), collisions_per_bc.size()); + for (const auto& collision : collisions_per_bc) { + fRegistry.fill(HIST("BC/Collision/hMultNTracksPV"), collision.multNTracksPV()); + fRegistry.fill(HIST("BC/Collision/hMultFT0AFT0C"), collision.multFT0A(), collision.multFT0C()); + fRegistry.fill(HIST("BC/Collision/hMultFT0AFV0A"), collision.multFT0A(), collision.multFV0A()); + fRegistry.fill(HIST("BC/Collision/hMultFT0CFV0A"), collision.multFT0C(), collision.multFV0A()); + } + + for (const auto& [col1, col2] : combinations(CombinationsStrictlyUpperIndexPolicy(collisions_per_bc, collisions_per_bc))) { + fRegistry.fill(HIST("BC/hDeltaZ"), col1.posZ() - col2.posZ()); + fRegistry.fill(HIST("BC/hDeltaT"), col1.collisionTime() - col2.collisionTime()); + fRegistry.fill(HIST("BC/hCorrNcontrib"), col1.numContrib(), col2.numContrib()); + } // end of pairing + } // end of bc loop + } + + for (const auto& collision : collisions) { + if constexpr (isTriggerAnalysis) { + const auto& bc = collision.template bc_as(); // don't use foundBC for CEFP. + initCCDB(bc); + if (!zorro.isSelected(bc.globalBC())) { // triggered event + continue; + } + } + const float centralities[3] = {collision.centFT0M(), collision.centFT0A(), collision.centFT0C()}; if (centralities[cfgCentEstimator] < cfgCentMin || cfgCentMax < centralities[cfgCentEstimator]) { continue; } + + if (cfgRequireGoodRCT && !rctChecker.checkTable(collision)) { + continue; + } + if (cfgFillEvent) { fillEventInfo<0>(collision); } @@ -887,7 +903,7 @@ struct eventQC { int nGlobalTracks = 0, nGlobalTracksPV = 0; auto tracks_per_coll = tracks.sliceBy(perCol, collision.globalIndex()); - for (auto& track : tracks_per_coll) { + for (const auto& track : tracks_per_coll) { if (!isSelectedTrack(track)) { continue; } @@ -918,145 +934,32 @@ struct eventQC { fRegistry.fill(HIST("Event/after/hMultNGlobalTracksPV"), nGlobalTracksPV); fRegistry.fill(HIST("Event/after/hMultFT0CvsMultNGlobalTracks"), collision.multFT0C(), nGlobalTracks); fRegistry.fill(HIST("Event/after/hMultFT0CvsMultNGlobalTracksPV"), collision.multFT0C(), nGlobalTracksPV); - fRegistry.fill(HIST("Event/after/hNGlobalTracksvsOccupancy"), nGlobalTracks, collision.trackOccupancyInTimeRange()); - fRegistry.fill(HIST("Event/after/hNGlobalTracksPVvsOccupancy"), nGlobalTracksPV, collision.trackOccupancyInTimeRange()); + fRegistry.fill(HIST("Event/after/hNGlobalTracksvsTrackOccupancy"), nGlobalTracks, collision.trackOccupancyInTimeRange()); + fRegistry.fill(HIST("Event/after/hNGlobalTracksPVvsTrackOccupancy"), nGlobalTracksPV, collision.trackOccupancyInTimeRange()); fRegistry.fill(HIST("Event/after/hCentFT0CvsMultNGlobalTracks"), collision.centFT0C(), nGlobalTracks); fRegistry.fill(HIST("Event/after/hCentFT0CvsMultNGlobalTracksPV"), collision.centFT0C(), nGlobalTracksPV); } - // for V0 PID - if constexpr (doV0s) { - auto v0hadrons_per_coll = v0strhadrons.sliceBy(perCol_v0, collision.globalIndex()); - for (auto& v0hadron : v0hadrons_per_coll) { - if (v0hadron.dcaV0daughters() > v0cuts.cfg_max_pca_v0hadron || v0hadron.v0cosPA() < v0cuts.cfg_min_cospa_v0hadron || v0hadron.v0radius() < v0cuts.cfg_min_radius_v0hadron) { - continue; - } - - fRegistry.fill(HIST("V0/hAP"), v0hadron.alpha(), v0hadron.qtarm()); - fRegistry.fill(HIST("V0/hPCA"), v0hadron.dcaV0daughters()); - fRegistry.fill(HIST("V0/hCosPA"), v0hadron.v0cosPA()); - fRegistry.fill(HIST("V0/hRadius"), v0hadron.v0radius()); - - fRegistry.fill(HIST("V0/K0S/hMass"), v0hadron.mK0Short(), v0hadron.pt()); - if (v0cuts.cfg_min_mass_k0s < v0hadron.mK0Short() && v0hadron.mK0Short() < v0cuts.cfg_max_mass_k0s) { // K0S - fRegistry.fill(HIST("V0/GammaTMP/hMass"), v0hadron.mGamma(), v0hadron.pt()); - fRegistry.fill(HIST("V0/Lambda/hMass"), v0hadron.mLambda(), v0hadron.pt()); - fRegistry.fill(HIST("V0/AntiLambda/hMass"), v0hadron.mAntiLambda(), v0hadron.pt()); - if (v0cuts.cfg_min_mass_lambda < v0hadron.mLambda() && v0hadron.mLambda() < v0cuts.cfg_max_mass_lambda) { // Lambda rejection - continue; - } - if (v0cuts.cfg_min_mass_lambda < v0hadron.mAntiLambda() && v0hadron.mAntiLambda() < v0cuts.cfg_max_mass_lambda) { // AntiLambda rejection - continue; - } - if (v0cuts.cfg_min_mass_photon < v0hadron.mGamma() && v0hadron.mGamma() < v0cuts.cfg_max_mass_photon) { // photon conversion rejection - continue; - } - - auto pos = tracks.rawIteratorAt(v0hadron.posTrackId()); - auto neg = tracks.rawIteratorAt(v0hadron.negTrackId()); - if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg)) { - continue; - } - if (!pos.hasITS() || !neg.hasITS()) { - continue; - } - if (std::fabs(pos.dcaXY()) < v0cuts.cfg_min_dcaxy_v0leg || std::fabs(neg.dcaXY()) < v0cuts.cfg_min_dcaxy_v0leg) { - continue; - } - - // if (pos.tpcNSigmaPi() < v0cuts.cfg_min_TPCNsigmaPi || v0cuts.cfg_max_TPCNsigmaPi < pos.tpcNSigmaPi()) { - // continue; - // } - // if (neg.tpcNSigmaPi() < v0cuts.cfg_min_TPCNsigmaPi || v0cuts.cfg_max_TPCNsigmaPi < neg.tpcNSigmaPi()) { - // continue; - // } - - bool isTPCOK_pos = pos.hasTPC() && v0cuts.cfg_min_TPCNsigmaPi < pos.tpcNSigmaPi() && pos.tpcNSigmaPi() < v0cuts.cfg_max_TPCNsigmaPi; - bool isTPCOK_neg = neg.hasTPC() && v0cuts.cfg_min_TPCNsigmaPi < neg.tpcNSigmaPi() && neg.tpcNSigmaPi() < v0cuts.cfg_max_TPCNsigmaPi; - bool isTOFOK_pos = pos.hasTOF() && pos.tofChi2() < v0cuts.cfg_max_chi2tof && v0cuts.cfg_min_TOFNsigmaPi < pos.tofNSigmaPi() && pos.tofNSigmaPi() < v0cuts.cfg_max_TOFNsigmaPi; - bool isTOFOK_neg = neg.hasTOF() && neg.tofChi2() < v0cuts.cfg_max_chi2tof && v0cuts.cfg_min_TOFNsigmaPi < neg.tofNSigmaPi() && neg.tofNSigmaPi() < v0cuts.cfg_max_TOFNsigmaPi; - - if (isTPCOK_neg && isTOFOK_neg) { // K0S is tagged by neg and pos is probe. - fRegistry.fill(HIST("V0/K0S/pion/hTPCdEdx"), pos.tpcInnerParam(), pos.tpcSignal()); - fRegistry.fill(HIST("V0/K0S/pion/hsEID"), pos.tpcInnerParam(), pos.eta(), pos.tpcNSigmaEl()); - } - if (isTPCOK_pos && isTOFOK_pos) { // K0S is tagged by pos and neg is probe. - fRegistry.fill(HIST("V0/K0S/pion/hTPCdEdx"), neg.tpcInnerParam(), neg.tpcSignal()); - fRegistry.fill(HIST("V0/K0S/pion/hsEID"), neg.tpcInnerParam(), neg.eta(), neg.tpcNSigmaEl()); - } - } // end of K0S - } // end of v0hadron loop - - auto v0photons_per_coll = v0photons.sliceBy(perCol_pcm, collision.globalIndex()); - for (auto& v0photon : v0photons_per_coll) { - if (v0photon.chiSquareNDF() > v0cuts.cfg_max_kfchi2) { - continue; - } - - fRegistry.fill(HIST("V0/Photon/hMass"), v0photon.mGamma(), v0photon.pt()); - fRegistry.fill(HIST("V0/Photon/hXY"), v0photon.vx(), v0photon.vy()); - fRegistry.fill(HIST("V0/Photon/hChi2"), v0photon.v0radius(), v0photon.chiSquareNDF()); - auto pos_v0leg = v0photon.template posTrack_as(); - auto neg_v0leg = v0photon.template negTrack_as(); - auto pos = tracks.rawIteratorAt(pos_v0leg.trackId()); - auto neg = tracks.rawIteratorAt(neg_v0leg.trackId()); - - if (!isSelectedV0Leg(pos) || !isSelectedV0Leg(neg)) { - continue; - } - if (std::fabs(pos.dcaXY()) < v0cuts.cfg_min_dcaxy_v0leg || std::fabs(neg.dcaXY()) < v0cuts.cfg_min_dcaxy_v0leg) { - continue; - } - - // if (pos.tpcNSigmaEl() < v0cuts.cfg_min_TPCNsigmaEl || v0cuts.cfg_max_TPCNsigmaEl < pos.tpcNSigmaEl()) { - // continue; - // } - // if (neg.tpcNSigmaEl() < v0cuts.cfg_min_TPCNsigmaEl || v0cuts.cfg_max_TPCNsigmaEl < neg.tpcNSigmaEl()) { - // continue; - // } - - bool isTPCOK_pos = pos.hasTPC() && v0cuts.cfg_min_TPCNsigmaEl < pos.tpcNSigmaEl() && pos.tpcNSigmaEl() < v0cuts.cfg_max_TPCNsigmaEl; - bool isTPCOK_neg = neg.hasTPC() && v0cuts.cfg_min_TPCNsigmaEl < neg.tpcNSigmaEl() && neg.tpcNSigmaEl() < v0cuts.cfg_max_TPCNsigmaEl; - bool isTOFOK_pos = pos.hasTOF() && pos.tofChi2() < v0cuts.cfg_max_chi2tof && v0cuts.cfg_min_TOFNsigmaEl < pos.tofNSigmaEl() && pos.tofNSigmaEl() < v0cuts.cfg_max_TOFNsigmaEl; - bool isTOFOK_neg = neg.hasTOF() && neg.tofChi2() < v0cuts.cfg_max_chi2tof && v0cuts.cfg_min_TOFNsigmaEl < neg.tofNSigmaEl() && neg.tofNSigmaEl() < v0cuts.cfg_max_TOFNsigmaEl; - - if (isTPCOK_neg && isTOFOK_neg) { // photon conversion is tagged by neg and pos is probe. - fRegistry.fill(HIST("V0/Photon/electron/hTPCdEdx"), pos.tpcInnerParam(), pos.tpcSignal()); - fRegistry.fill(HIST("V0/Photon/electron/hsEID"), pos.tpcInnerParam(), pos.eta(), pos.tpcNSigmaEl()); - } - if (isTPCOK_pos && isTOFOK_pos) { // photon conversion is tagged by pos and neg is probe. - fRegistry.fill(HIST("V0/Photon/electron/hTPCdEdx"), neg.tpcInnerParam(), neg.tpcSignal()); - fRegistry.fill(HIST("V0/Photon/electron/hsEID"), neg.tpcInnerParam(), neg.eta(), neg.tpcNSigmaEl()); - } - } // end of v0photon loop - } // end of V0 PID } // end of collision loop } // end of process - void processEventQC(FilteredMyCollisions const& collisions, FilteredMyTracks const& tracks) + void processEventQC(MyBCs const& bcs, FilteredMyCollisions const& collisions, FilteredMyTracks const& tracks) { - auto tracksWithITSPid = soa::Attach(tracks); - runQC(collisions, tracksWithITSPid, nullptr, nullptr, nullptr); + runQC(bcs, collisions, tracks); } PROCESS_SWITCH(eventQC, processEventQC, "event QC", true); - void processEventQC_Cent_Qvec(FilteredMyCollisions_Qvec const& collisions, FilteredMyTracks const& tracks) + void processEventQC_SWT(MyBCs const& bcs, FilteredMyCollisions const& collisions, FilteredMyTracks const& tracks) { - auto tracksWithITSPid = soa::Attach(tracks); - runQC(collisions, tracksWithITSPid, nullptr, nullptr, nullptr); + runQC(bcs, collisions, tracks); } - PROCESS_SWITCH(eventQC, processEventQC_Cent_Qvec, "event QC + q vector", false); + PROCESS_SWITCH(eventQC, processEventQC_SWT, "event QC", false); - //! 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_v0hadron&& o2::aod::v0data::dcaV0daughters < v0cuts.cfg_max_pca_v0hadron; - using filteredV0s = soa::Filtered; - - void processEventQC_V0_PID(FilteredMyCollisions const& collisions, FilteredMyTracks const& tracks, aod::V0PhotonsKF const& v0photons, aod::V0Legs const& v0legs, filteredV0s const& v0strhadrons) + void processEventQC_Cent_Qvec(MyBCs const& bcs, FilteredMyCollisions_Qvec const& collisions, FilteredMyTracks const& tracks) { - auto tracksWithITSPid = soa::Attach(tracks); - runQC(collisions, tracksWithITSPid, v0photons, v0legs, v0strhadrons); + runQC(bcs, collisions, tracks); } - PROCESS_SWITCH(eventQC, processEventQC_V0_PID, "event QC + V0 PID", false); + PROCESS_SWITCH(eventQC, processEventQC_Cent_Qvec, "event QC + q vector", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/Dilepton/Tasks/matchingMFT.cxx b/PWGEM/Dilepton/Tasks/matchingMFT.cxx index 0a9ee91a4c0..99a0db783e2 100644 --- a/PWGEM/Dilepton/Tasks/matchingMFT.cxx +++ b/PWGEM/Dilepton/Tasks/matchingMFT.cxx @@ -13,32 +13,33 @@ /// \brief a task to study matching MFT-[MCH-MID] in MC /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include - -#include "Framework/DataTypes.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #include "TableHelper.h" + +#include "Common/CCDB/RCTSelectionFlags.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 "TGeoGlobalMagField.h" -#include "Field/MagneticField.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 "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/fwdtrackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/CCDB/RCTSelectionFlags.h" +#include "TGeoGlobalMagField.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -88,7 +89,7 @@ struct matchingMFT { // for RCT Configurable cfgRequireGoodRCT{"cfgRequireGoodRCT", false, "require good detector flag in run condtion table"}; - Configurable cfgRCTLabel{"cfgRCTLabel", "CBT_muon_glo", "select 1 [CBT, CBT_hadron, CBT_muon_glo] see O2Physics/Common/CCDB/RCTSelectionFlags.h"}; + 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"}; @@ -125,7 +126,7 @@ struct matchingMFT { } mRunNumber = bc.runNumber(); LOGF(info, "mRunNumber = %d", mRunNumber); - std::map metadata; + std::map metadata; auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(ccdbApi, mRunNumber); auto ts = soreor.first; auto grpmag = ccdbApi.retrieveFromTFileAny(grpmagPath, metadata, ts); @@ -172,7 +173,7 @@ struct matchingMFT { 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}, {100, 0.0f, 1000}}, false); - fRegistry.add("MFTMCHMID/primary/correct/hChi2", "chi2;chi2", kTH1F, {{100, 0.0f, 100}}, 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); @@ -198,7 +199,7 @@ struct matchingMFT { fRegistry.addClone("MFTMCHMID/primary/", "MFTMCHMID/secondary/"); } - bool isSelected(const float pt, const float eta, const float rAtAbsorberEnd, const float pDCA, const float chi2, const uint8_t trackType, const float dcaXY) + 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) { if (pt < minPt || maxPt < pt) { return false; @@ -217,14 +218,14 @@ struct matchingMFT { if (maxDCAxy < dcaXY) { return false; } - if (chi2 < 0.f || maxChi2GL < chi2) { + 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; } - if (chi2 < 0.f || maxChi2SA < chi2) { + if (chi2_per_ndf < 0.f || maxChi2SA < chi2_per_ndf) { return false; } } else { @@ -299,11 +300,17 @@ struct matchingMFT { // LOGF(info, "mcParticle_MFTMCHMID.pdgCode() = %d, mcParticle_MCHMID.pdgCode() = %d, mcParticle_MFT.pdgCode() = %d", mcParticle_MFTMCHMID.pdgCode(), mcParticle_MCHMID.pdgCode(), mcParticle_MFT.pdgCode()); // LOGF(info, "mcParticle_MFTMCHMID.globalIndex() = %d, mcParticle_MCHMID.globalIndex() = %d, mcParticle_MFT.globalIndex() = %d", mcParticle_MFTMCHMID.globalIndex(), mcParticle_MCHMID.globalIndex(), mcParticle_MFT.globalIndex()); + int nClustersMFT = mfttrack.nClusters(); + float chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); + if (chi2mft < 0.f || maxChi2MFT < chi2mft) { + return; + } + if (fwdtrack.chi2MatchMCHMFT() > maxMatchingChi2MCHMFT) { return; } - if (fwdtrack.chi2() < 0.f || maxChi2GL < fwdtrack.chi2()) { + if (fwdtrack.chi2() < 0.f || maxChi2GL < fwdtrack.chi2() / (2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f)) { return; } @@ -311,7 +318,7 @@ struct matchingMFT { return; } - if (mfttrack.nClusters() < minNclustersMFT) { + if (nClustersMFT < minNclustersMFT) { return; } @@ -359,12 +366,6 @@ struct matchingMFT { 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; - int nClustersMFT = mfttrack.nClusters(); - float chi2mft = mfttrack.chi2() / (2.f * nClustersMFT - 5.f); - // float chi2mft = mfttrack.chi2(); - if (chi2mft < 0.f || maxChi2MFT < chi2mft) { - return; - } o2::dataformats::GlobalFwdTrack propmuonAtPV_Matched = propagateMuon(mchtrack, collision, propagationPoint::kToVertex); if (refitGlobalMuon) { @@ -387,7 +388,7 @@ struct matchingMFT { return; } - if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2(), fwdtrack.trackType(), dcaXY)) { + if (!isSelected(pt, eta, rAtAbsorberEnd, pDCA, fwdtrack.chi2() / (2.f * (mchtrack.nClusters() + nClustersMFT) - 5.f), fwdtrack.trackType(), dcaXY)) { return; } @@ -414,7 +415,7 @@ 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()); + 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()); @@ -451,7 +452,7 @@ 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()); + 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()); @@ -489,7 +490,7 @@ 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()); + 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()); @@ -525,7 +526,7 @@ 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()); + 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()); diff --git a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx index 5ac01703a06..d3a12ec6481 100644 --- a/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx +++ b/PWGEM/Dilepton/Tasks/prefilterDielectron.cxx @@ -14,32 +14,33 @@ // This code produces information on prefilter for dielectron. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include -#include -#include +#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 "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.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 "PWGEM/Dilepton/DataModel/dileptonTables.h" -#include "PWGEM/Dilepton/Core/DielectronCut.h" -#include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -52,7 +53,7 @@ using namespace o2::aod::pwgem::dilepton::utils::pairutil; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; struct prefilterDielectron { @@ -101,12 +102,14 @@ struct prefilterDielectron { Configurable cfg_max_phiv{"cfg_max_phiv", 3.2, "max phiv"}; // region to be rejected // 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_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_apply_detadphiposition_uls{"cfg_apply_detadphiposition_uls", false, "flag to apply generator deta-dphi elliptic cut in ULS"}; // region to be rejected + Configurable cfg_apply_detadphiposition_ls{"cfg_apply_detadphiposition_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_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"}; @@ -127,16 +130,15 @@ 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_p_its_cluster_size{"cfg_min_p_its_cluster_size", 0.0, "min p to apply ITS cluster size cut"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.0, "max p to apply ITS cluster size cut"}; 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]"}; 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_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"}; @@ -146,6 +148,8 @@ struct prefilterDielectron { Configurable cfg_min_TOFNsigmaEl{"cfg_min_TOFNsigmaEl", -3.0, "min. TOF n sigma for electron inclusion"}; Configurable cfg_max_TOFNsigmaEl{"cfg_max_TOFNsigmaEl", +3.0, "max. TOF n sigma for electron inclusion"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + 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)"}; @@ -169,6 +173,19 @@ struct prefilterDielectron { void init(InitContext& /*context*/) { + if (dielectroncuts.cfg_apply_detadphi_ls && dielectroncuts.cfg_apply_detadphiposition_ls) { + LOG(fatal) << "Please choose deta-dphi prefiter either at PV or certain radius"; + } + if (dielectroncuts.cfg_apply_detadphi_uls && dielectroncuts.cfg_apply_detadphiposition_uls) { + LOG(fatal) << "Please choose deta-dphi prefiter either at PV or certain radius"; + } + if (dielectroncuts.cfg_apply_detadphi_uls && dielectroncuts.cfg_apply_detadphiposition_ls) { + LOG(fatal) << "Please choose deta-dphi prefiter either at PV or certain radius"; + } + if (dielectroncuts.cfg_apply_detadphi_ls && dielectroncuts.cfg_apply_detadphiposition_uls) { + LOG(fatal) << "Please choose deta-dphi prefiter either at PV or certain radius"; + } + DefineEMEventCut(); DefineDielectronCut(); addhistograms(); @@ -236,6 +253,7 @@ struct prefilterDielectron { fRegistry.add("Pair/before/uls/hMvsPt", "m_{ee} vs. p_{T,ee}", kTH2D, {axis_mass, axis_pair_pt}, true); fRegistry.add("Pair/before/uls/hMvsPhiV", "m_{ee} vs. #varphi_{V};#varphi_{V} (rad.);m_{ee} (GeV/c^{2})", kTH2D, {axis_phiv, {200, 0, 1}}, 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}, {200, -1, +1}}, true); + fRegistry.add("Pair/before/uls/hDeltaEtaDeltaPhiPosition", "#Delta#eta-#Delta#varphi^{*} between 2 tracks;#Delta#varphi^{*} (rad.);#Delta#eta;", kTH2D, {{180, -M_PI, M_PI}, {200, -1, +1}}, true); fRegistry.addClone("Pair/before/uls/", "Pair/before/lspp/"); fRegistry.addClone("Pair/before/uls/", "Pair/before/lsmm/"); fRegistry.addClone("Pair/before/", "Pair/after/"); @@ -265,7 +283,7 @@ struct prefilterDielectron { fDielectronCut.SetPairDCARange(0.f, 1e+10); // in sigma fDielectronCut.ApplyPhiV(false); fDielectronCut.ApplyPrefilter(false); - fDielectronCut.SetMindEtadPhi(false, 1.f, 1.f); + fDielectronCut.SetMindEtadPhi(false, false, 1.f, 1.f); fDielectronCut.SetPairOpAng(0.f, 3.2f); fDielectronCut.SetRequireDifferentSides(false); @@ -280,18 +298,19 @@ struct prefilterDielectron { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_min_p_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + 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, 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.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); @@ -381,9 +400,18 @@ struct prefilterDielectron { float dphi = pos.sign() * v1.Pt() > ele.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); o2::math_utils::bringToPMPi(dphi); + float phiPosition1 = pos.phi() + std::asin(pos.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * pos.pt())); + float phiPosition2 = ele.phi() + std::asin(ele.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * ele.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = pos.sign() * v1.Pt() > ele.sign() * v2.Pt() ? phiPosition1 - phiPosition2 : phiPosition2 - phiPosition1; + o2::math_utils::bringToPMPi(dphiPosition); + fRegistry.fill(HIST("Pair/before/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/uls/hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/before/uls/hDeltaEtaDeltaPhi"), dphi, deta); + fRegistry.fill(HIST("Pair/before/uls/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta); if (dielectroncuts.cfg_min_mass < v12.M() && v12.M() < dielectroncuts.cfg_max_mass) { map_pfb[pos.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kMee); @@ -395,11 +423,18 @@ struct prefilterDielectron { map_pfb[ele.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kPhiV); } - if (dielectroncuts.cfg_apply_detadphi_uls && std::pow(deta / dielectroncuts.cfg_min_deta_uls, 2) + std::pow(dphi / dielectroncuts.cfg_min_dphi_uls, 2) < 1.f) { - map_pfb[pos.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); - map_pfb[ele.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + if (dielectroncuts.cfg_apply_detadphiposition_uls) { + if (std::pow(deta / dielectroncuts.cfg_min_deta_uls, 2) + std::pow(dphiPosition / dielectroncuts.cfg_min_dphi_uls, 2) < 1.f) { + map_pfb[pos.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + map_pfb[ele.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + } + } else if (dielectroncuts.cfg_apply_detadphi_uls) { + if (std::pow(deta / dielectroncuts.cfg_min_deta_uls, 2) + std::pow(dphi / dielectroncuts.cfg_min_dphi_uls, 2) < 1.f) { + map_pfb[pos.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + map_pfb[ele.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackULS); + } } - } + } // end of ULS pairing for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ if (!fDielectronCut.IsSelectedTrack(pos1) || !fDielectronCut.IsSelectedTrack(pos2)) { @@ -415,15 +450,31 @@ struct prefilterDielectron { float dphi = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); o2::math_utils::bringToPMPi(dphi); + float phiPosition1 = pos1.phi() + std::asin(pos1.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * pos1.pt())); + float phiPosition2 = pos2.phi() + std::asin(pos2.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * pos2.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? phiPosition1 - phiPosition2 : phiPosition2 - phiPosition1; + o2::math_utils::bringToPMPi(dphiPosition); + fRegistry.fill(HIST("Pair/before/lspp/hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/before/lspp/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/lspp/hDeltaEtaDeltaPhi"), dphi, deta); - - if (dielectroncuts.cfg_apply_detadphi_ls && std::pow(deta / dielectroncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dielectroncuts.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); + fRegistry.fill(HIST("Pair/before/lspp/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta); + + if (dielectroncuts.cfg_apply_detadphiposition_ls) { + if (std::pow(deta / dielectroncuts.cfg_min_deta_ls, 2) + std::pow(dphiPosition / dielectroncuts.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); + } + } else if (dielectroncuts.cfg_apply_detadphi_ls) { + if (std::pow(deta / dielectroncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dielectroncuts.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 (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- if (!fDielectronCut.IsSelectedTrack(ele1) || !fDielectronCut.IsSelectedTrack(ele2)) { @@ -439,15 +490,31 @@ struct prefilterDielectron { float dphi = ele1.sign() * v1.Pt() > ele2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); o2::math_utils::bringToPMPi(dphi); + float phiPosition1 = ele1.phi() + std::asin(ele1.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * ele1.pt())); + float phiPosition2 = ele2.phi() + std::asin(ele2.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * ele2.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = ele1.sign() * v1.Pt() > ele2.sign() * v2.Pt() ? phiPosition1 - phiPosition2 : phiPosition2 - phiPosition1; + o2::math_utils::bringToPMPi(dphiPosition); + fRegistry.fill(HIST("Pair/before/lsmm/hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/before/lsmm/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/before/lsmm/hDeltaEtaDeltaPhi"), dphi, deta); - - if (dielectroncuts.cfg_apply_detadphi_ls && std::pow(deta / dielectroncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dielectroncuts.cfg_min_dphi_ls, 2) < 1.f) { - map_pfb[ele1.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); - map_pfb[ele2.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + fRegistry.fill(HIST("Pair/before/lsmm/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta); + + if (dielectroncuts.cfg_apply_detadphiposition_ls) { + if (std::pow(deta / dielectroncuts.cfg_min_deta_ls, 2) + std::pow(dphiPosition / dielectroncuts.cfg_min_dphi_ls, 2) < 1.f) { + map_pfb[ele1.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + map_pfb[ele2.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + } + } else if (dielectroncuts.cfg_apply_detadphi_ls) { + if (std::pow(deta / dielectroncuts.cfg_min_deta_ls, 2) + std::pow(dphi / dielectroncuts.cfg_min_dphi_ls, 2) < 1.f) { + map_pfb[ele1.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + map_pfb[ele2.globalIndex()] |= 1 << static_cast(o2::aod::pwgem::dilepton::utils::pairutil::DileptonPrefilterBitDerived::kSplitOrMergedTrackLS); + } } - } + } // end of LS-- pairing } // end of collision loop @@ -486,9 +553,18 @@ struct prefilterDielectron { float dphi = pos.sign() * v1.Pt() > ele.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); o2::math_utils::bringToPMPi(dphi); + float phiPosition1 = pos.phi() + std::asin(pos.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * pos.pt())); + float phiPosition2 = ele.phi() + std::asin(ele.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * ele.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = pos.sign() * v1.Pt() > ele.sign() * v2.Pt() ? phiPosition1 - phiPosition2 : phiPosition2 - phiPosition1; + o2::math_utils::bringToPMPi(dphiPosition); + fRegistry.fill(HIST("Pair/after/uls/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/after/uls/hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/after/uls/hDeltaEtaDeltaPhi"), dphi, deta); + fRegistry.fill(HIST("Pair/after/uls/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta); } for (auto& [pos1, pos2] : combinations(CombinationsStrictlyUpperIndexPolicy(posTracks_per_coll, posTracks_per_coll))) { // LS++ @@ -507,9 +583,18 @@ struct prefilterDielectron { float dphi = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); o2::math_utils::bringToPMPi(dphi); + float phiPosition1 = pos1.phi() + std::asin(pos1.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * pos1.pt())); + float phiPosition2 = pos2.phi() + std::asin(pos2.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * pos2.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = pos1.sign() * v1.Pt() > pos2.sign() * v2.Pt() ? phiPosition1 - phiPosition2 : phiPosition2 - phiPosition1; + o2::math_utils::bringToPMPi(dphiPosition); + fRegistry.fill(HIST("Pair/after/lspp/hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/after/lspp/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/after/lspp/hDeltaEtaDeltaPhi"), dphi, deta); + fRegistry.fill(HIST("Pair/after/lspp/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta); } for (auto& [ele1, ele2] : combinations(CombinationsStrictlyUpperIndexPolicy(negTracks_per_coll, negTracks_per_coll))) { // LS-- @@ -528,9 +613,18 @@ struct prefilterDielectron { float dphi = ele1.sign() * v1.Pt() > ele2.sign() * v2.Pt() ? v1.Phi() - v2.Phi() : v2.Phi() - v1.Phi(); o2::math_utils::bringToPMPi(dphi); + float phiPosition1 = ele1.phi() + std::asin(ele1.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * ele1.pt())); + float phiPosition2 = ele2.phi() + std::asin(ele2.sign() * 0.30282 * (d_bz * 0.1) * dielectroncuts.cfgRefR / (2.f * ele2.pt())); + + phiPosition1 = RecoDecay::constrainAngle(phiPosition1, 0, 1); // 0-2pi + phiPosition2 = RecoDecay::constrainAngle(phiPosition2, 0, 1); // 0-2pi + float dphiPosition = ele1.sign() * v1.Pt() > ele2.sign() * v2.Pt() ? phiPosition1 - phiPosition2 : phiPosition2 - phiPosition1; + o2::math_utils::bringToPMPi(dphiPosition); + fRegistry.fill(HIST("Pair/after/lsmm/hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/after/lsmm/hMvsPhiV"), phiv, v12.M()); fRegistry.fill(HIST("Pair/after/lsmm/hDeltaEtaDeltaPhi"), dphi, deta); + fRegistry.fill(HIST("Pair/after/lsmm/hDeltaEtaDeltaPhiPosition"), dphiPosition, deta); } } // end of collision loop diff --git a/PWGEM/Dilepton/Tasks/qVectorDummyOTF.cxx b/PWGEM/Dilepton/Tasks/qVectorDummyOTF.cxx new file mode 100644 index 00000000000..d499a790a71 --- /dev/null +++ b/PWGEM/Dilepton/Tasks/qVectorDummyOTF.cxx @@ -0,0 +1,48 @@ +// 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 "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct qVectorDummyOTF { + Produces event_qvec; + + void init(InitContext&) {} + ~qVectorDummyOTF() {} + + void process(aod::EMEvents const& collisions) + { + for (int i = 0; i < collisions.size(); i++) { + event_qvec( + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, + 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f, 999.f); + } // end of collision loop + } // end of process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"qvector-dummy-otf"})}; +} diff --git a/PWGEM/Dilepton/Tasks/smearing.cxx b/PWGEM/Dilepton/Tasks/smearing.cxx index 7d2404645ca..03d0b272f46 100644 --- a/PWGEM/Dilepton/Tasks/smearing.cxx +++ b/PWGEM/Dilepton/Tasks/smearing.cxx @@ -13,21 +13,21 @@ // Analysis task to produce smeared pt, eta, phi for electrons/muons in dilepton analysis // Please write to: daiki.sekihata@cern.ch -#include -#include -#include +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "PWGEM/Dilepton/Utils/MomentumSmearer.h" #include "CCDB/BasicCCDBManager.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.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 "PWGDQ/DataModel/ReducedInfoTables.h" // remove this later, because 2 data tables (covariant matrix) in this header confilict against EM tables. -#include "PWGEM/Dilepton/Utils/MomentumSmearer.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -292,20 +292,16 @@ struct ApplySmearing { } void processDummyMCanalysisEM(aod::EMMCParticles const&) {} - // void processDummyMCanalysisDQ(ReducedMCTracks const&) {} PROCESS_SWITCH(ApplySmearing, processMCanalysisEM, "Run for MC analysis which uses skimmed EM data format", false); - // PROCESS_SWITCH(ApplySmearing, processMCanalysisDQ, "Run for MC analysis which uses skimmed DQ data format", false); PROCESS_SWITCH(ApplySmearing, processCocktail, "Run for cocktail analysis", false); PROCESS_SWITCH(ApplySmearing, processDummyMCanalysisEM, "Dummy process function", false); - // PROCESS_SWITCH(ApplySmearing, processDummyMCanalysisDQ, "Dummy process function", false); PROCESS_SWITCH(ApplySmearing, processDummyCocktail, "Dummy process function", true); }; struct CheckSmearing { - using EMMCParticlesWithSmearing = soa::Join; // this is only for electrons - // using MyReducedTracks = soa::Join; // this is only for electrons - using MyCocktailTracks = soa::Join; // this is only for electrons + using EMMCParticlesWithSmearing = soa::Join; + using MyCocktailTracks = soa::Join; // Run for electrons or muons Configurable fPdgCode{"cfgPdgCode", 11, "Set the type of particle to be checked"}; @@ -322,9 +318,9 @@ struct CheckSmearing { void init(o2::framework::InitContext&) { - registry.add("hCorrelation_Pt", "pT correlation;p_{T,l}^{gen} (GeV/c);p_{T,l}^{smeared} (GeV/c)", {HistType::kTH2F, {{1000, 0.0f, 10.0f}, {1000, 0.0f, 10.0f}}}); - registry.add("hCorrelation_Eta", "eta correlation;#eta_{l}^{gen};#eta_{l}^{smeared}", {HistType::kTH2F, {{200, -1.0f, +1.0f}, {200, -1.0f, +1.0f}}}); - registry.add("hCorrelation_Phi", "phi correlation;#varphi_{l}^{gen} (rad.);#varphi_{l}^{smeared} (rad.)", {HistType::kTH2F, {{100, 0.0f, TMath::TwoPi()}, {100, 0.0f, TMath::TwoPi()}}}); + registry.add("Electron/hCorrelation_Pt", "pT correlation;p_{T,l}^{gen} (GeV/c);p_{T,l}^{smeared} (GeV/c)", {HistType::kTH2F, {{1000, 0.0f, 10.0f}, {1000, 0.0f, 10.0f}}}); + registry.add("Electron/hCorrelation_Eta", "eta correlation;#eta_{l}^{gen};#eta_{l}^{smeared}", {HistType::kTH2F, {{200, -1.0f, +1.0f}, {200, -1.0f, +1.0f}}}); + registry.add("Electron/hCorrelation_Phi", "phi correlation;#varphi_{l}^{gen} (rad.);#varphi_{l}^{smeared} (rad.)", {HistType::kTH2F, {{100, 0.0f, TMath::TwoPi()}, {100, 0.0f, TMath::TwoPi()}}}); // Binning for resolution AxisSpec axisPtRes{ptResBins, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}; @@ -333,16 +329,19 @@ struct CheckSmearing { AxisSpec axisDeltaphiRes{deltaphiResBins, "#varphi^{gen} - #varphi^{rec} (rad.)"}; if (!fConfigUsePtVecRes) { - registry.add("PtGen_DeltaPtOverPtGen", "", HistType::kTH2D, {axisPtRes, axisDeltaptRes}, true); - registry.add("PtGen_DeltaEta", "", HistType::kTH2D, {axisPtRes, axisDeltaetaRes}, true); - registry.add("PtGen_DeltaPhi_Neg", "", HistType::kTH2D, {axisPtRes, axisDeltaphiRes}, true); - registry.add("PtGen_DeltaPhi_Pos", "", HistType::kTH2D, {axisPtRes, axisDeltaphiRes}, true); + registry.add("Electron/PtGen_DeltaPtOverPtGen", "", HistType::kTH2D, {axisPtRes, axisDeltaptRes}, true); + registry.add("Electron/PtGen_DeltaEta", "", HistType::kTH2D, {axisPtRes, axisDeltaetaRes}, true); + registry.add("Electron/PtGen_DeltaPhi_Neg", "", HistType::kTH2D, {axisPtRes, axisDeltaphiRes}, true); + registry.add("Electron/PtGen_DeltaPhi_Pos", "", HistType::kTH2D, {axisPtRes, axisDeltaphiRes}, true); } else { - registry.add("PtGen_DeltaPtOverPtGen", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaptRes}, true); - registry.add("PtGen_DeltaEta", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaetaRes}, true); - registry.add("PtGen_DeltaPhi_Neg", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaphiRes}, true); - registry.add("PtGen_DeltaPhi_Pos", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaphiRes}, true); + registry.add("Electron/PtGen_DeltaPtOverPtGen", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaptRes}, true); + registry.add("Electron/PtGen_DeltaEta", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaetaRes}, true); + registry.add("Electron/PtGen_DeltaPhi_Neg", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaphiRes}, true); + registry.add("Electron/PtGen_DeltaPhi_Pos", "", HistType::kTH2D, {{ptResBinsVec, "#it{p}^{gen}_{T,l} (GeV/#it{c})"}, axisDeltaphiRes}, true); } + + registry.addClone("Electron/", "GlobalMuon/"); + registry.addClone("Electron/", "StandaloneMuon/"); } template @@ -360,21 +359,59 @@ struct CheckSmearing { } } - float deltaptoverpt = -1000.; - if (mctrack.pt() > 0.) - deltaptoverpt = (mctrack.pt() - mctrack.ptSmeared()) / mctrack.pt(); - float deltaeta = mctrack.eta() - mctrack.etaSmeared(); - float deltaphi = mctrack.phi() - mctrack.phiSmeared(); - registry.fill(HIST("PtGen_DeltaPtOverPtGen"), mctrack.pt(), deltaptoverpt); - registry.fill(HIST("PtGen_DeltaEta"), mctrack.pt(), deltaeta); - if (mctrack.pdgCode() < 0) { - registry.fill(HIST("PtGen_DeltaPhi_Neg"), mctrack.pt(), deltaphi); - } else { - registry.fill(HIST("PtGen_DeltaPhi_Pos"), mctrack.pt(), deltaphi); + if (std::abs(mctrack.pdgCode()) == 11) { // for electrons + float deltaptoverpt = -1000.f; + if (mctrack.pt() > 0.f) { + deltaptoverpt = (mctrack.pt() - mctrack.ptSmeared()) / mctrack.pt(); + } + float deltaeta = mctrack.eta() - mctrack.etaSmeared(); + float deltaphi = mctrack.phi() - mctrack.phiSmeared(); + registry.fill(HIST("Electron/PtGen_DeltaPtOverPtGen"), mctrack.pt(), deltaptoverpt); + registry.fill(HIST("Electron/PtGen_DeltaEta"), mctrack.pt(), deltaeta); + if (mctrack.pdgCode() < 0) { // e+ + registry.fill(HIST("Electron/PtGen_DeltaPhi_Pos"), mctrack.pt(), deltaphi); + } else { // e- + registry.fill(HIST("Electron/PtGen_DeltaPhi_Neg"), mctrack.pt(), deltaphi); + } + registry.fill(HIST("Electron/hCorrelation_Pt"), mctrack.pt(), mctrack.ptSmeared()); + registry.fill(HIST("Electron/hCorrelation_Eta"), mctrack.eta(), mctrack.etaSmeared()); + registry.fill(HIST("Electron/hCorrelation_Phi"), mctrack.phi(), mctrack.phiSmeared()); + } else if (std::abs(mctrack.pdgCode()) == 13) { // for muons + float deltaptoverpt = -1000.f; + // for standalone muons + if (mctrack.pt() > 0.f) { + deltaptoverpt = (mctrack.pt() - mctrack.ptSmeared_sa_muon()) / mctrack.pt(); + } + float deltaeta = mctrack.eta() - mctrack.etaSmeared_sa_muon(); + float deltaphi = mctrack.phi() - mctrack.phiSmeared_sa_muon(); + registry.fill(HIST("StandaloneMuon/PtGen_DeltaPtOverPtGen"), mctrack.pt(), deltaptoverpt); + registry.fill(HIST("StandaloneMuon/PtGen_DeltaEta"), mctrack.pt(), deltaeta); + if (mctrack.pdgCode() < 0) { // mu+ + registry.fill(HIST("StandaloneMuon/PtGen_DeltaPhi_Pos"), mctrack.pt(), deltaphi); + } else { // mu- + registry.fill(HIST("StandaloneMuon/PtGen_DeltaPhi_Neg"), mctrack.pt(), deltaphi); + } + registry.fill(HIST("StandaloneMuon/hCorrelation_Pt"), mctrack.pt(), mctrack.ptSmeared_sa_muon()); + registry.fill(HIST("StandaloneMuon/hCorrelation_Eta"), mctrack.eta(), mctrack.etaSmeared_sa_muon()); + registry.fill(HIST("StandaloneMuon/hCorrelation_Phi"), mctrack.phi(), mctrack.phiSmeared_sa_muon()); + + // for global muons + if (mctrack.pt() > 0.f) { + deltaptoverpt = (mctrack.pt() - mctrack.ptSmeared_gl_muon()) / mctrack.pt(); + } + deltaeta = mctrack.eta() - mctrack.etaSmeared_gl_muon(); + deltaphi = mctrack.phi() - mctrack.phiSmeared_gl_muon(); + registry.fill(HIST("GlobalMuon/PtGen_DeltaPtOverPtGen"), mctrack.pt(), deltaptoverpt); + registry.fill(HIST("GlobalMuon/PtGen_DeltaEta"), mctrack.pt(), deltaeta); + if (mctrack.pdgCode() < 0) { // mu+ + registry.fill(HIST("GlobalMuon/PtGen_DeltaPhi_Pos"), mctrack.pt(), deltaphi); + } else { // mu- + registry.fill(HIST("GlobalMuon/PtGen_DeltaPhi_Neg"), mctrack.pt(), deltaphi); + } + registry.fill(HIST("GlobalMuon/hCorrelation_Pt"), mctrack.pt(), mctrack.ptSmeared_gl_muon()); + registry.fill(HIST("GlobalMuon/hCorrelation_Eta"), mctrack.eta(), mctrack.etaSmeared_gl_muon()); + registry.fill(HIST("GlobalMuon/hCorrelation_Phi"), mctrack.phi(), mctrack.phiSmeared_gl_muon()); } - registry.fill(HIST("hCorrelation_Pt"), mctrack.pt(), mctrack.ptSmeared()); - registry.fill(HIST("hCorrelation_Eta"), mctrack.eta(), mctrack.etaSmeared()); - registry.fill(HIST("hCorrelation_Phi"), mctrack.phi(), mctrack.phiSmeared()); } // end of mctrack loop } @@ -383,25 +420,17 @@ struct CheckSmearing { Check(tracksMC, mccollisions); } - // void processCheckMCanalysisDQ(MyReducedTracks const& tracksMC) - // { - // Check(tracksMC); - // } - void processCheckCocktail(MyCocktailTracks const& tracksMC) { Check(tracksMC, nullptr); } void processDummyMCanalysisEM(aod::EMMCParticles const&) {} - // void processDummyMCanalysisDQ(ReducedMCTracks const&) {} void processDummyCocktail(aod::McParticles const&) {} PROCESS_SWITCH(CheckSmearing, processCheckMCanalysisEM, "Run for MC analysis", false); - // PROCESS_SWITCH(CheckSmearing, processCheckMCanalysisDQ, "Run for MC analysis", false); PROCESS_SWITCH(CheckSmearing, processCheckCocktail, "Run for cocktail analysis", false); PROCESS_SWITCH(CheckSmearing, processDummyMCanalysisEM, "Dummy process function", false); - // PROCESS_SWITCH(CheckSmearing, processDummyMCanalysisDQ, "Dummy process function", false); PROCESS_SWITCH(CheckSmearing, processDummyCocktail, "Dummy process function", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx b/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx index 819a85efe65..9787a5bae04 100644 --- a/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx +++ b/PWGEM/Dilepton/Tasks/tableReaderBarrel.cxx @@ -12,39 +12,43 @@ // Contact: iarsene@cern.ch, i.c.arsene@fys.uio.no // -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" -#include "PWGDQ/Core/VarManager.h" -#include "PWGDQ/Core/HistogramManager.h" -#include "PWGDQ/Core/MixingHandler.h" -#include "PWGDQ/Core/AnalysisCut.h" #include "PWGDQ/Core/AnalysisCompositeCut.h" -#include "PWGDQ/Core/HistogramsLibrary.h" +#include "PWGDQ/Core/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 "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" -#include "Field/MagneticField.h" -#include "TGeoGlobalMagField.h" -#include "DetectorsBase/Propagator.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 "Common/CCDB/EventSelectionParams.h" + +#include "TGeoGlobalMagField.h" +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include using std::cout; using std::endl; @@ -123,12 +127,12 @@ struct AnalysisEventSelection { Produces hash; OutputObj fOutputList{"output"}; // TODO: Provide the mixing variables and binning directly via configurables (e.g. vectors of float) - Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; + Configurable fConfigMixingVariables{"cfgMixingVars", "", "Mixing configs separated by a comma, default no mixing"}; Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigITSROFrameStartBorderMargin{"ITSROFrameStartBorderMargin", -1, "Number of bcs at the start of ITS RO Frame border. Take from CCDB if -1"}; Configurable fConfigITSROFrameEndBorderMargin{"ITSROFrameEndBorderMargin", -1, "Number of bcs at the end of ITS RO Frame border. Take from CCDB if -1"}; Configurable fConfigAddEventHistogram{"cfgAddEventHistogram", "", "Comma separated list of histograms"}; - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; AnalysisCompositeCut* fEventCut; struct : ConfigurableGroup { @@ -284,10 +288,10 @@ struct AnalysisTrackSelection { // NOTE: For now, the candidate electron cuts must be provided first, then followed by any other needed selections Configurable fConfigQA{"cfgQA", false, "If true, fill QA histograms"}; Configurable fConfigQAIfSelEvt{"cfgQAIfSelEvt", true, "If true, fill QA only for selected events"}; - Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; + Configurable fConfigAddTrackHistogram{"cfgAddTrackHistogram", "", "Comma separated list of histograms"}; Configurable fConfigPrefilterCutId{"cfgPrefilterCutId", 32, "Id of the Prefilter track cut (starting at 0)"}; // In order to create another column prefilter (should be temporary before improving cut selection in configurables, then displaced to AnalysisPrefilterSelection) - Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; + Configurable fConfigCcdbUrl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable fConfigCcdbPathTPC{"ccdb-path-tpc", "Users/z/zhxiong/TPCPID/PostCalib", "base path to the ccdb object"}; Configurable fConfigNoLaterThan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigComputeTPCpostCalib{"cfgTPCpostCalib", false, "If true, compute TPC post-calibrated n-sigmas"}; Configurable fConfigRunPeriods{"cfgRunPeriods", "LHC22f", "run periods for used data"}; @@ -948,8 +952,8 @@ struct AnalysisSameEventPairing { OutputObj fOutputList{"output"}; Configurable fConfigNbTrackCut{"cfgNbTrackCut", 1, "Number of track cuts without prefilter cut, need to be consistent with the track selection"}; Configurable fConfigNbPairCut{"cfgNbPairCut", 1, "Number of pair cuts, need to be below 4 right now"}; - Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable ccdbPath{"ccdb-path", "Users/lm", "base path to the ccdb object"}; + Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable ccdbPath{"ccdb-path", "Users/lm", "base path to the ccdb object"}; Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "latest acceptable timestamp of creation for the object"}; Configurable fConfigAddSEPHistogram{"cfgAddSEPHistogram", "", "Comma separated list of histograms"}; Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -1072,7 +1076,7 @@ struct AnalysisSameEventPairing { } } - if (fConfigNbTrackCut > 0 && fConfigNbTrackCut < 31) { // if track cuts + if (fConfigNbTrackCut > 0 && fConfigNbTrackCut < 31) { // if track cuts for (std::size_t icut = 0; icut < fConfigNbTrackCut; ++icut) { // loop over track cuts fTwoTrackFilterMask |= (static_cast(1) << icut); // no pair cuts diff --git a/PWGEM/Dilepton/Tasks/taggingHFE.cxx b/PWGEM/Dilepton/Tasks/taggingHFE.cxx index e876aa5e760..f843b20819a 100644 --- a/PWGEM/Dilepton/Tasks/taggingHFE.cxx +++ b/PWGEM/Dilepton/Tasks/taggingHFE.cxx @@ -282,7 +282,8 @@ struct taggingHFE { fRegistry.add("e_Kpm/all/hCosPA", "cosPA;cosine of pointing angle", kTH1F, {{200, 0.8, 1}}, false); fRegistry.add("e_Kpm/all/hCosPAXY", "cosPA in XY;cosine of pointing angle in XY", kTH1F, {{200, 0.8, 1}}, false); fRegistry.add("e_Kpm/all/hDCA2Legs", "distance between 2 legs;distance between 2 legs (cm)", kTH1F, {{500, 0, 0.5}}, false); - fRegistry.add("e_Kpm/all/hMass", "mass;mass (GeV/c^{2});p_{T} (GeV/c)", kTH2F, {{40, 0.5, 2.5}, {100, 0, 10}}, false); + fRegistry.add("e_Kpm/all/hMass", "mass;mass (GeV/c^{2})", kTH1F, {{200, 0.5, 2.5}}, false); + fRegistry.add("e_Kpm/all/hMass_CosPA", "mass vs. cosPA;mass (GeV/c^{2});cosine of pointing angle", kTH2F, {{200, 0.5, 2.5}, {200, 0.8, 1.0}}, false); fRegistry.add("e_Kpm/all/hDeltaEtaDeltaPhi", "#Delta#varphi vs. #Delta#eta;#Delta#varphi = #varphi_{h} - #varphi_{e} (rad.);#Delta#eta = #eta_{h} - #eta_{e}", kTH2F, {{180, -M_PI, M_PI}, {200, -2, +2}}, false); fRegistry.add("e_Kpm/all/hRelDeltaPt", "rel delta pT;(p_{T,h} - p_{T,e})/p_{T,e}", kTH1F, {{80, -2, +2}}, false); fRegistry.add("e_Kpm/all/hProdDCAxy", "product of DCAxy;d_{xy}^{e} #times d_{xy}^{h} (#sigma)^{2}", kTH1F, {{200, -100, +100}}, false); @@ -642,7 +643,7 @@ struct taggingHFE { float mEK = RecoDecay::m(std::array{pvec0, pvec1}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassKaonCharged}); float cpa = RecoDecay::cpa(pVtx, svpos, pvecSum); float cpaXY = RecoDecay::cpaXY(pVtx, svpos, pvecSum); - float ptEK = RecoDecay::sqrtSumOfSquares(pvec0[0] + pvec1[0], pvec0[1] + pvec1[1]); + // float ptEK = RecoDecay::sqrtSumOfSquares(pvec0[0] + pvec1[0], pvec0[1] + pvec1[1]); float deta = RecoDecay::eta(pvec1) - RecoDecay::eta(pvec0); float dphi = RecoDecay::phi(pvec1[0], pvec1[1]) - RecoDecay::phi(pvec0[0], pvec0[1]); @@ -658,7 +659,8 @@ struct taggingHFE { fRegistry.fill(HIST("e_Kpm/all/hLz"), lz); fRegistry.fill(HIST("e_Kpm/all/hCosPAXY"), cpaXY); fRegistry.fill(HIST("e_Kpm/all/hCosPA"), cpa); - fRegistry.fill(HIST("e_Kpm/all/hMass"), mEK, ptEK); + fRegistry.fill(HIST("e_Kpm/all/hMass"), mEK); + fRegistry.fill(HIST("e_Kpm/all/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST("e_Kpm/all/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST("e_Kpm/all/hRelDeltaPt"), reldpt); fRegistry.fill(HIST("e_Kpm/all/hProdDCAxy"), dcaXY / std::sqrt(eleParCov.getSigmaY2()) * dcaXY_h / std::sqrt(trackParCov.getSigmaY2())); @@ -687,7 +689,8 @@ struct taggingHFE { fRegistry.fill(HIST("e_Kpm/D0/hLz"), lz); fRegistry.fill(HIST("e_Kpm/D0/hCosPAXY"), cpaXY); fRegistry.fill(HIST("e_Kpm/D0/hCosPA"), cpa); - fRegistry.fill(HIST("e_Kpm/D0/hMass"), mEK, ptEK); + fRegistry.fill(HIST("e_Kpm/D0/hMass"), mEK); + fRegistry.fill(HIST("e_Kpm/D0/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST("e_Kpm/D0/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST("e_Kpm/D0/hRelDeltaPt"), reldpt); fRegistry.fill(HIST("e_Kpm/D0/hProdDCAxy"), dcaXY / std::sqrt(eleParCov.getSigmaY2()) * dcaXY_h / std::sqrt(trackParCov.getSigmaY2())); @@ -704,7 +707,8 @@ struct taggingHFE { fRegistry.fill(HIST("e_Kpm/Dpm/hLz"), lz); fRegistry.fill(HIST("e_Kpm/Dpm/hCosPAXY"), cpaXY); fRegistry.fill(HIST("e_Kpm/Dpm/hCosPA"), cpa); - fRegistry.fill(HIST("e_Kpm/Dpm/hMass"), mEK, ptEK); + fRegistry.fill(HIST("e_Kpm/Dpm/hMass"), mEK); + fRegistry.fill(HIST("e_Kpm/Dpm/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST("e_Kpm/Dpm/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST("e_Kpm/Dpm/hRelDeltaPt"), reldpt); fRegistry.fill(HIST("e_Kpm/Dpm/hProdDCAxy"), dcaXY / std::sqrt(eleParCov.getSigmaY2()) * dcaXY_h / std::sqrt(trackParCov.getSigmaY2())); @@ -721,7 +725,8 @@ struct taggingHFE { fRegistry.fill(HIST("e_Kpm/Ds/hLz"), lz); fRegistry.fill(HIST("e_Kpm/Ds/hCosPAXY"), cpaXY); fRegistry.fill(HIST("e_Kpm/Ds/hCosPA"), cpa); - fRegistry.fill(HIST("e_Kpm/Ds/hMass"), mEK, ptEK); + fRegistry.fill(HIST("e_Kpm/Ds/hMass"), mEK); + fRegistry.fill(HIST("e_Kpm/Ds/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST("e_Kpm/Ds/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST("e_Kpm/Ds/hRelDeltaPt"), reldpt); fRegistry.fill(HIST("e_Kpm/Ds/hProdDCAxy"), dcaXY / std::sqrt(eleParCov.getSigmaY2()) * dcaXY_h / std::sqrt(trackParCov.getSigmaY2())); @@ -743,7 +748,8 @@ struct taggingHFE { fRegistry.fill(HIST("e_Kpm/fake/hLz"), lz); fRegistry.fill(HIST("e_Kpm/fake/hCosPAXY"), cpaXY); fRegistry.fill(HIST("e_Kpm/fake/hCosPA"), cpa); - fRegistry.fill(HIST("e_Kpm/fake/hMass"), mEK, ptEK); + fRegistry.fill(HIST("e_Kpm/fake/hMass"), mEK); + fRegistry.fill(HIST("e_Kpm/fake/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST("e_Kpm/fake/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST("e_Kpm/fake/hRelDeltaPt"), reldpt); fRegistry.fill(HIST("e_Kpm/fake/hProdDCAxy"), dcaXY / std::sqrt(eleParCov.getSigmaY2()) * dcaXY_h / std::sqrt(trackParCov.getSigmaY2())); @@ -824,7 +830,7 @@ struct taggingHFE { float dca2legs = std::sqrt(fitter.getChi2AtPCACandidate()); float lxy = std::sqrt(std::pow(svpos[0] - collision.posX(), 2) + std::pow(svpos[1] - collision.posY(), 2)); float lz = std::fabs(svpos[2] - collision.posZ()); - float ptEK = RecoDecay::sqrtSumOfSquares(pvec0[0] + pvec1[0], pvec0[1] + pvec1[1]); + // float ptEK = RecoDecay::sqrtSumOfSquares(pvec0[0] + pvec1[0], pvec0[1] + pvec1[1]); float deta = RecoDecay::eta(pvec1) - RecoDecay::eta(pvec0); float dphi = RecoDecay::phi(pvec1[0], pvec1[1]) - RecoDecay::phi(pvec0[0], pvec0[1]); @@ -855,7 +861,8 @@ struct taggingHFE { fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hLz"), lz); fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hCosPAXY"), cpaXY); fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hCosPA"), cpa); - fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hMass"), mEK, ptEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hMass"), mEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST(pair_names[pairId]) + HIST("all/hRelDeltaPt"), reldpt); @@ -882,7 +889,8 @@ struct taggingHFE { fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hLz"), lz); fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hCosPAXY"), cpaXY); fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hCosPA"), cpa); - fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hMass"), mEK, ptEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hMass"), mEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST(pair_names[pairId]) + HIST("D0/hRelDeltaPt"), reldpt); } else if (std::abs(cmp.pdgCode()) == 411) { // Dpm @@ -896,7 +904,8 @@ struct taggingHFE { fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hLz"), lz); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hCosPAXY"), cpaXY); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hCosPA"), cpa); - fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hMass"), mEK, ptEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hMass"), mEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Dpm/hRelDeltaPt"), reldpt); } else if (std::abs(cmp.pdgCode()) == 431) { // Ds @@ -910,7 +919,8 @@ struct taggingHFE { fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hLz"), lz); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hCosPAXY"), cpaXY); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hCosPA"), cpa); - fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hMass"), mEK, ptEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hMass"), mEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Ds/hRelDeltaPt"), reldpt); } @@ -928,7 +938,8 @@ struct taggingHFE { fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hLz"), lz); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hCosPAXY"), cpaXY); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hCosPA"), cpa); - fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hMass"), mEK, ptEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hMass"), mEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST(pair_names[pairId]) + HIST("Lc/hRelDeltaPt"), reldpt); } @@ -948,7 +959,8 @@ struct taggingHFE { fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hLz"), lz); fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hCosPAXY"), cpaXY); fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hCosPA"), cpa); - fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hMass"), mEK, ptEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hMass"), mEK); + fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hMass_CosPA"), mEK, cpa); fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hDeltaEtaDeltaPhi"), dphi, deta); fRegistry.fill(HIST(pair_names[pairId]) + HIST("fake/hRelDeltaPt"), reldpt); } diff --git a/PWGEM/Dilepton/Tasks/vpPairQC.cxx b/PWGEM/Dilepton/Tasks/vpPairQC.cxx index b9fe093e9f5..ffa82e3c3e5 100644 --- a/PWGEM/Dilepton/Tasks/vpPairQC.cxx +++ b/PWGEM/Dilepton/Tasks/vpPairQC.cxx @@ -14,30 +14,31 @@ // This code runs loop over ULS ee pars for virtual photon QC. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Common/Core/RecoDecay.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrack.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/Dilepton/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.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 +#include +#include using namespace o2; using namespace o2::aod; @@ -49,7 +50,7 @@ using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyTracks = soa::Join; +using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; struct vpPairQC { @@ -123,15 +124,15 @@ struct vpPairQC { Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.2, "max p to apply ITS cluster size cut"}; Configurable cfg_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::kTOFif), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + // Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -0.0, "min. TPC n sigma for kaon exclusion"}; @@ -143,6 +144,8 @@ struct vpPairQC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.5, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 0.5, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + 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)"}; @@ -255,15 +258,15 @@ struct vpPairQC { fRegistry.add("Track/positive/hChi2TOF", "TOF Chi2;p_{pv} (GeV/c);chi2", kTH2F, {{1000, 0, 10}, {100, 0, 10}}, false); fRegistry.add("Track/positive/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda);", kTH2F, {{1000, 0.f, 10.f}, {160, 0, 16}}, false); fRegistry.add("Track/positive/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hTPCNsigmaMu", "TPC n sigma mu;p_{in} (GeV/c);n #sigma_{#mu}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/positive/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/positive/hTPCNsigmaKa", "TPC n sigma ka;p_{in} (GeV/c);n #sigma_{K}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/positive/hTPCNsigmaPr", "TPC n sigma pr;p_{in} (GeV/c);n #sigma_{p}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/positive/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hTOFNsigmaMu", "TOF n sigma mu;p_{pv} (GeV/c);n #sigma_{#mu}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hTOFNsigmaKa", "TOF n sigma ka;p_{pv} (GeV/c);n #sigma_{K}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); + // fRegistry.add("Track/positive/hTOFNsigmaPr", "TOF n sigma pr;p_{pv} (GeV/c);n #sigma_{p}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.addClone("Track/positive/", "Track/negative/"); const AxisSpec axis_mass{50, 0, 0.05, "m_{ee} (GeV/c^{2})"}; @@ -323,16 +326,17 @@ struct vpPairQC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.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.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.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); @@ -378,7 +382,7 @@ struct vpPairQC { return false; } - if (!fDielectronCut.IsSelectedPair(t1, t2, d_bz)) { + if (!fDielectronCut.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { return false; } @@ -417,11 +421,6 @@ struct vpPairQC { if (track.sign() > 0) { fRegistry.fill(HIST("Track/positive/hs"), track.pt(), track.eta(), track.phi(), dca_3d, weight); fRegistry.fill(HIST("Track/positive/hQoverPt"), track.sign() / track.pt()); - fRegistry.fill(HIST("Track/positive/hPResolution"), track.p(), sigmaP(track) / track.p()); - fRegistry.fill(HIST("Track/positive/hPtResolution"), track.p(), sigmaPt(track) / track.pt()); - fRegistry.fill(HIST("Track/positive/hThetaResolution"), track.p(), sigmaTheta(track)); - fRegistry.fill(HIST("Track/positive/hEtaResolution"), track.p(), sigmaEta(track)); - fRegistry.fill(HIST("Track/positive/hPhiResolution"), track.p(), sigmaPhi(track)); fRegistry.fill(HIST("Track/positive/hDCAxyz"), track.dcaXY(), track.dcaZ()); fRegistry.fill(HIST("Track/positive/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); fRegistry.fill(HIST("Track/positive/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um @@ -442,23 +441,18 @@ struct vpPairQC { fRegistry.fill(HIST("Track/positive/hTOFbeta"), track.p(), track.beta()); fRegistry.fill(HIST("Track/positive/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/positive/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + // fRegistry.fill(HIST("Track/positive/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/positive/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/positive/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/positive/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); fRegistry.fill(HIST("Track/positive/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + // fRegistry.fill(HIST("Track/positive/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); } else { fRegistry.fill(HIST("Track/negative/hs"), track.pt(), track.eta(), track.phi(), dca_3d, weight); fRegistry.fill(HIST("Track/negative/hQoverPt"), track.sign() / track.pt()); - fRegistry.fill(HIST("Track/negative/hPResolution"), track.p(), sigmaP(track) / track.p()); - fRegistry.fill(HIST("Track/negative/hPtResolution"), track.p(), sigmaPt(track) / track.pt()); - fRegistry.fill(HIST("Track/negative/hThetaResolution"), track.p(), sigmaTheta(track)); - fRegistry.fill(HIST("Track/negative/hEtaResolution"), track.p(), sigmaEta(track)); - fRegistry.fill(HIST("Track/negative/hPhiResolution"), track.p(), sigmaPhi(track)); fRegistry.fill(HIST("Track/negative/hDCAxyz"), track.dcaXY(), track.dcaZ()); fRegistry.fill(HIST("Track/negative/hDCAxyzSigma"), track.dcaXY() / sqrt(track.cYY()), track.dcaZ() / sqrt(track.cZZ())); fRegistry.fill(HIST("Track/negative/hDCAxyRes_Pt"), track.pt(), sqrt(track.cYY()) * 1e+4); // convert cm to um @@ -479,15 +473,15 @@ struct vpPairQC { fRegistry.fill(HIST("Track/negative/hTOFbeta"), track.p(), track.beta()); fRegistry.fill(HIST("Track/negative/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); fRegistry.fill(HIST("Track/negative/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); + // fRegistry.fill(HIST("Track/negative/hTPCNsigmaMu"), track.tpcInnerParam(), track.tpcNSigmaMu()); fRegistry.fill(HIST("Track/negative/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/negative/hTPCNsigmaKa"), track.tpcInnerParam(), track.tpcNSigmaKa()); fRegistry.fill(HIST("Track/negative/hTPCNsigmaPr"), track.tpcInnerParam(), track.tpcNSigmaPr()); fRegistry.fill(HIST("Track/negative/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); - fRegistry.fill(HIST("Track/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaMu"), track.p(), track.tofNSigmaMu()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaKa"), track.p(), track.tofNSigmaKa()); + // fRegistry.fill(HIST("Track/negative/hTOFNsigmaPr"), track.p(), track.tofNSigmaPr()); } } diff --git a/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx b/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx index 58e47abad1d..d470a92afa2 100644 --- a/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx +++ b/PWGEM/Dilepton/Tasks/vpPairQCMC.cxx @@ -14,30 +14,31 @@ // This code runs loop over ULS ee pars for virtual photon QC. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/Core/RecoDecay.h" - -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Core/DielectronCut.h" #include "PWGEM/Dilepton/Core/EMEventCut.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/EventHistograms.h" +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.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/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 +#include +#include using namespace o2; using namespace o2::aod; @@ -49,7 +50,7 @@ using namespace o2::aod::pwgem::dilepton::utils::mcutil; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyMCTracks = soa::Join; +using MyMCTracks = soa::Join; using MyMCTrack = MyMCTracks::iterator; struct vpPairQCMC { @@ -123,15 +124,15 @@ struct vpPairQCMC { Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_min_its_cluster_size{"cfg_min_its_cluster_size", 0.f, "min ITS cluster size"}; Configurable cfg_max_its_cluster_size{"cfg_max_its_cluster_size", 16.f, "max ITS cluster size"}; - Configurable cfg_max_p_its_cluster_size{"cfg_max_p_its_cluster_size", 0.2, "max p to apply ITS cluster size cut"}; Configurable cfg_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::kTOFif), "pid scheme [kTOFreq : 0, kTPChadrej : 1, kTPChadrejORTOFreq : 2, kTPConly : 3, kTOFif : 4, kPIDML : 5]"}; Configurable cfg_min_TPCNsigmaEl{"cfg_min_TPCNsigmaEl", -2.0, "min. TPC n sigma for electron inclusion"}; Configurable cfg_max_TPCNsigmaEl{"cfg_max_TPCNsigmaEl", +3.0, "max. TPC n sigma for electron inclusion"}; - Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; - Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; + // Configurable cfg_min_TPCNsigmaMu{"cfg_min_TPCNsigmaMu", -0.0, "min. TPC n sigma for muon exclusion"}; + // Configurable cfg_max_TPCNsigmaMu{"cfg_max_TPCNsigmaMu", +0.0, "max. TPC n sigma for muon exclusion"}; Configurable cfg_min_TPCNsigmaPi{"cfg_min_TPCNsigmaPi", -0.0, "min. TPC n sigma for pion exclusion"}; Configurable cfg_max_TPCNsigmaPi{"cfg_max_TPCNsigmaPi", +0.0, "max. TPC n sigma for pion exclusion"}; Configurable cfg_min_TPCNsigmaKa{"cfg_min_TPCNsigmaKa", -0.0, "min. TPC n sigma for kaon exclusion"}; @@ -143,6 +144,8 @@ struct vpPairQCMC { Configurable cfg_min_pin_pirejTPC{"cfg_min_pin_pirejTPC", 0.5, "min. pin for pion rejection in TPC"}; Configurable cfg_max_pin_pirejTPC{"cfg_max_pin_pirejTPC", 0.5, "max. pin for pion rejection in TPC"}; Configurable enableTTCA{"enableTTCA", true, "Flag to enable or disable TTCA"}; + 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)"}; @@ -329,16 +332,17 @@ struct vpPairQCMC { fDielectronCut.SetChi2PerClusterTPC(0.0, dielectroncuts.cfg_max_chi2tpc); fDielectronCut.SetChi2PerClusterITS(0.0, dielectroncuts.cfg_max_chi2its); fDielectronCut.SetNClustersITS(dielectroncuts.cfg_min_ncluster_its, 7); - fDielectronCut.SetMeanClusterSizeITS(dielectroncuts.cfg_min_its_cluster_size, dielectroncuts.cfg_max_its_cluster_size, dielectroncuts.cfg_max_p_its_cluster_size); + fDielectronCut.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.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.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); @@ -408,7 +412,7 @@ struct vpPairQCMC { return false; } - if (!fDielectronCut.IsSelectedPair(t1, t2, d_bz)) { + if (!fDielectronCut.IsSelectedPair(t1, t2, d_bz, dielectroncuts.cfgRefR)) { return false; } diff --git a/PWGEM/Dilepton/Utils/EMTrack.h b/PWGEM/Dilepton/Utils/EMTrack.h index 0f894d5b4dc..d7ddae81476 100644 --- a/PWGEM/Dilepton/Utils/EMTrack.h +++ b/PWGEM/Dilepton/Utils/EMTrack.h @@ -15,15 +15,16 @@ #ifndef PWGEM_DILEPTON_UTILS_EMTRACK_H_ #define PWGEM_DILEPTON_UTILS_EMTRACK_H_ -#include #include "Math/Vector4D.h" +#include + namespace o2::aod::pwgem::dilepton::utils { class EMTrack { public: - EMTrack(int dfId, int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, std::vector amb_ele_self_ids = {}) + EMTrack(int dfId, int globalId, int collisionId, int trackId, float pt, float eta, float phi, float mass, int8_t charge = 0, float dcaXY = 0.f, float dcaZ = 0.f, std::vector amb_ele_self_ids = {}, float CYY = 0, float CZY = 0, float CZZ = 0) { fDFId = dfId; fGlobalId = globalId; @@ -36,6 +37,9 @@ class EMTrack fCharge = charge; fDCAxy = dcaXY; fDCAz = dcaZ; + fCYY = CYY; + fCZY = CZY; + fCZZ = CZZ; fPairDCA3DinSigmaOTF = 0; fAmbEleSelfIds = amb_ele_self_ids; @@ -78,6 +82,11 @@ class EMTrack int8_t sign() const { return fCharge; } float dcaXY() const { return fDCAxy; } float dcaZ() const { return fDCAz; } + + float cYY() const { return fCYY; } + float cZY() const { return fCZY; } + float cZZ() const { return fCZZ; } + float p() const { return fPt * std::cosh(fEta); } float px() const { return fPt * std::cos(fPhi); } float py() const { return fPt * std::sin(fPhi); } @@ -130,6 +139,10 @@ class EMTrack std::vector ambiguousPosLegIds() const { return fAmbPosLegSelfIds; } std::vector ambiguousNegLegIds() const { return fAmbNegLegSelfIds; } + void setCYY(float cYY) { fCYY = cYY; } + void setCZY(float cZY) { fCZY = cZY; } + void setCZZ(float cZZ) { fCZZ = cZZ; } + protected: int fDFId; int fGlobalId; @@ -142,6 +155,11 @@ class EMTrack int8_t fCharge; float fDCAxy; float fDCAz; + + float fCYY; + float fCZY; + float fCZZ; + float fPairDCA3DinSigmaOTF; bool fIsAmbiguous; std::vector fAmbEleSelfIds; @@ -199,9 +217,6 @@ class EMTrackWithCov : public EMTrack float snp() const { return fSnp; } float tgl() const { return fTgl; } - float cYY() const { return fCYY; } - float cZY() const { return fCZY; } - float cZZ() const { return fCZZ; } float cSnpY() const { return fCSnpY; } float cSnpZ() const { return fCSnpZ; } float cSnpSnp() const { return fCSnpSnp; } @@ -215,10 +230,6 @@ class EMTrackWithCov : public EMTrack float c1PtTgl() const { return fC1PtTgl; } float c1Pt21Pt2() const { return fC1Pt21Pt2; } - void setCYY(float cYY) { fCYY = cYY; } - void setCZY(float cZY) { fCZY = cZY; } - void setCZZ(float cZZ) { fCZZ = cZZ; } - protected: float fX; float fY; @@ -226,9 +237,6 @@ class EMTrackWithCov : public EMTrack float fAlpha; float fSnp; float fTgl; - float fCYY; - float fCZY; - float fCZZ; float fCSnpY; float fCSnpZ; float fCSnpSnp; diff --git a/PWGEM/Dilepton/Utils/EMTrackUtilities.h b/PWGEM/Dilepton/Utils/EMTrackUtilities.h index 6ac2275aee1..5c5b21e6ea0 100644 --- a/PWGEM/Dilepton/Utils/EMTrackUtilities.h +++ b/PWGEM/Dilepton/Utils/EMTrackUtilities.h @@ -15,14 +15,35 @@ #ifndef PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ #define PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ -#include -#include +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" + #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, +}; + //_______________________________________________________________________ template float dca3DinSigma(T const& track) @@ -65,12 +86,12 @@ 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 dcaX = track.fwdDcaX(); // in cm - float dcaY = track.fwdDcaY(); // in cm - float det = cXX * cYY - cXY * cXY; // determinant + float cXX = track.cXXatDCA(); // in cm^2 + float cYY = track.cYYatDCA(); // in cm^2 + float cXY = track.cXYatDCA(); // in cm^2 + float dcaX = track.fwdDcaX(); // in cm + float dcaY = track.fwdDcaY(); // in cm + float det = cXX * cYY - cXY * cXY; // determinant if (det < 0) { return 999.f; @@ -88,6 +109,20 @@ float sigmaFwdDcaXY(T const& track) return dcaXY / fwdDcaXYinSigma(track); } //_______________________________________________________________________ +template +bool checkMFTHitMap(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); +} +//_______________________________________________________________________ template bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) { @@ -115,36 +150,36 @@ bool isBestMatch(TTrack const& track, TCut const& cut, TTracks const& tracks) } } //_______________________________________________________________________ -template -float sigmaPt(T const& track) -{ - return std::sqrt(track.c1Pt21Pt2()) / std::pow(track.signed1Pt(), 2); // pT resolution -} -//_______________________________________________________________________ -template -float sigmaPhi(T const& track) -{ - return std::sqrt(track.cSnpSnp()) / std::sqrt(1.f - std::pow(track.snp(), 2)); // phi resolution -} -//_______________________________________________________________________ -template -float sigmaTheta(T const& track) -{ - return std::sqrt(track.cTglTgl()) / (1.f + std::pow(track.tgl(), 2)); // theta resolution = lambda resolution. // lambda = pi/2 - theta. theta is polar angle. -} -//_______________________________________________________________________ -template -float sigmaEta(T const& track) -{ - return std::sqrt(track.cTglTgl()) / std::sqrt(1.f + std::pow(track.tgl(), 2)); -} -//_______________________________________________________________________ -template -float sigmaP(T const& track) -{ - // p = 1/1/pT x 1/cos(lambda); - return std::sqrt(std::pow(1.f / track.signed1Pt(), 4) * ((1.f + std::pow(track.tgl(), 2)) * track.c1Pt21Pt2() + 1.f / (1.f + std::pow(track.tgl(), 2)) * std::pow(track.signed1Pt() * track.tgl(), 2) * track.cTglTgl() - 2.f * track.signed1Pt() * track.tgl() * track.c1PtTgl())); -} +// template +// float sigmaPt(T const& track) +// { +// return std::sqrt(track.c1Pt21Pt2()) / std::pow(track.signed1Pt(), 2); // pT resolution +// } +// //_______________________________________________________________________ +// template +// float sigmaPhi(T const& track) +// { +// return std::sqrt(track.cSnpSnp()) / std::sqrt(1.f - std::pow(track.snp(), 2)); // phi resolution +// } +// //_______________________________________________________________________ +// template +// float sigmaTheta(T const& track) +// { +// return std::sqrt(track.cTglTgl()) / (1.f + std::pow(track.tgl(), 2)); // theta resolution = lambda resolution. // lambda = pi/2 - theta. theta is polar angle. +// } +// //_______________________________________________________________________ +// template +// float sigmaEta(T const& track) +// { +// return std::sqrt(track.cTglTgl()) / std::sqrt(1.f + std::pow(track.tgl(), 2)); +// } +// //_______________________________________________________________________ +// template +// float sigmaP(T const& track) +// { +// // p = 1/1/pT x 1/cos(lambda); +// return std::sqrt(std::pow(1.f / track.signed1Pt(), 4) * ((1.f + std::pow(track.tgl(), 2)) * track.c1Pt21Pt2() + 1.f / (1.f + std::pow(track.tgl(), 2)) * std::pow(track.signed1Pt() * track.tgl(), 2) * track.cTglTgl() - 2.f * track.signed1Pt() * track.tgl() * track.c1PtTgl())); +// } //_______________________________________________________________________ } // namespace o2::aod::pwgem::dilepton::utils::emtrackutil #endif // PWGEM_DILEPTON_UTILS_EMTRACKUTILITIES_H_ diff --git a/PWGEM/Dilepton/Utils/EventHistograms.h b/PWGEM/Dilepton/Utils/EventHistograms.h index 7c1d2fe687e..ab448b1dcc6 100644 --- a/PWGEM/Dilepton/Utils/EventHistograms.h +++ b/PWGEM/Dilepton/Utils/EventHistograms.h @@ -14,6 +14,9 @@ #ifndef PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ #define PWGEM_DILEPTON_UTILS_EVENTHISTOGRAMS_H_ + +#include "Framework/HistogramRegistry.h" + using namespace o2::framework; namespace o2::aod::pwgem::dilepton::utils::eventhistogram @@ -46,16 +49,34 @@ void addEventHistograms(HistogramRegistry* fRegistry) hCollisionCounter->GetXaxis()->SetBinLabel(20, "Calibrated Q vector"); hCollisionCounter->GetXaxis()->SetBinLabel(21, "accepted"); + const AxisSpec axis_cent_ft0m{{0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 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, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 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, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 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)", kTH1F, {{100, -50, +50}}, false); fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, false); - fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry->add("Event/before/hCentFT0A_HMpp", "hCentFT0A for HM pp;centrality FT0A (%)", kTH1F, {{100, 0, 1}}, false); - fRegistry->add("Event/before/hCentFT0C_HMpp", "hCentFT0C for HM pp;centrality FT0C (%)", kTH1F, {{100, 0, 1}}, false); - fRegistry->add("Event/before/hCentFT0M_HMpp", "hCentFT0M for HM pp;centrality FT0M (%)", kTH1F, {{100, 0, 1}}, false); + fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{axis_cent_ft0a}}, false); + fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{axis_cent_ft0c}}, false); + fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{axis_cent_ft0m}}, false); fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {600, 0, 6000}}, false); fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2F, {{60, 0, 60000}, {200, 0, 20000}}, false); @@ -195,9 +216,6 @@ void fillEventInfo(HistogramRegistry* fRegistry, TCollision const& collision, co fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A"), collision.centFT0A()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C"), collision.centFT0C()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M"), collision.centFT0M()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0A_HMpp"), collision.centFT0A()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0C_HMpp"), collision.centFT0C()); - fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0M_HMpp"), collision.centFT0M()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hCentFT0CvsMultNTracksPV"), collision.centFT0C(), collision.multNTracksPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsMultNTracksPV"), collision.multFT0C(), collision.multNTracksPV()); fRegistry->fill(HIST("Event/") + HIST(event_types[ev_id]) + HIST("hMultFT0CvsOccupancy"), collision.multFT0C(), collision.trackOccupancyInTimeRange()); diff --git a/PWGEM/Dilepton/Utils/MCUtilities.h b/PWGEM/Dilepton/Utils/MCUtilities.h index c6c1aacfe04..dd12d2576f2 100644 --- a/PWGEM/Dilepton/Utils/MCUtilities.h +++ b/PWGEM/Dilepton/Utils/MCUtilities.h @@ -15,9 +15,12 @@ #ifndef PWGEM_DILEPTON_UTILS_MCUTILITIES_H_ #define PWGEM_DILEPTON_UTILS_MCUTILITIES_H_ +#include "Framework/AnalysisDataModel.h" +#include "Framework/Logger.h" + +#include #include #include -#include //_______________________________________________________________________ namespace o2::aod::pwgem::dilepton::utils::mcutil diff --git a/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h b/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h index ef1c7b33474..2ed0b02fe3c 100644 --- a/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h +++ b/PWGEM/Dilepton/Utils/MlResponseDielectronSingleTrack.h @@ -17,12 +17,12 @@ #ifndef PWGEM_DILEPTON_UTILS_MLRESPONSEDIELECTRONSINGLETRACK_H_ #define PWGEM_DILEPTON_UTILS_MLRESPONSEDIELECTRONSINGLETRACK_H_ +#include "Tools/ML/MlResponse.h" + #include #include #include -#include "Tools/ML/MlResponse.h" - // Fill the map of available input features // the key is the feature's name (std::string) // the value is the corresponding value in EnumInputFeatures @@ -76,6 +76,16 @@ break; \ } +// 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 GETTER1 and GETTER2 from track. +#define CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_RELDIFF(FEATURE, GETTER1, GETTER2) \ + case static_cast(InputFeaturesDielectronSingleTrack::FEATURE): { \ + inputFeature = (track.GETTER2() - track.GETTER1()) / track.GETTER1(); \ + break; \ + } + // 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 @@ -104,20 +114,21 @@ enum class InputFeaturesDielectronSingleTrack : uint8_t { tpcNClsShared, tpcChi2NCl, tpcInnerParam, + reldiffp, tpcSignal, tpcNSigmaEl, - tpcNSigmaMu, + // tpcNSigmaMu, tpcNSigmaPi, tpcNSigmaKa, tpcNSigmaPr, beta, tofNSigmaEl, - tofNSigmaMu, + // tofNSigmaMu, tofNSigmaPi, tofNSigmaKa, tofNSigmaPr, tpctofNSigmaEl, - tpctofNSigmaMu, + // tpctofNSigmaMu, tpctofNSigmaPi, tpctofNSigmaKa, tpctofNSigmaPr, @@ -225,20 +236,21 @@ class MlResponseDielectronSingleTrack : public MlResponse CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNClsShared); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcChi2NCl); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcInnerParam); + CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_RELDIFF(reldiffp, p, tpcInnerParam); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcSignal); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaEl); - CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaMu); + // CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaMu); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaPi); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaKa); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tpcNSigmaPr); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(beta); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tofNSigmaEl); - CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tofNSigmaMu); + // CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tofNSigmaMu); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tofNSigmaPi); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tofNSigmaKa); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK(tofNSigmaPr); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF(tpctofNSigmaEl, tpcNSigmaEl, tofNSigmaEl, hasTOF); - CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF(tpctofNSigmaMu, tpcNSigmaMu, tofNSigmaMu, hasTOF); + // CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF(tpctofNSigmaMu, tpcNSigmaMu, tofNSigmaMu, hasTOF); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF(tpctofNSigmaPi, tpcNSigmaPi, tofNSigmaPi, hasTOF); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF(tpctofNSigmaKa, tpcNSigmaKa, tofNSigmaKa, hasTOF); CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF(tpctofNSigmaPr, tpcNSigmaPr, tofNSigmaPr, hasTOF); @@ -372,20 +384,21 @@ class MlResponseDielectronSingleTrack : public MlResponse FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNClsShared), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcChi2NCl), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcInnerParam), + FILL_MAP_DIELECTRON_SINGLE_TRACK(reldiffp), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcSignal), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaEl), - FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaMu), + // FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaMu), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaPi), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaKa), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpcNSigmaPr), FILL_MAP_DIELECTRON_SINGLE_TRACK(beta), FILL_MAP_DIELECTRON_SINGLE_TRACK(tofNSigmaEl), - FILL_MAP_DIELECTRON_SINGLE_TRACK(tofNSigmaMu), + // FILL_MAP_DIELECTRON_SINGLE_TRACK(tofNSigmaMu), FILL_MAP_DIELECTRON_SINGLE_TRACK(tofNSigmaPi), FILL_MAP_DIELECTRON_SINGLE_TRACK(tofNSigmaKa), FILL_MAP_DIELECTRON_SINGLE_TRACK(tofNSigmaPr), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpctofNSigmaEl), - FILL_MAP_DIELECTRON_SINGLE_TRACK(tpctofNSigmaMu), + // FILL_MAP_DIELECTRON_SINGLE_TRACK(tpctofNSigmaMu), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpctofNSigmaPi), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpctofNSigmaKa), FILL_MAP_DIELECTRON_SINGLE_TRACK(tpctofNSigmaPr), @@ -475,6 +488,7 @@ class MlResponseDielectronSingleTrack : public MlResponse #undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_SQRT #undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_COS #undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_TPCTOF +#undef CHECK_AND_FILL_DIELECTRON_SINGLE_TRACK_RELDIFF #undef CHECK_AND_FILL_DIELECTRON_COLLISION #endif // PWGEM_DILEPTON_UTILS_MLRESPONSEDIELECTRONSINGLETRACK_H_ diff --git a/PWGEM/Dilepton/Utils/MlResponseO2Track.h b/PWGEM/Dilepton/Utils/MlResponseO2Track.h new file mode 100644 index 00000000000..ae0c17096fb --- /dev/null +++ b/PWGEM/Dilepton/Utils/MlResponseO2Track.h @@ -0,0 +1,333 @@ +// 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 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 + +#ifndef PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_H_ +#define PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_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_O2_TRACK(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesO2Track::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=FEATURE from track +#define CHECK_AND_FILL_O2_TRACK(GETTER) \ + case static_cast(InputFeaturesO2Track::GETTER): { \ + inputFeature = track.GETTER(); \ + break; \ + } + +// 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=FEATURE from track +#define CHECK_AND_FILL_O2_TRACKPARCOV(FEATURE, GETTER) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = trackParCov.GETTER(); \ + break; \ + } + +// mean ITS cluster size +#define CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(FEATURE, v1, v2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + int nsize = 0; \ + int ncls = 0; \ + for (int il = v1; il < v2; il++) { \ + nsize += track.itsClsSizeInLayer(il); \ + if (nsize > 0) { \ + ncls++; \ + } \ + } \ + inputFeature = static_cast(nsize) / static_cast(ncls); \ + break; \ + } + +// mean ITS cluster size x cos(lambda) +#define CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(FEATURE, v1, v2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + int nsize = 0; \ + int ncls = 0; \ + for (int il = v1; il < v2; il++) { \ + nsize += track.itsClsSizeInLayer(il); \ + if (nsize > 0) { \ + ncls++; \ + } \ + } \ + inputFeature = static_cast(nsize) / static_cast(ncls) * std::cos(std::atan(trackParCov.getTgl())); \ + break; \ + } + +// TPC+TOF combined nSigma +#define CHECK_AND_FILL_O2_TRACK_TPCTOF(FEATURE, GETTER1, GETTER2, GETTER3) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + if (!track.GETTER3()) { \ + inputFeature = track.GETTER1(); \ + } else { \ + if (track.GETTER1() > 0) { \ + inputFeature = sqrt((pow(track.GETTER1(), 2) + pow(track.GETTER2(), 2)) / 2.); \ + } else { \ + inputFeature = (-1) * sqrt((pow(track.GETTER1(), 2) + pow(track.GETTER2(), 2)) / 2.); \ + } \ + } \ + break; \ + } + +// 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 track and applying a sqrt +#define CHECK_AND_FILL_O2_TRACK_SQRT(FEATURE, GETTER) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = sqrt(track.GETTER()); \ + break; \ + } + +// 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 GETTER1 from track and multiplying with cos(atan(GETTER2)) +#define CHECK_AND_FILL_O2_TRACK_COS(FEATURE, GETTER1, GETTER2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = track.GETTER1() * std::cos(std::atan(track.GETTER2())); \ + break; \ + } + +// 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 GETTER1 and GETTER2 from track. +#define CHECK_AND_FILL_O2_TRACK_RELDIFF(FEATURE, GETTER1, GETTER2) \ + case static_cast(InputFeaturesO2Track::FEATURE): { \ + inputFeature = (track.GETTER2() - trackParCov.GETTER1()) / trackParCov.GETTER1(); \ + break; \ + } + +// 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=FEATURE from collision +#define CHECK_AND_FILL_DIELECTRON_COLLISION(GETTER) \ + case static_cast(InputFeaturesO2Track::GETTER): { \ + inputFeature = collision.GETTER(); \ + break; \ + } + +namespace o2::analysis +{ +// possible input features for ML +enum class InputFeaturesO2Track : uint8_t { + tpcInnerParam, + reldiffp, + tpcSignal, + tpcNSigmaEl, + // tpcNSigmaMu, + tpcNSigmaPi, + tpcNSigmaKa, + tpcNSigmaPr, + beta, + tofNSigmaEl, + // tofNSigmaMu, + tofNSigmaPi, + tofNSigmaKa, + tofNSigmaPr, + tpctofNSigmaEl, + // tpctofNSigmaMu, + tpctofNSigmaPi, + tpctofNSigmaKa, + tpctofNSigmaPr, + tpcNClsFound, + tpcNClsCrossedRows, + hasITS, + hasTPC, + hasTRD, + hasTOF, + tgl, + p, + itsClusterSizes, + meanClusterSizeITS, + meanClusterSizeITSib, + meanClusterSizeITSob, + meanClusterSizeITSCos, + meanClusterSizeITSibCos, + meanClusterSizeITSobCos, + posZ, + numContrib, + trackOccupancyInTimeRange, + ft0cOccupancyInTimeRange, +}; + +template +class MlResponseO2Track : public MlResponse +{ + public: + /// Default constructor + MlResponseO2Track() = default; + /// Default destructor + virtual ~MlResponseO2Track() = default; + + template + float return_feature(uint8_t idx, T const& track, U const& trackParCov, V const& collision) + { + float inputFeature = 0.; + switch (idx) { + CHECK_AND_FILL_O2_TRACK(tpcInnerParam); + CHECK_AND_FILL_O2_TRACK_RELDIFF(reldiffp, getP, tpcInnerParam); + CHECK_AND_FILL_O2_TRACK(tpcSignal); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaEl); + // CHECK_AND_FILL_O2_TRACK(tpcNSigmaMu); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaPi); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaKa); + CHECK_AND_FILL_O2_TRACK(tpcNSigmaPr); + CHECK_AND_FILL_O2_TRACK(beta); + CHECK_AND_FILL_O2_TRACK(tofNSigmaEl); + // CHECK_AND_FILL_O2_TRACK(tofNSigmaMu); + CHECK_AND_FILL_O2_TRACK(tofNSigmaPi); + CHECK_AND_FILL_O2_TRACK(tofNSigmaKa); + CHECK_AND_FILL_O2_TRACK(tofNSigmaPr); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaEl, tpcNSigmaEl, tofNSigmaEl, hasTOF); + // CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaMu, tpcNSigmaMu, tofNSigmaMu, hasTOF); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaPi, tpcNSigmaPi, tofNSigmaPi, hasTOF); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaKa, tpcNSigmaKa, tofNSigmaKa, hasTOF); + CHECK_AND_FILL_O2_TRACK_TPCTOF(tpctofNSigmaPr, tpcNSigmaPr, tofNSigmaPr, hasTOF); + CHECK_AND_FILL_O2_TRACK(tpcNClsFound); + CHECK_AND_FILL_O2_TRACK(tpcNClsCrossedRows); + CHECK_AND_FILL_O2_TRACK(hasITS); + CHECK_AND_FILL_O2_TRACK(hasTPC); + CHECK_AND_FILL_O2_TRACK(hasTRD); + CHECK_AND_FILL_O2_TRACK(hasTOF); + CHECK_AND_FILL_O2_TRACKPARCOV(tgl, getTgl); + CHECK_AND_FILL_O2_TRACKPARCOV(p, getP); + CHECK_AND_FILL_O2_TRACK(itsClusterSizes); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(meanClusterSizeITS, 0, 7); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(meanClusterSizeITSib, 0, 3); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE(meanClusterSizeITSob, 3, 7); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(meanClusterSizeITSCos, 0, 7); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(meanClusterSizeITSibCos, 0, 3); + CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS(meanClusterSizeITSobCos, 3, 7); + CHECK_AND_FILL_DIELECTRON_COLLISION(posZ); + CHECK_AND_FILL_DIELECTRON_COLLISION(numContrib); + CHECK_AND_FILL_DIELECTRON_COLLISION(trackOccupancyInTimeRange); + CHECK_AND_FILL_DIELECTRON_COLLISION(ft0cOccupancyInTimeRange); + } + return inputFeature; + } + + /// Method to get the input features vector needed for ML inference + /// \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 inputFeatures; + for (const auto& idx : MlResponse::mCachedIndices) { + float inputFeature = return_feature(idx, track, trackParCov, collision); + inputFeatures.emplace_back(inputFeature); + } + return inputFeatures; + } + + /// Method to get the value of variable chosen for binning + /// \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) + { + return return_feature(mCachedIndexBinning, track, trackParCov, collision); + } + + void cacheBinningIndex(std::string const& cfgBinningFeature) + { + setAvailableInputFeatures(); + if (MlResponse::mAvailableInputFeatures.count(cfgBinningFeature)) { + mCachedIndexBinning = MlResponse::mAvailableInputFeatures[cfgBinningFeature]; + } else { + LOG(fatal) << "Binning feature " << cfgBinningFeature << " not available! Please check your configurables."; + } + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_O2_TRACK(tpcInnerParam), + FILL_MAP_O2_TRACK(reldiffp), + FILL_MAP_O2_TRACK(tpcSignal), + FILL_MAP_O2_TRACK(tpcNSigmaEl), + // FILL_MAP_O2_TRACK(tpcNSigmaMu), + FILL_MAP_O2_TRACK(tpcNSigmaPi), + FILL_MAP_O2_TRACK(tpcNSigmaKa), + FILL_MAP_O2_TRACK(tpcNSigmaPr), + FILL_MAP_O2_TRACK(beta), + FILL_MAP_O2_TRACK(tofNSigmaEl), + // FILL_MAP_O2_TRACK(tofNSigmaMu), + FILL_MAP_O2_TRACK(tofNSigmaPi), + FILL_MAP_O2_TRACK(tofNSigmaKa), + FILL_MAP_O2_TRACK(tofNSigmaPr), + FILL_MAP_O2_TRACK(tpctofNSigmaEl), + // FILL_MAP_O2_TRACK(tpctofNSigmaMu), + FILL_MAP_O2_TRACK(tpctofNSigmaPi), + FILL_MAP_O2_TRACK(tpctofNSigmaKa), + FILL_MAP_O2_TRACK(tpctofNSigmaPr), + FILL_MAP_O2_TRACK(tpcNClsFound), + FILL_MAP_O2_TRACK(tpcNClsCrossedRows), + FILL_MAP_O2_TRACK(hasITS), + FILL_MAP_O2_TRACK(hasTPC), + FILL_MAP_O2_TRACK(hasTRD), + FILL_MAP_O2_TRACK(hasTOF), + FILL_MAP_O2_TRACK(tgl), + FILL_MAP_O2_TRACK(p), + FILL_MAP_O2_TRACK(itsClusterSizes), + FILL_MAP_O2_TRACK(meanClusterSizeITS), + FILL_MAP_O2_TRACK(meanClusterSizeITSib), + FILL_MAP_O2_TRACK(meanClusterSizeITSob), + FILL_MAP_O2_TRACK(meanClusterSizeITSCos), + FILL_MAP_O2_TRACK(meanClusterSizeITSibCos), + FILL_MAP_O2_TRACK(meanClusterSizeITSobCos), + FILL_MAP_O2_TRACK(posZ), + FILL_MAP_O2_TRACK(numContrib), + FILL_MAP_O2_TRACK(trackOccupancyInTimeRange), + FILL_MAP_O2_TRACK(ft0cOccupancyInTimeRange)}; + } + + uint8_t mCachedIndexBinning; // index correspondance between configurable and available input features +}; + +} // namespace o2::analysis + +#undef FILL_MAP_O2_TRACK +#undef CHECK_AND_FILL_O2_TRACK +#undef CHECK_AND_FILL_O2_TRACKPARCOV +#undef CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE +#undef CHECK_AND_FILL_O2_TRACK_MEAN_ITSCLUSTER_SIZE_COS +#undef CHECK_AND_FILL_O2_TRACK_SQRT +#undef CHECK_AND_FILL_O2_TRACK_COS +#undef CHECK_AND_FILL_O2_TRACK_TPCTOF +#undef CHECK_AND_FILL_O2_TRACK_RELDIFF +#undef CHECK_AND_FILL_DIELECTRON_COLLISION + +#endif // PWGEM_DILEPTON_UTILS_MLRESPONSEO2TRACK_H_ diff --git a/PWGEM/Dilepton/Utils/MomentumSmearer.h b/PWGEM/Dilepton/Utils/MomentumSmearer.h index 7e36dcfed0f..10699e4c2a0 100644 --- a/PWGEM/Dilepton/Utils/MomentumSmearer.h +++ b/PWGEM/Dilepton/Utils/MomentumSmearer.h @@ -15,22 +15,27 @@ #ifndef PWGEM_DILEPTON_UTILS_MOMENTUMSMEARER_H_ #define PWGEM_DILEPTON_UTILS_MOMENTUMSMEARER_H_ -#include +#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 -#include #include +#include -#include "CCDB/BasicCCDBManager.h" -#include "Framework/Logger.h" +#include -using namespace o2::framework; using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; class MomentumSmearer { diff --git a/PWGEM/Dilepton/Utils/PairUtilities.h b/PWGEM/Dilepton/Utils/PairUtilities.h index a1010e76435..1fcede0e14d 100644 --- a/PWGEM/Dilepton/Utils/PairUtilities.h +++ b/PWGEM/Dilepton/Utils/PairUtilities.h @@ -15,14 +15,18 @@ #ifndef PWGEM_DILEPTON_UTILS_PAIRUTILITIES_H_ #define PWGEM_DILEPTON_UTILS_PAIRUTILITIES_H_ -#include -#include +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" + +#include "ReconstructionDataFormats/TrackFwd.h" + +#include "Math/GenVector/Boost.h" #include "Math/SMatrix.h" #include "Math/Vector3D.h" #include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "Common/Core/RecoDecay.h" -#include "ReconstructionDataFormats/TrackFwd.h" + +#include +#include //_______________________________________________________________________ namespace o2::aod::pwgem::dilepton::utils::pairutil @@ -42,6 +46,11 @@ enum class DileptonAnalysisType : int { kHFll = 6, }; +enum class DileptonHadronAnalysisType : int { + kAzimuthalCorrelation = 0, + kCumulant = 1, +}; + enum class DileptonPrefilterBit : int { kElFromPC = 0, // electron from photon conversion kElFromPi0_1 = 1, // electron from pi0 dalitz decay, threshold 1 diff --git a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx index c2f313e6e62..d8475e550e9 100644 --- a/PWGEM/PhotonMeson/Core/CutsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/CutsLibrary.cxx @@ -132,7 +132,7 @@ V0PhotonCut* o2::aod::pwgem::photon::pcmcuts::GetCut(const char* cutName) cut->SetChi2PerClusterITS(-1e+10, 5.0); cut->SetNClustersITS(2, 4); cut->SetMeanClusterSizeITSob(0.0, 16.0); - cut->SetIsWithinBeamPipe(true); + // cut->SetIsWithinBeamPipe(true); // for v0 cut->SetMinCosPA(0.99); cut->SetMaxPCA(3.0); @@ -201,7 +201,7 @@ V0PhotonCut* o2::aod::pwgem::photon::pcmcuts::GetCut(const char* cutName) cut->SetChi2PerClusterITS(-1e+10, 5.0); cut->SetNClustersITS(2, 4); cut->SetMeanClusterSizeITSob(0.0, 16.0); - cut->SetIsWithinBeamPipe(true); + // cut->SetIsWithinBeamPipe(true); // for v0 cut->SetMinCosPA(0.995); cut->SetMaxPCA(0.5); @@ -216,7 +216,7 @@ V0PhotonCut* o2::aod::pwgem::photon::pcmcuts::GetCut(const char* cutName) cut->SetChi2PerClusterITS(-1e+10, 5.0); cut->SetNClustersITS(2, 4); cut->SetMeanClusterSizeITSob(0.0, 16.0); - cut->SetIsWithinBeamPipe(true); + // cut->SetIsWithinBeamPipe(true); cut->SetRequireITSTPC(true); // for v0 cut->SetMinCosPA(0.99); @@ -232,7 +232,7 @@ V0PhotonCut* o2::aod::pwgem::photon::pcmcuts::GetCut(const char* cutName) cut->SetChi2PerClusterITS(-1e+10, 5.0); cut->SetNClustersITS(2, 4); cut->SetMeanClusterSizeITSob(0.0, 16.0); - cut->SetIsWithinBeamPipe(true); + // cut->SetIsWithinBeamPipe(true); // for v0 cut->SetMinCosPA(0.99); cut->SetMaxPCA(3.0); @@ -249,7 +249,7 @@ V0PhotonCut* o2::aod::pwgem::photon::pcmcuts::GetCut(const char* cutName) cut->SetChi2PerClusterITS(-1e+10, 5.0); cut->SetNClustersITS(2, 4); cut->SetMeanClusterSizeITSob(0.0, 16.0); - cut->SetIsWithinBeamPipe(false); + // cut->SetIsWithinBeamPipe(false); // for v0 cut->SetMinCosPA(0.95); cut->SetMaxPCA(3.0); @@ -265,7 +265,7 @@ V0PhotonCut* o2::aod::pwgem::photon::pcmcuts::GetCut(const char* cutName) cut->SetChi2PerClusterITS(-1e+10, 5.0); cut->SetNClustersITS(2, 4); cut->SetMeanClusterSizeITSob(0.0, 16.0); - cut->SetIsWithinBeamPipe(false); + // cut->SetIsWithinBeamPipe(false); // for v0 cut->SetMinCosPA(0.95); cut->SetMaxPCA(3.0); diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx index 99ac9ee356a..df6418474a1 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.cxx +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.cxx @@ -13,11 +13,12 @@ // Class for dilepton Cut // -#include -#include +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" #include "Framework/Logger.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" + +#include +#include ClassImp(DalitzEECut); @@ -179,3 +180,9 @@ void DalitzEECut::SetPIDScheme(int scheme) mPIDScheme = scheme; LOG(info) << "DalitzEE Cut, PID scheme: " << static_cast(mPIDScheme); } +void DalitzEECut::IncludeITSsa(bool flag, float max) +{ + mIncludeITSsa = flag; + mMaxPtITSsa = max; + LOG(info) << "DalitzEE Cut, include ITSsa tracks: " << mIncludeITSsa << ", mMaxPtITSsa = " << mMaxPtITSsa; +} diff --git a/PWGEM/PhotonMeson/Core/DalitzEECut.h b/PWGEM/PhotonMeson/Core/DalitzEECut.h index 60dff1786d1..ddc1da18340 100644 --- a/PWGEM/PhotonMeson/Core/DalitzEECut.h +++ b/PWGEM/PhotonMeson/Core/DalitzEECut.h @@ -16,22 +16,24 @@ #ifndef PWGEM_PHOTONMESON_CORE_DALITZEECUT_H_ #define PWGEM_PHOTONMESON_CORE_DALITZEECUT_H_ -#include -#include -#include -#include -#include -#include "TNamed.h" -#include "Math/Vector4D.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" #include "Tools/ML/MlResponse.h" #include "Tools/ML/model.h" -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" #include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "Framework/DataTypes.h" +#include "Framework/Logger.h" + +#include "Math/Vector4D.h" +#include "TNamed.h" + +#include +#include +#include +#include +#include using namespace o2::aod::pwgem::dilepton::utils::emtrackutil; @@ -62,7 +64,6 @@ class DalitzEECut : public TNamed kDCAz, kITSNCls, kITSChi2NDF, - kITSCluserSize, kNCuts }; static const char* mCutNames[static_cast(DalitzEECuts::kNCuts)]; @@ -116,7 +117,7 @@ class DalitzEECut : public TNamed template bool IsSelectedTrack(TTrack const& track, TCollision const& = 0) const { - if (!track.hasITS() || !track.hasTPC()) { // track has to be ITS-TPC matched track + if (!track.hasITS()) { return false; } @@ -143,9 +144,6 @@ class DalitzEECut : public TNamed if (!IsSelectedTrack(track, DalitzEECuts::kITSChi2NDF)) { return false; } - if (!IsSelectedTrack(track, DalitzEECuts::kITSCluserSize)) { - return false; - } if (mRequireITSibAny) { auto hits_ib = std::count_if(its_ib_any_Requirement.second.begin(), its_ib_any_Requirement.second.end(), [&](auto&& requiredLayer) { return track.itsClusterMap() & (1 << requiredLayer); }); @@ -161,28 +159,44 @@ class DalitzEECut : public TNamed } } - // TPC cuts - if (!IsSelectedTrack(track, DalitzEECuts::kTPCNCls)) { - return false; - } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRows)) { + if (!mIncludeITSsa && (!track.hasITS() || !track.hasTPC())) { // track has to be ITS-TPC matched track return false; } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRowsOverNCls)) { - return false; - } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCFracSharedClusters)) { + + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && track.pt() > mMaxPtITSsa) { // ITSsa return false; } - if (!IsSelectedTrack(track, DalitzEECuts::kTPCChi2NDF)) { - return false; + + // TPC cuts + if (track.hasTPC()) { + if (!IsSelectedTrack(track, DalitzEECuts::kTPCNCls)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRows)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCCrossedRowsOverNCls)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCFracSharedClusters)) { + return false; + } + if (!IsSelectedTrack(track, DalitzEECuts::kTPCChi2NDF)) { + return false; + } } // PID cuts - if (!PassPID(track)) { - return false; + if (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) { // ITSsa + float meanClusterSizeITS = track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())); + if (meanClusterSizeITS < mMinMeanClusterSizeITS || mMaxMeanClusterSizeITS < meanClusterSizeITS) { + return false; + } + } else { + if (!PassPID(track)) { + return false; + } } - return true; } @@ -226,10 +240,10 @@ class DalitzEECut : public TNamed { switch (cut) { case DalitzEECuts::kTrackPtRange: - return track.pt() >= mMinTrackPt && track.pt() <= mMaxTrackPt; + return track.pt() > mMinTrackPt && track.pt() < mMaxTrackPt; case DalitzEECuts::kTrackEtaRange: - return track.eta() >= mMinTrackEta && track.eta() <= mMaxTrackEta; + return track.eta() > mMinTrackEta && track.eta() < mMaxTrackEta; case DalitzEECuts::kTPCNCls: return track.tpcNClsFound() >= mMinNClustersTPC; @@ -241,19 +255,19 @@ class DalitzEECut : public TNamed return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; case DalitzEECuts::kTPCFracSharedClusters: - return track.tpcFractionSharedCls() <= mMaxFracSharedClustersTPC; + return track.tpcFractionSharedCls() < mMaxFracSharedClustersTPC; case DalitzEECuts::kTPCChi2NDF: return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; case DalitzEECuts::kDCA3Dsigma: - return mMinDca3D <= dca3DinSigma(track) && dca3DinSigma(track) <= mMaxDca3D; // in sigma for single leg + return mMinDca3D < dca3DinSigma(track) && dca3DinSigma(track) < mMaxDca3D; // in sigma for single leg case DalitzEECuts::kDCAxy: - return std::fabs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); case DalitzEECuts::kDCAz: - return std::fabs(track.dcaZ()) <= mMaxDcaZ; + return std::fabs(track.dcaZ()) < mMaxDcaZ; case DalitzEECuts::kITSNCls: return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; @@ -261,9 +275,6 @@ class DalitzEECut : public TNamed case DalitzEECuts::kITSChi2NDF: return mMinChi2PerClusterITS < track.itsChi2NCl() && track.itsChi2NCl() < mMaxChi2PerClusterITS; - case DalitzEECuts::kITSCluserSize: - return mMinMeanClusterSizeITS < track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITS() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; - default: return false; } @@ -272,7 +283,7 @@ class DalitzEECut : public TNamed // Setters void SetPairPtRange(float minPt = 0.f, float maxPt = 1e10f); void SetPairYRange(float minY = -1e10f, float maxY = 1e10f); - void SetMeeRange(float min = 0.f, float max = 0.5); + void SetMeeRange(float min = 0.f, float max = 0.04); void SetMaxPhivPairMeeDep(std::function meeDepCut); void SelectPhotonConversion(bool flag); @@ -301,6 +312,7 @@ class DalitzEECut : public TNamed void SetMaxDcaXYPtDep(std::function ptDepCut); void ApplyPrefilter(bool flag); void ApplyPhiV(bool flag); + void IncludeITSsa(bool flag, float maxpt); // Getters bool IsPhotonConversionSelected() const { return mSelectPC; } @@ -338,8 +350,10 @@ class DalitzEECut : public TNamed float mMaxDcaZ{1.0f}; // max dca in z direction std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT bool mApplyPhiV{true}; - float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // max x cos(Lmabda) + float mMinMeanClusterSizeITS{-1e10f}, mMaxMeanClusterSizeITS{1e10f}; // x cos(lmabda) float mMinChi2TOF{-1e10f}, mMaxChi2TOF{1e10f}; // max tof chi2 per + bool mIncludeITSsa{false}; + float mMaxPtITSsa{0.15}; // pid cuts int mPIDScheme{-1}; diff --git a/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h b/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h new file mode 100644 index 00000000000..53e26450c64 --- /dev/null +++ b/PWGEM/PhotonMeson/Core/DiphotonHadronMPC.h @@ -0,0 +1,985 @@ +// 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/EMTrackUtilities.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/NMHistograms.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Common/CCDB/RCTSelectionFlags.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/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TString.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::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; + +using MyTracks = soa::Join; +using MyTrack = MyTracks::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", {60, -3, 3}, "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.clear(); + used_photonIds.shrink_to_fit(); + used_dileptonIds.clear(); + used_dileptonIds.shrink_to_fit(); + used_refTrackIds.clear(); + used_refTrackIds.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, -M_PI / 2, +3 * M_PI / 2, 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, 2 * M_PI, "#varphi_{h} (rad.)"}; + + fRegistry.add("Hadron/hs", "hadron", kTHnSparseD, {axis_pt_hadron, axis_eta_hadron, axis_phi_hadron}, true); + + 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{cfgNbinsDPhi, -M_PI / 2, +3 * M_PI / 2, "#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_track = aod::emprimarytrack::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 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; // + std::vector> used_dileptonIds; // + std::vector> used_refTrackIds; // + std::vector> used_diphotonIds; // + 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()); + for (const auto& track : refTracks_per_collision) { + if (fEMTrackCut.IsSelected(track)) { + fRegistry.fill(HIST("Hadron/hs"), track.pt(), track.eta(), track.phi()); + } + } + + 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; + 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, -M_PI / 2, 1U); + fRegistry.fill(HIST("DiphotonHadron/same/hs"), v12.M(), v12.Pt(), deta, dphi); + npair++; + std::pair pair_tmp_ref = std::make_pair(ndf, track.globalIndex()); + if (std::find(used_refTrackIds.begin(), used_refTrackIds.end(), pair_tmp_ref) == used_refTrackIds.end()) { // add a ref track in mixing pool + emh_ref->AddTrackToEventPool(key_df_collision, EMTrack(ndf, track.globalIndex(), collision.globalIndex(), track.globalIndex(), track.pt(), track.eta(), track.phi(), 0.139)); + used_refTrackIds.emplace_back(pair_tmp_ref); + } + } + } // end of ref track loop + + if (npair > 0) { + std::tuple tuple_tmp_diphoton = std::make_tuple(ndf, g1.globalIndex(), g2.globalIndex(), -1); + if (std::find(used_diphotonIds.begin(), used_diphotonIds.end(), tuple_tmp_diphoton) == used_diphotonIds.end()) { + emh_diphoton->AddTrackToEventPool(key_df_collision, EMTrack(ndf, -1, collision.globalIndex(), -1, v12.Pt(), v12.Eta(), v12.Phi(), v12.M())); + used_diphotonIds.emplace_back(tuple_tmp_diphoton); + } + } + + std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); + std::pair pair_tmp_id2 = std::make_pair(ndf, g2.globalIndex()); + if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id1) == used_photonIds.end()) { + emh1->AddTrackToEventPool(key_df_collision, EMTrack(ndf, g1.globalIndex(), collision.globalIndex(), g1.globalIndex(), g1.pt(), g1.eta(), g1.phi(), 0)); + used_photonIds.emplace_back(pair_tmp_id1); + } + if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id2) == used_photonIds.end()) { + emh1->AddTrackToEventPool(key_df_collision, EMTrack(ndf, g2.globalIndex(), collision.globalIndex(), g2.globalIndex(), g2.pt(), g2.eta(), g2.phi(), 0)); + used_photonIds.emplace_back(pair_tmp_id2); + } + 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; + 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, -M_PI / 2, 1U); + fRegistry.fill(HIST("DiphotonHadron/same/hs"), veeg.M(), veeg.Pt(), deta, dphi); + npair++; + + std::pair pair_tmp_ref = std::make_pair(ndf, track.globalIndex()); + if (std::find(used_refTrackIds.begin(), used_refTrackIds.end(), pair_tmp_ref) == used_refTrackIds.end()) { // add a ref track in mixing pool + emh_ref->AddTrackToEventPool(key_df_collision, EMTrack(ndf, track.globalIndex(), collision.globalIndex(), track.globalIndex(), track.pt(), track.eta(), track.phi(), 0.139)); + used_refTrackIds.emplace_back(pair_tmp_ref); + } + } // end of ref track loop + + if (npair > 0) { + std::tuple tuple_tmp_diphoton = std::make_tuple(ndf, g1.globalIndex(), pos2.trackId(), ele2.trackId()); + if (std::find(used_diphotonIds.begin(), used_diphotonIds.end(), tuple_tmp_diphoton) == used_diphotonIds.end()) { + emh_diphoton->AddTrackToEventPool(key_df_collision, EMTrack(ndf, -1, collision.globalIndex(), -1, veeg.Pt(), veeg.Eta(), veeg.Phi(), veeg.M())); + used_diphotonIds.emplace_back(tuple_tmp_diphoton); + } + } + + std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); + std::tuple tuple_tmp_id2 = std::make_tuple(ndf, collision.globalIndex(), pos2.trackId(), ele2.trackId()); + if (std::find(used_photonIds.begin(), used_photonIds.end(), pair_tmp_id1) == used_photonIds.end()) { + emh1->AddTrackToEventPool(key_df_collision, EMTrack(ndf, g1.globalIndex(), collision.globalIndex(), -1, g1.pt(), g1.eta(), g1.phi(), 0)); + used_photonIds.emplace_back(pair_tmp_id1); + } + if (std::find(used_dileptonIds.begin(), used_dileptonIds.end(), tuple_tmp_id2) == used_dileptonIds.end()) { + emh2->AddTrackToEventPool(key_df_collision, EMTrack(ndf, -1, collision.globalIndex(), -1, v_ee.Pt(), v_ee.Eta(), v_ee.Phi(), v_ee.M())); + used_dileptonIds.emplace_back(tuple_tmp_id2); + } + ndiphoton++; + } // end of dielectron loop + } // end of g1 loop + } // end of pairing in same event + + if (ndiphoton > 0) { + 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, -M_PI / 2, 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, -M_PI / 2, 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, -M_PI / 2, 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, -M_PI / 2, 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, MyTracks 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(FilteredMyCollisionsWithSWT const& collisions, MyTracks 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 582b9754057..199da171c11 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.cxx @@ -13,11 +13,17 @@ // Class for EMCal cluster selection // -#include -#include "Framework/Logger.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" + #include "PWGJE/DataModel/EMCALClusters.h" +#include "Framework/Logger.h" + +#include + +#include +#include + ClassImp(EMCPhotonCut); const char* EMCPhotonCut::mCutNames[static_cast(EMCPhotonCut::EMCPhotonCuts::kNCuts)] = {"Definition", "Energy", "NCell", "M02", "Timing", "TrackMatching", "Exotic"}; diff --git a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h index 8bfd8ca630f..1e3ac74f6cd 100644 --- a/PWGEM/PhotonMeson/Core/EMCPhotonCut.h +++ b/PWGEM/PhotonMeson/Core/EMCPhotonCut.h @@ -9,22 +9,19 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// -// Class for emcal photon selection -// +/// \file EMCPhotonCut.h +/// \brief Header of class for emcal photon selection. +/// \author M. Hemmer, marvin.hemmer@cern.ch; N. Strangmann, nicolas.strangmann@cern.ch #ifndef PWGEM_PHOTONMESON_CORE_EMCPHOTONCUT_H_ #define PWGEM_PHOTONMESON_CORE_EMCPHOTONCUT_H_ -#include -#include -#include +#include + +#include + +#include #include -#include -#include "Framework/Logger.h" -#include "Framework/DataTypes.h" -#include "Rtypes.h" -#include "TNamed.h" class EMCPhotonCut : public TNamed { @@ -95,14 +92,14 @@ class EMCPhotonCut : public TNamed return mMinTime <= cluster.time() && cluster.time() <= mMaxTime; case EMCPhotonCuts::kTM: { - auto trackseta = cluster.tracketa(); // std:vector - auto tracksphi = cluster.trackphi(); // std:vector - auto trackspt = cluster.trackpt(); // std:vector - auto tracksp = cluster.trackp(); // std:vector + auto dEtas = cluster.deltaEta(); // std:vector + auto dPhis = cluster.deltaPhi(); // std:vector + auto trackspt = cluster.trackpt(); // std:vector + auto tracksp = cluster.trackp(); // std:vector int ntrack = tracksp.size(); for (int itr = 0; itr < ntrack; itr++) { - float dEta = fabs(trackseta[itr] - cluster.eta()); - float dPhi = fabs(tracksphi[itr] - cluster.phi()); + float dEta = std::fabs(dEtas[itr]); + float dPhi = std::fabs(dPhis[itr]); bool result = (dEta > mTrackMatchingEta(trackspt[itr])) || (dPhi > mTrackMatchingPhi(trackspt[itr])) || (cluster.e() / tracksp[itr] >= mMinEoverP); if (!result) { return false; diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx index 50174ab9e08..e54a462e9dc 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.cxx @@ -9,28 +9,25 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -// Contact: daiki.sekihata@cern.ch -// -#include -#include -#include -using namespace std; +/// \file HistogramsLibrary.cxx +/// \brief Small histogram library for photon and meson analysis. +/// \author D. Sekihata, daiki.sekihata@cern.ch + +#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" + +#include -#include -#include +#include +#include #include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include "Framework/Logger.h" -#include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include + +#include + +#include + +using namespace std; void o2::aod::pwgem::photon::histogram::DefineHistograms(THashList* list, const char* histClass, const char* subGroup) { @@ -184,7 +181,7 @@ void o2::aod::pwgem::photon::histogram::DefineHistograms(THashList* list, const list->Add(new TH2F("hEtaRec_DeltaEta", "photon #eta resolution;#eta^{rec} of conversion point;#eta^{rec} - #eta^{gen}", 400, -2, +2, 400, -1.0f, 1.0f)); list->Add(new TH2F("hEtaRec_DeltaPhi", "photon #varphi resolution;#eta^{rec} of conversion point;#varphi^{rec} - #varphi^{gen} (rad.)", 400, -2, +2, 400, -1.0f, 1.0f)); } // end of mc - } // end of V0 + } // end of V0 if (TString(histClass).Contains("Dalitz")) { THnSparseF* hs_dilepton_uls_same = nullptr; @@ -576,7 +573,7 @@ void o2::aod::pwgem::photon::histogram::DefineHistograms(THashList* list, const hs_conv_point_mix->Sumw2(); list->Add(hs_conv_point_mix); } // end of pair - } // end of material budget study + } // end of material budget study if (TString(histClass) == "Generated") { list->Add(new TH1F("hCollisionCounter", "hCollisionCounter", 5, 0.5f, 5.5f)); diff --git a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h index 324718a663e..368acef59ce 100644 --- a/PWGEM/PhotonMeson/Core/HistogramsLibrary.h +++ b/PWGEM/PhotonMeson/Core/HistogramsLibrary.h @@ -8,34 +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. -// -// Contact: daiki.sekihata@cern.ch -// + +/// \file HistogramsLibrary.h +/// \brief Small histogram library for photon and meson analysis. +/// \author D. Sekihata, daiki.sekihata@cern.ch #ifndef PWGEM_PHOTONMESON_CORE_HISTOGRAMSLIBRARY_H_ #define PWGEM_PHOTONMESON_CORE_HISTOGRAMSLIBRARY_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/RecoDecay.h" +#include +#include +#include + +#include +#include +#include + enum EMHistType { kEvent = 0, kEvent_Cent = 1, @@ -48,6 +39,8 @@ enum EMHistType { kEMCCluster = 8, }; +const float maxZ = 10.f; + namespace o2::aod { namespace pwgem::photon::histogram @@ -81,7 +74,7 @@ void FillHistClass(THashList* list, const char* subGroup, T1 const& obj1 /*, con if (obj1.sel8()) { reinterpret_cast(list->FindObject("hCollisionCounter"))->Fill("sel8", 1.f); } - if (abs(obj1.posZ()) < 10.0) { + if (std::abs(obj1.posZ()) < maxZ) { reinterpret_cast(list->FindObject("hCollisionCounter"))->Fill("|Z_{vtx}| < 10 cm", 1.f); } @@ -176,9 +169,9 @@ void FillHistClass(THashList* list, const char* subGroup, T1 const& obj1 /*, con reinterpret_cast(list->FindObject("hQoverPt"))->Fill(obj1.sign() / obj1.pt()); reinterpret_cast(list->FindObject("hEtaPhi"))->Fill(obj1.phi(), obj1.eta()); reinterpret_cast(list->FindObject("hDCAxyz"))->Fill(obj1.dcaXY(), obj1.dcaZ()); - reinterpret_cast(list->FindObject("hDCAxyzSigma"))->Fill(obj1.dcaXY() / sqrt(obj1.cYY()), obj1.dcaZ() / sqrt(obj1.cZZ())); - reinterpret_cast(list->FindObject("hDCAxyRes_Pt"))->Fill(obj1.pt(), sqrt(obj1.cYY()) * 1e+4); // convert cm to um - reinterpret_cast(list->FindObject("hDCAzRes_Pt"))->Fill(obj1.pt(), sqrt(obj1.cZZ()) * 1e+4); // convert cm to um + reinterpret_cast(list->FindObject("hDCAxyzSigma"))->Fill(obj1.dcaXY() / std::sqrt(obj1.cYY()), obj1.dcaZ() / std::sqrt(obj1.cZZ())); + reinterpret_cast(list->FindObject("hDCAxyRes_Pt"))->Fill(obj1.pt(), std::sqrt(obj1.cYY()) * 1e+4); // convert cm to um + reinterpret_cast(list->FindObject("hDCAzRes_Pt"))->Fill(obj1.pt(), std::sqrt(obj1.cZZ()) * 1e+4); // convert cm to um reinterpret_cast(list->FindObject("hNclsITS"))->Fill(obj1.itsNCls()); reinterpret_cast(list->FindObject("hNclsTPC"))->Fill(obj1.tpcNClsFound()); reinterpret_cast(list->FindObject("hNcrTPC"))->Fill(obj1.tpcNClsCrossedRows()); @@ -225,8 +218,8 @@ void FillHistClass(THashList* list, const char* subGroup, T1 const& obj1 /*, con reinterpret_cast(list->FindObject("hPt"))->Fill(obj1.pt()); reinterpret_cast(list->FindObject("hE"))->Fill(obj1.e()); reinterpret_cast(list->FindObject("hEtaPhi"))->Fill(obj1.phi(), obj1.eta()); - for (size_t itrack = 0; itrack < obj1.tracketa().size(); itrack++) { // Fill TrackEtaPhi histogram with delta phi and delta eta of all tracks saved in the vectors in skimmerGammaCalo.cxx - reinterpret_cast(list->FindObject("hTrackEtaPhi"))->Fill(obj1.trackphi()[itrack] - obj1.phi(), obj1.tracketa()[itrack] - obj1.eta()); + for (size_t itrack = 0; itrack < obj1.deltaEta().size(); itrack++) { // Fill TrackEtaPhi histogram with delta phi and delta eta of all tracks saved in the vectors in skimmerGammaCalo.cxx + reinterpret_cast(list->FindObject("hTrackEtaPhi"))->Fill(obj1.deltaPhi()[itrack], obj1.deltaEta()[itrack]); } } } diff --git a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h index e4bc8414601..cf859a59fc4 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGamma.h @@ -19,46 +19,47 @@ #ifndef PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMA_H_ #define PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMA_H_ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/LorentzRotation.h" -#include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#include "DetectorsBase/GeometryManager.h" -#include "EMCALBase/Geometry.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/Dilepton/Utils/EMTrack.h" +#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/Dilepton/Utils/EventMixingHandler.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/Utils/PairUtilities.h" -#include "PWGEM/Dilepton/Utils/EMTrack.h" -#include "PWGEM/Dilepton/Utils/EventMixingHandler.h" +#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" #include "PWGEM/PhotonMeson/Utils/NMHistograms.h" -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "EMCALBase/Geometry.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.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 using namespace o2; using namespace o2::aod; @@ -70,9 +71,12 @@ 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 = soa::Join; using MyCollision = MyCollisions::iterator; +using MyCollisionsWithJJMC = soa::Join; +using MyCollisionWithJJMC = MyCollisionsWithJJMC::iterator; + using MyV0Photons = soa::Filtered>; using MyV0Photon = MyV0Photons::iterator; @@ -141,18 +145,17 @@ struct Pi0EtaToGammaGamma { 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_min_cospa{"cfg_min_cospa", 0.999, "min V0 CosPA"}; + Configurable cfg_max_pca{"cfg_max_pca", 1.5, "max distance btween 2 legs"}; Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_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", 10, "min ncluster tpc"}; + 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", 5.0, "max chi2/NclsITS"}; + 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"}; @@ -176,12 +179,14 @@ struct Pi0EtaToGammaGamma { 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_chi2its{"cfg_max_chi2its", 36.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_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to electron"}; + 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"}; 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"}; @@ -368,7 +373,6 @@ struct Pi0EtaToGammaGamma { fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); @@ -400,6 +404,7 @@ struct Pi0EtaToGammaGamma { 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(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); @@ -544,8 +549,8 @@ struct Pi0EtaToGammaGamma { Preslice perCollision_phos = aod::phoscluster::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); + 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; + 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; using MyEMH = o2::aod::pwgem::dilepton::utils::EventMixingHandler, std::pair, EMTrack>; MyEMH* emh1 = nullptr; @@ -568,7 +573,12 @@ struct Pi0EtaToGammaGamma { continue; } - if (eventcuts.onlyKeepWeightedEvents && std::fabs(collision.weight() - 1.) < 1E-10) { + float weight = 1.f; + if constexpr (std::is_same_v, FilteredMyCollisionsWithJJMC>) { + weight = collision.weight(); + } + + if (eventcuts.onlyKeepWeightedEvents && std::fabs(weight - 1.f) < 1E-10) { continue; } @@ -577,13 +587,13 @@ struct Pi0EtaToGammaGamma { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, collision.weight()); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, weight); if (!fEMEventCut.IsSelected(collision)) { continue; } - 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 + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, weight); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0, weight); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0, weight); // accepted int zbin = lower_bound(zvtx_bin_edges.begin(), zvtx_bin_edges.end(), collision.posZ()) - zvtx_bin_edges.begin() - 1; if (zbin < 0) { @@ -651,10 +661,10 @@ struct Pi0EtaToGammaGamma { } } - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), weight); if constexpr (pairtype == PairType::kEMCEMC) { - RotationBackground(v12, v1, v2, photons2_per_collision, g1.globalIndex(), g2.globalIndex(), collision.weight()); + RotationBackground(v12, v1, v2, photons2_per_collision, g1.globalIndex(), g2.globalIndex(), weight); } std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); @@ -708,7 +718,7 @@ struct Pi0EtaToGammaGamma { continue; } - fRegistry.fill(HIST("Pair/same/hs"), veeg.M(), veeg.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/same/hs"), veeg.M(), veeg.Pt(), weight); std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); std::tuple tuple_tmp_id2 = std::make_tuple(ndf, collision.globalIndex(), pos2.trackId(), ele2.trackId()); @@ -738,7 +748,7 @@ struct Pi0EtaToGammaGamma { continue; } - fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/same/hs"), v12.M(), v12.Pt(), weight); std::pair pair_tmp_id1 = std::make_pair(ndf, g1.globalIndex()); std::pair pair_tmp_id2 = std::make_pair(ndf, g2.globalIndex()); @@ -795,7 +805,7 @@ struct Pi0EtaToGammaGamma { continue; } - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), weight); } } } // end of loop over mixed event pool @@ -830,7 +840,7 @@ struct Pi0EtaToGammaGamma { if (std::fabs(v12.Rapidity()) > maxY) { continue; } - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), weight); } } } // end of loop over mixed event pool @@ -863,7 +873,7 @@ struct Pi0EtaToGammaGamma { if (std::fabs(v12.Rapidity()) > maxY) { continue; } - fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/mix/hs"), v12.M(), v12.Pt(), weight); } } } // end of loop over mixed event pool @@ -921,9 +931,46 @@ struct Pi0EtaToGammaGamma { // } ndf++; } - PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysis, "process pair analysis", false); + PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysis, "process pair analysis", true); + + using FilteredMyCollisionsWithJJMC = soa::Filtered; + void processAnalysisJJMC(FilteredMyCollisionsWithJJMC const& collisions, 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...)); + runPairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut); + } else if constexpr (pairtype == PairType::kPCMDalitzEE) { + auto v0photons = std::get<0>(std::tie(args...)); + auto v0legs = std::get<1>(std::tie(args...)); + auto emprimaryelectrons = std::get<2>(std::tie(args...)); + // LOGF(info, "electrons.size() = %d, positrons.size() = %d", electrons.size(), positrons.size()); + runPairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut); + } else if constexpr (pairtype == PairType::kEMCEMC) { + auto emcclusters = std::get<0>(std::tie(args...)); + runPairing(collisions, emcclusters, emcclusters, nullptr, nullptr, perCollision_emc, perCollision_emc, fEMCCut, fEMCCut); + } else if constexpr (pairtype == PairType::kPHOSPHOS) { + auto phosclusters = std::get<0>(std::tie(args...)); + runPairing(collisions, phosclusters, phosclusters, nullptr, nullptr, perCollision_phos, perCollision_phos, fPHOSCut, fPHOSCut); + } + // else if constexpr (pairtype == 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) { + // auto v0photons = std::get<0>(std::tie(args...)); + // auto v0legs = std::get<1>(std::tie(args...)); + // auto phosclusters = std::get<2>(std::tie(args...)); + // runPairing(collisions, v0photons, phosclusters, v0legs, nullptr, perCollision_pcm, perCollision_phos, fV0PhotonCut, fPHOSCut, nullptr, nullptr); + // } + ndf++; + } + PROCESS_SWITCH(Pi0EtaToGammaGamma, processAnalysisJJMC, "process pair analysis", false); void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(Pi0EtaToGammaGamma, processDummy, "Dummy function", true); + 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 87e2f7b04d4..b329e9a52a3 100644 --- a/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h +++ b/PWGEM/PhotonMeson/Core/Pi0EtaToGammaGammaMC.h @@ -17,35 +17,36 @@ #ifndef PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMAMC_H_ #define PWGEM_PHOTONMESON_CORE_PI0ETATOGAMMAGAMMAMC_H_ -#include -#include -#include +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#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/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Utils/NMHistograms.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "TF1.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/Utils/NMHistograms.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/Dilepton/Utils/MCUtilities.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TString.h" + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -56,9 +57,12 @@ using namespace o2::aod::pwgem::photonmeson::photonpair; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; using namespace o2::aod::pwgem::dilepton::utils::mcutil; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; +using MyCollisionsWithJJMC = soa::Join; +using MyCollisionWithJJMC = MyCollisionsWithJJMC::iterator; + using MyMCCollisions = soa::Join; using MyMCCollision = MyMCCollisions::iterator; @@ -127,17 +131,16 @@ struct Pi0EtaToGammaGammaMC { 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_min_cospa{"cfg_min_cospa", 0.999, "min V0 CosPA"}; + Configurable cfg_max_pca{"cfg_max_pca", 1.5, "max distance btween 2 legs"}; Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_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", 10, "min ncluster tpc"}; + 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_chi2tpc{"cfg_max_chi2tpc", 4.0, "max chi2/NclsTPC"}; - Configurable cfg_max_chi2its{"cfg_max_chi2its", 5.0, "max chi2/NclsITS"}; + Configurable cfg_max_chi2its{"cfg_max_chi2its", 36.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"}; @@ -163,11 +166,13 @@ struct Pi0EtaToGammaGammaMC { 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_chi2its{"cfg_max_chi2its", 36.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_apply_cuts_from_prefilter_derived{"cfg_apply_cuts_from_prefilter_derived", false, "flag to apply prefilter to electron"}; + 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"}; 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"}; @@ -327,7 +332,6 @@ struct Pi0EtaToGammaGammaMC { fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); @@ -359,6 +363,7 @@ struct Pi0EtaToGammaGammaMC { 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(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); @@ -404,8 +409,8 @@ struct Pi0EtaToGammaGammaMC { Preslice perCollision_phos = aod::phoscluster::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); + 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; + 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; template void runTruePairing(TCollisions const& collisions, @@ -422,7 +427,12 @@ struct Pi0EtaToGammaGammaMC { continue; } - if (eventcuts.onlyKeepWeightedEvents && std::fabs(collision.weight() - 1.) < 1E-10) { + float weight = 1.f; + if constexpr (std::is_same_v, FilteredMyCollisionsWithJJMC>) { + weight = collision.weight(); + } + + if (eventcuts.onlyKeepWeightedEvents && std::fabs(weight - 1.0) < 1e-10) { continue; } @@ -431,13 +441,13 @@ struct Pi0EtaToGammaGammaMC { continue; } - o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, collision.weight()); + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<0>(&fRegistry, collision, weight); if (!fEMEventCut.IsSelected(collision)) { continue; } - 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 + o2::aod::pwgem::photonmeson::utils::eventhistogram::fillEventInfo<1>(&fRegistry, collision, weight); + fRegistry.fill(HIST("Event/before/hCollisionCounter"), 12.0, weight); // accepted + fRegistry.fill(HIST("Event/after/hCollisionCounter"), 12.0, weight); // accepted int photonid1 = -1, photonid2 = -1, pi0id = -1, etaid = -1; if constexpr (pairtype == PairType::kPCMPCM || pairtype == PairType::kPHOSPHOS || pairtype == PairType::kEMCEMC) { // same kinds pairing @@ -508,9 +518,9 @@ struct Pi0EtaToGammaGammaMC { if (g1mc.globalIndex() == g2mc.globalIndex()) { if (getMotherPDGCode(g1mc, mcparticles) == 111) - fRegistry.fill(HIST("Pair/Pi0/hs_FromSameGamma"), v12.M(), v12.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/Pi0/hs_FromSameGamma"), v12.M(), v12.Pt(), weight); else if (getMotherPDGCode(g1mc, mcparticles) == 221) - fRegistry.fill(HIST("Pair/Eta/hs_FromSameGamma"), v12.M(), v12.Pt(), collision.weight()); + fRegistry.fill(HIST("Pair/Eta/hs_FromSameGamma"), v12.M(), v12.Pt(), weight); continue; } @@ -519,13 +529,13 @@ 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, collision.weight()); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); } 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, collision.weight()); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); } } // end of pairing loop } else if constexpr (pairtype == PairType::kPCMDalitzEE) { @@ -585,13 +595,13 @@ struct Pi0EtaToGammaGammaMC { if (cfgRequireTrueAssociation && (pi0mc.emmceventId() != collision.emmceventId())) { continue; } - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); } else if (etaid > 0) { auto etamc = mcparticles.iteratorAt(etaid); if (cfgRequireTrueAssociation && (etamc.emmceventId() != collision.emmceventId())) { continue; } - o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); + o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, veeg, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); } } // end of dielectron loop } // end of pcm loop @@ -611,10 +621,10 @@ struct Pi0EtaToGammaGammaMC { } // if (pi0id > 0) { // auto pi0mc = mcparticles.iteratorAt(pi0id); - // o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); + // o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, pi0mc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); // } else if (etaid > 0) { // auto etamc = mcparticles.iteratorAt(etaid); - // o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, collision.weight()); + // o2::aod::pwgem::photonmeson::utils::nmhistogram::fillTruePairInfo(&fRegistry, v12, etamc, mcparticles, mccollisions, f1fd_k0s_to_pi0, weight); // } } // end of pairing loop } // end of pairing in same event @@ -664,7 +674,12 @@ struct Pi0EtaToGammaGammaMC { continue; // I don't know why this is necessary in simulation. } - if (eventcuts.onlyKeepWeightedEvents && std::fabs(collision.weight() - 1.) < 1E-10) { + float weight = 1.f; + if constexpr (std::is_same_v, FilteredMyCollisionsWithJJMC>) { + weight = collision.weight(); + } + + if (eventcuts.onlyKeepWeightedEvents && std::fabs(weight - 1.0) < 1e-10) { continue; } @@ -680,8 +695,8 @@ struct Pi0EtaToGammaGammaMC { auto mccollision = collision.template emmcevent_as(); auto binned_data_pi0_gen = mccollision.generatedPi0(); auto binned_data_eta_gen = mccollision.generatedEta(); - fillBinnedData<0>(binned_data_pi0_gen, collision.weight()); - fillBinnedData<1>(binned_data_eta_gen, collision.weight()); + fillBinnedData<0>(binned_data_pi0_gen, weight); + fillBinnedData<1>(binned_data_eta_gen, weight); } // end of collision loop } @@ -730,9 +745,49 @@ struct Pi0EtaToGammaGammaMC { // runPairing(collisions, v0photons, phosclusters, v0legs, nullptr, perCollision_pcm, perCollision_phos, fV0PhotonCut, fPHOSCut, nullptr, nullptr); // } } - PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysis, "process pair analysis", false); + PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysis, "process pair analysis", true); + + using FilteredMyCollisionsWithJJMC = soa::Filtered; + void processAnalysisJJMC(FilteredMyCollisionsWithJJMC const& collisions, MyMCCollisions const& mccollisions, aod::EMMCParticles const& mcparticles, Types const&... args) + { + if constexpr (pairtype == PairType::kPCMPCM) { + auto v0photons = std::get<0>(std::tie(args...)); + auto v0legs = std::get<1>(std::tie(args...)); + runTruePairing(collisions, v0photons, v0photons, v0legs, v0legs, perCollision_pcm, perCollision_pcm, fV0PhotonCut, fV0PhotonCut, mccollisions, mcparticles); + runGenInfo(collisions, mccollisions, mcparticles); + } else if constexpr (pairtype == PairType::kPCMDalitzEE) { + auto v0photons = std::get<0>(std::tie(args...)); + auto v0legs = std::get<1>(std::tie(args...)); + auto emprimaryelectrons = std::get<2>(std::tie(args...)); + // LOGF(info, "electrons.size() = %d, positrons.size() = %d", electrons.size(), positrons.size()); + runTruePairing(collisions, v0photons, emprimaryelectrons, v0legs, emprimaryelectrons, perCollision_pcm, perCollision_electron, fV0PhotonCut, fDileptonCut, mccollisions, mcparticles); + runGenInfo(collisions, mccollisions, mcparticles); + } else if constexpr (pairtype == PairType::kEMCEMC) { + auto emcclusters = std::get<0>(std::tie(args...)); + runTruePairing(collisions, emcclusters, emcclusters, nullptr, nullptr, perCollision_emc, perCollision_emc, fEMCCut, fEMCCut, mccollisions, mcparticles); + runGenInfo(collisions, mccollisions, mcparticles); + } + + // else if constexpr (pairtype == PairType::kPHOSPHOS) { + // auto phosclusters = std::get<0>(std::tie(args...)); + // runPairing(collisions, phosclusters, phosclusters, nullptr, nullptr, perCollision_phos, perCollision_phos, fPHOSCut, fPHOSCut, nullptr, nullptr); + // } + // else if constexpr (pairtype == 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) { + // auto v0photons = std::get<0>(std::tie(args...)); + // auto v0legs = std::get<1>(std::tie(args...)); + // auto phosclusters = std::get<2>(std::tie(args...)); + // runPairing(collisions, v0photons, phosclusters, v0legs, nullptr, perCollision_pcm, perCollision_phos, fV0PhotonCut, fPHOSCut, nullptr, nullptr); + // } + } + PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processAnalysisJJMC, "process pair analysis", false); void processDummy(MyCollisions const&) {} - PROCESS_SWITCH(Pi0EtaToGammaGammaMC, processDummy, "Dummy function", true); + 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 d74af2ceb0c..5f37d60d277 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0.h @@ -138,7 +138,6 @@ struct TaggingPi0 { 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_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 10, "min ncluster tpc"}; @@ -369,7 +368,6 @@ struct TaggingPi0 { fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); diff --git a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h index 56c6274a141..ac3b51be4f2 100644 --- a/PWGEM/PhotonMeson/Core/TaggingPi0MC.h +++ b/PWGEM/PhotonMeson/Core/TaggingPi0MC.h @@ -130,7 +130,6 @@ struct TaggingPi0MC { 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_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 10, "min ncluster tpc"}; @@ -339,7 +338,6 @@ struct TaggingPi0MC { fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx index 07d805fa291..4c149b7fd20 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.cxx @@ -193,12 +193,6 @@ void V0PhotonCut::SetMeanClusterSizeITSob(float min, float max) LOG(info) << "V0 Photon Cut, set mean cluster size ITS range: " << mMinMeanClusterSizeITS << " - " << mMaxMeanClusterSizeITS; } -void V0PhotonCut::SetIsWithinBeamPipe(bool flag) -{ - mIsWithinBP = flag; - LOG(info) << "V0 Photon Cut, propagated to within beam pipe: " << mIsWithinBP; -} - void V0PhotonCut::SetRequireITSTPC(bool flag) { mRequireITSTPC = flag; diff --git a/PWGEM/PhotonMeson/Core/V0PhotonCut.h b/PWGEM/PhotonMeson/Core/V0PhotonCut.h index d6064ab8786..dcd9cd2c5ce 100644 --- a/PWGEM/PhotonMeson/Core/V0PhotonCut.h +++ b/PWGEM/PhotonMeson/Core/V0PhotonCut.h @@ -16,16 +16,18 @@ #ifndef PWGEM_PHOTONMESON_CORE_V0PHOTONCUT_H_ #define PWGEM_PHOTONMESON_CORE_V0PHOTONCUT_H_ -#include -#include -#include -#include -#include #include "Rtypes.h" -#include "TNamed.h" -#include "TMath.h" #include "PWGEM/PhotonMeson/Utils/TrackSelection.h" + +#include "TMath.h" +#include "TNamed.h" + +#include +#include +#include +#include +#include using namespace o2::pwgem::photonmeson; class V0PhotonCut : public TNamed @@ -64,7 +66,6 @@ class V0PhotonCut : public TNamed kITSNCls, kITSChi2NDF, kITSClusterSize, - kIsWithinBeamPipe, kRequireITSTPC, kRequireITSonly, kRequireTPConly, @@ -140,9 +141,6 @@ class V0PhotonCut : public TNamed if (!IsSelectedTrack(track, V0PhotonCuts::kDCAz)) { return false; } - if (mIsWithinBP && !IsSelectedTrack(track, V0PhotonCuts::kIsWithinBeamPipe)) { - return false; - } if (!track.hasITS() && !track.hasTPC()) { // track has to be ITSonly or TPConly or ITS-TPC return false; } @@ -269,11 +267,6 @@ class V0PhotonCut : public TNamed if (v0.v0radius() < mMinRxy || mMaxRxy < v0.v0radius()) { return false; } - if (mRejectITSib) { - if (v0.v0radius() < 4.f || v0.pca() < -0.05 * v0.v0radius() + 0.3) { - return false; - } - } return true; } @@ -343,10 +336,10 @@ class V0PhotonCut : public TNamed { switch (cut) { case V0PhotonCuts::kTrackPtRange: - return track.pt() >= mMinTrackPt && track.pt() <= mMaxTrackPt; + return track.pt() > mMinTrackPt && track.pt() < mMaxTrackPt; case V0PhotonCuts::kTrackEtaRange: - return track.eta() >= mMinTrackEta && track.eta() <= mMaxTrackEta; + return track.eta() > mMinTrackEta && track.eta() < mMaxTrackEta; case V0PhotonCuts::kTPCNCls: return track.tpcNClsFound() >= mMinNClustersTPC; @@ -358,22 +351,22 @@ class V0PhotonCut : public TNamed return track.tpcCrossedRowsOverFindableCls() >= mMinNCrossedRowsOverFindableClustersTPC; case V0PhotonCuts::kTPCFracSharedClusters: - return track.tpcFractionSharedCls() <= mMaxFracSharedClustersTPC; + return track.tpcFractionSharedCls() < mMaxFracSharedClustersTPC; case V0PhotonCuts::kTPCChi2NDF: return mMinChi2PerClusterTPC < track.tpcChi2NCl() && track.tpcChi2NCl() < mMaxChi2PerClusterTPC; case V0PhotonCuts::kTPCNsigmaEl: - return track.tpcNSigmaEl() >= mMinTPCNsigmaEl && track.tpcNSigmaEl() <= mMaxTPCNsigmaEl; + return track.tpcNSigmaEl() > mMinTPCNsigmaEl && track.tpcNSigmaEl() < mMaxTPCNsigmaEl; case V0PhotonCuts::kTPCNsigmaPi: - return track.tpcNSigmaPi() >= mMinTPCNsigmaPi && track.tpcNSigmaPi() <= mMaxTPCNsigmaPi; + return track.tpcNSigmaPi() > mMinTPCNsigmaPi && track.tpcNSigmaPi() < mMaxTPCNsigmaPi; case V0PhotonCuts::kDCAxy: - return std::fabs(track.dcaXY()) <= ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); + return std::fabs(track.dcaXY()) < ((mMaxDcaXYPtDep) ? mMaxDcaXYPtDep(track.pt()) : mMaxDcaXY); case V0PhotonCuts::kDCAz: - return std::fabs(track.dcaZ()) <= mMaxDcaZ; + return std::fabs(track.dcaZ()) < mMaxDcaZ; case V0PhotonCuts::kITSNCls: return mMinNClustersITS <= track.itsNCls() && track.itsNCls() <= mMaxNClustersITS; @@ -388,28 +381,6 @@ class V0PhotonCut : public TNamed return mMinMeanClusterSizeITS < track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl())) && track.meanClusterSizeITSob() * std::cos(std::atan(track.tgl())) < mMaxMeanClusterSizeITS; } - case V0PhotonCuts::kIsWithinBeamPipe: { - if (!isTPConlyTrack(track)) { // TPC-TRD, TPC-TOF, TPC-TRD-TOF are constrained. - return true; - } - - // if (abs(track.y()) > abs(track.x() * TMath::Tan(10.f * TMath::DegToRad())) + 15.f) { - // return false; - // } - if (track.x() < 0.1 && std::fabs(track.y()) > 15.f) { - return false; - } - if (track.x() > 82.9 && std::fabs(track.y()) > std::fabs(track.x() * std::tan(10.f * TMath::DegToRad())) + 5.f) { - return false; - } - if (track.x() > 82.9 && std::fabs(track.y()) < 15.0 && abs(abs(track.z()) - 44.5) < 2.5) { - return false; - } - return true; - // const float slope = TMath::Tan(2 * TMath::ATan(TMath::Exp(-0.5))); - // return !(track.x() > 82.9 && abs(track.y()) < 15.f && abs(abs(track.z()) - track.x() / slope) < 3.f && 15.f < abs(track.dcaXY())); - //// return !(track.x() > 82.9 && abs(track.y()) < 40.f && abs(abs(track.z()) - 47.f) < 3.f && 15.f < abs(track.dcaXY())); - } case V0PhotonCuts::kRequireITSTPC: return isITSTPCTrack(track); @@ -515,7 +486,6 @@ class V0PhotonCut : public TNamed float mMaxDcaXY{1e10f}; // max dca in xy plane float mMaxDcaZ{1e10f}; // max dca in z direction std::function mMaxDcaXYPtDep{}; // max dca in xy plane as function of pT - bool mIsWithinBP{false}; bool mRequireITSTPC{false}; bool mRequireITSonly{false}; bool mRequireTPConly{false}; diff --git a/PWGEM/PhotonMeson/DataModel/bcWiseTables.h b/PWGEM/PhotonMeson/DataModel/bcWiseTables.h index f44769f1d94..a306d5645ce 100644 --- a/PWGEM/PhotonMeson/DataModel/bcWiseTables.h +++ b/PWGEM/PhotonMeson/DataModel/bcWiseTables.h @@ -19,10 +19,10 @@ #ifndef PWGEM_PHOTONMESON_DATAMODEL_BCWISETABLES_H_ #define PWGEM_PHOTONMESON_DATAMODEL_BCWISETABLES_H_ -#include - #include "Framework/AnalysisDataModel.h" +#include + namespace o2::aod { @@ -41,23 +41,25 @@ enum Observable { kFT0Amp, kpT, kMu, + kTimeSinceSOF, nObservables }; // Values in tables are stored in downscaled format to save disk space const float downscalingFactors[nObservables]{ - 1E0, // Cluster definition - 1E3, // Cluster energy - 1E4, // Cluster eta - 1E4, // Cluster phi - 1E0, // Number of cells - 1E4, // M02 - 1E2, // Cluster time - 2E0, // FT0M centrality - 1E3, // Z-vertex position - 1E-1, // FT0M amplitude - 1E3, // MC pi0 pt - 1E5}; // Mu + 1E0, // Cluster definition + 1E3, // Cluster energy + 1E4, // Cluster eta + 1E4, // Cluster phi + 1E0, // Number of cells + 1E4, // M02 + 1E2, // Cluster time + 2E0, // FT0M centrality + 1E3, // Z-vertex position + 1E-1, // FT0M amplitude + 1E3, // MC pi0 pt + 1E5, // Mu + 5E-1}; // Time since start of fill (since ADJUST decleration) } // namespace emdownscaling namespace bcwisebc @@ -66,18 +68,19 @@ DECLARE_SOA_COLUMN(HasFT0, hasFT0, bool); //! has_ DECLARE_SOA_COLUMN(HasTVX, hasTVX, bool); //! has the TVX trigger flag DECLARE_SOA_COLUMN(HaskTVXinEMC, haskTVXinEMC, bool); //! kTVXinEMC DECLARE_SOA_COLUMN(HasEMCCell, hasEMCCell, bool); //! at least one EMCal cell in the BC -DECLARE_SOA_COLUMN(HasNoTFROFBorder, hasNoTFROFBorder, bool); //! not in the TF border or ITS ROF border region DECLARE_SOA_COLUMN(StoredCentrality, storedCentrality, uint8_t); //! FT0M centrality (0-100) (x2) DECLARE_SOA_COLUMN(StoredFT0MAmplitude, storedFT0MAmplitude, uint16_t); //! ft0a+c amplitude DECLARE_SOA_COLUMN(StoredMu, storedMu, uint16_t); //! probability of TVX collision per BC (x1000) +DECLARE_SOA_COLUMN(StoredTimeSinceSOF, storedTimeSinceSOF, uint16_t); //! time since decreation of ADJUST in seconds (x2) DECLARE_SOA_DYNAMIC_COLUMN(Centrality, centrality, [](uint8_t storedcentrality) -> float { return std::nextafter(storedcentrality / emdownscaling::downscalingFactors[emdownscaling::kFT0MCent], std::numeric_limits::infinity()); }); //! Centrality (0-100) DECLARE_SOA_DYNAMIC_COLUMN(FT0MAmplitude, ft0Amplitude, [](uint16_t storedFT0MAmplitude) -> float { return std::nextafter(storedFT0MAmplitude / emdownscaling::downscalingFactors[emdownscaling::kFT0Amp], std::numeric_limits::infinity()); }); //! FT0M amplitude DECLARE_SOA_DYNAMIC_COLUMN(Mu, mu, [](uint16_t storedMu) -> float { return std::nextafter(storedMu / emdownscaling::downscalingFactors[emdownscaling::kMu], std::numeric_limits::infinity()); }); //! probability of TVX collision per BC +DECLARE_SOA_DYNAMIC_COLUMN(TimeSinceSOF, timeSinceSOF, [](uint16_t storedTimeSinceSOF) -> float { return std::nextafter(storedTimeSinceSOF / emdownscaling::downscalingFactors[emdownscaling::kTimeSinceSOF], std::numeric_limits::infinity()); }); //! probability of TVX collision per BC } // namespace bcwisebc DECLARE_SOA_TABLE(BCWiseBCs, "AOD", "BCWISEBC", //! table of bc wise centrality estimation and event selection input - o2::soa::Index<>, bcwisebc::HasFT0, bcwisebc::HasTVX, bcwisebc::HaskTVXinEMC, bcwisebc::HasEMCCell, bcwisebc::HasNoTFROFBorder, bcwisebc::StoredCentrality, - bcwisebc::StoredFT0MAmplitude, bcwisebc::StoredMu, bcwisebc::Centrality, bcwisebc::FT0MAmplitude, bcwisebc::Mu); + o2::soa::Index<>, bcwisebc::HasFT0, bcwisebc::HasTVX, bcwisebc::HaskTVXinEMC, bcwisebc::HasEMCCell, bcwisebc::StoredCentrality, + bcwisebc::StoredFT0MAmplitude, bcwisebc::StoredMu, bcwisebc::StoredTimeSinceSOF, bcwisebc::Centrality, bcwisebc::FT0MAmplitude, bcwisebc::Mu, bcwisebc::TimeSinceSOF); DECLARE_SOA_INDEX_COLUMN(BCWiseBC, bcWiseBC); //! bunch crossing ID used as index @@ -121,7 +124,7 @@ DECLARE_SOA_TABLE(BCWiseClusters, "AOD", "BCWISECLUSTER", //! table of skimmed E bcwisecluster::Definition, bcwisecluster::E, bcwisecluster::Eta, bcwisecluster::Phi, bcwisecluster::NCells, bcwisecluster::M02, bcwisecluster::Time, bcwisecluster::IsExotic, bcwisecluster::Pt); -namespace bcwisemcpi0s +namespace bcwisemcmesons { DECLARE_SOA_COLUMN(StoredPt, storedPt, uint16_t); //! Transverse momentum of generated pi0 (1 MeV -> Maximum pi0 pT of ~65 GeV) DECLARE_SOA_COLUMN(IsAccepted, isAccepted, bool); //! Both decay photons are within the EMCal acceptance @@ -129,22 +132,26 @@ DECLARE_SOA_COLUMN(IsPrimary, isPrimary, bool); //! mcParticle.isPhysicalPrima DECLARE_SOA_COLUMN(IsFromWD, isFromWD, bool); //! Pi0 from a weak decay according to pwgem::photonmeson::utils::mcutil::IsFromWD DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](uint16_t storedpt) -> float { return std::nextafter(storedpt / emdownscaling::downscalingFactors[emdownscaling::kpT], std::numeric_limits::infinity()); }); //! pT of pi0 (GeV) -} // namespace bcwisemcpi0s +} // namespace bcwisemcmesons DECLARE_SOA_TABLE(BCWiseMCPi0s, "AOD", "BCWISEMCPI0", //! table of pi0s on MC level - o2::soa::Index<>, BCWiseBCId, bcwisemcpi0s::StoredPt, bcwisemcpi0s::IsAccepted, bcwisemcpi0s::IsPrimary, bcwisemcpi0s::IsFromWD, - bcwisemcpi0s::Pt); + o2::soa::Index<>, BCWiseBCId, bcwisemcmesons::StoredPt, bcwisemcmesons::IsAccepted, bcwisemcmesons::IsPrimary, bcwisemcmesons::IsFromWD, + bcwisemcmesons::Pt); +DECLARE_SOA_TABLE(BCWiseMCEtas, "AOD", "BCWISEMCETA", //! table of eta mesons on MC level + o2::soa::Index<>, BCWiseBCId, bcwisemcmesons::StoredPt, bcwisemcmesons::IsAccepted, bcwisemcmesons::IsPrimary, bcwisemcmesons::IsFromWD, + bcwisemcmesons::Pt); namespace bcwisemccluster { -DECLARE_SOA_COLUMN(Pi0ID, pi0ID, int32_t); //! Index of the mother pi0 (-1 if not from pi0) +DECLARE_SOA_COLUMN(MesonID, mesonID, int32_t); //! Index of the mother mesom (-1 if not from a pi0 or eta) +DECLARE_SOA_COLUMN(IsEta, isEta, bool); //! Boolean flag to indicate if the cluster is from an eta meson, otherwise it is from a pi0 DECLARE_SOA_COLUMN(StoredTrueE, storedTrueE, uint16_t); //! energy of cluster inducing particle (1 MeV -> Maximum cluster energy of ~65 GeV) DECLARE_SOA_DYNAMIC_COLUMN(TrueE, trueE, [](uint16_t storedTrueE) -> float { return std::nextafter(storedTrueE / emdownscaling::downscalingFactors[emdownscaling::kEnergy], std::numeric_limits::infinity()); }); //! energy of cluster inducing particle (GeV) } // namespace bcwisemccluster DECLARE_SOA_TABLE(BCWiseMCClusters, "AOD", "BCWISEMCCLS", //! table of MC information for clusters -> To be joined with the cluster table - o2::soa::Index<>, BCWiseBCId, bcwisemccluster::Pi0ID, bcwisemccluster::StoredTrueE, + o2::soa::Index<>, BCWiseBCId, bcwisemccluster::MesonID, bcwisemccluster::IsEta, bcwisemccluster::StoredTrueE, bcwisemccluster::TrueE); } // namespace o2::aod diff --git a/PWGEM/PhotonMeson/DataModel/gammaTables.h b/PWGEM/PhotonMeson/DataModel/gammaTables.h index 0abbc3bfe76..a6b7017f550 100644 --- a/PWGEM/PhotonMeson/DataModel/gammaTables.h +++ b/PWGEM/PhotonMeson/DataModel/gammaTables.h @@ -9,15 +9,21 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include +#include "PWGEM/Dilepton/DataModel/dileptonTables.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/CaloClusters.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGEM/Dilepton/DataModel/dileptonTables.h" +#include +#include -#include "PWGJE/DataModel/EMCALClusters.h" +#include +#include +#include +#include #ifndef PWGEM_PHOTONMESON_DATAMODEL_GAMMATABLES_H_ #define PWGEM_PHOTONMESON_DATAMODEL_GAMMATABLES_H_ @@ -117,10 +123,12 @@ DECLARE_SOA_COLUMN(IsMoved, isMoved, bool); //! moved by drift manager. r DECLARE_SOA_COLUMN(Px, px, float); //! Px at SV DECLARE_SOA_COLUMN(Py, py, float); //! Py at SV DECLARE_SOA_COLUMN(Pz, pz, float); //! Pz at SV + DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, [](float px, float py, float pz) -> float { return RecoDecay::eta(std::array{px, py, pz}); }); DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) -> float { return RecoDecay::phi(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Tgl, tgl, [](float px, float py, float pz) -> float { return std::tan(M_PI_2 - 2 * std::atan(std::exp(-RecoDecay::eta(std::array{px, py, pz})))); }); DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITS, meanClusterSizeITS, [](uint32_t itsClusterSizes) -> float { int total_cluster_size = 0, nl = 0; for (unsigned int layer = 0; layer < 7; layer++) { @@ -167,7 +175,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(MeanClusterSizeITSob, meanClusterSizeITSob, [](uint32 } }); } // namespace v0leg -DECLARE_SOA_TABLE(V0Legs, "AOD", "V0LEG", //! +DECLARE_SOA_TABLE(V0Legs_000, "AOD", "V0LEG", //! o2::soa::Index<>, v0leg::CollisionId, v0leg::TrackId, v0leg::Sign, v0leg::Px, v0leg::Py, v0leg::Pz, track::DcaXY, track::DcaZ, @@ -188,15 +196,52 @@ DECLARE_SOA_TABLE(V0Legs, "AOD", "V0LEG", //! track::TPCFoundOverFindableCls, track::TPCFractionSharedCls, track::v001::ITSClusterMap, track::v001::ITSNCls, track::v001::ITSNClsInnerBarrel, - track::HasITS, track::HasTPC, - track::HasTRD, track::HasTOF, + track::HasITS, track::HasTPC, track::HasTRD, track::HasTOF, v0leg::MeanClusterSizeITS, v0leg::MeanClusterSizeITSib, v0leg::MeanClusterSizeITSob); +DECLARE_SOA_TABLE_VERSIONED(V0Legs_001, "AOD", "V0LEG", 1, //! + o2::soa::Index<>, v0leg::CollisionId, v0leg::TrackId, v0leg::Sign, + v0leg::Px, v0leg::Py, v0leg::Pz, + track::DcaXY, track::DcaZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, + track::TPCChi2NCl, track::TPCInnerParam, + track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, + track::ITSClusterSizes, track::ITSChi2NCl, track::DetectorMap, + + // dynamic column + v0leg::P, + v0leg::Pt, + v0leg::Eta, + v0leg::Phi, + v0leg::Tgl, + + track::TPCNClsFound, + 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, + v0leg::MeanClusterSizeITS, + v0leg::MeanClusterSizeITSib, + v0leg::MeanClusterSizeITSob); + +using V0Legs = V0Legs_001; // iterators using V0Leg = V0Legs::iterator; +DECLARE_SOA_TABLE_VERSIONED(V0LegsXYZ_000, "AOD", "V0LEGXYZ", 0, track::X, track::Y, track::Z); +using V0LegsXYZ = V0LegsXYZ_000; +// iterators +using V0LegXYZ = V0LegsXYZ::iterator; + +DECLARE_SOA_TABLE_VERSIONED(V0LegsDeDxMC_000, "AOD", "V0LEGDEDXMC", 0, mcpidtpc::DeDxTunedMc, o2::soa::Marker<2>); +using V0LegsDeDxMC = V0LegsDeDxMC_000; +// iterators +using V0LegDeDxMC = V0LegsDeDxMC::iterator; + namespace emevent { DECLARE_SOA_COLUMN(NgPCM, ngpcm, int); @@ -223,23 +268,25 @@ DECLARE_SOA_COLUMN(Vz, vz, float); //! seco DECLARE_SOA_COLUMN(Px, px, float); //! px for photon kf DECLARE_SOA_COLUMN(Py, py, float); //! py for photon kf DECLARE_SOA_COLUMN(Pz, pz, float); //! pz for photon kf -DECLARE_SOA_COLUMN(MGamma, mGamma, float); //! invariant mass of dielectron at SV -DECLARE_SOA_COLUMN(DCAxyToPV, dcaXYtopv, float); //! DCAxy of V0 to PV -DECLARE_SOA_COLUMN(DCAzToPV, dcaZtopv, float); //! DCAz of V0 to PV -DECLARE_SOA_COLUMN(CosPA, cospa, float); //! -DECLARE_SOA_COLUMN(CosPAXY, cospaXY, float); //! -DECLARE_SOA_COLUMN(CosPARZ, cospaRZ, float); //! -DECLARE_SOA_COLUMN(PCA, pca, float); //! -DECLARE_SOA_COLUMN(Alpha, alpha, float); //! -DECLARE_SOA_COLUMN(QtArm, qtarm, float); //! -DECLARE_SOA_COLUMN(ChiSquareNDF, chiSquareNDF, float); //! Chi2 / NDF of the reconstructed V0 -DECLARE_SOA_COLUMN(SigmaPx2, sigmaPx2, float); //! error^2 of px in covariant matrix -DECLARE_SOA_COLUMN(SigmaPy2, sigmaPy2, float); //! error^2 of py in covariant matrix -DECLARE_SOA_COLUMN(SigmaPz2, sigmaPz2, float); //! error^2 of pz in covariant matrix -DECLARE_SOA_COLUMN(SigmaPxPy, sigmaPxPy, float); //! error of px x py in covariant matrix -DECLARE_SOA_COLUMN(SigmaPyPz, sigmaPyPz, float); //! error of py x pz in covariant matrix -DECLARE_SOA_COLUMN(SigmaPzPx, sigmaPzPx, float); //! error of pz x px in covariant matrix -DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! + +DECLARE_SOA_COLUMN(MGamma, mGamma, float); //! invariant mass of dielectron at SV +DECLARE_SOA_COLUMN(DCAxyToPV, dcaXYtopv, float); //! DCAxy of V0 to PV +DECLARE_SOA_COLUMN(DCAzToPV, dcaZtopv, float); //! DCAz of V0 to PV +DECLARE_SOA_COLUMN(CosPA, cospa, float); //! +DECLARE_SOA_COLUMN(CosPAXY, cospaXY, float); //! +DECLARE_SOA_COLUMN(CosPARZ, cospaRZ, float); //! +DECLARE_SOA_COLUMN(PCA, pca, float); //! +DECLARE_SOA_COLUMN(Alpha, alpha, float); //! +DECLARE_SOA_COLUMN(QtArm, qtarm, float); //! +DECLARE_SOA_COLUMN(ChiSquareNDF, chiSquareNDF, float); //! Chi2 / NDF of the reconstructed V0 + +DECLARE_SOA_COLUMN(SigmaPx2, sigmaPx2, float); //! error^2 of px in covariant matrix +DECLARE_SOA_COLUMN(SigmaPy2, sigmaPy2, float); //! error^2 of py in covariant matrix +DECLARE_SOA_COLUMN(SigmaPz2, sigmaPz2, float); //! error^2 of pz in covariant matrix +DECLARE_SOA_COLUMN(SigmaPxPy, sigmaPxPy, float); //! error of px x py in covariant matrix +DECLARE_SOA_COLUMN(SigmaPyPz, sigmaPyPz, float); //! error of py x pz in covariant matrix +DECLARE_SOA_COLUMN(SigmaPzPx, sigmaPzPx, float); //! error of pz x px in covariant matrix +DECLARE_SOA_COLUMN(PrefilterBitDerived, pfbderived, uint16_t); //! DECLARE_SOA_DYNAMIC_COLUMN(E, e, [](float px, float py, float pz, float m = 0) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz, m); }); //! energy of v0 photn, mass to be given as argument when getter is called! DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); @@ -248,7 +295,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, [](float px, float py) -> float { return Re DECLARE_SOA_DYNAMIC_COLUMN(P, p, [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); DECLARE_SOA_DYNAMIC_COLUMN(V0Radius, v0radius, [](float vx, float vy) -> float { return RecoDecay::sqrtSumOfSquares(vx, vy); }); } // namespace v0photonkf -DECLARE_SOA_TABLE(V0PhotonsKF, "AOD", "V0PHOTONKF", //! +DECLARE_SOA_TABLE(V0PhotonsKF_000, "AOD", "V0PHOTONKF", //! o2::soa::Index<>, v0photonkf::CollisionId, v0photonkf::V0Id, v0photonkf::PosTrackId, v0photonkf::NegTrackId, v0photonkf::Vx, v0photonkf::Vy, v0photonkf::Vz, v0photonkf::Px, v0photonkf::Py, v0photonkf::Pz, @@ -265,6 +312,27 @@ DECLARE_SOA_TABLE(V0PhotonsKF, "AOD", "V0PHOTONKF", //! v0photonkf::Phi, v0photonkf::P, v0photonkf::V0Radius); + +DECLARE_SOA_TABLE_VERSIONED(V0PhotonsKF_001, "AOD", "V0PHOTONKF", 1, //! + o2::soa::Index<>, v0photonkf::CollisionId, v0photonkf::V0Id, v0photonkf::PosTrackId, v0photonkf::NegTrackId, + v0photonkf::Vx, v0photonkf::Vy, v0photonkf::Vz, + v0photonkf::Px, v0photonkf::Py, v0photonkf::Pz, + v0photonkf::MGamma, + v0photonkf::DCAxyToPV, v0photonkf::DCAzToPV, + v0photonkf::CosPA, v0photonkf::CosPAXY, v0photonkf::CosPARZ, v0photonkf::PCA, + v0photonkf::Alpha, v0photonkf::QtArm, + v0photonkf::ChiSquareNDF, + + // dynamic column + v0photonkf::E, + v0photonkf::Pt, + v0photonkf::Eta, + v0photonkf::Phi, + v0photonkf::P, + v0photonkf::V0Radius); + +using V0PhotonsKF = V0PhotonsKF_001; + // iterators using V0PhotonKF = V0PhotonsKF::iterator; @@ -281,7 +349,7 @@ DECLARE_SOA_TABLE(V0PhotonsKFPrefilterBitDerived, "AOD", "V0PHOTONKFPFBPI0", v0p // iterators using V0PhotonKFPrefilterBitDerived = V0PhotonsKFPrefilterBitDerived::iterator; -DECLARE_SOA_TABLE(EMPrimaryElectronsFromDalitz, "AOD", "EMPRIMARYELDA", //! +DECLARE_SOA_TABLE(EMPrimaryElectronsFromDalitz_000, "AOD", "EMPRIMARYELDA", //! o2::soa::Index<>, emprimaryelectron::CollisionId, emprimaryelectron::TrackId, emprimaryelectron::Sign, track::Pt, track::Eta, track::Phi, track::DcaXY, track::DcaZ, track::CYY, track::CZY, track::CZZ, @@ -308,6 +376,38 @@ DECLARE_SOA_TABLE(EMPrimaryElectronsFromDalitz, "AOD", "EMPRIMARYELDA", //! emprimaryelectron::MeanClusterSizeITS, emprimaryelectron::MeanClusterSizeITSib, emprimaryelectron::MeanClusterSizeITSob); + +DECLARE_SOA_TABLE_VERSIONED(EMPrimaryElectronsFromDalitz_001, "AOD", "EMPRIMARYELDA", 1, //! + o2::soa::Index<>, emprimaryelectron::CollisionId, + emprimaryelectron::TrackId, emprimaryelectron::Sign, + track::Pt, track::Eta, track::Phi, track::DcaXY, track::DcaZ, track::CYY, track::CZY, track::CZZ, + track::TPCNClsFindable, track::TPCNClsFindableMinusFound, track::TPCNClsFindableMinusCrossedRows, track::TPCNClsShared, + track::TPCChi2NCl, track::TPCInnerParam, + track::TPCSignal, pidtpc::TPCNSigmaEl, pidtpc::TPCNSigmaPi, + pidtofbeta::Beta, pidtof::TOFNSigmaEl, + track::ITSClusterSizes, track::ITSChi2NCl, track::TOFChi2, track::DetectorMap, + + // dynamic column + track::TPCNClsFound, + track::TPCNClsCrossedRows, + track::TPCCrossedRowsOverFindableCls, + track::TPCFoundOverFindableCls, + track::v001::ITSClusterMap, track::v001::ITSNCls, track::v001::ITSNClsInnerBarrel, + track::TPCFractionSharedCls, + track::HasITS, track::HasTPC, track::HasTRD, track::HasTOF, + + emprimaryelectron::Signed1Pt, + emprimaryelectron::P, + emprimaryelectron::Px, + emprimaryelectron::Py, + emprimaryelectron::Pz, + emprimaryelectron::Tgl, + emprimaryelectron::MeanClusterSizeITS, + emprimaryelectron::MeanClusterSizeITSib, + emprimaryelectron::MeanClusterSizeITSob); + +using EMPrimaryElectronsFromDalitz = EMPrimaryElectronsFromDalitz_001; + // iterators using EMPrimaryElectronFromDalitz = EMPrimaryElectronsFromDalitz::iterator; @@ -462,16 +562,16 @@ DECLARE_SOA_COLUMN(Time, time, float); DECLARE_SOA_COLUMN(IsExotic, isExotic, bool); //! flag to mark cluster as exotic DECLARE_SOA_COLUMN(Definition, definition, int); //! cluster definition, see EMCALClusterDefinition.h DECLARE_SOA_ARRAY_INDEX_COLUMN(Track, track); //! TrackIds -DECLARE_SOA_COLUMN(TrackEta, tracketa, std::vector); //! eta values of the matched tracks -DECLARE_SOA_COLUMN(TrackPhi, trackphi, std::vector); //! phi values of the matched tracks +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, std::vector); //! phi values of the matched tracks +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, std::vector); //! eta values of the matched tracks DECLARE_SOA_COLUMN(TrackP, trackp, std::vector); //! momentum values of the matched tracks DECLARE_SOA_COLUMN(TrackPt, trackpt, std::vector); //! pt values of the matched tracks DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float e, float eta, float m = 0) -> float { return sqrt(e * e - m * m) / cosh(eta); }); //! cluster pt, mass to be given as argument when getter is called! } // namespace emccluster -DECLARE_SOA_TABLE(SkimEMCClusters, "AOD", "SKIMEMCCLUSTERS", //! table of skimmed EMCal clusters +DECLARE_SOA_TABLE(SkimEMCClusters, "AOD", "SKIMEMCCLUSTER", //! table of skimmed EMCal clusters o2::soa::Index<>, skimmedcluster::CollisionId, emccluster::Definition, skimmedcluster::E, skimmedcluster::Eta, skimmedcluster::Phi, - skimmedcluster::M02, skimmedcluster::NCells, skimmedcluster::Time, emccluster::IsExotic, emccluster::TrackEta, - emccluster::TrackPhi, emccluster::TrackP, emccluster::TrackPt, emccluster::Pt); + skimmedcluster::M02, skimmedcluster::NCells, skimmedcluster::Time, emccluster::IsExotic, emccluster::DeltaPhi, + emccluster::DeltaEta, emccluster::TrackP, emccluster::TrackPt, emccluster::Pt); using SkimEMCCluster = SkimEMCClusters::iterator; DECLARE_SOA_TABLE(EMCEMEventIds, "AOD", "EMCEMEVENTID", emccluster::EMEventId); // To be joined with SkimEMCClusters table at analysis level. @@ -523,42 +623,11 @@ namespace caloextra { DECLARE_SOA_INDEX_COLUMN_FULL(Cluster, cluster, int, SkimEMCClusters, ""); //! reference to the gamma in the skimmed EMCal table DECLARE_SOA_INDEX_COLUMN_FULL(Cell, cell, int, Calos, ""); //! reference to the gamma in the skimmed EMCal table -// DECLARE_SOA_INDEX_COLUMN(Track, track); //! TrackID -DECLARE_SOA_COLUMN(TrackEta, tracketa, float); //! eta of the matched track -DECLARE_SOA_COLUMN(TrackPhi, trackphi, float); //! phi of the matched track -DECLARE_SOA_COLUMN(TrackP, trackp, float); //! momentum of the matched track -DECLARE_SOA_COLUMN(TrackPt, trackpt, float); //! pt of the matched track } // namespace caloextra 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; - -DECLARE_SOA_TABLE(SkimEMCMTs, "AOD", "SKIMEMCMTS", //! table of link between skimmed EMCal clusters and their matched tracks - o2::soa::Index<>, caloextra::ClusterId, caloextra::TrackEta, - caloextra::TrackPhi, caloextra::TrackP, caloextra::TrackPt); -using SkimEMCMT = SkimEMCMTs::iterator; - -namespace gammareco -{ -DECLARE_SOA_COLUMN(Method, method, int); //! cut bit for PCM photon candidates -DECLARE_SOA_INDEX_COLUMN_FULL(SkimmedPCM, skimmedPCM, int, V0PhotonsKF, ""); //! reference to the gamma in the skimmed PCM table -DECLARE_SOA_INDEX_COLUMN_FULL(SkimmedPHOS, skimmedPHOS, int, PHOSClusters, ""); //! reference to the gamma in the skimmed PHOS table -DECLARE_SOA_INDEX_COLUMN_FULL(SkimmedEMC, skimmedEMC, int, SkimEMCClusters, ""); //! reference to the gamma in the skimmed EMCal table -DECLARE_SOA_COLUMN(PCMCutBit, pcmcutbit, uint64_t); //! cut bit for PCM photon candidates -DECLARE_SOA_COLUMN(PHOSCutBit, phoscutbit, uint64_t); //! cut bit for PHOS photon candidates -DECLARE_SOA_COLUMN(EMCCutBit, emccutbit, uint64_t); //! cut bit for EMCal photon candidates -} // namespace gammareco -DECLARE_SOA_TABLE(SkimGammas, "AOD", "SKIMGAMMAS", //! table of all gamma candidates (PCM, EMCal and PHOS) after cuts - o2::soa::Index<>, skimmedcluster::CollisionId, gammareco::Method, - skimmedcluster::E, skimmedcluster::Eta, skimmedcluster::Phi, - gammareco::SkimmedEMCId, gammareco::SkimmedPHOSId); -DECLARE_SOA_TABLE(SkimPCMCuts, "AOD", "SKIMPCMCUTS", //! table of link between skimmed PCM photon candidates and their cuts - o2::soa::Index<>, gammareco::SkimmedPCMId, gammareco::PCMCutBit); //! -DECLARE_SOA_TABLE(SkimPHOSCuts, "AOD", "SKIMPHOSCUTS", //! table of link between skimmed PHOS photon candidates and their cuts - o2::soa::Index<>, gammareco::SkimmedPHOSId, gammareco::PHOSCutBit); //! -DECLARE_SOA_TABLE(SkimEMCCuts, "AOD", "SKIMEMCCUTS", //! table of link between skimmed EMCal photon candidates and their cuts - o2::soa::Index<>, gammareco::SkimmedEMCId, gammareco::EMCCutBit); //! } // namespace o2::aod #endif // PWGEM_PHOTONMESON_DATAMODEL_GAMMATABLES_H_ diff --git a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt index 511fb699611..a4cf2e6b566 100644 --- a/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt +++ b/PWGEM/PhotonMeson/TableProducer/CMakeLists.txt @@ -63,13 +63,3 @@ o2physics_add_dpl_workflow(skimmer-dalitz-ee SOURCES skimmerDalitzEE.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(gamma-table-producer - SOURCES gammaSelection.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(produce-meson-calo - SOURCES produceMesonCalo.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore - COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx index 8a09995167d..ab6bba76b3e 100644 --- a/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx +++ b/PWGEM/PhotonMeson/TableProducer/bcWiseClusterSkimmer.cxx @@ -16,25 +16,25 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt /// -#include -#include -#include -#include +#include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.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 "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" +#include +#include +#include +#include using namespace o2; using namespace o2::aod::emdownscaling; @@ -43,7 +43,7 @@ using namespace o2::framework::expressions; using MyCollisions = soa::Join; using MyMCCollisions = soa::Join; -using MyBCs = soa::Join; +using MyBCs = soa::Join; using SelectedUniqueClusters = soa::Filtered; // Clusters from collisions with only one collision in the BC using SelectedUniqueMCClusters = soa::Filtered>; // Clusters from collisions with only one collision in the BC @@ -56,6 +56,7 @@ struct bcWiseClusterSkimmer { Produces clusterTable; Produces collisionTable; Produces mcpi0Table; + Produces mcetaTable; Produces mcclusterTable; PresliceUnsorted perFoundBC = aod::evsel::foundBCId; @@ -70,11 +71,12 @@ struct bcWiseClusterSkimmer { Configurable cfgMinTime{"cfgMinTime", -25, "Minimum time of selected clusters (ns)"}; Configurable cfgMaxTime{"cfgMaxTime", 25, "Maximum time of selected clusters (ns)"}; Configurable cfgRapidityCut{"cfgRapidityCut", 0.8f, "Maximum absolute rapidity of counted generated particles"}; - Configurable cfgMinPtGenPi0{"cfgMinPtGenPi0", 0., "Minimum pT for stored generated pi0s (reduce disk space of derived data)"}; + Configurable cfgMinPtGen{"cfgMinPtGen", 0., "Minimum pT for stored generated mesons (reduce disk space of derived data)"}; Configurable cfgRequirekTVXinEMC{"cfgRequirekTVXinEMC", false, "Only store kTVXinEMC triggered BCs"}; 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"}; 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}; @@ -90,6 +92,7 @@ struct bcWiseClusterSkimmer { HistogramRegistry mHistManager{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; std::map fMapPi0Index; // Map to connect the MC index of the pi0 to the one saved in the derived table + std::map fMapEtaIndex; // Map to connect the MC index of the eta to the one saved in the derived table void init(o2::framework::InitContext&) { @@ -100,6 +103,7 @@ struct bcWiseClusterSkimmer { mHistManager.get(HIST("nBCs"))->GetXaxis()->SetBinLabel(iBin + 1, binLabels[iBin]); mHistManager.add("CentralityVsGenMultiplicity", "Centrality vs number of generated MC particles;Centrality;#bf{#it{N}_{gen}}", HistType::kTH2F, {{102, 0., 102}, cfgMultiplicityBinning}); + mHistManager.add("BCCentVsCollCent", "Centrality of the BC vs Centrality of the collision;BC Centrality;Collision Centrality", HistType::kTH2F, {{102, 0., 102}, {102, 0., 102}}); LOG(info) << "BC wise cluster skimmer cuts:"; LOG(info) << "------------------------------------"; @@ -107,7 +111,7 @@ struct bcWiseClusterSkimmer { LOG(info) << "| Shape cut: " << cfgMinM02 << " < M02 < " << cfgMaxM02; LOG(info) << "| Energy cut: " << cfgMinClusterEnergy << " < E < " << cfgMaxClusterEnergy; LOG(info) << "| Rapidity cut: |y| < " << cfgRapidityCut; - LOG(info) << "| Min gen pi0 pt: pT > " << cfgMinPtGenPi0; + LOG(info) << "| Min gen pt: pT > " << cfgMinPtGen; o2::emcal::Geometry::GetInstanceFromRunNumber(300000); if (cfgRequireGoodRCTQuality) @@ -153,56 +157,74 @@ struct bcWiseClusterSkimmer { { for (const auto& cluster : clusters) { float clusterInducerEnergy = 0.; - int32_t pi0MCIndex = -1; + int32_t mesonMCIndex = -1; if (cluster.amplitudeA().size() > 0) { int clusterInducerId = cluster.mcParticleIds()[0]; auto clusterInducer = mcParticles.iteratorAt(clusterInducerId); clusterInducerEnergy = clusterInducer.e(); - int daughterId = aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(clusterInducer, mcParticles, std::vector{111}); + int daughterId = aod::pwgem::photonmeson::utils::mcutil::FindMotherInChain(clusterInducer, mcParticles, std::vector{111, 221}); if (daughterId > 0) { - pi0MCIndex = mcParticles.iteratorAt(daughterId).mothersIds()[0]; - if (mcParticles.iteratorAt(pi0MCIndex).pt() < cfgMinPtGenPi0) - pi0MCIndex = -1; + mesonMCIndex = mcParticles.iteratorAt(daughterId).mothersIds()[0]; + if (mcParticles.iteratorAt(mesonMCIndex).pt() < cfgMinPtGen) + mesonMCIndex = -1; } } - if (pi0MCIndex >= 0) { - if (fMapPi0Index.find(pi0MCIndex) != fMapPi0Index.end()) // Some pi0s might not be found (not gg decay or too large y) - pi0MCIndex = fMapPi0Index[pi0MCIndex]; // 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 - pi0MCIndex = -1; + bool isEta = false; + if (mesonMCIndex >= 0) { + if (mcParticles.iteratorAt(mesonMCIndex).pdgCode() == 111) { + 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) { + 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 + else // If eta was not stored, treat photon as if not from eta + mesonMCIndex = -1; + } else { + mesonMCIndex = -1; // Not a pi0 or eta + } } - mcclusterTable(bcID, pi0MCIndex, convertForStorage(clusterInducerEnergy, kEnergy)); + mcclusterTable(bcID, mesonMCIndex, isEta, convertForStorage(clusterInducerEnergy, kEnergy)); } } bool isBCSelected(const auto& bc) { - if (cfgRequirekTVXinEMC && !bc.selection_bit(aod::evsel::kIsTriggerTVX)) + if (cfgRequirekTVXinEMC && !bc.alias_bit(kTVXinEMC)) return false; if (cfgRequireGoodRCTQuality && !isFT0EMCGoodRCTChecker(bc)) return false; return true; } - double calculateMu(const auto& bc) + void setLHCIFData(const auto& bc) { + if (mRunNumber == bc.runNumber()) + return; + auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); uint64_t timeStamp = bc.timestamp(); - if (mRunNumber != bc.runNumber()) { - std::map metadata; - mLHCIFdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); - 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; - } + std::map metadata; + mLHCIFdata = ccdbMgr.getSpecific("GLO/Config/GRPLHCIF", timeStamp, metadata); + 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; + + return; + } + + double calculateMu(const auto& bc) + { + auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + uint64_t timeStamp = bc.timestamp(); auto bfilling = mLHCIFdata->getBunchFilling(); double nbc = bfilling.getFilledBCs().size(); - double tvxRate = mRateFetcher.fetch(&ccdbMgr, timeStamp, bc.runNumber(), "T0VTX"); - double nTriggersPerFilledBC = tvxRate / nbc / o2::constants::lhc::LHCRevFreq; double mu = -std::log(1 - nTriggersPerFilledBC); @@ -217,7 +239,6 @@ struct bcWiseClusterSkimmer { bool hasTVX = bc.selection_bit(aod::evsel::kIsTriggerTVX); bool haskTVXinEMC = bc.alias_bit(kTVXinEMC); bool hasEMCCell = cellsInBC.size() > 0; - bool hasNoTFROFBorder = bc.selection_bit(aod::evsel::kNoTimeFrameBorder) && bc.selection_bit(aod::evsel::kNoITSROFrameBorder); mHistManager.fill(HIST("nBCs"), 0); if (hasFT0) mHistManager.fill(HIST("nBCs"), 1); @@ -227,16 +248,20 @@ struct bcWiseClusterSkimmer { mHistManager.fill(HIST("nBCs"), 3); if (hasEMCCell) mHistManager.fill(HIST("nBCs"), 4); - if (hasNoTFROFBorder) - mHistManager.fill(HIST("nBCs"), 5); + if (cfgStoreMu || cfgStoreTime) + setLHCIFData(bc); double mu = cfgStoreMu ? calculateMu(bc) : 0.; + float timeSinceSOF = cfgStoreTime ? (bc.timestamp() - mLHCIFdata->getFillNumberTime()) / 1e3 : 0.; // Convert to seconds float ft0Amp = hasFT0 ? bc.foundFT0().sumAmpA() + bc.foundFT0().sumAmpC() : 0.; - double centrality = 101.5; + double centralityOfCollision = 101.5; if (collisionsInBC.size() > 0) - centrality = collisionsInBC.iteratorAt(0).centFT0M(); + centralityOfCollision = collisionsInBC.iteratorAt(0).centFT0M(); + double centralityOfBC = bc.centFT0M(); - bcTable(hasFT0, hasTVX, haskTVXinEMC, hasEMCCell, hasNoTFROFBorder, convertForStorage(centrality, kFT0MCent), convertForStorage(ft0Amp, kFT0Amp), convertForStorage(mu, kMu)); + mHistManager.fill(HIST("BCCentVsCollCent"), centralityOfBC, centralityOfCollision); + + bcTable(hasFT0, hasTVX, haskTVXinEMC, hasEMCCell, convertForStorage(centralityOfBC, kFT0MCent), convertForStorage(ft0Amp, kFT0Amp), convertForStorage(mu, kMu), convertForStorage(timeSinceSOF, kTimeSinceSOF)); for (const auto& collision : collisionsInBC) collisionTable(bcTable.lastIndex(), convertForStorage(collision.centFT0M(), kFT0MCent), convertForStorage(collision.posZ(), kZVtx)); @@ -313,17 +338,20 @@ struct bcWiseClusterSkimmer { auto mcCollisionsBC = mcCollisions.sliceBy(mcCollperBC, bc.globalIndex()); for (const auto& mcCollision : mcCollisionsBC) { auto mcParticlesInColl = mcParticles.sliceBy(perMcCollision, mcCollision.globalIndex()); - double centrality = 101.5; - if (collisionsInBC.size() > 0) - centrality = collisionsInBC.iteratorAt(0).centFT0M(); - mHistManager.fill(HIST("CentralityVsGenMultiplicity"), centrality, mcParticlesInColl.size()); + mHistManager.fill(HIST("CentralityVsGenMultiplicity"), bc.centFT0M(), mcParticlesInColl.size()); for (const auto& mcParticle : mcParticlesInColl) { - if (mcParticle.pdgCode() != 111 || std::abs(mcParticle.y()) > cfgRapidityCut || !isGammaGammaDecay(mcParticle, mcParticles) || mcParticle.pt() < cfgMinPtGenPi0) + if (std::abs(mcParticle.y()) > cfgRapidityCut || !isGammaGammaDecay(mcParticle, mcParticles) || mcParticle.pt() < cfgMinPtGen) continue; bool isPrimary = mcParticle.isPhysicalPrimary() || mcParticle.producedByGenerator(); bool isFromWD = (aod::pwgem::photonmeson::utils::mcutil::IsFromWD(mcCollision, mcParticle, mcParticles)) > 0; - mcpi0Table(bc.globalIndex(), convertForStorage(mcParticle.pt(), kpT), isAccepted(mcParticle, mcParticles), isPrimary, isFromWD); - fMapPi0Index[mcParticle.globalIndex()] = static_cast(mcpi0Table.lastIndex()); + + if (mcParticle.pdgCode() == 111) { + mcpi0Table(bc.globalIndex(), 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); + fMapEtaIndex[mcParticle.globalIndex()] = static_cast(mcetaTable.lastIndex()); + } } } @@ -337,6 +365,7 @@ struct bcWiseClusterSkimmer { processClusterMCInfo(clustersInBC, bc.globalIndex(), mcParticles); } fMapPi0Index.clear(); + fMapEtaIndex.clear(); } } PROCESS_SWITCH(bcWiseClusterSkimmer, processMC, "Run skimming for MC", false); diff --git a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx index fc155fe5502..724b6347fa6 100644 --- a/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx +++ b/PWGEM/PhotonMeson/TableProducer/createEMEventPhoton.cxx @@ -14,23 +14,22 @@ /// /// \author Daiki Sekihata, daiki.sekihata@cern.ch -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGJE/DataModel/Jet.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/CCDB/TriggerAliases.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.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 using namespace o2; using namespace o2::framework; @@ -40,26 +39,33 @@ using namespace o2::soa; using MyBCs = soa::Join; using MyQvectors = soa::Join; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; using MyCollisionsCent = soa::Join; // centrality table has dependency on multiplicity table. using MyCollisionsCentQvec = soa::Join; +using MyCollisionsWithSWT = soa::Join; +using MyCollisionsWithSWT_Cent = soa::Join; // centrality table has dependency on multiplicity table. +using MyCollisionsWithSWT_Cent_Qvec = soa::Join; + using MyCollisionsMC = soa::Join; using MyCollisionsMCCent = soa::Join; // centrality table has dependency on multiplicity table. using MyCollisionsMCCentQvec = soa::Join; struct CreateEMEventPhoton { + Produces embc; Produces event; // Produces eventCov; Produces eventMult; Produces eventCent; Produces eventQvec; + Produces emswtbit; + Produces event_norm_info; Produces eventWeights; enum class EMEventType : int { kEvent = 0, - kEventCent = 1, - kEventCent_Qvec = 2, + kEvent_Cent = 1, + kEvent_Cent_Qvec = 2, kEvent_JJ = 3, }; @@ -129,9 +135,15 @@ struct CreateEMEventPhoton { mRunNumber = bc.runNumber(); } - template - void skimEvent(TCollisions const& collisions, TBCs const&) + template + void skimEvent(TCollisions const& collisions, TBCs const& bcs) { + for (const auto& bc : bcs) { + if (bc.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + embc(bc.alias_raw(), bc.selection_raw(), bc.rct_raw()); // TVX is fired. + } + } // end of bc loop + for (const auto& collision : collisions) { if constexpr (isMC) { if (!collision.has_mcCollision()) { @@ -152,6 +164,26 @@ struct CreateEMEventPhoton { continue; } + if constexpr (eventtype == EMEventType::kEvent) { + event_norm_info(collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), static_cast(10.f * collision.posZ()), 105.f); + } else if constexpr (eventtype == EMEventType::kEvent_Cent || eventtype == EMEventType::kEvent_Cent_Qvec) { + event_norm_info(collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), static_cast(10.f * collision.posZ()), collision.centFT0C()); + } else { + event_norm_info(collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), static_cast(10.f * collision.posZ()), 105.f); + } + + if (!collision.isEoI()) { // events with at least 1 photon for data reduction. + continue; + } + + if constexpr (isTriggerAnalysis) { + if (collision.swtaliastmp_raw() == 0) { + continue; + } else { + emswtbit(collision.swtaliastmp_raw(), collision.nInspectedTVX()); + } + } + const float qDefault = 999.f; // default value for q vectors if not obtained registry.fill(HIST("hEventCounter"), 1); @@ -161,26 +193,26 @@ struct CreateEMEventPhoton { } event(collision.globalIndex(), bc.runNumber(), bc.globalBC(), collision.alias_raw(), collision.selection_raw(), collision.rct_raw(), bc.timestamp(), - collision.posX(), collision.posY(), collision.posZ(), + collision.posZ(), collision.numContrib(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); // eventCov(collision.covXX(), collision.covXY(), collision.covXZ(), collision.covYY(), collision.covYZ(), collision.covZZ(), collision.chi2()); eventMult(collision.multFT0A(), collision.multFT0C(), collision.multNTracksPV(), collision.multNTracksPVeta1(), collision.multNTracksPVetaHalf()); - if constexpr (eventype != EMEventType::kEvent_JJ) { + if constexpr (eventtype != EMEventType::kEvent_JJ) { eventWeights(1.f); } - if constexpr (eventype == EMEventType::kEvent) { + if constexpr (eventtype == EMEventType::kEvent) { eventCent(105.f, 105.f, 105.f); eventQvec(qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault); - } else if constexpr (eventype == EMEventType::kEventCent) { + } else if constexpr (eventtype == EMEventType::kEvent_Cent) { eventCent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); eventQvec(qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault, qDefault); - } else if constexpr (eventype == EMEventType::kEventCent_Qvec) { + } else if constexpr (eventtype == EMEventType::kEvent_Cent_Qvec) { eventCent(collision.centFT0M(), collision.centFT0A(), collision.centFT0C()); const size_t qvecSize = collision.qvecFT0CReVec().size(); if (qvecSize >= 2) { // harmonics 2,3 @@ -232,46 +264,66 @@ struct CreateEMEventPhoton { } } + // for data void processEvent(MyCollisions const& collisions, MyBCs const& bcs) { - skimEvent(collisions, bcs); + skimEvent(collisions, bcs); } PROCESS_SWITCH(CreateEMEventPhoton, processEvent, "process event info", false); - void processEventMC(MyCollisionsMC const& collisions, MyBCs const& bcs) + void processEvent_Cent(MyCollisionsCent const& collisions, MyBCs const& bcs) { - skimEvent(collisions, bcs); + skimEvent(collisions, bcs); } - PROCESS_SWITCH(CreateEMEventPhoton, processEventMC, "process event info", false); + PROCESS_SWITCH(CreateEMEventPhoton, processEvent_Cent, "process event info", false); - void processEventJJMC(MyCollisionsMC const& collisions, MyJJCollisions const& mcCollisions, MyBCs const& bcs, aod::FullMCParticleLevelJets const& jets) + void processEvent_Cent_Qvec(MyCollisionsCentQvec const& collisions, MyBCs const& bcs) { - skimEvent(collisions, bcs); - fillEventWeights(collisions, mcCollisions, bcs, jets); + skimEvent(collisions, bcs); } - PROCESS_SWITCH(CreateEMEventPhoton, processEventJJMC, "process event info", false); + PROCESS_SWITCH(CreateEMEventPhoton, processEvent_Cent_Qvec, "process event info", false); - void processEvent_Cent(MyCollisionsCent const& collisions, MyBCs const& bcs) + void processEvent_SWT(MyCollisionsWithSWT const& collisions, MyBCs const& bcs) { - skimEvent(collisions, bcs); + skimEvent(collisions, bcs); } - PROCESS_SWITCH(CreateEMEventPhoton, processEvent_Cent, "process event info", false); + PROCESS_SWITCH(CreateEMEventPhoton, processEvent_SWT, "process event info", false); - void processEvent_Cent_Qvec(MyCollisionsCentQvec const& collisions, MyBCs const& bcs) + void processEvent_SWT_Cent(MyCollisionsWithSWT_Cent const& collisions, MyBCs const& bcs) { - skimEvent(collisions, bcs); + skimEvent(collisions, bcs); } - PROCESS_SWITCH(CreateEMEventPhoton, processEvent_Cent_Qvec, "process event info", false); + PROCESS_SWITCH(CreateEMEventPhoton, processEvent_SWT_Cent, "process event info", false); + + void processEvent_SWT_Cent_Qvec(MyCollisionsWithSWT_Cent_Qvec const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventPhoton, processEvent_SWT_Cent_Qvec, "process event info", false); + + // for MC + void processEventMC(MyCollisionsMC const& collisions, MyBCs const& bcs) + { + skimEvent(collisions, bcs); + } + PROCESS_SWITCH(CreateEMEventPhoton, processEventMC, "process event info", false); + + void processEventJJMC(MyCollisionsMC const& collisions, MyJJCollisions const& mcCollisions, MyBCs const& bcs, aod::FullMCParticleLevelJets const& jets) + { + skimEvent(collisions, bcs); + fillEventWeights(collisions, mcCollisions, bcs, jets); + } + PROCESS_SWITCH(CreateEMEventPhoton, processEventJJMC, "process event info", false); void processEventMC_Cent(MyCollisionsMCCent const& collisions, MyBCs const& bcs) { - skimEvent(collisions, bcs); + skimEvent(collisions, bcs); } PROCESS_SWITCH(CreateEMEventPhoton, processEventMC_Cent, "process event info", false); void processEventMC_Cent_Qvec(MyCollisionsMCCentQvec const& collisions, MyBCs const& bcs) { - skimEvent(collisions, bcs); + skimEvent(collisions, bcs); } PROCESS_SWITCH(CreateEMEventPhoton, processEventMC_Cent_Qvec, "process event info", false); @@ -281,14 +333,15 @@ struct CreateEMEventPhoton { struct AssociatePhotonToEMEvent { Produces v0kfeventid; Produces prmeleventid; - Produces prmmueventid; Produces phoseventid; Produces emceventid; + 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; void init(o2::framework::InitContext&) {} @@ -327,12 +380,18 @@ struct AssociatePhotonToEMEvent { fillEventId(collisions, photons, emceventid, perCollisionEMC); } + void processChargedTrack(aod::EMEvents const& collisions, aod::EMPrimaryTracks const& tracks) + { + fillEventId(collisions, tracks, prmtrackeventid, perCollision_track); + } + void processDummy(aod::EMEvents 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, processDummy, "process dummy", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGEM/PhotonMeson/TableProducer/gammaSelection.cxx b/PWGEM/PhotonMeson/TableProducer/gammaSelection.cxx deleted file mode 100644 index 7a3708d480b..00000000000 --- a/PWGEM/PhotonMeson/TableProducer/gammaSelection.cxx +++ /dev/null @@ -1,193 +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 skim cluster information to write photon cluster table in AO2D.root -/// dependencies: skimmergammacalo, skimmergammaconversions, skimmer-phos -/// \author marvin.hemmer@cern.ch - -// TODO: add PCM table -#include - -#include "PWGEM/PhotonMeson/Utils/gammaSelectionCuts.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - -// includes for the R recalculation -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "CCDB/BasicCCDBManager.h" - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -struct gammaSelection { - - uint64_t EMC_CutModeBit; - - Preslice perEMCClusterMT = o2::aod::caloextra::clusterId; - - Produces tableGammaReco; - Produces tableEMCCuts; - - // Configurable for filter/cuts - Configurable EMC_minTime{"EMC_minTime", -20., "Minimum cluster time for EMCal time cut"}; - Configurable EMC_maxTime{"EMC_maxTime", +25., "Maximum cluster time for EMCal time cut"}; - Configurable EMC_minM02{"EMC_minM02", 0.1, "Minimum M02 for EMCal M02 cut"}; - Configurable EMC_maxM02{"EMC_maxM02", 0.7, "Maximum M02 for EMCal M02 cut"}; - Configurable EMC_minE{"EMC_minE", 0.7, "Minimum cluster energy for EMCal energy cut"}; - Configurable EMC_minNCell{"EMC_minNCell", 1, "Minimum number of cells per cluster for EMCal NCell cut"}; - Configurable> EMC_TM_Eta{"EMC_TM_Eta", {0.01f, 4.07f, -2.5f}, "|eta| <= [0]+(pT+[1])^[2] for EMCal track matching"}; - Configurable> EMC_TM_Phi{"EMC_TM_Phi", {0.015f, 3.65f, -2.f}, "|phi| <= [0]+(pT+[1])^[2] for EMCal track matching"}; - Configurable EMC_Eoverp{"EMC_Eoverp", 1.75, "Minimum cluster energy over track momentum for EMCal track matching"}; - Configurable EMC_CutMode{"EMC_CutMode", "0", "Cut Mode that is run. Each bit is a different setting. The first bit will use the cuts from the configurables."}; - - Configurable PHOS_minTime{"PHOS_minTime", -30., "Minimum cluster time for PHOS time cut"}; - Configurable PHOS_maxTime{"PHOS_maxTime", +30., "Maximum cluster time for PHOS time cut"}; - Configurable PHOS_minM02{"PHOS_minM02", 0.1, "Minimum M02 for PHOS M02 cut"}; - Configurable PHOS_minE{"PHOS_minE", 0.3, "Minimum cluster energy for PHOS energy cut"}; - Configurable PHOS_minENCell{"PHOS_minENCell", 0.1, "Threshold cluster energy for switch for PHOS NCell and M02 cut"}; - Configurable PHOS_minNCell{"PHOS_minNCell", 1, "Minimum number of cells per cluster for PHOS NCell cut"}; - Configurable PHOS_TM_Eta{"PHOS_TM_Eta", 0.02f, "|eta| <= value for PHOS track matching"}; - Configurable PHOS_TM_Phi{"PHOS_TM_Phi", 0.08f, "|phi| <= value for PHOS track matching"}; - - Configurable PHOS_QA{"PHOS_QA", 0b0, "Flag to enable PHOS related QA plots. 1st bit for TM QA."}; - - HistogramRegistry EMCHistos{ - "EMCHistos", - {}, - OutputObjHandlingPolicy::QAObject, - true, - true}; - - HistogramRegistry PHOSHistos{ - "PHOSHistos", - {}, - OutputObjHandlingPolicy::QAObject, - true, - true}; - - void init(o2::framework::InitContext&) - { - EMC_CutModeBit = stoi(EMC_CutMode, 0, 2); - std::bitset<64> EMC_CutModeBitSet(EMC_CutModeBit); - // EMCal - EMCHistos.add("hClusterEIn", "hClusterEIn", gHistoSpec_clusterECuts); - EMCHistos.add("hClusterEOut", "hClusterEOut", gHistoSpec_clusterECuts); - auto hCaloCuts_EMC = EMCHistos.add("hCaloCuts_EMC", "hCaloCuts_EMC", kTH2I, {{7, -0.5, 6.5}, {64, -0.5, 63.5}}); - hCaloCuts_EMC->GetXaxis()->SetBinLabel(1, "in"); - hCaloCuts_EMC->GetXaxis()->SetBinLabel(2, "#it{t}_{cluster} cut"); - hCaloCuts_EMC->GetXaxis()->SetBinLabel(3, "#it{M}_{02} cut"); - hCaloCuts_EMC->GetXaxis()->SetBinLabel(4, "#it{E} cut"); - hCaloCuts_EMC->GetXaxis()->SetBinLabel(5, "#it{N}_{cell} cut"); - hCaloCuts_EMC->GetXaxis()->SetBinLabel(6, "TM"); - hCaloCuts_EMC->GetXaxis()->SetBinLabel(7, "out"); - - LOG(info) << "| ECMal cluster cut settings:"; - LOG(info) << "|\t Timing cut: " << EMC_minTime << " < t < " << EMC_maxTime; - LOG(info) << "|\t M02 cut: " << EMC_minM02 << " < M02 < " << EMC_maxM02; - LOG(info) << "|\t E_min cut: E_cluster > " << EMC_minE; - LOG(info) << "|\t N_cell cut: N_cell > " << EMC_minNCell; - LOG(info) << "|\t TM |eta|: |eta| <= " << EMC_TM_Eta->at(0) << " + (pT + " << EMC_TM_Eta->at(1) << ")^" << EMC_TM_Eta->at(2); - LOG(info) << "|\t TM |phi|: |phi| <= " << EMC_TM_Phi->at(0) << " + (pT + " << EMC_TM_Phi->at(1) << ")^" << EMC_TM_Phi->at(2); - LOG(info) << "|\t TM E/p: E/p < " << EMC_Eoverp; - LOG(info) << "|\t Cut bit is set to: " << EMC_CutModeBitSet << std::endl; - - gatherCutsEMC(EMC_minTime, EMC_maxTime, EMC_minM02, EMC_maxM02, EMC_minE, EMC_minNCell, EMC_TM_Eta, EMC_TM_Phi, EMC_Eoverp); - - // PHOS - PHOSHistos.add("hClusterEIn", "hClusterEIn", gHistoSpec_clusterECuts); - PHOSHistos.add("hClusterEOut", "hClusterEOut", gHistoSpec_clusterECuts); - auto hCaloCuts_PHOS = PHOSHistos.add("hCaloCuts_PHOS", "hCaloCuts_PHOS", kTH1I, {{7, -0.5, 6.5}}); - hCaloCuts_PHOS->GetXaxis()->SetBinLabel(1, "in"); - hCaloCuts_PHOS->GetXaxis()->SetBinLabel(2, "#it{t}_{cluster} cut"); - hCaloCuts_PHOS->GetXaxis()->SetBinLabel(3, "#it{M}_{02} cut"); - hCaloCuts_PHOS->GetXaxis()->SetBinLabel(4, "#it{E} cut"); - hCaloCuts_PHOS->GetXaxis()->SetBinLabel(5, "#it{N}_{cell} cut"); - hCaloCuts_PHOS->GetXaxis()->SetBinLabel(6, "TM"); - hCaloCuts_PHOS->GetXaxis()->SetBinLabel(7, "out"); - if (PHOS_QA & 0b1) { - PHOSHistos.add("clusterTM_dEtadPhi", "cluster trackmatching dEta/dPhi;d#it{#eta};d#it{#varphi} (rad)", kTH2F, {{100, -0.2, 0.2}, {100, -0.2, 0.2}}); // dEta dPhi map of matched tracks - } - - LOG(info) << "| PHOS cluster cut settings:"; - LOG(info) << "|\t Timing cut: " << PHOS_minTime << " < t < " << PHOS_maxTime; - LOG(info) << "|\t NCell cut: " << PHOS_minNCell << " <= NCell for E >= " << PHOS_minENCell; - LOG(info) << "|\t M02 cut: " << PHOS_minM02 << " < M02 for E >= " << PHOS_minENCell; - LOG(info) << "|\t E_min cut: E_cluster > " << PHOS_minE; - LOG(info) << "|\t TM |eta|: |eta| <= " << PHOS_TM_Eta; - LOG(info) << "|\t TM |phi|: |phi| <= " << PHOS_TM_Phi << std::endl; - } - - void processRec(aod::EMEvents const&, aod::SkimEMCClusters const& emcclusters, aod::SkimEMCMTs const& matchedtracks, aod::PHOSClusters const& phosclusters) - { - for (const auto& emccluster : emcclusters) { // loop of EMC clusters - uint64_t EMC_CutBit = doPhotonCutsEMC(EMC_CutModeBit, emccluster, matchedtracks, perEMCClusterMT, EMCHistos); - tableEMCCuts(emccluster.globalIndex(), EMC_CutBit); - } // end loop of EMC clusters - - for (const auto& phoscluster : phosclusters) { // loop over PHOS clusters - PHOSHistos.fill(HIST("hClusterEIn"), phoscluster.e(), 0); - PHOSHistos.fill(HIST("hCaloCuts_PHOS"), 0); - - if (phoscluster.time() > PHOS_maxTime || phoscluster.time() < PHOS_minTime) { - PHOSHistos.fill(HIST("hCaloCuts_PHOS"), 1); - continue; - } - if (!(phoscluster.e() >= PHOS_minENCell && phoscluster.m02() > PHOS_minM02)) { - PHOSHistos.fill(HIST("hCaloCuts_PHOS"), 2); - continue; - } - if (phoscluster.e() <= PHOS_minE) { - PHOSHistos.fill(HIST("hCaloCuts_PHOS"), 3); - continue; - } - if (!(phoscluster.e() >= PHOS_minENCell && phoscluster.nCells() > PHOS_minNCell)) { - PHOSHistos.fill(HIST("hCaloCuts_PHOS"), 4); - continue; - } - - // TODO: add track matching for PHOS when available! - // track matching - bool hasMatchedTrack_PHOS = false; - // double dEta_PHOS, dPhi_PHOS; - // // only consider closest match - // dEta_PHOS = phoscluster.tracketa() - phoscluster.eta(); - // dPhi_PHOS = phoscluster.trackphi() - phoscluster.phi(); - // if ((fabs(dEta_PHOS) < PHOS_TM_Eta) && (fabs(dPhi_PHOS) < PHOS_TM_Phi)) { - // hasMatchedTrack_PHOS = true; - // if (PHOS_QA & 0b1) { - // EMCHistos.fill(HIST("clusterTM_dEtadPhi"), dEta_PHOS, dPhi_PHOS); - // } - // } - if (hasMatchedTrack_PHOS) { - PHOSHistos.fill(HIST("hCaloCuts_PHOS"), 5); - } else { - PHOSHistos.fill(HIST("hClusterEOut"), phoscluster.e(), 0); - PHOSHistos.fill(HIST("hCaloCuts_PHOS"), 6); - tableGammaReco(phoscluster.collisionId(), 2, - phoscluster.e(), phoscluster.eta(), phoscluster.phi(), 0, phoscluster.globalIndex()); - } - } // end loop of PHOS clusters - } - PROCESS_SWITCH(gammaSelection, processRec, "process only reconstructed info", 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 f6299d4f056..c0eeeba224f 100644 --- a/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx +++ b/PWGEM/PhotonMeson/TableProducer/photonconversionbuilder.cxx @@ -15,43 +15,43 @@ // // \author Daiki Sekihata , Tokyo -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" +#include "Common/Core/TPCVDriftManager.h" +#include "Common/Core/TableHelper.h" #include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" +#include "Tools/KFparticle/KFUtilities.h" + #include "CCDB/BasicCCDBManager.h" -#include "Common/Core/TableHelper.h" -#include "Common/Core/TPCVDriftManager.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 "Tools/KFparticle/KFUtilities.h" +#include "Math/Vector4D.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -65,14 +65,16 @@ using MyCollisions = soa::Join; using MyCollisionsWithSWT = soa::Join; using MyCollisionsMC = soa::Join; -using MyTracksIU = soa::Join; -using MyTracksIUMC = soa::Join; +using MyTracksIU = soa::Join; +using MyTracksIUMC = soa::Join; struct PhotonConversionBuilder { Produces v0photonskf; - Produces v0photonskfcov; Produces v0legs; - Produces events_ngpcm; + Produces v0legsXYZ; + Produces v0legsDeDxMC; + // Produces v0photonskfcov; + // Produces events_ngpcm; // CCDB options Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -92,6 +94,7 @@ struct PhotonConversionBuilder { Configurable moveTPCTracks{"moveTPCTracks", true, "Move TPC-only tracks under the collision assumption"}; Configurable disableITSonlyTracks{"disableITSonlyTracks", false, "disable ITSonly tracks in V0 legs"}; Configurable disableTPConlyTracks{"disableTPConlyTracks", false, "disable TPConly tracks in V0 legs"}; + Configurable requireITShit{"requireITShit", false, "require ITS hit to V0 legs"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max chi2/NclsTPC"}; // default 4.0 + 1.0 Configurable maxchi2its{"maxchi2its", 6.0, "max chi2/NclsITS"}; // default 5.0 + 1.0 @@ -280,6 +283,10 @@ struct PhotonConversionBuilder { return false; } + if (requireITShit && !track.hasITS()) { + return false; + } + if (track.x() > maxX) { return false; } @@ -332,10 +339,10 @@ struct PhotonConversionBuilder { float px = kfp.GetPx(); float py = kfp.GetPy(); float cospaXY = RecoDecay::dotProd(std::array{lx, ly}, std::array{px, py}) / (RecoDecay::sqrtSumOfSquares(lx, ly) * RecoDecay::sqrtSumOfSquares(px, py)); - if (cospaXY < -1.) { - return -1.; - } else if (cospaXY > 1.) { - return 1.; + if (cospaXY < -1.f) { + return -1.f; + } else if (cospaXY > 1.f) { + return 1.f; } return cospaXY; } @@ -351,15 +358,15 @@ struct PhotonConversionBuilder { float pz = kfp.GetPz(); float cospaRZ = RecoDecay::dotProd(std::array{lt, lz}, std::array{pt, pz}) / (RecoDecay::sqrtSumOfSquares(lt, lz) * RecoDecay::sqrtSumOfSquares(pt, pz)); - if (cospaRZ < -1.) { - return -1.; - } else if (cospaRZ > 1.) { - return 1.; + if (cospaRZ < -1.f) { + return -1.f; + } else if (cospaRZ > 1.f) { + return 1.f; } return cospaRZ; } - template + template void fillTrackTable(TTrack const& track, TShiftedTrack const& shiftedtrack, TKFParticle const& kfp, const float dcaXY, const float dcaZ) { v0legs(track.collisionId(), track.globalIndex(), track.sign(), @@ -367,8 +374,13 @@ struct PhotonConversionBuilder { track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), track.tpcChi2NCl(), track.tpcInnerParam(), track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), - track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap(), - shiftedtrack.getX(), shiftedtrack.getY(), shiftedtrack.getZ(), shiftedtrack.getTgl()); + track.itsClusterSizes(), track.itsChi2NCl(), track.detectorMap()); + + v0legsXYZ(shiftedtrack.getX(), shiftedtrack.getY(), shiftedtrack.getZ()); + + if constexpr (isMC) { + v0legsDeDxMC(track.mcTunedTPCSignal()); + } } template @@ -594,6 +606,11 @@ struct PhotonConversionBuilder { return; } + float chi2kf = gammaKF_DecayVtx.GetChi2() / gammaKF_DecayVtx.GetNDF(); + if (chi2kf > 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()); @@ -634,8 +651,6 @@ struct PhotonConversionBuilder { registry.fill(HIST("V0/hCosPAXY_Rxy"), rxy, cospaXY_kf); registry.fill(HIST("V0/hCosPARZ_Rxy"), rxy, cospaRZ_kf); - float chi2kf = gammaKF_DecayVtx.GetChi2() / gammaKF_DecayVtx.GetNDF(); - for (auto& leg : {kfp_pos_DecayVtx, kfp_ele_DecayVtx}) { float legpt = RecoDecay::sqrtSumOfSquares(leg.GetPx(), leg.GetPy()); float legeta = RecoDecay::eta(std::array{leg.GetPx(), leg.GetPy(), leg.GetPz()}); @@ -663,12 +678,13 @@ struct PhotonConversionBuilder { 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); + cospa_kf, cospaXY_kf, cospaRZ_kf, + pca_kf, alpha, qt, chi2kf); - 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)); + // 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, pTrack, kfp_pos_DecayVtx, posdcaXY, posdcaZ); // positive leg first + fillTrackTable(ele, nTrack, kfp_ele_DecayVtx, eledcaXY, eledcaZ); // negative leg second } // end of fill table } @@ -795,7 +811,7 @@ struct PhotonConversionBuilder { continue; } } - events_ngpcm(nv0_map[collision.globalIndex()]); + // events_ngpcm(nv0_map[collision.globalIndex()]); } // end of collision loop pca_map.clear(); diff --git a/PWGEM/PhotonMeson/TableProducer/produceMesonCalo.cxx b/PWGEM/PhotonMeson/TableProducer/produceMesonCalo.cxx deleted file mode 100644 index 7fd19416d3d..00000000000 --- a/PWGEM/PhotonMeson/TableProducer/produceMesonCalo.cxx +++ /dev/null @@ -1,151 +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 perform calo photon analysis on calo photons from skimmergammacalo task -/// dependencies: skimmergammacalo -/// \author marvin.hemmer@cern.ch - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/DataModel/mesonTables.h" - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -// includes for the R recalculation -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/GeometryManager.h" -#include "CCDB/BasicCCDBManager.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -struct produceMesonCalo { - - Produces tableCaloMeson; - - HistogramRegistry spectra = { - "spectra", - {}, - OutputObjHandlingPolicy::AnalysisObject, - true, - true}; - - // Configurable for histograms - Configurable nBinsMinv{"nBinsMinv", 800, "N bins for minv axis"}; - Configurable minMinv{"minMinv", 0.0, "Minimum value for minv axis"}; - Configurable maxMinv{"maxMinv", 0.8, "Maximum value for minv axis"}; - Configurable nBinsPt{"nBinsPt", 180, "N bins for pT axis"}; - Configurable minPt{"minPt", 0., "Minimum value for pT axis"}; - Configurable maxPt{"maxPt", 60., "Maximum value for pT axis"}; - - void init(o2::framework::InitContext&) - { - std::vector ptBinning(nBinsPt, 0); - - for (int i = 0; i < nBinsPt; i++) { - if (i < 100) { - ptBinning.at(i) = 0.10 * i; - } else if (i < 140) { - ptBinning.at(i) = 10. + 0.25 * (i - 100); - } else if (i < 180) { - ptBinning.at(i) = 20. + 1.00 * (i - 140); - } else { - ptBinning.at(i) = maxPt; - } - } - - AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec minvAxis = {nBinsMinv, minMinv, maxMinv, - "#it{m}_{inv} (GeV/#it{c}^{2})"}; - AxisSpec etaAxis = {100, -0.8, 0.8, "#eta"}; - AxisSpec phiAxis = {360, 0, 2 * M_PI, "#varphi (rad)"}; - AxisSpec alphaAxis = {200, -1, +1, "#alpha"}; - AxisSpec oaAxis = {180, 0, M_PI, "#vartheta_{#gamma#gamma} (rad)"}; - - HistogramConfigSpec defaultPtMinvHist( - {HistType::kTH2F, {minvAxis, ptAxis}}); - - HistogramConfigSpec defaultEtaPhiHist( - {HistType::kTH2F, {etaAxis, phiAxis}}); - - HistogramConfigSpec defaultPtMotherPtGammaHist( - {HistType::kTH2F, {ptAxis, ptAxis}}); - - HistogramConfigSpec defaultPtAlpha( - {HistType::kTH2F, {ptAxis, alphaAxis}}); - - HistogramConfigSpec defaultPtOA( - {HistType::kTH2F, {ptAxis, oaAxis}}); - - spectra.add("SameEvent_Minv_Pt", "SameEvent_Minv_Pt", defaultPtMinvHist, true); - spectra.add("SameEvent_Eta_Phi", "SameEvent_Eta_Phi", defaultEtaPhiHist, true); - spectra.add("SameEvent_Pt_Alpha", "SameEvent_Pt_Alpha", defaultPtAlpha, true); - spectra.add("SameEvent_Pt_OA", "SameEvent_Pt_OA", defaultPtOA, true); - spectra.add("SameEvent_PtMother_PtGamma", "SameEvent_PtMother_PtGamma", defaultPtMotherPtGammaHist, true); - - spectra.add("Photon_Eta_Phi", "Photon_Eta_Phi", defaultEtaPhiHist, true); - } - - void - processRec(aod::Collision const&, - aod::SkimGammas const& skimgammas) - { - for (auto& [gamma0, gamma1] : // EMC-EMC - combinations(o2::soa::CombinationsStrictlyUpperIndexPolicy(skimgammas, - skimgammas))) { - float openingAngle = acos((cos(gamma0.phi() - gamma1.phi()) + - sinh(gamma0.eta()) * sinh(gamma1.eta())) / - (cosh(gamma0.eta()) * cosh(gamma1.eta()))); - float E = gamma0.e() + gamma1.e(); - float pt0 = gamma0.e() / cosh(gamma0.eta()); - float pt1 = gamma1.e() / cosh(gamma1.eta()); - float px = - pt0 * cos(gamma0.phi()) + pt1 * cos(gamma1.phi()); - float py = - pt0 * sin(gamma0.phi()) + pt1 * sin(gamma1.phi()); - float pz = - pt0 * sinh(gamma0.eta()) + pt1 * sinh(gamma1.eta()); - float alpha = (gamma0.e() - gamma1.e()) != 0. - ? (gamma0.e() - gamma1.e()) / (gamma0.e() + gamma1.e()) - : 0.; - float Pt = sqrt(pt0 * pt0 + pt1 * pt1 + - 2. * pt0 * pt1 * - cos(gamma0.phi() - gamma1.phi())); - float minv = - sqrt(2. * gamma0.e() * gamma1.e() * (1. - cos(openingAngle))); - float eta = asinh(pz / Pt); - float phi = atan2(py, px); - phi = (phi < 0) ? phi + 2. * M_PI : phi; - tableCaloMeson(gamma0.collisionId(), gamma0.globalIndex(), gamma1.globalIndex(), - openingAngle, px, py, pz, E, alpha, minv, eta, phi, - Pt); - spectra.get(HIST("SameEvent_Minv_Pt"))->Fill(minv, Pt); - spectra.get(HIST("SameEvent_Eta_Phi"))->Fill(eta, phi); - spectra.get(HIST("SameEvent_Pt_Alpha"))->Fill(Pt, alpha); - spectra.get(HIST("SameEvent_Pt_OA"))->Fill(Pt, openingAngle); - spectra.get(HIST("SameEvent_PtMother_PtGamma"))->Fill(Pt, pt0); - spectra.get(HIST("SameEvent_PtMother_PtGamma"))->Fill(Pt, pt1); - - spectra.get(HIST("Photon_Eta_Phi"))->Fill(gamma0.eta(), gamma0.phi()); - spectra.get(HIST("Photon_Eta_Phi"))->Fill(gamma1.eta(), gamma1.phi()); - } - } - PROCESS_SWITCH(produceMesonCalo, processRec, - "process only reconstructed info", true); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; - return workflow; -} diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx index da85ef3c8b4..0de9fee8f62 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaCalo.cxx @@ -9,40 +9,48 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file skimmerGammaCalo.cxx /// \brief skim cluster information to write photon cluster table in AO2D.root /// dependencies: emcal-correction-task /// \author marvin.hemmer@cern.ch -#include -#include +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" +#include "PWGJE/DataModel/EMCALClusters.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TableHelper.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -// includes for the R recalculation -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "CCDB/BasicCCDBManager.h" +#include -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -struct skimmerGammaCalo { +struct SkimmerGammaCalo { - Preslice CellperCluster = o2::aod::emcalclustercell::emcalclusterId; - Preslice MTperCluster = o2::aod::emcalclustercell::emcalclusterId; + Preslice psCellperCluster = o2::aod::emcalclustercell::emcalclusterId; + Preslice psMTperCluster = o2::aod::emcalclustercell::emcalclusterId; Produces tableGammaEMCReco; Produces tableEMCClusterMCLabels; Produces tableCellEMCReco; - Produces tableTrackEMCReco; // Configurable for filter/cuts Configurable minTime{"minTime", -200., "Minimum cluster time for time cut"}; @@ -53,6 +61,7 @@ struct skimmerGammaCalo { Configurable> clusterDefinitions{"clusterDefinitions", {0, 1, 2, 10, 11, 12, 13, 20, 21, 22, 30, 40, 41, 42, 43, 44, 45}, "Cluster definitions to be accepted (e.g. 13 for kV3MostSplitLowSeed)"}; Configurable maxdEta{"maxdEta", 0.1, "Set a maximum difference in eta for tracks and cluster to still count as matched"}; Configurable maxdPhi{"maxdPhi", 0.1, "Set a maximum difference in phi for tracks and cluster to still count as matched"}; + Configurable needEMCTrigger{"needEMCTrigger", false, "flag to only save events which have kTVXinEMC trigger bit. To reduce PbPb derived data size"}; HistogramRegistry historeg{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; @@ -86,6 +95,9 @@ struct skimmerGammaCalo { if (!collision.isSelected()) { return; } + if (needEMCTrigger.value && !collision.alias_bit(kTVXinEMC)) { + return; + } for (const auto& emccluster : emcclusters) { historeg.fill(HIST("hCaloClusterFilter"), 0); @@ -124,7 +136,7 @@ struct skimmerGammaCalo { historeg.fill(HIST("TimeOut"), emccluster.time()); // Skimmed cell table - auto groupedCells = emcclustercells.sliceBy(CellperCluster, emccluster.globalIndex()); + auto groupedCells = emcclustercells.sliceBy(psCellperCluster, emccluster.globalIndex()); for (const auto& emcclustercell : groupedCells) { tableCellEMCReco(emcclustercell.emcalclusterId(), emcclustercell.caloId()); } @@ -135,28 +147,26 @@ struct skimmerGammaCalo { std::vector vPhi; std::vector vP; std::vector vPt; - auto groupedMTs = emcmatchedtracks.sliceBy(MTperCluster, emccluster.globalIndex()); + auto groupedMTs = emcmatchedtracks.sliceBy(psMTperCluster, emccluster.globalIndex()); vTrackIds.reserve(groupedMTs.size()); vEta.reserve(groupedMTs.size()); vPhi.reserve(groupedMTs.size()); vP.reserve(groupedMTs.size()); vPt.reserve(groupedMTs.size()); for (const auto& emcmatchedtrack : groupedMTs) { - if (std::abs(emccluster.eta() - emcmatchedtrack.track_as().trackEtaEmcal()) >= maxdEta || std::abs(emccluster.phi() - emcmatchedtrack.track_as().trackPhiEmcal()) >= maxdPhi) { + if (std::abs(emcmatchedtrack.deltaEta()) >= maxdEta || std::abs(emcmatchedtrack.deltaPhi()) >= maxdPhi) { continue; } historeg.fill(HIST("MTEtaPhi"), emccluster.eta() - emcmatchedtrack.track_as().trackEtaEmcal(), emccluster.phi() - emcmatchedtrack.track_as().trackPhiEmcal()); vTrackIds.emplace_back(emcmatchedtrack.trackId()); - vEta.emplace_back(emcmatchedtrack.track_as().trackEtaEmcal()); - vPhi.emplace_back(emcmatchedtrack.track_as().trackPhiEmcal()); + vEta.emplace_back(emcmatchedtrack.deltaEta()); + vPhi.emplace_back(emcmatchedtrack.deltaPhi()); vP.emplace_back(emcmatchedtrack.track_as().p()); vPt.emplace_back(emcmatchedtrack.track_as().pt()); - tableTrackEMCReco(emcmatchedtrack.emcalclusterId(), emcmatchedtrack.track_as().trackEtaEmcal(), emcmatchedtrack.track_as().trackPhiEmcal(), - emcmatchedtrack.track_as().p(), emcmatchedtrack.track_as().pt()); } tableGammaEMCReco(emccluster.collisionId(), emccluster.definition(), emccluster.energy(), emccluster.eta(), emccluster.phi(), emccluster.m02(), - emccluster.nCells(), emccluster.time(), emccluster.isExotic(), vEta, vPhi, vP, vPt); + emccluster.nCells(), emccluster.time(), emccluster.isExotic(), vPhi, vEta, vP, vPt); } } void processMC(soa::Join::iterator const& collision, soa::Join const& emcclusters, aod::McParticles const&) @@ -195,18 +205,18 @@ struct skimmerGammaCalo { mcLabels.clear(); } } - PROCESS_SWITCH(skimmerGammaCalo, processRec, "process only reconstructed info", true); - PROCESS_SWITCH(skimmerGammaCalo, processMC, "process MC info", false); // Run this in addition to processRec for MCs to copy the cluster mc labels from the EMCALMCClusters to the skimmed EMCClusterMCLabels table + PROCESS_SWITCH(SkimmerGammaCalo, processRec, "process only reconstructed info", true); + PROCESS_SWITCH(SkimmerGammaCalo, processMC, "process MC info", false); // Run this in addition to processRec for MCs to copy the cluster mc labels from the EMCALMCClusters to the skimmed EMCClusterMCLabels table void processDummy(aod::Collision const&) { // do nothing } - PROCESS_SWITCH(skimmerGammaCalo, processDummy, "Dummy function", false); + PROCESS_SWITCH(SkimmerGammaCalo, processDummy, "Dummy function", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - WorkflowSpec workflow{adaptAnalysisTask(cfgc, TaskName{"skimmer-gamma-calo"})}; + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; return workflow; } diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx index 6a39aea8881..fa843d22f54 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerGammaConversion.cxx @@ -23,38 +23,37 @@ // 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 #include // todo: remove reduantant information in GammaConversionsInfoTrue #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h" #include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include "PWGEM/PhotonMeson/Utils/gammaConvDefinitions.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" // includes for the R recalculation -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" +#include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/HelixHelper.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" #include "ReconstructionDataFormats/TrackFwd.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" +#include "Math/Vector4D.h" #include #include -#include "Math/Vector4D.h" - -#include "Tools/KFparticle/KFUtilities.h" using namespace o2; using namespace o2::framework; @@ -189,8 +188,7 @@ struct skimmerGammaConversion { theTrack.tpcNClsFindable(), theTrack.tpcNClsFindableMinusFound(), theTrack.tpcNClsFindableMinusCrossedRows(), theTrack.tpcNClsShared(), theTrack.tpcChi2NCl(), theTrack.tpcInnerParam(), theTrack.tpcSignal(), theTrack.tpcNSigmaEl(), theTrack.tpcNSigmaPi(), - theTrack.itsClusterSizes(), theTrack.itsChi2NCl(), theTrack.detectorMap(), - theTrack.x(), theTrack.y(), theTrack.z(), theTrack.tgl()); + theTrack.itsClusterSizes(), theTrack.itsChi2NCl(), theTrack.detectorMap()); } template diff --git a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx index 7f840cb179c..435e9451a83 100644 --- a/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx +++ b/PWGEM/PhotonMeson/TableProducer/skimmerPrimaryElectronFromDalitzEE.cxx @@ -12,25 +12,28 @@ /// \brief write relevant information about primary electrons. /// \author daiki.sekihata@cern.ch -#include -#include -#include -#include +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/Core/trackUtilities.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/TrackSelection.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.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 using namespace o2; using namespace o2::soa; @@ -39,17 +42,21 @@ using namespace o2::framework::expressions; using namespace o2::constants::physics; using namespace o2::pwgem::photonmeson; -using MyCollisions = soa::Join; +using MyCollisions = soa::Join; +using MyCollisionsWithSWT = soa::Join; + using MyCollisionsMC = soa::Join; using MyTracks = soa::Join; using MyTrack = MyTracks::iterator; -using MyTracksMC = soa::Join; +using MyTracksMC = soa::Join; using MyTrackMC = MyTracksMC::iterator; struct skimmerPrimaryElectronFromDalitzEE { SliceCache cache; Preslice perCol = o2::aod::track::collisionId; + Preslice perCol_pcm = o2::aod::v0photonkf::collisionId; Produces emprimaryelectrons; + Produces emprimaryelectronsDeDxMC; // Configurables Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; @@ -66,8 +73,8 @@ struct skimmerPrimaryElectronFromDalitzEE { Configurable min_ncluster_its{"min_ncluster_its", 4, "min ncluster its"}; Configurable min_ncluster_itsib{"min_ncluster_itsib", 1, "min ncluster itsib"}; Configurable maxchi2tpc{"maxchi2tpc", 5.0, "max. chi2/NclsTPC"}; - Configurable maxchi2its{"maxchi2its", 6.0, "max. chi2/NclsITS"}; - Configurable minpt{"minpt", 0.05, "min pt for track"}; + Configurable maxchi2its{"maxchi2its", 36.0, "max. chi2/NclsITS"}; + Configurable minpt{"minpt", 0.05, "min pt for ITS-TPC track"}; Configurable maxeta{"maxeta", 2.0, "max eta acceptance"}; Configurable dca_xy_max{"dca_xy_max", 1, "max DCAxy in cm"}; Configurable dca_z_max{"dca_z_max", 1, "max DCAz in cm"}; @@ -80,6 +87,11 @@ struct skimmerPrimaryElectronFromDalitzEE { Configurable maxTOFNsigmaEl{"maxTOFNsigmaEl", +3.5, "max. TOF n sigma for electron inclusion"}; Configurable maxMee{"maxMee", 0.04, "max. mee to store dalitz ee pairs"}; Configurable fillLS{"fillLS", true, "flag to fill LS histograms for QA"}; + 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 slope{"slope", 0.0185, "slope for m vs. phiv"}; + Configurable intercept{"intercept", -0.0380, "intercept for m vs. phiv"}; HistogramRegistry fRegistry{"output", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; static constexpr std::string_view dileptonSigns[3] = {"uls/", "lspp/", "lsmm/"}; @@ -91,6 +103,10 @@ struct skimmerPrimaryElectronFromDalitzEE { void init(InitContext&) { + if (doprocessRec && doprocessRec_SWT) { + LOGF(fatal, "Cannot enable doprocessRec and doprocessRec_SWT at the same time. Please choose one."); + } + mRunNumber = 0; d_bz = 0; @@ -102,7 +118,7 @@ struct skimmerPrimaryElectronFromDalitzEE { 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, {{180, 0, 2 * M_PI}, {400, -2.0f, 2.0f}}, false); fRegistry.add("Track/hQoverPt", "q/pT;q/p_{T} (GeV/c)^{-1}", kTH1F, {{400, -20, 20}}, false); - fRegistry.add("Track/hRelDeltaPt", "pT resolution;p_{T} (GeV/c);#Deltap_{T}/p_{T}", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); + fRegistry.add("Track/hRelDeltaPt", "pT resolution;p_{T} (GeV/c);#Deltap_{T}/p_{T}", kTH2F, {{1000, 0, 10}, {100, 0, 0.1}}, false); fRegistry.add("Track/hDCAxyz", "DCA xy vs. z;DCA_{xy} (cm);DCA_{z} (cm)", kTH2F, {{200, -1.0f, 1.0f}, {200, -1.0f, 1.0f}}, false); fRegistry.add("Track/hDCAxy_Pt", "DCA_{xy} vs. pT;p_{T} (GeV/c);DCA_{xy} (cm)", kTH2F, {{200, 0, 10}, {200, -1, 1}}, false); fRegistry.add("Track/hDCAz_Pt", "DCA_{z} vs. pT;p_{T} (GeV/c);DCA_{z} (cm)", kTH2F, {{200, 0, 10}, {200, -1, 1}}, false); @@ -118,14 +134,17 @@ struct skimmerPrimaryElectronFromDalitzEE { fRegistry.add("Track/hTPCNcls2Nf", "TPC Ncls/Nfindable", kTH1F, {{200, 0, 2}}, false); fRegistry.add("Track/hTPCNclsShared", "TPC Ncls shared/Ncls;p_{T} (GeV/c);N_{cls}^{shared}/N_{cls} in TPC", kTH2F, {{1000, 0, 10}, {100, 0, 1}}, false); fRegistry.add("Track/hTPCdEdx", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); + fRegistry.add("Track/hTPCdEdxMC", "TPC dE/dx;p_{in} (GeV/c);TPC dE/dx (a.u.)", kTH2F, {{1000, 0, 10}, {200, 0, 200}}, false); fRegistry.add("Track/hTPCNsigmaEl", "TPC n sigma el;p_{in} (GeV/c);n #sigma_{e}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/hTPCNsigmaPi", "TPC n sigma pi;p_{in} (GeV/c);n #sigma_{#pi}^{TPC}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); // ITS fRegistry.add("Track/hNclsITS", "number of ITS clusters", kTH1F, {{8, -0.5, 7.5}}, false); - fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); + fRegistry.add("Track/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{400, 0, 40}}, false); fRegistry.add("Track/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); - fRegistry.add("Track/hMeanClusterSizeITS", "mean cluster size ITS;p_{pv} (GeV/c); on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {150, 0, 15}}, 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); // TOF fRegistry.add("Track/hChi2TOF", "chi2 of TOF", kTH1F, {{100, 0, 10}}, false); @@ -190,17 +209,14 @@ struct skimmerPrimaryElectronFromDalitzEE { } } - if (track.tpcChi2NCl() > maxchi2tpc) { + if (!track.hasITS()) { return false; } - if (track.itsChi2NCl() > maxchi2its) { + if (track.itsChi2NCl() < 0.f || maxchi2its < track.itsChi2NCl()) { return false; } - if (!track.hasITS() || !track.hasTPC()) { - return false; - } if (track.itsNCls() < min_ncluster_its) { return false; } @@ -208,20 +224,30 @@ struct skimmerPrimaryElectronFromDalitzEE { return false; } - if (track.tpcNClsFound() < min_ncluster_tpc) { + if (!includeITSsa && (!track.hasITS() || !track.hasTPC())) { return false; } - if (track.tpcNClsCrossedRows() < mincrossedrows) { - return false; - } + if (track.hasTPC()) { + if (track.tpcChi2NCl() < 0.f || maxchi2tpc < track.tpcChi2NCl()) { + return false; + } - if (track.tpcCrossedRowsOverFindableCls() < min_tpc_cr_findable_ratio) { - return false; - } + if (track.tpcNClsFound() < min_ncluster_tpc) { + return false; + } - if (track.tpcFractionSharedCls() > max_frac_shared_clusters_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 (std::fabs(track.dcaXY()) > dca_xy_max || std::fabs(track.dcaZ()) > dca_z_max) { @@ -240,7 +266,13 @@ struct skimmerPrimaryElectronFromDalitzEE { return false; } - if (track.pt() < minpt || std::fabs(track.eta()) > maxeta) { + if (std::fabs(track.eta()) > maxeta) { + return false; + } + if ((track.hasITS() && track.hasTPC()) && track.pt() < minpt) { + return false; + } + if ((track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF()) && maxpt_itssa < track.pt()) { return false; } @@ -250,6 +282,23 @@ struct skimmerPrimaryElectronFromDalitzEE { template bool isElectron(TTrack const& track) { + if (includeITSsa && (track.hasITS() && !track.hasTPC() && !track.hasTRD() && !track.hasTOF())) { + 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 (maxMeanITSClusterSize > static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))) { + return true; + } else { + return false; + } + } + if (track.tpcNSigmaEl() < minTPCNsigmaEl || maxTPCNsigmaEl < track.tpcNSigmaEl()) { return false; } @@ -262,56 +311,90 @@ struct skimmerPrimaryElectronFromDalitzEE { return true; } - template + template void fillTrackTable(TCollision const& collision, TTrack const& track) { - if (std::find(stored_trackIds.begin(), stored_trackIds.end(), std::make_pair(collision.globalIndex(), track.globalIndex())) == stored_trackIds.end()) { - emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), - track.pt(), track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), track.cYY(), track.cZY(), track.cZZ(), - track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), - track.tpcChi2NCl(), track.tpcInnerParam(), - track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), - track.beta(), track.tofNSigmaEl(), track.tofNSigmaPi(), - track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap(), track.tgl()); - - fRegistry.fill(HIST("Track/hPt"), track.pt()); - fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); - fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); - fRegistry.fill(HIST("Track/hRelDeltaPt"), track.pt(), track.sigma1Pt() * track.pt()); - fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); - fRegistry.fill(HIST("Track/hDCAxy_Pt"), track.pt(), track.dcaXY()); - fRegistry.fill(HIST("Track/hDCAz_Pt"), track.pt(), track.dcaZ()); - fRegistry.fill(HIST("Track/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); - fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um - fRegistry.fill(HIST("Track/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um - - fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); - fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); - fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); - 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/hTPCdEdx"), track.tpcInnerParam(), track.tpcSignal()); - fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); - fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); - - fRegistry.fill(HIST("Track/hChi2TOF"), track.tofChi2()); - fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); - fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); - - fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); - fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); - fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); - - int nsize = 0; - for (int il = 0; il < 7; il++) { - nsize += track.itsClsSizeInLayer(il); + emprimaryelectrons(collision.globalIndex(), track.globalIndex(), track.sign(), + track.pt(), track.eta(), track.phi(), track.dcaXY(), track.dcaZ(), track.cYY(), track.cZY(), track.cZZ(), + track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), track.tpcNClsFindableMinusCrossedRows(), track.tpcNClsShared(), + track.tpcChi2NCl(), track.tpcInnerParam(), + track.tpcSignal(), track.tpcNSigmaEl(), track.tpcNSigmaPi(), + track.beta(), track.tofNSigmaEl(), + track.itsClusterSizes(), track.itsChi2NCl(), track.tofChi2(), track.detectorMap()); + + if constexpr (isMC) { + emprimaryelectronsDeDxMC(track.mcTunedTPCSignal()); + } + } + + template + void fillTrackHistograms(TTrack const& track) + { + float mcTunedTPCSignal = 0.f; + if constexpr (isMC) { + mcTunedTPCSignal = track.mcTunedTPCSignal(); + } + + fRegistry.fill(HIST("Track/hPt"), track.pt()); + fRegistry.fill(HIST("Track/hEtaPhi"), track.phi(), track.eta()); + fRegistry.fill(HIST("Track/hQoverPt"), track.sign() / track.pt()); + fRegistry.fill(HIST("Track/hRelDeltaPt"), track.pt(), track.sigma1Pt() * track.pt()); + fRegistry.fill(HIST("Track/hDCAxyz"), track.dcaXY(), track.dcaZ()); + fRegistry.fill(HIST("Track/hDCAxy_Pt"), track.pt(), track.dcaXY()); + fRegistry.fill(HIST("Track/hDCAz_Pt"), track.pt(), track.dcaZ()); + fRegistry.fill(HIST("Track/hDCAxyzSigma"), track.dcaXY() / std::sqrt(track.cYY()), track.dcaZ() / std::sqrt(track.cZZ())); + fRegistry.fill(HIST("Track/hDCAxyRes_Pt"), track.pt(), std::sqrt(track.cYY()) * 1e+4); // convert cm to um + fRegistry.fill(HIST("Track/hDCAzRes_Pt"), track.pt(), std::sqrt(track.cZZ()) * 1e+4); // convert cm to um + + fRegistry.fill(HIST("Track/hNclsTPC"), track.tpcNClsFound()); + fRegistry.fill(HIST("Track/hNcrTPC"), track.tpcNClsCrossedRows()); + fRegistry.fill(HIST("Track/hChi2TPC"), track.tpcChi2NCl()); + 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/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/hChi2TOF"), track.tofChi2()); + fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); + fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); + fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); + + fRegistry.fill(HIST("Track/hNclsITS"), track.itsNCls()); + fRegistry.fill(HIST("Track/hChi2ITS"), track.itsChi2NCl()); + fRegistry.fill(HIST("Track/hITSClusterMap"), track.itsClusterMap()); + + 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++; } - fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(nsize) / static_cast(track.itsNCls()) * std::cos(std::atan(track.tgl()))); + total_cluster_size_ib += cluster_size_per_layer; + } - stored_trackIds.emplace_back(std::make_pair(collision.globalIndex(), track.globalIndex())); + 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; } + fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), static_cast(total_cluster_size) / static_cast(nl) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSib"), track.p(), static_cast(total_cluster_size_ib) / static_cast(nl_ib) * std::cos(std::atan(track.tgl()))); + fRegistry.fill(HIST("Track/hMeanClusterSizeITSob"), track.p(), static_cast(total_cluster_size_ob) / static_cast(nl_ob) * std::cos(std::atan(track.tgl()))); } template @@ -336,9 +419,35 @@ struct skimmerPrimaryElectronFromDalitzEE { if (v12.M() > maxMee) { // don't store continue; } - fillTrackTable(collision, t1); - fillTrackTable(collision, t2); - } // end of pairing + + if (v12.M() < slope * phiv + intercept) { + continue; + } + + if (t1.sign() > 0) { // for positron + if (std::find(acceptedPosTrackIds_per_collision.begin(), acceptedPosTrackIds_per_collision.end(), t1.globalIndex()) == acceptedPosTrackIds_per_collision.end()) { + fillTrackHistograms(t1); + acceptedPosTrackIds_per_collision.emplace_back(t1.globalIndex()); + } + } else { // for electron + if (std::find(acceptedNegTrackIds_per_collision.begin(), acceptedNegTrackIds_per_collision.end(), t1.globalIndex()) == acceptedNegTrackIds_per_collision.end()) { + fillTrackHistograms(t1); + acceptedNegTrackIds_per_collision.emplace_back(t1.globalIndex()); + } + } + + if (t2.sign() > 0) { // for positron + if (std::find(acceptedPosTrackIds_per_collision.begin(), acceptedPosTrackIds_per_collision.end(), t2.globalIndex()) == acceptedPosTrackIds_per_collision.end()) { + fillTrackHistograms(t2); + acceptedPosTrackIds_per_collision.emplace_back(t2.globalIndex()); + } + } else { // for electron + if (std::find(acceptedNegTrackIds_per_collision.begin(), acceptedNegTrackIds_per_collision.end(), t2.globalIndex()) == acceptedNegTrackIds_per_collision.end()) { + fillTrackHistograms(t2); + acceptedNegTrackIds_per_collision.emplace_back(t2.globalIndex()); + } + } + } // end of ULS pairing } else { // LS for (auto& [t1, t2] : combinations(CombinationsStrictlyUpperIndexPolicy(tracks1, tracks2))) { if (!checkTrack(collision, t1) || !checkTrack(collision, t2)) { @@ -354,19 +463,20 @@ struct skimmerPrimaryElectronFromDalitzEE { 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); fRegistry.fill(HIST("Pair/") + HIST(dileptonSigns[pairtype]) + HIST("hMvsPt"), v12.M(), v12.Pt()); fRegistry.fill(HIST("Pair/") + HIST(dileptonSigns[pairtype]) + HIST("hMvsPhiV"), phiv, v12.M()); - } // end of pairing + } // end of LS pairing } } - std::vector> stored_trackIds; - Filter trackFilter = o2::aod::track::pt > minpt&& nabs(o2::aod::track::eta) < maxeta&& o2::aod::track::tpcChi2NCl < maxchi2tpc&& o2::aod::track::itsChi2NCl < maxchi2its&& ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::TPC) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max&& nabs(o2::aod::track::dcaZ) < dca_z_max; - Filter pidFilter = minTPCNsigmaEl < o2::aod::pidtpc::tpcNSigmaEl && o2::aod::pidtpc::tpcNSigmaEl < maxTPCNsigmaEl; + std::vector acceptedPosTrackIds_per_collision; + std::vector acceptedNegTrackIds_per_collision; + std::vector> stored_trackIds; + Filter trackFilter = minpt < o2::aod::track::pt && nabs(o2::aod::track::eta) < maxeta && o2::aod::track::itsChi2NCl < maxchi2its && ncheckbit(aod::track::v001::detectorMap, (uint8_t)o2::aod::track::ITS) == true && nabs(o2::aod::track::dcaXY) < dca_xy_max && nabs(o2::aod::track::dcaZ) < dca_z_max; using MyFilteredTracks = soa::Filtered; Partition posTracks = o2::aod::track::signed1Pt > 0.f; Partition negTracks = o2::aod::track::signed1Pt < 0.f; // ---------- for data ---------- - void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks) + void processRec(MyCollisions const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks, aod::V0PhotonsKF const& v0photons) { stored_trackIds.reserve(tracks.size()); @@ -377,55 +487,136 @@ struct skimmerPrimaryElectronFromDalitzEE { continue; } - if (collision.ngpcm() < 1) { + const auto& v0photons_per_coll = v0photons.sliceBy(perCol_pcm, collision.globalIndex()); + 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); + acceptedPosTrackIds_per_collision.reserve(posTracks_per_coll.size()); + acceptedNegTrackIds_per_collision.reserve(negTracks_per_coll.size()); + + fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS + if (fillLS) { + fillPairInfo(collision, posTracks_per_coll, posTracks_per_coll); // LS++ + fillPairInfo(collision, negTracks_per_coll, negTracks_per_coll); // LS-- + } + + if ((v0photons_per_coll.size() >= 1 && acceptedPosTrackIds_per_collision.size() >= 1 && acceptedNegTrackIds_per_collision.size() >= 1) || (acceptedPosTrackIds_per_collision.size() >= 2 && acceptedNegTrackIds_per_collision.size() >= 2)) { + // LOGF(info, "v0photons_per_coll.size() = %d, acceptedPosTrackIds_per_collision.size() = %d, acceptedNegTrackIds_per_collision.size() = %d", v0photons_per_coll.size(), acceptedPosTrackIds_per_collision.size(), acceptedNegTrackIds_per_collision.size()); + for (const auto& posId : acceptedPosTrackIds_per_collision) { + const auto& pos = tracks.rawIteratorAt(posId); + fillTrackTable(collision, pos); + } + for (const auto& eleId : acceptedNegTrackIds_per_collision) { + const auto& ele = tracks.rawIteratorAt(eleId); + fillTrackTable(collision, ele); + } + } + + acceptedPosTrackIds_per_collision.clear(); + acceptedPosTrackIds_per_collision.shrink_to_fit(); + acceptedNegTrackIds_per_collision.clear(); + acceptedNegTrackIds_per_collision.shrink_to_fit(); + } // end of collision loop + + stored_trackIds.clear(); + stored_trackIds.shrink_to_fit(); + } + PROCESS_SWITCH(skimmerPrimaryElectronFromDalitzEE, processRec, "process reconstructed info only", true); // standalone + + void processRec_SWT(MyCollisionsWithSWT const& collisions, aod::BCsWithTimestamps const&, MyFilteredTracks const& tracks, aod::V0PhotonsKF const& v0photons) + { + stored_trackIds.reserve(tracks.size()); + + for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); + if (!collision.isSelected()) { continue; } - auto posTracks_per_coll = posTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracks->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + if (collision.swtaliastmp_raw() == 0) { + continue; + } + + const auto& v0photons_per_coll = v0photons.sliceBy(perCol_pcm, collision.globalIndex()); + 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); + acceptedPosTrackIds_per_collision.reserve(posTracks_per_coll.size()); + acceptedNegTrackIds_per_collision.reserve(negTracks_per_coll.size()); fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS if (fillLS) { fillPairInfo(collision, posTracks_per_coll, posTracks_per_coll); // LS++ fillPairInfo(collision, negTracks_per_coll, negTracks_per_coll); // LS-- } + + if ((v0photons_per_coll.size() >= 1 && acceptedPosTrackIds_per_collision.size() >= 1 && acceptedNegTrackIds_per_collision.size() >= 1) || (acceptedPosTrackIds_per_collision.size() >= 2 && acceptedNegTrackIds_per_collision.size() >= 2)) { + // LOGF(info, "v0photons_per_coll.size() = %d, acceptedPosTrackIds_per_collision.size() = %d, acceptedNegTrackIds_per_collision.size() = %d", v0photons_per_coll.size(), acceptedPosTrackIds_per_collision.size(), acceptedNegTrackIds_per_collision.size()); + for (const auto& posId : acceptedPosTrackIds_per_collision) { + const auto& pos = tracks.rawIteratorAt(posId); + fillTrackTable(collision, pos); + } + for (const auto& eleId : acceptedNegTrackIds_per_collision) { + const auto& ele = tracks.rawIteratorAt(eleId); + fillTrackTable(collision, ele); + } + } + + acceptedPosTrackIds_per_collision.clear(); + acceptedPosTrackIds_per_collision.shrink_to_fit(); + acceptedNegTrackIds_per_collision.clear(); + acceptedNegTrackIds_per_collision.shrink_to_fit(); } // end of collision loop stored_trackIds.clear(); stored_trackIds.shrink_to_fit(); } - PROCESS_SWITCH(skimmerPrimaryElectronFromDalitzEE, processRec, "process reconstructed info only", true); // standalone + PROCESS_SWITCH(skimmerPrimaryElectronFromDalitzEE, processRec_SWT, "process reconstructed info with CEFP", false); // with cefp using MyFilteredTracksMC = soa::Filtered; Partition posTracksMC = o2::aod::track::signed1Pt > 0.f; Partition negTracksMC = o2::aod::track::signed1Pt < 0.f; // ---------- for MC ---------- - void processMC(MyCollisionsMC const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks) + void processMC(MyCollisionsMC const& collisions, aod::McCollisions const&, aod::BCsWithTimestamps const&, MyFilteredTracksMC const& tracks, aod::V0PhotonsKF const& v0photons) { stored_trackIds.reserve(tracks.size()); for (const auto& collision : collisions) { + auto bc = collision.template foundBC_as(); + initCCDB(bc); if (!collision.has_mcCollision()) { continue; } if (!collision.isSelected()) { continue; } - auto bc = collision.template foundBC_as(); - initCCDB(bc); - - if (collision.ngpcm() < 1) { - continue; - } - auto posTracks_per_coll = posTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); - auto negTracks_per_coll = negTracksMC->sliceByCached(o2::aod::track::collisionId, collision.globalIndex(), cache); + const auto& v0photons_per_coll = v0photons.sliceBy(perCol_pcm, collision.globalIndex()); + 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); + acceptedPosTrackIds_per_collision.reserve(posTracks_per_coll.size()); + acceptedNegTrackIds_per_collision.reserve(negTracks_per_coll.size()); fillPairInfo(collision, posTracks_per_coll, negTracks_per_coll); // ULS if (fillLS) { fillPairInfo(collision, posTracks_per_coll, posTracks_per_coll); // LS++ fillPairInfo(collision, negTracks_per_coll, negTracks_per_coll); // LS-- } + if ((v0photons_per_coll.size() >= 1 && acceptedPosTrackIds_per_collision.size() >= 1 && acceptedNegTrackIds_per_collision.size() >= 1) || (acceptedPosTrackIds_per_collision.size() >= 2 && acceptedNegTrackIds_per_collision.size() >= 2)) { + // LOGF(info, "v0photons_per_coll.size() = %d, acceptedPosTrackIds_per_collision.size() = %d, acceptedNegTrackIds_per_collision.size() = %d", v0photons_per_coll.size(), acceptedPosTrackIds_per_collision.size(), acceptedNegTrackIds_per_collision.size()); + for (const auto& posId : acceptedPosTrackIds_per_collision) { + const auto& pos = tracks.rawIteratorAt(posId); + fillTrackTable(collision, pos); + } + for (const auto& eleId : acceptedNegTrackIds_per_collision) { + const auto& ele = tracks.rawIteratorAt(eleId); + fillTrackTable(collision, ele); + } + } + + acceptedPosTrackIds_per_collision.clear(); + acceptedPosTrackIds_per_collision.shrink_to_fit(); + acceptedNegTrackIds_per_collision.clear(); + acceptedNegTrackIds_per_collision.shrink_to_fit(); } // end of collision loop stored_trackIds.clear(); diff --git a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/CMakeLists.txt index 6483af43f4c..332cafc0795 100644 --- a/PWGEM/PhotonMeson/Tasks/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/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(gammaconversions SOURCES gammaConversions.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore @@ -24,8 +26,8 @@ o2physics_add_dpl_workflow(emc-pi0-qc PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(emc-bc-wise-pi0 - SOURCES emcalBcWisePi0.cxx +o2physics_add_dpl_workflow(emc-bc-wise-gammagamma + SOURCES emcalBcWiseGammaGamma.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -64,6 +66,11 @@ o2physics_add_dpl_workflow(heavy-neutral-meson PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(omega-meson-emc + SOURCES OmegaMesonEMC.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phos-qc SOURCES phosQC.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::DetectorsBase O2Physics::AnalysisCore O2Physics::PWGEMPhotonMesonCore @@ -149,3 +156,19 @@ 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) + diff --git a/ALICE3/Tools/CMakeLists.txt b/PWGEM/PhotonMeson/Tasks/Converters/CMakeLists.txt similarity index 60% rename from ALICE3/Tools/CMakeLists.txt rename to PWGEM/PhotonMeson/Tasks/Converters/CMakeLists.txt index 7aecd79362b..89aceb70f98 100644 --- a/ALICE3/Tools/CMakeLists.txt +++ b/PWGEM/PhotonMeson/Tasks/Converters/CMakeLists.txt @@ -9,7 +9,12 @@ # granted to it by virtue of its status as an Intergovernmental Organization # or submit itself to any jurisdiction. -o2physics_add_executable(pidparam-tof-reso-alice3 - SOURCES handleParamTOFResoALICE3.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::ALICE3Core - ) +o2physics_add_dpl_workflow(pcm-converter1 + SOURCES pcmConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(electron-from-dalitz-converter1 + SOURCES electronFromDalitzConverter1.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx b/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx new file mode 100644 index 00000000000..961f8b0dfe7 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/Converters/electronFromDalitzConverter1.cxx @@ -0,0 +1,69 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// This code runs loop over ULS ee pars for virtual photon QC. +// Please write to: daiki.sekihata@cern.ch + +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct electronFromDalitzConverter1 { + Produces electron_001; + + void process(aod::EMPrimaryElectronsFromDalitz_000 const& tracks) + { + for (const auto& track : tracks) { + electron_001(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.tpcNClsFindableMinusCrossedRows(), + track.tpcNClsShared(), + track.tpcChi2NCl(), + track.tpcInnerParam(), + track.tpcSignal(), + track.tpcNSigmaEl(), + track.tpcNSigmaPi(), + track.beta(), + track.tofNSigmaEl(), + track.itsClusterSizes(), + track.itsChi2NCl(), + track.tofChi2(), + track.detectorMap()); + + } // end of track loop + } // end of process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"electronFromDalitz-converter1"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx b/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx new file mode 100644 index 00000000000..1607c30b94a --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/Converters/pcmConverter1.cxx @@ -0,0 +1,88 @@ +// 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/PhotonMeson/DataModel/gammaTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct pcmConverter1 { + Produces v0photon_001; + Produces v0leg_001; + + void process(aod::V0PhotonsKF_000 const& v0s, aod::V0Legs_000 const& v0legs) + { + for (auto& v0 : v0s) { + v0photon_001( + v0.collisionId(), + v0.v0Id(), + v0.posTrackId(), + v0.negTrackId(), + v0.vx(), + v0.vy(), + v0.vz(), + v0.px(), + v0.py(), + v0.pz(), + v0.mGamma(), + v0.dcaXYtopv(), + v0.dcaZtopv(), + v0.cospa(), + v0.cospaXY(), + v0.cospaRZ(), + v0.pca(), + v0.alpha(), + v0.qtarm(), + v0.chiSquareNDF()); + } // end of v0 loop + + for (auto& v0leg : v0legs) { + v0leg_001( + v0leg.collisionId(), + v0leg.trackId(), + v0leg.sign(), + v0leg.px(), + v0leg.py(), + v0leg.pz(), + v0leg.dcaXY(), + v0leg.dcaZ(), + v0leg.tpcNClsFindable(), + v0leg.tpcNClsFindableMinusFound(), + v0leg.tpcNClsFindableMinusCrossedRows(), + v0leg.tpcNClsShared(), + v0leg.tpcChi2NCl(), + v0leg.tpcInnerParam(), + v0leg.tpcSignal(), + v0leg.tpcNSigmaEl(), + v0leg.tpcNSigmaPi(), + v0leg.itsClusterSizes(), + v0leg.itsChi2NCl(), + v0leg.detectorMap()); + } // end of v0leg loop + } // end of process +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"pcm-converter1"})}; +} diff --git a/PWGEM/PhotonMeson/Tasks/OmegaMesonEMC.cxx b/PWGEM/PhotonMeson/Tasks/OmegaMesonEMC.cxx new file mode 100644 index 00000000000..d113fb5720b --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/OmegaMesonEMC.cxx @@ -0,0 +1,351 @@ +// 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 OmegaMesonEMC.cxx +/// +/// \brief This code loops over collisions to reconstruct heavy mesons (omega or eta') using EMCal clusters +/// +/// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt +/// + +#include "PWGEM/PhotonMeson/Utils/HNMUtilities.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.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 + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::pwgem::photonmeson; + +namespace o2::aod +{ +using MyBCs = soa::Join; +using MyCollisions = soa::Filtered>; +using MyCollision = MyCollisions::iterator; +using SelectedTracks = soa::Filtered>; +} // namespace o2::aod + +namespace hnm +{ + +enum TrackCuts { kpT, + kEta, + kTPCSigma, + kTrackCuts +}; + +const std::vector chargedPionMinMaxName{"Min", "Max"}; +const std::vector chargedPionCutsName{"pT", "eta", "TPC sigma"}; +const float chargedPionCutsTable[kTrackCuts][2]{{0.35f, 20.f}, {-.8f, .8f}, {-4.f, 4.f}}; + +} // namespace hnm + +struct OmegaMesonEMC { + + // --------------------------------> Configurables <------------------------------------ + // - Event selection cuts + // - Track selection cuts + // - Cluster shifts + // - HNM mass selection windows + // ------------------------------------------------------------------------------------- + // ---> Event selection + Configurable confEvtSelectZvtx{"confEvtSelectZvtx", true, "Event selection includes max. z-Vertex"}; + Configurable confEvtZvtx{"confEvtZvtx", 10.f, "Evt sel: Max. z-Vertex (cm)"}; + Configurable confEvtRequireSel8{"confEvtRequireSel8", true, "Evt sel: check for sel8 trigger bit"}; + Configurable confEvtRequirekTVXinEMC{"confEvtRequirekTVXinEMC", false, "Evt sel: check for EMCal MB trigger kTVXinEMC"}; + Configurable confEvtRequireL0{"confEvtRequireL0", false, "Evt sel: check for EMCal L0 trigger"}; + Configurable confEvtRequireGoodZVertex{"confEvtRequireGoodZVertex", false, "Evt sel: check for EMCal good z-vertex"}; + Configurable confEvtRequireNoSameBunchPileUp{"confEvtRequireNoSameBunchPileUp", false, "Evt sel: check for no same bunch pile-up"}; + + // ---> Track selection + Configurable> cfgChargedPionCuts{"cfgChargedPionCuts", {hnm::chargedPionCutsTable[0], 3, 2, hnm::chargedPionCutsName, hnm::chargedPionMinMaxName}, "Charged pion track cuts"}; + Configurable cfgTPCNClustersMin{"cfgTPCNClustersMin", 80, "Mininum of TPC Clusters"}; + Configurable cfgTrkTPCfCls{"cfgTrkTPCfCls", 0.83, "Minimum fraction of crossed rows over findable clusters"}; + Configurable cfgTrkTPCcRowsMin{"cfgTrkTPCcRowsMin", 70, "Minimum number of crossed TPC rows"}; + Configurable cfgTrkTPCsClsSharedFrac{"cfgTrkTPCsClsSharedFrac", 1.f, "Fraction of shared TPC clusters"}; + Configurable cfgTrkITSnclsMin{"cfgTrkITSnclsMin", 4, "Minimum number of ITS clusters"}; + Configurable cfgTrkDCAxyMax{"cfgTrkDCAxyMax", 0.15, "Maximum DCA_xy"}; + Configurable cfgTrkDCAzMax{"cfgTrkDCAzMax", 0.3, "Maximum DCA_z"}; + Configurable cfgTrkMaxChi2PerClusterTPC{"cfgTrkMaxChi2PerClusterTPC", 4.0f, "Minimal track selection: max allowed chi2 per TPC cluster"}; // 4.0 is default of global tracks on 20.01.2023 + Configurable cfgTrkMaxChi2PerClusterITS{"cfgTrkMaxChi2PerClusterITS", 36.0f, "Minimal track selection: max allowed chi2 per ITS cluster"}; // 36.0 is default of global tracks on 20.01.2023 + + // ---> Configurables to allow for a shift in eta/phi of EMCal clusters to better align with extrapolated TPC tracks + Configurable cfgDoEMCShift{"cfgDoEMCShift", false, "Apply SM-wise shift in eta and phi to EMCal clusters to align with TPC tracks"}; + Configurable> cfgEMCEtaShift{"cfgEMCEtaShift", {0.f}, "values for SM-wise shift in eta to be added to EMCal clusters to align with TPC tracks"}; + Configurable> cfgEMCPhiShift{"cfgEMCPhiShift", {0.f}, "values for SM-wise shift in phi to be added to EMCal clusters to align with TPC tracks"}; + static const int nSMs = 20; + std::array emcEtaShift = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + std::array emcPhiShift = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + // ---> Shift the omega/eta' mass based on the difference of the reconstructed mass of the pi0/eta to its PDG mass to reduce smearing caused by EMCal/PCM in photon measurement + Configurable cfgHNMMassCorrection{"cfgHNMMassCorrection", 1, "Use GG PDG mass to correct HNM mass (0 = off, 1 = subDeltaPi0, 2 = subLambda)"}; + + // ---> Mass windows for the selection of heavy neutral mesons (also based on mass of their light neutral meson decay daughter) + static constexpr float DefaultMassWindows[2] = {0.11, 0.16}; + Configurable> cfgMassWindowPi0{"cfgMassWindowPi0", {DefaultMassWindows, 2, {"min", "max"}}, "Mass window for selected decay pi0"}; + + Configurable cfgMaxMultiplicity{"cfgMaxMultiplicity", 5000, "Maximum number of tracks in a collision (can be used to increase the S/B -> Very experimental)"}; + Configurable cfgMinGGPtOverHNMPt{"cfgMinGGPtOverHNMPt", 0., "Minimum ratio of the pT of the gamma gamma pair over the pT of the HNM (can be used to increase the S/B)"}; + + Filter collisionZVtxFilter = nabs(aod::collision::posZ) < confEvtZvtx; + Filter collisionMultFilter = (o2::aod::mult::multNTracksPV <= cfgMaxMultiplicity); + + Filter trackPtFilter = (o2::aod::track::pt > cfgChargedPionCuts->get(hnm::kpT, "Min")) && (o2::aod::track::pt < cfgChargedPionCuts->get(hnm::kpT, "Max")); + Filter trackEtaFilter = (o2::aod::track::eta > cfgChargedPionCuts->get(hnm::kEta, "Min")) && (o2::aod::track::eta < cfgChargedPionCuts->get(hnm::kEta, "Max")); + Filter trackDCAXYFilter = nabs(o2::aod::track::dcaXY) < cfgTrkDCAxyMax; + Filter trackDCAZFilter = nabs(o2::aod::track::dcaZ) < cfgTrkDCAzMax; + + Filter trackTPCChi2Filter = o2::aod::track::tpcChi2NCl < cfgTrkMaxChi2PerClusterTPC; + Filter trackITSChi2Filter = o2::aod::track::itsChi2NCl < cfgTrkMaxChi2PerClusterITS; + + Filter trackTPCSigmaFilterTPC = (o2::aod::pidtpc::tpcNSigmaPi > cfgChargedPionCuts->get(hnm::kTPCSigma, "Min")) && (o2::aod::pidtpc::tpcNSigmaPi < cfgChargedPionCuts->get(hnm::kTPCSigma, "Max")); + + template + bool isSelectedTrack(T const& track) + { + if (track.tpcNClsFound() < cfgTPCNClustersMin) + return false; + if (track.tpcCrossedRowsOverFindableCls() < cfgTrkTPCfCls) + return false; + if (track.tpcNClsCrossedRows() < cfgTrkTPCcRowsMin) + return false; + if (track.tpcFractionSharedCls() > cfgTrkTPCsClsSharedFrac) + return false; + if (track.itsNCls() < cfgTrkITSnclsMin) + return false; + return true; + } + + HistogramRegistry mHistManager{"HeavyNeutralMesonHistograms", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Prepare vectors for different species + std::vector vGGs; + std::vector vHNMs; + std::vector pion, antipion; + + Preslice perCollisionEMC = aod::skimmedcluster::collisionId; + + void init(InitContext const&) + { + mHistManager.add("Event/nEMCalEvents", "Number of collisions with a certain combination of EMCal triggers;;#bf{#it{N}_{collisions}}", HistType::kTH1F, {{5, -0.5, 4.5}}); + std::vector nEventTitles = {"Cells & kTVXinEMC", "Cells & L0", "Cells & !kTVXinEMC & !L0", "!Cells & kTVXinEMC", "!Cells & L0"}; + for (size_t iBin = 0; iBin < nEventTitles.size(); iBin++) + mHistManager.get(HIST("Event/nEMCalEvents"))->GetXaxis()->SetBinLabel(iBin + 1, nEventTitles[iBin].data()); + mHistManager.add("Event/fMultiplicity", "Multiplicity after event cuts;#bf{#it{N}_{tracks}};#bf{#it{N}_{collisions}}", HistType::kTH1F, {{500, 0, 500}}); + mHistManager.add("Event/fZvtx", "Zvtx after event cuts;#bf{z_{vtx} (cm)};#bf{#it{N}_{collisions}}", HistType::kTH1F, {{300, -15, 15}}); + + mHistManager.add("GG/invMassVsPt", "Invariant mass and pT of gg candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})}", HistType::kTH2F, {{400, 0., 0.8}, {250, 0., 25.}}); + mHistManager.add("GG/invMassVsPt_selected", "Invariant mass and pT of gg candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})}", HistType::kTH2F, {{400, 0., 0.8}, {250, 0., 25.}}); + + const int nTrackSpecies = 2; // x2 because of anti particles + const char* particleSpecies[nTrackSpecies] = {"Pion", "AntiPion"}; + const char* particleSpeciesLatex[nTrackSpecies] = {"#pi^{+}", "#pi^{-}"}; + + for (int iParticle = 0; iParticle < nTrackSpecies; iParticle++) { + mHistManager.add(Form("TrackCuts/%s/fPt", particleSpecies[iParticle]), Form("%s transverse momentum;#bf{#it{p}_{T}^{%s} (GeV/#it{c})};#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{500, 0, 10}}); + mHistManager.add(Form("TrackCuts/%s/fEta", particleSpecies[iParticle]), Form("%s pseudorapidity distribution;#eta;#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{500, -2, 2}}); + mHistManager.add(Form("TrackCuts/%s/fPhi", particleSpecies[iParticle]), Form("%s azimuthal angle distribution;#phi;#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{720, 0, constants::math::TwoPI}}); + + mHistManager.add(Form("TrackCuts/%s/fNsigmaTPCvsP", particleSpecies[iParticle]), Form("NSigmaTPC %s P;#bf{#it{p}^{%s} (GeV/#it{c})};n#sigma_{TPC}^{%s}", particleSpecies[iParticle], particleSpeciesLatex[iParticle], particleSpeciesLatex[iParticle]), {HistType::kTH2F, {{100, 0.0f, 10.0f}, {100, -10.f, 10.f}}}); + + mHistManager.add(Form("TrackCuts/%s/fDCAxy", particleSpecies[iParticle]), Form("fDCAxy %s;#bf{DCA_{xy}};#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{500, -0.5f, 0.5f}}); + mHistManager.add(Form("TrackCuts/%s/fDCAz", particleSpecies[iParticle]), Form("fDCAz %s;#bf{DCA_{z}};#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{500, -0.5f, 0.5f}}); + mHistManager.add(Form("TrackCuts/%s/fTPCsCls", particleSpecies[iParticle]), Form("fTPCsCls %s;#bf{TPC Shared Clusters};#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{163, -1.0f, 162.0f}}); + mHistManager.add(Form("TrackCuts/%s/fTPCcRows", particleSpecies[iParticle]), Form("fTPCcRows %s;#bf{TPC Crossed Rows};#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{163, -1.0f, 162.0f}}); + mHistManager.add(Form("TrackCuts/%s/fTrkTPCfCls", particleSpecies[iParticle]), Form("fTrkTPCfCls %s;#bf{TPC Findable/CrossedRows};#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{500, 0.0f, 3.0f}}); + mHistManager.add(Form("TrackCuts/%s/fTPCncls", particleSpecies[iParticle]), Form("fTPCncls %s;#bf{TPC Clusters};#bf{#it{N}^{%s}}", particleSpecies[iParticle], particleSpeciesLatex[iParticle]), HistType::kTH1F, {{163, -1.0f, 162.0f}}); + } + + // --> HNM QA + // Properties of the pi+pi- pair + mHistManager.add("Omega/Before/PiPlPiMi/fInvMassVsPt", "Invariant mass and pT of #pi^+pi^- pairs;#bf{#it{M}^{#pi^{+}#pi^{-}} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#pi^{+}#pi^{-}} (GeV/#it{c})}", HistType::kTH2F, {{400, 0.2, 1.}, {250, 0., 25.}}); + mHistManager.add("Omega/Before/PiPlPiMi/fEta", "Pseudorapidity of HMNCand;#eta;#bf{#it{N}^{#pi^{+}#pi^{-}}}", HistType::kTH1F, {{500, -2, 2}}); + mHistManager.add("Omega/Before/PiPlPiMi/fPhi", "Azimuthal angle of HMNCand;#phi;#bf{#it{N}^{#pi^{+}#pi^{-}}}", HistType::kTH1F, {{720, 0, constants::math::TwoPI}}); + + for (const auto& BeforeAfterString : {"Before", "After"}) { + mHistManager.add(Form("Omega/%s/fInvMassVsPt", BeforeAfterString), "Invariant mass and pT of heavy neutral meson candidates;#bf{#it{M}^{#pi^{+}#pi^{-}#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#pi^{+}#pi^{-}#gamma#gamma} (GeV/#it{c})}", HistType::kTH2F, {{800, 0.4, 1.2}, {250, 0., 25.}}); + mHistManager.add(Form("Omega/%s/fEta", BeforeAfterString), "Pseudorapidity of HNM candidate;#eta;#bf{#it{N}^{#pi^{+}#pi^{-}#gamma#gamma}}", HistType::kTH1F, {{500, -2, 2}}); + mHistManager.add(Form("Omega/%s/fPhi", BeforeAfterString), "Azimuthal angle of HNM candidate;#phi;#bf{#it{N}^{#pi^{+}#pi^{-}#gamma#gamma}}", HistType::kTH1F, {{720, 0, constants::math::TwoPI}}); + } + if (cfgDoEMCShift.value) { + for (int iSM = 0; iSM < nSMs; iSM++) { + emcEtaShift[iSM] = cfgEMCEtaShift.value[iSM]; + emcPhiShift[iSM] = cfgEMCPhiShift.value[iSM]; + LOG(info) << "SM-wise shift in eta/phi for SM " << iSM << ": " << emcEtaShift[iSM] << " / " << emcPhiShift[iSM]; + } + } + } + + void process(aod::MyCollision const& collision, aod::MyBCs const&, aod::SkimEMCClusters const& clusters, aod::SelectedTracks const& tracks) + { + // clean vecs + pion.clear(); + antipion.clear(); + vHNMs.clear(); + + // ---------------------------------> EMCal event QA <---------------------------------- + // - Fill Event/nEMCalEvents histogram for EMCal event QA + // ------------------------------------------------------------------------------------- + bool bcHasEMCCells = collision.isemcreadout(); + auto foundBC = collision.foundBC_as(); + bool iskTVXinEMC = foundBC.alias_bit(kTVXinEMC); + bool isL0Triggered = foundBC.alias_bit(kEMC7) || foundBC.alias_bit(kDMC7) || foundBC.alias_bit(kEG1) || foundBC.alias_bit(kEG2); + + if (confEvtRequireSel8 && !collision.sel8()) + return; // Skip this collision if sel8 trigger bit is not set + if (confEvtRequirekTVXinEMC && !iskTVXinEMC) + return; // Skip this collision if kTVXinEMC trigger bit is not set + if (confEvtRequireL0 && !isL0Triggered) + return; // Skip this collision if L0 trigger bit is not set + if (confEvtRequireGoodZVertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; // Skip this collision if good z-vertex condition is not met + if (confEvtRequireNoSameBunchPileUp && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; // Skip this collision if no same bunch pileup condition is not met + + if (bcHasEMCCells && iskTVXinEMC) + mHistManager.fill(HIST("Event/nEMCalEvents"), 0); + if (bcHasEMCCells && isL0Triggered) + mHistManager.fill(HIST("Event/nEMCalEvents"), 1); + if (bcHasEMCCells && !iskTVXinEMC && !isL0Triggered) + mHistManager.fill(HIST("Event/nEMCalEvents"), 2); + if (!bcHasEMCCells && iskTVXinEMC) + mHistManager.fill(HIST("Event/nEMCalEvents"), 3); + if (!bcHasEMCCells && isL0Triggered) + mHistManager.fill(HIST("Event/nEMCalEvents"), 4); + + mHistManager.fill(HIST("Event/fMultiplicity"), collision.multNTracksPV()); + mHistManager.fill(HIST("Event/fZvtx"), collision.posZ()); + + // --------------------------------> Process Photons <---------------------------------- + // - Slice clusters and V0s by collision ID to get the ones in this collision + // - Store the clusters and V0s in the vGammas vector + // - Reconstruct gamma-gamma pairs + // ------------------------------------------------------------------------------------- + auto clustersInThisCollision = clusters.sliceBy(perCollisionEMC, collision.globalIndex()); + + std::vector vGammas; + hnmutilities::storeGammasInVector(clustersInThisCollision, vGammas, emcEtaShift, emcPhiShift); + hnmutilities::reconstructGGs(vGammas, vGGs); + vGammas.clear(); + + for (unsigned int iGG = 0; iGG < vGGs.size(); iGG++) { + auto lightMeson = &vGGs.at(iGG); + + mHistManager.fill(HIST("GG/invMassVsPt"), lightMeson->m(), lightMeson->pT()); + + if (lightMeson->m() > cfgMassWindowPi0->get("min") && lightMeson->m() < cfgMassWindowPi0->get("max")) { + lightMeson->isPi0 = true; + mHistManager.fill(HIST("GG/invMassVsPt_selected"), lightMeson->m(), lightMeson->pT()); + } else { + vGGs.erase(vGGs.begin() + iGG); + iGG--; + } + } + + // ------------------------------> Loop over all tracks <------------------------------- + // - Fill QA histograms for all tracks and per particle species + // ------------------------------------------------------------------------------------- + for (const auto& track : tracks) { + if (!isSelectedTrack(track)) + continue; // Skip tracks that do not pass the selection criteria + if (track.sign() > 0) { // Positive charge -> Particles + pion.emplace_back(track.pt(), track.eta(), track.phi(), constants::physics::MassPionCharged); + + mHistManager.fill(HIST("TrackCuts/Pion/fPt"), track.pt()); + mHistManager.fill(HIST("TrackCuts/Pion/fEta"), track.eta()); + mHistManager.fill(HIST("TrackCuts/Pion/fPhi"), track.phi()); + + mHistManager.fill(HIST("TrackCuts/Pion/fNsigmaTPCvsP"), track.p(), track.tpcNSigmaPi()); + + mHistManager.fill(HIST("TrackCuts/Pion/fDCAxy"), track.dcaXY()); + mHistManager.fill(HIST("TrackCuts/Pion/fDCAz"), track.dcaZ()); + mHistManager.fill(HIST("TrackCuts/Pion/fTPCsCls"), track.tpcNClsShared()); + mHistManager.fill(HIST("TrackCuts/Pion/fTPCcRows"), track.tpcNClsCrossedRows()); + mHistManager.fill(HIST("TrackCuts/Pion/fTrkTPCfCls"), track.tpcCrossedRowsOverFindableCls()); + mHistManager.fill(HIST("TrackCuts/Pion/fTPCncls"), track.tpcNClsFound()); + } else { // Negative charge -> Anti-particles + antipion.emplace_back(track.pt(), track.eta(), track.phi(), constants::physics::MassPionCharged); + + mHistManager.fill(HIST("TrackCuts/AntiPion/fPt"), track.pt()); + mHistManager.fill(HIST("TrackCuts/AntiPion/fEta"), track.eta()); + mHistManager.fill(HIST("TrackCuts/AntiPion/fPhi"), track.phi()); + + mHistManager.fill(HIST("TrackCuts/AntiPion/fNsigmaTPCvsP"), track.p(), track.tpcNSigmaPi()); + + mHistManager.fill(HIST("TrackCuts/AntiPion/fDCAxy"), track.dcaXY()); + mHistManager.fill(HIST("TrackCuts/AntiPion/fDCAz"), track.dcaZ()); + mHistManager.fill(HIST("TrackCuts/AntiPion/fTPCsCls"), track.tpcNClsShared()); + mHistManager.fill(HIST("TrackCuts/AntiPion/fTPCcRows"), track.tpcNClsCrossedRows()); + mHistManager.fill(HIST("TrackCuts/AntiPion/fTrkTPCfCls"), track.tpcCrossedRowsOverFindableCls()); + mHistManager.fill(HIST("TrackCuts/AntiPion/fTPCncls"), track.tpcNClsFound()); + } + } + + // -------------------------> Reconstruct HNM candidates <------------------------------ + // - Based on the previously filled (anti)pion vectors + // - Fill QA histograms for kinematics of the pions and their combinations + // ------------------------------------------------------------------------------------- + for (const auto& posPion : pion) { + for (const auto& negPion : antipion) { + ROOT::Math::PtEtaPhiMVector vecPiPlPiMi = posPion + negPion; + hnmutilities::reconstructHeavyNeutralMesons(vecPiPlPiMi, vGGs, vHNMs); + + mHistManager.fill(HIST("Omega/Before/PiPlPiMi/fInvMassVsPt"), vecPiPlPiMi.M(), vecPiPlPiMi.pt()); + mHistManager.fill(HIST("Omega/Before/PiPlPiMi/fEta"), vecPiPlPiMi.eta()); + mHistManager.fill(HIST("Omega/Before/PiPlPiMi/fPhi"), RecoDecay::constrainAngle(vecPiPlPiMi.phi())); + } + } + + // ---------------------------> Process HNM candidates <-------------------------------- + // - Fill invMassVsPt histograms separated into HNM types (based on GG mass) and gamma reco method + // ------------------------------------------------------------------------------------- + for (unsigned int iHNM = 0; iHNM < vHNMs.size(); iHNM++) { + auto heavyNeutralMeson = vHNMs.at(iHNM); + float massHNM = heavyNeutralMeson.m(cfgHNMMassCorrection); + + mHistManager.fill(HIST("Omega/Before/fInvMassVsPt"), massHNM, heavyNeutralMeson.pT()); + mHistManager.fill(HIST("Omega/Before/fEta"), heavyNeutralMeson.eta()); + mHistManager.fill(HIST("Omega/Before/fPhi"), RecoDecay::constrainAngle(heavyNeutralMeson.phi())); + + if (heavyNeutralMeson.gg->pT() / heavyNeutralMeson.pT() > cfgMinGGPtOverHNMPt) { + mHistManager.fill(HIST("Omega/After/fInvMassVsPt"), massHNM, heavyNeutralMeson.pT()); + mHistManager.fill(HIST("Omega/After/fEta"), heavyNeutralMeson.eta()); + mHistManager.fill(HIST("Omega/After/fPhi"), RecoDecay::constrainAngle(heavyNeutralMeson.phi())); + } + } + } +}; + +WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"omega-meson-emc"})}; } diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx index 9c82fa7b09a..d00c2e9732f 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhoton.cxx @@ -14,29 +14,37 @@ // This code loops over photon candidate and fill histograms // Please write to: daiki.sekihata@cern.ch -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" +#include "EMPhotonEventCut.h" + #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -266,8 +274,8 @@ struct SinglePhoton { return is_selected; } - template - void FillPhoton(TEvents const& collisions, TPhotons1 const& photons1, TPreslice1 const& perCollision1, TCuts1 const& cuts1, TV0Legs const&, TEMCMatchedTracks const&) + template + void FillPhoton(TEvents const& collisions, TPhotons1 const& photons1, TPreslice1 const& perCollision1, TCuts1 const& cuts1, TV0Legs const&) { THashList* list_ev_before = static_cast(fMainList->FindObject("Event")->FindObject(detnames[photontype].data())->FindObject(event_types[0].data())); THashList* list_ev_after = static_cast(fMainList->FindObject("Event")->FindObject(detnames[photontype].data())->FindObject(event_types[1].data())); @@ -339,17 +347,17 @@ struct SinglePhoton { void processPCM(MyCollisions const&, MyV0Photons const& v0photons, aod::V0Legs const& legs) { - FillPhoton(grouped_collisions, v0photons, perCollision, fPCMCuts, legs, nullptr); + FillPhoton(grouped_collisions, v0photons, perCollision, fPCMCuts, legs); } // void processPHOS(MyCollisions const& collisions, aod::PHOSClusters const& phosclusters) // { - // FillPhoton(grouped_collisions, phosclusters, perCollision_phos, fPHOSCuts, nullptr, nullptr); + // FillPhoton(grouped_collisions, phosclusters, perCollision_phos, fPHOSCuts, nullptr); // } - // void processEMC(MyCollisions const& collisions, aod::SkimEMCClusters const& emcclusters, aod::SkimEMCMTs const& emcmatchedtracks) + // void processEMC(MyCollisions const& collisions, aod::SkimEMCClusters const& emcclusters) // { - // FillPhoton(grouped_collisions, emcclusters, perCollision_emc, fEMCCuts, nullptr, emcmatchedtracks); + // FillPhoton(grouped_collisions, emcclusters, perCollision_emc, fEMCCuts, nullptr); // } void processDummy(MyCollisions::iterator const&) {} diff --git a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx index ccb33db7f3a..dd09bc17c4a 100644 --- a/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/SinglePhotonMC.cxx @@ -14,32 +14,35 @@ // This code loops over photon candidate and fill histograms // Please write to: daiki.sekihata@cern.ch -#include -#include - -#include "TString.h" -#include "TMath.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" +#include "EMPhotonEventCut.h" + +#include "PWGEM/Dilepton/Utils/MCUtilities.h" #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -272,8 +275,8 @@ struct SinglePhotonMC { return is_selected; } - template - void FillTruePhoton(TEvents const& collisions, TPhotons1 const& photons1, TPreslice1 const& perCollision1, TCuts1 const& cuts1, TV0Legs const&, TEMCMatchedTracks const&, TMCParticles const& mcparticles, TMCEvents const&) + template + void FillTruePhoton(TEvents const& collisions, TPhotons1 const& photons1, TPreslice1 const& perCollision1, TCuts1 const& cuts1, TV0Legs const&, TMCParticles const& mcparticles, TMCEvents const&) { THashList* list_ev_before = static_cast(fMainList->FindObject("Event")->FindObject(detnames[photontype].data())->FindObject(event_types[0].data())); THashList* list_ev_after = static_cast(fMainList->FindObject("Event")->FindObject(detnames[photontype].data())->FindObject(event_types[1].data())); @@ -351,25 +354,25 @@ struct SinglePhotonMC { } } // end of photon loop - } // end of cut loop - } // end of collision loop + } // end of cut loop + } // end of collision loop } Partition grouped_collisions = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); // this goes to same event. void processPCM(MyCollisions const&, MyV0Photons const& v0photons, MyMCV0Legs const& legs, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const& mccollisions) { - FillTruePhoton(grouped_collisions, v0photons, perCollision, fPCMCuts, legs, nullptr, mcparticles, mccollisions); + FillTruePhoton(grouped_collisions, v0photons, perCollision, fPCMCuts, legs, mcparticles, mccollisions); } // void processPHOS(MyCollisions const& collisions, aod::PHOSClusters const& phosclusters, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const& mccollisions) // { - // FillTruePhoton(grouped_collisions, phosclusters, perCollision_phos, fPHOSCuts, nullptr, nullptr, mcparticles, mccollisions); + // FillTruePhoton(grouped_collisions, phosclusters, perCollision_phos, fPHOSCuts, nullptr, mcparticles, mccollisions); // } - // void processEMC(MyCollisions const& collisions, aod::SkimEMCClusters const& emcclusters, aod::SkimEMCMTs const& emcmatchedtracks, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const& mccollisions) + // void processEMC(MyCollisions const& collisions, aod::SkimEMCClusters const& emcclusters, aod::EMMCParticles const& mcparticles, aod::EMMCEvents const& mccollisions) // { - // FillTruePhoton(grouped_collisions, emcclusters, perCollision_emc, fEMCCuts, nullptr, emcmatchedtracks, mcparticles, mccollisions); + // FillTruePhoton(grouped_collisions, emcclusters, perCollision_emc, fEMCCuts, nullptr, mcparticles, mccollisions); // } PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; diff --git a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx index 2f91a62dc43..17989065391 100644 --- a/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx +++ b/PWGEM/PhotonMeson/Tasks/TagAndProbe.cxx @@ -14,28 +14,47 @@ // This code is for data-driven efficiency for photon analyses. tag and probe method // Please write to: daiki.sekihata@cern.ch -#include -#include - -#include "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/LorentzRotation.h" -#include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/PairCut.h" +#include "EMPhotonEventCut.h" + #include "PWGEM/PhotonMeson/Core/CutsLibrary.h" +#include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/HistogramsLibrary.h" +#include "PWGEM/PhotonMeson/Core/PHOSPhotonCut.h" +#include "PWGEM/PhotonMeson/Core/PairCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Common/CCDB/TriggerAliases.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 +#include + +#include using namespace o2; using namespace o2::aod; @@ -126,7 +145,7 @@ struct TagAndProbe { THashList* list_pair_subsys_paircut = reinterpret_cast(list_pair_subsys_photoncut->FindObject(pair_cut_name.data())); o2::aod::pwgem::photon::histogram::DefineHistograms(list_pair_subsys_paircut, "tag_and_probe", pairname.data()); } // end of cut3 loop pair cut - } // end of cut2 loop + } // end of cut2 loop } static constexpr std::string_view pairnames[6] = {"PCMPCM", "PHOSPHOS", "EMCEMC", "PCMPHOS", "PCMEMC", "PHOSEMC"}; @@ -232,8 +251,8 @@ struct TagAndProbe { Preslice perCollision_phos = aod::skimmedcluster::collisionId; Preslice perCollision_emc = aod::skimmedcluster::collisionId; - template - void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TTagCut const& tagcut, TProbeCuts const& probecuts, TPairCuts const& paircuts, TLegs const& /*legs*/, TEMCMTs const& emcmatchedtracks) + template + void SameEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TTagCut const& tagcut, TProbeCuts const& probecuts, TPairCuts const& paircuts, TLegs const& /*legs*/) { THashList* list_ev_pair_before = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[0].data())); THashList* list_ev_pair_after = static_cast(fMainList->FindObject("Event")->FindObject(pairnames[pairtype].data())->FindObject(event_types[1].data())); @@ -315,13 +334,13 @@ struct TagAndProbe { reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", tagcut.GetName(), probecut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_PassingProbe_Same"))->Fill(v12.M(), v2.Pt()); if constexpr (pairtype == PairType::kEMCEMC) { - RotationBackground(v12, v1, v2, photons2_coll, g1.globalIndex(), g2.globalIndex(), probecut, paircut, emcmatchedtracks); + RotationBackground(v12, v1, v2, photons2_coll, g1.globalIndex(), g2.globalIndex(), probecut, paircut); } } // end of probe cut loop - } // end of pair cut loop - } // end of g2 loop - } // end of g1 loop - } // end of collision loop + } // end of pair cut loop + } // end of g2 loop + } // end of g1 loop + } // end of collision loop } Configurable ndepth{"ndepth", 10, "depth for event mixing"}; @@ -334,8 +353,8 @@ struct TagAndProbe { BinningType_A colBinning_A{{ConfVtxBins, ConfCentBins}, true}; BinningType_C colBinning_C{{ConfVtxBins, ConfCentBins}, true}; - template - void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TTagCut const& tagcut, TProbeCuts const& probecuts, TPairCuts const& paircuts, TLegs const& /*legs*/, TEMCMTs const& /*emcmatchedtracks*/, TMixedBinning const& colBinning) + template + void MixedEventPairing(TEvents const& collisions, TPhotons1 const& photons1, TPhotons2 const& photons2, TPreslice1 const& perCollision1, TPreslice2 const& perCollision2, TTagCut const& tagcut, TProbeCuts const& probecuts, TPairCuts const& paircuts, TLegs const& /*legs*/, TMixedBinning const& colBinning) { THashList* list_pair_ss = static_cast(fMainList->FindObject("Pair")->FindObject(pairnames[pairtype].data())); @@ -406,15 +425,15 @@ struct TagAndProbe { reinterpret_cast(list_pair_ss->FindObject(Form("%s_%s", tagcut.GetName(), probecut.GetName()))->FindObject(paircut.GetName())->FindObject("hMggPt_PassingProbe_Mixed"))->Fill(v12.M(), v2.Pt()); } // end of probe cut loop - } // end of pair cut loop - } // end of g2 loop - } // end of g1 loop - } // end of different collision combinations + } // end of pair cut loop + } // end of g2 loop + } // end of g1 loop + } // end of different collision combinations } /// \brief Calculate background (using rotation background method only for EMCal!) template - void RotationBackground(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photons_coll, unsigned int ig1, unsigned int ig2, EMCPhotonCut const& cut, PairCut const& paircut, SkimEMCMTs const& /*emcmatchedtracks*/) + void RotationBackground(const ROOT::Math::PtEtaPhiMVector& meson, ROOT::Math::PtEtaPhiMVector photon1, ROOT::Math::PtEtaPhiMVector photon2, TPhotons const& photons_coll, unsigned int ig1, unsigned int ig2, EMCPhotonCut const& cut, PairCut const& paircut) { // if less than 3 clusters are present skip event since we need at least 3 clusters if (photons_coll.size() < 3) { @@ -442,7 +461,7 @@ struct TagAndProbe { // only combine rotated photons with other photons continue; } - if (!cut.template IsSelected(photon)) { + if (!cut.template IsSelected(photon)) { continue; } @@ -474,32 +493,32 @@ struct TagAndProbe { } Partition grouped_collisions = cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax; // this goes to same event. - Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > (uint16_t)0 && o2::aod::evsel::sel8 == true; + Filter collisionFilter_common = nabs(o2::aod::collision::posZ) < 10.f && o2::aod::collision::numContrib > static_cast(0) && o2::aod::evsel::sel8 == true; Filter collisionFilter_centrality = (cfgCentMin < o2::aod::cent::centFT0M && o2::aod::cent::centFT0M < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0A && o2::aod::cent::centFT0A < cfgCentMax) || (cfgCentMin < o2::aod::cent::centFT0C && o2::aod::cent::centFT0C < cfgCentMax); using MyFilteredCollisions = soa::Filtered; // this goes to mixed event. void processPCMPCM(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, MyV0Photons const& v0photons, aod::V0Legs const& legs) { - SameEventPairing(grouped_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs, nullptr); + SameEventPairing(grouped_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs); if (cfgCentEstimator == 0) { - MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs, nullptr, colBinning_M); + MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs, colBinning_M); } else if (cfgCentEstimator == 1) { - MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs, nullptr, colBinning_A); + MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs, colBinning_A); } else if (cfgCentEstimator == 2) { - MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs, nullptr, colBinning_C); + MixedEventPairing(filtered_collisions, v0photons, v0photons, perCollision, perCollision, fTagPCMCut, fProbePCMCuts, fPairCuts, legs, colBinning_C); } } void processPHOSPHOS(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, aod::PHOSClusters const& phosclusters) { - SameEventPairing(grouped_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fTagPHOSCut, fProbePHOSCuts, fPairCuts, nullptr, nullptr); - MixedEventPairing(filtered_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fTagPHOSCut, fProbePHOSCuts, fPairCuts, nullptr, nullptr, colBinning_C); + SameEventPairing(grouped_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fTagPHOSCut, fProbePHOSCuts, fPairCuts, nullptr); + MixedEventPairing(filtered_collisions, phosclusters, phosclusters, perCollision_phos, perCollision_phos, fTagPHOSCut, fProbePHOSCuts, fPairCuts, nullptr, colBinning_C); } - void processEMCEMC(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, aod::SkimEMCClusters const& emcclusters, aod::SkimEMCMTs const& emcmatchedtracks) + void processEMCEMC(MyCollisions const&, MyFilteredCollisions const& filtered_collisions, aod::SkimEMCClusters const& emcclusters) { - SameEventPairing(grouped_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fTagEMCCut, fProbeEMCCuts, fPairCuts, nullptr, emcmatchedtracks); - MixedEventPairing(filtered_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fTagEMCCut, fProbeEMCCuts, fPairCuts, nullptr, emcmatchedtracks, colBinning_C); + SameEventPairing(grouped_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fTagEMCCut, fProbeEMCCuts, fPairCuts, nullptr); + MixedEventPairing(filtered_collisions, emcclusters, emcclusters, perCollision_emc, perCollision_emc, fTagEMCCut, fProbeEMCCuts, fPairCuts, nullptr, colBinning_C); } void processDummy(MyCollisions const&) {} diff --git a/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx new file mode 100644 index 00000000000..d2aafe07b2f --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/compconvbuilder.cxx @@ -0,0 +1,876 @@ +// 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 compconvbuilder.cxx +/// \brief QA task for photons in the EM and LF builder +/// \author S. Mrozinski, smrozins@cern.ch + +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGLF/DataModel/LFStrangenessMLTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/CCDB/EventSelectionParams.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 + +using namespace o2; +using namespace o2::framework; +using namespace o2::aod; +using namespace o2::soa; +using namespace o2::constants; + +using namespace o2::aod::pwgem::dilepton::utils::mcutil; + +using MyV0Photons = soa::Join; +using MyMCV0Legs = soa::Join; +using MyMCV0Leg = MyMCV0Legs::iterator; + +using MyCollisions = soa::Join; +using MyCollision = MyCollisions::iterator; + +using MyMCCollisions = soa::Join; +using MyMCCollision = MyMCCollisions::iterator; + +using MyStraCollisions = soa::Join; +using MyStraCollision = MyStraCollisions::iterator; + +using MyTracksIUMC = soa::Join; + +using V0DerivedMCDatas = soa::Join; + +using DauTracks = soa::Join; + +struct Compconvbuilder { + HistogramRegistry registry{"Compconvbuilder"}; + + enum ConversionBuilderID { + EMBuilder = 0, + LFBuilder = 1, + EMOnly = 2, + LFOnly = 3, + Common = 4, + NConversionBuilder + }; + + static constexpr std::string_view kConversionBuilder[NConversionBuilder] = {"EMBuilder/", "LFBuilder/", "EMOnly/", "LFOnly/", "Common/"}; + static constexpr std::string_view kEventTypes[2] = {"before/", "after/"}; + + EMPhotonEventCut fEMEventCut; + struct : ConfigurableGroup { + std::string prefix = "eventcut_group"; + Configurable cfgZvtxMax{"cfgZvtxMax", 10.f, "max. Zvtx"}; + Configurable cfgRequireSel8{"cfgRequireSel8", true, "require sel8 in event cut"}; + Configurable cfgRequireFT0AND{"cfgRequireFT0AND", true, "require FT0AND in event cut"}; + Configurable cfgRequireNoTFB{"cfgRequireNoTFB", 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. 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"}; + } eventcuts; + + 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.SetRequireNoCollInTimeRangeStandard(eventcuts.cfgRequireNoCollInTimeRangeStandard); + fEMEventCut.SetRequireNoCollInTimeRangeStrict(eventcuts.cfgRequireNoCollInTimeRangeStrict); + fEMEventCut.SetRequireNoCollInITSROFStandard(eventcuts.cfgRequireNoCollInITSROFStandard); + fEMEventCut.SetRequireNoCollInITSROFStrict(eventcuts.cfgRequireNoCollInITSROFStrict); + fEMEventCut.SetRequireNoHighMultCollInPrevRof(eventcuts.cfgRequireNoHighMultCollInPrevRof); + } + + // Link V0-photons to their collision + Preslice perV0PhotonCollision = aod::v0photonkf::emeventId; + + void init(InitContext const& /*ctx*/) + { + + defineEMEventCut(); + + for (int i = 0; i < NConversionBuilder; ++i) { + + registry.add(string(kConversionBuilder[i]) + "hPt", ";p_{T} (GeV/c); Counts", kTH1F, {{1000, 0., 10.}}); + registry.add(string(kConversionBuilder[i]) + "hR", ";R_{conv} (cm); Counts", kTH1F, {{100, 0., 100.}}); + + registry.add(string(kConversionBuilder[i]) + "hEta", ";#eta; Counts", kTH1F, {{200, -1.0f, 1.0f}}); + + registry.add(string(kConversionBuilder[i]) + "hcosPA", ";R_{conv} (cm); Counts", kTH1F, {{100, 0.99f, 1.0f}}); + + registry.add(string(kConversionBuilder[i]) + "MatchedDeltaRec", ";#Delta colID_{rec};Counts", kTH1F, {{21, -10.5, 10.5}}); + + registry.add(string(kConversionBuilder[i]) + "hZ", ";z (cm);Counts", kTH1F, {{200, -100, 100}}); + + registry.add(string(kConversionBuilder[i]) + "hZR", "conversion point in RZ;Z (cm);R_{xy} (cm)", kTH2F, {{200, -100, 100}, {200, 0.0f, 100.0f}}); + + registry.add(string(kConversionBuilder[i]) + "hAP", "AP plot;#alpha;q_{T} (GeV/c)", kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); + + registry.add(string(kConversionBuilder[i]) + "ResolutionGen/Z_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};z_{conv, rec} - z_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionGen/R_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};R_{conv, rec} - R_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionGen/Phi_res", "#varphi resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};#varphi_{conv, rec} - #varphi_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.2f, 0.2f} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionGen/Pt_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};p_{T, rec} - p_{T, gen}/p_{T, gen};", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {200, -1.0f, 1.0f} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionGen/Eta_res", "Conversion radius resolution;z_{conv, gen} (cm);R_{conv, gen} (cm);#varphi_{gen} (rad.);#eta_{gen};p_{T, gen};#eta_{conv, rec} - #eta_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.5f, 0.5f} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionRec/Z_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};z_{conv, rec} - z_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionRec/R_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};R_{conv, rec} - R_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {120, -30, 30} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionRec/Phi_res", "#varphi resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};#varphi_{conv, rec} - #varphi_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.2f, 0.2f} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionRec/Pt_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};p_{T, rec} - p_{T, gen}/p_{T, gen};", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {200, -1.0f, 1.0f} + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "ResolutionRec/Eta_res", "Conversion radius resolution;z_{conv, rec} (cm);R_{conv, rec} (cm);#varphi_{rec} (rad.);#eta_{rec};p_{T, rec};#eta_{conv, rec} - #eta_{conv, gen} (cm);", + kTHnSparseF, + {{200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + {100, -0.5f, 0.5f} + + }, + false); + registry.add(string(kConversionBuilder[i]) + "ConvInfo", "Conversion radius resolution;x_{conv} (cm);y_{conv} (cm);z_{conv} (cm);R_{conv} (cm);#varphi (rad.);#eta;p_{T, gen};", + kTHnSparseF, + { + {200, -100, 100}, + {200, -100, 100}, + {200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}, + + }, + false); + + registry.add(string(kConversionBuilder[i]) + "V0Leg/Asymmetry", "", kTH1F, {{100, 0, 1}}); + + auto hCollisionCounter = registry.add(string(kConversionBuilder[i]) + "Event/before/hCollisionCounter", "collision counter;;Number of events", kTH1F, {{10, 0.5, 10.5}}, false); + hCollisionCounter->GetXaxis()->SetBinLabel(1, "all"); + hCollisionCounter->GetXaxis()->SetBinLabel(2, "No TF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(3, "No ITS ROF border"); + hCollisionCounter->GetXaxis()->SetBinLabel(4, "No Same Bunch Pileup"); + hCollisionCounter->GetXaxis()->SetBinLabel(5, "Is Vertex ITSTPC"); + hCollisionCounter->GetXaxis()->SetBinLabel(6, "Is Good Zvtx FT0vsPV"); + hCollisionCounter->GetXaxis()->SetBinLabel(7, "FT0AND"); + hCollisionCounter->GetXaxis()->SetBinLabel(8, "sel8"); + hCollisionCounter->GetXaxis()->SetBinLabel(9, "|Z_{vtx}| < 10 cm"); + hCollisionCounter->GetXaxis()->SetBinLabel(10, "accepted"); + + registry.add(string(kConversionBuilder[i]) + "Event/before/hZvtx", "vertex z; Z_{vtx} (cm)", kTH1F, {{100, -50, +50}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{300, 0, 6000}, {300, 0, 6000}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hCentFT0MvsMultNTracksPV", "hCentFT0MvsMultNTracksPV;centrality FT0M (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {600, 0, 6000}}, false); + registry.add(string(kConversionBuilder[i]) + "Event/before/hMultFT0MvsMultNTracksPV", "hMultFT0MvsMultNTracksPV;mult. FT0M;N_{track} to PV", kTH2F, {{600, 0, 6000}, {600, 0, 6000}}, false); + registry.addClone(string(kConversionBuilder[i]) + "Event/before/", string(kConversionBuilder[i]) + "Event/after/"); + } + + registry.add("truePhotons/hPt_Converted", "Converted Photons; p_{T} (GeV/c); Counts", kTH1F, {{100, 0., 10.}}); + registry.add("truePhotons/hR_Converted", "Converted Photons; R (cm); Counts", kTH1F, {{100, 0., 100.}}); + + registry.add("truePhotons/Sparse_Converted", "Conversion radius resolution;x_{conv} (cm);z_{conv} (cm);y_{conv} (cm);R_{conv} (cm);#varphi (rad.);#eta;p_{T, gen};", + kTHnSparseF, + {{200, -100, 100}, + {200, -100, 100}, + {200, -100, 100}, + {200, 0, 100}, + {90, 0, math::TwoPI}, + {200, -1.0f, 1.0f}, + {500, 0, 10}}, + false); + + auto h = registry.add("EMBuilder/hV0SignType", "Crosscheck", kTH1F, {{3, 0.5, 4.5}}, false); + h->GetXaxis()->SetBinLabel(1, "Same-sign"); + h->GetXaxis()->SetBinLabel(2, "Opposite-sign"); + h->GetXaxis()->SetBinLabel(3, "Zero-sign"); + + auto h2 = registry.add("EMBuilder/hV0ElectronPositronTrue", "pair in MC truth;;counts", kTH1F, {{2, -0.5, 1.5}}); + h2->GetXaxis()->SetBinLabel(1, "Mismatch"); + h2->GetXaxis()->SetBinLabel(2, "Good"); + } + + template + void fillEventInfo(TCollision const& collision, const float /*weight*/ = 1.f) + { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 1.0); + + if (collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 2.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 3.0); + } + if (collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 4.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 5.0); + } + if (collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 6.0); + } + + if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 7.0); + } + + if (collision.sel8()) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 8.0); + } + if (std::fabs(collision.posZ()) < eventcuts.cfgZvtxMax) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hCollisionCounter"), 9.0); + } + + registry.fill(HIST(kConversionBuilder[type]) + HIST("Event/") + HIST(kEventTypes[ev_id]) + HIST("hMultNTracksPVeta1"), collision.multNTracksPVeta1()); + } + + template + void fillLegInfo(auto& v0, auto& posleg, auto& negleg) + { + if constexpr (type == 0) { + + float ptPos = posleg.pt(); + float ptNeg = negleg.pt(); + float asym = (ptPos - ptNeg) / (ptPos + ptNeg); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("V0Leg/Asymmetry"), asym); + + } else { + + float ptPos = v0.postrackpt(); + float ptNeg = negleg.negtrackpt(); + float asym = (ptPos - ptNeg) / (ptPos + ptNeg); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("V0Leg/Asymmetry"), asym); + } + } + + template + void fillV0Info(auto& v0, auto& v0MC, auto& mcleg) + { + registry.fill(HIST(kConversionBuilder[type]) + HIST("hPt"), v0.pt()); + registry.fill(HIST(kConversionBuilder[type]) + HIST("hEta"), v0.eta()); + registry.fill(HIST(kConversionBuilder[type]) + HIST("hAP"), v0.alpha(), v0.qtarm()); + + if constexpr (type == EMBuilder || type == EMOnly) { + registry.fill(HIST(kConversionBuilder[type]) + HIST("hZ"), v0.vz()); + registry.fill(HIST(kConversionBuilder[type]) + HIST("hcosPA"), v0.cospa()); + registry.fill(HIST(kConversionBuilder[type]) + HIST("hZR"), v0.vz(), v0.v0radius()); + + float deltapT = v0.pt() - v0MC.pt(); + float deltaZ = v0.vz() - mcleg.vz(); + float deltaPhi = v0.phi() - v0MC.phi(); + float deltaEta = v0.eta() - v0MC.eta(); + float deltaR = v0.v0radius() - std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Z_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaZ); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/R_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaR); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Phi_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaPhi); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Pt_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltapT); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Eta_res"), + mcleg.vz(), + std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), + v0MC.phi(), + v0MC.eta(), + v0MC.pt(), + deltaEta); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Z_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaZ); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/R_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaR); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Phi_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaPhi); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Pt_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltapT); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Eta_res"), + v0.vz(), + v0.v0radius(), + v0.phi(), + v0.eta(), + v0.pt(), + deltaEta); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ConvInfo"), + v0.vx(), // 0 + v0.vy(), // 1 + v0.vz(), // 2 + v0.v0radius(), // 3 + v0.phi(), // 4 + v0.eta(), // 5 + v0.pt()); // 6 + + } else { + registry.fill(HIST(kConversionBuilder[type]) + HIST("hZ"), v0.z()); + registry.fill(HIST(kConversionBuilder[type]) + HIST("hcosPA"), v0.v0cosPA()); + registry.fill(HIST(kConversionBuilder[type]) + HIST("hZR"), v0.z(), v0.v0radius()); + + float deltaR = v0.v0radius() - std::hypot(v0MC.xMC(), v0MC.yMC()); + + float phiRec = v0.phi(); + RecoDecay::constrainAngle(phiRec); + + float phiMC = std::atan2(v0MC.pyMC(), v0MC.pxMC()); + RecoDecay::constrainAngle(phiMC); + + float deltaPhi = phiRec - phiMC; + RecoDecay::constrainAngle(deltaPhi); + + float etaGen = 0.5f * std::log((std::hypot(v0MC.pxMC(), v0MC.pyMC(), v0MC.pzMC()) + v0MC.pzMC()) / (std::hypot(v0MC.pxMC(), v0MC.pyMC(), v0MC.pzMC()) - v0MC.pzMC())); + + float etaRec = 0.5f * std::log((std::hypot(v0.px(), v0.py(), v0.pz()) + v0.pz()) / (std::hypot(v0.px(), v0.py(), v0.pz()) - v0.pz())); + + float deltapT = v0.pt() - v0MC.ptMC(); + float deltaEta = etaRec - etaGen; + float deltaZ = v0.z() - v0MC.zMC(); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Z_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaZ); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/R_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaR); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Phi_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaPhi); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Pt_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltapT); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionGen/Eta_res"), + v0MC.zMC(), + std::hypot(v0MC.xMC(), v0MC.yMC()), + phiMC, + etaGen, + v0MC.ptMC(), + deltaEta); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Z_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaZ); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/R_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaR); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Phi_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaPhi); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Eta_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltaEta); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ResolutionRec/Pt_res"), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt(), + deltapT); + + registry.fill(HIST(kConversionBuilder[type]) + HIST("ConvInfo"), + v0.x(), + v0.y(), + v0.z(), + v0.v0radius(), + phiRec, + v0.eta(), + v0.pt()); + } + + registry.fill(HIST(kConversionBuilder[type]) + HIST("hR"), v0.v0radius()); + } + + Preslice perCollisionMCDerived = o2::aod::v0data::straCollisionId; + + void processLFV0sMC(MyStraCollisions const& stracollisions, + soa::Join const&, + V0DerivedMCDatas const& strangeV0s, + DauTracks const&) + { + + for (const auto& collision : stracollisions) { + + fillEventInfo<0, LFBuilder>(collision); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + fillEventInfo<1, LFBuilder>(collision); + + registry.fill(HIST((kConversionBuilder[1])) + HIST("Event/before/hCollisionCounter"), 10.0); + registry.fill(HIST((kConversionBuilder[1])) + HIST("Event/after/hCollisionCounter"), 10.0); // accepted + + auto myV0s = strangeV0s.sliceBy(perCollisionMCDerived, collision.globalIndex()); + + for (auto const& v0 : myV0s) { + if (!v0.has_v0MCCore()) { + continue; + } + + auto v0MC = v0.v0MCCore_as>(); + + if (v0MC.pdgCode() != kGamma || !v0MC.isPhysicalPrimary()) { + continue; + } + + auto posTrack = v0.template posTrackExtra_as(); + + fillV0Info(v0, v0MC, posTrack); + } + } + } + + Preslice perCollision = aod::v0photonkf::emeventId; + + void processEMV0sMC(MyV0Photons const& v0s, aod::EMMCParticles const& mcparticles, MyMCV0Legs const&, MyCollisions const& collisions) + { + + for (const auto& collision : collisions) { + + fillEventInfo<0, EMBuilder>(collision); + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + fillEventInfo<1, EMBuilder>(collision); + + registry.fill(HIST((kConversionBuilder[0])) + HIST("Event/before/hCollisionCounter"), 10.0); // accepted + registry.fill(HIST((kConversionBuilder[0])) + HIST("Event/after/hCollisionCounter"), 10.0); // accepted + + auto v0PhotonsColl = v0s.sliceBy(perCollision, collision.globalIndex()); + + for (auto const& v0 : v0PhotonsColl) { + + auto pos = v0.posTrack_as(); + auto ele = v0.negTrack_as(); + auto posmc = pos.template emmcparticle_as(); + auto elemc = ele.template emmcparticle_as(); + + int photonid = FindCommonMotherFrom2Prongs(posmc, elemc, kPositron, kElectron, kGamma, mcparticles); + + auto mcphoton = mcparticles.iteratorAt(photonid); + + if (mcphoton.isPhysicalPrimary()) { + + fillV0Info(v0, mcphoton, elemc); + } + + if (pos.sign() * ele.sign() > 0) { + registry.fill(HIST("EMBuilder/hV0SignType"), 1); // same-sign + } else if (pos.sign() * ele.sign() < 0) { + registry.fill(HIST("EMBuilder/hV0SignType"), 2); // opposite-sign + } else { + registry.fill(HIST("EMBuilder/hV0SignType"), 3); // zero or undefined + } + + if ((posmc.pdgCode() == kElectron && elemc.pdgCode() == kPositron) || (posmc.pdgCode() == kPositron && elemc.pdgCode() == kElectron)) { + registry.fill(HIST("EMBuilder/hV0ElectronPositronTrue"), 1); // good + } else { + registry.fill(HIST("EMBuilder/hV0ElectronPositronTrue"), 0); // mismatch + } + } + } + } + + PresliceUnsorted perMcCollision = aod::emmcparticle::emmceventId; + + void processConvV0s(MyCollisions const& collisions, + MyMCCollisions const&, + aod::EMMCParticles const& mcparticles, + MyTracksIUMC const& tracks) + { + for (const auto& collision : collisions) { + + const float minR = 5.0f; + const float maxR = 90.f; + + if (!fEMEventCut.IsSelected(collision)) { + continue; + } + + auto mccollision = collision.template emmcevent_as(); + + auto mcstack = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + auto mcTracksColl = mcparticles.sliceBy(perMcCollision, mccollision.globalIndex()); + + std::unordered_map mc2trk; + for (const auto& trk : tracks) { + if (trk.mcParticleId() >= 0) { + mc2trk[trk.mcParticleId()] = trk.globalIndex(); + } + } + + for (const auto& mc : mcTracksColl) { + if (mc.pdgCode() != kGamma || !mc.isPhysicalPrimary()) { + continue; + } + + auto daughters = mc.daughtersIds(); + if (daughters.size() != 2) { // o2-linter: disable=magic-number (this is pretty clear and not magic) + continue; + } + + auto d1 = mcparticles.iteratorAt(daughters[0]); + auto d2 = mcparticles.iteratorAt(daughters[1]); + + if (std::abs(d1.pdgCode()) != kElectron || std::abs(d2.pdgCode()) != kElectron) { + continue; + } + + float r = std::hypot(d1.vx(), d1.vy()); + if (r < minR || r > maxR) { + continue; + } + + registry.fill(HIST("truePhotons/hPt_Converted"), mc.pt()); + registry.fill(HIST("truePhotons/hR_Converted"), r); + + registry.fill(HIST("truePhotons/Sparse_Converted"), d1.vx(), mc.y(), d1.vz(), r, mc.phi(), mc.eta(), mc.pt()); + + int id1 = mc2trk.count(d1.globalIndex()) ? mc2trk[d1.globalIndex()] : -1; + int id2 = mc2trk.count(d2.globalIndex()) ? mc2trk[d2.globalIndex()] : -1; + if (id1 < 0 || id2 < 0) { + continue; + } + } + } + } + + void processMatchCategories( + MyCollisions const& collisions, + aod::EMMCEvents const&, + MyTracksIUMC const& tracksgen, + MyV0Photons const& emV0s, + soa::Join const&, + V0DerivedMCDatas const& lfV0s, + MyMCV0Legs const&, + aod::EMMCParticles const&, + aod::McParticles const& mcparticles, + DauTracks const&) + { + std::unordered_map trackToMcLabel; + for (auto const& t : tracksgen) { + int label = t.mcParticleId(); + if (label >= 0) { + trackToMcLabel[t.globalIndex()] = label; + } + } + + for (const auto& collision : collisions) { + if (!fEMEventCut.IsSelected(collision)) + continue; + + fillEventInfo<1, EMBuilder>(collision); + + auto emSlice = emV0s.sliceBy(perCollision, collision.globalIndex()); + auto lfSlice = lfV0s.sliceBy(perCollisionMCDerived, collision.globalIndex()); + + using EMIt = decltype(emSlice.begin()); + using LFIt = decltype(lfSlice.begin()); + struct Entry { + std::optional emIt; + std::optional lfIt; + }; + std::unordered_map table; + + for (EMIt it = emSlice.begin(); it != emSlice.end(); ++it) { + auto posmc = it.posTrack_as() + .emmcparticle_as(); + auto negmc = it.negTrack_as() + .emmcparticle_as(); + int pid = FindCommonMotherFrom2Prongs(posmc, negmc, + kPositron, kElectron, kGamma, mcparticles); + if (pid >= 0) + table[pid].emIt = it; + } + + for (LFIt it = lfSlice.begin(); it != lfSlice.end(); ++it) { + int posTrackIndex = it.posTrackId(); + auto negTrackIndex = it.negTrackId(); + + if (!trackToMcLabel.count(posTrackIndex) || !trackToMcLabel.count(negTrackIndex)) + continue; + auto posmc = mcparticles.iteratorAt(trackToMcLabel[posTrackIndex]); + auto negmc = mcparticles.iteratorAt(trackToMcLabel[negTrackIndex]); + int pid = FindCommonMotherFrom2Prongs(posmc, negmc, + kPositron, kElectron, kGamma, mcparticles); + if (pid >= 0) + table[pid].lfIt = it; + } + + for (auto const& [pid, entry] : table) { + auto mcphoton = mcparticles.iteratorAt(pid); + + if (entry.emIt.has_value() && entry.lfIt.has_value()) { + // --- Common V0 --- + auto& lfV0 = *entry.lfIt.value(); + auto v0MC = lfV0.template v0MCCore_as< + soa::Join>(); + auto posTrack = lfV0.template posTrackExtra_as(); + fillV0Info(lfV0, v0MC, posTrack); + + } else if (entry.emIt.has_value()) { + // --- EM-only V0 --- + auto& emV0 = *entry.emIt.value(); + auto negmc = emV0.negTrack_as() + .emmcparticle_as(); + fillV0Info(emV0, mcphoton, negmc); + + } else if (entry.lfIt.has_value()) { + // --- LF-only V0 --- + auto& lfV0 = *entry.lfIt.value(); + auto v0MC = lfV0.template v0MCCore_as< + soa::Join>(); + auto posTrack = lfV0.template posTrackExtra_as(); + fillV0Info(lfV0, v0MC, posTrack); + } + } + } + } + + PROCESS_SWITCH(Compconvbuilder, processMatchCategories, "Process V0s matched via MC photon", false); + PROCESS_SWITCH(Compconvbuilder, processLFV0sMC, "Process LF Builder V0s", true); + PROCESS_SWITCH(Compconvbuilder, processEMV0sMC, "Process EM Builder V0s", false); + PROCESS_SWITCH(Compconvbuilder, processConvV0s, "Process generated converted V0s", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfg) +{ + return WorkflowSpec{adaptAnalysisTask(cfg)}; +} diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx index 74c97448baf..376d4ca043a 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQC.cxx @@ -14,26 +14,27 @@ // This code runs loop over dalitz ee table for dalitz QC. // Please write to: daiki.sekihata@cern.ch -#include -#include +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Common/Core/RecoDecay.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.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 "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include using namespace o2; using namespace o2::aod; @@ -42,7 +43,7 @@ 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; @@ -98,6 +99,8 @@ struct DalitzEEQC { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; + 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"}; 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"}; @@ -210,7 +213,6 @@ struct DalitzEEQC { fRegistry.add("Track/hChi2TOF", "chi2 of TOF", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/hTOFbeta", "TOF beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); fRegistry.add("Track/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); } void DefineEMEventCut() @@ -250,6 +252,7 @@ struct DalitzEEQC { 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(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); @@ -321,7 +324,6 @@ struct DalitzEEQC { fRegistry.fill(HIST("Track/hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); fRegistry.fill(HIST("Track/hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); fRegistry.fill(HIST("Track/hTOFbeta"), track.p(), track.beta()); fRegistry.fill(HIST("Track/hMeanClusterSizeITS"), track.p(), track.meanClusterSizeITS() * std::cos(std::atan(track.tgl()))); } diff --git a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx index 4e2e33c2d18..3b84310b761 100644 --- a/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/dalitzEEQCMC.cxx @@ -14,28 +14,29 @@ // This code runs loop over dalitz ee table for dalitz QC. // Please write to: daiki.sekihata@cern.ch -#include -#include +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" +#include "Common/Core/RecoDecay.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.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 "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "Math/Vector4D.h" +#include "TString.h" + +#include +#include using namespace o2; using namespace o2::aod; @@ -45,7 +46,7 @@ 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; @@ -103,6 +104,8 @@ struct DalitzEEQCMC { Configurable cfg_max_dcaxy{"cfg_max_dcaxy", 1.0, "max dca XY for single track in cm"}; Configurable cfg_max_dcaz{"cfg_max_dcaz", 1.0, "max dca Z for single track in cm"}; Configurable cfg_max_dca3dsigma_track{"cfg_max_dca3dsigma_track", 1.5, "max DCA 3D in sigma"}; + 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"}; 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"}; @@ -184,7 +187,6 @@ struct DalitzEEQCMC { fRegistry.add("Track/primary/hChi2TOF", "chi2 of TOF", kTH1F, {{100, 0, 10}}, false); fRegistry.add("Track/primary/hTOFbeta", "TOF beta;p_{pv} (GeV/c);#beta", kTH2F, {{1000, 0, 10}, {240, 0, 1.2}}, false); fRegistry.add("Track/primary/hTOFNsigmaEl", "TOF n sigma el;p_{pv} (GeV/c);n #sigma_{e}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); - fRegistry.add("Track/primary/hTOFNsigmaPi", "TOF n sigma pi;p_{pv} (GeV/c);n #sigma_{#pi}^{TOF}", kTH2F, {{1000, 0, 10}, {100, -5, +5}}, false); fRegistry.add("Track/primary/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); fRegistry.add("Track/primary/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); fRegistry.add("Track/primary/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); @@ -282,6 +284,7 @@ struct DalitzEEQCMC { 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(dileptoncuts.includeITSsa, dileptoncuts.cfg_max_pt_track_ITSsa); // for eID fDileptonCut.SetPIDScheme(dileptoncuts.cfg_pid_scheme); @@ -476,7 +479,6 @@ struct DalitzEEQCMC { fRegistry.fill(HIST("Track/") + HIST(track_types[tracktype]) + HIST("hTPCNsigmaEl"), track.tpcInnerParam(), track.tpcNSigmaEl()); fRegistry.fill(HIST("Track/") + HIST(track_types[tracktype]) + HIST("hTPCNsigmaPi"), track.tpcInnerParam(), track.tpcNSigmaPi()); fRegistry.fill(HIST("Track/") + HIST(track_types[tracktype]) + HIST("hTOFNsigmaEl"), track.p(), track.tofNSigmaEl()); - fRegistry.fill(HIST("Track/") + HIST(track_types[tracktype]) + HIST("hTOFNsigmaPi"), track.p(), track.tofNSigmaPi()); fRegistry.fill(HIST("Track/") + HIST(track_types[tracktype]) + HIST("hTOFbeta"), track.p(), track.beta()); fRegistry.fill(HIST("Track/") + HIST(track_types[tracktype]) + HIST("hPtGen_DeltaPtOverPtGen"), mctrack.pt(), (track.pt() - mctrack.pt()) / mctrack.pt()); fRegistry.fill(HIST("Track/") + HIST(track_types[tracktype]) + HIST("hPtGen_DeltaEta"), mctrack.pt(), track.eta() - mctrack.eta()); diff --git a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx b/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.cxx new file mode 100644 index 00000000000..a3a7b548894 --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMDalitzEE.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. +// +// ======================== +// +// 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 "Common/Core/RecoDecay.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::aod; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"diphoton-hadron-mpc-pcmdalitzee"}), + }; +} diff --git a/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx b/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx new file mode 100644 index 00000000000..6f0dfff7c2f --- /dev/null +++ b/PWGEM/PhotonMeson/Tasks/diphotonHadronMPCPCMPCM.cxx @@ -0,0 +1,34 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +// +// ======================== +// +// 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" + +using namespace o2; +using namespace o2::aod; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask>(cfgc, TaskName{"diphoton-hadron-mpc-pcmpcm"}), + }; +} diff --git a/PWGEM/PhotonMeson/Tasks/emcalBcWisePi0.cxx b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx similarity index 66% rename from PWGEM/PhotonMeson/Tasks/emcalBcWisePi0.cxx rename to PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx index ec420371e54..0aacd233324 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalBcWisePi0.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalBcWiseGammaGamma.cxx @@ -10,27 +10,27 @@ // or submit itself to any jurisdiction. // /// -/// \file emcalBcWisePi0.cxx +/// \file emcalBcWiseGammaGamma.cxx /// -/// \brief Task that extracts pi0s from BC wise derived data of EMCal clusters +/// \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 "Framework/runDataProcessing.h" +#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 "TString.h" -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" +#include "Math/AxisAngle.h" #include "Math/LorentzRotation.h" #include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" - -#include "CommonConstants/MathConstants.h" -#include "EMCALBase/Geometry.h" -#include "PWGEM/PhotonMeson/DataModel/bcWiseTables.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TString.h" using namespace o2; using namespace o2::framework; @@ -39,10 +39,11 @@ using namespace o2::framework::expressions; using SelectedClusters = soa::Filtered; using SelectedMCClusters = soa::Filtered>; -struct EmcalBcWisePi0 { +struct EmcalBcWiseGammaGamma { HistogramRegistry mHistManager{"EmcalGammaGammaBcWiseHistograms"}; - Configurable cfgRequirekTVXinEMC{"cfgRequirekTVXinEMC", true, "Reconstruct pi0s only in kTVXinEMC triggered BCs"}; + Configurable cfgRequirekTVXinEMC{"cfgRequirekTVXinEMC", true, "Reconstruct mesons only in kTVXinEMC triggered BCs"}; + Configurable cfgRequireEMCCell{"cfgRequireEMCCell", true, "Reconstruct mesons only in BCs containing at least one EMCal cell (workaround for kTVXinEMC trigger)"}; Configurable cfgSelectOnlyUniqueAmbiguous{"cfgSelectOnlyUniqueAmbiguous", 0, "0: all clusters, 1: only unique clusters, 2: only ambiguous clusters"}; Configurable cfgClusterDefinition{"cfgClusterDefinition", 13, "Clusterizer to be selected, e.g. 13 for kV3MostSplitLowSeed"}; @@ -55,6 +56,8 @@ struct EmcalBcWisePi0 { Configurable cfgMinOpenAngle{"cfgMinOpenAngle", 0.0202, "Minimum opening angle between photons"}; Configurable cfgDistanceToEdge{"cfgDistanceToEdge", 1, "Distance to edge in cells required for rotated cluster to be accepted"}; Configurable cfgBGEventDownsampling{"cfgBGEventDownsampling", 1, "Only calculate background for every n-th event (performance reasons in PbPb)"}; + Configurable cfgMinTimeSinceSOF{"cfgMinTimeSinceSOF", -1, "Only analyze events with a time since start of fill larger than this value (in minutes)"}; + Configurable cfgMaxTimeSinceSOF{"cfgMaxTimeSinceSOF", 100000, "Only analyze events with a time since start of fill smaller than this value (in minutes)"}; ConfigurableAxis cfgCentralityBinning{"cfgCentralityBinning", {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, 101.f, 102.f}, "FT0M centrality (%)"}; @@ -82,7 +85,8 @@ struct EmcalBcWisePi0 { mHistManager.add("Event/nCollPerBC", "Number of collisions per BC;#bf{#it{N}_{coll}};#bf{FT0M centrality (%)};#bf{#it{N}_{BC}}", HistType::kTH2F, {{5, -0.5, 4.5}, cfgCentralityBinning}); mHistManager.add("Event/Z1VsZ2", "Z vertex positions for BCs with two collisions;#bf{#it{z}_{vtx}^{1} (cm)};#bf{#it{z}_{vtx}^{2} (cm)}", HistType::kTH2F, {{150, -15, 15}, {150, -15, 15}}); mHistManager.add("Event/dZ", "Distance between vertices for BCs with two collisions;#bf{#Delta #it{z}_{vtx} (cm)};#bf{#it{N}_{BC}}", HistType::kTH1F, {{600, -30, 30}}); - mHistManager.add("Event/Mu", "Probablity of a collision in the BC;#bf{#mu};#bf{#it{N}_{BC}}", HistType::kTH1F, {{1000, 0., 0.1}}); + mHistManager.add("Event/Mu", "Probablity of a collision in the BC;#bf{#mu};#bf{#it{N}_{BC}}", HistType::kTH1F, {{2000, 0., 0.4}}); + mHistManager.add("Event/TimeSinceSOF", "Time of BC since the start of fill;#bf{t-t_{SOF} (min)};#bf{#it{N}_{BC}}", HistType::kTH1F, {{2400, 0., 1200}}); mHistManager.add("Event/Centrality", "FT0M centrality;FT0M centrality (%);#bf{#it{N}_{BC}}", HistType::kTH1F, {cfgCentralityBinning}); mHistManager.add("Event/CentralityVsAmplitude", "FT0M AmplitudeVsCentrality;FT0M Centrality;FT0M Amplitude", HistType::kTH2F, {cfgCentralityBinning, {600, 0, 300000}}); @@ -94,20 +98,30 @@ struct EmcalBcWisePi0 { mHistManager.add("Cluster/Exotic", "Is cluster exotic?;#bf{Exotic?};#bf{FT0M centrality (%)};#bf{#it{N}_{clusters}}", HistType::kTH2F, {{2, -0.5, 1.5}, cfgCentralityBinning}); mHistManager.add("Cluster/EtaPhi", "Eta/Phi distribution of clusters;#eta;#phi;#bf{FT0M centrality (%)};#bf{#it{N}_{clusters}}", HistType::kTH3F, {{400, -0.8, 0.8}, {400, 0, constants::math::TwoPI}, cfgCentralityBinning}); - mHistManager.add("GG/invMassVsPt", "Invariant mass and pT of meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("GG/invMassVsPtBackground", "Invariant mass and pT of background meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); + mHistManager.add("GG/invMassVsPt", "Invariant mass and pT of meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("GG/invMassVsPtBackground", "Invariant mass and pT of background meson candidates;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); if (cfgIsMC) { mHistManager.add("True/clusterERecVsETrue", "True vs reconstructed energy of cluster inducing particle;#bf{#it{E}_{rec} (GeV)};#bf{#it{E}_{true}^{cls inducing part} (GeV)};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0, 20}, {200, 0, 20}, cfgCentralityBinning}); - mHistManager.add("True/PtRecVsPtTrue", "True vs reconstructed pT of true pi0s;#bf{#it{p}_{T}^{rec} (GeV/#it{c})};#bf{#it{p}_{T}^{true} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 20.}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("True/invMassVsPt_Primary", "Reconstructed validated primary pi0;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("True/invMassVsPt_Secondary", "Reconstructed validated pi0 from secondary decay;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); - mHistManager.add("True/invMassVsPt_HadronicShower", "Reconstructed validated pi0 from hadronic shower;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{200, 0., 0.4}, {200, 0., 20.}, cfgCentralityBinning}); - - mHistManager.add("Generated/pi0_AllBCs", "pT spectrum of generated pi0s in all BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); - mHistManager.add("Generated/pi0_TVX", "pT spectrum of generated pi0s in TVX triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); - mHistManager.add("Generated/pi0_kTVXinEMC", "pT spectrum of generated pi0s in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); - mHistManager.add("Accepted/pi0_kTVXinEMC", "pT spectrum of accepted pi0s in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{acc}}", HistType::kTH2F, {{200, 0, 20}, cfgCentralityBinning}); + mHistManager.add("True/pi0_PtRecVsPtTrue", "True vs reconstructed pT of true pi0s;#bf{#it{p}_{T}^{rec} (GeV/#it{c})};#bf{#it{p}_{T}^{true} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{300, 0, 30}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("True/pi0_invMassVsPt_Primary", "Reconstructed validated primary pi0;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("True/pi0_invMassVsPt_Secondary", "Reconstructed validated pi0 from secondary decay;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("True/pi0_invMassVsPt_HadronicShower", "Reconstructed validated pi0 from hadronic shower;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("True/eta_PtRecVsPtTrue", "True vs reconstructed pT of true eta meson;#bf{#it{p}_{T}^{rec} (GeV/#it{c})};#bf{#it{p}_{T}^{true} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{300, 0, 30}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("True/eta_invMassVsPt_Primary", "Reconstructed validated primary eta meson;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("True/eta_invMassVsPt_Secondary", "Reconstructed validated eta meson from secondary decay;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("True/eta_invMassVsPt_HadronicShower", "Reconstructed validated eta meson from hadronic shower;#bf{#it{M}^{#gamma#gamma} (GeV/#it{c}^{2})};#bf{#it{p}_{T}^{#gamma#gamma} (GeV/#it{c})};#bf{FT0M centrality (%)}", HistType::kTH3F, {{400, 0., 0.8}, {300, 0, 30}, cfgCentralityBinning}); + + mHistManager.add("Generated/pi0_AllBCs", "pT spectrum of generated pi0s in all BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Generated/pi0_FT0", "pT spectrum of generated pi0s in BCs with found FT0;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Generated/pi0_TVX", "pT spectrum of generated pi0s in TVX triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Generated/pi0_kTVXinEMC", "pT spectrum of generated pi0s in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Accepted/pi0_kTVXinEMC", "pT spectrum of accepted pi0s in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#pi^{0}}^{acc}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Generated/eta_AllBCs", "pT spectrum of generated eta mesons in all BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Generated/eta_FT0", "pT spectrum of generated eta mesons in BCs with found FT0;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Generated/eta_TVX", "pT spectrum of generated eta mesons in TVX triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Generated/eta_kTVXinEMC", "pT spectrum of generated eta mesons in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{gen}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); + mHistManager.add("Accepted/eta_kTVXinEMC", "pT spectrum of accepted eta mesons in kTVXinEMC triggered BCs;#bf{#it{p}_{T} (GeV/#it{c})};#bf{FT0M centrality (%)};#bf{#it{N}_{#eta}^{acc}}", HistType::kTH2F, {{300, 0, 30}, cfgCentralityBinning}); } } @@ -132,6 +146,7 @@ struct EmcalBcWisePi0 { mHistManager.fill(HIST("Event/nBCs"), 0, bc.centrality()); float mu = bc.mu(); mHistManager.fill(HIST("Event/Mu"), mu); + mHistManager.fill(HIST("Event/TimeSinceSOF"), bc.timeSinceSOF() / 60.); double p = mu > 0.001 ? mu / (1 - std::exp(-mu)) : 1.; // No pile-up for small mu (protection against division by zero) mHistManager.fill(HIST("Event/nCollisions"), 0, bc.centrality(), p); if (bc.hasFT0()) { @@ -231,10 +246,10 @@ struct EmcalBcWisePi0 { } } } - void reconstructTrueMesons(const auto& clusters, const auto& mcPi0s, const auto& bc) + void reconstructTrueMesons(const auto& clusters, const auto& mcPi0s, const auto& mcEtas, const auto& bc) { for (const auto& [g1, g2] : soa::combinations(soa::CombinationsStrictlyUpperIndexPolicy(clusters, clusters))) { - if (g1.pi0ID() == -1 || g1.pi0ID() != g2.pi0ID()) + if (g1.mesonID() != g2.mesonID() || g1.mesonID() == -1) continue; ROOT::Math::PtEtaPhiMVector v1(g1.pt(), g1.eta(), g1.phi(), 0.); @@ -247,16 +262,29 @@ struct EmcalBcWisePi0 { if (openingAngle12 < cfgMinOpenAngle) continue; - const auto& mcPi0 = mcPi0s.iteratorAt(g1.pi0ID() - mcPi0s.offset()); + if (!g1.isEta()) { + const auto& mcPi0 = mcPi0s.iteratorAt(g1.mesonID() - mcPi0s.offset()); - mHistManager.fill(HIST("True/PtRecVsPtTrue"), v12.Pt(), mcPi0.pt(), bc.centrality()); + mHistManager.fill(HIST("True/pi0_PtRecVsPtTrue"), v12.Pt(), mcPi0.pt(), bc.centrality()); - if (mcPi0.isPrimary()) - mHistManager.fill(HIST("True/invMassVsPt_Primary"), v12.M(), v12.Pt(), bc.centrality()); - else if (mcPi0.isFromWD()) - mHistManager.fill(HIST("True/invMassVsPt_Secondary"), v12.M(), v12.Pt(), bc.centrality()); - else - mHistManager.fill(HIST("True/invMassVsPt_HadronicShower"), v12.M(), v12.Pt(), bc.centrality()); + if (mcPi0.isPrimary()) + mHistManager.fill(HIST("True/pi0_invMassVsPt_Primary"), v12.M(), v12.Pt(), bc.centrality()); + else if (mcPi0.isFromWD()) + mHistManager.fill(HIST("True/pi0_invMassVsPt_Secondary"), v12.M(), v12.Pt(), bc.centrality()); + else + mHistManager.fill(HIST("True/pi0_invMassVsPt_HadronicShower"), v12.M(), v12.Pt(), bc.centrality()); + } else { + const auto& mcEta = mcEtas.iteratorAt(g1.mesonID() - mcEtas.offset()); + + mHistManager.fill(HIST("True/eta_PtRecVsPtTrue"), v12.Pt(), mcEta.pt(), bc.centrality()); + + if (mcEta.isPrimary()) + mHistManager.fill(HIST("True/eta_invMassVsPt_Primary"), v12.M(), v12.Pt(), bc.centrality()); + else if (mcEta.isFromWD()) + mHistManager.fill(HIST("True/eta_invMassVsPt_Secondary"), v12.M(), v12.Pt(), bc.centrality()); + else + mHistManager.fill(HIST("True/eta_invMassVsPt_HadronicShower"), v12.M(), v12.Pt(), bc.centrality()); + } } } @@ -264,18 +292,24 @@ struct EmcalBcWisePi0 { { if (cfgRequirekTVXinEMC && !bc.haskTVXinEMC()) return false; + if (cfgRequireEMCCell && !bc.hasEMCCell()) + return false; if (cfgSelectOnlyUniqueAmbiguous == 1 && collisions.size() != 1) return false; if (cfgSelectOnlyUniqueAmbiguous == 2 && collisions.size() == 1) return false; + if (cfgMinTimeSinceSOF > bc.timeSinceSOF() / 60 || cfgMaxTimeSinceSOF < bc.timeSinceSOF() / 60) + return false; return true; } - void fillGeneratedPi0Hists(const auto& mcPi0s, const auto& bc) + void fillGeneratedMesonHists(const auto& mcPi0s, const auto& mcEtas, const auto& bc) { for (const auto& mcPi0 : mcPi0s) { if (mcPi0.isPrimary()) { mHistManager.fill(HIST("Generated/pi0_AllBCs"), mcPi0.pt(), bc.centrality()); + if (bc.hasFT0()) + mHistManager.fill(HIST("Generated/pi0_FT0"), mcPi0.pt(), bc.centrality()); if (bc.hasTVX()) mHistManager.fill(HIST("Generated/pi0_TVX"), mcPi0.pt(), bc.centrality()); if (bc.haskTVXinEMC()) @@ -284,6 +318,19 @@ struct EmcalBcWisePi0 { mHistManager.fill(HIST("Accepted/pi0_kTVXinEMC"), mcPi0.pt(), bc.centrality()); } } + for (const auto& mcEta : mcEtas) { + if (mcEta.isPrimary()) { + mHistManager.fill(HIST("Generated/eta_AllBCs"), mcEta.pt(), bc.centrality()); + if (bc.hasFT0()) + mHistManager.fill(HIST("Generated/eta_FT0"), mcEta.pt(), bc.centrality()); + if (bc.hasTVX()) + mHistManager.fill(HIST("Generated/eta_TVX"), mcEta.pt(), bc.centrality()); + if (bc.haskTVXinEMC()) + mHistManager.fill(HIST("Generated/eta_kTVXinEMC"), mcEta.pt(), bc.centrality()); + if (mcEta.isAccepted() && bc.haskTVXinEMC()) + mHistManager.fill(HIST("Accepted/eta_kTVXinEMC"), mcEta.pt(), bc.centrality()); + } + } } void process(aod::BCWiseBCs::iterator const& bc, aod::BCWiseCollisions const& collisions, SelectedClusters const& clusters) @@ -298,12 +345,12 @@ struct EmcalBcWisePi0 { reconstructMesons(clusters, bc); } - void processMCInfo(aod::BCWiseBCs::iterator const& bc, aod::BCWiseCollisions const& collisions, SelectedMCClusters const& clusters, aod::BCWiseMCPi0s const& mcPi0s) + void processMCInfo(aod::BCWiseBCs::iterator const& bc, aod::BCWiseCollisions const& collisions, SelectedMCClusters const& clusters, aod::BCWiseMCPi0s const& mcPi0s, aod::BCWiseMCEtas const& mcEtas) { if (!cfgIsMC) LOG(fatal) << "MC processing is not enabled, but the task is running on MC data. Please set cfgIsMC to true."; - fillGeneratedPi0Hists(mcPi0s, bc); // Fill before BC selection to also store pi0s in BCs that were not triggered + fillGeneratedMesonHists(mcPi0s, mcEtas, bc); // Fill before BC selection to also store pi0s and eta mesons in BCs that were not triggered if (!isBCSelected(bc, collisions)) return; @@ -311,9 +358,9 @@ struct EmcalBcWisePi0 { for (const auto& cluster : clusters) mHistManager.fill(HIST("True/clusterERecVsETrue"), cluster.e(), cluster.trueE(), bc.centrality()); - reconstructTrueMesons(clusters, mcPi0s, bc); + reconstructTrueMesons(clusters, mcPi0s, mcEtas, bc); } - PROCESS_SWITCH(EmcalBcWisePi0, processMCInfo, "Run true and gen", false); + PROCESS_SWITCH(EmcalBcWiseGammaGamma, processMCInfo, "Run true and gen", false); }; -WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } +WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx index 4173c26eccf..6f298546c30 100644 --- a/PWGEM/PhotonMeson/Tasks/emcalQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/emcalQC.cxx @@ -18,28 +18,31 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) Goethe University Frankfurt /// -#include -#include -#include -#include "TString.h" -#include "THashList.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/RecoDecay.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "EMPhotonEventCut.h" + #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" -#include "PWGEM/PhotonMeson/Core/CutsLibrary.h" -#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" #include "PWGEM/PhotonMeson/Utils/ClusterHistograms.h" +#include "PWGEM/PhotonMeson/Utils/EventHistograms.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx index 9d9d2f6496e..1b784b5cb18 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQC.cxx @@ -14,18 +14,18 @@ // This code runs loop over v0 photons for PCM QC. // Please write to: daiki.sekihata@cern.ch -#include -#include +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include +#include using namespace o2; using namespace o2::aod; @@ -37,7 +37,7 @@ using namespace o2::aod::pwgem::photon; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; struct PCMQC { @@ -81,16 +81,15 @@ struct PCMQC { 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_min_cospa{"cfg_min_cospa", 0.999, "min V0 CosPA"}; + Configurable cfg_max_pca{"cfg_max_pca", 1.5, "max distance btween 2 legs"}; Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_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", 5.0, "max chi2/NclsITS"}; + 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"}; @@ -151,11 +150,6 @@ struct PCMQC { fRegistry.add("V0/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/hPResolution", "p resolution;p_{#gamma} (GeV/c);#Deltap/p", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); - fRegistry.add("V0/hPtResolution", "p_{T} resolution;p_{#gamma} (GeV/c);#Deltap_{T}/p_{T}", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); - fRegistry.add("V0/hEtaResolution", "#eta resolution;p_{#gamma} (GeV/c);#Delta#eta", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); - fRegistry.add("V0/hThetaResolution", "#theta resolution;p_{#gamma} (GeV/c);#Delta#theta (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); - fRegistry.add("V0/hPhiResolution", "#varphi resolution;p_{#gamma} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); fRegistry.add("V0/hsConvPoint", "photon conversion point;r_{xy} (cm);#varphi (rad.);#eta;", kTHnSparseF, {{100, 0.0f, 100}, {90, 0, 2 * M_PI}, {80, -2, +2}}, false); fRegistry.add("V0/hNgamma", "Number of #gamma candidates per collision", kTH1F, {{101, -0.5f, 100.5f}}); @@ -177,9 +171,9 @@ 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); - 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); + // 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); } void DefineEMEventCut() @@ -224,7 +218,6 @@ struct PCMQC { fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); @@ -292,11 +285,6 @@ struct PCMQC { fRegistry.fill(HIST("V0/hKFChi2vsX"), v0.vx(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/hKFChi2vsY"), v0.vy(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/hPResolution"), v0.p(), getPResolution(v0) / v0.p()); - fRegistry.fill(HIST("V0/hPtResolution"), v0.p(), getPtResolution(v0) / v0.pt()); - fRegistry.fill(HIST("V0/hEtaResolution"), v0.p(), getEtaResolution(v0)); - fRegistry.fill(HIST("V0/hThetaResolution"), v0.p(), getThetaResolution(v0)); - fRegistry.fill(HIST("V0/hPhiResolution"), v0.p(), getPhiResolution(v0)); float phi_cp = std::atan2(v0.vy(), v0.vx()); o2::math_utils::bringTo02Pi(phi_cp); @@ -326,9 +314,9 @@ struct PCMQC { fRegistry.fill(HIST("V0Leg/hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); fRegistry.fill(HIST("V0Leg/hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); fRegistry.fill(HIST("V0Leg/hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); - fRegistry.fill(HIST("V0Leg/hXY"), leg.x(), leg.y()); - fRegistry.fill(HIST("V0Leg/hZX"), leg.z(), leg.x()); - fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y()); + // fRegistry.fill(HIST("V0Leg/hXY"), leg.x(), leg.y()); + // fRegistry.fill(HIST("V0Leg/hZX"), leg.z(), leg.x()); + // fRegistry.fill(HIST("V0Leg/hZY"), leg.z(), leg.y()); } Preslice perCollision = aod::v0photonkf::emeventId; diff --git a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx index 5dd3e438c89..1b2590a33cd 100644 --- a/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/pcmQCMC.cxx @@ -14,20 +14,20 @@ // This code runs loop over v0 photons for PCM QC. // Please write to: daiki.sekihata@cern.ch -#include -#include +#include "PWGEM/Dilepton/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" -#include "PWGEM/PhotonMeson/Utils/MCUtilities.h" -#include "PWGEM/Dilepton/Utils/MCUtilities.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" +#include +#include using namespace o2; using namespace o2::aod; @@ -44,7 +44,7 @@ using MyCollision = MyCollisions::iterator; using MyMCCollisions = soa::Join; using MyMCCollision = MyMCCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; using MyMCV0Legs = soa::Join; @@ -59,7 +59,6 @@ struct PCMQCMC { 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"}; Configurable cfgRequireTrueAssociation{"cfgRequireTrueAssociation", false, "flag to require true mc collision association"}; - Configurable cfg_fill_resolution{"cfg_fill_resoltion", false, "flag to fill resolution histogram"}; EMPhotonEventCut fEMEventCut; struct : ConfigurableGroup { @@ -97,16 +96,15 @@ struct PCMQCMC { 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_min_cospa{"cfg_min_cospa", 0.999, "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_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", true, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_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", 5.0, "max chi2/NclsITS"}; + 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"}; @@ -196,11 +194,6 @@ struct PCMQCMC { fRegistry.add("V0/primary/hKFChi2vsX", "KF chi2 vs. conversion point in X;X (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/primary/hKFChi2vsY", "KF chi2 vs. conversion point in Y;Y (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); fRegistry.add("V0/primary/hKFChi2vsZ", "KF chi2 vs. conversion point in Z;Z (cm);KF chi2/NDF", kTH2F, {{200, -100.0f, 100.0f}, {100, 0.f, 100.0f}}, false); - fRegistry.add("V0/primary/hPResolution", "p resolution;p_{#gamma} (GeV/c);#Deltap/p", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); - fRegistry.add("V0/primary/hPtResolution", "p_{T} resolution;p_{#gamma} (GeV/c);#Deltap_{T}/p_{T}", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.1}}, false); - fRegistry.add("V0/primary/hEtaResolution", "#eta resolution;p_{#gamma} (GeV/c);#Delta#eta", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); - fRegistry.add("V0/primary/hThetaResolution", "#theta resolution;p_{#gamma} (GeV/c);#Delta#theta (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); - fRegistry.add("V0/primary/hPhiResolution", "#varphi resolution;p_{#gamma} (GeV/c);#Delta#varphi (rad.)", kTH2F, {{1000, 0.0f, 10}, {100, 0, 0.01}}, false); fRegistry.add("V0/primary/hNgamma", "Number of true #gamma per collision;N_{#gamma} per event;Number of events", kTH1F, {{101, -0.5f, 100.5f}}); fRegistry.add("V0/primary/hConvPoint_diffX", "conversion point diff X MC;X_{MC} (cm);X_{rec} - X_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); fRegistry.add("V0/primary/hConvPoint_diffY", "conversion point diff Y MC;Y_{MC} (cm);Y_{rec} - Y_{MC} (cm)", kTH2F, {{200, -100, +100}, {100, -50.0f, 50.0f}}, true); @@ -209,22 +202,9 @@ struct PCMQCMC { fRegistry.add("V0/primary/hPtGen_DeltaEta", "photon #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); fRegistry.add("V0/primary/hPtGen_DeltaPhi", "photon #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); fRegistry.add("V0/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); - fRegistry.add("V0/primary/hsPhotonResolution", - "Photon resolution;p_{T};#eta;R_{xy};Z_{conv};Z_{vtx};#Deltap_{T}/p_{T};#Delta#eta;#Delta#phi", - kTHnSparseF, - {{100, 0, 10}, - {80, -1.6, 1.6}, - {100, 0, 100}, - {100, -50, 50}, - {100, -50, 50}, - {200, -1, 1}, - {100, -0.5, 0.5}, - {100, -0.5, 0.5}}, - false); fRegistry.add("V0/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); fRegistry.add("V0/primary/hRxyGen_DeltaPhi", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); fRegistry.add("V0/primary/hRxyGen_DeltaR", "photon #varphi resolution;R_{xy}^{gen} (cm);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{100, 0, 100}, {100, 0, 100}}, true); - fRegistry.add("V0/primary/hsConvVtxZPtR", "z_{vtx} vs p_{T} vs R_{xy};z_{vtx} (cm);p_{T} (GeV/c);R_{xy} (cm)", kTHnSparseF, {{100, -20.0f, +20.0f}, {100, 0.0f, 10.0f}, {100, 0, 100}}, false); 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, 2 * M_PI}, {80, -2, +2}}, false); @@ -253,26 +233,11 @@ struct PCMQCMC { fRegistry.add("V0Leg/primary/hChi2ITS", "chi2/number of ITS clusters", kTH1F, {{100, 0, 10}}, false); fRegistry.add("V0Leg/primary/hITSClusterMap", "ITS cluster map", kTH1F, {{128, -0.5, 127.5}}, false); fRegistry.add("V0Leg/primary/hMeanClusterSizeITS", "mean cluster size ITS; on ITS #times cos(#lambda)", kTH2F, {{1000, 0, 10}, {160, 0, 16}}, false); - fRegistry.add("V0Leg/primary/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {40, -20, 20}}, false); - fRegistry.add("V0Leg/primary/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); - fRegistry.add("V0Leg/primary/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {40, -20, 20}}, false); + // fRegistry.add("V0Leg/primary/hXY", "X vs. Y;X (cm);Y (cm)", kTH2F, {{100, 0, 100}, {40, -20, 20}}, false); + // fRegistry.add("V0Leg/primary/hZX", "Z vs. X;Z (cm);X (cm)", kTH2F, {{200, -100, 100}, {100, 0, 100}}, false); + // fRegistry.add("V0Leg/primary/hZY", "Z vs. Y;Z (cm);Y (cm)", kTH2F, {{200, -100, 100}, {40, -20, 20}}, false); fRegistry.add("V0Leg/primary/hPtGen_DeltaPtOverPtGen", "electron p_{T} resolution;p_{T}^{gen} (GeV/c);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{1000, 0, 10}, {200, -1.0f, 1.0f}}, true); fRegistry.add("V0Leg/primary/hPtGen_DeltaEta", "electron #eta resolution;p_{T}^{gen} (GeV/c);#eta^{rec} - #eta^{gen}", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); - if (cfg_fill_resolution) { - fRegistry.add("V0Leg/primary/hsPhotonResolution", - "Photon resolution;p_{T};#eta;R_{xy};Z_{conv};Z_{vtx};#Deltap_{T}/p_{T};#Delta#eta;#Delta#phi", - kTHnSparseF, - {{100, 0, 10}, - {80, -1.6, 1.6}, - {100, 0, 100}, - {100, -50, 50}, - {100, -50, 50}, - {200, -1, 1}, - {100, -0.5, 0.5}, - {100, -0.5, 0.5}}, - false); - } - fRegistry.add("V0Leg/primary/hPtGen_DeltaPhi", "electron #varphi resolution;p_{T}^{gen} (GeV/c);#varphi^{rec} - #varphi^{gen} (rad.)", kTH2F, {{1000, 0, 10}, {100, -0.5f, 0.5f}}, true); fRegistry.add("V0Leg/primary/hRxyGen_DeltaPtOverPtGen", "photon p_{T} resolution; R_{xy}^{gen} (cm);(p_{T}^{rec} - p_{T}^{gen})/p_{T}^{gen}", kTH2F, {{100, 0, 100}, {200, -1.0f, 1.0f}}, true); fRegistry.add("V0Leg/primary/hRxyGen_DeltaEta", "photon #eta resolution;R_{xy}^{gen} (cm);#eta^{rec} - #eta^{gen}", kTH2F, {{100, 0, 100}, {100, -0.5f, 0.5f}}, true); @@ -330,7 +295,6 @@ struct PCMQCMC { fV0PhotonCut.SetChi2PerClusterITS(-1e+10, pcmcuts.cfg_max_chi2its); fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); fV0PhotonCut.SetDisableITSonly(pcmcuts.cfg_disable_itsonly_track); fV0PhotonCut.SetDisableTPConly(pcmcuts.cfg_disable_tpconly_track); fV0PhotonCut.SetRequireITSTPC(pcmcuts.cfg_require_v0_with_itstpc); @@ -396,33 +360,14 @@ struct PCMQCMC { fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hMassGamma"), v0.v0radius(), v0.mGamma()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsM"), v0.mGamma(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsR"), v0.v0radius(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsConvVtxZPtR"), - v0.vz(), v0.pt(), v0.v0radius()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsX"), v0.vx(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsY"), v0.vy(), v0.chiSquareNDF()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hKFChi2vsZ"), v0.vz(), v0.chiSquareNDF()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPResolution"), v0.p(), getPResolution(v0) / v0.p()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtResolution"), v0.p(), getPtResolution(v0) / v0.pt()); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hEtaResolution"), v0.p(), getEtaResolution(v0)); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hThetaResolution"), v0.p(), getThetaResolution(v0)); - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPhiResolution"), v0.p(), getPhiResolution(v0)); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcphoton.pt(), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcphoton.pt(), v0.eta() - mcphoton.eta()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcphoton.pt(), v0.phi() - mcphoton.phi()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (v0.pt() - mcphoton.pt()) / mcphoton.pt()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaEta"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.eta() - mcphoton.eta()); - if (cfg_fill_resolution) { - fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hsPhotonResolution"), - mcphoton.pt(), - mcphoton.eta(), - std::sqrt(mcleg.vx() * mcleg.vx() + mcleg.vy() * mcleg.vy()), - mcleg.vz(), - v0.vz(), - (v0.pt() - mcphoton.pt()) / mcphoton.pt(), - v0.eta() - mcphoton.eta(), - TVector2::Phi_mpi_pi(v0.phi() - mcphoton.phi())); - } fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPhi"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.phi() - mcphoton.phi()); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaR"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), v0.v0radius() - std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2))); fRegistry.fill(HIST("V0/") + HIST(mcphoton_types[mctype]) + HIST("hConvPoint_diffX"), mcleg.vx(), v0.vx() - mcleg.vx()); @@ -459,25 +404,14 @@ struct PCMQCMC { fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCdEdx"), leg.tpcInnerParam(), leg.tpcSignal()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaEl"), leg.tpcInnerParam(), leg.tpcNSigmaEl()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hTPCNsigmaPi"), leg.tpcInnerParam(), leg.tpcNSigmaPi()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), leg.x(), leg.y()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZX"), leg.z(), leg.x()); - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZY"), leg.z(), leg.y()); + // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hXY"), leg.x(), leg.y()); + // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZX"), leg.z(), leg.x()); + // fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hZY"), leg.z(), leg.y()); auto mcleg = leg.template emmcparticle_as(); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPtOverPtGen"), mcleg.pt(), (leg.pt() - mcleg.pt()) / mcleg.pt()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaEta"), mcleg.pt(), leg.eta() - mcleg.eta()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hPtGen_DeltaPhi"), mcleg.pt(), leg.phi() - mcleg.phi()); fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hRxyGen_DeltaPtOverPtGen"), std::sqrt(std::pow(mcleg.vx(), 2) + std::pow(mcleg.vy(), 2)), (leg.pt() - mcleg.pt()) / mcleg.pt()); - if (cfg_fill_resolution) { - fRegistry.fill(HIST("V0Leg/") + HIST(mcphoton_types[mctype]) + HIST("hsPhotonResolution"), - mcleg.pt(), - mcleg.eta(), - std::sqrt(mcleg.vx() * mcleg.vx() + mcleg.vy() * mcleg.vy()), - mcleg.vz(), - leg.z(), - (leg.pt() - mcleg.pt()) / mcleg.pt(), - leg.eta() - mcleg.eta(), - TVector2::Phi_mpi_pi(leg.phi() - mcleg.phi())); - } 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()); } diff --git a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx index 4b0ce098f6c..ea3dfd23dc1 100644 --- a/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx +++ b/PWGEM/PhotonMeson/Tasks/prefilterPhoton.cxx @@ -14,32 +14,33 @@ // This code produces information on prefilter for photon. // Please write to: daiki.sekihata@cern.ch -#include -#include -#include #include +#include #include +#include +#include // #include "TString.h" -#include "Math/Vector4D.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" // #include "Common/Core/RecoDecay.h" +#include "PWGEM/Dilepton/Utils/PairUtilities.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/PairUtilities.h" + #include "Common/Core/trackUtilities.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" -#include "PWGEM/PhotonMeson/Core/V0PhotonCut.h" -#include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" -#include "PWGEM/PhotonMeson/Core/DalitzEECut.h" -#include "PWGEM/Dilepton/Utils/PairUtilities.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" using namespace o2; using namespace o2::aod; @@ -51,7 +52,7 @@ using namespace o2::aod::pwgem::photonmeson::photonpair; using MyCollisions = soa::Join; using MyCollision = MyCollisions::iterator; -using MyV0Photons = soa::Join; +using MyV0Photons = soa::Join; using MyV0Photon = MyV0Photons::iterator; using MyPrimaryElectrons = soa::Join; @@ -103,7 +104,6 @@ struct prefilterPhoton { Configurable cfg_min_cospa{"cfg_min_cospa", 0.99, "min V0 CosPA"}; Configurable cfg_max_pca{"cfg_max_pca", 1.5, "max distance btween 2 legs"}; Configurable cfg_max_chi2kf{"cfg_max_chi2kf", 1e+10, "max chi2/ndf with KF"}; - Configurable cfg_require_v0_with_correct_xz{"cfg_require_v0_with_correct_xz", false, "flag to select V0s with correct xz"}; Configurable cfg_reject_v0_on_itsib{"cfg_reject_v0_on_itsib", true, "flag to reject V0s on ITSib"}; Configurable cfg_min_ncluster_tpc{"cfg_min_ncluster_tpc", 0, "min ncluster tpc"}; Configurable cfg_min_ncrossedrows{"cfg_min_ncrossedrows", 40, "min ncrossed rows"}; @@ -280,7 +280,6 @@ struct prefilterPhoton { fV0PhotonCut.SetNClustersITS(0, 7); fV0PhotonCut.SetMeanClusterSizeITSob(0.0, 16.0); - fV0PhotonCut.SetIsWithinBeamPipe(pcmcuts.cfg_require_v0_with_correct_xz); } void DefineDileptonCut() diff --git a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx index 2e64bd6ebe2..3f019289988 100644 --- a/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx +++ b/PWGEM/PhotonMeson/Tasks/taskPi0FlowEMC.cxx @@ -14,69 +14,89 @@ /// /// \author M. Hemmer, marvin.hemmer@cern.ch -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/LorentzRotation.h" -#include "Math/Rotation3D.h" -#include "Math/AxisAngle.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/EventPlaneHelper.h" -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/Qvectors.h" -#include "CommonConstants/MathConstants.h" - -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsEMCAL/Constants.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" - -#include "PWGEM/Dilepton/Utils/EMTrackUtilities.h" #include "PWGEM/PhotonMeson/Core/EMCPhotonCut.h" #include "PWGEM/PhotonMeson/Core/EMPhotonEventCut.h" #include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/EventHistograms.h" -#include "PWGEM/PhotonMeson/Utils/NMHistograms.h" +#include "PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/EventPlaneHelper.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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include // IWYU pragma: keep +#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::photonmeson::photonpair; using namespace o2::aod::pwgem::photon; -using namespace o2::aod::pwgem::dilepton::utils; - -enum QvecEstimator { FT0M = 0, - FT0A = 1, - FT0C, - TPCPos, - TPCNeg, - TPCTot }; - -enum CentralityEstimator { None = 0, - CFT0A = 1, - CFT0C, - CFT0M, - NCentralityEstimators + +enum QvecEstimator { + FT0M = 0, + FT0A = 1, + FT0C, + TPCPos, + TPCNeg, + TPCTot +}; + +enum CentralityEstimator { + None = 0, + CFT0A = 1, + CFT0C, + CFT0M, + NCentralityEstimators +}; + +enum Harmonics { + kNone = 0, + kDirect = 1, + kElliptic = 2, + kTriangluar = 3, + kQuadrangular = 4, + kPentagonal = 5, + kHexagonal = 6, + kHeptagonal = 7, + kOctagonal = 8 }; struct TaskPi0FlowEMC { @@ -98,6 +118,8 @@ struct TaskPi0FlowEMC { 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."}; // configurable axis ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {400, 0.0, 0.8}, ""}; @@ -205,6 +227,9 @@ struct TaskPi0FlowEMC { std::vector lookupTable1D; float epsilon = 1.e-8; + // static constexpr + static constexpr int64_t NMinPhotonRotBkg = 3; + // To access the 1D array inline int getIndex(int iEta, int iPhi) { @@ -265,7 +290,7 @@ struct TaskPi0FlowEMC { void init(InitContext&) { - if (harmonic != 2 && harmonic != 3) { + if (harmonic != kElliptic && harmonic != kTriangluar) { LOG(info) << "Harmonic was set to " << harmonic << " but can only be 2 or 3!"; } @@ -492,65 +517,65 @@ struct TaskPi0FlowEMC { switch (detector) { case QvecEstimator::FT0M: - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVec = collision.q2xft0m(); yQVec = collision.q2yft0m(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVec = collision.q3xft0m(); yQVec = collision.q3yft0m(); } break; case QvecEstimator::FT0A: - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVec = collision.q2xft0a(); yQVec = collision.q2yft0a(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVec = collision.q3xft0a(); yQVec = collision.q3yft0a(); } break; case QvecEstimator::FT0C: - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVec = collision.q2xft0c(); yQVec = collision.q2yft0c(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVec = collision.q3xft0c(); yQVec = collision.q3yft0c(); } break; case QvecEstimator::TPCPos: - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVec = collision.q2xbpos(); yQVec = collision.q2ybpos(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVec = collision.q3xbpos(); yQVec = collision.q3ybpos(); } break; case QvecEstimator::TPCNeg: - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVec = collision.q2xbneg(); yQVec = collision.q2ybneg(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVec = collision.q3xbneg(); yQVec = collision.q3ybneg(); } break; case QvecEstimator::TPCTot: - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVec = collision.q2xbtot(); yQVec = collision.q2ybtot(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVec = collision.q3xbtot(); yQVec = collision.q3ybtot(); } break; default: LOG(warning) << "Q vector estimator not valid. Falling back to FT0M"; - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVec = collision.q2xft0m(); yQVec = collision.q2yft0m(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVec = collision.q3xft0m(); yQVec = collision.q3yft0m(); } @@ -565,7 +590,7 @@ struct TaskPi0FlowEMC { { bool isgood = true; for (const auto& QVec : QVecs) { - if (std::fabs(QVec) > 20.f) { + if (std::fabs(QVec) > cfgMaxQVector) { isgood = false; break; } @@ -660,7 +685,7 @@ struct TaskPi0FlowEMC { 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, CollsWithQvecs::iterator const& collision) { // if less than 3 clusters are present skip event since we need at least 3 clusters - if (photons_coll.size() < 3) { + if (photons_coll.size() < NMinPhotonRotBkg) { return; } @@ -759,7 +784,7 @@ struct TaskPi0FlowEMC { 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, CollsWithQvecs::iterator const& collision) { // if less than 3 clusters are present skip event since we need at least 3 clusters - if (photons_coll.size() < 3) { + if (photons_coll.size() < NMinPhotonRotBkg) { return; } float cent = getCentrality(collision); @@ -794,7 +819,7 @@ struct TaskPi0FlowEMC { } ROOT::Math::PtEtaPhiMVector photon3(photon.pt(), photon.eta(), photon.phi(), 0.); if (iCellIDPhoton1 >= 0) { - if (std::fabs((photon1.E() - photon3.E()) / (photon1.E() + photon3.E()) < 0.1)) { // only use symmetric decays + 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())); @@ -812,7 +837,7 @@ struct TaskPi0FlowEMC { } } if (iCellIDPhoton2 >= 0) { - if (std::fabs((photon2.E() - photon3.E()) / (photon2.E() + photon3.E()) < 0.1)) { // only use symmetric decays + 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())); @@ -1138,7 +1163,7 @@ struct TaskPi0FlowEMC { float yQVecBNeg = -999.f; float xQVecBTot = -999.f; float yQVecBTot = -999.f; - if (harmonic == 2) { + if (harmonic == kElliptic) { xQVecFT0a = collision.q2xft0a(); yQVecFT0a = collision.q2yft0a(); xQVecFT0c = collision.q2xft0c(); @@ -1151,7 +1176,7 @@ struct TaskPi0FlowEMC { yQVecBNeg = collision.q2ybneg(); xQVecBTot = collision.q2xbtot(); yQVecBTot = collision.q2ybtot(); - } else if (harmonic == 3) { + } else if (harmonic == kTriangluar) { xQVecFT0a = collision.q3xft0a(); yQVecFT0a = collision.q3yft0a(); xQVecFT0c = collision.q3xft0c(); @@ -1203,7 +1228,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("epReso/hEpResoFT0mTPCneg"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0m, epBNegs))); registry.fill(HIST("epReso/hEpResoFT0mTPCtot"), centrality, std::cos(harmonic * getDeltaPsiInRange(epFT0m, epBTots))); registry.fill(HIST("epReso/hEpResoTPCposTPCneg"), centrality, std::cos(harmonic * getDeltaPsiInRange(epBPoss, epBNegs))); - for (int n = 1; n <= 8; n++) { + for (int n = 1; n <= kOctagonal; n++) { registry.fill(HIST("epReso/hEpCosCoefficientsFT0c"), centrality, n, std::cos(n * epFT0c)); registry.fill(HIST("epReso/hEpSinCoefficientsFT0c"), centrality, n, std::sin(n * epFT0c)); registry.fill(HIST("epReso/hEpCosCoefficientsFT0a"), centrality, n, std::cos(n * epFT0a)); @@ -1323,7 +1348,7 @@ struct TaskPi0FlowEMC { registry.fill(HIST("hClusterCuts"), 5); continue; } - if (std::fabs((v1.E() - v2.E()) / (v1.E() + v2.E()) < 0.1)) { // only use symmetric decays + 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)); } diff --git a/PWGEM/PhotonMeson/Utils/ClusterHistograms.h b/PWGEM/PhotonMeson/Utils/ClusterHistograms.h index bb1a641bbfe..b5f0eb6db85 100644 --- a/PWGEM/PhotonMeson/Utils/ClusterHistograms.h +++ b/PWGEM/PhotonMeson/Utils/ClusterHistograms.h @@ -9,40 +9,51 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// Header file for histograms used in EMC cluster QA -/// \author nicolas.strangmann@cern.ch +/// \file ClusterHistograms.h +/// \brief Header file for histograms used in EMC cluster QA +/// \author N. Strangmann, nicolas.strangmann@cern.ch #ifndef PWGEM_PHOTONMESON_UTILS_CLUSTERHISTOGRAMS_H_ #define PWGEM_PHOTONMESON_UTILS_CLUSTERHISTOGRAMS_H_ +#include +#include + +#include + +#include +#include + +#include + using namespace o2::framework; namespace o2::aod::pwgem::photonmeson::utils::clusterhistogram { -void addClusterHistograms(HistogramRegistry* fRegistry, bool do2DQA) +inline void addClusterHistograms(HistogramRegistry* fRegistry, bool do2DQA) { - fRegistry->add("Cluster/before/hE", "E_{cluster};#it{E}_{cluster} (GeV);#it{N}_{cluster}", kTH1F, {{500, 0.0f, 50}}, true); - fRegistry->add("Cluster/before/hPt", "Transverse momenta of clusters;#it{p}_{T} (GeV/c);#it{N}_{cluster}", 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}", kTH1F, {{51, -0.5f, 50.5f}}, true); - fRegistry->add("Cluster/before/hEtaPhi", "#eta vs #varphi;#eta;#varphi (rad.)", kTH2F, {{280, -0.7f, 0.7f}, {180, 0, 2 * M_PI}}, true); - fRegistry->add("Cluster/before/hNTracks", "Number of tracks considered for TM;#it{N}_{tracks};#it{N}_{cluster}", 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.)", kTH2F, {{200, -0.2f, 0.2f}, {200, -0.2f, 0.2f}}, true); + 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, 2 * M_PI}}, 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); if (do2DQA) { // Check if 2D QA histograms were selected in em-qc task - fRegistry->add("Cluster/before/hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{E}_{cluster} (GeV)", kTH2F, {{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)", kTH2F, {{200, 0, 2}, {200, 0, 20}}, true); - fRegistry->add("Cluster/before/hTime", "Cluster time;#it{t}_{cls} (ns);#it{E}_{cluster} (GeV)", 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)", 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)", kTH2F, {{200, -0.2f, 0.2f}, {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)", kTH2F, {{200, 0., 5.}, {200, 0, 20}}, true); + 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/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); } else { - fRegistry->add("Cluster/before/hNCell", "#it{N}_{cells};N_{cells} (GeV);#it{N}_{cluster}", kTH1F, {{26, -0.5, 25.5}}, true); - fRegistry->add("Cluster/before/hM02", "Long ellipse axis;#it{M}_{02} (cm);#it{N}_{cluster}", kTH1F, {{400, 0, 2}}, true); - fRegistry->add("Cluster/before/hTime", "Cluster time;#it{t}_{cls} (ns);#it{N}_{cluster}", kTH1F, {{600, -150, 150}}, true); - fRegistry->add("Cluster/before/hTrackEOverP", "Energy of cluster divided by momentum of matched tracks;#it{E}_{cluster}/#it{p}_{track} (#it{c})", kTH1F, {{200, 0., 5.}}, true); + 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); + fRegistry->add("Cluster/before/hTime", "Cluster time;#it{t}_{cls} (ns);#it{N}_{cluster}", o2::framework::kTH1F, {{600, -150, 150}}, true); + fRegistry->add("Cluster/before/hTrackEOverP", "Energy of cluster divided by momentum of matched tracks;#it{E}_{cluster}/#it{p}_{track} (#it{c})", o2::framework::kTH1F, {{200, 0., 5.}}, true); } - auto hClusterQualityCuts = fRegistry->add("Cluster/hClusterQualityCuts", "Energy at which clusters are removed by a given cut;;#it{E} (GeV)", kTH2F, {{8, -0.5, 7.5}, {500, 0, 50}}, true); + auto hClusterQualityCuts = fRegistry->add("Cluster/hClusterQualityCuts", "Energy at which clusters are removed by a given cut;;#it{E} (GeV)", o2::framework::kTH2F, {{8, -0.5, 7.5}, {500, 0, 50}}, true); hClusterQualityCuts->GetXaxis()->SetBinLabel(1, "In"); hClusterQualityCuts->GetXaxis()->SetBinLabel(2, "Energy"); hClusterQualityCuts->GetXaxis()->SetBinLabel(3, "NCell"); @@ -56,30 +67,30 @@ void addClusterHistograms(HistogramRegistry* fRegistry, bool do2DQA) } template -void fillClusterHistograms(HistogramRegistry* fRegistry, TCluster cluster, bool do2DQA, float weight = 1.f) +inline void fillClusterHistograms(HistogramRegistry* fRegistry, TCluster cluster, bool do2DQA, float weight = 1.f) { static constexpr std::string_view cluster_types[2] = {"before/", "after/"}; fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hE"), cluster.e(), weight); fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hPt"), cluster.pt(), weight); fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hEtaPhi"), cluster.eta(), cluster.phi(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hNTracks"), cluster.tracketa().size(), weight); - for (size_t itrack = 0; itrack < cluster.tracketa().size(); itrack++) { // Fill TrackEtaPhi histogram with delta phi and delta eta of all tracks saved in the vectors in skimmerGammaCalo.cxx - fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackdEtadPhi"), cluster.tracketa()[itrack] - cluster.eta(), cluster.trackphi()[itrack] - cluster.phi(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[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(cluster_types[cls_id]) + HIST("hTrackdEtadPhi"), cluster.deltaEta()[itrack], cluster.deltaPhi()[itrack], weight); } if (do2DQA) { fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hNCell"), cluster.nCells(), cluster.e(), weight); fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hM02"), cluster.m02(), cluster.e(), weight); fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTime"), cluster.time(), cluster.e(), weight); - for (size_t itrack = 0; itrack < cluster.tracketa().size(); itrack++) { + for (size_t itrack = 0; itrack < cluster.deltaEta().size(); itrack++) { fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackEOverP"), cluster.e() / cluster.trackp()[itrack], cluster.e(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackdEta"), cluster.tracketa()[itrack] - cluster.eta(), cluster.e(), weight); - fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackdPhi"), cluster.trackphi()[itrack] - cluster.phi(), cluster.e(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackdEta"), cluster.deltaEta()[itrack], cluster.e(), weight); + fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackdPhi"), cluster.deltaPhi()[itrack], cluster.e(), weight); } } else { fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hNCell"), cluster.nCells(), weight); fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hM02"), cluster.m02(), weight); fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTime"), cluster.time(), weight); - for (size_t itrack = 0; itrack < cluster.tracketa().size(); itrack++) { + for (size_t itrack = 0; itrack < cluster.deltaEta().size(); itrack++) { fRegistry->fill(HIST("Cluster/") + HIST(cluster_types[cls_id]) + HIST("hTrackEOverP"), cluster.e() / cluster.trackp()[itrack], weight); } } diff --git a/PWGEM/PhotonMeson/Utils/EventHistograms.h b/PWGEM/PhotonMeson/Utils/EventHistograms.h index 49d8ff05cdb..ef5f115e216 100644 --- a/PWGEM/PhotonMeson/Utils/EventHistograms.h +++ b/PWGEM/PhotonMeson/Utils/EventHistograms.h @@ -14,6 +14,9 @@ #ifndef PWGEM_PHOTONMESON_UTILS_EVENTHISTOGRAMS_H_ #define PWGEM_PHOTONMESON_UTILS_EVENTHISTOGRAMS_H_ + +#include "Framework/HistogramRegistry.h" + using namespace o2::framework; namespace o2::aod::pwgem::photonmeson::utils::eventhistogram @@ -35,13 +38,34 @@ void addEventHistograms(HistogramRegistry* fRegistry) hCollisionCounter->GetXaxis()->SetBinLabel(11, "EMC L0 Triggered"); hCollisionCounter->GetXaxis()->SetBinLabel(12, "accepted"); + const AxisSpec axis_cent_ft0m{{0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 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, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 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, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 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)", kTH1F, {{100, -50, +50}}, false); fRegistry->add("Event/before/hMultNTracksPV", "hMultNTracksPV; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); fRegistry->add("Event/before/hMultNTracksPVeta1", "hMultNTracksPVeta1; N_{track} to PV", kTH1F, {{6001, -0.5, 6000.5}}, false); fRegistry->add("Event/before/hMultFT0", "hMultFT0;mult. FT0A;mult. FT0C", kTH2F, {{200, 0, 200000}, {60, 0, 60000}}, false); - fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{110, 0, 110}}, false); - fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{110, 0, 110}}, false); + fRegistry->add("Event/before/hCentFT0A", "hCentFT0A;centrality FT0A (%)", kTH1F, {{axis_cent_ft0a}}, false); + fRegistry->add("Event/before/hCentFT0C", "hCentFT0C;centrality FT0C (%)", kTH1F, {{axis_cent_ft0c}}, false); + fRegistry->add("Event/before/hCentFT0M", "hCentFT0M;centrality FT0M (%)", kTH1F, {{axis_cent_ft0m}}, false); fRegistry->add("Event/before/hCentFT0CvsMultNTracksPV", "hCentFT0CvsMultNTracksPV;centrality FT0C (%);N_{track} to PV", kTH2F, {{110, 0, 110}, {500, 0, 5000}}, false); fRegistry->add("Event/before/hMultFT0CvsMultNTracksPV", "hMultFT0CvsMultNTracksPV;mult. FT0C;N_{track} to PV", kTH2F, {{60, 0, 60000}, {500, 0, 5000}}, false); fRegistry->add("Event/before/hMultFT0CvsOccupancy", "hMultFT0CvsOccupancy;mult. FT0C;N_{track} in time range", kTH2F, {{60, 0, 60000}, {2000, 0, 20000}}, false); diff --git a/PWGEM/PhotonMeson/Utils/HNMUtilities.h b/PWGEM/PhotonMeson/Utils/HNMUtilities.h index bb985686285..80101807641 100644 --- a/PWGEM/PhotonMeson/Utils/HNMUtilities.h +++ b/PWGEM/PhotonMeson/Utils/HNMUtilities.h @@ -158,6 +158,22 @@ void storeGammasInVector(C clusters, V v0s, std::vector& vPhotons, std:: vPhotons.push_back(Photon::fromPxPyPz(v0.px(), v0.py(), v0.pz())); } +/// \brief Store photons from EMC clusters in a vector and possibly add a eta and phi offset for alignment of EMCal clusters +template +void storeGammasInVector(C clusters, std::vector& vPhotons, std::array EMCEtaShift, std::array EMCPhiShift) +{ + vPhotons.clear(); + for (const auto& cluster : clusters) { + float eta = cluster.eta(); + float phi = cluster.phi(); + int smNumber = getSMNumber(eta, phi); + // LOG(info) << "Shifting in sm " << smNumber << ", eta/phi = " << eta << " / " << phi << " to eta/phi = " << eta + EMCEtaShift[getSMNumber(eta, phi)] << " / " << phi + EMCPhiShift[getSMNumber(eta, phi)]; + eta += EMCEtaShift[smNumber]; + phi += EMCPhiShift[smNumber]; + vPhotons.push_back(Photon::fromEtaPhiEnergy(eta, phi, cluster.e())); + } +} + /// \brief Reconstruct light neutral mesons from photons and fill them into the vGGs vector void reconstructGGs(std::vector vPhotons, std::vector& vGGs) { diff --git a/PWGEM/PhotonMeson/Utils/MCUtilities.h b/PWGEM/PhotonMeson/Utils/MCUtilities.h index 19432c66475..c72a8a0b06d 100644 --- a/PWGEM/PhotonMeson/Utils/MCUtilities.h +++ b/PWGEM/PhotonMeson/Utils/MCUtilities.h @@ -15,9 +15,11 @@ #ifndef PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ #define PWGEM_PHOTONMESON_UTILS_MCUTILITIES_H_ -#include -#include #include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" + +#include +#include //_______________________________________________________________________ namespace o2::aod::pwgem::photonmeson::utils::mcutil diff --git a/PWGEM/PhotonMeson/Utils/NMHistograms.h b/PWGEM/PhotonMeson/Utils/NMHistograms.h index 88df03a3aed..8915c6624b5 100644 --- a/PWGEM/PhotonMeson/Utils/NMHistograms.h +++ b/PWGEM/PhotonMeson/Utils/NMHistograms.h @@ -15,10 +15,14 @@ #ifndef PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ #define PWGEM_PHOTONMESON_UTILS_NMHISTOGRAMS_H_ -#include -#include "TF1.h" -#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" #include "PWGEM/PhotonMeson/Utils/MCUtilities.h" +#include "PWGEM/PhotonMeson/Utils/PairUtilities.h" + +#include "Framework/HistogramRegistry.h" + +#include "TF1.h" + +#include using namespace o2::framework; using namespace o2::aod::pwgem::photonmeson::utils::mcutil; diff --git a/PWGEM/PhotonMeson/Utils/PCMUtilities.h b/PWGEM/PhotonMeson/Utils/PCMUtilities.h index 625156cb373..e82d580cfcd 100644 --- a/PWGEM/PhotonMeson/Utils/PCMUtilities.h +++ b/PWGEM/PhotonMeson/Utils/PCMUtilities.h @@ -105,79 +105,79 @@ inline void Vtx_recalculation(o2::base::Propagator* prop, T1 lTrackPos, T2 lTrac Vtx_recalculationParCov(prop, trackPosInformation, trackNegInformation, xyz, matCorr); } //_______________________________________________________________________ -template -float getPtResolution(TV0 const& v0) -{ - float px = v0.px(); - float py = v0.py(); - float pt = v0.pt(); - float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); - float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); - float pxy_err = v0.sigmaPxPy(); - return std::sqrt(std::pow(px / pt * px_err, 2) + std::pow(py / pt * py_err, 2) + 2.f * px / pt * py / pt * pxy_err); -} -//_______________________________________________________________________ -template -float getPhiResolution(TV0 const& v0) -{ - float px = v0.px(); - float py = v0.py(); - float pt = v0.pt(); - float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); - float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); - float pxy_err = v0.sigmaPxPy(); - return std::sqrt(std::pow(px / pt / pt * py_err, 2) + std::pow(py / pt / pt * px_err, 2) - 2.f * px / pt / pt * py / pt / pt * pxy_err); -} -//_______________________________________________________________________ -template -float getThetaResolution(TV0 const& v0) -{ - float px = v0.px(); - float py = v0.py(); - float pz = v0.pz(); - float pt = v0.pt(); - float p = v0.p(); - float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); - float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); - float pz_err = std::sqrt(std::fabs(v0.sigmaPz2())); - float pxy_err = v0.sigmaPxPy(); - float pyz_err = v0.sigmaPyPz(); - float pzx_err = v0.sigmaPzPx(); - return std::sqrt(std::pow(pz * pz / p / p, 2) * (std::pow(px / pz / pt * px_err, 2) + std::pow(py / pz / pt * py_err, 2) + std::pow(pt / pz / pz * pz_err, 2) + 2.f * (px * py / pz / pz / pt / pt * pxy_err - py / pz / pz / pz * pyz_err - px / pz / pz / pz * pzx_err))); -} -//_______________________________________________________________________ -template -float getEtaResolution(TV0 const& v0) -{ - float px = v0.px(); - float py = v0.py(); - float pz = v0.pz(); - float pt = v0.pt(); - float p = v0.p(); - float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); - float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); - float pz_err = std::sqrt(std::fabs(v0.sigmaPz2())); - float pxy_err = v0.sigmaPxPy(); - float pyz_err = v0.sigmaPyPz(); - float pzx_err = v0.sigmaPzPx(); - return std::sqrt(std::pow(1.f / p / pt / pt, 2) * (std::pow(pz * px * px_err, 2) + std::pow(pz * py * py_err, 2) + std::pow(pt * pt * pz_err, 2) + 2.f * (pz * pz * px * py * pxy_err - pt * pt * py * pz * pyz_err - pt * pt * pz * px * pzx_err))); -} -//_______________________________________________________________________ -template -float getPResolution(TV0 const& v0) -{ - float px = v0.px(); - float py = v0.py(); - float pz = v0.pz(); - float p = v0.p(); - float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); - float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); - float pz_err = std::sqrt(std::fabs(v0.sigmaPz2())); - float pxy_err = v0.sigmaPxPy(); - float pyz_err = v0.sigmaPyPz(); - float pzx_err = v0.sigmaPzPx(); - return std::sqrt(std::pow(1.f / p, 2) * (std::pow(px * px_err, 2) + std::pow(py * py_err, 2) + std::pow(pz * pz_err, 2) + 2.f * (px * py * pxy_err + py * pz * pyz_err + pz * px * pzx_err))); -} +// template +// float getPtResolution(TV0 const& v0) +// { +// float px = v0.px(); +// float py = v0.py(); +// float pt = v0.pt(); +// float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); +// float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); +// float pxy_err = v0.sigmaPxPy(); +// return std::sqrt(std::pow(px / pt * px_err, 2) + std::pow(py / pt * py_err, 2) + 2.f * px / pt * py / pt * pxy_err); +// } +// //_______________________________________________________________________ +// template +// float getPhiResolution(TV0 const& v0) +// { +// float px = v0.px(); +// float py = v0.py(); +// float pt = v0.pt(); +// float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); +// float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); +// float pxy_err = v0.sigmaPxPy(); +// return std::sqrt(std::pow(px / pt / pt * py_err, 2) + std::pow(py / pt / pt * px_err, 2) - 2.f * px / pt / pt * py / pt / pt * pxy_err); +// } +// //_______________________________________________________________________ +// template +// float getThetaResolution(TV0 const& v0) +// { +// float px = v0.px(); +// float py = v0.py(); +// float pz = v0.pz(); +// float pt = v0.pt(); +// float p = v0.p(); +// float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); +// float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); +// float pz_err = std::sqrt(std::fabs(v0.sigmaPz2())); +// float pxy_err = v0.sigmaPxPy(); +// float pyz_err = v0.sigmaPyPz(); +// float pzx_err = v0.sigmaPzPx(); +// return std::sqrt(std::pow(pz * pz / p / p, 2) * (std::pow(px / pz / pt * px_err, 2) + std::pow(py / pz / pt * py_err, 2) + std::pow(pt / pz / pz * pz_err, 2) + 2.f * (px * py / pz / pz / pt / pt * pxy_err - py / pz / pz / pz * pyz_err - px / pz / pz / pz * pzx_err))); +// } +// //_______________________________________________________________________ +// template +// float getEtaResolution(TV0 const& v0) +// { +// float px = v0.px(); +// float py = v0.py(); +// float pz = v0.pz(); +// float pt = v0.pt(); +// float p = v0.p(); +// float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); +// float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); +// float pz_err = std::sqrt(std::fabs(v0.sigmaPz2())); +// float pxy_err = v0.sigmaPxPy(); +// float pyz_err = v0.sigmaPyPz(); +// float pzx_err = v0.sigmaPzPx(); +// return std::sqrt(std::pow(1.f / p / pt / pt, 2) * (std::pow(pz * px * px_err, 2) + std::pow(pz * py * py_err, 2) + std::pow(pt * pt * pz_err, 2) + 2.f * (pz * pz * px * py * pxy_err - pt * pt * py * pz * pyz_err - pt * pt * pz * px * pzx_err))); +// } +// //_______________________________________________________________________ +// template +// float getPResolution(TV0 const& v0) +// { +// float px = v0.px(); +// float py = v0.py(); +// float pz = v0.pz(); +// float p = v0.p(); +// float px_err = std::sqrt(std::fabs(v0.sigmaPx2())); +// float py_err = std::sqrt(std::fabs(v0.sigmaPy2())); +// float pz_err = std::sqrt(std::fabs(v0.sigmaPz2())); +// float pxy_err = v0.sigmaPxPy(); +// float pyz_err = v0.sigmaPyPz(); +// float pzx_err = v0.sigmaPzPx(); +// return std::sqrt(std::pow(1.f / p, 2) * (std::pow(px * px_err, 2) + std::pow(py * py_err, 2) + std::pow(pz * pz_err, 2) + 2.f * (px * py * pxy_err + py * pz * pyz_err + pz * px * pzx_err))); +// } //_______________________________________________________________________ //_______________________________________________________________________ #endif // PWGEM_PHOTONMESON_UTILS_PCMUTILITIES_H_ diff --git a/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h b/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h index 6ce678e9c35..f3eac77ca04 100644 --- a/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h +++ b/PWGEM/PhotonMeson/Utils/emcalHistoDefinitions.h @@ -12,9 +12,9 @@ /// \brief commonly used histogram (axis) definitions for emcal in PWGEM /// \author marvin.hemmer@cern.ch -#include +#include -#include "Framework/AnalysisTask.h" +#include #ifndef PWGEM_PHOTONMESON_UTILS_EMCALHISTODEFINITIONS_H_ #define PWGEM_PHOTONMESON_UTILS_EMCALHISTODEFINITIONS_H_ diff --git a/PWGEM/PhotonMeson/Utils/gammaSelectionCuts.h b/PWGEM/PhotonMeson/Utils/gammaSelectionCuts.h deleted file mode 100644 index 341a6c95e38..00000000000 --- a/PWGEM/PhotonMeson/Utils/gammaSelectionCuts.h +++ /dev/null @@ -1,165 +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 cut selection and cut functions for photon candidates -/// \author marvin.hemmer@cern.ch - -#include - -#include "Framework/AnalysisTask.h" -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" - -#ifndef PWGEM_PHOTONMESON_UTILS_GAMMASELECTIONCUTS_H_ -#define PWGEM_PHOTONMESON_UTILS_GAMMASELECTIONCUTS_H_ - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -namespace emccuts -{ -// set the standard cuts -std::vector EMC_minTime = {-20.f}; -std::vector EMC_maxTime = {+25.f}; -std::vector EMC_minM02 = {0.1f}; -std::vector EMC_maxM02 = {0.7f}; -std::vector EMC_minE = {0.7f}; -std::vector EMC_minNCell = {1}; -std::vector> EMC_TM_Eta = {{0.01f, 4.07f, -2.5f}}; -std::vector> EMC_TM_Phi = {{0.015f, 3.65f, -2.f}}; -std::vector EMC_Eoverp = {1.75f}; -} // namespace emccuts -void gatherCutsEMC(float minTime, float maxTime, float minM02, float maxM02, float minE, int minNCell, std::vector TM_Eta, std::vector TM_Phi, float Eoverp) -{ - // insert the configurable values in first position - emccuts::EMC_minTime.insert(emccuts::EMC_minTime.begin(), minTime); - emccuts::EMC_maxTime.insert(emccuts::EMC_maxTime.begin(), maxTime); - emccuts::EMC_minM02.insert(emccuts::EMC_minM02.begin(), minM02); - emccuts::EMC_maxM02.insert(emccuts::EMC_maxM02.begin(), maxM02); - emccuts::EMC_minE.insert(emccuts::EMC_minE.begin(), minE); - emccuts::EMC_minNCell.insert(emccuts::EMC_minNCell.begin(), minNCell); - emccuts::EMC_TM_Eta.insert(emccuts::EMC_TM_Eta.begin(), TM_Eta); - emccuts::EMC_TM_Phi.insert(emccuts::EMC_TM_Phi.begin(), TM_Phi); - emccuts::EMC_Eoverp.insert(emccuts::EMC_Eoverp.begin(), Eoverp); - - // fill up the rest of the vectors to size 64 to ensure no crashes can happen - emccuts::EMC_minTime.resize(64, 0); - emccuts::EMC_maxTime.resize(64, 0); - emccuts::EMC_minM02.resize(64, 0); - emccuts::EMC_maxM02.resize(64, 0); - emccuts::EMC_minE.resize(64, 0); - emccuts::EMC_minNCell.resize(64, 0); - emccuts::EMC_TM_Eta.resize(64, {0, 0, 0}); - emccuts::EMC_TM_Phi.resize(64, {0, 0, 0}); - emccuts::EMC_Eoverp.resize(64, 0); -} - -uint64_t doTimeCutEMC(int iCut, uint64_t cutbit, aod::SkimEMCCluster const& cluster, HistogramRegistry& registry) -{ - uint64_t cut_return = 0; - if (cutbit & ((uint64_t)1 << (uint64_t)iCut)) { // check if current cut should be applied - if (cluster.time() <= emccuts::EMC_maxTime.at(iCut) && cluster.time() >= emccuts::EMC_minTime.at(iCut)) { // check cut itself - cut_return |= (1 << iCut); // set bit of current cut to 1 for passing the cut - } else { - registry.fill(HIST("hCaloCuts_EMC"), 1, iCut); - } - } - return cut_return; -} - -uint64_t doM02CutEMC(int iCut, uint64_t cutbit, aod::SkimEMCCluster const& cluster, HistogramRegistry& registry) -{ - uint64_t cut_return = 0; - if (cutbit & ((uint64_t)1 << (uint64_t)iCut)) { // check if current cut should be applied - if (cluster.m02() <= emccuts::EMC_maxM02.at(iCut) && cluster.m02() >= emccuts::EMC_minM02.at(iCut)) { // check cut itself - cut_return |= (1 << iCut); // set bit of current cut to 1 for passing the cut - } else { - registry.fill(HIST("hCaloCuts_EMC"), 2, iCut); - } - } - return cut_return; -} - -uint64_t doMinECutEMC(int iCut, uint64_t cutbit, aod::SkimEMCCluster const& cluster, HistogramRegistry& registry) -{ - uint64_t cut_return = 0; - if (cutbit & ((uint64_t)1 << (uint64_t)iCut)) { // check if current cut should be applied - if (cluster.e() > emccuts::EMC_minE.at(iCut)) { // check cut itself - cut_return |= (1 << iCut); // set bit of current cut to 1 for passing the cut - } else { - registry.fill(HIST("hCaloCuts_EMC"), 3, iCut); - } - } - return cut_return; -} - -uint64_t doNCellCutEMC(int iCut, uint64_t cutbit, aod::SkimEMCCluster const& cluster, HistogramRegistry& registry) -{ - uint64_t cut_return = 0; - if (cutbit & ((uint64_t)1 << (uint64_t)iCut)) { // check if current cut should be applied - if (cluster.nCells() >= emccuts::EMC_minNCell.at(iCut)) { // check cut itself - cut_return |= (1 << iCut); // set bit of current cut to 1 for passing the cut - } else { - registry.fill(HIST("hCaloCuts_EMC"), 4, iCut); - } - } - return cut_return; -} - -uint64_t doTrackMatchingEMC(int iCut, uint64_t cutbit, aod::SkimEMCCluster const& cluster, aod::SkimEMCMTs const& tracks, HistogramRegistry& registry) -{ - uint64_t cut_return = 0; - double dEta, dPhi; - if (cutbit & ((uint64_t)1 << (uint64_t)iCut)) { // check if current cut should be applied - bool hasMatchedTrack_EMC = false; - for (const auto& track : tracks) { - dEta = track.tracketa() - cluster.eta(); - dPhi = track.trackphi() - cluster.phi(); - if ((fabs(dEta) <= emccuts::EMC_TM_Eta.at(iCut).at(0) + pow(track.trackpt() + emccuts::EMC_TM_Eta.at(iCut).at(1), emccuts::EMC_TM_Eta.at(iCut).at(2))) && - (fabs(dPhi) <= emccuts::EMC_TM_Phi.at(iCut).at(0) + pow(track.trackpt() + emccuts::EMC_TM_Phi.at(iCut).at(1), emccuts::EMC_TM_Phi.at(iCut).at(2))) && - cluster.e() / track.trackp() < emccuts::EMC_Eoverp.at(iCut)) { // check cut itself - hasMatchedTrack_EMC = true; // set bit of current cut to 1 for passing the cut - } - } - if (hasMatchedTrack_EMC) { - registry.fill(HIST("hCaloCuts_EMC"), 5, iCut); - } else { - cut_return |= (1 << iCut); - } - } - return cut_return; -} - -uint64_t doPhotonCutsEMC(uint64_t cutbit, aod::SkimEMCCluster const& cluster, aod::SkimEMCMTs const& tracks, Preslice perEMCClusterMT, HistogramRegistry& registry) -{ - uint64_t cut_return = 0; - auto tracksMatchedEMC = tracks.sliceBy(perEMCClusterMT, cluster.globalIndex()); - for (int iCut = 0; iCut < 64; iCut++) { // loop over max number of cut settings - if (cutbit & ((uint64_t)1 << (uint64_t)iCut)) { // check each cut setting if it is selected - registry.fill(HIST("hClusterEIn"), cluster.e(), iCut); - cut_return = doTimeCutEMC(iCut, cutbit, cluster, registry); - // use cut_return instead of cutbit from here on to only check cut settings that we want to look at - // where the cluster did not fail in the previous cut(s) - cut_return = doM02CutEMC(iCut, cut_return, cluster, registry); - cut_return = doMinECutEMC(iCut, cut_return, cluster, registry); - cut_return = doNCellCutEMC(iCut, cut_return, cluster, registry); - cut_return = doTrackMatchingEMC(iCut, cut_return, cluster, tracksMatchedEMC, registry); - - registry.fill(HIST("hCaloCuts_EMC"), 0, iCut); - if (cut_return & ((uint64_t)1 << (uint64_t)iCut)) { - registry.fill(HIST("hClusterEOut"), cluster.e(), iCut); - registry.fill(HIST("hCaloCuts_EMC"), 6, iCut); - } - } - } - return cut_return; -} - -#endif // PWGEM_PHOTONMESON_UTILS_GAMMASELECTIONCUTS_H_ diff --git a/PWGEM/Tasks/phosPi0.cxx b/PWGEM/Tasks/phosPi0.cxx index a47aaa0d485..d9eca400242 100644 --- a/PWGEM/Tasks/phosPi0.cxx +++ b/PWGEM/Tasks/phosPi0.cxx @@ -14,34 +14,35 @@ /// \author Dmitri Peresunko /// -#include -#include -#include -#include -#include -#include -#include - #include "Common/DataModel/CaloClusters.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" -#include "Framework/ConfigParamSpec.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.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 "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" +#include -#include "PHOSBase/Geometry.h" -#include "CommonDataFormat/InteractionRecord.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPLHCIFData.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod::evsel; @@ -52,7 +53,7 @@ struct PhosPi0 { Configurable skimmedProcessing{"skimmedProcessing", false, "Skimmed dataset processing"}; Configurable trigName{"trigName", "fPHOSPhoton", "name of offline trigger"}; Configurable zorroCCDBpath{"zorroCCDBpath", "/Users/m/mpuccio/EventFiltering/OTS/", "path to the zorro ccdb objects"}; - Configurable evSelTrig{"evSelTrig", aod::evsel::kIsTriggerTVX, "Select events with this trigger"}; + Configurable evSelTrig{"evSelTrig", kTVXinPHOS, "Select events with this trigger"}; Configurable isMC{"isMC", false, "to fill MC histograms"}; Configurable minCluE{"minCluE", 0.3, "Minimum cluster energy for analysis"}; Configurable minCluTime{"minCluTime", -25.e-9, "Min. cluster time"}; @@ -107,14 +108,19 @@ struct PhosPi0 { int mRunNumber = 0; // Current run number int mixedEventBin = 0; // Which list of Mixed use for mixing std::vector mCurEvent; - static constexpr int kMaxMixBins = 20; // maximal number of kinds of events for mixing + static constexpr int kMixBinsZ = 20; + static constexpr int kMixBinsPhi = 6; + static constexpr int kMaxMixBins = kMixBinsZ * kMixBinsPhi + 1; // maximal number of bins of events for mixing: vtx*event plane + hard + static constexpr double kEmixCut = 10.; // minimal clu energy for special hard mixing bin + static constexpr int kHardMixBin = kMaxMixBins - 1; // special hard mixing bin + std::array>, kMaxMixBins> mMixedEvents; std::array>, kMaxMixBins> mAmbMixedEvents; int mPrevMCColId = -1; // mark MC collissions already scanned // fast access to histos TH1* hColl; - TH3 *hReMod, *hMiMod; + TH3 *hReMod, *hMiMod, *hReAsym, *hMiAsym; TH2 *hReAll, *hReDisp, *hReCPV, *hReBoth, *hSignalAll, *hPi0SignalAll, *hPi0SignalCPV, *hPi0SignalDisp, *hPi0SignalBoth, *hMiAll, *hMiDisp, *hMiCPV, *hMiBoth; TH2 *hReOneAll, *hReOneDisp, *hReOneCPV, *hReOneBoth, *hMiOneAll, *hMiOneDisp, *hMiOneCPV, *hMiOneBoth; @@ -154,8 +160,8 @@ struct PhosPi0 { hColl->GetXaxis()->SetBinLabel(4, "T0a&&T0c"); hColl->GetXaxis()->SetBinLabel(5, "kTVXinPHOS"); hColl->GetXaxis()->SetBinLabel(6, "kIsTriggerTVX"); - hColl->GetXaxis()->SetBinLabel(7, "PHOSClu"); - hColl->GetXaxis()->SetBinLabel(8, "PHOSClu&&kTVXinPHOS"); + hColl->GetXaxis()->SetBinLabel(7, "kPHOS"); + hColl->GetXaxis()->SetBinLabel(8, "kPHOS&&kTVXinPHOS"); hColl->GetXaxis()->SetBinLabel(9, "Accepted"); auto h2{std::get>(mHistManager.add("eventsBC", "Number of events per trigger", HistType::kTH1F, {{8, 0., 8.}}))}; @@ -186,6 +192,7 @@ struct PhosPi0 { mHistManager.add("cluCPVOcc", "Cluster with CPV occupancy", HistType::kTH3F, {phiAxis, zAxis, modAxis}); mHistManager.add("cluDispOcc", "Cluster with Disp occupancy", HistType::kTH3F, {phiAxis, zAxis, modAxis}); mHistManager.add("cluBothOcc", "Cluster with Both occupancy", HistType::kTH3F, {phiAxis, zAxis, modAxis}); + mHistManager.add("qvec", "qvector", HistType::kTH2F, {{10, 0, o2::constants::math::PI, "#phi", "#phi (rad)"}, {10, 0., 1., "|q|", "|q|"}}); } hReMod = std::get>(mHistManager.add("mggReModComb", "inv mass per module", @@ -203,6 +210,9 @@ struct PhosPi0 { hReBoth = std::get>(mHistManager.add("mggReBoth", "inv mass for centrality", HistType::kTH2F, {mggAxis, ptAxis})) .get(); + hReAsym = std::get>(mHistManager.add("mggReAsym", "inv mass vs pt vs asym", + HistType::kTH3F, {mggAxis, ptAxis, {10, 0., 1., "asym", "a"}})) + .get(); hReOneAll = std::get>(mHistManager.add("mggReOneAll", "inv mass for centrality", HistType::kTH2F, {mggAxis, ptAxis})) .get(); @@ -262,6 +272,9 @@ struct PhosPi0 { hMiBoth = std::get>(mHistManager.add("mggMiBoth", "inv mass for centrality", HistType::kTH2F, {mggAxis, ptAxis})) .get(); + hMiAsym = std::get>(mHistManager.add("mggMiAsym", "inv mass vs pt vs asym", + HistType::kTH3F, {mggAxis, ptAxis, {10, 0., 1., "asym", "a"}})) + .get(); hMiOneAll = std::get>(mHistManager.add("mggMiOneAll", "inv mass for centrality", HistType::kTH2F, {mggAxis, ptAxis})) .get(); @@ -306,25 +319,28 @@ struct PhosPi0 { /// \brief Process PHOS data void processData(SelCollisions::iterator const& col, aod::CaloClusters const& clusters, + aod::FullTracks const& tracks, aod::BCsWithTimestamps const&) { aod::McParticles const* mcPart = nullptr; - scanAll(col, clusters, mcPart); + scanAll(col, clusters, tracks, mcPart); } PROCESS_SWITCH(PhosPi0, processData, "processData", true); void processMC(SelCollisionsMC::iterator const& col, McClusters const& clusters, + aod::FullTracks const& tracks, aod::McParticles const& mcPart, aod::McCollisions const& /*mcCol*/, aod::BCsWithTimestamps const&) { - scanAll(col, clusters, &mcPart); + scanAll(col, clusters, tracks, &mcPart); } PROCESS_SWITCH(PhosPi0, processMC, "processMC", false); template void scanAll(TCollision& col, TClusters& clusters, + aod::FullTracks const& tracks, aod::McParticles const* mcPart) { mixedEventBin = 0; @@ -341,7 +357,7 @@ struct PhosPi0 { return; /// } } else { - if (!col.selection_bit(evSelTrig)) { + if (!col.alias_bit(evSelTrig)) { return; } } @@ -350,13 +366,14 @@ struct PhosPi0 { const double vtxCut = 10.; double vtxZ = col.posZ(); mHistManager.fill(HIST("vertex"), vtxZ); - bool isColSelected = false; - if constexpr (isMC) { - isColSelected = (col.selection_bit(kIsTriggerTVX) && (clusters.size() > 0)); - } else { - isColSelected = col.selection_bit(evSelTrig) && std::abs(vtxZ) < vtxCut; // col.alias_bit(evSelTrig) - // collision.selection_bit(aod::evsel::kNoTimeFrameBorder); - } + bool isColSelected = col.alias_bit(evSelTrig) && std::abs(vtxZ) < vtxCut; + ; + // if constexpr (isMC) { + // isColSelected = (col.selection_bit(kIsTriggerTVX) && (clusters.size() > 0)); + // } else { + // isColSelected = col.alias_bit(evSelTrig) && std::abs(vtxZ) < vtxCut; // + // // collision.selection_bit(aod::evsel::kNoTimeFrameBorder); + // } if (col.selection_bit(kIsBBT0A) || col.selection_bit(kIsBBT0C)) { hColl->Fill(2.5); @@ -367,58 +384,33 @@ struct PhosPi0 { if (col.alias_bit(kTVXinPHOS)) { hColl->Fill(4.5); } - if (col.selection_bit(kIsTriggerTVX)) { + if (col.alias_bit(kIsTriggerTVX)) { hColl->Fill(5.5); } - if (clusters.size() > 0) { + if (col.alias_bit(kPHOS)) { hColl->Fill(6.5); if (col.alias_bit(kTVXinPHOS)) { hColl->Fill(7.5); } } - // //Event Plane| jet orientation - // if (flag & (kProton | kDeuteron | kTriton | kHe3 | kHe4) || doprocessMC) { /// ignore PID pre-selections for the MC - // if constexpr (std::is_same::value) { - // nuclei::candidates_flow.emplace_back(NucleusCandidateFlow{ - // collision.centFV0A(), - // collision.centFT0M(), - // collision.centFT0A(), - // collision.centFT0C(), - // collision.psiFT0A(), - // collision.multFT0A(), - // collision.psiFT0C(), - // collision.multFT0C(), - // collision.psiTPC(), - // collision.psiTPCL(), - // collision.psiTPCR(), - // collision.multTPC()}); - // } else if constexpr (std::is_same::value) { - // nuclei::candidates_flow.emplace_back(NucleusCandidateFlow{ - // collision.centFV0A(), - // collision.centFT0M(), - // collision.centFT0A(), - // collision.centFT0C(), - // 0.5 * std::atan2(collision.qvecFT0AIm(), collision.qvecFT0ARe()), - // collision.multFT0A(), - // 0.5 * std::atan2(collision.qvecFT0CIm(), collision.qvecFT0CRe()), - // collision.multFT0C(), - // -999., - // 0.5 * std::atan2(collision.qvecBNegIm(), collision.qvecBNegRe()), - // 0.5 * std::atan2(collision.qvecBPosIm(), collision.qvecBPosRe()), - // collision.multTPC()}); - // } - - int mult = 1.; // multiplicity TODO!!! - mixedEventBin = findMixedEventBin(vtxZ, mult); if (!isColSelected) { return; } hColl->Fill(8.5); + int mult = 1.; // multiplicity TODO!!! + std::pair q = evalQvec(tracks); + + // find proper event for mixing + // note, that if one find hard cluster in PHOS later, it will change bin to special one + mixedEventBin = findMixedEventBin(vtxZ, mult, q); + // Fill MC distributions // pion rapidity, pt, phi // secondary pi0s + const double rMax = 0.5; // consider pi0s within this radius as primary + const double yMax = 0.5; // rapidity range if constexpr (isMC) { // check current collision Id for clusters int cluMcBCId = -1; @@ -444,16 +436,16 @@ struct PhosPi0 { if (part.mcCollision().bcId() != col.bcId()) { continue; } - if (part.pdgCode() == 111) { + if (part.pdgCode() == PDG_t::kPi0) { double r = std::sqrt(std::pow(part.vx(), 2) + std::pow(part.vy(), 2)); - if (r < 0.5) { + if (r < rMax) { mHistManager.fill(HIST("hMCPi0RapPrim"), part.y()); } - if (std::abs(part.y()) < .5) { + if (std::abs(part.y()) < yMax) { double pt = part.pt(); mHistManager.fill(HIST("hMCPi0SpAll"), pt); double phiVtx = std::atan2(part.vy(), part.vx()); - if (r > 0.5) { + if (r > rMax) { mHistManager.fill(HIST("hMCPi0SecVtx"), r, phiVtx); } else { mHistManager.fill(HIST("hMCPi0SpPrim"), pt); @@ -482,11 +474,14 @@ struct PhosPi0 { clu.m02() < minM02) { continue; } + if (clu.e() > kEmixCut) { + mixedEventBin = kHardMixBin; + } if (fillQC) { mHistManager.fill(HIST("cluSp"), clu.e(), clu.mod()); if (clu.e() > minOccE) { mHistManager.fill(HIST("cluOcc"), clu.x(), clu.z(), clu.mod()); - if (clu.trackdist() > 2.) { + if (clu.trackdist() > cpvCut) { mHistManager.fill(HIST("cluCPVOcc"), clu.x(), clu.z(), clu.mod()); mHistManager.fill(HIST("cluSpCPV"), clu.e(), clu.mod()); if (testLambda(clu.e(), clu.m02(), clu.m20())) { @@ -529,6 +524,7 @@ struct PhosPi0 { } hReMod->Fill(m, pt, modComb, w); hReAll->Fill(m, pt, w); + hReAsym->Fill(m, pt, std::abs((ph1.e - ph2.e) / (ph1.e + ph2.e)), w); hReOneAll->Fill(m, ph1.pt(), w); hReOneAll->Fill(m, ph2.pt(), w); if (ph1.isCPVOK()) { @@ -550,28 +546,32 @@ struct PhosPi0 { } } // Test time eff - if (std::abs(ph1.time - timeOffset) < 12.5e-9) { // strict cut on first photon - if (std::abs(ph2.time - timeOffset) < 100.e-9) { + const double tofCut1 = 12.5e-9; + const double tofCut2 = 30.e-9; + const double tofCut3 = 50.e-9; + const double tofCut4 = 100.e-9; + if (std::abs(ph1.time - timeOffset) < tofCut1) { // strict cut on first photon + if (std::abs(ph2.time - timeOffset) < tofCut4) { hReTime100->Fill(m, ph2.pt()); - if (std::abs(ph2.time - timeOffset) < 50.e-9) { + if (std::abs(ph2.time - timeOffset) < tofCut3) { hReTime50->Fill(m, ph2.pt()); - if (std::abs(ph2.time - timeOffset) < 30.e-9) { + if (std::abs(ph2.time - timeOffset) < tofCut2) { hReTime30->Fill(m, ph2.pt()); - if (std::abs(ph2.time - timeOffset) < 12.5e-9) { + if (std::abs(ph2.time - timeOffset) < tofCut1) { hReTime12->Fill(m, ph2.pt()); } } } } } - if (std::abs(ph2.time - timeOffset) < 12.5e-9) { // strict cut on first photon - if (std::abs(ph1.time - timeOffset) < 100.e-9) { + if (std::abs(ph2.time - timeOffset) < tofCut1) { // strict cut on first photon + if (std::abs(ph1.time - timeOffset) < tofCut4) { hReTime100->Fill(m, ph1.pt()); - if (std::abs(ph1.time - timeOffset) < 50.e-9) { + if (std::abs(ph1.time - timeOffset) < tofCut3) { hReTime50->Fill(m, ph1.pt()); - if (std::abs(ph1.time - timeOffset) < 30.e-9) { + if (std::abs(ph1.time - timeOffset) < tofCut2) { hReTime30->Fill(m, ph1.pt()); - if (std::abs(ph1.time - timeOffset) < 12.5e-9) { + if (std::abs(ph1.time - timeOffset) < tofCut1) { hReTime12->Fill(m, ph1.pt()); } } @@ -584,7 +584,7 @@ struct PhosPi0 { int cp = commonParentPDG(ph1.label, ph2.label, mcPart); if (cp != 0) { hSignalAll->Fill(m, pt, w); - if (cp == 111) { + if (cp == PDG_t::kPi0) { isPi0 = true; hPi0SignalAll->Fill(m, pt, w); } @@ -633,6 +633,7 @@ struct PhosPi0 { } hMiMod->Fill(m, pt, modComb, w); hMiAll->Fill(m, pt, w); + hMiAsym->Fill(m, pt, std::abs((ph1.e - ph2.e) / (ph1.e + ph2.e)), w); hMiOneAll->Fill(m, ph1.pt(), w); hMiOneAll->Fill(m, ph2.pt(), w); if (ph1.isCPVOK()) { @@ -681,9 +682,10 @@ struct PhosPi0 { mixedEventBin = 0; mHistManager.fill(HIST("eventsBC"), 0.); - double vtxZ = 0; // no vtx info - int mult = 1.; // multiplicity TODO!!! - mixedEventBin = findMixedEventBin(vtxZ, mult); + double vtxZ = 0; // no vtx info + int mult = 1.; // multiplicity TODO!!! + std::pair q{0, 0}; // fake q-vector as no tracks + mixedEventBin = findMixedEventBin(vtxZ, mult, q); if (!isSelected) { return; @@ -709,7 +711,7 @@ struct PhosPi0 { mHistManager.fill(HIST("cluSp"), clu.e(), clu.mod()); if (clu.e() > minOccE) { mHistManager.fill(HIST("cluOcc"), clu.x(), clu.z(), clu.mod()); - if (clu.trackdist() > 2.) { + if (clu.trackdist() > cpvCut) { mHistManager.fill(HIST("cluCPVOcc"), clu.x(), clu.z(), clu.mod()); mHistManager.fill(HIST("cluSpCPV"), clu.e(), clu.mod()); if (testLambda(clu.e(), clu.m02(), clu.m20())) { @@ -809,7 +811,7 @@ struct PhosPi0 { if (d == 1) { return 3 + std::min(m1, m2); } - if (d == 2) { + if (d == 2) { // o2-linter: disable=magic-number (algoritm value) return 6 + std::min(m1, m2); } return 9; @@ -819,11 +821,11 @@ struct PhosPi0 { { // Parameterization for full dispersion // Parameterizatino for full dispersion - float l2Mean = 1.53126 + 9.50835e+06 / (1. + 1.08728e+07 * pt + 1.73420e+06 * pt * pt); - float l1Mean = 1.12365 + 0.123770 * std::exp(-pt * 0.246551) + 5.30000e-03 * pt; - float l2Sigma = 6.48260e-02 + 7.60261e+10 / (1. + 1.53012e+11 * pt + 5.01265e+05 * pt * pt) + 9.00000e-03 * pt; - float l1Sigma = 4.44719e-04 + 6.99839e-01 / (1. + 1.22497e+00 * pt + 6.78604e-07 * pt * pt) + 9.00000e-03 * pt; - float c = -0.35 - 0.550 * std::exp(-0.390730 * pt); + float l2Mean = 1.53126 + 9.50835e+06 / (1. + 1.08728e+07 * pt + 1.73420e+06 * pt * pt); // o2-linter: disable=magic-number (fixed parameterization) + float l1Mean = 1.12365 + 0.123770 * std::exp(-pt * 0.246551) + 5.30000e-03 * pt; // o2-linter: disable=magic-number (fixed parameterization) + float l2Sigma = 6.48260e-02 + 7.60261e+10 / (1. + 1.53012e+11 * pt + 5.01265e+05 * pt * pt) + 9.00000e-03 * pt; // o2-linter: disable=magic-number (fixed parameterization) + float l1Sigma = 4.44719e-04 + 6.99839e-01 / (1. + 1.22497e+00 * pt + 6.78604e-07 * pt * pt) + 9.00000e-03 * pt; // o2-linter: disable=magic-number (fixed parameterization) + float c = -0.35 - 0.550 * std::exp(-0.390730 * pt); // o2-linter: disable=magic-number (fixed parameterization) return 0.5 * (l1 - l1Mean) * (l1 - l1Mean) / l1Sigma / l1Sigma + 0.5 * (l2 - l2Mean) * (l2 - l2Mean) / l2Sigma / l2Sigma + @@ -831,17 +833,27 @@ struct PhosPi0 { 4.; } //_____________________________________________________________________________ - int findMixedEventBin(double vtxZ, double /*mult */) + int findMixedEventBin(double vtxZ, double /*mult*/, std::pair& q) { // calculate index for event mixing const double zwidth = 1.; // Width of zvtx bin - int res = static_cast((vtxZ + 10.) / zwidth); - - if (res < 0) - return 0; - if (res >= kMaxMixBins) - return kMaxMixBins - 1; - return res; + int iz = static_cast((vtxZ + 10.) / zwidth); + + if (iz < 0) + iz = 0; + if (iz >= kMixBinsZ) + iz = kMixBinsZ - 1; + + // event plane orientation + double phi = 0.5 * std::atan2(q.second, q.first); // 1/2 due to second order flow harmonic + while (phi < 0) + phi += o2::constants::math::PI; + while (phi > o2::constants::math::PI) + phi -= o2::constants::math::PI; + int iphi = static_cast(kMixBinsPhi * phi / o2::constants::math::PI); + mHistManager.fill(HIST("qvec"), phi, std::sqrt(q.first * q.first + q.second * q.second)); + + return iz * iphi; } //---------------------------------------- int commonParentPDG(int lab1, int lab2, aod::McParticles const* mcParticles) @@ -857,13 +869,16 @@ struct PhosPi0 { return mcParticles->iteratorAt(iparent1).pdgCode(); } auto parent2 = mcParticles->iteratorAt(iparent2); - if (parent2.mothersIds().size() == 0 || parent2.pdgCode() == 21 || std::abs(parent2.pdgCode()) < 11 || std::abs(parent2.pdgCode()) > 5000) { // no parents, parent not quark/gluon, strings + // no parents, parent not quark/gluon, strings + if (parent2.mothersIds().size() == 0 || parent2.pdgCode() == 21 || // o2-linter: disable=pdg/explicit-code (no code) o2-linter: disable=magic-number (pdg value) + std::abs(parent2.pdgCode()) < 11 || std::abs(parent2.pdgCode()) > 5000) { // o2-linter: disable=pdg/explicit-code (no code) o2-linter: disable=magic-number (pdg value) break; } iparent2 = parent2.mothersIds()[0]; } auto parent1 = mcParticles->iteratorAt(iparent1); - if (parent1.mothersIds().size() == 0 || parent1.pdgCode() == 21 || std::abs(parent1.pdgCode()) < 11 || std::abs(parent1.pdgCode()) > 5000) { // no parents, parent not quark/gluon, strings + // no parents, parent not quark/gluon, strings + if (parent1.mothersIds().size() == 0 || parent1.pdgCode() == 21 || std::abs(parent1.pdgCode()) < 11 || std::abs(parent1.pdgCode()) > 5000) { // o2-linter: disable=pdg/explicit-code (no code) o2-linter: disable=magic-number (pdg value) return 0; } iparent1 = parent1.mothersIds()[0]; @@ -879,24 +894,24 @@ struct PhosPi0 { if (tofEffParam == 0) { return 1.; } - if (tofEffParam == 1) { // Run2 100 ns + if (tofEffParam == 1) { // Run2 100 ns //o2-linter: disable=magic-number (local parameterization) // parameterization 01.08.2020 - if (en > 1.1) + if (en > 1.1) // o2-linter: disable=magic-number (local parameterization) en = 1.1; - if (en < 0.11) + if (en < 0.11) // o2-linter: disable=magic-number (local parameterization) en = 0.11; - return std::exp((-1.15295e+05 + 2.26754e+05 * en - 1.26063e+05 * en * en + en * en * en) / - (1. - 3.16443e+05 * en + 3.68044e+06 * en * en + en * en * en)); + return std::exp((-1.15295e+05 + 2.26754e+05 * en - 1.26063e+05 * en * en + en * en * en) / // o2-linter: disable=magic-number (local parameterization) + (1. - 3.16443e+05 * en + 3.68044e+06 * en * en + en * en * en)); // o2-linter: disable=magic-number (local parameterization) } - if (tofEffParam == 2) { // Run2 30 ns - if (en > 1.6) + if (tofEffParam == 2) { // Run2 30 ns //o2-linter: disable=magic-number (kind of TOF parameterization) + if (en > 1.6) // o2-linter: disable=magic-number (local parameterization) en = 1.6; - return 1. / (1. + std::exp((4.83230e+01 - 8.89758e+01 * en + 1.10897e+03 * en * en - 5.73755e+03 * en * en * en - - 1.43777e+03 * en * en * en * en) / - (1. - 1.23667e+02 * en + 1.07255e+03 * en * en + 5.87221e+02 * en * en * en))); + return 1. / (1. + std::exp((4.83230e+01 - 8.89758e+01 * en + 1.10897e+03 * en * en - 5.73755e+03 * en * en * en - // o2-linter: disable=magic-number (local parameterization) + 1.43777e+03 * en * en * en * en) / // o2-linter: disable=magic-number (local parameterization) + (1. - 1.23667e+02 * en + 1.07255e+03 * en * en + 5.87221e+02 * en * en * en))); // o2-linter: disable=magic-number (local parameterization) } - if (tofEffParam == 2) { // Run2 12.5 ns - if (en < 4.6) { + if (tofEffParam == 3) { // Run2 12.5 ns //o2-linter: disable=magic-number (local parameterization) + if (en < 4.6) { // o2-linter: disable=magic-number (local parameterization) return std::exp(3.64952e-03 * (-5.80032e+01 - 1.53442e+02 * en + 1.30994e+02 * en * en + -3.53094e+01 * en * en * en + en * en * en * en) / (-7.75638e-02 + 8.64761e-01 * en + 1.22320e+00 * en * en - 1.00177e+00 * en * en * en + en * en * en * en)); @@ -907,6 +922,30 @@ struct PhosPi0 { } return 1.; } + //_____________________________________________________________________________ + std::pair evalQvec(aod::FullTracks const& tracks) + { + // calculate approximate q-vector for event + const int ord = 2; // flow order + std::pair q{0, 0}; + int ntr = 0; + for (const auto& track : tracks) { + if (!track.has_collision()) { // ignore orphan tracks without collision + continue; + } + // if (!track.isGlobalTrack()) { // only global tracks + // continue; + // } + q.first += std::cos(ord * track.phi()); + q.second += std::sin(ord * track.phi()); + ntr++; + } + if (ntr > 0) { + q.first /= ntr; + q.second /= ntr; + } + return q; + } }; o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& cfgc) diff --git a/PWGHF/Core/CentralityEstimation.h b/PWGHF/Core/CentralityEstimation.h index e575e11aa57..bd1746c4604 100644 --- a/PWGHF/Core/CentralityEstimation.h +++ b/PWGHF/Core/CentralityEstimation.h @@ -16,7 +16,7 @@ #ifndef PWGHF_CORE_CENTRALITYESTIMATION_H_ #define PWGHF_CORE_CENTRALITYESTIMATION_H_ -#include +#include namespace o2::hf_centrality { diff --git a/PWGHF/Core/DecayChannels.h b/PWGHF/Core/DecayChannels.h index f56e8ce1005..0398afed1c2 100644 --- a/PWGHF/Core/DecayChannels.h +++ b/PWGHF/Core/DecayChannels.h @@ -35,23 +35,26 @@ namespace hf_cand_2prong /// @brief 2-prong candidates: main channels enum DecayChannelMain : int8_t { // D0 - D0ToPiK = 1, // π+ K− - D0ToPiKPi0, // π+ K− π0 - D0ToPiPi, // π+ π− - D0ToPiPiPi0, // π+ π− π0 - D0ToKK, // K+ K− + D0ToPiK = 1, // π+ K− + D0ToPiKPi0 = 2, // π+ K− π0 + D0ToPiPi = 3, // π+ π− + D0ToPiPiPi0 = 4, // π+ π− π0 + D0ToKK = 5, // K+ K− + // J/ψ + JpsiToEE = 6, // e+ e− + JpsiToMuMu = 7, // μ+ μ− // - LastChannelMain + NChannelsMain = JpsiToMuMu // last channel }; /// @brief 2-prong candidates: resonant channels enum DecayChannelResonant : int8_t { // D0 D0ToRhoplusPi = 1, // ρ+ π− - D0ToRhoplusK, // ρ+ K− - D0ToKstar0Pi0, // anti-K*0 π0 - D0ToKstarPi, // K*− π+ + D0ToRhoplusK = 2, // ρ+ K− + D0ToKstar0Pi0 = 3, // anti-K*0 π0 + D0ToKstarPi = 4, // K*− π+ // - LastChannelResonant + NChannelsResonant = D0ToKstarPi // last channel }; } // namespace hf_cand_2prong @@ -60,57 +63,73 @@ namespace hf_cand_3prong /// @brief 3-prong candidates: main channels enum DecayChannelMain : int8_t { // D+ - DplusToPiKPi = 1, // π+ K− π+ - DplusToPiKPiPi0, // π+ K− π+ π0 - DplusToPiPiPi, // π+ π− π+ - DplusToPiKK, // π+ K− K+ + DplusToPiKPi = 1, // π+ K− π+ + DplusToPiKPiPi0 = 2, // π+ K− π+ π0 + DplusToPiPiPi = 3, // π+ π− π+ + DplusToPiKK = 4, // π+ K− K+ // Ds+ - DsToPiKK, // π+ K− K+ - DsToPiKKPi0, // π+ K− K+ π0 - DsToPiPiK, // π+ π− K+ - DsToPiPiPi, // π+ π− π+ - DsToPiPiPiPi0, // π+ π− π+ π0 + DsToPiKK = 5, // π+ K− K+ + DsToPiKKPi0 = 6, // π+ K− K+ π0 + DsToPiPiK = 7, // π+ π− K+ + DsToPiPiPi = 8, // π+ π− π+ + DsToPiPiPiPi0 = 9, // π+ π− π+ π0 // D*+ - DstarToPiKPi, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPi = 10, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPiPi0 = 11, // π+ K− π+ π0 + DstarToPiKPiPi0Pi0 = 12, // π+ K− π+ π0 π0 + DstarToPiKK = 13, // π+ K− K+ + DstarToPiKKPi0 = 14, // π+ K− K+ π0 + DstarToPiPiPi = 15, // π+ π− π+ + DstarToPiPiPiPi0 = 16, // π+ π− π+ π0 // Λc+ - LcToPKPi, // p K− π+ - LcToPKPiPi0, // p K− π+ π0 - LcToPPiPi, // p π− π+ - LcToPKK, // p K− K+ + LcToPKPi = 17, // p K− π+ + LcToPKPiPi0 = 18, // p K− π+ π0 + LcToPPiPi = 19, // p π− π+ + LcToPKK = 20, // p K− K+ // Ξc+ - XicToPKPi, // p K− π+ - XicToPKK, // p K− K+ - XicToSPiPi, // Σ+ π− π+ + XicToPKPi = 21, // p K− π+ + XicToPKK = 22, // p K− K+ + XicToSPiPi = 23, // Σ+ π− π+ // - LastChannelMain + NChannelsMain = XicToSPiPi // last channel }; /// @brief 3-prong candidates: resonant channels enum DecayChannelResonant : int8_t { // D+ - DplusToPhiPi = 1, // φ π+ - DplusToKstar0K, // anti-K*0 K+ - DplusToKstar1430_0K, // anti-K*0(1430) K+ - DplusToRho0Pi, // ρ0 π+ - DplusToF2_1270Pi, // f2(1270) π+ + DplusToPhiPi = 1, // φ π+ + DplusToKstar0K = 2, // anti-K*0 K+ + DplusToKstar1430_0K = 3, // anti-K*0(1430) K+ + DplusToRho0Pi = 4, // ρ0 π+ + DplusToF2_1270Pi = 5, // f2(1270) π+ // Ds+ - DsToPhiPi, // φ π+ - DsToPhiRhoplus, // φ ρ+ - DsToKstar0K, // anti-K*0 K+ - DsToKstar0Pi, // anti-K*0 π+ - DsToRho0Pi, // ρ0 π+ - DsToRho0K, // ρ0 K+ - DsToF2_1270Pi, // f2(1270) π+ - DsToF0_1370K, // f0(1370) K+ - DsToEtaPi, // η π+ + DsToPhiPi = 6, // φ π+ + DsToPhiRhoplus = 7, // φ ρ+ + DsToKstar0K = 8, // anti-K*0 K+ + DsToKstar0Pi = 9, // anti-K*0 π+ + DsToRho0Pi = 10, // ρ0 π+ + DsToRho0K = 11, // ρ0 K+ + DsToF2_1270Pi = 12, // f2(1270) π+ + DsToF0_1370K = 13, // f0(1370) K+ + DsToEtaPi = 14, // η π+ + // D*+ + DstarToD0ToRhoplusPi = 15, // ρ+ π− + DstarToD0ToRhoplusK = 16, // ρ+ K− + DstarToD0ToKstar0Pi0 = 17, // anti-K*0 π0 + DstarToD0ToKstarPi = 18, // K*− π+ + DstarToDplusToPhiPi = 19, // φ π+ + DstarToDplusToKstar0K = 20, // anti-K*0 K+ + DstarToDplusToKstar1430_0K = 21, // anti-K*0(1430) K+ + DstarToDplusToRho0Pi = 22, // ρ0 π+ + DstarToDplusToF2_1270Pi = 23, // f2(1270) π+ // Λc+ - LcToPKstar0, // p K*0(892) - LcToDeltaplusplusK, // Δ++ K− - LcToL1520Pi, // Λ(1520) π+ + LcToPKstar0 = 24, // p anti-K*0(892) + LcToDeltaplusplusK = 25, // Δ++ K− + LcToL1520Pi = 26, // Λ(1520) π+ // Ξc+ - XicToPKstar0, // p anti-K*0(892) - XicToPPhi, // p φ + XicToPKstar0 = 27, // p anti-K*0(892) + XicToPPhi = 28, // p φ // - LastChannelResonant + NChannelsResonant = XicToPPhi // last channel }; } // namespace hf_cand_3prong @@ -119,10 +138,10 @@ namespace hf_cand_dstar /// @brief D*+ candidates: main channels enum DecayChannelMain : int8_t { // D*+ - DstarToPiKPi = 1, // π+ K− π+ (from [(D0 → π+ K−) π+]) - DstarToPiKPiPi0, // π+ K− π+ π0 (from [(D0 → π+ K− π0) π+] or [(D+ → π+ K− π+) π0]) + DstarToPiKPi = 1, // π+ K− π+ (from [(D0 → π+ K−) π+]) + DstarToPiKPiPi0 = 2, // π+ K− π+ π0 (from [(D0 → π+ K− π0) π+] or [(D+ → π+ K− π+) π0]) // - LastChannelMain + NChannelsMain = DstarToPiKPiPi0 // last channel }; } // namespace hf_cand_dstar @@ -131,50 +150,112 @@ namespace hf_cand_beauty /// @brief beauty candidates: main channels enum DecayChannelMain : int8_t { // B0 - B0ToDminusPi = 1, // D− π+ - B0ToDminusPiPi0, // D− π+ π0 - B0ToDminusPiGamma, // D− π+ γ0 - B0ToDminusK, // D− K+ - B0ToD0PiPi, // anti-D0 π+ π− + B0ToDminusPi = 1, // D− π+ + B0ToDminusPiPi0 = 2, // D− π+ π0 + B0ToDminusPiGamma = 3, // D− π+ γ0 + B0ToDminusK = 4, // D− K+ + B0ToD0PiPi = 5, // anti-D0 π+ π− + B0ToDsPi = 19, // Ds− π+ // Bs0 - BsToDsPi, // Ds− π+ - BsToDsPiPi0, // Ds− π+ π0 - BsToDsPiGamma, // Ds− π+ γ0 - BsToDsK, // Ds− K+ + BsToDsPi = 6, // Ds− π+ + BsToDsPiPi0 = 7, // Ds− π+ π0 + BsToDsPiGamma = 8, // Ds− π+ γ0 + BsToDsK = 9, // Ds− K+ // Λb0 - LbToLcPi, // Λc+ π− - LbToLcPiPi0, // Λc+ π− π0 - LbToLcPiGamma, // Λc+ π− γ0 - LbToLcK, // Λc+ K− - LbToLcKPi0, // Λc+ K− π0 + LbToLcPi = 10, // Λc+ π− + LbToLcPiPi0 = 11, // Λc+ π− π0 + LbToLcPiGamma = 12, // Λc+ π− γ0 + LbToLcK = 13, // Λc+ K− + LbToLcKPi0 = 14, // Λc+ K− π0 // B+ - BplusToD0Pi, // anti-D0 π+ - BplusToD0PiPi0, // anti-D0 π+ π0 - BplusToD0PiGamma, // anti-D0 π+ γ0 - BplusToD0K, // anti-D0 K+ + BplusToD0Pi = 15, // anti-D0 π+ + BplusToD0PiPi0 = 16, // anti-D0 π+ π0 + BplusToD0PiGamma = 17, // anti-D0 π+ γ0 + BplusToD0K = 18, // anti-D0 K+ // - LastChannelMain + NChannelsMain = B0ToDsPi // last channel }; /// @brief beauty candidates: resonant channels enum DecayChannelResonant : int8_t { // B0 B0ToDminusRhoplus = 1, // D− ρ+ - B0ToDstarminusPi, // D*− π+ + B0ToDstarminusPi = 2, // D*− π+ + // Bs0 + BsToDsRhoplus = 3, // Ds− ρ+ + BsToDsstarPi = 4, // Ds*− π+ + // Λb0 + LbToLcRhoplus = 5, // Λc+ ρ− + LbToScPi = 6, // Σc+ π− + LbToScK = 7, // Σc+ K− + LbToSc0Pi0 = 8, // Σc0 π0 + // B+ + BplusToD0Rhoplus = 9, // anti-D0 ρ+ + BplusToDstar0Pi = 10, // anti-D*0 π+ + // + NChannelsResonant = BplusToDstar0Pi // last channel +}; +/// @brief beauty candidates: beauty to J/ψ decay channels +enum DecayChannelToJpsiMain : int8_t { + // B0 + B0ToJpsiPiK = 1, // J/ψ π− K+ // Bs0 - BsToDsRhoplus, // Ds− ρ+ - BsToDsstarPi, // Ds*− π+ + BsToJpsiKK = 2, // J/ψ K+ K− // Λb0 - LbToLcRhoplus, // Λc+ ρ− - LbToScPi, // Σc+ π− - LbToScK, // Σc+ K− - LbToSc0Pi0, // Σc0 π0 + LbToJpsiPK = 3, // J/ψ p K− // B+ - BplusToD0Rhoplus, // anti-D0 ρ+ - BplusToDstar0Pi, // anti-D*0 π+ + BplusToJpsiK = 4, // J/ψ K+ + // Bc+ + BcToJpsiPi = 5, // J/ψ π+ + // + NChannelsToJpsiMain = BcToJpsiPi // last channel +}; +/// @brief beauty candidates: beauty to J/ψ resonant decay channels +enum DecayChannelToJpsiResonant : int8_t { + // B0 + B0ToJpsiKstar0 = 1, // J/ψ K*0(892) + // Bs0 + BsToJpsiPhi = 2, // J/ψ φ // - LastChannelResonant + NChannelsToJpsiResonant = BsToJpsiPhi // last channel }; } // namespace hf_cand_beauty + +namespace hf_cand_reso +{ +/// @brief resonance candidates: main channels +enum DecayChannelMain : int8_t { + // D1(2420)0 + D1zeroToDstarPi = 1, // D*+ π- + // D2*(2460)0 + D2starzeroToDplusPi = 2, // D+ π− + D2starzeroToDstarPi = 3, // D*+ π- + // D2*(2460)+ + D2starplusToD0Pi = 4, // D0 π+ + // Ds1(2536)+ + Ds1ToDstarK0s = 5, // D*+ K0s + // Ds2*(2573)+ + Ds2starToD0Kplus = 6, // D0 K+ + Ds2starToDplusK0s = 7, // D+ K0s + Ds2starToDstarK0s = 8, // D*+ K0s + // Ds1*(2700)+ + Ds1star2700ToDstarK0s = 9, // D*+ K0s + // Ds1*(2860)+ + Ds1star2860ToDstarK0s = 10, // D*+ K0s + // Ds3*(2860)+ + Ds3star2860ToDstarK0s = 11, // D*+ K0s + // Xic(3055)0 + Xic3055zeroToD0Lambda = 12, // D0 Λ + // Xic(3055)+ + Xic3055plusToDplusLambda = 13, // D+ Λ + // Xic(3080)0 + Xic3080zeroToD0Lambda = 14, // D0 Λ + // Xic(3080)+ + Xic3080plusToDplusLambda = 15, // D+ Λ + // D*+ + DstarToD0Pi = 16, // D0 π+ + NChannelsMain = DstarToD0Pi // last channel +}; +} // namespace hf_cand_reso } // namespace o2::hf_decay #endif // PWGHF_CORE_DECAYCHANNELS_H_ diff --git a/PWGHF/Core/HfHelper.h b/PWGHF/Core/HfHelper.h index 3f991854956..41239c48179 100644 --- a/PWGHF/Core/HfHelper.h +++ b/PWGHF/Core/HfHelper.h @@ -17,21 +17,22 @@ #ifndef PWGHF_CORE_HFHELPER_H_ #define PWGHF_CORE_HFHELPER_H_ -#include -#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.h" #include #include +#include +#include // IWYU pragma: keep (do not replace with Math/Vector4Dfwd.h) +#include + #include #include #include -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelectorPID.h" - -#include "PWGHF/Utils/utilsAnalysis.h" - class HfHelper { public: @@ -173,6 +174,12 @@ class HfHelper return candidate.m(std::array{o2::constants::physics::MassD0, o2::constants::physics::MassPiPlus}); } + template + auto invMassBplusToJpsiK(const T& candidate) + { + return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); + } + template auto cosThetaStarBplus(const T& candidate) { @@ -659,6 +666,12 @@ class HfHelper return candidate.m(std::array{o2::constants::physics::MassDSBar, o2::constants::physics::MassPiPlus}); } + template + auto invMassBsToJpsiPhi(const T& candidate) + { + return candidate.m(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + } + template auto cosThetaStarBs(const T& candidate) { @@ -784,8 +797,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of B0 candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of B0 candidate passes all selections - template - bool selectionB0ToDPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionB0ToDPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; @@ -805,10 +817,10 @@ class HfHelper template bool selectionBplusToD0PiTopol(const T1& candBp, const T2& cuts, const T3& binsPt) { - auto ptcandBp = candBp.pt(); + auto ptCandBp = candBp.pt(); auto ptPi = RecoDecay::pt(candBp.pxProng1(), candBp.pyProng1()); - int pTBin = o2::analysis::findBin(binsPt, ptcandBp); + int pTBin = o2::analysis::findBin(binsPt, ptCandBp); if (pTBin == -1) { return false; } @@ -860,8 +872,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of B+ candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of B+ candidate passes all selections - template - bool selectionBplusToD0PiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionBplusToD0PiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; @@ -873,6 +884,105 @@ class HfHelper return true; } + // Apply topological cuts as defined in SelectorCuts.h + /// \param candBp B+ candidate + /// \param cuts B+ candidate selection per pT bin + /// \param binsPt pT bin limits + /// \return true if candidate passes all selections + template + bool selectionBplusToJpsiKTopol(const T1& candBp, const T2& cuts, const T3& binsPt) + { + auto ptCandBp = candBp.pt(); + auto mCandBp = invMassBplusToJpsiK(candBp); + auto ptJpsi = RecoDecay::pt(candBp.pxProng0(), candBp.pyProng0()); + auto ptKa = RecoDecay::pt(candBp.pxProng1(), candBp.pyProng1()); + auto candJpsi = candBp.jpsi(); + float pseudoPropDecLen = candBp.decayLengthXY() * mCandBp / ptCandBp; + + int binPt = o2::analysis::findBin(binsPt, ptCandBp); + if (binPt == -1) { + return false; + } + + // B+ mass cut + if (std::abs(mCandBp - o2::constants::physics::MassBPlus) > cuts->get(binPt, "m")) { + return false; + } + + // kaon pt + if (ptKa < cuts->get(binPt, "pT K")) { + return false; + } + + // J/Psi pt + if (ptJpsi < cuts->get(binPt, "pT J/Psi")) { + return false; + } + + // J/Psi mass + if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) < cuts->get(binPt, "DeltaM J/Psi")) { + return false; + } + + // d0(J/Psi)xd0(K) + if (candBp.impactParameterProduct() > cuts->get(binPt, "B Imp. Par. Product")) { + return false; + } + + // B+ Decay length + if (candBp.decayLength() < cuts->get(binPt, "B decLen")) { + return false; + } + + // B+ Decay length XY + if (candBp.decayLengthXY() < cuts->get(binPt, "B decLenXY")) { + return false; + } + + // B+ CPA cut + if (candBp.cpa() < cuts->get(binPt, "CPA")) { + return false; + } + + // B+ CPAXY cut + if (candBp.cpaXY() < cuts->get(binPt, "CPAXY")) { + return false; + } + + // d0 of K + if (std::abs(candBp.impactParameter1()) < cuts->get(binPt, "d0 K")) { + return false; + } + + // d0 of J/Psi + if (std::abs(candBp.impactParameter0()) < cuts->get(binPt, "d0 J/Psi")) { + return false; + } + + // B pseudoproper decay length + if (pseudoPropDecLen < cuts->get(binPt, "B pseudoprop. decLen")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackKa PID status of trackKa (prong1 of B+ candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prong1 of B+ candidate passes all selections + bool selectionBplusToJpsiKPid(const int pidTrackKa, const bool acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && pidTrackKa != TrackSelectorPID::Accepted) { + return false; + } + if (acceptPIDNotApplicable && pidTrackKa == TrackSelectorPID::Rejected) { + return false; + } + + return true; + } + /// Apply topological cuts as defined in SelectorCuts.h /// \param candBs Bs candidate /// \param cuts Bs candidate selections @@ -947,8 +1057,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of Bs candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of Bs candidate passes all selections - template - bool selectionBsToDsPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionBsToDsPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; @@ -960,6 +1069,115 @@ class HfHelper return true; } + // Apply topological cuts as defined in SelectorCuts.h + /// \param candBs Bs candidate + /// \param candKa0 kaon candidate 0 (phi daughter) + /// \param candKa1 kaon candidate 1 (phi daughter) + /// \param cuts Bs candidate selection per pT bin + /// \param binsPt pT bin limits + /// \return true if candidate passes all selections + template + bool selectionBsToJpsiPhiTopol(const T1& candBs, const T2& candKa0, const T3& candKa1, const T4& cuts, const T5& binsPt) + { + auto ptCandBs = candBs.pt(); + auto mCandBs = invMassBsToJpsiPhi(candBs); + std::array pVecKa0 = candKa0.pVector(); + std::array pVecKa1 = candKa1.pVector(); + auto mCandPhi = RecoDecay::m(std::array{pVecKa0, pVecKa1}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + auto ptJpsi = RecoDecay::pt(candBs.pxProng0(), candBs.pyProng0()); + auto candJpsi = candBs.jpsi(); + float pseudoPropDecLen = candBs.decayLengthXY() * mCandBs / ptCandBs; + + int binPt = o2::analysis::findBin(binsPt, ptCandBs); + if (binPt == -1) { + return false; + } + + // Bs mass cut + if (std::abs(mCandBs - o2::constants::physics::MassBPlus) > cuts->get(binPt, "m")) { + return false; + } + + // kaon pt + if (candKa0.pt() < cuts->get(binPt, "pT K") && + candKa1.pt() < cuts->get(binPt, "pT K")) { + return false; + } + + // J/Psi pt + if (ptJpsi < cuts->get(binPt, "pT J/Psi")) { + return false; + } + + // phi mass + if (std::abs(mCandPhi - o2::constants::physics::MassPhi) < cuts->get(binPt, "DeltaM phi")) { + return false; + } + + // J/Psi mass + if (std::abs(candJpsi.m() - o2::constants::physics::MassJPsi) < cuts->get(binPt, "DeltaM J/Psi")) { + return false; + } + + // d0(J/Psi)xd0(phi) + if (candBs.impactParameterProduct() > cuts->get(binPt, "B Imp. Par. Product")) { + return false; + } + + // Bs Decay length + if (candBs.decayLength() < cuts->get(binPt, "B decLen")) { + return false; + } + + // Bs Decay length XY + if (candBs.decayLengthXY() < cuts->get(binPt, "B decLenXY")) { + return false; + } + + // Bs CPA cut + if (candBs.cpa() < cuts->get(binPt, "CPA")) { + return false; + } + + // Bs CPAXY cut + if (candBs.cpaXY() < cuts->get(binPt, "CPAXY")) { + return false; + } + + // d0 of phi + if (std::abs(candBs.impactParameter1()) < cuts->get(binPt, "d0 phi")) { + return false; + } + + // d0 of J/Psi + if (std::abs(candBs.impactParameter0()) < cuts->get(binPt, "d0 J/Psi")) { + return false; + } + + // B pseudoproper decay length + if (pseudoPropDecLen < cuts->get(binPt, "B pseudoprop. decLen")) { + return false; + } + + return true; + } + + /// Apply PID selection + /// \param pidTrackKa PID status of trackKa (prong1 of B+ candidate) + /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable + /// \return true if prong1 of B+ candidate passes all selections + bool selectionBsToJpsiPhiPid(const int pidTrackKa, const bool acceptPIDNotApplicable) + { + if (!acceptPIDNotApplicable && pidTrackKa != TrackSelectorPID::Accepted) { + return false; + } + if (acceptPIDNotApplicable && pidTrackKa == TrackSelectorPID::Rejected) { + return false; + } + + return true; + } + /// Apply topological cuts as defined in SelectorCuts.h /// \param candLb Lb candidate /// \param cuts Lb candidate selection per pT bin" @@ -988,7 +1206,7 @@ class HfHelper } // Lc pt - if (ptLc < cuts->get(pTBin, "pT Lc")) { + if (ptLc < cuts->get(pTBin, "pT Lc+")) { return false; } @@ -1018,7 +1236,7 @@ class HfHelper } // d0 of Lc - if (std::abs(candLb.impactParameter0()) < cuts->get(pTBin, "d0 Lc")) { + if (std::abs(candLb.impactParameter0()) < cuts->get(pTBin, "d0 Lc+")) { return false; } @@ -1028,8 +1246,7 @@ class HfHelper /// \param pidTrackPi PID status of trackPi (prong1 of Lb candidate) /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable /// \return true if prong1 of Lb candidate passes all selections - template - bool selectionLbToLcPiPid(const T1& pidTrackPi, const T2& acceptPIDNotApplicable) + bool selectionLbToLcPiPid(const int pidTrackPi, const bool acceptPIDNotApplicable) { if (!acceptPIDNotApplicable && pidTrackPi != TrackSelectorPID::Accepted) { return false; @@ -1047,7 +1264,7 @@ class HfHelper /// \param mlScores vector with ml scores of charm hadron (position 0:bkg 1:prompt 2:nonprompt) /// \return true if b-hadron candidate passes all selections template - bool applySelectionDmesMlScoresForB(const T1& cuts, const T2& binsPtC, float ptC, std::vector mlScores) + bool applySelectionDmesMlScoresForB(const T1& cuts, const T2& binsPtC, float ptC, const std::vector& mlScores) { int pTBin = o2::analysis::findBin(binsPtC, ptC); if (pTBin == -1) { diff --git a/PWGHF/Core/HfMlResponseB0ToDPi.h b/PWGHF/Core/HfMlResponseB0ToDPi.h index 7f6c1c80cc5..1f6d4940b7f 100644 --- a/PWGHF/Core/HfMlResponseB0ToDPi.h +++ b/PWGHF/Core/HfMlResponseB0ToDPi.h @@ -17,13 +17,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEB0TODPI_H_ #define PWGHF_CORE_HFMLRESPONSEB0TODPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBplusToD0Pi.h b/PWGHF/Core/HfMlResponseBplusToD0Pi.h index 90fb0669675..427e90fd16d 100644 --- a/PWGHF/Core/HfMlResponseBplusToD0Pi.h +++ b/PWGHF/Core/HfMlResponseBplusToD0Pi.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PI_H_ #define PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h b/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h index 6f56cbce245..93e2ea67eb4 100644 --- a/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h +++ b/PWGHF/Core/HfMlResponseBplusToD0PiReduced.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PIREDUCED_H_ #define PWGHF_CORE_HFMLRESPONSEBPLUSTOD0PIREDUCED_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h b/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h new file mode 100644 index 00000000000..ebf77e7effe --- /dev/null +++ b/PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h @@ -0,0 +1,182 @@ +// 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 HfMlResponseBplusToJpsiKReduced.h +/// \brief Class to compute the ML response for B± → J/Psi K± analysis selections in the reduced format +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino + +#ifndef PWGHF_CORE_HFMLRESPONSEBPLUSTOJPSIKREDUCED_H_ +#define PWGHF_CORE_HFMLRESPONSEBPLUSTOJPSIKREDUCED_H_ + +#include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" + +#include "Tools/ML/MlResponse.h" + +#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_BPLUS(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesBplusToJpsiKReduced::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_BPLUS_FULL(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::FEATURE): { \ + inputFeatures.emplace_back(OBJECT.GETTER()); \ + break; \ + } + +// 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 GETTER function taking OBJECT in argument +#define CHECK_AND_FILL_VEC_BPLUS_FUNC(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::FEATURE): { \ + inputFeatures.emplace_back(GETTER(OBJECT)); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate and FEATURE = GETTER +#define CHECK_AND_FILL_VEC_BPLUS(GETTER) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER()); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate, FEATURE = GETTER, and args are needed +#define CHECK_AND_FILL_VEC_BPLUS_WITH_ARGS(GETTER, ARGS...) \ + case static_cast(InputFeaturesBplusToJpsiKReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER(ARGS)); \ + break; \ + } + +namespace o2::analysis +{ + +enum class InputFeaturesBplusToJpsiKReduced : uint8_t { + ptProng0 = 0, + ptProng1, + impactParameter0, + impactParameter1, + impactParameter2, + impactParameterProduct, + impactParameterProductJpsi, + chi2PCA, + decayLength, + decayLengthXY, + decayLengthNormalised, + decayLengthXYNormalised, + cpa, + cpaXY, + maxNormalisedDeltaIP, + ctXY, + tpcNSigmaKa1, + tofNSigmaKa1, + tpcTofNSigmaKa1 +}; + +template +class HfMlResponseBplusToJpsiKReduced : public HfMlResponse +{ + public: + /// Default constructor + HfMlResponseBplusToJpsiKReduced() = default; + /// Default destructor + virtual ~HfMlResponseBplusToJpsiKReduced() = default; + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the B+ candidate + /// \param prong1 is the candidate's prong1 + /// \return inputFeatures vector + template + std::vector getInputFeatures(T1 const& candidate, + T2 const& prong1) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + CHECK_AND_FILL_VEC_BPLUS(ptProng0); + CHECK_AND_FILL_VEC_BPLUS(ptProng1); + CHECK_AND_FILL_VEC_BPLUS(impactParameter0); + CHECK_AND_FILL_VEC_BPLUS(impactParameter1); + CHECK_AND_FILL_VEC_BPLUS(impactParameter2); + CHECK_AND_FILL_VEC_BPLUS(impactParameterProduct); + CHECK_AND_FILL_VEC_BPLUS(impactParameterProductJpsi); + CHECK_AND_FILL_VEC_BPLUS(chi2PCA); + CHECK_AND_FILL_VEC_BPLUS(decayLength); + CHECK_AND_FILL_VEC_BPLUS(decayLengthXY); + CHECK_AND_FILL_VEC_BPLUS(decayLengthNormalised); + CHECK_AND_FILL_VEC_BPLUS(decayLengthXYNormalised); + CHECK_AND_FILL_VEC_BPLUS(cpa); + CHECK_AND_FILL_VEC_BPLUS(cpaXY); + CHECK_AND_FILL_VEC_BPLUS(maxNormalisedDeltaIP); + CHECK_AND_FILL_VEC_BPLUS_WITH_ARGS(ctXY, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); + // TPC PID variable + CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tpcNSigmaKa1, tpcNSigmaKa); + // TOF PID variable + CHECK_AND_FILL_VEC_BPLUS_FULL(prong1, tofNSigmaKa1, tofNSigmaKa); + // Combined PID variables + CHECK_AND_FILL_VEC_BPLUS_FUNC(prong1, tpcTofNSigmaKa1, o2::pid_tpc_tof_utils::getTpcTofNSigmaKa1); + } + } + + return inputFeatures; + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_BPLUS(ptProng0), + FILL_MAP_BPLUS(ptProng1), + FILL_MAP_BPLUS(impactParameter0), + FILL_MAP_BPLUS(impactParameter1), + FILL_MAP_BPLUS(impactParameter2), + FILL_MAP_BPLUS(impactParameterProduct), + FILL_MAP_BPLUS(impactParameterProductJpsi), + FILL_MAP_BPLUS(chi2PCA), + FILL_MAP_BPLUS(decayLength), + FILL_MAP_BPLUS(decayLengthXY), + FILL_MAP_BPLUS(decayLengthNormalised), + FILL_MAP_BPLUS(decayLengthXYNormalised), + FILL_MAP_BPLUS(cpa), + FILL_MAP_BPLUS(cpaXY), + FILL_MAP_BPLUS(maxNormalisedDeltaIP), + FILL_MAP_BPLUS(ctXY), + // TPC PID variable + FILL_MAP_BPLUS(tpcNSigmaKa1), + // TOF PID variable + FILL_MAP_BPLUS(tofNSigmaKa1), + // Combined PID variable + FILL_MAP_BPLUS(tpcTofNSigmaKa1)}; + } +}; + +} // namespace o2::analysis + +#undef FILL_MAP_BPLUS +#undef CHECK_AND_FILL_VEC_BPLUS_FULL +#undef CHECK_AND_FILL_VEC_BPLUS_FUNC +#undef CHECK_AND_FILL_VEC_BPLUS + +#endif // PWGHF_CORE_HFMLRESPONSEBPLUSTOJPSIKREDUCED_H_ diff --git a/PWGHF/Core/HfMlResponseBsToDsPi.h b/PWGHF/Core/HfMlResponseBsToDsPi.h index 111a76b1227..4c472034f71 100644 --- a/PWGHF/Core/HfMlResponseBsToDsPi.h +++ b/PWGHF/Core/HfMlResponseBsToDsPi.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEBSTODSPI_H_ #define PWGHF_CORE_HFMLRESPONSEBSTODSPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h b/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h new file mode 100644 index 00000000000..2af47921132 --- /dev/null +++ b/PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h @@ -0,0 +1,204 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file HfMlResponseBsToJpsiPhiReduced.h +/// \brief Class to compute the ML response for Bs0 → J/Psi phi analysis selections in the reduced format +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino + +#ifndef PWGHF_CORE_HFMLRESPONSEBSTOJPSIPHIREDUCED_H_ +#define PWGHF_CORE_HFMLRESPONSEBSTOJPSIPHIREDUCED_H_ + +#include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" + +#include "Tools/ML/MlResponse.h" + +#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_BS(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesBsToJpsiPhiReduced::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_BS_FULL(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::FEATURE): { \ + inputFeatures.emplace_back(OBJECT.GETTER()); \ + break; \ + } + +// 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 GETTER function taking OBJECT in argument +#define CHECK_AND_FILL_VEC_BS_FUNC(OBJECT, FEATURE, GETTER) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::FEATURE): { \ + inputFeatures.emplace_back(GETTER(OBJECT)); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate and FEATURE = GETTER +#define CHECK_AND_FILL_VEC_BS(GETTER) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER()); \ + break; \ + } + +// Specific case of CHECK_AND_FILL_VEC_BPLUS_FULL(OBJECT, FEATURE, GETTER) +// where OBJECT is named candidate and FEATURE = GETTER and args are needed +#define CHECK_AND_FILL_VEC_BS_WITH_ARGS(GETTER, ARGS...) \ + case static_cast(InputFeaturesBsToJpsiPhiReduced::GETTER): { \ + inputFeatures.emplace_back(candidate.GETTER(ARGS)); \ + break; \ + } + +namespace o2::analysis +{ + +enum class InputFeaturesBsToJpsiPhiReduced : uint8_t { + ptProng0 = 0, + ptProng1, + impactParameter0, + impactParameter1, + impactParameter2, + impactParameter3, + impactParameterProduct, + impactParameterProductJpsi, + impactParameterProductPhi, + chi2PCA, + decayLength, + decayLengthXY, + decayLengthNormalised, + decayLengthXYNormalised, + cpa, + cpaXY, + maxNormalisedDeltaIP, + ctXY, + tpcNSigmaKa0, + tofNSigmaKa0, + tpcTofNSigmaKa0, + tpcNSigmaKa1, + tofNSigmaKa1, + tpcTofNSigmaKa1 +}; + +template +class HfMlResponseBsToJpsiPhiReduced : public HfMlResponse +{ + public: + /// Default constructor + HfMlResponseBsToJpsiPhiReduced() = default; + /// Default destructor + virtual ~HfMlResponseBsToJpsiPhiReduced() = default; + + /// Method to get the input features vector needed for ML inference + /// \param candidate is the Bs candidate + /// \param prong1 is the candidate's prong1 + /// \return inputFeatures vector + template + std::vector getInputFeatures(T1 const& candidate, + T2 const& prong1, + T3 const& prong2) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + CHECK_AND_FILL_VEC_BS(ptProng0); + CHECK_AND_FILL_VEC_BS(ptProng1); + CHECK_AND_FILL_VEC_BS(impactParameter0); + CHECK_AND_FILL_VEC_BS(impactParameter1); + CHECK_AND_FILL_VEC_BS(impactParameter2); + CHECK_AND_FILL_VEC_BS(impactParameter3); + CHECK_AND_FILL_VEC_BS(impactParameterProduct); + CHECK_AND_FILL_VEC_BS(impactParameterProductJpsi); + CHECK_AND_FILL_VEC_BS(impactParameterProductPhi); + CHECK_AND_FILL_VEC_BS(chi2PCA); + CHECK_AND_FILL_VEC_BS(decayLength); + CHECK_AND_FILL_VEC_BS(decayLengthXY); + CHECK_AND_FILL_VEC_BS(decayLengthNormalised); + CHECK_AND_FILL_VEC_BS(decayLengthXYNormalised); + CHECK_AND_FILL_VEC_BS(cpa); + CHECK_AND_FILL_VEC_BS(cpaXY); + CHECK_AND_FILL_VEC_BS(maxNormalisedDeltaIP); + CHECK_AND_FILL_VEC_BS_WITH_ARGS(ctXY, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + // TPC PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong1, tpcNSigmaKa0, tpcNSigmaKa); + // TOF PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong1, tofNSigmaKa0, tofNSigmaKa); + // Combined PID variables + CHECK_AND_FILL_VEC_BS_FUNC(prong1, tpcTofNSigmaKa0, o2::pid_tpc_tof_utils::getTpcTofNSigmaKa1); + // TPC PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong2, tpcNSigmaKa1, tpcNSigmaKa); + // TOF PID variable + CHECK_AND_FILL_VEC_BS_FULL(prong2, tofNSigmaKa1, tofNSigmaKa); + // Combined PID variables + CHECK_AND_FILL_VEC_BS_FUNC(prong2, tpcTofNSigmaKa1, o2::pid_tpc_tof_utils::getTpcTofNSigmaKa1); + } + } + + return inputFeatures; + } + + protected: + /// Method to fill the map of available input features + void setAvailableInputFeatures() + { + MlResponse::mAvailableInputFeatures = { + FILL_MAP_BS(ptProng0), + FILL_MAP_BS(ptProng1), + FILL_MAP_BS(impactParameter0), + FILL_MAP_BS(impactParameter1), + FILL_MAP_BS(impactParameter2), + FILL_MAP_BS(impactParameter3), + FILL_MAP_BS(impactParameterProduct), + FILL_MAP_BS(impactParameterProductJpsi), + FILL_MAP_BS(impactParameterProductPhi), + FILL_MAP_BS(chi2PCA), + FILL_MAP_BS(decayLength), + FILL_MAP_BS(decayLengthXY), + FILL_MAP_BS(decayLengthNormalised), + FILL_MAP_BS(decayLengthXYNormalised), + FILL_MAP_BS(cpa), + FILL_MAP_BS(cpaXY), + FILL_MAP_BS(maxNormalisedDeltaIP), + FILL_MAP_BS(ctXY), + // TPC PID variable + FILL_MAP_BS(tpcNSigmaKa0), + // TOF PID variable + FILL_MAP_BS(tofNSigmaKa0), + // Combined PID variable + FILL_MAP_BS(tpcTofNSigmaKa0), + // TPC PID variable + FILL_MAP_BS(tpcNSigmaKa1), + // TOF PID variable + FILL_MAP_BS(tofNSigmaKa1), + // Combined PID variable + FILL_MAP_BS(tpcTofNSigmaKa1)}; + } +}; + +} // namespace o2::analysis + +#undef FILL_MAP_BS +#undef CHECK_AND_FILL_VEC_BS_FULL +#undef CHECK_AND_FILL_VEC_BS_FUNC +#undef CHECK_AND_FILL_VEC_BS + +#endif // PWGHF_CORE_HFMLRESPONSEBSTOJPSIPHIREDUCED_H_ diff --git a/PWGHF/Core/HfMlResponseD0ToKPi.h b/PWGHF/Core/HfMlResponseD0ToKPi.h index fbca4f8319e..8a1128bd65f 100644 --- a/PWGHF/Core/HfMlResponseD0ToKPi.h +++ b/PWGHF/Core/HfMlResponseD0ToKPi.h @@ -17,15 +17,16 @@ #ifndef PWGHF_CORE_HFMLRESPONSED0TOKPI_H_ #define PWGHF_CORE_HFMLRESPONSED0TOKPI_H_ -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.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 diff --git a/PWGHF/Core/HfMlResponseDplusToPiKPi.h b/PWGHF/Core/HfMlResponseDplusToPiKPi.h index 42dde77eda7..fd6085b5ce9 100644 --- a/PWGHF/Core/HfMlResponseDplusToPiKPi.h +++ b/PWGHF/Core/HfMlResponseDplusToPiKPi.h @@ -16,12 +16,13 @@ #ifndef PWGHF_CORE_HFMLRESPONSEDPLUSTOPIKPI_H_ #define PWGHF_CORE_HFMLRESPONSEDPLUSTOPIKPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseDsToKKPi.h b/PWGHF/Core/HfMlResponseDsToKKPi.h index ccb6a99e371..0c166e55e51 100644 --- a/PWGHF/Core/HfMlResponseDsToKKPi.h +++ b/PWGHF/Core/HfMlResponseDsToKKPi.h @@ -16,17 +16,20 @@ #ifndef PWGHF_CORE_HFMLRESPONSEDSTOKKPI_H_ #define PWGHF_CORE_HFMLRESPONSEDSTOKKPI_H_ -#include - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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_DS(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesDsToKKPi::FEATURE) \ +#define FILL_MAP_DS(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesDsToKKPi::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) diff --git a/PWGHF/Core/HfMlResponseDstarToD0Pi.h b/PWGHF/Core/HfMlResponseDstarToD0Pi.h index be309743893..af0351b2a73 100644 --- a/PWGHF/Core/HfMlResponseDstarToD0Pi.h +++ b/PWGHF/Core/HfMlResponseDstarToD0Pi.h @@ -16,19 +16,21 @@ #ifndef PWGHF_CORE_HFMLRESPONSEDSTARTOD0PI_H_ #define PWGHF_CORE_HFMLRESPONSEDSTARTOD0PI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" -#include "CommonConstants/PhysicsConstants.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_DSTAR(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesDstarToD0Pi::FEATURE) \ +#define FILL_MAP_DSTAR(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesDstarToD0Pi::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) @@ -111,6 +113,8 @@ enum class InputFeaturesDstarToD0Pi : uint8_t { ptSoftPi, impactParameter0, impactParameter1, + impactParameterXY0, + impactParameterXY1, impactParameterZ0, impactParameterZ1, impParamSoftPi, @@ -217,6 +221,28 @@ class HfMlResponseDstarToD0Pi : public HfMlResponse return inputFeatures; } + /// Method to get the input features used for D0 in HF triggers + /// \param candidate is the D* candidate + /// \return inputFeatures vector + template + std::vector getInputFeaturesTrigger(T1 const& candidate) + { + std::vector inputFeatures; + + for (const auto& idx : MlResponse::mCachedIndices) { + switch (idx) { + CHECK_AND_FILL_VEC_DSTAR(ptProng0); + CHECK_AND_FILL_VEC_DSTAR_GETTER(impactParameterXY0, impactParameter0); + CHECK_AND_FILL_VEC_DSTAR(impactParameterZ0); + CHECK_AND_FILL_VEC_DSTAR(ptProng1); + CHECK_AND_FILL_VEC_DSTAR_GETTER(impactParameterXY1, impactParameter1); + CHECK_AND_FILL_VEC_DSTAR(impactParameterZ1); + } + } + + return inputFeatures; + } + protected: /// Method to fill the map of available input features void setAvailableInputFeatures() @@ -236,6 +262,8 @@ class HfMlResponseDstarToD0Pi : public HfMlResponse FILL_MAP_DSTAR(ptSoftPi), FILL_MAP_DSTAR(impactParameter0), FILL_MAP_DSTAR(impactParameter1), + FILL_MAP_DSTAR(impactParameterXY0), + FILL_MAP_DSTAR(impactParameterXY1), FILL_MAP_DSTAR(impactParameterZ0), FILL_MAP_DSTAR(impactParameterZ1), FILL_MAP_DSTAR(impParamSoftPi), diff --git a/PWGHF/Core/HfMlResponseLbToLcPi.h b/PWGHF/Core/HfMlResponseLbToLcPi.h index a421f9019d4..8375e8cf5ea 100644 --- a/PWGHF/Core/HfMlResponseLbToLcPi.h +++ b/PWGHF/Core/HfMlResponseLbToLcPi.h @@ -16,13 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSELBTOLCPI_H_ #define PWGHF_CORE_HFMLRESPONSELBTOLCPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseLcToK0sP.h b/PWGHF/Core/HfMlResponseLcToK0sP.h index 2dc78cb19d1..a3484c029cb 100644 --- a/PWGHF/Core/HfMlResponseLcToK0sP.h +++ b/PWGHF/Core/HfMlResponseLcToK0sP.h @@ -17,19 +17,20 @@ #ifndef PWGHF_CORE_HFMLRESPONSELCTOK0SP_H_ #define PWGHF_CORE_HFMLRESPONSELCTOK0SP_H_ -#include -#include -#include - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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_LC(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesLcToK0sP::FEATURE) \ +#define FILL_MAP_LC(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesLcToK0sP::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) diff --git a/PWGHF/Core/HfMlResponseLcToPKPi.h b/PWGHF/Core/HfMlResponseLcToPKPi.h index 405e16cfc42..6c09afdbe8f 100644 --- a/PWGHF/Core/HfMlResponseLcToPKPi.h +++ b/PWGHF/Core/HfMlResponseLcToPKPi.h @@ -16,9 +16,15 @@ #ifndef PWGHF_CORE_HFMLRESPONSELCTOPKPI_H_ #define PWGHF_CORE_HFMLRESPONSELCTOPKPI_H_ -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +#include "Tools/ML/MlResponse.h" + +#include +#include +#include +#include // Fill the map of available input features // the key is the feature's name (std::string) @@ -129,10 +135,22 @@ enum class InputFeaturesLcToPKPi : uint8_t { tofNSigmaPrExpPr0, tofNSigmaPiExpPi2, tpcTofNSigmaPrExpPr0, - tpcTofNSigmaPiExpPi2 + tpcTofNSigmaPiExpPi2, + kfChi2PrimProton, + kfChi2PrimKaon, + kfChi2PrimPion, + kfChi2GeoKaonPion, + kfChi2GeoProtonPion, + kfChi2GeoProtonKaon, + kfDcaKaonPion, + kfDcaProtonPion, + kfDcaProtonKaon, + kfChi2Geo, + kfChi2Topo, + kfDecayLengthNormalised }; -template +template class HfMlResponseLcToPKPi : public HfMlResponse { public: @@ -179,8 +197,6 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcNSigmaPr2, nSigTpcPr2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcNSigmaKa2, nSigTpcKa2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcNSigmaPi2, nSigTpcPi2); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tpcNSigmaPrExpPr0, tpcNSigmaPr); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tpcNSigmaPiExpPi2, tpcNSigmaPi); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcNSigmaPrExpPr0, nSigTpcPr0, nSigTpcPr2); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcNSigmaPiExpPi2, nSigTpcPi2, nSigTpcPi0); // TOF PID variables @@ -193,8 +209,6 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tofNSigmaPr2, nSigTofPr2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tofNSigmaKa2, nSigTofKa2); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tofNSigmaPi2, nSigTofPi2); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tofNSigmaPrExpPr0, tofNSigmaPr); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tofNSigmaPiExpPi2, tofNSigmaPi); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tofNSigmaPrExpPr0, nSigTofPr0, nSigTofPr2); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tofNSigmaPiExpPi2, nSigTofPi2, nSigTofPi0); // Combined PID variables @@ -207,13 +221,29 @@ class HfMlResponseLcToPKPi : public HfMlResponse CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcTofNSigmaPr0, tpcTofNSigmaPr0); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcTofNSigmaPr1, tpcTofNSigmaPr1); CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, tpcTofNSigmaPr2, tpcTofNSigmaPr2); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong0, prong2, tpcTofNSigmaPrExpPr0, tpcTofNSigmaPr); - // CHECK_AND_FILL_VEC_LCTOPKPI_OBJECT_SIGNED(prong2, prong0, tpcTofNSigmaPiExpPi2, tpcTofNSigmaPi); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcTofNSigmaPrExpPr0, tpcTofNSigmaPr0, tpcTofNSigmaPr2); CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, tpcTofNSigmaPiExpPi2, tpcTofNSigmaPi2, tpcTofNSigmaPi0); } + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + switch (idx) { + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2PrimProton, kfChi2PrimProng0, kfChi2PrimProng2); + CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, kfChi2PrimKaon, kfChi2PrimProng1); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2PrimPion, kfChi2PrimProng2, kfChi2PrimProng0); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2GeoKaonPion, kfChi2GeoProng1Prong2, kfChi2GeoProng0Prong1); + CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, kfChi2GeoProtonPion, kfChi2GeoProng0Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfChi2GeoProtonKaon, kfChi2GeoProng0Prong1, kfChi2GeoProng1Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfDcaKaonPion, kfDcaProng1Prong2, kfDcaProng0Prong1); + CHECK_AND_FILL_VEC_LCTOPKPI_FULL(candidate, kfDcaProtonPion, kfDcaProng0Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI_SIGNED(candidate, kfDcaProtonKaon, kfDcaProng0Prong1, kfDcaProng1Prong2); + CHECK_AND_FILL_VEC_LCTOPKPI(kfChi2Geo); + CHECK_AND_FILL_VEC_LCTOPKPI(kfChi2Topo); + case static_cast(InputFeaturesLcToPKPi::kfDecayLengthNormalised): { + inputFeatures.emplace_back(candidate.kfDecayLength() / candidate.kfDecayLengthError()); + break; + } + } + } } - return inputFeatures; } @@ -273,6 +303,23 @@ class HfMlResponseLcToPKPi : public HfMlResponse FILL_MAP_LCTOPKPI(tpcTofNSigmaPr2), FILL_MAP_LCTOPKPI(tpcTofNSigmaPrExpPr0), FILL_MAP_LCTOPKPI(tpcTofNSigmaPiExpPi2)}; + if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { + std::map mapKfFeatures{ + // KFParticle variables + FILL_MAP_LCTOPKPI(kfChi2PrimProton), + FILL_MAP_LCTOPKPI(kfChi2PrimKaon), + FILL_MAP_LCTOPKPI(kfChi2PrimPion), + FILL_MAP_LCTOPKPI(kfChi2GeoKaonPion), + FILL_MAP_LCTOPKPI(kfChi2GeoProtonPion), + FILL_MAP_LCTOPKPI(kfChi2GeoProtonKaon), + FILL_MAP_LCTOPKPI(kfDcaKaonPion), + FILL_MAP_LCTOPKPI(kfDcaProtonPion), + FILL_MAP_LCTOPKPI(kfDcaProtonKaon), + FILL_MAP_LCTOPKPI(kfChi2Geo), + FILL_MAP_LCTOPKPI(kfChi2Topo), + FILL_MAP_LCTOPKPI(kfDecayLengthNormalised)}; + MlResponse::mAvailableInputFeatures.insert(mapKfFeatures.begin(), mapKfFeatures.end()); + } } }; diff --git a/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h b/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h index 53b40330e04..c61616cc9d4 100644 --- a/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h +++ b/PWGHF/Core/HfMlResponseOmegacToOmegaPi.h @@ -16,15 +16,14 @@ #ifndef PWGHF_CORE_HFMLRESPONSEOMEGACTOOMEGAPI_H_ #define PWGHF_CORE_HFMLRESPONSEOMEGACTOOMEGAPI_H_ -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h b/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h index d75bdcc4c10..3fbb6cf4052 100644 --- a/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h +++ b/PWGHF/Core/HfMlResponseXic0ToXiPiKf.h @@ -16,10 +16,13 @@ #ifndef PWGHF_CORE_HFMLRESPONSEXIC0TOXIPIKF_H_ #define PWGHF_CORE_HFMLRESPONSEXIC0TOXIPIKF_H_ -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 diff --git a/PWGHF/Core/HfMlResponseXicToPKPi.h b/PWGHF/Core/HfMlResponseXicToPKPi.h index d533c7fb8ab..f433d29bd5d 100644 --- a/PWGHF/Core/HfMlResponseXicToPKPi.h +++ b/PWGHF/Core/HfMlResponseXicToPKPi.h @@ -16,18 +16,19 @@ #ifndef PWGHF_CORE_HFMLRESPONSEXICTOPKPI_H_ #define PWGHF_CORE_HFMLRESPONSEXICTOPKPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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_XIC(FEATURE) \ - { \ -#FEATURE, static_cast < uint8_t>(InputFeaturesXicToPKPi::FEATURE) \ +#define FILL_MAP_XIC(FEATURE) \ + { \ + #FEATURE, static_cast(InputFeaturesXicToPKPi::FEATURE) \ } // Check if the index of mCachedIndices (index associated to a FEATURE) diff --git a/PWGHF/Core/HfMlResponseXicToXiPiPi.h b/PWGHF/Core/HfMlResponseXicToXiPiPi.h index d8c040b28ce..4bb4a4d023f 100644 --- a/PWGHF/Core/HfMlResponseXicToXiPiPi.h +++ b/PWGHF/Core/HfMlResponseXicToXiPiPi.h @@ -16,12 +16,13 @@ #ifndef PWGHF_CORE_HFMLRESPONSEXICTOXIPIPI_H_ #define PWGHF_CORE_HFMLRESPONSEXICTOXIPIPI_H_ -#include -#include -#include - #include "PWGHF/Core/HfMlResponse.h" +#include "Tools/ML/MlResponse.h" + +#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 @@ -62,10 +63,10 @@ enum class InputFeaturesXicToXiPiPi : uint8_t { decayLengthXYNormalised, cpa, cpaXY, - cosPaXi, - cosPaXYXi, - cosPaLambda, - cosPaXYLambda, + cpaXi, + cpaXYXi, + cpaLambda, + cpaXYLambda, impactParameterXi, impactParameterPi0, impactParameterPi1, @@ -119,10 +120,10 @@ class HfMlResponseXicToXiPiPi : public HfMlResponse CHECK_AND_FILL_VEC_XICTOXIPIPI(decayLengthXYNormalised); CHECK_AND_FILL_VEC_XICTOXIPIPI(cpa); CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXY); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaXi); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaXYXi); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaLambda); - CHECK_AND_FILL_VEC_XICTOXIPIPI(cosPaXYLambda); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXi); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXYXi); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaLambda); + CHECK_AND_FILL_VEC_XICTOXIPIPI(cpaXYLambda); CHECK_AND_FILL_VEC_XICTOXIPIPI_FULL(candidate, impactParameterXi, impactParameter0); CHECK_AND_FILL_VEC_XICTOXIPIPI_FULL(candidate, impactParameterPi0, impactParameter1); CHECK_AND_FILL_VEC_XICTOXIPIPI_FULL(candidate, impactParameterPi1, impactParameter2); @@ -166,10 +167,10 @@ class HfMlResponseXicToXiPiPi : public HfMlResponse FILL_MAP_XICTOXIPIPI(decayLengthXYNormalised), FILL_MAP_XICTOXIPIPI(cpa), FILL_MAP_XICTOXIPIPI(cpaXY), - FILL_MAP_XICTOXIPIPI(cosPaXi), - FILL_MAP_XICTOXIPIPI(cosPaXYXi), - FILL_MAP_XICTOXIPIPI(cosPaLambda), - FILL_MAP_XICTOXIPIPI(cosPaXYLambda), + FILL_MAP_XICTOXIPIPI(cpaXi), + FILL_MAP_XICTOXIPIPI(cpaXYXi), + FILL_MAP_XICTOXIPIPI(cpaLambda), + FILL_MAP_XICTOXIPIPI(cpaXYLambda), FILL_MAP_XICTOXIPIPI(impactParameterXi), FILL_MAP_XICTOXIPIPI(impactParameterPi0), FILL_MAP_XICTOXIPIPI(impactParameterPi1), diff --git a/PWGHF/Core/SelectorCuts.h b/PWGHF/Core/SelectorCuts.h index 61e17b16ff1..a3df78aee0f 100644 --- a/PWGHF/Core/SelectorCuts.h +++ b/PWGHF/Core/SelectorCuts.h @@ -702,6 +702,97 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"pT pi from Omegac"}; } // namespace hf_cuts_omegac_to_omega_pi +namespace hf_cuts_omegacxic_to_omega_ka +{ +static constexpr int NBinsPt = 4; +static constexpr int NCutVars = 1; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double BinsPt[NBinsPt + 1] = { + + 1.0, + 2.0, + 4.0, + 6.0, + 12.0}; + +auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; + +// default values for the cuts +// pi_pT +constexpr double Cuts[NBinsPt][NCutVars] = {{0.2}, /* 1 < pt < 2 */ + {0.2}, /* 2 < pt < 4 */ + {0.6}, /* 4 < pt < 6 */ + {0.8}}; /* 6 < pt < 12 */ + +// row labels +static const std::vector labelsPt = { + "pT bin 0", + "pT bin 1", + "pT bin 2", + "pT bin 3"}; + +// column labels +static const std::vector labelsCutVar = {"pT Ka from Omegac"}; +} // namespace hf_cuts_omegacxic_to_omega_ka + +namespace hf_cuts_xic_to_xi_pi +{ +static constexpr int NBinsPt = 11; +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 +constexpr double BinsPt[NBinsPt + 1] = { + 0.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 8.0, + 10.0, + 12.0, + 16.0, + 24.0}; + +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 */ + +// 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"}; + +// column labels +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"}; +} // namespace hf_cuts_xic_to_xi_pi + namespace hf_cuts_xic_to_p_k_pi { static constexpr int NBinsPt = 10; @@ -753,8 +844,8 @@ static const std::vector labelsCutVar = {"m", "pT p", "pT K", "pT P namespace hf_cuts_xic_to_xi_pi_pi { -static constexpr int NBinsPt = 10; -static constexpr int NCutVars = 12; +static constexpr int NBinsPt = 13; +static constexpr int NCutVars = 13; // default values for the pT bin edges (can be used to configure histogram axis) // offset by 1 from the bin numbers in cuts array constexpr double BinsPt[NBinsPt + 1] = { @@ -765,23 +856,29 @@ constexpr double BinsPt[NBinsPt + 1] = { 4., 5., 6., + 7., 8., + 9., + 10., + 11., 12., - 24., - 36.}; + 20.}; auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; -// default values for the cuts m ptXi ptPi0 ptPi1 chi2PCA dL dLXY cosp cospXY impParXY Xi Pi0 Pi1 -constexpr double Cuts[NBinsPt][NCutVars] = {{0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 0 < pT < 1 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 1 < pT < 2 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 2 < pT < 3 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 3 < pT < 4 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 4 < pT < 5 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 5 < pT < 6 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 6 < pT < 8 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 8 < pT < 10 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}, /* 12 < pT < 24 */ - {0.4, 0.4, 0.4, 0.4, 1e-5, 0.5, 0.5, 0.9, 0.9, 0.1, 0.1, 0.1}}; /* 24 < pT < 36 */ +// default values for the cuts m Y Eta EtaPi EtaXi pT Pi0 Pi1 Sum chi2SV dL dLXY invMass Xi-Pi pairs +constexpr double Cuts[NBinsPt][NCutVars] = {{0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 0 < pT < 1 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 1 < pT < 2 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 2 < pT < 3 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 3 < pT < 4 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 4 < pT < 5 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 5 < pT < 6 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 6 < pT < 7 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 7 < pT < 8 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 8 < pT < 9 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 9 < pT < 10 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 10 < pT < 11 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}, /* 11 < pT < 12 */ + {0.4, 0.8, 0.8, 0.8, 1.0, 0.1, 0.1, 0.2, 100, 0.0, 0.0, 2.4, 2.4}}; /* 12 < pT < 20 */ // row labels static const std::vector labelsPt = { @@ -794,10 +891,13 @@ static const std::vector labelsPt = { "pT bin 6", "pT bin 7", "pT bin 8", - "pT bin 9"}; + "pT bin 9", + "pT bin 10", + "pT bin 11", + "pT bin 12"}; // column labels -static const std::vector labelsCutVar = {"m", "pT Xi", "pT Pi0", "pT Pi1", "chi2PCA", "max decay length", "max decay length XY", "cos pointing angle", "cos pointing angle XY", "max impParXY Xi", "max impParXY Pi0", "max impParXY Pi1"}; +static const std::vector labelsCutVar = {"m", "y", "eta", "eta Pi from XicPlus", "eta Xi Daughters", "pT Pi0", "pT Pi1", "pT Pi0 + Pi1", "chi2SV", "min decay length", "min decay length XY", "max inv mass Xi-Pi0", "max inv mass Xi-Pi1"}; } // namespace hf_cuts_xic_to_xi_pi_pi namespace hf_cuts_xicc_to_p_k_pi_pi @@ -896,6 +996,53 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "DCA_xy", "DCA_z", "pT El", "chi2PCA"}; } // namespace hf_cuts_jpsi_to_e_e +namespace hf_cuts_jpsi_to_mu_mu +{ +static constexpr int NBinsPt = 9; +static constexpr int NCutVars = 8; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double BinsPt[NBinsPt + 1] = { + 0, + 0.5, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 6.0, + 10.0, + 16.0, +}; +auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; + +// default values for the cuts +constexpr double Cuts[NBinsPt][NCutVars] = {{0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 0 < pT < 0.5 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 0.5 < pT < 1 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 1 < pT < 2 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 2 < pT < 3 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 3 < pT < 4 */ + {0.6, 1.0, 0.2, 0.2, 0.9, 0.9, 0., 0.}, /* 4 < pT < 5 */ + {0.8, 1.0, 0.3, 0.3, 0.9, 0.9, 0., 0.}, /* 5 < pT < 6 */ + {0.8, 1.0, 0.3, 0.3, 0.9, 0.9, 1., 0.}, /* 6 < pT < 10 */ + {0.8, 1.0, 0.3, 0.3, 0.9, 0.9, 1., 0.}}; /* 10 < pT < 16 */ + +// 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"}; + +// column labels +static const std::vector labelsCutVar = {"m", "pT mu", "decay length", "decay length xy", "cpa", "cpa xy", "d0xd0", "pseudoprop. decay length"}; +} // namespace hf_cuts_jpsi_to_mu_mu + namespace hf_cuts_b0_to_d_pi { static constexpr int NBinsPt = 12; @@ -1003,6 +1150,62 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "CPA", "Chi2PCA", "d0 Ds", "d0 Pi", "pT Ds", "pT Pi", "Bs decLen", "Bs decLenXY", "Imp. Par. Product"}; } // namespace hf_cuts_bs_to_ds_pi +namespace hf_cuts_bs_to_jpsi_phi +{ +static constexpr int NBinsPt = 12; +static constexpr int NCutVars = 13; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double BinsPt[NBinsPt + 1] = { + 0, + 0.5, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 7.0, + 10.0, + 13.0, + 16.0, + 20.0, + 24.0}; + +auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; + +// default values for the cuts +// DeltaM CPA d0Jpsi d0K pTJpsi pTK BDecayLength BDecayLengthXY BIPProd DeltaMJpsi JpsiIPProd +constexpr double Cuts[NBinsPt][NCutVars] = {{1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 0 < pt < 0.5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 0.5 < pt < 1 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 1 < pt < 2 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 2 < pt < 3 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 3 < pt < 4 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 4 < pt < 5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 5 < pt < 7 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 7 < pt < 10 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 10 < pt < 13 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 13 < pt < 16 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}, /* 16 < pt < 20 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.02, 0.}}; /* 20 < pt < 24 */ +// 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"}; + +// column labels +static const std::vector labelsCutVar = {"m", "CPA", "CPAXY", "d0 J/Psi", "d0 phi", "pT J/Psi", "pT K", "B decLen", "B decLenXY", "B Imp. Par. Product", "DeltaM J/Psi", "DeltaM phi", "B pseudoprop. decLen"}; +} // namespace hf_cuts_bs_to_jpsi_phi + namespace hf_cuts_bplus_to_d0_pi { static constexpr int NBinsPt = 12; @@ -1059,6 +1262,62 @@ static const std::vector labelsPt = { static const std::vector labelsCutVar = {"m", "CPA", "d0 D0", "d0 Pi", "pT D0", "pT Pi", "B decLen", "B decLenXY", "Imp. Par. Product", "DeltaMD0", "Cos ThetaStar"}; } // namespace hf_cuts_bplus_to_d0_pi +namespace hf_cuts_bplus_to_jpsi_k +{ +static constexpr int NBinsPt = 12; +static constexpr int NCutVars = 12; +// default values for the pT bin edges (can be used to configure histogram axis) +// offset by 1 from the bin numbers in cuts array +constexpr double BinsPt[NBinsPt + 1] = { + 0, + 0.5, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0, + 7.0, + 10.0, + 13.0, + 16.0, + 20.0, + 24.0}; + +auto vecBinsPt = std::vector{BinsPt, BinsPt + NBinsPt + 1}; + +// default values for the cuts +// DeltaM CPA d0Jpsi d0K pTJpsi pTK BDecayLength BDecayLengthXY BIPProd DeltaMJpsi JpsiIPProd +constexpr double Cuts[NBinsPt][NCutVars] = {{1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 0 < pt < 0.5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 0.5 < pt < 1 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 1 < pt < 2 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 2 < pt < 3 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 3 < pt < 4 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 4 < pt < 5 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 5 < pt < 7 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 7 < pt < 10 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 10 < pt < 13 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 13 < pt < 16 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}, /* 16 < pt < 20 */ + {1., 0.8, 0.8, 0.01, 0.01, 1.0, 0.15, 0.05, 0.05, 0., 0.1, 0.}}; /* 20 < pt < 24 */ +// 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"}; + +// column labels +static const std::vector labelsCutVar = {"m", "CPA", "CPAXY", "d0 J/Psi", "d0 K", "pT J/Psi", "pT K", "B decLen", "B decLenXY", "B Imp. Par. Product", "DeltaM J/Psi", "B pseudoprop. decLen"}; +} // namespace hf_cuts_bplus_to_jpsi_k + namespace hf_cuts_lb_to_lc_pi { static constexpr int NBinsPt = 12; diff --git a/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h b/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h index 039de3834df..4373ded905c 100644 --- a/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h +++ b/PWGHF/D2H/Core/SelectorCutsRedDataFormat.h @@ -29,7 +29,7 @@ namespace hf_cuts_d_daughter static constexpr int NBinsPt = 7; static constexpr int NCutVars = 6; constexpr double BinsPt[NBinsPt + 1] = { - 1., + 0., 2., 4., 6., @@ -87,5 +87,15 @@ static const std::vector labelsPt{}; // column labels static const std::vector labelsCutVar = {"invMassLow", "invMassHigh", "cpaMin", "dcaMax", "radiusMin"}; } // namespace hf_cuts_v0_daughter + +namespace hf_cuts_track_daughter +{ +static constexpr int NCutVars = 7; +// default values for the cuts +constexpr double Cuts[1][NCutVars] = {{0.1, 3, 40, 4, 3, -1, -1}}; // nSigmaTpc, nSigmaTof, nSigmaCombined +// row labels +static const std::vector labelsCutVar = {"ptMin", "itsNClsMin", "tpcNCrossedRowsMin", "tpcChi2Max", "nSigmaTpc", "nSigmaTof", "nSigmaComb"}; +} // namespace hf_cuts_track_daughter + } // namespace o2::analysis #endif // PWGHF_D2H_CORE_SELECTORCUTSREDDATAFORMAT_H_ diff --git a/PWGHF/D2H/DataModel/ReducedDataModel.h b/PWGHF/D2H/DataModel/ReducedDataModel.h index 092210a22ca..06b219be522 100644 --- a/PWGHF/D2H/DataModel/ReducedDataModel.h +++ b/PWGHF/D2H/DataModel/ReducedDataModel.h @@ -19,16 +19,13 @@ /// \author Fabrizio Grosa , CERN /// \author Luca Aglietta , Università degli Studi di Torino (UniTO) /// \author Biao Zhang , Heidelberg University +/// \author Fabrizio Chinu , Università degli Studi di Torino (UniTO) #ifndef PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ #define PWGHF_D2H_DATAMODEL_REDUCEDDATAMODEL_H_ -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsPid.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" @@ -37,8 +34,15 @@ #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/Qvectors.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsPid.h" +#include +#include +#include +#include + +#include +#include +#include +#include namespace o2 { @@ -47,7 +51,7 @@ namespace aod namespace hf_reduced_collision { DECLARE_SOA_COLUMN(Bz, bz, float); //! Magnetic field in z-direction -DECLARE_SOA_COLUMN(HfCollisionRejectionMap, hfCollisionRejectionMap, uint16_t); //! Bitmask with failed selection criteria +DECLARE_SOA_COLUMN(HfCollisionRejectionMap, hfCollisionRejectionMap, uint32_t); //! Bitmask with failed selection criteria // keep track of the number of studied events (for normalization purposes) DECLARE_SOA_COLUMN(OriginalCollisionCount, originalCollisionCount, int); //! Size of COLLISION table processed DECLARE_SOA_COLUMN(ZvtxSelectedCollisionCount, zvtxSelectedCollisionCount, int); //! Number of COLLISIONS with |zvtx| < zvtxMax @@ -185,6 +189,7 @@ DECLARE_SOA_COLUMN(HasTOFProng2, hasTOFProng2, bool); DECLARE_SOA_COLUMN(ItsNCls, itsNCls, int); //! Number of clusters in ITS DECLARE_SOA_COLUMN(TpcNClsCrossedRows, tpcNClsCrossedRows, int); //! Number of TPC crossed rows DECLARE_SOA_COLUMN(TpcChi2NCl, tpcChi2NCl, float); //! TPC chi2 +DECLARE_SOA_COLUMN(ItsChi2NCl, itsChi2NCl, float); //! ITS chi2 DECLARE_SOA_COLUMN(ItsNClsProngMin, itsNClsProngMin, int); //! minimum value of number of ITS clusters for the decay daughter tracks DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMin, tpcNClsCrossedRowsProngMin, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks DECLARE_SOA_COLUMN(TpcChi2NClProngMax, tpcChi2NClProngMax, float); //! maximum value of TPC chi2 for the decay daughter tracks @@ -210,8 +215,16 @@ DECLARE_SOA_DYNAMIC_COLUMN(EtaProng1, etaProng1, //! [](float pxProng1, float pyProng1, float pzProng1) -> float { return RecoDecay::eta(std::array{pxProng1, pyProng1, pzProng1}); }); DECLARE_SOA_DYNAMIC_COLUMN(EtaProng2, etaProng2, //! [](float pxProng2, float pyProng2, float pzProng2) -> float { return RecoDecay::eta(std::array{pxProng2, pyProng2, pzProng2}); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVector, pVector, //! 3-momentum vector + [](float px, float py, float pz) -> std::array { return {px, py, pz}; }); } // namespace hf_track_vars_reduced +namespace hf_b_to_jpsi_track_vars_reduced +{ +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! transverse momentum + [](float signed1Pt) -> float { return std::abs(signed1Pt) <= o2::constants::math::Almost0 ? o2::constants::math::VeryBig : 1.f / std::abs(signed1Pt); }); +} // namespace hf_b_to_jpsi_track_vars_reduced + namespace hf_track_pid_reduced { DECLARE_SOA_COLUMN(TPCNSigmaPiProng0, tpcNSigmaPiProng0, float); //! NsigmaTPCPi for prong0, o2-linter: disable=name/o2-column (written to disk) @@ -272,9 +285,94 @@ DECLARE_SOA_TABLE(HfRedTrackBases, "AOD", "HFREDTRACKBASE", //! Table with track aod::track::Px, aod::track::Py, aod::track::Pz, - aod::track::PVector); + aod::track::PVector, + o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfRedTracksCov, "AOD", "HFREDTRACKCOV", //! Table with track covariance information for reduced workflow + soa::Index<>, + HFTRACKPARCOV_COLUMNS, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfRedSoftPiBases, "AOD", "HFREDSOFTPIBASE", //! Table with track information for reduced workflow + soa::Index<>, + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_track_vars_reduced::ItsNCls, + hf_track_vars_reduced::TpcNClsCrossedRows, + hf_track_vars_reduced::TpcChi2NCl, + aod::track::Px, + aod::track::Py, + aod::track::Pz, + aod::track::PVector, + o2::soa::Marker<2>); + +DECLARE_SOA_TABLE(HfRedSoftPiCov, "AOD", "HFREDSOFTPICOV", //! Table with track covariance information for reduced workflow + soa::Index<>, + HFTRACKPARCOV_COLUMNS, + o2::soa::Marker<2>); + +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedBach0Bases, "AOD", "HFREDBACH0BASE", //! Table with track information for reduced workflow + soa::Index<>, + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_b_to_jpsi_track_vars_reduced::Pt, + hf_track_vars_reduced::ItsNCls, + hf_track_vars_reduced::TpcNClsCrossedRows, + hf_track_vars_reduced::TpcChi2NCl, + hf_track_vars_reduced::ItsChi2NCl, + hf_track_vars_reduced::HasTPC, + hf_track_vars_reduced::HasTOF, + pidtpc::TPCNSigmaPi, + pidtof::TOFNSigmaPi, + pidtpc::TPCNSigmaKa, + pidtof::TOFNSigmaKa, + pidtpc::TPCNSigmaPr, + pidtof::TOFNSigmaPr, + hf_track_pid_reduced::TPCTOFNSigmaPi, + hf_track_pid_reduced::TPCTOFNSigmaKa, + hf_track_pid_reduced::TPCTOFNSigmaPr, + aod::track::Px, + aod::track::Py, + aod::track::Pz, + aod::track::PVector); + +DECLARE_SOA_TABLE(HfRedBach0Cov, "AOD", "HFREDBACH0COV", //! Table with track covariance information for reduced workflow + soa::Index<>, + HFTRACKPARCOV_COLUMNS); + +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedBach1Bases, "AOD", "HFREDBACH1BASE", //! Table with track information for reduced workflow + soa::Index<>, + hf_track_index_reduced::TrackId, + hf_track_index_reduced::HfRedCollisionId, + HFTRACKPAR_COLUMNS, + hf_b_to_jpsi_track_vars_reduced::Pt, + hf_track_vars_reduced::ItsNCls, + hf_track_vars_reduced::TpcNClsCrossedRows, + hf_track_vars_reduced::TpcChi2NCl, + hf_track_vars_reduced::ItsChi2NCl, + hf_track_vars_reduced::HasTPC, + hf_track_vars_reduced::HasTOF, + pidtpc::TPCNSigmaPi, + pidtof::TOFNSigmaPi, + pidtpc::TPCNSigmaKa, + pidtof::TOFNSigmaKa, + pidtpc::TPCNSigmaPr, + pidtof::TOFNSigmaPr, + hf_track_pid_reduced::TPCTOFNSigmaPi, + hf_track_pid_reduced::TPCTOFNSigmaKa, + hf_track_pid_reduced::TPCTOFNSigmaPr, + aod::track::Px, + aod::track::Py, + aod::track::Pz, + aod::track::PVector); + +DECLARE_SOA_TABLE(HfRedBach1Cov, "AOD", "HFREDBACH1COV", //! Table with track covariance information for reduced workflow soa::Index<>, HFTRACKPARCOV_COLUMNS); @@ -289,8 +387,14 @@ DECLARE_SOA_TABLE(HfRedTracksPid, "AOD", "HFREDTRACKPID", //! Table with PID tra DECLARE_SOA_EXTENDED_TABLE_USER(HfRedTracksExt, HfRedTrackBases, "HFREDTRACKEXT", //! Track parameters at collision vertex aod::track::Pt); +DECLARE_SOA_EXTENDED_TABLE_USER(HfRedBach0Ext, HfRedBach0Bases, "HFREDBACH0EXT", //! Track parameters at collision vertex + aod::track::Pt); +DECLARE_SOA_EXTENDED_TABLE_USER(HfRedBach1Ext, HfRedBach1Bases, "HFREDBACH1EXT", //! Track parameters at collision vertex + aod::track::Pt); using HfRedTracks = HfRedTracksExt; +using HfRedBach0Tracks = HfRedBach0Bases; +using HfRedBach1Tracks = HfRedBach1Bases; namespace hf_charm_cand_reduced { @@ -304,6 +408,115 @@ DECLARE_SOA_COLUMN(MlScorePromptMassHypo1, mlScorePromptMassHypo1, float); DECLARE_SOA_COLUMN(MlScoreNonpromptMassHypo1, mlScoreNonpromptMassHypo1, float); //! ML score for non-prompt class (mass hypothesis 1) } // namespace hf_charm_cand_reduced +namespace hf_jpsi_cand_reduced +{ +DECLARE_SOA_COLUMN(ProngPosId, prongPosId, int); //! Original track index +DECLARE_SOA_COLUMN(ProngNegId, prongNegId, int); //! Original track index +DECLARE_SOA_COLUMN(HfRedCollisionId, hfRedCollisionId, int); //! Collision index +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate in GeV/c2 + +DECLARE_SOA_COLUMN(ItsNClsDauPos, itsNClsDauPos, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsDauPos, tpcNClsCrossedRowsDauPos, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(TpcChi2NClDauPos, tpcChi2NClDauPos, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(ItsChi2NClDauPos, itsChi2NClDauPos, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(ItsNClsDauNeg, itsNClsDauNeg, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsDauNeg, tpcNClsCrossedRowsDauNeg, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(TpcChi2NClDauNeg, tpcChi2NClDauNeg, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(ItsChi2NClDauNeg, itsChi2NClDauNeg, float); //! ITS chi2 / Number of clusters + +DECLARE_SOA_COLUMN(XDauPos, xDauPos, float); //! x +DECLARE_SOA_COLUMN(XDauNeg, xDauNeg, float); //! x +DECLARE_SOA_COLUMN(YDauPos, yDauPos, float); //! y +DECLARE_SOA_COLUMN(YDauNeg, yDauNeg, float); //! y +DECLARE_SOA_COLUMN(ZDauPos, zDauPos, float); //! z +DECLARE_SOA_COLUMN(ZDauNeg, zDauNeg, float); //! z +DECLARE_SOA_COLUMN(AlphaDauPos, alphaDauPos, float); //! alpha of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(AlphaDauNeg, alphaDauNeg, float); //! alpha of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(SnpDauPos, snpDauPos, float); //! snp of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(SnpDauNeg, snpDauNeg, float); //! snp of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(TglDauPos, tglDauPos, float); //! tgl of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(TglDauNeg, tglDauNeg, float); //! tgl of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(Signed1PtDauPos, signed1PtDauPos, float); //! signed1Pt of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(Signed1PtDauNeg, signed1PtDauNeg, float); //! signed1Pt of the J/Psi negative decay daughter + +DECLARE_SOA_DYNAMIC_COLUMN(PxDauPos, pxDauPos, //! Momentum in x-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (r * cs - snp * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PyDauPos, pyDauPos, //! Momentum in y-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (snp * cs + r * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PzDauPos, pzDauPos, //! Momentum in z-direction in GeV/c + [](float signed1Pt, float tgl) -> float { + auto pt = 1.f / std::abs(signed1Pt); + return pt * tgl; + }); +DECLARE_SOA_DYNAMIC_COLUMN(PxDauNeg, pxDauNeg, //! Momentum in x-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (r * cs - snp * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PyDauNeg, pyDauNeg, //! Momentum in y-direction in GeV/c + [](float signed1Pt, float snp, float alpha) -> float { + auto pt = 1.f / std::abs(signed1Pt); + // FIXME: GCC & clang should optimize to sincosf + float cs = cosf(alpha), sn = sinf(alpha); + auto r = std::sqrt((1.f - snp) * (1.f + snp)); + return pt * (snp * cs + r * sn); + }); +DECLARE_SOA_DYNAMIC_COLUMN(PzDauNeg, pzDauNeg, //! Momentum in z-direction in GeV/c + [](float signed1Pt, float tgl) -> float { + auto pt = 1.f / std::abs(signed1Pt); + return pt * tgl; + }); + +// Covariance matrix of the J/Psi positive decay daughter +DECLARE_SOA_COLUMN(CYYDauPos, cYYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZYDauPos, cZYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZZDauPos, cZZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpYDauPos, cSnpYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpZDauPos, cSnpZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpSnpDauPos, cSnpSnpDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglYDauPos, cTglYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglZDauPos, cTglZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglSnpDauPos, cTglSnpDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglTglDauPos, cTglTglDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtYDauPos, c1PtYDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtZDauPos, c1PtZDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtSnpDauPos, c1PtSnpDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtTglDauPos, c1PtTglDauPos, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1Pt21Pt2DauPos, c1Pt21Pt2DauPos, float); //! Covariance matrix + +// Covariance matrix of the J/Psi negative decay daughter +DECLARE_SOA_COLUMN(CYYDauNeg, cYYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZYDauNeg, cZYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CZZDauNeg, cZZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpYDauNeg, cSnpYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpZDauNeg, cSnpZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CSnpSnpDauNeg, cSnpSnpDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglYDauNeg, cTglYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglZDauNeg, cTglZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglSnpDauNeg, cTglSnpDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(CTglTglDauNeg, cTglTglDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtYDauNeg, c1PtYDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtZDauNeg, c1PtZDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtSnpDauNeg, c1PtSnpDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1PtTglDauNeg, c1PtTglDauNeg, float); //! Covariance matrix +DECLARE_SOA_COLUMN(C1Pt21Pt2DauNeg, c1Pt21Pt2DauNeg, float); //! Covariance matrix +} // namespace hf_jpsi_cand_reduced + // CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) // to call DECLARE_SOA_INDEX_COLUMN_FULL later on DECLARE_SOA_TABLE(HfRed2Prongs, "AOD", "HFRED2PRONG", //! Table with 2prong candidate information for reduced workflow @@ -370,6 +583,55 @@ DECLARE_SOA_TABLE_VERSIONED(HfRed3ProngsMl_001, "AOD", "HFRED3PRONGML", 1, //! T using HfRed3ProngsMl = HfRed3ProngsMl_001; +// CAREFUL: need to follow convention [Name = Description + 's'] in DECLARE_SOA_TABLE(Name, "AOD", Description) +// to call DECLARE_SOA_INDEX_COLUMN_FULL later on +DECLARE_SOA_TABLE(HfRedJpsis, "AOD", "HFREDJPSI", //! Table with J/Psi candidate information for reduced workflow + o2::soa::Index<>, + hf_jpsi_cand_reduced::ProngPosId, + hf_jpsi_cand_reduced::ProngNegId, + hf_track_index_reduced::HfRedCollisionId, + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_jpsi_cand_reduced::M, + hf_jpsi_cand_reduced::ItsNClsDauPos, + hf_jpsi_cand_reduced::TpcNClsCrossedRowsDauPos, + hf_jpsi_cand_reduced::TpcChi2NClDauPos, + hf_jpsi_cand_reduced::ItsChi2NClDauPos, + hf_jpsi_cand_reduced::ItsNClsDauNeg, + hf_jpsi_cand_reduced::TpcNClsCrossedRowsDauNeg, + hf_jpsi_cand_reduced::TpcChi2NClDauNeg, + hf_jpsi_cand_reduced::ItsChi2NClDauNeg, + hf_jpsi_cand_reduced::XDauPos, hf_jpsi_cand_reduced::XDauNeg, + hf_jpsi_cand_reduced::YDauPos, hf_jpsi_cand_reduced::YDauNeg, + hf_jpsi_cand_reduced::ZDauPos, hf_jpsi_cand_reduced::ZDauNeg, + hf_jpsi_cand_reduced::AlphaDauPos, hf_jpsi_cand_reduced::AlphaDauNeg, + hf_jpsi_cand_reduced::SnpDauPos, hf_jpsi_cand_reduced::SnpDauNeg, + hf_jpsi_cand_reduced::TglDauPos, hf_jpsi_cand_reduced::TglDauNeg, + hf_jpsi_cand_reduced::Signed1PtDauPos, hf_jpsi_cand_reduced::Signed1PtDauNeg, + hf_jpsi_cand_reduced::PxDauPos, + hf_jpsi_cand_reduced::PxDauNeg, + hf_jpsi_cand_reduced::PyDauPos, + hf_jpsi_cand_reduced::PyDauNeg, + hf_jpsi_cand_reduced::PzDauPos, + hf_jpsi_cand_reduced::PzDauNeg); + +DECLARE_SOA_TABLE(HfRedJpsiCov, "AOD", "HFREDJPSICOV", //! Table with J/Psi candidate covariance for reduced workflow + o2::soa::Index<>, + hf_jpsi_cand_reduced::CYYDauPos, hf_jpsi_cand_reduced::CYYDauNeg, + hf_jpsi_cand_reduced::CZYDauPos, hf_jpsi_cand_reduced::CZYDauNeg, + hf_jpsi_cand_reduced::CZZDauPos, hf_jpsi_cand_reduced::CZZDauNeg, + hf_jpsi_cand_reduced::CSnpYDauPos, hf_jpsi_cand_reduced::CSnpYDauNeg, + hf_jpsi_cand_reduced::CSnpZDauPos, hf_jpsi_cand_reduced::CSnpZDauNeg, + hf_jpsi_cand_reduced::CSnpSnpDauPos, hf_jpsi_cand_reduced::CSnpSnpDauNeg, + hf_jpsi_cand_reduced::CTglYDauPos, hf_jpsi_cand_reduced::CTglYDauNeg, + hf_jpsi_cand_reduced::CTglZDauPos, hf_jpsi_cand_reduced::CTglZDauNeg, + hf_jpsi_cand_reduced::CTglSnpDauPos, hf_jpsi_cand_reduced::CTglSnpDauNeg, + hf_jpsi_cand_reduced::CTglTglDauPos, hf_jpsi_cand_reduced::CTglTglDauNeg, + hf_jpsi_cand_reduced::C1PtYDauPos, hf_jpsi_cand_reduced::C1PtYDauNeg, + hf_jpsi_cand_reduced::C1PtZDauPos, hf_jpsi_cand_reduced::C1PtZDauNeg, + hf_jpsi_cand_reduced::C1PtSnpDauPos, hf_jpsi_cand_reduced::C1PtSnpDauNeg, + hf_jpsi_cand_reduced::C1PtTglDauPos, hf_jpsi_cand_reduced::C1PtTglDauNeg, + hf_jpsi_cand_reduced::C1Pt21Pt2DauPos, hf_jpsi_cand_reduced::C1Pt21Pt2DauNeg); + DECLARE_SOA_TABLE(HfRedPidDau0s_000, "AOD", "HFREDPIDDAU0", //! hf_track_pid_reduced::TPCNSigmaPiProng0, hf_track_pid_reduced::TOFNSigmaPiProng0, @@ -474,6 +736,8 @@ namespace hf_cand_bplus_reduced { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed2Prongs, "_0"); //! Prong0 index DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +DECLARE_SOA_INDEX_COLUMN_FULL(Jpsi, jpsi, int, HfRedJpsis, "_0"); //! J/Psi index +DECLARE_SOA_INDEX_COLUMN_FULL(BachKa, bachKa, int, HfRedBach0Bases, "_0"); //! J/Psi index DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter @@ -482,6 +746,9 @@ DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! N DECLARE_SOA_TABLE(HfRedBplusProngs, "AOD", "HFREDBPPRONG", hf_cand_bplus_reduced::Prong0Id, hf_cand_bplus_reduced::Prong1Id); +DECLARE_SOA_TABLE(HfRedBplus2JpsiDaus, "AOD", "HFREDBP2JPSIDAU", + hf_cand_bplus_reduced::JpsiId, hf_cand_bplus_reduced::BachKaId); + DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML scores for the D0 daughter hf_cand_bplus_reduced::Prong0MlScoreBkg, hf_cand_bplus_reduced::Prong0MlScorePrompt, @@ -489,19 +756,26 @@ DECLARE_SOA_TABLE(HfRedBplusD0Mls, "AOD", "HFREDBPLUSD0ML", //! Table with ML sc o2::soa::Marker<1>); using HfRedCandBplus = soa::Join; +using HfRedCandBplusToJpsiK = soa::Join; namespace hf_cand_bs_reduced { -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index -DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index -DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter -DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter -DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3Prongs, "_0"); //! Prong0 index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrackBases, "_1"); //! Prong1 index +DECLARE_SOA_INDEX_COLUMN_FULL(Jpsi, jpsi, int, HfRedJpsis, "_0"); //! J/Psi index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0Phi, prong0Phi, int, HfRedBach0Bases, "_0"); //! J/Psi index +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1Phi, prong1Phi, int, HfRedBach1Bases, "_0"); //! J/Psi index +DECLARE_SOA_COLUMN(Prong0MlScoreBkg, prong0MlScoreBkg, float); //! Bkg ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScorePrompt, prong0MlScorePrompt, float); //! Prompt ML score of the D daughter +DECLARE_SOA_COLUMN(Prong0MlScoreNonprompt, prong0MlScoreNonprompt, float); //! Nonprompt ML score of the D daughter } // namespace hf_cand_bs_reduced DECLARE_SOA_TABLE(HfRedBsProngs, "AOD", "HFREDBSPRONG", //! Table with Bs daughter indices hf_cand_bs_reduced::Prong0Id, hf_cand_bs_reduced::Prong1Id); +DECLARE_SOA_TABLE(HfRedBs2JpsiDaus, "AOD", "HFREDBS2JPSIDAU", + hf_cand_bs_reduced::JpsiId, hf_cand_bs_reduced::Prong0PhiId, hf_cand_bs_reduced::Prong1PhiId); + DECLARE_SOA_TABLE(HfRedBsDsMls, "AOD", "HFREDBSDSML", //! Table with ML scores for the Ds daughter hf_cand_bs_reduced::Prong0MlScoreBkg, hf_cand_bs_reduced::Prong0MlScorePrompt, @@ -509,6 +783,7 @@ DECLARE_SOA_TABLE(HfRedBsDsMls, "AOD", "HFREDBSDSML", //! Table with ML scores f o2::soa::Marker<1>); using HfRedCandBs = soa::Join; +using HfRedCandBsToJpsiPhi = soa::Join; namespace hf_cand_lb_reduced { @@ -576,6 +851,7 @@ DECLARE_SOA_TABLE(HfMcCheckDpPis, "AOD", "HFMCCHECKDPPI", //! Table with reconst // 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_b0_mc::PtMother); @@ -591,6 +867,7 @@ DECLARE_SOA_TABLE(HfMcCheckB0s, "AOD", "HFMCCHECKB0", //! Table with reconstruct 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_b0_mc::PtTrack, hf_b0_mc::YTrack, hf_b0_mc::EtaTrack, @@ -599,7 +876,10 @@ DECLARE_SOA_TABLE(HfMcGenRedB0s, "AOD", "HFMCGENREDB0", //! Generation-level MC hf_b0_mc::EtaProng0, hf_b0_mc::PtProng1, hf_b0_mc::YProng1, - hf_b0_mc::EtaProng1); + hf_b0_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the B0 part @@ -644,6 +924,16 @@ DECLARE_SOA_TABLE(HfMcRecRedD0Pis, "AOD", "HFMCRECREDD0PI", //! Table with recon hf_cand_bplus::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_bplus_mc::PtMother); + // DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", DECLARE_SOA_TABLE(HfMcCheckD0Pis, "AOD", "HFMCCHECKD0PI", //! Table with reconstructed MC information on D0Pi(<-B0) pairs for MC checks in reduced workflow hf_bplus_mc::PdgCodeBeautyMother, @@ -656,6 +946,7 @@ 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_bplus_mc::PtMother); @@ -670,6 +961,7 @@ DECLARE_SOA_TABLE(HfMcCheckBps, "AOD", "HFMCCHECKBP", //! Table with reconstruct 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_bplus_mc::PtTrack, hf_bplus_mc::YTrack, hf_bplus_mc::EtaTrack, @@ -678,7 +970,10 @@ DECLARE_SOA_TABLE(HfMcGenRedBps, "AOD", "HFMCGENREDBP", //! Generation-level MC hf_bplus_mc::EtaProng0, hf_bplus_mc::PtProng1, hf_bplus_mc::YProng1, - hf_bplus_mc::EtaProng1); + hf_bplus_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the Bplus part @@ -687,6 +982,7 @@ namespace hf_cand_bplus_config DECLARE_SOA_COLUMN(MySelectionFlagD0, mySelectionFlagD0, int8_t); //! Flag to filter selected D0 mesons DECLARE_SOA_COLUMN(MySelectionFlagD0bar, mySelectionFlagD0bar, int8_t); //! Flag to filter selected D0 mesons DECLARE_SOA_COLUMN(MyInvMassWindowD0Pi, myInvMassWindowD0Pi, float); //! Half-width of the Bplus invariant-mass window in GeV/c2 +DECLARE_SOA_COLUMN(MyInvMassWindowJpsiK, myInvMassWindowJpsiK, float); //! Half-width of the Bplus invariant-mass window in GeV/c2 } // namespace hf_cand_bplus_config DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with configurables information for reduced workflow @@ -694,6 +990,9 @@ DECLARE_SOA_TABLE(HfCandBpConfigs, "AOD", "HFCANDBPCONFIG", //! Table with confi hf_cand_bplus_config::MySelectionFlagD0bar, hf_cand_bplus_config::MyInvMassWindowD0Pi); +DECLARE_SOA_TABLE(HfCfgBpToJpsi, "AOD", "HFCFGBPTOJPSI", //! Table with configurables information for reduced workflow + hf_cand_bplus_config::MyInvMassWindowJpsiK); + namespace hf_bs_mc { // MC Rec @@ -726,6 +1025,17 @@ DECLARE_SOA_TABLE(HfMcRecRedDsPis, "AOD", "HFMCRECREDDSPI", //! Table with recon hf_cand_bs::DebugMcRec, hf_bs_mc::PtMother); +// table with results of reconstruction level MC matching +DECLARE_SOA_TABLE(HfMcRecRedJPPhis, "AOD", "HFMCRECREDJPPHI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for reduced workflow + 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_bs_mc::PtMother); + // try with extended table ? // DECLARE_SOA_EXTENDED_TABLE_USER(ExTable, Tracks, "EXTABLE", DECLARE_SOA_TABLE(HfMcCheckDsPis, "AOD", "HFMCCHECKDSPI", //! Table with reconstructed MC information on DsPi(<-Bs) pairs for MC checks in reduced workflow @@ -740,6 +1050,7 @@ 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_bs_mc::PtMother); @@ -755,6 +1066,7 @@ DECLARE_SOA_TABLE(HfMcCheckBss, "AOD", "HFMCCHECKBS", //! Table with reconstruct 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_bs_mc::PtTrack, hf_bs_mc::YTrack, hf_bs_mc::EtaTrack, @@ -763,20 +1075,26 @@ DECLARE_SOA_TABLE(HfMcGenRedBss, "AOD", "HFMCGENREDBS", //! Generation-level MC hf_bs_mc::EtaProng0, hf_bs_mc::PtProng1, hf_bs_mc::YProng1, - hf_bs_mc::EtaProng1); + hf_bs_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the Bs part namespace hf_cand_bs_config { -DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected Ds mesons -DECLARE_SOA_COLUMN(MyInvMassWindowDPi, myInvMassWindowDPi, float); //! Half-width of the Bs invariant-mass window in GeV/c2 +DECLARE_SOA_COLUMN(MySelectionFlagD, mySelectionFlagD, int8_t); //! Flag to filter selected Ds mesons +DECLARE_SOA_COLUMN(MyInvMassWindowDPi, myInvMassWindowDPi, float); //! Half-width of the Bs invariant-mass window in GeV/c2 +DECLARE_SOA_COLUMN(MyInvMassWindowJpsiPhi, myInvMassWindowJpsiPhi, float); //! Half-width of the Bs invariant-mass window in GeV/c2 } // namespace hf_cand_bs_config DECLARE_SOA_TABLE(HfCandBsConfigs, "AOD", "HFCANDBSCONFIG", //! Table with configurables information for reduced workflow hf_cand_bs_config::MySelectionFlagD, hf_cand_bs_config::MyInvMassWindowDPi); +DECLARE_SOA_TABLE(HfCfgBsToJpsis, "AOD", "HFCFGBSTOJPSI", //! Table with configurables information for reduced workflow + hf_cand_bs_config::MyInvMassWindowJpsiPhi); namespace hf_lb_mc { // MC Rec @@ -844,7 +1162,10 @@ DECLARE_SOA_TABLE(HfMcGenRedLbs, "AOD", "HFMCGENREDLB", //! Generation-level MC hf_lb_mc::EtaProng0, hf_lb_mc::PtProng1, hf_lb_mc::YProng1, - hf_lb_mc::EtaProng1); + hf_lb_mc::EtaProng1, + hf_reduced_collision::HfCollisionRejectionMap, + cent::CentFT0C, + cent::CentFT0M); // store all configurables values used in the first part of the workflow // so we can use them in the B0 part @@ -861,8 +1182,10 @@ DECLARE_SOA_TABLE(HfCandLbConfigs, "AOD", "HFCANDLBCONFIG", //! Table with confi // Charm resonances analysis namespace hf_reso_3_prong { -DECLARE_SOA_COLUMN(DType, dType, int8_t); //! Integer with selected D candidate type: 1 = Dplus, -1 = Dminus, 2 = DstarPlus, -2 = DstarMinus - +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Integer with selected D candidate sign +DECLARE_SOA_COLUMN(ItsNClsSoftPi, itsNClsSoftPi, int); //! minimum value of number of ITS clusters for the decay daughter tracks +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsSoftPi, tpcNClsCrossedRowsSoftPi, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks +DECLARE_SOA_COLUMN(TpcChi2NClSoftPi, tpcChi2NClSoftPi, float); //! maximum value of TPC chi2 for the decay daughter tracks DECLARE_SOA_DYNAMIC_COLUMN(Px, px, //! [](float pxProng0, float pxProng1, float pxProng2) -> float { return 1.f * pxProng0 + 1.f * pxProng1 + 1.f * pxProng2; }); DECLARE_SOA_DYNAMIC_COLUMN(Py, py, //! @@ -951,6 +1274,7 @@ DECLARE_SOA_TABLE(HfRedVzeros, "AOD", "HFREDVZERO", //! Table with V0 candidate DECLARE_SOA_TABLE(HfRedTrkNoParams, "AOD", "HFREDTRKNOPARAM", //! Table with tracks without track parameters for resonances reduced workflow o2::soa::Index<>, // Indices + hf_track_index_reduced::TrackId, hf_track_index_reduced::HfRedCollisionId, // Static hf_track_vars_reduced::Px, @@ -974,7 +1298,8 @@ DECLARE_SOA_TABLE(HfRedTrkNoParams, "AOD", "HFREDTRKNOPARAM", //! Table with tra hf_track_vars_reduced::Phi, hf_track_pid_reduced::TPCTOFNSigmaPi, hf_track_pid_reduced::TPCTOFNSigmaKa, - hf_track_pid_reduced::TPCTOFNSigmaPr); + hf_track_pid_reduced::TPCTOFNSigmaPr, + hf_track_vars_reduced::PVector); DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong candidate information for resonances reduced workflow o2::soa::Index<>, @@ -987,7 +1312,7 @@ DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, hf_track_vars_reduced::ItsNClsProngMin, hf_track_vars_reduced::TpcNClsCrossedRowsProngMin, hf_track_vars_reduced::TpcChi2NClProngMax, - hf_reso_3_prong::DType, + hf_reso_3_prong::Sign, // Dynamic hf_reso_3_prong::Px, hf_reso_3_prong::Py, @@ -999,10 +1324,6 @@ DECLARE_SOA_TABLE(HfRed3PrNoTrks, "AOD", "HFRED3PRNOTRK", //! Table with 3 prong hf_track_vars_reduced::EtaProng1, hf_track_vars_reduced::EtaProng2, hf_reso_3_prong::InvMassDplus, - hf_cand_dstar::InvMassDstar, - hf_cand_dstar::InvMassAntiDstar, - hf_cand_dstar::InvMassD0, - hf_cand_dstar::InvMassD0Bar, hf_reso_3_prong::Pt, hf_cand::PVectorProng0, hf_cand::PVectorProng1, @@ -1029,44 +1350,102 @@ DECLARE_SOA_TABLE(HfRed2PrNoTrks, "AOD", "HFRED2PRNOTRK", //! Table with 2 prong hf_track_vars_reduced::EtaProng0, hf_track_vars_reduced::EtaProng1, hf_reso_2_prong::PVector, + hf_cand::PVectorProng0, + hf_cand::PVectorProng1, hf_reso_2_prong::Pt, // InvMasses hf_cand_dstar::InvMassD0, hf_cand_dstar::InvMassD0Bar); +DECLARE_SOA_TABLE(HfRedDstarNoTrks, "AOD", "HFREDDSTARNOTRK", //! Table with 3 prong candidate information for resonances reduced workflow + o2::soa::Index<>, + // Indices + hf_track_index_reduced::Prong0Id, hf_track_index_reduced::Prong1Id, hf_track_index_reduced::Prong2Id, + hf_track_index_reduced::HfRedCollisionId, + // Static + hf_cand::XSecondaryVertex, hf_cand::YSecondaryVertex, hf_cand::ZSecondaryVertex, + hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, + hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, + hf_cand::PxProng2, hf_cand::PyProng2, hf_cand::PzProng2, + hf_track_vars_reduced::ItsNClsProngMin, hf_track_vars_reduced::TpcNClsCrossedRowsProngMin, hf_track_vars_reduced::TpcChi2NClProngMax, + hf_reso_3_prong::ItsNClsSoftPi, hf_reso_3_prong::TpcNClsCrossedRowsSoftPi, hf_reso_3_prong::TpcChi2NClSoftPi, + hf_reso_3_prong::Sign, + // Dynamic + hf_reso_3_prong::Px, + hf_reso_3_prong::Py, + hf_reso_3_prong::Pz, + hf_track_vars_reduced::PtProng0, + hf_track_vars_reduced::PtProng1, + hf_track_vars_reduced::PtProng2, + hf_track_vars_reduced::EtaProng0, + hf_track_vars_reduced::EtaProng1, + hf_track_vars_reduced::EtaProng2, + hf_cand_dstar::InvMassDstar, + hf_cand_dstar::InvMassAntiDstar, + hf_cand_dstar::InvMassD0, + hf_cand_dstar::InvMassD0Bar, + hf_reso_3_prong::Pt, + hf_cand::PVectorProng0, + hf_cand::PVectorProng1, + hf_cand::PVectorProng2, + hf_reso_3_prong::PVector); + namespace hf_reso_cand_reduced { DECLARE_SOA_COLUMN(InvMass, invMass, float); //! Invariant mass in GeV/c2 DECLARE_SOA_COLUMN(InvMassProng0, invMassProng0, float); //! Invariant Mass of D daughter in GeV/c -DECLARE_SOA_COLUMN(InvMassProng1, invMassProng1, float); //! Invariant Mass of V0 daughter in GeV/c -DECLARE_SOA_COLUMN(InvMassD0, invMassD0, float); //! Invariant Mass of potential D0 daughter +DECLARE_SOA_COLUMN(InvMassProng1, invMassProng1, float); //! Invariant Mass of V0/Tr daughter in GeV/c +DECLARE_SOA_COLUMN(Sign, sign, int8_t); //! Sign of the Resonance candidate +DECLARE_SOA_COLUMN(IsWrongSign, isWrongSign, int8_t); //! Flag for wrong sign of the Resonance candidate, 1 = wrong sign, 0 = right sign -DECLARE_SOA_COLUMN(MlScoreBkgProng0, mlScoreBkgProng0, float); //! Bkg ML score of the D daughter -DECLARE_SOA_COLUMN(MlScorePromptProng0, mlScorePromptProng0, float); //! Prompt ML score of the D daughter -DECLARE_SOA_COLUMN(MlScoreNonpromptProng0, mlScoreNonpromptProng0, float); //! Nonprompt ML score of the D daughter - -DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3PrNoTrks, "_0"); //! Prong0 index (D daughter) -DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // flag for decay channel classification reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // flag for resonance decay channel classification reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchRecD, flagMcMatchRecD, int8_t); // flag for D meson bachelor decay channel classification reconstruction level +DECLARE_SOA_COLUMN(FlagMcMatchChanD, flagMcMatchChanD, int8_t); // flag for D meson resonant channel classification reconstruction level DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // flag for decay channel classification generator level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); // debug flag for mis-association at reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, uint16_t); // debug flag for mis-association at reconstruction level DECLARE_SOA_COLUMN(Origin, origin, int8_t); // Flag for origin of MC particle 1=promt, 2=FD DECLARE_SOA_COLUMN(SignD0, signD0, int8_t); // Sign of the D0 in the channels with D* -> D0 pi, needed in case of non-matched D* +DECLARE_SOA_COLUMN(PtGen, ptGen, float); // Pt at generation level in GeV/c DECLARE_SOA_COLUMN(InvMassGen, invMassGen, float); //! Invariant mass at generation level in GeV/c2 -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! [](float pxProng0, float pxProng1, float pyProng0, float pyProng1) -> float { return RecoDecay::pt((1.f * pxProng0 + 1.f * pxProng1), (1.f * pyProng0 + 1.f * pyProng1)); }); DECLARE_SOA_DYNAMIC_COLUMN(PtProng0, ptProng0, //! [](float pxProng0, float pyProng0) -> float { return RecoDecay::pt(pxProng0, pyProng0); }); DECLARE_SOA_DYNAMIC_COLUMN(PtProng1, ptProng1, //! [](float pxProng1, float pyProng1) -> float { return RecoDecay::pt(pxProng1, pyProng1); }); -DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarDs1, cosThetaStarDs1, //! costhetastar under Ds1 hypothesis - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDStar, o2::constants::physics::MassK0}, invMass, 1); }); -DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarDs2Star, cosThetaStarDs2Star, //! costhetastar under Ds2Star hypothesis - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassK0}, invMass, 1); }); -DECLARE_SOA_DYNAMIC_COLUMN(CosThetaStarXiC3055, cosThetaStarXiC3055, //! costhetastar under XiC3055 hypothesis - [](float px0, float py0, float pz0, float px1, float py1, float pz1, float invMass) -> float { return RecoDecay::cosThetaStar(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}}, std::array{o2::constants::physics::MassDPlus, o2::constants::physics::MassLambda0}, invMass, 1); }); } // namespace hf_reso_cand_reduced +namespace hf_reso_3pr_v0 +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) +} // namespace hf_reso_3pr_v0 +namespace hf_reso_dstar_v0 +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRedDstarNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) +} // namespace hf_reso_dstar_v0 +namespace hf_reso_2pr_v0 +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed2PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedVzeros, "_1"); //! Prong1 index (V0 daughter) +} // namespace hf_reso_2pr_v0 +namespace hf_reso_3pr_trk +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed3PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrkNoParams, "_1"); //! Prong1 index (Track daughter) +} // namespace hf_reso_3pr_trk +namespace hf_reso_dstar_trk +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRedDstarNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrkNoParams, "_1"); //! Prong1 index (Track daughter) +} // namespace hf_reso_dstar_trk +namespace hf_reso_2pr_trk +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, HfRed2PrNoTrks, "_0"); //! Prong0 index (D daughter) +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, HfRedTrkNoParams, "_1"); //! Prong1 index (Track daughter) +} // namespace hf_reso_2pr_trk + DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Resonance candidate information for resonances reduced workflow o2::soa::Index<>, // Static @@ -1075,10 +1454,8 @@ DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Reso hf_reso_cand_reduced::InvMass, hf_reso_cand_reduced::InvMassProng0, hf_reso_cand_reduced::InvMassProng1, - hf_reso_v0::Cpa, - hf_reso_v0::Dca, - hf_reso_v0::Radius, - hf_reso_cand_reduced::InvMassD0, + hf_reso_cand_reduced::Sign, + hf_reso_cand_reduced::IsWrongSign, // Dynamic hf_reso_cand_reduced::Pt, hf_reso_cand_reduced::PtProng0, @@ -1087,33 +1464,111 @@ DECLARE_SOA_TABLE(HfCandCharmReso, "AOD", "HFCANDCHARMRESO", //! Table with Reso hf_reso_v0::Py, hf_reso_v0::Pz, hf_cand::PVectorProng0, - hf_cand::PVectorProng1, - hf_reso_cand_reduced::CosThetaStarDs1, - hf_reso_cand_reduced::CosThetaStarDs2Star, - hf_reso_cand_reduced::CosThetaStarXiC3055); + hf_cand::PVectorProng1); -DECLARE_SOA_TABLE(HfResoIndices, "AOD", "HFRESOINDICES", //! Table with Indices of resonance daughters for MC matching +DECLARE_SOA_TABLE(Hf3PrV0Ids, "AOD", "HF3PRV0ID", hf_track_index_reduced::HfRedCollisionId, - hf_reso_cand_reduced::Prong0Id, - hf_reso_cand_reduced::Prong1Id); - -DECLARE_SOA_TABLE(HfCharmResoMLs, "AOD", "HFCHARMRESOML", //! Table with ML scores for the D daughter - hf_reso_cand_reduced::MlScoreBkgProng0, - hf_reso_cand_reduced::MlScorePromptProng0, - hf_reso_cand_reduced::MlScoreNonpromptProng0, - o2::soa::Marker<1>); + hf_reso_3pr_v0::Prong0Id, + hf_reso_3pr_v0::Prong1Id); +DECLARE_SOA_TABLE(HfDstarV0Ids, "AOD", "HFDSTARV0ID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_dstar_v0::Prong0Id, + hf_reso_dstar_v0::Prong1Id); +DECLARE_SOA_TABLE(Hf2PrV0Ids, "AOD", "HF2PRV0ID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_2pr_v0::Prong0Id, + hf_reso_2pr_v0::Prong1Id); +DECLARE_SOA_TABLE(Hf3PrTrkIds, "AOD", "HF3PRTRKID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_3pr_trk::Prong0Id, + hf_reso_3pr_trk::Prong1Id); +DECLARE_SOA_TABLE(HfDstarTrkIds, "AOD", "HFDSTARTRKID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_dstar_trk::Prong0Id, + hf_reso_dstar_trk::Prong1Id); +DECLARE_SOA_TABLE(Hf2PrTrkIds, "AOD", "HF2PRTRKID", + hf_track_index_reduced::HfRedCollisionId, + hf_reso_2pr_trk::Prong0Id, + hf_reso_2pr_trk::Prong1Id); // Tables for MC Resonance analysis // table with results of reconstruction level MC matching -DECLARE_SOA_TABLE(HfMcRecRedDV0s, "AOD", "HFMCRECREDDV0", //! Table with reconstructed MC information on DV0(<-Ds*) pairs for reduced workflow - hf_reso_cand_reduced::Prong0Id, - hf_reso_cand_reduced::Prong1Id, +DECLARE_SOA_TABLE(Hf3PrV0McRec, "AOD", "HF3PRV0MCREC", + hf_reso_3pr_v0::Prong0Id, + hf_reso_3pr_v0::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfDstarV0McRec, "AOD", "HFDSTARV0MCREC", + hf_reso_dstar_v0::Prong0Id, + hf_reso_dstar_v0::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(Hf2PrV0McRec, "AOD", "HF2PRV0MCREC", + hf_reso_2pr_v0::Prong0Id, + hf_reso_2pr_v0::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(Hf3PrTrkMcRec, "AOD", "HF3PRTRKMCREC", + hf_reso_3pr_trk::Prong0Id, + hf_reso_3pr_trk::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(HfDstarTrkMcRec, "AOD", "HFDSTARTRKMCREC", + hf_reso_dstar_trk::Prong0Id, + hf_reso_dstar_trk::Prong1Id, + hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, + hf_reso_cand_reduced::DebugMcRec, + hf_reso_cand_reduced::Origin, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(Hf2PrTrkMcRec, "AOD", "HF2PRTRKMCREC", + hf_reso_2pr_trk::Prong0Id, + hf_reso_2pr_trk::Prong1Id, hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, hf_reso_cand_reduced::DebugMcRec, hf_reso_cand_reduced::Origin, - hf_reso_cand_reduced::SignD0, - hf_b0_mc::PtMother, + hf_reso_cand_reduced::PtGen, hf_reso_cand_reduced::InvMassGen, + hf_cand::NTracksDecayed, o2::soa::Marker<1>); DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level MC information on Ds-Resonances candidates for reduced workflow @@ -1128,23 +1583,19 @@ DECLARE_SOA_TABLE(HfMcGenRedResos, "AOD", "HFMCGENREDRESO", //! Generation-level hf_b0_mc::PtProng1, hf_b0_mc::YProng1, hf_b0_mc::EtaProng1, + hf_reso_cand_reduced::InvMassGen, + hf_reduced_collision::HfCollisionRejectionMap, o2::soa::Marker<1>); -DECLARE_SOA_TABLE(HfCandChaResTr, "AOD", "HFCANDCHARESTR", //! Table with Resonance candidate information for resonances plus tracks reduced workflow - // Static - hf_cand::PxProng0, hf_cand::PyProng0, hf_cand::PzProng0, - hf_cand::PxProng1, hf_cand::PyProng1, hf_cand::PzProng1, - hf_reso_cand_reduced::InvMass, - hf_reso_cand_reduced::InvMassProng0, - // Dynamic - hf_reso_cand_reduced::PtProng0); - // Table with same size as HfCandCharmReso DECLARE_SOA_TABLE(HfMcRecRedResos, "AOD", "HFMCRECREDRESO", //! Reconstruction-level MC information on Ds-Resonances candidates for reduced workflow hf_reso_cand_reduced::FlagMcMatchRec, + hf_reso_cand_reduced::FlagMcMatchRecD, + hf_reso_cand_reduced::FlagMcMatchChanD, hf_reso_cand_reduced::DebugMcRec, hf_reso_cand_reduced::Origin, - hf_b0_mc::PtMother, + hf_reso_cand_reduced::PtGen, + hf_reso_cand_reduced::InvMassGen, o2::soa::Marker<1>); } // namespace aod diff --git a/PWGHF/D2H/Macros/CMakeLists_HFInvMassFitter.txt b/PWGHF/D2H/Macros/CMakeLists_HFInvMassFitter.txt new file mode 100644 index 00000000000..5a74cec1768 --- /dev/null +++ b/PWGHF/D2H/Macros/CMakeLists_HFInvMassFitter.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.10) + +project(HFInvMassFitter) + +set(HFFITTER_RAPIDJSON_INCLUDE_DIRS "" CACHE STRING "Location of rapidjson include directories") + +find_package(ROOT REQUIRED COMPONENTS RooFit RooFitCore) + +include_directories(${ROOT_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR} ${HFFITTER_RAPIDJSON_INCLUDE_DIRS}) + +set(SOURCES + HFInvMassFitter.cxx + runMassFitter.C +) + +add_executable(runMassFitter ${SOURCES} "HFInvMassFitter.h") + +ROOT_GENERATE_DICTIONARY(G__HFInvMassFitter + HFInvMassFitter.h LINKDEF HFInvMassFitterLinkDef.h + MODULE runMassFitter +) + +target_link_libraries(runMassFitter PRIVATE ${ROOT_LIBRARIES} ROOT::EG ROOT::RooFit ROOT::RooFitCore) diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.cxx b/PWGHF/D2H/Macros/HFInvMassFitter.cxx index 255de80a079..fba3d7c67a1 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.cxx +++ b/PWGHF/D2H/Macros/HFInvMassFitter.cxx @@ -16,6 +16,7 @@ /// \author Mingyu Zhang /// \author Xinye Peng /// \author Biao Zhang +/// \author Oleksii Lubynets #include "HFInvMassFitter.h" @@ -33,9 +34,6 @@ #include #include #include - -#include -#include #include #include #include @@ -45,24 +43,33 @@ #include #include +#include +#include + #include #include #include +#include +#include using namespace RooFit; ClassImp(HFInvMassFitter); HFInvMassFitter::HFInvMassFitter() : TNamed(), - mHistoInvMass(0x0), + mHistoInvMass(nullptr), mFitOption("L,E"), mMinMass(0), mMaxMass(5), mTypeOfBkgPdf(Expo), - mMassParticle(TDatabasePDG::Instance()->GetParticle("D0")->Mass()), 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), @@ -73,12 +80,6 @@ HFInvMassFitter::HFInvMassFitter() : TNamed(), mFixedMean(kFALSE), mBoundMean(kFALSE), mBoundReflMean(kFALSE), - mRooMeanSgn(0x0), - mRooSigmaSgn(0x0), - mMassLowLimit(0), - mMassUpLimit(0), - mMassReflLowLimit(0), - mMassReflUpLimit(0), mFixedSigma(kFALSE), mFixedSigmaDoubleGaus(kFALSE), mBoundSigma(kFALSE), @@ -93,27 +94,34 @@ HFInvMassFitter::HFInvMassFitter() : TNamed(), mEnableReflections(kFALSE), mRawYield(0), mRawYieldErr(0), + mRawYieldCounted(0), + mRawYieldCountedErr(0), mBkgYield(0), mBkgYieldErr(0), mSignificance(0), mSignificanceErr(0), - mChiSquareOverNdf(0), - mSgnPdf(0x0), - mBkgPdf(0x0), - mReflPdf(0x0), + mChiSquareOverNdfTotal(0), + mChiSquareOverNdfBkg(0), + mFixReflOverSgn(kFALSE), + mRooMeanSgn(nullptr), + mRooSigmaSgn(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), - mRooNSgn(0x0), - mRooNBkg(0x0), - mRooNRefl(0x0), - mTotalPdf(0x0), - mInvMassFrame(0x0), - mReflFrame(0x0), - mReflOnlyFrame(0x0), - mResidualFrame(0x0), - mWorkspace(0x0), - mHistoTemplateRefl(0x0), + mHistoTemplateRefl(nullptr), mDrawBgPrefit(kFALSE), mHighlightPeakRegion(kFALSE) { @@ -121,15 +129,19 @@ HFInvMassFitter::HFInvMassFitter() : TNamed(), } HFInvMassFitter::HFInvMassFitter(const TH1* histoToFit, Double_t minValue, Double_t maxValue, Int_t fitTypeBkg, Int_t fitTypeSgn) : TNamed(), - mHistoInvMass(0x0), + mHistoInvMass(nullptr), mFitOption("L,E"), mMinMass(minValue), mMaxMass(maxValue), mTypeOfBkgPdf(fitTypeBkg), - mMassParticle(TDatabasePDG::Instance()->GetParticle("D0")->Mass()), 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), @@ -140,12 +152,6 @@ HFInvMassFitter::HFInvMassFitter(const TH1* histoToFit, Double_t minValue, Doubl mFixedMean(kFALSE), mBoundMean(kFALSE), mBoundReflMean(kFALSE), - mRooMeanSgn(0x0), - mRooSigmaSgn(0x0), - mMassLowLimit(0), - mMassUpLimit(0), - mMassReflLowLimit(0), - mMassReflUpLimit(0), mFixedSigma(kFALSE), mFixedSigmaDoubleGaus(kFALSE), mBoundSigma(kFALSE), @@ -160,33 +166,40 @@ HFInvMassFitter::HFInvMassFitter(const TH1* histoToFit, Double_t minValue, Doubl mEnableReflections(kFALSE), mRawYield(0), mRawYieldErr(0), + mRawYieldCounted(0), + mRawYieldCountedErr(0), mBkgYield(0), mBkgYieldErr(0), mSignificance(0), mSignificanceErr(0), - mChiSquareOverNdf(0), - mSgnPdf(0x0), - mBkgPdf(0x0), - mReflPdf(0x0), + mChiSquareOverNdfTotal(0), + mChiSquareOverNdfBkg(0), + mFixReflOverSgn(kFALSE), + mRooMeanSgn(nullptr), + mRooSigmaSgn(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), - mRooNSgn(0x0), - mRooNBkg(0x0), - mRooNRefl(0x0), - mTotalPdf(0x0), - mInvMassFrame(0x0), - mReflFrame(0x0), - mReflOnlyFrame(0x0), - mResidualFrame(0x0), - mWorkspace(0x0), - mHistoTemplateRefl(0x0), + mHistoTemplateRefl(nullptr), mDrawBgPrefit(kFALSE), mHighlightPeakRegion(kFALSE) { // standard constructor mHistoInvMass = dynamic_cast(histoToFit->Clone(histoToFit->GetTitle())); - mHistoInvMass->SetDirectory(0); + mHistoInvMass->SetDirectory(nullptr); } HFInvMassFitter::~HFInvMassFitter() @@ -271,6 +284,12 @@ void HFInvMassFitter::doFit() mBkgPdf->fitTo(dataHistogram, Range("SBL,SBR"), Save()); } } + // define the frame to evaluate background sidebands chi2 (bg pdf needs to be plotted within sideband ranges) + RooPlot* frameTemporary = mass->frame(Title(Form("%s_temp", mHistoInvMass->GetTitle()))); + dataHistogram.plotOn(frameTemporary, Name("data_for_bkgchi2")); + mBkgPdf->plotOn(frameTemporary, Range("SBL", "SBR"), 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()); @@ -320,9 +339,9 @@ void HFInvMassFitter::doFit() mReflPdf = new RooAddPdf("mReflPdf", "reflection fit function", RooArgList(*reflPdf), RooArgList(*mRooNRefl)); RooAddPdf reflBkgPdf("reflBkgPdf", "reflBkgPdf", RooArgList(*bkgPdf, *reflPdf), RooArgList(*mRooNBkg, *mRooNRefl)); reflBkgPdf.plotOn(mInvMassFrame, Normalization(1.0, RooAbsReal::RelativeExpected), LineStyle(7), LineColor(kRed + 1), Name("ReflBkg_c")); - plotBkg(mTotalPdf); // plot bkg pdf in total pdf - plotRefl(mTotalPdf); // plot reflection in total pdf - mChiSquareOverNdf = mInvMassFrame->chiSquare("Tot_c", "data_c"); // calculate reduced chi2 / NDF + plotBkg(mTotalPdf); // plot bkg pdf in total pdf + plotRefl(mTotalPdf); // plot reflection in total pdf + mChiSquareOverNdfTotal = mInvMassFrame->chiSquare("Tot_c", "data_c"); // calculate reduced chi2 / NDF // plot residual distribution RooHist* residualHistogram = mInvMassFrame->residHist("data_c", "ReflBkg_c"); @@ -339,7 +358,7 @@ void HFInvMassFitter::doFit() plotBkg(mTotalPdf); mTotalPdf->plotOn(mInvMassFrame, Name("Tot_c"), LineColor(kBlue)); mSgnPdf->plotOn(mInvMassFrame, Normalization(1.0, RooAbsReal::RelativeExpected), DrawOption("F"), FillColor(TColor::GetColorTransparent(kBlue, 0.2)), VLines()); - mChiSquareOverNdf = mInvMassFrame->chiSquare("Tot_c", "data_c"); // calculate reduced chi2 / DNF + mChiSquareOverNdfTotal = mInvMassFrame->chiSquare("Tot_c", "data_c"); // calculate reduced chi2 / DNF // plot residual distribution mResidualFrame = mass->frame(Title("Residual Distribution")); RooHist* residualHistogram = mInvMassFrame->residHist("data_c", "Bkg_c"); @@ -562,14 +581,23 @@ void HFInvMassFitter::drawFit(TVirtualPad* pad, Int_t writeFitInfo) } if (mTypeOfBkgPdf != NoBkg) { textInfoLeft->AddText(Form("Signif (%d#sigma) = %.1f #pm %.1f ", mNSigmaForSidebands, mSignificance, mSignificanceErr)); - textInfoLeft->AddText(Form("#chi^{2} / ndf = %.3f", mChiSquareOverNdf)); + textInfoLeft->AddText(Form("#chi^{2} / ndf = %.3f", mChiSquareOverNdfTotal)); } if (mFixedMean) { textInfoRight->AddText(Form("mean(fixed) = %.3f #pm %.3f", mRooMeanSgn->getVal(), mRooMeanSgn->getError())); } else { textInfoRight->AddText(Form("mean(free) = %.3f #pm %.3f", mRooMeanSgn->getVal(), mRooMeanSgn->getError())); } - if (mFixedSigma) { + if (mTypeOfSgnPdf == DoubleGaus) { + auto const& baseSigmaSgn = mWorkspace->var("sigma"); + if (mFixedSigmaDoubleGaus) { + textInfoRight->AddText(Form("sigma(fixed) = %.3f #pm %.3f", baseSigmaSgn->getVal(), baseSigmaSgn->getError())); + textInfoRight->AddText(Form("sigma 2(fixed) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); + } else { + textInfoRight->AddText(Form("sigma(free) = %.3f #pm %.3f", baseSigmaSgn->getVal(), baseSigmaSgn->getError())); + textInfoRight->AddText(Form("sigma 2(free) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); + } + } else if (mFixedSigma) { textInfoRight->AddText(Form("sigma(fixed) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); } else { textInfoRight->AddText(Form("sigma(free) = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); @@ -600,7 +628,13 @@ 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) { + auto const& baseSigmaSgn = mWorkspace->var("sigma"); + textInfo->AddText(Form("sigma = %.3f #pm %.3f", baseSigmaSgn->getVal(), baseSigmaSgn->getError())); + textInfo->AddText(Form("sigma 2 = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); + } else { + textInfo->AddText(Form("sigma = %.3f #pm %.3f", mRooSigmaSgn->getVal(), mRooSigmaSgn->getError())); + } mResidualFrame->addObject(textInfo); mResidualFrame->Draw(); highlightPeakRegion(mResidualFrame); @@ -711,40 +745,22 @@ void HFInvMassFitter::checkForSignal(Double_t& estimatedSignal) // Create Background Fit Function RooAbsPdf* HFInvMassFitter::createBackgroundFitFunction(RooWorkspace* workspace) const { - RooAbsPdf* bkgPdf; - switch (mTypeOfBkgPdf) { - case 0: // exponential - { - bkgPdf = workspace->pdf("bkgFuncExpo"); - } break; - case 1: // poly1 - { - bkgPdf = workspace->pdf("bkgFuncPoly1"); - } break; - case 2: { - bkgPdf = workspace->pdf("bkgFuncPoly2"); - } break; - case 3: { - bkgPdf = workspace->pdf("bkgFuncPow"); - } break; - case 4: { - bkgPdf = workspace->pdf("bkgFuncPowExpo"); - } break; - case 5: { - bkgPdf = workspace->pdf("bkgFuncPoly3"); - } break; - case 6: // MC - break; - default: - break; + RooAbsPdf* bkgPdf{nullptr}; + if (mTypeOfBkgPdf == NoBkg) { + return bkgPdf; + } + if (mTypeOfBkgPdf < 0 || mTypeOfBkgPdf >= NTypesOfBkgPdf) { + throw std::runtime_error("createBackgroundFitFunction(): mTypeOfBkgPdf must be within [0; " + std::to_string(NTypesOfBkgPdf) + ") range"); } + bkgPdf = workspace->pdf(namesOfBkgPdf.at(mTypeOfBkgPdf)); + return bkgPdf; } // Create Signal Fit Function RooAbsPdf* HFInvMassFitter::createSignalFitFunction(RooWorkspace* workspace) { - RooAbsPdf* sgnPdf; + RooAbsPdf* sgnPdf{nullptr}; switch (mTypeOfSgnPdf) { case 0: { sgnPdf = workspace->pdf("sgnFuncGaus"); @@ -775,74 +791,33 @@ RooAbsPdf* HFInvMassFitter::createSignalFitFunction(RooWorkspace* workspace) // Create Reflection Fit Function RooAbsPdf* HFInvMassFitter::createReflectionFitFunction(RooWorkspace* workspace) const { - RooAbsPdf* reflPdf; - switch (mTypeOfReflPdf) { - case 0: { - reflPdf = workspace->pdf("reflFuncGaus"); - } break; - case 1: { - reflPdf = workspace->pdf("reflFuncDoubleGaus"); - } break; - case 2: { - reflPdf = workspace->pdf("reflFuncPoly3"); - } break; - case 3: { - reflPdf = workspace->pdf("reflFuncPoly6"); - } break; - default: - break; + if (mTypeOfReflPdf < 0 || mTypeOfReflPdf >= NTypesOfReflPdf) { + throw std::runtime_error("createReflectionFitFunction(): mTypeOfReflPdf must be within [0; " + std::to_string(NTypesOfReflPdf) + ") range"); } + RooAbsPdf* reflPdf = workspace->pdf(namesOfReflPdf.at(mTypeOfReflPdf)); + return reflPdf; } // Plot Bkg components of fTotFunction void HFInvMassFitter::plotBkg(RooAbsPdf* pdf, Color_t color) { - switch (mTypeOfBkgPdf) { - case 0: - pdf->plotOn(mInvMassFrame, Components("bkgFuncExpo"), Name("Bkg_c"), LineColor(color)); - break; - case 1: - pdf->plotOn(mInvMassFrame, Components("bkgFuncPoly1"), Name("Bkg_c"), LineColor(color)); - break; - case 2: - pdf->plotOn(mInvMassFrame, Components("bkgFuncPoly2"), Name("Bkg_c"), LineColor(color)); - break; - case 3: - pdf->plotOn(mInvMassFrame, Components("bkgFuncPow"), Name("Bkg_c"), LineColor(color)); - break; - case 4: - pdf->plotOn(mInvMassFrame, Components("bkgFuncPowExp"), Name("Bkg_c"), LineColor(color)); - break; - case 5: - pdf->plotOn(mInvMassFrame, Components("bkgFuncPoly3"), Name("Bkg_c"), LineColor(color)); - break; - case 6: - break; - default: - break; + if (mTypeOfBkgPdf == NoBkg) { + return; + } + if (mTypeOfBkgPdf < 0 || mTypeOfBkgPdf >= NTypesOfBkgPdf) { + throw std::runtime_error("plotBkg(): mTypeOfBkgPdf must be within [0; " + std::to_string(NTypesOfBkgPdf) + ") range"); } + pdf->plotOn(mInvMassFrame, Components(namesOfBkgPdf.at(mTypeOfBkgPdf).c_str()), Name("Bkg_c"), LineColor(color)); } // Plot Refl distribution on canvas void HFInvMassFitter::plotRefl(RooAbsPdf* pdf) { - switch (mTypeOfReflPdf) { - case 0: - pdf->plotOn(mInvMassFrame, Components("reflFuncGaus"), Name("Refl_c"), LineColor(kGreen)); - break; - case 1: - pdf->plotOn(mInvMassFrame, Components("reflFuncDoubleGaus"), Name("Refl_c"), LineColor(kGreen)); - break; - case 2: - pdf->plotOn(mInvMassFrame, Components("reflFuncPoly3"), Name("Refl_c"), LineColor(kGreen)); - break; - case 3: - pdf->plotOn(mInvMassFrame, Components("reflFuncPoly6"), Name("Refl_c"), LineColor(kGreen)); - break; - default: - break; + if (mTypeOfReflPdf < 0 || mTypeOfReflPdf >= NTypesOfReflPdf) { + throw std::runtime_error("plotRefl(): mTypeOfReflPdf must be within [0; " + std::to_string(NTypesOfReflPdf) + ") range"); } + pdf->plotOn(mInvMassFrame, Components(namesOfReflPdf.at(mTypeOfReflPdf).c_str()), Name("Refl_c"), LineColor(kGreen)); } // Fix reflection pdf diff --git a/PWGHF/D2H/Macros/HFInvMassFitter.h b/PWGHF/D2H/Macros/HFInvMassFitter.h index 8a236412a13..5ec95ebd473 100644 --- a/PWGHF/D2H/Macros/HFInvMassFitter.h +++ b/PWGHF/D2H/Macros/HFInvMassFitter.h @@ -16,6 +16,7 @@ /// \author Mingyu Zhang /// \author Xinye Peng /// \author Biao Zhang +/// \author Oleksii Lubynets #ifndef PWGHF_D2H_MACROS_HFINVMASSFITTER_H_ #define PWGHF_D2H_MACROS_HFINVMASSFITTER_H_ @@ -23,15 +24,17 @@ #include #include #include -#include -#include - #include #include #include #include +#include +#include + #include +#include +#include class HFInvMassFitter : public TNamed { @@ -43,20 +46,25 @@ class HFInvMassFitter : public TNamed Pow = 3, PowExpo = 4, Poly3 = 5, - NoBkg = 6 + NoBkg = 6, + NTypesOfBkgPdf }; + std::vector namesOfBkgPdf{"bkgFuncExpo", "bkgFuncPoly1", "bkgFuncPoly2", "bkgFuncPow", "bkgFuncPowExpo", "bkgFuncPoly3"}; enum TypeOfSgnPdf { SingleGaus = 0, DoubleGaus = 1, DoubleGausSigmaRatioPar = 2, - GausSec = 3 + GausSec = 3, + NTypesOfSgnPdf }; enum TypeOfReflPdf { SingleGausRefl = 0, DoubleGausRefl = 1, Poly3Refl = 2, - Poly6Refl = 3 + 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); ~HFInvMassFitter(); @@ -189,7 +197,8 @@ class HFInvMassFitter : public TNamed } void setDrawBgPrefit(Bool_t value = true) { mDrawBgPrefit = value; } void setHighlightPeakRegion(Bool_t value = true) { mHighlightPeakRegion = value; } - Double_t getChiSquareOverNDF() const { return mChiSquareOverNdf; } + Double_t getChiSquareOverNDFTotal() const { return mChiSquareOverNdfTotal; } + Double_t getChiSquareOverNDFBkg() const { return mChiSquareOverNdfBkg; } Double_t getRawYield() const { return mRawYield; } Double_t getRawYieldError() const { return mRawYieldErr; } Double_t getRawYieldCounted() const { return mRawYieldCounted; } @@ -268,7 +277,8 @@ class HFInvMassFitter : public TNamed Double_t mBkgYieldErr; /// err on background Double_t mSignificance; /// significance Double_t mSignificanceErr; /// err on significance - Double_t mChiSquareOverNdf; /// chi2/ndf + 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 diff --git a/PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h b/PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h new file mode 100644 index 00000000000..cc755de478f --- /dev/null +++ b/PWGHF/D2H/Macros/HFInvMassFitterLinkDef.h @@ -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. + +/// \file HFInvMassFitterLinkDef.h +/// \brief HFInvMassFitter dictionary definition file +/// +/// \author Zhen Zhang +/// \author Mingyu Zhang +/// \author Xinye Peng +/// \author Biao Zhang +/// \author Oleksii Lubynets + +#ifndef PWGHF_D2H_MACROS_HFINVMASSFITTERLINKDEF_H_ +#define PWGHF_D2H_MACROS_HFINVMASSFITTERLINKDEF_H_ + +#ifdef __CINT__ +#pragma link off all globals; +#pragma link off all classes; +#pragma link off all functions; +#pragma link C++ class HFInvMassFitter + ; +#endif + +#endif // PWGHF_D2H_MACROS_HFINVMASSFITTERLINKDEF_H_ diff --git a/PWGHF/D2H/Macros/README.md b/PWGHF/D2H/Macros/README.md new file mode 100644 index 00000000000..f65de110419 --- /dev/null +++ b/PWGHF/D2H/Macros/README.md @@ -0,0 +1,59 @@ +# Invariant-mass fitter +Invariant-mass fitter is implemented in the class `HFInvMassFitter` (`HFInvMassFitter.cxx/h` files), and its run is executed via `runMassFitter.C` macro. +Fitter is configured in `config_massfitter.json`.\ +The fitter is **not** a part of O2Physics source code. + +## Dependencies +1. ROOT +2. RapidJSON. Download the header-only (no compilation needed) RapidJSON library, see the link . + +If you have O2Physics compilation you do not need to fulfill these dependencies explicitly. + +## How to run +### As a ROOT macro +The `runMassFitter.C` can be compiled 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\")" +``` +If you have O2Physics compilation and enter into its environment there is no need to set environment variables (skip lines 2-3 above). + +### As a CMake project +It is also possible to compile the fitter as a CMake project or insert it into existing one if any. +Use the `CMakeLists_HFInvMassFitter.txt` (rename it into `CMakeLists.txt` before usage).\ +Compile the fitter with the following steps: +```bash +cd path-to-o2physics-src/PWGHF/D2H/Macros +mkdir build +cd build +source path-to-root-install/bin/thisroot.sh +cmake -DHFFITTER_RAPIDJSON_INCLUDE_DIRS=path-to-json-include ../ +make +``` +and run the fitter: +```bash +./runMassFitter ../config_massfitter.json +``` +### Directly from the terminal +Compile the fitter with the following steps: +```bash +cd path-to-o2physics-src/PWGHF/D2H/Macros +mkdir build +cd build +source path-to-root-install/bin/thisroot.sh + +# Generate ROOT dictionary: +rootcling -f G__HFInvMassFitter.cxx -c ../HFInvMassFitter.h ../HFInvMassFitterLinkDef.h + +# Compile source code: +g++ -fPIC -I$(root-config --incdir) -I path-to-json-include -c ../HFInvMassFitter.cxx ../runMassFitter.C G__HFInvMassFitter.cxx + +# Link the executable: +g++ -o runMassFitter HFInvMassFitter.o runMassFitter.o G__HFInvMassFitter.o $(root-config --libs) -lRooFit -lRooFitCore -lEG +``` +and run the fitter: +```bash +./runMassFitter ../config_massfitter.json +``` diff --git a/PWGHF/D2H/Macros/compute_fraction_cutvar.py b/PWGHF/D2H/Macros/compute_fraction_cutvar.py index 04b3e9f6fe2..35f751419fd 100644 --- a/PWGHF/D2H/Macros/compute_fraction_cutvar.py +++ b/PWGHF/D2H/Macros/compute_fraction_cutvar.py @@ -16,7 +16,7 @@ import ROOT # pylint: disable=import-error sys.path.insert(0, '..') from cut_variation import CutVarMinimiser -from utils.style_formatter import set_object_style +from style_formatter import set_object_style # pylint: disable=no-member,too-many-locals,too-many-statements @@ -27,6 +27,7 @@ def main(config): """ ROOT.gROOT.SetBatch(True) + ROOT.TH1.AddDirectory(False) with open(config, encoding="utf8") as fil: cfg = json.load(fil) @@ -34,22 +35,43 @@ def main(config): hist_rawy, hist_effp, hist_effnp = ([] for _ in range(3)) for filename_rawy, filename_eff in zip(cfg["rawyields"]["inputfiles"], cfg["efficiencies"]["inputfiles"]): infile_rawy = ROOT.TFile.Open(os.path.join(cfg["rawyields"]["inputdir"], filename_rawy)) - hist_rawy.append(infile_rawy.Get(cfg["rawyields"]["histoname"])) + 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.") hist_rawy[-1].SetDirectory(0) infile_rawy.Close() infile_eff = ROOT.TFile.Open(os.path.join(cfg["efficiencies"]["inputdir"], filename_eff)) - hist_effp.append(infile_eff.Get(cfg["efficiencies"]["histonames"]["prompt"])) - hist_effnp.append(infile_eff.Get(cfg["efficiencies"]["histonames"]["nonprompt"])) + hist_effp_name = cfg["efficiencies"]["histonames"]["prompt"] + 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.") 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.") + 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.") + 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 = infile_central_eff.Get(cfg["central_efficiency"]["histonames"]["prompt"]) - hist_central_effnp = infile_central_eff.Get(cfg["central_efficiency"]["histonames"]["nonprompt"]) + 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.") + 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.") hist_central_effp.SetDirectory(0) hist_central_effnp.SetDirectory(0) infile_central_eff.Close() @@ -61,12 +83,18 @@ def main(config): hist_corry_prompt = hist_rawy[0].Clone("hCorrYieldsPrompt") hist_corry_nonprompt = hist_rawy[0].Clone("hCorrYieldsNonPrompt") - hist_covariance = hist_rawy[0].Clone("hCovPromptNonPrompt") + hist_covariance_pnp = hist_rawy[0].Clone("hCovPromptNonPrompt") + hist_covariance_pp = hist_rawy[0].Clone("hCovPromptPrompt") + hist_covariance_npnp = hist_rawy[0].Clone("hCovNonPromptNonPrompt") hist_corrfrac_prompt = hist_rawy[0].Clone("hCorrFracPrompt") hist_corrfrac_nonprompt = hist_rawy[0].Clone("hCorrFracNonPrompt") + for histo in hist_corry_prompt, hist_corry_nonprompt, hist_covariance_pnp, hist_covariance_pp, hist_covariance_npnp, hist_corrfrac_prompt, hist_corrfrac_nonprompt: + histo.Reset() hist_corry_prompt.GetYaxis().SetTitle("corrected yields prompt") hist_corry_nonprompt.GetYaxis().SetTitle("corrected yields non-prompt") - hist_covariance.GetYaxis().SetTitle("#sigma(prompt, non-prompt)") + hist_covariance_pnp.GetYaxis().SetTitle("#sigma(prompt, non-prompt)") + hist_covariance_pp.GetYaxis().SetTitle("#sigma(prompt, prompt)") + hist_covariance_npnp.GetYaxis().SetTitle("#sigma(non-prompt, non-prompt)") hist_corrfrac_prompt.GetYaxis().SetTitle("corrected fraction prompt") hist_corrfrac_nonprompt.GetYaxis().SetTitle("corrected fraction non-prompt") set_object_style( @@ -81,7 +109,9 @@ def main(config): fillstyle=0, markerstyle=ROOT.kFullSquare, ) - set_object_style(hist_covariance) + set_object_style(hist_covariance_pnp) + set_object_style(hist_covariance_pp) + set_object_style(hist_covariance_npnp) set_object_style( hist_corrfrac_prompt, color=ROOT.kRed + 1, @@ -97,6 +127,8 @@ def main(config): if cfg["central_efficiency"]["computerawfrac"]: hist_frac_raw_prompt = hist_rawy[0].Clone("hRawFracPrompt") hist_frac_raw_nonprompt = hist_rawy[0].Clone("hRawFracNonPrompt") + for histo in hist_frac_raw_prompt, hist_frac_raw_nonprompt: + histo.Reset() hist_frac_raw_prompt.GetYaxis().SetTitle("raw fraction prompt") hist_frac_raw_nonprompt.GetYaxis().SetTitle("raw fraction non-prompt") set_object_style( @@ -113,72 +145,108 @@ def main(config): markerstyle=ROOT.kFullSquare, ) - output = ROOT.TFile(os.path.join(cfg["output"]["directory"], cfg["output"]["file"]), "recreate") + pt_bin_to_process_name_suffix = "" + if pt_bin_to_process != -1: + pt_bin_to_process_name_suffix = "_bin_" + str(pt_bin_to_process) + + output_name_template = cfg['output']['file'].replace(".root", "") + pt_bin_to_process_name_suffix + ".root" + output = ROOT.TFile(os.path.join(cfg["output"]["directory"], output_name_template), "recreate") n_sets = len(hist_rawy) + pt_axis_title = hist_rawy[0].GetXaxis().GetTitle() for ipt in range(hist_rawy[0].GetNbinsX()): + if pt_bin_to_process !=-1 and ipt+1 != pt_bin_to_process: + continue pt_min = hist_rawy[0].GetXaxis().GetBinLowEdge(ipt + 1) pt_max = hist_rawy[0].GetXaxis().GetBinUpEdge(ipt + 1) + print(f"\n\nINFO: processing pt range {ipt+1} from {pt_min} to {pt_max} {pt_axis_title}") rawy, effp, effnp, unc_rawy, unc_effp, unc_effnp = (np.zeros(n_sets) for _ in range(6)) for iset, (hrawy, heffp, heffnp) in enumerate(zip(hist_rawy, hist_effp, hist_effnp)): - rawy.itemset(iset, hrawy.GetBinContent(ipt + 1)) - effp.itemset(iset, heffp.GetBinContent(ipt + 1)) - effnp.itemset(iset, heffnp.GetBinContent(ipt + 1)) - unc_rawy.itemset(iset, hrawy.GetBinError(ipt + 1)) - unc_effp.itemset(iset, heffp.GetBinError(ipt + 1)) - unc_effnp.itemset(iset, heffnp.GetBinError(ipt + 1)) + rawy[iset] = hrawy.GetBinContent(ipt + 1) + effp[iset] = heffp.GetBinContent(ipt + 1) + effnp[iset] = heffnp.GetBinContent(ipt + 1) + unc_rawy[iset] = hrawy.GetBinError(ipt + 1) + unc_effp[iset] = heffp.GetBinError(ipt + 1) + unc_effnp[iset] = heffnp.GetBinError(ipt + 1) + + 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(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(f"raw yield uncertainties vector elements = {unc_rawy}\n") minimiser = CutVarMinimiser(rawy, effp, effnp, unc_rawy, unc_effp, unc_effnp) - minimiser.minimise_system(cfg["minimisation"]["correlated"]) - - hist_corry_prompt.SetBinContent(ipt + 1, minimiser.get_prompt_yield_and_error()[0]) - hist_corry_prompt.SetBinError(ipt + 1, minimiser.get_prompt_yield_and_error()[1]) - hist_corry_nonprompt.SetBinContent(ipt + 1, minimiser.get_nonprompt_yield_and_error()[0]) - hist_corry_nonprompt.SetBinError(ipt + 1, minimiser.get_nonprompt_yield_and_error()[1]) - hist_covariance.SetBinContent(ipt + 1, minimiser.get_prompt_nonprompt_cov()) - hist_covariance.SetBinError(ipt + 1, 0) - corr_frac_prompt = minimiser.get_corr_prompt_fraction() - corr_frac_nonprompt = minimiser.get_corr_nonprompt_fraction() - hist_corrfrac_prompt.SetBinContent(ipt + 1, corr_frac_prompt[0]) - hist_corrfrac_prompt.SetBinError(ipt + 1, corr_frac_prompt[1]) - hist_corrfrac_nonprompt.SetBinContent(ipt + 1, corr_frac_nonprompt[0]) - hist_corrfrac_nonprompt.SetBinError(ipt + 1, corr_frac_nonprompt[1]) - if cfg["central_efficiency"]["computerawfrac"]: - raw_frac_prompt = minimiser.get_raw_prompt_fraction( - hist_central_effp.GetBinContent(ipt + 1), hist_central_effnp.GetBinContent(ipt + 1) - ) - raw_frac_nonprompt = minimiser.get_raw_nonprompt_fraction( - hist_central_effp.GetBinContent(ipt + 1), hist_central_effnp.GetBinContent(ipt + 1) - ) - hist_frac_raw_prompt.SetBinContent(ipt + 1, raw_frac_prompt[0]) - hist_frac_raw_prompt.SetBinError(ipt + 1, raw_frac_prompt[1]) - hist_frac_raw_nonprompt.SetBinContent(ipt + 1, raw_frac_nonprompt[0]) - hist_frac_raw_nonprompt.SetBinError(ipt + 1, raw_frac_nonprompt[1]) - - canv_rawy, histos_rawy, leg_r = minimiser.plot_result(f"_pt{pt_min:.0f}_{pt_max:.0f}") - output.cd() - canv_rawy.Write() - for _, hist in histos_rawy.items(): - hist.Write() - - canv_eff, histos_eff, leg_e = minimiser.plot_efficiencies(f"_pt{pt_min:.0f}_{pt_max:.0f}") - output.cd() - canv_eff.Write() - for _, hist in histos_eff.items(): - hist.Write() - - canv_frac, histos_frac, leg_f = minimiser.plot_fractions(f"_pt{pt_min:.0f}_{pt_max:.0f}") - output.cd() - canv_frac.Write() - for _, hist in histos_frac.items(): - hist.Write() - - canv_cov, histo_cov = minimiser.plot_cov_matrix(True, f"_pt{pt_min:.0f}_{pt_max:.0f}") - output.cd() - canv_cov.Write() - histo_cov.Write() - - canv_combined = ROOT.TCanvas("canv_combined", "", 1000, 1000) + status = minimiser.minimise_system(cfg["minimisation"]["correlated"]) + + if status: + hist_corry_prompt.SetBinContent(ipt + 1, minimiser.get_prompt_yield_and_error()[0]) + hist_corry_prompt.SetBinError(ipt + 1, minimiser.get_prompt_yield_and_error()[1]) + hist_corry_nonprompt.SetBinContent(ipt + 1, minimiser.get_nonprompt_yield_and_error()[0]) + hist_corry_nonprompt.SetBinError(ipt + 1, minimiser.get_nonprompt_yield_and_error()[1]) + hist_covariance_pnp.SetBinContent(ipt + 1, minimiser.get_prompt_nonprompt_cov()) + hist_covariance_pnp.SetBinError(ipt + 1, 0) + hist_covariance_pp.SetBinContent(ipt + 1, minimiser.get_prompt_prompt_cov()) + hist_covariance_pp.SetBinError(ipt + 1, 0) + hist_covariance_npnp.SetBinContent(ipt + 1, minimiser.get_nonprompt_nonprompt_cov()) + hist_covariance_npnp.SetBinError(ipt + 1, 0) + corr_frac_prompt = minimiser.get_corr_prompt_fraction() + corr_frac_nonprompt = minimiser.get_corr_nonprompt_fraction() + hist_corrfrac_prompt.SetBinContent(ipt + 1, corr_frac_prompt[0]) + hist_corrfrac_prompt.SetBinError(ipt + 1, corr_frac_prompt[1]) + hist_corrfrac_nonprompt.SetBinContent(ipt + 1, corr_frac_nonprompt[0]) + hist_corrfrac_nonprompt.SetBinError(ipt + 1, corr_frac_nonprompt[1]) + if cfg["central_efficiency"]["computerawfrac"]: + raw_frac_prompt = minimiser.get_raw_prompt_fraction( + hist_central_effp.GetBinContent(ipt + 1), hist_central_effnp.GetBinContent(ipt + 1) + ) + raw_frac_nonprompt = minimiser.get_raw_nonprompt_fraction( + hist_central_effp.GetBinContent(ipt + 1), hist_central_effnp.GetBinContent(ipt + 1) + ) + hist_frac_raw_prompt.SetBinContent(ipt + 1, raw_frac_prompt[0]) + hist_frac_raw_prompt.SetBinError(ipt + 1, raw_frac_prompt[1]) + hist_frac_raw_nonprompt.SetBinContent(ipt + 1, raw_frac_nonprompt[0]) + hist_frac_raw_nonprompt.SetBinError(ipt + 1, raw_frac_nonprompt[1]) + + 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) + output.cd() + canv_rawy.Write() + for _, hist in histos_rawy.items(): + hist.Write() + + canv_unc, histos_unc, leg_unc = minimiser.plot_uncertainties(f"_pt{pt_min}_{pt_max}", hist_bin_title) + output.cd() + canv_unc.Write() + for _, hist in histos_unc.items(): + hist.Write() + + canv_eff, histos_eff, leg_e = minimiser.plot_efficiencies(f"_pt{pt_min}_{pt_max}", hist_bin_title) + output.cd() + canv_eff.Write() + for _, hist in histos_eff.items(): + hist.Write() + + canv_frac, histos_frac, leg_f = minimiser.plot_fractions(f"_pt{pt_min}_{pt_max}", hist_bin_title) + output.cd() + canv_frac.Write() + for _, hist in histos_frac.items(): + hist.Write() + + canv_cov, histo_cov = minimiser.plot_cov_matrix(True, f"_pt{pt_min}_{pt_max}", hist_bin_title) + output.cd() + canv_cov.Write() + histo_cov.Write() + else: + print(f"Minimization for pT {pt_min}, {pt_max} not successful") + canv_rawy = ROOT.TCanvas("c_rawy_minimization_error", "Minimization error", 500, 500) + canv_eff = ROOT.TCanvas("c_eff_minimization_error", "Minimization error", 500, 500) + canv_frac = ROOT.TCanvas("c_frac_minimization_error", "Minimization error", 500, 500) + canv_cov = ROOT.TCanvas("c_conv_minimization_error", "Minimization error", 500, 500) + + canv_combined = ROOT.TCanvas(f"canv_combined_{ipt}", "", 1000, 1000) canv_combined.Divide(2, 2) canv_combined.cd(1) canv_rawy.DrawClonePad() @@ -189,33 +257,36 @@ def main(config): canv_combined.cd(4) canv_cov.DrawClonePad() - output_name_rawy_pdf = f"Distr_{cfg['output']['file'].replace('.root', '.pdf')}" - output_name_eff_pdf = f"Eff_{cfg['output']['file'].replace('.root', '.pdf')}" - output_name_frac_pdf = f"Frac_{cfg['output']['file'].replace('.root', '.pdf')}" - output_name_covmat_pdf = f"CovMatrix_{cfg['output']['file'].replace('.root', '.pdf')}" - output_name_pdf = f"{cfg['output']['file'].replace('.root', '.pdf')}" - if ipt == 0: - canv_rawy.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}[") - canv_eff.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}[") - canv_frac.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}[") - canv_cov.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}[") - canv_combined.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}[") - canv_rawy.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}") - canv_eff.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}") - canv_frac.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}") - canv_cov.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}") - canv_combined.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}") - if ipt == hist_rawy[0].GetNbinsX() - 1: - canv_rawy.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}]") - canv_eff.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}]") - canv_frac.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}]") - canv_cov.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}]") - canv_combined.SaveAs(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}]") + output_name_template = output_name_template.replace('.root', '.pdf') + + output_name_rawy_pdf = f"Distr_{output_name_template}" + output_name_eff_pdf = f"Eff_{output_name_template}" + output_name_frac_pdf = f"Frac_{output_name_template}" + output_name_covmat_pdf = f"CovMatrix_{output_name_template}" + output_name_unc_pdf = f"Unc_{output_name_template}" + output_name_pdf = f"{output_name_template}" + + if hist_rawy[0].GetNbinsX() == 1 or pt_bin_to_process != -1: + print_bracket = "" + elif ipt == 0: + print_bracket = "(" + elif ipt == hist_rawy[0].GetNbinsX() - 1: + print_bracket = ")" + else: + print_bracket = "" + canv_rawy.Print(f"{os.path.join(cfg['output']['directory'], output_name_rawy_pdf)}{print_bracket}") + canv_eff.Print(f"{os.path.join(cfg['output']['directory'], output_name_eff_pdf)}{print_bracket}") + canv_frac.Print(f"{os.path.join(cfg['output']['directory'], output_name_frac_pdf)}{print_bracket}") + canv_cov.Print(f"{os.path.join(cfg['output']['directory'], output_name_covmat_pdf)}{print_bracket}") + canv_combined.Print(f"{os.path.join(cfg['output']['directory'], output_name_pdf)}{print_bracket}") + canv_unc.Print(f"{os.path.join(cfg['output']['directory'], output_name_unc_pdf)}{print_bracket}") output.cd() hist_corry_prompt.Write() hist_corry_nonprompt.Write() - hist_covariance.Write() + hist_covariance_pnp.Write() + hist_covariance_pp.Write() + hist_covariance_npnp.Write() hist_corrfrac_prompt.Write() hist_corrfrac_nonprompt.Write() if cfg["central_efficiency"]["computerawfrac"]: diff --git a/PWGHF/D2H/Macros/config_cutvar_example.json b/PWGHF/D2H/Macros/config_cutvar_example.json index 6ac80c747ad..20466b37044 100644 --- a/PWGHF/D2H/Macros/config_cutvar_example.json +++ b/PWGHF/D2H/Macros/config_cutvar_example.json @@ -70,4 +70,4 @@ "directory": ".", "file": "CutVarDplus_pp13TeV_MB.root" } -} \ No newline at end of file +} diff --git a/PWGHF/D2H/Macros/config_massfitter.json b/PWGHF/D2H/Macros/config_massfitter.json index 3199b780f68..43e67b76f5d 100644 --- a/PWGHF/D2H/Macros/config_massfitter.json +++ b/PWGHF/D2H/Macros/config_massfitter.json @@ -32,7 +32,8 @@ "Ds", "LcToPKPi", "LcToPK0s", - "Dstar" + "Dstar", + "XicToXiPiPi" ], "EnableRefl": false, "FixSigma": false, @@ -49,6 +50,25 @@ "FixMean": false, "MeanFile": "", "_MeanFile": "fix mean from file", + "FixMeanManual": [ + 0, + 0, + 0, + 0, + 0 + ], + "_FixMeanManual": "fix mean mannually", + "FixSecondSigma": false, + "SecondSigmaFile": "", + "_SecondSigmaFile": "fix second sigma for double gauss from file", + "FixSecondSigmaManual": [ + 0, + 0, + 0, + 0, + 0 + ], + "_FixSecondSigmaManual": "fix second sigma for double gauss manually", "SliceVarName": "T", "SliceVarUnit": "ps", "_SliceVarName, _SliceVarUnit": "e.g. pT, GeV/c or something else depending on user's needs", diff --git a/PWGHF/D2H/Macros/cut_variation.py b/PWGHF/D2H/Macros/cut_variation.py index ba827a6309c..3d862589836 100644 --- a/PWGHF/D2H/Macros/cut_variation.py +++ b/PWGHF/D2H/Macros/cut_variation.py @@ -12,7 +12,7 @@ import numpy as np # pylint: disable=import-error import ROOT # pylint: disable=import-error sys.path.insert(0, '..') -from utils.style_formatter import set_global_style, set_object_style +from style_formatter import set_global_style, set_object_style # pylint: disable=too-many-instance-attributes @@ -110,9 +110,9 @@ def __initialise_objects(self): self.unc_frac_nonprompt = np.zeros(shape=self.n_sets) for i_set, (rawy, effp, effnp) in enumerate(zip(self.raw_yields, self.eff_prompt, self.eff_nonprompt)): - self.m_rawy.itemset(i_set, rawy) - self.m_eff.itemset((i_set, 0), effp) - self.m_eff.itemset((i_set, 1), effnp) + self.m_rawy[i_set] = rawy + self.m_eff[(i_set, 0)] = effp + self.m_eff[(i_set, 1)] = effnp # pylint: disable=too-many-locals def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100): @@ -136,7 +136,7 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) self.m_eff = np.matrix(self.m_eff) m_corr_yields_old = np.zeros(shape=(2, 1)) - for _ in range(max_iterations): + for iteration in range(max_iterations): for i_row, (rw_unc_row, effp_unc_row, effnp_unc_row) in enumerate( zip(self.unc_raw_yields, self.unc_eff_prompt, self.unc_eff_nonprompt) ): @@ -165,15 +165,21 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) else: rho = 0.0 cov_row_col = rho * unc_row * unc_col - self.m_cov_sets.itemset((i_row, i_col), cov_row_col) + self.m_cov_sets[i_row, i_col] = cov_row_col self.m_cov_sets = np.matrix(self.m_cov_sets) - self.m_weights = np.linalg.inv(np.linalg.cholesky(self.m_cov_sets)) + try: + self.m_weights = np.linalg.inv(np.linalg.cholesky(self.m_cov_sets)) + except np.linalg.LinAlgError: + return False self.m_weights = self.m_weights.T * self.m_weights m_eff_tr = self.m_eff.T self.m_covariance = (m_eff_tr * self.m_weights) * self.m_eff - self.m_covariance = np.linalg.inv(np.linalg.cholesky(self.m_covariance)) + try: + self.m_covariance = np.linalg.inv(np.linalg.cholesky(self.m_covariance)) + except np.linalg.LinAlgError: + return False self.m_covariance = self.m_covariance.T * self.m_covariance self.m_corr_yields = self.m_covariance * (m_eff_tr * self.m_weights) * self.m_rawy @@ -189,6 +195,13 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) m_corr_yields_old = np.copy(self.m_corr_yields) + print(f"INFO: number of processed iterations = {iteration+1}\n") + 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(f"residual vector uncertainties elements = {np.sqrt(m_cov_sets_diag)}\n") + # chi2 self.chi_2 = float(np.transpose(self.m_res) * self.m_weights * self.m_res) @@ -211,10 +224,12 @@ def minimise_system(self, correlated=True, precision=1.0e-8, max_iterations=100) + der_fnp_np**2 * self.m_covariance.item(1, 1) + 2 * der_fnp_p * der_fnp_np * self.m_covariance.item(1, 0) ) - self.frac_prompt.itemset(i_set, rawyp / (rawyp + rawynp)) - self.frac_nonprompt.itemset(i_set, rawynp / (rawyp + rawynp)) - self.unc_frac_prompt.itemset(i_set, unc_fp) - self.unc_frac_nonprompt.itemset(i_set, unc_fnp) + self.frac_prompt[i_set] = rawyp / (rawyp + rawynp) + self.frac_nonprompt[i_set] = rawynp / (rawyp + rawynp) + self.unc_frac_prompt[i_set] = unc_fp + self.unc_frac_nonprompt[i_set] = unc_fnp + + return True def get_red_chi2(self): """ @@ -264,6 +279,30 @@ def get_prompt_nonprompt_cov(self): return self.m_covariance.item(1, 0) + def get_prompt_prompt_cov(self): + """ + Helper function to get covariance between prompt and prompt corrected yields + + Returns + ----------------------------------------------------- + - cov_p_np: float + covariance between prompt and prompt corrected yields + """ + + return self.m_covariance.item(0, 0) + + def get_nonprompt_nonprompt_cov(self): + """ + Helper function to get covariance between non-prompt and non-prompt corrected yields + + Returns + ----------------------------------------------------- + - cov_p_np: float + covariance between non-prompt and non-prompt corrected yields + """ + + return self.m_covariance.item(1, 1) + def get_raw_prompt_fraction(self, effacc_p, effacc_np): """ Helper function to get the raw prompt fraction given the efficiencies @@ -424,7 +463,7 @@ def get_corr_nonprompt_fraction(self): return self.get_raw_nonprompt_fraction(1.0, 1.0) # pylint: disable=no-member - def plot_result(self, suffix=""): + def plot_result(self, suffix="", title=""): """ Helper function to plot minimisation result as a function of cut set @@ -432,6 +471,8 @@ def plot_result(self, suffix=""): ----------------------------------------------------- - suffix: str suffix to be added in the name of the output objects + - title: str + title to be written at the top margin of the output objects Returns ----------------------------------------------------- @@ -528,6 +569,9 @@ def plot_result(self, suffix=""): hist_raw_yield_prompt.Draw("histsame") hist_raw_yield_nonprompt.Draw("histsame") hist_raw_yield_sum.Draw("histsame") + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() @@ -540,7 +584,7 @@ def plot_result(self, suffix=""): return canvas, histos, leg - def plot_cov_matrix(self, correlated=True, suffix=""): + def plot_cov_matrix(self, correlated=True, suffix="", title=""): """ Helper function to plot covariance matrix @@ -550,6 +594,8 @@ def plot_cov_matrix(self, correlated=True, suffix=""): correlation between cut sets - suffix: str suffix to be added in the name of the output objects + - title: str + title to be written at the top margin of the output objects Returns ----------------------------------------------------- @@ -563,6 +609,7 @@ def plot_cov_matrix(self, correlated=True, suffix=""): padleftmargin=0.14, padbottommargin=0.12, padrightmargin=0.12, + padtopmargin = 0.075, palette=ROOT.kRainBow, ) @@ -592,12 +639,15 @@ def plot_cov_matrix(self, correlated=True, suffix=""): canvas = ROOT.TCanvas(f"cCorrMatrixCutSets{suffix}", "", 500, 500) hist_corr_matrix.Draw("colz") + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() return canvas, hist_corr_matrix - def plot_efficiencies(self, suffix=""): + def plot_efficiencies(self, suffix="", title=""): """ Helper function to plot efficiencies as a function of cut set @@ -605,6 +655,8 @@ def plot_efficiencies(self, suffix=""): ----------------------------------------------------- - suffix: str suffix to be added in the name of the output objects + - title: str + title to be written at the top margin of the output objects Returns ----------------------------------------------------- @@ -616,7 +668,7 @@ def plot_efficiencies(self, suffix=""): needed otherwise it is destroyed """ - set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2) + set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2, padtopmargin = 0.075) hist_eff_prompt = ROOT.TH1F( f"hEffPromptVsCut{suffix}", @@ -678,12 +730,15 @@ def plot_efficiencies(self, suffix=""): leg.AddEntry(hist_eff_prompt, "prompt", "pl") leg.AddEntry(hist_eff_nonprompt, "non-prompt", "pl") leg.Draw() + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() return canvas, histos, leg - def plot_fractions(self, suffix=""): + def plot_fractions(self, suffix="", title=""): """ Helper function to plot fractions as a function of cut set @@ -691,6 +746,8 @@ def plot_fractions(self, suffix=""): ----------------------------------------------------- - suffix: str suffix to be added in the name of the output objects + - title: str + title to be written at the top margin of the output objects Returns ----------------------------------------------------- @@ -702,7 +759,7 @@ def plot_fractions(self, suffix=""): needed otherwise it is destroyed """ - set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2) + set_global_style(padleftmargin=0.14, padbottommargin=0.12, titleoffset=1.2, padtopmargin = 0.075) hist_f_prompt = ROOT.TH1F( f"hFracPromptVsCut{suffix}", @@ -757,7 +814,91 @@ def plot_fractions(self, suffix=""): leg.AddEntry(hist_f_prompt, "prompt", "pl") leg.AddEntry(hist_f_nonprompt, "non-prompt", "pl") leg.Draw() + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) canvas.Modified() canvas.Update() return canvas, histos, leg + + # pylint: disable=no-member + def plot_uncertainties(self, suffix="", title=""): + """ + Helper function to plot uncertainties as a function of cut set + + Parameters + ----------------------------------------------------- + - suffix: str + suffix to be added in the name of the output objects + - title: str + title to be written at the top margin of the output objects + + Returns + ----------------------------------------------------- + - canvas: ROOT.TCanvas + canvas with plot + - histos: dict + dictionary of ROOT.TH1F with uncertainties distributions for + raw yield and residual vector + - leg: ROOT.TLegend + needed otherwise it is destroyed + """ + + set_global_style(padleftmargin=0.16, padbottommargin=0.12, padtopmargin=0.075, titleoffsety=1.6) + + hist_raw_yield_unc = ROOT.TH1F( + f"hRawYieldUncVsCut{suffix}", + ";cut set;runc.", + self.n_sets, + -0.5, + self.n_sets - 0.5, + ) + + hist_residual_unc = ROOT.TH1F( + f"hResidualUncVsCut{suffix}", + ";cut set;unc.", + self.n_sets, + -0.5, + self.n_sets - 0.5, + ) + + m_cov_sets_diag = np.diag(self.m_cov_sets) + m_cov_sets_diag = np.sqrt(m_cov_sets_diag) + + for i_bin, (unc_rawy, unc_res) in enumerate(zip(self.unc_raw_yields, m_cov_sets_diag)): + hist_raw_yield_unc.SetBinContent(i_bin + 1, unc_rawy) + hist_residual_unc.SetBinContent(i_bin+1, unc_res) + + set_object_style(hist_raw_yield_unc, color=ROOT.kRed + 1, fillstyle=0) + set_object_style(hist_residual_unc, color=ROOT.kAzure + 4, fillstyle=0) + + canvas = ROOT.TCanvas(f"cUncVsCut{suffix}", "", 500, 500) + canvas.DrawFrame( + -0.5, + 0.0, + self.n_sets - 0.5, + hist_residual_unc.GetMaximum() * 1.2, + ";cut set;unc.", + ) + leg = ROOT.TLegend(0.6, 0.75, 0.8, 0.85) + leg.SetBorderSize(0) + leg.SetFillStyle(0) + leg.SetTextSize(0.04) + leg.AddEntry(hist_raw_yield_unc, "raw yield", "l") + leg.AddEntry(hist_residual_unc, "residual vector", "l") + leg.Draw() + hist_raw_yield_unc.Draw("histsame") + hist_residual_unc.Draw("histsame") + tex = ROOT.TLatex() + tex.SetTextSize(0.04) + tex.DrawLatexNDC(0.05, 0.95, title) + canvas.Modified() + canvas.Update() + + histos = { + "rawy": hist_raw_yield_unc, + "residual": hist_residual_unc, + } + + return canvas, histos, leg diff --git a/PWGHF/D2H/Macros/runMassFitter.C b/PWGHF/D2H/Macros/runMassFitter.C index 637171248cc..e6cb569f4b0 100644 --- a/PWGHF/D2H/Macros/runMassFitter.C +++ b/PWGHF/D2H/Macros/runMassFitter.C @@ -16,24 +16,28 @@ /// \author Mingyu Zhang /// \author Xinye Peng /// \author Biao Zhang +/// \author Oleksii Lubynets #if !defined(__CINT__) || defined(__CLING__) #include "HFInvMassFitter.h" // if .h file not found, please include your local rapidjson/document.h and rapidjson/filereadstream.h here +#include +#include +#include +#include + #include #include #include // for fclose +#include #include #include // std::string +#include #include // std::vector -#include -#include -#include - #endif using namespace rapidjson; @@ -95,6 +99,8 @@ int runMassFitter(const TString& configFileName) std::vector massMin; std::vector massMax; std::vector fixSigmaManual; + std::vector fixSecondSigmaManual; + std::vector fixMeanManual; std::vector nRebin; std::vector bkgFuncConfig; std::vector sgnFuncConfig; @@ -117,15 +123,24 @@ int runMassFitter(const TString& configFileName) const Value& fdSecPeakHistoNameValue = config["FDSecPeakHistoName"]; parseStringArray(fdSecPeakHistoNameValue, fdSecPeakHistoName); - bool fixSigma = config["FixSigma"].GetBool(); - std::string sigmaFile = config["SigmaFile"].GetString(); + const bool fixSigma = config["FixSigma"].GetBool(); + const std::string sigmaFile = config["SigmaFile"].GetString(); - bool fixMean = config["FixMean"].GetBool(); - std::string meanFile = config["MeanFile"].GetString(); + const bool fixMean = config["FixMean"].GetBool(); + const std::string meanFile = config["MeanFile"].GetString(); const Value& fixSigmaManualValue = config["FixSigmaManual"]; readArray(fixSigmaManualValue, fixSigmaManual); + const bool fixSecondSigma = config["FixSecondSigma"].GetBool(); + const std::string secondSigmaFile = config["SecondSigmaFile"].GetString(); + + const Value& fixSecondSigmaManualValue = config["FixSecondSigmaManual"]; + readArray(fixSecondSigmaManualValue, fixSecondSigmaManual); + + const Value& fixMeanManualValue = config["FixMeanManual"]; + readArray(fixMeanManualValue, fixMeanManual); + sliceVarName = config["SliceVarName"].GetString(); sliceVarUnit = config["SliceVarUnit"].GetString(); @@ -153,10 +168,10 @@ int runMassFitter(const TString& configFileName) const Value& sgnFuncValue = config["SgnFunc"]; readArray(sgnFuncValue, sgnFuncConfig); - bool enableRefl = config["EnableRefl"].GetBool(); + const bool enableRefl = config["EnableRefl"].GetBool(); - bool drawBgPrefit = config["drawBgPrefit"].GetBool(); - bool highlightPeakRegion = config["highlightPeakRegion"].GetBool(); + const bool drawBgPrefit = config["drawBgPrefit"].GetBool(); + const bool highlightPeakRegion = config["highlightPeakRegion"].GetBool(); const unsigned int nSliceVarBins = sliceVarMin.size(); std::vector bkgFunc(nSliceVarBins); @@ -167,40 +182,30 @@ int runMassFitter(const TString& configFileName) sliceVarLimits[iSliceVar] = sliceVarMin[iSliceVar]; sliceVarLimits[iSliceVar + 1] = sliceVarMax[iSliceVar]; - if (bkgFuncConfig[iSliceVar] < HFInvMassFitter::Expo || bkgFuncConfig[iSliceVar] > HFInvMassFitter::NoBkg) { + if (bkgFuncConfig[iSliceVar] < 0 || bkgFuncConfig[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] < HFInvMassFitter::SingleGaus || sgnFuncConfig[iSliceVar] > HFInvMassFitter::DoubleGausSigmaRatioPar) { + if (sgnFuncConfig[iSliceVar] < 0 || sgnFuncConfig[iSliceVar] >= HFInvMassFitter::NTypesOfSgnPdf) { throw std::runtime_error("ERROR: only SingleGaus, DoubleGaus and DoubleGausSigmaRatioPar signal functions supported! Exit"); } sgnFunc[iSliceVar] = sgnFuncConfig[iSliceVar]; } - TString massAxisTitle = ""; - double massPDG; - if (particleName == "Dplus") { - massAxisTitle = "#it{M}(K#pi#pi) (GeV/#it{c}^{2})"; - massPDG = TDatabasePDG::Instance()->GetParticle("D+")->Mass(); - } else if (particleName == "D0") { - massAxisTitle = "#it{M}(K#pi) (GeV/#it{c}^{2})"; - massPDG = TDatabasePDG::Instance()->GetParticle("D0")->Mass(); - } else if (particleName == "Ds") { - massAxisTitle = "#it{M}(KK#pi) (GeV/#it{c}^{2})"; - massPDG = TDatabasePDG::Instance()->GetParticle("D_s+")->Mass(); - } else if (particleName == "LcToPKPi") { - massAxisTitle = "#it{M}(pK#pi) (GeV/#it{c}^{2})"; - massPDG = TDatabasePDG::Instance()->GetParticle("Lambda_c+")->Mass(); - } else if (particleName == "LcToPK0s") { - massAxisTitle = "#it{M}(pK^{0}_{s}) (GeV/#it{c}^{2})"; - massPDG = TDatabasePDG::Instance()->GetParticle("Lambda_c+")->Mass(); - } else if (particleName == "Dstar") { - massAxisTitle = "#it{M}(pi^{+}) (GeV/#it{c}^{2})"; - massPDG = TDatabasePDG::Instance()->GetParticle("D*+")->Mass(); - } else { - throw std::runtime_error("ERROR: only Dplus, D0, Ds, LcToPKPi, LcToPK0s and Dstar particles supported! Exit"); + std::map> particles{ + {"Dplus", {"K#pi#pi", "D+"}}, + {"D0", {"K#pi", "D0"}}, + {"Ds", {"KK#pi", "D_s+"}}, + {"LcToPKPi", {"pK#pi", "Lambda_c+"}}, + {"LcToPK0s", {"pK^{0}_{s}", "Lambda_c+"}}, + {"Dstar", {"D^{0}pi^{+}", "D*+"}}, + {"XicToXiPiPi", {"#Xi#pi#pi", "Xi_c+"}}}; + if (particles.find(particleName.Data()) == particles.end()) { + throw std::runtime_error("ERROR: only Dplus, D0, Ds, LcToPKPi, LcToPK0s, Dstar and XicToXiPiPi particles supported! Exit"); } + const TString massAxisTitle = "#it{M}(" + particles[particleName.Data()].first + ") (GeV/#it{c}^{2})"; + const double massPDG = TDatabasePDG::Instance()->GetParticle(particles[particleName.Data()].second.c_str())->Mass(); // load inv-mass histograms auto inputFile = TFile::Open(inputFileName.Data()); @@ -250,69 +255,31 @@ int runMassFitter(const TString& configFileName) inputFile->Close(); // define output histos - auto hRawYields = new TH1D("hRawYields", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield", - nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsCounted = new TH1D("hRawYieldsCounted", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield via bin count", - nSliceVarBins, sliceVarLimits.data()); + auto hRawYieldsSignal = new TH1D("hRawYieldsSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield", + nSliceVarBins, sliceVarLimits.data()); + auto hRawYieldsSignalCounted = new TH1D("hRawYieldsSignalCounted", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield via bin count", + nSliceVarBins, sliceVarLimits.data()); auto hRawYieldsSigma = new TH1D( "hRawYieldsSigma", ";" + sliceVarName + "(" + sliceVarUnit + ");width (GeV/#it{c}^{2})", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSigmaRatio = new TH1D( - "hRawYieldsSigmaRatio", - ";" + sliceVarName + "(" + sliceVarUnit + ");ratio #sigma_{1}/#sigma_{2}", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSigma2 = new TH1D( - "hRawYieldsSigma2", ";" + sliceVarName + "(" + sliceVarUnit + ");width (GeV/#it{c}^{2})", - nSliceVarBins, sliceVarLimits.data()); auto hRawYieldsMean = new TH1D( "hRawYieldsMean", ";" + sliceVarName + "(" + sliceVarUnit + ");mean (GeV/#it{c}^{2})", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsFracGaus2 = new TH1D( - "hRawYieldsFracGaus2", - ";" + sliceVarName + "(" + sliceVarUnit + ");second-gaussian fraction", nSliceVarBins, sliceVarLimits.data()); auto hRawYieldsSignificance = new TH1D( "hRawYieldsSignificance", ";" + sliceVarName + "(" + sliceVarUnit + ");significance (3#sigma)", nSliceVarBins, sliceVarLimits.data()); auto hRawYieldsSgnOverBkg = new TH1D("hRawYieldsSgnOverBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");S/B (3#sigma)", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSignal = - new TH1D("hRawYieldsSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");Signal (3#sigma)", - nSliceVarBins, sliceVarLimits.data()); auto hRawYieldsBkg = new TH1D("hRawYieldsBkg", ";" + sliceVarName + "(" + sliceVarUnit + ");Background (3#sigma)", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsChiSquare = - new TH1D("hRawYieldsChiSquare", + auto hRawYieldsChiSquareBkg = + new TH1D("hRawYieldsChiSquareBkg", + ";" + sliceVarName + "(" + sliceVarUnit + ");#chi^{2}/#it{ndf}", nSliceVarBins, sliceVarLimits.data()); + auto hRawYieldsChiSquareTotal = + new TH1D("hRawYieldsChiSquareTotal", ";" + sliceVarName + "(" + sliceVarUnit + ");#chi^{2}/#it{ndf}", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSecondPeak = new TH1D( - "hRawYieldsSecondPeak", ";" + sliceVarName + "(" + sliceVarUnit + ");raw yield second peak", - nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsMeanSecondPeak = - new TH1D("hRawYieldsMeanSecondPeak", - ";" + sliceVarName + "(" + sliceVarUnit + ");mean second peak (GeV/#it{c}^{2})", - nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSigmaSecondPeak = - new TH1D("hRawYieldsSigmaSecondPeak", - ";" + sliceVarName + "(" + sliceVarUnit + ");width second peak (GeV/#it{c}^{2})", - nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSignificanceSecondPeak = - new TH1D("hRawYieldsSignificanceSecondPeak", - ";" + sliceVarName + "(" + sliceVarUnit + ");signficance second peak (3#sigma)", - nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSigmaRatioSecondFirstPeak = - new TH1D("hRawYieldsSigmaRatioSecondFirstPeak", - ";" + sliceVarName + "(" + sliceVarUnit + ");width second peak / width first peak", - nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSoverBSecondPeak = new TH1D( - "hRawYieldsSoverBSecondPeak", - ";" + sliceVarName + "(" + sliceVarUnit + ");S/B second peak (3#sigma)", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsSignalSecondPeak = new TH1D( - "hRawYieldsSignalSecondPeak", - ";" + sliceVarName + "(" + sliceVarUnit + ");Signal second peak (3#sigma)", nSliceVarBins, sliceVarLimits.data()); - auto hRawYieldsBkgSecondPeak = - new TH1D("hRawYieldsBkgSecondPeak", - ";" + sliceVarName + "(" + sliceVarUnit + ");Background second peak (3#sigma)", - nSliceVarBins, sliceVarLimits.data()); auto hReflectionOverSignal = new TH1D("hReflectionOverSignal", ";" + sliceVarName + "(" + sliceVarUnit + ");Refl/Signal", nSliceVarBins, sliceVarLimits.data()); @@ -328,56 +295,40 @@ int runMassFitter(const TString& configFileName) hFitConfig->GetXaxis()->SetBinLabel(i + 1, hFitConfigXLabel[i]); } - setHistoStyle(hRawYields); - setHistoStyle(hRawYieldsCounted); + setHistoStyle(hRawYieldsSignal); + setHistoStyle(hRawYieldsSignalCounted); setHistoStyle(hRawYieldsSigma); - setHistoStyle(hRawYieldsSigma2); setHistoStyle(hRawYieldsMean); - setHistoStyle(hRawYieldsFracGaus2); setHistoStyle(hRawYieldsSignificance); setHistoStyle(hRawYieldsSgnOverBkg); - setHistoStyle(hRawYieldsSignal); setHistoStyle(hRawYieldsBkg); - setHistoStyle(hRawYieldsChiSquare); - setHistoStyle(hRawYieldsSecondPeak, kRed + 1); - setHistoStyle(hRawYieldsMeanSecondPeak, kRed + 1); - setHistoStyle(hRawYieldsSigmaSecondPeak, kRed + 1); - setHistoStyle(hRawYieldsSignificanceSecondPeak, kRed + 1); - setHistoStyle(hRawYieldsSigmaRatioSecondFirstPeak, kRed + 1); - setHistoStyle(hRawYieldsSoverBSecondPeak, kRed + 1); - setHistoStyle(hRawYieldsSignalSecondPeak, kRed + 1); - setHistoStyle(hRawYieldsBkgSecondPeak, kRed + 1); + setHistoStyle(hRawYieldsChiSquareBkg); + setHistoStyle(hRawYieldsChiSquareTotal); setHistoStyle(hReflectionOverSignal, kRed + 1); - TH1* hSigmaToFix = nullptr; - if (fixSigma) { - if (fixSigmaManual.empty()) { - auto inputFileSigma = TFile::Open(sigmaFile.data()); - if (!inputFileSigma) { - return -2; - } - hSigmaToFix = inputFileSigma->Get("hRawYieldsSigma"); - hSigmaToFix->SetDirectory(0); - if (static_cast(hSigmaToFix->GetNbinsX()) != nSliceVarBins) { - printf("WARNING: Different number of bins for this analysis and histo for fix sigma!\n"); + auto getHistToFix = [&nSliceVarBins](bool const& isFix, std::vector const& fixManual, std::string const& fixFileName, std::string const& var) -> TH1* { + TH1* histToFix = nullptr; + if (isFix) { + if (fixManual.empty()) { + auto fixInputFile = TFile::Open(fixFileName.data()); + if (!fixInputFile) { + throw std::runtime_error("Cannot open file for fixed " + var); + } + const std::string histName = "hRawYields" + var; + histToFix = fixInputFile->Get(histName.data()); + histToFix->SetDirectory(nullptr); + if (static_cast(histToFix->GetNbinsX()) != nSliceVarBins) { + throw std::runtime_error("Different number of bins for this analysis and histo for fixed " + var); + } + fixInputFile->Close(); } - inputFileSigma->Close(); } - } + return histToFix; + }; - TH1* hMeanToFix = nullptr; - if (fixMean) { - auto inputFileMean = TFile::Open(meanFile.data()); - if (!inputFileMean) { - return -3; - } - hMeanToFix = inputFileMean->Get("hRawYieldsMean"); - hMeanToFix->SetDirectory(0); - if (static_cast(hMeanToFix->GetNbinsX()) != nSliceVarBins) { - printf("WARNING: Different number of bins for this analysis and histo for fix mean\n"); - } - inputFileMean->Close(); - } + TH1* hSigmaToFix = getHistToFix(fixSigma, fixSigmaManual, sigmaFile, "Sigma"); + TH1* hMeanToFix = getHistToFix(fixMean, fixMeanManual, meanFile, "Mean"); + TH1* hSecondSigmaToFix = getHistToFix(fixSecondSigma, fixSecondSigmaManual, secondSigmaFile, "Sigma"); // fit histograms @@ -392,12 +343,12 @@ int runMassFitter(const TString& configFileName) } Int_t nCanvasesMax = 20; // do not put more than 20 bins per canvas to make them visible - const Int_t nCanvases = ceil(static_cast(nSliceVarBins) / nCanvasesMax); + const Int_t nCanvases = std::ceil(static_cast(nSliceVarBins) / nCanvasesMax); std::vector canvasMass(nCanvases); std::vector canvasResiduals(nCanvases); std::vector canvasRefl(nCanvases); for (int iCanvas = 0; iCanvas < nCanvases; iCanvas++) { - int nPads = (nCanvases == 1) ? nSliceVarBins : nCanvasesMax; + 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); @@ -411,7 +362,7 @@ int runMassFitter(const TString& configFileName) } for (unsigned int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { - Int_t iCanvas = floor(static_cast(iSliceVar) / nCanvasesMax); + const Int_t iCanvas = std::floor(static_cast(iSliceVar) / nCanvasesMax); hMassForFit[iSliceVar] = static_cast(hMass[iSliceVar]->Rebin(nRebin[iSliceVar])); TString ptTitle = @@ -451,27 +402,30 @@ int runMassFitter(const TString& configFileName) massFitter->drawFit(gPad); - Double_t rawYield = massFitter->getRawYield(); - Double_t rawYieldErr = massFitter->getRawYieldError(); - Double_t rawYieldCounted = massFitter->getRawYieldCounted(); - Double_t rawYieldCountedErr = massFitter->getRawYieldCountedError(); - - Double_t sigma = massFitter->getSigma(); - Double_t sigmaErr = massFitter->getSigmaUncertainty(); - Double_t mean = massFitter->getMean(); - Double_t meanErr = massFitter->getMeanUncertainty(); - Double_t reducedChiSquare = massFitter->getChiSquareOverNDF(); - - hRawYields->SetBinContent(iSliceVar + 1, rawYield); - hRawYields->SetBinError(iSliceVar + 1, rawYieldErr); - hRawYieldsCounted->SetBinContent(iSliceVar + 1, rawYieldCounted); - hRawYieldsCounted->SetBinError(iSliceVar + 1, rawYieldCountedErr); + 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 sigma = massFitter->getSigma(); + const Double_t sigmaErr = massFitter->getSigmaUncertainty(); + const Double_t mean = massFitter->getMean(); + const Double_t meanErr = massFitter->getMeanUncertainty(); + const Double_t reducedChiSquareBkg = massFitter->getChiSquareOverNDFBkg(); + const Double_t reducedChiSquareTotal = massFitter->getChiSquareOverNDFTotal(); + + hRawYieldsSignal->SetBinContent(iSliceVar + 1, rawYield); + hRawYieldsSignal->SetBinError(iSliceVar + 1, rawYieldErr); + hRawYieldsSignalCounted->SetBinContent(iSliceVar + 1, rawYieldCounted); + hRawYieldsSignalCounted->SetBinError(iSliceVar + 1, rawYieldCountedErr); hRawYieldsSigma->SetBinContent(iSliceVar + 1, sigma); hRawYieldsSigma->SetBinError(iSliceVar + 1, sigmaErr); hRawYieldsMean->SetBinContent(iSliceVar + 1, mean); hRawYieldsMean->SetBinError(iSliceVar + 1, meanErr); - hRawYieldsChiSquare->SetBinContent(iSliceVar + 1, reducedChiSquare); - hRawYieldsChiSquare->SetBinError(iSliceVar + 1, 0.); + hRawYieldsChiSquareBkg->SetBinContent(iSliceVar + 1, reducedChiSquareBkg); + hRawYieldsChiSquareBkg->SetBinError(iSliceVar + 1, 0.); + hRawYieldsChiSquareTotal->SetBinContent(iSliceVar + 1, reducedChiSquareTotal); + hRawYieldsChiSquareTotal->SetBinError(iSliceVar + 1, 0.); } else { HFInvMassFitter* massFitter; massFitter = new HFInvMassFitter(hMassForFit[iSliceVar], massMin[iSliceVar], massMax[iSliceVar], @@ -484,24 +438,26 @@ int runMassFitter(const TString& configFileName) if (useLikelihood) { massFitter->setUseLikelihoodFit(); } - if (fixMean) { - massFitter->setFixGaussianMean(hMeanToFix->GetBinContent(iSliceVar + 1)); - } - if (fixSigma) { - if (fixSigmaManual.empty()) { - massFitter->setFixGaussianSigma(hSigmaToFix->GetBinContent(iSliceVar + 1)); - printf("*****************************\n"); - printf("FIXED SIGMA: %f\n", hSigmaToFix->GetBinContent(iSliceVar + 1)); - printf("*****************************\n"); - } else if (!fixSigmaManual.empty()) { - massFitter->setFixGaussianSigma(fixSigmaManual[iSliceVar]); - printf("*****************************\n"); - printf("FIXED SIGMA: %f\n", fixSigmaManual[iSliceVar]); - printf("*****************************\n"); - } else { - printf("WARNING: impossible to fix sigma! Wrong fix sigma file or value!\n"); + + auto setFixedValue = [&massFitter, &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"); + } } - } + }; + + 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"); if (enableRefl) { reflOverSgn = hMassForSgn[iSliceVar]->Integral(hMassForSgn[iSliceVar]->FindBin(massMin[iSliceVar] * 1.0001), hMassForSgn[iSliceVar]->FindBin(massMax[iSliceVar] * 0.999)); @@ -512,24 +468,25 @@ int runMassFitter(const TString& configFileName) massFitter->doFit(); - double rawYield = massFitter->getRawYield(); - double rawYieldErr = massFitter->getRawYieldError(); - double rawYieldCounted = massFitter->getRawYieldCounted(); - double rawYieldCountedErr = massFitter->getRawYieldCountedError(); - double sigma = massFitter->getSigma(); - double sigmaErr = massFitter->getSigmaUncertainty(); - double mean = massFitter->getMean(); - double meanErr = massFitter->getMeanUncertainty(); - double reducedChiSquare = massFitter->getChiSquareOverNDF(); - double significance = massFitter->getSignificance(); - double significanceErr = massFitter->getSignificanceError(); - double bkg = massFitter->getBkgYield(); - double bkgErr = massFitter->getBkgYieldError(); - - hRawYields->SetBinContent(iSliceVar + 1, rawYield); - hRawYields->SetBinError(iSliceVar + 1, rawYieldErr); - hRawYieldsCounted->SetBinContent(iSliceVar + 1, rawYieldCounted); - hRawYieldsCounted->SetBinError(iSliceVar + 1, rawYieldCountedErr); + const double rawYield = massFitter->getRawYield(); + const double rawYieldErr = massFitter->getRawYieldError(); + const double rawYieldCounted = massFitter->getRawYieldCounted(); + const double rawYieldCountedErr = massFitter->getRawYieldCountedError(); + const double sigma = massFitter->getSigma(); + const double sigmaErr = massFitter->getSigmaUncertainty(); + const double mean = massFitter->getMean(); + const double meanErr = massFitter->getMeanUncertainty(); + const double reducedChiSquareBkg = massFitter->getChiSquareOverNDFBkg(); + const double reducedChiSquareTotal = massFitter->getChiSquareOverNDFTotal(); + const double significance = massFitter->getSignificance(); + const double significanceErr = massFitter->getSignificanceError(); + const double bkg = massFitter->getBkgYield(); + const double bkgErr = massFitter->getBkgYieldError(); + + hRawYieldsSignal->SetBinContent(iSliceVar + 1, rawYield); + hRawYieldsSignal->SetBinError(iSliceVar + 1, rawYieldErr); + hRawYieldsSignalCounted->SetBinContent(iSliceVar + 1, rawYieldCounted); + hRawYieldsSignalCounted->SetBinError(iSliceVar + 1, rawYieldCountedErr); hRawYieldsSigma->SetBinContent(iSliceVar + 1, sigma); hRawYieldsSigma->SetBinError(iSliceVar + 1, sigmaErr); hRawYieldsMean->SetBinContent(iSliceVar + 1, mean); @@ -538,12 +495,12 @@ int runMassFitter(const TString& configFileName) hRawYieldsSignificance->SetBinError(iSliceVar + 1, significanceErr); hRawYieldsSgnOverBkg->SetBinContent(iSliceVar + 1, rawYield / bkg); hRawYieldsSgnOverBkg->SetBinError(iSliceVar + 1, rawYield / bkg * std::sqrt(rawYieldErr / rawYield * rawYieldErr / rawYield + bkgErr / bkg * bkgErr / bkg)); - hRawYieldsSignal->SetBinContent(iSliceVar + 1, rawYield); - hRawYieldsSignal->SetBinError(iSliceVar + 1, rawYieldErr); hRawYieldsBkg->SetBinContent(iSliceVar + 1, bkg); hRawYieldsBkg->SetBinError(iSliceVar + 1, bkgErr); - hRawYieldsChiSquare->SetBinContent(iSliceVar + 1, reducedChiSquare); - hRawYieldsChiSquare->SetBinError(iSliceVar + 1, 1.e-20); + hRawYieldsChiSquareBkg->SetBinContent(iSliceVar + 1, reducedChiSquareBkg); + hRawYieldsChiSquareBkg->SetBinError(iSliceVar + 1, 1.e-20); + hRawYieldsChiSquareTotal->SetBinContent(iSliceVar + 1, reducedChiSquareTotal); + hRawYieldsChiSquareTotal->SetBinError(iSliceVar + 1, 1.e-20); if (enableRefl) { hReflectionOverSignal->SetBinContent(iSliceVar + 1, reflOverSgn); } @@ -605,25 +562,18 @@ int runMassFitter(const TString& configFileName) for (unsigned int iSliceVar = 0; iSliceVar < nSliceVarBins; iSliceVar++) { hMass[iSliceVar]->Write(); } - hRawYields->Write(); - hRawYieldsCounted->Write(); + hRawYieldsSignal->Write(); + hRawYieldsSignalCounted->Write(); hRawYieldsSigma->Write(); hRawYieldsMean->Write(); hRawYieldsSignificance->Write(); hRawYieldsSgnOverBkg->Write(); - hRawYieldsSignal->Write(); hRawYieldsBkg->Write(); - hRawYieldsChiSquare->Write(); - hRawYieldsSigma2->Write(); - hRawYieldsFracGaus2->Write(); - hRawYieldsSecondPeak->Write(); - hRawYieldsMeanSecondPeak->Write(); - hRawYieldsSigmaSecondPeak->Write(); - hRawYieldsSignificanceSecondPeak->Write(); - hRawYieldsSigmaRatioSecondFirstPeak->Write(); - hRawYieldsSoverBSecondPeak->Write(); - hRawYieldsSignalSecondPeak->Write(); - hRawYieldsBkgSecondPeak->Write(); + hRawYieldsChiSquareBkg->Write(); + hRawYieldsChiSquareTotal->Write(); + if (enableRefl) { + hReflectionOverSignal->Write(); + } hFitConfig->Write(); outputFile.Close(); @@ -672,3 +622,16 @@ void divideCanvas(TCanvas* canvas, int nSliceVarBins) } } } + +int main(int argc, char* argv[]) +{ + if (argc == 1) { + throw std::runtime_error("Not enough arguments. Please use\n./runMassFitter configFileName"); + } + + const std::string configFileName = argv[1]; + + runMassFitter(configFileName); + + return 0; +} diff --git a/PWGHF/D2H/TableProducer/CMakeLists.txt b/PWGHF/D2H/TableProducer/CMakeLists.txt index 928359768a9..a60ab1d78ab 100644 --- a/PWGHF/D2H/TableProducer/CMakeLists.txt +++ b/PWGHF/D2H/TableProducer/CMakeLists.txt @@ -11,6 +11,11 @@ # Candidate creators +o2physics_add_dpl_workflow(candidate-creator-b-to-jpsi-reduced + SOURCES candidateCreatorBToJpsiReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-creator-b0-reduced SOURCES candidateCreatorB0Reduced.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter @@ -70,6 +75,11 @@ o2physics_add_dpl_workflow(data-creator-charm-reso-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(data-creator-jpsi-had-reduced + SOURCES dataCreatorJpsiHadReduced.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 89562743ef4..a5815359f4b 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorB0Reduced.cxx @@ -15,21 +15,33 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Fabrizio Grosa , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.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; @@ -203,7 +215,7 @@ struct HfCandidateCreatorB0Reduced { rowCandidateDmesMlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); } } // pi loop - } // D loop + } // D loop } void processData(HfRedCollisionsWithExtras const& collisions, @@ -295,7 +307,7 @@ struct HfCandidateCreatorB0ReducedExpressions { if ((rowDPiMcRec.prong0Id() != candB0.prong0Id()) || (rowDPiMcRec.prong1Id() != candB0.prong1Id())) { continue; } - rowB0McRec(rowDPiMcRec.flagMcMatchRec(), rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); + rowB0McRec(rowDPiMcRec.flagMcMatchRec(), -1 /*channel*/, rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); filledMcInfo = true; if constexpr (checkDecayTypeMc) { rowB0McCheck(rowDPiMcRec.pdgCodeBeautyMother(), @@ -308,7 +320,7 @@ struct HfCandidateCreatorB0ReducedExpressions { break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the D-Pi creator - rowB0McRec(0, -1, -1, -1.f); + rowB0McRec(0, -1, -1, -1, -1.f); if constexpr (checkDecayTypeMc) { rowB0McCheck(-1, -1, -1, -1, -1, -1); } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.cxx new file mode 100644 index 00000000000..d96365a6b47 --- /dev/null +++ b/PWGHF/D2H/TableProducer/candidateCreatorBToJpsiReduced.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. + +/// \file candidateCreatorBToJpsiReduced.cxx +/// \brief Reconstruction of B->J/Psi hadron candidates +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" + +#include "Common/Core/RecoDecay.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 + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_trkcandsel; + +enum DecayChannel : uint8_t { + B0ToJpsiK0Star = 0, + BplusToJpsiK, + BsToJpsiPhi +}; + +/// Reconstruction of B+ candidates +struct HfCandidateCreatorBToJpsiReduced { + Produces rowCandidateBpBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateBpProngs; // table defined in ReducedDataModel.h + Produces rowCandidateBsBase; // table defined in CandidateReconstructionTables.h + Produces rowCandidateBsProngs; // table defined in ReducedDataModel.h + + // 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", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B+ is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + + Configurable runJpsiToee{"runJpsiToee", false, "Run analysis for J/Psi to ee (debug)"}; + // selection + Configurable invMassWindowJpsiHadTolerance{"invMassWindowJpsiHadTolerance", 0.01, "invariant-mass window tolerance for J/Psi K pair preselections (GeV/c2)"}; + + float myInvMassWindowJpsiK{1.}, myInvMassWindowJpsiPhi{1.}; // variable that will store the value of invMassWindowJpsiK (defined in dataCreatorJpsiKReduced.cxx) + double massBplus{0.}, massBs{0.}; + double bz{0.}; + o2::vertexing::DCAFitterN<2> df2; // fitter for B vertex (2-prong vertex fitter) + o2::vertexing::DCAFitterN<3> df3; // fitter for B vertex (3-prong vertex fitter) + o2::vertexing::DCAFitterN<4> df4; // fitter for B vertex (4-prong vertex fitter) + + using HfRedCollisionsWithExtras = soa::Join; + + Preslice> candsJpsiPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> tracksLf0PerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice> tracksLf1PerCollision = hf_track_index_reduced::hfRedCollisionId; + + std::shared_ptr hCandidatesB, hCandidatesPhi; + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + HistogramRegistry registry{"registry"}; + + void init(InitContext const&) + { + // invariant-mass window cut + massBplus = o2::constants::physics::MassBPlus; + massBs = o2::constants::physics::MassBS; + + // Initialize fitters + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + df2.setMatCorrType(noMatCorr); + + df3.setPropagateToPCA(propagateToPCA); + df3.setMaxR(maxR); + df3.setMaxDZIni(maxDZIni); + df3.setMinParamChange(minParamChange); + df3.setMinRelChi2Change(minRelChi2Change); + df3.setUseAbsDCA(useAbsDCA); + df3.setWeightedFinalPCA(useWeightedFinalPCA); + df3.setMatCorrType(noMatCorr); + + df4.setPropagateToPCA(propagateToPCA); + df4.setMaxR(maxR); + df4.setMaxDZIni(maxDZIni); + df4.setMinParamChange(minParamChange); + df4.setMinRelChi2Change(minRelChi2Change); + df4.setUseAbsDCA(useAbsDCA); + df4.setWeightedFinalPCA(useWeightedFinalPCA); + df4.setMatCorrType(noMatCorr); + + // histograms + registry.add("hMassJpsi", "J/Psi mass;#it{M}_{#mu#mu} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{600, 2.5, 3.7, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hMassBplusToJpsiK", "2-prong candidates;inv. mass (B^{+} #rightarrow #overline{D^{0}}#pi^{#plus} #rightarrow #pi^{#minus}K^{#plus}#pi^{#plus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 3., 8.}}}); + registry.add("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); + registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); + registry.add("hEvents", "Events;;entries", HistType::kTH1F, {{1, 0.5, 1.5}}); + + /// candidate monitoring + hCandidatesB = registry.add("hFitCandidatesJpsi", "candidates counter", {HistType::kTH1D, {axisCands}}); + hCandidatesPhi = registry.add("hFitCandidatesPhi", "candidates counter", {HistType::kTH1D, {axisCands}}); + setLabelHistoCands(hCandidatesB); + setLabelHistoCands(hCandidatesPhi); + } + + /// Main function to perform B+ candidate creation + /// \param collision the collision + /// \param candsJpsiThisColl J/Psi candidates in this collision + /// \param tracksLfThisCollisionArr LF tracks in this collision + /// \param invMass2JpsiHadMin minimum B invariant-mass + /// \param invMass2JpsiHadMax maximum B invariant-mass + template + void runCandidateCreation(Coll const& collision, + Cands const& candsJpsiThisColl, + TTracks0 const& tracksLfDau0ThisCollision, + TTracks1 const& tracksLfDau1ThisCollision, + const float invMass2JpsiHadMin, + const float invMass2JpsiHadMax) + { + auto primaryVertex = getPrimaryVertex(collision); + auto covMatrixPV = primaryVertex.getCov(); + + // Set the magnetic field from ccdb + bz = collision.bz(); + df2.setBz(bz); + df3.setBz(bz); + df4.setBz(bz); + + for (const auto& candJpsi : candsJpsiThisColl) { + o2::track::TrackParametrizationWithError trackPosParCov( + candJpsi.xDauPos(), candJpsi.alphaDauPos(), {candJpsi.yDauPos(), candJpsi.zDauPos(), candJpsi.snpDauPos(), candJpsi.tglDauPos(), candJpsi.signed1PtDauPos()}, 1 /*Charge*/, 1 /*Muon*/); + o2::track::TrackParametrizationWithError trackNegParCov( + candJpsi.xDauNeg(), candJpsi.alphaDauNeg(), {candJpsi.yDauNeg(), candJpsi.zDauNeg(), candJpsi.snpDauNeg(), candJpsi.tglDauNeg(), candJpsi.signed1PtDauNeg()}, -1 /*Charge*/, 1 /*Muon*/); + + // --------------------------------- + // reconstruct J/Psi candidate + o2::track::TrackParCov trackParCovJpsi{}; + std::array pVecJpsi{}; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::BeforeFit); + try { + if (df2.process(trackPosParCov, trackNegParCov) == 0) { + LOG(info) << "DCAFitterN failed to reconstruct J/Psi candidate, skipping the candidate."; + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::FitOk); + + std::array pVecDauPos{candJpsi.pxDauPos(), candJpsi.pyDauPos(), candJpsi.pzDauPos()}; + std::array pVecDauNeg{candJpsi.pxDauNeg(), candJpsi.pyDauNeg(), candJpsi.pzDauNeg()}; + + df2.getTrack(0).getPxPyPzGlo(pVecDauPos); + df2.getTrack(1).getPxPyPzGlo(pVecDauNeg); + pVecJpsi = RecoDecay::pVec(pVecDauPos, pVecDauNeg); + trackParCovJpsi = df2.createParentTrackParCov(); + trackParCovJpsi.setAbsCharge(0); // to be sure + + float invMassJpsi{0.f}; + if (runJpsiToee) { + invMassJpsi = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); + } else { + invMassJpsi = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg}, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon}); + } + invMassJpsi = std::sqrt(invMassJpsi); + registry.fill(HIST("hMassJpsi"), invMassJpsi); + + for (const auto& trackLf0 : tracksLfDau0ThisCollision) { + // this track is among daughters + if (trackLf0.trackId() == candJpsi.prongPosId() || trackLf0.trackId() == candJpsi.prongNegId()) { + continue; + } + auto trackParCovLf0 = getTrackParCov(trackLf0); + std::array pVecTrackLf0{}; + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + // --------------------------------- + // reconstruct the 3-prong B+ vertex + hCandidatesB->Fill(SVFitting::BeforeFit); + try { + if (df3.process(trackPosParCov, trackNegParCov, trackParCovLf0) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + hCandidatesB->Fill(SVFitting::Fail); + continue; + } + hCandidatesB->Fill(SVFitting::FitOk); + // JpsiK passed B+ reconstruction + + // calculate relevant properties + const auto& secondaryVertexBplus = df3.getPCACandidate(); + auto chi2PCA = df3.getChi2AtPCACandidate(); + auto covMatrixPCA = df3.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate Jpsi daugthers and K to the B+ vertex + df3.propagateTracksToVertex(); + // 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 + df3.getTrack(2).getPxPyPzGlo(pVecTrackLf0); // momentum of K at the B+ vertex + + // compute invariant mass square and apply selection + auto invMass2JpsiK = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg, pVecTrackLf0}, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}); + if ((invMass2JpsiK < invMass2JpsiHadMin) || (invMass2JpsiK > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassBplusToJpsiK"), std::sqrt(invMass2JpsiK)); + + // compute impact parameters of Jpsi and K + o2::dataformats::DCA dcaDauPos, dcaDauNeg, dcaKaon; + trackPosParCov.propagateToDCA(primaryVertex, bz, &dcaDauPos); + trackNegParCov.propagateToDCA(primaryVertex, bz, &dcaDauNeg); + trackParCovLf0.propagateToDCA(primaryVertex, bz, &dcaKaon); + + // get uncertainty of the decay length + 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)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + // fill the candidate table for the B+ here: + rowCandidateBpBase(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexBplus[0], secondaryVertexBplus[1], secondaryVertexBplus[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecDauPos[0], pVecDauPos[1], pVecDauPos[2], + pVecDauNeg[0], pVecDauNeg[1], pVecDauNeg[2], + pVecTrackLf0[0], pVecTrackLf0[1], pVecTrackLf0[2], + dcaDauPos.getY(), dcaDauNeg.getY(), dcaKaon.getY(), + std::sqrt(dcaDauPos.getSigmaY2()), std::sqrt(dcaDauNeg.getSigmaY2()), std::sqrt(dcaKaon.getSigmaY2())); + + rowCandidateBpProngs(candJpsi.globalIndex(), trackLf0.globalIndex()); + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + for (const auto& trackLf1 : tracksLfDau1ThisCollision) { + // this track is among daughters + if (trackLf1.trackId() == candJpsi.prongPosId() || trackLf1.trackId() == candJpsi.prongNegId()) { + continue; + } + auto trackParCovLf1 = getTrackParCov(trackLf1); + std::array pVecTrackLf1 = trackLf1.pVector(); + + // --------------------------------- + // reconstruct the 4-prong Bs vertex + hCandidatesB->Fill(SVFitting::BeforeFit); + try { + if (df4.process(trackPosParCov, trackNegParCov, trackParCovLf0, trackParCovLf1) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + hCandidatesB->Fill(SVFitting::Fail); + continue; + } + hCandidatesB->Fill(SVFitting::FitOk); + // passed Bs reconstruction + + // calculate relevant properties + const auto& secondaryVertexBs = df4.getPCACandidate(); + auto chi2PCA = df4.getChi2AtPCACandidate(); + auto covMatrixPCA = df4.calcPCACovMatrixFlat(); + registry.fill(HIST("hCovSVXX"), covMatrixPCA[0]); + registry.fill(HIST("hCovPVXX"), covMatrixPV[0]); + + // propagate Jpsi and phi to the Bs vertex + df4.propagateTracksToVertex(); + // 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 + df4.getTrack(2).getPxPyPzGlo(pVecTrackLf0); // momentum of K at the B+ vertex + df4.getTrack(3).getPxPyPzGlo(pVecTrackLf1); // momentum of K at the B+ vertex + + // compute invariant mass square and apply selection + auto invMass2JpsiPhi = RecoDecay::m2(std::array{pVecDauPos, pVecDauNeg, pVecTrackLf0, pVecTrackLf1}, std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + if ((invMass2JpsiPhi < invMass2JpsiHadMin) || (invMass2JpsiPhi > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassBplusToJpsiK"), std::sqrt(invMass2JpsiPhi)); + + // compute impact parameters of Jpsi and K + o2::dataformats::DCA dcaDauPos, dcaDauNeg, dcaTrackLf0, dcaTrackLf1; + trackPosParCov.propagateToDCA(primaryVertex, bz, &dcaDauPos); + trackNegParCov.propagateToDCA(primaryVertex, bz, &dcaDauNeg); + trackParCovLf0.propagateToDCA(primaryVertex, bz, &dcaTrackLf0); + trackParCovLf1.propagateToDCA(primaryVertex, bz, &dcaTrackLf1); + + // get uncertainty of the decay length + 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)); + auto errorDecayLengthXY = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phi, 0.) + getRotatedCovMatrixXX(covMatrixPCA, phi, 0.)); + + // fill the candidate table for the Bs here: + rowCandidateBsBase(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), + secondaryVertexBs[0], secondaryVertexBs[1], secondaryVertexBs[2], + errorDecayLength, errorDecayLengthXY, + chi2PCA, + pVecDauPos[0], pVecDauPos[1], pVecDauPos[2], + pVecDauNeg[0], pVecDauNeg[1], pVecDauPos[2], + pVecTrackLf0[0], pVecTrackLf0[1], pVecTrackLf0[2], + pVecTrackLf1[0], pVecTrackLf1[1], pVecTrackLf0[2], + dcaDauPos.getY(), dcaDauNeg.getY(), dcaTrackLf0.getY(), dcaTrackLf1.getY(), + std::sqrt(dcaDauPos.getSigmaY2()), std::sqrt(dcaDauNeg.getSigmaY2()), std::sqrt(dcaTrackLf0.getSigmaY2()), std::sqrt(dcaTrackLf1.getSigmaY2())); + rowCandidateBsProngs(candJpsi.globalIndex(), trackLf0.globalIndex(), trackLf1.globalIndex()); + } + } + } // TrackLf0 loop + } // J/Psi loop + } // end runCandidateCreation + + void processDataBplus(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsJpsi, + soa::Join const& tracksKaon, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCfgBpToJpsi const& configs) + { + // Jpsi K invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowJpsiK = config.myInvMassWindowJpsiK(); + } + // invMassWindowJpsiHadTolerance is used to apply a slightly tighter cut than in JpsiK pair preselection + // to avoid accepting JpsiK pairs that were not formed in JpsiK pair creator + double invMass2JpsiKMin = (massBplus - myInvMassWindowJpsiK + invMassWindowJpsiHadTolerance) * (massBplus - myInvMassWindowJpsiK + invMassWindowJpsiHadTolerance); + double invMass2JpsiKMax = (massBplus + myInvMassWindowJpsiK - invMassWindowJpsiHadTolerance) * (massBplus + myInvMassWindowJpsiK - invMassWindowJpsiHadTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto tracksKaonThisCollision = tracksKaon.sliceBy(tracksLf0PerCollision, thisCollId); + runCandidateCreation(collision, candsJpsiThisColl, tracksKaonThisCollision, tracksKaonThisCollision, invMass2JpsiKMin, invMass2JpsiKMax); + } + } // processDataBplus + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReduced, processDataBplus, "Process data for B+", true); + + void processDataBs(HfRedCollisionsWithExtras const& collisions, + soa::Join const& candsJpsi, + soa::Join const& tracksLfDau0, + soa::Join const& tracksLfDau1, + aod::HfOrigColCounts const& collisionsCounter, + aod::HfCfgBsToJpsis const& configs) + { + // Jpsi K invariant-mass window cut + for (const auto& config : configs) { + myInvMassWindowJpsiPhi = config.myInvMassWindowJpsiPhi(); + } + // invMassWindowJpsiHadTolerance is used to apply a slightly tighter cut than in JpsiK pair preselection + // to avoid accepting JpsiK pairs that were not formed in JpsiK pair creator + double invMass2JpsiKMin = (massBs - myInvMassWindowJpsiPhi + invMassWindowJpsiHadTolerance) * (massBs - myInvMassWindowJpsiPhi + invMassWindowJpsiHadTolerance); + double invMass2JpsiKMax = (massBs + myInvMassWindowJpsiPhi - invMassWindowJpsiHadTolerance) * (massBs + myInvMassWindowJpsiPhi - invMassWindowJpsiHadTolerance); + + for (const auto& collisionCounter : collisionsCounter) { + registry.fill(HIST("hEvents"), 1, collisionCounter.originalCollisionCount()); + } + + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto tracksLf0ThisCollision = tracksLfDau0.sliceBy(tracksLf0PerCollision, thisCollId); + auto tracksLf1ThisCollision = tracksLfDau1.sliceBy(tracksLf1PerCollision, thisCollId); + runCandidateCreation(collision, candsJpsiThisColl, tracksLf0ThisCollision, tracksLf1ThisCollision, invMass2JpsiKMin, invMass2JpsiKMax); + } + } // processDataBs + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReduced, processDataBs, "Process data for Bs", false); +}; // struct + +/// Extends the table base with expression columns and performs MC matching. +struct HfCandidateCreatorBToJpsiReducedExpressions { + Spawns rowCandidateBPlus; + Spawns rowCandidateBs; + Produces rowBplusMcRec; + Produces rowBsMcRec; + + /// Fill candidate information at MC reconstruction level + /// \param rowsJpsiHadMcRec MC reco information on Jpsi hadron pairs + /// \param candsBIds prong global indices of B candidates + template + void fillMcRec(McRec const& rowsJpsiHadMcRec, CCands const& candsBIds) + { + for (const auto& candB : candsBIds) { + bool filledMcInfo{false}; + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + for (const auto& rowJpsiHadMcRec : rowsJpsiHadMcRec) { + if ((rowJpsiHadMcRec.jpsiId() != candB.jpsiId()) || (rowJpsiHadMcRec.bachKaId() != candB.bachKaId())) { + continue; + } + rowBplusMcRec(rowJpsiHadMcRec.flagMcMatchRec(), rowJpsiHadMcRec.flagMcDecayChanRec(), rowJpsiHadMcRec.flagWrongCollision(), rowJpsiHadMcRec.debugMcRec(), rowJpsiHadMcRec.ptMother()); + filledMcInfo = true; + break; + } + if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the Jpsi-K creator + rowBplusMcRec(0, -1, -1, -1, -1.f); + } + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + for (const auto& rowJpsiHadMcRec : rowsJpsiHadMcRec) { + if ((rowJpsiHadMcRec.jpsiId() != candB.jpsiId()) || (rowJpsiHadMcRec.prong0PhiId() != candB.prong0PhiId()) || (rowJpsiHadMcRec.prong1PhiId() != candB.prong1PhiId())) { + continue; + } + rowBsMcRec(rowJpsiHadMcRec.flagMcMatchRec(), rowJpsiHadMcRec.flagMcDecayChanRec(), rowJpsiHadMcRec.flagWrongCollision(), rowJpsiHadMcRec.debugMcRec(), rowJpsiHadMcRec.ptMother()); + filledMcInfo = true; + break; + } + if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the Jpsi-K creator + rowBsMcRec(0, -1, -1, -1, -1.f); + } + } + } + } + + void processMcBPlus(HfMcRecRedJPKs const& rowsJpsiKMcRec, HfRedBplus2JpsiDaus const& candsBplus) + { + fillMcRec(rowsJpsiKMcRec, candsBplus); + } + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReducedExpressions, processMcBPlus, "Process MC", false); + + void processMcBs(HfMcRecRedJPPhis const& rowsJpsiPhiMcRec, HfRedBs2JpsiDaus const& Bs) + { + fillMcRec(rowsJpsiPhiMcRec, Bs); + } + PROCESS_SWITCH(HfCandidateCreatorBToJpsiReducedExpressions, processMcBs, "Process MC", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx index 3cd3e0f571b..1bcff8ae7ae 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBplusReduced.cxx @@ -14,22 +14,33 @@ /// /// \author Antonio Palasciano , Università degli Studi di Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.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; @@ -293,7 +304,7 @@ struct HfCandidateCreatorBplusReducedExpressions { if ((rowD0PiMcRec.prong0Id() != candBplus.prong0Id()) || (rowD0PiMcRec.prong1Id() != candBplus.prong1Id())) { continue; } - rowBplusMcRec(rowD0PiMcRec.flagMcMatchRec(), rowD0PiMcRec.flagWrongCollision(), rowD0PiMcRec.debugMcRec(), rowD0PiMcRec.ptMother()); + rowBplusMcRec(rowD0PiMcRec.flagMcMatchRec(), -1 /*channel*/, rowD0PiMcRec.flagWrongCollision(), rowD0PiMcRec.debugMcRec(), rowD0PiMcRec.ptMother()); filledMcInfo = true; if constexpr (checkDecayTypeMc) { rowBplusMcCheck(rowD0PiMcRec.pdgCodeBeautyMother(), @@ -305,7 +316,7 @@ struct HfCandidateCreatorBplusReducedExpressions { break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the D0-Pi creator - rowBplusMcRec(0, -1, -1, -1.f); + rowBplusMcRec(0, -1, -1, -1, -1.f); if constexpr (checkDecayTypeMc) { rowBplusMcCheck(-1, -1, -1, -1, -1); } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx index 7198796bc9b..4a9ee3a9c57 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorBsReduced.cxx @@ -14,21 +14,33 @@ /// /// \author Fabio Catalano , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.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; @@ -292,7 +304,7 @@ struct HfCandidateCreatorBsReducedExpressions { if ((rowDPiMcRec.prong0Id() != candB.prong0Id()) || (rowDPiMcRec.prong1Id() != candB.prong1Id())) { continue; } - rowBsMcRec(rowDPiMcRec.flagMcMatchRec(), rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); + rowBsMcRec(rowDPiMcRec.flagMcMatchRec(), -1 /*channel*/, rowDPiMcRec.flagWrongCollision(), rowDPiMcRec.debugMcRec(), rowDPiMcRec.ptMother()); filledMcInfo = true; if constexpr (checkDecayTypeMc) { rowBsMcCheck(rowDPiMcRec.pdgCodeBeautyMother(), @@ -305,7 +317,7 @@ struct HfCandidateCreatorBsReducedExpressions { break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the DsPi creator - rowBsMcRec(0, -1, -1, -1.f); + rowBsMcRec(0, -1, -1, -1, -1.f); if constexpr (checkDecayTypeMc) { rowBsMcCheck(-1, -1, -1, -1, -1, -1); } diff --git a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx index 1055c891092..f5f8734c652 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorCharmResoReduced.cxx @@ -13,21 +13,40 @@ /// \brief Reconstruction of Resonance candidates /// /// \author Luca Aglietta , Università degli Studi di Torino -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" +/// \author Antonio Palasciano , INFN Bari -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/D2H/Core/SelectorCutsRedDataFormat.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsMcMatching.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 using namespace o2; using namespace o2::aod; @@ -39,16 +58,24 @@ using namespace o2::constants::physics; enum Selections : uint8_t { NoSel = 0, DSel, - V0Sel, - TrackSel, + BachSel, NSelSteps }; -enum DecayChannel : uint8_t { - Ds1ToDstarK0s = 0, - Ds2StarToDplusK0s, - XcToDplusLambda, - LambdaDminus, - DstarTrack + +enum D0Sel : uint8_t { + selectedD0 = 0, + selectedD0Bar +}; + +enum DType : uint8_t { + Dplus = 1, + Dstar, + D0 +}; + +enum BachelorType : uint8_t { + V0 = 1, + Track }; enum V0Type : uint8_t { @@ -57,574 +84,811 @@ enum V0Type : uint8_t { AntiLambda }; -enum DecayTypeMc : uint8_t { - Ds1ToDStarK0ToD0PiK0s = 1, - Ds2StarToDplusK0sToPiKaPiPiPi, - Ds1ToDStarK0ToDPlusPi0K0s, - Ds1ToDStarK0ToD0PiK0sPart, - Ds1ToDStarK0ToD0NoPiK0sPart, - Ds1ToDStarK0ToD0PiK0sOneMu, - Ds2StarToDplusK0sOneMu +enum TrackType : uint8_t { + Pion = 0, + Kaon, + Proton }; -const int nBinsPt = 7; -constexpr double binsPt[nBinsPt + 1] = { - 1., - 2., - 4., - 6., - 8., - 12., - 24., - 1000.}; -auto vecBinsPt = std::vector{binsPt, binsPt + nBinsPt + 1}; - struct HfCandidateCreatorCharmResoReduced { // Produces: Tables with resonance info Produces rowCandidateReso; - Produces rowCandidateResoTrack; - // Optional daughter ML scores table - Produces mlScores; - // Table with candidate indices for MC matching - Produces rowCandidateResoIndices; - - // Configurables - Configurable rejectDV0PairsWithCommonDaughter{"rejectDV0PairsWithCommonDaughter", true, "flag to reject the pairs that share a daughter track if not done in the derived data creation"}; - Configurable keepSideBands{"keepSideBands", false, "flag to keep events from D meson sidebands for backgorund estimation"}; - // QA switch - Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; - Configurable> binsPt{"binsPt", std::vector{vecBinsPt}, "Histogram pT bin limits"}; - // Daughters selection cuts - Configurable> cutsD{"cutsDdaughter", {hf_cuts_d_daughter::Cuts[0], hf_cuts_d_daughter::NBinsPt, hf_cuts_d_daughter::NCutVars, hf_cuts_d_daughter::labelsPt, hf_cuts_d_daughter::labelsCutVar}, "D daughter selections"}; - Configurable> binsPtD{"binsPtD", std::vector{hf_cuts_d_daughter::vecBinsPt}, "pT bin limits for D daughter cuts"}; - Configurable> cutsV0{"cutsV0daughter", {hf_cuts_v0_daughter::Cuts[0], hf_cuts_v0_daughter::NBinsPt, hf_cuts_v0_daughter::NCutVars, hf_cuts_v0_daughter::labelsPt, hf_cuts_v0_daughter::labelsCutVar}, "V0 daughter selections"}; - Configurable> binsPtV0{"binsPtV0", std::vector{hf_cuts_v0_daughter::vecBinsPt}, "pT bin limits for V0 daughter cuts"}; - - // Configurables for ME - Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; - Configurable numberEventsToSkip{"numberEventsToSkip", -1, "Number of events to Skip in ME process"}; - ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0., 45., 60., 75., 95, 250}, "event multiplicity pools (PV contributors for now)"}; - ConfigurableAxis zPoolBins{"zPoolBins", {VARIABLE_WIDTH, -10.0, -4, -1, 1, 4, 10.0}, "z vertex position pools"}; - - using HfRed3PrNoTrksWithMl = soa::Join; - - // Partition of V0 candidates based on v0Type - Partition candidatesK0s = aod::hf_reso_v0::v0Type == (uint8_t)1 || aod::hf_reso_v0::v0Type == (uint8_t)3 || aod::hf_reso_v0::v0Type == (uint8_t)5; - Partition candidatesLambda = aod::hf_reso_v0::v0Type == (uint8_t)2 || aod::hf_reso_v0::v0Type == (uint8_t)4; + // Tables with bachelors indices for MC matching and Task + Produces rowCandidateResoIndices3PrV0s; + Produces rowCandidateResoIndicesDstarV0s; + Produces rowCandidateResoIndices2PrV0s; + Produces rowCandidateResoIndices3PrTrks; + Produces rowCandidateResoIndicesDstarTrks; + Produces rowCandidateResoIndices2PrTrks; + // D Configurables + struct : ConfigurableGroup { + std::string prefix = "dmesonsCuts"; + Configurable> binsPtD{"binsPtD", std::vector{hf_cuts_d_daughter::vecBinsPt}, "pT bin limits for D daughter cuts"}; + Configurable> cutsD{"cutsD", {hf_cuts_d_daughter::Cuts[0], hf_cuts_d_daughter::NBinsPt, hf_cuts_d_daughter::NCutVars, hf_cuts_d_daughter::labelsPt, hf_cuts_d_daughter::labelsCutVar}, "D daughter selections"}; + Configurable keepSideBands{"keepSideBands", false, "flag to keep events from D meson sidebands for backgorund estimation"}; + } cfgDmesCuts; + // V0 cuts configurables + struct : ConfigurableGroup { + std::string prefix = "v0Cuts"; + Configurable> cutsV0{"cutsV0", {hf_cuts_v0_daughter::Cuts[0], hf_cuts_v0_daughter::NBinsPt, hf_cuts_v0_daughter::NCutVars, hf_cuts_v0_daughter::labelsPt, hf_cuts_v0_daughter::labelsCutVar}, "V0 daughter selections"}; + Configurable> binsPtV0{"binsPtV0", std::vector{hf_cuts_v0_daughter::vecBinsPt}, "pT bin limits for V0 daughter cuts"}; + Configurable v0Type{"v0Type", 0, "V0 type to be selected (0: K0s, 1: Lambda"}; + } cfgV0Cuts; + // Track cuts configurables + struct : ConfigurableGroup { + std::string prefix = "trackCuts"; + Configurable> cutsTrk{"cutsTrk", {hf_cuts_track_daughter::Cuts[0], hf_cuts_track_daughter::NCutVars, hf_cuts_track_daughter::labelsCutVar}, "Track daughter selections, set to -1 to disable cuts"}; + Configurable massHypo{"massHypo", 1, "Mass Hypothesis for the track daughters (0: pion, 1: kaon, 2: proton)"}; + } cfgTrackCuts; + // Mixed Event configurables + struct : ConfigurableGroup { + std::string prefix = "mixedEvent"; + Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; + Configurable numberEventsToSkip{"numberEventsToSkip", -1, "Number of events to Skip in ME process"}; + ConfigurableAxis multPoolBins{"multPoolBins", {VARIABLE_WIDTH, 0., 45., 60., 75., 95, 250}, "event multiplicity pools (PV contributors for now)"}; + ConfigurableAxis zPoolBins{"zPoolBins", {VARIABLE_WIDTH, -10.0, -4, -1, 1, 4, 10.0}, "z vertex position pools"}; + } cfgMixedEvent; + // Histogram axes configurables + struct : ConfigurableGroup { + std::string prefix = "histAxes"; + ConfigurableAxis axisPtD{"axisPtD", {100, 0., 50}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtV0{"axisPtV0", {100, 0., 50}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtReso{"axisPtReso", {100, 0., 50}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisMassD{"axisMassD", {100, 1.7f, 2.1f}, "inv. mass (D) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisMassV0{"axisMassV0", {100, 0.45f, 0.55f}, "inv. mass (V_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisMassDsj{"axisMassDsj", {400, 0.49f, 0.89f}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; + } cfgHistAxes; + // Other Configurables + Configurable rejectPairsWithCommonDaughter{"rejectPairsWithCommonDaughter", true, "flag to reject the pairs that share a daughter track if not done in the derived data creation"}; + Configurable useDeltaMass{"useDeltaMass", true, "Use Delta Mass for resonance invariant Mass calculation"}; SliceCache cache; Preslice candsV0PerCollision = aod::hf_track_index_reduced::hfRedCollisionId; Preslice candsTrackPerCollision = aod::hf_track_index_reduced::hfRedCollisionId; - Preslice candsDPerCollision = hf_track_index_reduced::hfRedCollisionId; - Preslice candsDPerCollisionWithMl = hf_track_index_reduced::hfRedCollisionId; + Preslice cands3PrPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice candsDstarPerCollision = hf_track_index_reduced::hfRedCollisionId; + Preslice cands2PrPerCollision = hf_track_index_reduced::hfRedCollisionId; HistogramRegistry registry{"registry"}; void init(InitContext const&) { - // check that only one process function is enabled - std::array doprocess{doprocessDs2StarToDplusK0s, doprocessDs2StarToDplusK0sWithMl, doprocessDs1ToDstarK0s, doprocessDs1ToDstarK0sWithMl, doprocessDs1ToDstarK0sMixedEvent, doprocessDs1ToDstarK0sMixedEventWithMl, doprocessDs2StarToDplusK0sMixedEventWithMl, - doprocessXcToDplusLambda, doprocessXcToDplusLambdaWithMl, doprocessLambdaDminus, doprocessLambdaDminusWithMl, doprocessDstarTrack, doprocessDstarTrackWithMl}; - if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { - LOGP(fatal, "Only one process function should be enabled! Please check your configuration!"); - } // histograms - const AxisSpec axisPt{(std::vector)vecBinsPt, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec axisMassDsj{400, 0.49f, 0.89f, ""}; - registry.add("hMassDs1", "Ds1 candidates;m_{Ds1} (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisMassDsj, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassDs2Star", "Ds^{*}2 candidates; m_Ds^{*}2 (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {axisMassDsj, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassXcRes", "XcRes candidates; m_XcRes (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{300, 1.1, 1.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassLambdaDminus", "LambdaDminus candidates; m_LambdaDminus (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{300, 1.1, 1.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("hMassDstarTrack", "DstarTrack candidates; m_DstarTrack (GeV/#it{c}^{2}) ;entries", {HistType::kTH2F, {{100, 0.9, 1.4}, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - if (doprocessDs1ToDstarK0sMixedEvent) { - registry.add("hNPvContCorr", "Collision number of PV contributors ; N contrib ; N contrib", {HistType::kTH2F, {{100, 0, 250}, {100, 0, 250}}}); - registry.add("hZvertCorr", "Collision Z Vtx ; z PV [cm] ; z PV [cm]", {HistType::kTH2F, {{120, -12., 12.}, {120, -12., 12.}}}); + registry.add("hMassDmesDauVsPt", "D daughter candidates inv. mass", {HistType::kTH2F, {cfgHistAxes.axisMassD, cfgHistAxes.axisPtD}}); + registry.add("hMassV0DauVsPt", "V0 daughter candidates inv. mass", {HistType::kTH2F, {cfgHistAxes.axisMassV0, cfgHistAxes.axisPtV0}}); + registry.add("hMassResoVsPt", "Resonance candidates inv. mass", {HistType::kTH2F, {cfgHistAxes.axisMassDsj, cfgHistAxes.axisPtReso}}); + registry.add("hNPvContCorr", "Collision number of PV contributors ; N contrib ; N contrib", {HistType::kTH2F, {{100, 0, 250}, {100, 0, 250}}}); + registry.add("hZvertCorr", "Collision Z Vtx ; z PV [cm] ; z PV [cm]", {HistType::kTH2F, {{120, -12., 12.}, {120, -12., 12.}}}); + constexpr int kNBinsSelections = Selections::NSelSteps; + std::string labels[kNBinsSelections]; + labels[Selections::NoSel] = "No selection"; + labels[Selections::DSel] = "D Candidates Selection"; + labels[Selections::BachSel] = "D & other bach. Selection"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelections", "Selections", {HistType::kTH1F, {axisSelections}}); + for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { + registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } + } - if (activateQA) { - constexpr int kNBinsSelections = Selections::NSelSteps; - std::string labels[kNBinsSelections]; - labels[Selections::NoSel] = "No selection"; - labels[Selections::DSel] = "D Candidates Selection"; - labels[Selections::V0Sel] = "D & V0 candidate Selection"; - labels[Selections::TrackSel] = "D & Track candidate Selection"; - static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; - registry.add("hSelections", "Selections", {HistType::kTH1F, {axisSelections}}); - for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { - registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); - } + bool isInMassInterval(float invMass, int ptBin) + { + if (!cfgDmesCuts.keepSideBands) { + return (invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalHigh")); + } else { + return ((invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassLeftSBLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassLeftSBHigh")) || + (invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassRightSBLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassRightSBHigh")) || + (invMass >= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalLow") && invMass <= cfgDmesCuts.cutsD->get(ptBin, "invMassSignalHigh"))); } } /// Basic selection of D candidates /// \param candD is the reduced D meson candidate /// \return true if selections are passed - template - bool isDSelected(DRedTable const& candD) + template + uint8_t selctionFlagBachD(DRedTable const& candD) { + uint8_t selection = {BIT(D0Sel::selectedD0) | BIT(D0Sel::selectedD0Bar)}; float invMassD{0.}; float ptD = candD.pt(); - int ptBin = findBin(binsPtD, ptD); + int ptBin = findBin(cfgDmesCuts.binsPtD, ptD); if (ptBin == -1) { - return false; + return 0; } - if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { + if constexpr (dType == DType::Dplus) { invMassD = candD.invMassDplus(); - } else if (channel == DecayChannel::Ds1ToDstarK0s || channel == DecayChannel::DstarTrack) { - if (candD.dType() > 0) + if (!isInMassInterval(invMassD, ptBin)) { + return 0; + } + } else if constexpr (dType == DType::Dstar) { + if (candD.sign() > 0) { invMassD = candD.invMassDstar() - candD.invMassD0(); - else + } else { invMassD = candD.invMassAntiDstar() - candD.invMassD0Bar(); - } - // invariant mass selection - if (!keepSideBands) { - if (invMassD < cutsD->get(ptBin, "invMassSignalLow") || invMassD > cutsD->get(ptBin, "invMassSignalHigh")) { - return false; } - } else { - if ((invMassD < cutsD->get(ptBin, "invMassLeftSBLow")) || - (invMassD > cutsD->get(ptBin, "invMassLeftSBHigh") && invMassD < cutsD->get(ptBin, "invMassSignalLow")) || - (invMassD > cutsD->get(ptBin, "invMassSignalHigh") && invMassD < cutsD->get(ptBin, "invMassRightSBLow")) || - (invMassD > cutsD->get(ptBin, "invMassRightSBHigh"))) { - return false; + if (!isInMassInterval(invMassD, ptBin)) { + return 0; + } + } else if constexpr (dType == DType::D0) { + if (TESTBIT(candD.selFlagD0(), D0Sel::selectedD0)) { + invMassD = candD.invMassD0(); + if (!isInMassInterval(invMassD, ptBin)) { + CLRBIT(selection, D0Sel::selectedD0); + } + } else { + CLRBIT(selection, D0Sel::selectedD0); + } + if (TESTBIT(candD.selFlagD0(), D0Sel::selectedD0Bar)) { + invMassD = candD.invMassD0Bar(); + if (!isInMassInterval(invMassD, ptBin)) { + CLRBIT(selection, D0Sel::selectedD0Bar); + } + } else { + CLRBIT(selection, D0Sel::selectedD0Bar); } } - return true; + return selection; } /// Basic selection of V0 and track candidates /// \param candV0 is the reduced V0 candidate - /// \param candD is the reduced D meson candidate /// \return true if selections are passed - template - bool isV0Selected(V0RedTable const& candV0, DRedTable const& candD) + template + bool isV0Selected(V0RedTable const& candV0) { - float massV0{0.}; - float invMassV0{0.}; - float ptV0 = candV0.pt(); - int ptBin = findBin(binsPtV0, ptV0); + int ptBin = findBin(cfgV0Cuts.binsPtV0, candV0.pt()); if (ptBin == -1) { return false; } - if (channel == DecayChannel::Ds2StarToDplusK0s || channel == DecayChannel::Ds1ToDstarK0s) { - massV0 = MassK0Short; - invMassV0 = candV0.invMassK0s(); - } else if (channel == DecayChannel::XcToDplusLambda || channel == DecayChannel::LambdaDminus) { - massV0 = MassLambda; - int wsFact{1}; - if (channel == DecayChannel::LambdaDminus) - wsFact = -1; - uint8_t targetV0Type{0}; - if (wsFact * candD.dType() > 0) { - invMassV0 = candV0.invMassLambda(); - targetV0Type = V0Type::Lambda; - } else { - invMassV0 = candV0.invMassAntiLambda(); - targetV0Type = V0Type::AntiLambda; + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + if (!TESTBIT(candV0.v0Type(), V0Type::K0s)) { + return false; } - // check skimming cuts - if (!TESTBIT(candV0.v0Type(), targetV0Type)) { + if ((candV0.invMassK0s() - MassK0Short) > cfgV0Cuts.cutsV0->get(ptBin, "invMassLow") && (MassK0Short - candV0.invMassK0s()) < cfgV0Cuts.cutsV0->get(ptBin, "invMassLow")) { return false; } - } - // selection on V0 candidate mass - if ((invMassV0 - massV0) > cutsV0->get(ptBin, "invMassLow") && (massV0 - invMassV0) < cutsV0->get(ptBin, "invMassLow")) { + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (!TESTBIT(candV0.v0Type(), V0Type::Lambda) && !TESTBIT(candV0.v0Type(), V0Type::AntiLambda)) { + return false; + } + if ((candV0.invMassLambda() - MassLambda) > cfgV0Cuts.cutsV0->get(ptBin, "invMassLow") && (MassLambda - candV0.invMassLambda()) < cfgV0Cuts.cutsV0->get(ptBin, "invMassLow")) { + return false; + } + if ((candV0.invMassAntiLambda() - MassLambda) > cfgV0Cuts.cutsV0->get(ptBin, "invMassLow") && (MassLambda - candV0.invMassAntiLambda()) < cfgV0Cuts.cutsV0->get(ptBin, "invMassLow")) { + return false; + } + } else { + LOG(error) << "Unsupported V0 type for selection: " << cfgV0Cuts.v0Type; return false; } // selection on kinematics and topology - if (candV0.dca() > cutsV0->get(ptBin, "dcaMax") || candV0.cpa() < cutsV0->get(ptBin, "cpaMin") || candV0.v0Radius() < cutsV0->get(ptBin, "radiusMin")) { + if (candV0.dca() > cfgV0Cuts.cutsV0->get(ptBin, "dcaMax") || candV0.cpa() < cfgV0Cuts.cutsV0->get(ptBin, "cpaMin") || candV0.v0Radius() < cfgV0Cuts.cutsV0->get(ptBin, "radiusMin")) { return false; } return true; } - template - void runCandidateCreation(Coll const& collision, - DRedTable const& candsD, - V0TrRedTable const& candsV0Tr) + // Basic selection of track candidates + /// \param candTr is the reduced track candidate + /// \return true if selections are passed + template + bool isTrackSelected(TrkRedTable const& candTr) { - // loop on D candidates - for (const auto& candD : candsD) { - // selection of D candidates - if (activateQA) { - registry.fill(HIST("hSelections"), 1); + // pT selection + if (cfgTrackCuts.cutsTrk->get("ptMin") > 0 && candTr.pt() < cfgTrackCuts.cutsTrk->get("ptMin")) { + return false; + } + // ITS quality selection + if (cfgTrackCuts.cutsTrk->get("itsNClsMin") > 0 && candTr.itsNCls() < cfgTrackCuts.cutsTrk->get("itsNClsMin")) { + return false; + } + // TPC quality selection + if (cfgTrackCuts.cutsTrk->get("tpcNCrossedRowsMin") > 0 && candTr.tpcNClsCrossedRows() < cfgTrackCuts.cutsTrk->get("tpcNCrossedRowsMin")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("tpcChi2Max") > 0 && candTr.tpcChi2NCl() > cfgTrackCuts.cutsTrk->get("tpcChi2Max")) { + return false; + } + // PID selection + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + if (cfgTrackCuts.cutsTrk->get("nSigmaTpc") > 0 && candTr.tpcNSigmaPi() > cfgTrackCuts.cutsTrk->get("nSigmaTpc")) { + return false; } - if (!isDSelected(candD)) { - continue; + if (cfgTrackCuts.cutsTrk->get("nSigmaTof") > 0 && candTr.tofNSigmaPi() > cfgTrackCuts.cutsTrk->get("nSigmaTof")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("nSigmaComb") > 0 && candTr.tpcTofNSigmaPi() > cfgTrackCuts.cutsTrk->get("nSigmaComb")) { + return false; + } + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + if (cfgTrackCuts.cutsTrk->get("nSigmaTpc") > 0 && candTr.tpcNSigmaKa() > cfgTrackCuts.cutsTrk->get("nSigmaTpc")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("nSigmaTof") > 0 && candTr.tofNSigmaKa() > cfgTrackCuts.cutsTrk->get("nSigmaTof")) { + return false; + } + if (cfgTrackCuts.cutsTrk->get("nSigmaComb") > 0 && candTr.tpcTofNSigmaKa() > cfgTrackCuts.cutsTrk->get("nSigmaComb")) { + return false; + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + if (cfgTrackCuts.cutsTrk->get("nSigmaTpc") > 0 && candTr.tpcNSigmaPr() > cfgTrackCuts.cutsTrk->get("nSigmaTpc")) { + return false; } - if (activateQA) { - registry.fill(HIST("hSelections"), 1 + Selections::DSel); + if (cfgTrackCuts.cutsTrk->get("nSigmaTof") > 0 && candTr.tofNSigmaPr() > cfgTrackCuts.cutsTrk->get("nSigmaTof")) { + return false; } - float invMassD{0.}; - float invMassD0{0.}; - if (std::abs(candD.dType()) == 1) - invMassD = candD.invMassDplus(); - if (candD.dType() == 2) { + if (cfgTrackCuts.cutsTrk->get("nSigmaComb") > 0 && candTr.tpcTofNSigmaPr() > cfgTrackCuts.cutsTrk->get("nSigmaComb")) { + return false; + } + } else { + LOG(error) << "Unsupported mass hypothesis for track selection: " << cfgTrackCuts.massHypo; + return false; + } + return true; + } + + /// Fill the output tables with the resonance candidates + /// \param collision is the collision information + /// \param candD is the reduced D meson candidate + /// \param candV0Tr is the reduced V0 or track candidate + /// \tparam dType is the type of D meson (Dplus, Dstar, D0) + /// \tparam bachType is the type of bachelor (V0 or Track) + template + void fillOutputTables(Coll const& collision, + DRedTable const& candD, + V0TrRedTable const& candV0Tr, + int selectionFlag) + { + std::vector> pVectorCharmProngs = {candD.pVectorProng0(), candD.pVectorProng1()}; + std::array pVecD = candD.pVector(); + std::array pVecV0Tr = candV0Tr.pVector(); + float invMassReso{-1}, invMassV0Tr{-1}, invMassD{-1}; + int8_t signReso{0}, isWrongSign{0}; + double ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0Tr, pVecD)); + + if constexpr (dType == DType::Dplus) { + invMassD = candD.invMassDplus(); + pVectorCharmProngs.push_back(candD.pVectorProng2()); + if constexpr (bachType == BachelorType::V0) { + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + signReso = candD.sign(); + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassK0Short}); + } + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + signReso = candD.sign(); + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + signReso = candD.sign(); + isWrongSign = 1; + } + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassLambda}); + } + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices3PrV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candD.sign() + candV0Tr.sign(); + isWrongSign = candD.sign() * candV0Tr.sign() > 0 ? 1 : 0; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassPiPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassKPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassProton}); + } + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices3PrTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } + } else if constexpr (dType == DType::Dstar) { + float invMassD0; + if (candD.sign() > 0) { invMassD = candD.invMassDstar(); invMassD0 = candD.invMassD0(); - } - if (candD.dType() == -2) { + } else { invMassD = candD.invMassAntiDstar(); invMassD0 = candD.invMassD0Bar(); } - std::array pVecD = {candD.px(), candD.py(), candD.pz()}; - - // loop on V0 or track candidates - bool alreadyCounted{false}; - for (const auto& candV0Tr : candsV0Tr) { - if (rejectDV0PairsWithCommonDaughter) { - const std::array dDaughtersIDs = {candD.prong0Id(), candD.prong1Id(), candD.prong2Id()}; - if constexpr (channel == DecayChannel::DstarTrack) { - if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.globalIndex()) != dDaughtersIDs.end()) { - continue; + pVectorCharmProngs.push_back(candD.pVectorProng2()); + if constexpr (bachType == BachelorType::V0) { + signReso = candD.sign(); + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; } } else { - if (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong0Id()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong1Id()) != dDaughtersIDs.end()) { - continue; - } + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassK0Short}); } - } - if constexpr (channel != DecayChannel::DstarTrack) { - if (!isV0Selected(candV0Tr, candD)) { - continue; + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + isWrongSign = 1; } - if (activateQA && !alreadyCounted) { - registry.fill(HIST("hSelections"), 1 + Selections::V0Sel); - alreadyCounted = true; + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; + } + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassLambda}); } } - - float invMassReso{0.}; - float invMassV0{0.}; - std::array pVecV0Tr = {candV0Tr.px(), candV0Tr.py(), candV0Tr.pz()}; - std::array, 3> pVectorCharmProngs = {candD.pVectorProng0(), candD.pVectorProng1(), candD.pVectorProng2()}; - float ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0Tr, pVecD)); - - if constexpr (channel == DecayChannel::DstarTrack) { - if (candD.dType() > 0) { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}); + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD - invMassD0, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndicesDstarV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD - invMassD0, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candD.sign() + candV0Tr.sign(); + isWrongSign = candD.sign() * candV0Tr.sign() > 0 ? 1 : 0; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } } else { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}); + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassPiPlus}); } - registry.fill(HIST("hMassDstarTrack"), invMassReso - invMassD, ptReso); - } else { - switch (channel) { - case DecayChannel::Ds1ToDstarK0s: - invMassV0 = candV0Tr.invMassK0s(); - if (candD.dType() > 0) { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; - } else { - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; - } - registry.fill(HIST("hMassDs1"), invMassReso, ptReso); - break; - case DecayChannel::Ds2StarToDplusK0s: - invMassV0 = candV0Tr.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0Short}) - invMassD; - registry.fill(HIST("hMassDs2Star"), invMassReso, ptReso); - break; - case DecayChannel::XcToDplusLambda: - if (candD.dType() > 0) { - invMassV0 = candV0Tr.invMassLambda(); - } else { - invMassV0 = candV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; - registry.fill(HIST("hMassXcRes"), invMassReso, ptReso); - break; - case DecayChannel::LambdaDminus: - if (candD.dType() < 0) { - invMassV0 = candV0Tr.invMassLambda(); - } else { - invMassV0 = candV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassLambda}) - invMassD; - registry.fill(HIST("hMassLambdaDminus"), invMassReso, ptReso); - break; - default: - break; + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassKPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + if (candD.sign() > 0) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[1], pVectorCharmProngs[0], pVectorCharmProngs[2], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassProton}) - invMassD; + } + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassProton}); } } - // Filling Output table - if constexpr (channel == DecayChannel::DstarTrack) { - rowCandidateResoTrack(pVecD[0], pVecD[1], pVecD[2], - candV0Tr.px(), candV0Tr.py(), candV0Tr.pz(), - invMassReso, - invMassD - invMassD0); - } else { + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD - invMassD0, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndicesDstarTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } + } else if constexpr (dType == DType::D0) { + // D0 + if (TESTBIT(selectionFlag, D0Sel::selectedD0)) { + invMassD = candD.invMassD0(); + if constexpr (bachType == BachelorType::V0) { + signReso = 0; + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassK0Short}); + } + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + isWrongSign = 1; + } + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassLambda}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassLambda}); + } + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candV0Tr.sign(); + isWrongSign = candV0Tr.sign() > 0 ? 0 : 1; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassPiPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassKPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassPiPlus, MassKPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0, MassProton}); + } + } rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], invMassReso, invMassD, - invMassV0, - candV0Tr.cpa(), - candV0Tr.dca(), - candV0Tr.v0Radius(), - invMassD0); - rowCandidateResoIndices(collision.globalIndex(), - candD.globalIndex(), - candV0Tr.globalIndex()); + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); } - if constexpr (fillMl) { - mlScores(candD.mlScoreBkgMassHypo0(), candD.mlScorePromptMassHypo0(), candD.mlScoreNonpromptMassHypo0()); + } + // D0bar + if (TESTBIT(selectionFlag, D0Sel::selectedD0Bar)) { + invMassD = candD.invMassD0Bar(); + if constexpr (bachType == BachelorType::V0) { + signReso = 0; + if (cfgV0Cuts.v0Type == V0Type::K0s) { // K0s + invMassV0Tr = candV0Tr.invMassK0s(); + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassK0Short}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassK0Short}); + } + } else if (cfgV0Cuts.v0Type == V0Type::Lambda) { // Lambda + if (candV0Tr.v0Type() == V0Type::Lambda) { + invMassV0Tr = candV0Tr.invMassLambda(); + isWrongSign = 1; + } else if (candV0Tr.v0Type() == V0Type::AntiLambda) { + invMassV0Tr = candV0Tr.invMassAntiLambda(); + } + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassLambda}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassLambda}); + } + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrV0s(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); + } else if constexpr (bachType == BachelorType::Track) { + signReso = candV0Tr.sign(); + isWrongSign = candV0Tr.sign() > 0 ? 1 : 0; + if (cfgTrackCuts.massHypo == TrackType::Pion) { // Pion + invMassV0Tr = MassPiPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassPiPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassPiPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Kaon) { // Kaon + invMassV0Tr = MassKPlus; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassKPlus}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassKPlus}); + } + } else if (cfgTrackCuts.massHypo == TrackType::Proton) { // Proton + invMassV0Tr = MassProton; + if (useDeltaMass) { + invMassReso = RecoDecay::m(std::array{pVectorCharmProngs[0], pVectorCharmProngs[1], pVecV0Tr}, std::array{MassKPlus, MassPiPlus, MassProton}) - invMassD; + } else { + invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassD0Bar, MassProton}); + } + } + rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], + pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], + invMassReso, + invMassD, + invMassV0Tr, + signReso, + isWrongSign); + rowCandidateResoIndices2PrTrks(collision.globalIndex(), candD.globalIndex(), candV0Tr.globalIndex()); + registry.fill(HIST("hMassResoVsPt"), invMassReso, ptReso); + registry.fill(HIST("hMassDmesDauVsPt"), invMassD, candD.pt()); + registry.fill(HIST("hMassV0DauVsPt"), invMassV0Tr, candV0Tr.pt()); } } } - } // main function + } + + template + void runCandidateCreation(Coll const& collision, + DRedTable const& candsD, + V0TrRedTable const& candsV0Tr) + { + // loop on D candidates + // LOG(info) << "Number of D candidates: " << candsD.size() << ", Number of V0/Track candidates: " << candsV0Tr.size(); + for (const auto& candD : candsD) { + // selection of D candidates + registry.fill(HIST("hSelections"), 1); + uint8_t selFlagD = selctionFlagBachD(candD); + if (selFlagD == 0) { + continue; + } + registry.fill(HIST("hSelections"), 1 + Selections::DSel); + std::vector dDaughtersIDs = {candD.prong0Id(), candD.prong1Id()}; + if constexpr (dType == DType::Dstar || dType == DType::Dplus) { + dDaughtersIDs.push_back(candD.prong2Id()); + } + // loop on V0 or track candidates + bool alreadyCounted{false}; + for (const auto& candV0Tr : candsV0Tr) { + if constexpr (bachType == BachelorType::V0) { // Case: V0 + if (rejectPairsWithCommonDaughter && (std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong0Id()) != dDaughtersIDs.end() || std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.prong1Id()) != dDaughtersIDs.end())) { + continue; + } + if (!isV0Selected(candV0Tr)) { + continue; + } + if (!alreadyCounted) { + registry.fill(HIST("hSelections"), 1 + Selections::BachSel); + alreadyCounted = true; + } + } else if constexpr (bachType == BachelorType::Track) { // Case: Track + if (rejectPairsWithCommonDaughter && std::find(dDaughtersIDs.begin(), dDaughtersIDs.end(), candV0Tr.trackId()) != dDaughtersIDs.end()) { + continue; + } + if (!isTrackSelected(candV0Tr)) { + continue; + } + if (!alreadyCounted) { + registry.fill(HIST("hSelections"), 1 + Selections::BachSel); + alreadyCounted = true; + } + } + // Filling of tables and histograms + fillOutputTables(collision, candD, candV0Tr, selFlagD); + } // end of loop on V0/Track candidates + } // end of loop on D candidates + } // end of function + // Process data with Mixed Event /// \tparam fillMl is a flag to Fill ML scores if present /// \tparam channel is the decay channel of the Resonance /// \param Coll is the reduced collisions table /// \param DRedTable is the D bachelors table /// \param V0TrRedTable is the V0/Track bachelors table - template + template void runCandidateCreationMixedEvent(Coll const& collisions, DRedTable const& candsD, V0TrRedTable const& candsV0Tr) { using BinningType = ColumnBinningPolicy; - BinningType corrBinning{{zPoolBins, multPoolBins}, true}; + BinningType corrBinning{{cfgMixedEvent.zPoolBins, cfgMixedEvent.multPoolBins}, true}; auto bachTuple = std::make_tuple(candsD, candsV0Tr); - Pair pairs{corrBinning, numberEventsMixed, numberEventsToSkip, collisions, bachTuple, &cache}; + Pair pairs{corrBinning, cfgMixedEvent.numberEventsMixed, cfgMixedEvent.numberEventsToSkip, collisions, bachTuple, &cache}; for (const auto& [collision1, bachDs, collision2, bachV0Trs] : pairs) { registry.fill(HIST("hNPvContCorr"), collision1.numContrib(), collision2.numContrib()); registry.fill(HIST("hZvertCorr"), collision1.posZ(), collision2.posZ()); for (const auto& [bachD, bachV0Tr] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(bachDs, bachV0Trs))) { // Apply analysis selections on D and V0 bachelors - if (!isDSelected(bachD) || !isV0Selected(bachV0Tr, bachD)) { + uint8_t selFlagD = selctionFlagBachD(bachD); + if (selFlagD == 0) { continue; } - // Retrieve D and V0 informations - float invMassD{0.}; - float invMassD0{0.}; - if (std::abs(bachD.dType()) == 1) - invMassD = bachD.invMassDplus(); - if (bachD.dType() == 2) { - invMassD = bachD.invMassDstar(); - invMassD0 = bachD.invMassD0(); - } - if (bachD.dType() == -2) { - invMassD = bachD.invMassAntiDstar(); - invMassD0 = bachD.invMassD0Bar(); - } - std::array pVecD = {bachD.px(), bachD.py(), bachD.pz()}; - float invMassReso{0.}; - float invMassV0{0.}; - std::array pVecV0Tr = {bachV0Tr.px(), bachV0Tr.py(), bachV0Tr.pz()}; - float ptReso = RecoDecay::pt(RecoDecay::sumOfVec(pVecV0Tr, pVecD)); - switch (channel) { - case DecayChannel::Ds1ToDstarK0s: - invMassV0 = bachV0Tr.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDStar, MassK0Short}); - registry.fill(HIST("hMassDs1"), invMassReso, ptReso); - break; - case DecayChannel::Ds2StarToDplusK0s: - invMassV0 = bachV0Tr.invMassK0s(); - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassK0Short}); - registry.fill(HIST("hMassDs2Star"), invMassReso, ptReso); - break; - case DecayChannel::XcToDplusLambda: - if (bachD.dType() > 0) { - invMassV0 = bachV0Tr.invMassLambda(); - } else { - invMassV0 = bachV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassLambda}); - registry.fill(HIST("hMassXcRes"), invMassReso, ptReso); - break; - case DecayChannel::LambdaDminus: - if (bachD.dType() < 0) { - invMassV0 = bachV0Tr.invMassLambda(); - } else { - invMassV0 = bachV0Tr.invMassAntiLambda(); - } - invMassReso = RecoDecay::m(std::array{pVecD, pVecV0Tr}, std::array{MassDPlus, MassLambda}); - registry.fill(HIST("hMassLambdaDminus"), invMassReso, ptReso); - break; - default: - break; - } - // Fill output table - rowCandidateReso(pVecD[0], pVecD[1], pVecD[2], - pVecV0Tr[0], pVecV0Tr[1], pVecV0Tr[2], - invMassReso, - invMassD, - invMassV0, - bachV0Tr.cpa(), - bachV0Tr.dca(), - bachV0Tr.v0Radius(), - invMassD0); - rowCandidateResoIndices(collision1.globalIndex(), - bachD.globalIndex(), - bachV0Tr.globalIndex()); - if constexpr (fillMl) { - mlScores(bachD.mlScoreBkgMassHypo0(), bachD.mlScorePromptMassHypo0(), bachD.mlScoreNonpromptMassHypo0()); + if constexpr (bachType == BachelorType::V0) { + if (!isV0Selected(bachV0Tr)) { + continue; + } + } else if constexpr (bachType == BachelorType::Track) { + if (!isTrackSelected(bachV0Tr)) { + continue; + } } + fillOutputTables(collision1, bachD, bachV0Tr, selFlagD); } } } // runCandidateCreationMixedEvent // List of Process Functions - void processDs2StarToDplusK0s(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + void process3ProngV0s(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(cands3PrPerCollision, thisCollId); + auto v0sThisColl = candsV0.sliceBy(candsV0PerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, v0sThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0s, "Process Ds2* candidates without ML info", true); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngV0s, "Process resonances decaying in a 3 prong D meson and a V0", true); - void processDs2StarToDplusK0sWithMl(aod::HfRedCollisions const& collisions, - soa::Join const& candsD, - aod::HfRedVzeros const&) + void processDstarV0s(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(candsDstarPerCollision, thisCollId); + auto v0sThisColl = candsV0.sliceBy(candsV0PerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, v0sThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0sWithMl, "Process Ds2* candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarV0s, "Process resonances decaying in a Dstar meson and a V0", false); - void processDs2StarToDplusK0sMixedEvent(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const& candsV0) + void process2PrV0s(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); - } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0sMixedEvent, "Process Ds2Star mixed Event without ML", false); - - void processDs2StarToDplusK0sMixedEventWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const& candsV0) - { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(cands2PrPerCollision, thisCollId); + auto v0sThisColl = candsV0.sliceBy(candsV0PerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, v0sThisColl); + } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs2StarToDplusK0sMixedEventWithMl, "Process Ds2Star mixed Event with ML", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrV0s, "Process resonances decaying in a 2 prong D meson and a V0", false); - void processDs1ToDstarK0s(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + void process3ProngTracks(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(cands3PrPerCollision, thisCollId); + auto trksThisColl = candsTr.sliceBy(candsTrackPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, trksThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0s, "Process Ds1 candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngTracks, "Process resonances decaying in a 3 prong D meson and a Track", false); - void processDs1ToDstarK0sWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const&) + void processDstarTracks(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { for (const auto& collision : collisions) { auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto k0sThisColl = candidatesK0s.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, k0sThisColl); + auto candsDThisColl = candsD.sliceBy(candsDstarPerCollision, thisCollId); + auto trksThisColl = candsTr.sliceBy(candsTrackPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, trksThisColl); } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0sWithMl, "Process Ds1 candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTracks, "Process resonances decaying in a Dstar meson and a Track", false); - void processDs1ToDstarK0sMixedEvent(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const& candsV0) + void process2PrTracks(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); + for (const auto& collision : collisions) { + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD.sliceBy(cands2PrPerCollision, thisCollId); + auto trksThisColl = candsTr.sliceBy(candsTrackPerCollision, thisCollId); + runCandidateCreation(collision, candsDThisColl, trksThisColl); + } } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0sMixedEvent, "Process Ds1 mixed Event without ML", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrTracks, "Process resonances decaying in a 2 prong D meson and a Track", false); - void processDs1ToDstarK0sMixedEventWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const& candsV0) + // Mixed Event Process Functions + void process3ProngV0sMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { - runCandidateCreationMixedEvent(collisions, candsD, candsV0); + runCandidateCreationMixedEvent(collisions, candsD, candsV0); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDs1ToDstarK0sMixedEventWithMl, "Process Ds1 mixed Event with ML", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngV0sMixedEvent, "Process mixed events for resonances decaying in a 3 prong D meson and a V0", false); - void processXcToDplusLambda(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + void processDstarV0sMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsV0); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processXcToDplusLambda, "Process Xc candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarV0sMixedEvent, "Process mixed events for resonances decaying in a Dstar meson and a V0", false); - void processXcToDplusLambdaWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const&) + void process2PrV0sMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + aod::HfRedVzeros const& candsV0) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsV0); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processXcToDplusLambdaWithMl, "Process Xc candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrV0sMixedEvent, "Process mixed events for resonances decaying in a 2 prong D meson and a V0", false); - void processLambdaDminus(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedVzeros const&) + void process3ProngTracksMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed3PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsTr); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processLambdaDminus, "Process LambdaDminus candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process3ProngTracksMixedEvent, "Process mixed events for resonances decaying in a 3 prong D meson and a Track", false); - void processLambdaDminusWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedVzeros const&) - { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto lambdaThisColl = candidatesLambda.sliceBy(candsV0PerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, lambdaThisColl); - } - } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processLambdaDminusWithMl, "Process LambdaDminus candidates with Ml info", false); - void processDstarTrack(aod::HfRedCollisions const& collisions, - aod::HfRed3PrNoTrks const& candsD, - aod::HfRedTrkNoParams const& candidatesTrack) + void processDstarTracksMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRedDstarNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollision, thisCollId); - auto trackThisColl = candidatesTrack.sliceBy(candsTrackPerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, trackThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsTr); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTrack, "Process DStar candidates without Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTracksMixedEvent, "Process mixed events for resonances decaying in a Dstar meson and a Track", false); - void processDstarTrackWithMl(aod::HfRedCollisions const& collisions, - HfRed3PrNoTrksWithMl const& candsD, - aod::HfRedTrkNoParams const& candidatesTrack) + void process2PrTracksMixedEvent(aod::HfRedCollisions const& collisions, + aod::HfRed2PrNoTrks const& candsD, + HfRedTrkNoParams const& candsTr) { - for (const auto& collision : collisions) { - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsD.sliceBy(candsDPerCollisionWithMl, thisCollId); - auto trackThisColl = candidatesTrack.sliceBy(candsTrackPerCollision, thisCollId); - runCandidateCreation(collision, candsDThisColl, trackThisColl); - } + runCandidateCreationMixedEvent(collisions, candsD, candsTr); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, processDstarTrackWithMl, "Process DStar candidates with Ml info", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReduced, process2PrTracksMixedEvent, "Process mixed events for resonances decaying in a 2 prong D meson and a Track", false); }; // struct HfCandidateCreatorCharmResoReduced @@ -632,14 +896,18 @@ struct HfCandidateCreatorCharmResoReducedExpressions { Produces rowResoMcRec; - using CandResoWithIndices = soa::Join; + using CandResoWithIndices2PrV0s = soa::Join; + using CandResoWithIndices2PrTrks = soa::Join; + using CandResoWithIndices3PrV0s = soa::Join; + using CandResoWithIndices3PrTrks = soa::Join; + using CandResoWithIndicesDstarV0s = soa::Join; + using CandResoWithIndicesDstarTrks = soa::Join; // Configurable axis ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis axisInvMassReso{"axisInvMassReso", {400, 0.49f, 0.89f}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {200, 0.14, 0.17}, "inv. mass (D) (GeV/#it{c}^{2})"}; ConfigurableAxis axisInvMassProng1{"axisInvMassProng1", {200, 0.47, 0.53}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; - ConfigurableAxis axisInvMassD0{"axisInvMassD0", {200, 1.65, 2.05}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; ConfigurableAxis axisDebug{"axisDebug", {16, -0.5, 15.5}, "MC debug flag"}; ConfigurableAxis axisOrigin{"axisOrigin", {3, -0.5, 2.5}, "MC origin flag"}; HistogramRegistry registry{"registry"}; @@ -650,64 +918,83 @@ struct HfCandidateCreatorCharmResoReducedExpressions { registry.add("hMassMcMatchedIncomplete", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisInvMassReso, axisPt}}); registry.add("hMassMcUnmatched", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisInvMassReso, axisPt}}); registry.add("hMassMcNoEntry", "Reso MC candidates w.o. entry in MC Reco table;m (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisInvMassReso, axisPt}}); - registry.add("hMassMcMatchedVsBach0Mass", "Reso MC candidates Matched with generate particle;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng0}}); - registry.add("hMassMcUnmatchedVsBach0Mass", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng0}}); - registry.add("hMassMcMatchedVsBach1Mass", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng1}}); - registry.add("hMassMcUnmatchedVsBach1Mass", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassProng1}}); - registry.add("hMassMcMatchedVsD0Mass", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassD0}}); - registry.add("hMassMcUnmatchedVsD0Mass", "Reso MC candidates Matched with generate particle w. Invcomplete decay;m (GeV/#it{c}^{2}); m (GeV/#it{c}^{2})", {HistType::kTH2F, {axisInvMassReso, axisInvMassD0}}); - registry.add("hMassMcUnmatchedVsDebug", "Reso MC candidates NOT Matched with generate particle;m (GeV/#it{c}^{2});debug flag", {HistType::kTH2F, {axisInvMassReso, axisDebug}}); - registry.add("hSparseUnmatchedDebug", "THn for debug of MC matching and Correlated BKG study", HistType::kTHnSparseF, {axisInvMassReso, axisPt, axisInvMassProng0, axisInvMassProng1, axisInvMassD0, axisDebug, axisOrigin}); } /// Fill candidate information at MC reconstruction level - /// \param rowsDV0McRec MC reco information on DPi pairs + /// \param rowsMcRec MC reco information on DPi pairs /// \param candsReso prong global indices of B0 candidates - template - void fillResoMcRec(McRec const& rowsDV0McRec, CandResoWithIndices const& candsReso) + template + void fillResoMcRec(McRec const& rowsMcRec, CandResoWithIndices const& candsReso) { for (const auto& candReso : candsReso) { bool filledMcInfo{false}; - for (const auto& rowDV0McRec : rowsDV0McRec) { + for (const auto& rowDV0McRec : rowsMcRec) { if ((rowDV0McRec.prong0Id() != candReso.prong0Id()) || (rowDV0McRec.prong1Id() != candReso.prong1Id())) { continue; } - rowResoMcRec(rowDV0McRec.flagMcMatchRec(), rowDV0McRec.debugMcRec(), rowDV0McRec.origin(), rowDV0McRec.ptMother()); + rowResoMcRec(rowDV0McRec.flagMcMatchRec(), + rowDV0McRec.flagMcMatchRecD(), + rowDV0McRec.flagMcMatchChanD(), + rowDV0McRec.debugMcRec(), + rowDV0McRec.origin(), + rowDV0McRec.ptGen(), + rowDV0McRec.invMassGen()); filledMcInfo = true; - if (std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0s || std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi || - std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0sOneMu || std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds2StarToDplusK0sOneMu) { + if (std::abs(rowDV0McRec.flagMcMatchRec()) > 0 && + !TESTBIT(rowDV0McRec.debugMcRec(), hf_decay::hf_cand_reso::PartialMatchMc::ResoPartlyMatched)) { registry.fill(HIST("hMassMcMatched"), candReso.invMass(), candReso.pt()); - registry.fill(HIST("hMassMcMatchedVsBach0Mass"), candReso.invMass(), candReso.invMassProng0() - candReso.invMassD0()); - registry.fill(HIST("hMassMcMatchedVsBach1Mass"), candReso.invMass(), candReso.invMassProng1()); - registry.fill(HIST("hMassMcMatchedVsD0Mass"), candReso.invMass(), candReso.invMassD0()); - - } else if (std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToD0NoPiK0sPart || std::abs(rowDV0McRec.flagMcMatchRec()) == DecayTypeMc::Ds1ToDStarK0ToDPlusPi0K0s) { + } else if (std::abs(rowDV0McRec.flagMcMatchRec()) > 0 && + TESTBIT(rowDV0McRec.debugMcRec(), hf_decay::hf_cand_reso::PartialMatchMc::ResoPartlyMatched)) { registry.fill(HIST("hMassMcMatchedIncomplete"), candReso.invMass(), candReso.pt()); } else { registry.fill(HIST("hMassMcUnmatched"), candReso.invMass(), candReso.pt()); - registry.fill(HIST("hMassMcUnmatchedVsBach0Mass"), candReso.invMass(), candReso.invMassProng0() - candReso.invMassD0()); - registry.fill(HIST("hMassMcUnmatchedVsBach1Mass"), candReso.invMass(), candReso.invMassProng1()); - registry.fill(HIST("hMassMcUnmatchedVsD0Mass"), candReso.invMass(), candReso.invMassD0()); - registry.fill(HIST("hMassMcUnmatchedVsDebug"), candReso.invMass(), rowDV0McRec.debugMcRec()); - registry.fill(HIST("hSparseUnmatchedDebug"), candReso.invMass(), candReso.pt(), candReso.invMassProng0() - candReso.invMassD0(), candReso.invMassProng1(), candReso.invMassD0(), rowDV0McRec.debugMcRec(), rowDV0McRec.origin()); } - break; } if (!filledMcInfo) { // protection to get same size tables in case something went wrong: we created a candidate that was not preselected in the D-Pi creator - rowResoMcRec(0, -1, -1, -1.f); + rowResoMcRec(0, 0, 0, 0, 0, -1.f, -1.f); registry.fill(HIST("hMassMcNoEntry"), candReso.invMass(), candReso.pt()); } } } - void processMc(aod::HfMcRecRedDV0s const& rowsDV0McRec, CandResoWithIndices const& candsReso) + void processDstarV0Mc(aod::HfDstarV0McRec const& rowsMcRec, CandResoWithIndicesDstarV0s const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processDstarV0Mc, "Process resonances to Dstar V0 MC", false); + + void processDstarTrackMc(aod::HfDstarTrkMcRec const& rowsMcRec, CandResoWithIndicesDstarTrks const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processDstarTrackMc, "Process resonances to Dstar track MC", false); + + void process2PrV0Mc(aod::Hf2PrV0McRec const& rowsMcRec, CandResoWithIndices2PrV0s const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process2PrV0Mc, "Process resonances to D0 V0 MC", false); + + void process2PrTrackMc(aod::Hf2PrTrkMcRec const& rowsMcRec, CandResoWithIndices2PrTrks const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process2PrTrackMc, "Process resonances to D0 track MC", false); + + void process3PrV0Mc(aod::Hf3PrV0McRec const& rowsMcRec, CandResoWithIndices3PrV0s const& candsReso) + { + fillResoMcRec(rowsMcRec, candsReso); + } + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process3PrV0Mc, "Process resonances to Dplus V0 MC", false); + + void process3PrTrackMc(aod::Hf3PrTrkMcRec const& rowsMcRec, CandResoWithIndices3PrTrks const& candsReso) { - fillResoMcRec(rowsDV0McRec, candsReso); + fillResoMcRec(rowsMcRec, candsReso); } - PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processMc, "Process MC", false); + PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, process3PrTrackMc, "Process resonances to Dplus track MC", false); - void processDummy(CandResoWithIndices const&) {} + void processDummy(aod::HfCandCharmReso const&) {} PROCESS_SWITCH(HfCandidateCreatorCharmResoReducedExpressions, processDummy, "Process dummy", true); }; diff --git a/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx b/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx index 9246748ab48..3246cedb03f 100644 --- a/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateCreatorLbReduced.cxx @@ -14,22 +14,34 @@ /// /// \author Biao Zhang , Heidelberg University -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/Utils/utilsTrkCandHf.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; @@ -86,7 +98,7 @@ struct HfCandidateCreatorLbReduced { df2.setWeightedFinalPCA(useWeightedFinalPCA); // histograms - registry.add("hMassLambdaLbToLcPi", "2-prong candidates;inv. mass (#Lambda_{b}^{0} #rightarrow #Lambda_{c}^{#plus}#pi^{#minus} #rightarrow pK^{#minus}#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 3., 8.}}}); + registry.add("hMassLambdaB0ToLcPi", "2-prong candidates;inv. mass (#Lambda_{b}^{0} #rightarrow #Lambda_{c}^{#plus}#pi^{#minus} #rightarrow pK^{#minus}#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 3., 8.}}}); registry.add("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); registry.add("hEvents", "Events;;entries", HistType::kTH1F, {{1, 0.5, 1.5}}); diff --git a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx index 5ddf1bcd1a8..53609fc66c9 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorB0ToDPiReduced.cxx @@ -15,22 +15,37 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Fabrizio Grosa , CERN -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseB0ToDPi.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx index b11b65a39fb..3e1554fdb2e 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorBplusToD0PiReduced.cxx @@ -14,22 +14,37 @@ /// /// \author Antonio Palasciano , Università degli Studi di Bari -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseBplusToD0PiReduced.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx index 7864ee493b7..99e71e34acd 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorBsToDsPiReduced.cxx @@ -14,22 +14,37 @@ /// /// \author Fabio Catalano , CERN -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseBsToDsPi.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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; diff --git a/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx b/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx index a4093a9340a..dbe86c4905d 100644 --- a/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/candidateSelectorLbToLcPiReduced.cxx @@ -14,22 +14,37 @@ /// /// \author Biao Zhang , Heidelberg University -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseLbToLcPi.h" #include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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; diff --git a/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx b/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx index ea9450eca08..90360a29cc0 100644 --- a/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx +++ b/PWGHF/D2H/TableProducer/converterReduced3ProngsMl.cxx @@ -14,12 +14,12 @@ /// /// \author Fabrizio Grosa , CERN -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - #include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx b/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx index 2d4036247f5..d1bf2d4e47c 100644 --- a/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx +++ b/PWGHF/D2H/TableProducer/converterReducedHadronDausPid.cxx @@ -14,12 +14,13 @@ /// /// \author Biao Zhang , Heidelberg University -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - #include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -29,21 +30,21 @@ struct HfConverterReducedHadronDausPid { Produces hfRedPidDau1s; Produces hfRedPidDau2s; - using HfRedPidDaus2Prong = soa::Join; - using HfRedPidDaus3Prong = soa::Join; + using HfRedPidDaus2Prong = soa::Join; + using HfRedPidDaus3Prong = soa::Join; void process2Prongs(HfRedPidDaus2Prong::iterator const& hfCandPidProngs) { - hfRedPidDau0s(hfCandPidProngs.nSigTpcPi0(), hfCandPidProngs.nSigTofPi0(), hfCandPidProngs.nSigTpcKa0(), hfCandPidProngs.nSigTofKa0(), -999.f, -999.f, hfCandPidProngs.hasTOFProng0(), hfCandPidProngs.hasTPCProng0()); - hfRedPidDau1s(hfCandPidProngs.nSigTpcPi1(), hfCandPidProngs.nSigTofPi1(), hfCandPidProngs.nSigTpcKa1(), hfCandPidProngs.nSigTofKa1(), -999.f, -999.f, hfCandPidProngs.hasTOFProng1(), hfCandPidProngs.hasTPCProng1()); + hfRedPidDau0s(hfCandPidProngs.tpcNSigmaPiProng0(), hfCandPidProngs.tofNSigmaPiProng0(), hfCandPidProngs.tpcNSigmaKaProng0(), hfCandPidProngs.tofNSigmaKaProng0(), -999.f, -999.f, hfCandPidProngs.hasTOFProng0(), hfCandPidProngs.hasTPCProng0()); + hfRedPidDau1s(hfCandPidProngs.tpcNSigmaPiProng1(), hfCandPidProngs.tofNSigmaPiProng1(), hfCandPidProngs.tpcNSigmaKaProng1(), hfCandPidProngs.tofNSigmaKaProng1(), -999.f, -999.f, hfCandPidProngs.hasTOFProng1(), hfCandPidProngs.hasTPCProng1()); } - PROCESS_SWITCH(HfConverterReducedHadronDausPid, process2Prongs, "Produce PID tables for 2-prong candidates", true); + PROCESS_SWITCH(HfConverterReducedHadronDausPid, process2Prongs, "Produce PID tables for 2-prong candidates", false); void process3Prongs(HfRedPidDaus3Prong::iterator const& hfCandPidProngs) { - hfRedPidDau0s(hfCandPidProngs.nSigTpcPi0(), hfCandPidProngs.nSigTofPi0(), hfCandPidProngs.nSigTpcKa0(), hfCandPidProngs.nSigTofKa0(), -999.f, -999.f, hfCandPidProngs.hasTOFProng0(), hfCandPidProngs.hasTPCProng0()); - hfRedPidDau1s(hfCandPidProngs.nSigTpcPi1(), hfCandPidProngs.nSigTofPi1(), hfCandPidProngs.nSigTpcKa1(), hfCandPidProngs.nSigTofKa1(), -999.f, -999.f, hfCandPidProngs.hasTOFProng1(), hfCandPidProngs.hasTPCProng1()); - hfRedPidDau2s(hfCandPidProngs.nSigTpcPi2(), hfCandPidProngs.nSigTofPi2(), hfCandPidProngs.nSigTpcKa2(), hfCandPidProngs.nSigTofKa2(), -999.f, -999.f, hfCandPidProngs.hasTOFProng2(), hfCandPidProngs.hasTPCProng2()); + hfRedPidDau0s(hfCandPidProngs.tpcNSigmaPiProng0(), hfCandPidProngs.tofNSigmaPiProng0(), hfCandPidProngs.tpcNSigmaKaProng0(), hfCandPidProngs.tofNSigmaKaProng0(), -999.f, -999.f, hfCandPidProngs.hasTOFProng0(), hfCandPidProngs.hasTPCProng0()); + hfRedPidDau1s(hfCandPidProngs.tpcNSigmaPiProng1(), hfCandPidProngs.tofNSigmaPiProng1(), hfCandPidProngs.tpcNSigmaKaProng1(), hfCandPidProngs.tofNSigmaKaProng1(), -999.f, -999.f, hfCandPidProngs.hasTOFProng1(), hfCandPidProngs.hasTPCProng1()); + hfRedPidDau2s(hfCandPidProngs.tpcNSigmaPiProng2(), hfCandPidProngs.tofNSigmaPiProng2(), hfCandPidProngs.tpcNSigmaKaProng2(), hfCandPidProngs.tofNSigmaKaProng2(), -999.f, -999.f, hfCandPidProngs.hasTOFProng2(), hfCandPidProngs.hasTPCProng2()); } PROCESS_SWITCH(HfConverterReducedHadronDausPid, process3Prongs, "Produce PID tables for 3-prong candidates", true); }; diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx index d03f8d9eda0..0b73b385893 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmHadPiReduced.cxx @@ -18,40 +18,73 @@ /// \author Fabio Catalano , CERN /// \author Biao Zhang , Heidelberg University -#include -#include -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Qvectors.h" - +#include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/D2H/Utils/utilsRedDataFormat.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsMcMatching.h" #include "PWGHF/Utils/utilsTrkCandHf.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/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.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 +#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::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::hf_decay; using namespace o2::hf_trkcandsel; enum Event : uint8_t { @@ -65,7 +98,8 @@ enum DecayChannel : uint8_t { B0ToDminusPi = 0, BplusToD0barPi, BsToDsminusPi, - LbToLcplusPi + LbToLcplusPi, + B0ToDstarPi }; enum WrongCollisionType : uint8_t { @@ -78,51 +112,67 @@ enum WrongCollisionType : uint8_t { struct HfDataCreatorCharmHadPiReduced { // Produces AOD tables to store track information // collision related tables - Produces hfReducedCollision; - Produces hfReducedCollCentrality; - Produces hfReducedQvector; - Produces hfReducedCollExtra; - Produces hfCollisionCounter; - // Pi bachelor related tables - Produces hfTrackPion; - Produces hfTrackCovPion; - Produces hfTrackPidPion; - // charm hadron related tables - Produces hfCand2Prong; - Produces hfCand2ProngCov; - Produces hfCand2ProngMl; - Produces hfCand3Prong; - Produces hfCand3ProngCov; - Produces hfCand3ProngMl; - // PID tables for charm-hadron candidate daughter tracks - Produces hfCandPidProng0; - Produces hfCandPidProng1; - Produces hfCandPidProng2; - - // B-hadron config and MC related tables - Produces rowCandidateConfigB0; - Produces rowHfDPiMcRecReduced; - Produces rowHfDPiMcCheckReduced; - Produces rowHfB0McGenReduced; - - Produces rowCandidateConfigBplus; - Produces rowHfD0PiMcRecReduced; - Produces rowHfD0PiMcCheckReduced; - Produces rowHfBpMcGenReduced; - - Produces rowCandidateConfigBs; - Produces rowHfDsPiMcRecReduced; - Produces rowHfDsPiMcCheckReduced; - Produces rowHfBsMcGenReduced; - - Produces rowCandidateConfigLb; - Produces rowHfLcPiMcRecReduced; - Produces rowHfLcPiMcCheckReduced; - Produces rowHfLbMcGenReduced; - + struct : ProducesGroup { + Produces hfReducedCollision; + Produces hfReducedCollCentrality; + Produces hfReducedQvector; + Produces hfReducedCollExtra; + Produces hfCollisionCounter; + // Pi bachelor related tables + Produces hfTrackPion; + Produces hfTrackCovPion; + Produces hfTrackPidPion; + // charm hadron related tables + Produces hfCand2Prong; + Produces hfCand2ProngCov; + Produces hfCand2ProngMl; + Produces hfCand3Prong; + Produces hfCand3ProngCov; + Produces hfCand3ProngMl; + // D* soft pion related tables + Produces hfTrackSoftPion; + Produces hfTrackCovSoftPion; + // PID tables for charm-hadron candidate daughter tracks + Produces hfCandPidProng0; + Produces hfCandPidProng1; + Produces hfCandPidProng2; + + // B-hadron config and MC related tables + Produces rowCandidateConfigB0; + Produces rowHfDPiMcRecReduced; + Produces rowHfDPiMcCheckReduced; + Produces rowHfB0McGenReduced; + + Produces rowCandidateConfigBplus; + Produces rowHfD0PiMcRecReduced; + Produces rowHfD0PiMcCheckReduced; + Produces rowHfBpMcGenReduced; + + Produces rowCandidateConfigBs; + Produces rowHfDsPiMcRecReduced; + Produces rowHfDsPiMcCheckReduced; + Produces rowHfBsMcGenReduced; + + Produces rowCandidateConfigLb; + Produces rowHfLcPiMcRecReduced; + Produces rowHfLcPiMcCheckReduced; + Produces rowHfLbMcGenReduced; + } tables; + + // generic configurables + struct : o2::framework::ConfigurableGroup { + // event selection + Configurable skipRejectedCollisions{"skipRejectedCollisions", true, "skips collisions rejected by the event selection, instead of flagging only"}; + // magnetic field setting from CCDB + 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)"}; + // pair selection + Configurable invMassWindowCharmHadPi{"invMassWindowCharmHadPi", 0.3, "invariant-mass window for CharmHad-Pi pair preselections (GeV/c2)"}; + // MC extra + Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "flag to enable MC checks on decay type"}; + } configs; // vertexing struct : o2::framework::ConfigurableGroup { - // Configurable bz{"bz", 5., "magnetic field"}; Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; @@ -139,24 +189,19 @@ struct HfDataCreatorCharmHadPiReduced { Configurable> binsPtPion{"binsPtPion", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for pion DCA XY pT-dependent cut"}; Configurable> cutsTrackPionDCA{"cutsTrackPionDCA", {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 pions"}; } trackPionConfigurations; - Configurable invMassWindowCharmHadPi{"invMassWindowCharmHadPi", 0.3, "invariant-mass window for CharmHad-Pi pair preselections (GeV/c2)"}; - + // HF flags struct : o2::framework::ConfigurableGroup { Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D+"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds"}; Configurable selectionFlagD0{"selectionFlagD0", 1, "Selection Flag for D0"}; Configurable selectionFlagD0bar{"selectionFlagD0bar", 1, "Selection Flag for D0bar"}; Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; + Configurable selectionFlagDstar{"selectionFlagDstar", true, "Selection Flag for D* decay to D0 Pi"}; } hfflagConfigurations; - // magnetic field setting from CCDB - 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)"}; - - // MC extra - Configurable checkDecayTypeMc{"checkDecayTypeMc", false, "flag to enable MC checks on decay type"}; HfHelper hfHelper; o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; // CCDB service Service ccdb; @@ -166,13 +211,13 @@ struct HfDataCreatorCharmHadPiReduced { // O2DatabasePDG service Service pdg; - double massPi{0.}; double massC{0.}; double massB{0.}; double invMass2ChHadPiMin{0.}; double invMass2ChHadPiMax{0.}; double bz{0.}; static constexpr std::size_t NDaughtersDs{2u}; + static constexpr std::size_t NDaughtersDstar{2u}; bool isHfCandBhadConfigFilled = false; // Fitter to redo D-vertex to get extrapolated daughter tracks (2/3-prong vertex filter) @@ -191,64 +236,78 @@ struct HfDataCreatorCharmHadPiReduced { using CandsD0FilteredWithMl = soa::Filtered>; using CandsLcFiltered = soa::Filtered>; using CandsLcFilteredWithMl = soa::Filtered>; + using CandsDstarFiltered = soa::Filtered>; + using CandsDstarFilteredWithMl = soa::Filtered>; using CollisionsWCent = soa::Join; using CollisionsWCentAndMcLabels = soa::Join; using CollisionsWCentAndQvectors = soa::Join; + using BCsInfo = soa::Join; Filter filterSelectDplusCandidates = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= hfflagConfigurations.selectionFlagDplus); Filter filterSelectDsCandidates = (aod::hf_sel_candidate_ds::isSelDsToKKPi >= hfflagConfigurations.selectionFlagDs || aod::hf_sel_candidate_ds::isSelDsToPiKK >= hfflagConfigurations.selectionFlagDs); Filter filterSelectDzeroCandidates = (aod::hf_sel_candidate_d0::isSelD0 >= hfflagConfigurations.selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= hfflagConfigurations.selectionFlagD0bar); Filter filterSelectLcCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= hfflagConfigurations.selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= hfflagConfigurations.selectionFlagLc); - - Preslice candsDplusPerCollision = aod::track_association::collisionId; - Preslice candsDplusPerCollisionWithMl = aod::track_association::collisionId; - Preslice candsDsPerCollision = aod::track_association::collisionId; - Preslice candsDsPerCollisionWithMl = aod::track_association::collisionId; - Preslice candsD0PerCollision = aod::track_association::collisionId; - Preslice candsD0PerCollisionWithMl = aod::track_association::collisionId; - Preslice candsLcPerCollision = aod::track_association::collisionId; - Preslice candsLcPerCollisionWithMl = aod::track_association::collisionId; - Preslice trackIndicesPerCollision = aod::track_association::collisionId; - PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; - - std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs, hCandidatesLc; + Filter filterSelectDstarCandidates = (aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == hfflagConfigurations.selectionFlagDstar); + + struct : PresliceGroup { + Preslice candsDplusPerCollision = aod::track_association::collisionId; + Preslice candsDplusPerCollisionWithMl = aod::track_association::collisionId; + Preslice candsDsPerCollision = aod::track_association::collisionId; + Preslice candsDsPerCollisionWithMl = aod::track_association::collisionId; + Preslice candsD0PerCollision = aod::track_association::collisionId; + Preslice candsD0PerCollisionWithMl = aod::track_association::collisionId; + Preslice candsLcPerCollision = aod::track_association::collisionId; + Preslice candsLcPerCollisionWithMl = aod::track_association::collisionId; + Preslice candsDstarPerCollision = aod::track_association::collisionId; + Preslice candsDstarPerCollisionWithMl = aod::track_association::collisionId; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + } preslices; + + std::shared_ptr hCandidatesD0, hCandidatesDPlus, hCandidatesDs, hCandidatesLc, hCandidatesDstar; HistogramRegistry registry{"registry"}; std::array arrPDGResonantDsPhiPi = {kPhi, kPiPlus}; // Ds± → Phi π± std::array arrPDGResonantDKstarK = {kK0Star892, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± - void init(InitContext const&) + void init(InitContext& initContext) { - std::array doProcess = {doprocessDplusPiData, doprocessDplusPiDataWithMl, doprocessDplusPiMc, doprocessDplusPiMcWithMl, - doprocessDsPiData, doprocessDsPiDataWithMl, doprocessDsPiMc, doprocessDsPiMcWithMl, - doprocessD0PiData, doprocessD0PiDataWithMl, doprocessD0PiMc, doprocessD0PiMcWithMl, - doprocessLcPiData, doprocessLcPiDataWithMl, doprocessLcPiMc, doprocessLcPiMcWithMl}; + std::array doProcess = {doprocessDplusPiData, doprocessDplusPiDataWithMl, doprocessDplusPiDataWithQvec, doprocessDplusPiDataWithMlAndQvec, doprocessDplusPiMc, doprocessDplusPiMcWithMl, + doprocessDsPiData, doprocessDsPiDataWithMl, doprocessDsPiDataWithQvec, doprocessDsPiDataWithMlAndQvec, doprocessDsPiMc, doprocessDsPiMcWithMl, + doprocessD0PiData, doprocessD0PiDataWithMl, doprocessD0PiDataWithQvec, doprocessD0PiDataWithMlAndQvec, doprocessD0PiMc, doprocessD0PiMcWithMl, + doprocessLcPiData, doprocessLcPiDataWithMl, doprocessLcPiMc, doprocessLcPiMcWithMl, + doprocessDstarPiData, doprocessDstarPiDataWithMl, doprocessDstarPiDataWithQvec, doprocessDstarPiDataWithMlAndQvec, doprocessDstarPiMc, doprocessDstarPiMcWithMl}; if (std::accumulate(doProcess.begin(), doProcess.end(), 0) != 1) { LOGP(fatal, "One and only one process function can be enabled at a time, please fix your configuration!"); } // invariant-mass window cut - massPi = MassPiPlus; - if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { + if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiDataWithQvec || doprocessDplusPiDataWithMlAndQvec || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { massC = MassDMinus; massB = MassB0; - } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { + } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiDataWithQvec || doprocessDsPiDataWithMlAndQvec || doprocessDsPiMc || doprocessDsPiMcWithMl) { massC = MassDS; massB = MassBS; - } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { + } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiDataWithQvec || doprocessD0PiDataWithMlAndQvec || doprocessD0PiMc || doprocessD0PiMcWithMl) { massC = MassD0; massB = MassBPlus; } else if (doprocessLcPiData || doprocessLcPiDataWithMl || doprocessLcPiMc || doprocessLcPiMcWithMl) { massC = MassLambdaCPlus; massB = MassLambdaB0; + } else if (doprocessDstarPiData || doprocessDstarPiDataWithMl || doprocessDstarPiDataWithQvec || doprocessDstarPiDataWithMlAndQvec || doprocessDstarPiMc || doprocessDstarPiMcWithMl) { + massC = MassDStar; + massB = MassB0; } - invMass2ChHadPiMin = (massB - invMassWindowCharmHadPi) * (massB - invMassWindowCharmHadPi); - invMass2ChHadPiMax = (massB + invMassWindowCharmHadPi) * (massB + invMassWindowCharmHadPi); + invMass2ChHadPiMin = (massB - configs.invMassWindowCharmHadPi) * (massB - configs.invMassWindowCharmHadPi); + invMass2ChHadPiMax = (massB + configs.invMassWindowCharmHadPi) * (massB + configs.invMassWindowCharmHadPi); // Initialize fitter - if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl || - doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl || doprocessLcPiData || doprocessLcPiDataWithMl || doprocessLcPiMc || doprocessLcPiMcWithMl) { + if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiDataWithQvec || doprocessDplusPiDataWithMlAndQvec || doprocessDplusPiMc || doprocessDplusPiMcWithMl || + doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiDataWithQvec || doprocessDsPiDataWithMlAndQvec || doprocessDsPiMc || doprocessDsPiMcWithMl || + doprocessLcPiData || doprocessLcPiDataWithMl || doprocessLcPiMc || doprocessLcPiMcWithMl || + doprocessDstarPiData || doprocessDstarPiDataWithMl || doprocessDstarPiDataWithQvec || doprocessDstarPiDataWithMlAndQvec || doprocessDstarPiMc || doprocessDstarPiMcWithMl) { df3.setPropagateToPCA(vertexConfigurations.propagateToPCA); df3.setMaxR(vertexConfigurations.maxR); df3.setMaxDZIni(vertexConfigurations.maxDZIni); @@ -257,7 +316,7 @@ struct HfDataCreatorCharmHadPiReduced { df3.setUseAbsDCA(vertexConfigurations.useAbsDCA); df3.setWeightedFinalPCA(vertexConfigurations.useWeightedFinalPCA); df3.setMatCorrType(noMatCorr); - } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { + } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiDataWithQvec || doprocessD0PiDataWithMlAndQvec || doprocessD0PiMc || doprocessD0PiMcWithMl) { df2.setPropagateToPCA(vertexConfigurations.propagateToPCA); df2.setMaxR(vertexConfigurations.maxR); df2.setMaxDZIni(vertexConfigurations.maxDZIni); @@ -269,7 +328,7 @@ struct HfDataCreatorCharmHadPiReduced { } // Configure CCDB access - ccdb->setURL(ccdbUrl); + ccdb->setURL(configs.ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); runNumber = 0; @@ -288,16 +347,16 @@ struct HfDataCreatorCharmHadPiReduced { std::string charmHadTitle = ""; std::string histMassTitle = ""; - if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { + if (doprocessDplusPiData || doprocessDplusPiDataWithMl || doprocessDplusPiDataWithQvec || doprocessDplusPiDataWithMlAndQvec || doprocessDplusPiMc || doprocessDplusPiMcWithMl) { charmHadTitle = "D^{#plus}"; histMassTitle = "Dplus"; registry.add("hMassDplus", "D^{#plus} candidates; #it{M}(K#pi#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); - } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiMc || doprocessDsPiMcWithMl) { + } else if (doprocessDsPiData || doprocessDsPiDataWithMl || doprocessDsPiDataWithQvec || doprocessDsPiDataWithMlAndQvec || doprocessDsPiMc || doprocessDsPiMcWithMl) { charmHadTitle = "D_{s}^{#plus}"; histMassTitle = "Ds"; registry.add("hMassDsToKKPi", "D_{s}^{#plus} to KKpi candidates; #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); registry.add("hMassDsToPiKK", "D_{s}^{#plus} to piKK candidates; #it{M}(KK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); - } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiMc || doprocessD0PiMcWithMl) { + } else if (doprocessD0PiData || doprocessD0PiDataWithMl || doprocessD0PiDataWithQvec || doprocessD0PiDataWithMlAndQvec || doprocessD0PiMc || doprocessD0PiMcWithMl) { charmHadTitle = "D^{0}"; histMassTitle = "D0"; registry.add("hMassD0", "D^{0} candidates; #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); @@ -305,7 +364,12 @@ struct HfDataCreatorCharmHadPiReduced { } else if (doprocessLcPiData || doprocessLcPiDataWithMl || doprocessLcPiMc || doprocessLcPiMcWithMl) { charmHadTitle = "#Lambda_{c}^{+}"; histMassTitle = "Lc"; - registry.add("hMassLc", "#Lambda_{c}^{+} candidates; #it{M}(pK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); + registry.add("hMassLcToPKPi", "#Lambda_{c}^{+} to KKpi candidates; #it{M}(pK#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); + registry.add("hMassLcToPiKP", "#Lambda_{c}^{+} to piKK candidates; #it{M}(#piKp) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 5.}}}); + } else if (doprocessDstarPiData || doprocessDstarPiDataWithMl || doprocessDstarPiDataWithQvec || doprocessDstarPiDataWithMlAndQvec || doprocessDstarPiMc || doprocessDstarPiMcWithMl) { + charmHadTitle = "D^{*}"; + histMassTitle = "Dstar"; + registry.add("hMassDstarToD0Pi", "D^{*} candidates; #it{M}(K#pi#pi) - #it{M}(K#pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 0., 1.}}}); } registry.add(Form("hPt%s", histMassTitle.data()), Form("%s candidates candidates;%s candidate #it{p}_{T} (GeV/#it{c});entries", charmHadTitle.data(), charmHadTitle.data()), {HistType::kTH1D, {{100, 0., 10.}}}); @@ -317,14 +381,30 @@ struct HfDataCreatorCharmHadPiReduced { hCandidatesDPlus = registry.add("hCandidatesDPlus", "Dplus candidate counter", {HistType::kTH1D, {axisCands}}); hCandidatesDs = registry.add("hCandidatesDs", "Ds candidate counter", {HistType::kTH1D, {axisCands}}); hCandidatesLc = registry.add("hCandidatesLc", "Lc candidate counter", {HistType::kTH1D, {axisCands}}); + hCandidatesDstar = registry.add("hCandidatesDstar", "Dstar candidate counter", {HistType::kTH1D, {axisCands}}); setLabelHistoCands(hCandidatesD0); setLabelHistoCands(hCandidatesDPlus); setLabelHistoCands(hCandidatesDs); setLabelHistoCands(hCandidatesLc); + setLabelHistoCands(hCandidatesDstar); // init HF event selection helper hfEvSel.init(registry); + if (doprocessDplusPiMc || doprocessDplusPiMcWithMl || + doprocessDsPiMc || doprocessDsPiMcWithMl || + doprocessD0PiMc || doprocessD0PiMcWithMl || + doprocessLcPiMc || doprocessLcPiMcWithMl || + doprocessDstarPiMc || doprocessDstarPiMcWithMl) { + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-data-creator-charm-had-pi-reduced") == 0) { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } + } } /// Pion selection (D Pi <-- B0) @@ -341,7 +421,7 @@ struct HfDataCreatorCharmHadPiReduced { return false; } // minimum pT and eta selection - if (trackParCovPion.getPt() < trackPionConfigurations.ptPionMin || std::abs(trackParCovPion.getEta()) > trackPionConfigurations.etaPionMax || !isSelectedTrackDCA(trackParCovPion, dcaPion)) { + if (trackParCovPion.getPt() < trackPionConfigurations.ptPionMin || std::abs(trackParCovPion.getEta()) > trackPionConfigurations.etaPionMax || !isSelectedTrackDCA(trackParCovPion, dcaPion, trackPionConfigurations.binsPtPion, trackPionConfigurations.cutsTrackPionDCA)) { return false; } // reject pions that are charm-hadron daughters @@ -354,27 +434,6 @@ struct HfDataCreatorCharmHadPiReduced { return true; } - /// Single-track cuts for pions on dcaXY - /// \param trackPar is the track parametrisation - /// \param dca is the 2-D array with track DCAs - /// \return true if track passes all cuts - template - bool isSelectedTrackDCA(const T1& trackPar, const T2& dca) - { - auto pTBinTrack = findBin(trackPionConfigurations.binsPtPion, trackPar.getPt()); - if (pTBinTrack == -1) { - return false; - } - - if (std::abs(dca[0]) < trackPionConfigurations.cutsTrackPionDCA->get(pTBinTrack, "min_dcaxytoprimary")) { - return false; // minimum DCAxy - } - if (std::abs(dca[0]) > trackPionConfigurations.cutsTrackPionDCA->get(pTBinTrack, "max_dcaxytoprimary")) { - return false; // maximum DCAxy - } - return true; - } - /// Calculates the index of the collision with the maximum number of contributions. ///\param collisions are the collisions to search through. ///\return The index of the collision with the maximum number of contributions. @@ -429,6 +488,7 @@ struct HfDataCreatorCharmHadPiReduced { // we check the MC matching to be stored int8_t sign{0}; + int8_t signD{0}; int8_t flag{0}; int8_t flagWrongCollision{WrongCollisionType::None}; int8_t debug{0}; @@ -463,7 +523,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // B0 → Ds- π+ → (K- K+ π-) π+ if (!flag) { indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kB0, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); @@ -551,9 +611,9 @@ struct HfDataCreatorCharmHadPiReduced { } } } - rowHfDPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); + tables.rowHfDPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); } - rowHfDPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); + tables.rowHfDPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); } else if constexpr (decChannel == DecayChannel::BsToDsminusPi) { // Bs → Ds- π+ → (K- K+ π-) π+ auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kBS, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); @@ -590,7 +650,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // B0 → Ds- π+ → (K- K+ π-) π+ if (!flag) { indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kB0, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); @@ -706,9 +766,9 @@ struct HfDataCreatorCharmHadPiReduced { } } } - rowHfDsPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); + tables.rowHfDsPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); } - rowHfDsPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); + tables.rowHfDsPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { // B+ → D0(bar) π+ → (K+ π-) π+ auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{+kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); @@ -730,7 +790,7 @@ struct HfDataCreatorCharmHadPiReduced { } } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { if (!flag) { // B+ → D0(bar) K+ → (K+ π-) K+ indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{+kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); @@ -803,9 +863,9 @@ struct HfDataCreatorCharmHadPiReduced { } } } - rowHfD0PiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2); + tables.rowHfD0PiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2); } - rowHfD0PiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); + tables.rowHfD0PiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); } else if constexpr (decChannel == DecayChannel::LbToLcplusPi) { // Lb → Lc+ π- → (p K- π+) π- auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kLambdaB0, std::array{+kProton, -kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); @@ -829,7 +889,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // Lb → Lc+ K- → (p K- π+) K- if (!flag) { indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kLambdaB0, std::array{+kProton, -kKPlus, +kPiPlus, -kKPlus}, true, &sign, 3); @@ -907,23 +967,67 @@ struct HfDataCreatorCharmHadPiReduced { } } } - rowHfLcPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); + tables.rowHfLcPiMcCheckReduced(pdgCodeBeautyMother, pdgCodeCharmMother, pdgCodeProng0, pdgCodeProng1, pdgCodeProng2, pdgCodeProng3); + } + tables.rowHfLcPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); + } else if constexpr (decChannel == DecayChannel::B0ToDstarPi) { + // B0 → D*+ π- → (D0 π+) π- → (K- π+ π+) π- + auto indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kB0, std::array{+kKPlus, -kPiPlus, -kPiPlus, +kPiPlus}, true, &sign, 4); + if (indexRec > -1) { + // D*+ → (D0 π+) → K- π+ π+ + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, +Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signD, 3); + if (indexRec > -1) { + std::vector arrDaughDstarIndex; + RecoDecay::getDaughters(particlesMc.rawIteratorAt(indexRec), &arrDaughDstarIndex, std::array{0}, 1); + if (arrDaughDstarIndex.size() == NDaughtersDstar) { + bool matchD0{0}; + for (auto iProng = 0u; iProng < arrDaughDstarIndex.size(); ++iProng) { + auto daughI = particlesMc.rawIteratorAt(arrDaughDstarIndex[iProng]); + if (std::abs(daughI.pdgCode()) == Pdg::kD0) { + matchD0 = RecoDecay::isMatchedMCGen(particlesMc, daughI, +Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD, 2); + } + } + if (matchD0) { + flag = sign * BIT(hf_cand_b0::DecayTypeMc::B0ToDstarPiToD0PiPiToKPiPiPi); + } else { + debug = 1; + LOGF(debug, "B0 decays in the expected final state but the condition on D* intermediate state is not fulfilled"); + } + } + } else { + debug = 1; + LOGF(debug, "B0 decays in the expected final state but the condition on the intermediate state is not fulfilled"); + } + + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersB.back().template mcParticle_as(), Pdg::kB0, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); + } } - rowHfLcPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); + tables.rowHfDPiMcRecReduced(indexHfCandCharm, selectedTracksPion[vecDaughtersB.back().globalIndex()], flag, flagWrongCollision, debug, motherPt); } } - template + template void runDataCreation(Coll const& collision, CCharmCands const& candsC, aod::TrackAssoc const& trackIndices, TTracks const&, PParticles const& particlesMc, uint64_t const& indexCollisionMaxNumContrib, - aod::BCsWithTimestamps const&) + BBCs const&) { + registry.fill(HIST("hEvents"), 1 + Event::Processed); + float centrality = -1.f; + auto hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (configs.skipRejectedCollisions && hfRejMap != 0) { + return; + } + // helpers for ReducedTables filling - int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; + int indexHfReducedCollision = tables.hfReducedCollision.lastIndex() + 1; // std::map where the key is the track.globalIndex() and // the value is the track index in the table of the selected pions std::map selectedTracksPion; @@ -934,10 +1038,10 @@ struct HfDataCreatorCharmHadPiReduced { // Set the magnetic field from ccdb. // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, // but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; - o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, bc.timestamp()); + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(configs.ccdbPathGrpMag, bc.timestamp()); if (grpo == nullptr) { LOGF(fatal, "Run 3 GRP object (type o2::parameters::GRPMagField) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); } @@ -953,13 +1057,13 @@ struct HfDataCreatorCharmHadPiReduced { int indexHfCandCharm{-1}; float invMassC0{-1.f}, invMassC1{-1.f}; if constexpr (decChannel == DecayChannel::B0ToDminusPi) { - indexHfCandCharm = hfCand3Prong.lastIndex() + 1; + indexHfCandCharm = tables.hfCand3Prong.lastIndex() + 1; invMassC0 = hfHelper.invMassDplusToPiKPi(candC); registry.fill(HIST("hMassDplus"), invMassC0); registry.fill(HIST("hPtDplus"), candC.pt()); registry.fill(HIST("hCpaDplus"), candC.cpa()); } else if constexpr (decChannel == DecayChannel::BsToDsminusPi) { - indexHfCandCharm = hfCand3Prong.lastIndex() + 1; + indexHfCandCharm = tables.hfCand3Prong.lastIndex() + 1; if (candC.isSelDsToKKPi() >= hfflagConfigurations.selectionFlagDs) { invMassC0 = hfHelper.invMassDsToKKPi(candC); registry.fill(HIST("hMassDsToKKPi"), invMassC0); @@ -971,7 +1075,7 @@ struct HfDataCreatorCharmHadPiReduced { registry.fill(HIST("hPtDs"), candC.pt()); registry.fill(HIST("hCpaDs"), candC.cpa()); } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { - indexHfCandCharm = hfCand2Prong.lastIndex() + 1; + indexHfCandCharm = tables.hfCand2Prong.lastIndex() + 1; if (candC.isSelD0() >= hfflagConfigurations.selectionFlagD0) { invMassC0 = hfHelper.invMassD0ToPiK(candC); registry.fill(HIST("hMassD0"), invMassC0); @@ -983,7 +1087,7 @@ struct HfDataCreatorCharmHadPiReduced { registry.fill(HIST("hPtD0"), candC.pt()); registry.fill(HIST("hCpaD0"), candC.cpa()); } else if constexpr (decChannel == DecayChannel::LbToLcplusPi) { - indexHfCandCharm = hfCand3Prong.lastIndex() + 1; + indexHfCandCharm = tables.hfCand3Prong.lastIndex() + 1; if (candC.isSelLcToPKPi() >= hfflagConfigurations.selectionFlagLc) { invMassC0 = hfHelper.invMassLcToPKPi(candC); registry.fill(HIST("hMassLcToPKPi"), invMassC0); @@ -994,8 +1098,17 @@ struct HfDataCreatorCharmHadPiReduced { } registry.fill(HIST("hPtLc"), candC.pt()); registry.fill(HIST("hCpaLc"), candC.cpa()); + } else if constexpr (decChannel == DecayChannel::B0ToDstarPi) { + indexHfCandCharm = tables.hfCand3Prong.lastIndex() + 1; + if (candC.signSoftPi() > 0) { + invMassC0 = candC.invMassDstar() - candC.invMassD0(); + } else { + invMassC0 = candC.invMassAntiDstar() - candC.invMassD0Bar(); + } + registry.fill(HIST("hMassDstarToD0Pi"), invMassC0); + registry.fill(HIST("hPtDstar"), candC.pt()); + registry.fill(HIST("hCpaDstar"), candC.cpaD0()); } - bool fillHfCandCharm = false; std::vector charmHadDauTracks{candC.template prong0_as(), candC.template prong1_as()}; @@ -1020,8 +1133,12 @@ struct HfDataCreatorCharmHadPiReduced { } // third track, if it's a 3-prong - if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi || decChannel == DecayChannel::LbToLcplusPi) { - charmHadDauTracks.push_back(candC.template prong2_as()); + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi || decChannel == DecayChannel::LbToLcplusPi || decChannel == DecayChannel::B0ToDstarPi) { + if constexpr (decChannel == DecayChannel::B0ToDstarPi) { + charmHadDauTracks.push_back(candC.template prongPi_as()); // Soft pion from D* decay + } else { + charmHadDauTracks.push_back(candC.template prong2_as()); + } trackParCov2 = getTrackParCov(charmHadDauTracks[2]); pVec2 = charmHadDauTracks[2].pVector(); auto dca2 = o2::dataformats::DCA(charmHadDauTracks[2].dcaXY(), charmHadDauTracks[2].dcaZ(), charmHadDauTracks[2].cYY(), charmHadDauTracks[2].cZY(), charmHadDauTracks[2].cZZ()); @@ -1092,6 +1209,28 @@ struct HfDataCreatorCharmHadPiReduced { } hCandidatesD0->Fill(SVFitting::FitOk); + auto secondaryVertexCharm = df2.getPCACandidate(); + trackParCov0.propagateTo(secondaryVertexCharm[0], bz); + trackParCov1.propagateTo(secondaryVertexCharm[0], bz); + df2.getTrack(0).getPxPyPzGlo(pVec0); + df2.getTrack(1).getPxPyPzGlo(pVec1); + pVecCharm = RecoDecay::pVec(pVec0, pVec1); + trackParCovCharmHad = df2.createParentTrackParCov(); + trackParCovCharmHad.setAbsCharge(0); // to be sure + } else if constexpr (decChannel == DecayChannel::B0ToDstarPi) { + + hCandidatesDstar->Fill(SVFitting::BeforeFit); + try { + // D0 vertex + if (df2.process(trackParCov0, trackParCov1) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + hCandidatesDstar->Fill(SVFitting::Fail); + continue; + } + hCandidatesDstar->Fill(SVFitting::FitOk); auto secondaryVertexCharm = df2.getPCACandidate(); trackParCov0.propagateTo(secondaryVertexCharm[0], bz); trackParCov1.propagateTo(secondaryVertexCharm[0], bz); @@ -1135,7 +1274,7 @@ struct HfDataCreatorCharmHadPiReduced { } // reject pi D with same sign as D - if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi || decChannel == DecayChannel::LbToLcplusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ and Lc∓ → p∓ K± π∓ + if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi || decChannel == DecayChannel::LbToLcplusPi || decChannel == DecayChannel::B0ToDstarPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ and Lc∓ → p∓ K± π∓ and D*+ → D0 π+ if (trackPion.sign() * charmHadDauTracks[0].sign() > 0) { continue; } @@ -1152,7 +1291,7 @@ struct HfDataCreatorCharmHadPiReduced { registry.fill(HIST("hPtPion"), trackParCovPion.getPt()); // compute invariant mass square and apply selection - auto invMass2DPi = RecoDecay::m2(std::array{pVecCharm, pVecPion}, std::array{massC, massPi}); + auto invMass2DPi = RecoDecay::m2(std::array{pVecCharm, pVecPion}, std::array{massC, MassPiPlus}); if ((invMass2DPi < invMass2ChHadPiMin) || (invMass2DPi > invMass2ChHadPiMax)) { continue; } @@ -1160,23 +1299,23 @@ struct HfDataCreatorCharmHadPiReduced { // fill Pion tracks table // if information on track already stored, go to next track if (!selectedTracksPion.count(trackPion.globalIndex())) { - hfTrackPion(trackPion.globalIndex(), indexHfReducedCollision, - trackParCovPion.getX(), trackParCovPion.getAlpha(), - trackParCovPion.getY(), trackParCovPion.getZ(), trackParCovPion.getSnp(), - trackParCovPion.getTgl(), trackParCovPion.getQ2Pt(), - trackPion.itsNCls(), trackPion.tpcNClsCrossedRows(), trackPion.tpcChi2NCl()); - hfTrackCovPion(trackParCovPion.getSigmaY2(), trackParCovPion.getSigmaZY(), trackParCovPion.getSigmaZ2(), - trackParCovPion.getSigmaSnpY(), trackParCovPion.getSigmaSnpZ(), - trackParCovPion.getSigmaSnp2(), trackParCovPion.getSigmaTglY(), trackParCovPion.getSigmaTglZ(), - trackParCovPion.getSigmaTglSnp(), trackParCovPion.getSigmaTgl2(), - trackParCovPion.getSigma1PtY(), trackParCovPion.getSigma1PtZ(), trackParCovPion.getSigma1PtSnp(), - trackParCovPion.getSigma1PtTgl(), trackParCovPion.getSigma1Pt2()); - hfTrackPidPion(trackPion.hasTPC(), trackPion.hasTOF(), - trackPion.tpcNSigmaPi(), trackPion.tofNSigmaPi()); + tables.hfTrackPion(trackPion.globalIndex(), indexHfReducedCollision, + trackParCovPion.getX(), trackParCovPion.getAlpha(), + trackParCovPion.getY(), trackParCovPion.getZ(), trackParCovPion.getSnp(), + trackParCovPion.getTgl(), trackParCovPion.getQ2Pt(), + trackPion.itsNCls(), trackPion.tpcNClsCrossedRows(), trackPion.tpcChi2NCl()); + tables.hfTrackCovPion(trackParCovPion.getSigmaY2(), trackParCovPion.getSigmaZY(), trackParCovPion.getSigmaZ2(), + trackParCovPion.getSigmaSnpY(), trackParCovPion.getSigmaSnpZ(), + trackParCovPion.getSigmaSnp2(), trackParCovPion.getSigmaTglY(), trackParCovPion.getSigmaTglZ(), + trackParCovPion.getSigmaTglSnp(), trackParCovPion.getSigmaTgl2(), + trackParCovPion.getSigma1PtY(), trackParCovPion.getSigma1PtZ(), trackParCovPion.getSigma1PtSnp(), + trackParCovPion.getSigma1PtTgl(), trackParCovPion.getSigma1Pt2()); + tables.hfTrackPidPion(trackPion.hasTPC(), trackPion.hasTOF(), + trackPion.tpcNSigmaPi(), trackPion.tofNSigmaPi()); // add trackPion.globalIndex() to a list // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another D candidate - // and keep track of their index in hfTrackPion for McRec purposes - selectedTracksPion[trackPion.globalIndex()] = hfTrackPion.lastIndex(); + // and keep track of their index in tables.hfTrackPion for McRec purposes + selectedTracksPion[trackPion.globalIndex()] = tables.hfTrackPion.lastIndex(); } if constexpr (doMc) { @@ -1192,19 +1331,19 @@ struct HfDataCreatorCharmHadPiReduced { if (fillHfCandCharm) { // fill candCplus table only once per D candidate constexpr std::size_t NSizeMLScore{3u}; if constexpr (decChannel == DecayChannel::B0ToDminusPi || decChannel == DecayChannel::BsToDsminusPi || decChannel == DecayChannel::LbToLcplusPi) { // D∓ → π∓ K± π∓ and Ds∓ → K∓ K± π∓ and Lc∓ → p∓ K± π∓ - hfCand3Prong(charmHadDauTracks[0].globalIndex(), charmHadDauTracks[1].globalIndex(), charmHadDauTracks[2].globalIndex(), - indexHfReducedCollision, - trackParCovCharmHad.getX(), trackParCovCharmHad.getAlpha(), - trackParCovCharmHad.getY(), trackParCovCharmHad.getZ(), trackParCovCharmHad.getSnp(), - trackParCovCharmHad.getTgl(), trackParCovCharmHad.getQ2Pt(), - candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0, invMassC1, - ptDauMin, etaDauMin, nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax); - hfCand3ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), - trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), - trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), - trackParCovCharmHad.getSigmaTglSnp(), trackParCovCharmHad.getSigmaTgl2(), - trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), - trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); + tables.hfCand3Prong(charmHadDauTracks[0].globalIndex(), charmHadDauTracks[1].globalIndex(), charmHadDauTracks[2].globalIndex(), + indexHfReducedCollision, + trackParCovCharmHad.getX(), trackParCovCharmHad.getAlpha(), + trackParCovCharmHad.getY(), trackParCovCharmHad.getZ(), trackParCovCharmHad.getSnp(), + trackParCovCharmHad.getTgl(), trackParCovCharmHad.getQ2Pt(), + candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0, invMassC1, + ptDauMin, etaDauMin, nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax); + tables.hfCand3ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), + trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), + trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), + trackParCovCharmHad.getSigmaTglSnp(), trackParCovCharmHad.getSigmaTgl2(), + trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), + trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); float nSigmaTpcPr0{-999.f}, nSigmaTpcPr1{-999.f}, nSigmaTpcPr2{-999.f}; float nSigmaTofPr0{-999.f}, nSigmaTofPr1{-999.f}, nSigmaTofPr2{-999.f}; if constexpr (decChannel == DecayChannel::LbToLcplusPi) { @@ -1216,13 +1355,13 @@ struct HfDataCreatorCharmHadPiReduced { nSigmaTofPr1 = candC.nSigTofPr1(); nSigmaTofPr2 = candC.nSigTofPr2(); } - hfCandPidProng0(candC.nSigTpcPi0(), candC.nSigTofPi0(), candC.nSigTpcKa0(), candC.nSigTofKa0(), nSigmaTpcPr0, nSigmaTofPr0, charmHadDauTracks[0].hasTOF(), charmHadDauTracks[0].hasTPC()); - hfCandPidProng1(candC.nSigTpcPi1(), candC.nSigTofPi1(), candC.nSigTpcKa1(), candC.nSigTofKa1(), nSigmaTpcPr1, nSigmaTofPr1, charmHadDauTracks[1].hasTOF(), charmHadDauTracks[1].hasTPC()); - hfCandPidProng2(candC.nSigTpcPi2(), candC.nSigTofPi2(), candC.nSigTpcKa2(), candC.nSigTofKa2(), nSigmaTpcPr2, nSigmaTofPr2, charmHadDauTracks[2].hasTOF(), charmHadDauTracks[2].hasTPC()); + tables.hfCandPidProng0(candC.nSigTpcPi0(), candC.nSigTofPi0(), candC.nSigTpcKa0(), candC.nSigTofKa0(), nSigmaTpcPr0, nSigmaTofPr0, charmHadDauTracks[0].hasTOF(), charmHadDauTracks[0].hasTPC()); + tables.hfCandPidProng1(candC.nSigTpcPi1(), candC.nSigTofPi1(), candC.nSigTpcKa1(), candC.nSigTofKa1(), nSigmaTpcPr1, nSigmaTofPr1, charmHadDauTracks[1].hasTOF(), charmHadDauTracks[1].hasTPC()); + tables.hfCandPidProng2(candC.nSigTpcPi2(), candC.nSigTofPi2(), candC.nSigTpcKa2(), candC.nSigTofKa2(), nSigmaTpcPr2, nSigmaTofPr2, charmHadDauTracks[2].hasTOF(), charmHadDauTracks[2].hasTPC()); if constexpr (withMl) { std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; if constexpr (decChannel == DecayChannel::B0ToDminusPi) { - hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2], -1., -1., -1.); + tables.hfCand3ProngMl(candC.mlProbDplusToPiKPi()[0], candC.mlProbDplusToPiKPi()[1], candC.mlProbDplusToPiKPi()[2], -1., -1., -1.); } else if constexpr (decChannel == DecayChannel::BsToDsminusPi) { if (candC.mlProbDsToKKPi().size() == NSizeMLScore) { std::copy(candC.mlProbDsToKKPi().begin(), candC.mlProbDsToKKPi().end(), mlScores.begin()); @@ -1230,7 +1369,7 @@ struct HfDataCreatorCharmHadPiReduced { if (candC.mlProbDsToPiKK().size() == NSizeMLScore) { std::copy(candC.mlProbDsToPiKK().begin(), candC.mlProbDsToPiKK().end(), mlScores.begin() + 3); } - hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); + tables.hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); } else if constexpr (decChannel == DecayChannel::LbToLcplusPi) { if (candC.mlProbLcToPKPi().size() == NSizeMLScore) { std::copy(candC.mlProbLcToPKPi().begin(), candC.mlProbLcToPKPi().end(), mlScores.begin()); @@ -1238,25 +1377,25 @@ struct HfDataCreatorCharmHadPiReduced { if (candC.mlProbLcToPiKP().size() == NSizeMLScore) { std::copy(candC.mlProbLcToPiKP().begin(), candC.mlProbLcToPiKP().end(), mlScores.begin() + 3); } - hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); + tables.hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); } } } else if constexpr (decChannel == DecayChannel::BplusToD0barPi) { // D0(bar) → K± π∓ - hfCand2Prong(charmHadDauTracks[0].globalIndex(), charmHadDauTracks[1].globalIndex(), - indexHfReducedCollision, - trackParCovCharmHad.getX(), trackParCovCharmHad.getAlpha(), - trackParCovCharmHad.getY(), trackParCovCharmHad.getZ(), trackParCovCharmHad.getSnp(), - trackParCovCharmHad.getTgl(), trackParCovCharmHad.getQ2Pt(), - candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0, invMassC1, - ptDauMin, etaDauMin, nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax); - hfCand2ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), - trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), - trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), - trackParCovCharmHad.getSigmaTglSnp(), trackParCovCharmHad.getSigmaTgl2(), - trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), - trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); - hfCandPidProng0(candC.nSigTpcPi0(), candC.nSigTofPi0(), candC.nSigTpcKa0(), candC.nSigTofKa0(), 0., 0., charmHadDauTracks[0].hasTOF(), charmHadDauTracks[0].hasTPC()); - hfCandPidProng1(candC.nSigTpcPi1(), candC.nSigTofPi1(), candC.nSigTpcKa1(), candC.nSigTofKa1(), 0., 0., charmHadDauTracks[1].hasTOF(), charmHadDauTracks[1].hasTPC()); + tables.hfCand2Prong(charmHadDauTracks[0].globalIndex(), charmHadDauTracks[1].globalIndex(), + indexHfReducedCollision, + trackParCovCharmHad.getX(), trackParCovCharmHad.getAlpha(), + trackParCovCharmHad.getY(), trackParCovCharmHad.getZ(), trackParCovCharmHad.getSnp(), + trackParCovCharmHad.getTgl(), trackParCovCharmHad.getQ2Pt(), + candC.xSecondaryVertex(), candC.ySecondaryVertex(), candC.zSecondaryVertex(), invMassC0, invMassC1, + ptDauMin, etaDauMin, nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax); + tables.hfCand2ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), + trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), + trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), + trackParCovCharmHad.getSigmaTglSnp(), trackParCovCharmHad.getSigmaTgl2(), + trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), + trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); + tables.hfCandPidProng0(candC.nSigTpcPi0(), candC.nSigTofPi0(), candC.nSigTpcKa0(), candC.nSigTofKa0(), 0., 0., charmHadDauTracks[0].hasTOF(), charmHadDauTracks[0].hasTPC()); + tables.hfCandPidProng1(candC.nSigTpcPi1(), candC.nSigTofPi1(), candC.nSigTpcKa1(), candC.nSigTofKa1(), 0., 0., charmHadDauTracks[1].hasTOF(), charmHadDauTracks[1].hasTPC()); if constexpr (withMl) { std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; if (candC.mlProbD0().size() == NSizeMLScore) { @@ -1265,41 +1404,109 @@ struct HfDataCreatorCharmHadPiReduced { if (candC.mlProbD0bar().size() == NSizeMLScore) { std::copy(candC.mlProbD0bar().begin(), candC.mlProbD0bar().end(), mlScores.begin() + 3); } - hfCand2ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); + tables.hfCand2ProngMl(mlScores[0], mlScores[1], mlScores[2], mlScores[3], mlScores[4], mlScores[5]); + } + } else if constexpr (decChannel == DecayChannel::B0ToDstarPi) { + tables.hfCand2Prong(charmHadDauTracks[0].globalIndex(), charmHadDauTracks[1].globalIndex(), + indexHfReducedCollision, + trackParCovCharmHad.getX(), trackParCovCharmHad.getAlpha(), + trackParCovCharmHad.getY(), trackParCovCharmHad.getZ(), trackParCovCharmHad.getSnp(), + trackParCovCharmHad.getTgl(), trackParCovCharmHad.getQ2Pt(), + candC.xSecondaryVertexD0(), candC.ySecondaryVertexD0(), candC.zSecondaryVertexD0(), invMassC0, invMassC1, + ptDauMin, etaDauMin, nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax); + tables.hfCand2ProngCov(trackParCovCharmHad.getSigmaY2(), trackParCovCharmHad.getSigmaZY(), trackParCovCharmHad.getSigmaZ2(), + trackParCovCharmHad.getSigmaSnpY(), trackParCovCharmHad.getSigmaSnpZ(), + trackParCovCharmHad.getSigmaSnp2(), trackParCovCharmHad.getSigmaTglY(), trackParCovCharmHad.getSigmaTglZ(), + trackParCovCharmHad.getSigmaTglSnp(), trackParCovCharmHad.getSigmaTgl2(), + trackParCovCharmHad.getSigma1PtY(), trackParCovCharmHad.getSigma1PtZ(), trackParCovCharmHad.getSigma1PtSnp(), + trackParCovCharmHad.getSigma1PtTgl(), trackParCovCharmHad.getSigma1Pt2()); + float nSigmaTpcPr0{-999.f}, nSigmaTpcPr1{-999.f}; + float nSigmaTofPr0{-999.f}, nSigmaTofPr1{-999.f}; + tables.hfCandPidProng0(candC.nSigTpcPi0(), candC.nSigTofPi0(), candC.nSigTpcKa0(), candC.nSigTofKa0(), nSigmaTpcPr0, nSigmaTofPr0, charmHadDauTracks[0].hasTOF(), charmHadDauTracks[0].hasTPC()); + tables.hfCandPidProng1(candC.nSigTpcPi1(), candC.nSigTofPi1(), candC.nSigTpcKa1(), candC.nSigTofKa1(), nSigmaTpcPr1, nSigmaTofPr1, charmHadDauTracks[1].hasTOF(), charmHadDauTracks[1].hasTPC()); + + // Soft pion tables + auto trackSoftPion = charmHadDauTracks.back(); + auto trackParCovSoftPion = getTrackParCov(trackSoftPion); + std::array dcaSoftPion{trackSoftPion.dcaXY(), trackSoftPion.dcaZ()}; + std::array pVecSoftPion = trackSoftPion.pVector(); + if (trackSoftPion.collisionId() != thisCollId) { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovSoftPion, 2.f, noMatCorr, &dcaSoftPion); + getPxPyPz(trackParCovSoftPion, pVecSoftPion); + } + tables.hfTrackSoftPion(trackSoftPion.globalIndex(), indexHfReducedCollision, + trackParCovSoftPion.getX(), trackParCovSoftPion.getAlpha(), + trackParCovSoftPion.getY(), trackParCovSoftPion.getZ(), trackParCovSoftPion.getSnp(), + trackParCovSoftPion.getTgl(), trackParCovSoftPion.getQ2Pt(), + trackSoftPion.itsNCls(), trackSoftPion.tpcNClsCrossedRows(), trackSoftPion.tpcChi2NCl()); + tables.hfTrackCovSoftPion(trackParCovSoftPion.getSigmaY2(), trackParCovSoftPion.getSigmaZY(), trackParCovSoftPion.getSigmaZ2(), + trackParCovSoftPion.getSigmaSnpY(), trackParCovSoftPion.getSigmaSnpZ(), + trackParCovSoftPion.getSigmaSnp2(), trackParCovSoftPion.getSigmaTglY(), trackParCovSoftPion.getSigmaTglZ(), + trackParCovSoftPion.getSigmaTglSnp(), trackParCovSoftPion.getSigmaTgl2(), + trackParCovSoftPion.getSigma1PtY(), trackParCovSoftPion.getSigma1PtZ(), trackParCovSoftPion.getSigma1PtSnp(), + trackParCovSoftPion.getSigma1PtTgl(), trackParCovSoftPion.getSigma1Pt2()); + if constexpr (withMl) { + std::array mlScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; + if (candC.mlProbDstarToD0Pi().size() == NSizeMLScore) { + std::copy(candC.mlProbDstarToD0Pi().begin(), candC.mlProbDstarToD0Pi().end(), mlScores.begin()); + } + tables.hfCand3ProngMl(mlScores[0], mlScores[1], mlScores[2], -1.f, -1.f, -1.f); } } fillHfReducedCollision = true; } } // candsC loop - registry.fill(HIST("hEvents"), 1 + Event::Processed); if (!fillHfReducedCollision) { registry.fill(HIST("hEvents"), 1 + Event::NoCharmHadPiSelected); return; } registry.fill(HIST("hEvents"), 1 + Event::CharmHadPiSelected); - float centrality = -1.f; - uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + // fill collision table if it contains a DPi pair a minima - hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); - hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), - collision.covXZ(), collision.covYZ(), collision.covZZ()); - hfReducedCollCentrality(collision.centFT0C(), collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); + tables.hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); + tables.hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ()); + tables.hfReducedCollCentrality(collision.centFT0C(), collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); if constexpr (withQvec) { - hfReducedQvector(collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.sumAmplFT0C(), - collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.sumAmplFT0A(), - collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.sumAmplFT0M(), - collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.nTrkTPCpos(), - collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), collision.nTrkTPCneg(), - collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + tables.hfReducedQvector(collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.sumAmplFT0C(), + collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.sumAmplFT0A(), + collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.sumAmplFT0M(), + collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.nTrkTPCpos(), + collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), collision.nTrkTPCneg(), + collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); } } template - void runMcGen(aod::McParticles const& particlesMc) + void runMcGen(aod::McCollision const& mcCollision, + aod::McParticles const& particlesMc, + CollisionsWCentAndMcLabels const& collisions, + BCsInfo const&) { + // Check event selection + float centDummy{-1.f}, centFT0C{-1.f}, centFT0M{-1.f}; + const auto collSlice = collisions.sliceBy(preslices.colPerMcCollision, mcCollision.globalIndex()); + auto hfRejMap = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centDummy); + if (configs.skipRejectedCollisions && hfRejMap != 0) { + return; + } + + // get centrality + float multiplicity{0.f}; + for (const auto& collision : collSlice) { + float collMult = collision.numContrib(); + if (collMult > multiplicity) { + centFT0C = collision.centFT0C(); + centFT0M = collision.centFT0M(); + multiplicity = collMult; + } + } + + const auto mcParticlesPerMcColl = particlesMc.sliceBy(preslices.mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Match generated particles. - for (const auto& particle : particlesMc) { + for (const auto& particle : mcParticlesPerMcColl) { int8_t sign{0}; int8_t flag{0}; if constexpr (decayChannel == DecayChannel::B0ToDminusPi) { @@ -1332,9 +1539,9 @@ struct HfDataCreatorCharmHadPiReduced { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - rowHfB0McGenReduced(flag, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + tables.rowHfB0McGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } else if constexpr (decayChannel == DecayChannel::BsToDsminusPi) { // Bs → Ds- π+ if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBS, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { @@ -1360,7 +1567,7 @@ struct HfDataCreatorCharmHadPiReduced { } // additional checks for correlated backgrounds - if (checkDecayTypeMc) { + if (configs.checkDecayTypeMc) { // B0 → Ds- π+ if (!flag) { if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kB0, std::array{-static_cast(Pdg::kDS), +kPiPlus}, true)) { @@ -1407,9 +1614,9 @@ struct HfDataCreatorCharmHadPiReduced { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - rowHfBsMcGenReduced(flag, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + tables.rowHfBsMcGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } else if constexpr (decayChannel == DecayChannel::BplusToD0barPi) { // B+ → D0bar π+ if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBPlus, std::array{-static_cast(Pdg::kD0), +kPiPlus}, true)) { @@ -1440,9 +1647,9 @@ struct HfDataCreatorCharmHadPiReduced { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - rowHfBpMcGenReduced(flag, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + tables.rowHfBpMcGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } else if constexpr (decayChannel == DecayChannel::LbToLcplusPi) { // Lb → Lc+ π- if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kLambdaB0, std::array{static_cast(Pdg::kLambdaCPlus), -kPiPlus}, true)) { @@ -1473,9 +1680,42 @@ struct HfDataCreatorCharmHadPiReduced { yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); counter++; } - rowHfLbMcGenReduced(flag, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); + tables.rowHfLbMcGenReduced(flag, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); + } else if constexpr (decayChannel == DecayChannel::B0ToDstarPi) { + // B0 → D* π+ + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kB0, std::array{-static_cast(Pdg::kDStar), +kPiPlus}, true)) { + // Match D- -> π- K+ π- + auto candCMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + // Printf("Checking D- -> π- K+ π-"); + if (RecoDecay::isMatchedMCGen(particlesMc, candCMC, +static_cast(Pdg::kDStar), std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 3)) { + flag = sign * BIT(hf_cand_b0::DecayType::B0ToDstarPi); + } + } + + // save information for B0 task + if (!TESTBIT(std::abs(flag), hf_cand_b0::DecayType::B0ToDstarPi)) { + continue; + } + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(particle.pVector(), massB); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + tables.rowHfB0McGenReduced(flag, -1 /*channel*/, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); } } // gen } @@ -1491,7 +1731,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1504,12 +1744,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDplusPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiData, "Process DplusPi without MC info and without ML info", true); @@ -1521,7 +1761,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1534,12 +1774,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiDataWithMl, "Process DplusPi without MC info and with ML info", false); @@ -1551,7 +1791,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1564,14 +1804,14 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDplusPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiDataWithQvec, "Process DplusPi without MC info, without ML info and with Q-vectors", true); + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiDataWithQvec, "Process DplusPi without MC info, without ML info and with Q-vectors", false); void processDplusPiDataWithMlAndQvec(CollisionsWCentAndQvectors const& collisions, CandsDplusFilteredWithMl const& candsC, @@ -1581,7 +1821,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1594,15 +1834,139 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiDataWithMlAndQvec, "Process DplusPi without MC info, with ML info and with Q-vectors", false); + void processDstarPiData(CollisionsWCent const& collisions, + CandsDstarFiltered const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs, + aod::Hf2Prongs const&) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDstar.value, configs.invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(preslices.candsDstarPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDstarPiData, "Process DstarPi without MC info and without ML info", false); + + void processDstarPiDataWithMl(CollisionsWCent const& collisions, + CandsDstarFilteredWithMl const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs, + aod::Hf2Prongs const&) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDstar.value, configs.invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(preslices.candsDstarPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDstarPiDataWithMl, "Process DstarPi without MC info and with ML info", false); + + void processDstarPiDataWithQvec(CollisionsWCentAndQvectors const& collisions, + CandsDstarFiltered const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs, + aod::Hf2Prongs const&) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDstar.value, configs.invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(preslices.candsDstarPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDstarPiDataWithQvec, "Process DstarPi without MC info, without ML info and with Q-vectors", false); + + void processDstarPiDataWithMlAndQvec(CollisionsWCentAndQvectors const& collisions, + CandsDstarFilteredWithMl const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs, + aod::Hf2Prongs const&) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDstar.value, configs.invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(preslices.candsDstarPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDstarPiDataWithMlAndQvec, "Process DstarPi without MC info, with ML info and with Q-vectors", false); + void processDsPiData(CollisionsWCent const& collisions, CandsDsFiltered const& candsC, aod::TrackAssoc const& trackIndices, @@ -1611,7 +1975,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1624,14 +1988,14 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDsPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiData, "Process DsPi without MC info and without ML info", true); + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiData, "Process DsPi without MC info and without ML info", false); void processDsPiDataWithMl(CollisionsWCent const& collisions, CandsDsFilteredWithMl const& candsC, @@ -1641,7 +2005,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1654,12 +2018,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDsPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiDataWithMl, "Process DsPi without MC info and with ML info", false); @@ -1671,7 +2035,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1684,14 +2048,14 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDsPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiDataWithQvec, "Process DsPi without MC info, without ML info and with Q-vectors", true); + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiDataWithQvec, "Process DsPi without MC info, without ML info and with Q-vectors", false); void processDsPiDataWithMlAndQvec(CollisionsWCentAndQvectors const& collisions, CandsDsFilteredWithMl const& candsC, @@ -1701,7 +2065,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1714,12 +2078,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsDsPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiDataWithMlAndQvec, "Process DsPi without MC info, with ML info and Q-vectors", false); @@ -1731,7 +2095,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1744,12 +2108,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsD0PerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsD0PerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiData, "Process D0Pi without MC info and without ML info", false); @@ -1761,7 +2125,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1774,12 +2138,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsD0PerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsD0PerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiDataWithMl, "Process D0Pi without MC info and with ML info", false); @@ -1791,7 +2155,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1804,12 +2168,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsD0PerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsD0PerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiDataWithQvec, "Process D0Pi without MC info, without ML info, and with Q-vectors", false); @@ -1821,7 +2185,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1834,12 +2198,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsD0PerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsD0PerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiDataWithMlAndQvec, "Process D0Pi without MC info, with ML info, and with Q-vectors", false); @@ -1851,7 +2215,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1864,14 +2228,14 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsLcPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsLcPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } - PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processLcPiData, "Process LcPi without MC info and without ML info", true); + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processLcPiData, "Process LcPi without MC info and without ML info", false); void processLcPiDataWithMl(CollisionsWCent const& collisions, CandsLcFilteredWithMl const& candsC, @@ -1881,7 +2245,7 @@ struct HfDataCreatorCharmHadPiReduced { { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1894,12 +2258,12 @@ struct HfDataCreatorCharmHadPiReduced { o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsLcPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto candsCThisColl = candsC.sliceBy(preslices.candsLcPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processLcPiDataWithMl, "Process LcPi without MC info and with ML info", false); @@ -1911,12 +2275,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1926,18 +2290,20 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsDplusPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiMc, "Process DplusPi with MC info and without ML info", false); @@ -1946,12 +2312,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B0 workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1961,32 +2327,110 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDplusPiMcWithMl, "Process DplusPi with MC info and with ML info", false); + void processDstarPiMc(CollisionsWCentAndMcLabels const& collisions, + CandsDstarFiltered const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisions const& mcCollisions, + aod::Hf2Prongs const&) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDstar.value, configs.invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(preslices.candsDstarPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDstarPiMc, "Process DstarPi with MC info and without ML info", false); + + void processDstarPiMcWithMl(CollisionsWCentAndMcLabels const& collisions, + CandsDstarFilteredWithMl const& candsC, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisions const& mcCollisions, + aod::Hf2Prongs const&) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + tables.rowCandidateConfigB0(hfflagConfigurations.selectionFlagDstar.value, configs.invMassWindowCharmHadPi.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsCThisColl = candsC.sliceBy(preslices.candsDstarPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDstarPiMcWithMl, "Process DstarPi with MC info and with ML info", false); + void processDsPiMc(CollisionsWCentAndMcLabels const& collisions, CandsDsFiltered const& candsC, aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -1996,18 +2440,20 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsDsPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMc, "Process DsPi with MC info and without ML info", false); @@ -2016,12 +2462,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Bs workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBs(hfflagConfigurations.selectionFlagDs.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2031,18 +2477,20 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsDplusPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsDsPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processDsPiMcWithMl, "Process DsPi with MC info and with ML info", false); @@ -2051,12 +2499,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2066,18 +2514,20 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsD0PerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsD0PerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiMc, "Process D0Pi with MC info and without ML info", false); @@ -2086,12 +2536,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for B+ workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigBplus(hfflagConfigurations.selectionFlagD0.value, hfflagConfigurations.selectionFlagD0bar.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2101,18 +2551,20 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsD0PerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsD0PerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processD0PiMcWithMl, "Process D0Pi with MC info and with ML info", false); @@ -2121,12 +2573,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagDplus.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigLb(hfflagConfigurations.selectionFlagDplus.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2136,18 +2588,20 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsLcPerCollision, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsLcPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processLcPiMc, "Process LcPi with MC info and without ML info", false); @@ -2156,12 +2610,12 @@ struct HfDataCreatorCharmHadPiReduced { aod::TrackAssoc const& trackIndices, TracksPidWithSelAndMc const& tracks, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs, - McCollisions const&) + BCsInfo const& bcs, + McCollisions const& mcCollisions) { // store configurables needed for Lb workflow if (!isHfCandBhadConfigFilled) { - rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, invMassWindowCharmHadPi.value); + tables.rowCandidateConfigLb(hfflagConfigurations.selectionFlagLc.value, configs.invMassWindowCharmHadPi.value); isHfCandBhadConfigFilled = true; } @@ -2171,18 +2625,20 @@ struct HfDataCreatorCharmHadPiReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsCThisColl = candsC.sliceBy(candsLcPerCollisionWithMl, thisCollId); - auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + auto candsCThisColl = candsC.sliceBy(preslices.candsLcPerCollisionWithMl, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(preslices.trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(preslices.colPerMcCollision, collision.mcCollisionId()); int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); runDataCreation(collision, candsCThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); } // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - runMcGen(particlesMc); + tables.hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } } PROCESS_SWITCH(HfDataCreatorCharmHadPiReduced, processLcPiMcWithMl, "Process LcPi with MC info and with ML info", false); diff --git a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx index a424d95d95b..fb1964d0ef9 100644 --- a/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx +++ b/PWGHF/D2H/TableProducer/dataCreatorCharmResoReduced.cxx @@ -15,34 +15,59 @@ /// \author Luca Aglietta , UniTO Turin /// \author Fabrizio Grosa , CERN -#include -#include -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGLF/DataModel/LFStrangenessTables.h" - +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsMcMatching.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" -#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "Common/Core/RecoDecay.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 +#include +#include +#include +#include +#include +#include +#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::analysis; @@ -50,7 +75,6 @@ using namespace o2::aod; using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; - // event types enum Event : uint8_t { Processed = 0, @@ -59,12 +83,6 @@ enum Event : uint8_t { kNEvent }; -enum DecayChannel : uint8_t { - DstarV0 = 0, - DplusV0, - DstarTrack -}; - enum BachelorType : uint8_t { K0s = 0, Lambda, @@ -89,25 +107,6 @@ enum D0Sel : uint8_t { selectedD0Bar }; -enum DecayTypeMc : uint8_t { - Ds1ToDstarK0ToD0PiK0s = 1, - Ds2StarToDplusK0sToPiKaPiPiPi, - Ds1ToDstarK0ToDplusPi0K0s, - Ds1ToDstarK0ToD0PiK0sPart, - Ds1ToDstarK0ToD0NoPiK0sPart, - Ds1ToDstarK0ToD0PiK0sOneMu, - Ds2StarToDplusK0sOneMu -}; - -enum PartialMatchMc : uint8_t { - K0Matched = 0, - D0Matched, - DstarMatched, - DplusMatched, - K0MuMatched, - DstarMuMatched -}; - /// Creation of D-V0 pairs struct HfDataCreatorCharmResoReduced { @@ -119,12 +118,18 @@ struct HfDataCreatorCharmResoReduced { Produces hfTrackNoParam; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD3Pr; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD2Pr; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h + Produces hfCandDstar; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // ML optional Tables Produces hfCandD3PrMl; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h Produces hfCandD2PrMl; // Defined in PWGHF/D2H/DataModel/ReducedDataModel.h // MC Tables - Produces rowHfDV0McRecReduced; Produces rowHfResoMcGenReduced; + Produces rowHf3PrV0McRecReduced; + Produces rowHfDstarV0McRecReduced; + Produces rowHf2PrV0McRecReduced; + Produces rowHf3PrTrkMcRecReduced; + Produces rowHfDstarTrkMcRecReduced; + Produces rowHf2PrTrkMcRecReduced; // selection D struct : ConfigurableGroup { @@ -157,7 +162,7 @@ struct HfDataCreatorCharmResoReduced { // selection single tracks struct : ConfigurableGroup { - std::string prefix = "single_tracks"; + std::string prefix = "singleTracks"; Configurable setTrackSelections{"setTrackSelections", 2, "flag to apply track selections: 0=none; 1=global track w/o DCA selection; 2=global track; 3=only ITS quality"}; Configurable maxEta{"maxEta", 0.8, "maximum pseudorapidity for single tracks to be paired with D mesons"}; Configurable minPt{"minPt", 0.1, "minimum pT for single tracks to be paired with D mesons"}; @@ -168,6 +173,7 @@ struct HfDataCreatorCharmResoReduced { // QA histograms struct : ConfigurableGroup { + std::string prefix = "qaPlots"; Configurable applyCutsForQaHistograms{"applyCutsForQaHistograms", true, "flag to apply cuts to QA histograms"}; Configurable cutMassDstarMin{"cutMassDstarMin", 0.143, "minimum mass for Dstar candidates"}; Configurable cutMassDstarMax{"cutMassDstarMax", 0.155, "maximum mass for Dstar candidates"}; @@ -184,9 +190,11 @@ struct HfDataCreatorCharmResoReduced { Configurable propagateV0toPV{"propagateV0toPV", false, "Enable or disable V0 propagation to V0"}; 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"}; HfHelper hfHelper; o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; // CCDB service o2::ccdb::CcdbApi ccdbApi; @@ -235,15 +243,29 @@ struct HfDataCreatorCharmResoReduced { std::array pVectorProng2; } varUtils; + // Dplus using CandsDplusFiltered = soa::Filtered>; using CandsDplusFilteredWithMl = soa::Filtered>; + using CandsDplusFilteredWithMc = soa::Filtered>; + using CandsDplusFilteredWithMlAndMc = soa::Filtered>; + // Dstar using CandsDstarFiltered = soa::Filtered>; using CandsDstarFilteredWithMl = soa::Filtered>; - using CandsD0Filtered = soa::Filtered>; - using CandsD0FilteredWithMl = soa::Filtered>; + using CandsDstarFilteredWithMc = soa::Filtered>; + using CandsDstarFilteredWithMlAndMc = soa::Filtered>; + // D0 + using CandsD0Filtered = soa::Filtered>; + using CandsD0FilteredWithMl = soa::Filtered>; + using CandsD0FilteredWithMc = soa::Filtered>; + using CandsD0FilteredWithMlAndMc = soa::Filtered>; + // Tracks using TracksWithPID = soa::Join; + using TracksWithPIDAndMC = soa::Join; using TracksIUWithPID = soa::Join; using TracksIUWithPIDAndMC = soa::Join; + // Collisions MC + using BCsInfo = soa::Join; + using McCollisionsNoCents = soa::Join; Filter filterSelectDplus = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= cfgDmesCuts.selectionFlagDplus); Filter filterSelectedCandDstar = (aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == cfgDmesCuts.selectionFlagDstarToD0Pi); @@ -257,10 +279,12 @@ struct HfDataCreatorCharmResoReduced { Preslice candsD0PerCollisionWithMl = aod::hf_cand::collisionId; Preslice candsV0PerCollision = aod::v0::collisionId; Preslice trackIndicesPerCollision = aod::track_association::collisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; HistogramRegistry registry{"registry"}; - void init(InitContext const&) + void init(InitContext& initContext) { // histograms constexpr int kNBinsEvents = kNEvent; @@ -287,64 +311,55 @@ struct HfDataCreatorCharmResoReduced { const AxisSpec axisDeltaMassToPr{500, 0.93, 1.93, "inv. mass (GeV/#it{c}^{2})"}; const AxisSpec axisDeltaMassToLambda{500, 1.05, 2.05, "inv. mass (GeV/#it{c}^{2})"}; const AxisSpec axisMassDsj{400, 0.49f, 0.89f, ""}; // Ds1 and Ds2Star legacy - registry.add("hMassVsPtDplusAll", "Dplus candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarAll", "Dstar candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtD0All", "D0 candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); - registry.add("hMassVsPtDplusPaired", "Dplus candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarPaired", "Dstar candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtD0Paired", "D0 candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); - registry.add("hMassVsPtD0BarPaired", "D0 candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); registry.add("hMassVsPtK0s", "K0^{s} candidates;#it{p}_{T} (GeV/#it{c});inv. mass (#pi^{#plus}#pi^{#minus}) (GeV/#it{c}^{2});entries", {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", {HistType::kTH2D, {axisPt, axisMassLambda}}); registry.add("hdEdxVsP", "Tracks;#it{p} (GeV/#it{c});d#it{E}/d#it{x};entries", {HistType::kTH2D, {axisP, axisDeDx}}); - registry.add("hDType", "D selection flag", {HistType::kTH1D, {{5, -2.5, 2.5}}}); - - // QA reso invariant mass histograms - registry.add("hMassD0Pi", "D0Pi candidates; m_{D^{0}#pi^{+}} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); - registry.add("hMassD0K", "D0Kplus candidates; m_{D^{0}K^{+}} - m_{D^{0} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); - registry.add("hMassD0Proton", "D0Proton candidates; m_{D^{0}p} - m_{D^{0} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); - registry.add("hMassD0Lambda", "D0Lambda candidates; m_{D^{0}#Lambda} - m_{D^{0} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); - registry.add("hMassDstarPi", "DstarPi candidates; m_{D^{*+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); - registry.add("hMassDstarK", "DstarK candidates; m_{D^{*+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); - registry.add("hMassDstarProton", "DstarProton candidates; m_{D^{*}p} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); - registry.add("hMassDstarK0s", "DstarK0s candidates; m_{D^{*}K^{0}_{S}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); - registry.add("hMassDstarLambda", "DstarLambda candidates; m_{D^{*}#Lambda} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); - registry.add("hMassDplusK0s", "DplusK0s candidates; m_{D^{+}K^{0}_{S}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); - registry.add("hMassDplusPi", "DplusPi candidates; m_{D^{+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); - registry.add("hMassDplusK", "DplusK candidates; m_{D^{+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); - registry.add("hMassDplusProton", "DplusProton candidates; m_{D^{+}p} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); - registry.add("hMassDplusLambda", "DplusLambda candidates; m_{D^{+}#Lambda} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); - // MC Rec - registry.add("hMCRecCounter", "Number of Reconstructed MC Matched candidates per channel", {HistType::kTH1D, {{17, -8.5, 8.5}}}); - registry.add("hMCRecDebug", "Debug of MC Reco", {HistType::kTH1D, {{16, -0.5, 15.5}}}); - registry.add("hMCRecOrigin", "Origin of Matched particles", {HistType::kTH1D, {{3, -0.5, 2.5}}}); - registry.add("hMCRecMassGen", "Generated inv. mass of resoncances", {HistType::kTH1D, {{2000, 1.8, 3.8}}}); - // MC Gen - registry.add("hMCGenCounter", "Number of Generated particles; Decay Channel Flag; pT [GeV/c]", {HistType::kTH2D, {{17, -8.5, 8.5}, {100, 0, 50}}}); - registry.add("hMCSignCounter", "Sign of Generated particles", {HistType::kTH1D, {{3, -1.5, 1.5}}}); - registry.add("hMCGenOrigin", "Origin of Generated particles", {HistType::kTH1D, {{3, -0.5, 2.5}}}); - registry.add("hMCOriginCounterWrongDecay", "Origin of Generated particles in Wrong decay", {HistType::kTH1D, {{3, -0.5, 2.5}}}); - - if (doMcRecQa) { - registry.add("hMassVsPtK0Matched", "K0s candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassKzero}}); - registry.add("hMassVsPtD0Matched", "D0 candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarMatched", "Dstar candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtDplusMatched", "Dplus candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDs1Matched", "Ds1 candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtDs2StarMatched", "Ds2Star candidates Matched ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtK0MatchedPiToMu", "K0s candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassKzero}}); - registry.add("hMassVsPtD0MatchedPiToMu", "D0 candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarMatchedPiToMu", "Dstar candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtDplusMatchedPiToMu", "Dplus candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDs1MatchedPiToMu", "Ds1 candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtDs2StarMatchedPiToMu", "Ds2Star candidates Matched with PiToMu decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtD0MatchedKaToPi", "D0 candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDstarMatchedKaToPi", "Dstar candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); - registry.add("hMassVsPtDplusMatchedKaToPi", "Dplus candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); - registry.add("hMassVsPtDs1MatchedKaToPi", "Ds1 candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - registry.add("hMassVsPtDs2StarMatchedKaToPi", "Ds2Star candidates Matched with KaToPi decay ;#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDsj}}); - } + if (doprocessD0V0 || doprocessD0Track || doprocessD0V0AndTrack || doprocessD0V0WithMl || doprocessD0TrackWithMl || doprocessD0V0AndTrackWithMl || + doprocessD0V0MC || doprocessD0TrackMC || doprocessD0V0AndTrackMC || doprocessD0V0MCWithMl || doprocessD0TrackMCWithMl || doprocessD0V0AndTrackMCWithMl) { + registry.add("hMassVsPtD0All", "D0 candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); + registry.add("hMassVsPtD0BarAll", "D0bar candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); + registry.add("hMassVsPtD0Paired", "D0 candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); + registry.add("hMassVsPtD0BarPaired", "D0 candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassD0}}); + registry.add("hMassD0Pi", "D0Pi candidates; m_{D^{0}#pi^{+}} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); + registry.add("hMassD0K", "D0Kplus candidates; m_{D^{0}K^{+}} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); + registry.add("hMassD0Proton", "D0Proton candidates; m_{D^{0}p} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); + registry.add("hMassD0Lambda", "D0Lambda candidates; m_{D^{0}#Lambda} - m_{D^{0}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); + } + if (doprocessDstarV0 || doprocessDstarTrack || doprocessDstarV0AndTrack || doprocessDstarV0WithMl || doprocessDstarTrackWithMl || doprocessDstarV0AndTrackWithMl || + doprocessDstarV0MC || doprocessDstarTrackMC || doprocessDstarV0AndTrackMC || doprocessDstarV0MCWithMl || doprocessDstarTrackMCWithMl || doprocessDstarV0AndTrackMCWithMl) { + registry.add("hMassVsPtDstarAll", "Dstar candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); + registry.add("hMassVsPtDstarPaired", "Dstar candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDstar}}); + registry.add("hMassDstarPi", "DstarPi candidates; m_{D^{*+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); + registry.add("hMassDstarK", "DstarK candidates; m_{D^{*+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); + registry.add("hMassDstarProton", "DstarProton candidates; m_{D^{*}p} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); + registry.add("hMassDstarK0s", "DstarK0s candidates; m_{D^{*}K^{0}_{S}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); + registry.add("hMassDstarLambda", "DstarLambda candidates; m_{D^{*}#Lambda} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); + } + if (doprocessDplusV0 || doprocessDplusTrack || doprocessDplusV0AndTrack || doprocessDplusV0WithMl || doprocessDplusTrackWithMl || doprocessDplusV0AndTrackWithMl || + doprocessDplusV0MC || doprocessDplusTrackMC || doprocessDplusV0AndTrackMC || doprocessDplusV0MCWithMl || doprocessDplusTrackMCWithMl || doprocessDplusV0AndTrackMCWithMl) { + registry.add("hMassVsPtDplusAll", "Dplus candidates (all, regardless the pairing with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); + registry.add("hMassVsPtDplusPaired", "Dplus candidates (paired with V0s);#it{p}_{T} (GeV/#it{c});inv. mass (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisMassDplus}}); + registry.add("hMassDplusK0s", "DplusK0s candidates; m_{D^{+}K^{0}_{S}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); + registry.add("hMassDplusPi", "DplusPi candidates; m_{D^{+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPi}}); + registry.add("hMassDplusK", "DplusK candidates; m_{D^{+}#pi^{-}} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToK}}); + registry.add("hMassDplusProton", "DplusProton candidates; m_{D^{+}p} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToPr}}); + registry.add("hMassDplusLambda", "DplusLambda candidates; m_{D^{+}#Lambda} (GeV/#it{c}^{2});entries", {HistType::kTH2D, {axisPt, axisDeltaMassToLambda}}); + } + if (doprocessD0V0MC || doprocessD0TrackMC || doprocessD0V0AndTrackMC || doprocessD0V0MCWithMl || doprocessD0TrackMCWithMl || doprocessD0V0AndTrackMCWithMl || + doprocessDstarV0MC || doprocessDstarTrackMC || doprocessDstarV0AndTrackMC || doprocessDstarV0MCWithMl || doprocessDstarTrackMCWithMl || doprocessDstarV0AndTrackMCWithMl || + doprocessDplusV0MC || doprocessDplusTrackMC || doprocessDplusV0AndTrackMC || doprocessDplusV0MCWithMl || doprocessDplusTrackMCWithMl || doprocessDplusV0AndTrackMCWithMl) { + // MC Rec + int nChannels = hf_decay::hf_cand_reso::DecayChannelMain::NChannelsMain; + registry.add("hMCRecCounter", "Number of Reconstructed MC Matched candidates per channel", {HistType::kTH1D, {{2 * nChannels + 1, -(nChannels + 0.5), nChannels + 0.5}}}); + registry.add("hMCRecDebug", "Debug of MC Reco", {HistType::kTH1D, {{551, -0.5, 550.5}}}); + registry.add("hMCRecOrigin", "Origin of Matched particles", {HistType::kTH1D, {{3, -0.5, 2.5}}}); + registry.add("hMCRecMassGen", "Generated inv. mass of resoncances", {HistType::kTH1D, {{2000, 1.8, 3.8}}}); + registry.add("hMCRecCharmDau", "Charm daughter flag", {HistType::kTH1D, {{57, -28.5, 28.5}}}); + // MC Gen + registry.add("hMCGenCounter", "Number of Generated particles; Decay Channel Flag; pT [GeV/c]", {HistType::kTH2D, {{17, -8.5, 8.5}, {100, 0, 50}}}); + registry.add("hMCGenOrigin", "Origin of Generated particles", {HistType::kTH1D, {{3, -0.5, 2.5}}}); + } // Configure CCDB access ccdb->setURL(ccdbUrl.value); ccdb->setCaching(true); @@ -367,6 +382,15 @@ struct HfDataCreatorCharmResoReduced { // init HF event selection helper hfEvSel.init(registry); + + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-data-creator-charm-reso-reduced") == 0) { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } } /// Basic track quality selections for V0 daughters @@ -421,7 +445,6 @@ struct HfDataCreatorCharmResoReduced { { auto trackPos = dauTracks[0]; auto trackNeg = dauTracks[1]; - // single-tracks selection if (!selectV0Daughter(trackPos, dDaughtersIds) || !selectV0Daughter(trackNeg, dDaughtersIds)) return false; @@ -443,7 +466,6 @@ struct HfDataCreatorCharmResoReduced { try { nCand = fitter.process(trackPosCov, trackNegCov); } catch (...) { - LOG(error) << "Exception caught in DCA fitter process call!"; return false; } if (nCand == 0) { @@ -454,9 +476,9 @@ struct HfDataCreatorCharmResoReduced { auto& trackNegProp = fitter.getTrack(1); trackPosProp.getPxPyPzGlo(candidateV0.momPos); trackNegProp.getPxPyPzGlo(candidateV0.momNeg); - for (int i = 0; i < 3; ++i) { // o2-linter: disable=magic-number (loop on xyz) - candidateV0.mom[i] = candidateV0.momPos[i] + candidateV0.momNeg[i]; - } + + candidateV0.mom = RecoDecay::pVec(candidateV0.momPos, candidateV0.momNeg); + candidateV0.pT = std::hypot(candidateV0.mom[0], candidateV0.mom[1]); // topological selections: // v0 eta @@ -475,9 +497,8 @@ struct HfDataCreatorCharmResoReduced { if (candidateV0.radius < cfgV0Cuts.radiusMin) { return false; } - for (int i = 0; i < 3; i++) { // o2-linter: disable=magic-number (loop on xyz) - candidateV0.pos[i] = vtx[i]; - } + std::copy(vtx.begin(), vtx.end(), candidateV0.pos.begin()); + // v0 DCA to primary vertex candidateV0.dcaV0ToPv = calculateDCAStraightToPV( vtx[0], vtx[1], vtx[2], @@ -494,42 +515,41 @@ struct HfDataCreatorCharmResoReduced { if (candidateV0.cosPA < cfgV0Cuts.cosPa) { return false; } - // distinguish between K0s, and Lambda hypotesys - candidateV0.v0Type = {BIT(K0s) | BIT(Lambda) | BIT(AntiLambda)}; + candidateV0.v0Type = {BIT(BachelorType::K0s) | BIT(BachelorType::Lambda) | BIT(BachelorType::AntiLambda)}; // for lambda hypotesys define if its lambda or anti-lambda candidateV0.alpha = alphaAP(candidateV0.mom, candidateV0.momPos, candidateV0.momNeg); bool matter = candidateV0.alpha > 0; - CLRBIT(candidateV0.v0Type, matter ? AntiLambda : Lambda); + CLRBIT(candidateV0.v0Type, matter ? BachelorType::AntiLambda : BachelorType::Lambda); auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; // mass hypotesis candidateV0.mLambda = RecoDecay::m(std::array{candidateV0.momPos, candidateV0.momNeg}, std::array{massPos, massNeg}); candidateV0.mK0Short = RecoDecay::m(std::array{candidateV0.momPos, candidateV0.momNeg}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); if (std::fabs(candidateV0.mK0Short - MassK0) > cfgV0Cuts.deltaMassK0s) { - CLRBIT(candidateV0.v0Type, K0s); + CLRBIT(candidateV0.v0Type, BachelorType::K0s); } if (std::fabs(candidateV0.mLambda - MassLambda0) > cfgV0Cuts.deltaMassLambda) { - CLRBIT(candidateV0.v0Type, Lambda); - CLRBIT(candidateV0.v0Type, AntiLambda); + CLRBIT(candidateV0.v0Type, BachelorType::Lambda); + CLRBIT(candidateV0.v0Type, BachelorType::AntiLambda); } // PID - if (TESTBIT(candidateV0.v0Type, K0s)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::K0s)) { if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc) || (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc)) - CLRBIT(candidateV0.v0Type, K0s); + CLRBIT(candidateV0.v0Type, BachelorType::K0s); } - if (TESTBIT(candidateV0.v0Type, Lambda)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::Lambda)) { if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPr()) > cfgV0Cuts.nSigmaTpc) || (trackPos.hasTOF() && std::fabs(trackPos.tofNSigmaPr()) > cfgV0Cuts.nSigmaTofPr) || (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc)) - CLRBIT(candidateV0.v0Type, Lambda); + CLRBIT(candidateV0.v0Type, BachelorType::Lambda); } - if (TESTBIT(candidateV0.v0Type, AntiLambda)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::AntiLambda)) { if ((trackPos.hasTPC() && std::fabs(trackPos.tpcNSigmaPi()) > cfgV0Cuts.nSigmaTpc) || (trackNeg.hasTPC() && std::fabs(trackNeg.tpcNSigmaPr()) > cfgV0Cuts.nSigmaTpc) || (trackNeg.hasTOF() && std::fabs(trackNeg.tofNSigmaPr()) > cfgV0Cuts.nSigmaTofPr)) - CLRBIT(candidateV0.v0Type, AntiLambda); + CLRBIT(candidateV0.v0Type, BachelorType::AntiLambda); } if (candidateV0.v0Type == 0) { return false; @@ -544,11 +564,9 @@ struct HfDataCreatorCharmResoReduced { template bool isTrackSelected(const Tr& track, const std::array& dDaughtersIds) { - if (rejectPairsWithCommonDaughter && std::find(dDaughtersIds.begin(), dDaughtersIds.end(), track.globalIndex()) != dDaughtersIds.end()) { return false; } - switch (cfgSingleTrackCuts.setTrackSelections) { case 1: if (!track.isGlobalTrackWoDCA()) { @@ -566,263 +584,427 @@ struct HfDataCreatorCharmResoReduced { } break; } - if (track.pt() < cfgSingleTrackCuts.minPt) { return false; } - if (std::abs(track.eta()) > cfgSingleTrackCuts.maxEta) { return false; } - if (!track.hasTPC()) { return false; } - bool isPion = std::abs(track.tpcNSigmaPi()) < cfgSingleTrackCuts.maxNsigmaTpcPi; bool isKaon = std::abs(track.tpcNSigmaKa()) < cfgSingleTrackCuts.maxNsigmaTpcKa; bool isProton = std::abs(track.tpcNSigmaPr()) < cfgSingleTrackCuts.maxNsigmaTpcPr; - if (!isPion && !isKaon && !isProton) { // we keep the track if is it compatible with at least one of the PID hypotheses selected return false; } - return true; } - /// Function for filling MC reco information in the tables - /// \param particlesMc is the table with MC particles - /// \param vecDaughtersReso is the vector with all daughter tracks (bachelor pion in last position) - /// \param indexHfCandCharm is the index of the charm-hadron bachelor in the reduced table - /// \param indexCandV0 is the index of the v0 bachelor in the reduced table - template - void fillMcRecoInfo(const PParticles& particlesMc, - const std::vector& vecDaughtersReso, - int& indexHfCandCharm, - int& indexCandV0) + template + int8_t getMatchingFlagV0(PParticles const& particlesMc, const std::array& arrDaughtersV0) { - // we check the MC matching to be stored - int8_t sign{0}; - int8_t signDstar{0}; - int8_t signDplus{0}; - int8_t signD0{0}; int8_t signV0{0}; - int8_t flag{0}; - int8_t debug{0}; - int8_t origin{0}; - int8_t nPiToMuReso{0}, nPiToMuV0, nPiToMuD0{0}, nPiToMuDstar{0}, nPiToMuDplus{0}; - int8_t nKaToPiReso{0}, nKaToPiV0, nKaToPiD0{0}, nKaToPiDstar{0}, nKaToPiDplus{0}; - std::vector idxBhadMothers{}; - float motherPt{-1.f}; - float invMassGen{-1.f}; - int indexRecReso{-1}, indexRecDstar{-1}, indexRecDplus{-1}, indexRecD0{-1}, indexRecK0{-1}, indexRecResoPartReco{-1}; + int indexRec{-1}; + int flagV0{0}; + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersV0, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2); + if (indexRec > -1) { + flagV0 = hf_decay::hf_cand_reso::PartialMatchMc::K0Matched; + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersV0, kLambda0, std::array{+kProton, -kPiPlus}, true, &signV0, 2); + if (indexRec > -1) { + flagV0 = signV0 * hf_decay::hf_cand_reso::PartialMatchMc::LambdaMatched; + } + } + return flagV0; // Placeholder, should return the actual flag based on matching logic + } + /// Function for filling MC reco information of DV0 candidates in the tables + /// \tparam dType is the D meson type (Dstar, Dplus or D0) + /// \param particlesMc is the table with MC particles + /// \param candCharmBach is the D meson candidate + /// \param bachelorV0 is the V0 candidate + /// \param tracks is the table with tracks + /// \param indexHfCandCharm is the index of the charm-hadron bachelor in the reduced table + /// \param indexCandV0TrBach is the index of the v0 bachelor in the reduced table + template + void fillMcRecoInfoDV0(PParticles const& particlesMc, + CCand const& candCharmBach, + BBachV0 const& bachelorV0, + Tr const& tracks, + int& indexHfCandCharm, + int64_t& indexCandV0Bach) + { + std::vector vecDaughtersReso{}; + int8_t sign{0}, nKinkedTracks{0}, origin{0}, flagCharmBach{0}, flagCharmBachInterm{0}, flagV0{0}, flagReso{0}; + int indexRec{-1}, debugMcRec{0}; + float ptGen{-1.f}, invMassGen{-1.f}; if constexpr (dType == DType::Dstar) { - // Ds1 → D* K0 → (D0 π+) K0s → ((K-π+) π+)(π+π-) - indexRecD0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1]}, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0, 1, &nPiToMuD0, &nKaToPiD0); - indexRecK0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2, &nPiToMuV0, &nKaToPiV0); - if (indexRecD0 > -1) { - indexRecDstar = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 2, &nPiToMuDstar, &nKaToPiDstar); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prongPiId())); + // Check if D* is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + if (flagCharmBach != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DstarMatched); + origin = candCharmBach.originMcRec(); } - if (indexRecD0 > -1 && indexRecDstar > -1 && indexRecK0 > -1) { - indexRecReso = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3, &nPiToMuReso, &nKaToPiReso); - if (indexRecReso > -1 && nPiToMuReso == 0 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0PiK0s; - } else if (indexRecReso > -1 && nPiToMuReso >= 1 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0PiK0sOneMu; - } + // Check if D0 is matched + flagCharmBachInterm = candCharmBach.flagMcMatchRecD0(); + if (flagCharmBachInterm != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); } - - // Ds1+ not matched: we check if it is partially reco - if (indexRecReso < 0) { - indexRecResoPartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); - indexRecDplus = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2); - if (indexRecResoPartReco > -1) { // we look for decays of D* or D0 with more daughters - if (indexRecDstar < 0 && indexRecK0 > -1) { - auto indexRecDstarPartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 3); - if (indexRecDstarPartReco > -1) { - if (indexRecDplus > -1) { // Ds1 -> D* K0s -> D+ π0 K0s - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; - } else { - auto indexRecD0PartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1]}, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &signD0, 2); - if (indexRecD0PartReco > -1) { // Ds1 -> D* K0s -> D0 π+ K0s -> K- π+ π0 π+ K0s - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0PiK0sPart; - } - } - } + // Check if V0 is matched + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.posTrackId())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.negTrackId())); + flagV0 = getMatchingFlagV0(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}); + if (flagV0 != 0) { + SETBIT(debugMcRec, std::abs(flagV0)); + } + // If both D* and K0s are matched, try to match resonance + if (flagCharmBach != 0 && flagV0 == hf_decay::hf_cand_reso::PartialMatchMc::K0Matched) { + std::array pdgCodesDaughters = {+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}; + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarK0s) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } - } else { // we look for D* not matched, but all the other ones yes, we check if we only lost the soft pion - if (indexRecD0 > -1 && indexRecK0 > -1 && indexRecDstar < 0) { - indexRecResoPartReco = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); - if (indexRecResoPartReco > -1) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToD0NoPiK0sPart; - } + } + } else if (flagCharmBachInterm != 0 && flagV0 == hf_decay::hf_cand_reso::PartialMatchMc::K0Matched) { + std::array pdgCodesDaughters = {+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}; + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[3], vecDaughtersReso[4]}; + // Peaking background of D0K0s <- Ds* with spurious soft pion + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarK0s) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::ResoPartlyMatched); + break; } } } - if (flag != 0) { - int indexParticle{-1}; - if (indexRecReso > -1) { - indexParticle = indexRecReso; - } else if (indexRecResoPartReco > -1) { - indexParticle = indexRecResoPartReco; - } - auto particleReso = particlesMc.iteratorAt(indexParticle); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particleReso, false, &idxBhadMothers); - motherPt = particleReso.pt(); + // No physical channel expected in D*Lambda + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); } - if (doMcRecQa) { - if (indexRecReso > -1) { - if (nPiToMuReso == 0 && nKaToPiReso == 0) { - registry.fill(HIST("hMassVsPtDs1Matched"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nPiToMuReso >= 1) { - registry.fill(HIST("hMassVsPtDs1MatchedPiToMu"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nKaToPiReso >= 1) { - registry.fill(HIST("hMassVsPtDs1MatchedKaToPi"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); + rowHfDstarV0McRecReduced(indexHfCandCharm, indexCandV0Bach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } else if constexpr (dType == DType::Dplus) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong2Id())); + // Check if D+ is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (flagCharmBach != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DplusMatched); + origin = candCharmBach.originMcRec(); + } + // Check if V0 is matched + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.posTrackId())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.negTrackId())); + flagV0 = getMatchingFlagV0(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}); + if (flagV0 != 0) { + SETBIT(debugMcRec, std::abs(flagV0)); + } + // If both D+ and K0s are matched, try to match resonance + if (hf_decay::hf_cand_3prong::daughtersDplusMain.contains(static_cast(std::abs(flagCharmBach))) && flagV0 == hf_decay::hf_cand_reso::PartialMatchMc::K0Matched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}; + auto pdgCodesDplusDaughters = hf_decay::hf_cand_3prong::daughtersDplusMain.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDplusDaughters[0], pdgCodesDplusDaughters[1], pdgCodesDplusDaughters[2], +kPiPlus, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusK0s) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecD0 > -1) { - if (nPiToMuD0 == 0 && nKaToPiD0 == 0) { - registry.fill(HIST("hMassVsPtD0Matched"), varUtils.ptD, varUtils.invMassD0); - } - if (nPiToMuD0 >= 1) { - registry.fill(HIST("hMassVsPtD0MatchedPiToMu"), varUtils.ptD, varUtils.invMassD0); - } - if (nKaToPiD0 >= 1) { - registry.fill(HIST("hMassVsPtD0MatchedKaToPi"), varUtils.ptD, varUtils.invMassD0); + } else if (hf_decay::hf_cand_3prong::daughtersDplusMain.contains(static_cast(std::abs(flagCharmBach))) && std::abs(flagV0) == hf_decay::hf_cand_reso::PartialMatchMc::LambdaMatched) { + // Peaking background of D+Lambda <- Ds* with spurious soft pion + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}; + auto pdgCodesDplusDaughters = hf_decay::hf_cand_3prong::daughtersDplusMain.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDplusDaughters[0], pdgCodesDplusDaughters[1], pdgCodesDplusDaughters[2], +kProton, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusLambda) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecDstar > -1) { - if (nPiToMuDstar == 0 && nKaToPiDstar == 0) { - registry.fill(HIST("hMassVsPtDstarMatched"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); - } - if (nPiToMuDstar >= 1) { - registry.fill(HIST("hMassVsPtDstarMatchedPiToMu"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); - } - if (nKaToPiDstar >= 1) { - registry.fill(HIST("hMassVsPtDstarMatchedKaToPi"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); + } + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHf3PrV0McRecReduced(indexHfCandCharm, indexCandV0Bach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } else if constexpr (dType == DType::D0) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + // Check if D0 is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (flagCharmBach != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); + origin = candCharmBach.originMcRec(); + } + // Check if V0 is matched + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.posTrackId())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(bachelorV0.negTrackId())); + flagV0 = getMatchingFlagV0(particlesMc, std::array{vecDaughtersReso[2], vecDaughtersReso[3]}); + if (flagV0 != 0) { + SETBIT(debugMcRec, std::abs(flagV0)); + } + // No physical channel expected in D0 K0s + // If both D0 and Lambda are matched, try to match resonance + if (hf_decay::hf_cand_2prong::daughtersD0Main.contains(static_cast(std::abs(flagCharmBach))) && std::abs(flagV0) == hf_decay::hf_cand_reso::PartialMatchMc::LambdaMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3]}; + auto pdgCodesDzeroDaughters = hf_decay::hf_cand_2prong::daughtersD0Main.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDzeroDaughters[0], pdgCodesDzeroDaughters[1], +kProton, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Lambda) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecK0 > -1) { - if (nPiToMuV0 == 0 && nKaToPiV0 == 0) { - registry.fill(HIST("hMassVsPtK0Matched"), candidateV0.pT, candidateV0.mK0Short); - } - if (nPiToMuV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedPiToMu"), candidateV0.pT, candidateV0.mK0Short); - } - if (nKaToPiV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedKaToPi"), candidateV0.pT, candidateV0.mK0Short); + } + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHf2PrV0McRecReduced(indexHfCandCharm, indexCandV0Bach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } + registry.fill(HIST("hMCRecDebug"), debugMcRec); + if (indexRec > -1) { + registry.fill(HIST("hMCRecCounter"), flagReso); + registry.fill(HIST("hMCRecOrigin"), origin); + registry.fill(HIST("hMCRecMassGen"), invMassGen); + } + if (flagCharmBach != 0) { + registry.fill(HIST("hMCRecCharmDau"), flagCharmBach); + } + } + + template + int8_t getMatchingFlagTrack(Tr const& bachTrack) + { + auto particle = bachTrack.mcParticle(); + auto pdgCode = std::abs(particle.pdgCode()); + if (pdgCode == kPiPlus) { + return hf_decay::hf_cand_reso::PartialMatchMc::PionMatched; + } else if (pdgCode == kKPlus) { + return hf_decay::hf_cand_reso::PartialMatchMc::KaonMatched; + } else if (pdgCode == kProton) { + return hf_decay::hf_cand_reso::PartialMatchMc::ProtonMatched; + } + return 0; + } + // Function for filling MC reco information of D Track candidates in the tables + /// \tparam dType is the D meson type (Dstar, Dplus or D0) + /// \param particlesMc is the table with MC particles + /// \param candCharmBach is the D meson candidate + /// \param bachelorTrack is the bachelor track + /// \param tracks is the table with tracks + /// \param indexHfCandCharm is the index of the charm-hadron bachelor in the reduced table + /// \param indexCandTrBach is the index of the v0 bachelor in the reduced table + template + void fillMcRecoInfoDTrack(PParticles const& particlesMc, + CCand const& candCharmBach, + BBachTr const& bachelorTrack, + Tr const& tracks, + int& indexHfCandCharm, + int64_t& indexCandTrBach) + { + std::vector vecDaughtersReso{}; + int8_t sign{0}, nKinkedTracks{0}, origin{0}, flagCharmBach{0}, flagCharmBachInterm{0}, flagTrack{0}, flagReso{0}; + int indexRec{-1}; + uint16_t debugMcRec{0}; + float ptGen{-1.f}, invMassGen{-1.f}; + if constexpr (dType == DType::Dstar) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prongPiId())); + // Check if D* is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + if (flagCharmBach != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DstarMatched); + origin = candCharmBach.originMcRec(); + } + // Check if D0 is matched + flagCharmBachInterm = candCharmBach.flagMcMatchRecD0(); + if (flagCharmBachInterm != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); + } + // Check if Track is matched + flagTrack = getMatchingFlagTrack(bachelorTrack); + if (flagTrack != 0) { + SETBIT(debugMcRec, flagTrack); + } + // If both D* and Track are matched, try to match resonance + if (flagCharmBach != 0 && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::PionMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], bachelorTrack}; + auto pdgCodesDaughters = std::array{+kPiPlus, -kKPlus, +kPiPlus, -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarPi) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } } + // No channels in D*K+ or D*Pr + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHfDstarTrkMcRecReduced(indexHfCandCharm, indexCandTrBach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); } else if constexpr (dType == DType::Dplus) { - // Ds2Star → D+ K0 → (π+K-π+) K0s → (π+K-π+)(π+π-) - indexRecK0 = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[3], vecDaughtersReso[4]}, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2, &nPiToMuV0, &nKaToPiV0); - indexRecDplus = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2, &nPiToMuDplus, &nKaToPiDplus); - if (indexRecK0 > -1 && indexRecDplus > -1) { - indexRecReso = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS2Star, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3, &nPiToMuReso, &nKaToPiReso); - if (indexRecReso > -1 && nPiToMuReso == 0 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi; - } else if (indexRecReso > -1 && nPiToMuReso >= 1 && nKaToPiReso == 0) { - flag = sign * DecayTypeMc::Ds2StarToDplusK0sOneMu; - } else if (indexRecReso < 0) { - // Verify partly reconstructed decay Ds1 -> D* K0s -> D+ π0 K0s - indexRecDstar = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2]}, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 2); - if (indexRecDstar > -1) { - indexRecReso = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], vecDaughtersReso[3], vecDaughtersReso[4]}, Pdg::kDS1, std::array{+kPiPlus, -kKPlus, +kPiPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); - if (indexRecReso > -1) { - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; - } + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong2Id())); + // Check if D+ is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (flagCharmBach != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::DplusMatched); + origin = candCharmBach.originMcRec(); + } + // Check if Track is matched + flagTrack = getMatchingFlagTrack(bachelorTrack); + if (flagTrack != 0) { + SETBIT(debugMcRec, flagTrack); + } + // If both D+ and Track are matched, try to match resonance + if (hf_decay::hf_cand_3prong::daughtersDplusMain.contains(static_cast(std::abs(flagCharmBach))) && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::PionMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], vecDaughtersReso[2], bachelorTrack}; + auto pdgCodesDplusDaughters = hf_decay::hf_cand_3prong::daughtersDplusMain.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDplusDaughters[0], pdgCodesDplusDaughters[1], pdgCodesDplusDaughters[2], -kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusPi) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } } - if (flag != 0) { - auto particleReso = particlesMc.iteratorAt(indexRecReso); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particleReso, false, &idxBhadMothers); - motherPt = particleReso.pt(); + // No channels in D+K+ or D+Pr + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); } - if (doMcRecQa) { - if (indexRecReso > -1) { - if (nPiToMuReso == 0 && nKaToPiReso == 0) { - registry.fill(HIST("hMassVsPtDs2StarMatched"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nPiToMuReso >= 1) { - registry.fill(HIST("hMassVsPtDs2StarMatchedPiToMu"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - if (nKaToPiReso >= 1) { - registry.fill(HIST("hMassVsPtDs2StarMatchedKaToPi"), varUtils.ptD, varUtils.invMassReso - varUtils.invMassD); - } - } - if (indexRecDplus > -1) { - if (nPiToMuDplus == 0 && nKaToPiDplus == 0) { - registry.fill(HIST("hMassVsPtDplusMatched"), varUtils.ptD, varUtils.invMassD); - } - if (nPiToMuDplus >= 1) { - registry.fill(HIST("hMassVsPtDplusMatchedPiToMu"), varUtils.ptD, varUtils.invMassD); - } - if (nKaToPiDplus >= 1) { - registry.fill(HIST("hMassVsPtDplusMatchedKaToPi"), varUtils.ptD, varUtils.invMassD); + rowHf3PrTrkMcRecReduced(indexHfCandCharm, indexCandTrBach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } else if constexpr (dType == DType::D0) { + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong0Id())); + vecDaughtersReso.push_back(tracks.rawIteratorAt(candCharmBach.prong1Id())); + // Check if D0 is matched + flagCharmBach = candCharmBach.flagMcMatchRec(); + flagCharmBachInterm = candCharmBach.flagMcDecayChanRec(); + if (flagCharmBach != 0) { + SETBIT(debugMcRec, hf_decay::hf_cand_reso::PartialMatchMc::D0Matched); + origin = candCharmBach.originMcRec(); + } + flagTrack = getMatchingFlagTrack(bachelorTrack); + if (flagTrack != 0) { + SETBIT(debugMcRec, flagTrack); + } + if (hf_decay::hf_cand_2prong::daughtersD0Main.contains(static_cast(std::abs(flagCharmBach))) && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::PionMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], bachelorTrack}; + auto pdgCodesDzeroDaughters = hf_decay::hf_cand_2prong::daughtersD0Main.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDzeroDaughters[0], pdgCodesDzeroDaughters[1], +kPiPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Pi) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } - if (indexRecK0 > -1) { - if (nPiToMuV0 == 0 && nKaToPiV0 == 0) { - registry.fill(HIST("hMassVsPtK0Matched"), candidateV0.pT, candidateV0.mK0Short); - } - if (nPiToMuV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedPiToMu"), candidateV0.pT, candidateV0.mK0Short); - } - if (nKaToPiV0 >= 1) { - registry.fill(HIST("hMassVsPtK0MatchedKaToPi"), candidateV0.pT, candidateV0.mK0Short); + } else if (hf_decay::hf_cand_2prong::daughtersD0Main.contains(static_cast(std::abs(flagCharmBach))) && flagTrack == hf_decay::hf_cand_reso::PartialMatchMc::KaonMatched) { + auto arrDaughtersReso = std::array{vecDaughtersReso[0], vecDaughtersReso[1], bachelorTrack}; + auto pdgCodesDzeroDaughters = hf_decay::hf_cand_2prong::daughtersD0Main.at(static_cast(std::abs(flagCharmBach))); + auto pdgCodesDaughters = std::array{pdgCodesDzeroDaughters[0], pdgCodesDzeroDaughters[1], +kKPlus}; + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Kplus) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, arrDaughtersReso, pdgCodeReso, pdgCodesDaughters, true, &sign, 3, &nKinkedTracks); + if (indexRec > -1) { + flagReso = sign * decayChannelFlag; + break; } } } - } // DecayChannel::DplusV0 - if (flag != 0) { - registry.fill(HIST("hMCRecCounter"), flag); + if (indexRec > -1) { + auto particleReso = particlesMc.iteratorAt(indexRec); + ptGen = particleReso.pt(); + invMassGen = RecoDecay::m(particleReso.p(), particleReso.e()); + } + rowHf2PrTrkMcRecReduced(indexHfCandCharm, indexCandTrBach, + flagReso, flagCharmBach, + flagCharmBachInterm, debugMcRec, + origin, ptGen, invMassGen, + nKinkedTracks); + } + registry.fill(HIST("hMCRecDebug"), debugMcRec); + if (indexRec > -1) { + registry.fill(HIST("hMCRecCounter"), flagReso); registry.fill(HIST("hMCRecOrigin"), origin); registry.fill(HIST("hMCRecMassGen"), invMassGen); - } else { - if (indexRecK0 > -1) { - SETBIT(debug, PartialMatchMc::K0Matched); - } - if (indexRecD0 > -1) { - SETBIT(debug, PartialMatchMc::D0Matched); - } - if (indexRecDstar > -1) { - SETBIT(debug, PartialMatchMc::DstarMatched); - } - if (indexRecDplus > -1) { - SETBIT(debug, PartialMatchMc::DplusMatched); - } - registry.fill(HIST("hMCRecDebug"), debug); } - rowHfDV0McRecReduced(indexHfCandCharm, indexCandV0, flag, debug, origin, signD0, motherPt, invMassGen); - } + if (flagCharmBach != 0) { + registry.fill(HIST("hMCRecCharmDau"), flagCharmBach); + } + } // fillMcRecoInfoDTrack - template + template void runDataCreation(Coll const& collision, CCands const& candsD, BBachV0s const& bachelorV0s, BBachTracks const& bachelorTrks, Tr const& tracks, - TrIU const&, + TrIU const& tracksIU, PParticles const& particlesMc, - aod::BCsWithTimestamps const&) + BCs const&) { // helpers for ReducedTables filling + float centrality = -1.f; + uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectCollisionsWithBadEvSel && hfRejMap != 0) { + return; + } int indexHfReducedCollision = hfReducedCollision.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; bool fillHfReducedCollision = false; - const bool doTracks = pairingType == PairingType::TrackOnly || pairingType == PairingType::V0AndTrack; - const bool doV0s = pairingType == PairingType::V0Only || pairingType == PairingType::V0AndTrack; - auto bc = collision.template bc_as(); + constexpr bool DoTracks = pairingType == PairingType::TrackOnly || pairingType == PairingType::V0AndTrack; + constexpr bool DoV0s = pairingType == PairingType::V0Only || pairingType == PairingType::V0AndTrack; + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, ccdbPathGrpMag, lut, false); @@ -836,9 +1018,8 @@ struct HfDataCreatorCharmResoReduced { bool fillHfCandD = false; std::array secondaryVertexD; std::array prongIdsD; - int8_t dtype{0}; std::array bdtScores = {-1.f, -1.f, -1.f, -1.f, -1.f, -1.f}; - std::vector charmHadDauTracks{}; + std::vector> charmHadDauTracks{}; varUtils.ptD = candD.pt(); if constexpr (dType == DType::Dstar) { varUtils.signD = candD.signSoftPi(); @@ -855,19 +1036,17 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[0] = candD.prong0Id(); prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = candD.prongPiId(); - std::copy(candD.pVectorProng0().begin(), candD.pVectorProng0().end(), varUtils.pVectorProng0.begin()); - std::copy(candD.pVectorProng1().begin(), candD.pVectorProng1().end(), varUtils.pVectorProng1.begin()); - std::copy(candD.pVecSoftPi().begin(), candD.pVecSoftPi().end(), varUtils.pVectorProng2.begin()); - charmHadDauTracks.push_back(candD.template prong0_as()); - charmHadDauTracks.push_back(candD.template prong1_as()); - charmHadDauTracks.push_back(candD.template prongPi_as()); - dtype = varUtils.signD * DType::Dstar; + varUtils.pVectorProng0 = candD.pVectorProng0(); + varUtils.pVectorProng1 = candD.pVectorProng1(); + varUtils.pVectorProng2 = candD.pVecSoftPi(); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong0Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong1Id())); if constexpr (withMl) { std::copy(candD.mlProbDstarToD0Pi().begin(), candD.mlProbDstarToD0Pi().end(), bdtScores.begin()); } registry.fill(HIST("hMassVsPtDstarAll"), varUtils.ptD, varUtils.invMassD - varUtils.invMassD0); } else if constexpr (dType == DType::Dplus) { - auto prong0 = candD.template prong0_as(); + auto prong0 = tracksIU.rawIteratorAt(candD.prong0Id()); varUtils.invMassD = hfHelper.invMassDplusToPiKPi(candD); secondaryVertexD[0] = candD.xSecondaryVertex(); secondaryVertexD[1] = candD.ySecondaryVertex(); @@ -876,17 +1055,16 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = candD.prong2Id(); varUtils.signD = prong0.sign(); - std::copy(candD.pVectorProng0().begin(), candD.pVectorProng0().end(), varUtils.pVectorProng0.begin()); - std::copy(candD.pVectorProng1().begin(), candD.pVectorProng1().end(), varUtils.pVectorProng1.begin()); - std::copy(candD.pVectorProng2().begin(), candD.pVectorProng2().end(), varUtils.pVectorProng2.begin()); - dtype = static_cast(varUtils.signD * DType::Dplus); - charmHadDauTracks.push_back(candD.template prong0_as()); - charmHadDauTracks.push_back(candD.template prong1_as()); - charmHadDauTracks.push_back(candD.template prong2_as()); + varUtils.pVectorProng0 = candD.pVectorProng0(); + varUtils.pVectorProng1 = candD.pVectorProng1(); + varUtils.pVectorProng2 = candD.pVectorProng2(); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong0Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong1Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong2Id())); if constexpr (withMl) { std::copy(candD.mlProbDplusToPiKPi().begin(), candD.mlProbDplusToPiKPi().end(), bdtScores.begin()); } - registry.fill(HIST("hMassVsPtDplusAll"), varUtils.ptD, varUtils.invMassD0); + registry.fill(HIST("hMassVsPtDplusAll"), varUtils.ptD, varUtils.invMassD); } else if constexpr (dType == DType::D0) { varUtils.invMassD0 = hfHelper.invMassD0ToPiK(candD); varUtils.invMassD0Bar = hfHelper.invMassD0barToKPi(candD); @@ -896,20 +1074,28 @@ struct HfDataCreatorCharmResoReduced { prongIdsD[0] = candD.prong0Id(); prongIdsD[1] = candD.prong1Id(); prongIdsD[2] = -1; // D0 does not have a third prong - charmHadDauTracks.push_back(candD.template prong0_as()); - charmHadDauTracks.push_back(candD.template prong1_as()); - std::copy(candD.pVectorProng0().begin(), candD.pVectorProng0().end(), varUtils.pVectorProng0.begin()); - std::copy(candD.pVectorProng1().begin(), candD.pVectorProng1().end(), varUtils.pVectorProng1.begin()); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong0Id())); + charmHadDauTracks.push_back(tracksIU.rawIteratorAt(candD.prong1Id())); + varUtils.pVectorProng0 = candD.pVectorProng0(); + varUtils.pVectorProng1 = candD.pVectorProng1(); varUtils.pVectorProng2 = {0.f, 0.f, 0.f}; // D0 does not have a third prong if constexpr (withMl) { std::copy(candD.mlProbD0().begin(), candD.mlProbD0().end(), bdtScores.begin()); std::copy(candD.mlProbD0bar().begin(), candD.mlProbD0bar().end(), bdtScores.begin() + 3); } + if (candD.isSelD0() >= cfgDmesCuts.selectionFlagD0) { + registry.fill(HIST("hMassVsPtD0All"), varUtils.ptD, varUtils.invMassD0); + } + if (candD.isSelD0bar() >= cfgDmesCuts.selectionFlagD0Bar) { + registry.fill(HIST("hMassVsPtD0BarAll"), varUtils.ptD, varUtils.invMassD0Bar); + } } // end of dType switch // Get single track variables float chi2TpcDauMax = -1.f; int nItsClsDauMin = 8, nTpcCrossRowsDauMin = 200; + float chi2TpcSoftPi = -1.f; + int nItsClsSoftPi = 8, nTpcCrossRowsSoftPi = 200; for (const auto& charmHadTrack : charmHadDauTracks) { if (charmHadTrack.itsNCls() < nItsClsDauMin) { nItsClsDauMin = charmHadTrack.itsNCls(); @@ -921,12 +1107,18 @@ struct HfDataCreatorCharmResoReduced { chi2TpcDauMax = charmHadTrack.tpcChi2NCl(); } } - + if constexpr (dType == DType::Dstar) { + auto softPi = tracksIU.rawIteratorAt(candD.prongPiId()); + nItsClsSoftPi = softPi.itsNCls(); + nTpcCrossRowsSoftPi = softPi.tpcNClsCrossedRows(); + chi2TpcSoftPi = softPi.tpcChi2NCl(); + charmHadDauTracks.push_back(softPi); + } // Loop on the bachelor V0s - if constexpr (doV0s) { + if constexpr (DoV0s) { for (const auto& v0 : bachelorV0s) { - auto trackPos = v0.template posTrack_as(); - auto trackNeg = v0.template negTrack_as(); + auto trackPos = tracksIU.rawIteratorAt(v0.posTrackId()); + auto trackNeg = tracksIU.rawIteratorAt(v0.negTrackId()); // Apply selsection auto v0DauTracks = std::array{trackPos, trackNeg}; if (!buildAndSelectV0(collision, prongIdsD, v0DauTracks)) { @@ -957,7 +1149,7 @@ struct HfDataCreatorCharmResoReduced { getPxPyPz(trackParK0, candidateV0.mom); } // compute resonance invariant mass and filling of QA histograms - if (TESTBIT(candidateV0.v0Type, K0s)) { + if (TESTBIT(candidateV0.v0Type, BachelorType::K0s)) { registry.fill(HIST("hMassVsPtK0s"), candidateV0.pT, candidateV0.mK0Short); switch (dType) { case DType::Dstar: @@ -990,8 +1182,8 @@ struct HfDataCreatorCharmResoReduced { break; // no other D meson types expected } // end of dType switch } // matched with K0s - bool isLambda = TESTBIT(candidateV0.v0Type, Lambda); - bool isAntiLambda = TESTBIT(candidateV0.v0Type, AntiLambda); + bool isLambda = TESTBIT(candidateV0.v0Type, BachelorType::Lambda); + bool isAntiLambda = TESTBIT(candidateV0.v0Type, BachelorType::AntiLambda); if (isLambda || isAntiLambda) { registry.fill(HIST("hMassVsPtLambda"), candidateV0.pT, candidateV0.mLambda); switch (dType) { @@ -1029,8 +1221,8 @@ struct HfDataCreatorCharmResoReduced { } varUtils.ptReso = RecoDecay::pt(RecoDecay::sumOfVec(varUtils.pVectorProng0, varUtils.pVectorProng1, candidateV0.mom)); if (!cfgQaPlots.applyCutsForQaHistograms || - (varUtils.invMassD0 > cfgQaPlots.cutMassDMin && - varUtils.invMassD0 < cfgQaPlots.cutMassDMax && + (((varUtils.invMassD0 > cfgQaPlots.cutMassDMin && varUtils.invMassD0 < cfgQaPlots.cutMassDMax) || + (varUtils.invMassD0Bar > cfgQaPlots.cutMassDMin && varUtils.invMassD0Bar < cfgQaPlots.cutMassDMax)) && candidateV0.mLambda > cfgQaPlots.cutMassLambdaMin && candidateV0.mLambda < cfgQaPlots.cutMassLambdaMax)) { if (isLambda) { @@ -1044,7 +1236,6 @@ struct HfDataCreatorCharmResoReduced { break; } // end of dType switch } // matched with Lambda or AntiLambda - // fill V0 table // if information on V0 already stored, go to next V0 if (!selectedV0s.count(v0.globalIndex())) { @@ -1061,21 +1252,20 @@ struct HfDataCreatorCharmResoReduced { } fillHfCandD = true; // Optional filling of MC Rec table, for now only implemented for Ds1->D*K0s and Ds2*->D+K0s - if constexpr (doMc && (dType == DType::Dstar || dType == DType::Dplus)) { - std::vector charmResoDauTracks{}; - for (const auto& track : charmHadDauTracks) { - charmResoDauTracks.push_back(track); - } - charmResoDauTracks.push_back(trackPos); - charmResoDauTracks.push_back(trackNeg); - int indexHfCandCharm = hfCandD3Pr.lastIndex() + 1; - int indexHfCandV0 = hfCandV0.lastIndex(); - fillMcRecoInfo(particlesMc, charmResoDauTracks, indexHfCandCharm, indexHfCandV0); + if constexpr (doMc) { + int indexHfCandCharm{-1}; + if constexpr (dType == DType::Dstar) + indexHfCandCharm = hfCandDstar.lastIndex() + 1; + else if constexpr (dType == DType::Dplus) + indexHfCandCharm = hfCandD3Pr.lastIndex() + 1; + else if constexpr (dType == DType::D0) + indexHfCandCharm = hfCandD2Pr.lastIndex() + 1; + fillMcRecoInfoDV0(particlesMc, candD, v0, tracksIU, indexHfCandCharm, selectedV0s[v0.globalIndex()]); } } // end of loop on V0 candidates } // end of do V0s // Loop on the bachelor tracks - if constexpr (doTracks) { + if constexpr (DoTracks) { for (const auto& trackIndex : bachelorTrks) { auto track = tracks.rawIteratorAt(trackIndex.trackId()); if (!isTrackSelected(track, prongIdsD)) { @@ -1195,8 +1385,10 @@ struct HfDataCreatorCharmResoReduced { } varUtils.ptReso = RecoDecay::pt(RecoDecay::sumOfVec(varUtils.pVectorProng0, varUtils.pVectorProng1, pVecTrack)); if (!cfgQaPlots.applyCutsForQaHistograms || - (varUtils.invMassD0 > cfgQaPlots.cutMassDMin && - varUtils.invMassD0 < cfgQaPlots.cutMassDMax)) { + ((varUtils.invMassD0 > cfgQaPlots.cutMassDMin && + varUtils.invMassD0 < cfgQaPlots.cutMassDMax) || + (varUtils.invMassD0Bar > cfgQaPlots.cutMassDMin && + varUtils.invMassD0Bar < cfgQaPlots.cutMassDMax))) { if (track.sign() > 0) { registry.fill(HIST("hMassD0Pi"), varUtils.ptReso, varUtils.invMassReso - varUtils.invMassD0); } else { @@ -1213,8 +1405,10 @@ struct HfDataCreatorCharmResoReduced { } varUtils.ptReso = RecoDecay::pt(RecoDecay::sumOfVec(varUtils.pVectorProng0, varUtils.pVectorProng1, pVecTrack)); if (!cfgQaPlots.applyCutsForQaHistograms || - (varUtils.invMassD0 > cfgQaPlots.cutMassDMin && - varUtils.invMassD0 < cfgQaPlots.cutMassDMax)) { + ((varUtils.invMassD0 > cfgQaPlots.cutMassDMin && + varUtils.invMassD0 < cfgQaPlots.cutMassDMax) || + (varUtils.invMassD0Bar > cfgQaPlots.cutMassDMin && + varUtils.invMassD0Bar < cfgQaPlots.cutMassDMax))) { if (track.sign() > 0) { registry.fill(HIST("hMassD0K"), varUtils.ptReso, varUtils.invMassReso - varUtils.invMassD0); } else { @@ -1225,14 +1419,16 @@ struct HfDataCreatorCharmResoReduced { // D0 p if (std::abs(track.tpcNSigmaPr()) < cfgSingleTrackCuts.maxNsigmaTpcPr) { if (track.sign() > 0) { - varUtils.invMassReso = RecoDecay::m(std::array{varUtils.pVectorProng0, varUtils.pVectorProng1, pVecTrack}, std::array{MassProton, MassKPlus, MassProton}); + varUtils.invMassReso = RecoDecay::m(std::array{varUtils.pVectorProng0, varUtils.pVectorProng1, pVecTrack}, std::array{MassPiPlus, MassKPlus, MassProton}); } else { - varUtils.invMassReso = RecoDecay::m(std::array{varUtils.pVectorProng1, varUtils.pVectorProng0, pVecTrack}, std::array{MassProton, MassKPlus, MassProton}); + varUtils.invMassReso = RecoDecay::m(std::array{varUtils.pVectorProng1, varUtils.pVectorProng0, pVecTrack}, std::array{MassPiPlus, MassKPlus, MassProton}); } varUtils.ptReso = RecoDecay::pt(RecoDecay::sumOfVec(varUtils.pVectorProng0, varUtils.pVectorProng1, pVecTrack)); if (!cfgQaPlots.applyCutsForQaHistograms || - (varUtils.invMassD0 > cfgQaPlots.cutMassDMin && - varUtils.invMassD0 < cfgQaPlots.cutMassDMax)) { + ((varUtils.invMassD0 > cfgQaPlots.cutMassDMin && + varUtils.invMassD0 < cfgQaPlots.cutMassDMax) || + (varUtils.invMassD0Bar > cfgQaPlots.cutMassDMin && + varUtils.invMassD0Bar < cfgQaPlots.cutMassDMax))) { if (track.sign() > 0) { registry.fill(HIST("hMassD0Proton"), varUtils.ptReso, varUtils.invMassReso - varUtils.invMassD0); } else { @@ -1246,7 +1442,8 @@ struct HfDataCreatorCharmResoReduced { } // end of DType switch // fill track table if (!selectedTracks.count(track.globalIndex())) { - hfTrackNoParam(indexHfReducedCollision, + hfTrackNoParam(track.globalIndex(), + indexHfReducedCollision, track.px(), track.py(), track.pz(), track.sign(), track.tpcNSigmaPi(), track.tpcNSigmaKa(), track.tpcNSigmaPr(), track.tofNSigmaPi(), track.tofNSigmaKa(), track.tofNSigmaPr(), @@ -1254,18 +1451,28 @@ struct HfDataCreatorCharmResoReduced { selectedTracks[track.globalIndex()] = hfTrackNoParam.lastIndex(); } fillHfCandD = true; + if constexpr (doMc) { + int indexHfCandCharm{-1}; + if constexpr (dType == DType::Dstar) + indexHfCandCharm = hfCandDstar.lastIndex() + 1; + else if constexpr (dType == DType::Dplus) + indexHfCandCharm = hfCandD3Pr.lastIndex() + 1; + else if constexpr (dType == DType::D0) + indexHfCandCharm = hfCandD2Pr.lastIndex() + 1; + fillMcRecoInfoDTrack(particlesMc, candD, track, tracks, indexHfCandCharm, selectedTracks[track.globalIndex()]); + } } // end of loop on bachelor tracks } // end of do tracks // 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 == DType::Dstar || dType == DType::Dplus) { + if constexpr (dType == DType::Dplus) { hfCandD3Pr(prongIdsD[0], prongIdsD[1], prongIdsD[2], indexHfReducedCollision, secondaryVertexD[0], secondaryVertexD[1], secondaryVertexD[2], candD.pxProng0(), candD.pyProng0(), candD.pzProng0(), candD.pxProng1(), candD.pyProng1(), candD.pzProng1(), varUtils.pVectorProng2[0], varUtils.pVectorProng2[1], varUtils.pVectorProng2[2], - nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax, dtype); + nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax, varUtils.signD); if constexpr (withMl) { hfCandD3PrMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); } @@ -1287,6 +1494,19 @@ struct HfDataCreatorCharmResoReduced { if constexpr (withMl) { hfCandD2PrMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); } + } else if constexpr (dType == DType::Dstar) { + hfCandDstar(prongIdsD[0], prongIdsD[1], prongIdsD[2], + indexHfReducedCollision, + secondaryVertexD[0], secondaryVertexD[1], secondaryVertexD[2], + candD.pxProng0(), candD.pyProng0(), candD.pzProng0(), + candD.pxProng1(), candD.pyProng1(), candD.pzProng1(), + varUtils.pVectorProng2[0], varUtils.pVectorProng2[1], varUtils.pVectorProng2[2], + nItsClsDauMin, nTpcCrossRowsDauMin, chi2TpcDauMax, + nItsClsSoftPi, nTpcCrossRowsSoftPi, chi2TpcSoftPi, + varUtils.signD); + if constexpr (withMl) { + hfCandD3PrMl(bdtScores[0], bdtScores[1], bdtScores[2], bdtScores[3], bdtScores[4], bdtScores[5]); + } } fillHfReducedCollision = true; if constexpr (dType == DType::Dstar) { @@ -1294,10 +1514,13 @@ struct HfDataCreatorCharmResoReduced { } else if constexpr (dType == DType::Dplus) { registry.fill(HIST("hMassVsPtDplusPaired"), candD.pt(), varUtils.invMassD); } else if constexpr (dType == DType::D0) { - registry.fill(HIST("hMassVsPtD0Paired"), candD.pt(), varUtils.invMassD0); - registry.fill(HIST("hMassVsPtD0BarPaired"), candD.pt(), varUtils.invMassD0Bar); + if (candD.isSelD0() >= cfgDmesCuts.selectionFlagD0) { + registry.fill(HIST("hMassVsPtD0Paired"), varUtils.ptD, varUtils.invMassD0); + } + if (candD.isSelD0bar() >= cfgDmesCuts.selectionFlagD0Bar) { + registry.fill(HIST("hMassVsPtD0BarPaired"), varUtils.ptD, varUtils.invMassD0Bar); + } } - registry.fill(HIST("hDType"), dtype); } } // candsD loop registry.fill(HIST("hEvents"), 1 + Event::Processed); @@ -1306,144 +1529,179 @@ struct HfDataCreatorCharmResoReduced { return; } registry.fill(HIST("hEvents"), 1 + Event::DV0Selected); - float centrality = -1.f; - uint16_t hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); // fill collision table if it contains a DPi pair a minima hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); } // end of runDataCreation function - // to be modified in the future to allow for different decay channels - template - void runMcGen(aod::McParticles const& particlesMc) + template + void runMcGen(McParticles const& mcParticles, + CCs const& collInfos, + McCollisions const& mcCollisions, + BCsInfo const&) { - // Match generated particles. - for (const auto& particle : particlesMc) { - int8_t sign{0}; - int8_t flag{0}; - int8_t signDstar{0}; - int8_t signDplus{0}; - int8_t signV0{0}; - int8_t origin = 0; - std::vector idxBhadMothers{}; - - if constexpr (decayChannel == DecayChannel::DstarV0) { - // Ds1 → D* K0 - if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kDS1, std::array{static_cast(Pdg::kDStar), +kK0}, true, &sign, 1)) { - registry.fill(HIST("hMCSignCounter"), sign); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCGenOrigin"), origin); - auto candV0MC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); - auto candDstarMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); - // K0 -> K0s -> π+π- - if (RecoDecay::isMatchedMCGen(particlesMc, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2)) { - // D* -> D0 π+ -> K-π+π+ - if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kD0), +static_cast(kPiPlus)}, true, &signDstar, 1)) { - auto candD0MC = particlesMc.rawIteratorAt(candDstarMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{-kKPlus, +kPiPlus, +kPiPlus}, true, &signDstar, 2)) { - flag = signDstar * DecayTypeMc::Ds1ToDstarK0ToD0PiK0s; - } else if (RecoDecay::isMatchedMCGen(particlesMc, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus, +kPiPlus, +kPi0}, true, &signDstar, 2) || - RecoDecay::isMatchedMCGen(particlesMc, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus, +kPiPlus, -kPi0}, true, &signDstar, 2)) { - flag = signDstar * DecayTypeMc::Ds1ToDstarK0ToD0PiK0sPart; + bool doV0s = (pairingType == PairingType::V0Only || pairingType == PairingType::V0AndTrack); + bool doTracks = (pairingType == PairingType::TrackOnly || pairingType == PairingType::V0AndTrack); + for (const auto& mcCollision : mcCollisions) { + // Slice the particles table to get the particles for the current MC collision + const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + // Slice the collisions table to get the collision info for the current MC collision + float centrality{-1.f}; + uint16_t rejectionMask{0}; + int nSplitColl = 0; + const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + hfEvSelMc.fillHistograms(mcCollision, rejectionMask, nSplitColl); + if (rejectCollisionsWithBadEvSel && rejectionMask != 0) { + // at least one event selection not satisfied --> reject all gen particles from this collision + continue; + } + for (const auto& particle : mcParticlesPerMcColl) { + int8_t sign{0}; + int8_t flag{0}; + int8_t signD{0}; + int8_t signBach{0}; + int8_t origin{0}; + bool matchedReso{false}, matchedD{false}, matchedV0Tr{false}; + std::vector idxBhadMothers{}; + if constexpr (dType == DType::Dstar) { + if (doV0s) { + // D* K0s + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarK0s) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDStar), +kK0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signBach, 2); + break; } - } else if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kPi0)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kPi0)}, true, &signDstar, 1)) { - auto candDplusMC = particlesMc.rawIteratorAt(candDstarMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMc, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2)) - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; } } - } else { - if (std::abs(particle.pdgCode()) == Pdg::kDS1) { - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCOriginCounterWrongDecay"), origin); + if (doTracks && !matchedReso) { + // D*+ pi- + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDstarPi) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDStar), -static_cast(kPiPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } } - } - // save information for task - if (flag == 0) { - continue; - } - - auto ptParticle = particle.pt(); - auto yParticle = RecoDecay::y(particle.pVector(), MassDS1); - auto etaParticle = particle.eta(); - - std::array ptProngs; - std::array yProngs; - std::array etaProngs; - int counter = 0; - for (const auto& daught : particle.daughters_as()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); - counter++; - } - registry.fill(HIST("hMCGenCounter"), flag, ptParticle); - rowHfResoMcGenReduced(flag, origin, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); - } else if constexpr (decayChannel == DecayChannel::DplusV0) { // Ds2Star → D+ K0 - if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kDS2Star, std::array{static_cast(Pdg::kDPlus), +kK0}, true, &sign, 1)) { - registry.fill(HIST("hMCSignCounter"), sign); - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCGenOrigin"), origin); - auto candV0MC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); - auto candDplusMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); - // K0 -> K0s -> π+π- - if (RecoDecay::isMatchedMCGen(particlesMc, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2)) { - // D* -> D0 π+ -> K-π+π+ - if (RecoDecay::isMatchedMCGen(particlesMc, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2)) { - flag = sign * DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi; + if (matchedReso && matchedV0Tr) { + auto candDstarMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kD0), +static_cast(kPiPlus)}, true, &signD, 1); + if (matchedD) { + auto candD0MC = mcParticles.rawIteratorAt(candDstarMC.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus}, true, &signD, 2); } } - } else if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kDS1, std::array{static_cast(Pdg::kDStar), +kK0}, true, &sign, 1)) { - auto candV0MC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); - // K0 -> K0s -> π+π- - if (RecoDecay::isMatchedMCGen(particlesMc, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signV0, 2)) { - auto candDstarMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); - // D* -> D+ π0/γ ->π+K-π+ π0/γ - if (RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kGamma)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), static_cast(kPi0)}, true, &signDstar, 1) || - RecoDecay::isMatchedMCGen(particlesMc, candDstarMC, Pdg::kDStar, std::array{static_cast(Pdg::kDPlus), -static_cast(kPi0)}, true, &signDstar, 1)) { - auto candDplusMC = particlesMc.rawIteratorAt(candDstarMC.daughtersIds().front()); - if (RecoDecay::isMatchedMCGen(particlesMc, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signDplus, 2)) - flag = sign * DecayTypeMc::Ds1ToDstarK0ToDplusPi0K0s; + } else if constexpr (dType == DType::Dplus) { + if (doV0s) { + // D+ K0s + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusK0s) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDPlus), +kK0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kK0, std::array{+kPiPlus, -kPiPlus}, true, &signBach, 2); + break; + } + } + if (!matchedReso) { + // D+ lambda + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusLambda) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDPlus), +kLambda0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kLambda0, std::array{+kProton, -kPiPlus}, true, &signBach, 1); + break; + } + } } } - } else { - if (std::abs(particle.pdgCode()) == Pdg::kDS2Star) { - origin = RecoDecay::getCharmHadronOrigin(particlesMc, particle, false, &idxBhadMothers); - registry.fill(HIST("hMCOriginCounterWrongDecay"), origin); + if (doTracks && !matchedReso) { + // D+ pi- + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToDplusPi) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kDPlus), -static_cast(kPiPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } + } + if (matchedReso && matchedV0Tr) { + auto candDplusMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candDplusMC, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &signD, 2); + } + } else if constexpr (dType == DType::D0) { + if (doV0s) { + // D0 Lambda + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Lambda) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kD0), +kLambda0}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + auto candV0MC = mcParticles.rawIteratorAt(particle.daughtersIds().back()); + matchedV0Tr = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candV0MC, kLambda0, std::array{+kProton, -kPiPlus}, true, &signBach, 1); + break; + } + } + } + if (doTracks && !matchedReso) { + // D0 pi+ + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Pi) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kD0), +static_cast(kPiPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } + // D0 K+ + if (!matchedReso) { + for (const auto& [decayChannelFlag, pdgCodeReso] : hf_decay::hf_cand_reso::particlesToD0Kplus) { + matchedReso = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, particle, pdgCodeReso, std::array{static_cast(Pdg::kD0), +static_cast(kKPlus)}, true, &sign, 1); + if (matchedReso) { + flag = sign * decayChannelFlag; + matchedV0Tr = true; + break; + } + } + } + } + if (matchedReso && matchedV0Tr) { + auto candD0MC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); + matchedD = RecoDecay::isMatchedMCGen(mcParticlesPerMcColl, candD0MC, Pdg::kD0, std::array{-kKPlus, +kPiPlus}, true, &signD, 2); } } - // save information for task - if (flag == 0) { - continue; - } - - auto ptParticle = particle.pt(); - auto yParticle = RecoDecay::y(particle.pVector(), MassDS2Star); - auto etaParticle = particle.eta(); - - std::array ptProngs; - std::array yProngs; - std::array etaProngs; - int counter = 0; - for (const auto& daught : particle.daughters_as()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); - counter++; + if (matchedReso && matchedD && matchedV0Tr) { + origin = RecoDecay::getCharmHadronOrigin(mcParticlesPerMcColl, particle, false, &idxBhadMothers); + registry.fill(HIST("hMCGenOrigin"), origin); + auto ptParticle = particle.pt(); + auto invMassGen = RecoDecay::m(particle.p(), particle.e()); + auto yParticle = RecoDecay::y(particle.pVector(), invMassGen); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.template daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + registry.fill(HIST("hMCGenCounter"), flag, ptParticle); + rowHfResoMcGenReduced(flag, origin, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], + invMassGen, rejectionMask); } - registry.fill(HIST("hMCGenCounter"), flag, ptParticle); - rowHfResoMcGenReduced(flag, origin, ptParticle, yParticle, etaParticle, - ptProngs[0], yProngs[0], etaProngs[0], - ptProngs[1], yProngs[1], etaProngs[1]); - } // Dplus V0 - } // for loop - } // gen + } + } + } // Process functions // No ML @@ -1465,7 +1723,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, tracksIU, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1489,7 +1747,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, tracks, bcs); + runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1539,7 +1797,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, tracksIU, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1563,7 +1821,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, tracks, bcs); + runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1613,7 +1871,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, tracksIU, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1637,7 +1895,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, tracks, bcs); + runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1670,61 +1928,6 @@ struct HfDataCreatorCharmResoReduced { } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrack, "Process D0 candidates paired with V0s and Tracks", false); - // MC - // D* - void processDstarV0MC(soa::Join const& collisions, - CandsDstarFiltered const& candsDstar, - aod::V0s const& v0s, - TracksIUWithPIDAndMC const& tracksIU, - aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) - { - int zvtxColl{0}; - int sel8Coll{0}; - int zvtxAndSel8Coll{0}; - int zvtxAndSel8CollAndSoftTrig{0}; - int allSelColl{0}; - for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); - auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); - } - runMcGen(particlesMc); - // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0MC, "Process Dstar candidates paired with V0s with MC matching", false); - - // Dplus - void processDplusV0MC(soa::Join const& collisions, - CandsDplusFiltered const& candsDplus, - aod::V0s const& v0s, - TracksIUWithPIDAndMC const& tracksIU, - aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) - { - int zvtxColl{0}; - int sel8Coll{0}; - int zvtxAndSel8Coll{0}; - int zvtxAndSel8CollAndSoftTrig{0}; - int allSelColl{0}; - for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); - auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); - auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); - } - runMcGen(particlesMc); - // handle normalization by the right number of collisions - hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); - } - PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0MC, "Process Dstar candidates paired with V0s with MC matching", false); - // D0 - // Not implemented yet - // ML // Data // D* @@ -1744,7 +1947,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, tracksIU, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1768,7 +1971,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, tracks, bcs); + runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1818,7 +2021,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, tracksIU, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1842,7 +2045,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, tracks, bcs); + runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1892,7 +2095,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, tracksIU, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1916,7 +2119,7 @@ struct HfDataCreatorCharmResoReduced { auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, tracks, bcs); + runDataCreation(collision, candsDThisColl, nullptr, trackIdsThisColl, tracks, tracks, nullptr, bcs); } // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); @@ -1950,39 +2153,356 @@ struct HfDataCreatorCharmResoReduced { PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrackWithMl, "Process D0 candidates paired with V0s and Tracks with ML info", false); // MC + // No ML // D* - void processDstarV0MCWithMl(soa::Join const& collisions, - CandsDstarFilteredWithMl const& candsDstar, - aod::V0s const& v0s, - TracksIUWithPIDAndMC const& tracksIU, - aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) - { - int zvtxColl{0}; + void processDstarV0MC(soa::Join const& collisions, + CandsDstarFilteredWithMc const& candsDstar, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; int sel8Coll{0}; int zvtxAndSel8Coll{0}; int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0MC, "Process Dstar candidates paired with V0s with MC matching", false); + + void processDstarTrackMC(soa::Join const& collisions, + CandsDstarFilteredWithMc const& candsDstar, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarTrackMC, "Process Dstar candidates paired with tracks with MC matching", false); + + void processDstarV0AndTrackMC(soa::Join const& collisions, + CandsDstarFilteredWithMc const& candsDstar, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0AndTrackMC, "Process Dstar candidates paired with V0s and tracks with MC matching", false); + + // Dplus + void processDplusV0MC(soa::Join const& collisions, + CandsDplusFilteredWithMc const& candsDplus, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0MC, "Process Dstar candidates paired with V0s with MC matching", false); + + void processDplusTrackMC(soa::Join const& collisions, + CandsDplusFilteredWithMc const& candsDplus, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusTrackMC, "Process Dplus candidates paired with tracks with MC matching", false); + + void processDplusV0AndTrackMC(soa::Join const& collisions, + CandsDplusFilteredWithMc const& candsDplus, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0AndTrackMC, "Process Dplus candidates paired with V0s and tracks with MC matching", false); + + // D0 + void processD0V0MC(soa::Join const& collisions, + CandsD0FilteredWithMc const& candsD0, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0MC, "Process D0 candidates paired with V0s with MC matching", false); + + void processD0TrackMC(soa::Join const& collisions, + CandsD0FilteredWithMc const& candsD0, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0TrackMC, "Process D0 candidates paired with tracks with MC matching", false); + + void processD0V0AndTrackMC(soa::Join const& collisions, + CandsD0FilteredWithMc const& candsD0, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollision, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); } - runMcGen(particlesMc); + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrackMC, "Process D0 candidates paired with V0s and tracks with MC matching", false); + // ML + // D* + void processDstarV0MCWithMl(soa::Join const& collisions, + CandsDstarFilteredWithMlAndMc const& candsDstar, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0MCWithMl, "Process Dstar candidates paired with V0s with MC matching and with ML info", false); + void processDstarTrackMCWithMl(soa::Join const& collisions, + CandsDstarFilteredWithMlAndMc const& candsDstar, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarTrackMCWithMl, "Process Dstar candidates paired with tracks with MC matching and with ML info", false); + + void processDstarV0AndTrackMCWithMl(soa::Join const& collisions, + CandsDstarFilteredWithMlAndMc const& candsDstar, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDstar.sliceBy(candsDstarPerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDstarV0AndTrackMCWithMl, "Process Dstar candidates paired with V0s and tracks with MC matching and with ML info", false); + // Dplus void processDplusV0MCWithMl(soa::Join const& collisions, - CandsDplusFilteredWithMl const& candsDplus, + CandsDplusFilteredWithMlAndMc const& candsDplus, aod::V0s const& v0s, TracksIUWithPIDAndMC const& tracksIU, aod::McParticles const& particlesMc, - aod::BCsWithTimestamps const& bcs) + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) { int zvtxColl{0}; int sel8Coll{0}; @@ -1990,19 +2510,159 @@ struct HfDataCreatorCharmResoReduced { int zvtxAndSel8CollAndSoftTrig{0}; int allSelColl{0}; for (const auto& collision : collisions) { - o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); auto thisCollId = collision.globalIndex(); - auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollision, thisCollId); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); - runDataCreation(collision, candsDThisColl, v0sThisColl, v0sThisColl, tracksIU, tracksIU, particlesMc, bcs); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); } - runMcGen(particlesMc); + runMcGen(particlesMc, collInfos, mcCollisions, bcs); // handle normalization by the right number of collisions hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); } PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0MCWithMl, "Process Dplus candidates paired with V0s with MC matching and with ML info", false); + + void processDplusTrackMCWithMl(soa::Join const& collisions, + CandsDplusFilteredWithMlAndMc const& candsDplus, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusTrackMCWithMl, "Process Dplus candidates paired with tracks with MC matching and with ML info", false); + + void processDplusV0AndTrackMCWithMl(soa::Join const& collisions, + CandsDplusFilteredWithMlAndMc const& candsDplus, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsDplus.sliceBy(candsDplusPerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processDplusV0AndTrackMCWithMl, "Process Dplus candidates paired with V0s and tracks with MC matching and with ML info", false); + // D0 - // Not implemented yet + void processD0V0MCWithMl(soa::Join const& collisions, + CandsD0FilteredWithMlAndMc const& candsD0, + aod::V0s const& v0s, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, nullptr, tracksIU, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0MCWithMl, "Process D0 candidates paired with V0s with MC matching and with ML info", false); + + void processD0TrackMCWithMl(soa::Join const& collisions, + CandsD0FilteredWithMlAndMc const& candsD0, + TracksWithPIDAndMC const& tracks, + aod::TrackAssoc const& trackIndices, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, trackIdsThisColl, trackIdsThisColl, tracks, tracks, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0TrackMCWithMl, "Process D0 candidates paired with tracks with MC matching and with ML info", false); + + void processD0V0AndTrackMCWithMl(soa::Join const& collisions, + CandsD0FilteredWithMlAndMc const& candsD0, + aod::V0s const& v0s, + aod::TrackAssoc const& trackIndices, + TracksWithPIDAndMC const& tracks, + TracksIUWithPIDAndMC const& tracksIU, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisionsNoCents const& collInfos, + aod::McCollisions const& mcCollisions) + { + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + auto thisCollId = collision.globalIndex(); + auto candsDThisColl = candsD0.sliceBy(candsD0PerCollisionWithMl, thisCollId); + auto v0sThisColl = v0s.sliceBy(candsV0PerCollision, thisCollId); + auto trackIdsThisColl = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsDThisColl, v0sThisColl, trackIdsThisColl, tracks, tracksIU, particlesMc, bcs); + } + runMcGen(particlesMc, collInfos, mcCollisions, bcs); + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorCharmResoReduced, processD0V0AndTrackMCWithMl, "Process D0 candidates paired with V0s and tracks with MC matching and with ML info", false); }; // struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx new file mode 100644 index 00000000000..cf6785d286c --- /dev/null +++ b/PWGHF/D2H/TableProducer/dataCreatorJpsiHadReduced.cxx @@ -0,0 +1,1244 @@ +// 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 dataCreatorJpsiHadReduced.cxx +/// \brief Creation of J/Psi-LF hadron pairs for Beauty hadron analyses +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/D2H/Utils/utilsRedDataFormat.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelectorPID.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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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::analysis; +using namespace o2::aod; +using namespace o2::constants::physics; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::hf_trkcandsel; + +enum Event : uint8_t { // TODO: check if needed + Processed = 0, + NoCharmHadPiSelected, + CharmHadPiSelected, + NEvent +}; + +enum DecayChannel : uint8_t { + B0ToJpsiK0Star = 0, + BplusToJpsiK, + BsToJpsiPhi +}; + +enum WrongCollisionType : uint8_t { + None = 0, + WrongAssociation, + SplitCollision, +}; + +/// Creation of Jpsi-Had pairs for Beauty hadrons +struct HfDataCreatorJpsiHadReduced { + // Produces AOD tables to store track information + // collision related tables + Produces hfReducedCollision; + Produces hfReducedCollCentrality; + Produces hfReducedQvector; + Produces hfReducedCollExtra; + Produces hfCollisionCounter; + // J/Psi related tables + Produces hfJpsi; + Produces hfRedJpsiCov; + // Ka bachelor related tables + Produces hfTrackLfDau0; + Produces hfTrackCovLfDau0; + Produces hfTrackLfDau1; + Produces hfTrackCovLfDau1; + // MC related tables + Produces rowHfJpsiKMcRecReduced; + Produces rowHfJpsiPhiMcRecReduced; + Produces rowHfBpMcGenReduced; + Produces rowHfBsMcGenReduced; + + Produces rowCandidateConfigBplus; + Produces rowCandidateConfigBs; + + Configurable skipRejectedCollisions{"skipRejectedCollisions", true, "skips collisions rejected by the event selection, instead of flagging only"}; + Configurable propagateToPCA{"propagateToPCA", true, "create tracks version propagated to PCA"}; + Configurable useAbsDCA{"useAbsDCA", false, "Minimise abs. distance rather than chi2"}; + Configurable useWeightedFinalPCA{"useWeightedFinalPCA", false, "Recalculate vertex position using track covariances, effective only if useAbsDCA is true"}; + Configurable maxR{"maxR", 200., "reject PCA's above this radius"}; + Configurable maxDZIni{"maxDZIni", 4., "reject (if>0) PCA candidate if tracks DZ exceeds threshold"}; + Configurable minParamChange{"minParamChange", 1.e-3, "stop iterations if largest change of any B0 is smaller than this"}; + Configurable minRelChi2Change{"minRelChi2Change", 0.9, "stop iterations is chi2/chi2old > this"}; + + Configurable runJpsiToee{"runJpsiToee", false, "Run analysis for J/Psi to ee (debug)"}; + struct : o2::framework::ConfigurableGroup { + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 5., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcElMax{"nSigmaTpcElMax", 4., "Electron nsigma cut on TPC only"}; + Configurable nSigmaTpcPiMin{"nSigmaTpcPiMin", 2.5, "Pion nsigma cut on TPC only"}; + Configurable nSigmaTpcPiMax{"nSigmaTpcPiMax", 99., "Pion nsigma cut on TPC only"}; + Configurable nSigmaTpcPrMin{"nSigmaTpcPrMin", -99., "Proton nsigma cut on TPC only"}; + Configurable nSigmaTpcPrMax{"nSigmaTpcPrMax", 99, "Proton nsigma cut on TPC only"}; + Configurable nSigmaTpcElCombinedMax{"nSigmaTpcElCombinedMax", 4., "Electron Nsigma cut on TPC combined with TOF"}; + Configurable nSigmaTpcPiCombinedMin{"nSigmaTpcPiCombinedMin", 2.5, "Pion Nsigma cut on TPC combined with TOF"}; + Configurable nSigmaTpcPiCombinedMax{"nSigmaTpcPiCombinedMax", 99., "Pion Nsigma cut on TPC combined with TOF"}; + Configurable nSigmaTpcPrCombinedMin{"nSigmaTpcPrCombinedMin", -99., "Proton Nsigma cut on TPC combined with TOF"}; + Configurable nSigmaTpcPrCombinedMax{"nSigmaTpcPrCombinedMax", 99, "Proton Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 5., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofElMax{"nSigmaTofElMax", 4., "Electron nsigma cut on TPC only"}; + Configurable nSigmaTofPiMin{"nSigmaTofPiMin", -99, "Pion nsigma cut on TPC only"}; + Configurable nSigmaTofPiMax{"nSigmaTofPiMax", 99., "Pion nsigma cut on TPC only"}; + Configurable nSigmaTofPrMin{"nSigmaTofPrMin", -99, "Proton nsigma cut on TPC only"}; + Configurable nSigmaTofPrMax{"nSigmaTofPrMax", 99., "Proton nsigma cut on TPC only"}; + Configurable nSigmaTofElCombinedMax{"nSigmaTofElCombinedMax", 4., "Electron Nsigma cut on TOF combined with TPC"}; + Configurable nSigmaTofPiCombinedMin{"nSigmaTofPiCombinedMin", 2.5, "Pion Nsigma cut on TOF combined with TPC"}; + Configurable nSigmaTofPiCombinedMax{"nSigmaTofPiCombinedMax", 99., "Pion Nsigma cut on TOF combined with TPC"}; + Configurable nSigmaTofPrCombinedMin{"nSigmaTofPrCombinedMin", -99., "Proton Nsigma cut on TOF combined with TPC"}; + Configurable nSigmaTofPrCombinedMax{"nSigmaTofPrCombinedMax", 99, "Proton Nsigma cut on TOF combined with TPC"}; + // AND logic for TOF+TPC PID (as in Run2) + Configurable usePidTpcAndTof{"usePidTpcAndTof", true, "Use AND logic for TPC and TOF PID"}; + } selectionsPid; + Configurable ptJpsiMin{"ptJpsiMin", 0., "Lower bound of J/Psi pT"}; + Configurable ptJpsiMax{"ptJpsiMax", 50., "Upper bound of J/Psi pT"}; + Configurable useTrackIsGlobalTrackWoDCA{"useTrackIsGlobalTrackWoDCA", true, "check isGlobalTrackWoDCA status for the bachelor tracks"}; + Configurable ptTrackMin{"ptTrackMin", 0.5, "minimum bachelor track pT threshold (GeV/c)"}; + Configurable absEtaTrackMax{"absEtaTrackMax", 0.8, "maximum bachelor track absolute eta threshold"}; + Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for bachelor track DCA XY pT-dependent cut"}; + Configurable> cutsTrackDCA{"cutsTrackDCA", {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 bachelor track"}; + // topological/kinematic cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_jpsi_to_mu_mu::vecBinsPt}, "J/Psi pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_jpsi_to_mu_mu::Cuts[0], hf_cuts_jpsi_to_mu_mu::NBinsPt, hf_cuts_jpsi_to_mu_mu::NCutVars, hf_cuts_jpsi_to_mu_mu::labelsPt, hf_cuts_jpsi_to_mu_mu::labelsCutVar}, "J/Psi candidate selection per pT bin"}; + Configurable invMassWindowJpsiHad{"invMassWindowJpsiHad", 0.3, "invariant-mass window for Jpsi-Had pair preselections (GeV/c2)"}; + Configurable deltaMPhiMax{"deltaMPhiMax", 0.02, "invariant-mass window for phi preselections (GeV/c2) (only for Bs->J/PsiPhi)"}; + Configurable cpaMin{"cpaMin", 0., "Minimum cosine of pointing angle for B candidates"}; + Configurable decLenMin{"decLenMin", 0., "Minimum decay length for B candidates"}; + + // magnetic field setting from CCDB + 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)"}; + + HfHelper hfHelper; + + TrackSelectorPi selectorPion; + TrackSelectorPr selectorProton; + TrackSelectorEl selectorElectron; + + // CCDB service + Service ccdb; + // O2DatabasePDG service + Service pdg; + + using TracksPid = soa::Join; + using TracksPidWithSel = soa::Join; + using TracksPidWithSelAndMc = soa::Join; + using CollisionsWCMcLabels = soa::Join; + using BCsInfo = soa::Join; + + Preslice candsJpsiPerCollision = aod::track_association::collisionId; + Preslice trackIndicesPerCollision = aod::track_association::collisionId; + Preslice mcParticlesPerMcCollision = aod::mcparticle::mcCollisionId; + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + + o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + int runNumber; + double bz{0.}; + double invMass2JpsiHadMin, invMass2JpsiHadMax; + bool isHfCandBhadConfigFilled = false; + + o2::hf_evsel::HfEventSelection hfEvSel; + o2::hf_evsel::HfEventSelectionMc hfEvSelMc; + + o2::vertexing::DCAFitterN<2> df2; + o2::vertexing::DCAFitterN<3> df3; + o2::vertexing::DCAFitterN<4> df4; + + HistogramRegistry registry{"registry"}; + + void init(InitContext& initContext) + { + selectorPion.setRangePtTpc(selectionsPid.ptPidTpcMin, selectionsPid.ptPidTpcMax); + selectorPion.setRangeNSigmaTpc(-selectionsPid.nSigmaTpcPiMax, selectionsPid.nSigmaTpcPiMax); + selectorPion.setRangeNSigmaTpcCondTof(-selectionsPid.nSigmaTpcPiCombinedMax, selectionsPid.nSigmaTpcPiCombinedMax); + selectorPion.setRangePtTof(selectionsPid.ptPidTofMin, selectionsPid.ptPidTofMax); + selectorPion.setRangeNSigmaTof(-selectionsPid.nSigmaTofPiMax, selectionsPid.nSigmaTofPiMax); + selectorPion.setRangeNSigmaTofCondTpc(-selectionsPid.nSigmaTofPiCombinedMax, selectionsPid.nSigmaTofPiCombinedMax); + + selectorProton.setRangePtTpc(selectionsPid.ptPidTpcMin, selectionsPid.ptPidTpcMax); + selectorProton.setRangeNSigmaTpc(-selectionsPid.nSigmaTpcPrMax, selectionsPid.nSigmaTpcPrMax); + selectorProton.setRangeNSigmaTpcCondTof(-selectionsPid.nSigmaTpcPrCombinedMax, selectionsPid.nSigmaTpcPrCombinedMax); + selectorProton.setRangePtTof(selectionsPid.ptPidTofMin, selectionsPid.ptPidTofMax); + selectorProton.setRangeNSigmaTof(-selectionsPid.nSigmaTofPrMax, selectionsPid.nSigmaTofPrMax); + selectorProton.setRangeNSigmaTofCondTpc(-selectionsPid.nSigmaTofPrCombinedMax, selectionsPid.nSigmaTofPrCombinedMax); + + selectorElectron.setRangePtTpc(selectionsPid.ptPidTpcMin, selectionsPid.ptPidTpcMax); + selectorElectron.setRangeNSigmaTpc(-selectionsPid.nSigmaTpcElMax, selectionsPid.nSigmaTpcElMax); + selectorElectron.setRangeNSigmaTpcCondTof(-selectionsPid.nSigmaTofElCombinedMax, selectionsPid.nSigmaTofElCombinedMax); + selectorElectron.setRangePtTof(selectionsPid.ptPidTofMin, selectionsPid.ptPidTofMax); + selectorElectron.setRangeNSigmaTof(-selectionsPid.nSigmaTofElMax, selectionsPid.nSigmaTofElMax); + selectorElectron.setRangeNSigmaTofCondTpc(-selectionsPid.nSigmaTofElCombinedMax, selectionsPid.nSigmaTofElCombinedMax); + + std::array doProcess = {doprocessJpsiKData, doprocessJpsiKMc, doprocessJpsiPhiData, doprocessJpsiPhiMc}; + if (std::accumulate(doProcess.begin(), doProcess.end(), 0) != 1) { + LOGP(fatal, "One and only one process function can be enabled at a time, please fix your configuration!"); + } + + // Set up the histogram registry + constexpr int kNBinsSelections = 2 + aod::SelectionStep::RecoPID; + 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"; + static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; + registry.add("hSelectionsJpsi", "J/Psi selection;;#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("hSelectionsJpsi"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + + constexpr int kNBinsEvents = NEvent; + std::string labelsEvents[kNBinsEvents]; + labelsEvents[Event::Processed] = "processed"; + labelsEvents[Event::NoCharmHadPiSelected] = "without CharmHad-Pi pairs"; + labelsEvents[Event::CharmHadPiSelected] = "with CharmHad-Pi pairs"; + static const AxisSpec axisEvents = {kNBinsEvents, 0.5, kNBinsEvents + 0.5, ""}; + registry.add("hEvents", "Events;;entries", HistType::kTH1F, {axisEvents}); + for (int iBin = 0; iBin < kNBinsEvents; iBin++) { + registry.get(HIST("hEvents"))->GetXaxis()->SetBinLabel(iBin + 1, labelsEvents[iBin].data()); + } + + registry.add("hMassJpsi", "J/Psi mass;#it{M}_{#mu#mu} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{600, 2.8, 3.4, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hPtJpsi", "J/Psi #it{p}_{T};#it{p}_{T} (GeV/#it{c});Counts", {HistType::kTH1F, {{(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("hCpaJpsi", "J/Psi cos#theta_{p};J/Psi cos#theta_{p};Counts", {HistType::kTH1F, {{200, -1., 1, "J/Psi cos#theta_{p}"}}}); + std::shared_ptr hFitCandidatesJpsi = registry.add("hFitCandidatesJpsi", "Jpsi candidate counter", {HistType::kTH1D, {axisCands}}); + std::shared_ptr hFitCandidatesBPlus = registry.add("hFitCandidatesBPlus", "hFitCandidatesBPlus candidate counter", {HistType::kTH1D, {axisCands}}); + std::shared_ptr hFitCandidatesBS = registry.add("hFitCandidatesBS", "hFitCandidatesBS candidate counter", {HistType::kTH1D, {axisCands}}); + setLabelHistoCands(hFitCandidatesJpsi); + setLabelHistoCands(hFitCandidatesBPlus); + setLabelHistoCands(hFitCandidatesBS); + if (doprocessJpsiKData || doprocessJpsiKMc) { + registry.add("hPtKaon", "Kaon #it{p}_{T};#it{p}_{T} (GeV/#it{c});Counts", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("hMassJpsiKaon", "J/Psi Kaon mass;#it{M}_{J/#PsiK} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{800, 4.9, 5.7}}}); + } else if (doprocessJpsiPhiData || doprocessJpsiPhiMc) { + registry.add("hPtPhi", "Phi #it{p}_{T};#it{p}_{T} (GeV/#it{c});Counts", {HistType::kTH1F, {{100, 0., 10.}}}); + registry.add("hMassPhi", "Phi mass;#it{M}_{KK} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{200, 0.9, 1.2}}}); + registry.add("hMassJpsiPhi", "J/Psi Phi mass;#it{M}_{J/#Psi#phi} (GeV/#it{c}^{2});Counts", {HistType::kTH1F, {{800, 4.9, 5.7}}}); + std::shared_ptr hFitCandidatesPhi = registry.add("hFitCandidatesPhi", "Phi candidate counter", {HistType::kTH1D, {axisCands}}); + setLabelHistoCands(hFitCandidatesPhi); + } + + df2.setPropagateToPCA(propagateToPCA); + df2.setMaxR(maxR); + df2.setMaxDZIni(maxDZIni); + df2.setMinParamChange(minParamChange); + df2.setMinRelChi2Change(minRelChi2Change); + df2.setUseAbsDCA(useAbsDCA); + df2.setWeightedFinalPCA(useWeightedFinalPCA); + df2.setMatCorrType(noMatCorr); + + df3.setPropagateToPCA(propagateToPCA); + df3.setMaxR(maxR); + df3.setMaxDZIni(maxDZIni); + df3.setMinParamChange(minParamChange); + df3.setMinRelChi2Change(minRelChi2Change); + df3.setUseAbsDCA(useAbsDCA); + df3.setWeightedFinalPCA(useWeightedFinalPCA); + df3.setMatCorrType(noMatCorr); + + df4.setPropagateToPCA(propagateToPCA); + df4.setMaxR(maxR); + df4.setMaxDZIni(maxDZIni); + df4.setMinParamChange(minParamChange); + df4.setMinRelChi2Change(minRelChi2Change); + df4.setUseAbsDCA(useAbsDCA); + df4.setWeightedFinalPCA(useWeightedFinalPCA); + df4.setMatCorrType(noMatCorr); + + // Configure CCDB access + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + runNumber = 0; + + if (doprocessJpsiKData || doprocessJpsiKMc) { + invMass2JpsiHadMin = (MassBPlus - invMassWindowJpsiHad) * (MassBPlus - invMassWindowJpsiHad); + invMass2JpsiHadMax = (MassBPlus + invMassWindowJpsiHad) * (MassBPlus + invMassWindowJpsiHad); + } else if (doprocessJpsiPhiData || doprocessJpsiPhiMc) { + invMass2JpsiHadMin = (MassBS - invMassWindowJpsiHad) * (MassBS - invMassWindowJpsiHad); + invMass2JpsiHadMax = (MassBS + invMassWindowJpsiHad) * (MassBS + invMassWindowJpsiHad); + } + + // init HF event selection helper + hfEvSel.init(registry); + if (doprocessJpsiKMc || doprocessJpsiPhiMc) { + const auto& workflows = initContext.services().get(); + for (const DeviceSpec& device : workflows.devices) { + if (device.name.compare("hf-data-creator-jpsi-had-reduced") == 0) { + // init HF event selection helper + hfEvSelMc.init(device, registry); + break; + } + } + } + } + + /// Topological cuts + /// \param candidate is candidate + /// \param trackPos is the positive track + /// \param trackNeg is the negative track + /// \return true if candidate passes all cuts + template + bool selectionTopol(const T1& candidate, const T2& trackPos, const T2& trackNeg) + { + auto candpT = candidate.pt(); + auto candInvMass = runJpsiToee ? hfHelper.invMassJpsiToEE(candidate) : hfHelper.invMassJpsiToMuMu(candidate); + auto pseudoPropDecLen = candidate.decayLengthXY() * candInvMass / candpT; + auto pTBin = findBin(binsPt, candpT); + if (pTBin == -1) { + return false; + } + + // check that the candidate pT is within the analysis range + if (candpT < ptJpsiMin || candpT >= ptJpsiMax) { + return false; + } + + // cut on μ+ μ− (e+e−) invariant mass + if (std::abs(candInvMass - o2::constants::physics::MassJPsi) > cuts->get(pTBin, "m")) { + return false; + } + + // cut on daughter pT (same cut used for both channels) + if (trackNeg.pt() < cuts->get(pTBin, "pT mu") || trackPos.pt() < cuts->get(pTBin, "pT mu")) { + return false; + } + + // decay length + if (candidate.decayLength() < cuts->get(pTBin, "decay length")) { + return false; + } + + // decay length in XY plane + if (candidate.decayLengthXY() < cuts->get(pTBin, "decay length xy")) { + return false; + } + + // cosine of pointing angle + if (candidate.cpa() < cuts->get(pTBin, "cpa")) { + return false; + } + + // cosine of pointing angle XY + if (candidate.cpaXY() < cuts->get(pTBin, "cpa xy")) { + return false; + } + + // product of daughter impact parameters + if (candidate.impactParameterProduct() > cuts->get(pTBin, "d0xd0")) { + return false; + } + + // pseudoproper decay length + if (pseudoPropDecLen < cuts->get(pTBin, "pseudoprop. decay length")) { + return false; + } + + return true; + } + + /// Kaon selection (J/Psi K+ <-- B+) + /// \param track is the considered track + /// \param trackParCov is the track parametrisation + /// \param dca is the 2-D array with track DCAs + /// \param jPsiDautracks J/Psi daughter tracks + /// \return true if track passes all cuts + template + bool isTrackSelected(const T1& track, const T2& trackParCov, const T3& dca, const std::vector& jPsiDautracks) + { + // check isGlobalTrackWoDCA status for kaons if wanted + if (useTrackIsGlobalTrackWoDCA && !track.isGlobalTrackWoDCA()) { + return false; + } + // minimum pT, eta, and DCA selection + if (trackParCov.getPt() < ptTrackMin || std::abs(trackParCov.getEta()) > absEtaTrackMax || !isSelectedTrackDCA(trackParCov, dca, binsPtTrack, cutsTrackDCA)) { + return false; + } + // reject kaons that are J/Psi daughters + for (const auto& trackJpsi : jPsiDautracks) { + if (track.globalIndex() == trackJpsi.globalIndex()) { + return false; + } + } + + return true; + } + + template + bool isSelectedJpsiDauPid(const T1& track) + { + int pidPion = -1; + int pidProton = -1; + int pidElectron = -1; + + if (selectionsPid.usePidTpcAndTof) { + pidPion = selectorPion.statusTpcAndTof(track, track.tpcNSigmaPi(), track.tofNSigmaPi()); + pidProton = selectorProton.statusTpcAndTof(track, track.tpcNSigmaPr(), track.tofNSigmaPr()); + pidElectron = selectorElectron.statusTpcAndTof(track, track.tpcNSigmaEl(), track.tofNSigmaEl()); + } else { + pidPion = selectorPion.statusTpcOrTof(track, track.tpcNSigmaPi(), track.tofNSigmaPi()); + pidProton = selectorProton.statusTpcOrTof(track, track.tpcNSigmaPr(), track.tofNSigmaPr()); + pidElectron = selectorElectron.statusTpcOrTof(track, track.tpcNSigmaEl(), track.tofNSigmaEl()); + } + + if (pidPion == TrackSelectorPID::Rejected || + pidProton == TrackSelectorPID::Rejected || + pidElectron == TrackSelectorPID::Rejected) { + return false; + } + return true; + } + + /// B meson preselections + /// \param momentum is the B meson momentum + /// \param secondaryVertex is the reconstructed secondary vertex + /// \param collision is the reconstructed collision + template + bool isBSelected(const T1& momentum, const T2& secondaryVertex, const T3& collision) + { + // B candidate CPA + if (RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex, momentum) < cpaMin) { + return false; + } + + // B candidate decay length + if (RecoDecay::distance(std::array{collision.posX(), collision.posY(), collision.posZ()}, secondaryVertex) < decLenMin) { + return false; + } + + return true; + } + + /// Checks if the B meson is associated with a different collision than the one it was generated in + /// \param particleMother is the mother particle + /// \param collision is the reconstructed collision + /// \param indexCollisionMaxNumContrib is the index of the collision associated with a given MC collision with the largest number of contributors. + /// \param flagWrongCollision is the flag indicating if whether the associated collision is incorrect. + template + void checkWrongCollision(const PParticle& particleMother, + const CColl& collision, + const int64_t& indexCollisionMaxNumContrib, + int8_t& flagWrongCollision) + { + + if (particleMother.mcCollision().globalIndex() != collision.mcCollisionId()) { + flagWrongCollision = WrongCollisionType::WrongAssociation; + } else { + if (collision.globalIndex() != indexCollisionMaxNumContrib) { + flagWrongCollision = WrongCollisionType::SplitCollision; + } + } + } + + /// Function for filling MC reco information in the tables + /// \param particlesMc is the table with MC particles + /// \param vecDaughtersB is the vector with all daughter tracks (Jpsi daughters in first position) + /// \param indexHfCandJpsi is the index of the Jpsi candidate + /// \param selectedTracksBach is the map with the indices of selected bachelor pion tracks + template + void fillMcRecoInfo(const CColl& collision, + const PParticles& particlesMc, + const std::vector& vecDaughtersB, + int& indexHfCandJpsi, + std::array, 2> selectedTracksBach, + const int64_t indexCollisionMaxNumContrib) + { + + // we check the MC matching to be stored + int8_t sign{0}, flag{0}, channel{0}; + int8_t flagWrongCollision{WrongCollisionType::None}; + int8_t debug{0}; + float motherPt{-1.f}; + + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + // B+ → J/Psi K+ → (µ+µ-) K+ + int indexRec = -1; + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{-kMuonMinus, +kMuonMinus, +kKPlus}, true, &sign, 3); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2]}, Pdg::kBPlus, std::array{-kElectron, +kElectron, +kKPlus}, true, &sign, 3); + } + if (indexRec > -1) { + // J/Psi → µ+µ- + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kMuonMinus, +kMuonMinus}, true); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kElectron, +kElectron}, true); + } + if (indexRec > -1) { + flag = sign * o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } else { + debug = 1; + LOGF(debug, "B+ decays in the expected final state but the condition on the intermediate state is not fulfilled"); + } + + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersB.back().template mcParticle_as(), Pdg::kBPlus, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); + } + } + rowHfJpsiKMcRecReduced(indexHfCandJpsi, selectedTracksBach[0][vecDaughtersB.back().globalIndex()], flag, channel, flagWrongCollision, debug, motherPt); + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + // Bs → J/Psi phi → (µ+µ-) (K+K-) + int indexRec = -1; + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kBS, std::array{-kMuonMinus, +kMuonMinus, +kKPlus, -kKPlus}, true, &sign, 4); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1], vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kBS, std::array{-kElectron, +kElectron, +kKPlus, -kKPlus}, true, &sign, 4); + } + if (indexRec > -1) { + // J/Psi → µ+µ- + if (!runJpsiToee) { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kMuonMinus, +kMuonMinus}, true, &sign, 1); + } else { + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[0], vecDaughtersB[1]}, Pdg::kJPsi, std::array{-kElectron, +kElectron}, true, &sign, 1); + } + if (indexRec > -1) { + flag = sign * o2::hf_decay::hf_cand_beauty::BsToJpsiKK; + indexRec = RecoDecay::getMatchedMCRec(particlesMc, std::array{vecDaughtersB[2], vecDaughtersB[3]}, Pdg::kPhi, std::array{-kKPlus, +kKPlus}, true, &sign, 1); + if (indexRec > -1) { + channel = o2::hf_decay::hf_cand_beauty::BsToJpsiPhi; + } else { + debug = 1; + LOGF(debug, "Bs decays in the expected final state but the condition on the phi intermediate state is not fulfilled"); + } + } else { + debug = 1; + LOGF(debug, "Bs decays in the expected final state but the condition on the J/Psi intermediate state is not fulfilled"); + } + + auto indexMother = RecoDecay::getMother(particlesMc, vecDaughtersB.back().template mcParticle_as(), Pdg::kBS, true); + if (indexMother >= 0) { + auto particleMother = particlesMc.rawIteratorAt(indexMother); + motherPt = particleMother.pt(); + checkWrongCollision(particleMother, collision, indexCollisionMaxNumContrib, flagWrongCollision); + } + } + rowHfJpsiPhiMcRecReduced(indexHfCandJpsi, selectedTracksBach[0][vecDaughtersB.back().globalIndex()], selectedTracksBach[1][vecDaughtersB.back().globalIndex()], flag, channel, flagWrongCollision, debug, motherPt); + } + } + + /// Calculates the index of the collision with the maximum number of contributions. + ///\param collisions are the collisions to search through. + ///\return The index of the collision with the maximum number of contributions. + template + int64_t getIndexCollisionMaxNumContrib(const CColl& collisions) + { + unsigned maxNumContrib = 0; + int64_t indexCollisionMaxNumContrib = -1; + for (const auto& collision : collisions) { + if (collision.numContrib() > maxNumContrib) { + maxNumContrib = collision.numContrib(); + indexCollisionMaxNumContrib = collision.globalIndex(); + } + } + return indexCollisionMaxNumContrib; + } + + template + void runMcGen(aod::McCollision const& mcCollision, + aod::McParticles const& particlesMc, + CollisionsWCMcLabels const& collisions, + BCsInfo const&) + { + // Check event selection + float centDummy{-1.f}, centFT0C{-1.f}, centFT0M{-1.f}; + const auto collSlice = collisions.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + auto hfRejMap = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centDummy); + if (skipRejectedCollisions && hfRejMap != 0) { + return; + } + + const auto mcParticlesPerMcColl = particlesMc.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); + + // Match generated particles. + for (const auto& particle : mcParticlesPerMcColl) { + int8_t sign{0}, flag{0}, channel{0}; + if constexpr (decChannel == DecayChannel::BplusToJpsiK) { + // B+ → J/Psi K+ → (µ+µ-) K+ + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBPlus, std::array{static_cast(Pdg::kJPsi), +kKPlus}, true, &sign)) { + // Match J/Psi -> µ+µ- + auto candJpsiMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + // Printf("Checking J/Psi -> µ+µ-"); + if (!runJpsiToee) { + if (RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kMuonMinus, +kMuonMinus}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } + } else { // debug + // Printf("Checking J/Psi -> e+e-"); + if (RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kElectron, +kElectron}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } + } + } + + // save information for B+ task + if (std::abs(flag) != o2::hf_decay::hf_cand_beauty::BplusToJpsiK) { + continue; + } + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(particle.pVector(), MassBPlus); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + rowHfBpMcGenReduced(flag, channel, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + // Bs → J/Psi phi → (µ+µ-) (K+K-) + if (RecoDecay::isMatchedMCGen(particlesMc, particle, Pdg::kBS, std::array{static_cast(Pdg::kJPsi), +kKPlus, -kKPlus}, true, &sign, 2)) { + // Match J/Psi -> µ+µ- and phi -> K+K- + auto candJpsiMC = particlesMc.rawIteratorAt(particle.daughtersIds().front()); + auto candPhiMC = particlesMc.rawIteratorAt(particle.daughtersIds().back()); + // Printf("Checking J/Psi -> µ+µ- and phi -> K+K-"); + if (runJpsiToee && RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kElectron, +kElectron}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BsToJpsiKK; + } else if (!runJpsiToee && RecoDecay::isMatchedMCGen(particlesMc, candJpsiMC, static_cast(Pdg::kJPsi), std::array{-kMuonMinus, +kMuonMinus}, true)) { + flag = sign * o2::hf_decay::hf_cand_beauty::BsToJpsiKK; + } + // Check phi -> K+K- + if (RecoDecay::isMatchedMCGen(particlesMc, candPhiMC, static_cast(Pdg::kPhi), std::array{-kKPlus, +kKPlus}, true)) { + channel = o2::hf_decay::hf_cand_beauty::BsToJpsiPhi; + } + } + + // save information for Bs task + if (std::abs(flag) != o2::hf_decay::hf_cand_beauty::BsToJpsiKK) { + continue; + } + + auto ptParticle = particle.pt(); + auto yParticle = RecoDecay::y(particle.pVector(), MassBPlus); + auto etaParticle = particle.eta(); + + std::array ptProngs; + std::array yProngs; + std::array etaProngs; + int counter = 0; + for (const auto& daught : particle.daughters_as()) { + ptProngs[counter] = daught.pt(); + etaProngs[counter] = daught.eta(); + yProngs[counter] = RecoDecay::y(daught.pVector(), pdg->Mass(daught.pdgCode())); + counter++; + } + rowHfBsMcGenReduced(flag, channel, ptParticle, yParticle, etaParticle, + ptProngs[0], yProngs[0], etaProngs[0], + ptProngs[1], yProngs[1], etaProngs[1], hfRejMap, centFT0C, centFT0M); + } + } // gen + } + + // Jpsi candidate selection + template + void runDataCreation(Coll const& collision, + JpsiCands const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TTracks const&, + PParticles const& particlesMc, + uint64_t const& indexCollisionMaxNumContrib, + BBCs const&) + { + + registry.fill(HIST("hEvents"), 1 + Event::Processed); + float centrality = -1.f; + auto hfRejMap = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (skipRejectedCollisions && hfRejMap != 0) { + return; + } + + // helpers for ReducedTables filling + int indexHfReducedCollision = hfReducedCollision.lastIndex() + 1; + // std::map where the key is the track.globalIndex() and + // the value is the track index in the table of the selected tracks + std::map selectedTracksBach; + std::map selectedTracksBach2; // for the second daughter (for B0 and Bs) + + bool fillHfReducedCollision = false; + + auto primaryVertex = getPrimaryVertex(collision); + + // Set the magnetic field from ccdb. + // The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, + // but this is not true when running on Run2 data/MC already converted into AO2Ds. + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, bc.timestamp()); + if (grpo == nullptr) { + LOGF(fatal, "Run 3 GRP object (type o2::parameters::GRPMagField) is not available in CCDB for run=%d at timestamp=%llu", bc.runNumber(), bc.timestamp()); + } + o2::base::Propagator::initFieldFromGRP(grpo); + bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << bz; + runNumber = bc.runNumber(); + } + df2.setBz(bz); + df3.setBz(bz); + df4.setBz(bz); + + auto thisCollId = collision.globalIndex(); + // looping over 2-prong candidates + for (const auto& candidate : candsJpsi) { + + // Apply the selections on the J/Psi candidates + registry.fill(HIST("hSelectionsJpsi"), 1, candidate.pt()); + + if (!(candidate.hfflag() & (1 << (runJpsiToee ? aod::hf_cand_2prong::DecayType::JpsiToEE : aod::hf_cand_2prong::DecayType::JpsiToMuMu)))) { + continue; + } + registry.fill(HIST("hSelectionsJpsi"), 2 + aod::SelectionStep::RecoSkims, candidate.pt()); + + auto trackPos = candidate.template prong0_as(); // positive daughter + auto trackNeg = candidate.template prong1_as(); // negative daughter + + auto trackPosParCov = getTrackParCov(trackPos); + auto trackNegParCov = getTrackParCov(trackNeg); + + std::vector jPsiDauTracks{trackPos, trackNeg}; + + auto dca0 = o2::dataformats::DCA(jPsiDauTracks[0].dcaXY(), jPsiDauTracks[0].dcaZ(), jPsiDauTracks[0].cYY(), jPsiDauTracks[0].cZY(), jPsiDauTracks[0].cZZ()); + auto dca1 = o2::dataformats::DCA(jPsiDauTracks[1].dcaXY(), jPsiDauTracks[1].dcaZ(), jPsiDauTracks[1].cYY(), jPsiDauTracks[1].cZY(), jPsiDauTracks[1].cZZ()); + + // repropagate tracks to this collision if needed + if (jPsiDauTracks[0].collisionId() != thisCollId) { + trackPosParCov.propagateToDCA(primaryVertex, bz, &dca0); + } + + if (jPsiDauTracks[1].collisionId() != thisCollId) { + trackNegParCov.propagateToDCA(primaryVertex, bz, &dca1); + } + + // --------------------------------- + // reconstruct J/Psi candidate secondary vertex + o2::track::TrackParCov trackParCovJpsi{}; + std::array pVecJpsi{}; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::BeforeFit); + try { + if (df2.process(trackPosParCov, trackNegParCov) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesJpsi"), SVFitting::FitOk); + + // topological selection + if (!selectionTopol(candidate, trackPos, trackNeg)) { + continue; + } + registry.fill(HIST("hSelectionsJpsi"), 2 + aod::SelectionStep::RecoTopol, candidate.pt()); + + // PID selection + if (!isSelectedJpsiDauPid(trackPos) || !isSelectedJpsiDauPid(trackNeg)) { + continue; + } + registry.fill(HIST("hSelectionsJpsi"), 2 + aod::SelectionStep::RecoPID, candidate.pt()); + + int indexHfCandJpsi = hfJpsi.lastIndex() + 1; + float invMassJpsi = runJpsiToee ? hfHelper.invMassJpsiToEE(candidate) : hfHelper.invMassJpsiToMuMu(candidate); + registry.fill(HIST("hMassJpsi"), invMassJpsi); + registry.fill(HIST("hPtJpsi"), candidate.pt()); + registry.fill(HIST("hCpaJpsi"), candidate.cpa()); + + bool fillHfCandJpsi = false; + + // TODO: add single track information (min eta, min ITS/TPC clusters, etc.) + double invMass2JpsiHad{0.}; + for (const auto& trackId : trackIndices) { + auto trackBach = trackId.template track_as(); + + // apply selections on bachelor tracks + auto trackParCovBach = getTrackParCov(trackBach); + std::array dcaBach{trackBach.dcaXY(), trackBach.dcaZ()}; + std::array pVecBach = trackBach.pVector(); + if (trackBach.collisionId() != thisCollId) { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovBach, 2.f, noMatCorr, &dcaBach); + getPxPyPz(trackParCovBach, pVecBach); + } + + // apply selections on bachelor tracks + if (!isTrackSelected(trackBach, trackParCovBach, dcaBach, jPsiDauTracks)) { + continue; + } + + 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 { + if (df3.process(trackPosParCov, trackNegParCov, trackParCovBach) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesBPlus"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesBPlus"), SVFitting::FitOk); + + o2::track::TrackParCov trackParCovBPlus{}; + 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); + trackParCovBPlus = df3.createParentTrackParCov(); + trackParCovBPlus.setAbsCharge(0); // to be sure + + if (!isBSelected(pVecBPlus, secondaryVertexBPlus, collision)) { + continue; + } + + // fill Kaon tracks table + // if information on track already stored, go to next track + if (!selectedTracksBach.count(trackBach.globalIndex())) { + hfTrackLfDau0(trackBach.globalIndex(), indexHfReducedCollision, + trackParCovBach.getX(), trackParCovBach.getAlpha(), + trackParCovBach.getY(), trackParCovBach.getZ(), trackParCovBach.getSnp(), + trackParCovBach.getTgl(), trackParCovBach.getQ2Pt(), + trackBach.itsNCls(), trackBach.tpcNClsCrossedRows(), trackBach.tpcChi2NCl(), trackBach.itsChi2NCl(), + trackBach.hasTPC(), trackBach.hasTOF(), + trackBach.tpcNSigmaPi(), trackBach.tofNSigmaPi(), + trackBach.tpcNSigmaKa(), trackBach.tofNSigmaKa(), + trackBach.tpcNSigmaPr(), trackBach.tofNSigmaPr()); + hfTrackCovLfDau0(trackParCovBach.getSigmaY2(), trackParCovBach.getSigmaZY(), trackParCovBach.getSigmaZ2(), + trackParCovBach.getSigmaSnpY(), trackParCovBach.getSigmaSnpZ(), + trackParCovBach.getSigmaSnp2(), trackParCovBach.getSigmaTglY(), trackParCovBach.getSigmaTglZ(), + trackParCovBach.getSigmaTglSnp(), trackParCovBach.getSigmaTgl2(), + trackParCovBach.getSigma1PtY(), trackParCovBach.getSigma1PtZ(), trackParCovBach.getSigma1PtSnp(), + trackParCovBach.getSigma1PtTgl(), trackParCovBach.getSigma1Pt2()); + // add trackBach.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another Jpsi candidate + // and keep track of their index in hfTrackLfDau0 for McRec purposes + selectedTracksBach[trackBach.globalIndex()] = hfTrackLfDau0.lastIndex(); + } + + if constexpr (doMc) { + std::vector beautyHadDauTracks{}; + for (const auto& track : jPsiDauTracks) { + beautyHadDauTracks.push_back(track); + } + beautyHadDauTracks.push_back(trackBach); + fillMcRecoInfo(collision, particlesMc, beautyHadDauTracks, indexHfCandJpsi, std::array, 2>{selectedTracksBach}, indexCollisionMaxNumContrib); + } + fillHfCandJpsi = true; + } else if constexpr (decChannel == DecayChannel::BsToJpsiPhi) { + for (auto trackBachId2 = trackId + 1; trackBachId2 != trackIndices.end(); ++trackBachId2) { + auto trackBach2 = trackBachId2.template track_as(); + auto trackBach2ParCov = getTrackParCov(trackBach2); + + std::array dcaBach2{trackBach2.dcaXY(), trackBach2.dcaZ()}; + std::array pVecBach2 = trackBach2.pVector(); + if (trackBach2.collisionId() != thisCollId) { + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackBach2ParCov, 2.f, noMatCorr, &dcaBach2); + getPxPyPz(trackBach2ParCov, pVecBach2); + } + + // apply selections on bachelor tracks + if (!isTrackSelected(trackBach2, trackBach2ParCov, dcaBach2, jPsiDauTracks)) { + continue; + } + std::array pVec2{trackBach.pVector()}, pVec3{trackBach2.pVector()}; + auto invMassPhi = RecoDecay::m(std::array{pVec2, pVec3}, std::array{MassKPlus, MassKPlus}); + + if (std::abs(invMassPhi - MassPhi) > deltaMPhiMax) { + continue; + } + + // --------------------------------- + // reconstruct Bs candidate secondary vertex + + registry.fill(HIST("hFitCandidatesBS"), SVFitting::BeforeFit); + try { + if (df4.process(trackPosParCov, trackNegParCov, trackParCovBach, trackBach2ParCov) == 0) { + continue; + } + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; + registry.fill(HIST("hFitCandidatesBS"), SVFitting::Fail); + continue; + } + registry.fill(HIST("hFitCandidatesBS"), SVFitting::FitOk); + + o2::track::TrackParCov trackParCovBS{}; + 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); + pVecPhi = RecoDecay::pVec(pVec2, pVec3); + trackParCovBS = df4.createParentTrackParCov(); + trackParCovBS.setAbsCharge(0); // to be sure + + if (!isBSelected(pVecBS, secondaryVertexBS, collision)) { + continue; + } + + registry.fill(HIST("hPtPhi"), RecoDecay::pt(pVecBach, pVecBach2)); + registry.fill(HIST("hMassPhi"), RecoDecay::m(std::array{pVecBach, pVecBach2}, std::array{MassKPlus, MassKPlus})); + invMass2JpsiHad = RecoDecay::m2(std::array{pVecJpsi, pVecPhi}, std::array{MassJPsi, MassPhi}); + if ((invMass2JpsiHad < invMass2JpsiHadMin) || (invMass2JpsiHad > invMass2JpsiHadMax)) { + continue; + } + registry.fill(HIST("hMassJpsiPhi"), std::sqrt(invMass2JpsiHad)); + + // fill daughter tracks table + // if information on track already stored, go to next track + if (!selectedTracksBach.count(trackBach.globalIndex())) { + hfTrackLfDau0(trackBach.globalIndex(), indexHfReducedCollision, + trackParCovBach.getX(), trackParCovBach.getAlpha(), + trackParCovBach.getY(), trackParCovBach.getZ(), trackParCovBach.getSnp(), + trackParCovBach.getTgl(), trackParCovBach.getQ2Pt(), + trackBach.itsNCls(), trackBach.tpcNClsCrossedRows(), trackBach.tpcChi2NCl(), trackBach.itsChi2NCl(), + trackBach.hasTPC(), trackBach.hasTOF(), + trackBach.tpcNSigmaPi(), trackBach.tofNSigmaPi(), + trackBach.tpcNSigmaKa(), trackBach.tofNSigmaKa(), + trackBach.tpcNSigmaPr(), trackBach.tofNSigmaPr()); + hfTrackCovLfDau0(trackParCovBach.getSigmaY2(), trackParCovBach.getSigmaZY(), trackParCovBach.getSigmaZ2(), + trackParCovBach.getSigmaSnpY(), trackParCovBach.getSigmaSnpZ(), + trackParCovBach.getSigmaSnp2(), trackParCovBach.getSigmaTglY(), trackParCovBach.getSigmaTglZ(), + trackParCovBach.getSigmaTglSnp(), trackParCovBach.getSigmaTgl2(), + trackParCovBach.getSigma1PtY(), trackParCovBach.getSigma1PtZ(), trackParCovBach.getSigma1PtSnp(), + trackParCovBach.getSigma1PtTgl(), trackParCovBach.getSigma1Pt2()); + // add trackBach.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another Jpsi candidate + // and keep track of their index in hfTrackLfDau0 for McRec purposes + selectedTracksBach[trackBach.globalIndex()] = hfTrackLfDau0.lastIndex(); + } + + // fill daughter tracks table + // if information on track already stored, go to next track + if (!selectedTracksBach2.count(trackBach2.globalIndex())) { + hfTrackLfDau1(trackBach2.globalIndex(), indexHfReducedCollision, + trackBach2ParCov.getX(), trackBach2ParCov.getAlpha(), + trackBach2ParCov.getY(), trackBach2ParCov.getZ(), trackBach2ParCov.getSnp(), + trackBach2ParCov.getTgl(), trackBach2ParCov.getQ2Pt(), + trackBach2.itsNCls(), trackBach2.tpcNClsCrossedRows(), trackBach2.tpcChi2NCl(), trackBach2.itsChi2NCl(), + trackBach2.hasTPC(), trackBach2.hasTOF(), + trackBach2.tpcNSigmaPi(), trackBach2.tofNSigmaPi(), + trackBach2.tpcNSigmaKa(), trackBach2.tofNSigmaKa(), + trackBach2.tpcNSigmaPr(), trackBach2.tofNSigmaPr()); + hfTrackCovLfDau1(trackBach2ParCov.getSigmaY2(), trackBach2ParCov.getSigmaZY(), trackBach2ParCov.getSigmaZ2(), + trackBach2ParCov.getSigmaSnpY(), trackBach2ParCov.getSigmaSnpZ(), + trackBach2ParCov.getSigmaSnp2(), trackBach2ParCov.getSigmaTglY(), trackBach2ParCov.getSigmaTglZ(), + trackBach2ParCov.getSigmaTglSnp(), trackBach2ParCov.getSigmaTgl2(), + trackBach2ParCov.getSigma1PtY(), trackBach2ParCov.getSigma1PtZ(), trackBach2ParCov.getSigma1PtSnp(), + trackBach2ParCov.getSigma1PtTgl(), trackBach2ParCov.getSigma1Pt2()); + // add trackBach2.globalIndex() to a list + // to keep memory of the pions filled in the table and avoid refilling them if they are paired to another Jpsi candidate + // and keep track of their index in hfTrackLfDau1 for McRec purposes + selectedTracksBach2[trackBach2.globalIndex()] = hfTrackLfDau1.lastIndex(); + } + + if constexpr (doMc) { + std::vector beautyHadDauTracks{}; + for (const auto& track : jPsiDauTracks) { + beautyHadDauTracks.push_back(track); + } + beautyHadDauTracks.push_back(trackBach); + fillMcRecoInfo(collision, particlesMc, beautyHadDauTracks, indexHfCandJpsi, std::array, 2>{selectedTracksBach, selectedTracksBach2}, indexCollisionMaxNumContrib); + } + fillHfCandJpsi = true; + } + } + } // kaon loop + if (fillHfCandJpsi) { // fill Jpsi table only once per Jpsi candidate + double invMassJpsi{0.}; + if (runJpsiToee) { + invMassJpsi = hfHelper.invMassJpsiToEE(candidate); + } else { + invMassJpsi = hfHelper.invMassJpsiToMuMu(candidate); + } + hfJpsi(trackPos.globalIndex(), trackNeg.globalIndex(), + indexHfReducedCollision, + candidate.xSecondaryVertex(), candidate.ySecondaryVertex(), candidate.zSecondaryVertex(), + invMassJpsi, + trackPos.itsNCls(), trackPos.tpcNClsCrossedRows(), trackPos.tpcChi2NCl(), trackPos.itsChi2NCl(), + trackNeg.itsNCls(), trackNeg.tpcNClsCrossedRows(), trackNeg.tpcChi2NCl(), trackNeg.itsChi2NCl(), + trackPosParCov.getX(), trackNegParCov.getX(), + trackPosParCov.getY(), trackNegParCov.getY(), + trackPosParCov.getZ(), trackNegParCov.getZ(), + trackPosParCov.getAlpha(), trackNegParCov.getAlpha(), + trackPosParCov.getSnp(), trackNegParCov.getSnp(), + trackPosParCov.getTgl(), trackNegParCov.getTgl(), + trackPosParCov.getQ2Pt(), trackNegParCov.getQ2Pt()); // Q/pT + hfRedJpsiCov(trackPosParCov.getSigmaY2(), trackNegParCov.getSigmaY2(), + trackPosParCov.getSigmaZY(), trackNegParCov.getSigmaZY(), + trackPosParCov.getSigmaZ2(), trackNegParCov.getSigmaZ2(), + trackPosParCov.getSigmaSnpY(), trackNegParCov.getSigmaSnpY(), + trackPosParCov.getSigmaSnpZ(), trackNegParCov.getSigmaSnpZ(), + trackPosParCov.getSigmaSnp2(), trackNegParCov.getSigmaSnp2(), + trackPosParCov.getSigmaTglY(), trackNegParCov.getSigmaTglY(), + trackPosParCov.getSigmaTglZ(), trackNegParCov.getSigmaTglZ(), + trackPosParCov.getSigmaTglSnp(), trackNegParCov.getSigmaTglSnp(), + trackPosParCov.getSigmaTgl2(), trackNegParCov.getSigmaTgl2(), + trackPosParCov.getSigma1PtY(), trackNegParCov.getSigma1PtY(), + trackPosParCov.getSigma1PtZ(), trackNegParCov.getSigma1PtZ(), + trackPosParCov.getSigma1PtSnp(), trackNegParCov.getSigma1PtSnp(), + trackPosParCov.getSigma1PtTgl(), trackNegParCov.getSigma1PtTgl(), + trackPosParCov.getSigma1Pt2(), trackNegParCov.getSigma1Pt2()); + fillHfReducedCollision = true; + } + } // candsJpsi loop + + if (!fillHfReducedCollision) { + registry.fill(HIST("hEvents"), 1 + Event::NoCharmHadPiSelected); + return; + } + registry.fill(HIST("hEvents"), 1 + Event::CharmHadPiSelected); + // fill collision table if it contains a J/Psi K pair at minimum + hfReducedCollision(collision.posX(), collision.posY(), collision.posZ(), collision.numContrib(), hfRejMap, bz); + hfReducedCollExtra(collision.covXX(), collision.covXY(), collision.covYY(), + collision.covXZ(), collision.covYZ(), collision.covZZ()); + // hfReducedCollCentrality(collision.centFT0C(), collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); // TODO: add + // if constexpr (withQvec) { + // hfReducedQvector(collision.qvecFT0CRe(), collision.qvecFT0CIm(), collision.sumAmplFT0C(), + // collision.qvecFT0ARe(), collision.qvecFT0AIm(), collision.sumAmplFT0A(), + // collision.qvecFT0MRe(), collision.qvecFT0MIm(), collision.sumAmplFT0M(), + // collision.qvecTPCposRe(), collision.qvecTPCposIm(), collision.nTrkTPCpos(), + // collision.qvecTPCnegRe(), collision.qvecTPCnegIm(), collision.nTrkTPCneg(), + // collision.qvecTPCallRe(), collision.qvecTPCallIm(), collision.nTrkTPCall()); + // } + } + + void processJpsiKData(soa::Join const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBplus(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiKData, "Process J/Psi K without MC info", true); + + void processJpsiPhiData(soa::Join const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSel const& tracks, + aod::BCsWithTimestamps const& bcs) + { + // store configurables needed for B0 workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, tracks, -1, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiPhiData, "Process J/Psi phi without MC info", false); + + void processJpsiKMc(CollisionsWCMcLabels const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisions const& mcCollisions) + { + // store configurables needed for B+ workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBplus(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiKMc, "Process J/Psi K with MC info", false); + + void processJpsiPhiMc(CollisionsWCMcLabels const& collisions, + aod::HfCand2ProngWPid const& candsJpsi, + aod::TrackAssoc const& trackIndices, + TracksPidWithSelAndMc const& tracks, + aod::McParticles const& particlesMc, + BCsInfo const& bcs, + McCollisions const& mcCollisions) + { + // store configurables needed for B+ workflow + if (!isHfCandBhadConfigFilled) { + rowCandidateConfigBs(invMassWindowJpsiHad.value); + isHfCandBhadConfigFilled = true; + } + + int zvtxColl{0}; + int sel8Coll{0}; + int zvtxAndSel8Coll{0}; + int zvtxAndSel8CollAndSoftTrig{0}; + int allSelColl{0}; + for (const auto& collision : collisions) { + o2::hf_evsel::checkEvSel(collision, hfEvSel, zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl, ccdb, registry); + + auto thisCollId = collision.globalIndex(); + auto candsJpsiThisColl = candsJpsi.sliceBy(candsJpsiPerCollision, thisCollId); + auto trackIdsThisCollision = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + auto collsSameMcCollision = collisions.sliceBy(colPerMcCollision, collision.mcCollisionId()); + int64_t indexCollisionMaxNumContrib = getIndexCollisionMaxNumContrib(collsSameMcCollision); + runDataCreation(collision, candsJpsiThisColl, trackIdsThisCollision, tracks, particlesMc, indexCollisionMaxNumContrib, bcs); + } + // handle normalization by the right number of collisions + hfCollisionCounter(collisions.tableSize(), zvtxColl, sel8Coll, zvtxAndSel8Coll, zvtxAndSel8CollAndSoftTrig, allSelColl); + for (const auto& mcCollision : mcCollisions) { + runMcGen(mcCollision, particlesMc, collisions, bcs); + } + } + PROCESS_SWITCH(HfDataCreatorJpsiHadReduced, processJpsiPhiMc, "Process J/Psi phi with MC info", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/CMakeLists.txt b/PWGHF/D2H/Tasks/CMakeLists.txt index 52019c9227e..24707fb011b 100644 --- a/PWGHF/D2H/Tasks/CMakeLists.txt +++ b/PWGHF/D2H/Tasks/CMakeLists.txt @@ -29,11 +29,21 @@ o2physics_add_dpl_workflow(task-bplus-reduced PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-bplus-to-jpsi-k-reduced + SOURCES taskBplusToJpsiKReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-bs-reduced SOURCES taskBsReduced.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-bs-to-jpsi-phi-reduced + SOURCES taskBsToJpsiPhiReduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-bs SOURCES taskBs.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -44,8 +54,13 @@ o2physics_add_dpl_workflow(task-charm-polarisation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(task-charm-reso-reduced - SOURCES taskCharmResoReduced.cxx +o2physics_add_dpl_workflow(task-charm-reso-to-d-v0-reduced + SOURCES taskCharmResoToDV0Reduced.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-charm-reso-to-d-trk-reduced + SOURCES taskCharmResoToDTrkReduced.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -128,3 +143,8 @@ o2physics_add_dpl_workflow(task-xicc SOURCES taskXicc.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(task-xic0-to-xi-pi + SOURCES taskXic0ToXiPi.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) \ No newline at end of file diff --git a/PWGHF/D2H/Tasks/taskB0.cxx b/PWGHF/D2H/Tasks/taskB0.cxx index c1076cab906..219d9dc50bb 100644 --- a/PWGHF/D2H/Tasks/taskB0.cxx +++ b/PWGHF/D2H/Tasks/taskB0.cxx @@ -14,24 +14,42 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.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 + using namespace o2; using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::hf_decay::hf_cand_beauty; /// B0 analysis task struct HfTaskB0 { @@ -130,15 +148,15 @@ struct HfTaskB0 { registry.add("hPtGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {{300, 0., 30.}}}); if (checkDecayTypeMc) { - constexpr uint8_t kNBinsDecayTypeMc = hf_cand_b0::DecayTypeMc::NDecayTypeMc; - TString labels[kNBinsDecayTypeMc]; + constexpr uint8_t NBinsDecayTypeMc = hf_cand_b0::DecayTypeMc::NDecayTypeMc; // FIXME + TString labels[NBinsDecayTypeMc]; labels[hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi] = "B^{0} #rightarrow (D^{#minus} #rightarrow #pi^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; labels[hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi] = "B^{0} #rightarrow (D^{#minus}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#minus}) #pi^{#plus}"; labels[hf_cand_b0::DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; labels[hf_cand_b0::DecayTypeMc::OtherDecay] = "Other decays"; - static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; + static const AxisSpec axisDecayType = {NBinsDecayTypeMc, 0.5, NBinsDecayTypeMc + 0.5, ""}; registry.add("hDecayTypeMc", "DecayType", {HistType::kTH3F, {axisDecayType, axisMassB0, axisPt}}); - for (uint8_t iBin = 0; iBin < kNBinsDecayTypeMc; ++iBin) { + for (uint8_t iBin = 0; iBin < NBinsDecayTypeMc; ++iBin) { registry.get(HIST("hDecayTypeMc"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin]); } } @@ -186,7 +204,7 @@ struct HfTaskB0 { registry.fill(HIST("hDecLenXYErr"), candidate.errorDecayLengthXY(), ptCandB0); registry.fill(HIST("hInvMassD"), hfHelper.invMassDplusToPiKPi(candD), ptCandB0); } // candidate loop - } // process + } // process /// B0 MC analysis and fill histograms void processMc(soa::Filtered> const& candidates, @@ -203,9 +221,9 @@ struct HfTaskB0 { auto ptCandB0 = candidate.pt(); auto candD = candidate.prong0_as>(); auto invMassCandB0 = hfHelper.invMassB0ToDPi(candidate); - int flagMcMatchRecB0 = std::abs(candidate.flagMcMatchRec()); + auto flagMcMatchRecB0 = std::abs(candidate.flagMcMatchRec()); - if (TESTBIT(flagMcMatchRecB0, hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi)) { + if (flagMcMatchRecB0 == DecayChannelMain::B0ToDminusPi) { auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kB0, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -251,9 +269,9 @@ struct HfTaskB0 { registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandB0); if (checkDecayTypeMc) { - if (TESTBIT(flagMcMatchRecB0, hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi)) { // B0 → Ds- π+ → (K- K+ π-) π+ + if (flagMcMatchRecB0 == DecayChannelMain::B0ToDsPi) { // B0 → Ds- π+ → (K- K+ π-) π+ registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi, invMassCandB0, ptCandB0); - } else if (TESTBIT(flagMcMatchRecB0, hf_cand_b0::DecayTypeMc::PartlyRecoDecay)) { // Partly reconstructed decay channel + } else if (flagMcMatchRecB0 == hf_cand_b0::DecayTypeMc::PartlyRecoDecay) { // FIXME, Partly reconstructed decay channel registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_b0::DecayTypeMc::PartlyRecoDecay, invMassCandB0, ptCandB0); } else { registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_b0::DecayTypeMc::OtherDecay, invMassCandB0, ptCandB0); @@ -264,7 +282,7 @@ struct HfTaskB0 { // MC gen. level for (const auto& particle : mcParticles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_b0::DecayType::B0ToDPi)) { + if (std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_beauty::DecayChannelMain::B0ToDminusPi) { auto ptParticle = particle.pt(); auto yParticle = RecoDecay::y(particle.pVector(), o2::constants::physics::MassB0); @@ -308,7 +326,7 @@ struct HfTaskB0 { registry.fill(HIST("hEtaGenWithProngsInAcceptance"), particle.eta(), ptParticle); } } // gen - } // process + } // process PROCESS_SWITCH(HfTaskB0, processMc, "Process MC", false); }; // struct diff --git a/PWGHF/D2H/Tasks/taskB0Reduced.cxx b/PWGHF/D2H/Tasks/taskB0Reduced.cxx index 87138a813bc..e1e30490f18 100644 --- a/PWGHF/D2H/Tasks/taskB0Reduced.cxx +++ b/PWGHF/D2H/Tasks/taskB0Reduced.cxx @@ -15,16 +15,31 @@ /// \author Alexandre Bigot , IPHC Strasbourg /// \author Fabrizio Grosa , CERN -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -506,7 +521,7 @@ struct HfTaskB0Reduced { } } if (fillSparses) { - if constexpr (withDmesMl) { + if constexpr (doMc) { if (isSignal) { if constexpr (withDmesMl) { registry.fill(HIST("hMassPtCutVarsRecSig"), invMassB0, ptCandB0, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassD, ptD, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); diff --git a/PWGHF/D2H/Tasks/taskBplus.cxx b/PWGHF/D2H/Tasks/taskBplus.cxx index b98a2930258..9b619329d25 100644 --- a/PWGHF/D2H/Tasks/taskBplus.cxx +++ b/PWGHF/D2H/Tasks/taskBplus.cxx @@ -18,24 +18,38 @@ /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari /// \author Deepa Thomas , UT Austin -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::hf_decay::hf_cand_beauty; // string definitions, used for histogram axis labels const TString stringPt = "#it{p}_{T} (GeV/#it{c})"; @@ -198,7 +212,7 @@ struct HfTaskBplus { registry.fill(HIST("hCPAFinerBinning"), candidate.cpa(), ptCandBplus); registry.fill(HIST("hCPAxyFinerBinning"), candidate.cpaXY(), ptCandBplus); } // candidate loop - } // process + } // process void processMc(soa::Join const&, soa::Join const& mcParticles, @@ -212,7 +226,7 @@ struct HfTaskBplus { } auto ptCandBplus = candidate.pt(); // auto candD0 = candidate.prong0_as(); - if (TESTBIT(std::abs(candidate.flagMcMatchRec()), hf_cand_bplus::DecayType::BplusToD0Pi)) { + if (std::abs(candidate.flagMcMatchRec()) == DecayChannelMain::BplusToD0Pi) { auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kBPlus, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -255,7 +269,7 @@ struct HfTaskBplus { // MC gen. level for (const auto& particle : mcParticles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bplus::DecayType::BplusToD0Pi)) { + if (std::abs(particle.flagMcMatchGen()) == DecayChannelMain::BplusToD0Pi) { auto ptParticle = particle.pt(); auto yParticle = RecoDecay::y(particle.pVector(), o2::constants::physics::MassBPlus); @@ -299,7 +313,7 @@ struct HfTaskBplus { registry.fill(HIST("hEtaGenWithProngsInAcceptance"), particle.eta(), ptParticle); } } // gen - } // processMc + } // processMc PROCESS_SWITCH(HfTaskBplus, processMc, "Process MC", false); }; diff --git a/PWGHF/D2H/Tasks/taskBplusReduced.cxx b/PWGHF/D2H/Tasks/taskBplusReduced.cxx index e319692b0c2..e7a9a8f93db 100644 --- a/PWGHF/D2H/Tasks/taskBplusReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBplusReduced.cxx @@ -14,18 +14,33 @@ /// /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" + +#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/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx new file mode 100644 index 00000000000..25bec4a1f6f --- /dev/null +++ b/PWGHF/D2H/Tasks/taskBplusToJpsiKReduced.cxx @@ -0,0 +1,563 @@ +// 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 taskBplusToJpsiKReduced.cxx +/// \brief B+ → Jpsi K+ → (µ+ µ-) K+ analysis task +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponseBplusToJpsiKReduced.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsPid.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 +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::pid_tpc_tof_utils; + +namespace o2::aod +{ +namespace hf_cand_bplustojpsik_lite +{ +DECLARE_SOA_COLUMN(PtJpsi, ptJpsi, float); //! Transverse momentum of Jpsi daughter candidate (GeV/c) +DECLARE_SOA_COLUMN(PtBach, ptBach, float); //! Transverse momentum of bachelor kaon (GeV/c) +DECLARE_SOA_COLUMN(ItsNClsJpsiDauPos, itsNClsJpsiDauPos, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsJpsiDauPos, tpcNClsCrossedRowsJpsiDauPos, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(ItsChi2NClJpsiDauPos, itsChi2NClJpsiDauPos, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(TpcChi2NClJpsiDauPos, tpcChi2NClJpsiDauPos, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(AbsEtaJpsiDauPos, absEtaJpsiDauPos, float); //! |eta| +DECLARE_SOA_COLUMN(ItsNClsJpsiDauNeg, itsNClsJpsiDauNeg, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsJpsiDauNeg, tpcNClsCrossedRowsJpsiDauNeg, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(ItsChi2NClJpsiDauNeg, itsChi2NClJpsiDauNeg, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(TpcChi2NClJpsiDauNeg, tpcChi2NClJpsiDauNeg, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(AbsEtaJpsiDauNeg, absEtaJpsiDauNeg, float); //! |eta| +DECLARE_SOA_COLUMN(ItsNClsLfTrack0, itsNClsLfTrack0, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsLfTrack0, tpcNClsCrossedRowsLfTrack0, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(ItsChi2NClLfTrack0, itsChi2NClLfTrack0, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(TpcChi2NClLfTrack0, tpcChi2NClLfTrack0, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(AbsEtaLfTrack0, absEtaLfTrack0, float); //! |eta| +DECLARE_SOA_COLUMN(MJpsi, mJpsi, float); //! Invariant mass of Jpsi daughter candidates (GeV/c) +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(PtGen, ptGen, 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(NSigTpcKaBachelor, nSigTpcKaBachelor, float); //! TPC Nsigma separation for bachelor with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKaBachelor, nSigTofKaBachelor, float); //! TOF Nsigma separation for bachelor with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKaBachelor, nSigTpcTofKaBachelor, float); //! Combined TPC and TOF Nsigma separation for bachelor with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauPos, nSigTpcMuJpsiDauPos, float); //! TPC Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauPos, nSigTofMuJpsiDauPos, float); //! TOF Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauPos, nSigTpcTofMuJpsiDauPos, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong0 with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauNeg, nSigTpcMuJpsiDauNeg, float); //! TPC Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauNeg, nSigTofMuJpsiDauNeg, float); //! TOF Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauNeg, nSigTpcTofMuJpsiDauNeg, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong1 with muon 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(CtXY, ctXY, float); //! Pseudo-proper decay length of candidate +DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! Impact parameter product of B daughters +DECLARE_SOA_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, float); //! Impact parameter product of Jpsi daughters +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauPos, impactParameterJpsiDauPos, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauNeg, impactParameterJpsiDauNeg, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterLfTrack0, impactParameterLfTrack0, float); //! Impact parameter of Phi daughter 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(CpaJpsi, cpaJpsi, float); //! Cosine pointing angle of Jpsi daughter candidate +DECLARE_SOA_COLUMN(CpaXYJpsi, cpaXYJpsi, float); //! Cosine pointing angle in transverse plane of Jpsi daughter candidate +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(MlScoreSig, mlScoreSig, float); //! ML score for signal class +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! Flag for association with wrong collision +} // namespace hf_cand_bplustojpsik_lite + +DECLARE_SOA_TABLE(HfRedCandBpLites, "AOD", "HFREDCANDBPLITE", //! Table with some B+ properties + hf_cand_bplustojpsik_lite::M, + hf_cand_bplustojpsik_lite::Pt, + hf_cand_bplustojpsik_lite::Eta, + hf_cand_bplustojpsik_lite::Phi, + hf_cand_bplustojpsik_lite::Y, + hf_cand_bplustojpsik_lite::Cpa, + hf_cand_bplustojpsik_lite::CpaXY, + hf_cand::Chi2PCA, + hf_cand_bplustojpsik_lite::DecayLength, + hf_cand_bplustojpsik_lite::DecayLengthXY, + hf_cand_bplustojpsik_lite::DecayLengthNormalised, + hf_cand_bplustojpsik_lite::DecayLengthXYNormalised, + hf_cand_bplustojpsik_lite::CtXY, + hf_cand_bplustojpsik_lite::ImpactParameterProduct, + hf_cand_bplustojpsik_lite::ImpactParameterProductJpsi, + hf_cand_bplustojpsik_lite::MaxNormalisedDeltaIP, + hf_cand_bplustojpsik_lite::MlScoreSig, + // hf_sel_candidate_bplus::IsSelBplusToJpsiPi, + // Jpsi meson features + hf_cand_bplustojpsik_lite::MJpsi, + hf_cand_bplustojpsik_lite::PtJpsi, + hf_cand_bplustojpsik_lite::ImpactParameterJpsiDauPos, + hf_cand_bplustojpsik_lite::ImpactParameterJpsiDauNeg, + hf_cand_bplustojpsik_lite::ImpactParameterLfTrack0, + // Jpsi daughter features + hf_cand_bplustojpsik_lite::ItsNClsJpsiDauPos, + hf_cand_bplustojpsik_lite::TpcNClsCrossedRowsJpsiDauPos, + hf_cand_bplustojpsik_lite::ItsChi2NClJpsiDauPos, + hf_cand_bplustojpsik_lite::TpcChi2NClJpsiDauPos, + hf_cand_bplustojpsik_lite::AbsEtaJpsiDauPos, + hf_cand_bplustojpsik_lite::ItsNClsJpsiDauNeg, + hf_cand_bplustojpsik_lite::TpcNClsCrossedRowsJpsiDauNeg, + hf_cand_bplustojpsik_lite::ItsChi2NClJpsiDauNeg, + hf_cand_bplustojpsik_lite::TpcChi2NClJpsiDauNeg, + hf_cand_bplustojpsik_lite::AbsEtaJpsiDauNeg, + // kaon features + hf_cand_bplustojpsik_lite::PtBach, + hf_cand_bplustojpsik_lite::ItsNClsLfTrack0, + hf_cand_bplustojpsik_lite::TpcNClsCrossedRowsLfTrack0, + hf_cand_bplustojpsik_lite::ItsChi2NClLfTrack0, + hf_cand_bplustojpsik_lite::TpcChi2NClLfTrack0, + hf_cand_bplustojpsik_lite::AbsEtaLfTrack0, + hf_cand_bplustojpsik_lite::NSigTpcKaBachelor, + 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_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_bplustojpsik_lite::FlagWrongCollision, +// hf_cand_bplustojpsik_lite::MJpsi, +// hf_cand_bplustojpsik_lite::PtJpsi, +// hf_cand_bplustojpsik_lite::M, +// hf_cand_bplustojpsik_lite::Pt, +// // hf_cand_bplustojpsik_lite::MlScoreSig, +// hf_bplus_mc::PdgCodeBeautyMother, +// hf_bplus_mc::PdgCodeCharmMother, +// hf_bplus_mc::PdgCodeDauPos, +// hf_bplus_mc::PdgCodeDauNeg, +// hf_bplus_mc::PdgCodeProng2); +} // namespace o2::aod + +// string definitions, used for histogram axis labels +const TString stringPt = "#it{p}_{T} (GeV/#it{c})"; +const TString stringPtJpsi = "#it{p}_{T}(Jpsi) (GeV/#it{c});"; +const TString bPlusCandTitle = "B+ candidates;"; +const TString entries = "entries"; +const TString bPlusCandMatch = "B+ candidates (matched);"; +const TString bPlusCandUnmatch = "B+ candidates (unmatched);"; +const TString mcParticleMatched = "MC particles (matched);"; + +/// B+ analysis task +struct HfTaskBplusToJpsiKReduced { + Produces hfRedCandBpLite; + // Produces hfRedBpMcCheck; + + Configurable selectionFlagBplus{"selectionFlagBplus", 1, "Selection Flag for Bplus"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; + Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses/tree (only MC)"}; + 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"}; + // topological cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_bplus_to_jpsi_k::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_bplus_to_jpsi_k::Cuts[0], hf_cuts_bplus_to_jpsi_k::NBinsPt, hf_cuts_bplus_to_jpsi_k::NCutVars, hf_cuts_bplus_to_jpsi_k::labelsPt, hf_cuts_bplus_to_jpsi_k::labelsCutVar}, "B+ candidate selection per pT bin"}; + // Enable PID + Configurable kaonPidMethod{"kaonPidMethod", PidMethod::TpcOrTof, "PID selection method for the bachelor kaon (PidMethod::NoPid: none, PidMethod::TpcOrTof: TPC or TOF, PidMethod::TpcAndTof: TPC and TOF)"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // B+ ML inference + Configurable> binsPtBpMl{"binsPtBpMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirBpMl{"cutDirBpMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsBpMl{"cutsBpMl", {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 nClassesBpMl{"nClassesBpMl", 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{"path_ccdb/BDT_BPLUS/"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_BPLUSToJPSIK.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"}; + + HfHelper hfHelper; + TrackSelectorKa selectorKaon; + o2::analysis::HfMlResponseBplusToJpsiKReduced hfMlResponse; + o2::ccdb::CcdbApi ccdbApi; + + using TracksKaon = soa::Join; + std::vector outputMl = {}; + + // Filter filterSelectCandidates = (aod::hf_sel_candidate_bplus::isSelBplusToJpsiPi >= selectionFlagBplus); + + HistogramRegistry registry{"registry"}; + + void init(InitContext&) + { + std::array processFuncData{doprocessData, doprocessDataWithBplusMl}; + if ((std::accumulate(processFuncData.begin(), processFuncData.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for data can be enabled at a time."); + } + std::array processFuncMc{doprocessMc, doprocessMcWithBplusMl}; + if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for MC can be enabled at a time."); + } + + if (kaonPidMethod < 0 || kaonPidMethod >= PidMethod::NPidMethods) { + LOGP(fatal, "Invalid PID option in configurable, please set 0 (no PID), 1 (TPC or TOF), or 2 (TPC and TOF)"); + } + + if (kaonPidMethod != PidMethod::NoPid) { + selectorKaon.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorKaon.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorKaon.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorKaon.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorKaon.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorKaon.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } + + const AxisSpec axisMassBplus{150, 4.5, 6.0}; + const AxisSpec axisMassJpsi{600, 2.8f, 3.4f}; + const AxisSpec axisPtProng{100, 0., 10.}; + const AxisSpec axisImpactPar{200, -0.05, 0.05}; + const AxisSpec axisPtJpsi{100, 0., 50.}; + const AxisSpec axisRapidity{100, -2., 2.}; + const AxisSpec axisPtB{(std::vector)binsPt, "#it{p}_{T}^{B^{+}} (GeV/#it{c})"}; + const AxisSpec axisPtKa{100, 0.f, 10.f}; + + registry.add("hMass", bPlusCandTitle + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassBplus, axisPtB}}); + registry.add("hMassJpsi", bPlusCandTitle + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hd0K", bPlusCandTitle + "Kaon DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + + // histograms processMC + if (doprocessMc || doprocessMcWithBplusMl) { + registry.add("hPtJpsiGen", mcParticleMatched + "J/#Psi #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtKGen", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "B^{+} #it{p}_{T}^{gen} (GeV/#it{c}); B^{+} #it{y}", {HistType::kTH2F, {axisPtProng, axisRapidity}}); + registry.add("hMassRecSig", bPlusCandMatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B^{+} " + stringPt, {HistType::kTH2F, {axisMassBplus, axisPtB}}); + registry.add("hMassJpsiRecSig", bPlusCandMatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hd0KRecSig", bPlusCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + registry.add("hMassRecBg", bPlusCandUnmatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B^{+} " + stringPt, {HistType::kTH2F, {axisMassBplus, axisPtB}}); + registry.add("hMassJpsiRecBg", bPlusCandUnmatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hd0KRecBg", bPlusCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + } + + if (doprocessDataWithBplusMl || doprocessMcWithBplusMl) { + hfMlResponse.configure(binsPtBpMl, cutsBpMl, cutDirBpMl, nClassesBpMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponse.init(); + } + } + + /// Selection of B+ daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of B+ prong + /// \param ptProng is the pT of B+ prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Calculate pseudorapidity from track tan(lambda) + /// \param tgl is the track tangent of the dip angle + /// \return pseudorapidity + inline float absEta(float tgl) + { + return std::abs(std::log(std::tan(o2::constants::math::PIQuarter - 0.5f * std::atan(tgl)))); + } + + /// Fill candidate information at reconstruction level + /// \param doMc is the flag to enable the filling with MC information + /// \param withBplusMl is the flag to enable the filling with ML scores for the B+ candidate + /// \param candidate is the B+ candidate + /// \param candidatesJpsi is the table with Jpsi candidates + template + void fillCand(Cand const& candidate, + aod::HfRedJpsis const& /*candidatesJpsi*/, + aod::HfRedBach0Tracks const&) + { + auto ptCandBplus = candidate.pt(); + auto invMassBplus = hfHelper.invMassBplusToJpsiK(candidate); + auto candJpsi = candidate.template jpsi_as(); + auto candKa = candidate.template bachKa_as(); + auto ptJpsi = candidate.ptProng0(); + auto invMassJpsi = candJpsi.m(); + uint8_t statusBplus = 0; + + int8_t flagMcMatchRec{0}, flagMcDecayChanRec{0}, flagWrongCollision{0}; + bool isSignal = false; + if constexpr (doMc) { + flagMcMatchRec = candidate.flagMcMatchRec(); + flagMcDecayChanRec = candidate.flagMcDecayChanRec(); + flagWrongCollision = candidate.flagWrongCollision(); + isSignal = std::abs(flagMcMatchRec) == o2::hf_decay::hf_cand_beauty::BplusToJpsiK; + } + + SETBIT(statusBplus, SelectionStep::RecoSkims); + if (hfHelper.selectionBplusToJpsiKTopol(candidate, cuts, binsPt)) { + SETBIT(statusBplus, SelectionStep::RecoTopol); + } else if (selectionFlagBplus >= BIT(SelectionStep::RecoTopol) * 2 - 1) { + return; + } + // track-level PID selection + // auto trackKa = candidate.template prong1_as(); + if (kaonPidMethod == PidMethod::TpcOrTof || kaonPidMethod == PidMethod::TpcAndTof) { + int pidTrackKa{TrackSelectorPID::Status::NotApplicable}; + if (kaonPidMethod == PidMethod::TpcOrTof) { + pidTrackKa = selectorKaon.statusTpcOrTof(candKa); + } else if (kaonPidMethod == PidMethod::TpcAndTof) { + pidTrackKa = selectorKaon.statusTpcAndTof(candKa); + } + if (hfHelper.selectionBplusToJpsiKPid(pidTrackKa, acceptPIDNotApplicable.value)) { + // LOGF(info, "B+ candidate selection failed at PID selection"); + SETBIT(statusBplus, SelectionStep::RecoPID); + } else if (selectionFlagBplus >= BIT(SelectionStep::RecoPID) * 2 - 1) { + return; + } + } + + float candidateMlScoreSig = -1; + if constexpr (withBplusMl) { + // B+ ML selections + std::vector inputFeatures = hfMlResponse.getInputFeatures(candidate, candKa); + if (hfMlResponse.isSelectedMl(inputFeatures, ptCandBplus, outputMl)) { + SETBIT(statusBplus, SelectionStep::RecoMl); + } else if (selectionFlagBplus >= BIT(SelectionStep::RecoMl) * 2 - 1) { + return; + } + candidateMlScoreSig = outputMl[1]; + } + + registry.fill(HIST("hMass"), invMassBplus, ptCandBplus); + registry.fill(HIST("hMassJpsi"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0K"), candidate.impactParameter1(), candidate.ptProng1()); + if constexpr (doMc) { + if (isSignal) { + registry.fill(HIST("hMassRecSig"), invMassBplus, ptCandBplus); + registry.fill(HIST("hMassJpsiRecSig"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0KRecSig"), candidate.impactParameter1(), candidate.ptProng1()); + } else if (fillBackground) { + registry.fill(HIST("hMassRecBg"), invMassBplus, ptCandBplus); + registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0KRecBg"), candidate.impactParameter1(), candidate.ptProng1()); + } + } + + float pseudoRndm = ptJpsi * 1000. - static_cast(ptJpsi * 1000); + if (ptCandBplus >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor) { + float ptMother = -1.; + if constexpr (doMc) { + ptMother = candidate.ptMother(); + } + + hfRedCandBpLite( + // B+ - meson features + invMassBplus, + ptCandBplus, + candidate.eta(), + candidate.phi(), + hfHelper.yBplus(candidate), + candidate.cpa(), + candidate.cpaXY(), + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ctXY(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus}), + candidate.impactParameterProduct(), + candidate.impactParameterProductJpsi(), + candidate.maxNormalisedDeltaIP(), + candidateMlScoreSig, + // J/Psi features + invMassJpsi, + ptJpsi, + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candJpsi.itsNClsDauPos(), + candJpsi.tpcNClsCrossedRowsDauPos(), + candJpsi.itsChi2NClDauPos(), + candJpsi.tpcChi2NClDauPos(), + absEta(candJpsi.tglDauPos()), + candJpsi.itsNClsDauNeg(), + candJpsi.tpcNClsCrossedRowsDauNeg(), + candJpsi.itsChi2NClDauNeg(), + candJpsi.tpcChi2NClDauNeg(), + absEta(candJpsi.tglDauNeg()), + // kaon features + candidate.ptProng1(), + candKa.itsNCls(), + candKa.tpcNClsCrossedRows(), + candKa.itsChi2NCl(), + candKa.tpcChi2NCl(), + absEta(candKa.tgl()), + candKa.tpcNSigmaKa(), + candKa.tofNSigmaKa(), + candKa.tpcTofNSigmaKa(), + // MC truth + flagMcMatchRec, + flagMcDecayChanRec, + isSignal, + flagWrongCollision, + ptMother); + } + } + + /// Fill particle histograms (gen MC truth) + void fillCandMcGen(aod::HfMcGenRedBps::iterator const& particle) + { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + return; + } + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + + registry.fill(HIST("hPtJpsiGen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtKGen"), ptProngs[1], ptParticle); + + // generated B+ with daughters in geometrical acceptance + if (prongsInAcc) { + registry.fill(HIST("hYGenWithProngsInAcceptance"), ptParticle, yParticle); + } + } + + // Process functions + void processData(aod::HfRedCandBplusToJpsiK const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // candidate loop + } // processData + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processData, "Process data without ML for B+", true); + + void processDataWithBplusMl(aod::HfRedCandBplusToJpsiK const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // candidate loop + } // processDataWithBplusMl + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processDataWithBplusMl, "Process data with ML for B+", false); + + void processMc(soa::Join const& candidates, + aod::HfMcGenRedBps const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processMc, "Process MC without ML for B+", false); + + void processMcWithBplusMl(soa::Join const& candidates, + aod::HfMcGenRedBps const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaonTracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBplus(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaonTracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcWithBplusMl + PROCESS_SWITCH(HfTaskBplusToJpsiKReduced, processMcWithBplusMl, "Process MC with ML for B+", false); + +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskBs.cxx b/PWGHF/D2H/Tasks/taskBs.cxx index c394db35d1d..d1d1e252c7c 100644 --- a/PWGHF/D2H/Tasks/taskBs.cxx +++ b/PWGHF/D2H/Tasks/taskBs.cxx @@ -15,24 +15,42 @@ /// /// \author Phil Stahlhut -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.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 + using namespace o2; using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::hf_decay::hf_cand_beauty; /// Bs analysis task struct HfTaskBs { @@ -128,15 +146,15 @@ struct HfTaskBs { registry.add("hYGenWithProngsInAcceptance", "MC particles (generated-daughters in acceptance);B^{0}_{s} candidate #it{y}^{gen};entries", {HistType::kTH2F, {{100, -2., 2.}, axisPt}}); if (checkDecayTypeMc) { - constexpr uint8_t kNBinsDecayTypeMc = hf_cand_bs::DecayTypeMc::NDecayTypeMc + 1; - TString labels[kNBinsDecayTypeMc]; + constexpr uint8_t NBinsDecayTypeMc = hf_cand_bs::DecayTypeMc::NDecayTypeMc + 1; + TString labels[NBinsDecayTypeMc]; labels[hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi] = "B^{0}_{s} #rightarrow (D^{#mp}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#mp}) #pi^{#pm}"; labels[hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi] = "B^{0} #rightarrow (D^{#pm}_{s} #rightarrow K^{#minus} K^{#plus} #pi^{#pm}) #pi^{#mp}"; labels[hf_cand_bs::DecayTypeMc::PartlyRecoDecay] = "Partly reconstructed decay channel"; labels[hf_cand_bs::DecayTypeMc::NDecayTypeMc] = "Other decays"; - static const AxisSpec axisDecayType = {kNBinsDecayTypeMc, 0.5, kNBinsDecayTypeMc + 0.5, ""}; + static const AxisSpec axisDecayType = {NBinsDecayTypeMc, 0.5, NBinsDecayTypeMc + 0.5, ""}; registry.add("hDecayTypeMc", "DecayType", {HistType::kTH3F, {axisDecayType, axisMassBs, axisPt}}); - for (uint8_t iBin = 0; iBin < kNBinsDecayTypeMc; ++iBin) { + for (uint8_t iBin = 0; iBin < NBinsDecayTypeMc; ++iBin) { registry.get(HIST("hDecayTypeMc"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin]); } } @@ -183,7 +201,7 @@ struct HfTaskBs { registry.fill(HIST("hIPProd"), candidate.impactParameterProduct(), ptCandBs); registry.fill(HIST("hInvMassDs"), hfHelper.invMassDsToKKPi(candDs), ptCandBs); } // candidate loop - } // process + } // process /// Bs MC analysis and fill histograms void processMc(soa::Filtered> const& candidates, @@ -200,9 +218,9 @@ struct HfTaskBs { auto ptCandBs = candidate.pt(); auto candDs = candidate.prong0_as>(); auto invMassCandBs = hfHelper.invMassBsToDsPi(candidate); - int flagMcMatchRecBs = std::abs(candidate.flagMcMatchRec()); + auto flagMcMatchRecBs = std::abs(candidate.flagMcMatchRec()); - if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { + if (flagMcMatchRecBs == DecayChannelMain::BsToDsPi) { auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kBS, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -248,9 +266,9 @@ struct HfTaskBs { registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandBs); if (checkDecayTypeMc) { - if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi)) { // B0(bar) → Ds± π∓ → (K- K+ π±) π∓ + if (flagMcMatchRecBs == DecayChannelMain::B0ToDsPi) { // B0(bar) → Ds± π∓ → (K- K+ π±) π∓ registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi, invMassCandBs, ptCandBs); - } else if (TESTBIT(flagMcMatchRecBs, hf_cand_bs::DecayTypeMc::PartlyRecoDecay)) { // Partly reconstructed decay channel + } else if (flagMcMatchRecBs == hf_cand_bs::DecayTypeMc::PartlyRecoDecay) { // FIXME, Partly reconstructed decay channel registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::PartlyRecoDecay, invMassCandBs, ptCandBs); } else { registry.fill(HIST("hDecayTypeMc"), 1 + hf_cand_bs::DecayTypeMc::NDecayTypeMc, invMassCandBs, ptCandBs); @@ -261,7 +279,7 @@ struct HfTaskBs { // MC gen. level for (const auto& particle : mcParticles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { + if (std::abs(particle.flagMcMatchGen()) == DecayChannelMain::BsToDsPi) { auto ptParticle = particle.pt(); auto yParticle = RecoDecay::y(particle.pVector(), o2::constants::physics::MassBS); @@ -304,7 +322,7 @@ struct HfTaskBs { registry.fill(HIST("hYGenWithProngsInAcceptance"), yParticle, ptParticle); } } // gen - } // process + } // process PROCESS_SWITCH(HfTaskBs, processMc, "Process MC", false); }; // struct diff --git a/PWGHF/D2H/Tasks/taskBsReduced.cxx b/PWGHF/D2H/Tasks/taskBsReduced.cxx index e892a526831..a5a89e241cf 100644 --- a/PWGHF/D2H/Tasks/taskBsReduced.cxx +++ b/PWGHF/D2H/Tasks/taskBsReduced.cxx @@ -14,16 +14,31 @@ /// /// \author Fabio Catalano , CERN -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -453,7 +468,7 @@ struct HfTaskBsReduced { } } if (fillSparses) { - if constexpr (withDmesMl) { + if constexpr (doMc) { if (isSignal) { if constexpr (withDmesMl) { registry.fill(HIST("hMassPtCutVarsRecSig"), invMassBs, ptCandBs, candidate.decayLength(), candidate.decayLengthXY() / candidate.errorDecayLengthXY(), candidate.impactParameterProduct(), candidate.cpa(), invMassDs, ptDs, candidate.prong0MlScoreBkg(), candidate.prong0MlScoreNonprompt()); diff --git a/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx new file mode 100644 index 00000000000..bf06d3c7295 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskBsToJpsiPhiReduced.cxx @@ -0,0 +1,622 @@ +// 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 taskBsToJpsiPhiReduced.cxx +/// \brief Bs → Jpsi phi → (µ+ µ-) (K+K-) analysis task +/// +/// \author Fabrizio Chinu , Università degli Studi and INFN Torino +/// \author Fabrizio Grosa , CERN + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponseBsToJpsiPhiReduced.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsPid.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 +#include +#include +#include + +using namespace o2; +using namespace o2::aod; +using namespace o2::analysis; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::aod::pid_tpc_tof_utils; + +namespace o2::aod +{ +namespace hf_cand_bstojpsiphi_lite +{ +DECLARE_SOA_COLUMN(PtJpsi, ptJpsi, float); //! Transverse momentum of Jpsi daughter candidate (GeV/c) +DECLARE_SOA_COLUMN(PtBach0, ptBach0, float); //! Transverse momentum of bachelor kaon(<- phi) (GeV/c) +DECLARE_SOA_COLUMN(PtBach1, ptBach1, float); //! Transverse momentum of bachelor kaon(<- phi) (GeV/c) +DECLARE_SOA_COLUMN(ItsNClsJpsiDauPos, itsNClsJpsiDauPos, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsJpsiDauPos, tpcNClsCrossedRowsJpsiDauPos, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(ItsChi2NClJpsiDauPos, itsChi2NClJpsiDauPos, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(TpcChi2NClJpsiDauPos, tpcChi2NClJpsiDauPos, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(AbsEtaJpsiDauPos, absEtaJpsiDauPos, float); //! |eta| +DECLARE_SOA_COLUMN(ItsNClsJpsiDauNeg, itsNClsJpsiDauNeg, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsJpsiDauNeg, tpcNClsCrossedRowsJpsiDauNeg, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(ItsChi2NClJpsiDauNeg, itsChi2NClJpsiDauNeg, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(TpcChi2NClJpsiDauNeg, tpcChi2NClJpsiDauNeg, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(AbsEtaJpsiDauNeg, absEtaJpsiDauNeg, float); //! |eta| +DECLARE_SOA_COLUMN(ItsNClsLfTrack0, itsNClsLfTrack0, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsLfTrack0, tpcNClsCrossedRowsLfTrack0, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(ItsChi2NClLfTrack0, itsChi2NClLfTrack0, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(TpcChi2NClLfTrack0, tpcChi2NClLfTrack0, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(AbsEtaLfTrack0, absEtaLfTrack0, float); //! |eta| +DECLARE_SOA_COLUMN(ItsNClsLfTrack1, itsNClsLfTrack1, int); //! Number of clusters in ITS +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsLfTrack1, tpcNClsCrossedRowsLfTrack1, int); //! Number of TPC crossed rows +DECLARE_SOA_COLUMN(ItsChi2NClLfTrack1, itsChi2NClLfTrack1, float); //! ITS chi2 / Number of clusters +DECLARE_SOA_COLUMN(TpcChi2NClLfTrack1, tpcChi2NClLfTrack1, float); //! TPC chi2 / Number of clusters +DECLARE_SOA_COLUMN(AbsEtaLfTrack1, absEtaLfTrack1, float); //! |eta| +DECLARE_SOA_COLUMN(MJpsi, mJpsi, float); //! Invariant mass of Jpsi daughter candidates (GeV/c) +DECLARE_SOA_COLUMN(MPhi, mPhi, float); //! Invariant mass of phi daughter candidates (GeV/c) +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(PtGen, ptGen, 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(NSigTpcKaBachelor0, nSigTpcKaBachelor0, float); //! TPC Nsigma separation for bachelor 0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKaBachelor0, nSigTofKaBachelor0, float); //! TOF Nsigma separation for bachelor 0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKaBachelor0, nSigTpcTofKaBachelor0, float); //! Combined TPC and TOF Nsigma separation for bachelor 0 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcKaBachelor1, nSigTpcKaBachelor1, float); //! TPC Nsigma separation for bachelor 1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofKaBachelor1, nSigTofKaBachelor1, float); //! TOF Nsigma separation for bachelor 1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofKaBachelor1, nSigTpcTofKaBachelor1, float); //! Combined TPC and TOF Nsigma separation for bachelor 1 with kaon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauPos, nSigTpcMuJpsiDauPos, float); //! TPC Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauPos, nSigTofMuJpsiDauPos, float); //! TOF Nsigma separation for Jpsi DauPos with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauPos, nSigTpcTofMuJpsiDauPos, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong0 with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcMuJpsiDauNeg, nSigTpcMuJpsiDauNeg, float); //! TPC Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTofMuJpsiDauNeg, nSigTofMuJpsiDauNeg, float); //! TOF Nsigma separation for Jpsi DauNeg with muon mass hypothesis +DECLARE_SOA_COLUMN(NSigTpcTofMuJpsiDauNeg, nSigTpcTofMuJpsiDauNeg, float); //! Combined TPC and TOF Nsigma separation for Jpsi prong1 with muon 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(CtXY, ctXY, float); //! Pseudo-proper decay length of candidate +DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! Impact parameter product of B daughters +DECLARE_SOA_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, float); //! Impact parameter product of Jpsi daughters +DECLARE_SOA_COLUMN(ImpactParameterProductPhi, impactParameterProductPhi, float); //! Impact parameter product of Phi daughters +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauPos, impactParameterJpsiDauPos, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterJpsiDauNeg, impactParameterJpsiDauNeg, float); //! Impact parameter of Jpsi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterLfTrack0, impactParameterLfTrack0, float); //! Impact parameter of Phi daughter candidate +DECLARE_SOA_COLUMN(ImpactParameterLfTrack1, impactParameterLfTrack1, float); //! Impact parameter of Phi daughter 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(CpaJpsi, cpaJpsi, float); //! Cosine pointing angle of Jpsi daughter candidate +DECLARE_SOA_COLUMN(CpaXYJpsi, cpaXYJpsi, float); //! Cosine pointing angle in transverse plane of Jpsi daughter candidate +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs +DECLARE_SOA_COLUMN(MlScoreSig, mlScoreSig, float); //! ML score for signal class +DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); //! Flag for association with wrong collision +} // namespace hf_cand_bstojpsiphi_lite + +DECLARE_SOA_TABLE(HfRedCandBsLites, "AOD", "HFREDCANDBSLITE", //! Table with some Bs properties + hf_cand_bstojpsiphi_lite::M, + hf_cand_bstojpsiphi_lite::Pt, + hf_cand_bstojpsiphi_lite::Eta, + hf_cand_bstojpsiphi_lite::Phi, + hf_cand_bstojpsiphi_lite::Y, + hf_cand_bstojpsiphi_lite::Cpa, + hf_cand_bstojpsiphi_lite::CpaXY, + hf_cand::Chi2PCA, + hf_cand_bstojpsiphi_lite::DecayLength, + hf_cand_bstojpsiphi_lite::DecayLengthXY, + hf_cand_bstojpsiphi_lite::DecayLengthNormalised, + hf_cand_bstojpsiphi_lite::DecayLengthXYNormalised, + hf_cand_bstojpsiphi_lite::CtXY, + hf_cand_bstojpsiphi_lite::ImpactParameterProduct, + hf_cand_bstojpsiphi_lite::ImpactParameterProductJpsi, + hf_cand_bstojpsiphi_lite::ImpactParameterProductPhi, + hf_cand_bstojpsiphi_lite::MaxNormalisedDeltaIP, + hf_cand_bstojpsiphi_lite::MlScoreSig, + // hf_sel_candidate_bplus::IsSelBsToJpsiPi, + // Jpsi meson features + hf_cand_bstojpsiphi_lite::MJpsi, + hf_cand_bstojpsiphi_lite::PtJpsi, + hf_cand_bstojpsiphi_lite::MPhi, + hf_cand_bstojpsiphi_lite::ImpactParameterJpsiDauPos, + hf_cand_bstojpsiphi_lite::ImpactParameterJpsiDauNeg, + hf_cand_bstojpsiphi_lite::ImpactParameterLfTrack0, + hf_cand_bstojpsiphi_lite::ImpactParameterLfTrack1, + // Jpsi daughter features + hf_cand_bstojpsiphi_lite::ItsNClsJpsiDauPos, + hf_cand_bstojpsiphi_lite::TpcNClsCrossedRowsJpsiDauPos, + hf_cand_bstojpsiphi_lite::ItsChi2NClJpsiDauPos, + hf_cand_bstojpsiphi_lite::TpcChi2NClJpsiDauPos, + hf_cand_bstojpsiphi_lite::AbsEtaJpsiDauPos, + hf_cand_bstojpsiphi_lite::ItsNClsJpsiDauNeg, + hf_cand_bstojpsiphi_lite::TpcNClsCrossedRowsJpsiDauNeg, + hf_cand_bstojpsiphi_lite::ItsChi2NClJpsiDauNeg, + hf_cand_bstojpsiphi_lite::TpcChi2NClJpsiDauNeg, + hf_cand_bstojpsiphi_lite::AbsEtaJpsiDauNeg, + // kaon features + hf_cand_bstojpsiphi_lite::PtBach0, + hf_cand_bstojpsiphi_lite::ItsNClsLfTrack0, + hf_cand_bstojpsiphi_lite::TpcNClsCrossedRowsLfTrack0, + hf_cand_bstojpsiphi_lite::ItsChi2NClLfTrack0, + hf_cand_bstojpsiphi_lite::TpcChi2NClLfTrack0, + hf_cand_bstojpsiphi_lite::AbsEtaLfTrack0, + hf_cand_bstojpsiphi_lite::NSigTpcKaBachelor0, + hf_cand_bstojpsiphi_lite::NSigTofKaBachelor0, + hf_cand_bstojpsiphi_lite::NSigTpcTofKaBachelor0, + hf_cand_bstojpsiphi_lite::PtBach1, + hf_cand_bstojpsiphi_lite::ItsNClsLfTrack1, + hf_cand_bstojpsiphi_lite::TpcNClsCrossedRowsLfTrack1, + hf_cand_bstojpsiphi_lite::ItsChi2NClLfTrack1, + hf_cand_bstojpsiphi_lite::TpcChi2NClLfTrack1, + hf_cand_bstojpsiphi_lite::AbsEtaLfTrack1, + hf_cand_bstojpsiphi_lite::NSigTpcKaBachelor1, + 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_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_bstojpsiphi_lite::FlagWrongCollision, +// hf_cand_bstojpsiphi_lite::MJpsi, +// hf_cand_bstojpsiphi_lite::PtJpsi, +// hf_cand_bstojpsiphi_lite::M, +// hf_cand_bstojpsiphi_lite::Pt, +// // hf_cand_bstojpsiphi_lite::MlScoreSig, +// hf_bplus_mc::PdgCodeBeautyMother, +// hf_bplus_mc::PdgCodeCharmMother, +// hf_bplus_mc::PdgCodeDauPos, +// hf_bplus_mc::PdgCodeDauNeg, +// hf_bplus_mc::PdgCodeProng2); +} // namespace o2::aod + +// string definitions, used for histogram axis labels +const TString stringPt = "#it{p}_{T} (GeV/#it{c})"; +const TString stringPtJpsi = "#it{p}_{T}(Jpsi) (GeV/#it{c});"; +const TString bSCandTitle = "B_{s}^{0} candidates;"; +const TString entries = "entries"; +const TString bSCandMatch = "B_{s}^{0} candidates (matched);"; +const TString bSCandUnmatch = "B_{s}^{0} candidates (unmatched);"; +const TString mcParticleMatched = "MC particles (matched);"; + +/// Bs analysis task +struct HfTaskBsToJpsiPhiReduced { + Produces hfRedCandBsLite; + // Produces hfRedBsMcCheck; + + Configurable selectionFlagBs{"selectionFlagBs", 1, "Selection Flag for Bs"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum"}; + Configurable fillBackground{"fillBackground", false, "Flag to enable filling of background histograms/sparses/tree (only MC)"}; + 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"}; + // topological cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_bs_to_jpsi_phi::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_bs_to_jpsi_phi::Cuts[0], hf_cuts_bs_to_jpsi_phi::NBinsPt, hf_cuts_bs_to_jpsi_phi::NCutVars, hf_cuts_bs_to_jpsi_phi::labelsPt, hf_cuts_bs_to_jpsi_phi::labelsCutVar}, "Bs candidate selection per pT bin"}; + // Enable PID + Configurable kaonPidMethod{"kaonPidMethod", PidMethod::TpcOrTof, "PID selection method for the bachelor kaon (PidMethod::NoPid: none, PidMethod::TpcOrTof: TPC or TOF, PidMethod::TpcAndTof: TPC and TOF)"}; + Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + // TPC PID + Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; + Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; + Configurable nSigmaTpcMax{"nSigmaTpcMax", 5., "Nsigma cut on TPC only"}; + Configurable nSigmaTpcCombinedMax{"nSigmaTpcCombinedMax", 5., "Nsigma cut on TPC combined with TOF"}; + // TOF PID + Configurable ptPidTofMin{"ptPidTofMin", 0.15, "Lower bound of track pT for TOF PID"}; + Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; + Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; + Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // Bs ML inference + Configurable> binsPtBsMl{"binsPtBsMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; + Configurable> cutDirBsMl{"cutDirBsMl", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold"}; + Configurable> cutsBsMl{"cutsBsMl", {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 nClassesBsMl{"nClassesBsMl", 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{"path_ccdb/BDT_BS/"}, "Paths of models on CCDB"}; + Configurable> onnxFileNames{"onnxFileNames", std::vector{"ModelHandler_onnx_BSToJpsiPhi.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"}; + + HfHelper hfHelper; + TrackSelectorKa selectorKaon; + o2::analysis::HfMlResponseBsToJpsiPhiReduced hfMlResponse; + o2::ccdb::CcdbApi ccdbApi; + + using TracksKaon = soa::Join; + std::vector outputMl = {}; + + // Filter filterSelectCandidates = (aod::hf_sel_candidate_bplus::isSelBsToJpsiPi >= selectionFlagBs); + + HistogramRegistry registry{"registry"}; + + void init(InitContext&) + { + std::array processFuncData{doprocessData, doprocessDataWithBsMl}; + if ((std::accumulate(processFuncData.begin(), processFuncData.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for data can be enabled at a time."); + } + std::array processFuncMc{doprocessMc, doprocessMcWithBsMl}; + if ((std::accumulate(processFuncMc.begin(), processFuncMc.end(), 0)) > 1) { + LOGP(fatal, "Only one process function for MC can be enabled at a time."); + } + + if (kaonPidMethod < 0 || kaonPidMethod >= PidMethod::NPidMethods) { + LOGP(fatal, "Invalid PID option in configurable, please set 0 (no PID), 1 (TPC or TOF), or 2 (TPC and TOF)"); + } + + if (kaonPidMethod != PidMethod::NoPid) { + selectorKaon.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); + selectorKaon.setRangeNSigmaTpc(-nSigmaTpcMax, nSigmaTpcMax); + selectorKaon.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedMax, nSigmaTpcCombinedMax); + selectorKaon.setRangePtTof(ptPidTofMin, ptPidTofMax); + selectorKaon.setRangeNSigmaTof(-nSigmaTofMax, nSigmaTofMax); + selectorKaon.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); + } + + const AxisSpec axisMassBs{150, 4.5, 6.0}; + const AxisSpec axisMassJpsi{600, 2.8f, 3.4f}; + const AxisSpec axisMassPhi{200, 0.9f, 1.1f}; + const AxisSpec axisPtProng{100, 0., 10.}; + const AxisSpec axisImpactPar{200, -0.05, 0.05}; + const AxisSpec axisPtJpsi{100, 0., 50.}; + const AxisSpec axisRapidity{100, -2., 2.}; + const AxisSpec axisPtB{(std::vector)binsPt, "#it{p}_{T}^{B_{s}^{0}} (GeV/#it{c})"}; + const AxisSpec axisPtKa{100, 0.f, 10.f}; + const AxisSpec axisPtPhi{100, 0.f, 10.f}; + + registry.add("hMass", bSCandTitle + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassBs, axisPtB}}); + registry.add("hMassJpsi", bSCandTitle + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hMassPhi", bSCandTitle + "inv. mass K^{+}K^{#minus} (GeV/#it{c}^{2});" + stringPt, {HistType::kTH2F, {axisMassPhi, axisPtPhi}}); + registry.add("hd0K", bSCandTitle + "Kaon DCAxy to prim. vertex (cm);" + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + + // histograms processMC + if (doprocessMc || doprocessMcWithBsMl) { + registry.add("hPtJpsiGen", mcParticleMatched + "J/#Psi #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtPhiGen", mcParticleMatched + "#phi #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hPtKGen", mcParticleMatched + "Kaon #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisPtProng, axisPtB}}); + registry.add("hYGenWithProngsInAcceptance", mcParticleMatched + "B_{s}^{0} #it{p}_{T}^{gen} (GeV/#it{c}); B_{s}^{0} #it{y}", {HistType::kTH2F, {axisPtProng, axisRapidity}}); + registry.add("hMassRecSig", bSCandMatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisMassBs, axisPtB}}); + registry.add("hMassJpsiRecSig", bSCandMatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hMassPhiRecSig", bSCandMatch + "inv. mass K^{+}K^{#minus} (GeV/#it{c}^{2}); #phi " + stringPt, {HistType::kTH2F, {axisMassPhi, axisPtPhi}}); + registry.add("hd0KRecSig", bSCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + registry.add("hMassRecBg", bSCandUnmatch + "inv. mass J/#Psi K^{+} (GeV/#it{c}^{2}); B_{s}^{0} " + stringPt, {HistType::kTH2F, {axisMassBs, axisPtB}}); + registry.add("hMassJpsiRecBg", bSCandUnmatch + "inv. mass #mu^{+}#mu^{#minus} (GeV/#it{c}^{2}); J/#Psi " + stringPt, {HistType::kTH2F, {axisMassJpsi, axisPtJpsi}}); + registry.add("hMassPhiRecBg", bSCandMatch + "inv. mass K^{+}K^{#minus} (GeV/#it{c}^{2}); #phi " + stringPt, {HistType::kTH2F, {axisMassPhi, axisPtPhi}}); + registry.add("hd0KRecBg", bSCandMatch + "Kaon DCAxy to prim. vertex (cm); K^{+} " + stringPt, {HistType::kTH2F, {axisImpactPar, axisPtKa}}); + } + + if (doprocessDataWithBsMl || doprocessMcWithBsMl) { + hfMlResponse.configure(binsPtBsMl, cutsBsMl, cutDirBsMl, nClassesBsMl); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); + } else { + hfMlResponse.setModelPathsLocal(onnxFileNames); + } + hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); + hfMlResponse.init(); + } + } + + /// Selection of Bs daughter in geometrical acceptance + /// \param etaProng is the pseudorapidity of Bs prong + /// \param ptProng is the pT of Bs prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Calculate pseudorapidity from track tan(lambda) + /// \param tgl is the track tangent of the dip angle + /// \return pseudorapidity + inline float absEta(float tgl) + { + return std::abs(std::log(std::tan(o2::constants::math::PIQuarter - 0.5f * std::atan(tgl)))); + } + + /// Fill candidate information at reconstruction level + /// \param doMc is the flag to enable the filling with MC information + /// \param withBsMl is the flag to enable the filling with ML scores for the Bs candidate + /// \param candidate is the Bs candidate + /// \param candidatesJpsi is the table with Jpsi candidates + template + void fillCand(Cand const& candidate, + aod::HfRedJpsis const& /*candidatesJpsi*/, + aod::HfRedBach0Tracks const&, + aod::HfRedBach1Tracks const&) + { + auto ptCandBs = candidate.pt(); + auto invMassBs = hfHelper.invMassBsToJpsiPhi(candidate); + auto candJpsi = candidate.template jpsi_as(); + auto candKa0 = candidate.template prong0Phi_as(); + auto candKa1 = candidate.template prong1Phi_as(); + std::array pVecKa0 = {candKa0.px(), candKa0.py(), candKa0.pz()}; + std::array pVecKa1 = {candKa1.px(), candKa1.py(), candKa1.pz()}; + auto ptJpsi = candidate.ptProng0(); + auto invMassJpsi = candJpsi.m(); + auto invMassPhi = RecoDecay::m(std::array{pVecKa0, pVecKa1}, std::array{o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}); + uint8_t statusBs = 0; + + int8_t flagMcMatchRec{0}, flagMcDecayChanRec{0}, flagWrongCollision{0}; + bool isSignal = false; + if constexpr (doMc) { + flagMcMatchRec = candidate.flagMcMatchRec(); + flagMcDecayChanRec = candidate.flagMcDecayChanRec(); + flagWrongCollision = candidate.flagWrongCollision(); + isSignal = flagMcMatchRec == o2::hf_decay::hf_cand_beauty::BsToJpsiKK && + flagMcDecayChanRec == o2::hf_decay::hf_cand_beauty::BsToJpsiPhi; + } + + SETBIT(statusBs, SelectionStep::RecoSkims); + if (hfHelper.selectionBsToJpsiPhiTopol(candidate, candKa0, candKa1, cuts, binsPt)) { + SETBIT(statusBs, SelectionStep::RecoTopol); + } else if (selectionFlagBs >= BIT(SelectionStep::RecoTopol) * 2 - 1) { + return; + } + // track-level PID selection + // auto trackKa = candidate.template prong1_as(); + if (kaonPidMethod == PidMethod::TpcOrTof || kaonPidMethod == PidMethod::TpcAndTof) { + int pidTrackKa0{TrackSelectorPID::Status::NotApplicable}; + int pidTrackKa1{TrackSelectorPID::Status::NotApplicable}; + if (kaonPidMethod == PidMethod::TpcOrTof) { + pidTrackKa0 = selectorKaon.statusTpcOrTof(candKa0); + pidTrackKa1 = selectorKaon.statusTpcOrTof(candKa1); + } else if (kaonPidMethod == PidMethod::TpcAndTof) { + pidTrackKa0 = selectorKaon.statusTpcAndTof(candKa0); + pidTrackKa1 = selectorKaon.statusTpcAndTof(candKa1); + } + if (hfHelper.selectionBsToJpsiPhiPid(pidTrackKa0, acceptPIDNotApplicable.value) && + hfHelper.selectionBsToJpsiPhiPid(pidTrackKa1, acceptPIDNotApplicable.value)) { + // LOGF(info, "Bs candidate selection failed at PID selection"); + SETBIT(statusBs, SelectionStep::RecoPID); + } else if (selectionFlagBs >= BIT(SelectionStep::RecoPID) * 2 - 1) { + return; + } + } + + float candidateMlScoreSig = -1; + if constexpr (withBsMl) { + // Bs ML selections + std::vector inputFeatures = hfMlResponse.getInputFeatures(candidate, candKa0, candKa1); + if (hfMlResponse.isSelectedMl(inputFeatures, ptCandBs, outputMl)) { + SETBIT(statusBs, SelectionStep::RecoMl); + } else if (selectionFlagBs >= BIT(SelectionStep::RecoMl) * 2 - 1) { + return; + } + candidateMlScoreSig = outputMl[1]; + } + + registry.fill(HIST("hMass"), invMassBs, ptCandBs); + registry.fill(HIST("hMassJpsi"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hMassPhi"), invMassPhi, candidate.ptProng0()); + registry.fill(HIST("hd0K"), candidate.impactParameter1(), candidate.ptProng1()); + if constexpr (doMc) { + if (isSignal) { + registry.fill(HIST("hMassRecSig"), invMassBs, ptCandBs); + registry.fill(HIST("hMassJpsiRecSig"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0KRecSig"), candidate.impactParameter1(), candidate.ptProng1()); + } else if (fillBackground) { + registry.fill(HIST("hMassRecBg"), invMassBs, ptCandBs); + registry.fill(HIST("hMassJpsiRecBg"), invMassJpsi, candidate.ptProng0()); + registry.fill(HIST("hd0KRecBg"), candidate.impactParameter1(), candidate.ptProng1()); + } + } + + float pseudoRndm = ptJpsi * 1000. - static_cast(ptJpsi * 1000); + if (ptCandBs >= ptMaxForDownSample || pseudoRndm < downSampleBkgFactor) { + float ptMother = -1.; + if constexpr (doMc) { + ptMother = candidate.ptMother(); + } + + hfRedCandBsLite( + // Bs - meson features + invMassBs, + ptCandBs, + candidate.eta(), + candidate.phi(), + hfHelper.yBs(candidate), + candidate.cpa(), + candidate.cpaXY(), + candidate.chi2PCA(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ctXY(std::array{o2::constants::physics::MassMuon, o2::constants::physics::MassMuon, o2::constants::physics::MassKPlus, o2::constants::physics::MassKPlus}), + candidate.impactParameterProduct(), + candidate.impactParameterProductJpsi(), + candidate.impactParameterProductPhi(), + candidate.maxNormalisedDeltaIP(), + candidateMlScoreSig, + // J/Psi features + invMassJpsi, + ptJpsi, + invMassPhi, + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.impactParameter3(), + candJpsi.itsNClsDauPos(), + candJpsi.tpcNClsCrossedRowsDauPos(), + candJpsi.itsChi2NClDauPos(), + candJpsi.tpcChi2NClDauPos(), + absEta(candJpsi.tglDauPos()), + candJpsi.itsNClsDauNeg(), + candJpsi.tpcNClsCrossedRowsDauNeg(), + candJpsi.itsChi2NClDauNeg(), + candJpsi.tpcChi2NClDauNeg(), + absEta(candJpsi.tglDauNeg()), + // kaon features + candKa0.pt(), + candKa0.itsNCls(), + candKa0.tpcNClsCrossedRows(), + candKa0.itsChi2NCl(), + candKa0.tpcChi2NCl(), + absEta(candKa0.tgl()), + // candKa.absEtaBach(candKa.tgl()), + candKa0.tpcNSigmaKa(), + candKa0.tofNSigmaKa(), + candKa0.tpcTofNSigmaKa(), + candKa1.pt(), + candKa1.itsNCls(), + candKa1.tpcNClsCrossedRows(), + candKa1.itsChi2NCl(), + candKa1.tpcChi2NCl(), + absEta(candKa1.tgl()), + candKa1.tpcNSigmaKa(), + candKa1.tofNSigmaKa(), + candKa1.tpcTofNSigmaKa(), + // MC truth + flagMcMatchRec, + flagMcDecayChanRec, + isSignal, + flagWrongCollision, + ptMother); + } + } + + /// Fill particle histograms (gen MC truth) + void fillCandMcGen(aod::HfMcGenRedBss::iterator const& particle) + { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + return; + } + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + + registry.fill(HIST("hPtJpsiGen"), ptProngs[0], ptParticle); + registry.fill(HIST("hPtKGen"), ptProngs[1], ptParticle); + + // generated Bs with daughters in geometrical acceptance + if (prongsInAcc) { + registry.fill(HIST("hYGenWithProngsInAcceptance"), ptParticle, yParticle); + } + } + + // Process functions + void processData(aod::HfRedCandBsToJpsiPhi const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // candidate loop + } // processData + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processData, "Process data without ML for Bs", true); + + void processDataWithBsMl(aod::HfRedCandBsToJpsiPhi const& candidates, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // candidate loop + } // processDataWithBsMl + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processDataWithBsMl, "Process data with ML for Bs", false); + + void processMc(soa::Join const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMc + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processMc, "Process MC without ML for Bs", false); + + void processMcWithBsMl(soa::Join const& candidates, + aod::HfMcGenRedBss const& mcParticles, + aod::HfRedJpsis const& candidatesJpsi, + aod::HfRedBach0Tracks const& kaon0Tracks, + aod::HfRedBach1Tracks const& kaon1Tracks) + { + // MC rec + for (const auto& candidate : candidates) { + if (yCandRecoMax >= 0. && std::abs(hfHelper.yBs(candidate)) > yCandRecoMax) { + continue; + } + fillCand(candidate, candidatesJpsi, kaon0Tracks, kaon1Tracks); + } // rec + + // MC gen. level + for (const auto& particle : mcParticles) { + fillCandMcGen(particle); + } // gen + } // processMcWithBsMl + PROCESS_SWITCH(HfTaskBsToJpsiPhiReduced, processMcWithBsMl, "Process MC with ML for Bs", false); + +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx index 95cefe1ff0f..16da492051f 100644 --- a/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx +++ b/PWGHF/D2H/Tasks/taskCharmPolarisation.cxx @@ -15,24 +15,48 @@ /// \author F. Grosa (CERN) fabrizio.grosa@cern.ch /// \author S. Kundu (CERN) sourav.kundu@cern.ch /// \author M. Faggin (CERN) mattia.faggin@cern.ch +/// \author M. Li (CCNU) mingze.li@cern.ch -#include - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// #include "Common/Core/EventPlaneHelper.h" -// #include "Common/DataModel/Qvectors.h" - +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Qvectors.h" + +#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 using namespace o2; using namespace o2::aod; @@ -48,6 +72,7 @@ enum CosThetaStarType : uint8_t { Production, Beam, Random, + EP, NTypes }; enum DecayChannel : uint8_t { @@ -61,6 +86,11 @@ enum MassHyposLcToPKPi : uint8_t { PiKP, NMassHypoLcToPKPi }; +enum QvecEstimator : uint8_t { + FV0A = 0, + FT0M, + FT0C, +}; /// columns for table to study the Lc->PKPi background DECLARE_SOA_COLUMN(MassLc, massLc, float); @@ -105,7 +135,7 @@ DECLARE_SOA_TABLE(HfLcPolBkg, "AOD", "HFLCPOLBKG", } // namespace o2::aod -struct TaskPolarisationCharmHadrons { +struct HfTaskCharmPolarisation { Produces rowCandLcBkg; float massPi{0.f}; @@ -120,25 +150,11 @@ struct TaskPolarisationCharmHadrons { Configurable selectionFlagDstarToD0Pi{"selectionFlagDstarToD0Pi", true, "Selection Flag for D* decay to D0 Pi"}; Configurable selectionFlagLcToPKPi{"selectionFlagLcToPKPi", 1, "Selection Flag for Lc decay to P K Pi"}; - ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {200, 0.139f, 0.179f}, "#it{M} (GeV/#it{c}^{2})"}; - ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.f, 100.f}, "#it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis configThnAxisY{"configThnAxisY", {20, -1.f, 1.f}, "#it{y}"}; - ConfigurableAxis configThnAxisCosThetaStarHelicity{"configThnAxisCosThetaStarHelicity", {20, -1.f, 1.f}, "cos(#vartheta_{helicity})"}; - ConfigurableAxis configThnAxisCosThetaStarProduction{"configThnAxisCosThetaStarProduction", {20, -1.f, 1.f}, "cos(#vartheta_{production})"}; - ConfigurableAxis configThnAxisCosThetaStarRandom{"configThnAxisCosThetaStarRandom", {20, -1.f, 1.f}, "cos(#vartheta_{random})"}; - ConfigurableAxis configThnAxisCosThetaStarBeam{"configThnAxisCosThetaStarBeam", {20, -1.f, 1.f}, "cos(#vartheta_{beam})"}; - ConfigurableAxis configThnAxisMlBkg{"configThnAxisMlBkg", {100, 0.f, 1.f}, "ML bkg"}; - ConfigurableAxis configThnAxisInvMassD0{"configThnAxisInvMassD0", {250, 1.65f, 2.15f}, "#it{M}(D^{0}) (GeV/#it{c}^{2})"}; // only for D*+ - ConfigurableAxis configThnAxisInvMassKPiLc{"configThnAxisInvMassKPiLc", {120, 0.65f, 1.25f}, "#it{M}(K#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; // only for Lc+->pKpi - // ConfigurableAxis configThnAxisMlPrompt{"configThnAxisMlPrompt", {100, 0.f, 1.f}, "ML prompt"}; - ConfigurableAxis configThnAxisMlNonPrompt{"configThnAxisMlNonPrompt", {100, 0.f, 1.f}, "ML non-prompt"}; - // ConfigurableAxis configThnAxisCent{"configThnAxisCent", {102, -1.f, 101.f}, "centrality (%)"}; - ConfigurableAxis configThnAxisNumPvContributors{"configThnAxisNumPvContributors", {300, -0.5f, 299.5f}, "num PV contributors"}; - ConfigurableAxis configThnAxisPtB{"configThnAxisPtB", {3000, 0.f, 300.f}, "#it{p}_{T}(B mother) (GeV/#it{c})"}; - ConfigurableAxis configThnAxisAbsEtaTrackMin{"configThnAxisEtaTrackMin", {3, 0.f, 0.3f}, "min |#it{#eta_{track}}|"}; - ConfigurableAxis configThnAxisNumItsClsMin{"configThnAxisNumItsClsMin", {4, 3.5f, 7.5f}, "min #it{N}_{cls ITS}"}; - ConfigurableAxis configThnAxisNumTpcClsMin{"configThnAxisNumTpcClsMin", {3, 79.5f, 140.5f}, "min #it{N}_{cls TPC}"}; - ConfigurableAxis configThnAxisCharge{"configThnAxisCharge", {2, -2.f, 2.f}, "electric charge"}; + // Configurable harmonic{"harmonic", 2, "harmonic number"}; + Configurable qVecDetector{"qVecDetector", 2, "Detector for Q vector estimation (FV0A: 0, FT0M: 1, FT0C: 2)"}; + Configurable centEstimator{"centEstimator", 2, "Centrality estimator ((None: 0, FT0C: 2, FT0M: 3))"}; + Configurable centralityMin{"centralityMin", 30, "Minimum centrality (0-100) to be considered in the analysis"}; + Configurable centralityMax{"centralityMax", 50, "Maximum centrality (0-100) to be considered in the analysis"}; /// activate rotational background Configurable nBkgRotations{"nBkgRotations", 0, "Number of rotated copies (background) per each original candidate"}; @@ -153,6 +169,7 @@ struct TaskPolarisationCharmHadrons { Configurable activateTHnSparseCosThStarProduction{"activateTHnSparseCosThStarProduction", true, "Activate the THnSparse with cosThStar w.r.t. production axis"}; Configurable activateTHnSparseCosThStarBeam{"activateTHnSparseCosThStarBeam", true, "Activate the THnSparse with cosThStar w.r.t. beam axis"}; Configurable activateTHnSparseCosThStarRandom{"activateTHnSparseCosThStarRandom", true, "Activate the THnSparse with cosThStar w.r.t. random axis"}; + Configurable activateTHnSparseCosThStarEP{"activateTHnSparseCosThStarEP", false, "Activate the THnSparse with cosThStar w.r.t. reaction plane axis"}; Configurable activatePartRecoDstar{"activatePartRecoDstar", false, "Activate the study of partly reconstructed D*+ -> D0 (-> KPiPi0) Pi decays"}; float minInvMass{0.f}; float maxInvMass{1000.f}; @@ -179,7 +196,7 @@ struct TaskPolarisationCharmHadrons { struct : ConfigurableGroup { /// monitoring histograms (Dalitz plot) Configurable activateTHnLcChannelMonitor{"activateTHnLcChannelMonitor", false, "Flag to switch on the monitoring THnSparse of M2(Kpi), M2(pK), M2(ppi), pt correlation for Lc -> pKpi"}; - ConfigurableAxis configThnAxisInvMass2KPiLcMonitoring{"configThnAxisInvMassKPiLcMonitoring", {200, 0.3f, 2.3f}, "#it{M}^{2}(K#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisInvMass2KPiLcMonitoring{"configThnAxisInvMass2KPiLcMonitoring", {200, 0.3f, 2.3f}, "#it{M}^{2}(K#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; ConfigurableAxis configThnAxisInvMass2PKLcMonitoring{"configThnAxisInvMass2PKLcMonitoring", {320, 2.f, 5.2f}, "#it{M}^{2}(pK) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; ConfigurableAxis configThnAxisInvMass2PPiLcMonitoring{"configThnAxisInvMass2PPiLcMonitoring", {400, 1.f, 5.f}, "#it{M}^{2}(p#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; @@ -192,15 +209,17 @@ struct TaskPolarisationCharmHadrons { /// Monitoring of phi Euler angle Configurable activateTHnEulerPhiMonitor{"activateTHnEulerPhiMonitor", false, "Flag to switch on the monitoring THnSparse vs. Euler angle phi (Lc -> pKpi)"}; - ConfigurableAxis configTHnAxisEulerPhi{"configTHnAxisEulerPhi", {24, -o2::constants::math::PI, o2::constants::math::PI}, "Euler polar angle #phi"}; /// Application of rapidity cut for reconstructed candidates Configurable rapidityCut{"rapidityCut", 999.f, "Max. value of reconstructed candidate rapidity (abs. value)"}; - Filter filterSelectDstarCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi; - Filter filterSelectLcToPKPiCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLcToPKPi) || (aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLcToPKPi); + HfHelper hfHelper; + SliceCache cache; + EventPlaneHelper epHelper; using CollisionsWithMcLabels = soa::SmallGroups>; + using CollisionsWithMcLabelsAndCent = soa::SmallGroups>; + using CollsWithQVecs = soa::Join; using TracksWithMcLabels = soa::Join; using TracksWithExtra = soa::Join; @@ -220,7 +239,9 @@ struct TaskPolarisationCharmHadrons { using FilteredCandLcToPKPiWSelFlagAndMc = soa::Filtered>; using FilteredCandLcToPKPiWSelFlagAndMcAndMl = soa::Filtered>; - SliceCache cache; + Filter filterSelectDstarCandidates = aod::hf_sel_candidate_dstar::isSelDstarToD0Pi == selectionFlagDstarToD0Pi; + Filter filterSelectLcToPKPiCandidates = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLcToPKPi) || (aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLcToPKPi); + Preslice dstarPerCollision = aod::hf_cand::collisionId; Preslice dstarWithMlPerCollision = aod::hf_cand::collisionId; Preslice dstarWithMcPerCollision = aod::hf_cand::collisionId; @@ -231,13 +252,37 @@ struct TaskPolarisationCharmHadrons { Preslice lcToPKPiWithMcPerCollision = aod::hf_cand::collisionId; Preslice lcToPKPiWithMcAndMlPerCollision = aod::hf_cand::collisionId; - HfHelper hfHelper; + PresliceUnsorted colPerMcCollision = aod::mcparticle::mcCollisionId; + + ConfigurableAxis configTHnAxisEulerPhi{"configTHnAxisEulerPhi", {24, -o2::constants::math::PI, o2::constants::math::PI}, "Euler polar angle #phi"}; + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {200, 0.139f, 0.179f}, "#it{M} (GeV/#it{c}^{2})"}; // o2-linter: disable=pdg/explicit-mass (false positive) + ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.f, 100.f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis configThnAxisY{"configThnAxisY", {20, -1.f, 1.f}, "#it{y}"}; + ConfigurableAxis configThnAxisCosThetaStarHelicity{"configThnAxisCosThetaStarHelicity", {20, -1.f, 1.f}, "cos(#vartheta_{helicity})"}; + ConfigurableAxis configThnAxisCosThetaStarProduction{"configThnAxisCosThetaStarProduction", {20, -1.f, 1.f}, "cos(#vartheta_{production})"}; + ConfigurableAxis configThnAxisCosThetaStarRandom{"configThnAxisCosThetaStarRandom", {20, -1.f, 1.f}, "cos(#vartheta_{random})"}; + ConfigurableAxis configThnAxisCosThetaStarBeam{"configThnAxisCosThetaStarBeam", {20, -1.f, 1.f}, "cos(#vartheta_{beam})"}; + ConfigurableAxis configThnAxisCosThetaStarEP{"configThnAxisCosThetaStarEP", {20, -1.f, 1.f}, "cos(#vartheta_{EP})"}; + ConfigurableAxis configThnAxisMlBkg{"configThnAxisMlBkg", {100, 0.f, 1.f}, "ML bkg"}; + ConfigurableAxis configThnAxisInvMassD0{"configThnAxisInvMassD0", {250, 1.65f, 2.15f}, "#it{M}(D^{0}) (GeV/#it{c}^{2})"}; // only for D*+ + ConfigurableAxis configThnAxisInvMassKPiLc{"configThnAxisInvMassKPiLc", {120, 0.65f, 1.25f}, "#it{M}(K#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; // only for Lc+->pKpi + // ConfigurableAxis configThnAxisMlPrompt{"configThnAxisMlPrompt", {100, 0.f, 1.f}, "ML prompt"}; + ConfigurableAxis configThnAxisMlNonPrompt{"configThnAxisMlNonPrompt", {100, 0.f, 1.f}, "ML non-prompt"}; + ConfigurableAxis configThnAxisCent{"configThnAxisCent", {102, -1.f, 101.f}, "centrality (%)"}; + ConfigurableAxis configThnAxisNumPvContributors{"configThnAxisNumPvContributors", {300, -0.5f, 299.5f}, "num PV contributors"}; + ConfigurableAxis configThnAxisPtB{"configThnAxisPtB", {3000, 0.f, 300.f}, "#it{p}_{T}(B mother) (GeV/#it{c})"}; + ConfigurableAxis configThnAxisAbsEtaTrackMin{"configThnAxisAbsEtaTrackMin", {3, 0.f, 0.3f}, "min |#it{#eta_{track}}|"}; + ConfigurableAxis configThnAxisNumItsClsMin{"configThnAxisNumItsClsMin", {4, 3.5f, 7.5f}, "min #it{N}_{cls ITS}"}; + ConfigurableAxis configThnAxisNumTpcClsMin{"configThnAxisNumTpcClsMin", {3, 79.5f, 140.5f}, "min #it{N}_{cls TPC}"}; + ConfigurableAxis configThnAxisCharge{"configThnAxisCharge", {2, -2.f, 2.f}, "electric charge"}; + ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {100, 0.f, 100.f}, "centrality (%)"}; + HistogramRegistry registry{"registry", {}}; void init(InitContext&) { /// check process functions - std::array processes = {doprocessDstar, doprocessDstarWithMl, doprocessLcToPKPi, doprocessLcToPKPiWithMl, doprocessDstarMc, doprocessDstarMcWithMl, doprocessLcToPKPiMc, doprocessLcToPKPiMcWithMl, doprocessLcToPKPiBackgroundMcWithMl}; + std::array processes = {doprocessDstar, doprocessDstarWithMl, doprocessLcToPKPi, doprocessLcToPKPiWithMl, doprocessDstarMc, doprocessDstarMcWithMl, doprocessLcToPKPiMc, doprocessLcToPKPiMcWithMl, doprocessLcToPKPiBackgroundMcWithMl, doprocessDstarInPbPb, doprocessDstarWithMlInPbPb, doprocessDstarMcInPbPb, doprocessDstarMcWithMlInPbPb}; 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"); @@ -246,7 +291,7 @@ struct TaskPolarisationCharmHadrons { } /// check output THnSparses - std::array sparses = {activateTHnSparseCosThStarHelicity, activateTHnSparseCosThStarProduction, activateTHnSparseCosThStarBeam, activateTHnSparseCosThStarRandom}; + std::array sparses = {activateTHnSparseCosThStarHelicity, activateTHnSparseCosThStarProduction, activateTHnSparseCosThStarBeam, activateTHnSparseCosThStarRandom, activateTHnSparseCosThStarEP}; if (std::accumulate(sparses.begin(), sparses.end(), 0) == 0) { LOGP(fatal, "No output THnSparses enabled"); } else { @@ -262,14 +307,17 @@ struct TaskPolarisationCharmHadrons { if (activateTHnSparseCosThStarRandom) { LOGP(info, "THnSparse with cosThStar w.r.t. random axis active."); } + if (activateTHnSparseCosThStarEP) { + LOGP(info, "THnSparse with cosThStar w.r.t. event plane axis active."); + } } - if (activatePartRecoDstar && !(doprocessDstarMc || doprocessDstarMcWithMl)) { + if (activatePartRecoDstar && !(doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb)) { LOGP(fatal, "Check on partly reconstructed D* mesons only possible for processDstarMc and processDstarMcWithMl"); } // check bkg rotation for MC (not supported currently) - if (nBkgRotations > 0 && (doprocessDstarMc || doprocessDstarMcWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl)) { + if (nBkgRotations > 0 && (doprocessDstarMc || doprocessDstarMcWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb)) { LOGP(fatal, "No background rotation supported for MC."); } @@ -289,6 +337,7 @@ struct TaskPolarisationCharmHadrons { const AxisSpec thnAxisCosThetaStarProduction{configThnAxisCosThetaStarProduction, "cos(#vartheta_{production})"}; const AxisSpec thnAxisCosThetaStarRandom{configThnAxisCosThetaStarRandom, "cos(#vartheta_{random})"}; const AxisSpec thnAxisCosThetaStarBeam{configThnAxisCosThetaStarBeam, "cos(#vartheta_{beam})"}; + const AxisSpec thnAxisCosThetaStarEP{configThnAxisCosThetaStarEP, "cos(#vartheta_{EP})"}; // reaction plane const AxisSpec thnAxisMlBkg{configThnAxisMlBkg, "ML bkg"}; const AxisSpec thnAxisMlNonPrompt{configThnAxisMlNonPrompt, "ML non-prompt"}; const AxisSpec thnAxisIsRotatedCandidate{2, -0.5f, 1.5f, "rotated bkg"}; @@ -305,6 +354,7 @@ struct TaskPolarisationCharmHadrons { const AxisSpec thnAxisInvMass2PKLcMonitoring{lcPKPiChannels.configThnAxisInvMass2PKLcMonitoring, "#it{M}^{2}(pK) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; const AxisSpec thnAxisInvMass2PPiLcMonitoring{lcPKPiChannels.configThnAxisInvMass2PPiLcMonitoring, "#it{M}^{2}(p#pi) from #Lambda_{c}^{+} (GeV/#it{c}^{2})"}; const AxisSpec thnAxisTHnAxisEulerPhi{configTHnAxisEulerPhi, "Euler polar angle #phi"}; + const AxisSpec thnAxisCentrality{configThnAxisCentrality, "centrality (%)"}; auto invMassBins = thnAxisInvMass.binEdges; minInvMass = invMassBins.front(); @@ -313,248 +363,305 @@ struct TaskPolarisationCharmHadrons { registry.add("hNumPvContributorsAll", "Number of PV contributors for all events ;num. PV contributors; counts", HistType::kTH1F, {thnAxisNumPvContributors}); registry.add("hNumPvContributorsCand", "Number of PV contributors for events with candidates;num. PV contributors; counts", HistType::kTH1F, {thnAxisNumPvContributors}); registry.add("hNumPvContributorsCandInMass", "Number of PV contributors for events with candidates in the signal region;num. PV contributors; counts", HistType::kTH1F, {thnAxisNumPvContributors}); + if (doprocessDstarInPbPb || doprocessDstarMcInPbPb || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + registry.add("hCentrality", "Centrality distribution for D*+ candidates;centrality (%); counts", HistType::kTH1D, {thnAxisCentrality}); + } - if (doprocessDstarWithMl || doprocessDstarMcWithMl) { - /// analysis for D*+ meson with ML, w/o rot. background axis - if (doprocessDstarWithMl) { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); - } - if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); - } - if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); - } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); - } - } else { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + if (activateTHnSparseCosThStarHelicity) { + std::vector hHelicityaxes = {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY}; + if (doprocessDstar || doprocessDstarMc || doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarInPbPb || doprocessDstarMcInPbPb || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + hHelicityaxes.insert(hHelicityaxes.end(), {thnAxisInvMassD0, thnAxisCosThetaStarHelicity}); + if (doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + hHelicityaxes.insert(hHelicityaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); + } + if (activateTrackingSys) { + hHelicityaxes.insert(hHelicityaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + } + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + std::vector hRecoPromptHelicityAxes(hHelicityaxes); + hRecoPromptHelicityAxes.insert(hRecoPromptHelicityAxes.end(), {thnAxisDauToMuons}); + std::vector hRecoNonPromptHelicityAxes(hHelicityaxes); + hRecoNonPromptHelicityAxes.insert(hRecoNonPromptHelicityAxes.end(), {thnAxisDauToMuons, thnAxisPtB}); + registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptHelicityAxes); + registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptHelicityAxes); if (activatePartRecoDstar) { - registry.add("hPartRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + registry.add("hPartRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for partially reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptHelicityAxes); + registry.add("hPartRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for partially reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptHelicityAxes); } - } - if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); - if (activatePartRecoDstar) { - registry.add("hPartRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + } else { + if (nBkgRotations > 0) { + hHelicityaxes.push_back(thnAxisIsRotatedCandidate); } + registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, hHelicityaxes); } - if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); - if (activatePartRecoDstar) { - registry.add("hPartRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + } else if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPi || doprocessLcToPKPiMc) { // Lc->pKpi + hHelicityaxes.insert(hHelicityaxes.end(), {thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity}); + if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { // Lc->pKpi with ML + hHelicityaxes.insert(hHelicityaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); + } + if (doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { // Lc->pKpi MC + std::vector hRecoHelicityAxes(hHelicityaxes); + if (doprocessLcToPKPiMc) { // Lc->pKpi MC without ML, have one more axis for rotated candidates + hRecoHelicityAxes.insert(hRecoHelicityAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + } else { + hRecoHelicityAxes.insert(hRecoHelicityAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); } + registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for reconstructed prompt Lc+ candidates", HistType::kTHnSparseF, hRecoHelicityAxes); + registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for reconstructed non-prompt Lc+ candidates", HistType::kTHnSparseF, hRecoHelicityAxes); } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); - if (activatePartRecoDstar) { - registry.add("hPartRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + hHelicityaxes.insert(hHelicityaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, hHelicityaxes); + + if (activateTHnEulerPhiMonitor) { + std::vector hEulerPhiAxes = {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi}; + if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + hEulerPhiAxes.insert(hEulerPhiAxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); + } + if (doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPiMc) { + hEulerPhiAxes.insert(hEulerPhiAxes.end(), {thnAxisResoChannelLc}); + } + hEulerPhiAxes.push_back(thnAxisCharge); + if (doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPiMc) { + registry.add("hRecPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, hEulerPhiAxes); + registry.add("hRecNonPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, hEulerPhiAxes); + } else { + registry.add("hEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis", HistType::kTHnSparseF, hEulerPhiAxes); } } } - } else if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { - /// analysis for Lc+ baryon with ML, w/ rot. background axis (for data only) - if (doprocessLcToPKPiWithMl) { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisCharge}); - } + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + std::vector hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + registry.add("hGenPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); + registry.add("hGenNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); + if (activatePartRecoDstar) { + registry.add("hGenPartRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for partially reconstructed generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); + registry.add("hGenPartRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores for partially reconstructed generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); } - if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisCharge}); + } + } + + if (activateTHnSparseCosThStarProduction) { + std::vector hProductionaxes = {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY}; + if (doprocessDstar || doprocessDstarMc || doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarInPbPb || doprocessDstarMcInPbPb || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + + hProductionaxes.insert(hProductionaxes.end(), {thnAxisInvMassD0, thnAxisCosThetaStarProduction}); + if (doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + hProductionaxes.insert(hProductionaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); + } + if (activateTrackingSys) { + hProductionaxes.insert(hProductionaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + } + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + std::vector hRecoPromptProductionAxes(hProductionaxes); + hRecoPromptProductionAxes.insert(hRecoPromptProductionAxes.end(), {thnAxisDauToMuons}); + std::vector hRecoNonPromptProductionAxes(hProductionaxes); + hRecoNonPromptProductionAxes.insert(hRecoNonPromptProductionAxes.end(), {thnAxisDauToMuons, thnAxisPtB}); + registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptProductionAxes); + registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptProductionAxes); + if (activatePartRecoDstar) { + registry.add("hPartRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for partially reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptProductionAxes); + registry.add("hPartRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for partially reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptProductionAxes); } - } - if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisCharge}); + } else { + if (nBkgRotations > 0) { + hProductionaxes.push_back(thnAxisIsRotatedCandidate); } + registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, hProductionaxes); } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + } else if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPi || doprocessLcToPKPiMc) { + hProductionaxes.insert(hProductionaxes.end(), {thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction}); + if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + hProductionaxes.insert(hProductionaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); } - } else { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hRecPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hRecNonPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + if (doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + std::vector hRecoProductionAxes(hProductionaxes); + if (doprocessLcToPKPiMc) { + hRecoProductionAxes.insert(hRecoProductionAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + } else { + hRecoProductionAxes.insert(hRecoProductionAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); } - } - if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hRecPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hRecNonPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for reconstructed prompt Lc+ candidates", HistType::kTHnSparseF, hRecoProductionAxes); + registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for reconstructed non-prompt Lc+ candidates", HistType::kTHnSparseF, hRecoProductionAxes); + } + hProductionaxes.insert(hProductionaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores", HistType::kTHnSparseF, hProductionaxes); + if (activateTHnEulerPhiMonitor) { + std::vector hEulerPhiAxes = {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi}; + if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + hEulerPhiAxes.insert(hEulerPhiAxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); } - } - if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hRecPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hRecNonPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisCharge}); + if (doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPiMc) { + hEulerPhiAxes.insert(hEulerPhiAxes.end(), {thnAxisResoChannelLc}); + } + hEulerPhiAxes.push_back(thnAxisCharge); + if (doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPiMc) { + registry.add("hRecPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, hEulerPhiAxes); + registry.add("hRecNonPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, hEulerPhiAxes); + } else { + registry.add("hEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis", HistType::kTHnSparseF, hEulerPhiAxes); } - } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisMlBkg, thnAxisMlNonPrompt, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); } } - } else if (doprocessDstar || doprocessDstarMc) { - /// analysis for D*+ meson, w/o rot. background axis - if (doprocessDstar) { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + std::vector hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + registry.add("hGenPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); + registry.add("hGenNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); + if (activatePartRecoDstar) { + registry.add("hGenPartRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for partially reconstructed generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); + registry.add("hGenPartRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis and BDT scores for partially reconstructed generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); } - if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); - } - if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); - } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate}); - } - } else { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + } + } + + if (activateTHnSparseCosThStarBeam) { + std::vector hBeamaxes = {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY}; + if (doprocessDstar || doprocessDstarMc || doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarInPbPb || doprocessDstarMcInPbPb || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + hBeamaxes.insert(hBeamaxes.end(), {thnAxisInvMassD0, thnAxisCosThetaStarBeam}); + if (doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + hBeamaxes.insert(hBeamaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); + } + if (activateTrackingSys) { + hBeamaxes.insert(hBeamaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + } + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + std::vector hRecoPromptBeamAxes(hBeamaxes); + hRecoPromptBeamAxes.insert(hRecoPromptBeamAxes.end(), {thnAxisDauToMuons}); + std::vector hRecoNonPromptBeamAxes(hBeamaxes); + hRecoNonPromptBeamAxes.insert(hRecoNonPromptBeamAxes.end(), {thnAxisDauToMuons, thnAxisPtB}); + registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptBeamAxes); + registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptBeamAxes); if (activatePartRecoDstar) { - registry.add("hPartRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + registry.add("hPartRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for partially reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptBeamAxes); + registry.add("hPartRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for partially reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptBeamAxes); } - } - if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); - if (activatePartRecoDstar) { - registry.add("hPartRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + } else { + if (nBkgRotations > 0) { + hBeamaxes.push_back(thnAxisIsRotatedCandidate); } + registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, hBeamaxes); } - if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); - if (activatePartRecoDstar) { - registry.add("hPartRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); - } + } else if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPi || doprocessLcToPKPiMc) { + hBeamaxes.insert(hBeamaxes.end(), {thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam}); + if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + hBeamaxes.insert(hBeamaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); - if (activatePartRecoDstar) { - registry.add("hPartRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- partially reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons}); - registry.add("hPartRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- partially reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassD0, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisDauToMuons, thnAxisPtB}); + if (doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + std::vector hRecoBeamAxes(hBeamaxes); + if (doprocessLcToPKPiMc) { + hRecoBeamAxes.insert(hRecoBeamAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + } else { + hRecoBeamAxes.insert(hRecoBeamAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); } - } - } - } else if (doprocessLcToPKPi || doprocessLcToPKPiMc) { - /// analysis for Lc+ baryon, rot. background axis (for data only) - if (doprocessLcToPKPi) { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisCharge}); + registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for reconstructed prompt Lc+ candidates", HistType::kTHnSparseF, hRecoBeamAxes); + registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for reconstructed non-prompt Lc+ candidates", HistType::kTHnSparseF, hRecoBeamAxes); + } + hBeamaxes.insert(hBeamaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores", HistType::kTHnSparseF, hBeamaxes); + if (activateTHnEulerPhiMonitor) { + std::vector hEulerPhiAxes = {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi}; + if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + hEulerPhiAxes.insert(hEulerPhiAxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); } - } - if (activateTHnSparseCosThStarProduction) { - registry.add("hProduction", "THn for polarisation studies with cosThStar w.r.t. production axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. helicity axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisCharge}); + if (doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPiMc) { + hEulerPhiAxes.insert(hEulerPhiAxes.end(), {thnAxisResoChannelLc}); } - } - if (activateTHnSparseCosThStarBeam) { - registry.add("hBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisCharge}); + hEulerPhiAxes.push_back(thnAxisCharge); + if (doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPiMc) { + registry.add("hRecPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, hEulerPhiAxes); + registry.add("hRecNonPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, hEulerPhiAxes); + } else { + registry.add("hEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis", HistType::kTHnSparseF, hEulerPhiAxes); } } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + } + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + std::vector hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + registry.add("hGenPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); + registry.add("hGenNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); + if (activatePartRecoDstar) { + registry.add("hGenPartRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for partially reconstructed generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); + registry.add("hGenPartRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis and BDT scores for partially reconstructed generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); } - } else { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - registry.add("hRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarHelicity, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hRecPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hRecNonPromptEulerPhiHelicity", "THn for polarisation studies with Euler phi w.r.t. helicity axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + } + } + + if (activateTHnSparseCosThStarRandom) { + std::vector hRandomaxes = {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY}; + if (doprocessDstar || doprocessDstarMc || doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarInPbPb || doprocessDstarMcInPbPb || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + + hRandomaxes.insert(hRandomaxes.end(), {thnAxisInvMassD0, thnAxisCosThetaStarRandom}); + if (doprocessDstarWithMl || doprocessDstarMcWithMl || doprocessDstarWithMlInPbPb || doprocessDstarMcWithMlInPbPb) { + hRandomaxes.insert(hRandomaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); + } + if (activateTrackingSys) { + hRandomaxes.insert(hRandomaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); + } + if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessDstarMcInPbPb || doprocessDstarMcWithMlInPbPb) { + std::vector hRecoPromptRandomAxes(hRandomaxes); + hRecoPromptRandomAxes.insert(hRecoPromptRandomAxes.end(), {thnAxisDauToMuons}); + std::vector hRecoNonPromptRandomAxes(hRandomaxes); + hRecoNonPromptRandomAxes.insert(hRecoNonPromptRandomAxes.end(), {thnAxisDauToMuons, thnAxisPtB}); + 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) { + registry.add("hPartRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for partially reconstructed prompt D*+ candidates", HistType::kTHnSparseF, hRecoPromptRandomAxes); + registry.add("hPartRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for partially reconstructed non-prompt D*+ candidates", HistType::kTHnSparseF, hRecoNonPromptRandomAxes); } - } - if (activateTHnSparseCosThStarProduction) { - registry.add("hRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - registry.add("hRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarProduction, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hRecPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hRecNonPromptEulerPhiProduction", "THn for polarisation studies with Euler phi w.r.t. production axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + } else { + if (nBkgRotations > 0) { + hRandomaxes.push_back(thnAxisIsRotatedCandidate); } + registry.add("hRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores", HistType::kTHnSparseF, hRandomaxes); } - if (activateTHnSparseCosThStarBeam) { - registry.add("hRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - registry.add("hRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarBeam, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - if (activateTHnEulerPhiMonitor) { - registry.add("hRecPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hRecNonPromptEulerPhiBeam", "THn for polarisation studies with Euler phi w.r.t. beam axis and BDT scores -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisInvMassKPiLc, thnAxisTHnAxisEulerPhi, thnAxisResoChannelLc, thnAxisCharge}); + } else if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl || doprocessLcToPKPi || doprocessLcToPKPiMc) { + hRandomaxes.insert(hRandomaxes.end(), {thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom}); + if (doprocessLcToPKPiWithMl || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + hRandomaxes.insert(hRandomaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); + } + if (doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { + std::vector hRecoRandomAxes(hRandomaxes); + if (doprocessLcToPKPiMc) { + hRecoRandomAxes.insert(hRecoRandomAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + } else { + hRecoRandomAxes.insert(hRecoRandomAxes.end(), {thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisCharge}); } + registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for reconstructed prompt Lc+ candidates", HistType::kTHnSparseF, hRecoRandomAxes); + registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for reconstructed non-prompt Lc+ candidates", HistType::kTHnSparseF, hRecoRandomAxes); } - if (activateTHnSparseCosThStarRandom) { - registry.add("hRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); - registry.add("hRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- reco non-prompt signal", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisInvMassKPiLc, thnAxisCosThetaStarRandom, thnAxisResoChannelLc, thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + hRandomaxes.insert(hRandomaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin, thnAxisIsRotatedCandidate, thnAxisCharge}); + 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 hgenPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + std::vector hgenNonPromptAxes = {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}; + 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) { + registry.add("hGenPartRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for partially reconstructed generated prompt D*+ candidates", HistType::kTHnSparseF, hgenPromptAxes); + registry.add("hGenPartRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis and BDT scores for partially reconstructed generated non-prompt D*+ candidates", HistType::kTHnSparseF, hgenNonPromptAxes); } } } - // MC Gen histos - if (doprocessDstarMc || doprocessDstarMcWithMl || doprocessLcToPKPiMc || doprocessLcToPKPiMcWithMl || doprocessLcToPKPiBackgroundMcWithMl) { - if (activateTHnSparseCosThStarHelicity) { - registry.add("hGenPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - if (activatePartRecoDstar && (doprocessDstarMc || doprocessDstarMcWithMl)) { - registry.add("hGenPartRecoPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen prompt partly reco signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenPartRecoNonPromptHelicity", "THn for polarisation studies with cosThStar w.r.t. helicity axis -- gen non-prompt partly reco signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarHelicity, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); + if (activateTHnSparseCosThStarEP && !(doprocessDstarInPbPb || doprocessDstarWithMlInPbPb)) { + LOGP(fatal, "THnSparse with cosThStar w.r.t. event plane axis is not supported for pp analysis, please check the configuration!"); + } else if (activateTHnSparseCosThStarEP) { + std::vector hEPaxes = {thnAxisInvMass, thnAxisPt, thnAxisNumPvContributors, thnAxisY}; + if (doprocessDstarInPbPb || doprocessDstarWithMlInPbPb) { + hEPaxes.insert(hEPaxes.end(), {thnAxisInvMassD0, thnAxisCosThetaStarEP}); + if (doprocessDstarWithMlInPbPb) { + hEPaxes.insert(hEPaxes.end(), {thnAxisMlBkg, thnAxisMlNonPrompt}); } - } - if (activateTHnSparseCosThStarProduction) { - registry.add("hGenPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - if (activatePartRecoDstar && (doprocessDstarMc || doprocessDstarMcWithMl)) { - registry.add("hGenPartRecoPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen partly reco prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenPartRecoNonPromptProduction", "THn for polarisation studies with cosThStar w.r.t. production axis -- gen partly reco non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarProduction, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); + if (activateTrackingSys) { + hEPaxes.insert(hEPaxes.end(), {thnAxisAbsEtaTrackMin, thnAxisNumItsClsMin, thnAxisNumTpcClsMin}); } - } - if (activateTHnSparseCosThStarBeam) { - registry.add("hGenPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - if (activatePartRecoDstar && (doprocessDstarMc || doprocessDstarMcWithMl)) { - registry.add("hGenPartRecoPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen partly reco prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenPartRecoNonPromptBeam", "THn for polarisation studies with cosThStar w.r.t. beam axis -- gen partly reco non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarBeam, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - } - } - if (activateTHnSparseCosThStarRandom) { - registry.add("hGenPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - if (activatePartRecoDstar && (doprocessDstarMc || doprocessDstarMcWithMl)) { - registry.add("hGenPartRecoPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen partly reco prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); - registry.add("hGenPartRecoNonPromptRandom", "THn for polarisation studies with cosThStar w.r.t. random axis -- gen partly reco non-prompt signal", HistType::kTHnSparseF, {thnAxisPt, thnAxisNumPvContributors, thnAxisY, thnAxisCosThetaStarRandom, thnAxisPtB, thnAxisDausAcc, thnAxisResoChannelLc, thnAxisCharge}); + if (nBkgRotations > 0) { + hEPaxes.push_back(thnAxisIsRotatedCandidate); } + registry.add("hEP", "THn for polarisation studies with cosThStar w.r.t. event plane axis and BDT scores", HistType::kTHnSparseF, hEPaxes); } } @@ -600,8 +707,20 @@ struct TaskPolarisationCharmHadrons { if constexpr (cosThetaStarType == charm_polarisation::CosThetaStarType::Helicity) { // Helicity if constexpr (!doMc) { // data if constexpr (withMl) { // with ML - if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + } else { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); if (activateTHnEulerPhiMonitor) { @@ -610,7 +729,19 @@ struct TaskPolarisationCharmHadrons { } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate); + } else { + registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); if (activateTHnEulerPhiMonitor) { @@ -622,10 +753,18 @@ struct TaskPolarisationCharmHadrons { if constexpr (withMl) { // with ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); @@ -635,10 +774,18 @@ struct TaskPolarisationCharmHadrons { } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + 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); + } else { + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); @@ -650,10 +797,18 @@ struct TaskPolarisationCharmHadrons { } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } else { + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + } else { + registry.fill(HIST("hPartRecoPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, 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); @@ -663,10 +818,18 @@ struct TaskPolarisationCharmHadrons { } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } else { + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + } else { + registry.fill(HIST("hPartRecoNonPromptHelicity"), invMassCharmHad, ptCharmHad, numPvContributors, 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); @@ -681,7 +844,19 @@ struct TaskPolarisationCharmHadrons { if constexpr (!doMc) { // data if constexpr (withMl) { // with ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + } else { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); if (activateTHnEulerPhiMonitor) { @@ -690,7 +865,19 @@ struct TaskPolarisationCharmHadrons { } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate); + } else { + registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hProduction"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); if (activateTHnEulerPhiMonitor) { @@ -702,10 +889,18 @@ struct TaskPolarisationCharmHadrons { if constexpr (withMl) { // with ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); @@ -715,10 +910,18 @@ struct TaskPolarisationCharmHadrons { } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + 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); + } else { + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); @@ -730,10 +933,18 @@ struct TaskPolarisationCharmHadrons { } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } else { + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + } else { + registry.fill(HIST("hPartRecoPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, 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); @@ -743,10 +954,18 @@ struct TaskPolarisationCharmHadrons { } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } else { + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + } else { + registry.fill(HIST("hPartRecoNonPromptProduction"), invMassCharmHad, ptCharmHad, numPvContributors, 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); @@ -761,7 +980,19 @@ struct TaskPolarisationCharmHadrons { if constexpr (!doMc) { // data if constexpr (withMl) { // with ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + } else { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); if (activateTHnEulerPhiMonitor) { @@ -770,7 +1001,19 @@ struct TaskPolarisationCharmHadrons { } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate); + } else { + registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hBeam"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); if (activateTHnEulerPhiMonitor) { @@ -782,10 +1025,18 @@ struct TaskPolarisationCharmHadrons { if constexpr (withMl) { // with ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); @@ -795,10 +1046,18 @@ struct TaskPolarisationCharmHadrons { } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + 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); + } else { + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); @@ -810,10 +1069,18 @@ struct TaskPolarisationCharmHadrons { } else { // without ML if (origin == RecoDecay::OriginType::Prompt) { // prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } else { + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + } } else { - registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons); + } else { + registry.fill(HIST("hPartRecoPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, 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); @@ -823,10 +1090,18 @@ struct TaskPolarisationCharmHadrons { } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } else { + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + } } else { - registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, nMuons, ptBhadMother); + } else { + registry.fill(HIST("hPartRecoNonPromptBeam"), invMassCharmHad, ptCharmHad, numPvContributors, 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); @@ -841,13 +1116,37 @@ struct TaskPolarisationCharmHadrons { if constexpr (!doMc) { // data if constexpr (withMl) { // with ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + } else { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); } } else { // without ML if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + if (activateTrackingSys) { + if (nBkgRotations > 0) { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate); + } else { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate); + } else { + registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar); + } + } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ registry.fill(HIST("hRandom"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassKPiLc, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin, isRotatedCandidate, charge); } @@ -856,20 +1155,36 @@ struct TaskPolarisationCharmHadrons { if constexpr (withMl) { // with 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, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (activateTrackingSys) { + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } else { - registry.fill(HIST("hPartRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons); + if (!isPartRecoDstar) { + registry.fill(HIST("hRecoPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); } } else { // non-prompt if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (!isPartRecoDstar) { - registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin, nMuons, ptBhadMother); + 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); + } else { + registry.fill(HIST("hPartRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, 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 (!isPartRecoDstar) { + registry.fill(HIST("hRecoNonPromptRandom"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } } } 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); @@ -899,6 +1214,78 @@ struct TaskPolarisationCharmHadrons { } } } + } else if constexpr (cosThetaStarType == charm_polarisation::CosThetaStarType::EP) { // EP + if constexpr (!doMc) { // data + if constexpr (withMl) { // with ML + 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); + } else { + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], isRotatedCandidate); + } else { + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2]); + } + } + } + } else { + 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); + } else { + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, absEtaMin, numItsClsMin, numTpcClsMin); + } + } else { + if (nBkgRotations > 0) { + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar, isRotatedCandidate); + } else { + registry.fill(HIST("hEP"), invMassCharmHad, ptCharmHad, numPvContributors, std::abs(rapCharmHad), invMassD0, cosThetaStar); + } + } + } + } + } else { + if constexpr (withMl) { // with ML + if (origin == RecoDecay::OriginType::Prompt) { // prompt + 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); + } else { + registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } else { + registry.fill(HIST("hPartRecoPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons); + } + } + } + } else { // non-prompt + 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); + } else { + registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, 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); + } else { + registry.fill(HIST("hPartRecoNonPromptEP"), invMassCharmHad, ptCharmHad, numPvContributors, rapCharmHad, invMassD0, cosThetaStar, outputMl[0], /*outputMl[1],*/ outputMl[2], nMuons, ptBhadMother); + } + } + } + } + } + } } } @@ -970,6 +1357,20 @@ struct TaskPolarisationCharmHadrons { 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); + } else { + registry.fill(HIST("hGenPartRecoPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, areDausInAcc, resoChannelLc, charge); + } + } else { // non-prompt + if (!isPartRecoDstar) { + registry.fill(HIST("hGenNonPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + } else { + registry.fill(HIST("hGenPartRecoNonPromptEP"), ptCharmHad, numPvContributors, rapCharmHad, cosThetaStar, ptBhadMother, areDausInAcc, resoChannelLc, charge); + } + } } } @@ -992,12 +1393,18 @@ struct TaskPolarisationCharmHadrons { template bool isInSignalRegion(float invMass) { + float invMassMin = 0.f; + float invMassMax = 100.f; if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { // D*+ - if (0.142f < invMass && invMass < 0.15f) { + invMassMin = 0.142f; + invMassMax = 0.15f; + if (invMassMin < invMass && invMass < invMassMax) { return true; } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { // Lc+ (to be tuned!) - if (2.25f < invMass && invMass < 2.35f) { + invMassMin = 2.25f; + invMassMax = 2.35f; + if (invMassMin < invMass && invMass < invMassMax) { return true; } } @@ -1068,15 +1475,51 @@ struct TaskPolarisationCharmHadrons { } } + /// Get the Q vector + /// \param collision is the collision with the Q vector information + template + std::vector getQVec(Coll const& collision) + { + float xQVec = -999.; + float yQVec = -999.; + float amplQVec = -999.; + switch (qVecDetector) { + case charm_polarisation::QvecEstimator::FV0A: + xQVec = collision.qvecFV0ARe(); + yQVec = collision.qvecFV0AIm(); + break; + case charm_polarisation::QvecEstimator::FT0M: + xQVec = collision.qvecFT0MRe(); + yQVec = collision.qvecFT0MIm(); + break; + case charm_polarisation::QvecEstimator::FT0C: + xQVec = collision.qvecFT0CRe(); + yQVec = collision.qvecFT0CIm(); + break; + default: + LOG(warning) << "Q vector estimator not valid. Please choose between FV0A, FT0M, FT0A, FT0C, TPC Pos, TPC Neg. Fallback to FV0A"; + xQVec = collision.qvecFV0ARe(); + yQVec = collision.qvecFV0AIm(); + break; + } + return {xQVec, yQVec, amplQVec}; + } + /// \param candidates are the selected candidates /// \param bkgRotationId is the id for the background rotation /// \param numPvContributors is the number of PV contributors /// \param particles are the generated particles /// \param tracks are the reconstructed tracks /// \return true if candidate in signal region - template - bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors, Part const& particles, Trk const& /*tracks*/) + template + bool runPolarisationAnalysis(Cand const& candidate, int bkgRotationId, int numPvContributors, Part const& particles, Trk const& /*tracks*/, QVecs const* qVecs = nullptr) { + if constexpr (withEP) { + assert(qVecs && "EP analysis requested but qVecs == nullptr"); + } + + constexpr std::size_t NScores{3u}; + bool isCandidateInSignalRegion{false}; int8_t origin{RecoDecay::OriginType::None}; int8_t massHypoMcTruth{-1}; @@ -1095,7 +1538,7 @@ struct TaskPolarisationCharmHadrons { ptBhadMother = candidate.ptBhadMotherPart(); int pdgBhadMother = candidate.pdgBhadMotherPart(); // For unknown reasons there are charm hadrons coming directly from beauty diquarks without an intermediate B-hadron which have an unreasonable correlation between the pT of the charm hadron and the beauty mother. We also remove charm hadrons from quarkonia. - if (origin == RecoDecay::OriginType::NonPrompt && (pdgBhadMother == 5101 || pdgBhadMother == 5103 || pdgBhadMother == 5201 || pdgBhadMother == 5203 || pdgBhadMother == 5301 || pdgBhadMother == 5303 || pdgBhadMother == 5401 || pdgBhadMother == 5403 || pdgBhadMother == 5503 || pdgBhadMother == 553 || pdgBhadMother == 555 || pdgBhadMother == 553 || pdgBhadMother == 557)) { + if (origin == RecoDecay::OriginType::NonPrompt && (pdgBhadMother == 5101 || pdgBhadMother == 5103 || pdgBhadMother == 5201 || pdgBhadMother == 5203 || pdgBhadMother == 5301 || pdgBhadMother == 5303 || pdgBhadMother == 5401 || pdgBhadMother == 5403 || pdgBhadMother == 5503 || pdgBhadMother == 553 || pdgBhadMother == 555 || pdgBhadMother == 553 || pdgBhadMother == 557)) { // o2-linter: disable=pdg/explicit-code, magic-number (constants not in the PDG header) return isCandidateInSignalRegion; } } else if constexpr (channel == charm_polarisation::DecayChannel::LcToPKPi) { @@ -1241,7 +1684,7 @@ struct TaskPolarisationCharmHadrons { invMassCharmHadForSparse = hfHelper.invMassLcToPKPi(candidate); } if constexpr (withMl) { - if (candidate.mlProbLcToPKPi().size() == 3) { + if (candidate.mlProbLcToPKPi().size() == NScores) { // protect from empty vectors // the BDT output score might be empty if no preselections were enabled (selectionFlag null) // !!! NB: each rotated candidates inherits the BDT scores of the original candidate, even if the candidate pt changed after the rotation of the kaon-track pt !!! @@ -1275,7 +1718,7 @@ struct TaskPolarisationCharmHadrons { invMassCharmHadForSparse = hfHelper.invMassLcToPiKP(candidate); } if constexpr (withMl) { - if (candidate.mlProbLcToPiKP().size() == 3) { + if (candidate.mlProbLcToPiKP().size() == NScores) { // protect from empty vectors // the BDT output score might be empty if no preselections were enabled (selectionFlag null) // !!! NB: each rotated candidates inherits the BDT scores of the original candidate, even if the candidate pt changed after the rotation of the kaon-track pt !!! @@ -1386,6 +1829,21 @@ struct TaskPolarisationCharmHadrons { nMuons = candidate.nTracksDecayed(); } + if constexpr (withEP && !doMc) { + /// EP analysis + float xQvec = (*qVecs).at(0); + float yQvec = (*qVecs).at(1); + ROOT::Math::XYZVector qVecNorm = ROOT::Math::XYZVector(yQvec, -xQvec, 0.f); + float cosThetaStarEP = -10.f; + float phiEP = -99.f; + + if (activateTHnSparseCosThStarEP) { + // EP + 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); + } + } + if (activateTHnSparseCosThStarHelicity) { // helicity cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(helicityVec.Mag2()); @@ -1595,9 +2053,18 @@ struct TaskPolarisationCharmHadrons { /// \param mcParticle is the Mc particle /// \param mcParticles is the table of Mc particles /// \param numPvContributors is the number of PV contributors in the associated reco collision - template - void runMcGenPolarisationAnalysis(Part const& mcParticle, Particles const& mcParticles, int numPvContributors) + template + void runMcGenPolarisationAnalysis(Part const& mcParticle, Particles const& mcParticles, int numPvContributors, Cent const* centrality = nullptr) { + if constexpr (withCent) { + assert(qVecs && "Centrality analysis requested but Cent == nullptr"); + } + if constexpr (withCent) { + if (*centrality < centralityMin || *centrality > centralityMax) { + return; // skip this collision if outside of the centrality range + } + } + int8_t origin{RecoDecay::OriginType::None}; std::vector listDaughters{}; float massDau{0.f}, massCharmHad{0.f}; @@ -1607,8 +2074,8 @@ struct TaskPolarisationCharmHadrons { int8_t charge = -99; bool partRecoDstar{false}; if constexpr (channel == charm_polarisation::DecayChannel::DstarToDzeroPi) { - partRecoDstar = TESTBIT(std::abs(mcParticle.flagMcMatchGen()), hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPiPi0) && TESTBIT(std::abs(mcParticle.flagMcMatchGenD0()), hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0); - bool signalDstar = TESTBIT(std::abs(mcParticle.flagMcMatchGen()), hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) && TESTBIT(std::abs(mcParticle.flagMcMatchGenD0()), hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); + partRecoDstar = (std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPiPi0) && (std::abs(mcParticle.flagMcMatchGenD0()) == hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiKPi0); + bool signalDstar = (std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) && (std::abs(mcParticle.flagMcMatchGenD0()) == hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); if (!signalDstar && (!activatePartRecoDstar || !partRecoDstar)) { // this particle is not signal and not partially reconstructed signal, skip return; @@ -1618,7 +2085,7 @@ struct TaskPolarisationCharmHadrons { auto bHadMother = mcParticles.rawIteratorAt(mcParticle.idxBhadMotherPart() - mcParticles.offset()); int pdgBhadMother = std::abs(bHadMother.pdgCode()); // For unknown reasons there are charm hadrons coming directly from beauty diquarks without an intermediate B-hadron which have an unreasonable correlation between the pT of the charm hadron and the beauty mother. We also remove charm hadrons from quarkonia. - if (pdgBhadMother == 5101 || pdgBhadMother == 5103 || pdgBhadMother == 5201 || pdgBhadMother == 5203 || pdgBhadMother == 5301 || pdgBhadMother == 5303 || pdgBhadMother == 5401 || pdgBhadMother == 5403 || pdgBhadMother == 5503 || pdgBhadMother == 553 || pdgBhadMother == 555 || pdgBhadMother == 553 || pdgBhadMother == 557) { + if (pdgBhadMother == 5101 || pdgBhadMother == 5103 || pdgBhadMother == 5201 || pdgBhadMother == 5203 || pdgBhadMother == 5301 || pdgBhadMother == 5303 || pdgBhadMother == 5401 || pdgBhadMother == 5403 || pdgBhadMother == 5503 || pdgBhadMother == 553 || pdgBhadMother == 555 || pdgBhadMother == 553 || pdgBhadMother == 557) { // o2-linter: disable=pdg/explicit-code, magic-number (constants not in the PDG header) return; } ptBhadMother = bHadMother.pt(); @@ -1746,7 +2213,7 @@ struct TaskPolarisationCharmHadrons { fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processDstar, "Process Dstar candidates without ML", true); + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstar, "Process Dstar candidates without ML", true); // Dstar with ML cuts void processDstarWithMl(aod::Collisions const& collisions, @@ -1772,7 +2239,7 @@ struct TaskPolarisationCharmHadrons { fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processDstarWithMl, "Process Dstar candidates with ML", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstarWithMl, "Process Dstar candidates with ML", false); // Dstar in MC with rectangular cuts void processDstarMc(aod::McCollisions::iterator const&, @@ -1805,7 +2272,7 @@ struct TaskPolarisationCharmHadrons { runMcGenPolarisationAnalysis(mcParticle, mcParticles, numPvContributorsGen); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processDstarMc, "Process Dstar candidates in MC without ML", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstarMc, "Process Dstar candidates in MC without ML", false); // Dstar in MC with ML cuts void processDstarMcWithMl(aod::McCollisions::iterator const&, @@ -1838,7 +2305,149 @@ struct TaskPolarisationCharmHadrons { runMcGenPolarisationAnalysis(mcParticle, mcParticles, numPvContributorsGen); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processDstarMcWithMl, "Process Dstar candidates in MC with ML", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstarMcWithMl, "Process Dstar candidates in MC with ML", false); + + void processDstarInPbPb(CollsWithQVecs const& collisions, + FilteredCandDstarWSelFlag const& dstarCandidates, + TracksWithExtra const& tracks) + { + for (const auto& collision : collisions) { + float centrality = {-1.f}; + centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); + if (centrality < centralityMin || centrality > centralityMax) { + return; // skip this collision if outside of the centrality range + } + registry.fill(HIST("hCentrality"), centrality); + + auto thisCollId = collision.globalIndex(); + int numPvContributors = collision.numContrib(); + auto groupedDstarCandidates = dstarCandidates.sliceBy(dstarPerCollision, thisCollId); + int nCands{0}, nCandsInSignalRegion{0}; + + std::vector qVecs = getQVec(collision); + + for (const auto& dstarCandidate : groupedDstarCandidates) { + nCands++; + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, &qVecs)) { + nCandsInSignalRegion++; + } + } + fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); + } + } + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstarInPbPb, "Process Dstar candidates in PbPb collisions", false); + + void processDstarWithMlInPbPb(CollsWithQVecs const& collisions, + FilteredCandDstarWSelFlagAndMl const& dstarCandidates, + TracksWithExtra const& tracks) + { + for (const auto& collision : collisions) { + float centrality = {-1.f}; + centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); + if (centrality < centralityMin || centrality > centralityMax) { + return; // skip this collision if outside of the centrality range + } + registry.fill(HIST("hCentrality"), centrality); + + auto thisCollId = collision.globalIndex(); + int numPvContributors = collision.numContrib(); + auto groupedDstarCandidates = dstarCandidates.sliceBy(dstarWithMlPerCollision, thisCollId); + int nCands{0}, nCandsInSignalRegion{0}; + + std::vector qVecs = getQVec(collision); + + for (const auto& dstarCandidate : groupedDstarCandidates) { + nCands++; + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks, &qVecs)) { + nCandsInSignalRegion++; + } + } + fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); + } + } + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstarWithMlInPbPb, "Process Dstar candidates with ML in PbPb collisions", false); + + void processDstarMcInPbPb(aod::McCollisions::iterator const&, + McParticlesDstarMatched const& mcParticles, + CollisionsWithMcLabelsAndCent const& collisions, // this is grouped with SmallGroupsCollisionsWithMcLabels const& collisions, + FilteredCandDstarWSelFlagAndMc const& dstarCandidates, + TracksWithExtra const& tracks) + { + float centrality = {-1.f}; + int numPvContributorsGen{0}; + + for (const auto& collision : collisions) { // loop over reco collisions associated to this gen collision + centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); + if (centrality < centralityMin || centrality > centralityMax) { + return; // skip this collision if outside of the centrality range + } + registry.fill(HIST("hCentrality"), centrality); + + auto thisCollId = collision.globalIndex(); + int numPvContributors = collision.numContrib(); + auto groupedDstarCandidates = dstarCandidates.sliceBy(dstarWithMcPerCollision, thisCollId); + int nCands{0}, nCandsInSignalRegion{0}; + + if (numPvContributors > numPvContributorsGen) { // we take the associated reconstructed collision with higher number of PV contributors + numPvContributorsGen = numPvContributors; + } + + for (const auto& dstarCandidate : groupedDstarCandidates) { + nCands++; + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { + nCandsInSignalRegion++; + } + } + fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); + } + for (const auto& mcParticle : mcParticles) { + const auto& recoCollsPerMcColl = collisions.sliceBy(colPerMcCollision, mcParticle.mcCollision().globalIndex()); + float cent = o2::hf_centrality::getCentralityGenColl(recoCollsPerMcColl, centEstimator); + runMcGenPolarisationAnalysis(mcParticle, mcParticles, numPvContributorsGen, ¢); + } + } + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstarMcInPbPb, "Process Dstar candidates in PbPb MC without ML", false); + + void processDstarMcWithMlInPbPb(aod::McCollisions::iterator const&, + McParticlesDstarMatched const& mcParticles, + CollisionsWithMcLabelsAndCent const& collisions, // this is grouped with SmallGroupsCollisionsWithMcLabels const& collisions, + FilteredCandDstarWSelFlagAndMcAndMl const& dstarCandidates, + TracksWithExtra const& tracks) + { + float centrality = {-1.f}; + int numPvContributorsGen{0}; + + for (const auto& collision : collisions) { // loop over reco collisions associated to this gen collision + centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); + if (centrality < centralityMin || centrality > centralityMax) { + return; // skip this collision if outside of the centrality range + } + registry.fill(HIST("hCentrality"), centrality); + + auto thisCollId = collision.globalIndex(); + int numPvContributors = collision.numContrib(); + auto groupedDstarCandidates = dstarCandidates.sliceBy(dstarWithMcAndMlPerCollision, thisCollId); + int nCands{0}, nCandsInSignalRegion{0}; + + if (numPvContributors > numPvContributorsGen) { // we take the associated reconstructed collision with higher number of PV contributors + numPvContributorsGen = numPvContributors; + } + + for (const auto& dstarCandidate : groupedDstarCandidates) { + nCands++; + if (runPolarisationAnalysis(dstarCandidate, 0, numPvContributors, -1 /*MC particles*/, tracks)) { + nCandsInSignalRegion++; + } + } + fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); + } + for (const auto& mcParticle : mcParticles) { + const auto& recoCollsPerMcColl = collisions.sliceBy(colPerMcCollision, mcParticle.mcCollision().globalIndex()); + float cent = o2::hf_centrality::getCentralityGenColl(recoCollsPerMcColl, centEstimator); + runMcGenPolarisationAnalysis(mcParticle, mcParticles, numPvContributorsGen, ¢); + } + } + PROCESS_SWITCH(HfTaskCharmPolarisation, processDstarMcWithMlInPbPb, "Process Dstar candidates in PbPb MC with ML", false); //////////////////////////// // Lc->pKpi analysis /// @@ -1869,7 +2478,7 @@ struct TaskPolarisationCharmHadrons { fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processLcToPKPi, "Process Lc candidates without ML", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processLcToPKPi, "Process Lc candidates without ML", false); // Lc->pKpi with ML cuts void processLcToPKPiWithMl(aod::Collisions const& collisions, @@ -1896,7 +2505,7 @@ struct TaskPolarisationCharmHadrons { fillMultHistos(numPvContributors, nCands, nCandsInSignalRegion); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processLcToPKPiWithMl, "Process Lc candidates with ML", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processLcToPKPiWithMl, "Process Lc candidates with ML", false); // Lc->pKpi in MC with rectangular cuts void processLcToPKPiMc(aod::McCollisions::iterator const&, @@ -1929,7 +2538,7 @@ struct TaskPolarisationCharmHadrons { runMcGenPolarisationAnalysis(mcParticle, mcParticles, numPvContributorsGen); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processLcToPKPiMc, "Process Lc candidates in MC without ML", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processLcToPKPiMc, "Process Lc candidates in MC without ML", false); // Lc->pKpi in MC with ML cuts void processLcToPKPiMcWithMl(aod::McCollisions::iterator const&, @@ -1962,7 +2571,7 @@ struct TaskPolarisationCharmHadrons { runMcGenPolarisationAnalysis(mcParticle, mcParticles, numPvContributorsGen); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processLcToPKPiMcWithMl, "Process Lc candidates in MC with ML", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processLcToPKPiMcWithMl, "Process Lc candidates in MC with ML", false); // Lc->pKpi in MC with ML cuts w/o mcCollision grouping (to study Lc background) void processLcToPKPiBackgroundMcWithMl(McParticles3ProngMatched const& mcParticles, @@ -1977,10 +2586,10 @@ struct TaskPolarisationCharmHadrons { runMcGenPolarisationAnalysis(mcParticle, mcParticles, /*numPvContributorsGen*/ -1); } } - PROCESS_SWITCH(TaskPolarisationCharmHadrons, processLcToPKPiBackgroundMcWithMl, "Process Lc candidates in MC with ML w/o mcCollision grouping", false); + PROCESS_SWITCH(HfTaskCharmPolarisation, processLcToPKPiBackgroundMcWithMl, "Process Lc candidates in MC with ML w/o mcCollision grouping", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx b/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx deleted file mode 100644 index 37aef67937a..00000000000 --- a/PWGHF/D2H/Tasks/taskCharmResoReduced.cxx +++ /dev/null @@ -1,477 +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 taskCharmResoReduced.cxx -/// \brief Charmed Resonances analysis task -/// -/// \author Luca Aglietta , University and INFN Torino - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" - -// #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" - -using namespace o2; -using namespace o2::soa; -using namespace o2::analysis; -using namespace o2::framework; -using namespace o2::framework::expressions; -using namespace o2::constants::physics; - -enum DecayTypeMc : uint8_t { - Ds1ToDStarK0ToD0PiK0s = 1, - Ds2StarToDplusK0sToPiKaPiPiPi, - Ds1ToDStarK0ToDPlusPi0K0s, - Ds1ToDStarK0ToD0PiK0sPart, - Ds1ToDStarK0ToD0NoPiK0sPart, - Ds1ToDStarK0ToD0PiK0sOneMu, - Ds2StarToDplusK0sOneMu -}; - -namespace o2::aod -{ -namespace hf_cand_reso_lite -{ -DECLARE_SOA_COLUMN(PtBach0, ptBach0, float); //! Transverse momentum of bachelor 0 (GeV/c) -DECLARE_SOA_COLUMN(PtBach1, ptBach1, float); //! Transverse momentum of bachelor 1 (GeV/c) -DECLARE_SOA_COLUMN(MBach0, mBach0, float); //! Invariant mass of bachelor 0 (GeV/c) -DECLARE_SOA_COLUMN(MBach1, mBach1, float); //! Invariant mass of bachelor 1 (GeV/c) -DECLARE_SOA_COLUMN(MBachD0, mBachD0, float); //! Invariant mass of D0 bachelor (of bachelor 0) (GeV/c) -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(Sign, sign, int8_t); //! Sign of candidate -DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); //! VosThetaStar of candidate (GeV) -DECLARE_SOA_COLUMN(MlScoreBkgBach0, mlScoreBkgBach0, float); //! ML score for background class of charm daughter -DECLARE_SOA_COLUMN(MlScorePromptBach0, mlScorePromptBach0, float); //! ML score for prompt class of charm daughter -DECLARE_SOA_COLUMN(MlScoreNonPromptBach0, mlScoreNonPromptBach0, float); //! ML score for non-prompt class of charm daughter -DECLARE_SOA_COLUMN(ItsNClsProngMinBach0, itsNClsProngMinBach0, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 0 -DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach0, tpcNClsCrossedRowsProngMinBach0, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 0 -DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach0, tpcChi2NClProngMaxBach0, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 0 -DECLARE_SOA_COLUMN(ItsNClsProngMinBach1, itsNClsProngMinBach1, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 1 -DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach1, tpcNClsCrossedRowsProngMinBach1, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 1 -DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach1, tpcChi2NClProngMaxBach1, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 1 -DECLARE_SOA_COLUMN(CpaBach1, cpaBach1, float); //! Cosine of Pointing Angle of bachelor 1 -DECLARE_SOA_COLUMN(DcaBach1, dcaBach1, float); //! DCA of bachelor 1 -DECLARE_SOA_COLUMN(RadiusBach1, radiusBach1, float); //! Radius of bachelor 1 -DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); //! flag for decay channel classification reconstruction level -DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int8_t); //! debug flag for mis-association at reconstruction level -DECLARE_SOA_COLUMN(Origin, origin, int8_t); //! Flag for origin of MC particle 1=promt, 2=FD -DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! Transverse momentum of candidate (GeV/c) -DECLARE_SOA_COLUMN(SignD0, signD0, float); //! Flag to distinguish D0 and D0Bar - -} // namespace hf_cand_reso_lite - -DECLARE_SOA_TABLE(HfCandResoLites, "AOD", "HFCANDRESOLITE", //! Table with some B0 properties - // Candidate Properties - hf_cand_reso_lite::M, - hf_cand_reso_lite::Pt, - hf_cand_reso_lite::P, - hf_cand_reso_lite::Y, - hf_cand_reso_lite::Eta, - hf_cand_reso_lite::Phi, - hf_cand_reso_lite::E, - hf_cand_reso_lite::CosThetaStar, - hf_cand_reso_lite::Sign, - // Bachelors Properties - hf_cand_reso_lite::MBach0, - hf_cand_reso_lite::PtBach0, - hf_cand_reso_lite::MlScoreBkgBach0, - hf_cand_reso_lite::MlScorePromptBach0, - hf_cand_reso_lite::MlScoreNonPromptBach0, - hf_cand_reso_lite::ItsNClsProngMinBach0, - hf_cand_reso_lite::TpcNClsCrossedRowsProngMinBach0, - hf_cand_reso_lite::TpcChi2NClProngMaxBach0, - hf_cand_reso_lite::MBach1, - hf_cand_reso_lite::PtBach1, - hf_cand_reso_lite::CpaBach1, - hf_cand_reso_lite::DcaBach1, - hf_cand_reso_lite::RadiusBach1, - hf_cand_reso_lite::ItsNClsProngMinBach1, - hf_cand_reso_lite::TpcNClsCrossedRowsProngMinBach1, - hf_cand_reso_lite::TpcChi2NClProngMaxBach1, - // MC - hf_cand_reso_lite::FlagMcMatchRec, - hf_cand_reso_lite::DebugMcRec, - hf_cand_reso_lite::Origin, - hf_cand_reso_lite::PtGen, - hf_cand_reso_lite::SignD0); - -DECLARE_SOA_TABLE(HfGenResoLites, "AOD", "HFGENRESOLITE", //! Table with some B0 properties - hf_cand_reso_lite::Pt, - hf_cand_reso_lite::Y, - hf_cand_reso_lite::Origin); - -} // namespace o2::aod - -enum DecayChannel : uint8_t { - Ds1ToDstarK0s = 0, - Ds2StarToDplusK0s, - XcToDplusLambda, - LambdaDminus -}; - -struct HfTaskCharmResoReduced { - Produces hfCandResoLite; - Produces hfGenResoLite; - Configurable ptMinReso{"ptMinReso", -1, "Discard events with smaller pT"}; - Configurable fillTrees{"fillTrees", true, "Fill output Trees"}; - Configurable fillSparses{"fillSparses", false, "Fill output Sparses"}; - Configurable useDeltaMass{"useDeltaMass", true, "Use Delta Mass for resonance invariant Mass calculation"}; - Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to Fill only signal candidates (MC only)"}; - Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; - Configurable yCandRecoMax{"yCandRecoMax", -1, "max. cand. rapidity"}; - Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity for acceptance calculation"}; - Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum for acceptance calculation"}; - Configurable massResoMin{"massResoMin", 0.49, "min. mass of resonance"}; - Configurable massResoMax{"massResoMax", 1.29, "max. mass of resonance"}; - // Configurables axis for histos - ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis axisPtProng0{"axisPtProng0", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong0 bach. #it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis axisPtProng1{"axisPtProng1", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong1 bach. #it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis axisInvMassReso{"axisInvMassReso", {200, 2.34, 2.74}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; - ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {175, 1.70, 2.05}, "inv. mass (D) (GeV/#it{c}^{2})"}; - ConfigurableAxis axisInvMassProng1{"axisInvMassProng1", {80, 0.46, 0.54}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; - ConfigurableAxis axisCosThetaStar{"axisCosThetaStar", {40, -1, 1}, "cos(#vartheta*)"}; - ConfigurableAxis axisBkgBdtScore{"axisBkgBdtScore", {100, 0, 1}, "bkg BDT Score"}; - ConfigurableAxis axisNonPromptBdtScore{"axisNonPromptBdtScore", {100, 0, 1}, "non-prompt BDT Score"}; - ConfigurableAxis axisEta{"axisEta", {30, -1.5, 1.5}, "pseudorapidity"}; - ConfigurableAxis axisOrigin{"axisOrigin", {3, -0.5, 2.5}, "origin"}; - ConfigurableAxis axisFlag{"axisFlag", {65, -32.5, 32.5}, "mc flag"}; - - using ReducedReso = soa::Join; - using ReducedResoWithMl = soa::Join; - using ReducedResoMc = soa::Join; - using ReducedResoWithMlMc = soa::Join; - - // Histogram Registry - HistogramRegistry registry; - - // init - void init(InitContext&) - { - registry.add("hMass", "Charm resonance candidates inv. mass", {HistType::kTH1F, {axisInvMassReso}}); - registry.add("hMassProng0", "D daughters inv. mass", {HistType::kTH1F, {axisInvMassProng0}}); - registry.add("hMassProng1", "V0 daughter inv. mass", {HistType::kTH1F, {axisInvMassProng1}}); - registry.add("hPt", "Charm resonance candidates pT", {HistType::kTH1F, {axisPt}}); - registry.add("hPtProng0", "D daughters pT", {HistType::kTH1F, {axisPtProng0}}); - registry.add("hPtProng1", "V0 daughter pT", {HistType::kTH1F, {axisPtProng1}}); - registry.add("hNPvCont", "Collision number of PV contributors ; N contrib ; entries", {HistType::kTH1F, {{125, -0.5, 249.5}}}); - registry.add("hZvert", "Collision Z Vtx ; z PV [cm] ; entries", {HistType::kTH1F, {{120, -12., 12.}}}); - registry.add("hBz", "Collision Bz ; Bz [T] ; entries", {HistType::kTH1F, {{20, -10., 10.}}}); - registry.add("hSparse", "THn for production studies with cosThStar and BDT scores", HistType::kTHnSparseF, {axisPt, axisPtProng0, axisPtProng1, axisInvMassReso, axisInvMassProng0, axisInvMassProng1, axisCosThetaStar, axisBkgBdtScore, axisNonPromptBdtScore}); - - if (doprocessDs1Mc || doprocessDs2StarMc || doprocessDs1McWithMl || doprocessDs2StarMcWithMl) { - // gen histos - registry.add("hYRecPrompt", "Charm resonance candidates pT", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYRecNonPrompt", "Charm resonance candidates pT", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenPrompt", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenPromptWithProngsInAcceptance", "Prompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenNonPrompt", "NonPrompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); - registry.add("hYGenNonPromptWithProngsInAcceptance", "NonPrompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2F, {axisPt, axisEta}}); - if (fillSparses) { - registry.add("hPtYGenSig", "{D_{S}}^j particles (generated);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); - registry.add("hPtYWithProngsInAccepanceGenSig", "{D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); - } - } - } - - // Fill histograms - /// \tparam channel is the decay channel of the Resonance - /// \param candidate is a candidate - /// \param coll is a reduced collision - /// \param bach0 is a bachelor of the candidate - /// \param bach1 is a bachelor of the candidate - template - void fillCand(const Cand& candidate, const Coll& collision, const CharmBach& bach0, const V0Bach& bach1) - { - // Compute quantities to be saved - float invMassReso{0}, pdgMassReso, invMassBach0, invMassBach1, pdgMassBach0, pdgMassBach1, sign, invMassD0, cosThetaStar; - if (channel == DecayChannel::Ds1ToDstarK0s) { - pdgMassReso = MassDS1; - pdgMassBach0 = MassDStar; - pdgMassBach1 = MassK0; - invMassBach1 = bach1.invMassK0s(); - cosThetaStar = candidate.cosThetaStarDs1(); - if (bach0.dType() > 0) { - invMassBach0 = bach0.invMassDstar(); - invMassD0 = bach0.invMassD0(); - sign = 1; - if (useDeltaMass) { - invMassReso = RecoDecay::m(std::array{bach0.pVectorProng0(), bach0.pVectorProng1(), bach0.pVectorProng2(), bach1.pVector()}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); - } - } else { - invMassBach0 = bach0.invMassAntiDstar(); - invMassD0 = bach0.invMassD0Bar(); - sign = -1; - if (useDeltaMass) { - invMassReso = RecoDecay::m(std::array{bach0.pVectorProng1(), bach0.pVectorProng0(), bach0.pVectorProng2(), bach1.pVector()}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); - } - } - } else if (channel == DecayChannel::Ds2StarToDplusK0s) { - pdgMassReso = MassDS2Star; - pdgMassBach0 = MassDPlus; - pdgMassBach1 = MassK0; - invMassBach0 = bach0.invMassDplus(); - invMassD0 = 0; - invMassBach1 = bach1.invMassK0s(); - cosThetaStar = candidate.cosThetaStarDs2Star(); - if (useDeltaMass) { - invMassReso = RecoDecay::m(std::array{bach0.pVectorProng0(), bach0.pVectorProng1(), bach0.pVectorProng2(), bach1.pVector()}, std::array{MassPiPlus, MassKPlus, MassPiPlus, MassK0}); - } - if (bach0.dType() > 0) { - sign = 1; - } else { - sign = -1; - } - } - float y = RecoDecay::y(std::array{candidate.px(), candidate.py(), candidate.pz()}, pdgMassReso); - float eta = RecoDecay::eta(std::array{candidate.px(), candidate.py(), candidate.pz()}); - float phi = RecoDecay::phi(candidate.px(), candidate.py()); - float p = RecoDecay::p(std::array{candidate.px(), candidate.py(), candidate.pz()}); - float e = RecoDecay::e(std::array{candidate.px(), candidate.py(), candidate.pz()}, pdgMassReso); - if (useDeltaMass) { - invMassReso = invMassReso - invMassBach0; - } else { - invMassReso = RecoDecay::m(std::array{bach0.pVector(), bach1.pVector()}, std::array{pdgMassBach0, pdgMassBach1}); - } - if (invMassReso < massResoMin || invMassReso > massResoMax) { - return; - } - invMassBach0 = invMassBach0 - invMassD0; - float ptGen{-1.}; - int8_t origin{-1}, flagMcMatchRec{-1}, debugMcRec{-1}, signD0{0}; - if constexpr (doMc) { - ptGen = candidate.ptMother(); - origin = candidate.origin(); - flagMcMatchRec = candidate.flagMcMatchRec(); - debugMcRec = candidate.debugMcRec(); - if (fillOnlySignal) { - if (channel == DecayChannel::Ds1ToDstarK0s && !(std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0s || std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0sPart || std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0NoPiK0sPart || std::abs(flagMcMatchRec) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0sOneMu)) { - return; - } - if (channel == DecayChannel::Ds2StarToDplusK0s && !(std::abs(flagMcMatchRec) == DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi || std::abs(flagMcMatchRec) == DecayTypeMc::Ds2StarToDplusK0sOneMu)) { - return; - } - } - if (origin == 1) { - registry.fill(HIST("hYRecPrompt"), candidate.pt(), y); - } else if (origin == 2) { - registry.fill(HIST("hYRecNonPrompt"), candidate.pt(), y); - } - } - float mlScoreBkg{-1.}, mlScorePrompt{-1.}, mlScoreNonPrompt{-1.}; - if constexpr (withMl) { - mlScoreBkg = bach0.mlScoreBkgMassHypo0(); - mlScorePrompt = bach0.mlScorePromptMassHypo0(); - mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); - } - // Collision properties - registry.fill(HIST("hNPvCont"), collision.numContrib()); - registry.fill(HIST("hZvert"), collision.posZ()); - registry.fill(HIST("hBz"), collision.bz()); - // Candidate properties - registry.fill(HIST("hMass"), invMassReso); - registry.fill(HIST("hMassProng0"), invMassBach0); - registry.fill(HIST("hMassProng1"), invMassBach1); - registry.fill(HIST("hPt"), candidate.pt()); - registry.fill(HIST("hPtProng0"), candidate.ptProng0()); - registry.fill(HIST("hPtProng1"), candidate.ptProng1()); - if (fillSparses) { - registry.fill(HIST("hSparse"), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), invMassReso, invMassBach0, invMassBach1, cosThetaStar, mlScoreBkg, mlScoreNonPrompt); - } - - if (fillTrees) { - hfCandResoLite( - invMassReso, - candidate.pt(), - p, - y, - eta, - phi, - e, - cosThetaStar, - sign, - // Bachelors Properties - invMassBach0, - bach0.pt(), - mlScoreBkg, - mlScorePrompt, - mlScoreNonPrompt, - bach0.itsNClsProngMin(), - bach0.tpcNClsCrossedRowsProngMin(), - bach0.tpcChi2NClProngMax(), - invMassBach1, - bach1.pt(), - bach1.cpa(), - bach1.dca(), - bach1.v0Radius(), - bach1.itsNClsProngMin(), - bach1.tpcNClsCrossedRowsProngMin(), - bach1.tpcChi2NClProngMax(), - // MC - flagMcMatchRec, - debugMcRec, - origin, - ptGen, - signD0); - } - } // fillCand - - // Process data - /// \tparam channel is the decay channel of the Resonance - /// \param Coll is the reduced collisions table - /// \param CharmBach is the reduced 3 prong table - /// \param V0Bach is the reduced v0 table - /// \param Cand is the candidates table - template - void processData(Coll const&, Candidates const& candidates, CharmBach const&, aod::HfRedVzeros const&) - { - for (const auto& cand : candidates) { - if (ptMinReso >= 0 && cand.pt() < ptMinReso) { - continue; - } - float pdgMassReso{0}; - if (channel == DecayChannel::Ds1ToDstarK0s) { - pdgMassReso = MassDS1; - } else if (channel == DecayChannel::Ds2StarToDplusK0s) { - pdgMassReso = MassDS2Star; - } - if (yCandRecoMax >= 0. && std::abs(RecoDecay::y(std::array{cand.px(), cand.py(), cand.pz()}, pdgMassReso)) > yCandRecoMax) { - continue; - } - auto coll = cand.template hfRedCollision_as(); - auto bach0 = cand.template prong0_as(); - auto bach1 = cand.template prong1_as(); - fillCand(cand, coll, bach0, bach1); - } - } - - /// Selection of resonance daughters in geometrical acceptance - /// \param etaProng is the pseudorapidity of Resonance prong - /// \param ptProng is the pT of Resonance prong - /// \return true if prong is in geometrical acceptance - template - bool isProngInAcceptance(const T& etaProng, const T& ptProng) - { - return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; - } - - /// Fill particle histograms (gen MC truth) - template - void fillCandMcGen(aod::HfMcGenRedResos const& mcParticles) - { - for (const auto& particle : mcParticles) { - auto ptParticle = particle.ptTrack(); - auto yParticle = particle.yTrack(); - auto originParticle = particle.origin(); - auto flag = particle.flagMcMatchGen(); - if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { - continue; - } - std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; - std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; - bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); - if ((channel == DecayChannel::Ds1ToDstarK0s && std::abs(flag) == DecayTypeMc::Ds1ToDStarK0ToD0PiK0s) || - (channel == DecayChannel::Ds2StarToDplusK0s && std::abs(flag) == DecayTypeMc::Ds2StarToDplusK0sToPiKaPiPiPi)) { - if (originParticle == 1) { // prompt particles - registry.fill(HIST("hYGenPrompt"), ptParticle, yParticle); - if (prongsInAcc) { - registry.fill(HIST("hYGenPromptWithProngsInAcceptance"), ptParticle, yParticle); - } - } else if (originParticle == 2) { - registry.fill(HIST("hYGenNonPrompt"), ptParticle, yParticle); - if (prongsInAcc) { - registry.fill(HIST("hYGenNonPromptWithProngsInAcceptance"), ptParticle, yParticle); - } - } - } - if (fillSparses) { - registry.fill(HIST("hPtYGenSig"), ptParticle, yParticle, originParticle, flag); - if (prongsInAcc) { - registry.fill(HIST("hPtYWithProngsInAccepanceGenSig"), ptParticle, yParticle, originParticle, flag); - } - } - if (fillTrees) { - hfGenResoLite(ptParticle, yParticle, originParticle); - } - } - } // fillCandMcGen - - // process functions - - void processDs1Data(aod::HfRedCollisions const& collisions, ReducedReso const& candidates, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1Data, "Process data for Ds1 analysis without Ml", true); - - void processDs1DataWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1DataWithMl, "Process data for Ds1 analysis with Ml", false); - - void processDs2StarData(aod::HfRedCollisions const& collisions, ReducedReso const& candidates, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarData, "Process data Ds2Star analysis without Ml", false); - - void processDs2StarDataWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMl const& candidates, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarDataWithMl, "Process data Ds2Star analysis with Ml", false); - - void processDs1Mc(aod::HfRedCollisions const& collisions, ReducedResoMc const& candidates, aod::HfMcGenRedResos const& mcParticles, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1Mc, "Process Mc for Ds1 analysis without Ml", false); - - void processDs1McWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMlMc const& candidates, aod::HfMcGenRedResos const& mcParticles, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs1McWithMl, "Process Mc for Ds1 analysis with Ml", false); - - void processDs2StarMc(aod::HfRedCollisions const& collisions, ReducedResoMc const& candidates, aod::HfMcGenRedResos const& mcParticles, aod::HfRed3PrNoTrks const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarMc, "Process Mc for Ds2Star analysis without Ml", false); - - void processDs2StarMcWithMl(aod::HfRedCollisions const& collisions, ReducedResoWithMlMc const& candidates, aod::HfMcGenRedResos const& mcParticles, soa::Join const& charmBachs, aod::HfRedVzeros const& v0Bachs) - { - processData(collisions, candidates, charmBachs, v0Bachs); - fillCandMcGen(mcParticles); - } - PROCESS_SWITCH(HfTaskCharmResoReduced, processDs2StarMcWithMl, "Process Mc for Ds2Star analysis with Ml", false); - -}; // struct HfTaskCharmResoReduced -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{adaptAnalysisTask(cfgc)}; -} diff --git a/PWGHF/D2H/Tasks/taskCharmResoToDTrkReduced.cxx b/PWGHF/D2H/Tasks/taskCharmResoToDTrkReduced.cxx new file mode 100644 index 00000000000..362933d9124 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskCharmResoToDTrkReduced.cxx @@ -0,0 +1,477 @@ +// 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 taskCharmResoToDTrkReduced.cxx +/// \brief Charmed Resonances decaying in a D meson and a Track analysis task +/// +/// \author Luca Aglietta , University and INFN Torino + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/Utils/utilsMcMatching.h" + +#include "Common/Core/RecoDecay.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; + +enum BachelorType : uint8_t { + K0s = 0, + Lambda, + AntiLambda +}; + +namespace o2::aod +{ +namespace hf_cand_reso_to_trk_lite +{ +DECLARE_SOA_COLUMN(PtBach0, ptBach0, float); //! Transverse momentum of bachelor 0 (GeV/c) +DECLARE_SOA_COLUMN(PtBach1, ptBach1, float); //! Transverse momentum of bachelor 1 (GeV/c) +DECLARE_SOA_COLUMN(MBach0, mBach0, float); //! Invariant mass of bachelor 0 (GeV/c) +DECLARE_SOA_COLUMN(MBach1, mBach1, float); //! Invariant mass of bachelor 1 (GeV/c) +DECLARE_SOA_COLUMN(MBachD0, mBachD0, float); //! Invariant mass of D0 bachelor (of bachelor 0) (GeV/c) +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(Sign, sign, int8_t); //! Sign of candidate +DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); //! VosThetaStar of candidate (GeV) +DECLARE_SOA_COLUMN(MlScoreBkgBach0, mlScoreBkgBach0, float); //! ML score for background class of charm daughter +DECLARE_SOA_COLUMN(MlScorePromptBach0, mlScorePromptBach0, float); //! ML score for prompt class of charm daughter +DECLARE_SOA_COLUMN(MlScoreNonPromptBach0, mlScoreNonPromptBach0, float); //! ML score for non-prompt class of charm daughter +DECLARE_SOA_COLUMN(ItsNClsProngMinBach0, itsNClsProngMinBach0, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach0, tpcNClsCrossedRowsProngMinBach0, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach0, tpcChi2NClProngMaxBach0, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(ItsNClsBach1, itsNClsBach1, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsBach1, tpcNClsCrossedRowsBach1, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcChi2NClBach1, tpcChi2NClBach1, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcNSigmaBach1, tpcNSigmaBach1, float); //! NsigmaTPC for Bach1 for its mass hypothesis +DECLARE_SOA_COLUMN(TofNSigmaBach1, tofNSigmaBach1, float); //! NsigmaTOF for Bach1 for its mass hypothesis +DECLARE_SOA_COLUMN(TpcTofNSigmaBach1, tpcTofNSigmaBach1, float); //! Combined NsigmaTPC-TOF for Bach1 for its mass hypothesis +DECLARE_SOA_COLUMN(FlagMcMatch, flagMcMatch, int8_t); //! flag for decay channel classification reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int); //! debug flag for mis-association at reconstruction level +DECLARE_SOA_COLUMN(Origin, origin, int8_t); //! Flag for origin of MC particle 1=promt, 2=FD +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(InvMassGen, invMassGen, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(FlagCharmBach, flagCharmBach, int8_t); //! Flag for charm bachelor classification +DECLARE_SOA_COLUMN(FlagCharmBachInterm, flagCharmBachInterm, int8_t); //! Flag for charm bachelor classification intermediate +} // namespace hf_cand_reso_to_trk_lite + +DECLARE_SOA_TABLE(HfCandDTrkLites, "AOD", "HFCANDDTRKLITE", //! Table with some B0 properties + // Candidate Properties + hf_cand_reso_to_trk_lite::M, + hf_cand_reso_to_trk_lite::Pt, + hf_cand_reso_to_trk_lite::P, + hf_cand_reso_to_trk_lite::Y, + hf_cand_reso_to_trk_lite::Eta, + hf_cand_reso_to_trk_lite::Phi, + hf_cand_reso_to_trk_lite::E, + hf_cand_reso_to_trk_lite::CosThetaStar, + hf_cand_reso_to_trk_lite::Sign, + // Bachelors Properties + hf_cand_reso_to_trk_lite::MBach0, + hf_cand_reso_to_trk_lite::PtBach0, + hf_cand_reso_to_trk_lite::MlScoreBkgBach0, + hf_cand_reso_to_trk_lite::MlScorePromptBach0, + hf_cand_reso_to_trk_lite::MlScoreNonPromptBach0, + hf_cand_reso_to_trk_lite::ItsNClsProngMinBach0, + hf_cand_reso_to_trk_lite::TpcNClsCrossedRowsProngMinBach0, + hf_cand_reso_to_trk_lite::TpcChi2NClProngMaxBach0, + hf_cand_reso_to_trk_lite::PtBach1, + hf_cand_reso_to_trk_lite::ItsNClsBach1, + hf_cand_reso_to_trk_lite::TpcNClsCrossedRowsBach1, + hf_cand_reso_to_trk_lite::TpcChi2NClBach1, + hf_cand_reso_to_trk_lite::TpcNSigmaBach1, + hf_cand_reso_to_trk_lite::TofNSigmaBach1, + hf_cand_reso_to_trk_lite::TpcTofNSigmaBach1, + // MC + hf_cand_reso_to_trk_lite::FlagMcMatch, + hf_cand_reso_to_trk_lite::DebugMcRec, + hf_cand_reso_to_trk_lite::Origin, + hf_cand_reso_to_trk_lite::PtGen, + hf_cand_reso_to_trk_lite::InvMassGen, + hf_cand_reso_to_trk_lite::FlagCharmBach, + hf_cand_reso_to_trk_lite::FlagCharmBachInterm); + +DECLARE_SOA_TABLE(HfGenResoLites, "AOD", "HFGENRESOLITE", //! Table with some B0 properties + hf_cand_reso_to_trk_lite::Pt, + hf_cand_reso_to_trk_lite::Y, + hf_cand_reso_to_trk_lite::Origin, + hf_cand_reso_to_trk_lite::FlagMcMatch); + +} // namespace o2::aod + +enum DecayChannel : uint8_t { + D0Kplus = 0 +}; + +struct HfTaskCharmResoToDTrkReduced { + Produces hfCandResoLite; + Produces hfGenResoLite; + + Configurable doWrongSign{"doWrongSign", false, "Flag to enable wrong sign candidates"}; + Configurable ptMinReso{"ptMinReso", -1, "Discard events with smaller pT"}; + Configurable fillTrees{"fillTrees", true, "Fill output Trees"}; + Configurable fillSparses{"fillSparses", false, "Fill output Sparses"}; + Configurable useDeltaMass{"useDeltaMass", true, "Use Delta Mass for resonance invariant Mass calculation"}; + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to Fill only signal candidates (MC only)"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", -1, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity for acceptance calculation"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum for acceptance calculation"}; + Configurable massResoMin{"massResoMin", 0.2, "min. mass of resonance"}; + Configurable massResoMax{"massResoMax", 1.29, "max. mass of resonance"}; + + using ReducedReso2PrTrk = soa::Join; + using ReducedReso2PrTrkMC = soa::Join; + + // Configurables axis for histos + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng0{"axisPtProng0", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong0 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng1{"axisPtProng1", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong1 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisInvMassReso{"axisInvMassReso", {200, 2.34, 2.74}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {175, 1.70, 2.05}, "inv. mass (D) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisCosThetaStar{"axisCosThetaStar", {40, -1, 1}, "cos(#vartheta*)"}; + ConfigurableAxis axisBkgBdtScore{"axisBkgBdtScore", {100, 0, 1}, "bkg BDT Score"}; + ConfigurableAxis axisNonPromptBdtScore{"axisNonPromptBdtScore", {100, 0, 1}, "non-prompt BDT Score"}; + ConfigurableAxis axisEta{"axisEta", {30, -1.5, 1.5}, "pseudorapidity"}; + ConfigurableAxis axisOrigin{"axisOrigin", {3, -0.5, 2.5}, "origin"}; + ConfigurableAxis axisFlag{"axisFlag", {65, -32.5, 32.5}, "mc flag"}; + + // Histogram Registry + HistogramRegistry registry; + + // init + void init(InitContext&) + { + registry.add("hMass", "Charm resonance candidates inv. mass", {HistType::kTH1D, {axisInvMassReso}}); + registry.add("hMassProng0", "D daughters inv. mass", {HistType::kTH1D, {axisInvMassProng0}}); + registry.add("hPt", "Charm resonance candidates pT", {HistType::kTH1D, {axisPt}}); + registry.add("hPtProng0", "D daughters pT", {HistType::kTH1D, {axisPtProng0}}); + registry.add("hPtProng1", "Track daughter pT", {HistType::kTH1D, {axisPtProng1}}); + registry.add("hNPvCont", "Collision number of PV contributors ; N contrib ; entries", {HistType::kTH1D, {{125, -0.5, 249.5}}}); + registry.add("hZvert", "Collision Z Vtx ; z PV [cm] ; entries", {HistType::kTH1D, {{120, -12., 12.}}}); + registry.add("hBz", "Collision Bz ; Bz [T] ; entries", {HistType::kTH1D, {{20, -10., 10.}}}); + registry.add("hSparse", "THn for production studies with cosThStar and BDT scores", HistType::kTHnSparseF, {axisPt, axisPtProng0, axisPtProng1, axisInvMassReso, axisInvMassProng0, axisCosThetaStar, axisBkgBdtScore, axisNonPromptBdtScore}); + + if (doprocessD0KplusMC || doprocessD0KplusMCWithMl) { + // gen histos + registry.add("hYRecPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYRecNonPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenAll", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPrompt", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPromptWithProngsInAcceptance", "Prompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPrompt", "NonPrompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPromptWithProngsInAcceptance", "NonPrompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + if (fillSparses) { + registry.add("hPtYGenSig", "{D_{S}}^j particles (generated);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); + registry.add("hPtYWithProngsInAccepanceGenSig", "{D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); + } + } + } + + // Fill histograms + /// \tparam channel is the decay channel of the Resonance + /// \param candidate is a candidate + /// \param coll is a reduced collision + /// \param bach0 is a bachelor of the candidate + /// \param bach1 is a bachelor of the candidate + template + void fillCand(const Cand& candidate, const Coll& collision, const CharmBach& bach0, const TrkBach& bach1) + { + // Base + float massReso{0}, cosThetaStar{0}; + int8_t sign{0}; + float tpcNSigmaBach1{0}, tofNSigmaBach1{0}, tpcTofNSigmaBach1{0}; + if constexpr (channel == DecayChannel::D0Kplus) { + massReso = useDeltaMass ? candidate.invMass() + MassD0 : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassD0, MassKPlus}, massReso, 0); + tpcNSigmaBach1 = bach1.tpcNSigmaKa(); + tofNSigmaBach1 = bach1.tofNSigmaKa(); + tpcTofNSigmaBach1 = bach1.tpcTofNSigmaKa(); + sign = bach1.sign(); + } + float y = RecoDecay::y(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); + float eta = RecoDecay::eta(std::array{candidate.px(), candidate.py(), candidate.pz()}); + float phi = RecoDecay::phi(candidate.px(), candidate.py()); + float p = RecoDecay::p(std::array{candidate.px(), candidate.py(), candidate.pz()}); + float e = RecoDecay::e(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); + + // MC Rec + float ptGen{-1.}, invMassGen{-1}; + int8_t origin{0}, flagMcMatchRec{0}, flagCharmBach{0}, flagCharmBachInterm{0}; + int debugMcRec{-1}; + if constexpr (doMc) { + ptGen = candidate.ptGen(); + origin = candidate.origin(); + flagMcMatchRec = candidate.flagMcMatchRec(); + debugMcRec = candidate.debugMcRec(); + invMassGen = candidate.invMassGen(); + flagCharmBach = candidate.flagMcMatchRecD(); + flagCharmBachInterm = candidate.flagMcMatchChanD(); + if (fillOnlySignal) { + if (channel == DecayChannel::D0Kplus && + !hf_decay::hf_cand_reso::particlesToD0Kplus.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } + } + if (origin == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("hYRecPrompt"), candidate.pt(), y); + } else if (origin == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hYRecNonPrompt"), candidate.pt(), y); + } + } + + // Ml + float mlScoreBkg{-1.}, mlScorePrompt{-1.}, mlScoreNonPrompt{-1.}; + if constexpr (withMl) { + if constexpr (channel == DecayChannel::D0Kplus) { + if (bach1.sign() > 0 && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } else if (bach1.sign() < 0 && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (bach1.sign() > 0 && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (bach1.sign() < 0 && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } + } else { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } + } + // Collision properties + registry.fill(HIST("hNPvCont"), collision.numContrib()); + registry.fill(HIST("hZvert"), collision.posZ()); + registry.fill(HIST("hBz"), collision.bz()); + // Candidate properties + registry.fill(HIST("hMass"), candidate.invMass()); + registry.fill(HIST("hMassProng0"), candidate.invMassProng0()); + registry.fill(HIST("hPt"), candidate.pt()); + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + if (fillSparses) { + registry.fill(HIST("hSparse"), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), candidate.invMass(), candidate.invMassProng0(), cosThetaStar, mlScoreBkg, mlScoreNonPrompt); + } + if (fillTrees) { + hfCandResoLite( + candidate.invMass(), + candidate.pt(), + p, + y, + eta, + phi, + e, + cosThetaStar, + sign, + // Bachelors Properties + candidate.invMassProng0(), + bach0.pt(), + mlScoreBkg, + mlScorePrompt, + mlScoreNonPrompt, + bach0.itsNClsProngMin(), + bach0.tpcNClsCrossedRowsProngMin(), + bach0.tpcChi2NClProngMax(), + bach1.pt(), + bach1.itsNCls(), + bach1.tpcNClsCrossedRows(), + bach1.tpcChi2NCl(), + tpcNSigmaBach1, + tofNSigmaBach1, + tpcTofNSigmaBach1, + // MC + flagMcMatchRec, + debugMcRec, + origin, + ptGen, + invMassGen, + flagCharmBach, + flagCharmBachInterm); + } + } // fillCand + + // Process data + /// \tparam channel is the decay channel of the Resonance + /// \param Coll is the reduced collisions table + /// \param CharmBach is the reduced 3 prong table + /// \param TrkBach is the reduced v0 table + /// \param Cand is the candidates table + template + void processData(Coll const&, Candidates const& candidates, CharmBach const&, aod::HfRedTrkNoParams const&) + { + for (const auto& cand : candidates) { + if (ptMinReso >= 0 && cand.pt() < ptMinReso) { + continue; + } + if ((massResoMin >= 0 && cand.invMass() < massResoMin) || + (massResoMax >= 0 && cand.invMass() > massResoMax)) { + continue; + } + if (doWrongSign && cand.isWrongSign() == 0) { + continue; + } else if (!doWrongSign && cand.isWrongSign() != 0) { + continue; + } + + float massReso{0}; + if (useDeltaMass) { + switch (channel) { + case DecayChannel::D0Kplus: + massReso = cand.invMass() + MassD0; + break; + default: + break; + } + } else { + massReso = cand.invMass(); + } + if (yCandRecoMax >= 0. && std::abs(RecoDecay::y(std::array{cand.px(), cand.py(), cand.pz()}, massReso)) > yCandRecoMax) { + continue; + } + auto coll = cand.template hfRedCollision_as(); + auto bach0 = cand.template prong0_as(); + auto bach1 = cand.template prong1_as(); + fillCand(cand, coll, bach0, bach1); + } + } + + /// Selection of resonance daughters in geometrical acceptance + /// \param etaProng is the pseudorapidity of Resonance prong + /// \param ptProng is the pT of Resonance prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Fill particle histograms (gen MC truth) + template + void fillCandMcGen(aod::HfMcGenRedResos const& mcParticles) + { + for (const auto& particle : mcParticles) { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + auto originParticle = particle.origin(); + auto flag = particle.flagMcMatchGen(); + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + if (channel == DecayChannel::D0Kplus && + !hf_decay::hf_cand_reso::particlesToD0Kplus.contains(static_cast(std::abs(flag)))) { + continue; + } + registry.fill(HIST("hYGenAll"), ptParticle, yParticle); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + continue; + } + if (originParticle == RecoDecay::OriginType::Prompt) { // prompt particles + registry.fill(HIST("hYGenPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenPromptWithProngsInAcceptance"), ptParticle, yParticle); + } + } else if (originParticle == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hYGenNonPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenNonPromptWithProngsInAcceptance"), ptParticle, yParticle); + } + } + if (fillSparses) { + registry.fill(HIST("hPtYGenSig"), ptParticle, yParticle, originParticle, flag); + if (prongsInAcc) { + registry.fill(HIST("hPtYWithProngsInAccepanceGenSig"), ptParticle, yParticle, originParticle, flag); + } + } + if (fillTrees) { + hfGenResoLite(ptParticle, yParticle, originParticle, flag); + } + } + } // fillCandMcGen + + // process functions + void processD0KplusData(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrk const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs) + { + processData(collisions, candidates, charmBachs, trkBachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusData, "Process data for D0Kplus analysis", true); + + // Process data with ML + void processD0KplusDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrk const& candidates, + soa::Join const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs) + { + processData(collisions, candidates, charmBachs, trkBachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusDataWithMl, "Process data for D0Kplus analysis with Ml", false); + + // MC + void processD0KplusMC(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrkMC const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, trkBachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusMC, "Process MC for D0Kplus analysis", false); + + // MC with Ml + void processD0KplusMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrTrkMC const& candidates, + soa::Join const& charmBachs, + aod::HfRedTrkNoParams const& trkBachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, trkBachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDTrkReduced, processD0KplusMCWithMl, "Process MC for D0Kplus analysis with Ml", false); + +}; // struct HfTaskCharmResoToDTrkReduced +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskCharmResoToDV0Reduced.cxx b/PWGHF/D2H/Tasks/taskCharmResoToDV0Reduced.cxx new file mode 100644 index 00000000000..360b8a3002f --- /dev/null +++ b/PWGHF/D2H/Tasks/taskCharmResoToDV0Reduced.cxx @@ -0,0 +1,658 @@ +// 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 taskCharmResoToDV0Reduced.cxx +/// \brief Charmed Resonances decaying in a D meson and a V0 analysis task +/// +/// \author Luca Aglietta , University and INFN Torino + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" +#include "PWGHF/Utils/utilsMcMatching.h" + +#include "Common/Core/RecoDecay.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; + +enum BachelorType : uint8_t { + K0s = 0, + Lambda, + AntiLambda +}; + +namespace o2::aod +{ +namespace hf_cand_reso_to_v0_lite +{ +DECLARE_SOA_COLUMN(PtBach0, ptBach0, float); //! Transverse momentum of bachelor 0 (GeV/c) +DECLARE_SOA_COLUMN(PtBach1, ptBach1, float); //! Transverse momentum of bachelor 1 (GeV/c) +DECLARE_SOA_COLUMN(MBach0, mBach0, float); //! Invariant mass of bachelor 0 (GeV/c) +DECLARE_SOA_COLUMN(MBach1, mBach1, float); //! Invariant mass of bachelor 1 (GeV/c) +DECLARE_SOA_COLUMN(MBachD0, mBachD0, float); //! Invariant mass of D0 bachelor (of bachelor 0) (GeV/c) +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(Sign, sign, int8_t); //! Sign of candidate +DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); //! VosThetaStar of candidate (GeV) +DECLARE_SOA_COLUMN(MlScoreBkgBach0, mlScoreBkgBach0, float); //! ML score for background class of charm daughter +DECLARE_SOA_COLUMN(MlScorePromptBach0, mlScorePromptBach0, float); //! ML score for prompt class of charm daughter +DECLARE_SOA_COLUMN(MlScoreNonPromptBach0, mlScoreNonPromptBach0, float); //! ML score for non-prompt class of charm daughter +DECLARE_SOA_COLUMN(ItsNClsProngMinBach0, itsNClsProngMinBach0, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach0, tpcNClsCrossedRowsProngMinBach0, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach0, tpcChi2NClProngMaxBach0, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(ItsNClsSoftPi, itsNClsSoftPi, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsSoftPi, tpcNClsCrossedRowsSoftPi, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(TpcChi2NClSoftPi, tpcChi2NClSoftPi, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 0 +DECLARE_SOA_COLUMN(ItsNClsProngMinBach1, itsNClsProngMinBach1, int); //! minimum value of number of ITS clusters for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcNClsCrossedRowsProngMinBach1, tpcNClsCrossedRowsProngMinBach1, int); //! minimum value of number of TPC crossed rows for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(TpcChi2NClProngMaxBach1, tpcChi2NClProngMaxBach1, float); //! maximum value of TPC chi2 for the decay daughter tracks of bachelor 1 +DECLARE_SOA_COLUMN(CpaBach1, cpaBach1, float); //! Cosine of Pointing Angle of bachelor 1 +DECLARE_SOA_COLUMN(DcaBach1, dcaBach1, float); //! DCA of bachelor 1 +DECLARE_SOA_COLUMN(RadiusBach1, radiusBach1, float); //! Radius of bachelor 1 +DECLARE_SOA_COLUMN(FlagMcMatch, flagMcMatch, int8_t); //! flag for decay channel classification reconstruction level +DECLARE_SOA_COLUMN(DebugMcRec, debugMcRec, int); //! debug flag for mis-association at reconstruction level +DECLARE_SOA_COLUMN(Origin, origin, int8_t); //! Flag for origin of MC particle 1=promt, 2=FD +DECLARE_SOA_COLUMN(PtGen, ptGen, float); //! Transverse momentum of candidate (GeV/c) +DECLARE_SOA_COLUMN(InvMassGen, invMassGen, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(FlagCharmBach, flagCharmBach, int8_t); //! Flag for charm bachelor classification +DECLARE_SOA_COLUMN(FlagCharmBachInterm, flagCharmBachInterm, int8_t); //! Flag for charm bachelor classification intermediate +} // namespace hf_cand_reso_to_v0_lite + +DECLARE_SOA_TABLE(HfCandDV0Lites, "AOD", "HFCANDDV0LITE", //! Table with some Resonances properties + // Candidate Properties + hf_cand_reso_to_v0_lite::M, + hf_cand_reso_to_v0_lite::Pt, + hf_cand_reso_to_v0_lite::P, + hf_cand_reso_to_v0_lite::Y, + hf_cand_reso_to_v0_lite::Eta, + hf_cand_reso_to_v0_lite::Phi, + hf_cand_reso_to_v0_lite::E, + hf_cand_reso_to_v0_lite::CosThetaStar, + hf_cand_reso_to_v0_lite::Sign, + // Bachelors Properties + hf_cand_reso_to_v0_lite::MBach0, + hf_cand_reso_to_v0_lite::PtBach0, + hf_cand_reso_to_v0_lite::MlScoreBkgBach0, + hf_cand_reso_to_v0_lite::MlScorePromptBach0, + hf_cand_reso_to_v0_lite::MlScoreNonPromptBach0, + hf_cand_reso_to_v0_lite::ItsNClsProngMinBach0, + hf_cand_reso_to_v0_lite::TpcNClsCrossedRowsProngMinBach0, + hf_cand_reso_to_v0_lite::TpcChi2NClProngMaxBach0, + hf_cand_reso_to_v0_lite::ItsNClsSoftPi, + hf_cand_reso_to_v0_lite::TpcNClsCrossedRowsSoftPi, + hf_cand_reso_to_v0_lite::TpcChi2NClSoftPi, + hf_cand_reso_to_v0_lite::MBach1, + hf_cand_reso_to_v0_lite::PtBach1, + hf_cand_reso_to_v0_lite::CpaBach1, + hf_cand_reso_to_v0_lite::DcaBach1, + hf_cand_reso_to_v0_lite::RadiusBach1, + hf_cand_reso_to_v0_lite::ItsNClsProngMinBach1, + hf_cand_reso_to_v0_lite::TpcNClsCrossedRowsProngMinBach1, + hf_cand_reso_to_v0_lite::TpcChi2NClProngMaxBach1, + // MC + hf_cand_reso_to_v0_lite::FlagMcMatch, + hf_cand_reso_to_v0_lite::DebugMcRec, + hf_cand_reso_to_v0_lite::Origin, + hf_cand_reso_to_v0_lite::PtGen, + hf_cand_reso_to_v0_lite::InvMassGen, + hf_cand_reso_to_v0_lite::FlagCharmBach, + hf_cand_reso_to_v0_lite::FlagCharmBachInterm); + +DECLARE_SOA_TABLE(HfGenResoLites, "AOD", "HFGENRESOLITE", //! Table with some B0 properties + hf_cand_reso_to_v0_lite::Pt, + hf_cand_reso_to_v0_lite::Y, + hf_cand_reso_to_v0_lite::Origin, + hf_cand_reso_to_v0_lite::FlagMcMatch); + +} // namespace o2::aod + +enum DecayChannel : uint8_t { + DstarK0s = 0, + DplusK0s, + DplusLambda, + D0Lambda +}; + +struct HfTaskCharmResoToDV0Reduced { + Produces hfCandResoLite; + Produces hfGenResoLite; + + Configurable doWrongSign{"doWrongSign", false, "Flag to enable wrong sign candidates"}; + Configurable ptMinReso{"ptMinReso", -1, "Discard events with smaller pT"}; + Configurable fillTrees{"fillTrees", true, "Fill output Trees"}; + Configurable fillSparses{"fillSparses", false, "Fill output Sparses"}; + Configurable useDeltaMass{"useDeltaMass", true, "Use Delta Mass for resonance invariant Mass calculation"}; + Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to Fill only signal candidates (MC only)"}; + Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; + Configurable yCandRecoMax{"yCandRecoMax", -1, "max. cand. rapidity"}; + Configurable etaTrackMax{"etaTrackMax", 0.8, "max. track pseudo-rapidity for acceptance calculation"}; + Configurable ptTrackMin{"ptTrackMin", 0.1, "min. track transverse momentum for acceptance calculation"}; + Configurable massResoMin{"massResoMin", 0.49, "min. mass of resonance"}; + Configurable massResoMax{"massResoMax", 1.29, "max. mass of resonance"}; + + using ReducedReso3PrV0 = soa::Join; + using ReducedResoDstarV0 = soa::Join; + using ReducedReso2PrV0 = soa::Join; + using ReducedReso3PrV0MC = soa::Join; + using ReducedResoDstarV0MC = soa::Join; + using ReducedReso2PrV0MC = soa::Join; + + // Configurables axis for histos + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng0{"axisPtProng0", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong0 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisPtProng1{"axisPtProng1", {VARIABLE_WIDTH, 0., 1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 8.f, 12.f, 24.f, 50.f}, "prong1 bach. #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisInvMassReso{"axisInvMassReso", {200, 2.34, 2.74}, "inv. mass (DV_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisInvMassProng0{"axisInvMassProng0", {175, 1.70, 2.05}, "inv. mass (D) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisInvMassProng1{"axisInvMassProng1", {80, 0.46, 0.54}, "inv. mass ({V}_{0}) (GeV/#it{c}^{2})"}; + ConfigurableAxis axisCosThetaStar{"axisCosThetaStar", {40, -1, 1}, "cos(#vartheta*)"}; + ConfigurableAxis axisBkgBdtScore{"axisBkgBdtScore", {100, 0, 1}, "bkg BDT Score"}; + ConfigurableAxis axisNonPromptBdtScore{"axisNonPromptBdtScore", {100, 0, 1}, "non-prompt BDT Score"}; + ConfigurableAxis axisEta{"axisEta", {30, -1.5, 1.5}, "pseudorapidity"}; + ConfigurableAxis axisOrigin{"axisOrigin", {3, -0.5, 2.5}, "origin"}; + ConfigurableAxis axisFlag{"axisFlag", {65, -32.5, 32.5}, "mc flag"}; + + // Histogram Registry + HistogramRegistry registry; + + // init + void init(InitContext&) + { + registry.add("hMass", "Charm resonance candidates inv. mass", {HistType::kTH1D, {axisInvMassReso}}); + registry.add("hMassProng0", "D daughters inv. mass", {HistType::kTH1D, {axisInvMassProng0}}); + registry.add("hMassProng1", "V0 daughter inv. mass", {HistType::kTH1D, {axisInvMassProng1}}); + registry.add("hPt", "Charm resonance candidates pT", {HistType::kTH1D, {axisPt}}); + registry.add("hPtProng0", "D daughters pT", {HistType::kTH1D, {axisPtProng0}}); + registry.add("hPtProng1", "V0 daughter pT", {HistType::kTH1D, {axisPtProng1}}); + registry.add("hNPvCont", "Collision number of PV contributors ; N contrib ; entries", {HistType::kTH1D, {{125, -0.5, 249.5}}}); + registry.add("hZvert", "Collision Z Vtx ; z PV [cm] ; entries", {HistType::kTH1D, {{120, -12., 12.}}}); + registry.add("hBz", "Collision Bz ; Bz [T] ; entries", {HistType::kTH1D, {{20, -10., 10.}}}); + registry.add("hSparse", "THn for production studies with cosThStar and BDT scores", HistType::kTHnSparseF, {axisPt, axisPtProng0, axisPtProng1, axisInvMassReso, axisInvMassProng0, axisInvMassProng1, axisCosThetaStar, axisBkgBdtScore, axisNonPromptBdtScore}); + + if (doprocessDstarK0sMC || doprocessDplusK0sMC || doprocessDstarK0sMCWithMl || doprocessDplusK0sMCWithMl || + doprocessDplusLambdaMC || doprocessD0LambdaMC || doprocessDplusLambdaMCWithMl || doprocessD0LambdaMCWithMl) { + // gen histos + registry.add("hYRecPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYRecNonPrompt", "Charm resonance candidates pT", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenAll", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPrompt", "Prompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenPromptWithProngsInAcceptance", "Prompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPrompt", "NonPrompt {D_{S}}^j particles (generated);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + registry.add("hYGenNonPromptWithProngsInAcceptance", "NonPrompt {D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}^{gen}({D_{S}}^j) (GeV/#it{c});#it{y}^{gen}({D_{S}}^j);entries", {HistType::kTH2D, {axisPt, axisEta}}); + if (fillSparses) { + registry.add("hPtYGenSig", "{D_{S}}^j particles (generated);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); + registry.add("hPtYWithProngsInAccepanceGenSig", "{D_{S}}^j particles (generated-daughters in acceptance);#it{p}_{T}({D_{S}}^j) (GeV/#it{c});#it{y}({D_{S}}^j)", {HistType::kTHnSparseF, {axisPt, axisEta, axisOrigin, axisFlag}}); + } + } + } + + // Fill histograms + /// \tparam channel is the decay channel of the Resonance + /// \param candidate is a candidate + /// \param coll is a reduced collision + /// \param bach0 is a bachelor of the candidate + /// \param bach1 is a bachelor of the candidate + template + void fillCand(const Cand& candidate, const Coll& collision, const CharmBach& bach0, const V0Bach& bach1) + { + // Base + float massReso{0}, cosThetaStar{0}; + int8_t sign{0}; + int itsNClsSoftPi{0}, tpcNClsCrossedRowsSoftPi{0}; + float tpcChi2NClSoftPi{0.}; + if constexpr (channel == DecayChannel::DstarK0s) { + sign = bach0.sign(); + massReso = useDeltaMass ? candidate.invMass() + MassDStar : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassDStar, MassK0}, massReso, 0); + itsNClsSoftPi = bach0.itsNClsSoftPi(); + tpcNClsCrossedRowsSoftPi = bach0.tpcNClsCrossedRowsSoftPi(); + tpcChi2NClSoftPi = bach0.tpcChi2NClSoftPi(); + } else if constexpr (channel == DecayChannel::DplusK0s) { + sign = bach0.sign(); + massReso = useDeltaMass ? candidate.invMass() + MassDPlus : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassDPlus, MassK0}, massReso, 0); + } else if constexpr (channel == DecayChannel::DplusLambda) { + sign = bach0.sign(); + massReso = useDeltaMass ? candidate.invMass() + MassDPlus : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassDPlus, MassLambda0}, massReso, 0); + } else if constexpr (channel == DecayChannel::D0Lambda) { + massReso = useDeltaMass ? candidate.invMass() + MassD0 : candidate.invMass(); + cosThetaStar = RecoDecay::cosThetaStar(std::array{bach0.pVector(), bach1.pVector()}, std::array{MassD0, MassLambda0}, massReso, 0); + } + float y = RecoDecay::y(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); + float eta = RecoDecay::eta(std::array{candidate.px(), candidate.py(), candidate.pz()}); + float phi = RecoDecay::phi(candidate.px(), candidate.py()); + float p = RecoDecay::p(std::array{candidate.px(), candidate.py(), candidate.pz()}); + float e = RecoDecay::e(std::array{candidate.px(), candidate.py(), candidate.pz()}, massReso); + + // MC Rec + float ptGen{-1.}, invMassGen{-1}; + int8_t origin{0}, flagMcMatchRec{0}, flagCharmBach{0}, flagCharmBachInterm{0}; + int debugMcRec{-1}; + if constexpr (doMc) { + ptGen = candidate.ptGen(); + origin = candidate.origin(); + flagMcMatchRec = candidate.flagMcMatchRec(); + debugMcRec = candidate.debugMcRec(); + invMassGen = candidate.invMassGen(); + flagCharmBach = candidate.flagMcMatchRecD(); + flagCharmBachInterm = candidate.flagMcMatchChanD(); + if (fillOnlySignal) { + if (channel == DecayChannel::DstarK0s && + !hf_decay::hf_cand_reso::particlesToDstarK0s.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } else if (channel == DecayChannel::DplusK0s && + !hf_decay::hf_cand_reso::particlesToDplusK0s.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } else if (channel == DecayChannel::DplusLambda && + !hf_decay::hf_cand_reso::particlesToDplusLambda.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } else if (channel == DecayChannel::D0Lambda && + !hf_decay::hf_cand_reso::particlesToD0Lambda.contains(static_cast(std::abs(flagMcMatchRec)))) { + return; + } + } + if (origin == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("hYRecPrompt"), candidate.pt(), y); + } else if (origin == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hYRecNonPrompt"), candidate.pt(), y); + } + } + + // Ml + float mlScoreBkg{-1.}, mlScorePrompt{-1.}, mlScoreNonPrompt{-1.}; + if constexpr (withMl) { + if constexpr (channel == DecayChannel::D0Lambda) { + if (TESTBIT(bach1.v0Type(), BachelorType::Lambda) && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } else if (TESTBIT(bach1.v0Type(), BachelorType::AntiLambda) && !doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (TESTBIT(bach1.v0Type(), BachelorType::Lambda) && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo1(); + mlScorePrompt = bach0.mlScorePromptMassHypo1(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo1(); + } else if (TESTBIT(bach1.v0Type(), BachelorType::AntiLambda) && doWrongSign) { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } + } else { + mlScoreBkg = bach0.mlScoreBkgMassHypo0(); + mlScorePrompt = bach0.mlScorePromptMassHypo0(); + mlScoreNonPrompt = bach0.mlScoreNonpromptMassHypo0(); + } + } + // Collision properties + registry.fill(HIST("hNPvCont"), collision.numContrib()); + registry.fill(HIST("hZvert"), collision.posZ()); + registry.fill(HIST("hBz"), collision.bz()); + // Candidate properties + registry.fill(HIST("hMass"), candidate.invMass()); + registry.fill(HIST("hMassProng0"), candidate.invMassProng0()); + registry.fill(HIST("hMassProng1"), candidate.invMassProng1()); + registry.fill(HIST("hPt"), candidate.pt()); + registry.fill(HIST("hPtProng0"), candidate.ptProng0()); + registry.fill(HIST("hPtProng1"), candidate.ptProng1()); + if (fillSparses) { + registry.fill(HIST("hSparse"), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), candidate.invMass(), candidate.invMassProng0(), candidate.invMassProng1(), cosThetaStar, mlScoreBkg, mlScoreNonPrompt); + } + if (fillTrees) { + hfCandResoLite( + candidate.invMass(), + candidate.pt(), + p, + y, + eta, + phi, + e, + cosThetaStar, + sign, + // Bachelors Properties + candidate.invMassProng0(), + bach0.pt(), + mlScoreBkg, + mlScorePrompt, + mlScoreNonPrompt, + bach0.itsNClsProngMin(), + bach0.tpcNClsCrossedRowsProngMin(), + bach0.tpcChi2NClProngMax(), + itsNClsSoftPi, + tpcNClsCrossedRowsSoftPi, + tpcChi2NClSoftPi, + candidate.invMassProng1(), + bach1.pt(), + bach1.cpa(), + bach1.dca(), + bach1.v0Radius(), + bach1.itsNClsProngMin(), + bach1.tpcNClsCrossedRowsProngMin(), + bach1.tpcChi2NClProngMax(), + // MC + flagMcMatchRec, + debugMcRec, + origin, + ptGen, + invMassGen, + flagCharmBach, + flagCharmBachInterm); + } + } // fillCand + + // Process data + /// \tparam channel is the decay channel of the Resonance + /// \param Coll is the reduced collisions table + /// \param CharmBach is the reduced 3 prong table + /// \param V0Bach is the reduced v0 table + /// \param Cand is the candidates table + template + void processData(Coll const&, Candidates const& candidates, CharmBach const&, aod::HfRedVzeros const&) + { + for (const auto& cand : candidates) { + if (ptMinReso >= 0 && cand.pt() < ptMinReso) { + continue; + } + if ((massResoMin >= 0 && cand.invMass() < massResoMin) || + (massResoMax >= 0 && cand.invMass() > massResoMax)) { + continue; + } + if (doWrongSign && cand.isWrongSign() == 0) { + continue; + } else if (!doWrongSign && cand.isWrongSign() != 0) { + continue; + } + + float massReso{0}; + if (useDeltaMass) { + switch (channel) { + case DecayChannel::DstarK0s: + massReso = cand.invMass() + MassDStar; + break; + case DecayChannel::DplusK0s: + massReso = cand.invMass() + MassDPlus; + break; + case DecayChannel::DplusLambda: + massReso = cand.invMass() + MassDPlus; + break; + case DecayChannel::D0Lambda: + massReso = cand.invMass() + MassD0; + break; + default: + break; + } + } else { + massReso = cand.invMass(); + } + if (yCandRecoMax >= 0. && std::abs(RecoDecay::y(std::array{cand.px(), cand.py(), cand.pz()}, massReso)) > yCandRecoMax) { + continue; + } + auto coll = cand.template hfRedCollision_as(); + auto bach0 = cand.template prong0_as(); + auto bach1 = cand.template prong1_as(); + fillCand(cand, coll, bach0, bach1); + } + } + + /// Selection of resonance daughters in geometrical acceptance + /// \param etaProng is the pseudorapidity of Resonance prong + /// \param ptProng is the pT of Resonance prong + /// \return true if prong is in geometrical acceptance + template + bool isProngInAcceptance(const T& etaProng, const T& ptProng) + { + return std::abs(etaProng) <= etaTrackMax && ptProng >= ptTrackMin; + } + + /// Fill particle histograms (gen MC truth) + template + void fillCandMcGen(aod::HfMcGenRedResos const& mcParticles) + { + for (const auto& particle : mcParticles) { + auto ptParticle = particle.ptTrack(); + auto yParticle = particle.yTrack(); + auto originParticle = particle.origin(); + auto flag = particle.flagMcMatchGen(); + std::array ptProngs = {particle.ptProng0(), particle.ptProng1()}; + std::array etaProngs = {particle.etaProng0(), particle.etaProng1()}; + bool prongsInAcc = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]); + if (channel == DecayChannel::DstarK0s && + !hf_decay::hf_cand_reso::particlesToDstarK0s.contains(static_cast(std::abs(flag)))) { + continue; + } else if (channel == DecayChannel::DplusK0s && + !hf_decay::hf_cand_reso::particlesToDplusK0s.contains(static_cast(std::abs(flag)))) { + continue; + } else if (channel == DecayChannel::DplusLambda && + !hf_decay::hf_cand_reso::particlesToDplusLambda.contains(static_cast(std::abs(flag)))) { + continue; + } else if (channel == DecayChannel::D0Lambda && + !hf_decay::hf_cand_reso::particlesToD0Lambda.contains(static_cast(std::abs(flag)))) { + continue; + } + registry.fill(HIST("hYGenAll"), ptParticle, yParticle); + if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { + continue; + } + if (originParticle == RecoDecay::OriginType::Prompt) { // prompt particles + registry.fill(HIST("hYGenPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenPromptWithProngsInAcceptance"), ptParticle, yParticle); + } + } else if (originParticle == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("hYGenNonPrompt"), ptParticle, yParticle); + if (prongsInAcc) { + registry.fill(HIST("hYGenNonPromptWithProngsInAcceptance"), ptParticle, yParticle); + } + } + if (fillSparses) { + registry.fill(HIST("hPtYGenSig"), ptParticle, yParticle, originParticle, flag); + if (prongsInAcc) { + registry.fill(HIST("hPtYWithProngsInAccepanceGenSig"), ptParticle, yParticle, originParticle, flag); + } + } + if (fillTrees) { + hfGenResoLite(ptParticle, yParticle, originParticle, flag); + } + } + } // fillCandMcGen + + // process functions + void processDstarK0sData(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0 const& candidates, + aod::HfRedDstarNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sData, "Process data for DstarK0s analysis", true); + + void processDplusK0sData(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sData, "Process data for DplusK0s analysis", false); + + void processDplusLambdaData(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaData, "Process data for DplusLambda analysis", false); + + void processD0LambdaData(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0 const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaData, "Process data for D0Lambda analysis", false); + + // Process data with ML + void processDstarK0sDataWithMl(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sDataWithMl, "Process data for DstarK0s analysis with Ml", false); + + void processDplusK0sDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sDataWithMl, "Process data for DplusK0s analysis with Ml", false); + + void processDplusLambdaDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaDataWithMl, "Process data for DplusLambda analysis with Ml", false); + + void processD0LambdaDataWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0 const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs) + { + processData(collisions, candidates, charmBachs, v0Bachs); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaDataWithMl, "Process data for D0Lambda analysis with Ml", false); + + // MC + void processDstarK0sMC(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0MC const& candidates, + aod::HfRedDstarNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sMC, "Process MC for DstarK0s analysis", false); + + void processDplusK0sMC(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sMC, "Process MC for DplusK0s analysis", false); + + void processDplusLambdaMC(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + aod::HfRed3PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaMC, "Process MC for DplusLambda analysis", false); + + void processD0LambdaMC(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0MC const& candidates, + aod::HfRed2PrNoTrks const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaMC, "Process MC for D0Lambda analysis", false); + + // MC with Ml + void processDstarK0sMCWithMl(aod::HfRedCollisions const& collisions, + ReducedResoDstarV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& charmBachsMc) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(charmBachsMc); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDstarK0sMCWithMl, "Process MC for DstarK0s analysis with Ml", false); + + void processDplusK0sMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusK0sMCWithMl, "Process MC for DplusK0s analysis with Ml", false); + + void processDplusLambdaMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso3PrV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processDplusLambdaMCWithMl, "Process MC for DplusLambda analysis with Ml", false); + + void processD0LambdaMCWithMl(aod::HfRedCollisions const& collisions, + ReducedReso2PrV0MC const& candidates, + soa::Join const& charmBachs, + aod::HfRedVzeros const& v0Bachs, + aod::HfMcGenRedResos const& mcParticles) + { + processData(collisions, candidates, charmBachs, v0Bachs); + fillCandMcGen(mcParticles); + } + PROCESS_SWITCH(HfTaskCharmResoToDV0Reduced, processD0LambdaMCWithMl, "Process MC for D0Lambda analysis with Ml", false); + +}; // struct HfTaskCharmResoToDV0Reduced +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskD0.cxx b/PWGHF/D2H/Tasks/taskD0.cxx index b650e5bd4f0..30bc3787e24 100644 --- a/PWGHF/D2H/Tasks/taskD0.cxx +++ b/PWGHF/D2H/Tasks/taskD0.cxx @@ -15,22 +15,38 @@ /// \author Gian Michele Innocenti , CERN /// \author Vít Kučera , CERN -#include -#include // std::min - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/Utils/utilsEvSelHf.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 + +#include // std::min +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -554,7 +570,7 @@ struct HfTaskD0 { } auto trackPos = candidate.template prong0_as(); // positive daughter auto trackNeg = candidate.template prong1_as(); // negative daughter - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // Get the corresponding MC particle. auto indexMother = RecoDecay::getMother(mcParticles, trackPos.template mcParticle_as>(), o2::constants::physics::Pdg::kD0, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -648,7 +664,7 @@ struct HfTaskD0 { int minTpcCrossedRowsOfProngs = std::min(trackPos.tpcNClsCrossedRows(), trackNeg.tpcNClsCrossedRows()); if (candidate.isSelD0() >= selectionFlagD0) { registry.fill(HIST("hMassSigBkgD0"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hPtProng0Sig"), ptProng0, rapidityCandidate); registry.fill(HIST("hPtProng1Sig"), ptProng1, rapidityCandidate); registry.fill(HIST("hDecLengthSig"), declengthCandidate, rapidityCandidate); @@ -712,7 +728,7 @@ struct HfTaskD0 { registry.fill(HIST("hCPABkg"), cpaCandidate, rapidityCandidate); registry.fill(HIST("hCPAxyBkg"), cpaxyCandidate, rapidityCandidate); registry.fill(HIST("hMassBkgD0"), massD0, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassReflBkgD0"), massD0, ptCandidate, rapidityCandidate); if constexpr (applyMl) { if (storeCentrality && storeOccupancy) { @@ -744,7 +760,7 @@ struct HfTaskD0 { } if (candidate.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hMassSigBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassSigD0bar"), massD0bar, ptCandidate, rapidityCandidate); if constexpr (applyMl) { if (storeCentrality && storeOccupancy) { @@ -773,7 +789,7 @@ struct HfTaskD0 { } } else { registry.fill(HIST("hMassBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); - if (candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassReflBkgD0bar"), massD0bar, ptCandidate, rapidityCandidate); if constexpr (applyMl) { if (storeCentrality && storeOccupancy) { @@ -806,7 +822,7 @@ struct HfTaskD0 { } // MC gen. for (const auto& particle : mcParticles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { if (yCandGenMax >= 0. && std::abs(RecoDecay::y(particle.pVector(), o2::constants::physics::MassD0)) > yCandGenMax) { continue; } diff --git a/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx index db2300126f2..bc4d3308c18 100644 --- a/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskDirectedFlowCharmHadrons.cxx @@ -15,24 +15,36 @@ /// \author Prottay Das, prottay.das@cern.ch /// \author Biao Zhang, biao.zhanng@cern.ch -#include -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/EventPlaneHelper.h" -#include "PWGLF/DataModel/SPCalibrationTables.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" + +#include "Common/Core/EventPlaneHelper.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 using namespace o2; using namespace o2::aod; diff --git a/PWGHF/D2H/Tasks/taskDplus.cxx b/PWGHF/D2H/Tasks/taskDplus.cxx index cbf6118ce68..921d39364e6 100644 --- a/PWGHF/D2H/Tasks/taskDplus.cxx +++ b/PWGHF/D2H/Tasks/taskDplus.cxx @@ -17,14 +17,8 @@ /// \author Vít Kučera , CERN /// \author Luca Aglietta , University and INFN Torino -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -32,6 +26,31 @@ #include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/Utils/utilsEvSelHf.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 +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -51,6 +70,7 @@ struct HfTaskDplus { Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; Configurable storeCentrality{"storeCentrality", false, "Flag to store centrality information"}; Configurable storeOccupancy{"storeOccupancy", false, "Flag to store occupancy information"}; + Configurable storePvContributors{"storePvContributors", false, "Flag to store number of PV contributors information"}; Configurable fillMcBkgHistos{"fillMcBkgHistos", false, "Flag to fill and store histograms for MC background"}; HfHelper hfHelper; @@ -82,8 +102,9 @@ struct HfTaskDplus { Partition recoBkgCandidatesWithMl = nabs(aod::hf_cand_3prong::flagMcMatchRec) != static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) && aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagDplus; ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {40, -1, 1}, "Cand. rapidity bins"}; - ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {110, 0., 110.}, ""}; - ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for centrality"}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {110, 0., 110.}, "axis for centrality"}; + ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {14, 0, 14000}, "axis for occupancy"}; + ConfigurableAxis thnConfigAxisPvContributors{"thnConfigAxisPvContributors", {100, 0., 100.}, "axis for PV contributors"}; ConfigurableAxis thnConfigAxisPtBHad{"thnConfigAxisPtBHad", {25, 0., 50}, "axis for pt of B hadron decayed into D candidate"}; ConfigurableAxis thnConfigAxisFlagBHad{"thnConfigAxisFlagBHad", {5, 0., 5}, "axis for PDG of B hadron"}; ConfigurableAxis thnConfigAxisMlScore0{"thnConfigAxisMlScore0", {100, 0., 1.}, "axis for ML output score 0"}; @@ -119,6 +140,7 @@ struct HfTaskDplus { AxisSpec thnAxisFlagBHad{thnConfigAxisFlagBHad, "B Hadron flag"}; AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality"}; AxisSpec thnAxisOccupancy{thnConfigAxisOccupancy, "Occupancy"}; + AxisSpec thnAxisPvContributors{thnConfigAxisPvContributors, "PV contributors"}; registry.add("hMass", "3-prong candidates;inv. mass (#pi K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{350, 1.7, 2.05}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); registry.add("hEta", "3-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vbins, "#it{p}_{T} (GeV/#it{c})"}}}); @@ -162,13 +184,15 @@ struct HfTaskDplus { std::vector axes = {thnAxisMass, thnAxisPt}; if (doprocessDataWithMl) { - axes.insert(axes.end(), {thnAxisMlScore0, thnAxisMlScore1, thnAxisMlScore2}); + axes.push_back(thnAxisMlScore0); + axes.push_back(thnAxisMlScore1); + axes.push_back(thnAxisMlScore2); } if (storeCentrality) { - axes.insert(axes.end(), {thnAxisCent}); + axes.push_back(thnAxisCent); } if (storeOccupancy) { - axes.insert(axes.end(), {thnAxisOccupancy}); + axes.push_back(thnAxisOccupancy); } registry.add("hSparseMass", "THn for Dplus", HistType::kTHnSparseF, axes); @@ -184,22 +208,28 @@ struct HfTaskDplus { axesFD.insert(axesFD.end(), {thnAxisMlScore0, thnAxisMlScore1, thnAxisMlScore2}); } if (storeCentrality) { - axes.insert(axes.end(), {thnAxisCent}); - axesFD.insert(axesFD.end(), {thnAxisCent}); - axesGenPrompt.insert(axesGenPrompt.end(), {thnAxisCent}); - axesGenFD.insert(axesGenFD.end(), {thnAxisCent}); + axes.push_back(thnAxisCent); + axesFD.push_back(thnAxisCent); + axesGenPrompt.push_back(thnAxisCent); + axesGenFD.push_back(thnAxisCent); } if (storeOccupancy) { - axes.insert(axes.end(), {thnAxisOccupancy}); - axesFD.insert(axesFD.end(), {thnAxisOccupancy}); - axesGenPrompt.insert(axesGenPrompt.end(), {thnAxisOccupancy}); - axesGenFD.insert(axesGenFD.end(), {thnAxisOccupancy}); + axes.push_back(thnAxisOccupancy); + axesFD.push_back(thnAxisOccupancy); + axesGenPrompt.push_back(thnAxisOccupancy); + axesGenFD.push_back(thnAxisOccupancy); + } + if (storePvContributors) { + axes.push_back(thnAxisPvContributors); + axesFD.push_back(thnAxisPvContributors); + axesGenPrompt.push_back(thnAxisPvContributors); + axesGenFD.push_back(thnAxisPvContributors); } - axesFD.insert(axesFD.end(), {thnAxisPtBHad}); - axesFD.insert(axesFD.end(), {thnAxisFlagBHad}); - axesGenFD.insert(axesGenFD.end(), {thnAxisPtBHad}); - axesGenFD.insert(axesGenFD.end(), {thnAxisFlagBHad}); + axesFD.push_back(thnAxisPtBHad); + axesFD.push_back(thnAxisFlagBHad); + axesGenFD.push_back(thnAxisPtBHad); + axesGenFD.push_back(thnAxisFlagBHad); registry.add("hSparseMassPrompt", "THn for Dplus Prompt", HistType::kTHnSparseF, axes); registry.add("hSparseMassFD", "THn for Dplus FD", HistType::kTHnSparseF, axesFD); @@ -249,12 +279,14 @@ struct HfTaskDplus { /// \param flagBHad transverse momentum of beauty mother for nonprompt candidates /// \param centrality collision centrality /// \param occupancy collision occupancy + /// \param numPvContributors contributors to the PV template void fillSparseML(const T1& candidate, float ptbhad, int flagBHad, float centrality, - float occupancy) + float occupancy, + float numPvContributors) { std::vector outputMl = {-999., -999., -999.}; for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { @@ -270,6 +302,8 @@ struct HfTaskDplus { registry.fill(HIST("hSparseMassPrompt"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], centrality); } else if (!storeCentrality && storeOccupancy) { registry.fill(HIST("hSparseMassPrompt"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], occupancy); + } else if (!storeCentrality && !storeOccupancy && storePvContributors) { + registry.fill(HIST("hSparseMassPrompt"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], numPvContributors); } else { registry.fill(HIST("hSparseMassPrompt"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2]); } @@ -282,6 +316,8 @@ struct HfTaskDplus { registry.fill(HIST("hSparseMassFD"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], centrality, ptbhad, flagBHad); } else if (!storeCentrality && storeOccupancy) { registry.fill(HIST("hSparseMassFD"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], occupancy, ptbhad, flagBHad); + } else if (!storeCentrality && !storeOccupancy && storePvContributors) { + registry.fill(HIST("hSparseMassFD"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], numPvContributors); } else { registry.fill(HIST("hSparseMassFD"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], ptbhad, flagBHad); } @@ -294,6 +330,8 @@ struct HfTaskDplus { registry.fill(HIST("hSparseMassBkg"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], centrality); } else if (!storeCentrality && storeOccupancy) { registry.fill(HIST("hSparseMassBkg"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], occupancy); + } else if (!storeCentrality && !storeOccupancy && storePvContributors) { + registry.fill(HIST("hSparseMassBkg"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], numPvContributors); } else { registry.fill(HIST("hSparseMassBkg"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2]); } @@ -306,6 +344,8 @@ struct HfTaskDplus { registry.fill(HIST("hSparseMassNotMatched"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], centrality); } else if (!storeCentrality && storeOccupancy) { registry.fill(HIST("hSparseMassNotMatched"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], occupancy); + } else if (!storeCentrality && !storeOccupancy && storePvContributors) { + registry.fill(HIST("hSparseMassNotMatched"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], numPvContributors); } else { registry.fill(HIST("hSparseMassNotMatched"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2]); } @@ -317,6 +357,8 @@ struct HfTaskDplus { registry.fill(HIST("hSparseMass"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], centrality); } else if (!storeCentrality && storeOccupancy) { registry.fill(HIST("hSparseMass"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], occupancy); + } else if (!storeCentrality && !storeOccupancy && storePvContributors) { + registry.fill(HIST("hSparseMass"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2], numPvContributors); } else { registry.fill(HIST("hSparseMass"), hfHelper.invMassDplusToPiKPi(candidate), candidate.pt(), outputMl[0], outputMl[1], outputMl[2]); } @@ -398,12 +440,14 @@ struct HfTaskDplus { /// \param flagGenB transverse momentum of beauty mother for nonprompt candidates /// \param centrality collision centrality /// \param occupancy collision occupancy + /// \param numPvContributors contributors to the PV template void fillSparseMcGen(const T1& particle, float ptGenB, int flagGenB, float centrality, - float occupancy) + float occupancy, + float numPvContributors) { auto yGen = RecoDecay::y(particle.pVector(), o2::constants::physics::MassDPlus); if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { @@ -413,6 +457,8 @@ struct HfTaskDplus { registry.fill(HIST("hSparseMassGenPrompt"), particle.pt(), yGen, centrality); } else if (!storeCentrality && storeOccupancy) { registry.fill(HIST("hSparseMassGenPrompt"), particle.pt(), yGen, occupancy); + } else if (!storeCentrality && !storeOccupancy && storePvContributors) { + registry.fill(HIST("hSparseMassGenPrompt"), particle.pt(), yGen, numPvContributors); } else { registry.fill(HIST("hSparseMassGenPrompt"), particle.pt(), yGen); } @@ -423,6 +469,8 @@ struct HfTaskDplus { registry.fill(HIST("hSparseMassGenFD"), particle.pt(), yGen, centrality, ptGenB, flagGenB); } else if (!storeCentrality && storeOccupancy) { registry.fill(HIST("hSparseMassGenFD"), particle.pt(), yGen, occupancy, ptGenB, flagGenB); + } else if (!storeCentrality && !storeOccupancy && storePvContributors) { + registry.fill(HIST("hSparseMassGenFD"), particle.pt(), yGen, numPvContributors, ptGenB, flagGenB); } else { registry.fill(HIST("hSparseMassGenFD"), particle.pt(), yGen, ptGenB, flagGenB); } @@ -436,6 +484,7 @@ struct HfTaskDplus { { float cent{-1.f}; float occ{-1.f}; + float numPvContr{-1.f}; float ptBhad{-1.f}; int flagBHad{-1}; if constexpr (!fillMl) { @@ -459,10 +508,13 @@ struct HfTaskDplus { if (storeOccupancy && occEstimator != OccupancyEstimator::None) { occ = getOccupancyColl(collision, occEstimator); } + if (storePvContributors) { + numPvContr = collision.numContrib(); + } } fillHisto(candidate); - fillSparseML(candidate, ptBhad, flagBHad, cent, occ); + fillSparseML(candidate, ptBhad, flagBHad, cent, occ, numPvContr); } } } @@ -475,6 +527,7 @@ struct HfTaskDplus { { float cent{-1}; float occ{-1}; + float numPvContr{-1}; float ptBhad{-1}; int flagBHad{-1}; @@ -512,11 +565,14 @@ struct HfTaskDplus { if (storeOccupancy && occEstimator != OccupancyEstimator::None) { occ = getOccupancyColl(collision, occEstimator); } + if (storePvContributors) { + numPvContr = collision.numContrib(); + } } fillHisto(candidate); fillHistoMCRec(candidate); - fillSparseML(candidate, ptBhad, flagBHad, cent, occ); + fillSparseML(candidate, ptBhad, flagBHad, cent, occ, numPvContr); } // Bkg ptBhad = -1; @@ -533,8 +589,11 @@ struct HfTaskDplus { if (storeOccupancy && occEstimator != OccupancyEstimator::None) { occ = getOccupancyColl(collision, occEstimator); } + if (storePvContributors) { + numPvContr = collision.numContrib(); + } fillHistoMCRec(candidate); - fillSparseML(candidate, ptBhad, flagBHad, cent, occ); + fillSparseML(candidate, ptBhad, flagBHad, cent, occ, numPvContr); } } } @@ -552,6 +611,7 @@ struct HfTaskDplus { // MC gen. float cent{-1.}; float occ{-1.}; + float numPvContr{-1.}; float ptGenB{-1.}; int flagGenB{-1}; @@ -568,6 +628,7 @@ struct HfTaskDplus { for (const auto& particle : mcParticlesPerGenMcColl) { ptGenB = -1; flagGenB = -1; + numPvContr = -1; auto yGen = RecoDecay::y(particle.pVector(), o2::constants::physics::MassDPlus); if ((yCandGenMax >= 0. && std::abs(yGen) > yCandGenMax) || (std::abs(particle.flagMcMatchGen()) != hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi)) { continue; @@ -577,9 +638,12 @@ struct HfTaskDplus { flagGenB = getBHadMotherFlag(bHadMother.pdgCode()); ptGenB = bHadMother.pt(); } + for (const auto& recCol : mcRecoCollisions) { + numPvContr = std::max(numPvContr, recCol.numContrib()); + } fillHistoMCGen(particle); if constexpr (fillMl) { - fillSparseMcGen(particle, ptGenB, flagGenB, cent, occ); + fillSparseMcGen(particle, ptGenB, flagGenB, cent, occ, numPvContr); } } } diff --git a/PWGHF/D2H/Tasks/taskDs.cxx b/PWGHF/D2H/Tasks/taskDs.cxx index 2b94c93f6b8..2621b1e1163 100644 --- a/PWGHF/D2H/Tasks/taskDs.cxx +++ b/PWGHF/D2H/Tasks/taskDs.cxx @@ -17,32 +17,56 @@ /// \author Stefano Politanò , Politecnico & INFN Torino /// \author Fabrizio Chinu , Universita and INFN Torino -#include -#include -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "MetadataHelper.h" - -#include "PWGHF/Core/HfHelper.h" #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/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/Core/MetadataHelper.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#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 +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper enum FinalState { KKPi = 0, PiKK }; @@ -71,7 +95,7 @@ static std::unordered_map> channelsRe {Mother::Dplus, {{ResonantChannel::PhiPi, hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi}, {ResonantChannel::Kstar0K, hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToKstar0K}}}}}; template -concept hasDsMlInfo = requires(T candidate) { +concept HasDsMlInfo = requires(T candidate) { candidate.mlProbDsToKKPi(); candidate.mlProbDsToPiKK(); }; @@ -138,7 +162,7 @@ struct HfTaskDs { ConfigurableAxis axisMlScore0{"axisMlScore0", {100, 0., 1.}, "axis for ML output score 0"}; ConfigurableAxis axisMlScore1{"axisMlScore1", {100, 0., 1.}, "axis for ML output score 1"}; ConfigurableAxis axisMlScore2{"axisMlScore2", {100, 0., 1.}, "axis for ML output score 2"}; - ConfigurableAxis axisCentrality{"axisCentrality", {100, 0., 1.}, "axis for centrality/multiplicity"}; + ConfigurableAxis axisCentrality{"axisCentrality", {100, 0, 100}, "axis for centrality/multiplicity"}; ConfigurableAxis axisOccupancy{"axisOccupancy", {14, 0., 14000.}, "axis for occupancy"}; int mRunNumber{0}; @@ -183,7 +207,7 @@ struct HfTaskDs { AxisSpec flagBHad{axisFlagBHad, "B Hadron flag"}; AxisSpec ybins = {100, -5., 5, "#it{y}"}; AxisSpec massbins = {600, 1.67, 2.27, "inv. mass (KK#pi) (GeV/#it{c}^{2})"}; - AxisSpec centralitybins = {100, 0., 100., "Centrality"}; + AxisSpec centralitybins = {axisCentrality, "Centrality"}; AxisSpec npvcontributorsbins = {axisNPvContributors, "NPvContributors"}; AxisSpec mlscore0bins = {axisMlScore0, "Score 0"}; AxisSpec mlscore1bins = {axisMlScore1, "Score 1"}; @@ -444,7 +468,7 @@ struct HfTaskDs { /// \param candidate is candidate /// \param dataType is data class, as defined in DataType enum /// \param finalState is either KKPi or PiKK, as defined in FinalState enum - template + template void fillSparse(const Cand& candidate, DataType dataType, FinalState finalState) { auto mass = finalState == FinalState::KKPi ? hfHelper.invMassDsToKKPi(candidate) : hfHelper.invMassDsToPiKK(candidate); @@ -572,13 +596,10 @@ struct HfTaskDs { { int id = o2::constants::physics::Pdg::kDS; - auto yCand = hfHelper.yDs(candidate); if (dataType == DataType::McDplusPrompt || dataType == DataType::McDplusNonPrompt || dataType == DataType::McDplusBkg) { id = o2::constants::physics::Pdg::kDPlus; - yCand = hfHelper.yDplus(candidate); } else if (dataType == DataType::McLcBkg) { id = o2::constants::physics::Pdg::kLambdaCPlus; - yCand = hfHelper.yLc(candidate); } auto indexMother = RecoDecay::getMother(mcParticles, @@ -586,13 +607,14 @@ struct HfTaskDs { id, true); if (indexMother != -1) { - if (yCandRecoMax >= 0. && std::abs(yCand) > yCandRecoMax) { - return; - } auto pt = candidate.pt(); // rec. level pT if (candidate.isSelDsToKKPi() >= selectionFlagDs) { // KKPi + auto yCand = candidate.y(hfHelper.invMassDsToKKPi(candidate)); + if (yCandRecoMax >= 0. && std::abs(yCand) > yCandRecoMax) { + return; + } fillHisto(candidate, dataType); fillHistoKKPi(candidate, dataType); @@ -607,6 +629,10 @@ struct HfTaskDs { } } if (candidate.isSelDsToPiKK() >= selectionFlagDs) { // PiKK + auto yCand = candidate.y(hfHelper.invMassDsToPiKK(candidate)); + if (yCandRecoMax >= 0. && std::abs(yCand) > yCandRecoMax) { + return; + } fillHisto(candidate, dataType); fillHistoPiKK(candidate, dataType); @@ -627,15 +653,17 @@ struct HfTaskDs { template void runDataAnalysisPerCandidate(CandDs const& candidate) { - if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { - return; - } - if (candidate.isSelDsToKKPi() >= selectionFlagDs) { // KKPi + if (yCandRecoMax >= 0. && std::abs(candidate.y(hfHelper.invMassDsToKKPi(candidate))) > yCandRecoMax) { + return; + } fillHisto(candidate, DataType::Data); fillHistoKKPi(candidate, DataType::Data); } if (candidate.isSelDsToPiKK() >= selectionFlagDs) { // PiKK + if (yCandRecoMax >= 0. && std::abs(candidate.y(hfHelper.invMassDsToPiKK(candidate))) > yCandRecoMax) { + return; + } fillHisto(candidate, DataType::Data); fillHistoPiKK(candidate, DataType::Data); } @@ -663,16 +691,19 @@ struct HfTaskDs { } } if (isBkg && fillMcBkgHistos) { - if (yCandRecoMax >= 0. && std::abs(hfHelper.yDs(candidate)) > yCandRecoMax) { - return; - } if (candidate.isSelDsToKKPi() >= selectionFlagDs || candidate.isSelDsToPiKK() >= selectionFlagDs) { if (candidate.isSelDsToKKPi() >= selectionFlagDs) { // KKPi + if (yCandRecoMax >= 0. && std::abs(candidate.y(hfHelper.invMassDsToKKPi(candidate))) > yCandRecoMax) { + return; + } fillHisto(candidate, DataType::McBkg); fillHistoKKPi(candidate, DataType::McBkg); } if (candidate.isSelDsToPiKK() >= selectionFlagDs) { // PiKK + if (yCandRecoMax >= 0. && std::abs(candidate.y(hfHelper.invMassDsToPiKK(candidate))) > yCandRecoMax) { + return; + } fillHisto(candidate, DataType::McBkg); fillHistoPiKK(candidate, DataType::McBkg); } diff --git a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx index 0682c0584aa..801e25e3460 100644 --- a/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx +++ b/PWGHF/D2H/Tasks/taskDstarToD0Pi.cxx @@ -17,19 +17,35 @@ /// \brief Dstar production analysis task (With and Without ML) -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.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::analysis; using namespace o2::framework; @@ -39,12 +55,31 @@ using namespace o2::soa; /// Dstar analysis task struct HfTaskDstarToD0Pi { Configurable selectionFlagDstarToD0Pi{"selectionFlagDstarToD0Pi", true, "Selection Flag for D* decay to D0 & Pi"}; + Configurable isCentStudy{"isCentStudy", true, "Flag to select centrality study"}; + Configurable qaEnabled{"qaEnabled", true, "Flag to enable QA histograms"}; + + // 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 yCandDstarRecoMax{"yCandDstarRecoMax", 0.8, "max. candidate Dstar rapidity"}; Configurable yCandDstarGenMax{"yCandDstarGenMax", 0.5, "max. rapidity of Generator level Particle"}; Configurable selectionFlagHfD0ToPiK{"selectionFlagHfD0ToPiK", true, "Selection Flag for HF flagged candidates"}; Configurable> ptBins{"ptBins", std::vector{hf_cuts_dstar_to_d0_pi::vecBinsPt}, "pT bin limits for Dstar"}; + Configurable deltaMassMin{"deltaMassMin", 0.142, "Lower bound of the signal region for Delta Invariant MassDstar"}; + Configurable deltaMassMax{"deltaMassMax", 0.15, "Upper bound of the signal region for Delta Invariant MassDstar"}; + o2::ccdb::CcdbApi ccdbApi; SliceCache cache; + std::vector hWeights; + std::vector axesPtVsCentVsBDTVsPvContrib; + std::vector axesPtVsCentVsPvContrib; + std::vector axesPtVsBDT; using CandDstarWSelFlag = soa::Join; using CandDstarWSelFlagWMl = soa::Join; @@ -73,17 +108,9 @@ struct HfTaskDstarToD0Pi { ConfigurableAxis binningDeltaInvMass{"binningDeltaInvMass", {100, 0.13, 0.16}, "Bins of Delta InvMass of Dstar"}; 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"}; - HistogramRegistry registry{ - "registry", - {{"QA/hPtDstar", "Dstar Candidates; Dstar candidate #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, - {"QA/hPtD0", "D0 Candiades; D0 Candidate #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, - {"QA/hPtProng0D0", "Prong0 of D0 Candidates; Prong0 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, - {"QA/hPtProng1D0", "Prong1 of D0 Candidates; Prong1 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, - {"QA/hPtProng0D0Bar", "Prong0 of D0Bar Candidates; Prong0 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, - {"QA/hPtProng1D0Bar", "Prong1 of D0Bar Candidates; Prong1 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}}, - {"QA/hPtSoftPi", "Soft Pi ; Soft Pi #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{100, 0., 1.}}}}, - {"QA/hDeltaCentGen", "#{Delta}Cent % distribution of Collisions having same MC Collision;FT0M #{Delta}Cent %; Counts", {HistType::kTH1F, {{100, 0.0, 100.0}}}}}}; + HistogramRegistry registry{"registry", {}}; void init(InitContext&) { @@ -100,84 +127,173 @@ struct HfTaskDstarToD0Pi { AxisSpec axisBDTScorePrompt = {binningSigBDTScore, "BDT Score for Prompt Cand"}; AxisSpec axisBDTScoreNonPrompt = {binningSigBDTScore, "BDT Score for Non-Prompt Cand"}; AxisSpec axisBDTScoreBackground = {binningBkgBDTScore, "BDT Score for Background Cand"}; + AxisSpec axisPvContrib = {binningPvContrib, "PV Contribution"}; + AxisSpec axisPt = {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}; + + axesPtVsCentVsBDTVsPvContrib = {axisPt, axisCentrality, axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt, axisPvContrib}; + axesPtVsCentVsPvContrib = {axisPt, axisCentrality, axisPvContrib}; + axesPtVsBDT = {axisPt, axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt}; + + if (qaEnabled) { + // only QA + registry.add("QA/hPtDstar", "Dstar Candidates; Dstar candidate #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("QA/hPtD0", "D0 Candiades; D0 Candidate #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("QA/hPtProng0D0", "Prong0 of D0 Candidates; Prong0 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("QA/hPtProng1D0", "Prong1 of D0 Candidates; Prong1 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("QA/hPtProng0D0Bar", "Prong0 of D0Bar Candidates; Prong0 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("QA/hPtProng1D0Bar", "Prong1 of D0Bar Candidates; Prong1 #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{360, 0., 36.}}}); + registry.add("QA/hPtSoftPi", "Soft Pi ; Soft Pi #it{p}_{T} (GeV/#it{c}); entries", {HistType::kTH1F, {{100, 0., 1.}}}); + registry.add("QA/hDeltaCentGen", "#{Delta}Cent % distribution of Collisions having same MC Collision;FT0M #{Delta}Cent %; Counts", {HistType::kTH1F, {{100, 0.0, 100.0}}}); + + registry.add("QA/hEtaDstar", "D* Candidate; D* Candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hCtD0", "D0 Candidate; D0 Candidate's proper life time #it{c}#tau (cm) ; entries ", {HistType::kTH2F, {{1000, -0.1, 14.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hDecayLengthD0", "D0 Candidate; D0 Candidate's decay length (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hDecayLengthXYD0", "D0 Candidate; D0 Candidate's decay length xy (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hDecayLengthNormalisedD0", "D0 Candidates;Do Candidate's normalised decay length (cm); entries", {HistType::kTH2F, {axisNormDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hDecayLengthXYNormalisedD0", "D0 candidate; D0 Candidate's normalised decay length xy (cm); entries", {HistType::kTH2F, {axisNormDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hCPAD0", "D0 Candidates; D0 Candidate's cosine pointing angle; entries", {HistType::kTH2F, {{110, -1., 1.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hCPAxyD0", "D0 candidates; D0 Candidate's cosine of pointing angle xy; entries", {HistType::kTH2F, {{110, -1., 1.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hImpactParameterXYD0", "D0 Candidates; D0 Candidate's reconstructed impact parameter xy (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hDeltaIPMaxNormalisedD0", "D0 Candidate; D0 Candidate's Norm. Delta IP; entries", {HistType::kTH2F, {{1000, -20., 20.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hSqSumProngsImpactParameterD0", "D0 Candidates; Sqr Sum of Impact params of D0 Prongs; entries ", {HistType::kTH2F, {{1000, 0., 0.25}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hDecayLengthErrorD0", "D0 Candidates; D0 Candidate's Decay Length Error (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hDecayLengthXYErrorD0", "D0 Candidates; D0 Candidate's Decay Length Error XY (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hImpactParameterError", "D0 Prongs; Impact param error of different D0 Prongs (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hd0Prong0", "Prong0; DCAxy of Prong0 (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hd0Prong1", "Prong1; DCAxy of Prong1 (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hd0ProngSoftPi", "ProngSoftPi; DCAxy of Prong Soft Pi (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + + // MC Matching at Reconstruction Level Successful + registry.add("QA/hCPASkimD0RecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; cosine of pointing angle", {HistType::kTH1F, {{110, -1.1, 1.1}}}); + registry.add("QA/hEtaSkimD0RecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{#eta} of D0 Prong", {HistType::kTH1F, {{100, -2., 2.}}}); + registry.add("QA/hEtaSkimDstarRecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{#eta} of D* Candidate", {HistType::kTH1F, {{100, -2., 2.}}}); + + // pt vs y + registry.add("QA/hPtSkimDstarGenSig", "MC Matched Skimed D* Reconstructed Candidates at Generator Level; #it{p}_{T} of D* at Generator Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); + registry.add("QA/hPtVsCentSkimDstarGenSig", "MC Matched Skimed D* Reconstructed Candidates at Generator Level; #it{p}_{T} of D* at Generator Level (GeV/#it{c}); Centrality (%)", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); + registry.add("QA/hPtVsYSkimDstarRecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtVsYRecoTopolDstarRecSig", "MC Matched RecoTopol D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtVsYRecoPidDstarRecSig", "MC Matched RecoPid D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtFullRecoDstarRecSig", "MC Matched FullReco D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + + // Only Prompt RecSig + registry.add("QA/hPtVsYSkimPromptDstarRecSig", "MC Matched Skimed Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}; #it{y})", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtVsYRecoTopolPromptDstarRecSig", "MC Matched RecoTopol Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtVsYRecoPidPromptDstarRecSig", "MC Matched RecoPid Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtFullRecoPromptDstarRecSig", "MC Matched FullReco Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + // Only Non-Prompt RecSig + registry.add("QA/hPtVsYSkimNonPromptDstarRecSig", "MC Matched Skimed Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtVsYRecoTopolNonPromptDstarRecSig", "MC Matched RecoTopol Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtVsYRecoPidNonPromptDstarRecSig", "MC Matched RecoPid Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("QA/hPtFullRecoNonPromptDstarRecSig", "MC Matched FullReco Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + // MC Matching UnSuccessful + registry.add("QA/hCPASkimD0RecBg", "MC UnMatched Skimmed D0 Candidates at Reconstruction Level; cosine of pointing angle", {HistType::kTH1F, {{110, -1., 1.}}}); + registry.add("QA/hEtaSkimD0RecBg", "MC UnMatched Skimmed D0 Candidates at Reconstruction Level; #it{#eta} of D0 Prong", {HistType::kTH1F, {{100, -2., 2.}}}); + registry.add("QA/hEtaSkimDstarRecBg", "MC UnMatched Skimmed D* Candidates at Reconstruction Level; #it{#eta} of D* Candidate", {HistType::kTH1F, {{100, -2., 2.}}}); + // registry.add("QA/hPtSkimD0RecBg", "MC UnMatched Skimmed D0 Candidates at Reconstruction Level; #it{p}_{T} of D0", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + registry.add("QA/hPtSkimDstarRecBg", "MC UnMatched Skimmed D* Candidates at Reconstruction Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + + // MC Matching at Generator level Successful + registry.add("QA/hEtaDstarGen", "MC Matched D* Candidates at Generator Level; #it{#eta}", {HistType::kTH1F, {{100, -2., 2.}}}); + registry.add("QA/hPtDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); + } - registry.add("Yield/hDeltaInvMassDstar3D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c}); FT0M centrality", {HistType::kTH3F, {{axisDeltaInvMass}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); - registry.add("Yield/hDeltaInvMassDstar2D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{axisDeltaInvMass}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); registry.add("Yield/hDeltaInvMassDstar1D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2}); entries", {HistType::kTH1F, {{axisDeltaInvMass}}}, true); registry.add("Yield/hInvMassDstar", "#Delta #it{M}_{inv} D* Candidate; inv. mass (#pi #pi k) (GeV/#it{c}^{2}); entries", {HistType::kTH1F, {{500, 0., 5.0}}}, true); registry.add("Yield/hInvMassD0", "#it{M}_{inv}D^{0} candidate;#it{M}_{inv} D^{0} (GeV/#it{c});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{500, 0., 5.0}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); - // only QA - registry.add("QA/hEtaDstar", "D* Candidate; D* Candidate #it{#eta};entries", {HistType::kTH2F, {{100, -2., 2.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hCtD0", "D0 Candidate; D0 Candidate's proper life time #it{c}#tau (cm) ; entries ", {HistType::kTH2F, {{1000, -0.1, 14.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hDecayLengthD0", "D0 Candidate; D0 Candidate's decay length (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hDecayLengthXYD0", "D0 Candidate; D0 Candidate's decay length xy (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hDecayLengthNormalisedD0", "D0 Candidates;Do Candidate's normalised decay length (cm); entries", {HistType::kTH2F, {axisNormDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hDecayLengthXYNormalisedD0", "D0 candidate; D0 Candidate's normalised decay length xy (cm); entries", {HistType::kTH2F, {axisNormDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hCPAD0", "D0 Candidates; D0 Candidate's cosine pointing angle; entries", {HistType::kTH2F, {{110, -1., 1.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hCPAxyD0", "D0 candidates; D0 Candidate's cosine of pointing angle xy; entries", {HistType::kTH2F, {{110, -1., 1.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hImpactParameterXYD0", "D0 Candidates; D0 Candidate's reconstructed impact parameter xy (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hDeltaIPMaxNormalisedD0", "D0 Candidate; D0 Candidate's Norm. Delta IP; entries", {HistType::kTH2F, {{1000, -20., 20.}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hSqSumProngsImpactParameterD0", "D0 Candidates; Sqr Sum of Impact params of D0 Prongs; entries ", {HistType::kTH2F, {{1000, 0., 0.25}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hDecayLengthErrorD0", "D0 Candidates; D0 Candidate's Decay Length Error (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hDecayLengthXYErrorD0", "D0 Candidates; D0 Candidate's Decay Length Error XY (cm); entries", {HistType::kTH2F, {axisDecayLength, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hImpactParameterError", "D0 Prongs; Impact param error of different D0 Prongs (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hd0Prong0", "Prong0; DCAxy of Prong0 (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hd0Prong1", "Prong1; DCAxy of Prong1 (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hd0ProngSoftPi", "ProngSoftPi; DCAxy of Prong Soft Pi (cm); entries", {HistType::kTH2F, {axisImpactParam, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - // MC Matching at Reconstruction Level Successful - registry.add("QA/hCPASkimD0RecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; cosine of pointing angle", {HistType::kTH1F, {{110, -1.1, 1.1}}}); - registry.add("QA/hEtaSkimD0RecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{#eta} of D0 Prong", {HistType::kTH1F, {{100, -2., 2.}}}); - registry.add("QA/hEtaSkimDstarRecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{#eta} of D* Candidate", {HistType::kTH1F, {{100, -2., 2.}}}); + + // BDT Score (axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt) + if (doprocessDataWML) { + registry.add("Yield/hDeltaInvMassVsPtVsCentVsBDTScore", "#Delta #it{M}_{inv} Vs Pt Vs Cent Vs BDTScore", {HistType::kTHnSparseF, {{axisDeltaInvMass}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}, {axisBDTScoreBackground}, {axisBDTScorePrompt}, {axisBDTScoreNonPrompt}}}, true); + } else if (doprocessDataWoML) { + registry.add("Yield/hDeltaInvMassDstar2D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {{axisDeltaInvMass}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); + registry.add("Yield/hDeltaInvMassDstar3D", "#Delta #it{M}_{inv} D* Candidate; inv. mass ((#pi #pi k) - (#pi k)) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c}); FT0M centrality", {HistType::kTH3F, {{axisDeltaInvMass}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); + } + // pt vs y - registry.add("QA/hPtSkimDstarGenSig", "MC Matched Skimed D* Reconstructed Candidates at Generator Level; #it{p}_{T} of D* at Generator Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}, true); - registry.add("Efficiency/hPtVsCentSkimDstarGenSig", "MC Matched Skimed D* Reconstructed Candidates at Generator Level; #it{p}_{T} of D* at Generator Level (GeV/#it{c}); Centrality (%)", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); - registry.add("QA/hPtVsYSkimDstarRecSig", "MC Matched Skimed D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtVsYRecoTopolDstarRecSig", "MC Matched RecoTopol D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtVsYRecoPidDstarRecSig", "MC Matched RecoPid D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtFullRecoDstarRecSig", "MC Matched FullReco D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Efficiency/hPtVsCentFullRecoDstarRecSig", "MC Matched FullReco D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); Centrality (%)", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); - // Only Prompt RecSig - registry.add("QA/hPtVsYSkimPromptDstarRecSig", "MC Matched Skimed Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}; #it{y})", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtVsYRecoTopolPromptDstarRecSig", "MC Matched RecoTopol Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtVsYRecoPidPromptDstarRecSig", "MC Matched RecoPid Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtFullRecoPromptDstarRecSig", "MC Matched FullReco Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - // Only Non-Prompt RecSig - registry.add("QA/hPtVsYSkimNonPromptDstarRecSig", "MC Matched Skimed Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtVsYRecoTopolNonPromptDstarRecSig", "MC Matched RecoTopol Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtVsYRecoPidNonPromptDstarRecSig", "MC Matched RecoPid Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c}); #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); - registry.add("QA/hPtFullRecoNonPromptDstarRecSig", "MC Matched FullReco Non-Prompt D* Candidates at Reconstruction Level; #it{p}_{T} of D* at Reconstruction Level (GeV/#it{c})", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - // MC Matching UnSuccessful - registry.add("QA/hCPASkimD0RecBg", "MC UnMatched Skimmed D0 Candidates at Reconstruction Level; cosine of pointing angle", {HistType::kTH1F, {{110, -1., 1.}}}); - registry.add("QA/hEtaSkimD0RecBg", "MC UnMatched Skimmed D0 Candidates at Reconstruction Level; #it{#eta} of D0 Prong", {HistType::kTH1F, {{100, -2., 2.}}}); - registry.add("QA/hEtaSkimDstarRecBg", "MC UnMatched Skimmed D* Candidates at Reconstruction Level; #it{#eta} of D* Candidate", {HistType::kTH1F, {{100, -2., 2.}}}); - registry.add("QA/hPtSkimD0RecBg", "MC UnMatched Skimmed D0 Candidates at Reconstruction Level; #it{p}_{T} of D0", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hPtSkimDstarRecBg", "MC UnMatched Skimmed D* Candidates at Reconstruction Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - // MC Matching at Generator level Successful - registry.add("QA/hEtaDstarGen", "MC Matched D* Candidates at Generator Level; #it{#eta}", {HistType::kTH1F, {{100, -2., 2.}}}); - registry.add("QA/hPtDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("Efficiency/hPtVsCentDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*;Centrality (%) ", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}}}, true); - registry.add("QA/hPtVsYDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*; #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + registry.add("Efficiency/hPtVsYDstarGen", "MC Matched D* Candidates at Generator Level; #it{p}_{T} of D*; #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}, true); // Prompt Gen - registry.add("QA/hPtPromptDstarGen", "MC Matched Prompt D* Candidates at Generator Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hPtVsYPromptDstarGen", "MC Matched 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.}}}); + registry.add("Efficiency/hPtVsYPromptDstarGen", "MC Matched 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); // Non Prmpt Gen - registry.add("QA/hPtNonPromptDstarGen", "MC Matched Non-Prompt D* Candidates at Generator Level; #it{p}_{T} of D*", {HistType::kTH1F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}}}); - registry.add("QA/hPtVsYNonPromptDstarGen", "MC Matched Non-Prompt D* Candidates at Generator Level; #it{p}_{T} of D*; #it{y}", {HistType::kTH2F, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {100, -5., 5.}}}); + 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 - registry.add("Efficiency/hNumPvContributorsAll", "PV Contributors; PV Contributor; FT0M Centrality", {HistType::kTH2F, {{100, 0, 300}, {axisCentrality}}}, true); - registry.add("Efficiency/hNumPvContributorsCand", "PV Contributors; PV Contributor; FT0M Centrality", {HistType::kTH2F, {{100, 0, 300}, {axisCentrality}}}, true); - registry.add("Efficiency/hNumPvContributorsCandInMass", "PV Contributors; PV Contributor; FT0M Centrality", {HistType::kTH2F, {{100, 0, 300}, {axisCentrality}}}, true); + // Checking PV contributors from Data as well MC rec for calculation 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); + registry.add("Efficiency/hNumPvContributorsCandInMass", "PV Contributors; PV Contributor; FT0M Centrality", {HistType::kTH2F, {{axisPvContrib}, {axisCentrality}}}, true); + } - // BDT Score (axisBDTScoreBackground, axisBDTScorePrompt, axisBDTScoreNonPrompt) - if (doprocessDataWML) { - registry.add("Yield/hDeltaInvMassVsPtVsCentVsBDTScore", "#Delta #it{M}_{inv} Vs Pt Vs Cent Vs BDTScore", {HistType::kTHnSparseF, {{axisDeltaInvMass}, {vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}, {axisBDTScoreBackground}, {axisBDTScorePrompt}, {axisBDTScoreNonPrompt}}}); + // Hists at Reco level W/O ML usefull for efficiency calculation + if (doprocessMcWoMl && isCentStudy) { + 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); + } 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); } - if (doprocessMcWML) { - registry.add("Efficiency/hPtVsCentVsBDTScore", "Pt Vs Cent Vs BDTScore", {HistType::kTHnSparseF, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}, {axisBDTScoreBackground}, {axisBDTScorePrompt}, {axisBDTScoreNonPrompt}}}); - registry.add("Efficiency/hPtPromptVsCentVsBDTScore", "Pt Vs Cent Vs BDTScore", {HistType::kTHnSparseF, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}, {axisBDTScoreBackground}, {axisBDTScorePrompt}, {axisBDTScoreNonPrompt}}}); - registry.add("Efficiency/hPtNonPromptVsCentVsBDTScore", "Pt Vs Cent Vs BDTScore", {HistType::kTHnSparseF, {{vecPtBins, "#it{p}_{T} (GeV/#it{c})"}, {axisCentrality}, {axisBDTScoreBackground}, {axisBDTScorePrompt}, {axisBDTScoreNonPrompt}}}); + + // Hists at Reco level W/ ML usefull for efficiency calculation + if (doprocessMcWML && isCentStudy) { + 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); // 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); + } + + // Hists at Gen level usefull for efficiency calculation + if (doprocessMcWoMl || doprocessMcWML) { + if (isCentStudy) { + 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); + } 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 weights to be applied + if (useWeight) { + ccdbApi.init(ccdbUrl); + std::map metadata; + // Retrieve the file from CCDB + bool isFileAvailable = ccdbApi.retrieveBlob(ccdbPathForWeight, ".", metadata, timestampCCDB, false, weightFileName); + if (!isFileAvailable) { + LOGF(fatal, "Failed to retrieve weight file from CCDB: %s", ccdbPathForWeight.value.c_str()); + return; + } + + if (isCentStudy) { + // Open the ROOT file + TFile* weightFile = TFile::Open(weightFileName.value.c_str(), "READ"); + if (weightFile && !weightFile->IsZombie()) { + // Ensure hWeights is properly sized + hWeights.resize(nWeights); + for (int ithWeight = 0; ithWeight < nWeights; ++ithWeight) { + std::string histName = "hMult" + std::to_string(ithWeight + 1) + "_Weight"; + hWeights[ithWeight] = reinterpret_cast(weightFile->Get(histName.c_str())); + if (!hWeights[ithWeight]) { + LOGF(fatal, "Histogram %s not found in weight file!", histName.c_str()); + return; + } + hWeights[ithWeight]->SetDirectory(0); + 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()); + return; + } + } } } @@ -207,7 +323,6 @@ struct HfTaskDstarToD0Pi { auto nCandsCurrentCol = selectedCandsCurrentCol.size(); if (nCandsCurrentCol > 0) { - // LOGF(debug, "size of selectedCandsCurrentCol: %d", nCandsCurrentCol); registry.fill(HIST("Efficiency/hNumPvContributorsCand"), nPVContributors, centrality); } @@ -218,28 +333,30 @@ struct HfTaskDstarToD0Pi { continue; } - registry.fill(HIST("QA/hPtDstar"), candDstar.pt()); - registry.fill(HIST("QA/hPtD0"), candDstar.ptD0()); - registry.fill(HIST("QA/hPtSoftPi"), candDstar.ptSoftPi()); - registry.fill(HIST("QA/hEtaDstar"), candDstar.eta(), candDstar.pt()); - registry.fill(HIST("QA/hCtD0"), candDstar.ctD0(), candDstar.pt()); - registry.fill(HIST("QA/hDecayLengthD0"), candDstar.decayLengthD0(), candDstar.pt()); - registry.fill(HIST("QA/hDecayLengthXYD0"), candDstar.decayLengthXYD0(), candDstar.pt()); - registry.fill(HIST("QA/hDecayLengthNormalisedD0"), candDstar.decayLengthNormalisedD0(), candDstar.pt()); - registry.fill(HIST("QA/hDecayLengthXYNormalisedD0"), candDstar.decayLengthXYNormalisedD0(), candDstar.pt()); - registry.fill(HIST("QA/hCPAD0"), candDstar.cpaD0(), candDstar.pt()); - registry.fill(HIST("QA/hCPAxyD0"), candDstar.cpaXYD0(), candDstar.pt()); - registry.fill(HIST("QA/hImpactParameterXYD0"), candDstar.impactParameterXYD0(), candDstar.pt()); - registry.fill(HIST("QA/hDeltaIPMaxNormalisedD0"), candDstar.deltaIPNormalisedMaxD0(), candDstar.pt()); - registry.fill(HIST("QA/hSqSumProngsImpactParameterD0"), candDstar.impactParameterProngSqSumD0(), candDstar.pt()); - registry.fill(HIST("QA/hDecayLengthErrorD0"), candDstar.errorDecayLengthD0(), candDstar.pt()); - registry.fill(HIST("QA/hDecayLengthXYErrorD0"), candDstar.errorDecayLengthXYD0(), candDstar.pt()); - registry.fill(HIST("QA/hImpactParameterError"), candDstar.errorImpactParameter0(), candDstar.pt()); - registry.fill(HIST("QA/hImpactParameterError"), candDstar.errorImpactParameter1(), candDstar.pt()); - registry.fill(HIST("QA/hImpactParameterError"), candDstar.errorImpParamSoftPi(), candDstar.pt()); - registry.fill(HIST("QA/hd0Prong0"), candDstar.impactParameter0(), candDstar.pt()); - registry.fill(HIST("QA/hd0Prong1"), candDstar.impactParameter1(), candDstar.pt()); - registry.fill(HIST("QA/hd0ProngSoftPi"), candDstar.impParamSoftPi(), candDstar.pt()); + if (qaEnabled) { + registry.fill(HIST("QA/hPtDstar"), candDstar.pt()); + registry.fill(HIST("QA/hPtD0"), candDstar.ptD0()); + registry.fill(HIST("QA/hPtSoftPi"), candDstar.ptSoftPi()); + registry.fill(HIST("QA/hEtaDstar"), candDstar.eta(), candDstar.pt()); + registry.fill(HIST("QA/hCtD0"), candDstar.ctD0(), candDstar.pt()); + registry.fill(HIST("QA/hDecayLengthD0"), candDstar.decayLengthD0(), candDstar.pt()); + registry.fill(HIST("QA/hDecayLengthXYD0"), candDstar.decayLengthXYD0(), candDstar.pt()); + registry.fill(HIST("QA/hDecayLengthNormalisedD0"), candDstar.decayLengthNormalisedD0(), candDstar.pt()); + registry.fill(HIST("QA/hDecayLengthXYNormalisedD0"), candDstar.decayLengthXYNormalisedD0(), candDstar.pt()); + registry.fill(HIST("QA/hCPAD0"), candDstar.cpaD0(), candDstar.pt()); + registry.fill(HIST("QA/hCPAxyD0"), candDstar.cpaXYD0(), candDstar.pt()); + registry.fill(HIST("QA/hImpactParameterXYD0"), candDstar.impactParameterXYD0(), candDstar.pt()); + registry.fill(HIST("QA/hDeltaIPMaxNormalisedD0"), candDstar.deltaIPNormalisedMaxD0(), candDstar.pt()); + registry.fill(HIST("QA/hSqSumProngsImpactParameterD0"), candDstar.impactParameterProngSqSumD0(), candDstar.pt()); + registry.fill(HIST("QA/hDecayLengthErrorD0"), candDstar.errorDecayLengthD0(), candDstar.pt()); + registry.fill(HIST("QA/hDecayLengthXYErrorD0"), candDstar.errorDecayLengthXYD0(), candDstar.pt()); + registry.fill(HIST("QA/hImpactParameterError"), candDstar.errorImpactParameter0(), candDstar.pt()); + registry.fill(HIST("QA/hImpactParameterError"), candDstar.errorImpactParameter1(), candDstar.pt()); + registry.fill(HIST("QA/hImpactParameterError"), candDstar.errorImpParamSoftPi(), candDstar.pt()); + registry.fill(HIST("QA/hd0Prong0"), candDstar.impactParameter0(), candDstar.pt()); + registry.fill(HIST("QA/hd0Prong1"), candDstar.impactParameter1(), candDstar.pt()); + registry.fill(HIST("QA/hd0ProngSoftPi"), candDstar.impParamSoftPi(), candDstar.pt()); + } auto invDstar = candDstar.invMassDstar(); auto invAntiDstar = candDstar.invMassAntiDstar(); @@ -249,7 +366,7 @@ struct HfTaskDstarToD0Pi { auto signDstar = candDstar.signSoftPi(); if (signDstar > 0) { auto deltaMDstar = std::abs(invDstar - invD0); - if (0.142f < deltaMDstar && deltaMDstar < 0.15f) { + if (deltaMassMin < deltaMDstar && deltaMDstar < deltaMassMax) { nCandsSignalRegion++; } @@ -258,17 +375,21 @@ struct HfTaskDstarToD0Pi { registry.fill(HIST("Yield/hDeltaInvMassVsPtVsCentVsBDTScore"), deltaMDstar, candDstar.pt(), centrality, mlBdtScore[0], mlBdtScore[1], mlBdtScore[2]); } - registry.fill(HIST("Yield/hDeltaInvMassDstar3D"), deltaMDstar, candDstar.pt(), centrality); - registry.fill(HIST("Yield/hDeltaInvMassDstar2D"), deltaMDstar, candDstar.pt()); + if (doprocessDataWoML) { + registry.fill(HIST("Yield/hDeltaInvMassDstar3D"), deltaMDstar, candDstar.pt(), centrality); + registry.fill(HIST("Yield/hDeltaInvMassDstar2D"), deltaMDstar, candDstar.pt()); + } registry.fill(HIST("Yield/hInvMassD0"), invD0, candDstar.ptD0()); registry.fill(HIST("Yield/hDeltaInvMassDstar1D"), deltaMDstar); registry.fill(HIST("Yield/hInvMassDstar"), invDstar); // filling pt of two pronges of D0 - registry.fill(HIST("QA/hPtProng0D0"), candDstar.ptProng0()); - registry.fill(HIST("QA/hPtProng1D0"), candDstar.ptProng1()); + if (qaEnabled) { + registry.fill(HIST("QA/hPtProng0D0"), candDstar.ptProng0()); + registry.fill(HIST("QA/hPtProng1D0"), candDstar.ptProng1()); + } } else if (signDstar < 0) { auto deltaMAntiDstar = std::abs(invAntiDstar - invD0Bar); - if (0.142f < deltaMAntiDstar && deltaMAntiDstar < 0.15f) { + if (deltaMassMin < deltaMAntiDstar && deltaMAntiDstar < deltaMassMax) { nCandsSignalRegion++; } @@ -277,14 +398,19 @@ struct HfTaskDstarToD0Pi { registry.fill(HIST("Yield/hDeltaInvMassVsPtVsCentVsBDTScore"), deltaMAntiDstar, candDstar.pt(), centrality, mlBdtScore[0], mlBdtScore[1], mlBdtScore[2]); } - registry.fill(HIST("Yield/hDeltaInvMassDstar3D"), deltaMAntiDstar, candDstar.pt(), centrality); - registry.fill(HIST("Yield/hDeltaInvMassDstar2D"), deltaMAntiDstar, candDstar.pt()); + if (doprocessDataWoML) { + registry.fill(HIST("Yield/hDeltaInvMassDstar3D"), deltaMAntiDstar, candDstar.pt(), centrality); + registry.fill(HIST("Yield/hDeltaInvMassDstar2D"), deltaMAntiDstar, candDstar.pt()); + } + registry.fill(HIST("Yield/hInvMassD0"), invD0Bar, candDstar.ptD0()); registry.fill(HIST("Yield/hDeltaInvMassDstar1D"), deltaMAntiDstar); registry.fill(HIST("Yield/hInvMassDstar"), invAntiDstar); // filling pt of two pronges of D0Bar - registry.fill(HIST("QA/hPtProng0D0Bar"), candDstar.ptProng0()); - registry.fill(HIST("QA/hPtProng1D0Bar"), candDstar.ptProng1()); + if (qaEnabled) { + registry.fill(HIST("QA/hPtProng0D0Bar"), candDstar.ptProng0()); + registry.fill(HIST("QA/hPtProng1D0Bar"), candDstar.ptProng1()); + } } } // candidate loop for current collision ends @@ -302,11 +428,9 @@ struct HfTaskDstarToD0Pi { template void runMcRecTaskDstar(T1 const& candsMcRecSel, CandDstarMcGen const& rowsMcPartilces) { - // LOGF(info, "Running MC Rec Task Dstar"); int8_t signDstar = 0; // MC at Reconstruction level for (const auto& candDstarMcRec : candsMcRecSel) { - // LOGF(info, "MC Rec Dstar loop"); auto ptDstarRecSig = candDstarMcRec.pt(); auto yDstarRecSig = candDstarMcRec.y(constants::physics::MassDStar); if (yCandDstarRecoMax >= 0. && std::abs(yDstarRecSig) > yCandDstarRecoMax) { @@ -314,72 +438,115 @@ struct HfTaskDstarToD0Pi { } auto collision = candDstarMcRec.template collision_as(); auto centrality = collision.centFT0M(); // 0-100% + auto nPVContributors = collision.numContrib(); // number of PV contributors if (std::abs(candDstarMcRec.flagMcMatchRec()) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { // if MC matching is successful at Reconstruction Level - // LOGF(info, "MC Rec Dstar loop MC Matched"); // get MC Mother particle 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? - registry.fill(HIST("QA/hPtSkimDstarGenSig"), particleMother.pt()); // generator level pt - registry.fill(HIST("Efficiency/hPtVsCentSkimDstarGenSig"), particleMother.pt(), 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); - } - if (candDstarMcRec.isRecoPid()) { // if PID selection is passed - registry.fill(HIST("QA/hPtVsYRecoPidDstarRecSig"), ptDstarRecSig, yDstarRecSig); - } - if (candDstarMcRec.isSelDstarToD0Pi()) { // if all selection passed - registry.fill(HIST("QA/hPtFullRecoDstarRecSig"), ptDstarRecSig); - registry.fill(HIST("Efficiency/hPtVsCentFullRecoDstarRecSig"), ptDstarRecSig, centrality); - if constexpr (applyMl) { - auto bdtScore = candDstarMcRec.mlProbDstarToD0Pi(); - registry.fill(HIST("Efficiency/hPtVsCentVsBDTScore"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2]); - } - } - registry.fill(HIST("QA/hCPASkimD0RecSig"), candDstarMcRec.cpaD0()); - registry.fill(HIST("QA/hEtaSkimD0RecSig"), candDstarMcRec.etaD0()); - registry.fill(HIST("QA/hEtaSkimDstarRecSig"), candDstarMcRec.eta()); - - // only prompt signal at reconstruction level - if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("QA/hPtVsYSkimPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); // Skimed at level of trackIndexSkimCreator - if (candDstarMcRec.isRecoTopol()) { // if Topological selection are passed - registry.fill(HIST("QA/hPtVsYRecoTopolPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + auto particleMother = rowsMcPartilces.rawIteratorAt(indexMother); // What is difference between rawIterator() or iteratorAt() methods? + if (qaEnabled) { + registry.fill(HIST("QA/hPtSkimDstarGenSig"), particleMother.pt()); // generator level pt + registry.fill(HIST("QA/hPtVsCentSkimDstarGenSig"), particleMother.pt(), 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); } if (candDstarMcRec.isRecoPid()) { // if PID selection is passed - registry.fill(HIST("QA/hPtVsYRecoPidPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + registry.fill(HIST("QA/hPtVsYRecoPidDstarRecSig"), ptDstarRecSig, yDstarRecSig); } - if (candDstarMcRec.isSelDstarToD0Pi()) { // if all selection passed - registry.fill(HIST("QA/hPtFullRecoPromptDstarRecSig"), ptDstarRecSig); - if constexpr (applyMl) { - auto bdtScore = candDstarMcRec.mlProbDstarToD0Pi(); - registry.fill(HIST("Efficiency/hPtPromptVsCentVsBDTScore"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2]); + } + + if (candDstarMcRec.isSelDstarToD0Pi()) { // if all selection passed + float weightValue = 1.0; + if (useWeight && (hWeights.size() < 1 || hWeights[0] == nullptr)) { + LOGF(fatal, "Weight histograms are not initialized or empty. Check CCDB path or weight file."); + return; + } else 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; + } } } - } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { // only non-prompt signal at reconstruction level - registry.fill(HIST("QA/hPtVsYSkimNonPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); - if (candDstarMcRec.isRecoTopol()) { // if Topological selection are passed - registry.fill(HIST("QA/hPtVsYRecoTopolNonPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); - } - if (candDstarMcRec.isRecoPid()) { // if PID selection is passed - registry.fill(HIST("QA/hPtVsYRecoPidNonPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + if (qaEnabled) { + registry.fill(HIST("QA/hPtFullRecoDstarRecSig"), ptDstarRecSig); } - if (candDstarMcRec.isSelDstarToD0Pi()) { // if all selection passed - registry.fill(HIST("QA/hPtFullRecoNonPromptDstarRecSig"), ptDstarRecSig); - if constexpr (applyMl) { + + if constexpr (applyMl) { // All efficiency histograms at reconstruction level w/ ml + if (isCentStudy) { + 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); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/hPtNonPrompRectVsCentVsBDTScorePvContribRecSig"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2], nPVContributors, weightValue); + } + } else { auto bdtScore = candDstarMcRec.mlProbDstarToD0Pi(); - registry.fill(HIST("Efficiency/hPtNonPromptVsCentVsBDTScore"), ptDstarRecSig, centrality, bdtScore[0], bdtScore[1], bdtScore[2]); + 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); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/hPtNonPromptVsBDTScoreRecSig"), ptDstarRecSig, bdtScore[0], bdtScore[1], bdtScore[2], weightValue); + } + } + } 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); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/hPtNonPromptVsCentVsPvContribRecSig"), ptDstarRecSig, centrality, nPVContributors, weightValue); + } + } else { + registry.fill(HIST("Efficiency/hPtVsPvContribRecSig"), ptDstarRecSig, nPVContributors, weightValue); + if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("Efficiency/hPtPromptVsPvContribRecSig"), ptDstarRecSig, nPVContributors, weightValue); + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/hPtNonPromptVsPvContribRecSig"), ptDstarRecSig, nPVContributors, weightValue); + } + } + } + } + if (qaEnabled) { + registry.fill(HIST("QA/hCPASkimD0RecSig"), candDstarMcRec.cpaD0()); + registry.fill(HIST("QA/hEtaSkimD0RecSig"), candDstarMcRec.etaD0()); + registry.fill(HIST("QA/hEtaSkimDstarRecSig"), candDstarMcRec.eta()); + + // only prompt signal at reconstruction level + if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("QA/hPtVsYSkimPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); // Skimed at level of trackIndexSkimCreator + if (candDstarMcRec.isRecoTopol()) { // if Topological selection are passed + registry.fill(HIST("QA/hPtVsYRecoTopolPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + } + if (candDstarMcRec.isRecoPid()) { // if PID selection is passed + registry.fill(HIST("QA/hPtVsYRecoPidPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + } + if (candDstarMcRec.isSelDstarToD0Pi()) { // if all selection passed + registry.fill(HIST("QA/hPtFullRecoPromptDstarRecSig"), ptDstarRecSig); + } + } else if (candDstarMcRec.originMcRec() == RecoDecay::OriginType::NonPrompt) { // only non-prompt signal at reconstruction level + registry.fill(HIST("QA/hPtVsYSkimNonPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + if (candDstarMcRec.isRecoTopol()) { // if Topological selection are passed + registry.fill(HIST("QA/hPtVsYRecoTopolNonPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + } + if (candDstarMcRec.isRecoPid()) { // if PID selection is passed + registry.fill(HIST("QA/hPtVsYRecoPidNonPromptDstarRecSig"), ptDstarRecSig, yDstarRecSig); + } + if (candDstarMcRec.isSelDstarToD0Pi()) { // if all selection passed + registry.fill(HIST("QA/hPtFullRecoNonPromptDstarRecSig"), ptDstarRecSig); } } } } else { // MC Unmatched (Baground at Reconstruction Level) - registry.fill(HIST("QA/hCPASkimD0RecBg"), candDstarMcRec.cpaD0()); - registry.fill(HIST("QA/hEtaSkimD0RecBg"), candDstarMcRec.etaD0()); - registry.fill(HIST("QA/hEtaSkimDstarRecBg"), candDstarMcRec.eta()); - if (candDstarMcRec.isSelDstarToD0Pi()) { - registry.fill(HIST("QA/hPtSkimDstarRecBg"), candDstarMcRec.pt()); + if (qaEnabled) { + registry.fill(HIST("QA/hCPASkimD0RecBg"), candDstarMcRec.cpaD0()); + registry.fill(HIST("QA/hEtaSkimD0RecBg"), candDstarMcRec.etaD0()); + registry.fill(HIST("QA/hEtaSkimDstarRecBg"), candDstarMcRec.eta()); + if (candDstarMcRec.isSelDstarToD0Pi()) { + registry.fill(HIST("QA/hPtSkimDstarRecBg"), candDstarMcRec.pt()); + } } } } // candidate loop ends @@ -398,16 +565,24 @@ struct HfTaskDstarToD0Pi { if (yCandDstarGenMax >= 0. && std::abs(yGen) > yCandDstarGenMax) { continue; } + auto mcCollision = mcParticle.template mcCollision_as(); auto recCollisions = collisions.sliceBy(colsPerMcCollision, mcCollision.globalIndex()); - // looking if a generated collision reconstructed more than a times. - if (recCollisions.size() > 1) { - for (const auto& [c1, c2] : combinations(CombinationsStrictlyUpperIndexPolicy(recCollisions, recCollisions))) { - auto deltaCent = std::abs(c1.centFT0M() - c2.centFT0M()); - registry.fill(HIST("QA/hDeltaCentGen"), deltaCent); + if (qaEnabled) { + registry.fill(HIST("QA/hEtaDstarGen"), mcParticle.eta()); + registry.fill(HIST("QA/hPtDstarGen"), ptGen); + + // looking if a generated collision reconstructed more than a times. + if (recCollisions.size() > 1) { + for (const auto& [c1, c2] : combinations(CombinationsStrictlyUpperIndexPolicy(recCollisions, recCollisions))) { + auto deltaCent = std::abs(c1.centFT0M() - c2.centFT0M()); + registry.fill(HIST("QA/hDeltaCentGen"), deltaCent); + } } } + float centFT0MGen; + float pvContributors; // assigning centrality to MC Collision using max FT0M amplitute from Reconstructed collisions if (recCollisions.size()) { std::vector::iterator, int>> tempRecCols; @@ -416,20 +591,49 @@ struct HfTaskDstarToD0Pi { } std::sort(tempRecCols.begin(), tempRecCols.end(), compare); centFT0MGen = tempRecCols.at(0).first.centFT0M(); + pvContributors = tempRecCols.at(0).second; } else { centFT0MGen = -999.; + pvContributors = -999.; } - registry.fill(HIST("QA/hEtaDstarGen"), mcParticle.eta()); - registry.fill(HIST("QA/hPtDstarGen"), ptGen); - registry.fill(HIST("QA/hPtVsYDstarGen"), ptGen, yGen); - registry.fill(HIST("Efficiency/hPtVsCentDstarGen"), ptGen, centFT0MGen); - // only promt Dstar candidate at Generator level + + float weightValue = 1.0; + if (useWeight && (hWeights.size() < 1 || hWeights[0] == nullptr)) { + LOGF(fatal, "Weight histograms are not initialized or empty. Check CCDB path or weight file."); + return; + } else 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; + } + } + } + + registry.fill(HIST("Efficiency/hPtVsYDstarGen"), ptGen, yGen, weightValue); + if (isCentStudy) { + registry.fill(HIST("Efficiency/hPtVsCentVsPvContribGen"), ptGen, centFT0MGen, pvContributors, weightValue); + } else { + registry.fill(HIST("Efficiency/hPtGen"), ptGen, weightValue); + } + + // Prompt if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("QA/hPtPromptDstarGen"), ptGen); - registry.fill(HIST("QA/hPtVsYPromptDstarGen"), ptGen, yGen); - } else if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { // only non-prompt Dstar candidate at Generator level - registry.fill(HIST("QA/hPtNonPromptDstarGen"), ptGen); - registry.fill(HIST("QA/hPtVsYNonPromptDstarGen"), ptGen, yGen); + registry.fill(HIST("Efficiency/hPtVsYPromptDstarGen"), ptGen, yGen, weightValue); + if (isCentStudy) { + registry.fill(HIST("Efficiency/hPtPromptVsCentVsPvContribGen"), ptGen, centFT0MGen, pvContributors, weightValue); + } else { + registry.fill(HIST("Efficiency/hPtPromptVsGen"), ptGen, weightValue); + } + // Non-Prompt + } else if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { + registry.fill(HIST("Efficiency/hPtVsYNonPromptDstarGen"), ptGen, yGen, weightValue); + if (isCentStudy) { + registry.fill(HIST("Efficiency/hPtNonPromptVsCentVsPvContribGen"), ptGen, centFT0MGen, pvContributors, weightValue); + + } else { + registry.fill(HIST("Efficiency/hPtNonPromptVsGen"), ptGen, weightValue); + } } } } // MC Particle loop ends diff --git a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx index 862b4910c72..7960aeb7f4f 100644 --- a/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx +++ b/PWGHF/D2H/Tasks/taskFlowCharmHadrons.cxx @@ -14,23 +14,43 @@ /// /// \author S. Politanò, INFN Torino, Italy /// \author Wu Chuntai, CUG, China +/// \author Ran Tu, Fudan University, China +/// \author Marcello Di Costanzo , Polytechnic University of Turin and INFN -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#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/Core/EventPlaneHelper.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Qvectors.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsEvSelHf.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; @@ -40,6 +60,23 @@ using namespace o2::hf_centrality; using namespace o2::hf_occupancy; using namespace o2::hf_evsel; +namespace o2::aod +{ +namespace full +{ +DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) +DECLARE_SOA_COLUMN(Pt, pt, float); //! Transverse momentum of candidate (GeV/c) +// 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(HfCandPtCent, "AOD", "HFCANDPTCENT", + full::M, + full::Pt, + full::MlScore0, + full::MlScore1); +} // namespace o2::aod + enum DecayChannel { DplusToPiKPi = 0, DsToKKPi, DsToPiKK, @@ -48,7 +85,8 @@ enum DecayChannel { DplusToPiKPi = 0, LcToPKPi, LcToPiKP, XicToPKPi, - XicToPiKP + XicToPiKP, + Xic0ToXiPi }; enum QvecEstimator { FV0A = 0, @@ -60,6 +98,8 @@ enum QvecEstimator { FV0A = 0, TPCTot }; struct HfTaskFlowCharmHadrons { + Produces rowCandidateMassPtMlScores; + 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)"}; @@ -68,6 +108,9 @@ struct HfTaskFlowCharmHadrons { Configurable centralityMax{"centralityMax", 100., "Maximum centrality accepted in SP/EP computation (not applied in resolution process)"}; Configurable storeEP{"storeEP", false, "Flag to store EP-related axis"}; Configurable storeMl{"storeMl", false, "Flag to store ML scores"}; + Configurable fillMassPtMlTree{"fillMassPtMlTree", false, "Flag to fill mass and pt tree"}; + Configurable downSampleFactor{"downSampleFactor", 1., "Fraction of candidates to keep in TTree"}; + Configurable ptDownSampleMax{"ptDownSampleMax", 10., "Maximum pt for the application of the downsampling factor"}; Configurable storeResoOccu{"storeResoOccu", false, "Flag to store Occupancy in resolution ThnSparse"}; Configurable storeEpCosSin{"storeEpCosSin", false, "Flag to store cos and sin of EP angle in ThnSparse"}; Configurable occEstimator{"occEstimator", 0, "Occupancy estimation (0: None, 1: ITS, 2: FT0C)"}; @@ -75,25 +118,11 @@ struct HfTaskFlowCharmHadrons { Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable> classMl{"classMl", {0, 2}, "Indexes of BDT scores to be stored. Two indexes max."}; - ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {100, 1.78, 2.05}, ""}; - ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {10, 0., 10.}, ""}; - ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {10000, 0., 100.}, ""}; - ConfigurableAxis thnConfigAxisCosNPhi{"thnConfigAxisCosNPhi", {100, -1., 1.}, ""}; - ConfigurableAxis thnConfigAxisPsi{"thnConfigAxisPsi", {6000, 2. * TMath::Pi(), 2. * TMath::Pi()}, ""}; - ConfigurableAxis thnConfigAxisCosDeltaPhi{"thnConfigAxisCosDeltaPhi", {100, -1., 1.}, ""}; - ConfigurableAxis thnConfigAxisScalarProd{"thnConfigAxisScalarProd", {100, 0., 1.}, ""}; - ConfigurableAxis thnConfigAxisMlOne{"thnConfigAxisMlOne", {1000, 0., 1.}, ""}; - ConfigurableAxis thnConfigAxisMlTwo{"thnConfigAxisMlTwo", {1000, 0., 1.}, ""}; - ConfigurableAxis thnConfigAxisOccupancyITS{"thnConfigAxisOccupancyITS", {14, 0, 14000}, ""}; - ConfigurableAxis thnConfigAxisOccupancyFT0C{"thnConfigAxisOccupancyFT0C", {14, 0, 140000}, ""}; - ConfigurableAxis thnConfigAxisNoSameBunchPileup{"thnConfigAxisNoSameBunchPileup", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisNoCollInTimeRangeNarrow{"thnConfigAxisNoCollInTimeRangeNarrow", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisNoCollInTimeRangeStandard{"thnConfigAxisNoCollInTimeRangeStandard", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisNoCollInRofStandard{"thnConfigAxisNoCollInRofStandard", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisResoFT0cFV0a{"thnConfigAxisResoFT0cFV0a", {160, -8, 8}, ""}; - ConfigurableAxis thnConfigAxisResoFT0cTPCtot{"thnConfigAxisResoFT0cTPCtot", {160, -8, 8}, ""}; - ConfigurableAxis thnConfigAxisResoFV0aTPCtot{"thnConfigAxisResoFV0aTPCtot", {160, -8, 8}, ""}; + HfHelper hfHelper; + EventPlaneHelper epHelper; + HfEventSelection hfEvSel; // event selection and monitoring + o2::framework::Service ccdb; + SliceCache cache; using CandDsDataWMl = soa::Filtered>; using CandDsData = soa::Filtered>; @@ -103,6 +132,8 @@ struct HfTaskFlowCharmHadrons { using CandLcDataWMl = soa::Filtered>; using CandXicData = soa::Filtered>; using CandXicDataWMl = soa::Filtered>; + using CandXic0Data = soa::Filtered>; + using CandXic0DataWMl = soa::Filtered>; using CandD0DataWMl = soa::Filtered>; using CandD0Data = soa::Filtered>; using CollsWithQvecs = soa::Join; @@ -112,6 +143,7 @@ struct HfTaskFlowCharmHadrons { 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 || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlag; Filter filterSelectXicCandidates = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag || aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; + Filter filterSelectXic0Candidates = aod::hf_sel_toxipi::resultSelections == true; Partition selectedDsToKKPi = aod::hf_sel_candidate_ds::isSelDsToKKPi >= selectionFlag; Partition selectedDsToPiKK = aod::hf_sel_candidate_ds::isSelDsToPiKK >= selectionFlag; @@ -129,12 +161,28 @@ struct HfTaskFlowCharmHadrons { Partition selectedXicToPiKP = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; Partition selectedXicToPKPiWMl = aod::hf_sel_candidate_xic::isSelXicToPKPi >= selectionFlag; Partition selectedXicToPiKPWMl = aod::hf_sel_candidate_xic::isSelXicToPiKP >= selectionFlag; + Partition selectedXic0 = aod::hf_sel_toxipi::resultSelections == true; + Partition selectedXic0WMl = aod::hf_sel_toxipi::resultSelections == true; - SliceCache cache; - HfHelper hfHelper; - EventPlaneHelper epHelper; - HfEventSelection hfEvSel; // event selection and monitoring - o2::framework::Service ccdb; + ConfigurableAxis thnConfigAxisInvMass{"thnConfigAxisInvMass", {100, 1.78, 2.05}, ""}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {10, 0., 10.}, ""}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {10000, 0., 100.}, ""}; + ConfigurableAxis thnConfigAxisCosNPhi{"thnConfigAxisCosNPhi", {100, -1., 1.}, ""}; + ConfigurableAxis thnConfigAxisPsi{"thnConfigAxisPsi", {6000, 0, constants::math::TwoPI}, ""}; + ConfigurableAxis thnConfigAxisCosDeltaPhi{"thnConfigAxisCosDeltaPhi", {100, -1., 1.}, ""}; + ConfigurableAxis thnConfigAxisScalarProd{"thnConfigAxisScalarProd", {100, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisMlOne{"thnConfigAxisMlOne", {1000, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisMlTwo{"thnConfigAxisMlTwo", {1000, 0., 1.}, ""}; + ConfigurableAxis thnConfigAxisOccupancyITS{"thnConfigAxisOccupancyITS", {14, 0, 14000}, ""}; + ConfigurableAxis thnConfigAxisOccupancyFT0C{"thnConfigAxisOccupancyFT0C", {14, 0, 140000}, ""}; + ConfigurableAxis thnConfigAxisNoSameBunchPileup{"thnConfigAxisNoSameBunchPileup", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisOccupancy{"thnConfigAxisOccupancy", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisNoCollInTimeRangeNarrow{"thnConfigAxisNoCollInTimeRangeNarrow", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisNoCollInTimeRangeStandard{"thnConfigAxisNoCollInTimeRangeStandard", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisNoCollInRofStandard{"thnConfigAxisNoCollInRofStandard", {2, 0, 2}, ""}; + ConfigurableAxis thnConfigAxisResoFT0cFV0a{"thnConfigAxisResoFT0cFV0a", {160, -8, 8}, ""}; + ConfigurableAxis thnConfigAxisResoFT0cTPCtot{"thnConfigAxisResoFT0cTPCtot", {160, -8, 8}, ""}; + ConfigurableAxis thnConfigAxisResoFV0aTPCtot{"thnConfigAxisResoFV0aTPCtot", {160, -8, 8}, ""}; HistogramRegistry registry{"registry", {}}; @@ -231,15 +279,15 @@ struct HfTaskFlowCharmHadrons { } if (storeResoOccu) { - std::vector axes_reso = {thnAxisCent, thnAxisResoFT0cFV0a, thnAxisResoFT0cTPCtot, thnAxisResoFV0aTPCtot}; + std::vector axesReso = {thnAxisCent, thnAxisResoFT0cFV0a, thnAxisResoFT0cTPCtot, thnAxisResoFV0aTPCtot}; if (occEstimator == 1) { - axes_reso.insert(axes_reso.end(), {thnAxisOccupancyITS, thnAxisNoSameBunchPileup, thnAxisOccupancy, - thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); + axesReso.insert(axesReso.end(), {thnAxisOccupancyITS, thnAxisNoSameBunchPileup, thnAxisOccupancy, + thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); } else { - axes_reso.insert(axes_reso.end(), {thnAxisOccupancyFT0C, thnAxisNoSameBunchPileup, thnAxisOccupancy, - thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); + axesReso.insert(axesReso.end(), {thnAxisOccupancyFT0C, thnAxisNoSameBunchPileup, thnAxisOccupancy, + thnAxisNoCollInTimeRangeNarrow, thnAxisNoCollInTimeRangeStandard, thnAxisNoCollInRofStandard}); } - registry.add("spReso/hSparseReso", "THn for resolution with occupancy", HistType::kTHnSparseF, axes_reso); + registry.add("spReso/hSparseReso", "THn for resolution with occupancy", HistType::kTHnSparseF, axesReso); } hfEvSel.addHistograms(registry); // collision monitoring @@ -249,6 +297,20 @@ struct HfTaskFlowCharmHadrons { } }; // end init + /// Fill the mass, pt and ML scores of a candidate + /// \param mass is the candidate mass + /// \param pt is the candidate transverse momentum + /// \param mlscore0 is the first ML score + /// \param mlscore1 is the second ML score + void fillMassPt(const float mass, const float pt, const float mlscore0, const float mlscore1) + { + rowCandidateMassPtMlScores( + mass, + pt, + mlscore0, + mlscore1); + } + /// Compute the Q vector for the candidate's tracks /// \param cand is the candidate /// \param tracksQx is the X component of the Q vector for the tracks @@ -285,6 +347,44 @@ struct HfTaskFlowCharmHadrons { } } + /// Compute the Q vector for the candidate's tracks + /// \param cand is the candidate + /// \param tracksQx is the X component of the Q vector for the tracks + /// \param tracksQy is the Y component of the Q vector for the tracks + /// \param channel is the decay channel + template + void getQvecXic0Tracks(const T1& cand, + std::vector& tracksQx, + std::vector& tracksQy, + float ampl) + { + // add possibility to consider different weights for the tracks, at the moment only pT is considered; + float pXTrack0 = cand.pxPosV0Dau(); + float pYTrack0 = cand.pyPosV0Dau(); + float pTTrack0 = std::hypot(pXTrack0, pYTrack0); + float phiTrack0 = std::atan2(pXTrack0, pYTrack0); + float pXTrack1 = cand.pxNegV0Dau(); + float pYTrack1 = cand.pyNegV0Dau(); + float pTTrack1 = std::hypot(pXTrack1, pYTrack1); + float phiTrack1 = std::atan2(pXTrack1, pYTrack1); + float pYTrack2 = cand.pxBachFromCasc(); + float pXTrack2 = cand.pyBachFromCasc(); + float pTTrack2 = std::hypot(pXTrack2, pYTrack2); + float phiTrack2 = std::atan2(pXTrack2, pYTrack2); + float pXTrack3 = cand.pxBachFromCharmBaryon(); + float pYTrack3 = cand.pyBachFromCharmBaryon(); + float pTTrack3 = std::hypot(pXTrack3, pYTrack3); + float phiTrack3 = std::atan2(pXTrack3, pYTrack3); + + tracksQx.push_back(std::cos(harmonic * phiTrack0) * pTTrack0 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack0) * pTTrack0 / ampl); + tracksQx.push_back(std::cos(harmonic * phiTrack1) * pTTrack1 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack1) * pTTrack1 / ampl); + tracksQx.push_back(std::cos(harmonic * phiTrack2) * pTTrack2 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack2) * pTTrack2 / ampl); + tracksQx.push_back(std::cos(harmonic * phiTrack3) * pTTrack3 / ampl); + tracksQy.push_back(std::sin(harmonic * phiTrack3) * pTTrack3 / ampl); + } /// Compute the delta psi in the range [0, pi/harmonic] /// \param psi1 is the first angle /// \param psi2 is the second angle @@ -292,18 +392,13 @@ struct HfTaskFlowCharmHadrons { float getDeltaPsiInRange(float psi1, float psi2) { float deltaPsi = psi1 - psi2; - if (std::abs(deltaPsi) > constants::math::PI / harmonic) { - if (deltaPsi > 0.) - deltaPsi -= constants::math::TwoPI / harmonic; - else - deltaPsi += constants::math::TwoPI / harmonic; - } + deltaPsi = RecoDecay::constrainAngle(deltaPsi, -o2::constants::math::PI / harmonic, harmonic); return deltaPsi; } /// Get the event selection flags /// \param hfevselflag is the event selection flag - std::vector getEventSelectionFlags(uint16_t hfevselflag) + std::vector getEventSelectionFlags(uint32_t hfevselflag) { return { TESTBIT(hfevselflag, o2::hf_evsel::EventRejection::NoSameBunchPileup), @@ -333,7 +428,7 @@ struct HfTaskFlowCharmHadrons { float& sp, std::vector& outputMl, float& occupancy, - uint16_t& hfevselflag) + uint32_t& hfevselflag) { if (occEstimator != 0) { std::vector evtSelFlags = getEventSelectionFlags(hfevselflag); @@ -451,7 +546,7 @@ struct HfTaskFlowCharmHadrons { return; } float occupancy = 0.; - uint16_t hfevflag{}; + uint32_t hfevflag{}; if (occEstimator != 0) { occupancy = getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); @@ -552,18 +647,36 @@ struct HfTaskFlowCharmHadrons { default: break; } + } else if constexpr (std::is_same_v || std::is_same_v) { + massCand = candidate.invMassCharmBaryon(); + if constexpr (std::is_same_v) { + for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) + outputMl[iclass] = candidate.mlProbToXiPi()[classMl->at(iclass)]; + } } - float ptCand = candidate.pt(); - float phiCand = candidate.phi(); + float ptCand = 0.; + float phiCand = 0.; + + if constexpr (std::is_same_v || std::is_same_v) { + ptCand = RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + phiCand = std::atan2(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + } else { + ptCand = candidate.pt(); + phiCand = candidate.phi(); + } // If TPC is used for the SP estimation, the tracks of the hadron candidate must be removed from the TPC Q vector to avoid double counting if (qvecDetector == QvecEstimator::TPCNeg || qvecDetector == QvecEstimator::TPCPos) { float ampl = amplQVec - static_cast(nProngs); std::vector tracksQx = {}; std::vector tracksQy = {}; - - getQvecDtracks(candidate, tracksQx, tracksQy, ampl); + if constexpr (std::is_same_v || std::is_same_v) { + // std::cout<(candidate, tracksQx, tracksQy, ampl); + } for (auto iTrack{0u}; iTrack < tracksQx.size(); ++iTrack) { xQVec -= tracksQx[iTrack]; yQVec -= tracksQy[iTrack]; @@ -575,7 +688,17 @@ struct HfTaskFlowCharmHadrons { float scalprodCand = cosNPhi * xQVec + sinNPhi * yQVec; float cosDeltaPhi = std::cos(harmonic * (phiCand - evtPl)); - fillThn(massCand, ptCand, cent, cosNPhi, sinNPhi, cosDeltaPhi, scalprodCand, outputMl, occupancy, hfevflag); + if (fillMassPtMlTree && storeMl) { + if (downSampleFactor < 1.) { + float pseudoRndm = ptCand * 1000. - static_cast(ptCand * 1000); + if (ptCand < ptDownSampleMax && pseudoRndm >= downSampleFactor) { + continue; + } + } + fillMassPt(massCand, ptCand, outputMl[0], outputMl[1]); + } else { + fillThn(massCand, ptCand, cent, cosNPhi, sinNPhi, cosDeltaPhi, scalprodCand, outputMl, occupancy, hfevflag); + } } } @@ -683,6 +806,24 @@ struct HfTaskFlowCharmHadrons { } PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic, "Process Xic candidates", false); + // Xic0 with ML + void processXic0Ml(CollsWithQvecs::iterator const& collision, + CandXic0DataWMl const&) + { + auto candsXic0WMl = selectedXic0WMl->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + runFlowAnalysis(collision, candsXic0WMl); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic0Ml, "Process Xic0 candidates with ML", false); + + // Xic0 + void processXic0(CollsWithQvecs::iterator const& collision, + CandXic0Data const&) + { + auto candsXic0 = selectedXic0->sliceByCached(aod::hf_cand::collisionId, collision.globalIndex(), cache); + runFlowAnalysis(collision, candsXic0); + } + PROCESS_SWITCH(HfTaskFlowCharmHadrons, processXic0, "Process Xic0 candidates", false); + // Resolution void processResolution(CollsWithQvecs::iterator const& collision, aod::BCsWithTimestamps const& bcs) @@ -708,7 +849,7 @@ struct HfTaskFlowCharmHadrons { float occupancy{-1.f}; occupancy = getOccupancyColl(collision, occEstimator); registry.fill(HIST("trackOccVsFT0COcc"), collision.trackOccupancyInTimeRange(), collision.ft0cOccupancyInTimeRange()); - uint16_t hfevflag = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t hfevflag = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); std::vector evtSelFlags = getEventSelectionFlags(hfevflag); registry.fill(HIST("spReso/hSparseReso"), centrality, xQVecFT0c * xQVecFV0a + yQVecFT0c * yQVecFV0a, xQVecFT0c * xQVecBTot + yQVecFT0c * yQVecBTot, diff --git a/PWGHF/D2H/Tasks/taskLb.cxx b/PWGHF/D2H/Tasks/taskLb.cxx index e934a37b554..3272db196b3 100644 --- a/PWGHF/D2H/Tasks/taskLb.cxx +++ b/PWGHF/D2H/Tasks/taskLb.cxx @@ -15,29 +15,44 @@ /// \author Panos Christakoglou , Nikhef /// \author Martin Voelkl , University of Birmingham -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Common/DataModel/Centrality.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.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 + using namespace o2; using namespace o2::aod; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; - -#include "Framework/runDataProcessing.h" +using namespace o2::hf_decay::hf_cand_beauty; /// Λb0 analysis task struct HfTaskLb { @@ -334,9 +349,9 @@ struct HfTaskLb { continue; } auto candLc = candidate.prong0_as>(); - int flagMcMatchRecLb = std::abs(candidate.flagMcMatchRec()); + auto flagMcMatchRecLb = std::abs(candidate.flagMcMatchRec()); - if (TESTBIT(flagMcMatchRecLb, hf_cand_lb::DecayType::LbToLcPi)) { + if (flagMcMatchRecLb == DecayChannelMain::LbToLcPi) { auto indexMother = RecoDecay::getMother(mcParticles, candidate.prong1_as().mcParticle_as>(), o2::constants::physics::Pdg::kLambdaB0, true); auto particleMother = mcParticles.rawIteratorAt(indexMother); @@ -383,7 +398,7 @@ struct HfTaskLb { // MC gen. level for (const auto& particle : mcParticles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << hf_cand_lb::DecayType::LbToLcPi) { + if (std::abs(particle.flagMcMatchGen()) == DecayChannelMain::LbToLcPi) { auto yParticle = RecoDecay::y(particle.pVector(), o2::constants::physics::MassLambdaB0); if (yCandGenMax >= 0. && std::abs(yParticle) > yCandGenMax) { diff --git a/PWGHF/D2H/Tasks/taskLbReduced.cxx b/PWGHF/D2H/Tasks/taskLbReduced.cxx index 6ca71f85a55..f756d9abc62 100644 --- a/PWGHF/D2H/Tasks/taskLbReduced.cxx +++ b/PWGHF/D2H/Tasks/taskLbReduced.cxx @@ -14,16 +14,31 @@ /// /// \author Biao Zhang , Heidelberg University -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/RecoDecay.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" + +#include "Common/Core/RecoDecay.h" + +#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/PWGHF/D2H/Tasks/taskLc.cxx b/PWGHF/D2H/Tasks/taskLc.cxx index cf3c070e6b7..85eee1bb213 100644 --- a/PWGHF/D2H/Tasks/taskLc.cxx +++ b/PWGHF/D2H/Tasks/taskLc.cxx @@ -18,20 +18,36 @@ /// \author Annalena Kalteyer , GSI Darmstadt /// \author Biao Zhang , Heidelberg University -#include // std::vector - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsEvSelHf.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 +#include +#include // std::vector + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx index 5b379e9e759..f107452344a 100644 --- a/PWGHF/D2H/Tasks/taskLcToK0sP.cxx +++ b/PWGHF/D2H/Tasks/taskLcToK0sP.cxx @@ -17,17 +17,26 @@ /// /// \note based on taskD0.cxx, taskLc.cxx -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -257,17 +266,9 @@ struct HfTaskLcToK0sP { TracksWPid const&) { for (const auto& candidate : candidates) { - /* - // no such selection for LcK0sp for now - it is the only cascade - if (!(candidate.hfflag() & 1 << D0ToPiK)) { - continue; - } - */ - if (etaCandMax >= 0. && std::abs(candidate.eta()) > etaCandMax) { continue; } - if (yCandRecoMax >= 0. && std::abs(hfHelper.yLc(candidate)) > yCandRecoMax) { continue; } diff --git a/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx b/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx index 2550d41c386..a611d7e166a 100644 --- a/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx +++ b/PWGHF/D2H/Tasks/taskOmegac0ToOmegapi.cxx @@ -14,31 +14,64 @@ /// \author Yunfan Liu , China University of Geosciences /// \author Fabio Catalano , University of Houston -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsEvSelHf.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 +#include +#include +#include using namespace o2; using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; +namespace o2::aod +{ +namespace ml +{ +// collision info +DECLARE_SOA_COLUMN(KfptPiFromOmegac, kfptPiFromOmegac, float); +DECLARE_SOA_COLUMN(KfptOmegac, kfptOmegac, float); +DECLARE_SOA_COLUMN(InvMassCharmBaryon, invMassCharmBaryon, float); +DECLARE_SOA_COLUMN(MlProbOmegac, mlProbOmegac, float); +DECLARE_SOA_COLUMN(Cent, cent, float); +} // namespace ml +DECLARE_SOA_TABLE(HfKfOmegacML, "AOD", "HFKFOMEGACML", + ml::InvMassCharmBaryon, ml::KfptOmegac, ml::KfptPiFromOmegac, ml::MlProbOmegac, ml::Cent); +} // namespace o2::aod + /// Omegac0 analysis task struct HfTaskOmegac0ToOmegapi { + + Produces kfCandMl; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; Configurable fillCent{"fillCent", false, "Flag to fill centrality information"}; + Configurable fillTree{"fillTree", false, "Fill TTree for local analysis.(Enabled only with ML)"}; Configurable selectionFlagOmegac0{"selectionFlagOmegac0", true, "Select Omegac0 candidates"}; Configurable yCandGenMax{"yCandGenMax", 0.5, "max. gen particle rapidity"}; Configurable yCandRecoMax{"yCandRecoMax", 0.8, "max. cand. rapidity"}; @@ -88,9 +121,18 @@ struct HfTaskOmegac0ToOmegapi { void init(InitContext&) { - std::array doprocess{doprocessDataWithKFParticle, doprocessMcWithKFParticle, doprocessDataWithKFParticleMl, doprocessMcWithKFParticleMl, doprocessDataWithKFParticleFT0C, doprocessDataWithKFParticleMlFT0C, doprocessDataWithKFParticleFT0M, doprocessDataWithKFParticleMlFT0M}; - if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { - LOGP(fatal, "One and only one process function should be enabled at a time."); + std::array doprocess{doprocessDataWithKFParticle, doprocessDataWithKFParticleMl, doprocessDataWithKFParticleFT0C, doprocessDataWithKFParticleMlFT0C, doprocessDataWithKFParticleFT0M, doprocessDataWithKFParticleMlFT0M}; + if (std::accumulate(doprocess.begin(), doprocess.end(), 0) > 1) { + LOGP(fatal, "At most one data process function should be enabled at a time."); + } + + std::array doprocessMc{doprocessMcWithKFParticle, doprocessMcWithKFParticleMl}; + if (std::accumulate(doprocessMc.begin(), doprocessMc.end(), 0) > 1) { + LOGP(fatal, "At most one MC process function should be enabled at a time."); + } + + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0) + std::accumulate(doprocessMc.begin(), doprocessMc.end(), 0)) == 0) { + LOGP(fatal, "At least one process function should be enabled."); } const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (#Omega#pi) (GeV/#it{c}^{2})"}; @@ -186,14 +228,22 @@ struct HfTaskOmegac0ToOmegapi { } float cent = evaluateCentralityColl(collision); if constexpr (applyMl) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), - candidate.mlProbOmegac()[0], - candidate.invMassCharmBaryon(), - candidate.ptCharmBaryon(), - candidate.kfRapOmegac(), - cent, - candidate.kfptPiFromOmegac(), - numPvContributors); + if (fillTree) { + kfCandMl(candidate.invMassCharmBaryon(), + candidate.ptCharmBaryon(), + candidate.kfptPiFromOmegac(), + candidate.mlProbOmegac()[0], + cent); + } else { + registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), + candidate.mlProbOmegac()[0], + candidate.invMassCharmBaryon(), + candidate.ptCharmBaryon(), + candidate.kfRapOmegac(), + cent, + candidate.kfptPiFromOmegac(), + numPvContributors); + } } else { registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), candidate.invMassCharmBaryon(), @@ -226,10 +276,10 @@ struct HfTaskOmegac0ToOmegapi { auto numPvContributors = candidate.template collision_as().numContrib(); if constexpr (applyMl) { - registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), candidate.mlProbOmegac()[0], candidate.invMassCharmBaryon(), candidate.ptCharmBaryon(), candidate.kfRapOmegac(), candidate.ptBhadMotherPart(), candidate.originRec(), candidate.flagMcMatchRec(), numPvContributors); + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), candidate.mlProbOmegac()[0], candidate.invMassCharmBaryon(), candidate.ptCharmBaryon(), candidate.kfRapOmegac(), candidate.ptBhadMotherPart(), candidate.originMcRec(), candidate.flagMcMatchRec(), numPvContributors); } else { - registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), candidate.invMassCharmBaryon(), candidate.ptCharmBaryon(), candidate.kfRapOmegac(), candidate.ptBhadMotherPart(), candidate.originRec(), candidate.flagMcMatchRec(), numPvContributors); + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsOmegac0Type"), candidate.invMassCharmBaryon(), candidate.ptCharmBaryon(), candidate.kfRapOmegac(), candidate.ptBhadMotherPart(), candidate.originMcRec(), candidate.flagMcMatchRec(), numPvContributors); } } @@ -248,7 +298,7 @@ struct HfTaskOmegac0ToOmegapi { maxNumContrib = recCol.numContrib() > maxNumContrib ? recCol.numContrib() : maxNumContrib; } - if (particle.originGen() == RecoDecay::OriginType::Prompt) { + if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hSparseAcc"), ptGen, -1., yGen, RecoDecay::OriginType::Prompt, maxNumContrib); } else { float ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); diff --git a/PWGHF/D2H/Tasks/taskSigmac.cxx b/PWGHF/D2H/Tasks/taskSigmac.cxx index dff39af4c28..b14d0640c88 100644 --- a/PWGHF/D2H/Tasks/taskSigmac.cxx +++ b/PWGHF/D2H/Tasks/taskSigmac.cxx @@ -15,17 +15,36 @@ /// /// \author Mattia Faggin , University and INFN PADOVA -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.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 + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -42,6 +61,7 @@ struct HfTaskSigmac { 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"}; HfHelper hfHelper; bool isMc; @@ -61,24 +81,7 @@ struct HfTaskSigmac { ConfigurableAxis configAxisDeltaMassSigmaC{"configAxisDeltaMassSigmaC", {200, 0.13, 0.23}, ""}; ConfigurableAxis thnConfigAxisBdtScoreLcBkg{"thnConfigAxisBdtScoreLcBkg", {100, 0., 1.}, ""}; ConfigurableAxis thnConfigAxisBdtScoreLcNonPrompt{"thnConfigAxisBdtScoreLcNonPrompt", {100, 0., 1.}, ""}; - const AxisSpec thnAxisMassLambdaC{configAxisMassLambdaC, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; - const AxisSpec thnAxisPtLambdaC{thnConfigAxisPt, "#it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})"}; - const AxisSpec thnAxisPtSigmaC{thnConfigAxisPt, "#it{p}_{T}(#Sigma_{c}^{0,++}) (GeV/#it{c})"}; - const AxisSpec thnAxisDecLength{thnConfigAxisDecLength, "decay length #Lambda_{c}^{+} (cm)"}; - const AxisSpec thnAxisDecLengthXY{thnConfigAxisDecLengthXY, "decay length XY #Lambda_{c}^{+} (cm)"}; - const AxisSpec thnAxisCPA{thnConfigAxisCPA, "cosine of pointing angle #Lambda_{c}^{+}"}; - const AxisSpec thnAxisCPAXY{thnConfigAxisCPAXY, "cosine of pointing angle XY #Lambda_{c}^{+}"}; - const AxisSpec thnAxisOriginMc{3, -0.5, 2.5, "0: none, 1: prompt, 2: non-prompt"}; - const AxisSpec thnAxisChargeSigmaC{3, -0.5, 2.5, "#Sigma_{c}-baryon charge"}; - const AxisSpec thnAxisChannel{4, -0.5, 3.5, "0: direct 1,2,3: resonant"}; - const AxisSpec thnAxisBdtScoreLcBkg{thnConfigAxisBdtScoreLcBkg, "BDT bkg score (Lc)"}; - const AxisSpec thnAxisBdtScoreLcNonPrompt{thnConfigAxisBdtScoreLcNonPrompt, "BDT non-prompt score (Lc)"}; - const AxisSpec thnAxisGenPtLambdaC{thnConfigAxisGenPt, "#it{p}_{T}^{gen}(#Lambda_{c}^{+}) (GeV/#it{c})"}; - const AxisSpec thnAxisGenPtSigmaC{thnConfigAxisGenPt, "#it{p}_{T}^{gen}(#Sigma_{c}^{0,++}) (GeV/#it{c})"}; - const AxisSpec thnAxisGenPtLambdaCBMother{thnConfigAxisGenPtB, "#it{p}_{T}^{gen}(#Lambda_{c}^{+} B mother) (GeV/#it{c})"}; - const AxisSpec thnAxisGenPtSigmaCBMother{thnConfigAxisGenPtB, "#it{p}_{T}^{gen}(#Sigma_{c}^{0,++} B mother) (GeV/#it{c})"}; - 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"}; + ConfigurableAxis thnConfigAxisSoftPiAbsDca{"thnConfigAxisSoftPiAbsDca", {14, 0., 0.07}, ""}; /// analysis histograms HistogramRegistry registry{ @@ -154,6 +157,26 @@ struct HfTaskSigmac { isMc = false; } + const AxisSpec thnAxisMassLambdaC{configAxisMassLambdaC, "inv. mass (p K #pi) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPtLambdaC{thnConfigAxisPt, "#it{p}_{T}(#Lambda_{c}^{+}) (GeV/#it{c})"}; + const AxisSpec thnAxisPtSigmaC{thnConfigAxisPt, "#it{p}_{T}(#Sigma_{c}^{0,++}) (GeV/#it{c})"}; + const AxisSpec thnAxisDecLength{thnConfigAxisDecLength, "decay length #Lambda_{c}^{+} (cm)"}; + const AxisSpec thnAxisDecLengthXY{thnConfigAxisDecLengthXY, "decay length XY #Lambda_{c}^{+} (cm)"}; + const AxisSpec thnAxisCPA{thnConfigAxisCPA, "cosine of pointing angle #Lambda_{c}^{+}"}; + const AxisSpec thnAxisCPAXY{thnConfigAxisCPAXY, "cosine of pointing angle XY #Lambda_{c}^{+}"}; + const AxisSpec thnAxisOriginMc{3, -0.5, 2.5, "0: none, 1: prompt, 2: non-prompt"}; + const AxisSpec thnAxisChargeSigmaC{3, -0.5, 2.5, "#Sigma_{c}-baryon charge"}; + const AxisSpec thnAxisChannel{4, -0.5, 3.5, "0: direct 1,2,3: resonant"}; + const AxisSpec thnAxisBdtScoreLcBkg{thnConfigAxisBdtScoreLcBkg, "BDT bkg score (Lc)"}; + const AxisSpec thnAxisBdtScoreLcNonPrompt{thnConfigAxisBdtScoreLcNonPrompt, "BDT non-prompt score (Lc)"}; + const AxisSpec thnAxisGenPtLambdaC{thnConfigAxisGenPt, "#it{p}_{T}^{gen}(#Lambda_{c}^{+}) (GeV/#it{c})"}; + const AxisSpec thnAxisGenPtSigmaC{thnConfigAxisGenPt, "#it{p}_{T}^{gen}(#Sigma_{c}^{0,++}) (GeV/#it{c})"}; + const AxisSpec thnAxisGenPtLambdaCBMother{thnConfigAxisGenPtB, "#it{p}_{T}^{gen}(#Lambda_{c}^{+} B mother) (GeV/#it{c})"}; + const AxisSpec thnAxisGenPtSigmaCBMother{thnConfigAxisGenPtB, "#it{p}_{T}^{gen}(#Sigma_{c}^{0,++} B mother) (GeV/#it{c})"}; + const AxisSpec thnAxisSoftPiAbsDcaXY{thnConfigAxisSoftPiAbsDca, "|dca_{xy}|(#pi^{-,+} #leftarrow #Sigma_{c}^{0,++}) (cm)"}; + const AxisSpec thnAxisSoftPiAbsDcaZ{thnConfigAxisSoftPiAbsDca, "|dca_{z}|(#pi^{-,+} #leftarrow #Sigma_{c}^{0,++}) (cm)"}; + 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})"}; 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.}}}); @@ -278,6 +301,10 @@ struct HfTaskSigmac { axesSigmaCWithMl.push_back(thnAxisGenPtSigmaCBMother); axesSigmaCWithMl.push_back(thnAxisGenSigmaCSpecies); axesSigmaCWithMl.push_back(thnAxisSigmaCParticleAntiparticle); + if (addSoftPiDcaToSigmacSparse) { + 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); } else { @@ -285,14 +312,26 @@ struct HfTaskSigmac { axesSigmaCWoMl.push_back(thnAxisGenPtSigmaCBMother); axesSigmaCWoMl.push_back(thnAxisGenSigmaCSpecies); axesSigmaCWoMl.push_back(thnAxisSigmaCParticleAntiparticle); + 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); } } else { if (doprocessDataWithMl) { + if (addSoftPiDcaToSigmacSparse) { + 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); } 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); } @@ -412,6 +451,8 @@ struct HfTaskSigmac { if (enableTHn) { 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()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -420,10 +461,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + 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)); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + 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)); + } } } } @@ -485,6 +534,8 @@ struct HfTaskSigmac { if (enableTHn) { 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()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -493,10 +544,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + 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)); + } } else { /// fill w/o BDT information - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, 0, 0, ptSc, std::abs(chargeSc)); + if (addSoftPiDcaToSigmacSparse) { + 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)); + } } } } @@ -866,6 +925,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -874,10 +935,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + 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 - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } @@ -941,6 +1010,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -949,10 +1020,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + 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 - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } @@ -991,7 +1070,7 @@ struct HfTaskSigmac { double decLengthLc(candidateLc.decayLength()), decLengthXYLc(candidateLc.decayLengthXY()); double cpaLc(candidateLc.cpa()), cpaXYLc(candidateLc.cpaXY()); int origin = candSc.originMcRec(); - auto channel = candidateLc.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π± + auto channel = candidateLc.flagMcDecayChanRec(); /// 0: direct; 1: Λc± → p± K*; 2: Λc± → Δ(1232)±± K∓; 3: Λc± → Λ(1520) π±; FIXME: DecayChannelResonant /// candidate Λc+ → pK-π+ (and charge conjugate) within the range of M(pK-π+) chosen in the Σc0,++ builder if ((TESTBIT(isCandPKPiPiKP, o2::aod::hf_cand_sigmac::Decays::PKPi)) && std::abs(candidateLc.template prong0_as().mcParticle().pdgCode()) == kProton) { @@ -1052,6 +1131,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -1060,10 +1141,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPKPi()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPKPi()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + 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 - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } @@ -1125,6 +1214,8 @@ struct HfTaskSigmac { /// THn for candidate Σc0,++ cut variation if (enableTHn) { int8_t particleAntiparticle = candSc.particleAntiparticle(); + const float softPiAbsDcaXY = std::abs(candSc.softPiDcaXY()); + const float softPiAbsDcaZ = std::abs(candSc.softPiDcaZ()); if constexpr (useMl) { /// fill with ML information /// BDT index 0: bkg score; BDT index 2: non-prompt score @@ -1133,10 +1224,18 @@ struct HfTaskSigmac { outputMl.at(0) = candidateLc.mlProbLcToPiKP()[0]; /// bkg score outputMl.at(1) = candidateLc.mlProbLcToPiKP()[2]; /// non-prompt score } - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, outputMl.at(0), outputMl.at(1), origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + 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 - registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + 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); + } else { + registry.get(HIST("hnSigmaC"))->Fill(ptLc, deltaMass, decLengthLc, decLengthXYLc, cpaLc, cpaXYLc, origin, channel, ptSc, std::abs(chargeSc), candSc.ptBhadMotherPart(), sigmacSpecies, particleAntiparticle); + } } } diff --git a/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx b/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx index dbdd51410ce..fc527254dac 100644 --- a/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx +++ b/PWGHF/D2H/Tasks/taskSigmacToCascade.cxx @@ -15,21 +15,24 @@ /// \author Rutuparna Rath , INFN BOLOGNA and GSI Darmstadt /// In collaboration with Andrea Alici , INFN BOLOGNA -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/D2H/Tasks/taskXic.cxx b/PWGHF/D2H/Tasks/taskXic.cxx index 3ef874240ec..8a07bfbe3bd 100644 --- a/PWGHF/D2H/Tasks/taskXic.cxx +++ b/PWGHF/D2H/Tasks/taskXic.cxx @@ -19,19 +19,35 @@ /// \author Himanshu Sharma , University and INFN Padova /// \author Cristina Terrevoli , INFN Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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::framework; @@ -234,9 +250,9 @@ struct HfTaskXic { const AxisSpec thnAxisMCAllProngAccepted{2, -0.5, 1.5, "All MC prongs accepted"}; if (doprocessDataWithMl || doprocessMcWithMl) { // with ML - registry.add("hnXicVarsWithBdt", "THn for Xic candidates with BDT scores", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisBdtScoreXicBkg, thnAxisBdtScoreXicPrompt, thnAxisBdtScoreXicNonPrompt, thnAxisMcOrigin, thnAxisPtMC, thnAxisYMC, thnAxisMCAllProngAccepted}); + registry.add("hnXicVarsWithBdt", "THn for Xic candidates with BDT scores", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisBdtScoreXicBkg, thnAxisBdtScoreXicPrompt, thnAxisBdtScoreXicNonPrompt, thnAxisMcOrigin}); } else { - registry.add("hnXicVars", "THn for Xic candidates", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisChi2PCA, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisMcOrigin, thnAxisPtMC, thnAxisYMC, thnAxisMCAllProngAccepted}); + registry.add("hnXicVars", "THn for Xic candidates", HistType::kTHnSparseF, {thnAxisMass, thnAxisPt, thnAxisChi2PCA, thnAxisDecLength, thnAxisDecLengthXY, thnAxisCPA, thnAxisMcOrigin}); } } } // end init @@ -361,9 +377,9 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPKPi()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate Xic - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0, 0.0, 0.0, false); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, false); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0, 0.0, 0.0, false); + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), false); } } if (candidate.isSelXicToPiKP() >= selectionFlagXic) { @@ -375,9 +391,9 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPiKP()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, 0, 0.0, 0.0, false); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, false); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), 0, 0.0, 0.0, false); + registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), false); } } } // thn for Xic @@ -430,9 +446,6 @@ struct HfTaskXic { // Get the corresponding MC particle. auto mcParticleProng0 = candidate.template prong0_as().template mcParticle_as>(); auto pdgCodeProng0 = std::abs(mcParticleProng0.pdgCode()); - auto yProng0 = RecoDecay::y(mcParticleProng0.pVector(), o2::constants::physics::MassXiCPlus); - std::array ptProngs; - std::array etaProngs; // Signal registry.fill(HIST("MC/reconstructed/signal/hPtRecSig"), ptCandidate); // rec. level pT @@ -464,7 +477,8 @@ struct HfTaskXic { registry.fill(HIST("MC/reconstructed/signal/hEtaVsPtRecSig"), candidate.eta(), ptCandidate); /// reconstructed signal prompt - if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { + int origin = candidate.originMcRec(); + if (origin == RecoDecay::OriginType::Prompt) { if ((candidate.isSelXicToPKPi() >= selectionFlagXic) && pdgCodeProng0 == kProton) { registry.fill(HIST("MC/reconstructed/prompt/hMassRecSigPrompt"), massXicToPKPi); registry.fill(HIST("MC/reconstructed/prompt/hMassVsPtRecSigPrompt"), massXicToPKPi, ptCandidate); @@ -489,19 +503,9 @@ struct HfTaskXic { } if (enableTHn) { - double massXic(-1); double outputBkg(-1), outputPrompt(-1), outputFD(-1); const int ternaryCl = 3; - bool allProngsInAcceptance = false; if ((candidate.isSelXicToPKPi() >= selectionFlagXic) && pdgCodeProng0 == kProton) { - massXic = hfHelper.invMassXicToPKPi(candidate); - int counter = 0; - for (const auto& daught : mcParticleProng0.template daughters_as>()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - counter++; - } - allProngsInAcceptance = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]) && isProngInAcceptance(etaProngs[2], ptProngs[2]); if constexpr (useMl) { if (candidate.mlProbXicToPKPi().size() == ternaryCl) { outputBkg = candidate.mlProbXicToPKPi()[0]; /// bkg score @@ -509,20 +513,12 @@ struct HfTaskXic { outputFD = candidate.mlProbXicToPKPi()[2]; /// non-prompt score } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXicToPKPi, ptCandidate, outputBkg, outputPrompt, outputFD, origin); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVars"))->Fill(massXicToPKPi, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), origin); } } if ((candidate.isSelXicToPiKP() >= selectionFlagXic) && pdgCodeProng0 == kPiPlus) { - massXic = hfHelper.invMassXicToPiKP(candidate); - int counter = 0; - for (const auto& daught : mcParticleProng0.template daughters_as>()) { - ptProngs[counter] = daught.pt(); - etaProngs[counter] = daught.eta(); - counter++; - } - allProngsInAcceptance = isProngInAcceptance(etaProngs[0], ptProngs[0]) && isProngInAcceptance(etaProngs[1], ptProngs[1]) && isProngInAcceptance(etaProngs[2], ptProngs[2]); if constexpr (useMl) { if (candidate.mlProbXicToPiKP().size() == ternaryCl) { outputBkg = candidate.mlProbXicToPiKP()[0]; /// bkg score @@ -531,9 +527,9 @@ struct HfTaskXic { } /// Fill the ML outputScores and variables of candidate (todo: add multiplicity) // add here the pT_Mother, y_Mother, level (reco, Gen, Gen + Acc) - registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXic, ptCandidate, outputBkg, outputPrompt, outputFD, candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVarsWithBdt"))->Fill(massXicToPiKP, ptCandidate, outputBkg, outputPrompt, outputFD, origin); } else { - registry.get(HIST("hnXicVars"))->Fill(massXic, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), candidate.originMcRec(), mcParticleProng0.pt(), yProng0, allProngsInAcceptance); + registry.get(HIST("hnXicVars"))->Fill(massXicToPiKP, ptCandidate, candidate.chi2PCA(), candidate.decayLength(), candidate.decayLengthXY(), candidate.cpa(), origin); } } } // enable THn diff --git a/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx new file mode 100644 index 00000000000..40efcbbcc31 --- /dev/null +++ b/PWGHF/D2H/Tasks/taskXic0ToXiPi.cxx @@ -0,0 +1,361 @@ +// 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 taskXic0ToXiPi.cxx +/// \brief Task for Ξc^0 → Ξ∓ π± Kf analysis +/// \author Tao Fang , Central China Normal University +/// \author Ran Tu , Fudan University + +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/HfHelper.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 +#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::framework::expressions; + +/// Xic0 analysis task + +struct HfTaskXic0ToXiPi { + // ML inference + Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; + Configurable fillCent{"fillCent", false, "Flag to fill centrality information"}; + Configurable yCandGenMax{"yCandGenMax", 0.8, "max. gen particle rapidity"}; + Configurable yCandRecMax{"yCandRecMax", 0.8, "max. cand. rapidity"}; + + HfHelper hfHelper; + SliceCache cache; + + using TracksMc = soa::Join; + + using Xic0CandsKF = soa::Filtered>; + using Xic0CandsMcKF = soa::Filtered>; + + using Xic0CandsMlKF = soa::Filtered>; + using Xic0CandsMlMcKF = soa::Filtered>; + + using Xic0Gen = soa::Filtered>; + + using CollisionsWithEvSels = soa::Join; + using CollisionsWithFT0C = soa::Join; + using CollisionsWithFT0M = soa::Join; + using CollisionsWithMcLabels = 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)); + Preslice candXicKFPerCollision = aod::hf_cand_xic0_omegac0::collisionId; + Preslice candXicKFMlPerCollision = aod::hf_cand_xic0_omegac0::collisionId; + + PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; + + // ThnSparse for ML outputScores and Vars + ConfigurableAxis thnConfigAxisPromptScore{"thnConfigAxisPromptScore", {100, 0, 1}, "Prompt score bins"}; + ConfigurableAxis thnConfigAxisMass{"thnConfigAxisMass", {120, 2.4, 3.1}, "Cand. inv-mass bins"}; + ConfigurableAxis thnConfigAxisPtB{"thnConfigAxisPtB", {1000, 0, 100}, "Cand. beauty mother pTB bins"}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {100, 0, 20}, "Cand. pT bins"}; + ConfigurableAxis thnConfigAxisY{"thnConfigAxisY", {20, -1, 1}, "Cand. rapidity bins"}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {100, 0, 100}, "Centrality bins"}; + ConfigurableAxis thnConfigAxisPtPion{"thnConfigAxisPtPion", {100, 0, 10}, "PtPion from Xic0 bins"}; + ConfigurableAxis thnConfigAxisOrigin{"thnConfigAxisOrigin", {3, -0.5, 2.5}, "Cand. origin type"}; + ConfigurableAxis thnConfigAxisMatchFlag{"thnConfigAxisMatchFlag", {15, -7.5, 7.5}, "Cand. MC Match Flag type"}; + ConfigurableAxis thnConfigAxisGenPtD{"thnConfigAxisGenPtD", {500, 0, 50}, "Gen Pt D"}; + ConfigurableAxis thnConfigAxisGenPtB{"thnConfigAxisGenPtB", {1000, 0, 100}, "Gen Pt B"}; + ConfigurableAxis thnConfigAxisNumPvContr{"thnConfigAxisNumPvContr", {200, -0.5, 199.5}, "Number of PV contributors"}; + HistogramRegistry registry{"registry", {}}; + + void init(InitContext&) + { + std::array doprocess{doprocessDataWithKFParticle, doprocessMcWithKFParticle, doprocessDataWithKFParticleMl, doprocessMcWithKFParticleMl, doprocessDataWithKFParticleFT0C, doprocessDataWithKFParticleMlFT0C, doprocessDataWithKFParticleFT0M, doprocessDataWithKFParticleMlFT0M}; + if ((std::accumulate(doprocess.begin(), doprocess.end(), 0)) != 1) { + LOGP(fatal, "One and only one process function should be enabled at a time."); + } + + const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (#Xi#pi) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisPtB{thnConfigAxisPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; + const AxisSpec thnAxisY{thnConfigAxisY, "y"}; + const AxisSpec thnAxisOrigin{thnConfigAxisOrigin, "Origin"}; + const AxisSpec thnAxisMatchFlag{thnConfigAxisMatchFlag, "MatchFlag"}; + const AxisSpec thnAxisGenPtD{thnConfigAxisGenPtD, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisGenPtB{thnConfigAxisGenPtB, "#it{p}_{T}^{B} (GeV/#it{c})"}; + const AxisSpec thnAxisNumPvContr{thnConfigAxisNumPvContr, "Number of PV contributors"}; + + if (doprocessMcWithKFParticle || doprocessMcWithKFParticleMl) { + std::vector axesAcc = {thnAxisGenPtD, thnAxisGenPtB, thnAxisY, thnAxisOrigin, thnAxisNumPvContr}; + registry.add("hSparseAcc", "Thn for generated Xic0 from charm and beauty", HistType::kTHnSparseD, axesAcc); + registry.get(HIST("hSparseAcc"))->Sumw2(); + } + + std::vector axes = {thnAxisMass, thnAxisPt, thnAxisY}; + if (doprocessMcWithKFParticle || doprocessMcWithKFParticleMl) { + axes.push_back(thnAxisPtB); + axes.push_back(thnAxisOrigin); + axes.push_back(thnAxisMatchFlag); + axes.push_back(thnAxisNumPvContr); + } + if (applyMl) { + const AxisSpec thnAxisPromptScore{thnConfigAxisPromptScore, "BDT score prompt."}; + axes.insert(axes.begin(), thnAxisPromptScore); + registry.add("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsXic0Type", "Thn for Xic0 candidates", HistType::kTHnSparseD, axes); + registry.get(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsXic0Type"))->Sumw2(); + } else { + registry.add("hMassVsPtVsPtBVsYVsOriginVsXic0Type", "Thn for Xic0 candidates", HistType::kTHnSparseF, axes); + registry.get(HIST("hMassVsPtVsPtBVsYVsOriginVsXic0Type"))->Sumw2(); + } + if (fillCent) { + const AxisSpec thnAxisPromptScore{thnConfigAxisPromptScore, "BDT score prompt."}; + const AxisSpec thnAxisCent{thnConfigAxisCent, "Centrality."}; + const AxisSpec thnAxisPtPion{thnConfigAxisPtPion, "Pt of Pion from Xic0."}; + std::vector axesWithBdtCent = {thnAxisPromptScore, thnAxisMass, thnAxisPt, thnAxisY, thnAxisCent, thnAxisPtPion, thnConfigAxisNumPvContr}; + std::vector axesWithCent = {thnAxisMass, thnAxisPt, thnAxisY, thnAxisCent, thnAxisPtPion, thnConfigAxisNumPvContr}; + registry.add("hBdtScoreVsMassVsPtVsYVsCentVsPtPion", "Thn for Xic0 candidates with BDT&Cent&pTpi", HistType::kTHnSparseD, axesWithBdtCent); + registry.add("hMassVsPtVsYVsCentVsPtPion", "Thn for Xic0 candidates with Cent&pTpi", HistType::kTHnSparseD, axesWithCent); + registry.get(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"))->Sumw2(); + registry.get(HIST("hMassVsPtVsYVsCentVsPtPion"))->Sumw2(); + } + } + + template + void processData(const CandType& candidates, CollType const&) + { + for (const auto& candidate : candidates) { + if (candidate.resultSelections() != true) { + continue; + } + if (yCandRecMax >= 0. && std::abs(candidate.kfRapXic()) > yCandRecMax) { + continue; + } + + if constexpr (applyMl) { + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsXic0Type"), candidate.mlProbToXiPi()[0], candidate.invMassCharmBaryon(), candidate.kfptXic(), candidate.kfRapXic()); + } else { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsXic0Type"), candidate.invMassCharmBaryon(), candidate.kfptXic(), candidate.kfRapXic()); + } + } + } + + template + void processDataCent(const CandType& candidates, CollType const& collisions) + { + for (const auto& collision : collisions) { + + auto thisCollId = collision.globalIndex(); + auto groupedXicCandidates = applyMl + ? candidates.sliceBy(candXicKFMlPerCollision, thisCollId) + : candidates.sliceBy(candXicKFPerCollision, thisCollId); + // auto numPvContributors = collision.numContrib(); + + for (const auto& candidate : groupedXicCandidates) { + if (candidate.resultSelections() != true) { + continue; + } + if (yCandRecMax >= 0. && std::abs(candidate.kfRapXic()) > yCandRecMax) { + continue; + } + + auto numPvContributors = candidate.template collision_as().numContrib(); + float centrality = -999.f; + if constexpr (useCentrality) { + auto const& collision = candidate.template collision_as(); + centrality = o2::hf_centrality::getCentralityColl(collision); + } + double kfptXic = RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + double kfptPiFromXic = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); + if constexpr (applyMl) { + registry.fill(HIST("hBdtScoreVsMassVsPtVsYVsCentVsPtPion"), + candidate.mlProbToXiPi()[0], + candidate.invMassCharmBaryon(), + kfptXic, + candidate.kfRapXic(), + centrality, + kfptPiFromXic, + numPvContributors); + } else { + registry.fill(HIST("hMassVsPtVsYVsCentVsPtPion"), + candidate.invMassCharmBaryon(), + kfptXic, + candidate.kfRapXic(), + centrality, + kfptPiFromXic, + numPvContributors); + } + } + } + } + + template + void processMc(const CandType& candidates, + Xic0Gen const& mcParticles, + TracksMc const&, + CollType const& collisions, + aod::McCollisions const&) + { + // MC rec. + for (const auto& candidate : candidates) { + if (candidate.resultSelections() != true) { + continue; + } + if (yCandRecMax >= 0. && std::abs(candidate.kfRapXic()) > yCandRecMax) { + continue; + } + + auto numPvContributors = candidate.template collision_as().numContrib(); + double kfptXic = RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + if constexpr (applyMl) { + registry.fill(HIST("hBdtScoreVsMassVsPtVsPtBVsYVsOriginVsXic0Type"), + candidate.mlProbToXiPi()[0], + candidate.invMassCharmBaryon(), + kfptXic, + candidate.kfRapXic(), + candidate.ptBhadMotherPart(), + candidate.originMcRec(), + candidate.flagMcMatchRec(), + numPvContributors); + } else { + registry.fill(HIST("hMassVsPtVsPtBVsYVsOriginVsXic0Type"), + candidate.invMassCharmBaryon(), + kfptXic, + candidate.kfRapXic(), + candidate.ptBhadMotherPart(), + candidate.originMcRec(), + candidate.flagMcMatchRec(), + numPvContributors); + } + } + + // MC gen. + for (const auto& particle : mcParticles) { + if (yCandGenMax >= 0. && std::abs(particle.rapidityCharmBaryonGen()) > yCandGenMax) { + continue; + } + + auto ptGen = particle.pt(); + auto yGen = particle.rapidityCharmBaryonGen(); + + unsigned maxNumContrib = 0; + const auto& recoCollsPerMcColl = collisions.sliceBy(colPerMcCollision, particle.mcCollision().globalIndex()); + for (const auto& recCol : recoCollsPerMcColl) { + maxNumContrib = recCol.numContrib() > maxNumContrib ? recCol.numContrib() : maxNumContrib; + } + + if (particle.originMcGen() == RecoDecay::OriginType::Prompt) { + registry.fill(HIST("hSparseAcc"), + ptGen, + -1., + yGen, + RecoDecay::OriginType::Prompt, + maxNumContrib); + } else { + float ptGenB = mcParticles.rawIteratorAt(particle.idxBhadMotherPart()).pt(); + registry.fill(HIST("hSparseAcc"), + ptGen, + ptGenB, + yGen, + RecoDecay::OriginType::NonPrompt, + maxNumContrib); + } + } + } + + void processDataWithKFParticle(Xic0CandsKF const& candidates, + CollisionsWithEvSels const& collisions) + { + processDataCent(candidates, collisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticle, "process HfTaskXic0ToXiPi with KFParticle", true); + + void processDataWithKFParticleMl(Xic0CandsMlKF const& candidates, + CollisionsWithEvSels const& collisions) + { + processDataCent(candidates, collisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMl, "process HfTaskXic0ToXiPi with KFParticle and ML selections", false); + + void processDataWithKFParticleFT0C(Xic0CandsKF const& candidates, + CollisionsWithFT0C const& collisions) + { + processDataCent(candidates, collisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleFT0C, "process HfTaskXic0ToXiPi with KFParticle and with FT0C centrality", false); + + void processDataWithKFParticleFT0M(Xic0CandsKF const& candidates, + CollisionsWithFT0M const& collisions) + { + processDataCent(candidates, collisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleFT0M, "process HfTaskXic0ToXiPi with KFParticle and with FT0M centrality", false); + + void processDataWithKFParticleMlFT0C(Xic0CandsMlKF const& candidates, + CollisionsWithFT0C const& collisions) + { + processDataCent(candidates, collisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMlFT0C, "process HfTaskXic0ToXiPi with KFParticle and ML selections and with FT0C centrality", false); + + void processDataWithKFParticleMlFT0M(Xic0CandsMlKF const& candidates, + CollisionsWithFT0M const& collisions) + { + processDataCent(candidates, collisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processDataWithKFParticleMlFT0M, "process HfTaskXic0ToXiPi with KFParticle and ML selections and with FT0M centrality", false); + + void processMcWithKFParticle(Xic0CandsMcKF const& Xic0CandidatesMcKF, + Xic0Gen const& mcParticles, + TracksMc const& tracks, + CollisionsWithMcLabels const& collisions, + aod::McCollisions const& mcCollisions) + { + processMc(Xic0CandidatesMcKF, mcParticles, tracks, collisions, mcCollisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processMcWithKFParticle, "Process MC with KFParticle", false); + + void processMcWithKFParticleMl(Xic0CandsMlMcKF const& Xic0CandidatesMlMcKF, + Xic0Gen const& mcParticles, + TracksMc const& tracks, + CollisionsWithMcLabels const& collisions, + aod::McCollisions const& mcCollisions) + { + processMc(Xic0CandidatesMlMcKF, mcParticles, tracks, collisions, mcCollisions); + } + PROCESS_SWITCH(HfTaskXic0ToXiPi, processMcWithKFParticleMl, "Process MC with KFParticle and ML selections", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx index d9958ba459f..cc3459eba4a 100644 --- a/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx +++ b/PWGHF/D2H/Tasks/taskXicToXiPiPi.cxx @@ -17,18 +17,37 @@ /// \author Carolina Reetz , Heidelberg University /// \author Jaeyoon Cho , Inha University -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#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 + using namespace o2; using namespace o2::aod; using namespace o2::analysis; @@ -48,6 +67,8 @@ struct HfTaskXicToXiPiPi { // THnSparese for ML selection check Configurable enableTHn{"enableTHn", false, "Fill THnSparse for Xic"}; + const int nVarsMultiClass = 3; + Service pdg; Filter filterSelectCandidates = (aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= selectionFlagXic); @@ -130,10 +151,9 @@ struct HfTaskXicToXiPiPi { registry.add("hMassXiPi2", "#Xi^{#plus}_{c} candidates;inv. mass #Xi^{#mp} #pi^{#pm} (prong 2) (GeV/#it{c}^{2});#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisMassXiRes, axisPt}}); // KFParticle if (doprocessWithKFParticle || doprocessWithKFParticleAndML) { - registry.add("hChi2geoXi", "#Xi^{#plus}_{c} candidates;#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoLam", "#Xi^{#plus}_{c} candidates;#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoToPV", "#Xi^{#plus}_{c} candidates;#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoXiToXicPlus", "#Xi^{#plus}_{c} candidates;#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoXi", "#Xi^{#plus}_{c} candidates;#chi^{2}_{geo} (#Xi^{#mp});entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoLam", "#Xi^{#plus}_{c} candidates;#chi^{2}_{geo} (#Lambda);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2TopoXicPlusToPV", "#Xi^{#plus}_{c} candidates;#chi^{2}_{topo} (#Xi^{#plus}_{c} #rightarrow PV);entries", {HistType::kTH2F, {axisChi2, axisPt}}); } } @@ -202,14 +222,12 @@ struct HfTaskXicToXiPiPi { registry.add("hMassXiPi2RecBg", "#Xi^{#plus}_{c} candidates (unmatched);inv. mass #Xi^{#mp} #pi^{#pm} (prong 2) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{300, 1.0, 2.0}, axisPt}}); // MC reconstructed with KFParticle if (doprocessMcWithKFParticle || doprocessMcWithKFParticleAndML) { - registry.add("hChi2topoToPVRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoToPVRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#plus}_{c} candidate #chi^{2}_{topo} to PV;entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoXiRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoXiRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#mp} #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoLamRecSig", "#Xi^{#plus}_{c} candidates (matched);#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2geoLamRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Lambda #chi^{2}_{geo};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoXiToXicPlusRecSig", "#Xi^{#plus}_{c} candidates (matched);#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); - registry.add("hChi2topoXiToXicPlusRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#Xi^{#mp} candidate #chi^{2}_{topo} to #Xi^{#plus}_{c};entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoXiRecSig", "#Xi^{#plus}_{c} candidates (matched);#chi^{2}_{geo} (#Xi^{#mp});entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoXiRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#chi^{2}_{geo} (#Xi^{#mp});entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoLamRecSig", "#Xi^{#plus}_{c} candidates (matched);#chi^{2}_{geo} (#Lambda);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2GeoLamRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#chi^{2}_{geo} (#Lambda);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2TopoXicPlusToPVRecSig", "#Xi^{#plus}_{c} candidates (matched);#chi^{2}_{topo} (#Xi^{#plus}_{c} #rightarrow PV);entries", {HistType::kTH2F, {axisChi2, axisPt}}); + registry.add("hChi2TopoXicPlusToPVRecBg", "#Xi^{#plus}_{c} candidates (unmatched);#chi^{2}_{topo} (#Xi^{#plus}_{c} #rightarrow PV);entries", {HistType::kTH2F, {axisChi2, axisPt}}); } // MC generated registry.add("hPtProng0Gen", "MC particles (generated);prong 0 (#Xi^{#mp}) #it{p}_{T}^{gen} (GeV/#it{c});entries", {HistType::kTH2F, {{300, 0., 30.}, axisPt}}); @@ -284,7 +302,7 @@ struct HfTaskXicToXiPiPi { if (scoreSize > 0) { outputBkg = candidate.mlProbXicToXiPiPi()[0]; outputPrompt = candidate.mlProbXicToXiPiPi()[1]; - if (scoreSize == 3) { + if (scoreSize == nVarsMultiClass) { outputFD = candidate.mlProbXicToXiPiPi()[2]; } } @@ -343,19 +361,18 @@ struct HfTaskXicToXiPiPi { registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter1(), ptCandXic); registry.fill(HIST("hImpParErr"), candidate.errorImpactParameter2(), ptCandXic); registry.fill(HIST("hChi2PCA"), candidate.chi2PCA(), ptCandXic); - registry.fill(HIST("hCPAXi"), candidate.cosPaXi(), ptCandXic); - registry.fill(HIST("hCPAxyXi"), candidate.cosPaXYXi(), ptCandXic); - registry.fill(HIST("hCPALambda"), candidate.cosPaLambda(), ptCandXic); - registry.fill(HIST("hCPAxyLambda"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAXi"), candidate.cpaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXi"), candidate.cpaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambda"), candidate.cpaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambda"), candidate.cpaLambda(), ptCandXic); registry.fill(HIST("hMassXiPi1"), candidate.invMassXiPi0(), ptCandXic); registry.fill(HIST("hMassXiPi2"), candidate.invMassXiPi1(), ptCandXic); // fill KFParticle specific histograms if constexpr (useKfParticle) { - registry.fill(HIST("hChi2topoToPV"), candidate.chi2TopoXicPlusToPV(), ptCandXic); - registry.fill(HIST("hChi2topoXiToXicPlus"), candidate.chi2TopoXiToXicPlus(), ptCandXic); - registry.fill(HIST("hChi2geoXi"), candidate.kfCascadeChi2(), ptCandXic); - registry.fill(HIST("hChi2geoLam"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2GeoXi"), candidate.kfCascadeChi2(), ptCandXic); + registry.fill(HIST("hChi2GeoLam"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2TopoXicPlusToPV"), candidate.chi2TopoXicPlusToPV(), ptCandXic); } // fill THnSparse @@ -385,7 +402,7 @@ struct HfTaskXicToXiPiPi { } auto ptCandXic = candidate.pt(); - int flagMcMatchRecXic = std::abs(candidate.flagMcMatchRec()); + auto flagMcMatchRecXic = std::abs(candidate.flagMcMatchRec()); if (TESTBIT(flagMcMatchRecXic, hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi) || TESTBIT(flagMcMatchRecXic, hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiResPiToXiPiPi)) { auto indexMother = RecoDecay::getMother(mcParticles, candidate.template pi0_as().template mcParticle_as>(), o2::constants::physics::Pdg::kXiCPlus, true); @@ -418,17 +435,16 @@ struct HfTaskXicToXiPiPi { registry.fill(HIST("hImpParErrRecSig"), candidate.errorImpactParameter1(), ptCandXic); registry.fill(HIST("hImpParErrRecSig"), candidate.errorImpactParameter2(), ptCandXic); registry.fill(HIST("hChi2PCARecSig"), candidate.chi2PCA(), ptCandXic); - registry.fill(HIST("hCPAXiRecSig"), candidate.cosPaXi(), ptCandXic); - registry.fill(HIST("hCPAxyXiRecSig"), candidate.cosPaXYXi(), ptCandXic); - registry.fill(HIST("hCPALambdaRecSig"), candidate.cosPaLambda(), ptCandXic); - registry.fill(HIST("hCPAxyLambdaRecSig"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAXiRecSig"), candidate.cpaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXiRecSig"), candidate.cpaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambdaRecSig"), candidate.cpaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambdaRecSig"), candidate.cpaLambda(), ptCandXic); // fill KFParticle specific histograms if constexpr (useKfParticle) { - registry.fill(HIST("hChi2topoToPVRecSig"), candidate.chi2TopoXicPlusToPV(), ptCandXic); - registry.fill(HIST("hChi2topoXiToXicPlusRecSig"), candidate.chi2TopoXiToXicPlus(), ptCandXic); registry.fill(HIST("hChi2geoXiRecSig"), candidate.kfCascadeChi2(), ptCandXic); registry.fill(HIST("hChi2geoLamRecSig"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2TopoXicPlusToPVRecSig"), candidate.chi2TopoXicPlusToPV(), ptCandXic); } } else { registry.fill(HIST("hPtRecBg"), ptCandXic); @@ -457,17 +473,16 @@ struct HfTaskXicToXiPiPi { registry.fill(HIST("hImpParErrRecBg"), candidate.errorImpactParameter1(), ptCandXic); registry.fill(HIST("hImpParErrRecBg"), candidate.errorImpactParameter2(), ptCandXic); registry.fill(HIST("hChi2PCARecBg"), candidate.chi2PCA(), ptCandXic); - registry.fill(HIST("hCPAXiRecBg"), candidate.cosPaXi(), ptCandXic); - registry.fill(HIST("hCPAxyXiRecBg"), candidate.cosPaXYXi(), ptCandXic); - registry.fill(HIST("hCPALambdaRecBg"), candidate.cosPaLambda(), ptCandXic); - registry.fill(HIST("hCPAxyLambdaRecBg"), candidate.cosPaLambda(), ptCandXic); + registry.fill(HIST("hCPAXiRecBg"), candidate.cpaXi(), ptCandXic); + registry.fill(HIST("hCPAxyXiRecBg"), candidate.cpaXYXi(), ptCandXic); + registry.fill(HIST("hCPALambdaRecBg"), candidate.cpaLambda(), ptCandXic); + registry.fill(HIST("hCPAxyLambdaRecBg"), candidate.cpaLambda(), ptCandXic); // fill KFParticle specific histograms if constexpr (useKfParticle) { - registry.fill(HIST("hChi2topoToPVRecBg"), candidate.chi2TopoXicPlusToPV(), ptCandXic); - registry.fill(HIST("hChi2topoXiToXicPlusRecBg"), candidate.chi2TopoXiToXicPlus(), ptCandXic); registry.fill(HIST("hChi2geoXiRecBg"), candidate.kfCascadeChi2(), ptCandXic); registry.fill(HIST("hChi2geoLamRecBg"), candidate.kfV0Chi2(), ptCandXic); + registry.fill(HIST("hChi2TopoXicPlusToPVRecBg"), candidate.chi2TopoXicPlusToPV(), ptCandXic); } } diff --git a/PWGHF/D2H/Tasks/taskXicc.cxx b/PWGHF/D2H/Tasks/taskXicc.cxx index 1e49bb8649b..90f4c5da24d 100644 --- a/PWGHF/D2H/Tasks/taskXicc.cxx +++ b/PWGHF/D2H/Tasks/taskXicc.cxx @@ -16,17 +16,26 @@ /// \author Gian Michele Innocenti , CERN /// \author Jinjoo Seo , Inha University -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -38,7 +47,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Ξcc±± analysis task struct HfTaskXicc { diff --git a/PWGHF/D2H/Utils/utilsRedDataFormat.h b/PWGHF/D2H/Utils/utilsRedDataFormat.h index a083e9713b2..4e4bc2b9b3c 100644 --- a/PWGHF/D2H/Utils/utilsRedDataFormat.h +++ b/PWGHF/D2H/Utils/utilsRedDataFormat.h @@ -16,16 +16,16 @@ #ifndef PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ #define PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ -#include +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Utils/utilsEvSelHf.h" -#include +#include +#include +#include -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/HistogramRegistry.h" +#include -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Utils/utilsEvSelHf.h" +#include namespace o2::hf_evsel { @@ -81,6 +81,31 @@ float getTpcTofNSigmaPi1(const T1& prong1) } return defaultNSigma; } + +/// Helper function to retrive PID information of bachelor kaon from b-hadron decay +/// \param prong1 kaon track from reduced data format, aod::HfRedBachProng0Tracks +/// \return the combined TPC and TOF n-sigma for kaon +template +float getTpcTofNSigmaKa1(const T1& prong1) +{ + float defaultNSigma = -999.f; // -999.f is the default value set in TPCPIDResponse.h and PIDTOF.h + + bool hasTpc = prong1.hasTPC(); + bool hasTof = prong1.hasTOF(); + + if (hasTpc && hasTof) { + float tpcNSigma = prong1.tpcNSigmaKa(); + float tofNSigma = prong1.tofNSigmaKa(); + return std::sqrt(.5f * tpcNSigma * tpcNSigma + .5f * tofNSigma * tofNSigma); + } + if (hasTpc) { + return std::abs(prong1.tpcNSigmaKa()); + } + if (hasTof) { + return std::abs(prong1.tofNSigmaKa()); + } + return defaultNSigma; +} } // namespace o2::pid_tpc_tof_utils #endif // PWGHF_D2H_UTILS_UTILSREDDATAFORMAT_H_ diff --git a/PWGHF/DataModel/CandidateReconstructionTables.h b/PWGHF/DataModel/CandidateReconstructionTables.h index 014bfa3e32e..3ee949eadc8 100644 --- a/PWGHF/DataModel/CandidateReconstructionTables.h +++ b/PWGHF/DataModel/CandidateReconstructionTables.h @@ -18,28 +18,28 @@ #ifndef PWGHF_DATAMODEL_CANDIDATERECONSTRUCTIONTABLES_H_ #define PWGHF_DATAMODEL_CANDIDATERECONSTRUCTIONTABLES_H_ -#include -#include -#include - -#include -#include -#include +#include "PWGHF/Utils/utilsPid.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ALICE3/DataModel/ECAL.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include +#include +#include -#include "PWGHF/Utils/utilsPid.h" -#include "PWGHF/Core/DecayChannels.h" // FIXME: temporary until propagated where needed +#include +#include +#include namespace o2::aod { // Table aliases +using BcFullInfos = soa::Join; using TracksWCov = soa::Join; using TracksWDca = soa::Join; @@ -192,7 +192,7 @@ DECLARE_SOA_TABLE(PidTpcTofTinyPr, "AOD", "PIDTPCTOFTINYPR", //! Table of the TP namespace hf_sel_collision { -DECLARE_SOA_COLUMN(WhyRejectColl, whyRejectColl, uint16_t); //! +DECLARE_SOA_COLUMN(WhyRejectColl, whyRejectColl, uint32_t); //! } // namespace hf_sel_collision DECLARE_SOA_TABLE(HfSelCollision, "AOD", "HFSELCOLLISION", //! @@ -245,6 +245,7 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, Tracks, "_0"); //! Index to f DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, Tracks, "_1"); //! Index to second prong DECLARE_SOA_INDEX_COLUMN_FULL(Prong2, prong2, int, Tracks, "_2"); //! Index to third prong DECLARE_SOA_INDEX_COLUMN_FULL(Prong3, prong3, int, Tracks, "_3"); //! Index to fourth prong +DECLARE_SOA_INDEX_COLUMN_FULL(Prong4, prong4, int, Tracks, "_4"); //! Index to fifth prong DECLARE_SOA_INDEX_COLUMN(V0, v0); //! Index to V0 prong DECLARE_SOA_INDEX_COLUMN(Cascade, cascade); //! Index to cascade prong DECLARE_SOA_COLUMN(HFflag, hfflag, uint8_t); //! Bitmap to store selection results, o2-linter: disable=name/o2-column (written to disk) @@ -485,6 +486,23 @@ DECLARE_SOA_COLUMN(ImpactParameterZ2, impactParameterZ2, float); DECLARE_SOA_COLUMN(ErrorImpactParameterZ2, errorImpactParameterZ2, float); //! DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterZNormalised2, impactParameterZNormalised2, //! [](float dca, float err) -> float { return dca / err; }); +DECLARE_SOA_COLUMN(PxProng3, pxProng3, float); //! +DECLARE_SOA_COLUMN(PyProng3, pyProng3, float); //! +DECLARE_SOA_COLUMN(PzProng3, pzProng3, float); //! +DECLARE_SOA_DYNAMIC_COLUMN(PtProng3, ptProng3, //! + [](float px, float py) -> float { return RecoDecay::pt(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt2Prong3, pt2Prong3, //! + [](float px, float py) -> float { return RecoDecay::pt2(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(PVectorProng3, pVectorProng3, //! + [](float px, float py, float pz) -> std::array { return std::array{px, py, pz}; }); +DECLARE_SOA_COLUMN(ImpactParameter3, impactParameter3, float); //! +DECLARE_SOA_COLUMN(ErrorImpactParameter3, errorImpactParameter3, float); //! +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterNormalised3, impactParameterNormalised3, //! + [](float dca, float err) -> float { return dca / err; }); +DECLARE_SOA_COLUMN(ImpactParameterZ3, impactParameterZ3, float); //! +DECLARE_SOA_COLUMN(ErrorImpactParameterZ3, errorImpactParameterZ3, float); //! +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterZNormalised3, impactParameterZNormalised3, //! + [](float dca, float err) -> float { return dca / err; }); DECLARE_SOA_COLUMN(NProngsContributorsPV, nProngsContributorsPV, uint8_t); //! number of prongs contributing to the primary-vertex reconstruction DECLARE_SOA_COLUMN(BitmapProngsContributorsPV, bitmapProngsContributorsPV, uint8_t); //! bitmap with booleans indicating prongs contributing to the primary-vertex reconstruction /// prong PID nsigma @@ -618,11 +636,16 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, [](float impParProng0, float impParProng1) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1); }); 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(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 DECLARE_SOA_COLUMN(KfGeoMassD0bar, kfGeoMassD0bar, float); //! mass of the D0bar candidate from the KFParticle geometric fit @@ -736,6 +759,7 @@ DECLARE_SOA_TABLE(HfCand2ProngKF, "AOD", "HFCAND2PKF", 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, @@ -745,6 +769,7 @@ DECLARE_SOA_TABLE(HfCand2ProngMcRec, "AOD", "HFCAND2PMCREC", //! DECLARE_SOA_TABLE(HfCand2ProngMcGen, "AOD", "HFCAND2PMCGEN", //! hf_cand_2prong::FlagMcMatchGen, hf_cand_2prong::OriginMcGen, + hf_cand_2prong::FlagMcDecayChanGen, hf_cand::IdxBhadMotherPart); // cascade decay candidate table @@ -817,9 +842,9 @@ DECLARE_SOA_TABLE(HfCandCascBase, "AOD", "HFCANDCASCBASE", //! hf_cand_casc::PtV0Pos, // pT of positive V0 daughter hf_cand_casc::PtV0Neg, // pT of negative V0 daughter v0data::V0Radius, - v0data::MLambda, - v0data::MAntiLambda, - v0data::MK0Short, + v0data::legacy::MLambda, + v0data::legacy::MAntiLambda, + v0data::legacy::MK0Short, v0data::MGamma, hf_cand_casc::CtV0); // , @@ -851,12 +876,18 @@ 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); // reconstruction level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, 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 +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_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 + [](float dcaDauPos, float dcaDauNeg) -> float { return dcaDauPos * dcaDauNeg; }); enum DecayType { BplusToD0Pi = 0 }; @@ -865,6 +896,11 @@ enum DecayTypeMc : uint8_t { BplusToD0PiToKPiPi = 0, PartlyRecoDecay, OtherDecay, NDecayTypeMc }; + +enum class DecayTypeBToJpsiMc : uint8_t { BplusToJpsiKToMuMuK = 0, + PartlyRecoDecay, + OtherDecay, + NDecayTypeMc }; } // namespace hf_cand_bplus // declare dedicated BPlus decay candidate table @@ -898,7 +934,8 @@ DECLARE_SOA_TABLE(HfCandBplusBase, "AOD", "HFCANDBPLUSBASE", hf_cand::Phi, hf_cand::Y, hf_cand::E, - hf_cand::E2); + hf_cand::E2, + hf_cand_2prong::CtXY); // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBplusExt, HfCandBplusBase, "HFCANDBPLUSEXT", @@ -912,11 +949,13 @@ 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); // 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); // specific 3-prong decay properties @@ -936,6 +975,10 @@ DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, [](float impParProng0, float impParProng1, float impParProng2) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1, impParProng2); }); 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 ip2, float errIp2, float px0, float py0, float px1, float py1, float px2, float py2) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1, ip2}, std::array{errIp0, errIp1, errIp2}, std::array{std::array{px0, py0}, std::array{px1, py1}, std::array{px2, py2}}); }); +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 @@ -1077,6 +1120,55 @@ DECLARE_SOA_TABLE(HfCand3ProngMcGen, "AOD", "HFCAND3PMCGEN", //! hf_cand_3prong::FlagMcDecayChanGen, hf_cand::IdxBhadMotherPart); +// declare dedicated BPlus -> J/Psi K decay candidate table +// convention: prongs 0 and 1 should be J/Psi decay products +DECLARE_SOA_TABLE(HfCandBpJPBase, "AOD", "HFCANDBPJPBASE", + // general columns + HFCAND_COLUMNS, + /* prong 2 */ hf_cand::ImpactParameterNormalised2, + hf_cand::PtProng2, + hf_cand::Pt2Prong2, + hf_cand::PVectorProng2, + // 3-prong specific columns + o2::soa::Index<>, + 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, + /* dynamic columns */ + hf_cand_3prong::M, + hf_cand_3prong::M2, + hf_cand_3prong::ImpactParameterProngSqSum, + hf_cand_bplus::ImpactParameterProduct, + hf_cand_bplus::ImpactParameterProductJpsi, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt, + hf_cand::Pt2, + hf_cand::P, + hf_cand::P2, + hf_cand::PVector, + hf_cand::Cpa, + hf_cand::CpaXY, + hf_cand::Ct, + hf_cand::ImpactParameterXY, + hf_cand_3prong::MaxNormalisedDeltaIP, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E, + hf_cand::E2, + hf_cand_3prong::CtXY); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBpJPExt, HfCandBpJPBase, "HFCANDBPJPEXT", + hf_cand_3prong::Px, hf_cand_3prong::Py, hf_cand_3prong::Pz); + +DECLARE_SOA_TABLE(HfCandBpJPDaus, "AOD", "HFCANDBPJPDAUS", + hf_track_index::Prong0Id, hf_track_index::Prong1Id, hf_track_index::Prong2Id); + +using HfCandBplusToJpsi = soa::Join; + namespace hf_cand_casc_lf { // mapping of decay types @@ -1315,6 +1407,50 @@ DECLARE_SOA_COLUMN(ErrorDecayLengthCharmBaryon, errorDecayLengthCharmBaryon, flo DECLARE_SOA_COLUMN(ErrorDecayLengthXYCharmBaryon, errorDecayLengthXYCharmBaryon, float); // KFParticle results +DECLARE_SOA_COLUMN(XPvKf, xPvKf, float); +DECLARE_SOA_COLUMN(YPvKf, yPvKf, float); +DECLARE_SOA_COLUMN(ZPvKf, zPvKf, float); +DECLARE_SOA_COLUMN(XDecayVtxV0Kf, xDecayVtxV0Kf, float); +DECLARE_SOA_COLUMN(YDecayVtxV0Kf, yDecayVtxV0Kf, float); +DECLARE_SOA_COLUMN(ZDecayVtxV0Kf, zDecayVtxV0Kf, float); +DECLARE_SOA_COLUMN(XDecayVtxCascadeKf, xDecayVtxCascadeKf, float); +DECLARE_SOA_COLUMN(YDecayVtxCascadeKf, yDecayVtxCascadeKf, float); +DECLARE_SOA_COLUMN(ZDecayVtxCascadeKf, zDecayVtxCascadeKf, float); +DECLARE_SOA_COLUMN(PxLambdaKf, pxLambdaKf, float); +DECLARE_SOA_COLUMN(PyLambdaKf, pyLambdaKf, float); +DECLARE_SOA_COLUMN(PzLambdaKf, pzLambdaKf, float); +DECLARE_SOA_COLUMN(PxCascKf, pxCascKf, float); +DECLARE_SOA_COLUMN(PyCascKf, pyCascKf, float); +DECLARE_SOA_COLUMN(PzCascKf, pzCascKf, float); +DECLARE_SOA_COLUMN(XDecayVtxOmegaKaKf, xDecayVtxOmegaKaKf, float); +DECLARE_SOA_COLUMN(YDecayVtxOmegaKaKf, yDecayVtxOmegaKaKf, float); +DECLARE_SOA_COLUMN(ZDecayVtxOmegaKaKf, zDecayVtxOmegaKaKf, float); +DECLARE_SOA_COLUMN(PxOmegaKaKf, pxOmegaKaKf, float); +DECLARE_SOA_COLUMN(PyOmegaKaKf, pyOmegaKaKf, float); +DECLARE_SOA_COLUMN(PzOmegaKaKf, pzOmegaKaKf, float); +DECLARE_SOA_COLUMN(EtaV0DauPr, etaV0DauPr, float); +DECLARE_SOA_COLUMN(EtaV0DauPi, etaV0DauPi, float); +DECLARE_SOA_COLUMN(InvMassCascadeRej, invMassCascadeRej, float); +DECLARE_SOA_COLUMN(InvMassLambdaErr, invMassLambdaErr, float); +DECLARE_SOA_COLUMN(InvMassCascadeErr, invMassCascadeErr, float); +DECLARE_SOA_COLUMN(InvMassCascadeRejErr, invMassCascadeRejErr, float); +DECLARE_SOA_COLUMN(InvMassCharmBaryonErr, invMassCharmBaryonErr, float); +DECLARE_SOA_COLUMN(CTauOmegaKa, cTauOmegaKa, float); +DECLARE_SOA_COLUMN(Chi2GeoOmegaKa, chi2GeoOmegaKa, float); +DECLARE_SOA_COLUMN(OmegaKaldl, omegaKaldl, float); +DECLARE_SOA_COLUMN(Chi2TopoKaFromOmegaKaToPv, chi2TopoKaFromOmegaKaToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoOmegaKaToPv, chi2TopoOmegaKaToPv, float); +DECLARE_SOA_COLUMN(Chi2TopoKaToCasc, chi2TopoKaToCasc, float); +DECLARE_SOA_COLUMN(Chi2TopoCascToOmegaKa, chi2TopoCascToOmegaKa, float); +DECLARE_SOA_COLUMN(Chi2TopoKaToOmegaKa, chi2TopoKaToOmegaKa, float); +DECLARE_SOA_COLUMN(CosPaCascToOmegaKa, cosPaCascToOmegaKa, float); +DECLARE_SOA_COLUMN(CosPaXYCascToOmegaKa, cosPaXYCascToOmegaKa, float); +DECLARE_SOA_COLUMN(KfRapOmegaKa, kfRapOmegaKa, float); +DECLARE_SOA_COLUMN(KfPtKaFromOmegaKa, kfPtKaFromOmegaKa, float); +DECLARE_SOA_COLUMN(KfPtOmega, kfPtOmega, float); +DECLARE_SOA_COLUMN(KfPtOmegaKa, kfPtOmegaKa, float); +DECLARE_SOA_COLUMN(CosThetaStarKaFromOmegac, cosThetaStarKaFromOmegac, float); +DECLARE_SOA_COLUMN(CosThetaStarKaFromXic, cosThetaStarKaFromXic, float); DECLARE_SOA_COLUMN(KfDcaXYPiFromOmegac, kfDcaXYPiFromOmegac, float); DECLARE_SOA_COLUMN(KfDcaXYPiFromXic, kfDcaXYPiFromXic, float); DECLARE_SOA_COLUMN(KfDcaXYCascToPv, kfDcaXYCascToPv, float); @@ -1354,9 +1490,7 @@ DECLARE_SOA_COLUMN(KfMassOmegac, kfMassOmegac, float); DECLARE_SOA_COLUMN(KfRapOmegac, kfRapOmegac, float); DECLARE_SOA_COLUMN(KfRapXic, kfRapXic, float); DECLARE_SOA_COLUMN(KfptPiFromOmegac, kfptPiFromOmegac, float); -DECLARE_SOA_COLUMN(KfptPiFromXic, kfptPiFromXic, float); DECLARE_SOA_COLUMN(KfptOmegac, kfptOmegac, float); -DECLARE_SOA_COLUMN(KfptXic, kfptXic, float); DECLARE_SOA_COLUMN(CosThetaStarPiFromOmegac, cosThetaStarPiFromOmegac, float); DECLARE_SOA_COLUMN(CosThetaStarPiFromXic, cosThetaStarPiFromXic, float); DECLARE_SOA_COLUMN(V0Ndf, v0Ndf, float); @@ -1433,8 +1567,8 @@ 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(OriginRec, originRec, int8_t); -DECLARE_SOA_COLUMN(OriginGen, originGen, 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); @@ -1571,10 +1705,41 @@ DECLARE_SOA_TABLE(HfOmegacKf, "AOD", "HFOMEGACKF", //! hf_cand_xic0_omegac0::V0Chi2OverNdf, hf_cand_xic0_omegac0::CascChi2OverNdf, hf_cand_xic0_omegac0::OmegacChi2OverNdf, hf_cand_xic0_omegac0::MassV0Chi2OverNdf, hf_cand_xic0_omegac0::MassCascChi2OverNdf, hf_cand_xic0_omegac0::CascRejectInvmass); +// OmegaKa reconstruct by KFParticle +DECLARE_SOA_TABLE(HfCandToOmegaKaKf, "AOD", "HFCANDTOOMEGAKAKF", + o2::soa::Index<>, + hf_cand_xic0_omegac0::CollisionId, hf_cand_xic0_omegac0::XPv, hf_cand_xic0_omegac0::YPv, hf_cand_xic0_omegac0::ZPv, + hf_cand_xic0_omegac0::XPvKf, hf_cand_xic0_omegac0::YPvKf, hf_cand_xic0_omegac0::ZPvKf, + hf_cand_xic0_omegac0::XDecayVtxV0, hf_cand_xic0_omegac0::YDecayVtxV0, hf_cand_xic0_omegac0::ZDecayVtxV0, + hf_cand_xic0_omegac0::PxLambda, hf_cand_xic0_omegac0::PyLambda, hf_cand_xic0_omegac0::PzLambda, + hf_cand_xic0_omegac0::XDecayVtxCascade, hf_cand_xic0_omegac0::YDecayVtxCascade, hf_cand_xic0_omegac0::ZDecayVtxCascade, + hf_cand_xic0_omegac0::PxCasc, hf_cand_xic0_omegac0::PyCasc, hf_cand_xic0_omegac0::PzCasc, + hf_cand_xic0_omegac0::XDecayVtxV0Kf, hf_cand_xic0_omegac0::YDecayVtxV0Kf, hf_cand_xic0_omegac0::ZDecayVtxV0Kf, + hf_cand_xic0_omegac0::PxLambdaKf, hf_cand_xic0_omegac0::PyLambdaKf, hf_cand_xic0_omegac0::PzLambdaKf, + hf_cand_xic0_omegac0::XDecayVtxCascadeKf, hf_cand_xic0_omegac0::YDecayVtxCascadeKf, hf_cand_xic0_omegac0::ZDecayVtxCascadeKf, + hf_cand_xic0_omegac0::PxCascKf, hf_cand_xic0_omegac0::PyCascKf, hf_cand_xic0_omegac0::PzCascKf, + hf_cand_xic0_omegac0::XDecayVtxOmegaKaKf, hf_cand_xic0_omegac0::YDecayVtxOmegaKaKf, hf_cand_xic0_omegac0::ZDecayVtxOmegaKaKf, + hf_cand_xic0_omegac0::PxOmegaKaKf, hf_cand_xic0_omegac0::PyOmegaKaKf, hf_cand_xic0_omegac0::PzOmegaKaKf, + hf_cand_xic0_omegac0::SignDecay, hf_cand_xic0_omegac0::EtaV0DauPr, hf_cand_xic0_omegac0::EtaV0DauPi, hf_cand_xic0_omegac0::EtaBachFromCasc, + hf_cand_xic0_omegac0::EtaBachFromCharmBaryon, hf_cand_xic0_omegac0::EtaV0, hf_cand_xic0_omegac0::EtaCascade, hf_cand_xic0_omegac0::EtaCharmBaryon, + hf_cand_xic0_omegac0::KfRapOmegaKa, hf_cand_xic0_omegac0::ImpactParBachFromCharmBaryonXY, hf_cand_xic0_omegac0::ErrImpactParBachFromCharmBaryonXY, hf_cand_xic0_omegac0::ImpactParCascXY, hf_cand_xic0_omegac0::ErrImpactParCascXY, + hf_cand_xic0_omegac0::DcaV0Dau, hf_cand_xic0_omegac0::DcaCascDau, hf_cand_xic0_omegac0::DcaCharmBaryonDau, + hf_cand_xic0_omegac0::CosPAV0, hf_cand_xic0_omegac0::CosPACasc, hf_cand_xic0_omegac0::CosPACharmBaryon, hf_cand_xic0_omegac0::CosPAXYV0, hf_cand_xic0_omegac0::CosPAXYCasc, hf_cand_xic0_omegac0::CosPAXYCharmBaryon, + hf_cand_xic0_omegac0::CosPaV0ToCasc, hf_cand_xic0_omegac0::CosPaCascToOmegaKa, hf_cand_xic0_omegac0::CosPaXYV0ToCasc, hf_cand_xic0_omegac0::CosPaXYCascToOmegaKa, + hf_cand_xic0_omegac0::Chi2GeoV0, hf_cand_xic0_omegac0::Chi2GeoCasc, hf_cand_xic0_omegac0::Chi2GeoOmegaKa, + hf_cand_xic0_omegac0::MassV0Chi2OverNdf, hf_cand_xic0_omegac0::MassCascChi2OverNdf, + hf_cand_xic0_omegac0::Chi2TopoV0ToCasc, hf_cand_xic0_omegac0::Chi2TopoKaToCasc, hf_cand_xic0_omegac0::Chi2TopoKaToOmegaKa, hf_cand_xic0_omegac0::Chi2TopoCascToOmegaKa, + hf_cand_xic0_omegac0::Chi2TopoV0ToPv, hf_cand_xic0_omegac0::Chi2TopoCascToPv, hf_cand_xic0_omegac0::Chi2TopoKaFromOmegaKaToPv, hf_cand_xic0_omegac0::Chi2TopoOmegaKaToPv, + hf_cand_xic0_omegac0::V0ldl, hf_cand_xic0_omegac0::Cascldl, hf_cand_xic0_omegac0::OmegaKaldl, + hf_cand_xic0_omegac0::DecLenV0, hf_cand_xic0_omegac0::DecLenCascade, hf_cand_xic0_omegac0::DecLenCharmBaryon, + hf_cand_xic0_omegac0::InvMassLambda, hf_cand_xic0_omegac0::InvMassLambdaErr, hf_cand_xic0_omegac0::InvMassCascade, hf_cand_xic0_omegac0::InvMassCascadeErr, hf_cand_xic0_omegac0::InvMassCascadeRej, hf_cand_xic0_omegac0::InvMassCascadeRejErr, hf_cand_xic0_omegac0::InvMassCharmBaryon, hf_cand_xic0_omegac0::InvMassCharmBaryonErr, + hf_cand_xic0_omegac0::KfPtOmegaKa, hf_cand_xic0_omegac0::KfPtKaFromOmegaKa, hf_cand_xic0_omegac0::KfPtOmega, + hf_cand_xic0_omegac0::CosThetaStarKaFromOmegac, hf_cand_xic0_omegac0::CosThetaStarKaFromXic, hf_cand_xic0_omegac0::CTauV0, hf_cand_xic0_omegac0::CTauCascade, hf_cand_xic0_omegac0::CTauOmegaKa, + hf_cand_xic0_omegac0::V0Id, v0data::PosTrackId, v0data::NegTrackId, hf_cand_xic0_omegac0::CascadeId, cascdata::BachelorId, hf_cand_xic0_omegac0::BachelorFromCharmBaryonId); + DECLARE_SOA_TABLE(HfCandToXiPiKf, "AOD", "HFCANDTOXIPIKF", //! o2::soa::Index<>, hf_cand_xic0_omegac0::CollisionId, hf_cand_xic0_omegac0::XPv, hf_cand_xic0_omegac0::YPv, hf_cand_xic0_omegac0::ZPv, - hf_cand_xic0_omegac0::XDecayVtxCharmBaryon, hf_cand_xic0_omegac0::YDecayVtxCharmBaryon, hf_cand_xic0_omegac0::ZDecayVtxCharmBaryon, hf_cand_xic0_omegac0::XDecayVtxCascade, hf_cand_xic0_omegac0::YDecayVtxCascade, hf_cand_xic0_omegac0::ZDecayVtxCascade, hf_cand_xic0_omegac0::XDecayVtxV0, hf_cand_xic0_omegac0::YDecayVtxV0, hf_cand_xic0_omegac0::ZDecayVtxV0, hf_cand_xic0_omegac0::SignDecay, @@ -1586,28 +1751,23 @@ DECLARE_SOA_TABLE(HfCandToXiPiKf, "AOD", "HFCANDTOXIPIKF", //! hf_cand_xic0_omegac0::PxBachFromCasc, hf_cand_xic0_omegac0::PyBachFromCasc, hf_cand_xic0_omegac0::PzBachFromCasc, hf_cand_xic0_omegac0::PxPosV0Dau, hf_cand_xic0_omegac0::PyPosV0Dau, hf_cand_xic0_omegac0::PzPosV0Dau, hf_cand_xic0_omegac0::PxNegV0Dau, hf_cand_xic0_omegac0::PyNegV0Dau, hf_cand_xic0_omegac0::PzNegV0Dau, - hf_cand_xic0_omegac0::ImpactParCascXY, hf_cand_xic0_omegac0::ImpactParBachFromCharmBaryonXY, hf_cand_xic0_omegac0::ImpactParCascZ, hf_cand_xic0_omegac0::ImpactParBachFromCharmBaryonZ, - hf_cand_xic0_omegac0::ErrImpactParCascXY, hf_cand_xic0_omegac0::ErrImpactParBachFromCharmBaryonXY, hf_cand_xic0_omegac0::V0Id, v0data::PosTrackId, v0data::NegTrackId, hf_cand_xic0_omegac0::CascadeId, hf_cand_xic0_omegac0::BachelorFromCharmBaryonId, cascdata::BachelorId, hf_cand_xic0_omegac0::InvMassLambda, hf_cand_xic0_omegac0::InvMassCascade, hf_cand_xic0_omegac0::InvMassCharmBaryon, - hf_cand_xic0_omegac0::CosPAV0, hf_cand_xic0_omegac0::CosPACharmBaryon, hf_cand_xic0_omegac0::CosPACasc, hf_cand_xic0_omegac0::CosPAXYV0, hf_cand_xic0_omegac0::CosPAXYCharmBaryon, hf_cand_xic0_omegac0::CosPAXYCasc, - hf_cand_xic0_omegac0::CTauOmegac, hf_cand_xic0_omegac0::CTauCascade, hf_cand_xic0_omegac0::CTauV0, hf_cand_xic0_omegac0::CTauXic, + hf_cand_xic0_omegac0::CosPAV0, hf_cand_xic0_omegac0::CosPACasc, + hf_cand_xic0_omegac0::CTauCascade, hf_cand_xic0_omegac0::CTauV0, hf_cand_xic0_omegac0::CTauXic, hf_cand_xic0_omegac0::EtaV0PosDau, hf_cand_xic0_omegac0::EtaV0NegDau, hf_cand_xic0_omegac0::EtaBachFromCasc, hf_cand_xic0_omegac0::EtaBachFromCharmBaryon, hf_cand_xic0_omegac0::EtaCharmBaryon, hf_cand_xic0_omegac0::EtaCascade, hf_cand_xic0_omegac0::EtaV0, 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_cand_xic0_omegac0::KfDcaXYPiFromXic, hf_cand_xic0_omegac0::KfDcaXYCascToPv, hf_cand_xic0_omegac0::Chi2GeoV0, hf_cand_xic0_omegac0::Chi2GeoCasc, hf_cand_xic0_omegac0::Chi2GeoXic, hf_cand_xic0_omegac0::Chi2MassV0, hf_cand_xic0_omegac0::Chi2MassCasc, - hf_cand_xic0_omegac0::V0ldl, hf_cand_xic0_omegac0::Cascldl, hf_cand_xic0_omegac0::Xicldl, + hf_cand_xic0_omegac0::V0ldl, hf_cand_xic0_omegac0::Cascldl, hf_cand_xic0_omegac0::Chi2TopoV0ToPv, hf_cand_xic0_omegac0::Chi2TopoCascToPv, hf_cand_xic0_omegac0::Chi2TopoPiFromXicToPv, hf_cand_xic0_omegac0::Chi2TopoXicToPv, hf_cand_xic0_omegac0::Chi2TopoV0ToCasc, hf_cand_xic0_omegac0::Chi2TopoCascToXic, hf_cand_xic0_omegac0::DecayLenXYLambda, hf_cand_xic0_omegac0::DecayLenXYCasc, hf_cand_xic0_omegac0::DecayLenXYXic, - hf_cand_xic0_omegac0::CosPaV0ToCasc, hf_cand_xic0_omegac0::CosPaCascToXic, hf_cand_xic0_omegac0::CosPaXYV0ToCasc, hf_cand_xic0_omegac0::CosPaXYCascToXic, + hf_cand_xic0_omegac0::CosPaV0ToCasc, hf_cand_xic0_omegac0::CosPaCascToXic, hf_cand_xic0_omegac0::KfRapXic, - hf_cand_xic0_omegac0::KfptPiFromXic, hf_cand_xic0_omegac0::KfptXic, hf_cand_xic0_omegac0::CosThetaStarPiFromXic, hf_cand_xic0_omegac0::V0Ndf, hf_cand_xic0_omegac0::CascNdf, hf_cand_xic0_omegac0::XicNdf, hf_cand_xic0_omegac0::MassV0Ndf, hf_cand_xic0_omegac0::MassCascNdf, @@ -1631,7 +1791,7 @@ DECLARE_SOA_TABLE(HfCandToXiPiKfQa, "AOD", "HFCANDTOXIPIKFQA", DECLARE_SOA_TABLE(HfXicToXiPiMCRec, "AOD", "HFXICXIPIMCREC", //! hf_cand_xic0_omegac0::FlagMcMatchRec, hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginRec, + hf_cand_xic0_omegac0::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, hf_cand::PtBhadMotherPart, hf_cand::PdgBhadMotherPart, @@ -1639,7 +1799,7 @@ DECLARE_SOA_TABLE(HfXicToXiPiMCRec, "AOD", "HFXICXIPIMCREC", //! DECLARE_SOA_TABLE(HfOmegacToXiPiMCRec, "AOD", "HFOMCXIPIMCREC", //! hf_cand_xic0_omegac0::FlagMcMatchRec, hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginRec, + hf_cand_xic0_omegac0::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, hf_cand::PtBhadMotherPart, hf_cand::PdgBhadMotherPart, @@ -1647,7 +1807,7 @@ DECLARE_SOA_TABLE(HfOmegacToXiPiMCRec, "AOD", "HFOMCXIPIMCREC", //! DECLARE_SOA_TABLE(HfToOmegaPiMCRec, "AOD", "HFTOOMEPIMCREC", //! hf_cand_xic0_omegac0::FlagMcMatchRec, hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginRec, + hf_cand_xic0_omegac0::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, hf_cand::PtBhadMotherPart, hf_cand::PdgBhadMotherPart, @@ -1655,7 +1815,7 @@ DECLARE_SOA_TABLE(HfToOmegaPiMCRec, "AOD", "HFTOOMEPIMCREC", //! DECLARE_SOA_TABLE(HfToOmegaKMCRec, "AOD", "HFTOOMEKMCREC", //! hf_cand_xic0_omegac0::FlagMcMatchRec, hf_cand_xic0_omegac0::DebugMcRec, - hf_cand_xic0_omegac0::OriginRec, + hf_cand_xic0_omegac0::OriginMcRec, hf_cand_xic0_omegac0::CollisionMatched, hf_cand::PtBhadMotherPart, hf_cand::PdgBhadMotherPart, @@ -1664,40 +1824,40 @@ DECLARE_SOA_TABLE(HfToOmegaKMCRec, "AOD", "HFTOOMEKMCREC", //! // 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::OriginGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<1>); + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<1>); 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::OriginGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<2>); + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<2>); 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::OriginGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<3>); + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<3>); DECLARE_SOA_TABLE(HfToOmegaKMCGen, "AOD", "HFTOOMEKMCGEN", //! hf_cand_xic0_omegac0::FlagMcMatchGen, hf_cand_xic0_omegac0::DebugGenCharmBar, hf_cand_xic0_omegac0::DebugGenCasc, hf_cand_xic0_omegac0::DebugGenLambda, - hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<4>); + hf_cand_xic0_omegac0::PtCharmBaryonGen, hf_cand_xic0_omegac0::RapidityCharmBaryonGen, hf_cand_xic0_omegac0::OriginMcGen, hf_cand::IdxBhadMotherPart, o2::soa::Marker<4>); // specific Xic to Xi Pi Pi candidate properties namespace hf_cand_xic_to_xi_pi_pi { DECLARE_SOA_INDEX_COLUMN_FULL(Pi0, pi0, int, Tracks, "_pi0"); DECLARE_SOA_INDEX_COLUMN_FULL(Pi1, pi1, int, Tracks, "_pi1"); +DECLARE_SOA_COLUMN(Sign, sign, int8_t); +DECLARE_SOA_COLUMN(InvMassXicPlus, invMassXicPlus, float); +DECLARE_SOA_COLUMN(InvMassXi, invMassXi, float); +DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); +DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); +DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); DECLARE_SOA_COLUMN(XPvErr, xPvErr, float); DECLARE_SOA_COLUMN(YPvErr, yPvErr, float); DECLARE_SOA_COLUMN(ZPvErr, zPvErr, float); DECLARE_SOA_COLUMN(XSvErr, xSvErr, float); DECLARE_SOA_COLUMN(YSvErr, ySvErr, float); DECLARE_SOA_COLUMN(ZSvErr, zSvErr, float); -DECLARE_SOA_COLUMN(CosPaXi, cosPaXi, float); -DECLARE_SOA_COLUMN(CosPaXYXi, cosPaXYXi, float); -DECLARE_SOA_COLUMN(CosPaLambda, cosPaLambda, float); -DECLARE_SOA_COLUMN(CosPaXYLambda, cosPaXYLambda, float); -DECLARE_SOA_COLUMN(CosPaLambdaToXi, cosPaLambdaToXi, float); -DECLARE_SOA_COLUMN(CosPaXYLambdaToXi, cosPaXYLambdaToXi, float); -DECLARE_SOA_COLUMN(InvMassXicPlus, invMassXicPlus, float); -DECLARE_SOA_COLUMN(InvMassXi, invMassXi, float); -DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); -DECLARE_SOA_COLUMN(Sign, sign, float); -DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); -DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); +DECLARE_SOA_COLUMN(CpaXi, cpaXi, float); +DECLARE_SOA_COLUMN(CpaXYXi, cpaXYXi, float); +DECLARE_SOA_COLUMN(CpaLambda, cpaLambda, float); +DECLARE_SOA_COLUMN(CpaXYLambda, cpaXYLambda, float); +DECLARE_SOA_COLUMN(CpaLambdaToXi, cpaLambdaToXi, float); +DECLARE_SOA_COLUMN(CpaXYLambdaToXi, cpaXYLambdaToXi, float); DECLARE_SOA_COLUMN(PBachelorPi, pBachelorPi, float); DECLARE_SOA_COLUMN(PPiFromLambda, pPiFromLambda, float); DECLARE_SOA_COLUMN(PPrFromLambda, pPrFromLambda, float); @@ -1709,16 +1869,20 @@ DECLARE_SOA_COLUMN(DcaBachelorToPV, dcaBachelorToPV, float); DECLARE_SOA_COLUMN(DcaXYCascToPV, dcaXYCascToPV, float); DECLARE_SOA_COLUMN(DcaZCascToPV, dcaZCascToPV, float); // KF specific columns -DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); -DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); -DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); +DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPV, chi2TopoXicPlusToPV, float); +DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPVBefConst, chi2TopoXicPlusToPVBefConst, float); +DECLARE_SOA_COLUMN(Chi2PrimXi, chi2PrimXi, float); +DECLARE_SOA_COLUMN(Chi2PrimPi0, chi2PrimPi0, float); +DECLARE_SOA_COLUMN(Chi2PrimPi1, chi2PrimPi1, float); +DECLARE_SOA_COLUMN(Chi2DevPi0Pi1, chi2DevPi0Pi1, float); +DECLARE_SOA_COLUMN(Chi2DevPi0Xi, chi2DevPi0Xi, float); +DECLARE_SOA_COLUMN(Chi2DevPi1Xi, chi2DevPi1Xi, float); DECLARE_SOA_COLUMN(DcaPi0Pi1, dcaPi0Pi1, float); DECLARE_SOA_COLUMN(DcaPi0Xi, dcaPi0Xi, float); DECLARE_SOA_COLUMN(DcaPi1Xi, dcaPi1Xi, float); -DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPV, chi2TopoXicPlusToPV, float); -DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPVBeforeConstraint, chi2TopoXicPlusToPVBeforeConstraint, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlus, chi2TopoXiToXicPlus, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlusBeforeConstraint, chi2TopoXiToXicPlusBeforeConstraint, float); +DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); +DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); +DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); DECLARE_SOA_COLUMN(KfDecayLength, kfDecayLength, float); DECLARE_SOA_COLUMN(KfDecayLengthNormalised, kfDecayLengthNormalised, float); DECLARE_SOA_COLUMN(KfDecayLengthXY, kfDecayLengthXY, float); @@ -1737,8 +1901,23 @@ 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(OriginRec, originRec, int8_t); -DECLARE_SOA_COLUMN(OriginGen, originGen, int8_t); +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); +// Residuals and pulls +DECLARE_SOA_COLUMN(PtResidual, ptResidual, float); +DECLARE_SOA_COLUMN(PResidual, pResidual, float); +DECLARE_SOA_COLUMN(XPvResidual, xPvResidual, float); +DECLARE_SOA_COLUMN(YPvResidual, yPvResidual, float); +DECLARE_SOA_COLUMN(ZPvResidual, zPvResidual, float); +DECLARE_SOA_COLUMN(XPvPull, xPvPull, float); +DECLARE_SOA_COLUMN(YPvPull, yPvPull, float); +DECLARE_SOA_COLUMN(ZPvPull, zPvPull, float); +DECLARE_SOA_COLUMN(XSvResidual, xSvResidual, float); +DECLARE_SOA_COLUMN(YSvResidual, ySvResidual, float); +DECLARE_SOA_COLUMN(ZSvResidual, zSvResidual, float); +DECLARE_SOA_COLUMN(XSvPull, xSvPull, float); +DECLARE_SOA_COLUMN(YSvPull, ySvPull, float); +DECLARE_SOA_COLUMN(ZSvPull, zSvPull, float); // Dynamic columns DECLARE_SOA_DYNAMIC_COLUMN(PProng0, pProng0, //! [](float px, float py, float pz) -> float { return RecoDecay::p(px, py, pz); }); @@ -1772,7 +1951,7 @@ DECLARE_SOA_TABLE(HfCandXicBase, "AOD", "HFCANDXICBASE", hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, // cascade specific columns hf_cand_xic_to_xi_pi_pi::PBachelorPi, hf_cand_xic_to_xi_pi_pi::PPiFromLambda, hf_cand_xic_to_xi_pi_pi::PPrFromLambda, - hf_cand_xic_to_xi_pi_pi::CosPaXi, hf_cand_xic_to_xi_pi_pi::CosPaXYXi, hf_cand_xic_to_xi_pi_pi::CosPaLambda, hf_cand_xic_to_xi_pi_pi::CosPaXYLambda, hf_cand_xic_to_xi_pi_pi::CosPaLambdaToXi, hf_cand_xic_to_xi_pi_pi::CosPaXYLambdaToXi, + 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, hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, hf_cand_xic_to_xi_pi_pi::InvMassXi, hf_cand_xic_to_xi_pi_pi::InvMassLambda, hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, // DCA hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, hf_cand_xic_to_xi_pi_pi::DcaPosToPV, hf_cand_xic_to_xi_pi_pi::DcaNegToPV, hf_cand_xic_to_xi_pi_pi::DcaBachelorToPV, hf_cand_xic_to_xi_pi_pi::DcaXYCascToPV, hf_cand_xic_to_xi_pi_pi::DcaZCascToPV, @@ -1810,26 +1989,47 @@ DECLARE_SOA_TABLE(HfCandXicBase, "AOD", "HFCANDXICBASE", // extended table with expression columns that can be used as arguments of dynamic columns DECLARE_SOA_EXTENDED_TABLE_USER(HfCandXicExt, HfCandXicBase, "HFCANDXICEXT", hf_cand_3prong::Px, hf_cand_3prong::Py, hf_cand_3prong::Pz); - using HfCandXic = HfCandXicExt; +// table with KF-specific variables DECLARE_SOA_TABLE(HfCandXicKF, "AOD", "HFCANDXICKF", - cascdata::KFCascadeChi2, cascdata::KFV0Chi2, hf_cand_xic_to_xi_pi_pi::KfDecayLength, hf_cand_xic_to_xi_pi_pi::KfDecayLengthNormalised, hf_cand_xic_to_xi_pi_pi::KfDecayLengthXY, hf_cand_xic_to_xi_pi_pi::KfDecayLengthXYNormalised, - hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBeforeConstraint, hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, hf_cand_xic_to_xi_pi_pi::Chi2TopoXiToXicPlusBeforeConstraint, hf_cand_xic_to_xi_pi_pi::Chi2TopoXiToXicPlus, - hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi, - hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaPi1Xi); + cascdata::KFCascadeChi2, cascdata::KFV0Chi2, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBefConst, hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, + hf_cand_xic_to_xi_pi_pi::Chi2PrimXi, hf_cand_xic_to_xi_pi_pi::Chi2PrimPi0, hf_cand_xic_to_xi_pi_pi::Chi2PrimPi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Pi1, hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Xi, hf_cand_xic_to_xi_pi_pi::Chi2DevPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); // table with results of reconstruction level MC matching -DECLARE_SOA_TABLE(HfCandXicMcRec, "AOD", "HFCANDXICMCREC", //! +DECLARE_SOA_TABLE(HfCandXicMcRec, "AOD", "HFCANDXICMCREC", hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, - hf_cand_xic_to_xi_pi_pi::OriginRec); + hf_cand_xic_to_xi_pi_pi::OriginMcRec); + // table with results of generator level MC matching -DECLARE_SOA_TABLE(HfCandXicMcGen, "AOD", "HFCANDXICMCGEN", //! +DECLARE_SOA_TABLE(HfCandXicMcGen, "AOD", "HFCANDXICMCGEN", hf_cand_xic_to_xi_pi_pi::FlagMcMatchGen, - hf_cand_xic_to_xi_pi_pi::OriginGen, + hf_cand_xic_to_xi_pi_pi::OriginMcGen, hf_cand::PdgBhadMotherPart); +// table with residuals and pulls of PV +DECLARE_SOA_TABLE(HfCandXicResid, "AOD", "HFCANDXICRESID", + hf_cand_xic_to_xi_pi_pi::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, + hf_cand_xic_to_xi_pi_pi::YPvResidual, + hf_cand_xic_to_xi_pi_pi::ZPvResidual, + hf_cand_xic_to_xi_pi_pi::XPvPull, + hf_cand_xic_to_xi_pi_pi::YPvPull, + hf_cand_xic_to_xi_pi_pi::ZPvPull, + hf_cand_xic_to_xi_pi_pi::XSvResidual, + hf_cand_xic_to_xi_pi_pi::YSvResidual, + hf_cand_xic_to_xi_pi_pi::ZSvResidual, + hf_cand_xic_to_xi_pi_pi::XSvPull, + hf_cand_xic_to_xi_pi_pi::YSvPull, + hf_cand_xic_to_xi_pi_pi::ZSvPull); + // specific chic candidate properties namespace hf_cand_chic { @@ -1906,11 +2106,13 @@ 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); // reconstruction level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +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 // mapping of decay types enum DecayType { LbToLcPi }; // move this to a dedicated cascade namespace in the future? @@ -1965,12 +2167,14 @@ 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); // 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); // specific B0 candidate properties @@ -1978,20 +2182,24 @@ 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); // reconstruction level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(FlagMcMatchGen, flagMcMatchGen, int8_t); // generator level +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 // mapping of decay types -enum DecayType { B0ToDPi }; +enum DecayType { B0ToDPi = 0, + B0ToDstarPi }; enum DecayTypeMc : uint8_t { B0ToDplusPiToPiKPiPi = 0, B0ToDsPiToKKPiPi, BsToDsPiToKKPiPi, B0ToDplusKToPiKPiK, + B0ToDstarPiToD0PiPiToKPiPiPi, PartlyRecoDecay, OtherDecay, NDecayTypeMc }; @@ -2041,12 +2249,14 @@ using HfCandB0 = soa::Join; // 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); // 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); // specific Bs candidate properties @@ -2054,15 +2264,27 @@ 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); // reconstruction level -DECLARE_SOA_COLUMN(FlagWrongCollision, flagWrongCollision, 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 +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_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})); + float impParPhi = RecoDecay::impParXY(std::array{xVtxP, yVtxP, zVtxP}, std::array{xVtxS, yVtxS, zVtxS}, RecoDecay::pVec(std::array{pxLfTrack0, pyLfTrack0, pzLfTrack0}, std::array{pxLfTrack1, pyLfTrack1, pzLfTrack1})); + return impParJpsi * impParPhi; + }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProductJpsi, impactParameterProductJpsi, // J/Psi impact parameter for Bs -> J/Psi phi + [](float dcaDauPos, float dcaDauNeg) -> float { return dcaDauPos * dcaDauNeg; }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProductPhi, impactParameterProductPhi, // J/Psi impact parameter for Bs -> J/Psi phi + [](float dcaLfTrack0, float dcaLfTrack1) -> float { return dcaLfTrack0 * dcaLfTrack1; }); // mapping of decay types -enum DecayType { BsToDsPi }; +enum DecayType { BsToDsPi = 0 }; enum DecayTypeMc : uint8_t { BsToDsPiToPhiPiPiToKKPiPi = 0, // Bs(bar) → Ds∓ π± → (Phi π∓) π± → (K- K+ π∓) π± BsToDsPiToK0starKPiToKKPiPi, // Bs(bar) → Ds∓ π± → (K0* K∓) π± → (K- K+ π∓) π± @@ -2074,6 +2296,11 @@ enum DecayTypeMc : uint8_t { BsToDsPiToPhiPiPiToKKPiPi = 0, // Bs(bar) → Ds∓ OtherDecay, NDecayTypeMc }; // counter of differentiated MC decay types +enum class DecayTypeBToJpsiMc : uint8_t { BsToJpsiPhiToMuMuKK = 0, // Bs(bar) → J/Psi Phi → (µ+ µ-) (K- K+) + PartlyRecoDecay, // 4 final state particles have another common b-hadron ancestor + OtherDecay, + NDecayTypeMc }; // counter of differentiated MC decay types + } // namespace hf_cand_bs // declare dedicated Bs decay candidate table @@ -2107,6 +2334,7 @@ DECLARE_SOA_TABLE(HfCandBsBase, "AOD", "HFCANDBSBASE", hf_cand::Y, hf_cand::E, hf_cand::E2, + hf_cand_2prong::CtXY, o2::soa::Marker<1>); // extended table with expression columns that can be used as arguments of dynamic columns @@ -2120,11 +2348,89 @@ 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::FlagMcMatchRec, + hf_cand_bs::FlagMcDecayChanRec); // table with results of generator level MC matching DECLARE_SOA_TABLE(HfCandBsMcGen, "AOD", "HFCANDBSMCGEN", - hf_cand_bs::FlagMcMatchGen); + hf_cand_bs::FlagMcMatchGen, + hf_cand_bs::FlagMcDecayChanGen); + +namespace hf_cand_4prong +{ +DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! + float, 1.f * aod::hf_cand::pxProng0 + 1.f * aod::hf_cand::pxProng1 + 1.f * aod::hf_cand::pxProng2 + 1.f * aod::hf_cand::pxProng3); +DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! + float, 1.f * aod::hf_cand::pyProng0 + 1.f * aod::hf_cand::pyProng1 + 1.f * aod::hf_cand::pyProng2 + 1.f * aod::hf_cand::pyProng3); +DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! + float, 1.f * aod::hf_cand::pzProng0 + 1.f * aod::hf_cand::pzProng1 + 1.f * aod::hf_cand::pzProng2 + 1.f * aod::hf_cand::pzProng3); +DECLARE_SOA_DYNAMIC_COLUMN(M, m, //! + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float px3, float py3, float pz3, const std::array& m) -> float { return RecoDecay::m(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}, std::array{px3, py3, pz3}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(M2, m2, //! + [](float px0, float py0, float pz0, float px1, float py1, float pz1, float px2, float py2, float pz2, float px3, float py3, float pz3, const std::array& m) -> float { return RecoDecay::m2(std::array{std::array{px0, py0, pz0}, std::array{px1, py1, pz1}, std::array{px2, py2, pz2}, std::array{px3, py3, pz3}}, m); }); +DECLARE_SOA_DYNAMIC_COLUMN(ImpactParameterProngSqSum, impactParameterProngSqSum, //! + [](float impParProng0, float impParProng1, float impParProng2, float impParProng3) -> float { return RecoDecay::sumOfSquares(impParProng0, impParProng1, impParProng2, impParProng3); }); +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 ip2, float errIp2, float ip3, float errIp3, float px0, float py0, float px1, float py1, float px2, float py2, float px3, float py3) -> float { return RecoDecay::maxNormalisedDeltaIP(std::array{xVtxP, yVtxP}, std::array{xVtxS, yVtxS}, errDlxy, std::array{pxM, pyM}, std::array{ip0, ip1, ip2, ip3}, std::array{errIp0, errIp1, errIp2, errIp3}, std::array{std::array{px0, py0}, std::array{px1, py1}, std::array{px2, py2}, std::array{px3, py3}}); }); +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 px3, float py3, float pz3, 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}, std::array{px3, py3, pz3}}, m); }); +} // namespace hf_cand_4prong + +// declare dedicated Bs -> J/Psi phi decay candidate table +// convention: prongs 0 and 1 should be J/Psi decay products, 2 and 3 should be phi decay products +DECLARE_SOA_TABLE(HfCandBsJPBase, "AOD", "HFCANDBSJPBASE", + // general columns + HFCAND_COLUMNS, + /* prong 2 */ hf_cand::ImpactParameterNormalised2, + hf_cand::PtProng2, + hf_cand::Pt2Prong2, + hf_cand::PVectorProng2, + /* prong 3 */ hf_cand::ImpactParameterNormalised3, + hf_cand::PtProng3, + hf_cand::Pt2Prong3, + hf_cand::PVectorProng3, + // 4-prong specific columns + o2::soa::Index<>, + 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::PxProng3, hf_cand::PyProng3, hf_cand::PzProng3, + hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, hf_cand::ImpactParameter2, hf_cand::ImpactParameter3, + hf_cand::ErrorImpactParameter0, hf_cand::ErrorImpactParameter1, hf_cand::ErrorImpactParameter2, hf_cand::ErrorImpactParameter3, + /* dynamic columns */ + hf_cand_4prong::M, + hf_cand_4prong::M2, + hf_cand_4prong::ImpactParameterProngSqSum, + hf_cand_bs::ImpactParameterProduct, + hf_cand_bs::ImpactParameterProductJpsi, + hf_cand_bs::ImpactParameterProductPhi, + /* dynamic columns that use candidate momentum components */ + hf_cand::Pt, + hf_cand::Pt2, + hf_cand::P, + hf_cand::P2, + hf_cand::PVector, + hf_cand::Cpa, + hf_cand::CpaXY, + hf_cand::Ct, + hf_cand::ImpactParameterXY, + hf_cand_4prong::MaxNormalisedDeltaIP, + hf_cand::Eta, + hf_cand::Phi, + hf_cand::Y, + hf_cand::E, + hf_cand::E2, + hf_cand_4prong::CtXY, + o2::soa::Marker<1>); + +// extended table with expression columns that can be used as arguments of dynamic columns +DECLARE_SOA_EXTENDED_TABLE_USER(HfCandBsJPExt, HfCandBsJPBase, "HFCANDBSJPEXT", + hf_cand_4prong::Px, hf_cand_4prong::Py, hf_cand_4prong::Pz); + +DECLARE_SOA_TABLE(HfCandBsJPDaus, "AOD", "HFCANDBSJPDAUS", + hf_cand_bs::Prong0Id, hf_track_index::Prong1Id, hf_track_index::Prong2Id, hf_track_index::Prong3Id); + +using HfCandBsToJpsi = soa::Join; // specific Σc0,++ candidate properties namespace hf_cand_sigmac @@ -2133,6 +2439,8 @@ DECLARE_SOA_INDEX_COLUMN_FULL(ProngLc, prongLc, int, HfCand3Prong, ""); DECLARE_SOA_COLUMN(Charge, charge, int8_t); //! // Σc charge(either 0 or ++) DECLARE_SOA_COLUMN(StatusSpreadLcMinvPKPiFromPDG, statusSpreadLcMinvPKPiFromPDG, int); //! // Λc Minv(pKpi) spread from PDG Λc mass DECLARE_SOA_COLUMN(StatusSpreadLcMinvPiKPFromPDG, statusSpreadLcMinvPiKPFromPDG, int); //! // Λc Minv(piKp) spread from PDG Λc mass +DECLARE_SOA_COLUMN(SoftPiDcaXY, softPiDcaXY, float); //! soft-pion impact parameter in xy +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 @@ -2176,6 +2484,7 @@ DECLARE_SOA_TABLE(HfCandScBase, "AOD", "HFCANDSCBASE", /* Σc0,++ specific columns */ hf_cand_sigmac::Charge, hf_cand_sigmac::StatusSpreadLcMinvPKPiFromPDG, hf_cand_sigmac::StatusSpreadLcMinvPiKPFromPDG, + hf_cand_sigmac::SoftPiDcaXY, hf_cand_sigmac::SoftPiDcaZ, /* prong 0 */ // hf_cand::ImpactParameterNormalised0, hf_cand::PtProng0, diff --git a/PWGHF/DataModel/CandidateSelectionTables.h b/PWGHF/DataModel/CandidateSelectionTables.h index f693605f635..7f5786ee1f6 100644 --- a/PWGHF/DataModel/CandidateSelectionTables.h +++ b/PWGHF/DataModel/CandidateSelectionTables.h @@ -250,19 +250,23 @@ DECLARE_SOA_TABLE(HfMlB0ToDPi, "AOD", "HFMLB0", //! namespace hf_sel_candidate_bs { -DECLARE_SOA_COLUMN(IsSelBsToDsPi, isSelBsToDsPi, int); //! -DECLARE_SOA_COLUMN(MlProbBsToDsPi, mlProbBsToDsPi, std::vector); //! +DECLARE_SOA_COLUMN(IsSelBsToDsPi, isSelBsToDsPi, int); //! +DECLARE_SOA_COLUMN(MlProbBsToDsPi, mlProbBsToDsPi, std::vector); //! +DECLARE_SOA_COLUMN(MlProbBsToJpsiPhi, mlProbBsToJpsiPhi, std::vector); //! } // namespace hf_sel_candidate_bs DECLARE_SOA_TABLE(HfSelBsToDsPi, "AOD", "HFSELBS", //! hf_sel_candidate_bs::IsSelBsToDsPi); DECLARE_SOA_TABLE(HfMlBsToDsPi, "AOD", "HFMLBS", //! hf_sel_candidate_bs::MlProbBsToDsPi); +DECLARE_SOA_TABLE(HfMlBsToJpsiPhi, "AOD", "HFMLBSTOJPSIPHI", //! + hf_sel_candidate_bs::MlProbBsToDsPi); namespace hf_sel_candidate_bplus { -DECLARE_SOA_COLUMN(IsSelBplusToD0Pi, isSelBplusToD0Pi, int); //! selection flag on B+ candidate -DECLARE_SOA_COLUMN(MlProbBplusToD0Pi, mlProbBplusToD0Pi, float); //! ML score of B+ candidate for signal class +DECLARE_SOA_COLUMN(IsSelBplusToD0Pi, isSelBplusToD0Pi, int); //! selection flag on B+ candidate +DECLARE_SOA_COLUMN(MlProbBplusToD0Pi, mlProbBplusToD0Pi, float); //! ML score of B+ candidate for signal class +DECLARE_SOA_COLUMN(MlProbBplusToJpsiK, mlProbBplusToJpsiK, float); //! ML score of B+ candidate for signal class } // namespace hf_sel_candidate_bplus DECLARE_SOA_TABLE(HfSelBplusToD0Pi, "AOD", "HFSELBPLUS", //! @@ -271,6 +275,8 @@ DECLARE_SOA_TABLE(HfSelBplusToD0Pi, "AOD", "HFSELBPLUS", //! DECLARE_SOA_TABLE(HfMlBplusToD0Pi, "AOD", "HFMLBPLUS", //! hf_sel_candidate_bplus::MlProbBplusToD0Pi); +DECLARE_SOA_TABLE(HfMlBplusToJpsiK, "AOD", "HFMLBPLUSTOJPSIK", //! + hf_sel_candidate_bplus::MlProbBplusToJpsiK); namespace hf_sel_candidate_lb { DECLARE_SOA_COLUMN(IsSelLbToLcPi, isSelLbToLcPi, int); //! selection flag on Lb candidate @@ -311,6 +317,14 @@ DECLARE_SOA_COLUMN(MlProbXicToPiKP, mlProbXicToPiKP, std::vector); //! // XicPlus to Xi Pi Pi DECLARE_SOA_COLUMN(IsSelXicToXiPiPi, isSelXicToXiPiPi, int); //! DECLARE_SOA_COLUMN(MlProbXicToXiPiPi, mlProbXicToXiPiPi, std::vector); //! +enum XicToXiPiPiSelectionStep { + RecoTotal = 0, + RecoKinTopol, + RecoTrackQuality, + RecoPID, + RecoMl, + NSelectionSteps +}; } // namespace hf_sel_candidate_xic DECLARE_SOA_TABLE(HfSelXicToPKPi, "AOD", "HFSELXIC", //! @@ -361,9 +375,7 @@ DECLARE_SOA_TABLE(HfSelToXiPi, "AOD", "HFSELTOXIPI", hf_sel_toxipi::TofNSigmaPiFromCharmBaryon, hf_sel_toxipi::TofNSigmaPiFromCasc, hf_sel_toxipi::TofNSigmaPiFromLambda, hf_sel_toxipi::TofNSigmaPrFromLambda); DECLARE_SOA_TABLE(HfSelToXiPiKf, "AOD", "HFSELTOXIPIKF", - hf_sel_toxipi::StatusPidCharmBaryon, hf_sel_toxipi::StatusPidCascade, hf_sel_toxipi::StatusPidLambda, - hf_sel_toxipi::StatusInvMassCharmBaryon, hf_sel_toxipi::StatusInvMassCascade, hf_sel_toxipi::StatusInvMassLambda, - hf_sel_toxipi::ResultSelections, hf_sel_toxipi::PidTpcInfoStored, hf_sel_toxipi::PidTofInfoStored, + hf_sel_toxipi::ResultSelections, hf_sel_toxipi::TpcNSigmaPiFromCharmBaryon, hf_sel_toxipi::TpcNSigmaPiFromCasc, hf_sel_toxipi::TpcNSigmaPiFromLambda, hf_sel_toxipi::TpcNSigmaPrFromLambda, hf_sel_toxipi::TofNSigmaPiFromCharmBaryon, hf_sel_toxipi::TofNSigmaPiFromCasc, hf_sel_toxipi::TofNSigmaPiFromLambda, hf_sel_toxipi::TofNSigmaPrFromLambda); @@ -380,12 +392,12 @@ DECLARE_SOA_COLUMN(StatusInvMassCascade, statusInvMassCascade, bool); DECLARE_SOA_COLUMN(StatusInvMassCharmBaryon, statusInvMassCharmBaryon, bool); DECLARE_SOA_COLUMN(ResultSelections, resultSelections, bool); DECLARE_SOA_COLUMN(TpcNSigmaPiFromCharmBaryon, tpcNSigmaPiFromCharmBaryon, float); -// DECLARE_SOA_COLUMN(TpcNSigmaKaFromCharmBaryon, tpcNSigmaKaFromCharmBaryon, float); +DECLARE_SOA_COLUMN(TpcNSigmaKaFromCharmBaryon, tpcNSigmaKaFromCharmBaryon, float); DECLARE_SOA_COLUMN(TpcNSigmaKaFromCasc, tpcNSigmaKaFromCasc, float); DECLARE_SOA_COLUMN(TpcNSigmaPiFromLambda, tpcNSigmaPiFromLambda, float); DECLARE_SOA_COLUMN(TpcNSigmaPrFromLambda, tpcNSigmaPrFromLambda, float); DECLARE_SOA_COLUMN(TofNSigmaPiFromCharmBaryon, tofNSigmaPiFromCharmBaryon, float); -// DECLARE_SOA_COLUMN(TofNSigmaKaFromCharmBaryon, tofNSigmaKaFromCharmBaryon, float); +DECLARE_SOA_COLUMN(TofNSigmaKaFromCharmBaryon, tofNSigmaKaFromCharmBaryon, float); DECLARE_SOA_COLUMN(TofNSigmaKaFromCasc, tofNSigmaKaFromCasc, float); DECLARE_SOA_COLUMN(TofNSigmaPiFromLambda, tofNSigmaPiFromLambda, float); DECLARE_SOA_COLUMN(TofNSigmaPrFromLambda, tofNSigmaPrFromLambda, float); @@ -402,6 +414,13 @@ DECLARE_SOA_TABLE(HfSelToOmegaPi, "AOD", "HFSELTOOMEPI", hf_sel_toomegapi::TpcNSigmaPiFromCharmBaryon, hf_sel_toomegapi::TpcNSigmaKaFromCasc, hf_sel_toomegapi::TpcNSigmaPiFromLambda, hf_sel_toomegapi::TpcNSigmaPrFromLambda, hf_sel_toomegapi::TofNSigmaPiFromCharmBaryon, hf_sel_toomegapi::TofNSigmaKaFromCasc, hf_sel_toomegapi::TofNSigmaPiFromLambda, hf_sel_toomegapi::TofNSigmaPrFromLambda); +DECLARE_SOA_TABLE(HfSelToOmegaKaKf, "AOD", "HFSELTOOMEGAKAKF", + hf_sel_toomegapi::StatusPidLambda, hf_sel_toomegapi::StatusPidCascade, hf_sel_toomegapi::StatusPidCharmBaryon, + hf_sel_toomegapi::StatusInvMassLambda, hf_sel_toomegapi::StatusInvMassCascade, hf_sel_toomegapi::StatusInvMassCharmBaryon, + hf_sel_toomegapi::ResultSelections, hf_sel_toomegapi::PidTpcInfoStored, hf_sel_toomegapi::PidTofInfoStored, + hf_sel_toomegapi::TpcNSigmaKaFromCharmBaryon, hf_sel_toomegapi::TpcNSigmaKaFromCasc, hf_sel_toomegapi::TpcNSigmaPiFromLambda, hf_sel_toomegapi::TpcNSigmaPrFromLambda, + hf_sel_toomegapi::TofNSigmaKaFromCharmBaryon, hf_sel_toomegapi::TofNSigmaKaFromCasc, hf_sel_toomegapi::TofNSigmaPiFromLambda, hf_sel_toomegapi::TofNSigmaPrFromLambda); + DECLARE_SOA_TABLE(HfMlSelOmegacToOmegaPi, "AOD", "HFMLOMEGAC", //! hf_sel_toomegapi::MlProbOmegac); namespace hf_sel_toomegaka diff --git a/PWGHF/DataModel/DerivedTables.h b/PWGHF/DataModel/DerivedTables.h index 337abce14e0..e3602a0ba63 100644 --- a/PWGHF/DataModel/DerivedTables.h +++ b/PWGHF/DataModel/DerivedTables.h @@ -16,17 +16,18 @@ #ifndef PWGHF_DATAMODEL_DERIVEDTABLES_H_ #define PWGHF_DATAMODEL_DERIVEDTABLES_H_ -#include -#include - -#include -#include -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include + +#include + +#include +#include namespace o2::aod { @@ -34,12 +35,13 @@ namespace o2::aod // D0 → K− π+ // Λc → p K− π+ // D+ → K− π+ π+ -// Ds+ → K− K+ π+ (todo) +// Ds+ → K− K+ π+ // composite species // B0 → D− π+ // B+ → D0 π+ // D*+ → D0 π+ +// Ξc± → (Ξ∓ → (Λ → p π∓) π∓) π± π± // ================ // Collision tables @@ -86,30 +88,30 @@ DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); //! original global index of o2::soa::Marker); // Declares the base table with MC collisions (McCollBases) and joinable tables (McCollIds, McRCollIds). -#define DECLARE_TABLES_MCCOLL(_hf_type_, _hf_description_, _hf_namespace_) \ - namespace hf_mc_coll \ - { \ - namespace der_##_hf_namespace_ \ - { \ - DECLARE_SOA_ARRAY_INDEX_COLUMN_CUSTOM(Hf##_hf_type_##CollBase, hfCollBases, "HF" _hf_description_ "COLLBASES"); \ - } \ - } \ - DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##McCollBases, "HF" _hf_description_ "MCCOLLBASE", \ - o2::soa::Index<>, \ - mccollision::PosX, \ - mccollision::PosY, \ - mccollision::PosZ, \ - cent::CentFT0M, \ - o2::soa::Marker); \ - \ - using Hf##_hf_type_##McCollBase = Hf##_hf_type_##McCollBases::iterator; \ - using StoredHf##_hf_type_##McCollBase = StoredHf##_hf_type_##McCollBases::iterator; \ - \ - DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##McCollIds, "HF" _hf_description_ "MCCOLLID", \ - hf_mc_coll::McCollisionId, \ - o2::soa::Marker); \ - \ - DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##McRCollIds, "HF" _hf_description_ "MCRCOLLID", \ +#define DECLARE_TABLES_MCCOLL(_hf_type_, _hf_description_, _hf_namespace_) \ + namespace hf_mc_coll \ + { \ + namespace der_##_hf_namespace_ \ + { \ + DECLARE_SOA_ARRAY_INDEX_COLUMN_CUSTOM(Hf##_hf_type_##CollBase, hfCollBases, "HF" _hf_description_ "COLLBASES"); /* o2-linter: disable=name/o2-column (unified getter) */ \ + } \ + } \ + DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##McCollBases, "HF" _hf_description_ "MCCOLLBASE", \ + o2::soa::Index<>, \ + mccollision::PosX, \ + mccollision::PosY, \ + mccollision::PosZ, \ + cent::CentFT0M, \ + o2::soa::Marker); \ + \ + using Hf##_hf_type_##McCollBase = Hf##_hf_type_##McCollBases::iterator; \ + using StoredHf##_hf_type_##McCollBase = StoredHf##_hf_type_##McCollBases::iterator; \ + \ + DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##McCollIds, "HF" _hf_description_ "MCCOLLID", \ + hf_mc_coll::McCollisionId, \ + o2::soa::Marker); \ + \ + DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##McRCollIds, "HF" _hf_description_ "MCRCOLLID", \ hf_mc_coll::der_##_hf_namespace_::Hf##_hf_type_##CollBaseIds); // ================ @@ -163,27 +165,27 @@ DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant } // namespace hf_mc_particle // Declares the base table with candidates (Bases). -#define DECLARE_TABLE_CAND_BASE(_hf_type_, _hf_description_, _hf_namespace_) \ - namespace hf_cand_base \ - { \ - namespace der_##_hf_namespace_ \ - { \ - DECLARE_SOA_INDEX_COLUMN_CUSTOM(Hf##_hf_type_##CollBase, hfCollBase, "HF" _hf_description_ "COLLBASES"); \ - } \ - } \ - \ - DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##Bases, "HF" _hf_description_ "BASE", \ - o2::soa::Index<>, \ - hf_cand_base::der_##_hf_namespace_::Hf##_hf_type_##CollBaseId, \ - hf_cand_base::Pt, \ - hf_cand_base::Eta, \ - hf_cand_base::Phi, \ - hf_cand_base::M, \ - hf_cand_base::Y, \ - hf_cand_base::Px, \ - hf_cand_base::Py, \ - hf_cand_base::Pz, \ - hf_cand_base::P, \ +#define DECLARE_TABLE_CAND_BASE(_hf_type_, _hf_description_, _hf_namespace_) \ + namespace hf_cand_base \ + { \ + namespace der_##_hf_namespace_ \ + { \ + DECLARE_SOA_INDEX_COLUMN_CUSTOM(Hf##_hf_type_##CollBase, hfCollBase, "HF" _hf_description_ "COLLBASES"); /* o2-linter: disable=name/o2-column (unified getter) */ \ + } \ + } \ + \ + DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##Bases, "HF" _hf_description_ "BASE", \ + o2::soa::Index<>, \ + hf_cand_base::der_##_hf_namespace_::Hf##_hf_type_##CollBaseId, \ + hf_cand_base::Pt, \ + hf_cand_base::Eta, \ + hf_cand_base::Phi, \ + hf_cand_base::M, \ + hf_cand_base::Y, \ + hf_cand_base::Px, \ + hf_cand_base::Py, \ + hf_cand_base::Pz, \ + hf_cand_base::P, \ o2::soa::Marker); // Declares the table with global indices for 2-prong candidates (Ids). @@ -213,6 +215,17 @@ DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant hf_track_index::Prong3Id, \ o2::soa::Marker); +// Declares the table with global indices for 5-prong candidates (Ids). +#define DECLARE_TABLE_CAND_ID_5P(_hf_type_, _hf_description_) \ + DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##Ids, "HF" _hf_description_ "ID", \ + hf_cand::CollisionId, \ + hf_track_index::Prong0Id, \ + hf_track_index::Prong1Id, \ + hf_track_index::Prong2Id, \ + hf_track_index::Prong3Id, \ + hf_track_index::Prong4Id, \ + o2::soa::Marker); + // Declares the table with candidate selection flags (Sels). #define DECLARE_TABLE_CAND_SEL(_hf_type_, _hf_description_) \ DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##Sels, "HF" _hf_description_ "SEL", \ @@ -224,27 +237,27 @@ DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant // ================ // Declares the base table with MC particles (PBases). -#define DECLARE_TABLE_MCPARTICLE_BASE(_hf_type_, _hf_description_, _hf_namespace_) \ - namespace hf_mc_particle \ - { \ - namespace der_##_hf_namespace_ \ - { \ - DECLARE_SOA_INDEX_COLUMN_CUSTOM(Hf##_hf_type_##McCollBase, hfMcCollBase, "HF" _hf_description_ "MCCOLLBASES"); \ - } \ - } \ - DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##PBases, "HF" _hf_description_ "PBASE", \ - o2::soa::Index<>, \ - hf_mc_particle::der_##_hf_namespace_::Hf##_hf_type_##McCollBaseId, \ - hf_cand_base::Pt, \ - hf_cand_base::Eta, \ - hf_cand_base::Phi, \ - hf_cand_base::Y, \ - hf_mc_particle::FlagMcMatchGen, \ - hf_mc_particle::OriginMcGen, \ - hf_cand_base::Px, \ - hf_cand_base::Py, \ - hf_cand_base::Pz, \ - hf_cand_base::P, \ +#define DECLARE_TABLE_MCPARTICLE_BASE(_hf_type_, _hf_description_, _hf_namespace_) \ + namespace hf_mc_particle \ + { \ + namespace der_##_hf_namespace_ \ + { \ + DECLARE_SOA_INDEX_COLUMN_CUSTOM(Hf##_hf_type_##McCollBase, hfMcCollBase, "HF" _hf_description_ "MCCOLLBASES"); /* o2-linter: disable=name/o2-column (unified getter) */ \ + } \ + } \ + DECLARE_SOA_TABLE_STAGED(Hf##_hf_type_##PBases, "HF" _hf_description_ "PBASE", \ + o2::soa::Index<>, \ + hf_mc_particle::der_##_hf_namespace_::Hf##_hf_type_##McCollBaseId, \ + hf_cand_base::Pt, \ + hf_cand_base::Eta, \ + hf_cand_base::Phi, \ + hf_cand_base::Y, \ + hf_mc_particle::FlagMcMatchGen, \ + hf_mc_particle::OriginMcGen, \ + hf_cand_base::Px, \ + hf_cand_base::Py, \ + hf_cand_base::Pz, \ + hf_cand_base::P, \ o2::soa::Marker); // Declares the table with global indices for MC particles (PIds). @@ -281,6 +294,11 @@ DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant DECLARE_TABLES_COMMON(_hf_type_, _hf_description_, _hf_namespace_) \ DECLARE_TABLE_CAND_ID_4P(_hf_type_, _hf_description_) +#define DECLARE_TABLES_5P(_hf_type_, _hf_description_, _hf_namespace_, _marker_number_) \ + constexpr uint Marker##_hf_type_ = _marker_number_; \ + DECLARE_TABLES_COMMON(_hf_type_, _hf_description_, _hf_namespace_) \ + DECLARE_TABLE_CAND_ID_5P(_hf_type_, _hf_description_) + // ================ // Declarations of common tables for individual species // ================ @@ -288,6 +306,7 @@ DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); //! resonant DECLARE_TABLES_2P(D0, "D0", d0, 2); DECLARE_TABLES_3P(Lc, "LC", lc, 3); DECLARE_TABLES_3P(Dplus, "DP", dplus, 4); +DECLARE_TABLES_3P(Ds, "DS", ds, 9); DECLARE_TABLES_3P(Bplus, "BP", bplus, 5); DECLARE_TABLES_3P(Dstar, "DST", dstar, 6); // Workaround for the existing B0 macro in termios.h @@ -295,6 +314,7 @@ DECLARE_TABLES_3P(Dstar, "DST", dstar, 6); #undef B0 DECLARE_TABLES_4P(B0, "B0", b0, 7); #pragma pop_macro("B0") +DECLARE_TABLES_5P(XicToXiPiPi, "XICXPP", xic_to_xi_pi_pi, 8); // ================ // Additional species-specific candidate tables @@ -303,35 +323,39 @@ DECLARE_TABLES_4P(B0, "B0", b0, 7); // Candidate properties used for selection namespace hf_cand_par { -DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); //! cosine of theta star -DECLARE_SOA_COLUMN(Cpa, cpa, float); //! cosine of pointing angle -DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! cosine of pointing angle in the transverse plane -DECLARE_SOA_COLUMN(Ct, ct, float); //! proper lifetime times c -DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! decay length -DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! decay length divided by its uncertainty -DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! decay length in the transverse plane -DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! decay length in the transverse plane divided by its uncertainty -DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! impact parameter of prong 0 divided by its uncertainty -DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! impact parameter of prong 1 divided by its uncertainty -DECLARE_SOA_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, float); //! impact parameter of prong 2 divided by its uncertainty -DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! product of impact parameters of prong 0 and prong 1 -DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! see RecoDecay::maxNormalisedDeltaIP -DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! momentum magnitude of prong 0 -DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! momentum magnitude of prong 1 -DECLARE_SOA_COLUMN(PProng2, pProng2, float); //! momentum magnitude of prong 2 -DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! transverse momentum of prong 0 -DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! transverse momentum of prong 1 -DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); //! transverse momentum of prong 2 -DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); //! distance of the secondary vertex from the z axis +DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); //! cosine of theta star +DECLARE_SOA_COLUMN(Cpa, cpa, float); //! cosine of pointing angle +DECLARE_SOA_COLUMN(CpaXY, cpaXY, float); //! cosine of pointing angle in the transverse plane +DECLARE_SOA_COLUMN(Ct, ct, float); //! proper lifetime times c +DECLARE_SOA_COLUMN(DecayLength, decayLength, float); //! decay length +DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! decay length divided by its uncertainty +DECLARE_SOA_COLUMN(DecayLengthXY, decayLengthXY, float); //! decay length in the transverse plane +DECLARE_SOA_COLUMN(DecayLengthXYNormalised, decayLengthXYNormalised, float); //! decay length in the transverse plane divided by its uncertainty +DECLARE_SOA_COLUMN(ImpactParameterXi, impactParameterXi, float); //! impact parameter of the Xi prong +DECLARE_SOA_COLUMN(ImpactParameterPi0, impactParameterPi0, float); //! impact parameter of the first pion prong +DECLARE_SOA_COLUMN(ImpactParameterPi1, impactParameterPi1, float); //! impact parameter of the second pion prong +DECLARE_SOA_COLUMN(ImpactParameterNormalised0, impactParameterNormalised0, float); //! impact parameter of prong 0 divided by its uncertainty +DECLARE_SOA_COLUMN(ImpactParameterNormalised1, impactParameterNormalised1, float); //! impact parameter of prong 1 divided by its uncertainty +DECLARE_SOA_COLUMN(ImpactParameterNormalised2, impactParameterNormalised2, float); //! impact parameter of prong 2 divided by its uncertainty +DECLARE_SOA_COLUMN(ImpactParameterNormalisedXi, impactParameterNormalisedXi, float); //! impact parameter of the Xi prong divided by its uncertainty +DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi0, impactParameterNormalisedPi0, float); //! impact parameter of the first pion prong divided by its uncertainty +DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi1, impactParameterNormalisedPi1, float); //! impact parameter of the second pion prong divided by its uncertainty +DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); //! product of impact parameters of prong 0 and prong 1 +DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! see RecoDecay::maxNormalisedDeltaIP +DECLARE_SOA_COLUMN(PProng0, pProng0, float); //! momentum magnitude of prong 0 +DECLARE_SOA_COLUMN(PProng1, pProng1, float); //! momentum magnitude of prong 1 +DECLARE_SOA_COLUMN(PProng2, pProng2, float); //! momentum magnitude of prong 2 +DECLARE_SOA_COLUMN(PProngPi0, pProngPi0, float); //! momentum magnitude of the first pion prong +DECLARE_SOA_COLUMN(PProngPi1, pProngPi1, float); //! momentum magnitude of the second pion prong +DECLARE_SOA_COLUMN(PtProng0, ptProng0, float); //! transverse momentum of prong 0 +DECLARE_SOA_COLUMN(PtProng1, ptProng1, float); //! transverse momentum of prong 1 +DECLARE_SOA_COLUMN(PtProng2, ptProng2, float); //! transverse momentum of prong 2 +DECLARE_SOA_COLUMN(PtProngXi, ptProngXi, float); //! transverse momentum of the Xi prong +DECLARE_SOA_COLUMN(PtProngPi0, ptProngPi0, float); //! transverse momentum of the first pion prong +DECLARE_SOA_COLUMN(PtProngPi1, ptProngPi1, float); //! transverse momentum of the second pion prong +DECLARE_SOA_COLUMN(RSecondaryVertex, rSecondaryVertex, float); //! distance of the secondary vertex from the z axis // D*± → D0(bar) π± -DECLARE_SOA_COLUMN(MassD0, massD0, float); //! invariant mass of D0 -DECLARE_SOA_COLUMN(CpaD0, cpaD0, float); //! cosine of pointing angle of D0 -DECLARE_SOA_COLUMN(CpaXYD0, cpaXYD0, float); //! cosine of pointing angle in the transverse plane of D0 -DECLARE_SOA_COLUMN(DecayLengthD0, decayLengthD0, float); //! decay length of D0 -DECLARE_SOA_COLUMN(DecayLengthXYD0, decayLengthXYD0, float); //! decay length in the transverse plane of D0 -DECLARE_SOA_COLUMN(DecayLengthNormalisedD0, decayLengthNormalisedD0, float); //! decay length of D0 divided by its uncertainty -DECLARE_SOA_COLUMN(DecayLengthXYNormalisedD0, decayLengthXYNormalisedD0, float); //! decay length in the transverse plane of D0 divided by its uncertainty -DECLARE_SOA_COLUMN(NormalisedImpParamSoftPi, normalisedImpParamSoftPi, float); //! impact parameter of soft pion divided by its uncertainty +DECLARE_SOA_COLUMN(SignProng1, signProng1, int8_t); // TOF DECLARE_SOA_COLUMN(NSigTofKa0, nSigTofKa0, float); DECLARE_SOA_COLUMN(NSigTofKa1, nSigTofKa1, float); @@ -346,7 +370,6 @@ DECLARE_SOA_COLUMN(NSigTofPiExpKa, nSigTofPiExpKa, float); DECLARE_SOA_COLUMN(NSigTofPr0, nSigTofPr0, float); DECLARE_SOA_COLUMN(NSigTofPr1, nSigTofPr1, float); DECLARE_SOA_COLUMN(NSigTofPr2, nSigTofPr2, float); -DECLARE_SOA_COLUMN(NSigTofPiSoftPi, nSigTofPiSoftPi, float); // TPC DECLARE_SOA_COLUMN(NSigTpcKa0, nSigTpcKa0, float); DECLARE_SOA_COLUMN(NSigTpcKa1, nSigTpcKa1, float); @@ -361,7 +384,6 @@ DECLARE_SOA_COLUMN(NSigTpcPiExpKa, nSigTpcPiExpKa, float); DECLARE_SOA_COLUMN(NSigTpcPr0, nSigTpcPr0, float); DECLARE_SOA_COLUMN(NSigTpcPr1, nSigTpcPr1, float); DECLARE_SOA_COLUMN(NSigTpcPr2, nSigTpcPr2, float); -DECLARE_SOA_COLUMN(NSigTpcPiSoftPi, nSigTpcPiSoftPi, float); // TPC+TOF DECLARE_SOA_COLUMN(NSigTpcTofKa0, nSigTpcTofKa0, float); DECLARE_SOA_COLUMN(NSigTpcTofKa1, nSigTpcTofKa1, float); @@ -376,7 +398,6 @@ DECLARE_SOA_COLUMN(NSigTpcTofPiExpKa, nSigTpcTofPiExpKa, float); DECLARE_SOA_COLUMN(NSigTpcTofPr0, nSigTpcTofPr0, float); DECLARE_SOA_COLUMN(NSigTpcTofPr1, nSigTpcTofPr1, float); DECLARE_SOA_COLUMN(NSigTpcTofPr2, nSigTpcTofPr2, float); -DECLARE_SOA_COLUMN(NSigTpcTofPiSoftPi, nSigTpcTofPiSoftPi, float); } // namespace hf_cand_par // Candidate properties of the charm daughter candidate used for selection of the beauty candidate @@ -402,6 +423,12 @@ DECLARE_SOA_COLUMN(ImpactParameterNormalised1Charm, impactParameterNormalised1Ch DECLARE_SOA_COLUMN(ImpactParameterNormalised2Charm, impactParameterNormalised2Charm, float); //! impact parameter of prong 2 divided by its uncertainty DECLARE_SOA_COLUMN(ImpactParameterProductCharm, impactParameterProductCharm, float); //! product of impact parameters of prong 0 and prong 1 DECLARE_SOA_COLUMN(MaxNormalisedDeltaIPCharm, maxNormalisedDeltaIPCharm, float); //! see RecoDecay::maxNormalisedDeltaIP +DECLARE_SOA_COLUMN(PxProng0Charm, pxProng0Charm, float); //! x-component of momentum of prong 0 +DECLARE_SOA_COLUMN(PyProng0Charm, pyProng0Charm, float); //! y-component of momentum of prong 0 +DECLARE_SOA_COLUMN(PzProng0Charm, pzProng0Charm, float); //! z-component of momentum of prong 0 +DECLARE_SOA_COLUMN(PxProng1Charm, pxProng1Charm, float); //! x-component of momentum of prong 1 +DECLARE_SOA_COLUMN(PyProng1Charm, pyProng1Charm, float); //! y-component of momentum of prong 1 +DECLARE_SOA_COLUMN(PzProng1Charm, pzProng1Charm, float); //! z-component of momentum of prong 1 DECLARE_SOA_COLUMN(PProng0Charm, pProng0Charm, float); //! momentum magnitude of prong 0 DECLARE_SOA_COLUMN(PProng1Charm, pProng1Charm, float); //! momentum magnitude of prong 1 DECLARE_SOA_COLUMN(PProng2Charm, pProng2Charm, float); //! momentum magnitude of prong 2 @@ -409,6 +436,7 @@ DECLARE_SOA_COLUMN(PtProng0Charm, ptProng0Charm, float); DECLARE_SOA_COLUMN(PtProng1Charm, ptProng1Charm, float); //! transverse momentum of prong 1 DECLARE_SOA_COLUMN(PtProng2Charm, ptProng2Charm, float); //! transverse momentum of prong 2 DECLARE_SOA_COLUMN(RSecondaryVertexCharm, rSecondaryVertexCharm, float); //! distance of the secondary vertex from the z axis +DECLARE_SOA_COLUMN(InvMassCharm, invMassCharm, float); //! mass of the charm daughter // TOF DECLARE_SOA_COLUMN(NSigTofKa0Charm, nSigTofKa0Charm, float); DECLARE_SOA_COLUMN(NSigTofKa1Charm, nSigTofKa1Charm, float); @@ -842,58 +870,216 @@ DECLARE_SOA_TABLE_STAGED(HfDplusMcs, "HFDPMC", //! Table with MC candidate info o2::soa::Marker); // ---------------- -// D*+ +// Ds+ // ---------------- -DECLARE_SOA_TABLE_STAGED(HfDstarPars, "HFDSTARPAR", //! Table with candidate properties used for selection - hf_cand_dstar::Chi2PCAD0, - hf_cand_par::CpaD0, - hf_cand_par::CpaXYD0, - hf_cand_par::DecayLengthD0, - hf_cand_par::DecayLengthXYD0, - hf_cand_par::DecayLengthNormalisedD0, - hf_cand_par::DecayLengthXYNormalisedD0, - hf_cand::PxProng0, - hf_cand::PyProng0, - hf_cand::PzProng0, - hf_cand::PxProng1, - hf_cand::PyProng1, - hf_cand::PzProng1, - hf_cand_dstar::PxD0, - hf_cand_dstar::PyD0, - hf_cand_dstar::PzD0, - hf_cand_dstar::PxSoftPi, - hf_cand_dstar::PySoftPi, - hf_cand_dstar::PzSoftPi, - hf_cand_dstar::PtSoftPi, - hf_cand_dstar::SignSoftPi, - hf_cand_dstar::PtD0, - hf_cand_par::MassD0, +DECLARE_SOA_TABLE_STAGED(HfDsPars, "HFDSPAR", //! Table with candidate properties used for selection + hf_cand::Chi2PCA, + hf_cand::NProngsContributorsPV, + hf_cand_par::Cpa, + hf_cand_par::CpaXY, + hf_cand_par::DecayLength, + hf_cand_par::DecayLengthXY, + hf_cand_par::DecayLengthNormalised, + hf_cand_par::DecayLengthXYNormalised, + hf_cand_par::PtProng0, + hf_cand_par::PtProng1, + hf_cand_par::PtProng2, hf_cand::ImpactParameter0, hf_cand::ImpactParameter1, - hf_cand_dstar::ImpParamSoftPi, + hf_cand::ImpactParameter2, hf_cand_par::ImpactParameterNormalised0, hf_cand_par::ImpactParameterNormalised1, - hf_cand_par::NormalisedImpParamSoftPi, + hf_cand_par::ImpactParameterNormalised2, hf_cand_par::NSigTpcPi0, + hf_cand_par::NSigTpcKa0, hf_cand_par::NSigTofPi0, + hf_cand_par::NSigTofKa0, hf_cand_par::NSigTpcTofPi0, + hf_cand_par::NSigTpcTofKa0, hf_cand_par::NSigTpcKa1, hf_cand_par::NSigTofKa1, hf_cand_par::NSigTpcTofKa1, - hf_cand_par::NSigTpcPiSoftPi, - hf_cand_par::NSigTofPiSoftPi, - hf_cand_par::NSigTpcTofPiSoftPi, + hf_cand_par::NSigTpcPi2, + hf_cand_par::NSigTpcKa2, + hf_cand_par::NSigTofPi2, + hf_cand_par::NSigTofKa2, + hf_cand_par::NSigTpcTofPi2, + hf_cand_par::NSigTpcTofKa2, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfDsParEs, "HFDSPARE", //! 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_par::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::ErrorImpactParameter0, + hf_cand::ErrorImpactParameter1, + hf_cand::ErrorImpactParameter2, + hf_cand_par::Ct, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfDsMls, "HFDSML", //! Table with candidate selection ML scores + hf_cand_mc::MlScores, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfDsMcs, "HFDSMC", //! Table with MC candidate info + hf_cand_mc::FlagMcMatchRec, + hf_cand_mc::OriginMcRec, + hf_cand_mc::IsCandidateSwapped, + hf_cand_mc::FlagMcDecayChanRec, + o2::soa::Marker); + +// ---------------- +// D*+ +// ---------------- + +DECLARE_SOA_TABLE_STAGED(HfDstarPars, "HFDSTPAR", //! Table with candidate properties used for selection + hf_cand::PxProng0, // Prong0 is the D0 + hf_cand::PyProng0, + hf_cand::PzProng0, + hf_cand::PxProng1, // Prong1 is the soft pion + hf_cand::PyProng1, + hf_cand::PzProng1, + hf_cand::PtProng1, + hf_cand_par::SignProng1, + hf_cand::PtProng0, + hf_cand::ImpactParameter1, + hf_cand_par::ImpactParameterNormalised1, + hf_cand_par::NSigTpcPi1, + hf_cand_par::NSigTofPi1, + hf_cand_par::NSigTpcTofPi1, o2::soa::Marker); -DECLARE_SOA_TABLE_STAGED(HfDstarMls, "HFDSTARML", //! Table with candidate selection ML scores +DECLARE_SOA_TABLE_STAGED(HfDstarParD0s, "HFDSTPARD0", //! Table with candidate properties used for selection + hf_cand_par_charm::Chi2PCACharm, + hf_cand_par_charm::CpaCharm, + hf_cand_par_charm::CpaXYCharm, + hf_cand_par_charm::DecayLengthCharm, + hf_cand_par_charm::DecayLengthXYCharm, + hf_cand_par_charm::DecayLengthNormalisedCharm, + hf_cand_par_charm::DecayLengthXYNormalisedCharm, + hf_cand_par_charm::PxProng0Charm, // prong0 is the first D0 daughter + hf_cand_par_charm::PyProng0Charm, + hf_cand_par_charm::PzProng0Charm, + hf_cand_par_charm::PxProng1Charm, // prong 1 is the second D0 daughter + hf_cand_par_charm::PyProng1Charm, + hf_cand_par_charm::PzProng1Charm, + hf_cand_par_charm::InvMassCharm, + hf_cand_par_charm::ImpactParameter0Charm, + hf_cand_par_charm::ImpactParameter1Charm, + hf_cand_par_charm::ImpactParameterNormalised0Charm, + hf_cand_par_charm::ImpactParameterNormalised1Charm, + hf_cand_par_charm::NSigTpcPi0Charm, + hf_cand_par_charm::NSigTofPi0Charm, + hf_cand_par_charm::NSigTpcTofPi0Charm, + hf_cand_par_charm::NSigTpcKa0Charm, + hf_cand_par_charm::NSigTofKa0Charm, + hf_cand_par_charm::NSigTpcTofKa0Charm, + hf_cand_par_charm::NSigTpcPi1Charm, + hf_cand_par_charm::NSigTofPi1Charm, + hf_cand_par_charm::NSigTpcTofPi1Charm, + hf_cand_par_charm::NSigTpcKa1Charm, + hf_cand_par_charm::NSigTofKa1Charm, + hf_cand_par_charm::NSigTpcTofKa1Charm, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfDstarMls, "HFDSTML", //! Table with candidate selection ML scores hf_cand_mc::MlScores, o2::soa::Marker); -DECLARE_SOA_TABLE_STAGED(HfDstarMcs, "HFDSTARMC", //! Table with MC candidate info +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, o2::soa::Marker); + +// ---------------- +// Ξc± → (Ξ∓ → (Λ → p π∓) π∓) π± π± +// ---------------- + +DECLARE_SOA_TABLE_STAGED(HfXicToXiPiPiPars, "HFXICXPPPAR", //! Table with candidate properties used for selection + hf_cand_xic_to_xi_pi_pi::Sign, + hf_cand_par::PtProngXi, + hf_cand_par::PtProngPi0, + hf_cand_par::PtProngPi1, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + hf_cand::Chi2PCA, + hf_cand_par::Ct, + hf_cand_par::DecayLength, + hf_cand_par::DecayLengthNormalised, + hf_cand_par::DecayLengthXY, + hf_cand_par::DecayLengthXYNormalised, + hf_cand_par::Cpa, + hf_cand_par::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, + hf_cand_par::ImpactParameterXi, + hf_cand_par::ImpactParameterNormalisedXi, + hf_cand_par::ImpactParameterPi0, + hf_cand_par::ImpactParameterNormalisedPi0, + hf_cand_par::ImpactParameterPi1, + hf_cand_par::ImpactParameterNormalisedPi1, + hf_cand_par::MaxNormalisedDeltaIP, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfXicToXiPiPiParEs, "HFXICXPPPARE", //! Table with additional candidate properties used for selection + hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, + hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, + hf_cand_par::PProngPi0, + hf_cand_par::PProngPi1, + hf_cand_xic_to_xi_pi_pi::PBachelorPi, + hf_cand_xic_to_xi_pi_pi::PPiFromLambda, + hf_cand_xic_to_xi_pi_pi::PPrFromLambda, + hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, + hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, + hf_cand_xic_to_xi_pi_pi::DcaPosToPV, + hf_cand_xic_to_xi_pi_pi::DcaNegToPV, + hf_cand_xic_to_xi_pi_pi::DcaBachelorToPV, + hf_cand_xic_to_xi_pi_pi::DcaXYCascToPV, + hf_cand_xic_to_xi_pi_pi::DcaZCascToPV, + hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromXicPlus0, + hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromXicPlus1, + hf_cand_xic_to_xi_pi_pi::NSigTpcBachelorPi, + hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromLambda, + hf_cand_xic_to_xi_pi_pi::NSigTpcPrFromLambda, + hf_cand_xic_to_xi_pi_pi::NSigTofPiFromXicPlus0, + hf_cand_xic_to_xi_pi_pi::NSigTofPiFromXicPlus1, + hf_cand_xic_to_xi_pi_pi::NSigTofBachelorPi, + hf_cand_xic_to_xi_pi_pi::NSigTofPiFromLambda, + hf_cand_xic_to_xi_pi_pi::NSigTofPrFromLambda, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfXicToXiPiPiMls, "HFXICXPPML", //! Table with candidate selection ML scores + hf_cand_mc::MlScores, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(HfXicToXiPiPiMcs, "HFXICXPPMC", //! Table with MC candidate info + hf_cand_mc::FlagMcMatchRec, + hf_cand_mc::OriginMcRec, + o2::soa::Marker); } // namespace o2::aod #endif // PWGHF_DATAMODEL_DERIVEDTABLES_H_ diff --git a/PWGHF/HFC/DataModel/CorrelationTables.h b/PWGHF/HFC/DataModel/CorrelationTables.h index eaf0b4f3c4a..a77035b7f3f 100644 --- a/PWGHF/HFC/DataModel/CorrelationTables.h +++ b/PWGHF/HFC/DataModel/CorrelationTables.h @@ -16,16 +16,16 @@ #ifndef PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ #define PWGHF_HFC_DATAMODEL_CORRELATIONTABLES_H_ +#include "PWGHF/DataModel/CandidateReconstructionTables.h" // IWYU pragma: keep + +#include "Common/Core/RecoDecay.h" + #include -#include // NOLINT #include +#include #include -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" // NOLINT - namespace o2::aod { // definition of columns and tables for D-Dbar correlation pairs diff --git a/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h b/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h index b9425517913..39a3231977c 100644 --- a/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h +++ b/PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h @@ -22,6 +22,7 @@ namespace o2::aod { namespace hf_collisions_reduced { +DECLARE_SOA_COLUMN(NumPvContrib, numPvContrib, int); //! Event multiplicity from PV contributors DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); //! Event multiplicity DECLARE_SOA_COLUMN(PosZ, posZ, float); //! Primary vertex z position @@ -30,6 +31,7 @@ DECLARE_SOA_COLUMN(PosZ, posZ, float); //! Primary vertex z posi DECLARE_SOA_TABLE(HfcRedCollisions, "AOD", "HFCREDCOLLISION", //! Table with collision info soa::Index<>, aod::hf_collisions_reduced::Multiplicity, + aod::hf_collisions_reduced::NumPvContrib, aod::hf_collisions_reduced::PosZ); using HfcRedCollision = HfcRedCollisions::iterator; diff --git a/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx b/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx index 446dcfbe4a0..c4faa289abb 100644 --- a/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx +++ b/PWGHF/HFC/Macros/DhCorrelationExtraction.cxx @@ -16,6 +16,16 @@ #include "DhCorrelationExtraction.h" +#include +#include +#include +#include +#include +#include +#include + +#include + #include #include diff --git a/PWGHF/HFC/Macros/DhCorrelationFitter.cxx b/PWGHF/HFC/Macros/DhCorrelationFitter.cxx index 7e5157bb752..8882c567535 100644 --- a/PWGHF/HFC/Macros/DhCorrelationFitter.cxx +++ b/PWGHF/HFC/Macros/DhCorrelationFitter.cxx @@ -16,32 +16,26 @@ #include "DhCorrelationFitter.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 // IWYU pragma: keep (do not replace with TMatrixDfwd.h) +#include #include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include using namespace std; diff --git a/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx b/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx index cffe8b898c2..a2ed89ce8d9 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0D0bar.cxx @@ -14,21 +14,32 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::analysis; @@ -296,7 +307,7 @@ struct HfCorrelatorD0D0bar { efficiencyWeight = 1. / efficiencyD->at(o2::analysis::findBin(binsPt, candidate1.pt())); } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate1.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // fill per-candidate distributions from D0/D0bar true candidates registry.fill(HIST("hPtCandMCRec"), candidate1.pt()); registry.fill(HIST("hPtProng0MCRec"), candidate1.ptProng0()); @@ -307,19 +318,19 @@ struct HfCorrelatorD0D0bar { registry.fill(HIST("hSelectionStatusMCRec"), candidate1.isSelD0bar() + (candidate1.isSelD0() * 2)); } // fill invariant mass plots from D0/D0bar signal and background candidates - if (candidate1.isSelD0() >= selectionFlagD0) { // only reco as D0 - if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // also matched as D0 + if (candidate1.isSelD0() >= selectionFlagD0) { // only reco as D0 + if (candidate1.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0 registry.fill(HIST("hMassD0MCRecSig"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + } else if (candidate1.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0MCRecRefl"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } else { registry.fill(HIST("hMassD0MCRecBkg"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } } - if (candidate1.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar - if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // also matched as D0bar + if (candidate1.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar + if (candidate1.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0bar registry.fill(HIST("hMassD0barMCRecSig"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + } else if (candidate1.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0barMCRecRefl"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { registry.fill(HIST("hMassD0barMCRecBkg"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); @@ -331,8 +342,8 @@ struct HfCorrelatorD0D0bar { if (candidate1.isSelD0() < selectionFlagD0) { // discard candidates not selected as D0 in outer loop continue; } - flagD0Signal = candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) - flagD0Reflection = candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) + flagD0Signal = candidate1.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) + flagD0Reflection = candidate1.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) for (const auto& candidate2 : selectedD0CandidatesGroupedMC) { if (!(candidate2.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // check decay channel flag for candidate2 continue; @@ -340,8 +351,8 @@ struct HfCorrelatorD0D0bar { if (candidate2.isSelD0bar() < selectionFlagD0bar) { // discard candidates not selected as D0bar in inner loop continue; } - flagD0barSignal = candidate2.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) - flagD0barReflection = candidate2.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) + flagD0barSignal = candidate2.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) + flagD0barReflection = candidate2.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; } @@ -445,7 +456,7 @@ struct HfCorrelatorD0D0bar { // fill pairs vs etaCut plot bool rightDecayChannels = false; - if ((std::abs(particle1.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if ((std::abs(particle1.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { rightDecayChannels = true; } do { diff --git a/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx b/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx index 9e090a49c57..8fa93dc0d63 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0D0barBarrelFullPid.cxx @@ -14,21 +14,32 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::analysis; @@ -297,7 +308,7 @@ struct HfCorrelatorD0D0barBarrelFullPid { efficiencyWeight = 1. / efficiencyD->at(o2::analysis::findBin(binsPt, candidate1.pt())); } - if (std::abs(candidate1.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate1.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // fill per-candidate distributions from D0/D0bar true candidates registry.fill(HIST("hPtCandMCRec"), candidate1.pt()); registry.fill(HIST("hPtProng0MCRec"), candidate1.ptProng0()); @@ -308,19 +319,19 @@ struct HfCorrelatorD0D0barBarrelFullPid { registry.fill(HIST("hSelectionStatusMCRec"), candidate1.isSelD0barTofPlusRichPid() + (candidate1.isSelD0TofPlusRichPid() * 2)); } // fill invariant mass plots from D0/D0bar signal and background candidates - if (candidate1.isSelD0TofPlusRichPid() >= selectionFlagD0) { // only reco as D0 - if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // also matched as D0 + if (candidate1.isSelD0TofPlusRichPid() >= selectionFlagD0) { // only reco as D0 + if (candidate1.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0 registry.fill(HIST("hMassD0MCRecSig"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + } else if (candidate1.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0MCRecRefl"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } else { registry.fill(HIST("hMassD0MCRecBkg"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt(), efficiencyWeight); } } - if (candidate1.isSelD0barTofPlusRichPid() >= selectionFlagD0bar) { // only reco as D0bar - if (candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // also matched as D0bar + if (candidate1.isSelD0barTofPlusRichPid() >= selectionFlagD0bar) { // only reco as D0bar + if (candidate1.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0bar registry.fill(HIST("hMassD0barMCRecSig"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); - } else if (candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + } else if (candidate1.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0barMCRecRefl"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); } else { registry.fill(HIST("hMassD0barMCRecBkg"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt(), efficiencyWeight); @@ -332,8 +343,8 @@ struct HfCorrelatorD0D0barBarrelFullPid { if (candidate1.isSelD0TofPlusRichPid() < selectionFlagD0) { // discard candidates not selected as D0 in outer loop continue; } - flagD0Signal = candidate1.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) - flagD0Reflection = candidate1.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) + flagD0Signal = candidate1.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Signal 'true' if candidate1 matched to D0 (particle) + flagD0Reflection = candidate1.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Reflection 'true' if candidate1, selected as D0 (particle), is matched to D0bar (antiparticle) for (const auto& candidate2 : selectedD0candidatesGroupedMC) { if (!(candidate2.hfflag() & 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // check decay channel flag for candidate2 continue; @@ -341,8 +352,8 @@ struct HfCorrelatorD0D0barBarrelFullPid { if (candidate2.isSelD0barTofPlusRichPid() < selectionFlagD0bar) { // discard candidates not selected as D0bar in inner loop continue; } - flagD0barSignal = candidate2.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) - flagD0barReflection = candidate2.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) + flagD0barSignal = candidate2.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0barSignal 'true' if candidate2 matched to D0bar (antiparticle) + flagD0barReflection = candidate2.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0barReflection 'true' if candidate2, selected as D0bar (antiparticle), is matched to D0 (particle) if (yCandMax >= 0. && std::abs(hfHelper.yD0(candidate2)) > yCandMax) { continue; } @@ -446,7 +457,7 @@ struct HfCorrelatorD0D0barBarrelFullPid { // fill pairs vs etaCut plot bool rightDecayChannels = false; - if ((std::abs(particle1.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if ((std::abs(particle1.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) && (std::abs(particle2.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK)) { rightDecayChannels = true; } do { diff --git a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx index f2a7afc6bdc..afe123a2386 100644 --- a/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorD0Hadrons.cxx @@ -15,25 +15,46 @@ /// \author Samrangy Sadhu , INFN Bari /// \author Swapnesh Santosh Khade , IIT Indore -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#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 "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::analysis; @@ -261,6 +282,7 @@ struct HfCorrelatorD0Hadrons { AxisSpec axisTrkCount = {5, 0., 5.}; AxisSpec axisBdtScoreBkg = {100, 0., 1., "Bdt score background"}; AxisSpec axisBdtScorePrompt = {100, 0., 1., "Bdt score prompt"}; + AxisSpec axisOrigin = {10, 0., 10., "Candidate origin"}; // Histograms for Data registry.add("hPtCand", "D0, D0bar candidates", {HistType::kTH1F, {axisPtD}}); @@ -276,7 +298,7 @@ struct HfCorrelatorD0Hadrons { registry.add("hMass1D", "D0, D0bar candidates mass", {HistType::kTH1F, {axisMassD}}); registry.add("hMassD01D", "D0 candidates mass", {HistType::kTH1F, {axisMassD}}); registry.add("hMassD0bar1D", "D0bar candidates mass", {HistType::kTH1F, {axisMassD}}); - registry.add("hMLScoresVsMassVsPt", "D0, D0bar candidates massVsPt", {HistType::kTHnSparseD, {{axisBdtScoreBkg}, {axisBdtScorePrompt}, {axisMassD}, {axisPtD}}}); + registry.add("hMLScoresVsMassVsPtVsOrigin", "D0, D0bar candidates massVsPt", {HistType::kTHnSparseD, {{axisBdtScoreBkg}, {axisBdtScorePrompt}, {axisMassD}, {axisPtD}, {axisOrigin}}}); // Histograms for MC Reco registry.add("hPtCandRec", "D0, D0bar candidates - MC reco", {HistType::kTH1F, {axisPtD}}); registry.add("hPtProng0Rec", "D0, D0bar candidates prong 0 - MC reco", {HistType::kTH1F, {axisPtD}}); @@ -292,8 +314,8 @@ struct HfCorrelatorD0Hadrons { registry.add("hMassD0barRecSig", "D0bar signal candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassD0barRecRef", "D0bar reflection candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassD0barRecBg", "D0bar background candidates massVsPt - MC reco", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); - registry.add("hPtCandRecSigPrompt", "D+,Hadron candidates Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandRecSigNonPrompt", "D+,Hadron candidates Non Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandRecSigPrompt", "D0,Hadron candidates Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandRecSigNonPrompt", "D0,Hadron candidates Non Prompt - MC Reco", {HistType::kTH1F, {axisPtD}}); registry.add("hPtVsMultiplicityRecPrompt", "Multiplicity FT0M - MC Rec Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); registry.add("hPtVsMultiplicityRecNonPrompt", "Multiplicity FT0M - MC Rec Non Prompt", {HistType::kTH2F, {{axisPtD}, {axisMultFT0M}}}); registry.add("hPtParticleAssocVsCandRec", "Associated Particle - MC reco", {HistType::kTH2F, {{axisPtHadron}, {axisPtD}}}); @@ -385,7 +407,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPt"), outputMlD0[0], outputMlD0[2], hfHelper.invMassD0ToPiK(candidate), candidate.pt()); + registry.fill(HIST("hMLScoresVsMassVsPtVsOrigin"), outputMlD0[0], outputMlD0[2], hfHelper.invMassD0ToPiK(candidate), candidate.pt(), candidate.isSelD0bar() ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0Only); } if (candidate.isSelD0bar() >= selectionFlagD0bar) { registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate), candidate.pt(), efficiencyWeight); @@ -394,7 +416,7 @@ struct HfCorrelatorD0Hadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMlD0bar[iclass] = candidate.mlProbD0bar()[classMl->at(iclass)]; } - registry.fill(HIST("hMLScoresVsMassVsPt"), outputMlD0bar[0], outputMlD0bar[2], hfHelper.invMassD0barToKPi(candidate), candidate.pt()); + registry.fill(HIST("hMLScoresVsMassVsPtVsOrigin"), outputMlD0bar[0], outputMlD0bar[2], hfHelper.invMassD0barToKPi(candidate), candidate.pt(), candidate.isSelD0() ? o2::aod::hf_correlation_d0_hadron::D0D0barBoth : o2::aod::hf_correlation_d0_hadron::D0barOnly); } entryD0CandRecoInfo(hfHelper.invMassD0ToPiK(candidate), hfHelper.invMassD0barToKPi(candidate), candidate.pt(), outputMlD0[0], outputMlD0[2], outputMlD0bar[0], outputMlD0bar[2]); @@ -537,7 +559,7 @@ struct HfCorrelatorD0Hadrons { efficiencyWeight = 1. / efficiencyDmeson->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())); } - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // fill per-candidate distributions from D0/D0bar true candidates registry.fill(HIST("hPtCandRec"), candidate.pt()); registry.fill(HIST("hPtProng0Rec"), candidate.ptProng0()); @@ -548,8 +570,8 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hSelectionStatusRec"), candidate.isSelD0bar() + (candidate.isSelD0() * 2)); } // fill invariant mass plots from D0/D0bar signal and background candidates - if (candidate.isSelD0() >= selectionFlagD0) { // only reco as D0 - if (candidate.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { // also matched as D0 + if (candidate.isSelD0() >= selectionFlagD0) { // only reco as D0 + if (candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0 registry.fill(HIST("hMassD0RecSig"), hfHelper.invMassD0ToPiK(candidate), candidate.pt(), efficiencyWeight); if (isD0Prompt) { registry.fill(HIST("hPtCandRecSigPrompt"), candidate.pt()); @@ -558,7 +580,7 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hPtCandRecSigNonPrompt"), candidate.pt()); registry.fill(HIST("hPtVsMultiplicityRecNonPrompt"), candidate.pt(), collision.multFT0M()); } - } else if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { + } else if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0RecRef"), hfHelper.invMassD0ToPiK(candidate), candidate.pt(), efficiencyWeight); } else { registry.fill(HIST("hMassD0RecBg"), hfHelper.invMassD0ToPiK(candidate), candidate.pt(), efficiencyWeight); @@ -567,8 +589,8 @@ struct HfCorrelatorD0Hadrons { outputMlD0[iclass] = candidate.mlProbD0()[classMl->at(iclass)]; } } - if (candidate.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar - if (candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK)) { // also matched as D0bar + if (candidate.isSelD0bar() >= selectionFlagD0bar) { // only reco as D0bar + if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // also matched as D0bar registry.fill(HIST("hMassD0barRecSig"), hfHelper.invMassD0barToKPi(candidate), candidate.pt(), efficiencyWeight); if (isD0Prompt) { registry.fill(HIST("hPtCandRecSigPrompt"), candidate.pt()); @@ -577,7 +599,7 @@ struct HfCorrelatorD0Hadrons { registry.fill(HIST("hPtCandRecSigNonPrompt"), candidate.pt()); registry.fill(HIST("hPtVsMultiplicityRecNonPrompt"), candidate.pt(), collision.multFT0M()); } - } else if (candidate.flagMcMatchRec() == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + } else if (candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMassD0barRecRef"), hfHelper.invMassD0barToKPi(candidate), candidate.pt(), efficiencyWeight); } else { registry.fill(HIST("hMassD0barRecBg"), hfHelper.invMassD0barToKPi(candidate), candidate.pt(), efficiencyWeight); @@ -595,8 +617,8 @@ struct HfCorrelatorD0Hadrons { // ============== D-h correlation dedicated section ==================================== - flagD0 = candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Signal 'true' if candidate matched to D0 (particle) - flagD0bar = candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate, selected as D0 (particle), is matched to D0bar (antiparticle) + flagD0 = candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Signal 'true' if candidate matched to D0 (particle) + flagD0bar = candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Reflection 'true' if candidate, selected as D0 (particle), is matched to D0bar (antiparticle) // ========== track loop starts here ======================== @@ -720,7 +742,7 @@ struct HfCorrelatorD0Hadrons { if (std::abs(particleTrigg.pdgCode()) != Pdg::kD0) { continue; } - if (std::abs(particleTrigg.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(particleTrigg.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { double yD = RecoDecay::y(particleTrigg.pVector(), MassD0); if (yCandMax >= 0. && std::abs(yD) > yCandMax) { continue; @@ -952,8 +974,8 @@ struct HfCorrelatorD0Hadrons { } } - flagD0 = candidate.flagMcMatchRec() == (1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Signal 'true' if candidate matched to D0 (particle) - flagD0bar = candidate.flagMcMatchRec() == -(1 << aod::hf_cand_2prong::DecayType::D0ToPiK); // flagD0Reflection 'true' if candidate, selected as D0 (particle), is matched to D0bar (antiparticle) + flagD0 = candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Signal 'true' if candidate matched to D0 (particle) + flagD0bar = candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; // flagD0Reflection 'true' if candidate, selected as D0 (particle), is matched to D0bar (antiparticle) int signalStatus = 0; if (flagD0 && (candidate.isSelD0() >= selectionFlagD0)) { @@ -1030,7 +1052,7 @@ struct HfCorrelatorD0Hadrons { if (std::abs(particleTrigg.pdgCode()) != Pdg::kD0) { continue; } - if (std::abs(particleTrigg.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(particleTrigg.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { double yD = RecoDecay::y(particleTrigg.pVector(), MassD0); if (std::abs(yD) >= yCandMax || particleTrigg.pt() <= ptCandMin || std::abs(particleAssoc.eta()) >= etaTrackMax || particleAssoc.pt() <= ptTrackMin) { continue; diff --git a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx index ee0ab36ce91..8616569468c 100644 --- a/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDMesonPairs.cxx @@ -14,24 +14,39 @@ /// /// \author Andrea Tavira García , IJCLab Orsay -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseD0ToKPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/DMesonPairsTables.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 + using namespace o2; using namespace o2::analysis; using namespace o2::constants::physics; @@ -75,6 +90,7 @@ struct HfCorrelatorDMesonPairs { Configurable massCut{"massCut", 0.05, "Maximum deviation from PDG peak allowed for signal region"}; Configurable daughterTracksCutFlag{"daughterTracksCutFlag", false, "Flag to add cut on daughter tracks"}; Configurable removeAmbiguous{"removeAmbiguous", false, "Flag to remove ambiguous candidates"}; + Configurable ptMaxRemoveAmbiguous{"ptMaxRemoveAmbiguous", 5.0, "Max. pT to remove the ambiguous candidates"}; // ML inference Configurable applyMl{"applyMl", false, "Flag to apply ML selections"}; @@ -311,10 +327,10 @@ struct HfCorrelatorDMesonPairs { SETBIT(candidateType, SelectedDbar); } if constexpr (isMcRec) { - if (candidate.flagMcMatchRec() == 1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK) { // matched as D0 + if (candidate.flagMcMatchRec() == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // matched as D0 SETBIT(candidateType, TrueD); } - if (candidate.flagMcMatchRec() == -(1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK)) { // matched as D0bar + if (candidate.flagMcMatchRec() == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { // matched as D0bar SETBIT(candidateType, TrueDbar); } } @@ -517,18 +533,18 @@ struct HfCorrelatorDMesonPairs { { // Fill hMatchingMcRec - Cand 1 registry.fill(HIST("hMatchingMcRec"), 1); - if (matchedRec1 == 1) { + if (matchedRec1 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcRec"), 2); - } else if (matchedRec1 == -1) { + } else if (matchedRec1 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcRec"), 3); } else if (matchedRec1 == 0) { registry.fill(HIST("hMatchingMcRec"), 4); } // Fill hMatchingMcRec - Cand 2 registry.fill(HIST("hMatchingMcRec"), 5); - if (matchedRec2 == 1) { + if (matchedRec2 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcRec"), 6); - } else if (matchedRec2 == -1) { + } else if (matchedRec2 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcRec"), 7); } else if (matchedRec2 == 0) { registry.fill(HIST("hMatchingMcRec"), 8); @@ -612,7 +628,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand1 && isDbarCand1)) { + if (removeAmbiguous && (isDCand1 && isDbarCand1) && candidate1.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -687,7 +703,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand2 && isDbarCand2)) { + if (removeAmbiguous && (isDCand2 && isDbarCand2) && candidate2.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -776,7 +792,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand1 && isDbarCand1)) { + if (removeAmbiguous && (isDCand1 && isDbarCand1) && candidate1.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -803,10 +819,10 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hMass"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); registry.fill(HIST("hNContribMcRec"), collision.numContrib()); - if (originRec1 == 1) { + if (originRec1 == RecoDecay::Prompt) { registry.fill(HIST("hMassMcRecPrompt"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRecPrompt"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); - } else if (originRec1 == 2) { + } else if (originRec1 == RecoDecay::NonPrompt) { registry.fill(HIST("hMassMcRecNonPrompt"), hfHelper.invMassD0ToPiK(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRecNonPrompt"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); } @@ -824,9 +840,9 @@ struct HfCorrelatorDMesonPairs { registry.fill(HIST("hMass"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); registry.fill(HIST("hPtVsYVsNContribMcRec"), candidate1.pt(), hfHelper.yD0(candidate1), collision.numContrib()); registry.fill(HIST("hNContribMcRec"), collision.numContrib()); - if (originRec1 == 1) { + if (originRec1 == RecoDecay::Prompt) { registry.fill(HIST("hMassMcRecPrompt"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); - } else if (originRec1 == 2) { + } else if (originRec1 == RecoDecay::NonPrompt) { registry.fill(HIST("hMassMcRecNonPrompt"), hfHelper.invMassD0barToKPi(candidate1), candidate1.pt()); } } else if (isTrueDCand1) { @@ -893,7 +909,7 @@ struct HfCorrelatorDMesonPairs { } // Remove ambiguous D0 candidates if flag is true - if (removeAmbiguous && (isDCand2 && isDbarCand2)) { + if (removeAmbiguous && (isDCand2 && isDbarCand2) && candidate2.pt() < ptMaxRemoveAmbiguous) { continue; } @@ -1011,10 +1027,10 @@ struct HfCorrelatorDMesonPairs { } registry.fill(HIST("hPtVsYVsNContribMcGen"), particle1.pt(), particle1.y(), numPvContributorsGen); - if (originGen1 == 1) { + if (originGen1 == RecoDecay::Prompt) { registry.fill(HIST("hPtVsYVsNContribMcGenPrompt"), particle1.pt(), particle1.y(), numPvContributorsGen); } - if (originGen1 == 2) { + if (originGen1 == RecoDecay::NonPrompt) { registry.fill(HIST("hPtVsYVsNContribMcGenNonPrompt"), particle1.pt(), particle1.y(), numPvContributorsGen); } registry.fill(HIST("hNContribMcGen"), numPvContributorsGen); @@ -1042,18 +1058,18 @@ struct HfCorrelatorDMesonPairs { // Fill hMatchingMcGen - Cand 1 registry.fill(HIST("hMatchingMcGen"), 1); - if (matchedGen1 == 1) { + if (matchedGen1 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcGen"), 2); - } else if (matchedGen1 == -1) { + } else if (matchedGen1 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcGen"), 3); } else if (matchedGen1 == 0) { registry.fill(HIST("hMatchingMcGen"), 4); } // Fill hMatchingMcRec - Cand 2 registry.fill(HIST("hMatchingMcGen"), 5); - if (matchedGen2 == 1) { + if (matchedGen2 == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcGen"), 6); - } else if (matchedGen2 == -1) { + } else if (matchedGen2 == -o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { registry.fill(HIST("hMatchingMcGen"), 7); } else if (matchedGen2 == 0) { registry.fill(HIST("hMatchingMcGen"), 8); diff --git a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx index 3cbee2b072a..e4c2e0fe6bb 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusDminus.cxx @@ -14,21 +14,32 @@ /// /// \author Fabio Colamaria , INFN Bari -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx index a1a8941779b..c10865e21d2 100644 --- a/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDplusHadrons.cxx @@ -13,24 +13,41 @@ /// \brief D+-Hadrons correlator task - data-like, MC-reco and MC-Gen analyses /// \author Shyam Kumar -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#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 "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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::analysis; diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx index 2b9ea57bfd5..c788f35dd92 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadrons.cxx @@ -14,26 +14,44 @@ /// \author Grazia Luparello /// \author Samuele Cattaruzzi -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#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 "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h" +#include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::analysis; @@ -41,6 +59,7 @@ using namespace o2::constants::physics; using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::analysis::hf_correlations; enum ResonantChannel : int8_t { PhiPi = 1, @@ -162,6 +181,8 @@ struct HfCorrelatorDsHadrons { Configurable removeCollWSplitVtx{"removeCollWSplitVtx", false, "Flag for rejecting the splitted collisions"}; Configurable useSel8{"useSel8", true, "Flag for applying sel8 for collision selection (used only in MC processes)"}; Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing (used only in MC processes)"}; + Configurable pidTrkApplied{"pidTrkApplied", false, "Apply PID selection for associated tracks"}; + Configurable forceTOF{"forceTOF", false, "force the TOF signal for the PID"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds (avoid the case of flag = 0, no outputMlScore)"}; Configurable numberEventsMixed{"numberEventsMixed", 5, "Number of events mixed in ME process"}; Configurable decayChannel{"decayChannel", 1, "Resonant decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; @@ -175,13 +196,19 @@ struct HfCorrelatorDsHadrons { Configurable ptCandMax{"ptCandMax", 50., "max. cand pT"}; Configurable ptTrackMin{"ptTrackMin", 0.3, "min. track pT"}; Configurable ptTrackMax{"ptTrackMax", 50., "max. track pT"}; + Configurable zVtxMax{"zVtxMax", 10., "max. position-z of the reconstructed collision"}; + Configurable tofPIDThreshold{"tofPIDThreshold", 0.75, "minimum pT after which TOF PID is applicable"}; Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; + 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> pidTPCMax{"pidTPCMax", std::vector{3., 0., 0.}, "maximum nSigma TPC"}; + Configurable> pidTOFMax{"pidTOFMax", std::vector{3., 0., 0.}, "maximum nSigma TOF"}; Configurable> binsPtD{"binsPtD", std::vector{o2::analysis::hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits for candidate mass plots"}; Configurable> binsPtHadron{"binsPtHadron", std::vector{0.3, 2., 4., 8., 12., 50.}, "pT bin limits for assoc particle"}; Configurable> binsPtEfficiencyD{"binsPtEfficiencyD", std::vector{o2::analysis::hf_cuts_ds_to_k_k_pi::vecBinsPt}, "pT bin limits for efficiency"}; Configurable> efficiencyD{"efficiencyD", {1., 1., 1., 1., 1., 1.}, "efficiency values for Ds meson"}; int hfcReducedCollisionIndex = 0; + static constexpr std::size_t NDaughtersDs{3u}; HfHelper hfHelper; SliceCache cache; @@ -231,6 +258,7 @@ struct HfCorrelatorDsHadrons { AxisSpec axisStatus = {15, 0.5, 15.5, "Selection status"}; // Histograms for data analysis + registry.add("hCollisionPoolBin", "Ds candidates collision pool bin", {HistType::kTH1F, {axisPoolBin}}); if (fillHistoData) { registry.add("hPtCand", "Ds candidates pt", {HistType::kTH1F, {axisPtD}}); registry.add("hSelectionStatusDsToKKPi", "Ds candidates selection", {HistType::kTH1F, {axisStatus}}); @@ -247,7 +275,6 @@ struct HfCorrelatorDsHadrons { registry.add("hZVtx", "z vertex", {HistType::kTH1F, {axisPosZ}}); registry.add("hMassDsVsPt", "Ds candidates massVsPt", {HistType::kTH2F, {{axisMassD}, {axisPtD}}}); registry.add("hMassDsData", "Ds candidates mass", {HistType::kTH1F, {axisMassD}}); - registry.add("hCollisionPoolBin", "Ds candidates collision pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hDsPoolBin", "Ds candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); } @@ -284,6 +311,12 @@ struct HfCorrelatorDsHadrons { registry.add("hEtaMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); registry.add("hPhiMcGen", "Ds,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); registry.add("hMultFT0AMcGen", "Ds,Hadron multiplicity FT0A - MC Gen", {HistType::kTH1F, {axisMultiplicity}}); + registry.add("hCorrAllPrimaryParticles", "Ds-ch. part. correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryHadrons", "Ds-h correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryPions", "Ds-pion correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryKaons", "Ds-kaon correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hCorrAllPrimaryProtons", "Ds-proton correlations MC Gen", {HistType::kTH3F, {{axisPhi}, {axisPtD}, {axisPtHadron}}}); + registry.add("hFakeCollision", "Fake collision counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake coll"}}}); } } @@ -633,7 +666,7 @@ struct HfCorrelatorDsHadrons { if (useSel8 && !collision.sel8()) { continue; } - if (std::abs(collision.posZ()) > 10.) { + if (std::abs(collision.posZ()) > zVtxMax) { continue; } if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { @@ -666,7 +699,7 @@ struct HfCorrelatorDsHadrons { listDaughters.clear(); RecoDecay::getDaughters(particle, &listDaughters, arrDaughDsPDG, 2); int counterDaughters = 0; - if (listDaughters.size() == 3) { + if (listDaughters.size() == NDaughtersDs) { for (const auto& dauIdx : listDaughters) { // auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); auto daughI = groupedMcParticles.rawIteratorAt(dauIdx - groupedMcParticles.offset()); @@ -688,6 +721,21 @@ 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()); + } + } + // trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); trackOrigin = RecoDecay::getCharmHadronOrigin(groupedMcParticles, particleAssoc, true); registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); @@ -721,18 +769,20 @@ struct HfCorrelatorDsHadrons { // Ds fill histograms and Ds candidates information stored for (const auto& candidate : candsDsThisColl) { std::vector outputMl = {-1., -1., -1.}; + auto prong0 = candidate.template prong0_as(); + int chargeDs = prong0.sign(); // candidate selected if (candidate.isSelDsToKKPi() >= selectionFlagDs) { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMl[iclass] = candidate.mlProbDsToKKPi()[classMl->at(iclass)]; } - candReduced(indexHfcReducedCollision, candidate.phi(), candidate.eta(), candidate.pt(), hfHelper.invMassDsToKKPi(candidate), candidate.prong0Id(), candidate.prong1Id(), candidate.prong2Id()); + candReduced(indexHfcReducedCollision, candidate.phi(), candidate.eta(), candidate.pt() * chargeDs, hfHelper.invMassDsToKKPi(candidate), candidate.prong0Id(), candidate.prong1Id(), candidate.prong2Id()); candSelInfo(indexHfcReducedCollision, outputMl[0], outputMl[2]); } else if (candidate.isSelDsToPiKK() >= selectionFlagDs) { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; } - candReduced(indexHfcReducedCollision, candidate.phi(), candidate.eta(), candidate.pt(), hfHelper.invMassDsToPiKK(candidate), candidate.prong0Id(), candidate.prong1Id(), candidate.prong2Id()); + candReduced(indexHfcReducedCollision, candidate.phi(), candidate.eta(), candidate.pt() * chargeDs, hfHelper.invMassDsToPiKK(candidate), candidate.prong0Id(), candidate.prong1Id(), candidate.prong2Id()); candSelInfo(indexHfcReducedCollision, outputMl[0], outputMl[2]); } } @@ -742,11 +792,15 @@ struct HfCorrelatorDsHadrons { if (!track.isGlobalTrackWoDCA()) { continue; } - assocTrackReduced(indexHfcReducedCollision, track.globalIndex(), track.phi(), track.eta(), track.pt()); + if (pidTrkApplied) { + if (!passPIDSelection(track, trkPIDspecies, pidTPCMax, pidTOFMax, tofPIDThreshold, forceTOF)) + continue; + } + assocTrackReduced(indexHfcReducedCollision, track.globalIndex(), track.phi(), track.eta(), track.pt() * track.sign()); assocTrackSelInfo(indexHfcReducedCollision, track.tpcNClsCrossedRows(), track.itsClusterMap(), track.itsNCls(), track.dcaXY(), track.dcaZ()); } - collReduced(collision.multFT0M(), collision.posZ()); + collReduced(collision.multFT0M(), collision.numContrib(), collision.posZ()); } } PROCESS_SWITCH(HfCorrelatorDsHadrons, processDerivedDataDs, "Process derived data Ds", false); diff --git a/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx b/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx index d005659cc69..5684619dd3f 100644 --- a/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDsHadronsReduced.cxx @@ -13,19 +13,30 @@ /// \brief Ds-Hadrons correlator task for offline analysis /// \author Samuele Cattaruzzi -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/DataModel/DerivedDataCorrelationTables.h" +#include "Common/Core/RecoDecay.h" + +#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::constants::physics; using namespace o2::constants::math; using namespace o2::framework; diff --git a/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx index 849d15e9013..1a4cafe02ac 100644 --- a/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorDstarHadrons.cxx @@ -15,24 +15,36 @@ /// \brief Correlator for D* and hadrons. This task is used to produce table for D* and hadron pairs. -// c++ -#include - -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -// O2Physics -#include "Common/DataModel/Multiplicity.h" - -// PWGHF #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/Utils/utilsAnalysis.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 + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx index 25b5d476269..3469c1fad69 100644 --- a/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorHfeHadrons.cxx @@ -14,37 +14,45 @@ /// \author Rashi Gupta , IIT Indore /// \author Ravindra Singh , IIT Indore -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" -#include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/HFC/DataModel/CorrelationTables.h" -#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" +#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::aod::hf_sel_electron; + std::vector zBins{VARIABLE_WIDTH, -10.0, -2.5, 2.5, 10.0}; std::vector multBins{VARIABLE_WIDTH, 0., 200., 500.0, 5000.}; std::vector multBinsMcGen{VARIABLE_WIDTH, 0., 20., 50.0, 500.}; // In MCGen multiplicity is defined by counting primaries using BinningType = ColumnBinningPolicy>; BinningType corrBinning{{zBins, multBins}, true}; using BinningTypeMcGen = ColumnBinningPolicy; -struct HfCorrelatorHfeHadrons { +struct HfCorrelatorHfeHadrons { Produces entryElectronHadronPair; Produces entryElectronHadronPairmcGen; Produces entryElectron; @@ -54,6 +62,7 @@ struct HfCorrelatorHfeHadrons { Configurable zPvPosMax{"zPvPosMax", 10., "Maximum z of the primary vertex (cm)"}; Configurable isRun3{"isRun3", true, "Data is from Run3 or Run2"}; + Configurable numberEventsMixed{"numberEventsMixed", 5, "number of events mixed in ME process"}; // Associated Hadron selection Configurable ptTrackMin{"ptTrackMin", 0.1f, "Transverse momentum range for associated hadron tracks"}; Configurable etaTrackMax{"etaTrackMax", 0.8f, "Eta range for associated hadron tracks"}; @@ -143,12 +152,17 @@ struct HfCorrelatorHfeHadrons { int gCollisionId = collision.globalIndex(); int64_t timeStamp = bc.timestamp(); + // Add hadron Table For Mix Event Electron Hadron correlation + for (const auto& hTrack : tracks) { + registry.fill(HIST("hTracksBin"), poolBin); + entryHadron(hTrack.phi(), hTrack.eta(), hTrack.pt(), poolBin, gCollisionId, timeStamp); + } + // Construct Deta Phi between electrons and hadrons double ptElectron = -999; double phiElectron = -999; double etaElectron = -999; - int nElectron = 0; for (const auto& eTrack : electron) { ptElectron = eTrack.ptTrack(); @@ -190,10 +204,9 @@ struct HfCorrelatorHfeHadrons { if (!selAssoHadron(hTrack)) { continue; } - if (nElectron == 0) { - registry.fill(HIST("hTracksBin"), poolBin); - entryHadron(phiHadron, etaHadron, ptHadron, poolBin, gCollisionId, timeStamp); - } + ptHadron = hTrack.pt(); + phiHadron = hTrack.phi(); + etaHadron = hTrack.eta(); if (hTrack.globalIndex() == eTrack.trackId()) { continue; } @@ -201,9 +214,6 @@ struct HfCorrelatorHfeHadrons { if (ptCondition && (ptElectron < ptHadron)) { continue; } - ptHadron = hTrack.pt(); - phiHadron = hTrack.phi(); - etaHadron = hTrack.eta(); deltaPhi = RecoDecay::constrainAngle(phiElectron - phiHadron, -o2::constants::math::PIHalf); deltaEta = etaElectron - etaHadron; @@ -228,7 +238,7 @@ struct HfCorrelatorHfeHadrons { entryElectronHadronPair(deltaPhi, deltaEta, ptElectron, ptHadron, poolBin, nElHadLSCorr, nElHadUSCorr); } // end Hadron Track loop - nElectron++; + } // end Electron loop } @@ -377,7 +387,7 @@ struct HfCorrelatorHfeHadrons { void processDataMixedEvent(TableCollisions const& collision, aod::HfCorrSelEl const& electron, TableTracks const& tracks) { auto tracksTuple = std::make_tuple(electron, tracks); - Pair pair{corrBinning, 5, -1, collision, tracksTuple, &cache}; + Pair pair{corrBinning, numberEventsMixed, -1, collision, tracksTuple, &cache}; // loop over the rows of the new table for (const auto& [c1, tracks1, c2, tracks2] : pair) { @@ -392,7 +402,7 @@ struct HfCorrelatorHfeHadrons { void processMcRecMixedEvent(McTableCollisions const& mccollision, aod::HfCorrSelEl const& electron, McTableTracks const& mcTracks) { auto tracksTuple = std::make_tuple(electron, mcTracks); - Pair pairMcRec{corrBinning, 5, -1, mccollision, tracksTuple, &cache}; + Pair pairMcRec{corrBinning, numberEventsMixed, -1, mccollision, tracksTuple, &cache}; // loop over the rows of the new table for (const auto& [c1, tracks1, c2, tracks2] : pairMcRec) { diff --git a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx index c76ec3d62d2..22770502878 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcHadrons.cxx @@ -16,27 +16,47 @@ /// \author Zhen Zhang /// \author Ravindra Singh -#include -#include "TRandom3.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#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 "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::analysis; @@ -45,6 +65,7 @@ using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::analysis::hf_correlations; + /// /// Returns deltaPhi values in range [-pi/2., 3.*pi/2.], typically used for correlation studies /// @@ -211,7 +232,7 @@ struct HfCorrelatorLcHadrons { Service pdg; int leadingIndex = 0; bool correlationStatus = false; - static constexpr size_t nDaughters{3u}; + static constexpr std::size_t NDaughters{3u}; TRandom3* rnd = new TRandom3(0); // Event Mixing for the Data Mode @@ -232,8 +253,10 @@ struct HfCorrelatorLcHadrons { Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); - // Preslice perTrueCollision = o2::aod::mcparticle::McCollisionId; Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; + Preslice perCollisionID = aod::track::collisionId; + Preslice cand3ProngPerCol = aod::hf_cand::collisionId; + // configurable axis definition 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"}; @@ -441,7 +464,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPKPi(candidate), false); entryLcHadronGenInfo(false, false, 0); entryLcHadronMlInfo(outputMl[0], outputMl[1]); @@ -457,7 +480,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPiKP(candidate), false); entryLcHadronGenInfo(false, false, 0); entryLcHadronMlInfo(outputMl[0], outputMl[1]); @@ -694,7 +717,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPKPi(candidate), isLcSignal); if (fillTrkPID) { entryLcHadronPairTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); @@ -724,7 +747,7 @@ struct HfCorrelatorLcHadrons { track.pt() * track.sign(), poolBin, correlationStatus); - entryLcHadronPairY(track.y() - hfHelper.yLc(candidate)); + entryLcHadronPairY(track.rapidity(MassProton) - hfHelper.yLc(candidate)); // only for proton as of now entryLcHadronRecoInfo(hfHelper.invMassLcToPiKP(candidate), isLcSignal); if (fillTrkPID) { entryLcHadronPairTrkPID(track.tpcNSigmaPr(), track.tpcNSigmaKa(), track.tpcNSigmaPi(), track.tofNSigmaPr(), track.tofNSigmaKa(), track.tofNSigmaPi()); @@ -801,12 +824,12 @@ struct HfCorrelatorLcHadrons { // prompt and non-prompt division std::vector listDaughters{}; - std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; - std::array prongsId; + std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; + std::array prongsId; listDaughters.clear(); RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); int counterDaughters = 0; - if (listDaughters.size() == nDaughters) { + if (listDaughters.size() == NDaughters) { for (const auto& dauIdx : listDaughters) { auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); counterDaughters += 1; diff --git a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx index 77c31d17969..b06f67990a9 100644 --- a/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx +++ b/PWGHF/HFC/TableProducer/correlatorLcScHadrons.cxx @@ -16,28 +16,51 @@ /// \author Zhen Zhang /// \author Ravindra Singh -#include -#include "TRandom3.h" - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#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 "CommonConstants/MathConstants.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::analysis; @@ -60,7 +83,7 @@ using BinningTypeMcGen = ColumnBinningPolicy lcSel; + Produces candSel; 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"}; @@ -75,54 +98,42 @@ struct HfCorrelatorLcScHadronsSelection { using SelCollisions = soa::Join; using CandsLcDataFiltered = soa::Filtered>; using CandsLcMcRecFiltered = soa::Filtered>; + using CandsScMcRec = soa::Join; using CandidatesLcMcGen = soa::Join; - + using CandidatesScMcGen = soa::Join; // filter on selection of Lc and decay channel Lc->PKPi Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); - /// Code to select collisions with at least one Lc - for real data and data-like analysis - void processLcSelectionData(SelCollisions::iterator const& collision, - CandsLcDataFiltered const& candidates) + template + void selectionCollision(CollType const& collision, CandType const& candidates) { bool isSelColl = true; - bool isLcFound = true; + bool isCandFound = false; bool isSel8 = true; bool isNosameBunchPileUp = true; + double yCand = -999.; + const int chargeZero = 0; if (doSelLcCollision) { for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yLc(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - isLcFound = false; - continue; + + if constexpr (isCandSc) { + int8_t chargeCand = candidate.charge(); + + if (chargeCand == chargeZero) { + yCand = hfHelper.ySc0(candidate); + } else { + yCand = hfHelper.yScPlusPlus(candidate); + } + + } else { + yCand = hfHelper.yLc(candidate); } - isLcFound = true; - break; - } - } - if (useSel8) { - isSel8 = collision.sel8(); - } - if (selNoSameBunchPileUpColl) { - isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); - } - isSelColl = isLcFound && isSel8 && isNosameBunchPileUp; - lcSel(isSelColl); - } - PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionData, "Process Lc Collision Selection Data", true); - void processLcSelectionMcRec(SelCollisions::iterator const& collision, - CandsLcMcRecFiltered const& candidates) - { - bool isSelColl = true; - bool isLcFound = true; - bool isSel8 = true; - bool isNosameBunchPileUp = true; - if (doSelLcCollision) { - for (const auto& candidate : candidates) { - if (std::abs(hfHelper.yLc(candidate)) > yCandMax || candidate.pt() < ptCandMin) { - isLcFound = false; + if (std::abs(yCand) > yCandMax || candidate.pt() < ptCandMin) { + isCandFound = false; continue; } - isLcFound = true; + isCandFound = true; break; } } @@ -132,31 +143,76 @@ struct HfCorrelatorLcScHadronsSelection { if (selNoSameBunchPileUpColl) { isNosameBunchPileUp = static_cast(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)); } - isSelColl = isLcFound && isSel8 && isNosameBunchPileUp; - lcSel(isSelColl); + isSelColl = isCandFound && isSel8 && isNosameBunchPileUp; + candSel(isSelColl); } - PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcRec, "Process Lc Selection McRec", false); - void processLcSelectionMcGen(aod::McCollision const&, - CandidatesLcMcGen const& mcParticles) + template + void selectionCollisionMcGen(CandType const& mcParticles) { - bool isLcFound = true; + bool isCandFound = false; + double massCand = -999.0; for (const auto& particle : mcParticles) { - if (std::abs(particle.pdgCode()) != Pdg::kLambdaCPlus) { - isLcFound = false; + + isCandFound = matchCandAndMass(particle, massCand); + if (!isCandFound) { continue; } - double yL = RecoDecay::y(particle.pVector(), MassLambdaCPlus); - if (std::abs(yL) > yCandMax || particle.pt() < ptCandMin) { - isLcFound = false; + + double yCand = RecoDecay::y(particle.pVector(), massCand); + if (std::abs(yCand) > yCandMax || particle.pt() < ptCandMin) { + isCandFound = false; continue; } - isLcFound = true; + + isCandFound = true; break; } - lcSel(isLcFound); + candSel(isCandFound); + } + + /// Code to select collisions with at least one Lc - for real data and data-like analysis + void processLcSelection(SelCollisions::iterator const& collision, + CandsLcDataFiltered const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelection, "Process Lc Collision Selection for Data and Mc", true); + + void processScSelection(SelCollisions::iterator const& collision, + aod::HfCandSc const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelection, "Process Sc Collision Selection for Data and Mc", false); + + void processLcSelectionMcRec(SelCollisions::iterator const& collision, + CandsLcMcRecFiltered const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcRec, "Process Lc Selection McRec", false); + + void processScSelectionMcRec(SelCollisions::iterator const& collision, + CandsScMcRec const& candidates) + { + selectionCollision(collision, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelectionMcRec, "Process Sc Selection McRec", false); + + void processLcSelectionMcGen(aod::McCollision const&, + CandidatesLcMcGen const& mcParticles) + { + selectionCollisionMcGen(mcParticles); } PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processLcSelectionMcGen, "Process Lc Selection McGen", false); + + void processScSelectionMcGen(aod::McCollision const&, + CandidatesScMcGen const& mcParticles) + { + selectionCollisionMcGen(mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadronsSelection, processScSelectionMcGen, "Process Lc Selection McGen", false); }; // Lc-Hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via Mc truth) @@ -212,6 +268,8 @@ struct HfCorrelatorLcScHadrons { HfHelper hfHelper; SliceCache cache; Service pdg; + int8_t chargeCand = 3; + int8_t signSoftPion = 0; int leadingIndex = 0; int poolBin = 0; int poolBinLc = 0; @@ -219,17 +277,19 @@ struct HfCorrelatorLcScHadrons { bool isPrompt = false; bool isNonPrompt = false; bool isSignal = false; + const int8_t chargeScPlusPlus = 2; + const int8_t chargeZero = 0; + const int8_t assignedChargeSc0 = 1; // to distingush sc0 from anti-sc0, charge set to +1 and -1 - static constexpr size_t NDaughters{3u}; TRandom3* rnd = new TRandom3(0); - std::vector outputMl = {-1., -1., -1.}; + // std::vector outputMl = {-1., -1., -1.}; std::vector outputMlPKPi = {-1., -1., -1.}; std::vector outputMlPiKP = {-1., -1., -1.}; // Event Mixing for the Data Mode - using SelCollisionsWithSc = soa::Join; - using SelCollisionsWithLc = soa::Filtered>; - using SelCollisionsWithLcMc = soa::Filtered>; // collisionFilter applied + // using SelCollisionsWithSc = soa::Join; + using SelCollisions = soa::Filtered>; + using SelCollisionsMc = soa::Filtered>; // collisionFilter applied using CandsLcData = soa::Join; using CandsLcDataFiltered = soa::Filtered; @@ -238,6 +298,8 @@ struct HfCorrelatorLcScHadrons { using CandsLcMcRec = soa::Join; using CandsLcMcRecFiltered = soa::Filtered; using CandidatesLcMcGen = soa::Join; // flagLcFilter applied + using CandsScMcRec = soa::Join; + using CandidatesScMcGen = soa::Join; // Event Mixing for the MCGen Mode using McCollisionsSel = soa::Filtered>; using McParticlesSel = soa::Filtered; @@ -249,8 +311,11 @@ struct HfCorrelatorLcScHadrons { Filter lcFilter = ((o2::aod::hf_track_index::hfflag & static_cast(1 << aod::hf_cand_3prong::DecayType::LcToPKPi)) != static_cast(0)) && (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); Filter trackFilter = (nabs(aod::track::eta) < etaTrackMax) && (nabs(aod::track::pt) > ptTrackMin) && (nabs(aod::track::dcaXY) < dcaXYTrackMax) && (nabs(aod::track::dcaZ) < dcaZTrackMax); - // Preslice perTrueCollision = o2::aod::mcparticle::McCollisionId; Preslice perTrueCollision = o2::aod::mcparticle::mcCollisionId; + Preslice perCollisionID = aod::track::collisionId; + Preslice cand3ProngPerCol = aod::hf_cand::collisionId; + Preslice csndScPerCol = aod::hf_cand::collisionId; + // configurable axis definition 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"}; @@ -279,7 +344,7 @@ struct HfCorrelatorLcScHadrons { AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; AxisSpec axisPoolBin = {binsPoolBin, "PoolBin"}; AxisSpec axisRapidity = {100, -2, 2, "Rapidity"}; - AxisSpec axisSign = {2, -1, 1, "Sign"}; + AxisSpec axisSign = {5, -2.5, 2.5, "Sign"}; registry.add("hPtCand", "Lc,Hadron candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); registry.add("hPtProng0", "Lc,Hadron candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); @@ -297,6 +362,7 @@ struct HfCorrelatorLcScHadrons { registry.add("hCandBin", "Lc selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); registry.add("hTracksBin", "Tracks selected in pool Bin;pool Bin;entries", {HistType::kTH1F, {{9, 0., 9.}}}); registry.add("hMassLcVsPt", "Lc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {{axisCandMass}, {axisPtLc}}}); + registry.add("hMassScVsPtVsSign", "Sc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});sign;entries", {HistType::kTH3F, {{axisCandMass}, {axisPtLc}, {axisSign}}}); registry.add("hMassLcData", "Lc candidates;inv. mass (p K #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{axisCandMass}}}); registry.add("hLcPoolBin", "Lc candidates pool bin", {HistType::kTH1F, {axisPoolBin}}); registry.add("hTracksPoolBin", "Particles associated pool bin", {HistType::kTH1F, {axisPoolBin}}); @@ -329,7 +395,9 @@ struct HfCorrelatorLcScHadrons { registry.add("hPtCandMcGen", "Lc,Hadron particles - MC gen;particle #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPtLc}}); registry.add("hYMcGen", "Lc,Hadron candidates - MC gen;candidate #it{#y};entries", {HistType::kTH1F, {axisRapidity}}); registry.add("hPtCandMcGenPrompt", "Lc,Hadron particles - MC Gen Prompt", {HistType::kTH1F, {axisPtLc}}); - registry.add("hPtCandMcGenNonPrompt", "Lc,Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtLc}}); + registry.add("hPtCandVsChargeMcGenPrompt", "Charm Hadron particles - MC Gen Prompt", {HistType::kTH2F, {{axisPtLc}, {axisSign}}}); + registry.add("hPtCandMcGenNonPrompt", "Charm Hadron particles - MC Gen Non Prompt", {HistType::kTH1F, {axisPtLc}}); + registry.add("hPtCandVsChargeMcGenNonPrompt", "Lc,Hadron particles - MC Gen Non Prompt", {HistType::kTH2F, {{axisPtLc}, {axisSign}}}); registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); registry.add("hEtaMcGen", "Lc,Hadron particles - MC Gen", {HistType::kTH1F, {axisEta}}); registry.add("hPhiMcGen", "Lc,Hadron particles - MC Gen", {HistType::kTH1F, {axisPhi}}); @@ -350,11 +418,10 @@ struct HfCorrelatorLcScHadrons { double estimateY(CandType const& candidate) { double y = -999.; - const int chargeScZero = 0; if constexpr (isCandSc) { int8_t chargeCand = candidate.charge(); - if (chargeCand == chargeScZero) { + if (chargeCand == chargeZero) { y = hfHelper.ySc0(candidate); } else { y = hfHelper.yScPlusPlus(candidate); @@ -399,7 +466,7 @@ struct HfCorrelatorLcScHadrons { continue; auto chargeTrack = pdg->GetParticle(track.pdgCode())->Charge(); // Retrieve charge - registry.fill(HIST("hPtTracksVsSignGen"), track.pt(), chargeTrack / (2 * std::abs(chargeTrack))); + registry.fill(HIST("hPtTracksVsSignGen"), track.pt(), chargeTrack / (std::abs(chargeTrack))); } } template @@ -416,7 +483,7 @@ struct HfCorrelatorLcScHadrons { track.pt() * track.sign(), binPool, correlStatus); - entryCandHadronPairY(track.y() - yCand); + entryCandHadronPairY(track.rapidity(MassProton) - yCand); entryCandHadronMlInfo(outMl[0], outMl[1]); entryTrackRecoInfo(track.dcaXY(), track.dcaZ(), track.tpcNClsCrossedRows()); entryPairCandCharge(signCand); @@ -449,8 +516,6 @@ struct HfCorrelatorLcScHadrons { int nTracks = 0; int64_t timeStamp = 0; - const int chargeScPlusPlus = 2; - const int chargeScZero = 0; bool skipMixedEventTableFilling = false; float multiplicityFT0M = collision.multFT0M(); int gCollisionId = collision.globalIndex(); @@ -492,8 +557,6 @@ struct HfCorrelatorLcScHadrons { int countCand = 1; for (const auto& candidate : candidates) { - - int8_t chargeCand = 3; double efficiencyWeightCand = 1.; double yCand = -999.0; double etaCand = -999.0; @@ -538,31 +601,38 @@ struct HfCorrelatorLcScHadrons { if (selLcPKPi) { const auto& probs = candidateLc.mlProbLcToPKPi(); fillMlOutput(probs, outputMlPKPi); - massCandPKPi = hfHelper.invMassScRecoLcToPKPi(candidate, candidateLc); + massCandPKPi = std::abs(hfHelper.invMassScRecoLcToPKPi(candidate, candidateLc) - hfHelper.invMassLcToPKPi(candidateLc)); } if (selLcPiKP) { const auto& probs = candidateLc.mlProbLcToPiKP(); fillMlOutput(probs, outputMlPiKP); - massCandPiKP = hfHelper.invMassScRecoLcToPiKP(candidate, candidateLc); + massCandPiKP = std::abs(hfHelper.invMassScRecoLcToPiKP(candidate, candidateLc) - hfHelper.invMassLcToPiKP(candidateLc)); } if constexpr (isMcRec) { // isSignal = // (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi) && chargeCand == 0) || // (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi) && std::abs(chargeCand) == 2); isSignal = - (std::abs(candidate.flagMcMatchRec()) == (1 << aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi) && chargeCand == chargeScZero) || + (std::abs(candidate.flagMcMatchRec()) == (1 << aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi) && chargeCand == chargeZero) || (std::abs(candidate.flagMcMatchRec()) == (1 << aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi) && std::abs(chargeCand) == chargeScPlusPlus); auto trackPos1 = candidateLc.template prong0_as(); auto trackPos2 = candidateLc.template prong2_as(); + signSoftPion = candidate.template prong1_as().sign(); if (calTrkEff && countCand == 1 && (isSignal || !calEffEventWithCand)) { calculateTrkEff(trackPos1, trackPos2, *mcParticles); } registry.fill(HIST("hPtProng1"), candidate.template prong1_as().pt()); } else { + signSoftPion = candidate.template prong1_as().sign(); registry.fill(HIST("hPtProng1"), candidate.prong1().pt()); } registry.fill(HIST("hPtProng0"), ptCandLc); + + if (chargeCand == chargeZero) { + chargeCand = (signSoftPion < chargeZero) ? assignedChargeSc0 : -assignedChargeSc0; // to distingush sc0 from anti-sc0, charge set to +1 and -1 + } + } else { selLcPKPi = candidate.isSelLcToPKPi() >= selectionFlagLc; selLcPiKP = candidate.isSelLcToPiKP() >= selectionFlagLc; @@ -580,7 +650,7 @@ struct HfCorrelatorLcScHadrons { auto trackPos2 = candidate.template prong2_as(); chargeCand = trackPos1.sign(); if constexpr (isMcRec) { - isSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi); + isSignal = std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; if (calTrkEff && countCand == 1 && (isSignal || !calEffEventWithCand)) { calculateTrkEff(trackPos1, trackPos2, *mcParticles); } @@ -599,6 +669,7 @@ struct HfCorrelatorLcScHadrons { if (selLcPKPi) { registry.fill(HIST("hMassLcVsPt"), massCandPKPi, ptCand, efficiencyWeightCand); + registry.fill(HIST("hMassScVsPtVsSign"), massCandPKPi, ptCand, chargeCand, efficiencyWeightCand); registry.fill(HIST("hMassLcData"), massCandPKPi, efficiencyWeightCand); registry.fill(HIST("hSelectionStatusLcToPKPi"), selLcPKPi); if (isPrompt) { @@ -619,6 +690,7 @@ struct HfCorrelatorLcScHadrons { if (selLcPiKP) { registry.fill(HIST("hMassLcVsPt"), massCandPiKP, ptCand, efficiencyWeightCand); + registry.fill(HIST("hMassScVsPtVsSign"), massCandPKPi, ptCand, chargeCand, efficiencyWeightCand); registry.fill(HIST("hMassLcData"), massCandPiKP, efficiencyWeightCand); registry.fill(HIST("hSelectionStatusLcToPiKP"), selLcPiKP); if (isPrompt) { @@ -678,9 +750,9 @@ struct HfCorrelatorLcScHadrons { if (std::abs(motherTrk.pdgCode()) == kLambdaCPlus) continue; - registry.fill(HIST("hPtTracksVsSignRec"), track.pt(), track.sign() / 2.); + registry.fill(HIST("hPtTracksVsSignRec"), track.pt(), track.sign()); if (std::abs(mcParticle.pdgCode()) == kProton) - registry.fill(HIST("hPtTracksVsSignRecTrue"), track.pt(), track.sign() / 2.); + registry.fill(HIST("hPtTracksVsSignRecTrue"), track.pt(), track.sign()); } } @@ -727,8 +799,6 @@ struct HfCorrelatorLcScHadrons { double massCandPiKP = -999.0; bool selLcPKPi = false; bool selLcPiKP = false; - const int chargeScPlusPlus = 2; - const int chargeScZero = 0; auto tracksTuple = std::make_tuple(candidates, tracks); Pair pairData{corrBinning, numberEventsMixed, -1, collisions, tracksTuple, &cache}; @@ -752,22 +822,29 @@ struct HfCorrelatorLcScHadrons { if constexpr (isCandSc) { const auto& candidateLc = candidate.template prongLc_as(); chargeCand = candidate.charge(); + selLcPKPi = (candidateLc.isSelLcToPKPi() >= selectionFlagLc) && (candidate.statusSpreadLcMinvPKPiFromPDG()); selLcPiKP = (candidateLc.isSelLcToPiKP() >= selectionFlagLc) && (candidate.statusSpreadLcMinvPiKPFromPDG()); if (selLcPKPi) { const auto& probs = candidateLc.mlProbLcToPKPi(); fillMlOutput(probs, outputMlPKPi); - massCandPKPi = hfHelper.invMassScRecoLcToPKPi(candidate, candidateLc); + massCandPKPi = std::abs(hfHelper.invMassScRecoLcToPKPi(candidate, candidateLc) - hfHelper.invMassLcToPKPi(candidateLc)); } if (selLcPiKP) { const auto& probs = candidateLc.mlProbLcToPiKP(); fillMlOutput(probs, outputMlPiKP); - massCandPiKP = hfHelper.invMassScRecoLcToPKPi(candidate, candidateLc); + massCandPiKP = std::abs(hfHelper.invMassScRecoLcToPiKP(candidate, candidateLc) - hfHelper.invMassLcToPiKP(candidateLc)); } if constexpr (isMcRec) { isSignal = - (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi) && chargeCand == chargeScZero) || + (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi) && chargeCand == chargeZero) || (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi) && std::abs(chargeCand) == chargeScPlusPlus); + signSoftPion = candidate.template prong1_as().sign(); + } else { + signSoftPion = candidate.template prong1_as().sign(); + } + if (chargeCand == chargeZero) { + chargeCand = (signSoftPion < chargeZero) ? assignedChargeSc0 : -assignedChargeSc0; // to distingush sc0 from anti-sc0, charge set to +1 and -1 } } else { selLcPKPi = candidate.isSelLcToPKPi() >= selectionFlagLc; @@ -785,7 +862,7 @@ struct HfCorrelatorLcScHadrons { auto trackPos1 = candidate.template prong0_as(); chargeCand = trackPos1.sign(); if constexpr (isMcRec) { - isSignal = TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_3prong::DecayType::LcToPKPi); + isSignal = std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; } } @@ -827,99 +904,14 @@ struct HfCorrelatorLcScHadrons { } } - //} - - /// Lc-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) - void processDataLc(SelCollisionsWithLc::iterator const& collision, - TracksData const& tracks, - CandsLcDataFiltered const& candidates, - aod::BCsWithTimestamps const&) + template + void doSameEventMcGen(CollisionType const& mcCollision, PartType const& mcParticles) { - doSameEvent(collision, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLc, "Process data", true); - void processDataSc(SelCollisionsWithSc::iterator const& collision, - TracksData const& tracks, - aod::Tracks const&, - aod::HfCandSc const& candidates, - CandsLcData const&, - aod::BCsWithTimestamps const&) // MUST be last among index-compatible - { - doSameEvent(collision, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataSc, "Process data Sc", false); + int counterCharmCand = 0; + static constexpr std::size_t PDGChargeScale{3u}; - /// Lc-Hadron correlation process starts for McRec - void processMcRecLc(SelCollisionsWithLc::iterator const& collision, - TracksWithMc const& tracks, - CandsLcMcRecFiltered const& candidates, - aod::McParticles const& mcParticles) - { - doSameEvent(collision, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecLc, "Process Mc Reco mode", false); - - /// Lc-Hadron correlation process starts for McRec - void processMcRecSc(SelCollisionsWithSc::iterator const& collision, - TracksWithMc const& tracks, - aod::TracksWMc const&, - soa::Join const& candidates, - CandsLcData const&, - aod::McParticles const& mcParticles) - { - doSameEvent(collision, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecSc, "Process Mc Reco mode", false); - - void processDataMixedEventSc(SelCollisionsWithSc const& collisions, - TracksData const& tracks, - aod::Tracks const&, - aod::HfCandSc const& candidates, - CandsLcData const&) - { - doMixEvent(collisions, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventSc, "Process Mixed Event Data", false); - - void processDataMixedEventLc(SelCollisionsWithLc const& collisions, - CandsLcDataFiltered const& candidates, - TracksData const& tracks) - { - - doMixEvent(collisions, tracks, candidates); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventLc, "Process Mixed Event Data", false); - - void processMcRecMixedEventSc(SelCollisionsWithSc const& collisions, - TracksWithMc const& tracks, - aod::TracksWMc const&, - soa::Join const& candidates, - CandsLcData const&, - aod::McParticles const& mcParticles) - { - doMixEvent(collisions, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventSc, "Process Mixed Event McRec", false); - - void processMcRecMixedEventLc(SelCollisionsWithLc const& collisions, - CandsLcMcRecFiltered const& candidates, - TracksWithMc const& tracks, - aod::McParticles const& mcParticles) - { - doMixEvent(collisions, tracks, candidates, &mcParticles); - } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventLc, "Process Mixed Event McRec", false) - - /// Lc-Hadron correlation pair builder - for Mc Gen-level analysis - void processMcGen(SelCollisionsWithLcMc::iterator const& mcCollision, - CandidatesLcMcGen const& mcParticles) - { - int counterLcHadron = 0; registry.fill(HIST("hMcEvtCount"), 0); - BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; poolBin = corrBinningMcGen.getBin(std::make_tuple(mcCollision.posZ(), mcCollision.multMCFT0A())); registry.fill(HIST("hMultFT0AMcGen"), mcCollision.multMCFT0A()); @@ -928,48 +920,70 @@ struct HfCorrelatorLcScHadrons { if (correlateLcWithLeadingParticle) { leadingIndex = findLeadingParticleMcGen(mcParticles, etaTrackMax.value, ptTrackMin.value); } - // Mc Gen level for (const auto& particle : mcParticles) { - if (std::abs(particle.pdgCode()) != Pdg::kLambdaCPlus) { - continue; - } - if (!TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_3prong::DecayType::LcToPKPi)) { + + double massCand = -999.0; + bool isCandFound = isCandSc ? matchCandAndMass(particle, massCand) : matchCandAndMass(particle, massCand); + if (!isCandFound) { continue; } - double yL = RecoDecay::y(particle.pVector(), MassLambdaCPlus); - if (std::abs(yL) > yCandGenMax || particle.pt() < ptCandMin) { + double yCand = RecoDecay::y(particle.pVector(), massCand); + + if (std::abs(yCand) > yCandGenMax || particle.pt() < ptCandMin) { continue; } registry.fill(HIST("hCandBin"), 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"), yL); + registry.fill(HIST("hYMcGen"), yCand); + + int8_t chargeCand = pdg->GetParticle(particle.pdgCode())->Charge() / PDGChargeScale; // Retrieve charge + if (chargeCand == chargeZero) { + chargeCand = (particle.pdgCode() > chargeZero) ? assignedChargeSc0 : -assignedChargeSc0; // to distingush sc0 from anti-sc0, charge set to +1 and -1 + } isPrompt = particle.originMcGen() == RecoDecay::OriginType::Prompt; isNonPrompt = particle.originMcGen() == RecoDecay::OriginType::NonPrompt; if (isPrompt) { registry.fill(HIST("hPtCandMcGenPrompt"), particle.pt()); + registry.fill(HIST("hPtCandVsChargeMcGenPrompt"), particle.pt(), chargeCand); } else if (isNonPrompt) { registry.fill(HIST("hPtCandMcGenNonPrompt"), particle.pt()); + registry.fill(HIST("hPtCandVsChargeMcGenNonPrompt"), particle.pt(), chargeCand); } - // prompt and non-prompt division + static constexpr std::size_t NDaughtersSc{4u}; + static constexpr std::size_t NDaughtersLc{3u}; std::vector listDaughters{}; - std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; - std::array prongsId; listDaughters.clear(); - RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); + const std::size_t nDaughtersExpected = isCandSc ? NDaughtersSc : NDaughtersLc; + + if (isCandSc) { + if (massCand == o2::constants::physics::MassSigmaC0 || massCand == o2::constants::physics::MassSigmaCStar0) { + std::array arrDaughSc0PDG = {kProton, -kKPlus, kPiPlus, kPiMinus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughSc0PDG, 2); + } else { + std::array arrDaughScPlusPDG = {kProton, -kKPlus, kPiPlus, kPiPlus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughScPlusPDG, 2); + } + } else { + std::array arrDaughLcPDG = {kProton, -kKPlus, kPiPlus}; + RecoDecay::getDaughters(particle, &listDaughters, arrDaughLcPDG, 2); + } + int counterDaughters = 0; - if (listDaughters.size() == NDaughters) { + std::vector prongsId(nDaughtersExpected); + if (listDaughters.size() == nDaughtersExpected) { for (const auto& dauIdx : listDaughters) { auto daughI = mcParticles.rawIteratorAt(dauIdx - mcParticles.offset()); counterDaughters += 1; prongsId[counterDaughters - 1] = daughI.globalIndex(); } } - counterLcHadron++; + counterCharmCand++; + // Lc Hadron correlation dedicated section // if it's a Lc particle, search for Hadron and evalutate correlations registry.fill(HIST("hcountCandtriggersMcGen"), 0, particle.pt()); // to count trigger Lc for normalisation @@ -977,7 +991,8 @@ struct HfCorrelatorLcScHadrons { if (std::abs(particleAssoc.eta()) > etaTrackMax || particleAssoc.pt() < ptTrackMin || particleAssoc.pt() > ptTrackMax) { continue; } - if (particleAssoc.globalIndex() == prongsId[0] || particleAssoc.globalIndex() == prongsId[1] || particleAssoc.globalIndex() == prongsId[2]) { + + if (std::find(prongsId.begin(), prongsId.end(), particleAssoc.globalIndex()) != prongsId.end()) { if (!storeAutoCorrelationFlag) { continue; } @@ -1001,33 +1016,132 @@ struct HfCorrelatorLcScHadrons { } } - int8_t chargeLc = pdg->GetParticle(particle.pdgCode())->Charge(); // Retrieve charge - int8_t chargeAssoc = pdg->GetParticle(particleAssoc.pdgCode())->Charge(); // Retrieve charge - int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, particleAssoc, true); + int8_t chargeAssoc = pdg->GetParticle(particleAssoc.pdgCode())->Charge(); // Retrieve charge + chargeAssoc = chargeAssoc / std::abs(chargeAssoc); registry.fill(HIST("hPtParticleAssocMcGen"), particleAssoc.pt()); entryCandHadronPair(getDeltaPhi(particleAssoc.phi(), particle.phi()), particleAssoc.eta() - particle.eta(), - particle.pt() * chargeLc / std::abs(chargeLc), - particleAssoc.pt() * chargeAssoc / std::abs(chargeAssoc), + particle.pt(), + particleAssoc.pt() * chargeAssoc, poolBin, correlationStatus); - entryCandHadronPairY(particleAssoc.y() - yL); - entryCandHadronRecoInfo(MassLambdaCPlus, true); + entryCandHadronPairY(particleAssoc.y() - yCand); + entryCandHadronRecoInfo(massCand, true); entryCandHadronGenInfo(isPrompt, particleAssoc.isPhysicalPrimary(), trackOrigin); + entryPairCandCharge(chargeCand); } // end inner loop } // end outer loop - registry.fill(HIST("hcountCandHadronPerEvent"), counterLcHadron); + registry.fill(HIST("hcountCandHadronPerEvent"), counterCharmCand); registry.fill(HIST("hZvtx"), mcCollision.posZ()); } - PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGen, "Process Mc Gen mode", false); - void processMcGenMixedEvent(SelCollisionsWithLcMc const& collisions, + //} + + /// Lc-hadron correlation pair builder - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) + void processDataLc(SelCollisions::iterator const& collision, + TracksData const& tracks, + CandsLcDataFiltered const& candidates, + aod::BCsWithTimestamps const&) + { + doSameEvent(collision, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataLc, "Process data", true); + + void processDataSc(SelCollisions::iterator const& collision, + TracksData const& tracks, + aod::Tracks const&, + aod::HfCandSc const& candidates, + CandsLcData const&, + aod::BCsWithTimestamps const&) // MUST be last among index-compatible + { + doSameEvent(collision, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataSc, "Process data Sc", false); + + /// Lc-Hadron correlation process starts for McRec + void processMcRecLc(SelCollisions::iterator const& collision, + TracksWithMc const& tracks, + CandsLcMcRecFiltered const& candidates, + aod::McParticles const& mcParticles) + { + doSameEvent(collision, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecLc, "Process Mc Reco mode", false); + + /// Lc-Hadron correlation process starts for McRec + void processMcRecSc(SelCollisions::iterator const& collision, + TracksWithMc const& tracks, + aod::TracksWMc const&, + CandsScMcRec const& candidates, + CandsLcData const&, + aod::McParticles const& mcParticles) + { + doSameEvent(collision, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecSc, "Process Mc Reco mode", false); + + void processDataMixedEventSc(SelCollisions const& collisions, + TracksData const& tracks, + aod::Tracks const&, + aod::HfCandSc const& candidates, + CandsLcData const&) + { + doMixEvent(collisions, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventSc, "Process Mixed Event Data", false); + + void processDataMixedEventLc(SelCollisions const& collisions, + CandsLcDataFiltered const& candidates, + TracksData const& tracks) + { + + doMixEvent(collisions, tracks, candidates); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processDataMixedEventLc, "Process Mixed Event Data", false); + + void processMcRecMixedEventSc(SelCollisions const& collisions, + TracksWithMc const& tracks, + aod::TracksWMc const&, + soa::Join const& candidates, + CandsLcData const&, + aod::McParticles const& mcParticles) + { + doMixEvent(collisions, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventSc, "Process Mixed Event McRec", false); + + void processMcRecMixedEventLc(SelCollisions const& collisions, + CandsLcMcRecFiltered const& candidates, + TracksWithMc const& tracks, + aod::McParticles const& mcParticles) + { + doMixEvent(collisions, tracks, candidates, &mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcRecMixedEventLc, "Process Mixed Event McRec", false) + + /// Lc-Hadron correlation pair builder - for Mc Gen-level analysis + void processMcGenLc(SelCollisionsMc::iterator const& mcCollision, + CandidatesLcMcGen const& mcParticles) + { + doSameEventMcGen(mcCollision, mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGenLc, "Process Mc Gen Lc mode", false); + + void processMcGenSc(SelCollisionsMc::iterator const& mcCollision, + CandidatesScMcGen const& mcParticles) + { + doSameEventMcGen(mcCollision, mcParticles); + } + PROCESS_SWITCH(HfCorrelatorLcScHadrons, processMcGenSc, "Process Mc Gen Sc mode", false); + + void processMcGenMixedEvent(SelCollisionsMc const& collisions, CandidatesLcMcGen const& mcParticles) { BinningTypeMcGen corrBinningMcGen{{binsZVtx, binsMultiplicityMc}, true}; auto tracksTuple = std::make_tuple(mcParticles, mcParticles); - Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; + Pair pairMcGen{corrBinningMcGen, numberEventsMixed, -1, collisions, tracksTuple, &cache}; for (const auto& [c1, tracks1, c2, tracks2] : pairMcGen) { poolBin = corrBinningMcGen.getBin(std::make_tuple(c1.posZ(), c1.multMCFT0A())); for (const auto& [candidate, particleAssoc] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { diff --git a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx index ee8ec8aaa26..1255781f2b0 100644 --- a/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx +++ b/PWGHF/HFC/TableProducer/femtoDreamProducer.cxx @@ -13,40 +13,56 @@ /// \brief Tasks that produces the track tables used for the pairing /// \author Ravindra Singh, GSI, ravindra.singh@cern.ch /// \author Biao Zhang, Heidelberg University, biao.zhang@cern.ch +/// \author Yunfan Liu, Central China Normal University, yunfan.l@cern.ch -#include -#include - -#include "TMCProcess.h" - -#include "CCDB/BasicCCDBManager.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" - -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" - -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGCF/FemtoDream/Core/femtoDreamCollisionSelection.h" +#include "PWGCF/DataModel/FemtoDerived.h" +#include "PWGCF/FemtoDream/Core/femtoDreamSelection.h" #include "PWGCF/FemtoDream/Core/femtoDreamTrackSelection.h" #include "PWGCF/FemtoDream/Core/femtoDreamUtils.h" - +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponseDplusToPiKPi.h" #include "PWGHF/Core/HfMlResponseLcToPKPi.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.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 +#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; @@ -73,6 +89,11 @@ enum MlMode : uint8_t { FillMlFromNewBDT }; +// decay channels +enum DecayChannel { DplusToPiKPi = 0, + LcToPKPi +}; + struct HfFemtoDreamProducer { Produces outputCollision; @@ -81,6 +102,7 @@ struct HfFemtoDreamProducer { Produces rowCandMcCharmHad; Produces rowCandCharmHadGen; Produces outputPartsIndex; + Produces outputPartsTime; Produces outputMcCollision; Produces outputCollsMcLabels; Produces outputParts; @@ -105,16 +127,16 @@ struct HfFemtoDreamProducer { Configurable isDebug{"isDebug", true, "Enable Debug tables"}; Configurable isRun3{"isRun3", true, "Running on Run3 or pilot"}; - /// Lc table - Configurable selectionFlagLc{"selectionFlagLc", 1, "Selection Flag for Lc"}; - Configurable useCent{"useCent", false, "Enable centrality for lc"}; + /// Charm hadron table + Configurable selectionFlagHadron{"selectionFlagHadron", 1, "Selection Flag for Charm Hadron: 1 for Lc, 7 for Dplus (Topologic and PID cuts)"}; + Configurable useCent{"useCent", false, "Enable centrality for Charm Hadron"}; Configurable trkPDGCode{"trkPDGCode", 2212, "PDG code of the selected track for Monte Carlo truth"}; Configurable> trkCharge{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kSign, "trk"), std::vector{-1, 1}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kSign, "Track selection: ")}; Configurable> trkDCAxyMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAxyMax, "trk"), std::vector{0.1f, 3.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAxyMax, "Track selection: ")}; Configurable> trkDCAzMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kDCAzMax, "trk"), std::vector{0.2f, 3.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kDCAzMax, "Track selection: ")}; Configurable> trkEta{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kEtaMax, "trk"), std::vector{0.8f, 0.7f, 0.9f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kEtaMax, "Track selection: ")}; - Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton}, "Trk sel: Particles species for PID"}; + Configurable> trkPIDspecies{"trkPIDspecies", std::vector{o2::track::PID::Pion, o2::track::PID::Kaon, o2::track::PID::Proton, o2::track::PID::Deuteron}, "Trk sel: Particles species for PID"}; Configurable> trkPIDnSigmaMax{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kPIDnSigmaMax, "trk"), std::vector{3.5f, 3.f, 2.5f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kPIDnSigmaMax, "Track selection: ")}; Configurable trkPIDnSigmaOffsetTPC{"trkPIDnSigmaOffsetTPC", 0., "Offset for TPC nSigma because of bad calibration"}; Configurable trkPIDnSigmaOffsetTOF{"trkPIDnSigmaOffsetTOF", 0., "Offset for TOF nSigma because of bad calibration"}; @@ -127,7 +149,7 @@ struct HfFemtoDreamProducer { Configurable> trkITSnclsIbMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsIbMin, "trk"), std::vector{-1.f, 1.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsIbMin, "Track selection: ")}; Configurable> trkITSnclsMin{FemtoDreamTrackSelection::getSelectionName(femtoDreamTrackSelection::kITSnClsMin, "trk"), std::vector{-1.f, 2.f, 4.f}, FemtoDreamTrackSelection::getSelectionHelper(femtoDreamTrackSelection::kITSnClsMin, "Track selection: ")}; // ML inference - Configurable applyMlMode{"applyMlMode", 1, "None: 0, BDT model from Lc selector: 1, New BDT model on Top of Lc selector: 2"}; + Configurable applyMlMode{"applyMlMode", 1, "None: 0, BDT model from candidate selector: 1, New BDT model on Top of candidate selector: 2"}; 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"}; @@ -138,6 +160,8 @@ struct HfFemtoDreamProducer { HfHelper hfHelper; o2::analysis::HfMlResponseLcToPKPi hfMlResponse; + o2::analysis::HfMlResponseDplusToPiKPi hfMlResponseDplus; + std::vector outputMlDplus = {}; std::vector outputMlPKPi = {}; std::vector outputMlPiKP = {}; o2::ccdb::CcdbApi ccdbApi; @@ -148,6 +172,8 @@ struct HfFemtoDreamProducer { float magField; int runNumber; + using CandidateDplus = soa::Join; + using CandidateDplusMc = soa::Join; using CandidateLc = soa::Join; using CandidateLcMc = soa::Join; @@ -162,14 +188,16 @@ struct HfFemtoDreamProducer { using GeneratedMc = soa::Filtered>; - Filter filterSelectCandidateLc = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLc || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLc); + Filter filterSelectCandidateDplus = (aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagHadron || aod::hf_sel_candidate_dplus::isSelDplusToPiKPi >= selectionFlagHadron); + Filter filterSelectCandidateLc = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagHadron || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagHadron); HistogramRegistry qaRegistry{"QAHistos", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry trackRegistry{"Tracks", {}, OutputObjHandlingPolicy::AnalysisObject}; void init(InitContext&) { - std::array processes = {doprocessDataCharmHad, doprocessMcCharmHad, doprocessDataCharmHadWithML, doprocessMcCharmHadWithML, doprocessMcCharmHadGen}; + std::array processes = {doprocessDataDplusToPiKPi, doprocessMcDplusToPiKPi, doprocessDataDplusToPiKPiWithML, doprocessMcDplusToPiKPiWithML, doprocessMcDplusToPiKPiGen, + doprocessDataLcToPKPi, doprocessMcLcToPKPi, doprocessDataLcToPKPiWithML, doprocessMcLcToPKPiWithML, doprocessMcLcToPKPiGen}; if (std::accumulate(processes.begin(), processes.end(), 0) != 1) { LOGP(fatal, "One and only one process function must be enabled at a time."); } @@ -364,9 +392,11 @@ struct HfFemtoDreamProducer { trackCuts.fillQA(track); // the bit-wise container of the systematic variations is obtained auto cutContainer = trackCuts.getCutContainer(track, track.pt(), track.eta(), sqrtf(powf(track.dcaXY(), 2.f) + powf(track.dcaZ(), 2.f))); - + auto bc = col.template bc_as(); + int64_t timeStamp = bc.timestamp(); // track global index outputPartsIndex(track.globalIndex()); + outputPartsTime(timeStamp); // now the table is filled outputParts(outputCollision.lastIndex(), @@ -390,7 +420,7 @@ struct HfFemtoDreamProducer { return fIsTrackFilled; } - template + template void fillCharmHadronTable(CollisionType const& col, TrackType const& tracks, CandType const& candidates) { const auto vtxZ = col.posZ(); @@ -437,44 +467,15 @@ struct HfFemtoDreamProducer { bool isTrackFilled = false; bool isSelectedMlLcToPKPi = true; bool isSelectedMlLcToPiKP = true; + bool isSelectedMlDplusToPiKPi = true; for (const auto& candidate : candidates) { + outputMlDplus = {-1.0f, -1.0f, -1.0f}; outputMlPKPi = {-1.0f, -1.0f, -1.0f}; outputMlPiKP = {-1.0f, -1.0f, -1.0f}; auto trackPos1 = candidate.template prong0_as(); // positive daughter (negative for the antiparticles) auto trackNeg = candidate.template prong1_as(); // negative daughter (positive for the antiparticles) auto trackPos2 = candidate.template prong2_as(); // positive daughter (negative for the antiparticles) - if constexpr (useCharmMl) { - /// fill with ML information - /// BDT index 0: bkg score; BDT index 1: prompt score; BDT index 2: non-prompt score - if (applyMlMode == FillMlFromSelector) { - if (candidate.mlProbLcToPKPi().size() > 0) { - outputMlPKPi.at(0) = candidate.mlProbLcToPKPi()[0]; /// bkg score - outputMlPKPi.at(1) = candidate.mlProbLcToPKPi()[1]; /// prompt score - outputMlPKPi.at(2) = candidate.mlProbLcToPKPi()[2]; /// non-prompt score - } - if (candidate.mlProbLcToPiKP().size() > 0) { - outputMlPiKP.at(0) = candidate.mlProbLcToPiKP()[0]; /// bkg score - outputMlPiKP.at(1) = candidate.mlProbLcToPiKP()[1]; /// prompt score - outputMlPiKP.at(2) = candidate.mlProbLcToPiKP()[2]; /// non-prompt score - } - } else if (applyMlMode == FillMlFromNewBDT) { - isSelectedMlLcToPKPi = false; - isSelectedMlLcToPiKP = false; - if (candidate.mlProbLcToPKPi().size() > 0) { - std::vector inputFeaturesLcToPKPi = hfMlResponse.getInputFeatures(candidate, true); - isSelectedMlLcToPKPi = hfMlResponse.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlPKPi); - } - if (candidate.mlProbLcToPiKP().size() > 0) { - std::vector inputFeaturesLcToPiKP = hfMlResponse.getInputFeatures(candidate, false); - isSelectedMlLcToPiKP = hfMlResponse.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlPKPi); - } - if (!isSelectedMlLcToPKPi && !isSelectedMlLcToPiKP) - continue; - } else { - LOGF(fatal, "Please check your Ml configuration!!"); - } - } auto bc = col.template bc_as(); int64_t timeStamp = bc.timestamp(); auto fillTable = [&](int CandFlag, @@ -512,8 +513,65 @@ struct HfFemtoDreamProducer { } } }; - fillTable(0, candidate.isSelLcToPKPi(), outputMlPKPi.at(0), outputMlPKPi.at(1), outputMlPKPi.at(2)); - fillTable(1, candidate.isSelLcToPiKP(), outputMlPiKP.at(0), outputMlPiKP.at(1), outputMlPiKP.at(2)); + if constexpr (channel == DecayChannel::DplusToPiKPi) { + if constexpr (useCharmMl) { + /// fill with ML information + /// BDT index 0: bkg score; BDT index 1: prompt score; BDT index 2: non-prompt score + if (applyMlMode == FillMlFromSelector) { + if (candidate.mlProbDplusToPiKPi().size() > 0) { + outputMlDplus.at(0) = candidate.mlProbDplusToPiKPi()[0]; /// bkg score + outputMlDplus.at(1) = candidate.mlProbDplusToPiKPi()[1]; /// prompt score + outputMlDplus.at(2) = candidate.mlProbDplusToPiKPi()[2]; /// non-prompt score + } + } else if (applyMlMode == FillMlFromNewBDT) { + isSelectedMlDplusToPiKPi = false; + if (candidate.mlProbDplusToPiKPi().size() > 0) { + std::vector inputFeaturesDplusToPiKPi = hfMlResponseDplus.getInputFeatures(candidate); + isSelectedMlDplusToPiKPi = hfMlResponseDplus.isSelectedMl(inputFeaturesDplusToPiKPi, candidate.pt(), outputMlDplus); + } + if (!isSelectedMlDplusToPiKPi) + continue; + } else { + LOGF(fatal, "Please check your Ml configuration!!"); + } + } + fillTable(2, candidate.isSelDplusToPiKPi(), outputMlDplus.at(0), outputMlDplus.at(1), outputMlDplus.at(2)); + + } else if constexpr (channel == DecayChannel::LcToPKPi) { + if constexpr (useCharmMl) { + /// fill with ML information + /// BDT index 0: bkg score; BDT index 1: prompt score; BDT index 2: non-prompt score + if (applyMlMode == FillMlFromSelector) { + if (candidate.mlProbLcToPKPi().size() > 0) { + outputMlPKPi.at(0) = candidate.mlProbLcToPKPi()[0]; /// bkg score + outputMlPKPi.at(1) = candidate.mlProbLcToPKPi()[1]; /// prompt score + outputMlPKPi.at(2) = candidate.mlProbLcToPKPi()[2]; /// non-prompt score + } + if (candidate.mlProbLcToPiKP().size() > 0) { + outputMlPiKP.at(0) = candidate.mlProbLcToPiKP()[0]; /// bkg score + outputMlPiKP.at(1) = candidate.mlProbLcToPiKP()[1]; /// prompt score + outputMlPiKP.at(2) = candidate.mlProbLcToPiKP()[2]; /// non-prompt score + } + } else if (applyMlMode == FillMlFromNewBDT) { + isSelectedMlLcToPKPi = false; + isSelectedMlLcToPiKP = false; + if (candidate.mlProbLcToPKPi().size() > 0) { + std::vector inputFeaturesLcToPKPi = hfMlResponse.getInputFeatures(candidate, true); + isSelectedMlLcToPKPi = hfMlResponse.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlPKPi); + } + if (candidate.mlProbLcToPiKP().size() > 0) { + std::vector inputFeaturesLcToPiKP = hfMlResponse.getInputFeatures(candidate, false); + isSelectedMlLcToPiKP = hfMlResponse.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlPKPi); + } + if (!isSelectedMlLcToPKPi && !isSelectedMlLcToPiKP) + continue; + } else { + LOGF(fatal, "Please check your Ml configuration!!"); + } + } + fillTable(0, candidate.isSelLcToPKPi(), outputMlPKPi.at(0), outputMlPKPi.at(1), outputMlPKPi.at(2)); + fillTable(1, candidate.isSelLcToPiKP(), outputMlPiKP.at(0), outputMlPiKP.at(1), outputMlPiKP.at(2)); + } } if (!isTrackFilled) { @@ -557,22 +615,97 @@ struct HfFemtoDreamProducer { return true; } - template + template void fillCharmHadMcGen(ParticleType particles) { // Filling particle properties rowCandCharmHadGen.reserve(particles.size()); - for (const auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { - rowCandCharmHadGen( - particle.mcCollisionId(), - particle.flagMcMatchGen(), - particle.originMcGen()); + if constexpr (channel == DecayChannel::DplusToPiKPi) { + for (const auto& particle : particles) { + if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) { + rowCandCharmHadGen( + particle.mcCollisionId(), + particle.flagMcMatchGen(), + particle.originMcGen()); + } + } + } else if constexpr (channel == DecayChannel::LcToPKPi) { + for (const auto& particle : particles) { + if (std::abs(particle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { + rowCandCharmHadGen( + particle.mcCollisionId(), + particle.flagMcMatchGen(), + particle.originMcGen()); + } } } } - void processDataCharmHad(FemtoFullCollision const& col, + /// DplusToPiKPi + void processDataDplusToPiKPi(FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + FemtoHFTracks const& tracks, + soa::Filtered const& candidates) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + fillCharmHadronTable(col, tracks, candidates); + } + PROCESS_SWITCH(HfFemtoDreamProducer, processDataDplusToPiKPi, + "Provide experimental data for DplusToPiKPi femto", false); + + void processDataDplusToPiKPiWithML(FemtoFullCollision const& col, + aod::BCsWithTimestamps const&, + FemtoHFTracks const& tracks, + soa::Filtered> const& candidates) + { + + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + fillCharmHadronTable(col, tracks, candidates); + } + PROCESS_SWITCH(HfFemtoDreamProducer, processDataDplusToPiKPiWithML, + "Provide experimental data for DplusToPiKPi with ml", false); + + void processMcDplusToPiKPi(FemtoFullCollisionMc const& col, + aod::BCsWithTimestamps const&, + FemtoHFMcTracks const& tracks, + aod::McParticles const&, + CandidateDplusMc const& candidates) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + fillCharmHadronTable(col, tracks, candidates); + } + PROCESS_SWITCH(HfFemtoDreamProducer, processMcDplusToPiKPi, "Provide Mc for DplusToPiKPi", false); + + void processMcDplusToPiKPiWithML(FemtoFullCollisionMc const& col, + aod::BCsWithTimestamps const&, + FemtoHFMcTracks const& tracks, + aod::McParticles const&, + soa::Join const& candidates) + { + // get magnetic field for run + getMagneticFieldTesla(col.bc_as()); + + fillCharmHadronTable(col, tracks, candidates); + } + PROCESS_SWITCH(HfFemtoDreamProducer, processMcDplusToPiKPiWithML, "Provide Mc for DplusToPiKPi with ml", false); + + void processMcDplusToPiKPiGen(GeneratedMc const& particles) + { + + fillCharmHadMcGen(particles); + } + PROCESS_SWITCH(HfFemtoDreamProducer, processMcDplusToPiKPiGen, "Provide Mc Generated DplusToPiKPi", false); + + /// LcToPKPi + void processDataLcToPKPi(FemtoFullCollision const& col, aod::BCsWithTimestamps const&, FemtoHFTracks const& tracks, soa::Filtered const& candidates) @@ -580,12 +713,12 @@ struct HfFemtoDreamProducer { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); - fillCharmHadronTable(col, tracks, candidates); + fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(HfFemtoDreamProducer, processDataCharmHad, - "Provide experimental data for charm hadron femto", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processDataLcToPKPi, + "Provide experimental data for Lc(PKPi)-proton femto", false); - void processDataCharmHadWithML(FemtoFullCollision const& col, + void processDataLcToPKPiWithML(FemtoFullCollision const& col, aod::BCsWithTimestamps const&, FemtoHFTracks const& tracks, soa::Filtered()); - fillCharmHadronTable(col, tracks, candidates); + fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(HfFemtoDreamProducer, processDataCharmHadWithML, - "Provide experimental data for charm hadron femto with ml", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processDataLcToPKPiWithML, + "Provide experimental data for Lc(PKPi)-proton femto with ml", false); - void processMcCharmHad(FemtoFullCollisionMc const& col, + void processMcLcToPKPi(FemtoFullCollisionMc const& col, aod::BCsWithTimestamps const&, FemtoHFMcTracks const& tracks, aod::McParticles const&, @@ -609,11 +742,11 @@ struct HfFemtoDreamProducer { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); - fillCharmHadronTable(col, tracks, candidates); + fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(HfFemtoDreamProducer, processMcCharmHad, "Provide Mc for charm hadron", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processMcLcToPKPi, "Provide Mc for lctopkpi", false); - void processMcCharmHadWithML(FemtoFullCollisionMc const& col, + void processMcLcToPKPiWithML(FemtoFullCollisionMc const& col, aod::BCsWithTimestamps const&, FemtoHFMcTracks const& tracks, aod::McParticles const&, @@ -623,16 +756,16 @@ struct HfFemtoDreamProducer { // get magnetic field for run getMagneticFieldTesla(col.bc_as()); - fillCharmHadronTable(col, tracks, candidates); + fillCharmHadronTable(col, tracks, candidates); } - PROCESS_SWITCH(HfFemtoDreamProducer, processMcCharmHadWithML, "Provide Mc for charm hadron with ml", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processMcLcToPKPiWithML, "Provide Mc for lctopkpi with ml", false); - void processMcCharmHadGen(GeneratedMc const& particles) + void processMcLcToPKPiGen(GeneratedMc const& particles) { - fillCharmHadMcGen(particles); + fillCharmHadMcGen(particles); } - PROCESS_SWITCH(HfFemtoDreamProducer, processMcCharmHadGen, "Provide Mc Generated charm hadron", false); + PROCESS_SWITCH(HfFemtoDreamProducer, processMcLcToPKPiGen, "Provide Mc Generated lctopkpi", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx index b8a0005e6ac..5632f7eefe8 100644 --- a/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx +++ b/PWGHF/HFC/Tasks/taskCharmHadronsFemtoDream.cxx @@ -9,30 +9,43 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -/// \file taskCharmHadronsFemtoDream.cxx.cxx +/// \file taskCharmHadronsFemtoDream.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 - -#include -#include - -#include "Framework/Expressions.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StepTHn.h" +/// \author Yunfan Liu, Central China Normal University, yunfan.l@cern.ch #include "PWGCF/DataModel/FemtoDerived.h" -#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" -#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" #include "PWGCF/FemtoDream/Core/femtoDreamContainer.h" #include "PWGCF/FemtoDream/Core/femtoDreamDetaDphiStar.h" +#include "PWGCF/FemtoDream/Core/femtoDreamEventHisto.h" +#include "PWGCF/FemtoDream/Core/femtoDreamMath.h" +#include "PWGCF/FemtoDream/Core/femtoDreamPairCleaner.h" +#include "PWGCF/FemtoDream/Core/femtoDreamParticleHisto.h" #include "PWGCF/FemtoDream/Core/femtoDreamUtils.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::soa; @@ -40,6 +53,11 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::analysis::femtoDream; +inline o2::framework::expressions::Node coshEta(o2::framework::expressions::Node&& eta) +{ + return (nexp(std::move(eta)) + nexp(0.0f - std::move(eta))) * 0.5f; +} + struct HfTaskCharmHadronsFemtoDream { enum TrackCharge { @@ -47,27 +65,22 @@ struct HfTaskCharmHadronsFemtoDream { NegativeCharge = -1 }; - /// Binning configurables - ConfigurableAxis bin4Dkstar{"bin4Dkstar", {1500, 0., 6.}, "binning kstar for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis bin4DMult{"bin4Dmult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "multiplicity Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis bin4DmT{"bin4DmT", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis bin4DmultPercentile{"bin4DmultPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; - ConfigurableAxis binInvMass{"binInvMass", {400, 2.10, 2.50}, "InvMass binning"}; - ConfigurableAxis binpTCharm{"binpTCharm", {360, 0, 36}, "pT binning of charm hadron"}; - ConfigurableAxis binTempFitVarTrack{"binTempFitVarTrack", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Track)"}; - ConfigurableAxis binmT{"binmT", {225, 0., 7.5}, "binning mT"}; - ConfigurableAxis binmultTempFit{"binmultTempFit", {1, 0, 1}, "multiplicity Binning for the TempFitVar plot"}; - ConfigurableAxis binMulPercentile{"binMulPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning"}; - ConfigurableAxis binpTTrack{"binpTTrack", {50, 0.5, 10.05}, "pT binning of the pT vs. TempFitVar plot (Track)"}; - ConfigurableAxis binEta{"binEta", {{200, -1.5, 1.5}}, "eta binning"}; - ConfigurableAxis binPhi{"binPhi", {{200, 0, TMath::TwoPi()}}, "phi binning"}; - ConfigurableAxis binkT{"binkT", {150, 0., 9.}, "binning kT"}; - ConfigurableAxis binkstar{"binkstar", {1500, 0., 6.}, "binning kstar"}; - ConfigurableAxis binNSigmaTPC{"binNSigmaTPC", {1600, -8, 8}, "Binning of Nsigma TPC plot"}; - ConfigurableAxis binNSigmaTOF{"binNSigmaTOF", {3000, -15, 15}, "Binning of the Nsigma TOF plot"}; - ConfigurableAxis binNSigmaTPCTOF{"binNSigmaTPCTOF", {3000, -15, 15}, "Binning of the Nsigma TPC+TOF plot"}; - ConfigurableAxis binTPCClusters{"binTPCClusters", {163, -0.5, 162.5}, "Binning of TPC found clusters plot"}; - Configurable ConfTempFitVarMomentum{"ConfTempFitVarMomentum", 0, "Momentum used for binning: 0 -> pt; 1 -> preco; 2 -> ptpc"}; + enum PairSign { + PairNotDefined = 0, + LikeSignPair = 1, + UnLikeSignPair = 2 + }; + + constexpr static int OriginRecPrompt = 1; + constexpr static int OriginRecFD = 2; + constexpr static int CutBitChargePositive = 2; + + Produces rowFemtoResultPairs; + Produces rowFemtoResultCharm; + Produces rowFemtoResultTrk; + Produces rowFemtoResultColl; + + Configurable confTempFitVarMomentum{"confTempFitVarMomentum", 0, "Momentum used for binning: 0 -> pt; 1 -> preco; 2 -> ptpc"}; /// Particle 2 (Charm Hadrons) Configurable charmHadBkgBDTmax{"charmHadBkgBDTmax", 1., "Maximum background bdt score for Charm Hadron (particle 2)"}; @@ -93,14 +106,10 @@ struct HfTaskCharmHadronsFemtoDream { Configurable smearingByOrigin{"smearingByOrigin", false, "Obtain the smearing matrix differential in the MC origin of particle 1 and particle 2. High memory consumption. Use with care!"}; Configurable use4D{"use4D", false, "Enable four dimensional histogramms (to be used only for analysis with high statistics): k* vs multiplicity vs multiplicity percentil vs mT"}; Configurable useCPR{"useCPR", false, "Close Pair Rejection"}; - ConfigurableAxis dummy{"dummy", {1, 0, 1}, "dummy axis"}; // Mixing configurables - ConfigurableAxis mixingBinMult{"mixingBinMult", {VARIABLE_WIDTH, 0.0f, 20.0f, 60.0f, 200.0f}, "Mixing bins - multiplicity"}; - ConfigurableAxis mixingBinMultPercentile{"mixingBinMultPercentile", {VARIABLE_WIDTH, 0.0f, 100.f}, "Mixing bins - multiplicity percentile"}; - ConfigurableAxis mixingBinVztx{"mixingBinVztx", {VARIABLE_WIDTH, -10.0f, -4.f, 0.f, 4.f, 10.f}, "Mixing bins - z-vertex"}; - Configurable mixingDepth{"mixingDepth", 5, "Number of events for mixing"}; Configurable mixingBinPolicy{"mixingBinPolicy", 0, "Binning policy for mixing - 0: multiplicity, 1: multipliciy percentile, 2: both"}; + Configurable mixingDepth{"mixingDepth", 5, "Number of events for mixing"}; /// Event selection struct : ConfigurableGroup { @@ -122,23 +131,7 @@ struct HfTaskCharmHadronsFemtoDream { Configurable etaTrack1Min{"etaTrack1Min", -10., "Minimum eta of partricle 1 (Track)"}; Configurable ptTrack1Min{"ptTrack1Min", 0., "Minimum pT of partricle 1 (Track)"}; - ColumnBinningPolicy colBinningMult{{mixingBinVztx, mixingBinMult}, true}; - ColumnBinningPolicy colBinningMultPercentile{{mixingBinVztx, mixingBinMultPercentile}, true}; - ColumnBinningPolicy colBinningMultMultPercentile{{mixingBinVztx, mixingBinMult, mixingBinMultPercentile}, true}; - - FemtoDreamContainer sameEventCont; - FemtoDreamContainer mixedEventCont; - FemtoDreamPairCleaner pairCleaner; - FemtoDreamDetaDphiStar pairCloseRejectionSE; - FemtoDreamDetaDphiStar pairCloseRejectionME; - Filter eventMultiplicity = aod::femtodreamcollision::multNtr >= eventSel.multMin && aod::femtodreamcollision::multNtr <= eventSel.multMax; - Filter eventMultiplicityPercentile = aod::femtodreamcollision::multV0M >= eventSel.multPercentileMin && aod::femtodreamcollision::multV0M <= eventSel.multPercentileMax; - Filter hfCandSelFilter = aod::fdhf::candidateSelFlag >= static_cast(charmHadCandSel.value); - Filter hfMcSelFilter = nabs(aod::fdhf::flagMc) == static_cast(charmHadMcSel.value); - Filter trackEtaFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta < etaTrack1Max, true); - Filter trackEtaFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta > etaTrack1Min, true); - Filter trackPtFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt < ptTrack1Max, true); - Filter trackPtFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt > ptTrack1Min, true); + SliceCache cache; using FilteredCharmCands = soa::Filtered; using FilteredCharmCand = FilteredCharmCands::iterator; @@ -155,10 +148,70 @@ struct HfTaskCharmHadronsFemtoDream { using FilteredFDMcParts = soa::Filtered>; using FilteredFDMcPart = FilteredFDMcParts::iterator; - using FilteredFDParticles = soa::Filtered>; + using FilteredFDParticles = soa::Filtered>; using FilteredFDParticle = FilteredFDParticles::iterator; - femtodreamcollision::BitMaskType BitMask = 1 << 0; + Filter eventMultiplicity = aod::femtodreamcollision::multNtr >= eventSel.multMin && aod::femtodreamcollision::multNtr <= eventSel.multMax; + Filter eventMultiplicityPercentile = aod::femtodreamcollision::multV0M >= eventSel.multPercentileMin && aod::femtodreamcollision::multV0M <= eventSel.multPercentileMax; + Filter hfCandSelFilter = aod::fdhf::candidateSelFlag >= static_cast(charmHadCandSel.value); + Filter hfMcSelFilter = nabs(aod::fdhf::flagMc) == static_cast(charmHadMcSel.value); + Filter trackEtaFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta < etaTrack1Max, true); + Filter trackEtaFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::eta > etaTrack1Min, true); + Filter trackPtFilterLow = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt < ptTrack1Max, true); + Filter trackPtFilterUp = ifnode(aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack), aod::femtodreamparticle::pt > ptTrack1Min, true); + + Preslice perCol = aod::femtodreamparticle::fdCollisionId; + Preslice perHfByCol = aod::femtodreamparticle::fdCollisionId; + + /// Partition for particle 1 + Partition partitionTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && (ncheckbit(aod::femtodreamparticle::cut, cutBitTrack1)) && ifnode(aod::femtodreamparticle::pt * coshEta(aod::femtodreamparticle::eta) <= pidThresTrack1, ncheckbit(aod::femtodreamparticle::pidcut, tpcBitTrack1), ncheckbit(aod::femtodreamparticle::pidcut, tpcTofBitTrack1)); + + Partition partitionMcTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && + (ncheckbit(aod::femtodreamparticle::cut, cutBitTrack1)) && + ifnode(aod::femtodreamparticle::pt * coshEta(aod::femtodreamparticle::eta) <= pidThresTrack1, ncheckbit(aod::femtodreamparticle::pidcut, tpcBitTrack1), ncheckbit(aod::femtodreamparticle::pidcut, tpcTofBitTrack1)); + + /// Partition for particle 2 + Partition partitionCharmHadron = aod::fdhf::bdtBkg < charmHadBkgBDTmax && aod::fdhf::bdtFD < charmHadFdBDTmax && aod::fdhf::bdtFD > charmHadFdBDTmin&& aod::fdhf::bdtPrompt charmHadPromptBDTmin; + Partition partitionMcCharmHadron = aod::fdhf::originMcRec == OriginRecPrompt || aod::fdhf::originMcRec == OriginRecFD; + + /// Axis configurables + ConfigurableAxis dummy{"dummy", {1, 0, 1}, "dummy axis"}; + /// Binning configurables + ConfigurableAxis bin4Dkstar{"bin4Dkstar", {1500, 0., 6.}, "binning kstar for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis bin4DMult{"bin4DMult", {VARIABLE_WIDTH, 0.0f, 4.0f, 8.0f, 12.0f, 16.0f, 20.0f, 24.0f, 28.0f, 32.0f, 36.0f, 40.0f, 44.0f, 48.0f, 52.0f, 56.0f, 60.0f, 64.0f, 68.0f, 72.0f, 76.0f, 80.0f, 84.0f, 88.0f, 92.0f, 96.0f, 100.0f, 200.0f}, "multiplicity Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis bin4DmT{"bin4DmT", {VARIABLE_WIDTH, 1.02f, 1.14f, 1.20f, 1.26f, 1.38f, 1.56f, 1.86f, 4.50f}, "mT Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis bin4DmultPercentile{"bin4DmultPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning for the 4Dimensional plot: k* vs multiplicity vs multiplicity percentile vs mT (set <> to true in order to use)"}; + ConfigurableAxis binInvMass{"binInvMass", {400, 2.10, 2.50}, "InvMass binning"}; + ConfigurableAxis binpTCharm{"binpTCharm", {360, 0, 36}, "pT binning of charm hadron"}; + ConfigurableAxis binTempFitVarTrack{"binTempFitVarTrack", {300, -0.15, 0.15}, "binning of the TempFitVar in the pT vs. TempFitVar plot (Track)"}; + ConfigurableAxis binmT{"binmT", {225, 0., 7.5}, "binning mT"}; + ConfigurableAxis binmultTempFit{"binmultTempFit", {1, 0, 1}, "multiplicity Binning for the TempFitVar plot"}; + ConfigurableAxis binMulPercentile{"binMulPercentile", {10, 0.0f, 100.0f}, "multiplicity percentile Binning"}; + ConfigurableAxis binpTTrack{"binpTTrack", {50, 0.5, 10.05}, "pT binning of the pT vs. TempFitVar plot (Track)"}; + ConfigurableAxis binEta{"binEta", {{200, -1.5, 1.5}}, "eta binning"}; + ConfigurableAxis binPhi{"binPhi", {{200, 0, 2.f * 3.14159274101257324e+00f}}, "phi binning"}; + ConfigurableAxis binkT{"binkT", {150, 0., 9.}, "binning kT"}; + ConfigurableAxis binkstar{"binkstar", {1500, 0., 6.}, "binning kstar"}; + ConfigurableAxis binNSigmaTPC{"binNSigmaTPC", {1600, -8, 8}, "Binning of Nsigma TPC plot"}; + ConfigurableAxis binNSigmaTOF{"binNSigmaTOF", {3000, -15, 15}, "Binning of the Nsigma TOF plot"}; + ConfigurableAxis binNSigmaTPCTOF{"binNSigmaTPCTOF", {3000, -15, 15}, "Binning of the Nsigma TPC+TOF plot"}; + ConfigurableAxis binTPCClusters{"binTPCClusters", {163, -0.5, 162.5}, "Binning of TPC found clusters plot"}; + // Mixing axis configurables + ConfigurableAxis mixingBinMult{"mixingBinMult", {VARIABLE_WIDTH, 0.0f, 20.0f, 60.0f, 200.0f}, "Mixing bins - multiplicity"}; + ConfigurableAxis mixingBinMultPercentile{"mixingBinMultPercentile", {VARIABLE_WIDTH, 0.0f, 100.f}, "Mixing bins - multiplicity percentile"}; + ConfigurableAxis mixingBinVztx{"mixingBinVztx", {VARIABLE_WIDTH, -10.0f, -4.f, 0.f, 4.f, 10.f}, "Mixing bins - z-vertex"}; + + ColumnBinningPolicy colBinningMult{{mixingBinVztx, mixingBinMult}, true}; + ColumnBinningPolicy colBinningMultPercentile{{mixingBinVztx, mixingBinMultPercentile}, true}; + ColumnBinningPolicy colBinningMultMultPercentile{{mixingBinVztx, mixingBinMult, mixingBinMultPercentile}, true}; + + FemtoDreamContainer sameEventCont; + FemtoDreamContainer mixedEventCont; + FemtoDreamPairCleaner pairCleaner; + FemtoDreamDetaDphiStar pairCloseRejectionSE; + FemtoDreamDetaDphiStar pairCloseRejectionME; + + femtodreamcollision::BitMaskType bitMask = 1 << 0; /// Histogramming for particle 1 FemtoDreamParticleHisto allTrackHisto; @@ -170,29 +223,12 @@ struct HfTaskCharmHadronsFemtoDream { HistogramRegistry registry{"CorrelationsAndQA", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry registryMixQa{"registryMixQa"}; HistogramRegistry registryCharmHadronQa{"registryCharmHadronQa"}; - /// Partition for particle 1 - - Partition partitionTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && (ncheckbit(aod::femtodreamparticle::cut, cutBitTrack1)) && ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= pidThresTrack1, ncheckbit(aod::femtodreamparticle::pidcut, tpcBitTrack1), ncheckbit(aod::femtodreamparticle::pidcut, tpcTofBitTrack1)); - - Partition partitionMcTrk1 = (aod::femtodreamparticle::partType == uint8_t(aod::femtodreamparticle::ParticleType::kTrack)) && - (ncheckbit(aod::femtodreamparticle::cut, cutBitTrack1)) && - ifnode(aod::femtodreamparticle::pt * (nexp(aod::femtodreamparticle::eta) + nexp(-1.f * aod::femtodreamparticle::eta)) / 2.f <= pidThresTrack1, ncheckbit(aod::femtodreamparticle::pidcut, tpcBitTrack1), ncheckbit(aod::femtodreamparticle::pidcut, tpcTofBitTrack1)); - - /// Partition for particle 2 - Partition partitionCharmHadron = aod::fdhf::bdtBkg < charmHadBkgBDTmax && aod::fdhf::bdtFD < charmHadFdBDTmax && aod::fdhf::bdtFD > charmHadFdBDTmin&& aod::fdhf::bdtPrompt charmHadPromptBDTmin; - Partition partitionMcCharmHadron = aod::fdhf::originMcRec == 1 || aod::fdhf::originMcRec == 2; float massOne = o2::analysis::femtoDream::getMass(pdgCodeTrack1); float massTwo = o2::analysis::femtoDream::getMass(charmHadPDGCode); int8_t partSign = 0; int64_t processType = 0; - SliceCache cache; - Preslice perCol = aod::femtodreamparticle::fdCollisionId; - Produces rowFemtoResultCharm; - Produces rowFemtoResultTrk; - Produces rowFemtoResultColl; - void init(InitContext& /*context*/) { // setup columnpolicy for binning @@ -238,12 +274,36 @@ struct HfTaskCharmHadronsFemtoDream { registryMixQa.fill(HIST("MixingQA/hSECollisionPool"), col.posZ(), col.multNtr()); } + /// Compute the charm hadron candidates mass with the daughter masses + /// assumes the candidate is either a D+ or Λc+ + template + float getCharmHadronMass(const Candidate& cand) + { + float invMass = 0.0f; + if (charmHadPDGCode == o2::constants::physics::Pdg::kLambdaCPlus) { + if (cand.candidateSelFlag() == 1) { + invMass = cand.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); + return invMass; + } else { + invMass = cand.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); + return invMass; + } + } + // D+ → π K π (PDG: 411) + if (charmHadPDGCode == o2::constants::physics::Pdg::kDPlus) { + invMass = cand.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); + return invMass; + } + // Add more channels as needed + return invMass; + } + /// This function processes the same event and takes care of all the histogramming template void doSameEvent(PartitionType& sliceTrk1, CandType& sliceCharmHad, TableTracks const& parts, Collision const& col) { fillCollision(col); - + processType = 1; // for same event for (auto const& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceTrk1, sliceCharmHad))) { if (p1.trackId() == p2.prong0Id() || p1.trackId() == p2.prong1Id() || p1.trackId() == p2.prong2Id()) @@ -259,25 +319,12 @@ struct HfTaskCharmHadronsFemtoDream { continue; } - // proton track charge - float chargeTrack = 0.; - if ((p1.cut() & 2) == 2) { - chargeTrack = PositiveCharge; - } else { - chargeTrack = NegativeCharge; - } - float kstar = FemtoDreamMath::getkstar(p1, massOne, p2, massTwo); if (kstar > highkstarCut) { continue; } - float invMass; - if (p2.candidateSelFlag() == 1) { - invMass = p2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); - } else { - invMass = p2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); - } + float invMass = getCharmHadronMass(p2); if (invMass < charmHadMinInvMass || invMass > charmHadMaxInvMass) { continue; @@ -286,8 +333,23 @@ struct HfTaskCharmHadronsFemtoDream { if (p2.pt() < charmHadMinPt || p2.pt() > charmHadMaxPt) { continue; } + + // proton track charge + float chargeTrack = 0.; + if ((p1.cut() & CutBitChargePositive) == CutBitChargePositive) { + chargeTrack = PositiveCharge; + } else { + chargeTrack = NegativeCharge; + } + int pairSign = 0; + if (chargeTrack == p2.charge()) { + pairSign = LikeSignPair; + } else { + pairSign = UnLikeSignPair; + } + /// Filling QA histograms of the selected tracks - selectedTrackHisto.fillQA(p1, static_cast(ConfTempFitVarMomentum.value), col.multNtr(), col.multV0M()); + selectedTrackHisto.fillQA(p1, static_cast(confTempFitVarMomentum.value), col.multNtr(), col.multV0M()); int charmHadMc = 0; int originType = 0; @@ -296,39 +358,24 @@ struct HfTaskCharmHadronsFemtoDream { originType = p2.originMcRec(); } - rowFemtoResultCharm( - col.globalIndex(), - p2.timeStamp(), + rowFemtoResultPairs( invMass, p2.pt(), - p2.eta(), - p2.phi(), - p2.charge(), + p1.pt(), p2.bdtBkg(), p2.bdtPrompt(), p2.bdtFD(), + kstar, + FemtoDreamMath::getkT(p1, massOne, p2, massTwo), + FemtoDreamMath::getmT(p1, massOne, p2, massTwo), + col.multNtr(), + col.multV0M(), + p2.charge(), + pairSign, + processType, charmHadMc, originType); - rowFemtoResultTrk( - col.globalIndex(), - p2.timeStamp(), - p1.pt(), - p1.eta(), - p1.phi(), - chargeTrack, - p1.tpcNClsFound(), - p1.tpcNClsFindable(), - p1.tpcNClsCrossedRows(), - p1.tpcNSigmaPr(), - p1.tofNSigmaPr()); - - rowFemtoResultColl( - col.globalIndex(), - p2.timeStamp(), - col.posZ(), - col.multNtr()); - sameEventCont.setPair(p1, p2, col.multNtr(), col.multV0M(), use4D, extendedPlots, smearingByOrigin); } } @@ -336,15 +383,15 @@ struct HfTaskCharmHadronsFemtoDream { template void doMixedEvent(CollisionType const& cols, PartType const& parts, PartitionType1& part1, PartitionType2& part2, BinningType policy) { - + processType = 2; // for mixed event // Mixed events that contain the pair of interest - Partition PartitionMaskedCol1 = (aod::femtodreamcollision::bitmaskTrackOne & BitMask) == BitMask; - PartitionMaskedCol1.bindTable(cols); + Partition partitionMaskedCol1 = (aod::femtodreamcollision::bitmaskTrackOne & bitMask) == bitMask; + partitionMaskedCol1.bindTable(cols); - Partition PartitionMaskedCol2 = (aod::femtodreamcollision::bitmaskTrackTwo & BitMask) == BitMask; - PartitionMaskedCol2.bindTable(cols); + Partition partitionMaskedCol2 = (aod::femtodreamcollision::bitmaskTrackTwo & bitMask) == bitMask; + partitionMaskedCol2.bindTable(cols); - for (auto const& [collision1, collision2] : combinations(soa::CombinationsBlockFullIndexPolicy(policy, mixingDepth.value, -1, *PartitionMaskedCol1.mFiltered, *PartitionMaskedCol2.mFiltered))) { + for (auto const& [collision1, collision2] : combinations(soa::CombinationsBlockFullIndexPolicy(policy, mixingDepth.value, -1, *partitionMaskedCol1.mFiltered, *partitionMaskedCol2.mFiltered))) { // make sure that tracks in the same events are not mixed if (collision1.globalIndex() == collision2.globalIndex()) { continue; @@ -355,7 +402,7 @@ struct HfTaskCharmHadronsFemtoDream { auto sliceTrk1 = part1->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision1.globalIndex(), cache); auto sliceCharmHad = part2->sliceByCached(aod::femtodreamparticle::fdCollisionId, collision2.globalIndex(), cache); - for (auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceTrk1, sliceCharmHad))) { + for (const auto& [p1, p2] : combinations(CombinationsFullIndexPolicy(sliceTrk1, sliceCharmHad))) { if (useCPR.value) { if (pairCloseRejectionME.isClosePair(p1, p2, parts, collision1.magField())) { @@ -370,12 +417,8 @@ struct HfTaskCharmHadronsFemtoDream { if (kstar > highkstarCut) { continue; } - float invMass; - if (p2.candidateSelFlag() == 1) { - invMass = p2.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); - } else { - invMass = p2.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); - } + + float invMass = getCharmHadronMass(p2); if (invMass < charmHadMinInvMass || invMass > charmHadMaxInvMass) { continue; @@ -384,8 +427,45 @@ struct HfTaskCharmHadronsFemtoDream { if (p2.pt() < charmHadMinPt || p2.pt() > charmHadMaxPt) { continue; } + // proton track charge + float chargeTrack = 0.; + if ((p1.cut() & CutBitChargePositive) == CutBitChargePositive) { + chargeTrack = PositiveCharge; + } else { + chargeTrack = NegativeCharge; + } + int pairSign = 0; + if (chargeTrack == p2.charge()) { + pairSign = LikeSignPair; + } else { + pairSign = UnLikeSignPair; + } + + int charmHadMc = 0; + int originType = 0; + if constexpr (isMc) { + charmHadMc = p2.flagMc(); + originType = p2.originMcRec(); + } + + rowFemtoResultPairs( + invMass, + p2.pt(), + p1.pt(), + p2.bdtBkg(), + p2.bdtPrompt(), + p2.bdtFD(), + kstar, + FemtoDreamMath::getkT(p1, massOne, p2, massTwo), + FemtoDreamMath::getmT(p1, massOne, p2, massTwo), + collision1.multNtr(), + collision1.multV0M(), + p2.charge(), + pairSign, + processType, + charmHadMc, + originType); - // if constexpr (!isMc) mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), use4D, extendedPlots, smearingByOrigin); mixedEventCont.setPair(p1, p2, collision1.multNtr(), collision1.multV0M(), use4D, extendedPlots, smearingByOrigin); } } @@ -398,23 +478,66 @@ struct HfTaskCharmHadronsFemtoDream { eventHisto.fillQA(col); auto sliceTrk1 = partitionTrk1->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); auto sliceCharmHad = partitionCharmHadron->sliceByCached(aod::femtodreamparticle::fdCollisionId, col.globalIndex(), cache); + int64_t timeStamp = -999; + /// Filling QA histograms of the all tracks and all charm hadrons before pairing for (auto const& part : sliceTrk1) { - allTrackHisto.fillQA(part, static_cast(ConfTempFitVarMomentum.value), col.multNtr(), col.multV0M()); - } - for (auto const& part : sliceCharmHad) { - float invMass; - if (part.candidateSelFlag() == 1) { - invMass = part.m(std::array{o2::constants::physics::MassProton, o2::constants::physics::MassKPlus, o2::constants::physics::MassPiPlus}); + allTrackHisto.fillQA(part, static_cast(confTempFitVarMomentum.value), col.multNtr(), col.multV0M()); + + // proton track charge + float chargeTrack = 0.; + if ((part.cut() & CutBitChargePositive) == CutBitChargePositive) { + chargeTrack = PositiveCharge; } else { - invMass = part.m(std::array{o2::constants::physics::MassPiPlus, o2::constants::physics::MassKPlus, o2::constants::physics::MassProton}); + chargeTrack = NegativeCharge; } + timeStamp = part.timeStamp(); + rowFemtoResultTrk( + col.globalIndex(), + timeStamp, + part.pt(), + part.eta(), + part.phi(), + part.trackId(), + chargeTrack, + part.tpcNClsFound(), + part.tpcNClsFindable(), + part.tpcNClsCrossedRows(), + part.tpcNSigmaPr(), + part.tofNSigmaPr()); + } + for (auto const& part : sliceCharmHad) { + float invMass = getCharmHadronMass(part); registryCharmHadronQa.fill(HIST("CharmHadronQA/hPtVsMass"), part.pt(), invMass); + timeStamp = part.timeStamp(); + + rowFemtoResultCharm( + col.globalIndex(), + timeStamp, + invMass, + part.pt(), + part.eta(), + part.phi(), + part.prong0Id(), + part.prong1Id(), + part.prong2Id(), + part.charge(), + part.bdtBkg(), + part.bdtPrompt(), + part.bdtFD()); } - if ((col.bitmaskTrackOne() & BitMask) != BitMask || (col.bitmaskTrackTwo() & BitMask) != BitMask) { + if (sliceCharmHad.size() || sliceTrk1.size()) { + + rowFemtoResultColl( + col.globalIndex(), + timeStamp, + col.posZ(), + col.multNtr()); + } else { return; } + doSameEvent(sliceTrk1, sliceCharmHad, parts, col); } PROCESS_SWITCH(HfTaskCharmHadronsFemtoDream, processSameEvent, "Enable processing same event", false); @@ -459,10 +582,10 @@ struct HfTaskCharmHadronsFemtoDream { } /// Filling QA histograms of the all mc tracks before pairing for (auto const& part : sliceMcTrk1) { - allTrackHisto.fillQA(part, static_cast(ConfTempFitVarMomentum.value), col.multNtr(), col.multV0M()); + allTrackHisto.fillQA(part, static_cast(confTempFitVarMomentum.value), col.multNtr(), col.multV0M()); } - if ((col.bitmaskTrackOne() & BitMask) != BitMask || (col.bitmaskTrackTwo() & BitMask) != BitMask) { + if ((col.bitmaskTrackOne() & bitMask) != bitMask || (col.bitmaskTrackTwo() & bitMask) != bitMask) { return; } doSameEvent(sliceMcTrk1, sliceMcCharmHad, parts, col); diff --git a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx index 93c0fecd90d..bea1510a24b 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationD0Hadrons.cxx @@ -16,19 +16,40 @@ /// \author Samrangy Sadhu , INFN Bari /// \author Swapnesh Santosh Khade , IIT Indore -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::constants::physics; @@ -365,7 +386,7 @@ struct HfTaskCorrelationD0Hadrons { } } // check if correlation entry belongs to signal region, sidebands or is outside both, and fill correlation plots - if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && ((signalStatus == ParticleTypeData::D0Only) || (signalStatus == ParticleTypeData::D0D0barBoth))) { + if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && (signalStatus == ParticleTypeData::D0Only)) { // in signal region registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegion"), deltaPhi, deltaEta, efficiencyWeight); @@ -373,7 +394,7 @@ struct HfTaskCorrelationD0Hadrons { registry.fill(HIST("hDeltaPhiPtIntSignalRegion"), deltaPhi, efficiencyWeight); } - if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && ((signalStatus == ParticleTypeData::D0OnlySoftPi) || (signalStatus >= ParticleTypeData::D0D0barBothSoftPi))) { + if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && (signalStatus == ParticleTypeData::D0OnlySoftPi)) { // in signal region, fills for soft pion only in ME registry.fill(HIST("hCorrel2DVsPtSignalRegionSoftPi"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionSoftPi"), deltaPhi, deltaEta, efficiencyWeight); @@ -381,7 +402,7 @@ struct HfTaskCorrelationD0Hadrons { registry.fill(HIST("hDeltaPhiPtIntSignalRegionSoftPi"), deltaPhi, efficiencyWeight); } - if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && ((signalStatus == ParticleTypeData::D0barOnly) || (signalStatus == ParticleTypeData::D0D0barBoth))) { + if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && (signalStatus == ParticleTypeData::D0barOnly)) { // in signal region registry.fill(HIST("hCorrel2DVsPtSignalRegion"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegion"), deltaPhi, deltaEta, efficiencyWeight); @@ -399,7 +420,7 @@ struct HfTaskCorrelationD0Hadrons { if (((massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) || (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD))) && - ((signalStatus == ParticleTypeData::D0Only) || (signalStatus == ParticleTypeData::D0D0barBoth))) { + (signalStatus == ParticleTypeData::D0Only)) { // in sideband region registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebands"), deltaPhi, deltaEta, efficiencyWeight); @@ -409,7 +430,7 @@ struct HfTaskCorrelationD0Hadrons { if (((massD > sidebandLeftOuter->at(ptBinD) && massD < sidebandLeftInner->at(ptBinD)) || (massD > sidebandRightInner->at(ptBinD) && massD < sidebandRightOuter->at(ptBinD))) && - ((signalStatus == ParticleTypeData::D0OnlySoftPi) || (signalStatus >= ParticleTypeData::D0D0barBothSoftPi))) { + (signalStatus == ParticleTypeData::D0OnlySoftPi)) { // in sideband region, fills for soft pion only in ME registry.fill(HIST("hCorrel2DVsPtSidebandsSoftPi"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebandsSoftPi"), deltaPhi, deltaEta, efficiencyWeight); @@ -419,7 +440,7 @@ struct HfTaskCorrelationD0Hadrons { if (((massDbar > sidebandLeftOuter->at(ptBinD) && massDbar < sidebandLeftInner->at(ptBinD)) || (massDbar > sidebandRightInner->at(ptBinD) && massDbar < sidebandRightOuter->at(ptBinD))) && - ((signalStatus == ParticleTypeData::D0barOnly) || (signalStatus == ParticleTypeData::D0D0barBoth))) { + (signalStatus == ParticleTypeData::D0barOnly)) { // in sideband region registry.fill(HIST("hCorrel2DVsPtSidebands"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSidebands"), deltaPhi, deltaEta, efficiencyWeight); @@ -482,7 +503,7 @@ struct HfTaskCorrelationD0Hadrons { float bdtScorePromptD0bar = pairEntry.mlScorePromptD0bar(); float bdtScoreBkgD0bar = pairEntry.mlScoreBkgD0bar(); bool isPhysicalPrimary = pairEntry.isPhysicalPrimary(); - int statusD0Prompt = static_cast(pairEntry.isPrompt()); + bool isD0Prompt = pairEntry.isPrompt(); int statusPromptHadron = pairEntry.trackOrigin(); if (bdtScorePromptD0 < mlOutputPromptD0->at(ptBinD) || bdtScoreBkgD0 > mlOutputBkgD0->at(ptBinD) || @@ -529,15 +550,15 @@ struct HfTaskCorrelationD0Hadrons { // ---------------------- Fill plots for signal case, D0 ->1, D0bar ->8 --------------------------------------------- if ((massD > signalRegionLeft->at(ptBinD) && massD < signalRegionRight->at(ptBinD)) && (TESTBIT(signalStatus, ParticleTypeMcRec::D0Sig))) { // in signal region, tests bit ParticleTypeMcRec::D0Sig, SE-> softpi removed, ME-> inclusive - registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, statusD0Prompt, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, static_cast(isD0Prompt), poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecSig"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecSig"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecSig"), deltaPhi, efficiencyWeight); if (isPhysicalPrimary) { - registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryRecSig"), deltaPhi, deltaEta, ptD, ptHadron, statusD0Prompt, poolBin, efficiencyWeight); - if (statusD0Prompt == 1 && statusPromptHadron == 1) { + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryRecSig"), deltaPhi, deltaEta, ptD, ptHadron, static_cast(isD0Prompt), poolBin, efficiencyWeight); + if (isD0Prompt && statusPromptHadron == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hCorrel2DVsPtSignalRegionPromptD0PromptHadronRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); - } else if (statusD0Prompt == 0 && statusPromptHadron == 2) { + } else if (!isD0Prompt && statusPromptHadron == RecoDecay::OriginType::NonPrompt) { registry.fill(HIST("hCorrel2DVsPtSignalRegionNonPromptD0NonPromptHadronRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); } } @@ -545,15 +566,15 @@ struct HfTaskCorrelationD0Hadrons { if ((massDbar > signalRegionLeft->at(ptBinD) && massDbar < signalRegionRight->at(ptBinD)) && (TESTBIT(signalStatus, ParticleTypeMcRec::D0barSig))) { // in signal region, tests bit ParticleTypeMcRec::D0barSig, SE-> softpi removed, ME-> inclusive - registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, statusD0Prompt, poolBin, efficiencyWeight); + registry.fill(HIST("hCorrel2DVsPtSignalRegionRecSig"), deltaPhi, deltaEta, ptD, ptHadron, static_cast(isD0Prompt), poolBin, efficiencyWeight); registry.fill(HIST("hCorrel2DPtIntSignalRegionRecSig"), deltaPhi, deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaEtaPtIntSignalRegionRecSig"), deltaEta, efficiencyWeight); registry.fill(HIST("hDeltaPhiPtIntSignalRegionRecSig"), deltaPhi, efficiencyWeight); if (isPhysicalPrimary) { - registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryRecSig"), deltaPhi, deltaEta, ptD, ptHadron, statusD0Prompt, poolBin, efficiencyWeight); - if (statusD0Prompt == 1 && statusPromptHadron == 1) { + registry.fill(HIST("hCorrel2DVsPtPhysicalPrimaryRecSig"), deltaPhi, deltaEta, ptD, ptHadron, static_cast(isD0Prompt), poolBin, efficiencyWeight); + if (isD0Prompt && statusPromptHadron == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hCorrel2DVsPtSignalRegionPromptD0PromptHadronRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); - } else if (statusD0Prompt == 0 && statusPromptHadron == 2) { + } else if (!isD0Prompt && statusPromptHadron == RecoDecay::OriginType::NonPrompt) { registry.fill(HIST("hCorrel2DVsPtSignalRegionNonPromptD0NonPromptHadronRecSig"), deltaPhi, deltaEta, ptD, ptHadron, poolBin, efficiencyWeight); } } @@ -751,12 +772,12 @@ struct HfTaskCorrelationD0Hadrons { } if (isD0Prompt) { registry.fill(HIST("hCorrel2DVsPtGenPrompt"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); - if (statusPromptHadron == 1) { + if (statusPromptHadron == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hCorrel2DVsPtGenPromptD0PromptHadron"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); } } else { registry.fill(HIST("hCorrel2DVsPtGenNonPrompt"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); - if (statusPromptHadron == 2) { + if (statusPromptHadron == RecoDecay::OriginType::NonPrompt) { registry.fill(HIST("hCorrel2DVsPtGenNonPromptD0NonPromptHadron"), deltaPhi, deltaEta, ptD, ptHadron, poolBin); } } @@ -780,11 +801,11 @@ struct HfTaskCorrelationD0Hadrons { float multiplicity = -1.; for (const auto& mcParticle : mcParticles) { // generated candidates - if (std::abs(mcParticle.pdgCode()) != Pdg::kD0) { + if (std::abs(mcParticle.pdgCode()) == Pdg::kD0) { auto mcCollision = mcParticle.template mcCollision_as>(); multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C hCandidates->Fill(kCandidateStepMcGenAll, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); - if (std::abs(mcParticle.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(mcParticle.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { hCandidates->Fill(kCandidateStepMcGenD0ToPiKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); auto yD0 = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassD0); if (std::abs(yD0) <= yCandGenMax) { @@ -836,7 +857,7 @@ struct HfTaskCorrelationD0Hadrons { continue; } multiplicity = collision.multFT0M(); - if (std::abs(candidate.flagMcMatchRec()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicity, candidate.originMcRec()); if (std::abs(hfHelper.yD0(candidate)) <= yCandMax) { hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicity, candidate.originMcRec()); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx b/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx index f7b50def0a4..21321f51f21 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDDbar.cxx +++ b/PWGHF/HFC/Tasks/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/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.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/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx b/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx index 41a1f77836f..31082ef795a 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDMesonPairs.cxx @@ -14,15 +14,21 @@ /// /// \author Andrea Tavira García , IJCLab Orsay -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/DMesonPairsTables.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/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx index 339ab91a27c..ebdbab469df 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDplusHadrons.cxx @@ -13,21 +13,48 @@ /// \brief D+-Hadrons azimuthal correlations analysis task - data-like, MC-reco and MC-Gen analyses /// \author Shyam Kumar -#include // std::shared_ptr -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 // std::shared_ptr +#include +#include using namespace o2; using namespace o2::constants::math; @@ -80,7 +107,8 @@ struct HfTaskCorrelationDplusHadrons { Configurable selectionFlagDplus{"selectionFlagDplus", 7, "Selection Flag for D+"}; // 7 corresponds to topo+PID cuts Configurable selNoSameBunchPileUpColl{"selNoSameBunchPileUpColl", true, "Flag for rejecting the collisions associated with the same bunch crossing"}; Configurable> classMl{"classMl", {0, 1, 2}, "Indexes of ML scores to be stored. Three indexes max."}; - Configurable> mlScorePromptOrNonPrompt{"mlScorePromptOrNonPrompt", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for prompt or Feed-down"}; + Configurable> mlScorePromptOrNonPromptMin{"mlScorePromptOrNonPromptMin", {0.5, 0.5, 0.5, 0.5}, "Minimum Machine learning scores for prompt or Feed-down"}; + Configurable> mlScorePromptOrNonPromptMax{"mlScorePromptOrNonPromptMax", {1.0, 1.0, 1.0, 1.0}, "Maximum Machine learning scores for prompt or Feed-down"}; Configurable> mlScoreBkg{"mlScoreBkg", {0.5, 0.5, 0.5, 0.5}, "Machine learning scores for bkg"}; // pT ranges for correlation plots: the default values are those embedded in hf_cuts_dplus_to_pi_k_pi (i.e. the mass pT bins), but can be redefined via json files Configurable> binsPtCorrelations{"binsPtCorrelations", std::vector{ptBinsCorrelationsVec}, "pT bin limits for correlation plots"}; @@ -315,7 +343,7 @@ struct HfTaskCorrelationDplusHadrons { continue; } - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } double efficiencyWeightD = 1.; @@ -354,7 +382,7 @@ struct HfTaskCorrelationDplusHadrons { continue; } - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { @@ -417,7 +445,7 @@ struct HfTaskCorrelationDplusHadrons { if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) continue; - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } double efficiencyWeightD = 1.; @@ -471,7 +499,7 @@ struct HfTaskCorrelationDplusHadrons { if (ptD < binsPtEfficiencyD->front() || ptD > binsPtEfficiencyD->back()) continue; - if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPrompt->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { + if (bdtScorePromptOrNonPrompt < mlScorePromptOrNonPromptMin->at(effBinD) || bdtScorePromptOrNonPrompt > mlScorePromptOrNonPromptMax->at(effBinD) || bdtScoreBkg > mlScoreBkg->at(effBinD)) { continue; } if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { @@ -628,7 +656,7 @@ struct HfTaskCorrelationDplusHadrons { for (unsigned int iclass = 0; iclass < classMl->size(); iclass++) { outputMl[iclass] = candidate.mlProbDplusToPiKPi()[classMl->at(iclass)]; } - if (outputMl[0] > mlScoreBkg->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())) || outputMl[idxBdtScore] < mlScorePromptOrNonPrompt->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt()))) { + if (outputMl[0] > mlScoreBkg->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())) || outputMl[idxBdtScore] < mlScorePromptOrNonPromptMin->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt())) || outputMl[idxBdtScore] > mlScorePromptOrNonPromptMax->at(o2::analysis::findBin(binsPtEfficiencyD, candidate.pt()))) { continue; } auto collision = candidate.template collision_as>(); diff --git a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx index 3375d71b86d..51a56e5a766 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDsHadrons.cxx @@ -14,21 +14,47 @@ /// \author Grazia Luparello /// \author Samuele Cattaruzzi -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::constants::physics; @@ -36,6 +62,13 @@ using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; +enum ResonantChannel : int8_t { + PhiPi = 1, + Kstar0K = 2 +}; + +static std::unordered_map channelsResonant = {{{ResonantChannel::PhiPi, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi}, {ResonantChannel::Kstar0K, hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K}}}; + /// Ds-Hadron correlation pair filling task, from pair tables - for real data and data-like analysis (i.e. reco-level w/o matching request via MC truth) struct HfTaskCorrelationDsHadrons { Configurable fillHistoData{"fillHistoData", true, "Flag for filling histograms in data processes"}; @@ -48,11 +81,12 @@ struct HfTaskCorrelationDsHadrons { Configurable removeCollWSplitVtx{"removeCollWSplitVtx", false, "Flag for rejecting the splitted collisions"}; Configurable loadAccXEffFromCCDB{"loadAccXEffFromCCDB", false, "Flag for loading efficiency distributions from CCDB"}; Configurable separateTrackOrigins{"separateTrackOrigins", false, "Flag to enable separation of track origins (from c or b)"}; + Configurable useHighDimHistoForEff{"useHighDimHistoForEff", false, "Flag to create higher dimension histograms in the efficiency processes"}; // Configurable doMcCollisionCheck{"doMcCollisionCheck", false, "Flag for applying the collision check and selection based on MC collision info"}; Configurable selectionFlagDs{"selectionFlagDs", 7, "Selection Flag for Ds (avoid the case of flag = 0, no outputMlScore)"}; Configurable nTpcCrossedRaws{"nTpcCrossedRaws", 70, "Number of crossed TPC Rows"}; // Configurable eventGeneratorType{"eventGeneratorType", -1, "If positive, enable event selection using subGeneratorId information. The value indicates which events to keep (0 = MB, 4 = charm triggered, 5 = beauty triggered)"}; - Configurable decayChannel{"decayChannel", 1, "Decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; + Configurable decayChannel{"decayChannel", 1, "Resonant decay channels: 1 for Ds->PhiPi->KKpi, 2 for Ds->K0*K->KKPi"}; Configurable cutCollPosZMc{"cutCollPosZMc", 10., "max z-vertex position for collision acceptance"}; Configurable dcaXYTrackMax{"dcaXYTrackMax", 1., "max. DCA_xy of tracks"}; Configurable dcaZTrackMax{"dcaZTrackMax", 1., "max. DCA_z of tracks"}; @@ -87,25 +121,9 @@ struct HfTaskCorrelationDsHadrons { Configurable fdEffCcdbPath{"fdEffCcdbPath", "", "CCDB path for trigger efficiency"}; Configurable timestampCcdb{"timestampCcdb", -1, "timestamp of the efficiency files used to query in CCDB"}; - std::shared_ptr mEfficiencyD = nullptr; - std::shared_ptr mEfficiencyAssociated = nullptr; - - enum CandidateStep { - kCandidateStepMcGenDsToKKPi = 0, - kCandidateStepMcCandInAcceptance, - kCandidateStepMcDaughtersInAcceptance, - kCandidateStepMcReco, - kCandidateStepMcRecoInAcceptance, - kCandidateNSteps - }; - - enum AssocTrackStep { kAssocTrackStepMcGen = 0, - kAssocTrackStepMcGenInAcceptance, - kAssocTrackStepRecoAll, - kAssocTrackStepRecoMcMatch, - kAssocTrackStepRecoPrimaries, - kAssocTrackStepRecoSpecies, - kAssocTrackNSteps }; + std::shared_ptr hEfficiencyD = nullptr; + std::shared_ptr hEfficiencyAssociated = nullptr; + const float epsilon = 1.e-8; HfHelper hfHelper; SliceCache cache; @@ -135,6 +153,7 @@ struct HfTaskCorrelationDsHadrons { ConfigurableAxis binsPhi{"binsPhi", {64, -PIHalf, 3. * PIHalf}, "#it{#varphi}"}; ConfigurableAxis binsMultFT0M{"binsMultFT0M", {600, 0., 8000.}, "Multiplicity as FT0M signal amplitude"}; ConfigurableAxis binsPosZ{"binsPosZ", {100, -10., 10.}, "primary vertex z coordinate"}; + ConfigurableAxis binsNumPvContr{"binsNumPvContr", {100, 0., 1000.}, "number PV contributors"}; ConfigurableAxis binsPoolBin{"binsPoolBin", {9, 0., 9.}, "PoolBin"}; HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -151,6 +170,7 @@ struct HfTaskCorrelationDsHadrons { AxisSpec axisBdtScore = {binsBdtScore, "Bdt score"}; AxisSpec axisMultFT0M = {binsMultFT0M, "MultiplicityFT0M"}; AxisSpec axisPosZ = {binsPosZ, "PosZ"}; + AxisSpec axisNumPvContr = {binsNumPvContr, "Num PV contributors"}; AxisSpec axisDsPrompt = {2, -0.5, 1.5, "Prompt Ds"}; // Histograms for data analysis @@ -210,41 +230,52 @@ struct HfTaskCorrelationDsHadrons { } // Histograms for efficiencies if (fillHistoMcEff) { - registry.add("hPtCandMcRecPrompt", "Ds prompt candidates pt", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcRecNonPrompt", "Ds non prompt candidates pt", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtCandMcGenDaughterInAcc", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); - registry.add("hPtParticleAssocMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtMcParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPionMcRec", "Primary pions - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmKaonMcRec", "Primary kaons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmProtonMcRec", "Primary protons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmElectronMcRec", "Primary electrons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmMuonMcRec", "Primary muons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPromptPartMcRec", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmNonPromptPartMcRec", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPionMcGen", "Primary pions - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmKaonMcGen", "Primary kaons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmProtonMcGen", "Primary protons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmElectronMcGen", "Primary electrons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmMuonMcGen", "Primary muons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmPromptPartMcGen", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); - registry.add("hPtPrmNonPromptPartMcGen", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); registry.add("hFakeCollision", "Fake collision counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake coll"}}}); registry.add("hFakeTracks", "Fake tracks counter", {HistType::kTH1F, {{1, -0.5, 0.5, "n fake tracks"}}}); + registry.add("hNumPvContrib", "Num PV contributors", {HistType::kTH1F, {axisNumPvContr}}); + registry.add("hPtPrmPromptPartMcGen", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmNonPromptPartMcGen", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmPromptPartMcRec", "Primary prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmNonPromptPartMcRec", "Primary non-prompt particles - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtMcParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtParticleAssocMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtCandMcGenDaughterInAcc", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); - auto hCandidates = registry.add("hCandidates", "Candidate count at different steps", {HistType::kStepTHnF, {axisPtD, axisMultFT0M, {RecoDecay::OriginType::NonPrompt + 1, +RecoDecay::OriginType::None - 0.5, +RecoDecay::OriginType::NonPrompt + 0.5}}, kCandidateNSteps}); - hCandidates->GetAxis(0)->SetTitle("#it{p}_{T} (GeV/#it{c})"); - hCandidates->GetAxis(1)->SetTitle("multiplicity"); - hCandidates->GetAxis(2)->SetTitle("Charm hadron origin"); - auto hAssocTracks = registry.add("hAssocTracks", "Associated tracks at different steps", {HistType::kStepTHnF, {axisEta, axisPtHadron, axisMultFT0M, axisPosZ}, kAssocTrackNSteps}); - hAssocTracks->GetAxis(0)->SetTitle("#eta"); - hAssocTracks->GetAxis(1)->SetTitle("#it{p}_{T} (GeV/#it{c})"); - hAssocTracks->GetAxis(2)->SetTitle("multiplicity"); - hAssocTracks->GetAxis(3)->SetTitle("pos z"); + if (useHighDimHistoForEff) { + registry.add("hPtCandMcRecPrompt", "Ds prompt candidates", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtCandMcRecNonPrompt", "Ds non prompt candidates pt", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles prompt - MC Gen", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH2F, {{axisPtD}, {axisNumPvContr}}}); + registry.add("hPtParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTHnSparseF, {axisPtHadron}}); + registry.add("hPtPrmPionMcRec", "Primary pions - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmKaonMcRec", "Primary kaons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmProtonMcRec", "Primary protons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmElectronMcRec", "Primary electrons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmMuonMcRec", "Primary muons - MC Rec", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmPionMcGen", "Primary pions - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmKaonMcGen", "Primary kaons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmProtonMcGen", "Primary protons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmElectronMcGen", "Primary electrons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + registry.add("hPtPrmMuonMcGen", "Primary muons - MC Gen", {HistType::kTHnSparseF, {{axisPtHadron}, {axisEta}, {axisPosZ}, {axisNumPvContr}}}); + } else { + registry.add("hPtCandMcRecPrompt", "Ds prompt candidates pt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcRecNonPrompt", "Ds non prompt candidates pt", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcGenPrompt", "Ds,Hadron particles prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtCandMcGenNonPrompt", "Ds,Hadron particles non prompt - MC Gen", {HistType::kTH1F, {axisPtD}}); + registry.add("hPtParticleAssocSpecieMcRec", "Associated Particle - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmPionMcRec", "Primary pions - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmKaonMcRec", "Primary kaons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmProtonMcRec", "Primary protons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmElectronMcRec", "Primary electrons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmMuonMcRec", "Primary muons - MC Rec", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtParticleAssocMcGen", "Associated Particle - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmPionMcGen", "Primary pions - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmKaonMcGen", "Primary kaons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmProtonMcGen", "Primary protons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmElectronMcGen", "Primary electrons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + registry.add("hPtPrmMuonMcGen", "Primary muons - MC Gen", {HistType::kTH1F, {axisPtHadron}}); + } } // Loading efficiency histograms from CCDB @@ -254,26 +285,78 @@ struct HfTaskCorrelationDsHadrons { ccdb->setLocalObjectValidityChecking(); ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - mEfficiencyD = std::shared_ptr(ccdb->getForTimeStamp(promptEffCcdbPath, timestampCcdb)); - if (mEfficiencyD == nullptr) { + hEfficiencyD = std::shared_ptr(ccdb->getForTimeStamp(promptEffCcdbPath, timestampCcdb)); + if (hEfficiencyD == nullptr) { LOGF(fatal, "Could not load efficiency histogram for trigger particles from %s", promptEffCcdbPath.value.c_str()); } LOGF(info, "Loaded trigger efficiency (prompt D) histogram from %s", promptEffCcdbPath.value.c_str()); - mEfficiencyAssociated = std::shared_ptr(ccdb->getForTimeStamp(associatedEffCcdbPath, timestampCcdb)); - if (mEfficiencyAssociated == nullptr) { + hEfficiencyAssociated = std::shared_ptr(ccdb->getForTimeStamp(associatedEffCcdbPath, timestampCcdb)); + if (hEfficiencyAssociated == nullptr) { LOGF(fatal, "Could not load efficiency histogram for associated particles from %s", associatedEffCcdbPath.value.c_str()); } LOGF(info, "Loaded associated efficiency histogram from %s", associatedEffCcdbPath.value.c_str()); } } + enum class EfficiencyMode { + DsOnly = 1, + DsHadronPair = 2 + }; + bool isSelectedCandidate(const int ptBinD, const float bdtScorePrompt, const float bdtScoreBkg) { return (ptBinD != -1 && bdtScorePrompt >= mlOutputPromptMin->at(ptBinD) && bdtScorePrompt <= mlOutputPromptMax->at(ptBinD) && bdtScoreBkg <= mlOutputBkg->at(ptBinD)); } + double getEfficiencyWeight(float ptD, std::optional ptAssoc = std::nullopt, EfficiencyMode mode = EfficiencyMode::DsOnly) + { + if (!applyEfficiency) { + return 1.; + } + + double weight = 1.; + + switch (mode) { + case EfficiencyMode::DsOnly: + if (loadAccXEffFromCCDB) { + if (hEfficiencyD->GetBinContent(hEfficiencyD->FindBin(ptD)) <= epsilon) { + LOG(fatal) << "A bin content in Ds-meson efficiency histogram is zero!"; + } + weight = 1. / hEfficiencyD->GetBinContent(hEfficiencyD->FindBin(ptD)); + } else { + if (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) <= epsilon) { + LOG(fatal) << "A bin content in Ds-meson efficiency vector is zero!"; + } + weight = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); + } + break; + case EfficiencyMode::DsHadronPair: + if (loadAccXEffFromCCDB) { + if (ptAssoc && hEfficiencyAssociated) { + if (hEfficiencyAssociated->GetBinContent(hEfficiencyAssociated->FindBin(*ptAssoc)) <= epsilon) { + LOG(fatal) << "A bin content in associated particle efficiency histogram is zero!"; + } + weight = 1. / (hEfficiencyD->GetBinContent(hEfficiencyD->FindBin(ptD)) * hEfficiencyAssociated->GetBinContent(hEfficiencyAssociated->FindBin(*ptAssoc))); + } + } else { + if (ptAssoc) { + if (efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, *ptAssoc)) <= epsilon) { + LOG(fatal) << "A bin content in associated particle efficiency vector is zero!"; + } + weight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, *ptAssoc))); + } + } + break; + default: + LOG(fatal) << "Unknown efficiency mode!"; + break; + } + + return weight; + } + void processData(DsHadronPairWithMl const& pairEntries, aod::DsCandRecoInfo const& candidates) { @@ -288,13 +371,8 @@ struct HfTaskCorrelationDsHadrons { continue; } - double efficiencyWeightD = 1.; - if (applyEfficiency) { - efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); - if (loadAccXEffFromCCDB) { - efficiencyWeightD = 1. / mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)); - } - } + double efficiencyWeightD = getEfficiencyWeight(ptD); + registry.fill(HIST("hMassDsVsPt"), massD, ptD, efficiencyWeightD); registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); registry.fill(HIST("hBdtScoreBkg"), bdtScoreBkg); @@ -322,13 +400,8 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { @@ -368,13 +441,8 @@ struct HfTaskCorrelationDsHadrons { continue; } - double efficiencyWeightD = 1.; - if (applyEfficiency) { - efficiencyWeightD = 1. / efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)); - if (loadAccXEffFromCCDB) { - efficiencyWeightD = 1. / mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)); - } - } + double efficiencyWeightD = getEfficiencyWeight(ptD); + if (isDsPrompt) { registry.fill(HIST("hMassPromptDsVsPt"), massD, ptD, efficiencyWeightD); registry.fill(HIST("hBdtScorePrompt"), bdtScorePrompt); @@ -411,13 +479,9 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); + // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { // prompt and non-prompt division @@ -506,13 +570,8 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { @@ -548,13 +607,7 @@ struct HfTaskCorrelationDsHadrons { int poolBin = pairEntry.poolBin(); int ptBinD = o2::analysis::findBin(binsPtD, ptD); - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { @@ -606,13 +659,9 @@ struct HfTaskCorrelationDsHadrons { if (trackDcaXY > dcaXYTrackMax || trackDcaZ > dcaZTrackMax || trackTpcCrossedRows < nTpcCrossedRaws) { continue; } - double efficiencyWeight = 1.; - if (applyEfficiency) { - efficiencyWeight = 1. / (efficiencyD->at(o2::analysis::findBin(binsPtEfficiencyD, ptD)) * efficiencyHad->at(o2::analysis::findBin(binsPtEfficiencyHad, ptHadron))); - if (loadAccXEffFromCCDB) { - efficiencyWeight = 1. / (mEfficiencyD->GetBinContent(mEfficiencyD->FindBin(ptD)) * mEfficiencyAssociated->GetBinContent(mEfficiencyAssociated->FindBin(ptHadron))); - } - } + + double efficiencyWeight = getEfficiencyWeight(ptD, ptHadron, EfficiencyMode::DsHadronPair); + // in signal region if (massD > signalRegionInner->at(ptBinD) && massD < signalRegionOuter->at(ptBinD)) { // prompt and non-prompt division @@ -653,8 +702,6 @@ struct HfTaskCorrelationDsHadrons { CandDsMcReco const& candidates, aod::TracksWMc const&) { - auto hCandidates = registry.get(HIST("hCandidates")); - /// loop over generated collisions for (const auto& mcCollision : mcCollisions) { @@ -686,38 +733,43 @@ struct HfTaskCorrelationDsHadrons { continue; } - float multiplicityReco = collision.multFT0M(); - float multiplicityGen = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C + registry.fill(HIST("hNumPvContrib"), collision.numContrib()); const auto groupedCandidates = candidates.sliceBy(perCollisionCand, collision.globalIndex()); // generated candidate loop for (const auto& mcParticle : groupedMcParticles) { - if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { - hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); + if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == channelsResonant[decayChannel])) { auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); if (std::abs(yDs) <= yCandGenMax) { - hCandidates->Fill(kCandidateStepMcCandInAcceptance, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); + } } if (mcParticle.originMcGen() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcGenNonPrompt"), mcParticle.pt()); + } } - } - bool isDaughterInAcceptance = true; - auto daughters = mcParticle.template daughters_as(); - for (const auto& daughter : daughters) { - if (daughter.pt() < ptDaughterMin || std::abs(daughter.eta()) > etaTrackMax) { - isDaughterInAcceptance = false; + + bool isDaughterInAcceptance = true; + auto daughters = mcParticle.template daughters_as(); + for (const auto& daughter : daughters) { + if (daughter.pt() < ptDaughterMin || std::abs(daughter.eta()) > etaTrackMax) { + isDaughterInAcceptance = false; + } + } + if (isDaughterInAcceptance) { + registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); } - } - if (isDaughterInAcceptance) { - hCandidates->Fill(kCandidateStepMcDaughtersInAcceptance, mcParticle.pt(), multiplicityGen, mcParticle.originMcGen()); - registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); } } - } + } // end loop candidate gen // reconstructed candidate loop for (const auto& candidate : groupedCandidates) { @@ -734,28 +786,33 @@ struct HfTaskCorrelationDsHadrons { outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; } } - if (outputMl[0] < mlOutputPromptMin->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[0] < mlOutputPromptMax->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[2] > mlOutputBkg->at(o2::analysis::findBin(binsPtD, candidate.pt()))) { + if (outputMl[0] < mlOutputPromptMin->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[0] > mlOutputPromptMax->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[2] > mlOutputBkg->at(o2::analysis::findBin(binsPtD, candidate.pt()))) { continue; } - if ((std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanRec() == decayChannel)) { + if ((std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanRec() == channelsResonant[decayChannel])) { auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); // DsToKKPi and DsToPiKK division if (((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs))) { - hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicityReco, candidate.originMcRec()); if (std::abs(hfHelper.yDs(candidate)) <= yCandMax) { - hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicityReco, candidate.originMcRec()); if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { - registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt()); + } } if (candidate.originMcRec() == RecoDecay::OriginType::NonPrompt) { - registry.fill(HIST("hPtCandMcRecNonPrompt"), candidate.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtCandMcRecNonPrompt"), candidate.pt(), collision.numContrib()); + } else { + registry.fill(HIST("hPtCandMcRecNonPrompt"), candidate.pt()); + } } } } } - } - + } // end loop candidate reco } // end loop reconstructed collision } // end loop generated collisions } @@ -767,19 +824,12 @@ struct HfTaskCorrelationDsHadrons { CandDsMcReco const& candidates, aod::TracksWMc const&) { - auto hCandidates = registry.get(HIST("hCandidates")); - /// Gen loop - float multiplicity = -1.; for (const auto& mcParticle : mcParticles) { // generated candidates - if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == decayChannel)) { - auto mcCollision = mcParticle.template mcCollision_as>(); - multiplicity = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C - hCandidates->Fill(kCandidateStepMcGenDsToKKPi, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); + if ((std::abs(mcParticle.flagMcMatchGen()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (mcParticle.flagMcDecayChanGen() == channelsResonant[decayChannel])) { auto yDs = RecoDecay::y(mcParticle.pVector(), o2::constants::physics::MassDS); if (std::abs(yDs) <= yCandGenMax) { - hCandidates->Fill(kCandidateStepMcCandInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); if (mcParticle.originMcGen() == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hPtCandMcGenPrompt"), mcParticle.pt()); } @@ -795,7 +845,6 @@ struct HfTaskCorrelationDsHadrons { } } if (isDaughterInAcceptance) { - hCandidates->Fill(kCandidateStepMcDaughtersInAcceptance, mcParticle.pt(), multiplicity, mcParticle.originMcGen()); registry.fill(HIST("hPtCandMcGenDaughterInAcc"), mcParticle.pt()); } } @@ -816,21 +865,18 @@ struct HfTaskCorrelationDsHadrons { outputMl[iclass] = candidate.mlProbDsToPiKK()[classMl->at(iclass)]; } } - if (outputMl[0] < mlOutputPromptMin->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[0] < mlOutputPromptMax->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[2] > mlOutputBkg->at(o2::analysis::findBin(binsPtD, candidate.pt()))) { + if (outputMl[0] < mlOutputPromptMin->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[0] > mlOutputPromptMax->at(o2::analysis::findBin(binsPtD, candidate.pt())) || outputMl[2] > mlOutputBkg->at(o2::analysis::findBin(binsPtD, candidate.pt()))) { continue; } auto collision = candidate.template collision_as>(); if (selNoSameBunchPileUpColl && !(collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup))) { continue; } - multiplicity = collision.multFT0M(); - if ((std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanRec() == decayChannel)) { + if ((std::abs(candidate.flagMcMatchRec()) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) && (candidate.flagMcDecayChanRec() == channelsResonant[decayChannel])) { auto prong0McPart = candidate.template prong0_as().template mcParticle_as(); // DsToKKPi and DsToPiKK division if (((std::abs(prong0McPart.pdgCode()) == kKPlus) && (candidate.isSelDsToKKPi() >= selectionFlagDs)) || ((std::abs(prong0McPart.pdgCode()) == kPiPlus) && (candidate.isSelDsToPiKK() >= selectionFlagDs))) { - hCandidates->Fill(kCandidateStepMcReco, candidate.pt(), multiplicity, candidate.originMcRec()); if (std::abs(hfHelper.yDs(candidate)) <= yCandMax) { - hCandidates->Fill(kCandidateStepMcRecoInAcceptance, candidate.pt(), multiplicity, candidate.originMcRec()); if (candidate.originMcRec() == RecoDecay::OriginType::Prompt) { registry.fill(HIST("hPtCandMcRecPrompt"), candidate.pt()); } @@ -850,7 +896,6 @@ struct HfTaskCorrelationDsHadrons { aod::McParticles const& mcParticles, TracksWithMc const& tracksData) { - auto hAssocTracks = registry.get(HIST("hAssocTracks")); /// loop over generated collisions for (const auto& mcCollision : mcCollisions) { @@ -883,31 +928,39 @@ struct HfTaskCorrelationDsHadrons { continue; } - float multiplicityReco = collision.multFT0M(); - float posZReco = collision.posZ(); - float multiplicityGen = mcCollision.multMCFT0A() + mcCollision.multMCFT0C(); // multFT0M = multFt0A + multFT0C - float posZGen = mcCollision.posZ(); - const auto groupedTracks = tracksData.sliceBy(perCollision, collision.globalIndex()); // generated track loop for (const auto& mcParticle : groupedMcParticles) { if (mcParticle.isPhysicalPrimary() && ((std::abs(mcParticle.pdgCode()) == kElectron) || (std::abs(mcParticle.pdgCode()) == kMuonMinus) || (std::abs(mcParticle.pdgCode()) == kPiPlus) || (std::abs(mcParticle.pdgCode()) == kKPlus) || (std::abs(mcParticle.pdgCode()) == kProton))) { if (mcParticle.pt() > ptTrackMin && mcParticle.pt() < ptTrackMax) { - hAssocTracks->Fill(kAssocTrackStepMcGen, mcParticle.eta(), mcParticle.pt(), multiplicityGen, posZGen); if (std::abs(mcParticle.eta()) < etaTrackMax) { - hAssocTracks->Fill(kAssocTrackStepMcGenInAcceptance, mcParticle.eta(), mcParticle.pt(), multiplicityGen, posZGen); - registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt()); - if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt(), mcParticle.eta(), collision.posZ(), collision.numContrib()); + } + } else { + registry.fill(HIST("hPtParticleAssocMcGen"), mcParticle.pt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcGen"), mcParticle.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcGen"), mcParticle.pt()); + } } if (separateTrackOrigins) { int trackOrigin = RecoDecay::getCharmHadronOrigin(mcParticles, mcParticle, true); @@ -928,26 +981,38 @@ struct HfTaskCorrelationDsHadrons { continue; } if (track.has_mcParticle()) { - hAssocTracks->Fill(kAssocTrackStepRecoMcMatch, track.eta(), track.pt(), multiplicityReco, posZReco); auto mcParticle = track.template mcParticle_as(); if (mcParticle.isPhysicalPrimary()) { - hAssocTracks->Fill(kAssocTrackStepRecoPrimaries, track.eta(), track.pt(), multiplicityReco, posZReco); registry.fill(HIST("hPtParticleAssocMcRec"), track.pt()); if ((std::abs(mcParticle.pdgCode()) == kElectron) || (std::abs(mcParticle.pdgCode()) == kMuonMinus) || (std::abs(mcParticle.pdgCode()) == kPiPlus) || (std::abs(mcParticle.pdgCode()) == kKPlus) || (std::abs(mcParticle.pdgCode()) == kProton)) { - hAssocTracks->Fill(kAssocTrackStepRecoSpecies, track.eta(), track.pt(), multiplicityReco, posZReco); - registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); // check the pt spectra of mcParticle registry.fill(HIST("hPtMcParticleAssocSpecieMcRec"), mcParticle.pt()); - if (std::abs(mcParticle.pdgCode()) == kPiPlus) { - registry.fill(HIST("hPtPrmPionMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { - registry.fill(HIST("hPtPrmKaonMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kProton) { - registry.fill(HIST("hPtPrmProtonMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kElectron) { - registry.fill(HIST("hPtPrmElectronMcRec"), track.pt()); - } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { - registry.fill(HIST("hPtPrmMuonMcRec"), track.pt()); + if (useHighDimHistoForEff) { + registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcRec"), track.pt(), track.eta(), collision.posZ(), collision.numContrib()); + } + } else { + registry.fill(HIST("hPtParticleAssocSpecieMcRec"), track.pt()); + if (std::abs(mcParticle.pdgCode()) == kPiPlus) { + registry.fill(HIST("hPtPrmPionMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kKPlus) { + registry.fill(HIST("hPtPrmKaonMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kProton) { + registry.fill(HIST("hPtPrmProtonMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kElectron) { + registry.fill(HIST("hPtPrmElectronMcRec"), track.pt()); + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { + registry.fill(HIST("hPtPrmMuonMcRec"), track.pt()); + } } // check track origin if (separateTrackOrigins) { diff --git a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx index 1e002d9118d..eb450cc7e61 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationDstarHadrons.cxx @@ -14,18 +14,23 @@ /// \author Fabrizio Grosa , CERN /// \author Shyam Kumar -#include - -// Framework -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// PWGHF #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/Utils/utilsAnalysis.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/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx index 94786e27372..00202c55122 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationHfeHadrons.cxx @@ -14,13 +14,16 @@ /// \author Rashi Gupta , IIT Indore /// \author Ravindra Singh , IIT Indore -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" +#include +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx index 791dd045f99..84386ab9794 100644 --- a/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx +++ b/PWGHF/HFC/Tasks/taskCorrelationLcHadrons.cxx @@ -14,22 +14,49 @@ /// \author Marianna Mazzilli /// \author Zhen Zhang -#include // std::shared_ptr -#include -#include - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" #include "PWGHF/HFC/DataModel/CorrelationTables.h" #include "PWGHF/HFC/Utils/utilsCorrelations.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/Core/RecoDecay.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 // std::shared_ptr +#include +#include using namespace o2; using namespace o2::constants::math; diff --git a/PWGHF/HFC/Tasks/taskFlow.cxx b/PWGHF/HFC/Tasks/taskFlow.cxx index 981ce78e7ca..b3813942454 100644 --- a/PWGHF/HFC/Tasks/taskFlow.cxx +++ b/PWGHF/HFC/Tasks/taskFlow.cxx @@ -15,42 +15,46 @@ /// \author Katarina Krizkova Gajdosova , CERN /// \author Maja Kabus , CERN -#include -#include - -#include -#include -#include +#include "PWGCF/Core/CorrelationContainer.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsPid.h" +#include "PWGMM/Mult/DataModel/bestCollisionTable.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/Logger.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/GlobalTrackID.h" - -#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/MathConstants.h" -#include "PWGMM/Mult/DataModel/Index.h" -#include "PWGMM/Mult/DataModel/bestCollisionTable.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsPid.h" +#include +#include +#include +#include using namespace o2; using namespace o2::analysis; @@ -59,6 +63,29 @@ using namespace o2::constants::math; using namespace o2::framework; using namespace o2::framework::expressions; +enum MftTrackSelectionStep { + NoSelection = 0, + Eta, + Cluster, + NMftTrackSelectionSteps +}; + +enum MftTrackAmbiguityStep { + AllMftTracks = 0, + AfterTrackSelection, + NumberOfAmbiguousTracks, + NumberOfNonAmbiguousTracks, + NMftAmbiguitySteps +}; + +enum EventSelectionStep { + AllEvents = 0, + AfterEventSelection, + NEventSelectionSteps +}; + +// static constexpr float kPairCutDefaults[1][5] = {{-1, -1, -1, -1, -1}}; + struct HfTaskFlow { // configurables for processing options @@ -66,11 +93,13 @@ struct HfTaskFlow { Configurable centralityBinsForMc{"centralityBinsForMc", false, "false = OFF, true = ON for data like multiplicity/centrality bins for MC steps"}; Configurable mftMaxDCAxy{"mftMaxDCAxy", 2.0f, "Cut on dcaXY for MFT tracks"}; Configurable doReferenceFlow{"doReferenceFlow", false, "Flag to know if reference flow should be done"}; + // Configurable doTwoTrackCut{"doTwoTrackCut", -1, "Two track cut: -1 = off; >0 otherwise distance value (suggested: 0.02)"}; Configurable processRun2{"processRun2", false, "Flag to run on Run 2 data"}; Configurable processRun3{"processRun3", true, "Flag to run on Run 3 data"}; Configurable processMc{"processMc", false, "Flag to run on MC"}; Configurable nMixedEvents{"nMixedEvents", 5, "Number of mixed events per event"}; - // configurables for collisions + // Configurable twoTrackCutMinRadius{"twoTrackCutMinRadius", 0.8f, "Two track cut : radius in m from which two tracks cuts are applied"}; + // configurables for collisions Configurable zVertexMax{"zVertexMax", 7.0f, "Accepted z-vertex range"}; // configurables for TPC tracks Configurable etaTpcTrackMax{"etaTpcTrackMax", 0.8f, "max. eta of TPC tracks"}; @@ -93,6 +122,7 @@ struct HfTaskFlow { HfHelper hfHelper; SliceCache cache; Service pdg; + // Service ccdb; std::vector hfIndexCache; // ========================= @@ -102,8 +132,11 @@ struct HfTaskFlow { using FilteredCollisionsWSelMult = soa::Filtered>; using HfCandidatesSelD0 = soa::Filtered>; using HfCandidatesSelLc = soa::Filtered>; - // using FilteredMftTracksWColls = soa::Filtered>; - using FilteredMftTracksWColls = soa::Filtered; + + // using FilteredMftTracks = soa::Filtered; + // using FilteredMftTracksWColls = soa::Filtered>; + // using FilteredAndReassociatedMftTracks = soa::Filtered>; + using FilteredTracksWDcaSel = soa::Filtered>; // ========================= @@ -122,7 +155,7 @@ struct HfTaskFlow { using McParticles2ProngMatched = soa::Join; using McParticles3ProngMatched = soa::Join; // using FilteredMftTracksWCollsMcLabels = soa::Filtered>; - using FilteredMftTracksWCollsMcLabels = soa::Filtered>; + using MftTracksMcLabels = soa::Join; using FilteredTracksWDcaSelMC = soa::Filtered>; // ========================= @@ -145,12 +178,12 @@ struct HfTaskFlow { (aod::track::pt > ptTpcTrackMin) && requireGlobalTrackWoPtEtaInFilter(); - Filter mftTrackEtaFilter = (aod::fwdtrack::eta < etaMftTrackMax) && - (aod::fwdtrack::eta > etaMftTrackMin); - - Filter mftTrackCollisionIdFilter = (aod::fwdtrack::bestCollisionId >= 0); + // Filter mftTrackEtaFilter = (aod::fwdtrack::eta < etaMftTrackMax) && + // (aod::fwdtrack::eta > etaMftTrackMin); - Filter mftTrackDcaFilter = (nabs(aod::fwdtrack::bestDCAXY) < mftMaxDCAxy); + // Filters below will be used for uncertainties + // Filter mftTrackCollisionIdFilter = (aod::fwdtrack::bestCollisionId >= 0); + // Filter mftTrackDcaFilter = (nabs(aod::fwdtrack::bestDCAXY) < mftMaxDCAxy); // ========================= // Filters & partitions : MC @@ -181,13 +214,13 @@ struct HfTaskFlow { // Preslice : DATA // ========================= - // Preslice dataPerCol = aod::track::collisionId; + Preslice perCol = o2::aod::fwdtrack::collisionId; // ========================= // Preslice : MC // ========================= - Preslice mftTracksPerCollision = aod::fwdtrack::collisionId; + Preslice mftTracksPerCollision = aod::fwdtrack::collisionId; // Preslice d0CandidatesPerCollision = aod::hf_cand::collisionId; // Preslice mcPerCol = aod::mcparticle::mcCollisionId; // PresliceUnsorted collisionsMcLabelPerMcCollision = aod::mccollisionlabel::mcCollisionId; @@ -230,23 +263,46 @@ struct HfTaskFlow { // ========================= void init(InitContext&) { + const int nBinsMix = axisMultiplicity->size() * axisVertex->size(); + // ========================= // Event histograms // TO-DO : do i have to separate event histograms between DATA and MC ? // ========================= - constexpr int kNBinsEvents = 2; - registry.add("Data/hEventCounter", "hEventCounter", {HistType::kTH1F, {{kNBinsEvents, 0.5, 0.5 + kNBinsEvents}}}); - // set axes of the event counter histogram - std::string labels[kNBinsEvents]; - labels[0] = "all"; - labels[1] = "after Physics selection"; - const int nBinsMix = axisMultiplicity->size() * 14; // 14 bins for z-vertex + registry.add("Data/hEventCounter", "hEventCounter", {HistType::kTH1D, {{EventSelectionStep::NEventSelectionSteps, -0.5, +EventSelectionStep::NEventSelectionSteps - 0.5}}}); + std::string labels[EventSelectionStep::NEventSelectionSteps]; + labels[EventSelectionStep::AllEvents] = "all"; + labels[EventSelectionStep::AfterEventSelection] = "after Physics selection"; + registry.get(HIST("Data/hEventCounter"))->SetMinimum(0); - for (int iBin = 0; iBin < kNBinsEvents; iBin++) { + for (int iBin = 0; iBin < EventSelectionStep::NEventSelectionSteps; iBin++) { registry.get(HIST("Data/hEventCounter"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); } + registry.add("Data/TpcMft/hAmbiguityOfMftTracks", "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("Data/TpcMft/hAmbiguityOfMftTracks"))->SetMinimum(0); + + for (int iBin = 0; iBin < NMftAmbiguitySteps; iBin++) { + registry.get(HIST("Data/TpcMft/hAmbiguityOfMftTracks"))->GetXaxis()->SetBinLabel(iBin + 1, labelsAmbiguityOfMftTracks[iBin].data()); + } + + registry.add("Data/TpcMft/hMftTracksSelection", "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"; + registry.get(HIST("Data/TpcMft/hMftTracksSelection"))->SetMinimum(0); + + for (int iBin = 0; iBin < MftTrackSelectionStep::NMftTrackSelectionSteps; iBin++) { + registry.get(HIST("Data/TpcMft/hMftTracksSelection"))->GetXaxis()->SetBinLabel(iBin + 1, labelsMftTracksSelection[iBin].data()); + } + // ========================= // DATA : histograms for TPC-TPC h-h case // ========================= @@ -254,12 +310,12 @@ struct HfTaskFlow { // DATA : event histograms for TPC-TPC h-h same event registry.add("Data/TpcTpc/HadronHadron/SameEvent/hMultiplicity", "hMultiplicity", {HistType::kTH1F, {axisMultiplicity}}); registry.add("Data/TpcTpc/HadronHadron/SameEvent/hVtxZ", "hVtxZ", {HistType::kTH1F, {axisVertex}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); // DATA : associated particles histograms for TPC-TPC h-h same event registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPt", "pT", {HistType::kTH1F, {axisPt}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {axisEtaTpc}}); - registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {axisPhi}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEta", "eta", {HistType::kTH1D, {axisEtaTpc}}); + registry.add("Data/TpcTpc/HadronHadron/SameEvent/hPhi", "phi", {HistType::kTH1D, {axisPhi}}); registry.add("Data/TpcTpc/HadronHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaTpc}}); registry.add("Data/TpcTpc/HadronHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {axisMultiplicity, axisEtaTpc, axisPhi}}); @@ -267,7 +323,7 @@ struct HfTaskFlow { registry.add("Data/TpcTpc/HadronHadron/SameEvent/hVzEta", "eta vs. Vz", {HistType::kTH2F, {axisEtaTpc, axisVertex}}); // DATA : event mixing histograms for TPC-TPC h-h mixed event - registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); // ========================= // DATA : histograms for TPC-TPC HF-h case for 2PRONG @@ -275,16 +331,16 @@ struct HfTaskFlow { // DATA : event histograms for TPC-TPC HF-h same event registry.add("Data/TpcTpc/HfHadron/SameEvent/hPt", "pT", {HistType::kTH1F, {axisPt}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/hEta", "eta", {HistType::kTH1F, {axisEtaTpc}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/hPhi", "phi", {HistType::kTH1F, {axisPhi}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hEta", "eta", {HistType::kTH1D, {axisEtaTpc}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/hPhi", "phi", {HistType::kTH1D, {axisPhi}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/hYields", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaTpc}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/hEtaPhi", "multiplicity vs eta vs phi", {HistType::kTH3F, {axisMultiplicity, axisEtaTpc, axisPhi}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hEventCountSame", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hEta", "eta", {HistType::kTH1F, {axisEtaTpc}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hPhi", "phi", {HistType::kTH1F, {axisPhi}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hEventCountSame", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hEta", "eta", {HistType::kTH1D, {axisEtaTpc}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hPhi", "phi", {HistType::kTH1D, {axisPhi}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hMultiplicity", "multiplicity;multiplicity;entries", {HistType::kTH1F, {axisMultiplicity}}); - registry.add("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); // DATA : trigger particles (candidates) histograms for TPC-TPC D0-h same event registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hPtCandidate", "2-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); @@ -292,7 +348,7 @@ struct HfTaskFlow { registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hMassVsPt", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisMass, axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hMassVsPtVsMult", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2}); p_{T}; multiplicity", {HistType::kTH3F, {axisMass, axisPt, axisMultiplicity}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {axisMass}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hEtaCandVsPt", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {axisEtaTpc, axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/2Prong/hSelectionStatus", "2-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, axisPt}}); @@ -300,17 +356,17 @@ struct HfTaskFlow { // DATA : histograms for TPC-TPC HF-h case for 3PRONG // =================== - registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hEventCountSame", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hEventCountSame", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hMassVsPt", "3-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisMass, axisPt}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hMass", "3-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hMass", "3-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {axisMass}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hMassVsPtVsMult", "3-prong candidates;inv. mass (p K #pi) (GeV/#it{c}^{2}); p_{T}; multiplicity", {HistType::kTH3F, {axisMass, axisPt, axisMultiplicity}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hMultiplicity", "multiplicity;multiplicity;entries", {HistType::kTH1F, {axisMultiplicity}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hPt", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hPtProng0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hPtProng1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hPtProng2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hEta", "3-prong candidates;#it{#eta};entries", {HistType::kTH1F, {axisEtaTpc}}); - registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hPhi", "3-prong candidates;#it{#Phi};entries", {HistType::kTH1F, {axisPhi}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hEta", "3-prong candidates;#it{#eta};entries", {HistType::kTH1D, {axisEtaTpc}}); + registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hPhi", "3-prong candidates;#it{#Phi};entries", {HistType::kTH1D, {axisPhi}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hEtaVsPt", "3-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {axisEtaTpc, axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hPhiVsPt", "3-prong candidates;candidate #it{#Phi};entries", {HistType::kTH2F, {axisPhi, axisPt}}); registry.add("Data/TpcTpc/HfHadron/SameEvent/3Prong/hSelectionStatus", "3-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, axisPt}}); @@ -320,34 +376,34 @@ struct HfTaskFlow { // ========================= // DATA : trigger particles (TPC tracks) histograms for TPC-MFT h-h same event - registry.add("Data/TpcMft/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hEventCountSame", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaPhiTPC", "multiplicity vs eta vs phi in TPC", {HistType::kTH3F, {axisMultiplicity, axisEtaTpc, axisPhi}}); - registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaTPC", "etaTPC", {HistType::kTH1F, {axisEtaTpc}}); - registry.add("Data/TpcMft/HadronHadron/SameEvent/hPhiTPC", "phiTPC", {HistType::kTH1F, {axisPhi}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaTPC", "etaTPC", {HistType::kTH1D, {axisEtaTpc}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hPhiTPC", "phiTPC", {HistType::kTH1D, {axisPhi}}); registry.add("Data/TpcMft/HadronHadron/SameEvent/hPtTPC", "pT", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HadronHadron/SameEvent/hYieldsTPC", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaTpc}}); registry.add("Data/TpcMft/HadronHadron/SameEvent/hMultiplicityTPC", "multiplicity;multiplicity;entries", {HistType::kTH1F, {axisMultiplicity}}); // DATA : associated particles (MFT tracks) histograms for TPC-MFT h-h same event registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaPhiMFT", "multiplicity vs eta vs phi in MFT", {HistType::kTH3F, {axisMultiplicity, axisEtaMft, axisPhi}}); - registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaMFT", "etaMFT", {HistType::kTH1F, {axisEtaMft}}); - registry.add("Data/TpcMft/HadronHadron/SameEvent/hPhiMFT", "phiMFT", {HistType::kTH1F, {axisPhi}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hEtaMFT", "etaMFT", {HistType::kTH1D, {axisEtaMft}}); + registry.add("Data/TpcMft/HadronHadron/SameEvent/hPhiMFT", "phiMFT", {HistType::kTH1D, {axisPhi}}); registry.add("Data/TpcMft/HadronHadron/SameEvent/hPtMFT", "pT", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HadronHadron/SameEvent/hYieldsMFT", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaMft}}); // DATA : histograms for TPC-MFT h-h event mixing for events QA - registry.add("Data/TpcMft/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcMft/HadronHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); // ========================= // DATA : histograms for TPC-MFT HF-h case FOR 2PRONG // ========================= // DATA : trigger particles (candidates) histograms for TPC-MFT HF-h same event - registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hEventCountSame", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hEventCountSame", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hEtaPhiCandidate", "multiplicity vs eta vs phi in TPC", {HistType::kTH3F, {axisMultiplicity, axisEtaMft, axisPhi}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hEtaCandidate", "etaTPC", {HistType::kTH1F, {axisEtaMft}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hPhiCandidate", "phiTPC", {HistType::kTH1F, {axisPhi}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hYieldsCandidate", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaMft}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hEtaCandidate", "etaTPC", {HistType::kTH1D, {axisEtaTpc}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hPhiCandidate", "phiTPC", {HistType::kTH1D, {axisPhi}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hYieldsCandidate", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaTpc}}); registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hMultiplicityCandidate", "multiplicity;multiplicity;entries", {HistType::kTH1F, {axisMultiplicity}}); // DATA : trigger particles (candidates) histograms for TPC-MFT HF-h same event @@ -355,42 +411,55 @@ struct HfTaskFlow { registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hPtProng0", "2-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hPtProng1", "2-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hMassVsPt", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisMass, axisPt}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hMass", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {axisMass}}); registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hMassVsPtVsMult", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2}); p_{T}; multiplicity", {HistType::kTH3F, {axisMass, axisPt, axisMultiplicity}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hEtaCandVsPt", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {axisEtaMft, axisPt}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hEtaCandVsPt", "2-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {axisEtaTpc, axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/2Prong/hSelectionStatus", "2-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, axisPt}}); // DATA : associated particles (MFT tracks) histograms for TPC-MFT h-h same event registry.add("Data/TpcMft/HfHadron/SameEvent/hEtaPhiMFT", "multiplicity vs eta vs phi in MFT", {HistType::kTH3F, {axisMultiplicity, axisEtaMft, axisPhi}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/hEtaMFT", "etaMFT", {HistType::kTH1F, {axisEtaMft}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/hPhiMFT", "phiMFT", {HistType::kTH1F, {axisPhi}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hEtaMFT", "etaMFT", {HistType::kTH1D, {axisEtaMft}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/hPhiMFT", "phiMFT", {HistType::kTH1D, {axisPhi}}); registry.add("Data/TpcMft/HfHadron/SameEvent/hPtMFT", "pT", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/hYieldsMFT", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaMft}}); // DATA : histograms for TPC-MFT h-h event mixing for events QA - registry.add("Data/TpcMft/HfHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcMft/HfHadron/MixedEvent/hEventCountMixing", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); // ========================= // DATA : histograms for TPC-MFT HF-h case FOR 3PRONG // ========================= - registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEventCountSame", "bin", {HistType::kTH1F, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hYieldsCandidate", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaMft}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEventCountSame", "bin", {HistType::kTH1D, {{nBinsMix + 2, -2.5, -0.5 + nBinsMix, "bin"}}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hYieldsCandidate", "multiplicity vs pT vs eta", {HistType::kTH3F, {axisMultiplicity, axisPt, axisEtaTpc}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hMultiplicityCandidate", "multiplicity;multiplicity;entries", {HistType::kTH1F, {axisMultiplicity}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEtaPhiCandidate", "multiplicity vs eta vs phi in TPC", {HistType::kTH3F, {axisMultiplicity, axisEtaMft, axisPhi}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEtaPhiCandidate", "multiplicity vs eta vs phi in TPC", {HistType::kTH3F, {axisMultiplicity, axisEtaTpc, axisPhi}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hMassVsPt", "3-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH2F, {axisMass, axisPt}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hMass", "3-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hMass", "3-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {axisMass}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hMassVsPtVsMult", "3-prong candidates;inv. mass (p K #pi) (GeV/#it{c}^{2}); p_{T}; multiplicity", {HistType::kTH3F, {axisMass, axisPt, axisMultiplicity}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hPt", "3-prong candidates;candidate #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hPtProng0", "3-prong candidates;prong 0 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hPtProng1", "3-prong candidates;prong 1 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hPtProng2", "3-prong candidates;prong 2 #it{p}_{T} (GeV/#it{c});entries", {HistType::kTH1F, {axisPt}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEta", "3-prong candidates;#it{#eta};entries", {HistType::kTH1F, {axisEtaMft}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hPhi", "3-prong candidates;#it{#Phi};entries", {HistType::kTH1F, {axisPhi}}); - registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEtaVsPt", "3-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {axisEtaMft, axisPt}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEta", "3-prong candidates;#it{#eta};entries", {HistType::kTH1D, {axisEtaTpc}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hPhi", "3-prong candidates;#it{#Phi};entries", {HistType::kTH1D, {axisPhi}}); + registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hEtaVsPt", "3-prong candidates;candidate #it{#eta};entries", {HistType::kTH2F, {axisEtaTpc, axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hPhiVsPt", "3-prong candidates;candidate #it{#Phi};entries", {HistType::kTH2F, {axisPhi, axisPt}}); registry.add("Data/TpcMft/HfHadron/SameEvent/3Prong/hSelectionStatus", "3-prong candidates;selection status;entries", {HistType::kTH2F, {{5, -0.5, 4.5}, axisPt}}); + // ========================= + // DATA : histograms for MFT reassociated distributions (to plot all MFT tracks, and only non-ambiguous MFT trakcs) + // ressociated tracks distribution can be found in the normal eta and phi distributions of each individual cases + // ========================= + + // All MFT tracks + registry.add("Data/TpcMft/kCFStepAll/hEta", "eta", {HistType::kTH1D, {axisEtaMft}}); + registry.add("Data/TpcMft/kCFStepAll/hPhi", "phi", {HistType::kTH1D, {axisPhi}}); + + // Only non-ambiguous MFT tracks + registry.add("Data/TpcMft/kCFStepTracked/hEta", "eta", {HistType::kTH1D, {axisEtaMft}}); + registry.add("Data/TpcMft/kCFStepTracked/hPhi", "phi", {HistType::kTH1D, {axisPhi}}); + // ========================= // MC : histograms for TPC-TPC h-h case // ========================= @@ -719,7 +788,7 @@ struct HfTaskFlow { bool isAcceptedCollision(TCollision const& collision, bool fillHistograms = false) { if (fillHistograms) { - registry.fill(HIST("Data/hEventCounter"), 1); + registry.fill(HIST("Data/hEventCounter"), EventSelectionStep::AllEvents); } if (processMc == false) { @@ -729,7 +798,7 @@ struct HfTaskFlow { } if (fillHistograms) { - registry.fill(HIST("Data/hEventCounter"), 2); + registry.fill(HIST("Data/hEventCounter"), EventSelectionStep::AfterEventSelection); } return true; @@ -771,29 +840,54 @@ struct HfTaskFlow { // 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 isAcceptedMftTrack(TTrack const& mftTrack, bool fillHistograms) { // cut on the eta of MFT tracks - // if (mftTrack.eta() > etaMftTrackMax || mftTrack.eta() < etaMftTrackMin) { - // return false; - // } + if (mftTrack.eta() > etaMftTrackMax || mftTrack.eta() < etaMftTrackMin) { + return false; + } + + if (fillHistograms) { + registry.fill(HIST("Data/TpcMft/hMftTracksSelection"), MftTrackSelectionStep::Eta); + } // cut on the number of clusters of the reconstructed MFT track if (mftTrack.nClusters() < nClustersMftTrack) { return false; } + if (fillHistograms) { + registry.fill(HIST("Data/TpcMft/hMftTracksSelection"), MftTrackSelectionStep::Cluster); + } + 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/TpcMft/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfAmbiguousTracks); + } + return true; + } + + if (fillHistograms) { + registry.fill(HIST("Data/TpcMft/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::NumberOfNonAmbiguousTracks); + } + return false; + } + // I am not sure if to template McParticles is useful, I'll address this when doing the MC Gen case of HF-h correlations - template + template bool isAcceptedMcCandidate(TMcTrack& mcCandidate) { auto etaCandidate = mcCandidate.eta(); if constexpr (std::is_same_v) { // For now, that means we do D0 - if (std::abs(mcCandidate.flagMcMatchGen()) == 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(mcCandidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { if (etaCandidateMax >= 0. && std::abs(etaCandidate) > etaCandidateMax) { return false; @@ -866,8 +960,8 @@ struct HfTaskFlow { // fillCorrelations // =============================================================================================================================================================================== - template - void fillCorrelations(TTarget target, + template + void fillCorrelations(TTarget target, CorrelationContainer::CFStep step, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, float multiplicity, float posZ, bool sameEvent) { @@ -915,7 +1009,7 @@ struct HfTaskFlow { // Selections for MC GENERATED if constexpr (std::is_same_v || std::is_same_v) { // TODO: Check how to put this into a Filter -> Pretty sure it cannot be a filter - if (!isAcceptedMcCandidate(track1)) { + if (!isAcceptedMcCandidate(track1)) { continue; } fillingHFcontainer = true; @@ -936,10 +1030,10 @@ struct HfTaskFlow { } // FILL QA PLOTS for trigger particle - if (sameEvent) { - if (processMc == false) { // If DATA - if constexpr (!std::is_same_v) { // IF TPC-TPC case - if constexpr (std::is_same_v) { // IF D0 CASE -> TPC-TPC D0-h + if (sameEvent && (step == CorrelationContainer::kCFStepReconstructed)) { + if (processMc == false) { // If DATA + if constexpr (!std::is_same_v) { // IF TPC-TPC case + if constexpr (std::is_same_v) { // IF D0 CASE -> TPC-TPC D0-h fillTpcTpcD0CandidateQa(multiplicity, track1); } else if constexpr (std::is_same_v) { // IF LC CASE -> TPC-TPC Lc-h fillTpcTpcLcCandidateQa(multiplicity, track1); @@ -956,8 +1050,8 @@ struct HfTaskFlow { } // end of if condition for TPC-TPC or TPC-MFT case } // Maybe I won't need it for MC (first files are way lighter in MC, but also I need to loop over all tracks in MC GEN) - } else { // If MC (add cases later) - if constexpr (!std::is_same_v) { // IF TPC-TPC case + } else { // If MC (add cases later) + if constexpr (!std::is_same_v) { // IF TPC-TPC case fillTpcTpcChChSameEventQaMc(multiplicity, track1); } } @@ -969,8 +1063,10 @@ struct HfTaskFlow { for (const auto& track2 : tracks2) { // apply cuts for MFT tracks - if constexpr (std::is_same_v) { - if (!isAcceptedMftTrack(track2)) { + if constexpr (std::is_same_v) { + registry.fill(HIST("Data/TpcMft/hMftTracksSelection"), MftTrackSelectionStep::NoSelection); + + if (!isAcceptedMftTrack(track2, true)) { continue; } } @@ -985,8 +1081,8 @@ struct HfTaskFlow { // in case of HF-h correlations, remove candidate daughters from the pool of associated hadrons // with which the candidate is being correlated (will not have to do it for TPC-MFT case) - if constexpr (!std::is_same_v) { // if NOT TPC-MFT case -> TPC-TPC case - if constexpr (std::is_same_v) { // Remove the 2 prong daughters + if constexpr (!std::is_same_v) { // if NOT TPC-MFT case -> TPC-TPC case + if constexpr (std::is_same_v) { // Remove the 2 prong daughters if ((track1.prong0Id() == track2.globalIndex()) || (track1.prong1Id() == track2.globalIndex())) { continue; } @@ -1006,6 +1102,10 @@ struct HfTaskFlow { } } + // if constexpr (std::is_same_v) { + // registry.fill(HIST("MC/Gen/TpcMft/HfHadron/SameEvent/hEtaMFT"), track2.eta()); + // } + float eta2 = track2.eta(); float pt2 = track2.pt(); float phi2 = track2.phi(); @@ -1019,6 +1119,7 @@ struct HfTaskFlow { // set range of delta phi in (-pi/2 , 3/2*pi) deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); + // IF EVERYTHING WORKS WITH THE REASSOCIATED MFT TRACKS, I WILL HAVE TO CHANGE HOW THOSE FUNCTIONS ARE FILLED TOO if (!fillingHFcontainer) { // fill pair correlations target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, @@ -1029,10 +1130,10 @@ struct HfTaskFlow { } // FILL QA PLOTS for associated particle - if (sameEvent && (loopCounter == 1)) { + if (sameEvent && (loopCounter == 1) && (step == CorrelationContainer::kCFStepReconstructed)) { // if constexpr (std::is_same_v) { // If DATA - if constexpr (!std::is_same_v) { // IF TPC-TPC case - if constexpr (std::is_same_v) { // IF D0 CASE -> TPC-TPC D0-h + if constexpr (!std::is_same_v) { // IF TPC-TPC case + if constexpr (std::is_same_v) { // IF D0 CASE -> TPC-TPC D0-h fillTpcTpcHfChSameEventQa(multiplicity, track2); } else if constexpr (std::is_same_v) { // IF LC CASE -> TPC-TPC Lc-h fillTpcTpcHfChSameEventQa(multiplicity, track2); @@ -1052,6 +1153,207 @@ struct HfTaskFlow { //} } + if (sameEvent && (loopCounter == 1)) { + // FILL USUAL MFT DISTRIBUTIONS + registry.fill(HIST("Data/TpcMft/kCFStepAll/hEta"), eta2); + registry.fill(HIST("Data/TpcMft/kCFStepAll/hPhi"), phi2); + } + + } // end of loop over tracks2 + } // end of loop over tracks 1 + } + + template + void fillCorrelationsReassociatedMftTracks(TTarget target, CorrelationContainer::CFStep step, + TTracksTrig const& tracks1, TTracksAssoc const& tracks2, + float multiplicity, float posZ, bool sameEvent, bool cutAmbiguousTracks) + { + auto triggerWeight = 1; + auto associatedWeight = 1; + + // To avoid filling associated tracks QA many times + // I fill it only for the first trigger track of the collision + auto loopCounter = 0; + + // + // TRIGGER PARTICLE + // + for (const auto& track1 : tracks1) { + + loopCounter++; + + float eta1 = track1.eta(); + float pt1 = track1.pt(); + float phi1 = track1.phi(); + o2::math_utils::bringTo02Pi(phi1); + + // TODO: add getter for NUE trigger efficiency here + + // calculating inv. mass to be filled into the container below + // Note: this is needed only in case of HF-hadron correlations + // TO DO ? Add one more if condition if its MC ? + bool fillingHFcontainer = false; + double invmass = 0; + if constexpr (std::is_same_v || std::is_same_v) { + // TODO: Check how to put this into a Filter -> Pretty sure it cannot be a filter + if (!isAcceptedCandidate(track1)) { + continue; + } + fillingHFcontainer = true; + if constexpr (std::is_same_v) { // If D0 + invmass = hfHelper.invMassD0ToPiK(track1); + // Should add D0 bar ? + } else { // If Lc + invmass = hfHelper.invMassLcToPKPi(track1); + // Should add Lc bar ? (maybe not its the same mass right ?) + } + } + + //// Selections for MC GENERATED + // if constexpr (std::is_same_v || std::is_same_v) { + // // TODO: Check how to put this into a Filter -> Pretty sure it cannot be a filter + // if (!isAcceptedMcCandidate(track1)) { + // continue; + // } + // fillingHFcontainer = true; + // if constexpr (std::is_same_v) { // If D0 + // invmass = o2::constants::physics::MassD0; + // // Should add D0 bar ? + // } else { // If Lc + // invmass = o2::constants::physics::MassLambdaCPlus; + // // Should add Lc bar ? (maybe not its the same mass right ?) + // } + // } + + // fill single-track distributions + if (!fillingHFcontainer) { // if not HF-h case + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, triggerWeight); + } else { + target->getTriggerHist()->Fill(step, pt1, multiplicity, posZ, invmass, triggerWeight); + } + + // FILL QA PLOTS for trigger particle + if (sameEvent && (cutAmbiguousTracks == false)) { + if constexpr (std::is_same_v) { + fillTpcMftD0CandidateQa(multiplicity, track1); + } else if constexpr (std::is_same_v) { + fillTpcTpcLcCandidateQa(multiplicity, track1); + } else { + fillTpcMftChChSameEventQa(multiplicity, track1, true); + } + } + + // + // ASSOCIATED PARTICLE + // + for (const auto& track2 : tracks2) { + + // Fill QA plot for all MFT tracks () (only if cutAmbiguousTracks is false to avoid double counting) + if (!cutAmbiguousTracks) { + registry.fill(HIST("Data/TpcMft/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AllMftTracks); + } + + // const auto& reassociatedMftTrack = track2.mfttrack(); + // No one uses const and auto& here, so I will follow + auto reassociatedMftTrack = track2.template mfttrack_as(); + + if (!isAcceptedMftTrack(reassociatedMftTrack, false)) { + continue; + } + + // Fill QA plot for MFT tracks after physical selection (eta + clusters) + if (!cutAmbiguousTracks) { + registry.fill(HIST("Data/TpcMft/hAmbiguityOfMftTracks"), MftTrackAmbiguityStep::AfterTrackSelection); + } + + // We check if the track is ambiguous or non-ambiguous (QA plots are filled in isAmbiguousMftTrack) + // Fill plots only if cutAmbiguousTracks is false (to avoid double counting) + if (isAmbiguousMftTrack(track2, !cutAmbiguousTracks)) { + // If the MFT track is ambiguous we may cut or not on the ambiguous track + if (cutAmbiguousTracks) { + continue; + } + } + + if (reassociatedMftTrack.collisionId() != track2.bestCollisionId()) { + // track.collision_as().posZ() + continue; + } + + // case of h-h correlations where the two types of tracks are the same + // this avoids autocorrelations and double counting of particle pairs + // if constexpr (std::is_same_v) { + // if (track1.index() <= reassociatedMftTrack.index()) { + // continue; + // } + //} + + // in case of HF-h correlations, remove candidate daughters from the pool of associated hadrons + // with which the candidate is being correlated (will not have to do it for TPC-MFT case) + if constexpr (std::is_same_v) { // Remove the 2 prong daughters + if ((track1.prong0Id() == reassociatedMftTrack.globalIndex()) || (track1.prong1Id() == reassociatedMftTrack.globalIndex())) { + continue; + } + } + if constexpr (std::is_same_v) { // Remove the 3 prong daughters + if ((track1.prong0Id() == reassociatedMftTrack.globalIndex()) || (track1.prong1Id() == reassociatedMftTrack.globalIndex()) || (track1.prong2Id() == reassociatedMftTrack.globalIndex())) { + continue; + } + } + + // in case of MC-generated, do additional selection on MCparticles : charge and isPhysicalPrimary + // if (processMc) { + if constexpr (std::is_same_v || std::is_same_v) { + if (!isAcceptedMftMcParticle(reassociatedMftTrack)) { + continue; + } + } + + // if constexpr (std::is_same_v) { + // registry.fill(HIST("MC/Gen/TpcMft/HfHadron/SameEvent/hEtaMFT"), reassociatedMftTrack.eta()); + // } + + float eta2 = reassociatedMftTrack.eta(); + float pt2 = reassociatedMftTrack.pt(); + float phi2 = reassociatedMftTrack.phi(); + o2::math_utils::bringTo02Pi(phi2); + + // TODO: add getter for NUE associated efficiency here + + // TODO: add pair cuts on phi* + + float deltaPhi = phi1 - phi2; + // set range of delta phi in (-pi/2 , 3/2*pi) + deltaPhi = RecoDecay::constrainAngle(deltaPhi, -PIHalf); + + // IF EVERYTHING WORKS WITH THE REASSOCIATED MFT TRACKS, I WILL HAVE TO CHANGE HOW THOSE FUNCTIONS ARE FILLED TOO + if (!fillingHFcontainer) { + // fill pair correlations + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, + triggerWeight * associatedWeight); + } else { + target->getPairHist()->Fill(step, eta1 - eta2, pt2, pt1, multiplicity, deltaPhi, posZ, invmass, + triggerWeight * associatedWeight); + } + + // FILL QA PLOTS for associated particle + if (sameEvent && (loopCounter == 1) && (cutAmbiguousTracks == false)) { + if constexpr (std::is_same_v) { + fillTpcMftHfChSameEventQa(multiplicity, reassociatedMftTrack); + } else if constexpr (std::is_same_v) { + fillTpcMftHfChSameEventQa(multiplicity, reassociatedMftTrack); + } else { + fillTpcMftChChSameEventQa(multiplicity, reassociatedMftTrack, false); + } + } + + // QA plots for basic MFT distributions for non-ambiguous tracks only (kCFStepTracked) + if (cutAmbiguousTracks && sameEvent && (loopCounter == 1)) { + // FILL USUAL MFT DISTRIBUTIONS + registry.fill(HIST("Data/TpcMft/kCFStepTracked/hEta"), eta2); + registry.fill(HIST("Data/TpcMft/kCFStepTracked/hPhi"), phi2); + } + } // end of loop over tracks2 } // end of loop over tracks 1 } @@ -1061,7 +1363,7 @@ struct HfTaskFlow { // =============================================================================================================================================================================== template - void mixCollisions(TCollisions const& collisions, + void mixCollisions(TCollisions const& collisions, CorrelationContainer::CFStep step, TTracksTrig const& tracks1, TTracksAssoc const& tracks2, TLambda getPartsSize, OutputObj& corrContainer) @@ -1092,7 +1394,7 @@ struct HfTaskFlow { if constexpr (std::is_same_v) { // If MC registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); } else { // If not MC - if constexpr (std::is_same_v) { // IF TPC-MFT case + if constexpr (std::is_same_v) { // IF TPC-MFT case if constexpr (std::is_same_v || std::is_same_v) { // IF HF-h case -> TPC-MFT HF-h registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hEventCountMixing"), bin); } else { // IF h-h case -> TPC-MFT h-h case @@ -1107,11 +1409,70 @@ struct HfTaskFlow { } // end of if condition for TPC-TPC or TPC-MFT case } - corrContainer->fillEvent(multiplicityTracks1, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(corrContainer, tracks1, tracks2, multiplicityTracks1, collision1.posZ(), false); + corrContainer->fillEvent(multiplicityTracks1, step); + fillCorrelations(corrContainer, step, tracks1, tracks2, multiplicityTracks1, collision1.posZ(), false); } } + /* + template + void mixCollisionsReassociatedMftTracks(TCollisions const& collisions, int step, + TTracksTrig const& tracks1, TTracksAssoc const& tracks2, + TLambda getPartsSize, + OutputObj& corrContainer, + bool cutAmbiguousTracks) + { + + // The first one that I call "Data" should work for data and mc rec + using BinningTypeData = FlexibleBinningPolicy, aod::collision::PosZ, decltype(getPartsSize)>; + + BinningTypeData binningWithTracksSize{{getPartsSize}, {binsMixingVertex, binsMixingMultiplicity}, true}; + auto tracksTuple = std::make_tuple(tracks1, tracks2); + Pair pair{binningWithTracksSize, nMixedEvents, -1, collisions, tracksTuple, &cache}; + + for (const auto& [collision1, tracks1, collision2, tracks2] : pair) { + + if constexpr (!std::is_same_v) { // if NOT MC -> do collision cut + if (!(isAcceptedCollision(collision1, false))) { + continue; + } + if (!(isAcceptedCollision(collision2, false))) { + continue; + } + } + + auto binningValues = binningWithTracksSize.getBinningValues(collision1, collisions); + int bin = binningWithTracksSize.getBin(binningValues); + + const auto multiplicityTracks1 = getPartsSize(collision1); + + + + if constexpr (std::is_same_v) { // If MC + registry.fill(HIST("MC/Rec/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); + } else { // If not MC + if constexpr (std::is_same_v) { // IF TPC-MFT case + if constexpr (std::is_same_v || std::is_same_v) { // IF HF-h case -> TPC-MFT HF-h + registry.fill(HIST("Data/TpcMft/HfHadron/MixedEvent/hEventCountMixing"), bin); + } else { // IF h-h case -> TPC-MFT h-h case + registry.fill(HIST("Data/TpcMft/HadronHadron/MixedEvent/hEventCountMixing"), bin); + } + } else { // IF TPC-TPC case + if constexpr (std::is_same_v || std::is_same_v) { // IF HF-h case -> TPC-TPC HF-h + registry.fill(HIST("Data/TpcTpc/HfHadron/MixedEvent/hEventCountHFMixing"), bin); + } else { // IF h-h case -> TPC-TPC h-h case + registry.fill(HIST("Data/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); + } + } // end of if condition for TPC-TPC or TPC-MFT case + } + + + corrContainer->fillEvent(multiplicityTracks1, step); + fillCorrelationsReassociatedMftTracks(corrContainer, step, tracks1, tracks2, multiplicityTracks1, collision1.posZ(), false, cutAmbiguousTracks, field ); + } + } + */ + // =============================================================================================================================================================================== // mixCollisions for GENERATED events // =============================================================================================================================================================================== @@ -1139,7 +1500,7 @@ struct HfTaskFlow { registry.fill(HIST("MC/Gen/TpcTpc/HadronHadron/MixedEvent/hEventCountMixing"), bin); corrContainer->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); - fillCorrelations(corrContainer, tracks1, tracks2, multiplicity, collision1.posZ(), false); + fillCorrelations(corrContainer, CorrelationContainer::CFStep::kCFStepAll, tracks1, tracks2, multiplicity, collision1.posZ(), false); } } @@ -1180,7 +1541,7 @@ struct HfTaskFlow { sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); // TO-DO : add if condition for when we will implant corrected correlations (kCFStepReconstructed -> kCFStepCorrected) - fillCorrelations(sameEvent, tracks, tracks, multiplicity, collision.posZ(), true); + fillCorrelations(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, tracks, multiplicity, collision.posZ(), true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcChCh, "DATA : Process same-event correlations for TPC-TPC h-h case", false); @@ -1209,7 +1570,7 @@ struct HfTaskFlow { sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(sameEventHf, candidates, tracks, multiplicity, collision.posZ(), true); + fillCorrelations(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, tracks, multiplicity, collision.posZ(), true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcD0Ch, "DATA : Process same-event correlations for TPC-TPC D0-h case", false); @@ -1238,7 +1599,7 @@ struct HfTaskFlow { sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(sameEventHf, candidates, tracks, multiplicity, collision.posZ(), true); + fillCorrelations(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, tracks, multiplicity, collision.posZ(), true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcTpcLcCh, "DATA : Process same-event correlations for TPC-TPC Lc-h case", false); @@ -1248,7 +1609,7 @@ struct HfTaskFlow { void processSameTpcMftChCh(FilteredCollisionsWSelMult::iterator const& collision, FilteredTracksWDcaSel const& tracks, - FilteredMftTracksWColls const& mftTracks) + aod::MFTTracks const& mftTracks) { if (!(isAcceptedCollision(collision, true))) { return; @@ -1259,12 +1620,54 @@ struct HfTaskFlow { int bin = baseBinning.getBin(std::make_tuple(collision.posZ(), multiplicity)); registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEventCountSame"), bin); + // I use kCFStepAll for running my code with all MFTTracks were the reassociation process was not applied + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelations(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, mftTracks, multiplicity, collision.posZ(), true); - fillCorrelations(sameEvent, tracks, mftTracks, multiplicity, collision.posZ(), true); + // I use the step kCFStepReconstructed for reassociatedMftTracks (most likely the ones we will use in the end) + // sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + // fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + + // I use kCFStepTracked for running my code with only non-ambiguous MFTTracks + // This is the same as running with reassociatedMftTracks, but applying one more cut in the fillCorrelations function + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks + // sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + // fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepTracked, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), false, true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChCh, "DATA : Process same-event correlations for TPC-MFT h-h case", false); + void processSameTpcMftChChReassociated(FilteredCollisionsWSelMult::iterator const& collision, + soa::SmallGroups const& reassociatedMftTracks, + FilteredTracksWDcaSel const& tracks, + aod::MFTTracks const& mftTracks) + { + if (!(isAcceptedCollision(collision, true))) { + return; // when process function has iterator + } + + const auto multiplicity = collision.multNTracksPV(); + BinningPolicyBase<2> baseBinning{{axisVertex, axisMultiplicity}, true}; + int bin = baseBinning.getBin(std::make_tuple(collision.posZ(), multiplicity)); + registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEventCountSame"), bin); + + // I use kCFStepAll for running my code with all MFTTracks were the reassociation process was not applied + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + fillCorrelations(sameEvent, CorrelationContainer::CFStep::kCFStepAll, tracks, mftTracks, multiplicity, collision.posZ(), true); + + // I use the step kCFStepReconstructed for reassociatedMftTracks (most likely the ones we will use in the end) + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + + // I use kCFStepTracked for running my code with only non-ambiguous MFTTracks + // This is the same as running with reassociatedMftTracks, but applying one more cut in the fillCorrelations function + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks + sameEvent->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + fillCorrelationsReassociatedMftTracks(sameEvent, CorrelationContainer::CFStep::kCFStepTracked, tracks, reassociatedMftTracks, multiplicity, collision.posZ(), true, true); + } + PROCESS_SWITCH(HfTaskFlow, processSameTpcMftChChReassociated, "DATA : Process same-event correlations for TPC-MFT h-h case reassociated", false); + // ===================================== // DATA : process same event correlations: TPC-MFT HF-h case for D0 // ===================================== @@ -1272,7 +1675,7 @@ struct HfTaskFlow { void processSameTpcMftD0Ch(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelD0 const& candidates, FilteredTracksWDcaSel const& /*tracks*/, - FilteredMftTracksWColls const& mftTracks) + aod::MFTTracks const& mftTracks) { auto fillEventSelectionPlots = true; @@ -1291,10 +1694,41 @@ struct HfTaskFlow { sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(sameEventHf, candidates, mftTracks, multiplicity, collision.posZ(), true); + fillCorrelations(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, mftTracks, multiplicity, collision.posZ(), true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftD0Ch, "DATA : Process same-event correlations for TPC-MFT D0-h case", false); + void processSameTpcMftD0ChReassociated(FilteredCollisionsWSelMult::iterator const& collision, + HfCandidatesSelD0 const& candidates, + soa::SmallGroups const& reassociatedMftTracks, + aod::MFTTracks const& mftTracks) + { + if (!(isAcceptedCollision(collision, true))) { + return; // when process function has iterator + } + + const auto multiplicity = collision.multNTracksPV(); + BinningPolicyBase<2> baseBinning{{axisVertex, axisMultiplicity}, true}; + // int bin = baseBinning.getBin(std::make_tuple(collision.posZ(), multiplicity)); + // registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEventCountSame"), bin); + + // I use kCFStepAll for running my code with all MFTTracks were the reassociation process was not applied + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks + sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + fillCorrelations(sameEventHf, CorrelationContainer::CFStep::kCFStepAll, candidates, mftTracks, multiplicity, collision.posZ(), true); + + // I use the step kCFStepReconstructed for reassociatedMftTracks (most likely the ones we will use in the end) + sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + + // I use kCFStepTracked for running my code with only non-ambiguous MFTTracks + // This is the same as running with reassociatedMftTracks, but applying one more cut in the fillCorrelations function + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks + sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + fillCorrelationsReassociatedMftTracks(sameEventHf, CorrelationContainer::CFStep::kCFStepTracked, candidates, reassociatedMftTracks, multiplicity, collision.posZ(), true, true); + } + PROCESS_SWITCH(HfTaskFlow, processSameTpcMftD0ChReassociated, "DATA : Process same-event correlations for TPC-MFT D0-h case reassociated", false); + // ===================================== // DATA : process same event correlations: TPC-MFT HF-h case for Lc // ===================================== @@ -1302,7 +1736,7 @@ struct HfTaskFlow { void processSameTpcMftLcCh(FilteredCollisionsWSelMult::iterator const& collision, HfCandidatesSelLc const& candidates, FilteredTracksWDcaSel const& /*tracks*/, - FilteredMftTracksWColls const& mftTracks) + aod::MFTTracks const& mftTracks) { auto fillEventSelectionPlots = true; @@ -1321,10 +1755,41 @@ struct HfTaskFlow { sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); - fillCorrelations(sameEventHf, candidates, mftTracks, multiplicity, collision.posZ(), true); + fillCorrelations(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, mftTracks, multiplicity, collision.posZ(), true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftLcCh, "DATA : Process same-event correlations for TPC-MFT Lc-h case", false); + void processSameTpcMftLcChReassociated(FilteredCollisionsWSelMult::iterator const& collision, + HfCandidatesSelLc const& candidates, + soa::SmallGroups const& reassociatedMftTracks, + aod::MFTTracks const& mftTracks) + { + if (!(isAcceptedCollision(collision, true))) { + return; // when process function has iterator + } + + const auto multiplicity = collision.multNTracksPV(); + BinningPolicyBase<2> baseBinning{{axisVertex, axisMultiplicity}, true}; + // int bin = baseBinning.getBin(std::make_tuple(collision.posZ(), multiplicity)); + // registry.fill(HIST("Data/TpcMft/HadronHadron/SameEvent/hEventCountSame"), bin); + + // I use kCFStepAll for running my code with all MFTTracks were the reassociation process was not applied + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks + sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); + fillCorrelations(sameEventHf, CorrelationContainer::CFStep::kCFStepAll, candidates, mftTracks, multiplicity, collision.posZ(), true); + + // I use the step kCFStepReconstructed for reassociatedMftTracks (most likely the ones we will use in the end) + sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepReconstructed); + fillCorrelationsReassociatedMftTracks(sameEventHf, CorrelationContainer::CFStep::kCFStepReconstructed, candidates, reassociatedMftTracks, multiplicity, collision.posZ(), true, false); + + // I use kCFStepTracked for running my code with only non-ambiguous MFTTracks + // This is the same as running with reassociatedMftTracks, but applying one more cut in the fillCorrelations function + // We don't fill "normal" QA plots with these tracks, only specific plots to compare with other type of MFTTracks + sameEventHf->fillEvent(multiplicity, CorrelationContainer::kCFStepTracked); + fillCorrelationsReassociatedMftTracks(sameEventHf, CorrelationContainer::CFStep::kCFStepTracked, candidates, reassociatedMftTracks, multiplicity, collision.posZ(), true, true); + } + PROCESS_SWITCH(HfTaskFlow, processSameTpcMftLcChReassociated, "DATA : Process same-event correlations for TPC-MFT Lc-h case reassociated", false); + // =================================================================================================================================================================================================================================================================== // MONTE-CARLO // =================================================================================================================================================================================================================================================================== @@ -1344,7 +1809,7 @@ struct HfTaskFlow { // registry.fill(HIST("MC/Gen/TpcMft/HfHadron/SameEvent/2Prong/hEventCountSame"), bin); sameEventHfMc->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); - fillCorrelations(sameEventHfMc, mcParticles2Prong, mcParticles, multiplicity, mcCollision.posZ(), true); + fillCorrelations(sameEventHfMc, CorrelationContainer::CFStep::kCFStepAll, mcParticles2Prong, mcParticles, multiplicity, mcCollision.posZ(), true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftD0ChMcGen, "MONTE-CARLO : Process same-event correlations for TPC-MFT D0-h case", false); @@ -1363,7 +1828,7 @@ struct HfTaskFlow { // registry.fill(HIST("MC/Gen/TpcMft/HfHadron/SameEvent/2Prong/hEventCountSame"), bin); sameEventHfMc->fillEvent(multiplicity, CorrelationContainer::kCFStepAll); - fillCorrelations(sameEventHfMc, mcParticles3Prong, mcParticles, multiplicity, mcCollision.posZ(), true); + fillCorrelations(sameEventHfMc, CorrelationContainer::CFStep::kCFStepAll, mcParticles3Prong, mcParticles, multiplicity, mcCollision.posZ(), true); } PROCESS_SWITCH(HfTaskFlow, processSameTpcMftLcChMcGen, "MONTE-CARLO : Process same-event correlations for TPC-MFT Lc-h case", false); @@ -1397,7 +1862,7 @@ struct HfTaskFlow { }; // mixCollisions(collisions, tracks, tracks, getTracksSize, mixedEvent); - mixCollisions(collisions, tracks, tracks, getMultiplicity, mixedEvent); + mixCollisions(collisions, CorrelationContainer::CFStep::kCFStepReconstructed, tracks, tracks, getMultiplicity, mixedEvent); } PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcChCh, "DATA : Process mixed-event correlations for TPC-TPC h-h case", false); @@ -1414,7 +1879,7 @@ struct HfTaskFlow { return multiplicity; }; - mixCollisions(collisions, candidates, tracks, getMultiplicity, mixedEventHf); + mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, candidates, tracks, getMultiplicity, mixedEventHf); } PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcD0Ch, "DATA : Process mixed-event correlations for TPC-TPC D0-h case", false); @@ -1431,7 +1896,7 @@ struct HfTaskFlow { return multiplicity; }; - mixCollisions(collisions, candidates, tracks, getMultiplicity, mixedEventHf); + mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, candidates, tracks, getMultiplicity, mixedEventHf); } PROCESS_SWITCH(HfTaskFlow, processMixedTpcTpcLcCh, "DATA : Process mixed-event correlations for TPC-TPC Lc-h case", false); @@ -1441,14 +1906,23 @@ struct HfTaskFlow { void processMixedTpcMftChCh(FilteredCollisionsWSelMult const& collisions, FilteredTracksWDcaSel const& tracks, - FilteredMftTracksWColls const& mftTracks) + aod::MFTTracks const& mftTracks) { auto getMultiplicity = [](FilteredCollisionsWSelMult::iterator const& collision) { auto multiplicity = collision.numContrib(); return multiplicity; }; - mixCollisions(collisions, tracks, mftTracks, getMultiplicity, mixedEvent); + mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, tracks, mftTracks, getMultiplicity, mixedEvent); + // mixCollisions(collisions, CorrelationContainer::kCFStepAll, tracks, mftTracks, getMultiplicity, mixedEvent); + + // The next following two lines were supposed to be used to do mixed event with the reassociated MFT tracks + // However it seems the O2physics framework cannot handle how these combinations requests grouping according to Anton Alkin + // So I leave them commented for now until it is solved, and put the "normal" mixCollisions back with kCFStepReconstructed + + // mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepReconstructed, tracks, reassociatedMftTracks, getMultiplicity, mixedEvent, false); + + // mixCollisionsReassociatedMftTracks(collisions, CorrelationContainer::kCFStepTracked, tracks, reassociatedMftTracks, getMultiplicity, mixedEvent, true); } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftChCh, "DATA : Process mixed-event correlations for TPC-MFT h-h case", false); @@ -1458,7 +1932,7 @@ struct HfTaskFlow { void processMixedTpcMftD0Ch(FilteredCollisionsWSelMult const& collisions, HfCandidatesSelD0 const& candidates, - FilteredMftTracksWColls const& mftTracks, + aod::MFTTracks const& mftTracks, FilteredTracksWDcaSel const& /*tracks*/) { auto getMultiplicity = [](FilteredCollisionsWSelMult::iterator const& collision) { @@ -1466,7 +1940,7 @@ struct HfTaskFlow { return multiplicity; }; - mixCollisions(collisions, candidates, mftTracks, getMultiplicity, mixedEventHf); + mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, candidates, mftTracks, getMultiplicity, mixedEventHf); } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftD0Ch, "DATA : Process mixed-event correlations for TPC-MFT D0-h case", false); @@ -1476,14 +1950,14 @@ struct HfTaskFlow { void processMixedTpcMftLcCh(FilteredCollisionsWSelMult const& collisions, HfCandidatesSelLc const& candidates, - FilteredMftTracksWColls const& mftTracks) + aod::MFTTracks const& mftTracks) { auto getMultiplicity = [](FilteredCollisionsWSelMult::iterator const& collision) { auto multiplicity = collision.numContrib(); return multiplicity; }; - mixCollisions(collisions, candidates, mftTracks, getMultiplicity, mixedEventHf); + mixCollisions(collisions, CorrelationContainer::kCFStepReconstructed, candidates, mftTracks, getMultiplicity, mixedEventHf); } PROCESS_SWITCH(HfTaskFlow, processMixedTpcMftLcCh, "DATA : Process mixed-event correlations for TPC-MFT Lc-h case", false); @@ -1535,7 +2009,7 @@ struct HfTaskFlow { void processMcEfficiencyMft(FilteredMcCollisions::iterator const& mcCollision, McParticles const& mcParticles, soa::SmallGroups> const& collisionsMcLabels, - FilteredMftTracksWCollsMcLabels const& mftTTracksMcLabels) + MftTracksMcLabels const& mftTTracksMcLabels) { LOGF(info, "MC collision at vtx-z = %f with %d mc particles and %d reconstructed collisions", mcCollision.posZ(), mcParticles.size(), collisionsMcLabels.size()); diff --git a/PWGHF/HFC/Utils/utilsCorrelations.h b/PWGHF/HFC/Utils/utilsCorrelations.h index 90f7b8524d9..56fc5e435e2 100644 --- a/PWGHF/HFC/Utils/utilsCorrelations.h +++ b/PWGHF/HFC/Utils/utilsCorrelations.h @@ -16,18 +16,23 @@ #ifndef PWGHF_HFC_UTILS_UTILSCORRELATIONS_H_ #define PWGHF_HFC_UTILS_UTILSCORRELATIONS_H_ +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" + +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include +#include +#include + #include -#include +#include #include #include -#include "CommonConstants/MathConstants.h" - -#include "Common/DataModel/PIDResponseTPC.h" -#include "Common/DataModel/PIDResponseTOF.h" - namespace o2::analysis::hf_correlations { enum Region { @@ -45,12 +50,16 @@ enum PairSign { LcNegTrkNeg }; +constexpr float PhiTowardMax{o2::constants::math::PIThird}; +constexpr float PhiAwayMin{2.f * o2::constants::math::PIThird}; +constexpr float PhiAwayMax{4.f * o2::constants::math::PIThird}; + template Region getRegion(T const deltaPhi) { - if (std::abs(deltaPhi) < o2::constants::math::PIThird) { + if (std::abs(deltaPhi) < PhiTowardMax) { return Toward; - } else if (deltaPhi > 2. * o2::constants::math::PIThird && deltaPhi < 4. * o2::constants::math::PIThird) { + } else if (deltaPhi > PhiAwayMin && deltaPhi < PhiAwayMax) { return Away; } else { return Transverse; @@ -119,6 +128,70 @@ bool passPIDSelection(Atrack const& track, SpeciesContainer const mPIDspecies, return true; // Passed all checks } +/// @brief Selects a candidate based on its PDG code, decay channel, and assigns the corresponding mass. +/// +/// @tparam isScCandidate Boolean template parameter: +/// - `true` to check for Sigma_c candidates +/// - `false` to check for Lambda_c candidates +/// @tparam McParticleType Type representing the MC particle, must provide `pdgCode()` and `flagMcMatchGen()` +/// +/// @param[in] particle MC particle whose PDG code and decay flag are evaluated +/// @param[out] massCand Mass of the matched candidate is set here, if a valid match is found +/// +/// @return `true` if candidate matches expected PDG and decay flag, and mass is set; `false` otherwise +template +bool matchCandAndMass(McParticleType const& particle, double& massCand) +{ + const auto pdgCand = std::abs(particle.pdgCode()); + const auto matchGenFlag = std::abs(particle.flagMcMatchGen()); + + // Validate PDG code based on candidate type + if (isScCandidate) { + if (!(pdgCand == o2::constants::physics::Pdg::kSigmaC0 || + pdgCand == o2::constants::physics::Pdg::kSigmaCPlusPlus || + pdgCand == o2::constants::physics::Pdg::kSigmaCStar0 || + pdgCand == o2::constants::physics::Pdg::kSigmaCStarPlusPlus)) { + return false; + } + } else { + if (pdgCand != o2::constants::physics::Pdg::kLambdaCPlus) { + return false; + } + } + + // Map decay type to mass + switch (matchGenFlag) { + case BIT(aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi): { + massCand = o2::constants::physics::MassSigmaC0; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScStar0ToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStar0; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStarPlusPlus; + return true; + } + + case BIT(aod::hf_cand_sigmac::DecayType::ScStarPlusPlusToPKPiPi): { + massCand = o2::constants::physics::MassSigmaCStarPlusPlus; + return true; + } + + case hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi: { + massCand = o2::constants::physics::MassLambdaCPlus; + return true; + } + + default: { + return false; + } + } +} + // ========= Find Leading Particle ============== template //// FIXME: 14 days int findLeadingParticle(TTracks const& tracks, T1 const etaTrackMax) diff --git a/PWGHF/HFJ/CMakeLists.txt b/PWGHF/HFJ/CMakeLists.txt index bbfd7adac2b..62f88c324cf 100644 --- a/PWGHF/HFJ/CMakeLists.txt +++ b/PWGHF/HFJ/CMakeLists.txt @@ -7,4 +7,4 @@ # # In applying this license CERN does not waive the privileges and immunities # granted to it by virtue of its status as an Intergovernmental Organization -# or submit itself to any jurisdiction. +# or submit itself to any jurisdiction. \ No newline at end of file diff --git a/PWGHF/HFL/DataModel/ElectronSelectionTable.h b/PWGHF/HFL/DataModel/ElectronSelectionTable.h index 477011950e2..cae859d08f1 100644 --- a/PWGHF/HFL/DataModel/ElectronSelectionTable.h +++ b/PWGHF/HFL/DataModel/ElectronSelectionTable.h @@ -18,8 +18,8 @@ #ifndef PWGHF_HFL_DATAMODEL_ELECTRONSELECTIONTABLE_H_ #define PWGHF_HFL_DATAMODEL_ELECTRONSELECTIONTABLE_H_ -#include // NOLINT #include +#include #include diff --git a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx index ae8be97b6b9..7dac8c0a83d 100644 --- a/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx +++ b/PWGHF/HFL/TableProducer/electronSelectionWithTpcEmcal.cxx @@ -14,28 +14,38 @@ /// \author Rashi Gupta , IIT Indore /// \author Ravindra Singh , IIT Indore -#include "THnSparse.h" -#include "TPDGCode.h" - -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" +#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" +#include "PWGJE/DataModel/EMCALClusters.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.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 "Tools/KFparticle/KFUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/HFL/DataModel/ElectronSelectionTable.h" +#include + +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::constants::physics; @@ -87,10 +97,10 @@ struct HfElectronSelectionWithTpcEmcal { Configurable etaTrackDCalNegativeMin{"etaTrackDCalNegativeMin", -0.6f, "Eta range for electron tracks"}; Configurable etaTrackDCalPositiveMax{"etaTrackDCalPositiveMax", 0.6f, "Eta range for electron Dcal tracks"}; Configurable etaTrackDCalPositiveMin{"etaTrackDCalPositiveMin", 0.22f, "Eta range for electron tracks"}; - Configurable phiTrackDCalMax{"phiTrackDCalMax", 3.3621f, "phi range for electron tracks associated Dcal"}; - Configurable phiTrackDCalMin{"phiTrackDCalMin", 1.3955f, "phi range for electron tracks associated Dcal"}; - Configurable phiTrackEMCalMax{"phiTrackEMCalMax", 5.708f, "phi range for electron tracks associated Emcal"}; - Configurable phiTrackEMCalMin{"phiTrackEMCalMin", 4.5355f, "phi range for electron tracks associated Emcal"}; + Configurable phiTrackDCalMax{"phiTrackDCalMax", 5.708f, "phi range for electron tracks associated Dcal"}; + Configurable phiTrackDCalMin{"phiTrackDCalMin", 4.5355f, "phi range for electron tracks associated Dcal"}; + Configurable phiTrackEMCalMax{"phiTrackEMCalMax", 3.3621f, "phi range for electron tracks associated Emcal"}; + Configurable phiTrackEMCalMin{"phiTrackEMCalMin", 1.3955f, "phi range for electron tracks associated Emcal"}; // Track and EMCal Cluster matching cut Configurable deltaEtaMatchMin{"deltaEtaMatchMin", -0.013f, "Min Eta distance of EMCAL cluster to its closest track"}; @@ -202,8 +212,9 @@ struct HfElectronSelectionWithTpcEmcal { registry.add("hAfterPIDEtaPhi", "PID Info after PID Cuts Eta vs Phi ; #eta; #varphi; ", {HistType::kTH2F, {{axisEta}, {axisPhi}}}); registry.add("hEPRatioAfterPID", "E/P Ratio after PID Cuts apply only trackwodca filter", {HistType::kTH2F, {{axisPt}, {axisEmcEnergy}}}); - registry.add("hPIDAfterPIDCuts", "PID Info after PID cuts; E/P;#it{p}_{T} (GeV#it{/c});n#sigma;m02; m20;", {HistType::kTHnSparseF, {{binsEoP}, {binsPt}, {binsnSigma}, {binsM02}, {binsM20}}}); - registry.add("hEmcClsTrkEtaPhiDiffTime", "EmcClsTrkEtaPhiDiffTime;#Delta#eta;#Delta#varphi;Sec;", {HistType::kTH3F, {{binsDeltaEta}, {binsDeltaPhi}, {binsEmcClsTime}}}); + + registry.add("hPIDAfterPIDCuts", "PID Info after PID cuts; E/P;#it{p}_{T} (GeV#it{/c});n#sigma;m02; m20;", {HistType::kTHnSparseF, {{axisEoP}, {axisPt}, {axisnSigma}, {axisM02}, {axisM20}}}); + registry.add("hEmcClsTrkEtaPhiDiffTime", "EmcClsTrkEtaPhiDiffTime;#Delta#eta;#Delta#varphi;Sec;", {HistType::kTH3F, {{axisDeltaEta}, {axisDeltaPhi}, {axisEmcClsTime}}}); } // Track Selection Cut template @@ -365,6 +376,11 @@ struct HfElectronSelectionWithTpcEmcal { return; registry.fill(HIST("hNevents"), 1); + + // skip events with no clusters + if (emcClusters.size() == 0) { + return; + } registry.fill(HIST("hZvertex"), collision.posZ()); ///////////////////////////////// @@ -452,8 +468,8 @@ struct HfElectronSelectionWithTpcEmcal { timeEmcCluster = emcCluster.time(); cellEmcCluster = emcCluster.nCells(); - deltaPhiMatch = matchTrack.trackPhiEmcal() - phiMatchEmcCluster; - deltaEtaMatch = matchTrack.trackEtaEmcal() - etaMatchEmcCluster; + deltaPhiMatch = ematchTrack.deltaPhi(); + deltaEtaMatch = ematchTrack.deltaEta(); // Track and EMCal cluster Matching if (std::abs(timeEmcCluster) > timeEmcClusterMax) { diff --git a/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx b/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx index b8faca73bf7..1b32608a310 100644 --- a/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx +++ b/PWGHF/HFL/TableProducer/treeCreatorElectronDCA.cxx @@ -14,18 +14,27 @@ /// /// \author Martin Voelkl , University of Birmingham -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "Common/DataModel/Centrality.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/HFL/Tasks/CMakeLists.txt b/PWGHF/HFL/Tasks/CMakeLists.txt index 7c87297ca23..49bafac661a 100644 --- a/PWGHF/HFL/Tasks/CMakeLists.txt +++ b/PWGHF/HFL/Tasks/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(task-electron-weak-boson SOURCES taskElectronWeakBoson.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils KFParticle::KFParticle COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(task-muon-charm-beauty-separation @@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(task-muon-charm-beauty-separation PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-single-electron + SOURCES taskSingleElectron.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(task-single-muon SOURCES taskSingleMuon.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore diff --git a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx index be71ab35a01..a9b15ce7a0f 100644 --- a/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx +++ b/PWGHF/HFL/Tasks/taskElectronWeakBoson.cxx @@ -12,31 +12,48 @@ /// \file taskElectronWeakBoson.cxx /// \brief task for WeakBoson (W/Z) based on electron in mid-rapidity /// \author S. Sakai & S. Ito (Univ. of Tsukuba) -#include -#include - -#include "CCDB/BasicCCDBManager.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" +#ifndef HomogeneousField +#define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) +#endif -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" +#include "PWGJE/DataModel/EMCALClusters.h" #include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" - #include "EventFiltering/Zorro.h" - -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGHF/Core/HfHelper.h" +#include "EventFiltering/ZorroSummary.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 using namespace o2; using namespace o2::framework; @@ -52,11 +69,14 @@ struct HfTaskElectronWeakBoson { Configurable vtxZ{"vtxZ", 10.f, ""}; - Configurable etaTrLow{"etaTrLow", -0.6f, "minimun track eta"}; - Configurable etaTrUp{"etaTrUp", 0.6f, "maximum track eta"}; + Configurable etaTrMin{"etaTrMin", -1.0f, "minimun track eta"}; + Configurable etaTrMax{"etaTrMax", 1.0f, "maximum track eta"}; + Configurable etaEmcMax{"etaEmcMax", 0.6f, "maximum track eta"}; Configurable dcaxyMax{"dcaxyMax", 2.0f, "mximum DCA xy"}; Configurable chi2ItsMax{"chi2ItsMax", 15.0f, "its chi2 cut"}; Configurable ptMin{"ptMin", 3.0f, "minimum pT cut"}; + Configurable ptAssMin{"ptAssMin", 0.15, "minimum pT cut for associated hadrons"}; + Configurable ptMatch{"ptMatch", 0.001, "pT match in Z->ee and associated tracks"}; Configurable ptZeeMin{"ptZeeMin", 20.0f, "minimum pT cut for Zee"}; Configurable chi2TpcMax{"chi2TpcMax", 4.0f, "tpc chi2 cut"}; Configurable nclItsMin{"nclItsMin", 2.0f, "its # of cluster cut"}; @@ -81,6 +101,10 @@ struct HfTaskElectronWeakBoson { Configurable energyIsolationMax{"energyIsolationMax", 0.1, "isolation cut on energy"}; Configurable trackIsolationMax{"trackIsolationMax", 3, "Maximum number of tracks in isolation cone"}; + Configurable massZMin{"massZMin", 60.0, "Minimum Z mass (GeV/c^2)"}; + Configurable massZMax{"massZMax", 120.0, "Maximum Z mass (GeV/c^2)"}; + Configurable correctionPtElectron{"correctionPtElectron", 1.0, "momentum correction factor for decay electrons from Z boson"}; + // flag for THn Configurable isTHnElectron{"isTHnElectron", true, "Enables THn for electrons"}; Configurable ptTHnThresh{"ptTHnThresh", 5.0, "Threshold for THn make"}; @@ -89,8 +113,15 @@ struct HfTaskElectronWeakBoson { Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", true, "Enables processing of skimmed datasets"}; Configurable cfgTriggerName{"cfgTriggerName", "fGammaHighPtEMCAL", "Trigger of interest (comma separated for multiple)"}; - // CCDB service object + // CCDB service configurations Configurable cfgCCDBPath{"cfgCCDBPath", "Users/m/mpuccio/EventFiltering/OTS/", "Path to CCDB for trigger data"}; + Configurable ccdbPathGrpMag{"ccdbPathGrpMag", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object (Run 3)"}; + + // KFParticle + Configurable kfConstructMethod{"kfConstructMethod", 2, "KF Construct Method"}; + Configurable chiSqNdfMax{"chiSqNdfMax", 10, "Chi2 Max for mass reco by KF particle"}; + + // CCDB service object Service ccdb; struct HfElectronCandidate { @@ -104,9 +135,18 @@ struct HfTaskElectronWeakBoson { std::vector selectedElectronsIso; std::vector selectedElectronsAss; + struct HfZeeCandidate { + float pt, eta, phi, mass, ptchild0, ptchild1; + int charge; + HfZeeCandidate(float ptr, float e, float ph, float m, int ch, float ptzee0, float ptzee1) + : pt(ptr), eta(e), phi(ph), mass(m), ptchild0(ptzee0), ptchild1(ptzee1), charge(ch) {} + }; + std::vector reconstructedZ; + using SelectedClusters = o2::aod::EMCALClusters; // PbPb - using TrackEle = o2::soa::Join; + // using TrackEle = o2::soa::Join; + using TrackEle = o2::soa::Join; // pp // using TrackEle = o2::soa::Filtered>; @@ -115,7 +155,7 @@ struct HfTaskElectronWeakBoson { Filter eventFilter = (o2::aod::evsel::sel8 == true); Filter posZFilter = (nabs(o2::aod::collision::posZ) < vtxZ); - Filter etafilter = (aod::track::eta < etaTrUp) && (aod::track::eta > etaTrLow); + Filter etafilter = (aod::track::eta < etaTrMax) && (aod::track::eta > etaTrMin); Filter dcaxyfilter = (nabs(aod::track::dcaXY) < dcaxyMax); Filter filterGlobalTr = requireGlobalTrackInFilter(); @@ -156,10 +196,13 @@ struct HfTaskElectronWeakBoson { const AxisSpec axisEta{20, -1.0, 1.0, "#eta"}; const AxisSpec axisPt{nBinsPt, 0, binPtmax, "p_{T}"}; const AxisSpec axisNsigma{100, -5, 5, "N#sigma"}; + const AxisSpec axisDedx{150, 0, 150, "dEdx"}; const AxisSpec axisE{nBinsE, 0, binEmax, "Energy"}; const AxisSpec axisM02{100, 0, 1, "M02"}; const AxisSpec axisdPhi{100, -0.5, 0.5, "dPhi"}; const AxisSpec axisdEta{100, -0.5, 0.5, "dEta"}; + const AxisSpec axisdR{20, 0.0, 0.2, "dR"}; + const AxisSpec axisNcell{50, 0.0, 50.0, "Ncell"}; const AxisSpec axisPhi{350, 0, 7, "Phi"}; const AxisSpec axisEop{200, 0, 2, "Eop"}; const AxisSpec axisChi2{250, 0.0, 25.0, "#chi^{2}"}; @@ -170,11 +213,15 @@ struct HfTaskElectronWeakBoson { const AxisSpec axisIsoTrack{15, -0.5, 14.5, "Isolation Track"}; const AxisSpec axisInvMassZ{150, 0, 150, "M_{ee} (GeV/c^{2})"}; const AxisSpec axisTrigger{3, -0.5, 2.5, "Trigger status of zorro"}; + const AxisSpec axisDPhiZh{64, -o2::constants::math::PIHalf, 3 * o2::constants::math::PIHalf, "#Delta#phi(Z-h)"}; + const AxisSpec axisPtHadron{50, 0, 50, "p_{T,hadron} (GeV/c)"}; + const AxisSpec axisPtZ{150, 0, 150, "p_{T,Z} (GeV/c)"}; + const AxisSpec axisSign{2, -2, 2, "charge sign"}; // create registrygrams - registry.add("hZvtx", "Z vertex", kTH1F, {axisZvtx}); - registry.add("hEventCounterInit", "hEventCounterInit", kTH1F, {axisCounter}); - registry.add("hEventCounter", "hEventCounter", kTH1F, {axisCounter}); + registry.add("hZvtx", "Z vertex", kTH1D, {axisZvtx}); + registry.add("hEventCounterInit", "hEventCounterInit", kTH1D, {axisCounter}); + registry.add("hEventCounter", "hEventCounter", kTH1D, {axisCounter}); registry.add("hITSchi2", "ITS #chi^{2}", kTH1F, {axisChi2}); registry.add("hTPCchi2", "TPC #chi^{2}", kTH1F, {axisChi2}); registry.add("hTPCnCls", "TPC NCls", kTH1F, {axisCluster}); @@ -184,7 +231,8 @@ struct HfTaskElectronWeakBoson { registry.add("hPt", "track pt", kTH1F, {axisPt}); registry.add("hTPCNsigma", "TPC electron Nsigma", kTH2F, {{axisPt}, {axisNsigma}}); registry.add("hEnergy", "EMC cluster energy", kTH1F, {axisE}); - registry.add("hTrMatch", "Track EMC Match", kTH2F, {{axisdPhi}, {axisdEta}}); + registry.add("hEnergyNcell", "EMC cluster energy and cell", kTH2F, {{axisE}, {axisNcell}}); + registry.add("hTrMatchR", "Track EMC Match in radius", kTH2F, {{axisPt}, {axisdR}}); registry.add("hTrMatch_mim", "Track EMC Match minimu minimumm", kTH2F, {{axisdPhi}, {axisdEta}}); registry.add("hMatchPhi", "Match in Phi", kTH2F, {{axisPhi}, {axisPhi}}); registry.add("hMatchEta", "Match in Eta", kTH2F, {{axisEta}, {axisEta}}); @@ -197,10 +245,17 @@ struct HfTaskElectronWeakBoson { registry.add("hIsolationTrack", "Isolation Track", kTH2F, {{axisE}, {axisIsoTrack}}); registry.add("hInvMassZeeLs", "invariant mass for Z LS pair", kTH2F, {{axisPt}, {axisInvMassZ}}); registry.add("hInvMassZeeUls", "invariant mass for Z ULS pair", kTH2F, {{axisPt}, {axisInvMassZ}}); - registry.add("hTHnElectrons", "electron info", HistType::kTHnSparseF, {axisPt, axisNsigma, axisM02, axisEop, axisIsoEnergy, axisIsoTrack}); + registry.add("hKfInvMassZeeLs", "invariant mass for Z LS pair KFp", kTH2F, {{axisPt}, {axisInvMassZ}}); + registry.add("hKfInvMassZeeUls", "invariant mass for Z ULS pair KFp", kTH2F, {{axisPt}, {axisInvMassZ}}); + registry.add("hTHnElectrons", "electron info", HistType::kTHnSparseF, {axisPt, axisNsigma, axisM02, axisEop, axisIsoEnergy, axisIsoTrack, axisEta, axisDedx}); + registry.add("hTHnTrMatch", "Track EMC Match", HistType::kTHnSparseF, {axisPt, axisdPhi, axisdEta}); + + // Z-hadron correlation histograms + registry.add("hZHadronDphi", "Z-hadron #Delta#phi correlation", HistType::kTHnSparseF, {axisSign, axisPtZ, axisDPhiZh}); + registry.add("hZptSpectrum", "Z boson p_{T} spectrum", kTH2F, {{axisSign}, {axisPtZ}}); // hisotgram for EMCal trigger - registry.add("hEMCalTrigger", "EMCal trigger", kTH1F, {axisTrigger}); + registry.add("hEMCalTrigger", "EMCal trigger", kTH1D, {axisTrigger}); } double getIsolatedCluster(const o2::aod::EMCALCluster& cluster, @@ -261,6 +316,74 @@ struct HfTaskElectronWeakBoson { return (trackCount); } + void recoMassZee(KFParticle kfpIsoEle, + int charge, + TrackEle const& tracks) + { + // LOG(info) << "Invarimass cal by KF particle "; + for (const auto& track : tracks) { + + if (track.pt() < ptZeeMin) { + continue; + } + if (std::abs(track.tpcNSigmaEl()) > nsigTpcMax) { + continue; + } + if (std::abs(track.eta()) > etaTrMax) { + continue; + } + int pdgAss = kElectron; + if (track.sign() > 0) { + pdgAss = kPositron; + } + + KFPTrack kfpTrackAssEle = createKFPTrackFromTrack(track); + KFParticle kfpAssEle(kfpTrackAssEle, pdgAss); + // reco by RecoDecay + auto child1 = RecoDecayPtEtaPhi::pVector(kfpIsoEle.GetPt() * correctionPtElectron, kfpIsoEle.GetEta(), kfpIsoEle.GetPhi()); + auto child2 = RecoDecayPtEtaPhi::pVector(kfpAssEle.GetPt() * correctionPtElectron, kfpAssEle.GetEta(), kfpAssEle.GetPhi()); + double invMassEE = RecoDecay::m(std::array{child1, child2}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); + + // reco by KFparticle + const KFParticle* electronPairs[2] = {&kfpIsoEle, &kfpAssEle}; + KFParticle zeeKF; + zeeKF.SetConstructMethod(kfConstructMethod); + zeeKF.Construct(electronPairs, 2); + // LOG(info) << "Invarimass cal by KF particle Chi2/NDF = " << zeeKF.GetChi2()/zeeKF.GetNDF(); + float chiSqNdf = zeeKF.GetChi2() / zeeKF.GetNDF(); + if (zeeKF.GetNDF() < 1) { + continue; + } + if (zeeKF.GetChi2() < 0) { + continue; + } + if (chiSqNdf > chiSqNdfMax) { + continue; + } + float massZee, massZeeErr; + zeeKF.GetMass(massZee, massZeeErr); + // LOG(info) << "Invarimass cal by KF particle mass = " << massZee; + // LOG(info) << "Invarimass cal by RecoDecay = " << invMassEE; + + if (track.sign() * charge > 0) { + registry.fill(HIST("hKfInvMassZeeLs"), kfpIsoEle.GetPt(), massZee); + registry.fill(HIST("hInvMassZeeLs"), kfpIsoEle.GetPt(), invMassEE); + } else { + registry.fill(HIST("hKfInvMassZeeUls"), kfpIsoEle.GetPt(), massZee); + registry.fill(HIST("hInvMassZeeUls"), kfpIsoEle.GetPt(), invMassEE); + } + + reconstructedZ.emplace_back( + zeeKF.GetPt(), + zeeKF.GetEta(), + zeeKF.GetPhi(), + massZee, + track.sign() * charge, + kfpIsoEle.GetPt(), + kfpAssEle.GetPt()); + } + } + void process(soa::Filtered::iterator const& collision, aod::BCsWithTimestamps const&, SelectedClusters const& emcClusters, @@ -289,6 +412,14 @@ struct HfTaskElectronWeakBoson { zorro.initCCDB(ccdb.service, runNumber, currentTimestamp, cfgTriggerName); isFirstEvent = false; lastRunNumber = runNumber; + + // initialize magnetic field + o2::parameters::GRPMagField* grpo = ccdb->getForTimeStamp(ccdbPathGrpMag, currentTimestamp); + o2::base::Propagator::initFieldFromGRP(grpo); + double magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "magneticField = " << magneticField; + if (magneticField) + KFParticle::SetField(magneticField); } // Check if this is a triggered event using Zorro @@ -298,13 +429,14 @@ struct HfTaskElectronWeakBoson { registry.fill(HIST("hEMCalTrigger"), isTriggered ? 1 : 0); // Skip event if not triggered and we're processing skimmed data - if (!isTriggered && cfgSkimmedProcessing) { + if (!isTriggered) { return; } } // initialze for inclusive-electron selectedElectronsIso.clear(); selectedElectronsAss.clear(); + reconstructedZ.clear(); registry.fill(HIST("hEventCounter"), 0.5); @@ -316,22 +448,27 @@ struct HfTaskElectronWeakBoson { for (const auto& track : tracks) { - if (std::abs(track.eta()) > etaTrUp) + if (std::abs(track.eta()) > etaTrMax) { continue; - if (track.tpcNClsCrossedRows() < nclcrossTpcMin) - continue; - if (std::abs(track.dcaXY()) > dcaxyMax) + } + if (track.tpcNClsCrossedRows() < nclcrossTpcMin) { continue; - if (track.itsChi2NCl() > chi2ItsMax) + } + if (std::abs(track.dcaXY()) > dcaxyMax) { continue; - if (track.tpcChi2NCl() > chi2TpcMax) + } + if (track.itsChi2NCl() > chi2ItsMax) { continue; - if (track.tpcNClsFound() < nclTpcMin) + } + if (track.tpcChi2NCl() > chi2TpcMax) { continue; - if (track.itsNCls() < nclItsMin) + } + if (track.tpcNClsFound() < nclTpcMin) { continue; - if (track.pt() < ptMin) + } + if (track.itsNCls() < nclItsMin) { continue; + } registry.fill(HIST("hEta"), track.eta()); registry.fill(HIST("hITSchi2"), track.itsChi2NCl()); @@ -344,7 +481,7 @@ struct HfTaskElectronWeakBoson { float energyTrk = 0.0; - if (track.tpcNSigmaEl() > nsigTpcMinLose && track.tpcNSigmaEl() < nsigTpcMax && track.pt() > ptZeeMin) { + if (track.pt() > ptAssMin) { selectedElectronsAss.emplace_back( track.pt(), track.eta(), @@ -353,11 +490,16 @@ struct HfTaskElectronWeakBoson { track.sign()); } + if (track.pt() < ptMin) { + continue; + } // track - match // continue; if (track.phi() < phiEmcMin || track.phi() > phiEmcMax) continue; + if (std::abs(track.eta()) > etaEmcMax) + continue; auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, track.globalIndex()); // LOGF(info, "Number of matched track: %d", tracksofcluster.size()); @@ -397,13 +539,16 @@ struct HfTaskElectronWeakBoson { dPhiMin = dPhi; dEtaMin = dEta; } - registry.fill(HIST("hTrMatch"), dPhi, dEta); + registry.fill(HIST("hTHnTrMatch"), match.track_as().pt(), dPhi, dEta); registry.fill(HIST("hEMCtime"), timeEmc); registry.fill(HIST("hEnergy"), energyEmc); - if (r > rMatchMax) + if (std::abs(dPhi) > rMatchMax || std::abs(dEta) > rMatchMax) continue; + registry.fill(HIST("hTrMatchR"), match.track_as().pt(), r); + registry.fill(HIST("hEnergyNcell"), energyEmc, match.emcalcluster_as().nCells()); + const auto& cluster = match.emcalcluster_as(); double eop = energyEmc / match.track_as().p(); @@ -413,7 +558,7 @@ struct HfTaskElectronWeakBoson { int trackCount = getIsolatedTrack(track.eta(), track.phi(), track.pt(), tracks) - 1; if (match.track_as().pt() > ptTHnThresh && isTHnElectron) { - registry.fill(HIST("hTHnElectrons"), match.track_as().pt(), match.track_as().tpcNSigmaEl(), m02Emc, eop, isoEnergy, trackCount); + registry.fill(HIST("hTHnElectrons"), match.track_as().pt(), match.track_as().tpcNSigmaEl(), m02Emc, eop, isoEnergy, trackCount, track.eta(), track.tpcSignal()); } // LOG(info) << "E/p" << eop; registry.fill(HIST("hEopNsigTPC"), match.track_as().tpcNSigmaEl(), eop); @@ -427,10 +572,17 @@ struct HfTaskElectronWeakBoson { if (eop > eopMin && eop < eopMax && trackCount < trackIsolationMax) isIsolatedTr = true; - if (isIsolated) { + if (isIsolated && isIsolatedTr) { registry.fill(HIST("hEopIsolation"), match.track_as().pt(), eop); if (match.track_as().pt() > ptZeeMin) { + int pdgIso = kElectron; + if (match.track_as().sign() > 0) { + pdgIso = kPositron; + } + KFPTrack kfpTrackIsoEle = createKFPTrackFromTrack(match.track_as()); + KFParticle kfpIsoEle(kfpTrackIsoEle, pdgIso); + recoMassZee(kfpIsoEle, match.track_as().sign(), tracks); selectedElectronsIso.emplace_back( match.track_as().pt(), @@ -445,7 +597,6 @@ struct HfTaskElectronWeakBoson { } } } - nMatch++; } } @@ -456,30 +607,27 @@ struct HfTaskElectronWeakBoson { } } // end of track loop - - // calculate inv. mass - if (selectedElectronsIso.size() > 0) { - for (size_t i = 0; i < selectedElectronsIso.size(); i++) { - const auto& e1 = selectedElectronsIso[i]; - for (size_t j = 0; j < selectedElectronsAss.size(); j++) { - const auto& e2 = selectedElectronsAss[j]; - - float ptIso = e1.pt; - float ptAss = e2.pt; - if (ptIso == ptAss) + // Z-hadron + if (reconstructedZ.size() > 0) { + for (const auto& zBoson : reconstructedZ) { + // Z boson selection + if (zBoson.mass < massZMin || zBoson.mass > massZMax) { + continue; + } + registry.fill(HIST("hZptSpectrum"), zBoson.charge, zBoson.pt); + for (const auto& trackAss : selectedElectronsAss) { + if (std::abs(trackAss.pt - zBoson.ptchild0) < ptMatch) { + continue; + } + if (std::abs(trackAss.pt - zBoson.ptchild1) < ptMatch) { continue; - auto arr1 = RecoDecayPtEtaPhi::pVector(e1.pt, e1.eta, e1.phi); - auto arr2 = RecoDecayPtEtaPhi::pVector(e2.pt, e2.eta, e2.phi); - double mass = RecoDecay::m(std::array{arr1, arr2}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); - - if (e1.sign() * e2.sign() > 0) { - registry.fill(HIST("hInvMassZeeLs"), ptIso, mass); - } else { - registry.fill(HIST("hInvMassZeeUls"), ptIso, mass); } + // calculate Z-h correlation + double deltaPhi = RecoDecay::constrainAngle(trackAss.phi - zBoson.phi, -o2::constants::math::PIHalf); + registry.fill(HIST("hZHadronDphi"), zBoson.charge, zBoson.pt, deltaPhi); } } - } // end of inv. mass calculation + } // end of Z-hadron correlation } }; diff --git a/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx b/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx index cc2637cedc3..5fca08870fa 100644 --- a/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx +++ b/PWGHF/HFL/Tasks/taskMuonCharmBeautySeparation.cxx @@ -14,13 +14,18 @@ /// \brief Task to estimate HF->mu in the forward direction and use DCA observable to separate b-> mu, c-> mu. /// \author Shreyasi Acharya , LPC, France -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" - #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGHF/HFL/Tasks/taskSingleElectron.cxx b/PWGHF/HFL/Tasks/taskSingleElectron.cxx new file mode 100644 index 00000000000..d8a8b6e5b87 --- /dev/null +++ b/PWGHF/HFL/Tasks/taskSingleElectron.cxx @@ -0,0 +1,202 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. +/// +/// \file taskSingleElectron.cxx +/// \brief task for electrons from heavy-flavour hadron decays +/// \author Jonghan Park (Jeonbuk National University) + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include + +using namespace o2; +using namespace o2::constants::math; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct HfTaskSingleElectron { + + // Produces + + // Configurable + Configurable nContribMin{"nContribMin", 2, "min number of contributors"}; + Configurable posZMax{"posZMax", 10., "max posZ cut"}; + 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 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 nBinsPt{"nBinsPt", 100, "N bins in pT histo"}; + + // SliceCache + SliceCache cache; + + // using declarations + using MyCollisions = soa::Join; + using TracksEl = soa::Join; + + // Filter + Filter collZFilter = nabs(aod::collision::posZ) < posZMax; + + // Partition + + // ConfigurableAxis + 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"}; + + // AxisSpec + const AxisSpec axisEvt{4, 0., 4., "nEvents"}; + const AxisSpec axisNCont{100, 0., 100., "nCont"}; + const AxisSpec axisPosZ{600, -30., 30., "Z_{pos}"}; + const AxisSpec axisEta{30, -1.5, +1.5, "#eta"}; + const AxisSpec axisPt{nBinsPt, 0., 15., "p_{T}"}; + const AxisSpec axisNsig{800, -20., 20.}; + const AxisSpec axisTrackIp{4000, -0.2, 0.2, "dca"}; + + // Histogram registry + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(InitContext const&) + { + // create histograms + histos.add("hEventCounter", "hEventCounter", kTH1F, {axisEvt}); + histos.add("nEvents", "Number of events", kTH1F, {{1, 0., 1.}}); + histos.add("VtxZ", "VtxZ; cm; entries", kTH1F, {axisPosZ}); + histos.add("etaTrack", "etaTrack; #eta; entries", kTH1F, {axisEta}); + histos.add("ptTrack", "#it{p}_{T} distribution of selected tracks; #it{p}_{T} (GeV/#it{c}); entries", kTH1F, {axisPt}); + + // QA plots for trigger track selection + histos.add("tpcNClsTrack", "tpcNClsTrack", kTH1F, {{200, 0, 200}}); + histos.add("tpcFoundFindableTrack", "", kTH1F, {{10, 0, 1}}); + histos.add("tpcChi2Track", "", kTH1F, {{100, 0, 10}}); + histos.add("itsIBClsTrack", "", kTH1F, {{10, 0, 10}}); + histos.add("dcaXYTrack", "", kTH1F, {{600, -3, 3}}); + histos.add("dcaZTrack", "", kTH1F, {{600, -3, 3}}); + + // pid + histos.add("tofNSigPt", "", kTH2F, {{axisPtEl}, {axisNsig}}); + histos.add("tofNSigPtQA", "", kTH2F, {{axisPtEl}, {axisNsig}}); + histos.add("tpcNSigPt", "", kTH2F, {{axisPtEl}, {axisNsig}}); + histos.add("tpcNSigPtAfterTofCut", "", kTH2F, {{axisPtEl}, {axisNsig}}); + histos.add("tpcNSigPtQA", "", kTH2F, {{axisPtEl}, {axisNsig}}); + + // track impact parameter + histos.add("dcaTrack", "", kTH2F, {{axisPtEl}, {axisTrackIp}}); + } + + template + bool trackSel(const TrackType& track) + { + if ((track.pt() > ptTrackMax) || (track.pt() < ptTrackMin)) { + return false; + } + if (std::abs(track.eta()) > etaTrackMax) { + return false; + } + + if (track.tpcNClsCrossedRows() < tpcNCrossedRowMin) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < tpcNClsFoundOverFindableMin) { + return false; + } + if (track.tpcChi2NCl() > tpcChi2perNClMax) { + return false; + } + + if (!(track.itsNClsInnerBarrel() == itsIBClsMin)) { + return false; + } + + if (std::abs(track.dcaXY()) > dcaxyMax) { + return false; + } + if (std::abs(track.dcaZ()) > dcazMax) { + return false; + } + + return true; + } + + void process(soa::Filtered::iterator const& collision, + TracksEl const& tracks) + { + float flagEventFill = 0.5; + float flagAnalysedEvt = 0.5; + histos.fill(HIST("hEventCounter"), flagEventFill); + + if (!collision.sel8()) { + return; + } + flagEventFill += 1.; + histos.fill(HIST("hEventCounter"), flagEventFill); + + if (collision.numContrib() < nContribMin) { + return; + } + flagEventFill += 1.; + histos.fill(HIST("hEventCounter"), flagEventFill); + + histos.fill(HIST("VtxZ"), collision.posZ()); + histos.fill(HIST("nEvents"), flagAnalysedEvt); + + for (const auto& track : tracks) { + + if (!trackSel(track)) { + continue; + } + + histos.fill(HIST("etaTrack"), track.eta()); + histos.fill(HIST("ptTrack"), 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("tofNSigPt"), track.pt(), track.tofNSigmaEl()); + histos.fill(HIST("tpcNSigPt"), track.pt(), track.tpcNSigmaEl()); + + if (std::abs(track.tofNSigmaEl()) > tofNSigmaMax) { + continue; + } + histos.fill(HIST("tofNSigPtQA"), track.pt(), track.tofNSigmaEl()); + histos.fill(HIST("tpcNSigPtAfterTofCut"), track.pt(), track.tpcNSigmaEl()); + + if (track.tpcNSigmaEl() < tpcNSigmaMin || track.tpcNSigmaEl() > tpcNSigmaMax) { + continue; + } + histos.fill(HIST("tpcNSigPtQA"), track.pt(), track.tpcNSigmaEl()); + + histos.fill(HIST("dcaTrack"), track.pt(), track.dcaXY()); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/HFL/Tasks/taskSingleMuon.cxx b/PWGHF/HFL/Tasks/taskSingleMuon.cxx index 73445124ae9..9b38f3f45a6 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuon.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuon.cxx @@ -13,17 +13,23 @@ /// \brief Task used to extract the observables on single muons needed for the HF-muon analysis. /// \author Maolin Zhang , CCNU -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" - #include "Common/Core/RecoDecay.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx b/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx index 48cc13b74c4..b51635dda6b 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonMult.cxx @@ -13,22 +13,28 @@ /// \brief Task used to study the Open heavy flavour decay muon production as a function of multiplicity. /// \author Md Samsul Islam , IITB -#include - -#include "CommonConstants/MathConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.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 +#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/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx b/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx index 7d04bead362..52cb12b6f41 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonReader.cxx @@ -12,17 +12,20 @@ /// \file taskSingleMuonReader.cxx /// \brief Task used to read the derived table produced by the tableMaker of DQ framework and extract observables on single muons needed for the HF-muon analysis. /// \author Maolin Zhang , CCNU -#include -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" + #include "PWGDQ/DataModel/ReducedInfoTables.h" + #include "Common/Core/RecoDecay.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::aod; diff --git a/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx b/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx index 03fa6efb5a5..2b43e9ab14f 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonReaderAssoc.cxx @@ -13,18 +13,18 @@ /// \brief Task used to read the derived table produced by the tableMaker-association of DQ framework and extract observables on single muons needed for the HF-muon analysis. /// \author Maolin Zhang , CCNU -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" #include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx index d60a04f80d0..58f6654ee68 100644 --- a/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx +++ b/PWGHF/HFL/Tasks/taskSingleMuonSource.cxx @@ -13,20 +13,30 @@ // \brief Task used to seperate single muons source in Monte Carlo simulation. // \author Maolin Zhang , CCNU +#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 "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/TrackFwd.h" +#include -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/Macros/computeFonllPlusPythiaPredictions.C b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C index bdd8f1ca7e2..c112f7f5d24 100644 --- a/PWGHF/Macros/computeFonllPlusPythiaPredictions.C +++ b/PWGHF/Macros/computeFonllPlusPythiaPredictions.C @@ -16,27 +16,27 @@ #if !defined(__CINT__) || defined(__CLING__) -#include -#include -#include -#include -#include +#include +#include -#include -#include -#include #include -#include -#include +#include #include +#include +#include +#include +#include +#include -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" - -#include "CommonConstants/MathConstants.h" -#include "Framework/Logger.h" +#include -#include "Pythia8/Pythia.h" +#include +#include +#include +#include +#include +#include +#include #endif diff --git a/PWGHF/TableProducer/CMakeLists.txt b/PWGHF/TableProducer/CMakeLists.txt index 2ec33b5d134..e57147f6cfc 100644 --- a/PWGHF/TableProducer/CMakeLists.txt +++ b/PWGHF/TableProducer/CMakeLists.txt @@ -13,7 +13,7 @@ o2physics_add_dpl_workflow(track-index-skim-creator SOURCES trackIndexSkimCreator.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2::DCAFitter O2Physics::AnalysisCCDB O2Physics::MLCore O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing O2::DCAFitter O2Physics::AnalysisCCDB O2Physics::MLCore O2Physics::EventFilteringUtils O2Physics::SGCutParHolder COMPONENT_NAME Analysis) # Helpers @@ -37,12 +37,12 @@ o2physics_add_dpl_workflow(mc-pid-tof o2physics_add_dpl_workflow(candidate-creator-2prong SOURCES candidateCreator2Prong.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils O2Physics::SGCutParHolder COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-3prong SOURCES candidateCreator3Prong.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::EventFilteringUtils O2Physics::SGCutParHolder COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(candidate-creator-b0 @@ -172,6 +172,11 @@ o2physics_add_dpl_workflow(candidate-selector-omegac0-to-omega-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(candidate-selector-omegac0-xic0-to-omega-ka + SOURCES candidateSelectorOmegac0Xic0ToOmegaKa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(candidate-selector-xic0-to-xi-pi-kf SOURCES candidateSelectorXic0ToXiPiKf.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::MLCore @@ -315,8 +320,8 @@ o2physics_add_dpl_workflow(derived-data-creator-dplus-to-pi-k-pi PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(derived-data-creator-lc-to-p-k-pi - SOURCES derivedDataCreatorLcToPKPi.cxx +o2physics_add_dpl_workflow(derived-data-creator-ds-to-k-k-pi + SOURCES derivedDataCreatorDsToKKPi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -324,9 +329,20 @@ o2physics_add_dpl_workflow(derived-data-creator-dstar-to-d0-pi SOURCES derivedDataCreatorDstarToD0Pi.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(derived-data-creator-lc-to-p-k-pi + SOURCES derivedDataCreatorLcToPKPi.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 + COMPONENT_NAME Analysis) + # Converters o2physics_add_dpl_workflow(converter-dstar-indices - SOURCES converterDstarIndices.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) + SOURCES converterDstarIndices.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGHF/TableProducer/candidateCreator2Prong.cxx b/PWGHF/TableProducer/candidateCreator2Prong.cxx index d551922b7d5..a4c7c4ced21 100644 --- a/PWGHF/TableProducer/candidateCreator2Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator2Prong.cxx @@ -18,47 +18,68 @@ #ifndef HomogeneousField #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) +#include "PWGHF/Core/DecayChannels.h" #endif -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "ReconstructionDataFormats/DCA.h" - -#include "Common/Core/trackUtilities.h" -#include "Tools/KFparticle/KFUtilities.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsMcGen.h" +#include "PWGHF/Utils/utilsMcMatching.h" #include "PWGHF/Utils/utilsPid.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.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 using namespace o2; using namespace o2::analysis; using namespace o2::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::aod::hf_cand_2prong; +using namespace o2::hf_decay; +using namespace o2::hf_decay::hf_cand_2prong; using namespace o2::hf_centrality; using namespace o2::hf_occupancy; using namespace o2::constants::physics; @@ -100,27 +121,36 @@ struct HfCandidateCreator2Prong { float toMicrometers = 10000.; // from cm to µm double massPi{0.}; double massK{0.}; + double massE{0.}; + double massMu{0.}; double massPiK{0.}; double massKPi{0.}; + double massEE{0.}; + double massMuMu{0.}; double bz{0.}; std::shared_ptr hCandidates; + + ConfigurableAxis axisMass{"axisMass", {500, 1.6, 2.1}, "axis for mass (GeV/c^2)"}; + HistogramRegistry registry{"registry"}; void init(InitContext const&) { - std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, + std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, doprocessPvRefitWithDCAFitterNCentFT0C, doprocessNoPvRefitWithDCAFitterNCentFT0C, - doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M}; - std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, + doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M, doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc}; + std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, doprocessPvRefitWithKFParticleCentFT0C, doprocessNoPvRefitWithKFParticleCentFT0C, - doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M}; + doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc}; if ((std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) + std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0)) != 1) { LOGP(fatal, "One and only one process function must be enabled at a time."); } - std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M}; + std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M, doprocessCollisionsUpc}; const int nProcessesCollisions = std::accumulate(processesCollisions.begin(), processesCollisions.end(), 0); + std::array processesUpc = {doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc, doprocessCollisionsUpc}; + const int nProcessesUpc = std::accumulate(processesUpc.begin(), processesUpc.end(), 0); if (nProcessesCollisions > 1) { LOGP(fatal, "At most one process function for collision monitoring can be enabled at a time."); } @@ -134,10 +164,18 @@ struct HfCandidateCreator2Prong { if ((doprocessPvRefitWithDCAFitterNCentFT0M || doprocessNoPvRefitWithDCAFitterNCentFT0M || doprocessPvRefitWithKFParticleCentFT0M || doprocessNoPvRefitWithKFParticleCentFT0M) && !doprocessCollisionsCentFT0M) { LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsCentFT0M\"?"); } + if ((doprocessPvRefitWithDCAFitterNUpc || doprocessNoPvRefitWithDCAFitterNUpc || doprocessPvRefitWithKFParticleUpc || doprocessNoPvRefitWithKFParticleUpc) && !doprocessCollisionsUpc) { + LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsUpc\"?"); + } + } + if (nProcessesUpc > 0 && isRun2) { + LOGP(fatal, "Process function for UPC is only available in Run 3!"); } // histograms - registry.add("hMass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {{500, 1.6, 2.1}}}); + registry.add("hMass2", "2-prong candidates;inv. mass (#pi K) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); + registry.add("hMassEE", "2-prong candidates;inv. mass (e e) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); + registry.add("hMassMuMu", "2-prong candidates;inv. mass (#mu #mu) (GeV/#it{c}^{2});entries", {HistType::kTH1F, {axisMass}}); registry.add("hCovPVXX", "2-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); registry.add("hCovSVXX", "2-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 0.2}}}); registry.add("hCovPVYY", "2-prong candidates;YY element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1F, {{100, 0., 1.e-4}}}); @@ -156,6 +194,8 @@ struct HfCandidateCreator2Prong { massPi = MassPiPlus; massK = MassKPlus; + massE = MassElectron; + massMu = MassMuon; if (std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) == 1) { registry.fill(HIST("hVertexerType"), aod::hf_cand::VertexerType::DCAFitter); @@ -182,11 +222,11 @@ struct HfCandidateCreator2Prong { setLabelHistoCands(hCandidates); } - template + template void runCreator2ProngWithDCAFitterN(Coll const&, CandType const& rowsTrackIndexProng2, TTracks const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { // loop over pairs of track indices for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { @@ -194,7 +234,12 @@ struct HfCandidateCreator2Prong { /// reject candidates not satisfying the event selections auto collision = rowTrackIndexProng2.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -208,7 +253,7 @@ struct HfCandidateCreator2Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, nullptr, isRun2); @@ -324,17 +369,21 @@ struct HfCandidateCreator2Prong { auto arrayMomenta = std::array{pvec0, pvec1}; massPiK = RecoDecay::m(arrayMomenta, std::array{massPi, massK}); massKPi = RecoDecay::m(arrayMomenta, std::array{massK, massPi}); + massEE = RecoDecay::m(arrayMomenta, std::array{massE, massE}); + massMuMu = RecoDecay::m(arrayMomenta, std::array{massMu, massMu}); registry.fill(HIST("hMass2"), massPiK); registry.fill(HIST("hMass2"), massKPi); + registry.fill(HIST("hMassEE"), massEE); + registry.fill(HIST("hMassMuMu"), massMuMu); } } } - template + template void runCreator2ProngWithKFParticle(Coll const&, CandType const& rowsTrackIndexProng2, TTracks const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { for (const auto& rowTrackIndexProng2 : rowsTrackIndexProng2) { @@ -342,7 +391,12 @@ struct HfCandidateCreator2Prong { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng2.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -354,7 +408,7 @@ struct HfCandidateCreator2Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, nullptr, isRun2); @@ -494,7 +548,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter w/ PV refit and w/o centrality selections", false); @@ -504,7 +558,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter w/o PV refit and w/o centrality selections", true); @@ -514,7 +568,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticle, "Run candidate creator using KFParticle package w/ PV refit and w/o centrality selections", false); @@ -524,7 +578,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticle, "Run candidate creator using KFParticle package w/o PV refit and w/o centrality selections", false); @@ -540,7 +594,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter w/ PV refit and w/ centrality selection on FT0C", false); @@ -550,7 +604,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter w/o PV refit and w/ centrality selection FT0C", false); @@ -560,7 +614,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package w/ PV refit and w/ centrality selection on FT0C", false); @@ -570,7 +624,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package w/o PV refit and w/ centrality selection on FT0C", false); @@ -586,7 +640,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter w/ PV refit and w/ centrality selection on FT0M", false); @@ -596,7 +650,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter w/o PV refit and w/ centrality selection FT0M", false); @@ -606,7 +660,7 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package w/ PV refit and w/ centrality selection on FT0M", false); @@ -616,10 +670,72 @@ struct HfCandidateCreator2Prong { TracksWCovExtraPidPiKa const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package w/o PV refit and w/ centrality selection on FT0M", false); + ///////////////////////////////////////////// + /// /// + /// with centrality selection on UPC /// + /// /// + ///////////////////////////////////////////// + + /// @brief process function using DCA fitter w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithDCAFitterNUpc(soa::Join const& collisions, + soa::Join const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter w/ PV refit and w/ centrality selection on UltraPeripheral Collision", false); + + /// @brief process function using DCA fitter w/o PV refit and w/ centrality selection UPC + void processNoPvRefitWithDCAFitterNUpc(soa::Join const& collisions, + aod::Hf2Prongs const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithDCAFitterN(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter w/o PV refit and w/ centrality selection UltraPeripheral Collision", false); + + /// @brief process function using KFParticle package w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithKFParticleUpc(soa::Join const& collisions, + soa::Join const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package w/ PV refit and w/ centrality selection on UltraPeripheral Collision", false); + + /// @brief process function using KFParticle package w/o PV refit and w/o centrality selections on UPC + void processNoPvRefitWithKFParticleUpc(soa::Join const& collisions, + aod::Hf2Prongs const& rowsTrackIndexProng2, + TracksWCovExtraPidPiKa const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator2ProngWithKFParticle(collisions, rowsTrackIndexProng2, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processNoPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package w/o PV refit and w/ centrality selection on UltraPeripheral Collision", false); + /////////////////////////////////////////////////////////// /// /// /// Process functions only for collision monitoring /// @@ -634,7 +750,7 @@ struct HfCandidateCreator2Prong { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -652,7 +768,7 @@ struct HfCandidateCreator2Prong { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -670,7 +786,7 @@ struct HfCandidateCreator2Prong { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -679,6 +795,29 @@ struct HfCandidateCreator2Prong { } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreator2Prong, processCollisionsCentFT0M, "Collision monitoring - FT0M centrality", false); + + /// @brief process function to monitor collisions - UPC collision + void processCollisionsUpc(soa::Join const& collisions, + aod::BcFullInfos const& bcs, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + /// loop over collisions + for (const auto& collision : collisions) { + + /// bitmask with event. selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + + /// monitor the satisfied event selections + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + + } /// end loop over collisions + } + PROCESS_SWITCH(HfCandidateCreator2Prong, processCollisionsUpc, "Collision monitoring - UPC", false); }; /// Extends the base table with expression columns. @@ -691,6 +830,7 @@ struct HfCandidateCreator2ProngExpressions { Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; Configurable matchKinkedDecayTopology{"matchKinkedDecayTopology", false, "Match also candidates with tracks that decay with kinked topology"}; Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", false, "Match also candidates with tracks that interact with material"}; + Configurable matchCorrelatedBackground{"matchCorrelatedBackground", false, "Match correlated background candidates"}; HfEventSelectionMc hfEvSelMc; // mc event selection and monitoring @@ -737,15 +877,18 @@ struct HfCandidateCreator2ProngExpressions { int indexRec = -1; int8_t sign = 0; - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelResonant = 0; int8_t origin = 0; int8_t nKinkedTracks = 0; int8_t nInteractionsWithMaterial = 0; + constexpr std::size_t NDaughtersResonant{2u}; // Match reconstructed candidates. // Spawned table can be used directly for (const auto& candidate : *rowCandidateProng2) { - flag = 0; + flagChannelMain = 0; + flagChannelResonant = 0; origin = 0; auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as()}; @@ -762,60 +905,120 @@ struct HfCandidateCreator2ProngExpressions { } } if (fromBkg) { - rowMcMatchRec(flag, origin, -1.f, 0, 0, 0); + rowMcMatchRec(flagChannelMain, origin, flagChannelResonant, -1.f, 0, 0, 0); continue; } } std::vector idxBhadMothers{}; - // D0(bar) → π± K∓ - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); - } - if (indexRec > -1) { - flag = sign * (1 << DecayType::D0ToPiK); - } + if (matchCorrelatedBackground) { + indexRec = -1; // Index of the matched reconstructed candidate + constexpr int FinalStateDepth = 2; + constexpr int ResoDepth = 1; + + // D0(bar) → π+ K−, π+ K− π0, π+ π−, π+ π− π0, K+ K− + for (const auto& [channelMain, finalState] : daughtersD0Main) { + std::array arrPdgDaughtersMain2Prongs = std::array{finalState[0], finalState[1]}; + if (finalState.size() == 3) { // o2-linter: disable=magic-number (partially reconstructed 3-prong decays) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth); + } - // J/ψ → e+ e− - if (flag == 0) { - if (matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); + if (indexRec > -1) { + auto motherParticle = mcParticles.rawIteratorAt(indexRec); + std::array arrPdgDaughtersMain3Prongs = std::array{finalState[0], finalState[1], finalState[2]}; + flipPdgSign(motherParticle.pdgCode(), +kPi0, arrPdgDaughtersMain3Prongs); + if (!RecoDecay::isMatchedMCGen(mcParticles, motherParticle, Pdg::kD0, arrPdgDaughtersMain3Prongs, true, &sign, FinalStateDepth)) { + indexRec = -1; // Reset indexRec if the generated decay does not match the reconstructed one + } + } + } else if (finalState.size() == 2) { // o2-linter: disable=magic-number (fully reconstructed 2-prong decays) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, FinalStateDepth); + } + } else { + LOG(fatal) << "Final state size not supported: " << finalState.size(); + return; + } + if (indexRec > -1) { + flagChannelMain = sign * channelMain; + + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrResoDaughIndex, std::array{0}, ResoDepth); + std::array arrPdgDaughters = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrResoDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPdgDaughters[iProng] = daughI.pdgCode(); + } + flagChannelResonant = getDecayChannelResonant(Pdg::kD0, arrPdgDaughters); + } + break; + } + } + } else { + // D0(bar) → π± K∓ + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign); } if (indexRec > -1) { - flag = 1 << DecayType::JpsiToEE; + flagChannelMain = sign * DecayChannelMain::D0ToPiK; } - } - // J/ψ → μ+ μ− - if (flag == 0) { - if (matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true); + // J/ψ → e+ e− + if (flagChannelMain == 0) { + if (matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, +kPositron}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kElectron, +kPositron}, true); + } + if (indexRec > -1) { + flagChannelMain = DecayChannelMain::JpsiToEE; + } } - if (indexRec > -1) { - flag = 1 << DecayType::JpsiToMuMu; + + // J/ψ → μ+ μ− + if (flagChannelMain == 0) { + if (matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonMinus, +kMuonPlus}, true, &sign, 1, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kJPsi, std::array{+kMuonMinus, +kMuonPlus}, true); + } + if (indexRec > -1) { + flagChannelMain = DecayChannelMain::JpsiToMuMu; + } } } // Check whether the particle is non-prompt (from a b quark). - if (flag != 0) { + if (flagChannelMain != 0) { auto particle = mcParticles.rawIteratorAt(indexRec); origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } if (origin == RecoDecay::OriginType::NonPrompt) { auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); - rowMcMatchRec(flag, origin, bHadMother.pt(), bHadMother.pdgCode(), nKinkedTracks, nInteractionsWithMaterial); + rowMcMatchRec(flagChannelMain, origin, flagChannelResonant, bHadMother.pt(), bHadMother.pdgCode(), nKinkedTracks, nInteractionsWithMaterial); } else { - rowMcMatchRec(flag, origin, -1.f, 0, nKinkedTracks, nInteractionsWithMaterial); + rowMcMatchRec(flagChannelMain, origin, flagChannelResonant, -1.f, 0, nKinkedTracks, nInteractionsWithMaterial); } } @@ -825,7 +1028,7 @@ struct HfCandidateCreator2ProngExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); @@ -842,11 +1045,11 @@ struct HfCandidateCreator2ProngExpressions { if (rejectionMask != 0) { // at least one event selection not satisfied --> reject all particles from this collision for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { - rowMcMatchGen(0, 0, -1); + rowMcMatchGen(0, 0, 0, -1); } continue; } - hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground); + hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground, matchCorrelatedBackground); } } diff --git a/PWGHF/TableProducer/candidateCreator3Prong.cxx b/PWGHF/TableProducer/candidateCreator3Prong.cxx index 145e84513db..f3bfce8ba51 100644 --- a/PWGHF/TableProducer/candidateCreator3Prong.cxx +++ b/PWGHF/TableProducer/candidateCreator3Prong.cxx @@ -19,45 +19,66 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "ReconstructionDataFormats/DCA.h" - -#include "Common/Core/trackUtilities.h" -#include "Tools/KFparticle/KFUtilities.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/CentralityEstimation.h" #include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsMcGen.h" +#include "PWGHF/Utils/utilsMcMatching.h" #include "PWGHF/Utils/utilsPid.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.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::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::aod::hf_cand_3prong; +using namespace o2::hf_decay; using namespace o2::hf_decay::hf_cand_3prong; using namespace o2::hf_centrality; using namespace o2::hf_occupancy; @@ -128,25 +149,28 @@ struct HfCandidateCreator3Prong { using TracksWCovExtraPidPiKaPr = soa::Join; // filter candidates - Filter filterSelected3Prongs = (createDplus && (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_3prong::DecayType::DplusToPiKPi))) != static_cast(0)) || (createDs && (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_3prong::DecayType::DsToKKPi))) != static_cast(0)) || (createLc && (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_3prong::DecayType::LcToPKPi))) != static_cast(0)) || (createXic && (o2::aod::hf_track_index::hfflag & static_cast(BIT(aod::hf_cand_3prong::DecayType::XicToPKPi))) != 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)); std::shared_ptr hCandidates; HistogramRegistry registry{"registry"}; void init(InitContext const&) { - std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, + std::array doprocessDF{doprocessPvRefitWithDCAFitterN, doprocessNoPvRefitWithDCAFitterN, doprocessPvRefitWithDCAFitterNCentFT0C, doprocessNoPvRefitWithDCAFitterNCentFT0C, - doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M}; - std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, + doprocessPvRefitWithDCAFitterNCentFT0M, doprocessNoPvRefitWithDCAFitterNCentFT0M, doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc}; + std::array doprocessKF{doprocessPvRefitWithKFParticle, doprocessNoPvRefitWithKFParticle, doprocessPvRefitWithKFParticleCentFT0C, doprocessNoPvRefitWithKFParticleCentFT0C, - doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M}; + doprocessPvRefitWithKFParticleCentFT0M, doprocessNoPvRefitWithKFParticleCentFT0M, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc}; if ((std::accumulate(doprocessDF.begin(), doprocessDF.end(), 0) + std::accumulate(doprocessKF.begin(), doprocessKF.end(), 0)) != 1) { LOGP(fatal, "One and only one process function must be enabled at a time."); } - - std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M}; + std::array processesCollisions = {doprocessCollisions, doprocessCollisionsCentFT0C, doprocessCollisionsCentFT0M, doprocessCollisionsUpc}; const int nProcessesCollisions = std::accumulate(processesCollisions.begin(), processesCollisions.end(), 0); + + std::array processesUpc = {doprocessPvRefitWithDCAFitterNUpc, doprocessNoPvRefitWithDCAFitterNUpc, doprocessPvRefitWithKFParticleUpc, doprocessNoPvRefitWithKFParticleUpc, doprocessCollisionsUpc}; + const int nProcessesUpc = std::accumulate(processesUpc.begin(), processesUpc.end(), 0); + if (nProcessesCollisions > 1) { LOGP(fatal, "At most one process function for collision monitoring can be enabled at a time."); } @@ -160,8 +184,13 @@ struct HfCandidateCreator3Prong { if ((doprocessPvRefitWithDCAFitterNCentFT0M || doprocessNoPvRefitWithDCAFitterNCentFT0M || doprocessPvRefitWithKFParticleCentFT0M || doprocessNoPvRefitWithKFParticleCentFT0M) && !doprocessCollisionsCentFT0M) { LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsCentFT0M\"?"); } + if ((doprocessPvRefitWithDCAFitterNUpc || doprocessNoPvRefitWithDCAFitterNUpc || doprocessPvRefitWithKFParticleUpc || doprocessNoPvRefitWithKFParticleUpc) && !doprocessCollisionsUpc) { + LOGP(fatal, "Process function for collision monitoring not correctly enabled. Did you enable \"processCollisionsUpc\"?"); + } + } + if (nProcessesUpc > 0 && isRun2) { + LOGP(fatal, "Process function for UPC is only available in Run 3!"); } - std::array creationFlags = {createDplus, createDs, createLc, createXic}; if (std::accumulate(creationFlags.begin(), creationFlags.end(), 0) == 0) { LOGP(fatal, "At least one particle specie should be enabled for the creation."); @@ -235,11 +264,11 @@ struct HfCandidateCreator3Prong { } } - template + template void runCreator3ProngWithDCAFitterN(Coll const&, Cand const& rowsTrackIndexProng3, TracksWCovExtraPidPiKaPr const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { // loop over triplets of track indices for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) { @@ -247,7 +276,12 @@ struct HfCandidateCreator3Prong { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng3.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -263,7 +297,7 @@ struct HfCandidateCreator3Prong { /// Set the magnetic field from ccdb. /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, /// but this is not true when running on Run2 data/MC already converted into AO2Ds. - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); if (runNumber != bc.runNumber()) { LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, nullptr, isRun2); @@ -403,17 +437,22 @@ struct HfCandidateCreator3Prong { } } - template + template void runCreator3ProngWithKFParticle(Coll const&, Cand const& rowsTrackIndexProng3, TracksWCovExtraPidPiKaPr const&, - aod::BCsWithTimestamps const& /*bcWithTimeStamps*/) + BCsType const& bcs) { for (const auto& rowTrackIndexProng3 : rowsTrackIndexProng3) { /// reject candidates in collisions not satisfying the event selections auto collision = rowTrackIndexProng3.template collision_as(); float centrality{-1.f}; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask{0}; + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + } if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject the candidate continue; @@ -653,7 +692,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter with PV refit and w/o centrality selections", false); @@ -663,7 +702,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterN, "Run candidate creator using DCA fitter without PV refit and w/o centrality selections", true); @@ -673,7 +712,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticle, "Run candidate creator using KFParticle package with PV refit and w/o centrality selections", false); @@ -683,7 +722,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticle, "Run candidate creator using KFParticle package without PV refit and w/o centrality selections", false); @@ -699,7 +738,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter with PV refit and w/ centrality selection on FT0C", false); @@ -709,7 +748,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterNCentFT0C, "Run candidate creator using DCA fitter without PV refit and w/ centrality selection on FT0C", false); @@ -719,7 +758,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package with PV refit and w/ centrality selection on FT0C", false); @@ -729,7 +768,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticleCentFT0C, "Run candidate creator using KFParticle package without PV refit and w/ centrality selection on FT0C", false); @@ -745,7 +784,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter with PV refit and w/ centrality selection on FT0M", false); @@ -755,7 +794,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterNCentFT0M, "Run candidate creator using DCA fitter without PV refit and w/ centrality selection on FT0M", false); @@ -765,7 +804,7 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package with PV refit and w/ centrality selection on FT0M", false); @@ -775,10 +814,72 @@ struct HfCandidateCreator3Prong { TracksWCovExtraPidPiKaPr const& tracks, aod::BCsWithTimestamps const& bcWithTimeStamps) { - runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); } PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticleCentFT0M, "Run candidate creator using KFParticle package without PV refit and w/ centrality selection on FT0M", false); + ///////////////////////////////////////////// + /// /// + /// with centrality selection on UPC /// + /// /// + ///////////////////////////////////////////// + + /// @brief process function using DCA fitter w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithDCAFitterNUpc(soa::Join const& collisions, + FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter with PV refit and w/ centrality selection on UPC", false); + + /// @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, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithDCAFitterN(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithDCAFitterNUpc, "Run candidate creator using DCA fitter without PV refit and w/ centrality selection on UPC", false); + + /// @brief process function using KFParticle package w/ PV refit and w/ centrality selection on UPC + void processPvRefitWithKFParticleUpc(soa::Join const& collisions, + FilteredPvRefitHf3Prongs const& rowsTrackIndexProng3, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package with PV refit and w/ centrality selection on UPC", false); + + /// @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, + TracksWCovExtraPidPiKaPr const& tracks, + aod::BcFullInfos const& bcWithTimeStamps, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + runCreator3ProngWithKFParticle(collisions, rowsTrackIndexProng3, tracks, bcWithTimeStamps); + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processNoPvRefitWithKFParticleUpc, "Run candidate creator using KFParticle package without PV refit and w/ centrality selection on UPC", false); + /////////////////////////////////////////////////////////// /// /// /// Process functions only for collision monitoring /// @@ -793,7 +894,7 @@ struct HfCandidateCreator3Prong { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -811,7 +912,7 @@ struct HfCandidateCreator3Prong { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -829,7 +930,7 @@ struct HfCandidateCreator3Prong { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -838,6 +939,29 @@ struct HfCandidateCreator3Prong { } /// end loop over collisions } PROCESS_SWITCH(HfCandidateCreator3Prong, processCollisionsCentFT0M, "Collision monitoring - FT0M centrality", false); + + /// @brief process function to monitor collisions - UPC + void processCollisionsUpc(soa::Join const& collisions, + aod::BcFullInfos const& bcs, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + /// loop over collisions + for (const auto& collision : collisions) { + + /// bitmask with event. selection info + float centrality{-1.f}; + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc(collision, centrality, ccdb, registry, bcs); + + /// monitor the satisfied event selections + hfEvSel.fillHistograms(collision, rejectionMask, centrality, occupancy); + + } /// end loop over collisions + } + PROCESS_SWITCH(HfCandidateCreator3Prong, processCollisionsUpc, "Collision monitoring - UPC", false); }; /// Extends the base table with expression columns. @@ -850,6 +974,8 @@ struct HfCandidateCreator3ProngExpressions { Configurable rejectBackground{"rejectBackground", true, "Reject particles from background events"}; Configurable matchKinkedDecayTopology{"matchKinkedDecayTopology", false, "Match also candidates with tracks that decay with kinked topology"}; Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", false, "Match also candidates with tracks that interact with material"}; + Configurable matchCorrelatedBackground{"matchCorrelatedBackground", false, "Match correlated background candidates"}; + Configurable> pdgMothersCorrelBkg{"pdgMothersCorrelBkg", {Pdg::kDPlus, Pdg::kDS, Pdg::kDStar, Pdg::kLambdaCPlus, Pdg::kXiCPlus}, "PDG codes of the mother particles of correlated background candidates"}; constexpr static std::size_t NDaughtersResonant{2u}; @@ -898,27 +1024,28 @@ struct HfCandidateCreator3ProngExpressions { int indexRec = -1; int8_t sign = 0; - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelResonant = 0; int8_t origin = 0; int8_t swapping = 0; - int8_t channel = 0; int8_t nKinkedTracks = 0; int8_t nInteractionsWithMaterial = 0; std::vector arrDaughIndex; - std::array arrPDGDaugh; - std::array arrPDGResonant1 = {kProton, 313}; // Λc± → p± K* - std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ - std::array arrPDGResonant3 = {102134, kPiPlus}; // Λc± → Λ(1520) π± - std::array arrPDGResonantDPhiPi = {333, kPiPlus}; // Ds± → Phi π± and D± → Phi π± - std::array arrPDGResonantDKstarK = {313, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± + std::array arrPdgDaugResonant; + const std::array arrPdgDaugResonantLcToPKstar0{daughtersLcResonant.at(DecayChannelResonant::LcToPKstar0)}; // Λc± → p± K* + const std::array arrPdgDaugResonantLcToDeltaplusplusK{daughtersLcResonant.at(DecayChannelResonant::LcToDeltaplusplusK)}; // Λc± → Δ(1232)±± K∓ + const std::array arrPdgDaugResonantLcToL1520Pi{daughtersLcResonant.at(DecayChannelResonant::LcToL1520Pi)}; // Λc± → Λ(1520) π± + const std::array arrPdgDaugResonantDToPhiPi{daughtersDsResonant.at(DecayChannelResonant::DsToPhiPi)}; // Ds± → φ π± and D± → φ π± + const std::array arrPdgDaugResonantDToKstar0K{daughtersDsResonant.at(DecayChannelResonant::DsToKstar0K)}; // Ds± → anti-K*(892)0 K± and D± → anti-K*(892)0 K± // Match reconstructed candidates. // Spawned table can be used directly for (const auto& candidate : *rowCandidateProng3) { - flag = 0; + flagChannelMain = 0; + flagChannelResonant = 0; origin = 0; swapping = 0; - channel = 0; + indexRec = -1; arrDaughIndex.clear(); std::vector idxBhadMothers{}; auto arrayDaughters = std::array{candidate.prong0_as(), candidate.prong1_as(), candidate.prong2_as()}; @@ -936,148 +1063,250 @@ struct HfCandidateCreator3ProngExpressions { } } if (fromBkg) { - rowMcMatchRec(flag, origin, swapping, channel, -1.f, 0, 0, 0); + rowMcMatchRec(flagChannelMain, origin, swapping, flagChannelResonant, -1.f, 0, 0, 0); continue; } } - // D± → π± K∓ π± - if (flag == 0) { - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2); - } - if (indexRec > -1) { - flag = sign * DecayChannelMain::DplusToPiKPi; - } - } + if (matchCorrelatedBackground) { + indexRec = -1; // Index of the matched reconstructed candidate + constexpr int DepthMainMax = 2; // Depth for final state matching + constexpr int DepthResoMax = 1; // Depth for resonant decay matching - // Ds± → K± K∓ π± and D± → K± K∓ π± - if (flag == 0) { - bool isDplus = false; - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + for (const auto& pdgMother : pdgMothersCorrelBkg.value) { + int depthMainMax = DepthMainMax; + if (pdgMother == Pdg::kDStar) { + depthMainMax = DepthMainMax + 1; // D0 resonant decays are active + } + auto finalStates = getDecayChannelsMain(pdgMother); + for (const auto& [channelMain, finalState] : finalStates) { + std::array arrPdgDaughtersMain3Prongs = std::array{finalState[0], finalState[1], finalState[2]}; + if (finalState.size() > 3) { // o2-linter: disable=magic-number (partially reconstructed decays with 4 or 5 final state particles) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax); + } + + if (indexRec > -1) { + auto motherParticle = mcParticles.rawIteratorAt(indexRec); + if (finalState.size() == 4) { // o2-linter: disable=magic-number (Check if the final state has 4 particles) + std::array arrPdgDaughtersMain4Prongs = std::array{finalState[0], finalState[1], finalState[2], finalState[3]}; + flipPdgSign(motherParticle.pdgCode(), +kPi0, arrPdgDaughtersMain4Prongs); + if (!RecoDecay::isMatchedMCGen(mcParticles, motherParticle, pdgMother, arrPdgDaughtersMain4Prongs, true, &sign, depthMainMax)) { + indexRec = -1; // Reset indexRec if the generated decay does not match the reconstructed one is not matched + } + } else if (finalState.size() == 5) { // o2-linter: disable=magic-number (Check if the final state has 5 particles) + std::array arrPdgDaughtersMain5Prongs = std::array{finalState[0], finalState[1], finalState[2], finalState[3], finalState[4]}; + flipPdgSign(motherParticle.pdgCode(), +kPi0, arrPdgDaughtersMain5Prongs); + if (!RecoDecay::isMatchedMCGen(mcParticles, motherParticle, pdgMother, arrPdgDaughtersMain5Prongs, true, &sign, depthMainMax)) { + indexRec = -1; // Reset indexRec if the generated decay does not match the reconstructed one is not matched + } + } + } + } else if (finalState.size() == 3) { // o2-linter: disable=magic-number(fully reconstructed 3-prong decays) + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax); + } + } else { + LOG(fatal) << "Final state size not supported: " << finalState.size(); + return; + } + if (indexRec > -1) { + flagChannelMain = sign * channelMain; + + /// swapping for D+, Ds->Kpipi and Lc->pKpi + if (std::abs(flagChannelMain) == DecayChannelMain::DplusToPiKK || std::abs(flagChannelMain) == DecayChannelMain::DsToPiKK || std::abs(flagChannelMain) == DecayChannelMain::LcToPKPi) { + if (arrayDaughters[0].has_mcParticle()) { + swapping = static_cast(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + } + } + + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + if (pdgMother == Pdg::kDStar) { + std::vector arrResoDaughIndexDstar = {}; + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrResoDaughIndexDstar, std::array{0}, DepthResoMax); + for (size_t iDaug = 0; iDaug < arrResoDaughIndexDstar.size(); iDaug++) { + auto daughDstar = mcParticles.rawIteratorAt(arrResoDaughIndexDstar[iDaug]); + if (std::abs(daughDstar.pdgCode()) == Pdg::kD0 || std::abs(daughDstar.pdgCode()) == Pdg::kDPlus) { + RecoDecay::getDaughters(daughDstar, &arrResoDaughIndex, std::array{0}, DepthResoMax); + break; + } + } + } else { + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrResoDaughIndex, std::array{0}, DepthResoMax); + } + std::array arrPdgDaughters = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < NDaughtersResonant; ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPdgDaughters[iProng] = daughI.pdgCode(); + } + flagChannelResonant = getDecayChannelResonant(pdgMother, arrPdgDaughters); + } + break; // Exit loop if a match is found + } + } + if (indexRec > -1) { + break; // Exit loop if a match is found + } } - if (indexRec == -1) { - isDplus = true; + } else { + // D± → π± K∓ π± + if (flagChannelMain == 0) { + auto arrPdgDaughtersDplusToPiKPi{std::array{+kPiPlus, -kKPlus, +kPiPlus}}; if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDplusToPiKPi, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDplusToPiKPi, true, &sign, 2, &nKinkedTracks); } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDplusToPiKPi, true, &sign, 2, nullptr, &nInteractionsWithMaterial); } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2); + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDplusToPiKPi, true, &sign, 2); + } + if (indexRec > -1) { + flagChannelMain = sign * DecayChannelMain::DplusToPiKPi; } } - if (indexRec > -1) { - flag = sign * (isDplus ? DecayChannelMain::DplusToPiKK : DecayChannelMain::DsToPiKK); - if (arrayDaughters[0].has_mcParticle()) { - swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + + // Ds± → K± K∓ π± and D± → K± K∓ π± + if (flagChannelMain == 0) { + auto arrPdgDaughtersDToPiKK{std::array{+kKPlus, -kKPlus, +kPiPlus}}; + bool isDplus = false; + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, arrPdgDaughtersDToPiKK, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, arrPdgDaughtersDToPiKK, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, arrPdgDaughtersDToPiKK, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDS, arrPdgDaughtersDToPiKK, true, &sign, 2); } - RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { - auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); - arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + if (indexRec == -1) { + isDplus = true; + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDToPiKK, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDToPiKK, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDToPiKK, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDPlus, arrPdgDaughtersDToPiKK, true, &sign, 2); } - if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? DecayChannelResonant::DplusToPhiPi : DecayChannelResonant::DsToPhiPi; - } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? DecayChannelResonant::DplusToKstar0K : DecayChannelResonant::DsToKstar0K; + } + if (indexRec > -1) { + flagChannelMain = sign * (isDplus ? DecayChannelMain::DplusToPiKK : DecayChannelMain::DsToPiKK); + if (arrayDaughters[0].has_mcParticle()) { + swapping = static_cast(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + } + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPdgDaugResonant[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPdgDaugResonant[0] == arrPdgDaugResonantDToPhiPi[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToPhiPi[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantDToPhiPi[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToPhiPi[0])) { + flagChannelResonant = isDplus ? DecayChannelResonant::DplusToPhiPi : DecayChannelResonant::DsToPhiPi; + } else if ((arrPdgDaugResonant[0] == arrPdgDaugResonantDToKstar0K[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToKstar0K[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantDToKstar0K[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToKstar0K[0])) { + flagChannelResonant = isDplus ? DecayChannelResonant::DplusToKstar0K : DecayChannelResonant::DsToKstar0K; + } } } } - } - - // D* → D0π → Kππ - if (flag == 0) { - if (matchKinkedDecayTopology) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2, &nKinkedTracks); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2); - } - if (indexRec > -1) { - flag = sign * DecayChannelMain::DstarToPiKPi; - channel = 1; - } - } - // Λc± → p± K∓ π± - if (flag == 0) { - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); + // D* → D0 π → K π π + if (flagChannelMain == 0) { + auto arrPdgDaughtersDstarToPiKPi{std::array{+kPiPlus, +kPiPlus, -kKPlus}}; + if (matchKinkedDecayTopology) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, arrPdgDaughtersDstarToPiKPi, true, &sign, 2, &nKinkedTracks); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kDStar, arrPdgDaughtersDstarToPiKPi, true, &sign, 2); + } + if (indexRec > -1) { + flagChannelMain = sign * DecayChannelMain::DstarToPiKPi; + flagChannelResonant = 0; + } } - if (indexRec > -1) { - flag = sign * DecayChannelMain::LcToPKPi; - // Flagging the different Λc± → p± K∓ π± decay channels - if (arrayDaughters[0].has_mcParticle()) { - swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + // Λc± → p± K∓ π± + if (flagChannelMain == 0) { + auto arrPdgDaughtersLcToPKPi{std::array{+kProton, -kKPlus, +kPiPlus}}; + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, arrPdgDaughtersLcToPKPi, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, arrPdgDaughtersLcToPKPi, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, arrPdgDaughtersLcToPKPi, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kLambdaCPlus, arrPdgDaughtersLcToPKPi, true, &sign, 2); } - RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { - auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); - arrPDGDaugh[iProng] = std::abs(daughI.pdgCode()); + if (indexRec > -1) { + flagChannelMain = sign * DecayChannelMain::LcToPKPi; + + // Flagging the different Λc± → p± K∓ π± decay channels + if (arrayDaughters[0].has_mcParticle()) { + swapping = static_cast(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); } - if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { - channel = 1; - } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { - channel = 2; - } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { - channel = 3; + RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRec), &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPdgDaugResonant[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPdgDaugResonant[0] == arrPdgDaugResonantLcToPKstar0[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToPKstar0[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantLcToPKstar0[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToPKstar0[0])) { + flagChannelResonant = DecayChannelResonant::LcToPKstar0; + } else if ((arrPdgDaugResonant[0] == arrPdgDaugResonantLcToDeltaplusplusK[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToDeltaplusplusK[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantLcToDeltaplusplusK[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToDeltaplusplusK[0])) { + flagChannelResonant = DecayChannelResonant::LcToDeltaplusplusK; + } else if ((arrPdgDaugResonant[0] == arrPdgDaugResonantLcToL1520Pi[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToL1520Pi[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantLcToL1520Pi[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToL1520Pi[0])) { + flagChannelResonant = DecayChannelResonant::LcToL1520Pi; + } } } } - } - // Ξc± → p± K∓ π± - if (flag == 0) { - if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); - } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, &nKinkedTracks); - } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2, nullptr, &nInteractionsWithMaterial); - } else { - indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2); - } - if (indexRec > -1) { - flag = sign * DecayChannelMain::XicToPKPi; - if (arrayDaughters[0].has_mcParticle()) { - swapping = int8_t(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + // Ξc± → p± K∓ π± + if (flagChannelMain == 0) { + auto arrPdgDaughtersXicToPKPi{std::array{+kProton, -kKPlus, +kPiPlus}}; + if (matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, arrPdgDaughtersXicToPKPi, true, &sign, 2, &nKinkedTracks, &nInteractionsWithMaterial); + } else if (matchKinkedDecayTopology && !matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, arrPdgDaughtersXicToPKPi, true, &sign, 2, &nKinkedTracks); + } else if (!matchKinkedDecayTopology && matchInteractionsWithMaterial) { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, arrPdgDaughtersXicToPKPi, true, &sign, 2, nullptr, &nInteractionsWithMaterial); + } else { + indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughters, Pdg::kXiCPlus, arrPdgDaughtersXicToPKPi, true, &sign, 2); + } + if (indexRec > -1) { + flagChannelMain = sign * DecayChannelMain::XicToPKPi; + flagChannelResonant = 0; // TODO + if (arrayDaughters[0].has_mcParticle()) { + swapping = static_cast(std::abs(arrayDaughters[0].mcParticle().pdgCode()) == kPiPlus); + } } } } // Check whether the particle is non-prompt (from a b quark). - if (flag != 0) { + if (flagChannelMain != 0) { auto particle = mcParticles.rawIteratorAt(indexRec); origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } if (origin == RecoDecay::OriginType::NonPrompt) { auto bHadMother = mcParticles.rawIteratorAt(idxBhadMothers[0]); - rowMcMatchRec(flag, origin, swapping, channel, bHadMother.pt(), bHadMother.pdgCode(), nKinkedTracks, nInteractionsWithMaterial); + rowMcMatchRec(flagChannelMain, origin, swapping, flagChannelResonant, bHadMother.pt(), bHadMother.pdgCode(), nKinkedTracks, nInteractionsWithMaterial); } else { - rowMcMatchRec(flag, origin, swapping, channel, -1.f, 0, nKinkedTracks, nInteractionsWithMaterial); + rowMcMatchRec(flagChannelMain, origin, swapping, flagChannelResonant, -1.f, 0, nKinkedTracks, nInteractionsWithMaterial); } } @@ -1087,7 +1316,7 @@ struct HfCandidateCreator3ProngExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); @@ -1108,7 +1337,7 @@ struct HfCandidateCreator3ProngExpressions { } continue; } - hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground); + hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen, rejectBackground, matchCorrelatedBackground ? pdgMothersCorrelBkg : std::vector{}); } } diff --git a/PWGHF/TableProducer/candidateCreatorB0.cxx b/PWGHF/TableProducer/candidateCreatorB0.cxx index b60e5e63a72..a2751e9f3eb 100644 --- a/PWGHF/TableProducer/candidateCreatorB0.cxx +++ b/PWGHF/TableProducer/candidateCreatorB0.cxx @@ -15,20 +15,7 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -37,6 +24,41 @@ #include "PWGHF/Utils/utilsMcGen.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#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 +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::aod; @@ -44,6 +66,7 @@ using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::hf_trkcandsel; +using namespace o2::hf_decay::hf_cand_beauty; /// Reconstruction of B0 candidates struct HfCandidateCreatorB0 { @@ -382,13 +405,14 @@ struct HfCandidateCreatorB0Expressions { int indexRec = -1; int8_t sign = 0; - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelReso = 0; int8_t origin = 0; int8_t debug = 0; // Match reconstructed candidates. for (const auto& candidate : candsB0) { - flag = 0; + flagChannelMain = 0; origin = 0; debug = 0; auto candD = candidate.prong0(); @@ -406,7 +430,7 @@ struct HfCandidateCreatorB0Expressions { // D- → π- K+ π- indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersD, Pdg::kDMinus, std::array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign, 2); if (indexRec > -1) { - flag = sign * BIT(hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); + flagChannelMain = sign * DecayChannelMain::B0ToDminusPi; } else { debug = 1; LOGF(debug, "WARNING: B0 in decays in the expected final state but the condition on the intermediate state is not fulfilled"); @@ -414,20 +438,20 @@ struct HfCandidateCreatorB0Expressions { } // B0 → Ds- π+ → (K- K+ π-) π+ - if (!flag) { + if (!flagChannelMain) { indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersB0, Pdg::kB0, std::array{-kKPlus, +kKPlus, -kPiPlus, +kPiPlus}, true, &sign, 3); if (indexRec > -1) { // Ds- → K- K+ π- indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersD, -Pdg::kDS, std::array{-kKPlus, +kKPlus, -kPiPlus}, true, &sign, 2); if (indexRec > -1) { - flag = sign * BIT(hf_cand_b0::DecayTypeMc::B0ToDsPiToKKPiPi); + flagChannelMain = sign * DecayChannelMain::B0ToDsPi; } } } // Partly reconstructed decays, i.e. the 4 prongs have a common b-hadron ancestor // convention: final state particles are prong0,1,2,3 - if (!flag) { + if (!flagChannelMain) { auto particleProng0 = arrayDaughtersB0[0].mcParticle(); auto particleProng1 = arrayDaughtersB0[1].mcParticle(); auto particleProng2 = arrayDaughtersB0[2].mcParticle(); @@ -442,16 +466,14 @@ struct HfCandidateCreatorB0Expressions { int index3Mother = RecoDecay::getMother(mcParticles, particleProng3, bHadronMotherHypo, true); // look for common b-hadron ancestor - if (index0Mother > -1 && index1Mother > -1 && index2Mother > -1 && index3Mother > -1) { - if (index0Mother == index1Mother && index1Mother == index2Mother && index2Mother == index3Mother) { - flag = BIT(hf_cand_b0::DecayTypeMc::PartlyRecoDecay); - break; - } + if (index0Mother > -1 && index0Mother == index1Mother && index1Mother == index2Mother && index2Mother == index3Mother) { + flagChannelMain = hf_cand_b0::DecayTypeMc::PartlyRecoDecay; // FIXME + break; } } } - rowMcMatchRec(flag, origin, debug); + rowMcMatchRec(flagChannelMain, flagChannelReso, origin, debug); } // rec hf_mc_gen::fillMcMatchGenB0(mcParticles, rowMcMatchGen); // gen diff --git a/PWGHF/TableProducer/candidateCreatorBplus.cxx b/PWGHF/TableProducer/candidateCreatorBplus.cxx index fea1a2778b4..f3cc0baa11e 100644 --- a/PWGHF/TableProducer/candidateCreatorBplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorBplus.cxx @@ -18,20 +18,7 @@ /// \author Deepa Thomas , UT Austin /// \author Antonio Palasciano , Università degli Studi di Bari & INFN, Sezione di Bari -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -40,6 +27,43 @@ #include "PWGHF/Utils/utilsMcGen.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#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 +#include +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::hf_trkcandsel; @@ -47,6 +71,7 @@ using namespace o2::aod; using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::hf_decay::hf_cand_beauty; /// Reconstruction of B± → D0bar(D0) π± → (K± π∓) π± struct HfCandidateCreatorBplus { @@ -365,14 +390,16 @@ struct HfCandidateCreatorBplusExpressions { int indexRec = -1, indexRecD0 = -1; int8_t signB = 0, signD0 = 0; - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelReso = 0; int8_t origin = 0; // Match reconstructed candidates. // Spawned table can be used directly for (const auto& candidate : candsBplus) { - flag = 0; + flagChannelMain = 0; + flagChannelReso = 0; origin = 0; auto candDaughterD0 = candidate.prong0(); auto arrayDaughtersD0 = std::array{candDaughterD0.prong0_as(), candDaughterD0.prong1_as()}; @@ -383,9 +410,9 @@ struct HfCandidateCreatorBplusExpressions { indexRecD0 = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersD0, -Pdg::kD0, std::array{+kKPlus, -kPiPlus}, true, &signD0, 1); if (indexRecD0 > -1 && indexRec > -1) { - flag = signB * (1 << hf_cand_bplus::DecayType::BplusToD0Pi); + flagChannelMain = signB * DecayChannelMain::BplusToD0Pi; } - rowMcMatchRec(flag, origin); + rowMcMatchRec(flagChannelMain, flagChannelReso, origin); } hf_mc_gen::fillMcMatchGenBplus(mcParticles, rowMcMatchGen); // gen } // process diff --git a/PWGHF/TableProducer/candidateCreatorBs.cxx b/PWGHF/TableProducer/candidateCreatorBs.cxx index 4f8128e474b..0bf80217b41 100644 --- a/PWGHF/TableProducer/candidateCreatorBs.cxx +++ b/PWGHF/TableProducer/candidateCreatorBs.cxx @@ -15,20 +15,7 @@ /// /// \author Phil Stahlhut -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -36,6 +23,41 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#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 +#include +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::aod; @@ -43,6 +65,7 @@ using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::hf_trkcandsel; +using namespace o2::hf_decay::hf_cand_beauty; /// Reconstruction of Bs candidates struct HfCandidateCreatorBs { @@ -368,14 +391,16 @@ struct HfCandidateCreatorBsExpressions { { int indexRec = -1; int8_t sign = 0; - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelReso = 0; std::vector arrDaughDsIndex; std::array arrPDGDaughDs; std::array arrPDGResonantDsPhiPi = {Pdg::kPhi, kPiPlus}; // Ds± → Phi π± // Match reconstructed candidates. for (const auto& candidate : candsBs) { - flag = 0; + flagChannelMain = 0; + flagChannelReso = 0; arrDaughDsIndex.clear(); auto candDs = candidate.prong0(); auto arrayDaughtersBs = std::array{candDs.prong0_as(), @@ -399,13 +424,13 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); + flagChannelMain = sign * DecayChannelMain::BsToDsPi; } } } } - if (!flag) { + if (!flagChannelMain) { // Checking B0(bar) → Ds± π∓ → (K- K+ π±) π∓ indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersBs, Pdg::kB0, std::array{-kKPlus, +kKPlus, +kPiPlus, -kPiPlus}, true, &sign, 3); if (indexRec > -1) { @@ -419,7 +444,7 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[iProng] = std::abs(daughI.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); + flagChannelMain = sign * DecayChannelMain::B0ToDsPi; } } } @@ -428,7 +453,7 @@ struct HfCandidateCreatorBsExpressions { // Partly reconstructed decays, i.e. the 4 prongs have a common b-hadron ancestor // convention: final state particles are prong0,1,2,3 - if (!flag) { + if (!flagChannelMain) { auto particleProng0 = arrayDaughtersBs[0].mcParticle(); auto particleProng1 = arrayDaughtersBs[1].mcParticle(); auto particleProng2 = arrayDaughtersBs[2].mcParticle(); @@ -443,21 +468,20 @@ struct HfCandidateCreatorBsExpressions { int index3Mother = RecoDecay::getMother(mcParticles, particleProng3, bHadronMotherHypo, true); // look for common b-hadron ancestor - if (index0Mother > -1 && index1Mother > -1 && index2Mother > -1 && index3Mother > -1) { - if (index0Mother == index1Mother && index1Mother == index2Mother && index2Mother == index3Mother) { - flag = BIT(hf_cand_bs::DecayTypeMc::PartlyRecoDecay); - break; - } + if (index0Mother > -1 && index0Mother == index1Mother && index1Mother == index2Mother && index2Mother == index3Mother) { + flagChannelMain = hf_cand_bs::DecayTypeMc::PartlyRecoDecay; // FIXME + break; } } } - rowMcMatchRec(flag); + rowMcMatchRec(flagChannelMain, flagChannelReso); } // rec // Match generated particles. for (const auto& particle : mcParticles) { - flag = 0; + flagChannelMain = 0; + flagChannelReso = 0; arrDaughDsIndex.clear(); // Checking Bs0(bar) → Ds∓ π± → (K- K+ π∓) π± @@ -472,13 +496,13 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); + flagChannelMain = sign * DecayChannelMain::BsToDsPi; } } } } - if (!flag) { + if (!flagChannelMain) { // Checking B0(bar) → Ds± π∓ → (K- K+ π±) π∓ if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kB0, std::array{+Pdg::kDS, -kPiPlus}, true)) { // Checking Ds± → K- K+ π± @@ -491,14 +515,14 @@ struct HfCandidateCreatorBsExpressions { arrPDGDaughDs[jProng] = std::abs(daughJ.pdgCode()); } if ((arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[0] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[1]) || (arrPDGDaughDs[0] == arrPDGResonantDsPhiPi[1] && arrPDGDaughDs[1] == arrPDGResonantDsPhiPi[0])) { - flag = sign * BIT(hf_cand_bs::DecayTypeMc::B0ToDsPiToPhiPiPiToKKPiPi); + flagChannelMain = sign * DecayChannelMain::B0ToDsPi; } } } } } - rowMcMatchGen(flag); + rowMcMatchGen(flagChannelMain, flagChannelReso); } // gen } // processMc PROCESS_SWITCH(HfCandidateCreatorBsExpressions, processMc, "Process MC", false); diff --git a/PWGHF/TableProducer/candidateCreatorCascade.cxx b/PWGHF/TableProducer/candidateCreatorCascade.cxx index 04faa873da7..20e16710463 100644 --- a/PWGHF/TableProducer/candidateCreatorCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorCascade.cxx @@ -15,35 +15,50 @@ /// \author Chiara Zampolli, , CERN /// Paul Buehler, , Vienna -#include -#include -#include - -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" - -#include "Common/Core/trackUtilities.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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 +#include +#include +#include +#include +#include +#include using namespace o2; -using namespace o2::analysis; using namespace o2::hf_evsel; using namespace o2::hf_trkcandsel; using namespace o2::hf_centrality; @@ -549,7 +564,7 @@ struct HfCandidateCreatorCascadeMc { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/TableProducer/candidateCreatorDstar.cxx b/PWGHF/TableProducer/candidateCreatorDstar.cxx index f25a09dbbb3..9036717104b 100644 --- a/PWGHF/TableProducer/candidateCreatorDstar.cxx +++ b/PWGHF/TableProducer/candidateCreatorDstar.cxx @@ -16,31 +16,49 @@ /// \author Deependra Sharma , IITB /// \author Fabrizio Grosa , CERN -// C++ -#include -#include -#include -// ROOT -#include -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -// O2Physics -#include "Common/Core/trackUtilities.h" -// PWGLF -#include "PWGLF/DataModel/mcCentrality.h" -// PWGHF #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" #include "PWGHF/Utils/utilsEvSelHf.h" #include "PWGHF/Utils/utilsPid.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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 +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::hf_evsel; @@ -714,7 +732,7 @@ struct HfCandidateCreatorDstarExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/TableProducer/candidateCreatorLb.cxx b/PWGHF/TableProducer/candidateCreatorLb.cxx index 49928fd70ad..9d15a7e3e1d 100644 --- a/PWGHF/TableProducer/candidateCreatorLb.cxx +++ b/PWGHF/TableProducer/candidateCreatorLb.cxx @@ -15,23 +15,40 @@ /// /// \author Panos Christakoglou , Nikhef -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsTrkCandHf.h" +#include "Common/Core/RecoDecay.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 + using namespace o2; using namespace o2::analysis; using namespace o2::aod; @@ -39,6 +56,7 @@ using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::hf_trkcandsel; +using namespace o2::hf_decay::hf_cand_beauty; /// Reconstruction of Λb candidates struct HfCandidateCreatorLb { @@ -260,13 +278,15 @@ struct HfCandidateCreatorLbExpressions { { int indexRec = -1; int8_t sign = 0; - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelReso = 0; int8_t origin = 0; int8_t debug = 0; // Match reconstructed candidates. for (const auto& candidate : candsLb) { - flag = 0; + flagChannelMain = 0; + flagChannelReso = 0; origin = 0; debug = 0; auto lcCand = candidate.prong0(); @@ -283,28 +303,29 @@ struct HfCandidateCreatorLbExpressions { // Λb → Λc+ π- indexRec = RecoDecay::getMatchedMCRec(mcParticles, arrayDaughtersLc, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 1); if (indexRec > -1) { - flag = 1 << hf_cand_lb::DecayType::LbToLcPi; + flagChannelMain = sign * DecayChannelMain::LbToLcPi; } else { debug = 1; LOGF(info, "WARNING: Λb in decays in the expected final state but the condition on the intermediate state is not fulfilled"); } } - rowMcMatchRec(flag, origin, debug); + rowMcMatchRec(flagChannelMain, flagChannelReso, origin, debug); } // Match generated particles. for (const auto& particle : mcParticles) { - flag = 0; + flagChannelMain = 0; + flagChannelReso = 0; origin = 0; // Λb → Λc+ π- if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaB0, std::array{static_cast(Pdg::kLambdaCPlus), -kPiPlus}, true)) { // Λc+ → p K- π+ auto candLcMc = mcParticles.rawIteratorAt(particle.daughtersIds().front()); if (RecoDecay::isMatchedMCGen(mcParticles, candLcMc, static_cast(Pdg::kLambdaCPlus), std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign)) { - flag = sign * (1 << hf_cand_lb::DecayType::LbToLcPi); + flagChannelMain = sign * DecayChannelMain::LbToLcPi; } } - rowMcMatchGen(flag, origin); + rowMcMatchGen(flagChannelMain, flagChannelReso, origin); } } PROCESS_SWITCH(HfCandidateCreatorLbExpressions, processMc, "Process MC", false); diff --git a/PWGHF/TableProducer/candidateCreatorMcGen.cxx b/PWGHF/TableProducer/candidateCreatorMcGen.cxx index 3c5f7a2c3c1..1c923a5b6e3 100644 --- a/PWGHF/TableProducer/candidateCreatorMcGen.cxx +++ b/PWGHF/TableProducer/candidateCreatorMcGen.cxx @@ -14,23 +14,23 @@ /// /// \author Nima Zardoshti, nima.zardoshti@cern.ch, CERN -#include -#include -#include - -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/Utils/utilsMcGen.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::framework; +using namespace o2::constants::physics; /// Reconstruction of heavy-flavour 2-prong decay candidates struct HfCandidateCreatorMcGen { @@ -41,6 +41,8 @@ struct HfCandidateCreatorMcGen { Produces rowMcMatchGenB0; Configurable fill2Prong{"fill2Prong", false, "fill table for 2 prong candidates"}; Configurable fill3Prong{"fill3Prong", false, "fill table for 3 prong candidates"}; + Configurable matchCorrelatedBackground{"matchCorrelatedBackground", false, "Match correlated background candidates"}; + Configurable> pdgMothersCorrelBkg{"pdgMothersCorrelBkg", {Pdg::kDPlus, Pdg::kDS, Pdg::kDStar, Pdg::kLambdaCPlus, Pdg::kXiCPlus}, "PDG codes of the mother particles of correlated background candidates"}; Configurable fillBplus{"fillBplus", false, "fill table for for B+ candidates"}; Configurable fillB0{"fillB0", false, "fill table for B0 candidates"}; Configurable rejectBackground2Prong{"rejectBackground2Prong", false, "Reject particles from PbPb background for 2 prong candidates"}; @@ -55,10 +57,10 @@ struct HfCandidateCreatorMcGen { for (const auto& mcCollision : mcCollisions) { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); if (fill2Prong) { - hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen2Prong, rejectBackground2Prong); + hf_mc_gen::fillMcMatchGen2Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen2Prong, rejectBackground2Prong, matchCorrelatedBackground); } if (fill3Prong) { - hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen3Prong, rejectBackground3Prong); + hf_mc_gen::fillMcMatchGen3Prong(mcParticles, mcParticlesPerMcColl, rowMcMatchGen3Prong, rejectBackground3Prong, matchCorrelatedBackground ? pdgMothersCorrelBkg : std::vector{}); } } if (fillBplus) { diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx index c8dbbf04b2b..9a59c28cf9c 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplus.cxx @@ -15,26 +15,8 @@ /// /// \author Mattia Faggin , University and INFN PADOVA -#include -#include -#include - -#include "CCDB/BasicCCDBManager.h" // for dca recalculation -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" // for dca recalculation -#include "DataFormatsParameters/GRPObject.h" // for dca recalculation -#include "DetectorsBase/GeometryManager.h" // for dca recalculation -#include "DetectorsBase/Propagator.h" // for dca recalculation -#include "DetectorsVertexing/PVertexer.h" // for dca recalculation -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/TrackSelectionDefaults.h" - +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" @@ -42,6 +24,44 @@ #include "PWGHF/Utils/utilsBfieldCCDB.h" // for dca recalculation #include "PWGHF/Utils/utilsEvSelHf.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/EventSelection.h" + +#include // for dca recalculation +#include +#include +#include // for dca recalculation +#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::constants::physics; @@ -172,7 +192,7 @@ struct HfCandidateCreatorSigmac0plusplus { /// @param candidates are 3-prong candidates satisfying the analysis selections for Λc+ → pK-π+ (and charge conj.) /// @param tracks are the tracks (with dcaXY, dcaZ information) → soft-pion candidate tracks template - void makeSoftPiLcPair(TRK const& trackSoftPi, CAND const& candidatesThisColl, aod::TracksWDcaExtra const&) + void makeSoftPiLcPair(const std::array softPiDca, TRK const& trackSoftPi, CAND const& candidatesThisColl, aod::TracksWDcaExtra const&) { /// loop over Λc+ → pK-π+ (and charge conj.) candidates @@ -253,7 +273,8 @@ struct HfCandidateCreatorSigmac0plusplus { candLc.hfflag(), /* Σc0,++ specific columns */ chargeSigmac, - statusSpreadMinvPKPiFromPDG, statusSpreadMinvPiKPFromPDG); + statusSpreadMinvPKPiFromPDG, statusSpreadMinvPiKPFromPDG, + softPiDca[0], softPiDca[1]); } /// end loop over Λc+ → pK-π+ (and charge conj.) candidates } /// end makeSoftPiLcPair @@ -278,6 +299,7 @@ struct HfCandidateCreatorSigmac0plusplus { if (!softPiCuts.IsSelected(trackSoftPi)) { return; } + std::array softPiDca = {-999.f, -999.f}; if constexpr (withTimeAssoc) { /// dcaXY, dcaZ selections /// To be done separately from the others, because for reassigned tracks the dca must be recalculated @@ -285,9 +307,8 @@ struct HfCandidateCreatorSigmac0plusplus { if (trackSoftPi.collisionId() == thisCollId) { /// this is a track originally assigned to the current collision /// therefore, the dcaXY, dcaZ are those already calculated in the track-propagation workflow - if (std::abs(trackSoftPi.dcaXY()) > softPiDcaXYMax || std::abs(trackSoftPi.dcaZ()) > softPiDcaZMax) { - return; - } + softPiDca[0] = trackSoftPi.dcaXY(); + softPiDca[1] = trackSoftPi.dcaZ(); } else { /// this is a reassigned track /// therefore we need to calculate the dcaXY, dcaZ with respect to this new primary vertex @@ -296,17 +317,19 @@ struct HfCandidateCreatorSigmac0plusplus { auto trackParSoftPi = getTrackPar(trackSoftPi); std::array dcaInfo{-999., -999.}; o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParSoftPi, 2.f, noMatCorr, &dcaInfo); - if (std::abs(dcaInfo[0]) > softPiDcaXYMax || std::abs(dcaInfo[1]) > softPiDcaZMax) { - return; - } + softPiDca[0] = dcaInfo[0]; + softPiDca[1] = dcaInfo[1]; } } else { /// this is a track originally assigned to the current collision /// therefore, the dcaXY, dcaZ are those already calculated in the track-propagation workflow /// No need to consider the time-reassociated tracks, since withTimeAssoc == false here - if (std::abs(trackSoftPi.dcaXY()) > softPiDcaXYMax || std::abs(trackSoftPi.dcaZ()) > softPiDcaZMax) { - return; - } + softPiDca[0] = trackSoftPi.dcaXY(); + softPiDca[1] = trackSoftPi.dcaZ(); + } + if (std::abs(softPiDca[0]) > softPiDcaXYMax || std::abs(softPiDca[1]) > softPiDcaZMax) { + /// soft-pion dca too large, reject the candidate + return; } histos.fill(HIST("hCounter"), 3); @@ -314,10 +337,10 @@ struct HfCandidateCreatorSigmac0plusplus { if constexpr (withTimeAssoc) { /// need to group candidates manually auto candidatesThisColl = candidates.sliceBy(hf3ProngPerCollision, thisCollId); - makeSoftPiLcPair(trackSoftPi, candidatesThisColl, tracks); + makeSoftPiLcPair(softPiDca, trackSoftPi, candidatesThisColl, tracks); } else { /// tracks and candidates already grouped by collision at the level of process function - makeSoftPiLcPair(trackSoftPi, candidates, tracks); + makeSoftPiLcPair(softPiDca, trackSoftPi, candidates, tracks); } } /// end createSigmaC @@ -394,7 +417,7 @@ struct HfCandidateSigmac0plusplusMc { using BCsInfo = soa::Join; using LambdacMc = soa::Join; - // using LambdacMcGen = soa::Join; + using McParticlesLcGenMatch = soa::Join; // including response of particle matching to MC from candidate-creator-3-prong using McCollisionsNoCents = soa::Join; PresliceUnsorted colPerMcCollision = aod::mccollisionlabel::mcCollisionId; @@ -443,9 +466,9 @@ struct HfCandidateSigmac0plusplusMc { /// @brief process function for MC matching of Σc0,++ → Λc+(→pK-π+) π- reconstructed candidates and counting of generated ones /// @param candidatesSigmac reconstructed Σc0,++ candidates /// @param mcParticles table of generated particles - void processMc(aod::McParticles const& mcParticles, + void processMc(McParticlesLcGenMatch const& mcParticles, aod::TracksWMc const& tracks, - LambdacMc const& candsLc /*, const LambdacMcGen&*/, + LambdacMc const& candsLc, McCollisionsNoCents const& collInfos, aod::McCollisions const&, BCsInfo const&) @@ -563,9 +586,8 @@ struct HfCandidateSigmac0plusplusMc { /// In case of need, readapt the code templetizing the function auto mcCollision = particle.mcCollision(); float centrality{-1.f}; - uint16_t rejectionMask{0}; const auto collSlice = collInfos.sliceBy(colPerMcCollision, mcCollision.globalIndex()); - rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + auto rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); hfEvSelMc.fillHistograms(mcCollision, rejectionMask, 0); if (rejectionMask != 0) { // at least one event selection not satisfied --> reject gen particles from this collision @@ -582,11 +604,11 @@ struct HfCandidateSigmac0plusplusMc { /// look for Σc0,++(2455) if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaC0, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { // generated Σc0(2455) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::Sc0ToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaC0); @@ -595,11 +617,11 @@ struct HfCandidateSigmac0plusplusMc { } } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaCPlusPlus, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { // generated Σc++(2455) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::ScplusplusToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaCPlusPlus); @@ -612,11 +634,11 @@ struct HfCandidateSigmac0plusplusMc { if (flag == 0) { if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaCStar0, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiMinus)}, true, &sign, 1)) { // generated Σc0(2520) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::ScStar0ToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaCStar0); @@ -625,11 +647,11 @@ struct HfCandidateSigmac0plusplusMc { } } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kSigmaCStarPlusPlus, std::array{static_cast(Pdg::kLambdaCPlus), static_cast(kPiPlus)}, true, &sign, 1)) { // generated Σc++(2520) - for (const auto& daughter : particle.daughters_as()) { + for (const auto& daughter : particle.daughters_as()) { // look for Λc+ daughter decaying in pK-π+ if (std::abs(daughter.pdgCode()) != Pdg::kLambdaCPlus) continue; - if (RecoDecay::isMatchedMCGen(mcParticles, daughter, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + if (std::abs(daughter.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { /// Λc+ daughter decaying in pK-π+ found! flag = sign * BIT(aod::hf_cand_sigmac::DecayType::ScStarPlusPlusToPKPiPi); particleAntiparticle = isParticleAntiparticle(particle, Pdg::kSigmaCStarPlusPlus); diff --git a/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx b/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx index ee784c35fae..71a61bec437 100644 --- a/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx +++ b/PWGHF/TableProducer/candidateCreatorSigmac0plusplusCascade.cxx @@ -15,21 +15,27 @@ /// \author Rutuparna Rath , INFN BOLOGNA and GSI Darmstadt /// In collaboration with Andrea Alici , INFN BOLOGNA -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelectionDefaults.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::constants::physics; diff --git a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx index 754272af541..9d7413d75d1 100644 --- a/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx +++ b/PWGHF/TableProducer/candidateCreatorXic0Omegac0.cxx @@ -21,52 +21,59 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include -#include -#include -#include - -/// includes KFParticle -#include "KFParticle.h" -#include "KFParticleBase.h" -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFVertex.h" - -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/V0.h" +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Tools/KFparticle/KFUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/mcCentrality.h" - -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.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::track; -using namespace o2::analysis; using namespace o2::aod; using namespace o2::aod::cascdata; using namespace o2::aod::v0data; @@ -92,6 +99,7 @@ struct HfCandidateCreatorXic0Omegac0 { Produces kfCandidateData; Produces kfCandidateXicData; Produces rowKfXic0Qa; + Produces kfCandidateOmegaKaData; Configurable propagateToPCA{"propagateToPCA", false, "create tracks version propagated to PCA"}; Configurable useAbsDCA{"useAbsDCA", true, "Minimise abs. distance rather than chi2"}; @@ -105,6 +113,10 @@ struct HfCandidateCreatorXic0Omegac0 { 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"}; + Configurable dcaXYToPVCascadeMax{"dcaXYToPVCascadeMax", 3.0, "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"}; // magnetic field setting from CCDB Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; @@ -118,6 +130,7 @@ struct HfCandidateCreatorXic0Omegac0 { Configurable lambdaMassWindow{"lambdaMassWindow", 0.0075, "Distance from Lambda mass"}; // cascade cuts Configurable massToleranceCascade{"massToleranceCascade", 0.01, "Invariant mass tolerance for cascade"}; + Configurable massToleranceCascadeRej{"massToleranceCascadeRej", 0.01, "Invariant mass tolerance for rejected Xi"}; // for KF particle operation Configurable kfConstructMethod{"kfConstructMethod", 2, "KF Construct Method"}; Configurable kfUseV0MassConstraint{"kfUseV0MassConstraint", false, "KF: use Lambda mass constraint"}; @@ -139,6 +152,7 @@ struct HfCandidateCreatorXic0Omegac0 { using MyV0Table = soa::Join; using MyLFTracksWCov = soa::Join; + using MyKfTracksIU = soa::Join; using MyKfTracks = soa::Join; using MyKfCascTable = soa::Join; using KFCascadesLinked = soa::Join; @@ -214,8 +228,6 @@ struct HfCandidateCreatorXic0Omegac0 { float cosPaXYCascToPv; float massV0; float massCasc; - float ptPiFromXic; - float ptXic; float rapXic; float massXic; float cosThetaStarPiFromXic; @@ -236,7 +248,6 @@ struct HfCandidateCreatorXic0Omegac0 { float ctV0; float ctCasc; float ctXic; - float ctOmegac; float chi2MassV0; float chi2MassCasc; float etaXic; @@ -729,7 +740,8 @@ struct HfCandidateCreatorXic0Omegac0 { template void runKfOmegac0CreatorWithKFParticle(Coll const&, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/, - MyKfTracks const&, + MyKfTracksIU const& tracksIU, + MyKfTracks const& tracks, MyKfCascTable const&, KFCascadesLinked const&, aod::HfCascLf2Prongs const& candidates, Hist& hInvMassCharmBaryon, @@ -760,8 +772,8 @@ struct HfCandidateCreatorXic0Omegac0 { df.setBz(magneticField); KFParticle::SetField(magneticField); // bachelor from Omegac0 - auto trackCharmBachelor = cand.prong0_as(); - + auto trackCharmBachelorId = cand.prong0Id(); + auto trackCharmBachelor = tracks.rawIteratorAt(trackCharmBachelorId); auto cascAodElement = cand.cascade_as(); hCascadesCounter->Fill(0); int v0index = cascAodElement.v0Id(); @@ -770,9 +782,12 @@ struct HfCandidateCreatorXic0Omegac0 { } auto casc = cascAodElement.kfCascData_as(); hCascadesCounter->Fill(1); - auto trackCascDauCharged = casc.bachelor_as(); // pion <- xi track - auto trackV0Dau0 = casc.posTrack_as(); // V0 positive daughter track - auto trackV0Dau1 = casc.negTrack_as(); // V0 negative daughter track + auto trackCascDauChargedId = casc.bachelorId(); + auto trackV0Dau0Id = casc.posTrackId(); + auto trackV0Dau1Id = casc.negTrackId(); + auto trackCascDauCharged = tracksIU.rawIteratorAt(trackCascDauChargedId); // pion <- xi track + auto trackV0Dau0 = tracksIU.rawIteratorAt(trackV0Dau0Id); // V0 positive daughter track + auto trackV0Dau1 = tracksIU.rawIteratorAt(trackV0Dau1Id); // V0 negative daughter track auto bachCharge = trackCascDauCharged.signed1Pt() > 0 ? +1 : -1; @@ -1206,7 +1221,8 @@ struct HfCandidateCreatorXic0Omegac0 { template void runKfXic0CreatorWithKFParticle(Coll const&, aod::BCsWithTimestamps const& /*bcWithTimeStamps*/, - MyKfTracks const&, + MyKfTracksIU const& tracksIU, + MyKfTracks const& tracks, MyKfCascTable const&, KFCascadesLinked const&, aod::HfCascLf2Prongs const& candidates, Hist& hInvMassCharmBaryon, @@ -1216,7 +1232,9 @@ struct HfCandidateCreatorXic0Omegac0 { { for (const auto& cand : candidates) { hCandidateCounter->Fill(1); - + if (!TESTBIT(cand.hfflag(), aod::hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi)) { + continue; + } auto collision = cand.collision_as(); float centrality{-1.f}; @@ -1238,8 +1256,8 @@ struct HfCandidateCreatorXic0Omegac0 { df.setBz(magneticField); KFParticle::SetField(magneticField); // bachelor from Xic0 - auto trackCharmBachelor = cand.prong0_as(); - + auto trackCharmBachelorId = cand.prong0Id(); + auto trackCharmBachelor = tracks.rawIteratorAt(trackCharmBachelorId); auto cascAodElement = cand.cascade_as(); hCascadesCounter->Fill(0); int v0index = cascAodElement.v0Id(); @@ -1248,9 +1266,12 @@ struct HfCandidateCreatorXic0Omegac0 { } auto casc = cascAodElement.kfCascData_as(); hCascadesCounter->Fill(1); - auto trackCascDauCharged = casc.bachelor_as(); // pion <- xi track - auto trackV0Dau0 = casc.posTrack_as(); // V0 positive daughter track - auto trackV0Dau1 = casc.negTrack_as(); // V0 negative daughter track + auto trackCascDauChargedId = casc.bachelorId(); + auto trackV0Dau0Id = casc.posTrackId(); + auto trackV0Dau1Id = casc.negTrackId(); + auto trackCascDauCharged = tracksIU.rawIteratorAt(trackCascDauChargedId); // pion <- xi track + auto trackV0Dau0 = tracksIU.rawIteratorAt(trackV0Dau0Id); // V0 positive daughter track + auto trackV0Dau1 = tracksIU.rawIteratorAt(trackV0Dau1Id); // V0 negative daughter track auto bachCharge = trackCascDauCharged.signed1Pt() > 0 ? +1 : -1; @@ -1443,16 +1464,13 @@ struct HfCandidateCreatorXic0Omegac0 { std::array vertexCasc = {kfXi.GetX(), kfXi.GetY(), kfXi.GetZ()}; std::array pVecCascBachelor = {kfBachPionToXi.GetPx(), kfBachPionToXi.GetPy(), kfBachPionToXi.GetPz()}; - auto primaryVertex = getPrimaryVertex(collision); std::array pvCoord = {collision.posX(), collision.posY(), collision.posZ()}; - std::array vertexCharmBaryonFromFitter = {0.0, 0.0, 0.0}; // This variable get from DCAfitter in default process, in KF process it is set as 0. std::array pVecCharmBachelorAsD; pVecCharmBachelorAsD[0] = kfCharmBachPionToXiC.GetPx(); pVecCharmBachelorAsD[1] = kfCharmBachPionToXiC.GetPy(); pVecCharmBachelorAsD[2] = kfCharmBachPionToXiC.GetPz(); std::array pVecCharmBaryon = {kfXiC0.GetPx(), kfXiC0.GetPy(), kfXiC0.GetPz()}; - std::array coordVtxCharmBaryon = {kfXiC0.GetX(), kfXiC0.GetY(), kfXiC0.GetZ()}; auto covVtxCharmBaryon = kfXiC0.CovarianceMatrix(); float covMatrixPV[6]; kfVertex.GetCovarianceMatrix(covMatrixPV); @@ -1460,38 +1478,17 @@ struct HfCandidateCreatorXic0Omegac0 { // impact parameters std::array impactParameterV0Dau0; std::array impactParameterV0Dau1; - std::array impactParameterKaFromCasc; + std::array impactParameterPiFromCasc; o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovV0Dau0, 2.f, matCorr, &impactParameterV0Dau0); o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, trackParCovV0Dau1, 2.f, matCorr, &impactParameterV0Dau1); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, xiDauChargedTrackParCov, 2.f, matCorr, &impactParameterKaFromCasc); + o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, xiDauChargedTrackParCov, 2.f, matCorr, &impactParameterPiFromCasc); float dcaxyV0Dau0 = impactParameterV0Dau0[0]; float dcaxyV0Dau1 = impactParameterV0Dau1[0]; - float dcaxyCascBachelor = impactParameterKaFromCasc[0]; - float dcazV0Dau0 = impactParameterV0Dau0[1]; - float dcazV0Dau1 = impactParameterV0Dau1[1]; - float dcazCascBachelor = impactParameterKaFromCasc[1]; + float dcaxyCascBachelor = impactParameterPiFromCasc[0]; // pseudorapidity float pseudorapCharmBachelor = kfCharmBachPionToXiC.GetEta(); - // impact parameters - o2::dataformats::DCA impactParameterCasc; - o2::dataformats::DCA impactParameterCharmBachelor; - o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackCasc, 2.f, matCorr, &impactParameterCasc); - o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVertex, trackParVarCharmBachelor, 2.f, matCorr, &impactParameterCharmBachelor); - float impactParBachFromCharmBaryonXY = impactParameterCharmBachelor.getY(); - float impactParBachFromCharmBaryonZ = impactParameterCharmBachelor.getZ(); - - // computing decay length and ctau - float decLenCharmBaryon = RecoDecay::distance(pvCoord, coordVtxCharmBaryon); - float decLenCascade = RecoDecay::distance(coordVtxCharmBaryon, vertexCasc); - float decLenV0 = RecoDecay::distance(vertexCasc, vertexV0); - - double phiCharmBaryon, thetaCharmBaryon; - getPointDirection(std::array{kfV0.GetX(), kfV0.GetY(), kfV0.GetZ()}, coordVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon); - auto errorDecayLengthCharmBaryon = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phiCharmBaryon, thetaCharmBaryon) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, thetaCharmBaryon)); - auto errorDecayLengthXYCharmBaryon = std::sqrt(getRotatedCovMatrixXX(covMatrixPV, phiCharmBaryon, 0.) + getRotatedCovMatrixXX(covVtxCharmBaryon, phiCharmBaryon, 0.)); - // fill test histograms hInvMassCharmBaryon->Fill(massXiC0); hCandidateCounter->Fill(3); @@ -1568,42 +1565,26 @@ struct HfCandidateCreatorXic0Omegac0 { kfXic0Candidate.massCasc = massCasc; kfXic0Candidate.massXic = massXiC0; - // KF pT - kfXic0Candidate.ptPiFromXic = kfCharmBachPionToXiC.GetPt(); - kfXic0Candidate.ptXic = kfXiC0.GetPt(); - // KF rapidity kfXic0Candidate.rapXic = kfXiC0.GetRapidity(); // KF cosThetaStar - kfXic0Candidate.cosThetaStarPiFromXic = cosThetaStarFromKF(0, 4332, 211, 3312, kfCharmBachPionToXiC, kfXiToXiC); + kfXic0Candidate.cosThetaStarPiFromXic = cosThetaStarFromKF(0, 4132, 211, 3312, kfCharmBachPionToXiC, kfXiToXiC); // KF ct - kfXic0Candidate.ctV0 = kfV0.GetLifeTime(); - kfXic0Candidate.ctCasc = kfXi.GetLifeTime(); - kfXic0Candidate.ctXic = kfXiC0.GetLifeTime(); - kfXic0Candidate.ctOmegac = kfXiC0.GetLifeTime(); - + kfXic0Candidate.ctV0 = kfV0ToCasc.GetLifeTime(); + kfXic0Candidate.ctCasc = kfXiToXiC.GetLifeTime(); + kfXic0Candidate.ctXic = kfXic0ToPv.GetLifeTime(); // KF eta kfXic0Candidate.etaXic = kfXiC0.GetEta(); // fill KF hist registry.fill(HIST("hKFParticleCascBachTopoChi2"), cascBachTopoChi2); - registry.fill(HIST("hKFParticleV0TopoChi2"), kfXic0Candidate.chi2NdfTopoV0ToCasc); - registry.fill(HIST("hKFParticleCascTopoChi2"), kfXic0Candidate.chi2NdfTopoCascToXic); - registry.fill(HIST("hKFParticleDcaCharmBaryonDau"), kfXic0Candidate.kfDcaXicDau); - registry.fill(HIST("hKFParticleDcaXYCascBachToPv"), dcaxyCascBachelor); - registry.fill(HIST("hKFParticleDcaXYV0DauPosToPv"), dcaxyV0Dau0); - registry.fill(HIST("hKFParticleDcaXYV0DauNegToPv"), dcaxyV0Dau1); - registry.fill(HIST("hKfLambda_ldl"), kfXic0Candidate.ldlV0); - registry.fill(HIST("hKfXi_ldl"), kfXic0Candidate.ldlCasc); registry.fill(HIST("hKfXiC0_ldl"), kfXic0Candidate.ldlXic); - registry.fill(HIST("hDcaXYCascadeToPVKf"), kfXic0Candidate.kfDcaXYCascToPv); // fill kf table kfCandidateXicData(collision.globalIndex(), pvCoord[0], pvCoord[1], pvCoord[2], - vertexCharmBaryonFromFitter[0], vertexCharmBaryonFromFitter[1], vertexCharmBaryonFromFitter[2], vertexCasc[0], vertexCasc[1], vertexCasc[2], vertexV0[0], vertexV0[1], vertexV0[2], trackCascDauCharged.sign(), @@ -1615,28 +1596,23 @@ struct HfCandidateCreatorXic0Omegac0 { pVecCascBachelor[0], pVecCascBachelor[1], pVecCascBachelor[2], pVecV0Dau0[0], pVecV0Dau0[1], pVecV0Dau0[2], pVecV0Dau1[0], pVecV0Dau1[1], pVecV0Dau1[2], - impactParameterCasc.getY(), impactParBachFromCharmBaryonXY, - impactParameterCasc.getZ(), impactParBachFromCharmBaryonZ, - std::sqrt(impactParameterCasc.getSigmaY2()), std::sqrt(impactParameterCharmBachelor.getSigmaY2()), v0index, casc.posTrackId(), casc.negTrackId(), casc.cascadeId(), trackCharmBachelor.globalIndex(), casc.bachelorId(), kfXic0Candidate.massV0, kfXic0Candidate.massCasc, kfXic0Candidate.massXic, - kfXic0Candidate.cosPaV0ToPv, kfXic0Candidate.cosPaXicToPv, kfXic0Candidate.cosPaCascToPv, kfXic0Candidate.cosPaXYV0ToPv, kfXic0Candidate.cosPaXYXicToPv, kfXic0Candidate.cosPaXYCascToPv, - kfXic0Candidate.ctOmegac, kfXic0Candidate.ctCasc, kfXic0Candidate.ctV0, kfXic0Candidate.ctXic, + kfXic0Candidate.cosPaV0ToPv, kfXic0Candidate.cosPaCascToPv, + kfXic0Candidate.ctCasc, kfXic0Candidate.ctV0, kfXic0Candidate.ctXic, pseudorapV0Dau0, pseudorapV0Dau1, pseudorapCascBachelor, pseudorapCharmBachelor, kfXic0Candidate.etaXic, kfXi.GetEta(), kfV0.GetEta(), dcaxyV0Dau0, dcaxyV0Dau1, dcaxyCascBachelor, - dcazV0Dau0, dcazV0Dau1, dcazCascBachelor, kfXic0Candidate.kfDcaCascDau, kfXic0Candidate.kfDcaV0Dau, kfXic0Candidate.kfDcaXicDau, - decLenCharmBaryon, decLenCascade, decLenV0, errorDecayLengthCharmBaryon, errorDecayLengthXYCharmBaryon, kfXic0Candidate.kfDcaXYPiFromXic, kfXic0Candidate.kfDcaXYCascToPv, kfXic0Candidate.chi2GeoV0, kfXic0Candidate.chi2GeoCasc, kfXic0Candidate.chi2GeoXic, kfXic0Candidate.chi2MassV0, kfXic0Candidate.chi2MassCasc, - kfXic0Candidate.ldlV0, kfXic0Candidate.ldlCasc, kfXic0Candidate.ldlXic, + kfXic0Candidate.ldlV0, kfXic0Candidate.ldlCasc, kfXic0Candidate.chi2NdfTopoV0ToPv, kfXic0Candidate.chi2NdfTopoCascToPv, kfXic0Candidate.chi2NdfTopoPiFromXicToPv, kfXic0Candidate.chi2NdfTopoXicToPv, kfXic0Candidate.chi2NdfTopoV0ToCasc, kfXic0Candidate.chi2NdfTopoCascToXic, kfXic0Candidate.decayLenXYLambda, kfXic0Candidate.decayLenXYCasc, kfXic0Candidate.decayLenXYXic, - kfXic0Candidate.cosPaV0ToCasc, kfXic0Candidate.cosPaCascToXic, kfXic0Candidate.cosPaXYV0ToCasc, kfXic0Candidate.cosPaXYCascToXic, - kfXic0Candidate.rapXic, kfXic0Candidate.ptPiFromXic, kfXic0Candidate.ptXic, + kfXic0Candidate.cosPaV0ToCasc, kfXic0Candidate.cosPaCascToXic, + kfXic0Candidate.rapXic, kfXic0Candidate.cosThetaStarPiFromXic, v0NDF, cascNDF, charmbaryonNDF, v0Ndfm, cascNdfm, v0Chi2OverNdf, cascChi2OverNdf, charmbaryonChi2OverNdf, v0Chi2OverNdfm, cascChi2OverNdfm); @@ -1655,6 +1631,339 @@ struct HfCandidateCreatorXic0Omegac0 { } } // loop over LF Cascade-bachelor candidates } + + template + void runOmegac0Xic0ToOmegaKaCreatorWithKFParticle(Coll const&, + aod::BCsWithTimestamps const& /*bcWithTimeStamps*/, + MyKfTracksIU const& tracksIU, + MyKfTracks const& tracks, + MyKfCascTable const&, KFCascadesLinked const&, + aod::HfCascLf2Prongs const& candidates, + Hist& hInvMassCharmBaryon, + Hist& hFitterStatus, + Hist& hCandidateCounter, + Hist& hCascadesCounter) + { + for (const auto& cand : candidates) { + hCandidateCounter->Fill(1); + + //----------------------check if the event is selected----------------------------- + auto collision = cand.collision_as(); + float centrality{-1.f}; + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + if (rejectionMask != 0) { + /// at least one event selection not satisfied --> reject the candidate + continue; + } + + //----------------------Set the magnetic field from ccdb----------------------------- + auto bc = collision.template bc_as(); + if (runNumber != bc.runNumber()) { + LOG(info) << ">>>>>>>>>>>> Current run number: " << runNumber; + initCCDB(bc, runNumber, ccdb, isRun2 ? ccdbPathGrp : ccdbPathGrpMag, lut, isRun2); + magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << ">>>>>>>>>>>> Magnetic field: " << magneticField; + runNumber = bc.runNumber(); + } + KFParticle::SetField(magneticField); + + // Retrieve skimmed cascade and pion tracks + auto cascAodElement = cand.cascade_as(); + hCascadesCounter->Fill(0); + if (!cascAodElement.has_kfCascData()) { + continue; + } + auto casc = cascAodElement.kfCascData_as(); + hCascadesCounter->Fill(1); + + // convert KaonFromCharm&KaFromOmega&V0DauPos&V0DauNeg tracks into KFParticle object + auto trackCharmBachelorId = cand.prong0Id(); + auto trackKaFromCharm = tracks.rawIteratorAt(trackCharmBachelorId); + auto trackCascDauChargedId = casc.bachelorId(); + auto trackV0Dau0Id = casc.posTrackId(); + auto trackV0Dau1Id = casc.negTrackId(); + auto trackKaFromOmega = tracksIU.rawIteratorAt(trackCascDauChargedId); // Ka <- Omega track + auto trackV0DauPos = tracksIU.rawIteratorAt(trackV0Dau0Id); // V0 positive daughter track + auto trackV0DauNeg = tracksIU.rawIteratorAt(trackV0Dau1Id); // V0 negative daughter track + auto kaFromOmegaCharge = trackKaFromOmega.sign(); + auto signOmega = casc.sign(); + + KFPTrack kfpTrackKaFromCharm = createKFPTrackFromTrack(trackKaFromCharm); + KFPTrack kfpTrackKaFromOmega = createKFPTrackFromTrack(trackKaFromOmega); + KFPTrack kfpTrackV0DauPos = createKFPTrackFromTrack(trackV0DauPos); + KFPTrack kfpTrackV0DauNeg = createKFPTrackFromTrack(trackV0DauNeg); + + KFParticle kfPrFromV0(kfpTrackV0DauPos, kProton); + KFParticle kfPiFromV0(kfpTrackV0DauNeg, kPiMinus); + KFParticle kfKaFromOmega(kfpTrackKaFromOmega, kKMinus); + KFParticle kfPiFromXiRej(kfpTrackKaFromOmega, kPiMinus); // rej + KFParticle kfKaFromCharm(kfpTrackKaFromCharm, kKPlus); + + if (signOmega == 0 || kaFromOmegaCharge == 0 || kaFromOmegaCharge != signOmega) { + continue; + } + // convert for Pos and Neg Particles + if (signOmega > 0) { + kfPiFromV0 = KFParticle(kfpTrackV0DauPos, kPiPlus); + kfPrFromV0 = KFParticle(kfpTrackV0DauNeg, -kProton); + kfKaFromOmega = KFParticle(kfpTrackKaFromOmega, kKPlus); + kfPiFromXiRej = KFParticle(kfpTrackKaFromOmega, kPiPlus); // rej + kfKaFromCharm = KFParticle(kfpTrackKaFromCharm, kKMinus); + } + + if (doCascadePreselection) { + if (std::abs(casc.dcaXYCascToPV()) > dcaXYToPVCascadeMax) { + continue; + } + if (std::abs(casc.dcaV0daughters()) > dcaV0DaughtersMax) { + continue; + } + if (std::abs(casc.dcacascdaughters()) > dcaCascDaughtersMax) { + continue; + } + if (std::abs(casc.mOmega() - MassOmegaMinus) > massToleranceCascade) { + continue; + } + } + + //----------------------info of V0 and cascade tracks from LF-table------------------ + std::array vertexV0 = {casc.xlambda(), casc.ylambda(), casc.zlambda()}; + std::array pVecV0 = {casc.pxlambda(), casc.pylambda(), casc.pzlambda()}; + std::array vertexCasc = {casc.x(), casc.y(), casc.z()}; + std::array pVecCasc = {casc.px(), casc.py(), casc.pz()}; + + // step 1 : construct V0 with KF + const KFParticle* v0Daughters[2] = {&kfPrFromV0, &kfPiFromV0}; + // construct V0 + KFParticle kfV0; + kfV0.SetConstructMethod(kfConstructMethod); + try { + kfV0.Construct(v0Daughters, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct cascade V0 from daughter tracks: " << e.what(); + continue; + } + // mass window cut on lambda before mass constraint + float massLam, sigLam; + kfV0.GetMass(massLam, sigLam); + if (std::abs(massLam - MassLambda0) > lambdaMassWindow) + continue; + // err_mass>0 of Lambda + if (sigLam <= 0) + continue; + // chi2>0 && NDF>0 for selecting Lambda + if ((kfV0.GetNDF() <= 0 || kfV0.GetChi2() <= 0)) + continue; + KFParticle kfV0MassConstrained = kfV0; + kfV0MassConstrained.SetNonlinearMassConstraint(o2::constants::physics::MassLambda); // set mass constrain to Lambda + if (kfUseV0MassConstraint) { + kfV0 = kfV0MassConstrained; + } + kfV0.TransportToDecayVertex(); + + // step 2 : reconstruct cascade(Omega) with KF + const KFParticle* omegaDaugthers[2] = {&kfKaFromOmega, &kfV0}; + const KFParticle* omegaDaugthersRej[2] = {&kfPiFromXiRej, &kfV0}; // rej + // construct cascade + KFParticle kfOmega; + KFParticle kfOmegarej; // rej + kfOmega.SetConstructMethod(kfConstructMethod); + kfOmegarej.SetConstructMethod(kfConstructMethod); // rej + try { + kfOmega.Construct(omegaDaugthers, 2); + kfOmegarej.Construct(omegaDaugthersRej, 2); // rej + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct Omega or Omega_rej from V0 and bachelor track: " << e.what(); + continue; + } + float massCasc, sigCasc; + float massCascrej, sigCascrej; + kfOmega.GetMass(massCasc, sigCasc); + kfOmegarej.GetMass(massCascrej, sigCascrej); // rej + // err_massOmega and err_massXiRej > 0 + if (sigCasc <= 0 || sigCascrej <= 0) + continue; + // chi2>0 && NDF>0 + if (kfOmega.GetNDF() <= 0 || kfOmega.GetChi2() <= 0) + continue; + if ((std::abs(massCasc - MassOmegaMinus) > massToleranceCascade) || (std::abs(massCascrej - MassXiMinus) < massToleranceCascadeRej)) + continue; + registry.fill(HIST("hInvMassXiMinus_rej"), massCascrej); // rej: Add competing rejection to minimize misidentified Xi impact. Reject if kfBachPionRej is Pion and the constructed cascade has Xi's invariant mass. + KFParticle kfOmegaMassConstrained = kfOmega; + kfOmegaMassConstrained.SetNonlinearMassConstraint(o2::constants::physics::MassOmegaMinus); // set mass constrain to XiMinus + if (kfUseCascadeMassConstraint) { + // set mass constraint if requested + kfOmega = kfOmegaMassConstrained; + } + registry.fill(HIST("hInvMassXiMinus"), massCasc); + kfOmega.TransportToDecayVertex(); + // rej: Add competing rejection to minimize misidentified Xi impact. Reject if kfBachPionRej is Pion and the constructed cascade has Xi's invariant mass. + + // step 3 : reconstruc OmegaKa with KF + // Create KF charm bach Pion from track + const KFParticle* omegaKaDaugthers[2] = {&kfKaFromCharm, &kfOmega}; + // construct Omegac0 or Xic0 + KFParticle kfOmegaKa; + kfOmegaKa.SetConstructMethod(kfConstructMethod); + try { + kfOmegaKa.Construct(omegaKaDaugthers, 2); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to construct OmegaKa from Cascade and bachelor pion track: " << e.what(); + continue; + } + float massOmegaKa, sigOmegaKa; + kfOmegaKa.GetMass(massOmegaKa, sigOmegaKa); + if (sigOmegaKa <= 0) + continue; + if (kfOmegaKa.GetNDF() <= 0 || kfOmegaKa.GetChi2() <= 0) + continue; + kfOmegaKa.TransportToDecayVertex(); + hFitterStatus->Fill(0); + hCandidateCounter->Fill(2); + + // initialize primary vertex + KFPVertex kfpVertex = createKFPVertexFromCollision(collision); + float covMatrixPV[6]; + kfpVertex.GetCovarianceMatrix(covMatrixPV); + KFParticle kfPv(kfpVertex); // for calculation of DCAs to PV + + // fill test histograms + hInvMassCharmBaryon->Fill(massOmegaKa); + + // topological constraint of daughter to mother + KFParticle kfKaFromCharmToOmegaKa = kfKaFromCharm; + KFParticle kfOmegaToOmegaKa = kfOmega; + KFParticle kfV0ToOmega = kfV0; + KFParticle kfKaToOmega = kfKaFromOmega; + KFParticle kfPrToV0 = kfPrFromV0; + KFParticle kfPiToV0 = kfPiFromV0; + + kfPrToV0.SetProductionVertex(kfV0); + kfPiToV0.SetProductionVertex(kfV0); + kfV0ToOmega.SetProductionVertex(kfOmega); + kfKaToOmega.SetProductionVertex(kfOmega); + kfKaFromCharmToOmegaKa.SetProductionVertex(kfOmegaKa); + kfOmegaToOmegaKa.SetProductionVertex(kfOmegaKa); + + // topological constraint to PV + // KFParticle to PV + KFParticle kfV0ToPv = kfV0; + KFParticle kfOmegaToPv = kfOmega; + KFParticle kfCharmToPv = kfOmegaKa; + KFParticle kfKaFromCharmToPv = kfKaFromCharm; + + kfV0ToPv.SetProductionVertex(kfPv); + kfOmegaToPv.SetProductionVertex(kfPv); + kfCharmToPv.SetProductionVertex(kfPv); + kfKaFromCharmToPv.SetProductionVertex(kfPv); + + //---------------------calculate physical parameters of OmegaKa candidate---------------------- + + // transport OmegaKa daughters to decay vertex (secondary vertex) + float secondaryVertex[3] = {0.}; + secondaryVertex[0] = kfOmegaKa.GetX(); + secondaryVertex[1] = kfOmegaKa.GetY(); + secondaryVertex[2] = kfOmegaKa.GetZ(); + kfKaFromCharm.TransportToPoint(secondaryVertex); + kfOmega.TransportToPoint(secondaryVertex); + + // get impact parameters of OmegaKa daughters + float impactParameterKaFromCharmXY = 0., errImpactParameterKaFromCharmXY = 0.; + float impactParameterOmegaXY = 0., errImpactParameterOmegaXY = 0.; + kfKaFromCharm.GetDistanceFromVertexXY(kfPv, impactParameterKaFromCharmXY, errImpactParameterKaFromCharmXY); + kfOmega.GetDistanceFromVertexXY(kfPv, impactParameterOmegaXY, errImpactParameterOmegaXY); + + // calculate cosine of pointing angle + float cosPaV0ToPv = cpaFromKF(kfV0, kfPv); + float cosPaCascToPv = cpaFromKF(kfOmega, kfPv); + float cosPaOmegaKaToPv = cpaFromKF(kfOmegaKa, kfPv); + float cosPaXYV0ToPv = cpaXYFromKF(kfV0, kfPv); + float cosPaXYCascToPv = cpaXYFromKF(kfOmega, kfPv); + float cosPaXYOmegaKaToPv = cpaXYFromKF(kfOmegaKa, kfPv); + float cosPaV0ToCasc = cpaFromKF(kfV0, kfOmega); + float cosPaCascToOmegaKa = cpaFromKF(kfOmega, kfOmegaKa); + float cosPaXYV0ToCasc = cpaXYFromKF(kfV0, kfOmega); + float cosPaXYCascToOmegaKa = cpaXYFromKF(kfOmega, kfOmegaKa); + + // Get Chi2Geo/NDF + float chi2GeoV0 = kfV0.GetChi2() / kfV0.GetNDF(); + float chi2GeoCasc = kfOmega.GetChi2() / kfOmega.GetNDF(); + float chi2GeoOmegaKa = kfOmegaKa.GetChi2() / kfOmegaKa.GetNDF(); + + // Get Chi2Topo/NDF + float chi2NdfTopoV0ToCasc = kfV0ToOmega.GetChi2() / kfV0ToOmega.GetNDF(); + float chi2NdfTopoKaToCasc = kfKaToOmega.GetChi2() / kfKaToOmega.GetNDF(); + float chi2NdfTopoKaFromOmegaKaToOmegaKa = kfKaFromCharmToOmegaKa.GetChi2() / kfKaFromCharmToOmegaKa.GetNDF(); + float chi2NdfTopoCascToOmegaKa = kfOmegaToOmegaKa.GetChi2() / kfOmegaToOmegaKa.GetNDF(); + float chi2NdfTopoV0ToPv = kfV0ToPv.GetChi2() / kfV0ToPv.GetNDF(); + float chi2NdfTopoCascToPv = kfOmegaToPv.GetChi2() / kfOmegaToPv.GetNDF(); + float chi2NdfTopoOmegaKaToPv = kfCharmToPv.GetChi2() / kfCharmToPv.GetNDF(); + float chi2NdfTopoKaFromOmegaKaToPv = kfKaFromCharmToPv.GetChi2() / kfKaFromCharmToPv.GetNDF(); + + // Get MassChi2/NDF + auto v0Chi2OverNdfm = kfV0MassConstrained.GetChi2() / kfV0MassConstrained.GetNDF(); + auto cascChi2OverNdfm = kfOmegaMassConstrained.GetChi2() / kfOmegaMassConstrained.GetNDF(); + + // KF ldl + float ldlV0 = ldlFromKF(kfV0, kfPv); + float ldlCasc = ldlFromKF(kfOmega, kfPv); + float ldlOmegaKa = ldlFromKF(kfOmegaKa, kfPv); + + // KF decay length + float decayLxyLam, errDecayLxyLam; + kfV0ToOmega.GetDecayLengthXY(decayLxyLam, errDecayLxyLam); + float decayLxyCasc, errDecayLxyCasc; + kfOmegaToOmegaKa.GetDecayLengthXY(decayLxyCasc, errDecayLxyCasc); + float decayLxyOmegaKa, errDecayLxyOmegaKa; + kfCharmToPv.GetDecayLengthXY(decayLxyOmegaKa, errDecayLxyOmegaKa); + + // KF pT + float ptOmegaKa = kfOmegaKa.GetPt(); + float ptKaFromCharm = kfKaFromCharm.GetPt(); + float ptOmega = kfOmega.GetPt(); + + // KF cosThetaStar + float cosThetaStarKaFromOmegac = cosThetaStarFromKF(0, 4332, 321, 3334, kfKaFromCharmToOmegaKa, kfOmegaToOmegaKa); + float cosThetaStarKaFromXic = cosThetaStarFromKF(0, 4132, 321, 3334, kfKaFromCharmToOmegaKa, kfOmegaToOmegaKa); + + // KF ct + float ctV0 = kfV0ToOmega.GetLifeTime(); + float ctCasc = kfOmegaToOmegaKa.GetLifeTime(); + float ctOmegaKa = kfCharmToPv.GetLifeTime(); + + hCandidateCounter->Fill(3); + + // fill full kf table + kfCandidateOmegaKaData(collision.globalIndex(), + collision.posX(), collision.posY(), collision.posZ(), // PV Coord + kfPv.GetX(), kfPv.GetY(), kfPv.GetZ(), // PV KF + vertexV0[0], vertexV0[1], vertexV0[2], // V0 Vtx from LF-table + pVecV0[0], pVecV0[1], pVecV0[2], // V0 P from LF-table + vertexCasc[0], vertexCasc[1], vertexCasc[2], // Casc Vtx from LF-table + pVecCasc[0], pVecCasc[1], pVecCasc[2], // Casc P from LF-table + kfV0.GetX(), kfV0.GetY(), kfV0.GetZ(), // V0 Vtx KF + kfV0.GetPx(), kfV0.GetPy(), kfV0.GetPz(), // V0 P KF + kfOmega.GetX(), kfOmega.GetY(), kfOmega.GetZ(), // Omega Vtx KF + kfOmega.GetPx(), kfOmega.GetPx(), kfOmega.GetPx(), // Omega Vtx KF + kfOmegaKa.GetX(), kfOmegaKa.GetY(), kfOmegaKa.GetZ(), // OmegaKa Vtx KF (SecondaryVertex) + kfOmegaKa.GetPx(), kfOmegaKa.GetPx(), kfOmegaKa.GetPx(), // OmegaKa P KF + signOmega, // Check Omega sign + kfPrFromV0.GetEta(), kfPiFromV0.GetEta(), kfKaFromOmega.GetEta(), kfKaFromCharm.GetEta(), kfV0.GetEta(), kfOmega.GetEta(), kfOmegaKa.GetEta(), kfOmegaKa.GetRapidity(), // Eta of daughters and mothers. Rapidity of OmegaKa + impactParameterKaFromCharmXY, errImpactParameterKaFromCharmXY, impactParameterOmegaXY, errImpactParameterOmegaXY, // DCAXY of KaFromCharm and Omega + kfPrToV0.GetDistanceFromParticle(kfPiToV0), kfV0ToOmega.GetDistanceFromParticle(kfKaToOmega), kfOmegaToOmegaKa.GetDistanceFromParticle(kfKaFromCharmToOmegaKa), // DCA of daughters + cosPaV0ToPv, cosPaCascToPv, cosPaOmegaKaToPv, cosPaXYV0ToPv, cosPaXYCascToPv, cosPaXYOmegaKaToPv, cosPaV0ToCasc, cosPaCascToOmegaKa, cosPaXYV0ToCasc, cosPaXYCascToOmegaKa, // CosPA of PV and mothers + chi2GeoV0, chi2GeoCasc, chi2GeoOmegaKa, // Chi2Geo/NDF + v0Chi2OverNdfm, cascChi2OverNdfm, // Chi2Mass/NDF + chi2NdfTopoV0ToCasc, chi2NdfTopoKaToCasc, chi2NdfTopoKaFromOmegaKaToOmegaKa, chi2NdfTopoCascToOmegaKa, chi2NdfTopoV0ToPv, chi2NdfTopoCascToPv, chi2NdfTopoKaFromOmegaKaToPv, chi2NdfTopoOmegaKaToPv, // Chi2Topo/NDF + ldlV0, ldlCasc, ldlOmegaKa, // ldl + decayLxyLam, decayLxyCasc, decayLxyOmegaKa, // DecaylengthXY + massLam, sigLam, massCasc, sigCasc, massCascrej, sigCascrej, massOmegaKa, sigOmegaKa, // massKF and masserror + ptOmegaKa, ptKaFromCharm, ptOmega, // pT + cosThetaStarKaFromOmegac, cosThetaStarKaFromXic, ctV0, ctCasc, ctOmegaKa, // cosThetaStar & ct + cascAodElement.v0Id(), casc.posTrackId(), casc.negTrackId(), casc.cascadeId(), casc.bachelorId(), trackKaFromCharm.globalIndex()); + } + } + /// @brief process function w/o centrality selections void processNoCentToXiPi(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, @@ -1694,23 +2003,37 @@ struct HfCandidateCreatorXic0Omegac0 { void processNoCentOmegacToOmegaPiWithKFParticle(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, MyKfTracks const& tracks, MyKfCascTable const& cascades, KFCascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runKfOmegac0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); + runKfOmegac0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processNoCentOmegacToOmegaPiWithKFParticle, "Run candidate creator w/o centrality selections for Omegac0 To omega pi decay channel using KFParticle", false); + void processNoCentOmegac0Xic0ToOmegaKaCreatorWithKFParticle(soa::Join const& collisions, + aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, + MyKfTracks const& tracks, + MyKfCascTable const& cascades, + KFCascadesLinked const& cascadeLinks, + aod::HfCascLf2Prongs const& candidates) + { + runOmegac0Xic0ToOmegaKaCreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processNoCentOmegac0Xic0ToOmegaKaCreatorWithKFParticle, "Run candidate creator w/o centrality selections for Omegac0 To omega ka decay channel using KFParticle", false); + void processNoCentXicToXiPiWithKFParticle(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, MyKfTracks const& tracks, MyKfCascTable const& cascades, KFCascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runKfXic0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); + runKfXic0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processNoCentXicToXiPiWithKFParticle, "Run candidate creator w/o centrality selections for Xic0 To Xi pi decay channel using KFParticle", false); @@ -1753,23 +2076,37 @@ struct HfCandidateCreatorXic0Omegac0 { void processCentFT0COmegacToOmegaPiWithKFParticle(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, MyKfTracks const& tracks, MyKfCascTable const& cascades, KFCascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runKfOmegac0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); + runKfOmegac0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0COmegacToOmegaPiWithKFParticle, "Run candidate creator w/o centrality selections for Omegac0 To omega pi decay channel using KFParticle", false); + void processCentFT0COmegac0Xic0ToOmegaKaCreatorWithKFParticle(soa::Join const& collisions, + aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, + MyKfTracks const& tracks, + MyKfCascTable const& cascades, + KFCascadesLinked const& cascadeLinks, + aod::HfCascLf2Prongs const& candidates) + { + runOmegac0Xic0ToOmegaKaCreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0COmegac0Xic0ToOmegaKaCreatorWithKFParticle, "Run candidate creator w/o centrality selections for Omegac0 To omega ka decay channel using KFParticle", false); + void processCentFT0CXicToXiPiWithKFParticle(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, MyKfTracks const& tracks, MyKfCascTable const& cascades, KFCascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runKfXic0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); + runKfXic0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0CXicToXiPiWithKFParticle, "Run candidate creator w FT0C centrality selections for Xic0 To Xi pi decay channel using KFParticle", false); @@ -1812,23 +2149,37 @@ struct HfCandidateCreatorXic0Omegac0 { void processCentFT0MOmegacToOmegaPiWithKFParticle(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, MyKfTracks const& tracks, MyKfCascTable const& cascades, KFCascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runKfOmegac0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); + runKfOmegac0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaPi, hFitterStatusToOmegaPi, hCandidateCounterToOmegaPi, hCascadesCounterToOmegaPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0MOmegacToOmegaPiWithKFParticle, "Run candidate creator w/o centrality selections for Omegac0 To omega pi decay channel using KFParticle", false); + void processCentFT0MOmegac0Xic0ToOmegaKaCreatorWithKFParticle(soa::Join const& collisions, + aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, + MyKfTracks const& tracks, + MyKfCascTable const& cascades, + KFCascadesLinked const& cascadeLinks, + aod::HfCascLf2Prongs const& candidates) + { + runOmegac0Xic0ToOmegaKaCreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToOmegaK, hFitterStatusToOmegaK, hCandidateCounterToOmegaK, hCascadesCounterToOmegaK); + } + PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0MOmegac0Xic0ToOmegaKaCreatorWithKFParticle, "Run candidate creator w/o centrality selections for Omegac0 To omega ka decay channel using KFParticle", false); + void processCentFT0MXicToXiPiWithKFParticle(soa::Join const& collisions, aod::BCsWithTimestamps const& bcWithTimeStamps, + MyKfTracksIU const& tracksIU, MyKfTracks const& tracks, MyKfCascTable const& cascades, KFCascadesLinked const& cascadeLinks, aod::HfCascLf2Prongs const& candidates) { - runKfXic0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); + runKfXic0CreatorWithKFParticle(collisions, bcWithTimeStamps, tracksIU, tracks, cascades, cascadeLinks, candidates, hInvMassCharmBaryonToXiPi, hFitterStatusToXiPi, hCandidateCounterToXiPi, hCascadesCounterToXiPi); } PROCESS_SWITCH(HfCandidateCreatorXic0Omegac0, processCentFT0MXicToXiPiWithKFParticle, "Run candidate creator w FT0M centrality selections for Xic0 To Xi pi decay channel using KFParticle", false); @@ -2375,18 +2726,22 @@ struct HfCandidateCreatorXic0Omegac0Mc { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; + int nSplitColl = 0; if constexpr (centEstimator == CentralityEstimator::FT0C) { const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); } else if constexpr (centEstimator == CentralityEstimator::FT0M) { const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollisionFT0M, mcCollision.globalIndex()); rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); } else if constexpr (centEstimator == CentralityEstimator::None) { const auto collSlice = collsWithMcLabels.sliceBy(colPerMcCollision, mcCollision.globalIndex()); rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, collSlice, centrality); + nSplitColl = collSlice.size(); } - hfEvSelMc.fillHistograms(mcCollision, rejectionMask); + hfEvSelMc.fillHistograms(mcCollision, rejectionMask, nSplitColl); if (rejectionMask != 0) { /// at least one event selection not satisfied --> reject all particles from this collision for (unsigned int i = 0; i < mcParticlesPerMcColl.size(); ++i) { diff --git a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx index 69fea11d5c9..5fea174e4f9 100644 --- a/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicToXiPiPi.cxx @@ -21,37 +21,55 @@ #define HomogeneousField // o2-linter: disable=name/macro (required by KFParticle) #endif -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "Framework/RunningWorkflowInfo.h" +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/CollisionAssociationTables.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Tools/KFparticle/KFUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::constants::physics; @@ -88,7 +106,6 @@ struct HfCandidateCreatorXicToXiPiPi { // KFParticle Configurable useXiMassConstraint{"useXiMassConstraint", true, "Use mass constraint for Xi"}; Configurable constrainXicPlusToPv{"constrainXicPlusToPv", false, "Constrain XicPlus to PV"}; - Configurable constrainXiToXicPlus{"constrainXiToXicPlus", false, "Constrain Xi to XicPlus"}; Configurable kfConstructMethod{"kfConstructMethod", 2, "Construct method of XicPlus: 0 fast mathematics without constraint of fixed daughter particle masses, 2 daughter particle masses stay fixed in construction process"}; Configurable rejDiffCollTrack{"rejDiffCollTrack", true, "Reject tracks coming from different collisions (effective only for KFParticle w/o derived data)"}; @@ -126,15 +143,16 @@ struct HfCandidateCreatorXicToXiPiPi { } // add histograms to registry + registry.add("hVertexerType", "Use DCAFitter or KFParticle;;entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); + 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"); + registry.add("hCandCounter", "hCandCounter", {HistType::kTH1D, {{4, -0.5, 3.5}}}); + registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + TotalSkimmedTriplets, "total"); + registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + SelEvent, "Event selected"); + registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + CascPreSel, "Cascade preselection"); + registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + VertexFit, "Successful vertex fit"); + // physical variables if (fillHistograms) { - // counter - registry.add("hVertexerType", "Use KF or DCAFitterN;Vertexer type;entries", {HistType::kTH1F, {{2, -0.5, 1.5}}}); // See o2::aod::hf_cand::VertexerType - registry.add("hCandCounter", "hCandCounter", {HistType::kTH1F, {{4, -0.5, 3.5}}}); - registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + TotalSkimmedTriplets, "total"); - registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + SelEvent, "Event selected"); - registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + CascPreSel, "Cascade preselection"); - registry.get(HIST("hCandCounter"))->GetXaxis()->SetBinLabel(1 + VertexFit, "Successful vertex fit"); - // physical variables registry.add("hMass3", "3-prong candidates;inv. mass (#Xi #pi #pi) (GeV/#it{c}^{2});entries", {HistType::kTH1D, {{500, 2.3, 2.7}}}); registry.add("hCovPVXX", "3-prong candidates;XX element of cov. matrix of prim. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 1.e-4}}}); registry.add("hCovSVXX", "3-prong candidates;XX element of cov. matrix of sec. vtx. position (cm^{2});entries", {HistType::kTH1D, {{100, 0., 0.2}}}); @@ -186,9 +204,7 @@ struct HfCandidateCreatorXicToXiPiPi { { // loop over triplets of track indices for (const auto& rowTrackIndexXicPlus : rowsTrackIndexXicPlus) { - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), TotalSkimmedTriplets); - } + registry.fill(HIST("hCandCounter"), TotalSkimmedTriplets); // check if the event is selected auto collision = rowTrackIndexXicPlus.collision_as(); @@ -198,9 +214,7 @@ struct HfCandidateCreatorXicToXiPiPi { /// at least one event selection not satisfied --> reject the candidate continue; } - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), SelEvent); - } + registry.fill(HIST("hCandCounter"), SelEvent); // Retrieve skimmed cascade and pion tracks auto cascAodElement = rowTrackIndexXicPlus.cascade_as(); @@ -220,9 +234,7 @@ struct HfCandidateCreatorXicToXiPiPi { continue; } } - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), CascPreSel); - } + registry.fill(HIST("hCandCounter"), CascPreSel); //----------------------Set the magnetic field from ccdb--------------------------------------- /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, @@ -275,13 +287,11 @@ struct HfCandidateCreatorXicToXiPiPi { LOG(info) << "Run time error found: " << error.what() << ". DCAFitterN cannot work, skipping the candidate."; continue; } - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), VertexFit); - } + registry.fill(HIST("hCandCounter"), VertexFit); //----------------------------calculate physical properties----------------------- // Charge of charm baryon - int signXic = casc.sign() < 0 ? +1 : -1; + int8_t signXic = casc.sign() < 0 ? +1 : -1; // get SV properties const auto& secondaryVertex = df.getPCACandidate(); @@ -427,9 +437,7 @@ struct HfCandidateCreatorXicToXiPiPi { { // loop over triplets of track indices for (const auto& rowTrackIndexXicPlus : rowsTrackIndexXicPlus) { - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), TotalSkimmedTriplets); - } + registry.fill(HIST("hCandCounter"), TotalSkimmedTriplets); // check if the event is selected auto collision = rowTrackIndexXicPlus.collision_as(); @@ -439,9 +447,7 @@ struct HfCandidateCreatorXicToXiPiPi { /// at least one event selection not satisfied --> reject the candidate continue; } - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), SelEvent); - } + registry.fill(HIST("hCandCounter"), SelEvent); // Retrieve skimmed cascade and pion tracks auto cascAodElement = rowTrackIndexXicPlus.cascade_as(); @@ -461,9 +467,7 @@ struct HfCandidateCreatorXicToXiPiPi { continue; } } - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), CascPreSel); - } + registry.fill(HIST("hCandCounter"), CascPreSel); //----------------------Set the magnetic field from ccdb----------------------------- /// The static instance of the propagator was already modified in the HFTrackIndexSkimCreator, @@ -520,48 +524,27 @@ struct HfCandidateCreatorXicToXiPiPi { LOG(debug) << "Failed to construct XicPlus : " << e.what(); continue; } - if (fillHistograms) { - registry.fill(HIST("hCandCounter"), VertexFit); - } + registry.fill(HIST("hCandCounter"), VertexFit); - // get geometrical chi2 of XicPlus + // get chi2 values float chi2GeoXicPlus = kfXicPlus.GetChi2() / kfXicPlus.GetNDF(); + float chi2PrimXi = kfXi.GetDeviationFromVertex(kfPv); + float chi2PrimPi0 = kfCharmBachelor0.GetDeviationFromVertex(kfPv); + float chi2PrimPi1 = kfCharmBachelor1.GetDeviationFromVertex(kfPv); // topological constraint of Xic to PV - float chi2topoXicPlusToPVBeforeConstraint = kfXicPlus.GetDeviationFromVertex(kfPv); + float chi2TopoXicPlusToPVBefConst = kfXicPlus.GetDeviationFromVertex(kfPv); KFParticle kfXicPlusToPV = kfXicPlus; kfXicPlusToPV.SetProductionVertex(kfPv); - float chi2topoXicPlusToPV = kfXicPlusToPV.GetChi2() / kfXicPlusToPV.GetNDF(); + float chi2TopoXicPlusToPV = kfXicPlusToPV.GetChi2() / kfXicPlusToPV.GetNDF(); if (constrainXicPlusToPv) { kfXicPlus = kfXicPlusToPV; kfXicPlus.TransportToDecayVertex(); } - // topological constraint of Xi to XicPlus - float chi2topoXiToXicPlusBeforeConstraint = kfXi.GetDeviationFromVertex(kfXicPlus); - KFParticle kfXiToXicPlus = kfXi; - kfXiToXicPlus.SetProductionVertex(kfXicPlus); - float chi2topoXiToXicPlus = kfXiToXicPlus.GetChi2() / kfXiToXicPlus.GetNDF(); - kfXiToXicPlus.TransportToDecayVertex(); - if (constrainXiToXicPlus) { - KFParticle kfXicPlusWithXiToXicPlus; - const KFParticle* kfDaughtersXicPlusWithXiToXicPlus[3] = {&kfCharmBachelor0, &kfCharmBachelor1, &kfXiToXicPlus}; - kfXicPlusWithXiToXicPlus.SetConstructMethod(kfConstructMethod); - try { - kfXicPlusWithXiToXicPlus.Construct(kfDaughtersXicPlusWithXiToXicPlus, 3); - } catch (std::runtime_error& e) { - LOG(debug) << "Failed to construct XicPlus with Xi connstrained to XicPlus: " << e.what(); - continue; - } - kfXicPlus = kfXicPlusWithXiToXicPlus; - } - - // get covariance matrix of XicPlus - auto covMatrixXicPlus = kfXicPlus.CovarianceMatrix(); - //---------------------calculate physical parameters of XicPlus candidate---------------------- // sign of charm baryon - int signXic = casc.sign() < 0 ? +1 : -1; + int8_t signXic = casc.sign() < 0 ? +1 : -1; // transport XicPlus daughters to XicPlus decay vertex (secondary vertex) float secondaryVertex[3] = {0.}; @@ -589,13 +572,18 @@ struct HfCandidateCreatorXicToXiPiPi { float cpaLambdaToXi = RecoDecay::cpa(vertexCasc, vertexV0, pVecV0); float cpaXYLambdaToXi = RecoDecay::cpaXY(vertexCasc, vertexV0, pVecV0); + // get chi2 deviation of Pi0-Pi1, Pi0-Xi, Pi1-Xi + float chi2DevPi0Pi1 = kfCharmBachelor0.GetDeviationFromParticle(kfCharmBachelor1); + float chi2DevPi0Xi = kfCharmBachelor0.GetDeviationFromParticle(kfXi); + float chi2DevPi1Xi = kfCharmBachelor1.GetDeviationFromParticle(kfXi); + // get DCAs of Pi0-Pi1, Pi0-Xi, Pi1-Xi - float dcaXYPi0Pi1 = kfCharmBachelor0.GetDistanceFromParticleXY(kfCharmBachelor1); - float dcaXYPi0Xi = kfCharmBachelor0.GetDistanceFromParticleXY(kfXi); - float dcaXYPi1Xi = kfCharmBachelor1.GetDistanceFromParticleXY(kfXi); float dcaPi0Pi1 = kfCharmBachelor0.GetDistanceFromParticle(kfCharmBachelor1); float dcaPi0Xi = kfCharmBachelor0.GetDistanceFromParticle(kfXi); float dcaPi1Xi = kfCharmBachelor1.GetDistanceFromParticle(kfXi); + float dcaXYPi0Pi1 = kfCharmBachelor0.GetDistanceFromParticleXY(kfCharmBachelor1); + float dcaXYPi0Xi = kfCharmBachelor0.GetDistanceFromParticleXY(kfXi); + float dcaXYPi1Xi = kfCharmBachelor1.GetDistanceFromParticleXY(kfXi); // mass of Xi-Pi0 pair KFParticle kfXiPi0; @@ -672,6 +660,7 @@ struct HfCandidateCreatorXicToXiPiPi { registry.fill(HIST("hCovPVXZ"), covMatrixPV[3]); registry.fill(HIST("hCovPVZZ"), covMatrixPV[5]); // covariance matrix elements of SV + auto covMatrixXicPlus = kfXicPlus.CovarianceMatrix(); registry.fill(HIST("hCovSVXX"), covMatrixXicPlus[0]); registry.fill(HIST("hCovSVYY"), covMatrixXicPlus[2]); registry.fill(HIST("hCovSVXZ"), covMatrixXicPlus[3]); @@ -708,11 +697,13 @@ struct HfCandidateCreatorXicToXiPiPi { /*PID information*/ nSigTpcPiFromXicPlus0, nSigTpcPiFromXicPlus1, nSigTpcBachelorPi, nSigTpcPiFromLambda, nSigTpcPrFromLambda, nSigTofPiFromXicPlus0, nSigTofPiFromXicPlus1, nSigTofBachelorPi, nSigTofPiFromLambda, nSigTofPrFromLambda); - rowCandidateKF(casc.kfCascadeChi2(), casc.kfV0Chi2(), - kfDecayLength, kfDecayLengthNormalised, kfDecayLengthXY, kfDecayLengthXYNormalised, - chi2topoXicPlusToPVBeforeConstraint, chi2topoXicPlusToPV, chi2topoXiToXicPlusBeforeConstraint, chi2topoXiToXicPlus, - dcaXYPi0Pi1, dcaXYPi0Xi, dcaXYPi1Xi, - dcaPi0Pi1, dcaPi0Xi, dcaPi1Xi); + rowCandidateKF(kfDecayLength, kfDecayLengthNormalised, kfDecayLengthXY, kfDecayLengthXYNormalised, + casc.kfCascadeChi2(), casc.kfV0Chi2(), + chi2TopoXicPlusToPVBefConst, chi2TopoXicPlusToPV, + chi2PrimXi, chi2PrimPi0, chi2PrimPi1, + chi2DevPi0Pi1, chi2DevPi0Xi, chi2DevPi1Xi, + dcaPi0Pi1, dcaPi0Xi, dcaPi1Xi, + dcaXYPi0Pi1, dcaXYPi0Xi, dcaXYPi1Xi); } // loop over track triplets } @@ -807,7 +798,7 @@ struct HfCandidateCreatorXicToXiPiPi { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -824,7 +815,7 @@ struct HfCandidateCreatorXicToXiPiPi { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -841,7 +832,7 @@ struct HfCandidateCreatorXicToXiPiPi { /// bitmask with event. selection info float centrality{-1.f}; - float occupancy = getOccupancyColl(collision, OccupancyEstimator::Its); + float occupancy = getOccupancyColl(collision, hfEvSel.occEstimator); const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); /// monitor the satisfied event selections @@ -857,10 +848,12 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { Spawns rowCandidateXic; Produces rowMcMatchRec; Produces rowMcMatchGen; + Produces rowResiduals; Configurable fillMcHistograms{"fillMcHistograms", true, "Fill validation plots"}; Configurable matchDecayedPions{"matchDecayedPions", true, "Match also candidates with daughter pion tracks that decay with kinked topology"}; Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", true, "Match also candidates with daughter tracks that interact with material"}; + Configurable fillResidualTable{"fillResidualTable", false, "Fill table containing residuals and pulls of PV and SV"}; HfEventSelectionMc hfEvSelMc; @@ -887,10 +880,10 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { // add histograms to registry if (fillMcHistograms) { registry.add("hDecayedPions", "hDecayedPions", {HistType::kTH1F, {{5, -0.5, 4.5}}}); - registry.add("hInteractionsWithMaterial", "hInteractionsWithMaterial", {HistType::kTH1F, {{21, -0.5, 20.5}}}); + registry.add("hInteractionsWithMaterial", "hInteractionsWithMaterial", {HistType::kTH1F, {{6, -0.5, 5.5}}}); registry.add("hDebugRec", "hDebugRec", {HistType::kTH1F, {{4, -0.5, 3.5}}}); registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + TotalRec, "total"); - registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + XicToFinalState, "#Xi^{+}_{c} #rightarrow #pi^{#plus}) #pi^{#plus} #pi^{#minus} p #pi^{#minus}"); + registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + XicToFinalState, "#Xi^{+}_{c} #rightarrow #pi^{#plus} #pi^{#plus} #pi^{#minus} p #pi^{#minus}"); registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + XiToPiPPi, "#Xi^{#minus} #rightarrow #pi^{#minus} p #pi^{#minus}"); registry.get(HIST("hDebugRec"))->GetXaxis()->SetBinLabel(1 + LambdaToPPi, "#Lambda #rightarrow p #pi^{#minus}"); } @@ -928,6 +921,12 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { std::array arrXiResonance = {3324, kPiPlus}; // 3324: Ξ(1530) // for non-prompt std::vector idxBhadMothers; + // residuals and pulls + std::array momentumResiduals{-9999.f}; + std::array pvResiduals{-9999.f}; + std::array pvPulls{-9999.f}; + std::array svResiduals{-9999.f}; + std::array svPulls{-9999.f}; // Match reconstructed candidates. for (const auto& candidate : *rowCandidateXic) { @@ -937,6 +936,13 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { nPionsDecayed = 0; nInteractionsWithMaterial = 0; arrDaughIndex.clear(); + if (fillResidualTable) { + momentumResiduals.fill(-9999.f); + pvResiduals.fill(-9999.f); + pvPulls.fill(-9999.f); + svResiduals.fill(-9999.f); + svPulls.fill(-9999.f); + } auto arrayDaughters = std::array{candidate.pi0_as(), // pi <- Xic candidate.pi1_as(), // pi <- Xic @@ -996,7 +1002,9 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { if (fillMcHistograms) { registry.fill(HIST("hDebugRec"), LambdaToPPi); } - RecoDecay::getDaughters(mcParticles.rawIteratorAt(indexRecXicPlus), &arrDaughIndex, std::array{0}, 1); + auto particleXicPlus = mcParticles.rawIteratorAt(indexRecXicPlus); + // Check whether XicPlus decays via resonant decay + RecoDecay::getDaughters(particleXicPlus, &arrDaughIndex, std::array{0}, 1); if (arrDaughIndex.size() == NDaughtersResonant) { for (auto iProng = 0u; iProng < NDaughtersResonant; ++iProng) { auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); @@ -1008,22 +1016,53 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { } else { flag = sign * (1 << aod::hf_cand_xic_to_xi_pi_pi::DecayType::XicToXiPiPi); } + // Check whether the charm baryon is non-prompt (from a b quark). + if (flag != 0) { + origin = RecoDecay::getCharmHadronOrigin(mcParticles, particleXicPlus, false); + } + // Calculate residuals and pulls + if (flag != 0 && fillResidualTable) { + auto mcCollision = particleXicPlus.template mcCollision_as(); + auto particleDaughter0 = mcParticles.rawIteratorAt(arrDaughIndex[0]); + + momentumResiduals[0] = candidate.p() - particleXicPlus.p(); + momentumResiduals[1] = candidate.pt() - particleXicPlus.pt(); + pvResiduals[0] = candidate.posX() - mcCollision.posX(); + pvResiduals[1] = candidate.posY() - mcCollision.posY(); + pvResiduals[2] = candidate.posZ() - mcCollision.posZ(); + svResiduals[0] = candidate.xSecondaryVertex() - particleDaughter0.vx(); + svResiduals[1] = candidate.ySecondaryVertex() - particleDaughter0.vy(); + svResiduals[2] = candidate.zSecondaryVertex() - particleDaughter0.vz(); + try { + pvPulls[0] = pvResiduals[0] / candidate.xPvErr(); + pvPulls[1] = pvResiduals[1] / candidate.yPvErr(); + pvPulls[2] = pvResiduals[2] / candidate.zPvErr(); + svPulls[0] = svResiduals[0] / candidate.xSvErr(); + svPulls[1] = svResiduals[1] / candidate.ySvErr(); + svPulls[2] = svResiduals[2] / candidate.zSvErr(); + } catch (const std::runtime_error& error) { + LOG(info) << "Run time error found: " << error.what() << ". Set values of vertex pulls to -9999.9."; + } + } } } } - // Check whether the charm baryon is non-prompt (from a b quark). - if (flag != 0) { - auto particle = mcParticles.rawIteratorAt(indexRecXicPlus); - origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false); - } // Fill histograms if (flag != 0 && fillMcHistograms) { registry.fill(HIST("hDecayedPions"), nPionsDecayed); registry.fill(HIST("hInteractionsWithMaterial"), nInteractionsWithMaterial); } - // Fill table + + // Fill tables rowMcMatchRec(flag, origin); + if (flag != 0 && fillResidualTable) { + rowResiduals(origin, momentumResiduals[0], momentumResiduals[1], + pvResiduals[0], pvResiduals[1], pvResiduals[2], + pvPulls[0], pvPulls[1], pvPulls[2], + svResiduals[0], svResiduals[1], svResiduals[2], + svPulls[0], svPulls[1], svPulls[2]); + } } // close loop over candidates // Match generated particles. @@ -1032,7 +1071,7 @@ struct HfCandidateCreatorXicToXiPiPiExpressions { const auto mcParticlesPerMcColl = mcParticles.sliceBy(mcParticlesPerMcCollision, mcCollision.globalIndex()); // Slice the collisions table to get the collision info for the current MC collision float centrality{-1.f}; - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; int nSplitColl = 0; if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0C) { const auto collSlice = collInfos.sliceBy(colPerMcCollisionFT0C, mcCollision.globalIndex()); diff --git a/PWGHF/TableProducer/candidateCreatorXicc.cxx b/PWGHF/TableProducer/candidateCreatorXicc.cxx index e4455828b8d..915d6501d6f 100644 --- a/PWGHF/TableProducer/candidateCreatorXicc.cxx +++ b/PWGHF/TableProducer/candidateCreatorXicc.cxx @@ -17,18 +17,34 @@ /// \author Luigi Dello Stritto , SALERNO /// \author Mattia Faggin , University and INFN PADOVA -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.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::constants::physics; @@ -41,7 +57,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Reconstruction of xicc candidates struct HfCandidateCreatorXicc { diff --git a/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx b/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx index cf7658810d8..60709a4e4dc 100644 --- a/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorB0ToDPi.cxx @@ -14,16 +14,6 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseB0ToDPi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -31,6 +21,33 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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; diff --git a/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx b/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx index 154067f6bc2..1bcc8bff8e0 100644 --- a/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/candidateSelectorBplusToD0Pi.cxx @@ -16,16 +16,6 @@ /// \author Deepa Thomas , UT Austin /// \author Nima Zardoshti , CERN -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseBplusToD0Pi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -33,6 +23,34 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsPid.h" +#include "Common/Core/TrackSelectorPID.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::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx index cfd8f418e0e..05a66854ada 100644 --- a/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorBsToDsPi.cxx @@ -15,21 +15,37 @@ /// /// \author Phil Stahlhut -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.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; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorD0.cxx b/PWGHF/TableProducer/candidateSelectorD0.cxx index ae0102b33fe..98634b9cf08 100644 --- a/PWGHF/TableProducer/candidateSelectorD0.cxx +++ b/PWGHF/TableProducer/candidateSelectorD0.cxx @@ -15,23 +15,34 @@ /// \author Nima Zardoshti , CERN /// \author Vít Kučera , CERN -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseD0ToKPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#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; diff --git a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx index 5aa753b28d1..a531b6dbab0 100644 --- a/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDplusToPiKPi.cxx @@ -15,15 +15,6 @@ /// \author Fabio Catalano , Politecnico and INFN Torino /// \author Vít Kučera , CERN -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseDplusToPiKPi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -31,6 +22,28 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#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; @@ -64,8 +77,6 @@ struct HfCandidateSelectorDplusToPiKPi { Configurable> binsPtTrack{"binsPtTrack", std::vector{hf_cuts_single_track::vecBinsPtTrack}, "track pT bin limits for DCA pT-dependent cut"}; // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; - // Correlated background from Ds and D+ - Configurable storeDsDplusBkg{"storeDsDplusBkg", false, "Flag to store correlated background from misidentified product of Ds and D+ decay"}; // 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"}; @@ -229,7 +240,7 @@ struct HfCandidateSelectorDplusToPiKPi { auto ptCand = candidate.pt(); - if (!TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DplusToPiKPi) && !(storeDsDplusBkg && TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DsToKKPi))) { // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + if (!TESTBIT(candidate.hfflag(), aod::hf_cand_3prong::DecayType::DplusToPiKPi)) { hfSelDplusToPiKPiCandidate(statusDplusToPiKPi); if (applyMl) { hfMlDplusToPiKPiCandidate(outputMlNotPreselected); diff --git a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx index 9196ce735de..80f22343ff1 100644 --- a/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDsToKKPi.cxx @@ -15,15 +15,6 @@ /// \author Fabio Catalano , Universita and INFN Torino /// \author Stefano Politano , Politecnico and INFN Torino -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseDsToKKPi.h" #include "PWGHF/Core/SelectorCuts.h" @@ -31,6 +22,28 @@ #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#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; diff --git a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx index cb058a18f6b..dbc06282ce0 100644 --- a/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/candidateSelectorDstarToD0Pi.cxx @@ -15,26 +15,36 @@ /// \author Deependra Sharma , IITB /// \author Fabrizio Grosa , CERN -#include -#include -#include - -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/Logger.h" -#include "Framework/runDataProcessing.h" -// O2Physics -#include "Common/Core/TrackSelectorPID.h" -// PWGHF #include "PWGHF/Core/HfHelper.h" +#include "PWGHF/Core/HfMlResponseD0ToKPi.h" #include "PWGHF/Core/HfMlResponseDstarToD0Pi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsAnalysis.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + using namespace o2; using namespace o2::constants::physics; using namespace o2::analysis; @@ -81,18 +91,27 @@ struct HfCandidateSelectorDstarToD0Pi { // QA switch Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; - // ML inference + // ML inference D* 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"}; + // ML inference D0 + Configurable applyMlD0Daug{"applyMlD0Daug", false, "Flag to apply ML selections on D0 daughter"}; + Configurable> binsPtMlD0Daug{"binsPtMlD0Daug", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application on D0 daughter"}; + Configurable> cutDirMlD0Daug{"cutDirMlD0Daug", std::vector{hf_cuts_ml::vecCutDir}, "Whether to reject score values greater or smaller than the threshold on D0 daughter"}; + Configurable> cutsMlD0Daug{"cutsMlD0Daug", {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 on D0 daughter"}; + Configurable nClassesMlD0Daug{"nClassesMlD0Daug", static_cast(hf_cuts_ml::NCutScores), "Number of classes in ML model on D0 daughter"}; + Configurable> namesInputFeaturesD0Daug{"namesInputFeaturesD0Daug", std::vector{"feature1", "feature2"}, "Names of ML model input features on D0 daughter"}; // CCDB configuration Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable> modelPathsCCDB{"modelPathsCCDB", std::vector{""}, "Paths of models on CCDB"}; + Configurable> modelPathsCCDBD0Daug{"modelPathsCCDBD0Daug", std::vector{""}, "Paths of models on CCDB for D0 daughter"}; Configurable> onnxFileNames{"onnxFileNames", std::vector{"Model.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path)"}; + Configurable> onnxFileNamesD0Daug{"onnxFileNamesD0Daug", std::vector{"Model.onnx"}, "ONNX file names for each pT bin (if not from CCDB full path) for D0 daughter"}; 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"}; @@ -101,7 +120,9 @@ struct HfCandidateSelectorDstarToD0Pi { HfHelper hfHelper; o2::analysis::HfMlResponseDstarToD0Pi hfMlResponse; + o2::analysis::HfMlResponseDstarToD0Pi hfMlResponseD0Daughter; std::vector outputMlDstarToD0Pi = {}; + std::vector outputMlD0ToKPi = {}; o2::ccdb::CcdbApi ccdbApi; TrackSelectorPi selectorPion; @@ -163,6 +184,18 @@ struct HfCandidateSelectorDstarToD0Pi { hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); hfMlResponse.init(); } + + if (applyMlD0Daug) { + hfMlResponseD0Daughter.configure(binsPtMlD0Daug, cutsMlD0Daug, cutDirMlD0Daug, nClassesMlD0Daug); + if (loadModelsFromCCDB) { + ccdbApi.init(ccdbUrl); + hfMlResponseD0Daughter.setModelPathsCCDB(onnxFileNamesD0Daug, ccdbApi, modelPathsCCDBD0Daug, timestampCCDB); + } else { + hfMlResponseD0Daughter.setModelPathsLocal(onnxFileNamesD0Daug); + } + hfMlResponseD0Daughter.cacheInputFeaturesIndices(namesInputFeaturesD0Daug); + hfMlResponseD0Daughter.init(); + } } /// Conjugate-independent topological cuts on D0 @@ -226,9 +259,13 @@ struct HfCandidateSelectorDstarToD0Pi { return false; } - //.............Why is this if condition commented? - if (candidate.decayLengthNormalisedD0() * candidate.decayLengthNormalisedD0() < 1.0) { - // return false; // add back when getter fixed + if (applyMlD0Daug) { + outputMlD0ToKPi.clear(); + std::vector inputFeaturesD0 = hfMlResponseD0Daughter.getInputFeaturesTrigger(candidate); + bool isSelectedMlD0 = hfMlResponseD0Daughter.isSelectedMl(inputFeaturesD0, candpT, outputMlD0ToKPi); + if (!isSelectedMlD0) { + return false; + } } return true; } diff --git a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx index 29ef2154d59..74abba33758 100644 --- a/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorLbToLcPi.cxx @@ -14,19 +14,26 @@ /// /// \author Panos Christakoglou , Nikhef -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorLc.cxx b/PWGHF/TableProducer/candidateSelectorLc.cxx index 93b84c79522..2b06decbec7 100644 --- a/PWGHF/TableProducer/candidateSelectorLc.cxx +++ b/PWGHF/TableProducer/candidateSelectorLc.cxx @@ -17,21 +17,36 @@ /// \author Vít Kučera , CERN /// \author Grazia Luparello , INFN Trieste -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseLcToPKPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" +#include "Common/DataModel/PIDResponseCombined.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::framework; @@ -93,7 +108,8 @@ struct HfCandidateSelectorLc { Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; HfHelper hfHelper; - o2::analysis::HfMlResponseLcToPKPi hfMlResponse; + o2::analysis::HfMlResponseLcToPKPi hfMlResponseDCA; + o2::analysis::HfMlResponseLcToPKPi hfMlResponseKF; std::vector outputMlLcToPKPi = {}; std::vector outputMlLcToPiKP = {}; o2::ccdb::CcdbApi ccdbApi; @@ -142,15 +158,28 @@ struct HfCandidateSelectorLc { } if (applyMl) { - hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); - if (loadModelsFromCCDB) { - ccdbApi.init(ccdbUrl); - hfMlResponse.setModelPathsCCDB(onnxFileNames, ccdbApi, modelPathsCCDB, timestampCCDB); - } else { - hfMlResponse.setModelPathsLocal(onnxFileNames); + if (doprocessNoBayesPidWithDCAFitterN || doprocessBayesPidWithDCAFitterN) { + 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(); + } + if (doprocessNoBayesPidWithKFParticle || doprocessBayesPidWithKFParticle) { + 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(); } - hfMlResponse.cacheInputFeaturesIndices(namesInputFeatures); - hfMlResponse.init(); } massK0Star892 = o2::constants::physics::MassK0Star892; @@ -273,7 +302,7 @@ struct HfCandidateSelectorLc { return false; } - float massLc, massKPi; + float massLc{0.f}, massKPi{0.f}; if constexpr (reconstructionType == aod::hf_cand::VertexerType::DCAFitter) { if (trackProton.globalIndex() == candidate.prong0Id()) { massLc = hfHelper.invMassLcToPKPi(candidate); @@ -553,13 +582,24 @@ struct HfCandidateSelectorLc { isSelectedMlLcToPKPi = false; isSelectedMlLcToPiKP = false; - if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { - std::vector inputFeaturesLcToPKPi = hfMlResponse.getInputFeatures(candidate, true); - isSelectedMlLcToPKPi = hfMlResponse.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); - } - if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { - std::vector inputFeaturesLcToPiKP = hfMlResponse.getInputFeatures(candidate, false); - isSelectedMlLcToPiKP = hfMlResponse.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); + if constexpr (reconstructionType == aod::hf_cand::VertexerType::DCAFitter) { + if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { + std::vector inputFeaturesLcToPKPi = hfMlResponseDCA.getInputFeatures(candidate, true); + isSelectedMlLcToPKPi = hfMlResponseDCA.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); + } + if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { + std::vector inputFeaturesLcToPiKP = hfMlResponseDCA.getInputFeatures(candidate, false); + isSelectedMlLcToPiKP = hfMlResponseDCA.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); + } + } else { + if (pidLcToPKPi == 1 && pidBayesLcToPKPi == 1 && topolLcToPKPi) { + std::vector inputFeaturesLcToPKPi = hfMlResponseKF.getInputFeatures(candidate, true); + isSelectedMlLcToPKPi = hfMlResponseKF.isSelectedMl(inputFeaturesLcToPKPi, candidate.pt(), outputMlLcToPKPi); + } + if (pidLcToPiKP == 1 && pidBayesLcToPiKP == 1 && topolLcToPiKP) { + std::vector inputFeaturesLcToPiKP = hfMlResponseKF.getInputFeatures(candidate, false); + isSelectedMlLcToPiKP = hfMlResponseKF.isSelectedMl(inputFeaturesLcToPiKP, candidate.pt(), outputMlLcToPiKP); + } } hfMlLcToPKPiCandidate(outputMlLcToPKPi, outputMlLcToPiKP); diff --git a/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx b/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx index 9f74fd9c583..9a68436f861 100644 --- a/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx +++ b/PWGHF/TableProducer/candidateSelectorLcPidMl.cxx @@ -17,22 +17,41 @@ /// \author Vít Kučera , CERN /// \author Maja Kabus , CERN, Warsaw University of Technology -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/CcdbApi.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" #include "Common/Core/trackUtilities.h" +#include "Common/DataModel/PIDResponseCombined.h" #include "Tools/ML/model.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.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::analysis; @@ -127,15 +146,11 @@ struct HfCandidateSelectorLcPidMl { } if (retrieveSuccess) { auto session = model.getSession(); -#if __has_include() - auto inputShapes = session->GetInputShapes(); -#else std::vector> inputShapes; Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < session->GetInputCount(); ++i) { inputShapes.emplace_back(session->GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif if (inputShapes[0][0] < 0) { LOGF(warning, "Model for Lc with negative input shape likely because converted with hummingbird, setting it to 1."); inputShapes[0][0] = 1; diff --git a/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx b/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx index 53df1ed2dfe..a4a026a005b 100644 --- a/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx +++ b/PWGHF/TableProducer/candidateSelectorLcToK0sP.cxx @@ -17,22 +17,37 @@ /// Daniel Samitz, , Vienna /// Elisa Meninno, , Vienna -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseLcToK0sP.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" +#include "Common/DataModel/PIDResponseCombined.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::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx index ce5787b730a..d65b56a40a9 100644 --- a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx +++ b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaKa.cxx @@ -13,17 +13,32 @@ /// \brief Omegac0 → Omega Ka selection task /// \author Federica Zanone , Heidelberg University -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.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 + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx index 24cb43ca348..7b31151af9d 100644 --- a/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorOmegac0ToOmegaPi.cxx @@ -16,23 +16,40 @@ /// \author Yunfan Liu , China University of Geosciences /// \author Fabio Catalano , University of Houston -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.h" - -#include "PWGHF/Core/HfMlResponse.h" #include "PWGHF/Core/HfMlResponseOmegacToOmegaPi.h" #include "PWGHF/Core/SelectorCuts.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 +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::framework; @@ -552,7 +569,7 @@ struct HfCandidateSelectorToOmegaPi { } // Chi2Geo/NDF V0&Casc&Omegac selection - if ((candidate.v0Chi2OverNdf() > KfconfigurableGroup.v0Chi2OverNdfMax) || (candidate.cascChi2OverNdf() > KfconfigurableGroup.cascChi2OverNdfMax) || (candidate.omegacChi2OverNdf() > KfconfigurableGroup.omegacChi2OverNdfMax)) { + if ((candidate.v0Chi2OverNdf() > KfconfigurableGroup.v0Chi2OverNdfMax) || (candidate.v0Chi2OverNdf() < 0) || (candidate.cascChi2OverNdf() > KfconfigurableGroup.cascChi2OverNdfMax) || (candidate.cascChi2OverNdf() < 0) || (candidate.omegacChi2OverNdf() > KfconfigurableGroup.omegacChi2OverNdfMax) || (candidate.omegacChi2OverNdf() < 0)) { resultSelections = false; registry.fill(HIST("hSelChi2GeooverNDFV0_Casc_Omegac"), 0); } else { @@ -560,7 +577,7 @@ struct HfCandidateSelectorToOmegaPi { } // Chi2Topo/NDF (chi2TopoV0ToCasc chi2TopoOmegacToPv chi2TopoCascToOmegac chi2TopoCascToPv) selection (???????????/NDF of which particle????????) - if ((candidate.chi2TopoV0ToCasc() > KfconfigurableGroup.chi2TopoV0ToCascMax) || (candidate.chi2TopoOmegacToPv() > KfconfigurableGroup.chi2TopoOmegacToPvMax) || (candidate.chi2TopoCascToOmegac() > KfconfigurableGroup.chi2TopoCascToOmegacMax) || (candidate.chi2TopoCascToPv() > KfconfigurableGroup.chi2TopoCascToPvMax)) { + if ((candidate.chi2TopoV0ToCasc() > KfconfigurableGroup.chi2TopoV0ToCascMax) || (candidate.chi2TopoV0ToCasc() < 0) || (candidate.chi2TopoOmegacToPv() > KfconfigurableGroup.chi2TopoOmegacToPvMax) || (candidate.chi2TopoOmegacToPv() < 0) || (candidate.chi2TopoCascToOmegac() > KfconfigurableGroup.chi2TopoCascToOmegacMax) || (candidate.chi2TopoCascToOmegac() < 0) || (candidate.chi2TopoCascToPv() > KfconfigurableGroup.chi2TopoCascToPvMax) || (candidate.chi2TopoCascToPv() < 0)) { resultSelections = false; registry.fill(HIST("hSelChi2TopooverNDFV0_Casc_Omegac"), 0); } else { diff --git a/PWGHF/TableProducer/candidateSelectorOmegac0Xic0ToOmegaKa.cxx b/PWGHF/TableProducer/candidateSelectorOmegac0Xic0ToOmegaKa.cxx new file mode 100644 index 00000000000..3bb9e410347 --- /dev/null +++ b/PWGHF/TableProducer/candidateSelectorOmegac0Xic0ToOmegaKa.cxx @@ -0,0 +1,720 @@ +// 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 candidateSelectorOmegaKa0Xic0ToOmegaKa.cxx +/// \brief OmegaKa0 Xic0 → Omega Ka selection task +/// \author Federica Zanone , Heidelberg University +/// \author Ruiqi Yin , Fudan University + +#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 "PWGHF/Core/HfMlResponseOmegaKaToOmegaKa.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" + +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::analysis; + +enum PidInfoStored { + PiFromLam = 0, + PrFromLam, + KaFromCasc, + KaFromCharm +}; + +/// Struct for applying OmegaKa -> Omega Ka selection cuts +struct HfCandidateSelectorToOmegaKa { + Produces hfSelToOmegaKaKf; + // Produces hfMlSelToOmegaKa; + + // LF analysis selections + Configurable radiusCascMin{"radiusCascMin", 0.5, "Min cascade radius"}; + Configurable radiusV0Min{"radiusV0Min", 1.1, "Min V0 radius"}; + Configurable cosPAV0Min{"cosPAV0Min", 0.97, "Min valueCosPA V0"}; + Configurable cosPACascMin{"cosPACascMin", 0.97, "Min value CosPA cascade"}; + Configurable dcaCascDauMax{"dcaCascDauMax", 1.0, "Max DCA cascade daughters"}; + Configurable dcaV0DauMax{"dcaV0DauMax", 1.0, "Max DCA V0 daughters"}; + Configurable dcaBachToPvMin{"dcaBachToPvMin", 0.04, "DCA Bach To PV"}; + Configurable v0MassWindow{"v0MassWindow", 0.01, "V0 mass window"}; + Configurable cascadeMassWindow{"cascadeMassWindow", 0.01, "Cascade mass window"}; + Configurable applyTrkSelLf{"applyTrkSelLf", true, "Apply track selection for LF daughters"}; + + // topological cuts + Configurable> binsPt{"binsPt", std::vector{hf_cuts_omegacxic_to_omega_ka::vecBinsPt}, "pT bin limits"}; + Configurable> cuts{"cuts", {hf_cuts_omegacxic_to_omega_ka::Cuts[0], hf_cuts_omegacxic_to_omega_ka::NBinsPt, hf_cuts_omegacxic_to_omega_ka::NCutVars, hf_cuts_omegacxic_to_omega_ka::labelsPt, hf_cuts_omegacxic_to_omega_ka::labelsCutVar}, "OmegaC0 candidate selection per pT bin"}; + + // limit charm baryon invariant mass spectrum + Configurable invMassCharmBaryonMin{"invMassCharmBaryonMin", 2.0, "Lower limit invariant mass spectrum charm baryon"}; // Xic0:2.470 Omegac0:2.695 + Configurable invMassCharmBaryonMax{"invMassCharmBaryonMax", 3.1, "Upper limit invariant mass spectrum charm baryon"}; + + // kinematic selections + Configurable etaTrackCharmBachMax{"etaTrackCharmBachMax", 0.8, "Max absolute value of eta for charm baryon bachelor"}; + Configurable etaTrackLFDauMax{"etaTrackLFDauMax", 0.8, "Max absolute value of eta for V0 and cascade daughters"}; + Configurable ptCascMin{"ptCascMin", 0.1, "Min pT kaon <- casc"}; + Configurable ptKaFromCharmBaryonMin{"ptKaFromCharmBaryonMin", 0.2, "Min pT Ka <- charm baryon"}; + + Configurable impactParameterXYKaFromCharmBaryonMin{"impactParameterXYKaFromCharmBaryonMin", 0., "Min dcaxy pi from charm baryon track to PV"}; + Configurable impactParameterXYKaFromCharmBaryonMax{"impactParameterXYKaFromCharmBaryonMax", 10., "Max dcaxy pi from charm baryon track to PV"}; + Configurable impactParameterXYCascMin{"impactParameterXYCascMin", 0., "Min dcaxy cascade track to PV"}; + Configurable impactParameterXYCascMax{"impactParameterXYCascMax", 10., "Max dcaxy cascade track to PV"}; + + Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; + Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; + + Configurable dcaCharmBaryonDauMax{"dcaCharmBaryonDauMax", 2.0, "Max DCA charm baryon daughters"}; + + // 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"}; + + Configurable ptKaPidTpcMin{"ptKaPidTpcMin", -1, "Lower bound of track pT for TPC PID for kaon selection"}; + Configurable ptKaPidTpcMax{"ptKaPidTpcMax", 9999.9, "Upper bound of track pT for TPC PID for kaon selection"}; + Configurable nSigmaTpcKaMax{"nSigmaTpcKaMax", 3., "Nsigma cut on TPC only for kaon selection"}; + Configurable nSigmaTpcCombinedKaMax{"nSigmaTpcCombinedKaMax", 0., "Nsigma cut on TPC combined with TOF for kaon 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"}; + + Configurable ptKaPidTofMin{"ptKaPidTofMin", -1, "Lower bound of track pT for TOF PID for kaon selection"}; + Configurable ptKaPidTofMax{"ptKaPidTofMax", 9999.9, "Upper bound of track pT for TOF PID for kaon selection"}; + Configurable nSigmaTofKaMax{"nSigmaTofKaMax", 3., "Nsigma cut on TOF only for kaon selection"}; + Configurable nSigmaTofCombinedKaMax{"nSigmaTofCombinedKaMax", 0., "Nsigma cut on TOF combined with TOF for kaon selection"}; + + // detector clusters 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"}; + + ConfigurableAxis thnConfigAxisMass{"thnConfigAxisMass", {120, 2.4, 3.1}, "Cand. inv-mass bins"}; + ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {100, 0, 20}, "Cand. pT bins"}; + ConfigurableAxis thnConfigAxisCent{"thnConfigAxisCent", {100, 0, 100}, "Centrality bins"}; + ConfigurableAxis thnConfigAxisPtKaon{"thnConfigAxisPtKaon", {100, 0, 10}, "PtPion from Omegac0 bins"}; + + struct : ConfigurableGroup { + //// KF selection + std::string prefix = "kfSel"; + Configurable applyCompetingCascRejection{"applyCompetingCascRejection", false, "Apply competing Xi(for OmegaKa) rejection"}; + Configurable cascadeRejMassWindow{"cascadeRejMassWindow", 0.01, "competing Xi(for OmegaKa) rejection mass window"}; + Configurable v0LdlMin{"v0LdlMin", 3., "Minimum value of l/dl of V0"}; // l/dl and Chi2 are to be determined + Configurable cascLdlMin{"cascLdlMin", 1., "Minimum value of l/dl of casc"}; + Configurable omegaKaLdlMax{"omegaKaLdlMax", 5., "Maximum value of l/dl of OmegaKa"}; + Configurable cTauOmegaKaMax{"cTauOmegaKaMax", 0.4, "lifetime τ of OmegaKa"}; + Configurable v0Chi2OverNdfMax{"v0Chi2OverNdfMax", 100., "Maximum chi2Geo/NDF of V0"}; + Configurable cascChi2OverNdfMax{"cascChi2OverNdfMax", 100., "Maximum chi2Geo/NDF of casc"}; + Configurable omegaKaChi2OverNdfMax{"omegaKaChi2OverNdfMax", 100., "Maximum chi2Geo/NDF of OmegaKa"}; + Configurable chi2TopoV0ToCascMax{"chi2TopoV0ToCascMax", 100., "Maximum chi2Topo/NDF of V0ToCasc"}; + Configurable chi2TopoKaToCascMax{"chi2TopoKaToCascMax", 100., "Maximum chi2Topo/NDF of KaToCasc"}; + Configurable chi2TopoOmegaKaToPvMax{"chi2TopoOmegaKaToPvMax", 100., "Maximum chi2Topo/NDF of OmegaKaToPv"}; + Configurable chi2TopoCascToOmegaKaMax{"chi2TopoCascToOmegaKaMax", 100., "Maximum chi2Topo/NDF of CascToOmegaKa"}; + Configurable chi2TopoKaToOmegaKaMax{"chi2TopoKaToOmegaKaMax", 100., "Maximum chi2Topo/NDF of KaToOmegaKa"}; + Configurable chi2TopoCascToPvMax{"chi2TopoCascToPvMax", 100., "Maximum chi2Topo/NDF of CascToPv"}; + Configurable chi2TopoKaFromOmegaKaToPvMax{"chi2TopoKaFromOmegaKaToPvMax", 100., "Maximum chi2Topo/NDF of CascToPv"}; + Configurable decayLenOmegaKaMax{"decayLenOmegaKaMax", 1.5, "Maximum decay lengthXY of OmegaKa"}; + Configurable decayLenCascMin{"decayLenCascMin", 1., "Minimum decay lengthXY of Cascade"}; + Configurable decayLenLambdaMin{"decayLenLambdaMin", 0., "Minimum decay lengthXY of V0"}; + Configurable cosPaCascToOmegaKaMin{"cosPaCascToOmegaKaMin", 0.995, "Minimum cosPA of cascade<-OmegaKa"}; + Configurable cosPaV0ToCascMin{"cosPaV0ToCascMin", 0.99, "Minimum cosPA of V0<-cascade"}; + } KfconfigurableGroup; + + TrackSelectorPi selectorPion; + TrackSelectorPr selectorProton; + TrackSelectorKa selectorKaon; + + using TracksSel = soa::Join; + using TracksSelLf = soa::Join; + + HistogramRegistry registry{"registry"}; // for QA of selections + + OutputObj hInvMassCharmBaryon{TH1D("hInvMassCharmBaryon", "Charm baryon invariant mass;inv mass;entries", 500, 2.0, 3.1)}; + OutputObj hPtCharmBaryon{TH1D("hPtCharmBaryon", "Charm baryon transverse momentum before sel;Pt;entries", 3000, 0., 30)}; + OutputObj hPtKaFromCharmBaryon{TH1D("hPtKaFromCharmBaryon", "Ka from charm baryon transverse momentum before sel;Pt;entries", 2000, 0., 20)}; + + void init(InitContext const&) + { + const AxisSpec thnAxisMass{thnConfigAxisMass, "inv. mass (#Omega#Ka) (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{thnConfigAxisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisPtKaon{thnConfigAxisPtKaon, "Pt of Kaon from Omegac0."}; + std::vector axes = {thnAxisMass, thnAxisPt, thnAxisPtKaon}; + registry.add("hMassVsPtVsPtKaon", "Thn for Omegac0 or Xic candidates with InvmassOmegaKa&pT&pTKa", HistType::kTHnSparseF, axes); + registry.get(HIST("hMassVsPtVsPtKaon"))->Sumw2(); + + 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); + + selectorKaon.setRangePtTpc(ptKaPidTpcMin, ptKaPidTpcMax); + selectorKaon.setRangeNSigmaTpc(-nSigmaTpcKaMax, nSigmaTpcKaMax); + selectorKaon.setRangeNSigmaTpcCondTof(-nSigmaTpcCombinedKaMax, nSigmaTpcCombinedKaMax); + selectorKaon.setRangePtTof(ptKaPidTofMin, ptKaPidTofMax); + selectorKaon.setRangeNSigmaTof(-nSigmaTofKaMax, nSigmaTofKaMax); + selectorKaon.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedKaMax, nSigmaTofCombinedKaMax); + + const AxisSpec axisSel{2, -0.5, 1.5, "status"}; + + registry.add("hSelPID", "hSelPID;status;entries", {HistType::kTH1D, {{12, 0., 12.}}}); + registry.add("hStatusCheck", "Check consecutive selections status;status;entries", {HistType::kTH1D, {{12, 0., 12.}}}); + + // for QA of the selections (bin 0 -> candidates that did not pass the selection, bin 1 -> candidates that passed the selection) + registry.add("hSelSignDec", "hSelSignDec;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelEtaPosV0Dau", "hSelEtaPosV0Dau;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelEtaNegV0Dau", "hSelEtaNegV0Dau;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelEtaKaFromCasc", "hSelEtaKaFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelEtaKaFromCharm", "hSelEtaKaFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelRadCasc", "hSelRadCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelRadV0", "hSelRadV0;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelCosPACasc", "hSelCosPACasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelCosPAV0", "hSelCosPAV0;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelDCACascDau", "hSelDCACascDau;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelDCAV0Dau", "hSelDCAV0Dau;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelDCACharmDau", "hSelDCACharmDau;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelDCAXYPrimPi", "hSelDCAXYPrimPi;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelDCAZPrimPi", "hSelDCAZPrimPi;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelDCAXYCasc", "hSelDCAXYCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelKfPtOmega", "hSelKfPtOmega;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelPtKaFromCharm", "hSelPtKaFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelTPCQualityKaFromCharm", "hSelTPCQualityKaFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelTPCQualityPiFromLam", "hSelTPCQualityPiFromLam;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelTPCQualityPrFromLam", "hSelTPCQualityPrFromLam;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelTPCQualityKaFromCasc", "hSelTPCQualityKaFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelITSQualityKaFromCharm", "hSelITSQualityKaFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelMassLam", "hSelMassLam;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelMassCasc", "hSelMassCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelMassCharmBaryon", "hSelMassCharmBaryon;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelDcaXYToPvKaFromCasc", "hSelDcaXYToPvKaFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelPtOmegaKa", "hSelPtOmegaKa;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelCompetingCasc", "hSelCompetingCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelV0_Casc_OmegaKaldl", "hSelV0_Casc_OmegaKaldl;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelctauOmegaKa", "hSelctauOmegaKa;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelChi2GeooverNDFV0_Casc_OmegaKa", "hSelChi2GeooverNDFV0_Casc_OmegaKa;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelChi2TopooverNDFV0_Casc_OmegaKa", "hSelChi2TopooverNDFV0_Casc_OmegaKa;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSeldecayLenOmegaKa_Casc_V0", "hSeldecayLenOmegaKa_Casc_V0;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelcosPaCascToOmegaKa_V0ToCasc", "hSelcosPaCascToOmegaKa_V0ToCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hInvMassXiMinus_rej_cut", "hInvMassXiMinus_rej_cut", kTH1D, {{1000, 1.25f, 1.65f}}); + } + // for pT-dependent cuts (other selections will move into this in futrue) + // \param hfCandOmegaKa is candidate + // return true if candidate passes all cuts + template + bool selectionTopol(const T1& hfCandOmegaKa) + { + auto candpT = hfCandOmegaKa.kfPtOmegaKa(); + auto KaPtFromOmegaKa = hfCandOmegaKa.kfPtKaFromOmegaKa(); + int pTBin = findBin(binsPt, candpT); + if (pTBin == -1) { + return false; + } + + // check that the candidate pT is within the analysis range + if (candpT <= ptCandMin || candpT >= ptCandMax) { + registry.fill(HIST("hSelPtOmegaKa"), 0); + return false; + } else { + registry.fill(HIST("hSelPtOmegaKa"), 1); + } + + // check that the candidate pT is within the analysis range + if (KaPtFromOmegaKa < cuts->get(pTBin, "pT ka from OmegaKa")) { + registry.fill(HIST("hSelPtKaFromCharm"), 0); + return false; + } else { + registry.fill(HIST("hSelPtKaFromCharm"), 1); + } + + return true; + } // end template + + void process(aod::HfCandToOmegaKaKf const& candidates, + TracksSel const& tracks, + TracksSelLf const& lfTracks) + { + // looping over charm baryon candidates + for (const auto& candidate : candidates) { + // initializing selection flags + bool statusPidLambda = false; + bool statusPidCascade = false; + bool statusPidCharmBaryon = false; + + bool statusInvMassLambda = false; + bool statusInvMassCascade = false; + bool statusInvMassCharmBaryon = false; + + bool resultSelections = true; // True if the candidate passes all the selections, False otherwise + + int infoTpcStored = 0; + int infoTofStored = 0; + + auto trackV0PosDauId = candidate.posTrackId(); // positive V0 daughter + auto trackV0NegDauId = candidate.negTrackId(); // negative V0 daughter + auto trackKaFromCascId = candidate.bachelorId(); // kaon <- cascade + auto trackKaFromCharmId = candidate.bachelorFromCharmBaryonId(); // pion <- charm baryon + auto trackV0PosDau = lfTracks.rawIteratorAt(trackV0PosDauId); + auto trackV0NegDau = lfTracks.rawIteratorAt(trackV0NegDauId); + auto trackKaFromCasc = lfTracks.rawIteratorAt(trackKaFromCascId); + auto trackKaFromCharm = tracks.rawIteratorAt(trackKaFromCharmId); + + auto trackPiFromLam = trackV0NegDau; + auto trackPrFromLam = trackV0PosDau; + + 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 if (signDecay < 0) { + registry.fill(HIST("hSelSignDec"), 0); // particle decay + } + + // pt-dependent selection + if (!selectionTopol(candidate)) { + resultSelections = false; + } + + // eta selection + double etaV0DauPr = candidate.etaV0DauPr(); + double etaV0DauPi = candidate.etaV0DauPi(); + double etaKaFromCasc = candidate.etaBachFromCasc(); + double etaKaFromCharmBaryon = candidate.etaBachFromCharmBaryon(); + if (std::abs(etaV0DauPr) > etaTrackLFDauMax) { + resultSelections = false; + registry.fill(HIST("hSelEtaPosV0Dau"), 0); + } else { + registry.fill(HIST("hSelEtaPosV0Dau"), 1); + } + if (std::abs(etaV0DauPi) > etaTrackLFDauMax) { + resultSelections = false; + registry.fill(HIST("hSelEtaNegV0Dau"), 0); + } else { + registry.fill(HIST("hSelEtaNegV0Dau"), 1); + } + if (std::abs(etaKaFromCasc) > etaTrackLFDauMax) { + resultSelections = false; + registry.fill(HIST("hSelEtaKaFromCasc"), 0); + } else { + registry.fill(HIST("hSelEtaKaFromCasc"), 1); + } + if (std::abs(etaKaFromCharmBaryon) > etaTrackCharmBachMax) { + resultSelections = false; + registry.fill(HIST("hSelEtaKaFromCharm"), 0); + } else { + registry.fill(HIST("hSelEtaKaFromCharm"), 1); + } + + // minimum radius cut (LFcut) + if (RecoDecay::sqrtSumOfSquares(candidate.xDecayVtxCascadeKf(), candidate.yDecayVtxCascadeKf()) < radiusCascMin) { + resultSelections = false; + registry.fill(HIST("hSelRadCasc"), 0); + } else { + registry.fill(HIST("hSelRadCasc"), 1); + } + if (RecoDecay::sqrtSumOfSquares(candidate.xDecayVtxV0Kf(), candidate.yDecayVtxV0Kf()) < radiusV0Min) { + resultSelections = false; + registry.fill(HIST("hSelRadV0"), 0); + } else { + registry.fill(HIST("hSelRadV0"), 1); + } + + // cosPA (LFcut) + if (candidate.cosPACasc() < cosPACascMin) { + resultSelections = false; + registry.fill(HIST("hSelCosPACasc"), 0); + } else { + registry.fill(HIST("hSelCosPACasc"), 1); + } + if (candidate.cosPAV0() < cosPAV0Min) { + resultSelections = false; + registry.fill(HIST("hSelCosPAV0"), 0); + } else { + registry.fill(HIST("hSelCosPAV0"), 1); + } + + // cascade and v0 daughters dca cut (LF cut) + if (candidate.dcaCascDau() > dcaCascDauMax) { + resultSelections = false; + registry.fill(HIST("hSelDCACascDau"), 0); + } else { + registry.fill(HIST("hSelDCACascDau"), 1); + } + + if (candidate.dcaV0Dau() > dcaV0DauMax) { + resultSelections = false; + registry.fill(HIST("hSelDCAV0Dau"), 0); + } else { + registry.fill(HIST("hSelDCAV0Dau"), 1); + } + + // dca charm baryon daughters cut + if (candidate.dcaCharmBaryonDau() > dcaCharmBaryonDauMax) { + resultSelections = false; + registry.fill(HIST("hSelDCACharmDau"), 0); + } else { + registry.fill(HIST("hSelDCACharmDau"), 1); + } + + // cut on charm bachelor Kaon dcaXY + if ((std::abs(candidate.impactParBachFromCharmBaryonXY()) < impactParameterXYKaFromCharmBaryonMin) || (std::abs(candidate.impactParBachFromCharmBaryonXY()) > impactParameterXYKaFromCharmBaryonMax)) { + resultSelections = false; + registry.fill(HIST("hSelDCAXYPrimPi"), 0); + } else { + registry.fill(HIST("hSelDCAXYPrimPi"), 1); + } + + // cut on cascade dcaXY + if ((std::abs(candidate.impactParCascXY()) < impactParameterXYCascMin) || (std::abs(candidate.impactParCascXY()) > impactParameterXYCascMax)) { + resultSelections = false; + registry.fill(HIST("hSelDCAXYCasc"), 0); + } else { + registry.fill(HIST("hSelDCAXYCasc"), 1); + } + + // Charm daughter pT selections + if (std::abs(candidate.kfPtOmega()) < ptCascMin) { + resultSelections = false; + registry.fill(HIST("hSelKfPtOmega"), 0); + } else { + registry.fill(HIST("hSelKfPtOmega"), 1); + } + if (std::abs(candidate.kfPtKaFromOmegaKa()) < ptKaFromCharmBaryonMin) { + resultSelections = false; + } + + // Competing Ξ rejection(KF) Try to reject cases in which the candidate has a an inv. mass compatibler to Xi (bachelor pion) instead of Omega (bachelor kaon) + if (KfconfigurableGroup.applyCompetingCascRejection) { + if (std::abs(candidate.invMassCascadeRej() - o2::constants::physics::MassXiMinus) < KfconfigurableGroup.cascadeRejMassWindow) { + resultSelections = false; + registry.fill(HIST("hSelCompetingCasc"), 0); + } else { + registry.fill(HIST("hSelCompetingCasc"), 1); + registry.fill(HIST("hInvMassXiMinus_rej_cut"), candidate.invMassCascadeRej()); + } + } + + // v0&Casc&OmegaKa ldl selection + if ((candidate.v0ldl() < KfconfigurableGroup.v0LdlMin) || (candidate.cascldl() < KfconfigurableGroup.cascLdlMin) || (candidate.omegaKaldl() > KfconfigurableGroup.omegaKaLdlMax)) { + resultSelections = false; + registry.fill(HIST("hSelV0_Casc_OmegaKaldl"), 0); + } else { + registry.fill(HIST("hSelV0_Casc_OmegaKaldl"), 1); + } + + // OmegaKa ctau selsection + if (candidate.cTauOmegaKa() > KfconfigurableGroup.cTauOmegaKaMax) { + resultSelections = false; + registry.fill(HIST("hSelctauOmegaKa"), 0); + } else { + registry.fill(HIST("hSelctauOmegaKa"), 1); + } + + // Chi2Geo/NDF V0&Casc&OmegaKa selection + if ((candidate.chi2GeoV0() > KfconfigurableGroup.v0Chi2OverNdfMax) || (candidate.chi2GeoV0() < 0) || (candidate.chi2GeoCasc() > KfconfigurableGroup.cascChi2OverNdfMax) || (candidate.chi2GeoCasc() < 0) || (candidate.chi2GeoOmegaKa() > KfconfigurableGroup.omegaKaChi2OverNdfMax) || (candidate.chi2GeoOmegaKa() < 0)) { + resultSelections = false; + registry.fill(HIST("hSelChi2GeooverNDFV0_Casc_OmegaKa"), 0); + } else { + registry.fill(HIST("hSelChi2GeooverNDFV0_Casc_OmegaKa"), 1); + } + + // Chi2Topo/NDF selection + if ((candidate.chi2TopoV0ToCasc() > KfconfigurableGroup.chi2TopoV0ToCascMax) || (candidate.chi2TopoV0ToCasc() < 0) || (candidate.chi2TopoKaToCasc() > KfconfigurableGroup.chi2TopoKaToCascMax) || (candidate.chi2TopoKaToCasc() < 0) || (candidate.chi2TopoCascToOmegaKa() > KfconfigurableGroup.chi2TopoCascToOmegaKaMax) || (candidate.chi2TopoCascToOmegaKa() < 0) || (candidate.chi2TopoKaToOmegaKa() > KfconfigurableGroup.chi2TopoKaToOmegaKaMax) || (candidate.chi2TopoKaToOmegaKa() < 0) || + (candidate.chi2TopoOmegaKaToPv() > KfconfigurableGroup.chi2TopoOmegaKaToPvMax) || (candidate.chi2TopoOmegaKaToPv() < 0) || (candidate.chi2TopoCascToPv() > KfconfigurableGroup.chi2TopoCascToPvMax) || (candidate.chi2TopoCascToPv() < 0) || (candidate.chi2TopoKaFromOmegaKaToPv() > KfconfigurableGroup.chi2TopoKaFromOmegaKaToPvMax) || (candidate.chi2TopoKaFromOmegaKaToPv() < 0)) { + resultSelections = false; + registry.fill(HIST("hSelChi2TopooverNDFV0_Casc_OmegaKa"), 0); + } else { + registry.fill(HIST("hSelChi2TopooverNDFV0_Casc_OmegaKa"), 1); + } + + // DecaylengthXY of OmegaKa&Casc&V0 selection + if ((std::abs(candidate.decLenCharmBaryon()) > KfconfigurableGroup.decayLenOmegaKaMax) || (std::abs(candidate.decLenCascade()) < KfconfigurableGroup.decayLenCascMin) || (std::abs(candidate.decLenV0()) < KfconfigurableGroup.decayLenLambdaMin)) { + resultSelections = false; + registry.fill(HIST("hSeldecayLenOmegaKa_Casc_V0"), 0); + } else { + registry.fill(HIST("hSeldecayLenOmegaKa_Casc_V0"), 1); + } + + // KFPA cut cosPaCascToOmegaKa cosPaV0ToCasc + if ((candidate.cosPaCascToOmegaKa() < KfconfigurableGroup.cosPaCascToOmegaKaMin) || (candidate.cosPaV0ToCasc() < KfconfigurableGroup.cosPaV0ToCascMin)) { + resultSelections = false; + registry.fill(HIST("hSelcosPaCascToOmegaKa_V0ToCasc"), 0); + } else { + registry.fill(HIST("hSelcosPaCascToOmegaKa_V0ToCasc"), 1); + } + + // TPC clusters selections + if (applyTrkSelLf) { + if (!isSelectedTrackTpcQuality(trackPiFromLam, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + registry.fill(HIST("hSelTPCQualityPiFromLam"), 0); + } else { + registry.fill(HIST("hSelTPCQualityPiFromLam"), 1); + } + if (!isSelectedTrackTpcQuality(trackPrFromLam, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + registry.fill(HIST("hSelTPCQualityPrFromLam"), 0); + } else { + registry.fill(HIST("hSelTPCQualityPrFromLam"), 1); + } + if (!isSelectedTrackTpcQuality(trackKaFromCasc, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + registry.fill(HIST("hSelTPCQualityKaFromCasc"), 0); + } else { + registry.fill(HIST("hSelTPCQualityKaFromCasc"), 1); + } + } + if (!isSelectedTrackTpcQuality(trackKaFromCharm, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + resultSelections = false; + registry.fill(HIST("hSelTPCQualityKaFromCharm"), 0); + } else { + registry.fill(HIST("hSelTPCQualityKaFromCharm"), 1); + } + + // ITS clusters selection + if (!isSelectedTrackItsQuality(trackKaFromCharm, nClustersItsMin, itsChi2PerClusterMax) || trackKaFromCharm.itsNClsInnerBarrel() < nClustersItsInnBarrMin) { + resultSelections = false; + registry.fill(HIST("hSelITSQualityKaFromCharm"), 0); + } else { + registry.fill(HIST("hSelITSQualityKaFromCharm"), 1); + } + + // track-level PID selection + + // for TrackSelectorPID + int statusPidPrFromLam = -999; + int statusPidPiFromLam = -999; + int statusPidKaFromCasc = -999; + int statusPidKaFromCharmBaryon = -999; + + if (usePidTpcOnly && usePidTpcTofCombined) { + LOGF(fatal, "Check the PID configurables, usePidTpcOnly and usePidTpcTofCombined can't have the same value"); + } else if (!usePidTpcOnly && !usePidTpcTofCombined) { + LOGF(fatal, "At least one PID method must be enabled"); + } + + if (trackPiFromLam.hasTPC()) { + SETBIT(infoTpcStored, PiFromLam); + } + if (trackPrFromLam.hasTPC()) { + SETBIT(infoTpcStored, PrFromLam); + } + if (trackKaFromCasc.hasTPC()) { + SETBIT(infoTpcStored, KaFromCasc); + } + if (trackKaFromCharm.hasTPC()) { + SETBIT(infoTpcStored, KaFromCharm); + } + if (trackPiFromLam.hasTOF()) { + SETBIT(infoTofStored, PiFromLam); + } + if (trackPrFromLam.hasTOF()) { + SETBIT(infoTofStored, PrFromLam); + } + if (trackKaFromCasc.hasTOF()) { + SETBIT(infoTofStored, KaFromCasc); + } + if (trackKaFromCharm.hasTOF()) { + SETBIT(infoTofStored, KaFromCharm); + } + + if (usePidTpcOnly) { + statusPidPrFromLam = selectorProton.statusTpc(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpc(trackPiFromLam); + statusPidKaFromCasc = selectorKaon.statusTpc(trackKaFromCasc); + statusPidKaFromCharmBaryon = selectorKaon.statusTpc(trackKaFromCharm); + } else if (usePidTpcTofCombined) { + statusPidPrFromLam = selectorProton.statusTpcOrTof(trackPrFromLam); + statusPidPiFromLam = selectorPion.statusTpcOrTof(trackPiFromLam); + statusPidKaFromCasc = selectorKaon.statusTpcOrTof(trackKaFromCasc); + statusPidKaFromCharmBaryon = selectorKaon.statusTpcOrTof(trackKaFromCharm); + } + + if (statusPidPrFromLam == TrackSelectorPID::Accepted && statusPidPiFromLam == TrackSelectorPID::Accepted) { + statusPidLambda = true; + if (resultSelections) { + registry.fill(HIST("hStatusCheck"), 0.5); + } + } else { + resultSelections = false; + } + + if (statusPidPrFromLam == TrackSelectorPID::Accepted && statusPidPiFromLam == TrackSelectorPID::Accepted && statusPidKaFromCasc == TrackSelectorPID::Accepted) { + statusPidCascade = true; + if (resultSelections) { + registry.fill(HIST("hStatusCheck"), 1.5); + } + } else { + resultSelections = false; + } + + if (statusPidPrFromLam == TrackSelectorPID::Accepted && statusPidPiFromLam == TrackSelectorPID::Accepted && statusPidKaFromCasc == TrackSelectorPID::Accepted && statusPidKaFromCharmBaryon == TrackSelectorPID::Accepted) { + statusPidCharmBaryon = true; + if (resultSelections) { + registry.fill(HIST("hStatusCheck"), 2.5); + } + } else { + resultSelections = false; + } + + // invariant mass cuts + double invMassLambda = candidate.invMassLambda(); + double invMassCascade = candidate.invMassCascade(); + double invMassCharmBaryon = candidate.invMassCharmBaryon(); + + if (std::abs(invMassLambda - o2::constants::physics::MassLambda0) < v0MassWindow) { + statusInvMassLambda = true; + registry.fill(HIST("hSelMassLam"), 1); + if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && resultSelections) { + registry.fill(HIST("hStatusCheck"), 3.5); + } + } else { + registry.fill(HIST("hSelMassLam"), 0); + resultSelections = false; + } + + if (std::abs(invMassCascade - o2::constants::physics::MassOmegaMinus) < cascadeMassWindow) { + statusInvMassCascade = true; + registry.fill(HIST("hSelMassCasc"), 1); + if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && statusInvMassLambda && resultSelections) { + registry.fill(HIST("hStatusCheck"), 4.5); + } + } else { + registry.fill(HIST("hSelMassCasc"), 0); + resultSelections = false; + } + + if ((invMassCharmBaryon >= invMassCharmBaryonMin) && (invMassCharmBaryon <= invMassCharmBaryonMax)) { + statusInvMassCharmBaryon = true; + registry.fill(HIST("hSelMassCharmBaryon"), 1); + if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && statusInvMassLambda && statusInvMassCascade && resultSelections) { + registry.fill(HIST("hStatusCheck"), 5.5); + } + } else { + registry.fill(HIST("hSelMassCharmBaryon"), 0); + resultSelections = false; + } + + hfSelToOmegaKaKf(statusPidLambda, statusPidCascade, statusPidCharmBaryon, statusInvMassLambda, statusInvMassCascade, statusInvMassCharmBaryon, resultSelections, infoTpcStored, infoTofStored, + trackKaFromCharm.tpcNSigmaKa(), trackKaFromCasc.tpcNSigmaKa(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), + trackKaFromCharm.tofNSigmaKa(), trackKaFromCasc.tofNSigmaKa(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); + + if (resultSelections) { + if (!statusPidLambda) { + registry.fill(HIST("hSelPID"), 0.5); + } + if (statusPidLambda) { + registry.fill(HIST("hSelPID"), 1.5); + } + if (!statusPidCascade) { + registry.fill(HIST("hSelPID"), 2.5); + } + if (statusPidCascade) { + registry.fill(HIST("hSelPID"), 3.5); + } + if (!statusPidCharmBaryon) { + registry.fill(HIST("hSelPID"), 4.5); + } + if (statusPidCharmBaryon) { + registry.fill(HIST("hSelPID"), 5.5); + } + if (!statusInvMassLambda) { + registry.fill(HIST("hSelPID"), 6.5); + } + if (statusInvMassLambda) { + registry.fill(HIST("hSelPID"), 7.5); + } + if (!statusInvMassCascade) { + registry.fill(HIST("hSelPID"), 8.5); + } + if (statusInvMassCascade) { + registry.fill(HIST("hSelPID"), 9.5); + } + if (!statusInvMassCharmBaryon) { + registry.fill(HIST("hSelPID"), 10.5); + } + if (statusInvMassCharmBaryon) { + registry.fill(HIST("hSelPID"), 11.5); + } + } + + if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && statusInvMassLambda && statusInvMassCascade && statusInvMassCharmBaryon && resultSelections) { + hInvMassCharmBaryon->Fill(invMassCharmBaryon); + hPtCharmBaryon->Fill(candidate.kfPtOmegaKa()); + hPtKaFromCharmBaryon->Fill(candidate.kfPtKaFromOmegaKa()); + registry.fill(HIST("hMassVsPtVsPtKaon"), + candidate.invMassCharmBaryon(), + candidate.kfPtOmegaKa(), + candidate.kfPtKaFromOmegaKa()); + } + } + } // end process +}; // end struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx index 8f118058f3e..4372e3cb40a 100644 --- a/PWGHF/TableProducer/candidateSelectorToXiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorToXiPi.cxx @@ -13,17 +13,32 @@ /// \brief Xic0 and Omegac0 → Xi Pi selection task /// \author Federica Zanone , Heidelberg University -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.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 + using namespace o2; using namespace o2::aod; using namespace o2::framework; diff --git a/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx b/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx index 81327bb70e1..88824d4d75d 100644 --- a/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx +++ b/PWGHF/TableProducer/candidateSelectorXic0ToXiPiKf.cxx @@ -14,23 +14,38 @@ /// \author Ran Tu , Fudan University /// \author Tao Fang , Central China Normal University -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfMlResponseXic0ToXiPiKf.h" #include "PWGHF/Core/SelectorCuts.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; @@ -48,16 +63,15 @@ struct HfCandidateSelectorXic0ToXiPiKf { Produces hfSelToXiPi; Produces hfMlToXiPi; - // LF analysis selections + // kinematic selections + Configurable etaTrackCharmBachMax{"etaTrackCharmBachMax", 0.8, "Max absolute value of eta for charm baryon bachelor"}; + Configurable etaTrackLFDauMax{"etaTrackLFDauMax", 0.8, "Max absolute value of eta for V0 and cascade daughters"}; + Configurable ptPiFromCascMin{"ptPiFromCascMin", 0.15, "Min pT pion <- casc"}; + + // minimum radius cut (LFcut) Configurable radiusCascMin{"radiusCascMin", 0.5, "Min cascade radius"}; Configurable radiusV0Min{"radiusV0Min", 1.1, "Min V0 radius"}; - Configurable cosPAV0Min{"cosPAV0Min", 0.97, "Min valueCosPA V0"}; - Configurable cosPACascMin{"cosPACascMin", 0.97, "Min value CosPA cascade"}; - Configurable dcaCascDauMax{"dcaCascDauMax", 1.0, "Max DCA cascade daughters"}; - Configurable dcaV0DauMax{"dcaV0DauMax", 1.0, "Max DCA V0 daughters"}; - Configurable dcaBachToPvMin{"dcaBachToPvMin", 0.04, "DCA Bach To PV"}; - Configurable dcaNegToPvMin{"dcaNegToPvMin", 0.06, "DCA Neg To PV"}; - Configurable dcaPosToPvMin{"dcaPosToPvMin", 0.06, "DCA Pos To PV"}; + Configurable v0MassWindow{"v0MassWindow", 0.01, "V0 mass window"}; Configurable cascadeMassWindow{"cascadeMassWindow", 0.01, "Cascade mass window"}; Configurable applyTrkSelLf{"applyTrkSelLf", true, "Apply track selection for LF daughters"}; @@ -66,27 +80,6 @@ struct HfCandidateSelectorXic0ToXiPiKf { Configurable invMassCharmBaryonMin{"invMassCharmBaryonMin", 2.0, "Lower limit invariant mass spectrum charm baryon"}; // 2.4 Omegac0 only Configurable invMassCharmBaryonMax{"invMassCharmBaryonMax", 3.1, "Upper limit invariant mass spectrum charm baryon"}; - // kinematic 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 pion <- casc"}; - Configurable ptPiFromCharmBaryonMin{"ptPiFromCharmBaryonMin", 0.2, "Min pT pi <- charm baryon"}; - - Configurable impactParameterXYPiFromCharmBaryonMin{"impactParameterXYPiFromCharmBaryonMin", 0., "Min dcaxy pi from charm baryon track to PV"}; - Configurable impactParameterXYPiFromCharmBaryonMax{"impactParameterXYPiFromCharmBaryonMax", 10., "Max dcaxy pi from charm baryon track to PV"}; - Configurable impactParameterZPiFromCharmBaryonMin{"impactParameterZPiFromCharmBaryonMin", 0., "Min dcaz pi from charm baryon track to PV"}; - Configurable impactParameterZPiFromCharmBaryonMax{"impactParameterZPiFromCharmBaryonMax", 10., "Max dcaz pi from charm baryon track to PV"}; - - Configurable impactParameterXYCascMin{"impactParameterXYCascMin", 0., "Min dcaxy cascade track to PV"}; - Configurable impactParameterXYCascMax{"impactParameterXYCascMax", 10., "Max dcaxy cascade track to PV"}; - Configurable impactParameterZCascMin{"impactParameterZCascMin", 0., "Min dcaz cascade track to PV"}; - Configurable impactParameterZCascMax{"impactParameterZCascMax", 10., "Max dcaz cascade track to PV"}; - - Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; - Configurable ptCandMax{"ptCandMax", 50., "Upper bound of candidate pT"}; - - Configurable dcaCharmBaryonDauMax{"dcaCharmBaryonDauMax", 2.0, "Max DCA charm baryon daughters"}; - // PID options Configurable usePidTpcOnly{"usePidTpcOnly", false, "Perform PID using only TPC"}; Configurable usePidTpcTofCombined{"usePidTpcTofCombined", true, "Perform PID using TPC & TOF"}; @@ -107,12 +100,12 @@ struct HfCandidateSelectorXic0ToXiPiKf { 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 nSigmaTofPrMax{"nSigmaTofPrMax", 5., "Nsigma cut on TOF only for proton selection"}; Configurable nSigmaTofCombinedPrMax{"nSigmaTofCombinedPrMax", 0., "Nsigma cut on TOF combined with TPC for proton selection"}; 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 nSigmaTofPiMax{"nSigmaTofPiMax", 5., "Nsigma cut on TOF only for pion selection"}; Configurable nSigmaTofCombinedPiMax{"nSigmaTofCombinedPiMax", 0., "Nsigma cut on TOF combined with TOF for pion selection"}; // detector clusters selections @@ -124,6 +117,10 @@ struct HfCandidateSelectorXic0ToXiPiKf { 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"}; + // topological 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", true, "Flag to apply ML selections"}; Configurable> binsPtMl{"binsPtMl", std::vector{hf_cuts_ml::vecBinsPt}, "pT bin limits for ML application"}; @@ -170,39 +167,25 @@ struct HfCandidateSelectorXic0ToXiPiKf { selectorPion.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedPiMax, nSigmaTofCombinedPiMax); const AxisSpec axisSel{2, -0.5, 1.5, "status"}; - - registry.add("hSelPID", "hSelPID;status;entries", {HistType::kTH1D, {{12, 0., 12.}}}); - registry.add("hStatusCheck", "Check consecutive selections status;status;entries", {HistType::kTH1D, {{12, 0., 12.}}}); - - // for QA of the selections (bin 0 -> candidates that did not pass the selection, bin 1 -> candidates that passed the selection) + registry.add("hStatusCheck", "Check consecutive selections status;status;entries", {HistType::kTH1D, {{3, 0., 3.}}}); + // sign of candidates registry.add("hSelSignDec", "hSelSignDec;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelEtaPosV0Dau", "hSelEtaPosV0Dau;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelEtaNegV0Dau", "hSelEtaNegV0Dau;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelEtaPiFromCasc", "hSelEtaPiFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelEtaPiFromCharm", "hSelEtaPiFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); + // basic selections (bin 0 -> candidates that did not pass the selection, bin 1 -> candidates that passed the selection) + registry.add("hSelPtPiFromCasc", "hSelPtPiFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelRadCasc", "hSelRadCasc;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelRadV0", "hSelRadV0;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelCosPACasc", "hSelCosPACasc;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelCosPAV0", "hSelCosPAV0;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDCACascDau", "hSelDCACascDau;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDCAV0Dau", "hSelDCAV0Dau;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDCACharmDau", "hSelDCACharmDau;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDCAXYPrimPi", "hSelDCAXYPrimPi;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDCAZPrimPi", "hSelDCAZPrimPi;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDCAXYCasc", "hSelDCAXYCasc;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDCAZCasc", "hSelDCAZCasc;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelPtPiFromCasc", "hSelPtPiFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelPtPiFromCharm", "hSelPtPiFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); + + // TPC and ITS selections (bin 0 -> candidates that did not pass the selection, bin 1 -> candidates that passed the selection) registry.add("hSelTPCQualityPiFromCharm", "hSelTPCQualityPiFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelTPCQualityPiFromLam", "hSelTPCQualityPiFromLam;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelTPCQualityPrFromLam", "hSelTPCQualityPrFromLam;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelTPCQualityPiFromCasc", "hSelTPCQualityPiFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelITSQualityPiFromCharm", "hSelITSQualityPiFromCharm;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelPID", "hSelPID;status;entries", {HistType::kTH1D, {{12, 0., 12.}}}); registry.add("hSelMassLam", "hSelMassLam;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelMassCasc", "hSelMassCasc;status;entries", {HistType::kTH1D, {axisSel}}); registry.add("hSelMassCharmBaryon", "hSelMassCharmBaryon;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDcaXYToPvV0Daughters", "hSelDcaXYToPvV0Daughters;status;entries", {HistType::kTH1D, {axisSel}}); - registry.add("hSelDcaXYToPvPiFromCasc", "hSelDcaXYToPvPiFromCasc;status;entries", {HistType::kTH1D, {axisSel}}); + registry.add("hSelMlXic0", "hSelMlXic0;status;entries", {HistType::kTH1D, {axisSel}}); if (applyMl) { hfMlResponse.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); @@ -225,6 +208,8 @@ struct HfCandidateSelectorXic0ToXiPiKf { // looping over charm baryon candidates for (const auto& candidate : candidates) { + outputMlXic0ToXiPiKf.clear(); + auto ptCand = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); bool resultSelections = true; // True if the candidate passes all the selections, False otherwise @@ -256,29 +241,15 @@ struct HfCandidateSelectorXic0ToXiPiKf { double etaV0NegDau = candidate.etaV0NegDau(); double etaPiFromCasc = candidate.etaBachFromCasc(); double etaPiFromCharmBaryon = candidate.etaBachFromCharmBaryon(); - if (std::abs(etaV0PosDau) > etaTrackLFDauMax) { - resultSelections = false; - registry.fill(HIST("hSelEtaPosV0Dau"), 0); - } else { - registry.fill(HIST("hSelEtaPosV0Dau"), 1); - } - if (std::abs(etaV0NegDau) > etaTrackLFDauMax) { - resultSelections = false; - registry.fill(HIST("hSelEtaNegV0Dau"), 0); - } else { - registry.fill(HIST("hSelEtaNegV0Dau"), 1); - } - if (std::abs(etaPiFromCasc) > etaTrackLFDauMax) { + if (std::abs(etaV0PosDau) > etaTrackLFDauMax || std::abs(etaV0NegDau) > etaTrackLFDauMax || std::abs(etaPiFromCasc) > etaTrackLFDauMax || std::abs(etaPiFromCharmBaryon) > etaTrackCharmBachMax) { resultSelections = false; - registry.fill(HIST("hSelEtaPiFromCasc"), 0); - } else { - registry.fill(HIST("hSelEtaPiFromCasc"), 1); } - if (std::abs(etaPiFromCharmBaryon) > etaTrackCharmBachMax) { + double ptPiFromCasc = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCasc(), candidate.pyBachFromCasc()); + if (std::abs(ptPiFromCasc) < ptPiFromCascMin) { resultSelections = false; - registry.fill(HIST("hSelEtaPiFromCharm"), 0); + registry.fill(HIST("hSelPtPiFromCasc"), 0); } else { - registry.fill(HIST("hSelEtaPiFromCharm"), 1); + registry.fill(HIST("hSelPtPiFromCasc"), 1); } // minimum radius cut (LFcut) @@ -295,103 +266,6 @@ struct HfCandidateSelectorXic0ToXiPiKf { registry.fill(HIST("hSelRadV0"), 1); } - // cosPA (LFcut) - if (candidate.cosPACasc() < cosPACascMin) { - resultSelections = false; - registry.fill(HIST("hSelCosPACasc"), 0); - } else { - registry.fill(HIST("hSelCosPACasc"), 1); - } - if (candidate.cosPAV0() < cosPAV0Min) { - resultSelections = false; - registry.fill(HIST("hSelCosPAV0"), 0); - } else { - registry.fill(HIST("hSelCosPAV0"), 1); - } - - // cascade and v0 daughters dca cut (LF cut) - if (candidate.dcaCascDau() > dcaCascDauMax) { - resultSelections = false; - registry.fill(HIST("hSelDCACascDau"), 0); - } else { - registry.fill(HIST("hSelDCACascDau"), 1); - } - - if (candidate.dcaV0Dau() > dcaV0DauMax) { - resultSelections = false; - registry.fill(HIST("hSelDCAV0Dau"), 0); - } else { - registry.fill(HIST("hSelDCAV0Dau"), 1); - } - - // dca charm baryon daughters cut - if (candidate.dcaCharmBaryonDau() > dcaCharmBaryonDauMax) { - resultSelections = false; - registry.fill(HIST("hSelDCACharmDau"), 0); - } else { - registry.fill(HIST("hSelDCACharmDau"), 1); - } - - // dcaXY v0 daughters to PV cut - if (std::abs(candidate.dcaXYToPvV0Dau0()) < dcaPosToPvMin || std::abs(candidate.dcaXYToPvV0Dau1()) < dcaNegToPvMin) { - resultSelections = false; - registry.fill(HIST("hSelDcaXYToPvV0Daughters"), 0); - } else { - registry.fill(HIST("hSelDcaXYToPvV0Daughters"), 1); - } - - // dcaXY ka <-- cascade to PV cut - if (std::abs(candidate.dcaXYToPvCascDau()) < dcaBachToPvMin) { - resultSelections = false; - registry.fill(HIST("hSelDcaXYToPvPiFromCasc"), 0); - } else { - registry.fill(HIST("hSelDcaXYToPvPiFromCasc"), 1); - } - - // cut on charm bachelor pion dcaXY and dcaZ - if ((std::abs(candidate.impactParBachFromCharmBaryonXY()) < impactParameterXYPiFromCharmBaryonMin) || (std::abs(candidate.impactParBachFromCharmBaryonXY()) > impactParameterXYPiFromCharmBaryonMax)) { - resultSelections = false; - registry.fill(HIST("hSelDCAXYPrimPi"), 0); - } else { - registry.fill(HIST("hSelDCAXYPrimPi"), 1); - } - if ((std::abs(candidate.impactParBachFromCharmBaryonZ()) < impactParameterZPiFromCharmBaryonMin) || (std::abs(candidate.impactParBachFromCharmBaryonZ()) > impactParameterZPiFromCharmBaryonMax)) { - resultSelections = false; - registry.fill(HIST("hSelDCAZPrimPi"), 0); - } else { - registry.fill(HIST("hSelDCAZPrimPi"), 1); - } - - // cut on cascade dcaXY and dcaZ - if ((std::abs(candidate.impactParCascXY()) < impactParameterXYCascMin) || (std::abs(candidate.impactParCascXY()) > impactParameterXYCascMax)) { - resultSelections = false; - registry.fill(HIST("hSelDCAXYCasc"), 0); - } else { - registry.fill(HIST("hSelDCAXYCasc"), 1); - } - if ((std::abs(candidate.impactParCascZ()) < impactParameterZCascMin) || (std::abs(candidate.impactParCascZ()) > impactParameterZCascMax)) { - resultSelections = false; - registry.fill(HIST("hSelDCAZCasc"), 0); - } else { - registry.fill(HIST("hSelDCAZCasc"), 1); - } - - // pT selections - double ptPiFromCasc = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCasc(), candidate.pyBachFromCasc()); - double ptPiFromCharmBaryon = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); - if (std::abs(ptPiFromCasc) < ptPiFromCascMin) { - resultSelections = false; - registry.fill(HIST("hSelPtPiFromCasc"), 0); - } else { - registry.fill(HIST("hSelPtPiFromCasc"), 1); - } - if (std::abs(ptPiFromCharmBaryon) < ptPiFromCharmBaryonMin) { - resultSelections = false; - registry.fill(HIST("hSelPtPiFromCharm"), 0); - } else { - registry.fill(HIST("hSelPtPiFromCharm"), 1); - } - // TPC clusters selections if (applyTrkSelLf) { if (!isSelectedTrackTpcQuality(trackPiFromLam, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { @@ -500,9 +374,9 @@ struct HfCandidateSelectorXic0ToXiPiKf { if (statusPidPrFromLam == TrackSelectorPID::Accepted && statusPidPiFromLam == TrackSelectorPID::Accepted && statusPidPiFromCasc == TrackSelectorPID::Accepted && statusPidPiFromCharmBaryon == TrackSelectorPID::Accepted) { statusPidCharmBaryon = true; - if (resultSelections) { - registry.fill(HIST("hStatusCheck"), 2.5); - } + } else { + registry.fill(HIST("hStatusCheck"), 2.5); + resultSelections = false; } // invariant mass cuts @@ -514,48 +388,46 @@ struct HfCandidateSelectorXic0ToXiPiKf { double invMassCascade = candidate.invMassCascade(); double invMassCharmBaryon = candidate.invMassCharmBaryon(); - if (std::abs(invMassLambda - o2::constants::physics::MassLambda0) < v0MassWindow) { - statusInvMassLambda = true; - registry.fill(HIST("hSelMassLam"), 1); - if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && resultSelections) { - registry.fill(HIST("hStatusCheck"), 3.5); + if (resultSelections) { + resultSelections = selectionTopolKf(candidate); + if (std::abs(invMassLambda - o2::constants::physics::MassLambda0) < v0MassWindow) { + statusInvMassLambda = true; + registry.fill(HIST("hSelMassLam"), 1); + } else { + resultSelections = false; + registry.fill(HIST("hSelMassLam"), 0); } - } else { - registry.fill(HIST("hSelMassLam"), 0); - } - if (std::abs(invMassCascade - o2::constants::physics::MassXiMinus) < cascadeMassWindow) { - statusInvMassCascade = true; - registry.fill(HIST("hSelMassCasc"), 1); - if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && statusInvMassLambda && resultSelections) { - registry.fill(HIST("hStatusCheck"), 4.5); + if (std::abs(invMassCascade - o2::constants::physics::MassXiMinus) < cascadeMassWindow) { + statusInvMassCascade = true; + registry.fill(HIST("hSelMassCasc"), 1); + } else { + resultSelections = false; + registry.fill(HIST("hSelMassCasc"), 0); } - } else { - registry.fill(HIST("hSelMassCasc"), 0); - } - if ((invMassCharmBaryon >= invMassCharmBaryonMin) && (invMassCharmBaryon <= invMassCharmBaryonMax)) { - statusInvMassCharmBaryon = true; - registry.fill(HIST("hSelMassCharmBaryon"), 1); - if (statusPidLambda && statusPidCascade && statusPidCharmBaryon && statusInvMassLambda && statusInvMassCascade && resultSelections) { - registry.fill(HIST("hStatusCheck"), 5.5); + if ((invMassCharmBaryon >= invMassCharmBaryonMin) && (invMassCharmBaryon <= invMassCharmBaryonMax)) { + statusInvMassCharmBaryon = true; + registry.fill(HIST("hSelMassCharmBaryon"), 1); + } else { + resultSelections = false; + registry.fill(HIST("hSelMassCharmBaryon"), 0); } - } else { - registry.fill(HIST("hSelMassCharmBaryon"), 0); } - // ML selections if (applyMl) { bool isSelectedMlXic0 = false; std::vector inputFeaturesXic0 = hfMlResponse.getInputFeatures(candidate, trackPiFromLam, trackPiFromCasc, trackPiFromCharm); - isSelectedMlXic0 = hfMlResponse.isSelectedMl(inputFeaturesXic0, ptCand, outputMlXic0ToXiPiKf); - if (!isSelectedMlXic0) { - continue; + if (!resultSelections) { + hfMlToXiPi(outputMlXic0ToXiPiKf); + } else { + isSelectedMlXic0 = hfMlResponse.isSelectedMl(inputFeaturesXic0, ptCand, outputMlXic0ToXiPiKf); + registry.fill(HIST("hSelMlXic0"), isSelectedMlXic0); + hfMlToXiPi(outputMlXic0ToXiPiKf); } - hfMlToXiPi(outputMlXic0ToXiPiKf); } - hfSelToXiPi(statusPidCharmBaryon, statusPidCascade, statusPidLambda, statusInvMassCharmBaryon, statusInvMassCascade, statusInvMassLambda, resultSelections, infoTpcStored, infoTofStored, + hfSelToXiPi(resultSelections, trackPiFromCharm.tpcNSigmaPi(), trackPiFromCasc.tpcNSigmaPi(), trackPiFromLam.tpcNSigmaPi(), trackPrFromLam.tpcNSigmaPr(), trackPiFromCharm.tofNSigmaPi(), trackPiFromCasc.tofNSigmaPi(), trackPiFromLam.tofNSigmaPi(), trackPrFromLam.tofNSigmaPr()); @@ -603,6 +475,125 @@ struct HfCandidateSelectorXic0ToXiPiKf { } } } // end process + + /// \param candidate is candidate + /// \return true if candidate passes all cuts + template + bool selectionTopolKf(const T& candidate) + { + auto candpT = RecoDecay::pt(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); + + int pTBin = findBin(binsPt, candpT); + if (pTBin == -1) { + return false; + } + + double ptPiFromCharmBaryon = RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()); + if (ptPiFromCharmBaryon <= cuts->get(pTBin, "ptPiFromCharmBaryon")) { + return false; + } + + // cosPA (LFcut) + if (candidate.cosPACasc() < cuts->get(pTBin, "cosPACasc")) { + return false; + } + if (candidate.cosPAV0() < cuts->get(pTBin, "cosPAV0")) { + return false; + } + if (candidate.cosPaCascToXic() < cuts->get(pTBin, "cosPaCascToXic")) { + return false; + } + if (candidate.cosPaV0ToCasc() < cuts->get(pTBin, "cosPaV0ToCasc")) { + return false; + } + + // dca cut + if (candidate.dcaCharmBaryonDau() > cuts->get(pTBin, "dcaCharmBaryonDau")) { + return false; + } + if (candidate.dcaCascDau() > cuts->get(pTBin, "dcaCascDau")) { + return false; + } + + if (candidate.dcaV0Dau() > cuts->get(pTBin, "dcaV0Dau")) { + return false; + } + + // dcaXY pion <-- cascade to PV cut + if (std::abs(candidate.dcaXYToPvCascDau()) < cuts->get(pTBin, "dcaXYToPvCascDau")) { + return false; + } + + // dcaXY v0 daughters to PV cut + if (std::abs(candidate.dcaXYToPvV0Dau0()) < cuts->get(pTBin, "dcaXYToPvV0Dau0") || std::abs(candidate.dcaXYToPvV0Dau1()) < cuts->get(pTBin, "dcaXYToPvV0Dau0")) { + return false; + } + + // dacXY pion <-- Xic0 to PV cut + if (std::abs(candidate.kfDcaXYPiFromXic()) > cuts->get(pTBin, "kfDcaXYPiFromXic")) { + return false; + } + + // dacXY cascade to PV cut + if (std::abs(candidate.kfDcaXYCascToPv()) > cuts->get(pTBin, "kfDcaXYCascToPv")) { + return false; + } + + // Chi2Geo + if (candidate.chi2GeoXic() < 0 || candidate.chi2GeoXic() > cuts->get(pTBin, "chi2GeoXic")) { + return false; + } + if (candidate.chi2GeoCasc() < 0 || candidate.chi2GeoCasc() > cuts->get(pTBin, "chi2GeoCasc")) { + return false; + } + if (candidate.chi2GeoV0() < 0 || candidate.chi2GeoV0() > cuts->get(pTBin, "chi2GeoV0")) { + return false; + } + + // Chi2Topo + if (candidate.chi2TopoXicToPv() < 0 || candidate.chi2TopoXicToPv() > cuts->get(pTBin, "chi2TopoXicToPv")) { + return false; + } + if (candidate.chi2TopoPiFromXicToPv() < 0 || candidate.chi2TopoPiFromXicToPv() > cuts->get(pTBin, "chi2TopoPiFromXicToPv")) { + return false; + } + if (candidate.chi2TopoCascToPv() < 0 || candidate.chi2TopoCascToPv() > cuts->get(pTBin, "chi2TopoCascToPv")) { + return false; + } + if (candidate.chi2TopoV0ToPv() > 0 && candidate.chi2TopoV0ToPv() < cuts->get(pTBin, "chi2TopoV0ToPv")) { + return false; + } + if (candidate.chi2TopoV0ToCasc() < 0 || candidate.chi2TopoV0ToCasc() > cuts->get(pTBin, "chi2TopoV0ToCasc")) { + return false; + } + if (candidate.chi2TopoCascToXic() < 0 || candidate.chi2TopoCascToXic() > cuts->get(pTBin, "chi2TopoCascToXic")) { + return false; + } + + // ldl + if (candidate.cascldl() < cuts->get(pTBin, "cascldl")) { + return false; + } + if (candidate.v0ldl() < cuts->get(pTBin, "v0ldl")) { + return false; + } + // decay length + if (std::abs(candidate.decayLenXYXic()) > cuts->get(pTBin, "decayLenXYXic")) { + return false; + } + if (std::abs(candidate.decayLenXYCasc()) < cuts->get(pTBin, "decayLenXYCasc")) { + return false; + } + if (std::abs(candidate.decayLenXYLambda()) < cuts->get(pTBin, "decayLenXYLambda")) { + return false; + } + // ctau + if (std::abs(candidate.cTauXic()) > cuts->get(pTBin, "cTauXic")) { + return false; + } + return true; + } + }; // end struct WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx index c986f9d1423..14b010aeaa2 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToPKPi.cxx @@ -17,21 +17,34 @@ /// \author Vít Kučera , CERN /// \author Cristina Terrevoli , INFN BARI -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - -#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/HfMlResponseXicToPKPi.h" +#include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" + +#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; diff --git a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx index 745a881d7ad..c4087a93e75 100644 --- a/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXicToXiPiPi.cxx @@ -15,19 +15,33 @@ /// \author Phil Lennart Stahlhut , Heidelberg University /// \author Jaeyoon Cho , Inha University -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfMlResponseXicToXiPiPi.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" // findBin function +#include "PWGHF/Utils/utilsAnalysis.h" + +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include using namespace o2; using namespace o2::aod; @@ -38,16 +52,12 @@ struct HfCandidateSelectorXicToXiPiPi { Produces hfSelXicToXiPiPiCandidate; Produces hfMlXicToXiPiPiCandidate; - Configurable ptCandMin{"ptCandMin", 0., "Lower bound of candidate pT"}; - Configurable ptCandMax{"ptCandMax", 36., "Upper bound of candidate pT"}; - // topological cuts Configurable> binsPt{"binsPt", std::vector{hf_cuts_xic_to_xi_pi_pi::vecBinsPt}, "pT bin limits"}; Configurable> cuts{"cuts", {hf_cuts_xic_to_xi_pi_pi::Cuts[0], hf_cuts_xic_to_xi_pi_pi::NBinsPt, hf_cuts_xic_to_xi_pi_pi::NCutVars, hf_cuts_xic_to_xi_pi_pi::labelsPt, hf_cuts_xic_to_xi_pi_pi::labelsCutVar}, "Xicplus candidate selection per pT bin"}; - // QA switch - Configurable activateQA{"activateQA", false, "Flag to enable QA histogram"}; + Configurable fillQAHistograms{"fillQAHistograms", false, "Switch to enable filling of QA histograms"}; // Enable PID Configurable usePid{"usePid", true, "Switch for PID selection at track level"}; - Configurable acceptPIDNotApplicable{"acceptPIDNotApplicable", true, "Switch to accept Status::NotApplicable [(NotApplicable for one detector) and (NotApplicable or Conditional for the other)] in PID selection"}; + Configurable useTpcPidOnly{"useTpcPidOnly", false, "Switch to use TPC PID only instead of TPC OR TOF)"}; // TPC PID Configurable ptPidTpcMin{"ptPidTpcMin", 0.15, "Lower bound of track pT for TPC PID"}; Configurable ptPidTpcMax{"ptPidTpcMax", 20., "Upper bound of track pT for TPC PID"}; @@ -58,6 +68,15 @@ struct HfCandidateSelectorXicToXiPiPi { Configurable ptPidTofMax{"ptPidTofMax", 20., "Upper bound of track pT for TOF PID"}; Configurable nSigmaTofMax{"nSigmaTofMax", 5., "Nsigma cut on TOF only"}; Configurable nSigmaTofCombinedMax{"nSigmaTofCombinedMax", 5., "Nsigma cut on TOF combined with TPC"}; + // TrackQualitySelection + Configurable doTrackQualitySelection{"doTrackQualitySelection", true, "Switch to apply track quality selections on final state daughter particles"}; + 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"}; // 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"}; @@ -77,13 +96,34 @@ struct HfCandidateSelectorXicToXiPiPi { o2::ccdb::CcdbApi ccdbApi; TrackSelectorPi selectorPion; TrackSelectorPr selectorProton; - - using TracksPidWithSel = soa::Join; + enum XicSelCriteria { All = 0, + Pt, + Mass, + Rapidity, + Eta, + EtaPionFromXicPlus, + EtaXiDaughters, + PtPionFromXicPlus, + Chi2SV, + MinDecayLength, + MaxInvMassXiPiPairs, + TpcTrackQualityXiDaughters, + TpcTrackQualityPiFromCharm, + ItsTrackQualityPiFromCharm, + PidSelected, + BdtSelected, + NSelectionCriteria }; + + using TracksExtraWPid = soa::Join; HistogramRegistry registry{"registry"}; void init(InitContext&) { + if ((doprocessData + doprocessMc) != 1) { + LOGP(fatal, "Enable exactly one process function at a time."); + } + if (usePid) { // pion selectorPion.setRangePtTpc(ptPidTpcMin, ptPidTpcMax); @@ -101,18 +141,109 @@ struct HfCandidateSelectorXicToXiPiPi { selectorProton.setRangeNSigmaTofCondTpc(-nSigmaTofCombinedMax, nSigmaTofCombinedMax); } - if (activateQA) { - constexpr int kNBinsSelections = 1 + SelectionStep::NSelectionSteps; - std::string labels[kNBinsSelections]; - labels[0] = "No selection"; - labels[1 + SelectionStep::RecoSkims] = "Skims selection"; - labels[1 + SelectionStep::RecoTopol] = "Skims & Topological selections"; - labels[1 + SelectionStep::RecoPID] = "Skims & Topological & PID selections"; - labels[1 + SelectionStep::RecoMl] = "Skims & Topological & PID & ML selections"; - static const AxisSpec axisSelections = {kNBinsSelections, 0.5, kNBinsSelections + 0.5, ""}; - registry.add("hSelections", "Selections;;#it{p}_{T} (GeV/#it{c})", {HistType::kTH2F, {axisSelections, {(std::vector)binsPt, "#it{p}_{T} (GeV/#it{c})"}}}); - for (int iBin = 0; iBin < kNBinsSelections; ++iBin) { - registry.get(HIST("hSelections"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + std::string labels[NSelectionCriteria]; + labels[All] = "All"; + labels[Pt] = "#it{p}_{T}"; + labels[Mass] = "#Delta M"; + labels[Rapidity] = "y"; + labels[Eta] = "#eta"; + labels[EtaPionFromXicPlus] = "#eta (#pi #leftarrow #Xi_{c}^{#plus})"; + labels[EtaXiDaughters] = "#eta (#Xi daughters)"; + labels[PtPionFromXicPlus] = "#it{p}_{T} (#pi #leftarrow #Xi_{c}^{#plus})"; + labels[Chi2SV] = "#chi^{2}_{SV}"; + labels[MinDecayLength] = "Decay length"; + labels[MaxInvMassXiPiPairs] = "M_{#Xi #pi}"; + labels[TpcTrackQualityXiDaughters] = "TPC track quality selection on #Xi daughters"; + labels[TpcTrackQualityPiFromCharm] = "TPC track quality selection on #pi #leftarrow #Xi_{c}^{#plus}"; + labels[ItsTrackQualityPiFromCharm] = "ITS track quality selection on #pi #leftarrow #Xi_{c}^{#plus}"; + labels[PidSelected] = "PID selection"; + labels[BdtSelected] = "BDT selection"; + + if (doprocessData) { + registry.add("hSelCandidates", ";;entries", {HistType::kTH1D, {{NSelectionCriteria, -0.5f, +NSelectionCriteria - 0.5f}}}); + for (int iBin = 0; iBin < NSelectionCriteria; ++iBin) { + registry.get(HIST("hSelCandidates"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + } else if (doprocessMc) { + registry.add("hSelCandidatesRecSig", ";;entries", {HistType::kTH1D, {{NSelectionCriteria, -0.5f, +NSelectionCriteria - 0.5f}}}); + registry.add("hSelCandidatesRecBkg", ";;entries", {HistType::kTH1D, {{NSelectionCriteria, -0.5f, +NSelectionCriteria - 0.5f}}}); + for (int iBin = 0; iBin < NSelectionCriteria; ++iBin) { + registry.get(HIST("hSelCandidatesRecSig"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + registry.get(HIST("hSelCandidatesRecBkg"))->GetXaxis()->SetBinLabel(iBin + 1, labels[iBin].data()); + } + } + + if (fillQAHistograms) { + if (doprocessData) { + // eta of all final state daughters + registry.add("hEtaPi0FromXic", ";#eta (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaPi1FromXic", ";#eta (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaBachelorPion", ";#eta (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaV0PosDau", ";;#eta (V0 pos. dau.);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaV0NegDau", ";;#eta (V0 neg. dau.);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + // pions from XicPlus + registry.add("hNClustersTpcPi0FromXic", ";#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcPi1FromXic", ";#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcPi0FromXic", ";#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcPi1FromXic", ";#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersItsPi0FromXic", ";#it{N}_{clusters}^{ITS} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{7, 0.5, 7.5}}}); + registry.add("hNClustersItsPi1FromXic", ";#it{N}_{clusters}^{ITS} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{7, 0.5, 7.5}}}); + registry.add("hNClustersItsInnBarrPi0FromXic", ";#it{N}_{clusters}^{ITS-IB} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{3, 0.5, 3.5}}}); + registry.add("hNClustersItsInnBarrPi1FromXic", ";#it{N}_{clusters}^{ITS-IB} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{3, 0.5, 3.5}}}); + // Xi daughters + registry.add("hNClustersTpcBachelorPion", ";#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcV0PosDau", ";#it{N}_{clusters}^{TPC} (V0 pos. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcV0NegDau", ";#it{N}_{clusters}^{TPC} (V0 neg. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcBachelorPion", ";#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcV0PosDau", ";#it{N}_{rows}^{TPC} (V0 pos. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcV0NegDau", ";#it{N}_{rows}^{TPC} (V0 neg. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + } else if (doprocessMc) { + // Reconstructed signal + // eta of all final state daughters + registry.add("hEtaPi0FromXicRecSig", "Reconstructed signal;#eta (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaPi1FromXicRecSig", "Reconstructed signal;#eta (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaBachelorPionRecSig", "Reconstructed signal;#eta (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaV0PosDauRecSig", "Reconstructed signal;#eta (V0 pos. dau.);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaV0NegDauRecSig", "Reconstructed signal;#eta (V0 neg. dau.);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + // pions from XicPlus + registry.add("hNClustersTpcPi0FromXicRecSig", "Reconstructed signal;#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcPi1FromXicRecSig", "Reconstructed signal;#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcPi0FromXicRecSig", "Reconstructed signal;#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcPi1FromXicRecSig", "Reconstructed signal;#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersItsPi0FromXicRecSig", "Reconstructed signal;#it{N}_{clusters}^{ITS} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{7, 0.5, 7.5}}}); + registry.add("hNClustersItsPi1FromXicRecSig", "Reconstructed signal;#it{N}_{clusters}^{ITS} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{7, 0.5, 7.5}}}); + registry.add("hNClustersItsInnBarrPi0FromXicRecSig", "Reconstructed signal;#it{N}_{clusters}^{ITS-IB} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{3, 0.5, 3.5}}}); + registry.add("hNClustersItsInnBarrPi1FromXicRecSig", "Reconstructed signal;#it{N}_{clusters}^{ITS-IB} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{3, 0.5, 3.5}}}); + // Xi daughters + registry.add("hNClustersTpcBachelorPionRecSig", "Reconstructed signal;#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcV0PosDauRecSig", "Reconstructed signal;#it{N}_{clusters}^{TPC} (V0 pos. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcV0NegDauRecSig", "Reconstructed signal;#it{N}_{clusters}^{TPC} (V0 neg. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcBachelorPionRecSig", "Reconstructed signal;#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcV0PosDauRecSig", "Reconstructed signal;#it{N}_{rows}^{TPC} (V0 pos. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcV0NegDauRecSig", "Reconstructed signal;#it{N}_{rows}^{TPC} (V0 neg. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + // Reconstructed background + // eta of all final state daughters + registry.add("hEtaPi0FromXicRecBkg", "Reconstructed background;#eta (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaPi1FromXicRecBkg", "Reconstructed background;#eta (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaBachelorPionRecBkg", "Reconstructed background;#eta (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaV0PosDauRecBkg", "Reconstructed background;#eta (V0 pos. dau.);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + registry.add("hEtaV0NegDauRecBkg", "Reconstructed background;#eta (V0 neg. dau.);entries", {HistType::kTH1F, {{150, -1.5f, +1.5f}}}); + // pions from XicPlus + registry.add("hNClustersTpcPi0FromXicRecBkg", "Reconstructed background;#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcPi1FromXicRecBkg", "Reconstructed background;#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcPi0FromXicRecBkg", "Reconstructed background;#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcPi1FromXicRecBkg", "Reconstructed background;#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersItsPi0FromXicRecBkg", "Reconstructed background;#it{N}_{clusters}^{ITS} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{7, 0.5, 7.5}}}); + registry.add("hNClustersItsPi1FromXicRecBkg", "Reconstructed background;#it{N}_{clusters}^{ITS} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{7, 0.5, 7.5}}}); + registry.add("hNClustersItsInnBarrPi0FromXicRecBkg", "Reconstructed background;#it{N}_{clusters}^{ITS-IB} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{3, 0.5, 3.5}}}); + registry.add("hNClustersItsInnBarrPi1FromXicRecBkg", "Reconstructed background;#it{N}_{clusters}^{ITS-IB} (#pi #leftarrow #Xi_{c}^{#plus});entries", {HistType::kTH1F, {{3, 0.5, 3.5}}}); + // Xi daughters + registry.add("hNClustersTpcBachelorPionRecBkg", "Reconstructed background;#it{N}_{clusters}^{TPC} (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcV0PosDauRecBkg", "Reconstructed background;#it{N}_{clusters}^{TPC} (V0 pos. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNClustersTpcV0NegDauRecBkg", "Reconstructed background;#it{N}_{clusters}^{TPC} (V0 neg. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcBachelorPionRecBkg", "Reconstructed background;#it{N}_{rows}^{TPC} (#pi #leftarrow #Xi);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcV0PosDauRecBkg", "Reconstructed background;#it{N}_{rows}^{TPC} (V0 pos. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); + registry.add("hNCrossedRowsTpcV0NegDauRecBkg", "Reconstructed background;#it{N}_{rows}^{TPC} (V0 neg. dau.);entries", {HistType::kTH1F, {{103, 49.5, 152.5}}}); } } @@ -129,183 +260,510 @@ struct HfCandidateSelectorXicToXiPiPi { } } - /// Conjugate-independent topological cuts - /// \param candidate is candidate - /// \return true if candidate passes all cuts - template - bool selectionTopol(const T1& hfCandXic) + /// Apply PID selection + /// \param statusPidPi0 PID status of prong1 with pion hypothesis + /// \param statusPidPi1 PID status of prong2 with pion hypothesis + /// \param statusPidPiXi PID status of bachelor track with pion hypothesis + /// \param statusPidPrLam PID status of V0 daughter with proton hypothesis + /// \param statusPidPiLam PID status of V0 daughter with pion hypothesis + /// \param usePidTpcOnly switch to check only TPC status + /// \return true if prongs of Xic candidate pass all PID selections + bool isSelectedPid(TrackSelectorPID::Status const statusPidPi0, + TrackSelectorPID::Status const statusPidPi1, + TrackSelectorPID::Status const statusPidPiXi, + TrackSelectorPID::Status const statusPidPrLam, + TrackSelectorPID::Status const statusPidPiLam, + bool const useTpcPidOnly) { - auto candpT = hfCandXic.pt(); - int pTBin = findBin(binsPt, candpT); - if (pTBin == -1) { + if (useTpcPidOnly) { + if ((statusPidPi0 != TrackSelectorPID::Accepted && statusPidPi0 != TrackSelectorPID::NotApplicable) || (statusPidPi1 != TrackSelectorPID::Accepted && statusPidPi1 != TrackSelectorPID::NotApplicable) || (statusPidPiXi != TrackSelectorPID::Accepted && statusPidPiXi != TrackSelectorPID::NotApplicable) || (statusPidPrLam != TrackSelectorPID::Accepted && statusPidPrLam != TrackSelectorPID::NotApplicable) || (statusPidPiLam != TrackSelectorPID::Accepted && statusPidPiLam != TrackSelectorPID::NotApplicable)) { + return false; + } + return true; + } + if (statusPidPi0 == TrackSelectorPID::Rejected || statusPidPi1 == TrackSelectorPID::Rejected || statusPidPiXi == TrackSelectorPID::Rejected || statusPidPrLam == TrackSelectorPID::Rejected || statusPidPiLam == TrackSelectorPID::Rejected) { return false; } + return true; + } + + /// Combine kinematic, topological, track quality and PID selections + /// \param hfCandXic Xic candidate + /// \param statusXicToXiPiPi Flag to store selection status as defined in hf_sel_candidate_xic::XicToXiPiPiSelectionStep + /// \param isMatchedSignal Flag to indicate if the candidate is matched to a genereated XiCplus MC particle + /// \return true if Xic candidate passes all selections, otherwise false + template + bool isSelectedXicToXiPiPiCandidateWoMl(XicCandidate const& hfCandXic, + TracksExtraWPid const&, + int& statusXicToXiPiPi, + bool const isMatchedSignal = false) + { + // Successful reconstruction + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoTotal); // RecoTotal = 0 --> statusXicToXiPiPi += 1 + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), All); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), All); + } + } else { + registry.fill(HIST("hSelCandidates"), All); + } + + // Retrieve daughter tracks + auto trackPi0 = hfCandXic.template pi0_as(); + auto trackPi1 = hfCandXic.template pi1_as(); + auto trackPiFromXi = hfCandXic.template bachelor_as(); + auto trackV0PosDau = hfCandXic.template posTrack_as(); + auto trackV0NegDau = hfCandXic.template negTrack_as(); + + if (fillQAHistograms) { + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hEtaPi0FromXicRecSig"), trackPi0.eta()); + registry.fill(HIST("hEtaPi1FromXicRecSig"), trackPi1.eta()); + registry.fill(HIST("hEtaBachelorPionRecSig"), trackPiFromXi.eta()); + registry.fill(HIST("hEtaV0PosDauRecSig"), trackV0PosDau.eta()); + registry.fill(HIST("hEtaV0NegDauRecSig"), trackV0NegDau.eta()); + registry.fill(HIST("hNClustersTpcPi0FromXicRecSig"), trackPi0.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcPi1FromXicRecSig"), trackPi1.tpcNClsFound()); + registry.fill(HIST("hNCrossedRowsTpcPi0FromXicRecSig"), trackPi0.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcPi1FromXicRecSig"), trackPi1.tpcNClsCrossedRows()); + registry.fill(HIST("hNClustersItsPi0FromXicRecSig"), trackPi0.itsNCls()); + registry.fill(HIST("hNClustersItsPi1FromXicRecSig"), trackPi1.itsNCls()); + registry.fill(HIST("hNClustersItsInnBarrPi0FromXicRecSig"), trackPi0.itsNClsInnerBarrel()); + registry.fill(HIST("hNClustersItsInnBarrPi1FromXicRecSig"), trackPi1.itsNClsInnerBarrel()); + registry.fill(HIST("hNClustersTpcBachelorPionRecSig"), trackPiFromXi.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcV0PosDauRecSig"), trackV0PosDau.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcV0NegDauRecSig"), trackV0NegDau.tpcNClsFound()); + registry.fill(HIST("hNCrossedRowsTpcBachelorPionRecSig"), trackPiFromXi.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcV0PosDauRecSig"), trackV0PosDau.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcV0NegDauRecSig"), trackV0NegDau.tpcNClsCrossedRows()); + } else { + registry.fill(HIST("hEtaPi0FromXicRecBkg"), trackPi0.eta()); + registry.fill(HIST("hEtaPi1FromXicRecBkg"), trackPi1.eta()); + registry.fill(HIST("hEtaBachelorPionRecBkg"), trackPiFromXi.eta()); + registry.fill(HIST("hEtaV0PosDauRecBkg"), trackV0PosDau.eta()); + registry.fill(HIST("hEtaV0NegDauRecBkg"), trackV0NegDau.eta()); + registry.fill(HIST("hNClustersTpcPi0FromXicRecBkg"), trackPi0.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcPi1FromXicRecBkg"), trackPi1.tpcNClsFound()); + registry.fill(HIST("hNCrossedRowsTpcPi0FromXicRecBkg"), trackPi0.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcPi1FromXicRecBkg"), trackPi1.tpcNClsCrossedRows()); + registry.fill(HIST("hNClustersItsPi0FromXicRecBkg"), trackPi0.itsNCls()); + registry.fill(HIST("hNClustersItsPi1FromXicRecBkg"), trackPi1.itsNCls()); + registry.fill(HIST("hNClustersItsInnBarrPi0FromXicRecBkg"), trackPi0.itsNClsInnerBarrel()); + registry.fill(HIST("hNClustersItsInnBarrPi1FromXicRecBkg"), trackPi1.itsNClsInnerBarrel()); + registry.fill(HIST("hNClustersTpcBachelorPionRecBkg"), trackPiFromXi.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcV0PosDauRecBkg"), trackV0PosDau.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcV0NegDauRecBkg"), trackV0NegDau.tpcNClsFound()); + registry.fill(HIST("hNCrossedRowsTpcBachelorPionRecBkg"), trackPiFromXi.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcV0PosDauRecBkg"), trackV0PosDau.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcV0NegDauRecBkg"), trackV0NegDau.tpcNClsCrossedRows()); + } + } else { + registry.fill(HIST("hEtaPi0FromXic"), trackPi0.eta()); + registry.fill(HIST("hEtaPi1FromXic"), trackPi1.eta()); + registry.fill(HIST("hEtaBachelorPion"), trackPiFromXi.eta()); + registry.fill(HIST("hEtaV0PosDau"), trackV0PosDau.eta()); + registry.fill(HIST("hEtaV0NegDau"), trackV0NegDau.eta()); + registry.fill(HIST("hNClustersTpcPi0FromXic"), trackPi0.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcPi1FromXic"), trackPi1.tpcNClsFound()); + registry.fill(HIST("hNCrossedRowsTpcPi0FromXic"), trackPi0.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcPi1FromXic"), trackPi1.tpcNClsCrossedRows()); + registry.fill(HIST("hNClustersItsPi0FromXic"), trackPi0.itsNCls()); + registry.fill(HIST("hNClustersItsPi1FromXic"), trackPi1.itsNCls()); + registry.fill(HIST("hNClustersItsInnBarrPi0FromXic"), trackPi0.itsNClsInnerBarrel()); + registry.fill(HIST("hNClustersItsInnBarrPi1FromXic"), trackPi1.itsNClsInnerBarrel()); + registry.fill(HIST("hNClustersTpcBachelorPion"), trackPiFromXi.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcV0PosDau"), trackV0PosDau.tpcNClsFound()); + registry.fill(HIST("hNClustersTpcV0NegDau"), trackV0NegDau.tpcNClsFound()); + registry.fill(HIST("hNCrossedRowsTpcBachelorPion"), trackPiFromXi.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcV0PosDau"), trackV0PosDau.tpcNClsCrossedRows()); + registry.fill(HIST("hNCrossedRowsTpcV0NegDau"), trackV0NegDau.tpcNClsCrossedRows()); + } + } - // check that the candidate pT is within the analysis range - if (candpT < ptCandMin || candpT >= ptCandMax) { + //////////////////////////////////////////////// + // Kinematic and topological selection // + //////////////////////////////////////////////// + + // check whether candidate is in analyzed pT range + auto ptCandXic = hfCandXic.pt(); + int pTBin = findBin(binsPt, ptCandXic); + if (pTBin == -1) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), Pt); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), Pt); + } + } else { + registry.fill(HIST("hSelCandidates"), Pt); + } - // check candidate mass is within a defined mass window + // check whether candidate mass is within a defined mass window if (std::abs(hfCandXic.invMassXicPlus() - o2::constants::physics::MassXiCPlus) > cuts->get(pTBin, "m")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), Mass); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), Mass); + } + } else { + registry.fill(HIST("hSelCandidates"), Mass); + } - // cosine of pointing angle - if (hfCandXic.cpa() <= cuts->get(pTBin, "cos pointing angle")) { + // cut on candidate rapidity + if (std::abs(hfCandXic.y(o2::constants::physics::MassXiCPlus)) > cuts->get(pTBin, "y")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), Rapidity); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), Rapidity); + } + } else { + registry.fill(HIST("hSelCandidates"), Rapidity); + } - // cosine of pointing angle XY - if (hfCandXic.cpaXY() <= cuts->get(pTBin, "cos pointing angle XY")) { + // cut on candidate pseudorapidity + if (std::abs(hfCandXic.eta()) > cuts->get(pTBin, "eta")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), Eta); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), Eta); + } + } else { + registry.fill(HIST("hSelCandidates"), Eta); + } - // candidate maximum decay length - if (hfCandXic.decayLength() > cuts->get(pTBin, "max decay length")) { + // cut on pseudorapidity of pions from XicPlus + if (std::abs(trackPi0.eta()) > cuts->get(pTBin, "eta Pi from XicPlus") || std::abs(trackPi1.eta()) > cuts->get(pTBin, "eta Pi from XicPlus")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), EtaPionFromXicPlus); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), EtaPionFromXicPlus); + } + } else { + registry.fill(HIST("hSelCandidates"), EtaPionFromXicPlus); + } - // candidate maximum decay length XY - if (hfCandXic.decayLengthXY() > cuts->get(pTBin, "max decay length XY")) { + // cut on pseudorapidity of Xi daughters + if (std::abs(trackPiFromXi.eta()) > cuts->get(pTBin, "eta Xi Daughters") || std::abs(trackV0PosDau.eta()) > cuts->get(pTBin, "eta Xi Daughters") || std::abs(trackV0NegDau.eta()) > cuts->get(pTBin, "eta Xi Daughters")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), EtaXiDaughters); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), EtaXiDaughters); + } + } else { + registry.fill(HIST("hSelCandidates"), EtaXiDaughters); + } - // candidate chi2PC - if (hfCandXic.chi2PCA() > cuts->get(pTBin, "chi2PCA")) { + // cut on pion pT + if (hfCandXic.ptProng1() < cuts->get(pTBin, "pT Pi0") || hfCandXic.ptProng2() < cuts->get(pTBin, "pT Pi1") || (hfCandXic.ptProng1() + hfCandXic.ptProng2()) < cuts->get(pTBin, "pT Pi0 + Pi1")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), PtPionFromXicPlus); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), PtPionFromXicPlus); + } + } else { + registry.fill(HIST("hSelCandidates"), PtPionFromXicPlus); + } - // maximum DCA of daughters - if ((std::abs(hfCandXic.impactParameter0()) > cuts->get(pTBin, "max impParXY Xi")) || - (std::abs(hfCandXic.impactParameter1()) > cuts->get(pTBin, "max impParXY Pi0")) || - (std::abs(hfCandXic.impactParameter2()) > cuts->get(pTBin, "max impParXY Pi1"))) { + // cut on chi2 of secondary vertex + if (hfCandXic.chi2PCA() > cuts->get(pTBin, "chi2SV")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), Chi2SV); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), Chi2SV); + } + } else { + registry.fill(HIST("hSelCandidates"), Chi2SV); + } - // cut on daughter pT - if (hfCandXic.ptProng0() < cuts->get(pTBin, "pT Xi") || - hfCandXic.ptProng1() < cuts->get(pTBin, "pT Pi0") || - hfCandXic.ptProng2() < cuts->get(pTBin, "pT Pi1")) { + // cut on candidate decay length + if (hfCandXic.decayLength() < cuts->get(pTBin, "min decay length") || hfCandXic.decayLengthXY() < cuts->get(pTBin, "min decay length XY")) { return false; } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), MinDecayLength); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), MinDecayLength); + } + } else { + registry.fill(HIST("hSelCandidates"), MinDecayLength); + } - return true; - } - - /// Apply PID selection - /// \param pidTrackPi0 PID status of trackPi0 (prong1 of Xic candidate) - /// \param pidTrackPi1 PID status of trackPi1 (prong2 of Xic candidate) - /// \param pidTrackPr PID status of trackPr (positive daughter of V0 candidate) - /// \param pidTrackPiLam PID status of trackPiLam (negative daughter of V0 candidate) - /// \param pidTrackPiXi PID status of trackPiXi (Bachelor of cascade candidate) - /// \param acceptPIDNotApplicable switch to accept Status::NotApplicable - /// \return true if prongs of Xic candidate pass all selections - bool selectionPid(TrackSelectorPID::Status const pidTrackPi0, - TrackSelectorPID::Status const pidTrackPi1, - TrackSelectorPID::Status const pidTrackPr, - TrackSelectorPID::Status const pidTrackPiLam, - TrackSelectorPID::Status const pidTrackPiXi, - bool const acceptPIDNotApplicable) - { - if (!acceptPIDNotApplicable && (pidTrackPi0 != TrackSelectorPID::Accepted || pidTrackPi1 != TrackSelectorPID::Accepted || pidTrackPr != TrackSelectorPID::Accepted || pidTrackPiLam != TrackSelectorPID::Accepted || pidTrackPiXi != TrackSelectorPID::Accepted)) { + // cut on invariant mass of Xi-pion pairs + if (hfCandXic.invMassXiPi0() > cuts->get(pTBin, "max inv mass Xi-Pi0") || hfCandXic.invMassXiPi1() > cuts->get(pTBin, "max inv mass Xi-Pi1")) { return false; } - if (acceptPIDNotApplicable && (pidTrackPi0 == TrackSelectorPID::Rejected || pidTrackPi1 == TrackSelectorPID::Rejected || pidTrackPr == TrackSelectorPID::Rejected || pidTrackPiLam == TrackSelectorPID::Rejected || pidTrackPiXi == TrackSelectorPID::Rejected)) { - return false; + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), MaxInvMassXiPiPairs); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), MaxInvMassXiPiPairs); + } + } else { + registry.fill(HIST("hSelCandidates"), MaxInvMassXiPiPairs); } + + // Successful kinematic and topological selection + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoKinTopol); // RecoKinTopol = 1 --> statusXicToXiPiPi += 2 + + //////////////////////////////////////////////// + // Track quality selection // + //////////////////////////////////////////////// + if (doTrackQualitySelection) { + // TPC track quality selection on Xi daughters (bachelor pion and V0 daughters) + if (!isSelectedTrackTpcQuality(trackPiFromXi, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax) || + !isSelectedTrackTpcQuality(trackV0PosDau, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax) || + !isSelectedTrackTpcQuality(trackV0NegDau, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + return false; + } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), TpcTrackQualityXiDaughters); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), TpcTrackQualityXiDaughters); + } + } else { + registry.fill(HIST("hSelCandidates"), TpcTrackQualityXiDaughters); + } + + // TPC track quality selection on pions from charm baryon + if (!isSelectedTrackTpcQuality(trackPi0, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax) || + !isSelectedTrackTpcQuality(trackPi1, nClustersTpcMin, nTpcCrossedRowsMin, tpcCrossedRowsOverFindableClustersRatioMin, tpcChi2PerClusterMax)) { + return false; + } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), TpcTrackQualityPiFromCharm); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), TpcTrackQualityPiFromCharm); + } + } else { + registry.fill(HIST("hSelCandidates"), TpcTrackQualityPiFromCharm); + } + + // ITS track quality selection on pions from charm baryon + if ((!isSelectedTrackItsQuality(trackPi0, nClustersItsMin, itsChi2PerClusterMax) || trackPi0.itsNClsInnerBarrel() < nClustersItsInnBarrMin) || + (!isSelectedTrackItsQuality(trackPi0, nClustersItsMin, itsChi2PerClusterMax) || trackPi1.itsNClsInnerBarrel() < nClustersItsInnBarrMin)) { + return false; + } + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), ItsTrackQualityPiFromCharm); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), ItsTrackQualityPiFromCharm); + } + } else { + registry.fill(HIST("hSelCandidates"), ItsTrackQualityPiFromCharm); + } + + // Successful track quality selection + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoTrackQuality); // RecoTrackQuality = 2 --> statusXicToXiPiPi += 4 + } else { + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), TpcTrackQualityXiDaughters); + registry.fill(HIST("hSelCandidatesRecSig"), TpcTrackQualityPiFromCharm); + registry.fill(HIST("hSelCandidatesRecSig"), ItsTrackQualityPiFromCharm); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), TpcTrackQualityXiDaughters); + registry.fill(HIST("hSelCandidatesRecBkg"), TpcTrackQualityPiFromCharm); + registry.fill(HIST("hSelCandidatesRecBkg"), ItsTrackQualityPiFromCharm); + } + } else { + registry.fill(HIST("hSelCandidates"), TpcTrackQualityXiDaughters); + registry.fill(HIST("hSelCandidates"), TpcTrackQualityPiFromCharm); + registry.fill(HIST("hSelCandidates"), ItsTrackQualityPiFromCharm); + } + } + + //////////////////////////////////////////////// + // PID selection // + //////////////////////////////////////////////// + if (usePid) { + TrackSelectorPID::Status statusPidPi0 = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPi1 = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPiXi = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPrLam = TrackSelectorPID::NotApplicable; + TrackSelectorPID::Status statusPidPiLam = TrackSelectorPID::NotApplicable; + + // assign proton and pion hypothesis to V0 daughters + auto trackPr = trackV0PosDau; + auto trackPiFromLam = trackV0NegDau; + if (hfCandXic.sign() < 0) { + trackPr = trackV0NegDau; + trackPiFromLam = trackV0PosDau; + } + + if (useTpcPidOnly) { + statusPidPi0 = selectorPion.statusTpc(trackPi0); + statusPidPi1 = selectorPion.statusTpc(trackPi1); + statusPidPiXi = selectorPion.statusTpc(trackPiFromXi); + statusPidPrLam = selectorProton.statusTpc(trackPr); + statusPidPiLam = selectorPion.statusTpc(trackPiFromLam); + } else { + statusPidPi0 = selectorPion.statusTpcOrTof(trackPi0); + statusPidPi1 = selectorPion.statusTpcOrTof(trackPi1); + statusPidPiXi = selectorPion.statusTpcOrTof(trackPiFromXi); + statusPidPrLam = selectorProton.statusTpcOrTof(trackPr); + statusPidPiLam = selectorPion.statusTpcOrTof(trackPiFromLam); + } + + if (!isSelectedPid(statusPidPi0, statusPidPi1, statusPidPiXi, statusPidPrLam, statusPidPiLam, useTpcPidOnly.value)) { + return false; + } + + // Successful PID selection + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoPID); // RecoPID = 3 --> statusXicToXiPiPi += 8 + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), PidSelected); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), PidSelected); + } + } else { + registry.fill(HIST("hSelCandidates"), PidSelected); + } + } else { + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), PidSelected); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), PidSelected); + } + } else { + registry.fill(HIST("hSelCandidates"), PidSelected); + } + } + return true; } - void process(aod::HfCandXic const& hfCandsXic, - TracksPidWithSel const&) + /// Apply BDT selection + /// \param hfCandXic Xic candidate + /// \param statusXicToXiPiPi Flag to store selection status as defined in hf_sel_candidate_xic::XicToXiPiPiSelectionStep + /// \param isMatchedSignal Flag to indicate if the candidate is matched to a genereated XiCplus MC particle + template + void isBdtSelected(XicCandidate const& hfCandXic, + int& statusXicToXiPiPi, + bool const isMatchedSignal = false) { - for (const auto& hfCandXic : hfCandsXic) { - int statusXicToXiPiPi = 0; + bool isSelectedMlXicToXiPiPi = false; + float ptCandXic = hfCandXic.pt(); - outputMlXicToXiPiPi.clear(); + std::vector inputFeaturesXicToXiPiPi = hfMlResponse.getInputFeatures(hfCandXic); + isSelectedMlXicToXiPiPi = hfMlResponse.isSelectedMl(inputFeaturesXicToXiPiPi, ptCandXic, outputMlXicToXiPiPi); - auto ptCandXic = hfCandXic.pt(); + hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); - if (activateQA) { - registry.fill(HIST("hSelections"), 1, ptCandXic); + if (!isSelectedMlXicToXiPiPi) { + return; + } + + // Successful ML selection + SETBIT(statusXicToXiPiPi, hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoMl); // RecoML = 4 --> statusXicToXiPiPi += 16 + if constexpr (isMc) { + if (isMatchedSignal) { + registry.fill(HIST("hSelCandidatesRecSig"), BdtSelected); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), BdtSelected); } + } else { + registry.fill(HIST("hSelCandidates"), BdtSelected); + } + } - // No hfflag -> by default skim selected - SETBIT(statusXicToXiPiPi, SelectionStep::RecoSkims); // RecoSkims = 0 --> statusXicToXiPiPi = 1 - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoSkims, ptCandXic); + void processData(aod::HfCandXic const& hfCandsXic, + TracksExtraWPid const& tracks) + { + for (const auto& hfCandXic : hfCandsXic) { + int statusXicToXiPiPi = 0; + if (applyMl) { + outputMlXicToXiPiPi.clear(); } - // topological cuts - if (!selectionTopol(hfCandXic)) { + // Kinematic, topological, track quality and PID selections + if (!isSelectedXicToXiPiPiCandidateWoMl(hfCandXic, tracks, statusXicToXiPiPi)) { hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); if (applyMl) { hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); } continue; } - SETBIT(statusXicToXiPiPi, SelectionStep::RecoTopol); // RecoTopol = 1 --> statusXicToXiPiPi = 3 - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoTopol, ptCandXic); - } - - // track-level PID selection - if (usePid) { - auto trackPi0 = hfCandXic.pi0_as(); - auto trackPi1 = hfCandXic.pi1_as(); - auto trackV0PosDau = hfCandXic.posTrack_as(); - auto trackV0NegDau = hfCandXic.negTrack_as(); - auto trackPiFromXi = hfCandXic.bachelor_as(); - // assign proton and pion hypothesis to V0 daughters - auto trackPr = trackV0PosDau; - auto trackPiFromLam = trackV0NegDau; - if (hfCandXic.sign() < 0) { - trackPr = trackV0NegDau; - trackPiFromLam = trackV0PosDau; - } - // PID info - TrackSelectorPID::Status pidTrackPi0 = selectorPion.statusTpcAndTof(trackPi0); - TrackSelectorPID::Status pidTrackPi1 = selectorPion.statusTpcAndTof(trackPi1); - TrackSelectorPID::Status pidTrackPr = selectorProton.statusTpcAndTof(trackPr); - TrackSelectorPID::Status pidTrackPiLam = selectorPion.statusTpcAndTof(trackPiFromLam); - TrackSelectorPID::Status pidTrackPiXi = selectorPion.statusTpcAndTof(trackPiFromXi); - - if (!selectionPid(pidTrackPi0, pidTrackPi1, pidTrackPr, pidTrackPiLam, pidTrackPiXi, acceptPIDNotApplicable.value)) { - hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); - if (applyMl) { - hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); - } - continue; - } - SETBIT(statusXicToXiPiPi, SelectionStep::RecoPID); // RecoPID = 2 --> statusXicToXiPiPi = 7 - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoPID, ptCandXic); - } - } // ML selection if (applyMl) { - bool isSelectedMlXicToXiPiPi = false; - std::vector inputFeaturesXicToXiPiPi = hfMlResponse.getInputFeatures(hfCandXic); + isBdtSelected(hfCandXic, statusXicToXiPiPi); + } else { + registry.fill(HIST("hSelCandidates"), BdtSelected); + } - isSelectedMlXicToXiPiPi = hfMlResponse.isSelectedMl(inputFeaturesXicToXiPiPi, ptCandXic, outputMlXicToXiPiPi); + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + } + } + PROCESS_SWITCH(HfCandidateSelectorXicToXiPiPi, processData, "Select candidates without MC matching information", true); - hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); + void processMc(soa::Join const& hfCandsXic, + TracksExtraWPid const& tracks) + { + for (const auto& hfCandXic : hfCandsXic) { + int statusXicToXiPiPi = 0; + if (applyMl) { + outputMlXicToXiPiPi.clear(); + } - if (!isSelectedMlXicToXiPiPi) { - hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); - continue; - } - SETBIT(statusXicToXiPiPi, aod::SelectionStep::RecoMl); - if (activateQA) { - registry.fill(HIST("hSelections"), 2 + SelectionStep::RecoMl, ptCandXic); + bool isMatchedCandidate = false; + if (hfCandXic.flagMcMatchRec() != int8_t(0)) { + isMatchedCandidate = true; + } + + // Kinematic, topological, track quality and PID selections + if (!isSelectedXicToXiPiPiCandidateWoMl(hfCandXic, tracks, statusXicToXiPiPi, isMatchedCandidate)) { + hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); + if (applyMl) { + hfMlXicToXiPiPiCandidate(outputMlXicToXiPiPi); } + continue; + } + + // ML selection + if (applyMl) { + isBdtSelected(hfCandXic, statusXicToXiPiPi, isMatchedCandidate); + } else if (isMatchedCandidate) { + registry.fill(HIST("hSelCandidatesRecSig"), BdtSelected); + } else { + registry.fill(HIST("hSelCandidatesRecBkg"), BdtSelected); } hfSelXicToXiPiPiCandidate(statusXicToXiPiPi); } } + PROCESS_SWITCH(HfCandidateSelectorXicToXiPiPi, processMc, "Select candidates with MC matching information", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx b/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx index 578cb27876d..dd178bd83f0 100644 --- a/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx +++ b/PWGHF/TableProducer/candidateSelectorXiccToPKPiPi.cxx @@ -14,19 +14,25 @@ /// /// \author Gian Michele Innocenti , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelectorPID.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/TrackSelectorPID.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; diff --git a/PWGHF/TableProducer/converterDstarIndices.cxx b/PWGHF/TableProducer/converterDstarIndices.cxx index 9596a571498..8b26f94610e 100644 --- a/PWGHF/TableProducer/converterDstarIndices.cxx +++ b/PWGHF/TableProducer/converterDstarIndices.cxx @@ -14,12 +14,12 @@ /// /// \author Fabrizio Grosa , CERN -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx index 0dda7288169..290773cfa9f 100644 --- a/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorB0ToDPi.cxx @@ -15,32 +15,45 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.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 "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" -#include "PWGHF/Utils/utilsPid.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::pid_tpc_tof_utils; using namespace o2::analysis::hf_derived; +using namespace o2::hf_decay::hf_cand_beauty; /// Writes the full information in an output TTree struct HfDerivedDataCreatorB0ToDPi { @@ -94,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(BIT(aod::hf_cand_b0::DecayType::B0ToDPi)); + Filter filterMcGenMatching = nabs(aod::hf_cand_b0::flagMcMatchGen) == static_cast(DecayChannelMain::B0ToDminusPi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -108,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(BIT(aod::hf_cand_b0::DecayType::B0ToDPi)); - Partition candidatesMcBkg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_b0::DecayType::B0ToDPi)); - Partition candidatesMcMlSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_b0::DecayType::B0ToDPi)); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_b0::DecayType::B0ToDPi)); + 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); void init(InitContext const&) { @@ -279,7 +292,7 @@ struct HfDerivedDataCreatorB0ToDPi { flagMcRec = candidate.flagMcMatchRec(); origin = candidate.originMcRec(); if constexpr (onlyBkg) { - if (TESTBIT(std::abs(flagMcRec), aod::hf_cand_b0::DecayType::B0ToDPi)) { + if (std::abs(flagMcRec) == DecayChannelMain::B0ToDminusPi) { continue; } if (downSampleBkgFactor < 1.) { @@ -290,7 +303,7 @@ struct HfDerivedDataCreatorB0ToDPi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(flagMcRec), aod::hf_cand_b0::DecayType::B0ToDPi)) { + if (std::abs(flagMcRec) != DecayChannelMain::B0ToDminusPi) { continue; } } diff --git a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx index abaf1573166..ca79660d0bc 100644 --- a/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorBplusToD0Pi.cxx @@ -15,32 +15,46 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" - -#include "PWGLF/DataModel/mcCentrality.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/DerivedTables.h" #include "PWGHF/Utils/utilsDerivedData.h" #include "PWGHF/Utils/utilsPid.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::aod::pid_tpc_tof_utils; using namespace o2::analysis::hf_derived; +using namespace o2::hf_decay::hf_cand_beauty; /// Writes the full information in an output TTree struct HfDerivedDataCreatorBplusToD0Pi { @@ -94,7 +108,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(BIT(aod::hf_cand_bplus::DecayType::BplusToD0Pi)); + Filter filterMcGenMatching = nabs(aod::hf_cand_bplus::flagMcMatchGen) == static_cast(DecayChannelMain::BplusToD0Pi); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesMcPerCollision = aod::hf_cand::collisionId; @@ -108,10 +122,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(BIT(aod::hf_cand_bplus::DecayType::BplusToD0Pi)); - Partition candidatesMcBkg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_bplus::DecayType::BplusToD0Pi)); - Partition candidatesMcMlSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_bplus::DecayType::BplusToD0Pi)); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_bplus::DecayType::BplusToD0Pi)); + 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); void init(InitContext const&) { @@ -281,7 +295,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { flagMcRec = candidate.flagMcMatchRec(); origin = candidate.originMcRec(); if constexpr (onlyBkg) { - if (TESTBIT(std::abs(flagMcRec), aod::hf_cand_bplus::DecayType::BplusToD0Pi)) { + if (std::abs(flagMcRec) == DecayChannelMain::BplusToD0Pi) { continue; } if (downSampleBkgFactor < 1.) { @@ -292,7 +306,7 @@ struct HfDerivedDataCreatorBplusToD0Pi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(flagMcRec), aod::hf_cand_bplus::DecayType::BplusToD0Pi)) { + if (std::abs(flagMcRec) != DecayChannelMain::BplusToD0Pi) { continue; } } diff --git a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx index 8ddc3d4464f..194b50eb2c0 100644 --- a/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorD0ToKPi.cxx @@ -15,26 +15,39 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" - -#include "PWGLF/DataModel/mcCentrality.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/DataModel/DerivedTables.h" #include "PWGHF/Utils/utilsDerivedData.h" #include "PWGHF/Utils/utilsPid.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; @@ -93,7 +106,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(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + Filter filterMcGenMatching = nabs(aod::hf_cand_2prong::flagMcMatchGen) == static_cast(o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK); Preslice candidatesPerCollision = aod::hf_cand::collisionId; Preslice candidatesKfPerCollision = aod::hf_cand::collisionId; @@ -115,14 +128,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(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition candidatesMcBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition candidatesMcKfSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition candidatesMcKfBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition candidatesMcMlSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition candidatesMcMlBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition candidatesMcKfMlSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition candidatesMcKfMlBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + 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); void init(InitContext const&) { @@ -272,7 +285,7 @@ struct HfDerivedDataCreatorD0ToKPi { flagMcRec = candidate.flagMcMatchRec(); origin = candidate.originMcRec(); if constexpr (onlyBkg) { - if (TESTBIT(std::abs(flagMcRec), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (std::abs(flagMcRec) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { continue; } if (downSampleBkgFactor < 1.) { @@ -283,7 +296,7 @@ struct HfDerivedDataCreatorD0ToKPi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(flagMcRec), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if (std::abs(flagMcRec) != o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { continue; } } diff --git a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx index 6897b30ec0e..96d3ed0acf4 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDplusToPiKPi.cxx @@ -15,25 +15,38 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.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 "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx new file mode 100644 index 00000000000..d63294ff14d --- /dev/null +++ b/PWGHF/TableProducer/derivedDataCreatorDsToKKPi.cxx @@ -0,0 +1,412 @@ +// 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 derivedDataCreatorDsToKKPi.cxx +/// \brief Producer of derived tables of Ds candidates, collisions and MC particles +/// \note Based on derivedDataCreatorDplusToPiKPi.cxx +/// +/// \author Vít Kučera , Inha University + +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.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 HfDerivedDataCreatorDsToKKPi { + HfProducesDerivedData< + o2::aod::HfDsBases, + o2::aod::HfDsCollBases, + o2::aod::HfDsCollIds, + o2::aod::HfDsMcCollBases, + o2::aod::HfDsMcCollIds, + o2::aod::HfDsMcRCollIds, + o2::aod::HfDsPBases, + o2::aod::HfDsPIds> + 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"}; + + HfHelper hfHelper; + SliceCache cache; + static constexpr double Mass{o2::constants::physics::MassDS}; + + 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_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); + + 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_ds::isSelDsToKKPi >= 0; + Partition candidatesMcAll = aod::hf_sel_candidate_ds::isSelDsToKKPi >= 0; + 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); + + 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, int candFlag, double invMass, + double ct, double y, int8_t flagMc, int8_t origin, int8_t swapping, int8_t flagDecayChan, const std::vector& mlScores) + { + rowsCommon.fillTablesCandidate(candidate, invMass, y); + if (fillCandidatePar) { + rowCandidatePar( + candidate.chi2PCA(), + candidate.nProngsContributorsPV(), + candidate.cpa(), + candidate.cpaXY(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameter2(), + candidate.impactParameterNormalised0(), + candidate.impactParameterNormalised1(), + candidate.impactParameterNormalised2(), + candidate.nSigTpcPi0(), + candidate.nSigTpcKa0(), + candidate.nSigTofPi0(), + candidate.nSigTofKa0(), + candidate.tpcTofNSigmaPi0(), + candidate.tpcTofNSigmaKa0(), + candidate.nSigTpcKa1(), + candidate.nSigTofKa1(), + candidate.tpcTofNSigmaKa1(), + candidate.nSigTpcPi2(), + candidate.nSigTpcKa2(), + candidate.nSigTofPi2(), + candidate.nSigTofKa2(), + candidate.tpcTofNSigmaPi2(), + candidate.tpcTofNSigmaKa2()); + } + 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()), + 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.errorImpactParameter0(), + candidate.errorImpactParameter1(), + candidate.errorImpactParameter2(), + ct); + } + if (fillCandidateSel) { + rowCandidateSel( + BIT(candFlag)); + } + if (fillCandidateMl) { + rowCandidateMl( + mlScores); + } + if (fillCandidateId) { + rowCandidateId( + candidate.collisionId(), + candidate.prong0Id(), + candidate.prong1Id(), + candidate.prong2Id()); + } + if (fillCandidateMc) { + rowCandidateMc( + flagMc, + origin, + swapping, + flagDecayChan); + } + } + + 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, swapping = 0, flagDecayChanRec = 0; + for (const auto& candidate : candidatesThisColl) { + if constexpr (isMl) { + if (!TESTBIT(candidate.isSelDsToKKPi(), aod::SelectionStep::RecoMl)) { + continue; + } + } + if constexpr (isMc) { + flagMcRec = candidate.flagMcMatchRec(); + origin = candidate.originMcRec(); + swapping = candidate.isCandidateSwapped(); + flagDecayChanRec = candidate.flagMcDecayChanRec(); + if constexpr (onlyBkg) { + if (std::abs(flagMcRec) == hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) { + continue; + } + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - static_cast(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + } + if constexpr (onlySig) { + if (std::abs(flagMcRec) != hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK) { + continue; + } + } + } + double ct = hfHelper.ctDs(candidate); + double y = hfHelper.yDs(candidate); + float massDsToKKPi = hfHelper.invMassDsToKKPi(candidate); + std::vector mlScoresDsToKKPi; + if constexpr (isMl) { + std::copy(candidate.mlProbDsToKKPi().begin(), candidate.mlProbDsToKKPi().end(), std::back_inserter(mlScoresDsToKKPi)); + } + fillTablesCandidate(candidate, 0, massDsToKKPi, ct, y, flagMcRec, origin, swapping, flagDecayChanRec, mlScoresDsToKKPi); + } + } + } + + void processData(CollisionsWCentMult const& collisions, + SelectedCandidates const&, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processCandidates(collisions, candidatesAll, tracks, bcs); + } + PROCESS_SWITCH(HfDerivedDataCreatorDsToKKPi, 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(HfDerivedDataCreatorDsToKKPi, 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(HfDerivedDataCreatorDsToKKPi, 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(HfDerivedDataCreatorDsToKKPi, 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(HfDerivedDataCreatorDsToKKPi, 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(HfDerivedDataCreatorDsToKKPi, 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(HfDerivedDataCreatorDsToKKPi, 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(HfDerivedDataCreatorDsToKKPi, processMcMlAll, "Process MC with ML", false); + + void processMcGenOnly(TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles) + { + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorDsToKKPi, processMcGenOnly, "Process MC gen. only", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx index 7c592e9ccb1..f1b14a5769f 100644 --- a/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorDstarToD0Pi.cxx @@ -15,24 +15,36 @@ /// /// \author Mingze Li , CCNU -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.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 "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -53,6 +65,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { rowsCommon; // Candidates Produces rowCandidatePar; + Produces rowCandidateParD0; Produces rowCandidateSel; Produces rowCandidateMl; Produces rowCandidateId; @@ -61,6 +74,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { // Switches for filling tables HfConfigurableDerivedData confDerData; Configurable fillCandidatePar{"fillCandidatePar", true, "Fill candidate parameters"}; + Configurable fillCandidateParD0{"fillCandidateParD0", true, "Fill charm daughter 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"}; @@ -70,7 +84,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; SliceCache cache; - static constexpr double mass{o2::constants::physics::MassDStar}; + static constexpr double Mass{o2::constants::physics::MassDStar}; using CollisionsWCentMult = soa::Join; using CollisionsWMcCentMult = soa::Join; @@ -112,12 +126,27 @@ struct HfDerivedDataCreatorDstarToD0Pi { } template - void fillTablesCandidate(const T& candidate, const U& prong0, const U& prong1, const U& prongSoftPi, int candFlag, double invMass, - double y, int8_t flagMc, int8_t origin, const std::vector& mlScores) + void fillTablesCandidate(const T& candidate, const U& prong0, const U& prong1, const U& prongSoftPi, int candFlag, double invMass, double invMassD0, + double y, int8_t flagMc, int8_t flagMcD0, int8_t origin, int8_t nTracksDecayed, double ptBhad, int pdgBhad, const std::vector& mlScores) { rowsCommon.fillTablesCandidate(candidate, invMass, y); if (fillCandidatePar) { rowCandidatePar( + candidate.pxD0(), + candidate.pyD0(), + candidate.pzD0(), + candidate.pxSoftPi(), + candidate.pySoftPi(), + candidate.pzSoftPi(), + candidate.signSoftPi(), + candidate.impParamSoftPi(), + candidate.normalisedImpParamSoftPi(), + prongSoftPi.tpcNSigmaPi(), + prongSoftPi.tofNSigmaPi(), + prongSoftPi.tpcTofNSigmaPi()); + } + if (fillCandidateParD0) { + rowCandidateParD0( candidate.chi2PCAD0(), candidate.cpaD0(), candidate.cpaXYD0(), @@ -131,29 +160,23 @@ struct HfDerivedDataCreatorDstarToD0Pi { candidate.pxProng1(), candidate.pyProng1(), candidate.pzProng1(), - candidate.pxD0(), - candidate.pyD0(), - candidate.pzD0(), - candidate.pxSoftPi(), - candidate.pySoftPi(), - candidate.pzSoftPi(), - candidate.signSoftPi(), - candidate.invMassD0(), + invMassD0, candidate.impactParameter0(), candidate.impactParameter1(), - candidate.impParamSoftPi(), candidate.impactParameterNormalised0(), candidate.impactParameterNormalised1(), - candidate.normalisedImpParamSoftPi(), prong0.tpcNSigmaPi(), prong0.tofNSigmaPi(), prong0.tpcTofNSigmaPi(), + prong0.tpcNSigmaKa(), + prong0.tofNSigmaKa(), + prong0.tpcTofNSigmaKa(), + prong1.tpcNSigmaPi(), + prong1.tofNSigmaPi(), + prong1.tpcTofNSigmaPi(), prong1.tpcNSigmaKa(), prong1.tofNSigmaKa(), - prong1.tpcTofNSigmaKa(), - prongSoftPi.tpcNSigmaPi(), - prongSoftPi.tofNSigmaPi(), - prongSoftPi.tpcTofNSigmaPi()); + prong1.tpcTofNSigmaKa()); } if (fillCandidateSel) { rowCandidateSel( @@ -173,7 +196,11 @@ struct HfDerivedDataCreatorDstarToD0Pi { if (fillCandidateMc) { rowCandidateMc( flagMc, - origin); + flagMcD0, + origin, + ptBhad, + pdgBhad, + nTracksDecayed); } } @@ -212,13 +239,16 @@ struct HfDerivedDataCreatorDstarToD0Pi { // Fill candidate properties rowsCommon.reserveTablesCandidates(sizeTableCand); reserveTable(rowCandidatePar, fillCandidatePar, sizeTableCand); + reserveTable(rowCandidateParD0, fillCandidateParD0, 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; + int8_t flagMcRec = 0, flagMcRecD0 = 0, origin = 0, nTracksDecayed = 0; + double ptBhadMotherPart = 0; + int pdgBhadMotherPart = 0; for (const auto& candidate : candidatesThisColl) { if constexpr (isMl) { if (!TESTBIT(candidate.isSelDstarToD0Pi(), aod::SelectionStep::RecoMl)) { @@ -227,7 +257,11 @@ struct HfDerivedDataCreatorDstarToD0Pi { } if constexpr (isMc) { flagMcRec = candidate.flagMcMatchRec(); + flagMcRecD0 = candidate.flagMcMatchRecD0(); origin = candidate.originMcRec(); + nTracksDecayed = candidate.nTracksDecayed(); + ptBhadMotherPart = candidate.ptBhadMotherPart(); + pdgBhadMotherPart = candidate.pdgBhadMotherPart(); if constexpr (onlyBkg) { if (std::abs(flagMcRec) == hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { continue; @@ -249,13 +283,22 @@ struct HfDerivedDataCreatorDstarToD0Pi { auto prong1 = candidate.template prong1_as(); auto prongSoftPi = candidate.template prongPi_as(); double y = candidate.y(o2::constants::physics::MassDStar); - double massDstar = candidate.invMassDstar(); + int flagSign = -1; + double massDstar = 0, invMassD0 = 0; std::vector mlScoresDstarToD0Pi; - bool isD0 = prongSoftPi.sign() < 0; if constexpr (isMl) { std::copy(candidate.mlProbDstarToD0Pi().begin(), candidate.mlProbDstarToD0Pi().end(), std::back_inserter(mlScoresDstarToD0Pi)); } - fillTablesCandidate(candidate, prong0, prong1, prongSoftPi, isD0 ? 0 : 1, y, massDstar, flagMcRec, origin, mlScoresDstarToD0Pi); + if (candidate.signSoftPi() > 0) { + massDstar = candidate.invMassDstar(); + invMassD0 = candidate.invMassD0(); + flagSign = 0; + } else { + massDstar = candidate.invMassAntiDstar(); + invMassD0 = candidate.invMassD0Bar(); + flagSign = 1; + } + fillTablesCandidate(candidate, prong0, prong1, prongSoftPi, flagSign, massDstar, invMassD0, y, flagMcRec, flagMcRecD0, origin, nTracksDecayed, ptBhadMotherPart, pdgBhadMotherPart, mlScoresDstarToD0Pi); } } } @@ -278,7 +321,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcSig, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorDstarToD0Pi, processMcSig, "Process MC only for signals", false); @@ -291,7 +334,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcBkg, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorDstarToD0Pi, processMcBkg, "Process MC only for background", false); @@ -304,7 +347,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcAll, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorDstarToD0Pi, processMcAll, "Process MC", false); @@ -328,7 +371,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcMlSig, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorDstarToD0Pi, processMcMlSig, "Process MC with ML only for signals", false); @@ -341,7 +384,7 @@ struct HfDerivedDataCreatorDstarToD0Pi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcMlBkg, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorDstarToD0Pi, processMcMlBkg, "Process MC with ML only for background", false); @@ -354,14 +397,14 @@ struct HfDerivedDataCreatorDstarToD0Pi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcMlAll, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorDstarToD0Pi, processMcMlAll, "Process MC with ML", false); void processMcGenOnly(TypeMcCollisions const& mcCollisions, MatchedGenCandidatesMc const& mcParticles) { - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorDstarToD0Pi, processMcGenOnly, "Process MC gen. only", false); }; diff --git a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx index a956d4ff202..96835cdefe5 100644 --- a/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/derivedDataCreatorLcToPKPi.cxx @@ -15,25 +15,38 @@ /// /// \author Vít Kučera , Inha University -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.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 "PWGLF/DataModel/mcCentrality.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/Utils/utilsDerivedData.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -74,7 +87,7 @@ struct HfDerivedDataCreatorLcToPKPi { HfHelper hfHelper; SliceCache cache; - static constexpr double mass{o2::constants::physics::MassLambdaCPlus}; + static constexpr double Mass{o2::constants::physics::MassLambdaCPlus}; using CollisionsWCentMult = soa::Join; using CollisionsWMcCentMult = soa::Join; @@ -267,6 +280,13 @@ struct HfDerivedDataCreatorLcToPKPi { continue; } } + } else { + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - static_cast(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } } double ct = hfHelper.ctLc(candidate); double y = hfHelper.yLc(candidate); @@ -305,7 +325,7 @@ struct HfDerivedDataCreatorLcToPKPi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcSig, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorLcToPKPi, processMcSig, "Process MC only for signals", false); @@ -318,7 +338,7 @@ struct HfDerivedDataCreatorLcToPKPi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcBkg, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorLcToPKPi, processMcBkg, "Process MC only for background", false); @@ -331,7 +351,7 @@ struct HfDerivedDataCreatorLcToPKPi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcAll, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorLcToPKPi, processMcAll, "Process MC", false); @@ -355,7 +375,7 @@ struct HfDerivedDataCreatorLcToPKPi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcMlSig, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorLcToPKPi, processMcMlSig, "Process MC with ML only for signals", false); @@ -368,7 +388,7 @@ struct HfDerivedDataCreatorLcToPKPi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcMlBkg, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorLcToPKPi, processMcMlBkg, "Process MC with ML only for background", false); @@ -381,14 +401,14 @@ struct HfDerivedDataCreatorLcToPKPi { { rowsCommon.preProcessMcCollisions(mcCollisions, mcParticlesPerMcCollision, mcParticles); processCandidates(collisions, candidatesMcMlAll, tracks, bcs); - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorLcToPKPi, processMcMlAll, "Process MC with ML", false); void processMcGenOnly(TypeMcCollisions const& mcCollisions, MatchedGenCandidatesMc const& mcParticles) { - rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, mass); + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); } PROCESS_SWITCH(HfDerivedDataCreatorLcToPKPi, processMcGenOnly, "Process MC gen. only", false); }; diff --git a/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx new file mode 100644 index 00000000000..a59636bc500 --- /dev/null +++ b/PWGHF/TableProducer/derivedDataCreatorXicToXiPiPi.cxx @@ -0,0 +1,409 @@ +// 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 derivedDataCreatorXicToXiPiPi.cxx +/// \brief Producer of derived tables of Ξc± → (Ξ∓ → (Λ → p π∓) π∓) π± π± candidates, collisions and MC particles +/// \note Based on derivedDataCreatorBplusToD0Pi.cxx +/// +/// \author Vít Kučera , Inha University + +#include "PWGHF/Core/HfHelper.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/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::aod::pid_tpc_tof_utils; +using namespace o2::analysis::hf_derived; +using namespace o2::aod::hf_cand_xic_to_xi_pi_pi; + +/// Writes the full information in an output TTree +struct HfDerivedDataCreatorXicToXiPiPi { + HfProducesDerivedData< + o2::aod::HfXicToXiPiPiBases, + o2::aod::HfXicToXiPiPiCollBases, + o2::aod::HfXicToXiPiPiCollIds, + o2::aod::HfXicToXiPiPiMcCollBases, + o2::aod::HfXicToXiPiPiMcCollIds, + o2::aod::HfXicToXiPiPiMcRCollIds, + o2::aod::HfXicToXiPiPiPBases, + o2::aod::HfXicToXiPiPiPIds> + 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"}; + + HfHelper hfHelper; + SliceCache cache; + static constexpr double Mass{o2::constants::physics::MassXiCPlus}; + + 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; + 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; + + 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_xic::isSelXicToXiPiPi >= 0; + Partition candidatesMcAll = aod::hf_sel_candidate_xic::isSelXicToXiPiPi >= 0; + 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; + + 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, int candFlag, double invMass, + double ct, double y, int8_t flagMc, int8_t origin, const std::vector& mlScores) + { + rowsCommon.fillTablesCandidate(candidate, invMass, y); + if (fillCandidatePar) { + rowCandidatePar( + candidate.sign(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.ptProng2(), + candidate.invMassXi(), + candidate.invMassLambda(), + candidate.invMassXiPi0(), + candidate.invMassXiPi1(), + candidate.chi2PCA(), + ct, + candidate.decayLength(), + candidate.decayLengthNormalised(), + candidate.decayLengthXY(), + candidate.decayLengthXYNormalised(), + 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()); + } + if (fillCandidateParE) { + rowCandidateParE( + candidate.cpaLambdaToXi(), + candidate.cpaXYLambdaToXi(), + candidate.pProng1(), + candidate.pProng2(), + candidate.pBachelorPi(), + candidate.pPiFromLambda(), + candidate.pPrFromLambda(), + candidate.dcaXiDaughters(), + candidate.dcaV0Daughters(), + candidate.dcaPosToPV(), + candidate.dcaNegToPV(), + candidate.dcaBachelorToPV(), + candidate.dcaXYCascToPV(), + candidate.dcaZCascToPV(), + candidate.nSigTpcPiFromXicPlus0(), + candidate.nSigTpcPiFromXicPlus1(), + candidate.nSigTpcBachelorPi(), + candidate.nSigTpcPiFromLambda(), + candidate.nSigTpcPrFromLambda(), + candidate.nSigTofPiFromXicPlus0(), + candidate.nSigTofPiFromXicPlus1(), + candidate.nSigTofBachelorPi(), + candidate.nSigTofPiFromLambda(), + candidate.nSigTofPrFromLambda()); + } + if (fillCandidateSel) { + rowCandidateSel( + BIT(candFlag)); + } + if (fillCandidateMl) { + rowCandidateMl( + mlScores); + } + if (fillCandidateId) { + rowCandidateId( + candidate.collisionId(), + candidate.pi0Id(), + candidate.pi1Id(), + candidate.bachelorId(), + 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 (isMl) { + if (!TESTBIT(candidate.isSelXicToXiPiPi(), o2::aod::hf_sel_candidate_xic::XicToXiPiPiSelectionStep::RecoMl)) { + continue; + } + } + if constexpr (isMc) { + flagMcRec = candidate.flagMcMatchRec(); + origin = candidate.originMcRec(); + if constexpr (onlyBkg) { + if (TESTBIT(std::abs(flagMcRec), DecayType::XicToXiPiPi)) { + continue; + } + if (downSampleBkgFactor < 1.) { + float pseudoRndm = candidate.ptProng0() * 1000. - static_cast(candidate.ptProng0() * 1000); + if (candidate.pt() < ptMaxForDownSample && pseudoRndm >= downSampleBkgFactor) { + continue; + } + } + } + if constexpr (onlySig) { + if (!TESTBIT(std::abs(flagMcRec), DecayType::XicToXiPiPi)) { + continue; + } + } + } + float massXicToXiPiPi = candidate.invMassXicPlus(); + double ct = hfHelper.ctXic(candidate); + double y = hfHelper.yXic(candidate); + std::vector mlScoresXicToXiPiPi; + if constexpr (isMl) { + std::copy(candidate.mlProbXicToXiPiPi().begin(), candidate.mlProbXicToXiPiPi().end(), std::back_inserter(mlScoresXicToXiPiPi)); + } + // FIXME: Remove candFlag? + fillTablesCandidate(candidate, 1, massXicToXiPiPi, ct, y, flagMcRec, origin, mlScoresXicToXiPiPi); + } + } + } + + void processData(CollisionsWCentMult const& collisions, + SelectedCandidates const&, + TracksWPid const& tracks, + aod::BCs const& bcs) + { + processCandidates(collisions, candidatesAll, tracks, bcs); + } + PROCESS_SWITCH(HfDerivedDataCreatorXicToXiPiPi, 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(HfDerivedDataCreatorXicToXiPiPi, 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(HfDerivedDataCreatorXicToXiPiPi, 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(HfDerivedDataCreatorXicToXiPiPi, 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(HfDerivedDataCreatorXicToXiPiPi, 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(HfDerivedDataCreatorXicToXiPiPi, 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(HfDerivedDataCreatorXicToXiPiPi, 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(HfDerivedDataCreatorXicToXiPiPi, processMcMlAll, "Process MC with ML", false); + + void processMcGenOnly(TypeMcCollisions const& mcCollisions, + MatchedGenCandidatesMc const& mcParticles) + { + rowsCommon.processMcParticles(mcCollisions, mcParticlesPerMcCollision, mcParticles, Mass); + } + PROCESS_SWITCH(HfDerivedDataCreatorXicToXiPiPi, processMcGenOnly, "Process MC gen. only", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGHF/TableProducer/mcPidTof.cxx b/PWGHF/TableProducer/mcPidTof.cxx index 52ae2e2ebf4..70e3d04f17e 100644 --- a/PWGHF/TableProducer/mcPidTof.cxx +++ b/PWGHF/TableProducer/mcPidTof.cxx @@ -16,39 +16,57 @@ /// It works only for MC and adds the possibility to apply postcalibrations for MC. /// -#include -#include -#include -#include -#include - -#include - -// O2 includes -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/Track.h" -#include "CCDB/BasicCCDBManager.h" -#include "TOFBase/EventTimeMaker.h" - -// O2Physics includes -#include "TableHelper.h" -#include "MetadataHelper.h" -#include "CollisionTypeHelper.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Core/CollisionTypeHelper.h" +#include "Common/Core/MetadataHelper.h" +#include "Common/Core/TableHelper.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.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 +#include +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::pid; using namespace o2::framework::expressions; using namespace o2::track; -MetadataHelper metadataInfo; +o2::common::core::MetadataHelper metadataInfo; // Input data types using Trks = o2::soa::Join; @@ -82,14 +100,14 @@ struct TOFCalibConfig { } template - void getCfg(o2::framework::InitContext& initContext, const std::string name, VType& v, const std::string task) + void getCfg(o2::framework::InitContext& initContext, const std::string& name, VType& v, const std::string& task) { if (!getTaskOptionValue(initContext, task, name, v, false)) { LOG(fatal) << "Could not get " << name << " from " << task << " task"; } } - void inheritFromBaseTask(o2::framework::InitContext& initContext, const std::string task = "tof-signal") + void inheritFromBaseTask(o2::framework::InitContext& initContext, const std::string& task = "tof-signal") { mInitMode = 2; getCfg(initContext, "ccdb-url", mUrl, task); @@ -297,7 +315,7 @@ struct TOFCalibConfig { // Configurable options std::string mUrl; std::string mPathGrpLhcIf; - int64_t mTimestamp; + int64_t mTimestamp{0}; std::string mTimeShiftCCDBPathPos; std::string mTimeShiftCCDBPathNeg; std::string mTimeShiftCCDBPathPosMC; @@ -306,10 +324,10 @@ struct TOFCalibConfig { std::string mParametrizationPath; std::string mReconstructionPass; std::string mReconstructionPassDefault; - bool mFatalOnPassNotAvailable; - bool mEnableTimeDependentResponse; - int mCollisionSystem; - bool mAutoSetProcessFunctions; + bool mFatalOnPassNotAvailable{false}; + bool mEnableTimeDependentResponse{false}; + int mCollisionSystem{-1}; + bool mAutoSetProcessFunctions{false}; }; // Part 1 TOF signal definition @@ -737,6 +755,10 @@ struct mcPidTof { Configurable ccdbPath{"ccdbPath", "Users/f/fgrosa/RecalibmcPidTof/", "path for MC recalibration objects in CCDB"}; } mcRecalib; + // list of productions for which the postcalibrations must be turned off (FT0 digitisation fixed) + const std::vector prodNoPostCalib = {"LHC24h1c"}; + bool enableMcRecalib{false}; + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Running variables @@ -793,6 +815,8 @@ struct mcPidTof { } hnSigmaFull[iSpecie] = histos.add(Form("nSigmaFull/%s", particleNames[iSpecie].c_str()), Form("N_{#sigma}^{TOF}(%s)", particleNames[iSpecie].c_str()), kTH2F, {pAxis, nSigmaAxis}); } + + enableMcRecalib = mcRecalib.enable; } // Reserves an empty table for the given particle ID with size of the given track table @@ -870,6 +894,10 @@ struct mcPidTof { std::map metadata; if (metadataInfo.isFullyDefined()) { metadata["RecoPassName"] = metadataInfo.get("AnchorPassName"); + if (std::find(prodNoPostCalib.begin(), prodNoPostCalib.end(), metadataInfo.get("LPMProductionTag")) != prodNoPostCalib.end()) { + enableMcRecalib = false; + LOGP(warn, "Nsigma postcalibrations turned off for {} (new MC productions have FT0 digitisation fixed)", metadataInfo.get("LPMProductionTag")); + } } else { LOGP(error, "Impossible to read metadata! Using default calibrations (2022 apass7)"); metadata["RecoPassName"] = ""; @@ -956,7 +984,7 @@ struct mcPidTof { continue; } - if (mcRecalib.enable) { + if (enableMcRecalib) { auto runNumber = trk.collision().bc_as().runNumber(); if (runNumber != currentRun) { // update postcalibration files @@ -970,7 +998,7 @@ struct mcPidTof { switch (pidId) { case idxPi: { nSigma = responsePi.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kPiPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -980,7 +1008,7 @@ struct mcPidTof { } case idxKa: { nSigma = responseKa.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kKPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -990,7 +1018,7 @@ struct mcPidTof { } case idxPr: { nSigma = responsePr.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kProton) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -1012,7 +1040,7 @@ struct mcPidTof { case idxPi: { resolution = responsePi.GetExpectedSigma(mRespParamsV3, trk); nSigma = responsePi.GetSeparation(mRespParamsV3, trk); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kPiPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -1023,7 +1051,7 @@ struct mcPidTof { case idxKa: { resolution = responseKa.GetExpectedSigma(mRespParamsV3, trk); nSigma = responseKa.GetSeparation(mRespParamsV3, trk, resolution); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kKPlus) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } @@ -1034,7 +1062,7 @@ struct mcPidTof { case idxPr: { resolution = responsePr.GetExpectedSigma(mRespParamsV3, trk); nSigma = responsePr.GetSeparation(mRespParamsV3, trk, resolution); - if (mcRecalib.enable && trk.has_mcParticle()) { + if (enableMcRecalib && trk.has_mcParticle()) { if (std::abs(trk.mcParticle().pdgCode()) == kProton) { // we rescale only true signal nSigma = applyMcRecalib(pidId, trk.pt(), nSigma); } diff --git a/PWGHF/TableProducer/pidCreator.cxx b/PWGHF/TableProducer/pidCreator.cxx index 57da53a0d30..d4a236b5d72 100644 --- a/PWGHF/TableProducer/pidCreator.cxx +++ b/PWGHF/TableProducer/pidCreator.cxx @@ -14,15 +14,21 @@ /// /// \author Vít Kučera , Inha University -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "Common/Core/TableHelper.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/refitPvDummy.cxx b/PWGHF/TableProducer/refitPvDummy.cxx index 64b13f2d5cb..51b7db06236 100644 --- a/PWGHF/TableProducer/refitPvDummy.cxx +++ b/PWGHF/TableProducer/refitPvDummy.cxx @@ -14,14 +14,15 @@ /// /// \author Mattia Faggin , University and INFN Padova, Italy -#include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "Common/Core/trackUtilities.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/trackIndexSkimCreator.cxx b/PWGHF/TableProducer/trackIndexSkimCreator.cxx index 0f98525ceb1..4b03533ce1f 100644 --- a/PWGHF/TableProducer/trackIndexSkimCreator.cxx +++ b/PWGHF/TableProducer/trackIndexSkimCreator.cxx @@ -21,40 +21,64 @@ /// \author Federica Zanone , Heidelberg University /// \author Ruiqi Yin , Fudan University -#include // std::find -#include // std::distance -#include // std::string -#include // std::vector - -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" // for PV refit -#include "DataFormatsParameters/GRPMagField.h" // for PV refit -#include "DataFormatsParameters/GRPObject.h" // for PV refit -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" // for PV refit -#include "DetectorsVertexing/PVertexer.h" // for PV refit -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/V0.h" -#include "ReconstructionDataFormats/Vertex.h" // for PV refit +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsAnalysis.h" +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" #include "Common/Core/trackUtilities.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 "Tools/ML/MlResponse.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include // for PV refit +#include +#include +#include +#include +#include +#include // for PV refit +#include // for PV refit +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for PV refit + +#include +#include + +#include +#include -#include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/Utils/utilsAnalysis.h" -#include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" +#include // std::find +#include +#include +#include +#include +#include // std::distance +#include +#include // std::string +#include // std::vector using namespace o2; using namespace o2::analysis; @@ -63,6 +87,7 @@ using namespace o2::aod; using namespace o2::hf_centrality; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::constants::physics; // enum for candidate type enum CandidateType { @@ -108,7 +133,7 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { void init(InitContext const&) { - std::array doProcess = {doprocessTrigAndCentFT0ASel, doprocessTrigAndCentFT0CSel, doprocessTrigAndCentFT0MSel, doprocessTrigAndCentFV0ASel, doprocessTrigSel, doprocessNoTrigSel}; + std::array doProcess = {doprocessTrigAndCentFT0ASel, doprocessTrigAndCentFT0CSel, doprocessTrigAndCentFT0MSel, doprocessTrigAndCentFV0ASel, doprocessTrigSel, doprocessNoTrigSel, doprocessUpcSel}; if (std::accumulate(doProcess.begin(), doProcess.end(), 0) != 1) { LOGP(fatal, "One and only one process function for collision selection can be enabled at a time!"); } @@ -132,11 +157,19 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { /// Collision selection /// \param collision collision table with - template - void selectCollision(const Col& collision, const BCs&) + template + void selectCollision(const Col& collision, const BCsType& bcs) { float centrality = -1.; - const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + uint32_t rejectionMask; + + if constexpr (applyUpcSel) { + rejectionMask = hfEvSel.getHfCollisionRejectionMaskWithUpc( + collision, centrality, ccdb, registry, bcs); + } else { + rejectionMask = hfEvSel.getHfCollisionRejectionMask( + collision, centrality, ccdb, registry); + } if (fillHistograms) { hfEvSel.fillHistograms(collision, rejectionMask, centrality); @@ -155,46 +188,69 @@ struct HfTrackIndexSkimCreatorTagSelCollisions { } /// Event selection with trigger and FT0A centrality selection - void processTrigAndCentFT0ASel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFT0ASel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFT0ASel, "Use trigger and centrality selection with FT0A", false); /// Event selection with trigger and FT0C centrality selection - void processTrigAndCentFT0CSel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFT0CSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFT0CSel, "Use trigger and centrality selection with FT0C", false); /// Event selection with trigger and FT0M centrality selection - void processTrigAndCentFT0MSel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFT0MSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFT0MSel, "Use trigger and centrality selection with FT0M", false); /// Event selection with trigger and FV0A centrality selection - void processTrigAndCentFV0ASel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigAndCentFV0ASel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigAndCentFV0ASel, "Use trigger and centrality selection with FV0A", false); /// Event selection with trigger selection - void processTrigSel(soa::Join::iterator const& collision, aod::BCsWithTimestamps const& bcs) + void processTrigSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processTrigSel, "Use trigger selection", false); /// Event selection without trigger selection - void processNoTrigSel(aod::Collision const& collision, aod::BCsWithTimestamps const& bcs) + void processNoTrigSel(aod::Collision const& collision, + aod::BcFullInfos const& bcs) { - selectCollision(collision, bcs); + selectCollision(collision, bcs); } PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processNoTrigSel, "Do not use trigger selection", true); + + /// Event selection with UPC + void processUpcSel(soa::Join::iterator const& collision, + aod::BcFullInfos const& bcs, + aod::FT0s const& /*ft0s*/, + aod::FV0As const& /*fv0as*/, + aod::FDDs const& /*fdds*/, + aod::Zdcs const& /*zdcs*/) + { + selectCollision(collision, bcs); + } + PROCESS_SWITCH(HfTrackIndexSkimCreatorTagSelCollisions, processUpcSel, "Use UPC event selection", false); }; /// Track selection @@ -455,7 +511,7 @@ struct HfTrackIndexSkimCreatorTagSelTracks { /// \param dca is a 2-element array with dca in transverse and longitudinal directions /// \param statusProng is the selection flag template - void isSelectedTrack(const T& hfTrack, const float& trackPt, const float& trackEta, const std::array& dca, int& statusProng) + void isSelectedTrack(const T& hfTrack, const float trackPt, const float trackEta, const std::array& dca, int& statusProng) { if (config.fillHistograms) { registry.fill(HIST("hPtNoCuts"), trackPt); @@ -1212,14 +1268,6 @@ struct HfTrackIndexSkimCreator { o2::base::Propagator::MatCorrType noMatCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; int runNumber; - double massPi{0.}; - double massK{0.}; - double massProton{0.}; - double massElectron{0.}; - double massMuon{0.}; - double massDzero{0.}; - double massPhi{0.}; - // 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 @@ -1246,7 +1294,7 @@ struct HfTrackIndexSkimCreator { using FilteredTrackAssocSel = soa::Filtered>; // filter collisions - Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); + Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); // filter track indices Filter filterSelectTrackIds = ((aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::Cand2Prong))) != 0u) || ((aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::Cand3Prong))) != 0u) || ((aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::CandDstar))) != 0u); @@ -1273,34 +1321,26 @@ struct HfTrackIndexSkimCreator { return; } - massPi = o2::constants::physics::MassPiPlus; - massK = o2::constants::physics::MassKPlus; - massProton = o2::constants::physics::MassProton; - massElectron = o2::constants::physics::MassElectron; - massMuon = o2::constants::physics::MassMuonPlus; - massDzero = o2::constants::physics::MassD0; - massPhi = o2::constants::physics::MassPhi; - - arrMass2Prong[hf_cand_2prong::DecayType::D0ToPiK] = std::array{std::array{massPi, massK}, - std::array{massK, massPi}}; + arrMass2Prong[hf_cand_2prong::DecayType::D0ToPiK] = std::array{std::array{MassPiPlus, MassKPlus}, + std::array{MassKPlus, MassPiPlus}}; - arrMass2Prong[hf_cand_2prong::DecayType::JpsiToEE] = std::array{std::array{massElectron, massElectron}, - std::array{massElectron, massElectron}}; + arrMass2Prong[hf_cand_2prong::DecayType::JpsiToEE] = std::array{std::array{MassElectron, MassElectron}, + std::array{MassElectron, MassElectron}}; - arrMass2Prong[hf_cand_2prong::DecayType::JpsiToMuMu] = std::array{std::array{massMuon, massMuon}, - std::array{massMuon, massMuon}}; + arrMass2Prong[hf_cand_2prong::DecayType::JpsiToMuMu] = std::array{std::array{MassMuonPlus, MassMuonPlus}, + std::array{MassMuonPlus, MassMuonPlus}}; - arrMass3Prong[hf_cand_3prong::DecayType::DplusToPiKPi] = std::array{std::array{massPi, massK, massPi}, - std::array{massPi, massK, massPi}}; + arrMass3Prong[hf_cand_3prong::DecayType::DplusToPiKPi] = std::array{std::array{MassPiPlus, MassKPlus, MassPiPlus}, + std::array{MassPiPlus, MassKPlus, MassPiPlus}}; - arrMass3Prong[hf_cand_3prong::DecayType::LcToPKPi] = std::array{std::array{massProton, massK, massPi}, - std::array{massPi, massK, massProton}}; + arrMass3Prong[hf_cand_3prong::DecayType::LcToPKPi] = std::array{std::array{MassProton, MassKPlus, MassPiPlus}, + std::array{MassPiPlus, MassKPlus, MassProton}}; - arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi] = std::array{std::array{massK, massK, massPi}, - std::array{massPi, massK, massK}}; + arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi] = std::array{std::array{MassKPlus, MassKPlus, MassPiPlus}, + std::array{MassPiPlus, MassKPlus, MassKPlus}}; - arrMass3Prong[hf_cand_3prong::DecayType::XicToPKPi] = std::array{std::array{massProton, massK, massPi}, - std::array{massPi, massK, massProton}}; + arrMass3Prong[hf_cand_3prong::DecayType::XicToPKPi] = std::array{std::array{MassProton, MassKPlus, MassPiPlus}, + std::array{MassPiPlus, MassKPlus, MassProton}}; // 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}; @@ -1517,10 +1557,10 @@ struct HfTrackIndexSkimCreator { whichHypo[kN2ProngDecays] = whichHypo[hf_cand_2prong::DecayType::D0ToPiK]; double deltaMass = config.cutsDstarToD0Pi->get(pTBinDstar, 1u); - if (TESTBIT(whichHypo[iDecay2P], 0) && (massHypos[0] > (massDzero + deltaMass) * (massDzero + deltaMass) || massHypos[0] < (massDzero - deltaMass) * (massDzero - deltaMass))) { + if (TESTBIT(whichHypo[iDecay2P], 0) && (massHypos[0] > (MassD0 + deltaMass) * (MassD0 + deltaMass) || massHypos[0] < (MassD0 - deltaMass) * (MassD0 - deltaMass))) { CLRBIT(whichHypo[kN2ProngDecays], 0); } - if (TESTBIT(whichHypo[iDecay2P], 1) && (massHypos[1] > (massDzero + deltaMass) * (massDzero + deltaMass) || massHypos[1] < (massDzero - deltaMass) * (massDzero - deltaMass))) { + if (TESTBIT(whichHypo[iDecay2P], 1) && (massHypos[1] > (MassD0 + deltaMass) * (MassD0 + deltaMass) || massHypos[1] < (MassD0 - deltaMass) * (MassD0 - deltaMass))) { CLRBIT(whichHypo[kN2ProngDecays], 1); } } @@ -1542,13 +1582,13 @@ struct HfTrackIndexSkimCreator { double deltaMassMax = cut3Prong[hf_cand_3prong::DecayType::DsToKKPi].get(pTBin, 4u); if (TESTBIT(whichHypo[hf_cand_3prong::DecayType::DsToKKPi], 0)) { double mass2PhiKKPi = RecoDecay::m2(std::array{pVecTrack0, pVecTrack1}, std::array{arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi][0][0], arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi][0][1]}); - if (mass2PhiKKPi > (massPhi + deltaMassMax) * (massPhi + deltaMassMax) || mass2PhiKKPi < (massPhi - deltaMassMax) * (massPhi - deltaMassMax)) { + if (mass2PhiKKPi > (MassPhi + deltaMassMax) * (MassPhi + deltaMassMax) || mass2PhiKKPi < (MassPhi - deltaMassMax) * (MassPhi - deltaMassMax)) { CLRBIT(whichHypo[hf_cand_3prong::DecayType::DsToKKPi], 0); } } if (TESTBIT(whichHypo[hf_cand_3prong::DecayType::DsToKKPi], 1)) { double mass2PhiPiKK = RecoDecay::m2(std::array{pVecTrack1, pVecTrack2}, std::array{arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi][1][1], arrMass3Prong[hf_cand_3prong::DecayType::DsToKKPi][1][2]}); - if (mass2PhiPiKK > (massPhi + deltaMassMax) * (massPhi + deltaMassMax) || mass2PhiPiKK < (massPhi - deltaMassMax) * (massPhi - deltaMassMax)) { + if (mass2PhiPiKK > (MassPhi + deltaMassMax) * (MassPhi + deltaMassMax) || mass2PhiPiKK < (MassPhi - deltaMassMax) * (MassPhi - deltaMassMax)) { CLRBIT(whichHypo[hf_cand_3prong::DecayType::DsToKKPi], 1); } } @@ -1646,7 +1686,7 @@ struct HfTrackIndexSkimCreator { /// \param cutStatus is a 2D array with outcome of each selection (filled only in debug mode) /// \param isSelected ia s bitmap with selection outcome template - void applySelections2Prong(const T1& pVecCand, const T2& secVtx, const T3& primVtx, T4& cutStatus, int& isSelected) + void applySelection2Prong(const T1& pVecCand, const T2& secVtx, const T3& primVtx, T4& cutStatus, int& isSelected) { if (config.debug || isSelected > 0) { @@ -1857,8 +1897,8 @@ struct HfTrackIndexSkimCreator { // D0 mass double deltaMassD0 = config.cutsDstarToD0Pi->get(pTBin, 1u); // 1u == deltaMassD0Index - double invMassD0 = RecoDecay::m(arrMomD0, std::array{massPi, massK}); - if (std::abs(invMassD0 - massDzero) > deltaMassD0) { + double invMassD0 = RecoDecay::m(arrMomD0, std::array{MassPiPlus, MassKPlus}); + if (std::abs(invMassD0 - MassD0) > deltaMassD0) { isSelected = 0; if (config.debug) { CLRBIT(cutStatus, 1); @@ -1868,7 +1908,7 @@ struct HfTrackIndexSkimCreator { // D*+ mass double maxDeltaMass = config.cutsDstarToD0Pi->get(pTBin, 0u); // 0u == deltaMassIndex - double invMassDstar = RecoDecay::m(arrMom, std::array{massPi, massK, massPi}); + double invMassDstar = RecoDecay::m(arrMom, std::array{MassPiPlus, MassKPlus, MassPiPlus}); deltaMass = invMassDstar - invMassD0; if (deltaMass > maxDeltaMass) { isSelected = 0; @@ -2254,7 +2294,7 @@ struct HfTrackIndexSkimCreator { pvCoord2Prong[1] = pvRefitCoord2Prong[1]; pvCoord2Prong[2] = pvRefitCoord2Prong[2]; } - applySelections2Prong(pVecCandProng2, secondaryVertex2, pvCoord2Prong, cutStatus2Prong, isSelected2ProngCand); + applySelection2Prong(pVecCandProng2, secondaryVertex2, pvCoord2Prong, cutStatus2Prong, isSelected2ProngCand); if (is2ProngCandidateGoodFor3Prong && config.do3Prong == 1) { is2ProngCandidateGoodFor3Prong = isTwoTrackVertexSelectedFor3Prongs(secondaryVertex2, pvCoord2Prong, df2); } @@ -3051,14 +3091,10 @@ struct HfTrackIndexSkimCreatorCascades { o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; int runNumber{0}; - double massP{0.}; - double massK0s{0.}; - double massLc{0.}; - using SelectedCollisions = soa::Filtered>; using FilteredTrackAssocSel = soa::Filtered>; - Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); + Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::CandV0bachelor))) != 0u && (config.applyProtonPid == false || (aod::hf_sel_track::isIdentifiedPid & static_cast(BIT(ChannelsProtonPid::LcToPK0S))) != 0u); Preslice trackIndicesPerCollision = aod::track_association::collisionId; @@ -3077,10 +3113,6 @@ struct HfTrackIndexSkimCreatorCascades { config.etaMinV0Daugh.value = -config.etaMaxV0Daugh; } - massP = o2::constants::physics::MassProton; - massK0s = o2::constants::physics::MassK0Short; - massLc = o2::constants::physics::MassLambdaCPlus; - if (config.useDCAFitter) { df2.setPropagateToPCA(config.propagateToPCA); df2.setMaxR(config.maxR); @@ -3170,7 +3202,7 @@ struct HfTrackIndexSkimCreatorCascades { } // V0 invariant mass selection - if (std::abs(v0.mK0Short() - massK0s) > config.cutInvMassV0) { + if (std::abs(v0.mK0Short() - MassK0Short) > config.cutInvMassV0) { continue; // should go to the filter, but since it is a dynamic column, I cannot use it there } @@ -3183,8 +3215,8 @@ struct HfTrackIndexSkimCreatorCascades { // invariant-mass cut: we do it here, before updating the momenta of bach and V0 during the fitting to save CPU // TODO: but one should better check that the value here and after the fitter do not change significantly!!! - double mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{massP, massK0s}); - if ((config.cutInvMassCascLc >= 0.) && (std::abs(mass2K0sP - massLc) > config.cutInvMassCascLc)) { + double mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{MassProton, MassK0Short}); + if ((config.cutInvMassCascLc >= 0.) && (std::abs(mass2K0sP - MassLambdaCPlus) > config.cutInvMassCascLc)) { continue; } @@ -3226,7 +3258,7 @@ struct HfTrackIndexSkimCreatorCascades { // invariant mass // re-calculate invariant masses with updated momenta, to fill the histogram - mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{massP, massK0s}); + mass2K0sP = RecoDecay::m(std::array{pVecBach, pVecV0}, std::array{MassProton, MassK0Short}); std::array posCasc = {0., 0., 0.}; if (config.useDCAFitter) { const auto& cascVtx = df2.getPCACandidate(); @@ -3261,6 +3293,7 @@ struct HfTrackIndexSkimCreatorLfCascades { Configurable do3Prong{"do3Prong", false, "do 3-prong cascade"}; Configurable rejDiffCollTrack{"rejDiffCollTrack", false, "Reject tracks coming from different collisions"}; + Configurable ptTolerance{"ptTolerance", 0.1, "pT tolerance in GeV/c for applying preselections before vertex reconstruction"}; // charm baryon invariant mass spectra limits Configurable massXiPiMin{"massXiPiMin", 2.1, "Invariant mass lower limit for xi pi decay channel"}; @@ -3290,18 +3323,20 @@ struct HfTrackIndexSkimCreatorLfCascades { Configurable ptMinOmegaczeroToOmegaKaLfCasc{"ptMinOmegaczeroToOmegaKaLfCasc", 0.f, "min. pT for Omegaczero in Omega + Ka decays"}; Configurable ptMinXicZeroOmegacZeroToXiPiLfCasc{"ptMinXicZeroOmegacZeroToXiPiLfCasc", 0.f, "min. pT for XicZeroOmegacZero in Xi + Pi decays"}; Configurable ptMinXicplusLfCasc{"ptMinXicplusLfCasc", 0.f, "min. pT for Xicplus in Xi + Pi + Pi decays"}; - Configurable v0TransvRadius{"v0TransvRadius", 1.0, "V0 radius in xy plane"}; // 1.2 (xi) and 1.1 (omega) in run2 - Configurable cascTransvRadius{"cascTransvRadius", 0.4, "Cascade radius in xy plane"}; // 0.5 cm (xi) and 0.6 (omega) in run2 - Configurable dcaBachToPv{"dcaBachToPv", 0.03, "DCA Bach To PV"}; // 0.04 in run2 - Configurable dcaV0ToPv{"dcaV0ToPv", 0.02, "DCA V0 To PV"}; // 0.03 in run2 - Configurable v0CosPA{"v0CosPA", 0.95, "V0 CosPA"}; // 0.97 in run2 - KEEP LOSE to re-cut after PVRefit! - double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable cascCosPA{"cascCosPA", 0.95, "Casc CosPA"}; // 0.97 in run2 - KEEP LOSE to re-cut after PVRefit! - double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable dcaV0Dau{"dcaV0Dau", 2.0, "DCA V0 Daughters"}; // conservative, a cut ar 1.0 should also be fine - Configurable dcaCascDau{"dcaCascDau", 2.0, "DCA Casc Daughters"}; // conservative, a cut ar 1.0 should also be fine - Configurable dcaNegToPv{"dcaNegToPv", 0.05, "DCA Neg To PV"}; // 0.06 in run2 - Configurable dcaPosToPv{"dcaPosToPv", 0.05, "DCA Pos To PV"}; // 0.06 in run2 - Configurable v0MassWindow{"v0MassWindow", 0.01, "V0 mass window"}; // 0.008 in run2 - Configurable cascadeMassWindow{"cascadeMassWindow", 0.01, "Cascade mass window"}; + Configurable v0TransvRadius{"v0TransvRadius", 1.f, "V0 radius in xy plane"}; // 1.2 (xi) and 1.1 (omega) in run2 + Configurable cascTransvRadius{"cascTransvRadius", 0.4f, "Cascade radius in xy plane"}; // 0.5 cm (xi) and 0.6 (omega) in run2 + Configurable decayLengthXicMin{"decayLengthXicMin", -1.f, "Min. decay length of Xic"}; // ... + Configurable dcaBachToPv{"dcaBachToPv", 0.03f, "DCA Bach To PV"}; // 0.04 in run2 + Configurable dcaV0ToPv{"dcaV0ToPv", 0.02f, "DCA V0 To PV"}; // 0.03 in run2 + Configurable v0CosPA{"v0CosPA", 0.95, "V0 CosPA"}; // 0.97 in run2 - KEEP LOSE to re-cut after PVRefit! - double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable cascCosPA{"cascCosPA", 0.95, "Casc CosPA"}; // 0.97 in run2 - KEEP LOSE to re-cut after PVRefit! - double -> N.B. dcos(x)/dx = 0 at x=0) + Configurable xicCosPA{"xicCosPA", 0.95, "Xic CosPA"}; // ... + Configurable dcaV0Dau{"dcaV0Dau", 2.f, "DCA V0 Daughters"}; // conservative, a cut ar 1.0 should also be fine + Configurable dcaCascDau{"dcaCascDau", 2.f, "DCA Casc Daughters"}; // conservative, a cut ar 1.0 should also be fine + Configurable dcaNegToPv{"dcaNegToPv", 0.05f, "DCA Neg To PV"}; // 0.06 in run2 + Configurable dcaPosToPv{"dcaPosToPv", 0.05f, "DCA Pos To PV"}; // 0.06 in run2 + Configurable v0MassWindow{"v0MassWindow", 0.01f, "V0 mass window"}; // 0.008 in run2 + Configurable cascadeMassWindow{"cascadeMassWindow", 0.01f, "Cascade mass window"}; // magnetic field setting from CCDB Configurable isRun2{"isRun2", false, "enable Run 2 or Run 3 GRP objects for magnetic field"}; @@ -3312,7 +3347,6 @@ struct HfTrackIndexSkimCreatorLfCascades { } config; o2::vertexing::DCAFitterN<2> df2; // 2-prong vertex fitter - o2::vertexing::DCAFitterN<3> df3; // 3-prong vertex fitter Service ccdb; o2::base::MatLayerCylSet* lut; o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; @@ -3324,20 +3358,12 @@ struct HfTrackIndexSkimCreatorLfCascades { std::array, kN2ProngDecays> arrMass2Prong; std::array, kN3ProngDecays> arrMass3Prong; - // PDG masses - double massP{0.}; - double massPi{0.}; - double massKaon{0.}; - double massXi{0.}; - double massOmega{0.}; - double massLambda{0.}; - using SelectedCollisions = soa::Filtered>; using SelectedHfTrackAssoc = soa::Filtered>; using CascFull = soa::Join; using V0Full = soa::Join; - Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); + Filter filterSelectCollisions = (aod::hf_sel_collision::whyRejectColl == static_cast(0)); Filter filterSelectTrackIds = (aod::hf_sel_track::isSelProng & static_cast(BIT(CandidateType::CandCascadeBachelor))) != 0u; Preslice tracksPerCollision = aod::track::collisionId; // needed for PV refit @@ -3353,17 +3379,10 @@ struct HfTrackIndexSkimCreatorLfCascades { return; } - massP = o2::constants::physics::MassProton; - massPi = o2::constants::physics::MassPiPlus; - massKaon = o2::constants::physics::MassKPlus; - massXi = o2::constants::physics::MassXiMinus; - massOmega = o2::constants::physics::MassOmegaMinus; - massLambda = o2::constants::physics::MassLambda0; - - arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi] = std::array{massXi, massPi}; - arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi] = std::array{massOmega, massPi}; - arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK] = std::array{massOmega, massKaon}; - arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi] = std::array{massXi, massPi, massPi}; + arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi] = std::array{MassXiMinus, MassPiPlus}; + arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi] = std::array{MassOmegaMinus, MassPiPlus}; + arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK] = std::array{MassOmegaMinus, MassKPlus}; + arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi] = std::array{MassXiMinus, MassPiPlus, MassPiPlus}; df2.setPropagateToPCA(config.propagateToPCA); df2.setMaxR(config.maxR); @@ -3373,14 +3392,6 @@ struct HfTrackIndexSkimCreatorLfCascades { df2.setUseAbsDCA(config.useAbsDCA); df2.setWeightedFinalPCA(config.useWeightedFinalPCA); - df3.setPropagateToPCA(config.propagateToPCA); - df3.setMaxR(config.maxR); - df3.setMaxDZIni(config.maxDZIni); - df3.setMinParamChange(config.minParamChange); - df3.setMinRelChi2Change(config.minRelChi2Change); - df3.setUseAbsDCA(config.useAbsDCA); - df3.setWeightedFinalPCA(config.useWeightedFinalPCA); - ccdb->setURL(config.ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -3438,7 +3449,7 @@ struct HfTrackIndexSkimCreatorLfCascades { /// Single-cascade cuts template - bool isPreselectedCascade(const TCascade& casc, const float& pvx, const float& pvy, const float& pvz) + bool isPreselectedCascade(const TCascade& casc, const float pvx, const float pvy, const float pvz) { registry.fill(HIST("hCandidateCounter"), 2.5); @@ -3452,7 +3463,7 @@ struct HfTrackIndexSkimCreatorLfCascades { std::abs(casc.dcav0topv(pvx, pvy, pvz)) > config.dcaV0ToPv && casc.v0radius() > config.v0TransvRadius && casc.cascradius() > config.cascTransvRadius && - std::abs(casc.mLambda() - massLambda) < config.v0MassWindow) { + std::abs(casc.mLambda() - MassLambda0) < config.v0MassWindow) { registry.fill(HIST("hCandidateCounter"), 3.5); // pass cascade selections @@ -3482,6 +3493,71 @@ struct HfTrackIndexSkimCreatorLfCascades { return false; } + /// Method to perform selections for Xic 3-prong candidates before vertex reconstruction + /// \param pVecXi is the momentum array of the Xi daughter track + /// \param pVecPi1 is the momentum array of the first pion daughter track + /// \param pVecPi2 is the momentum array of the second pion daughter track + /// \return selection outcome + template + bool isPreselectedCandidateXic(T1 const& pVecXi, T1 const& pVecPi1, T1 const& pVecPi2) + { + // pt + if (config.ptMinXicplusLfCasc > 0.f) { + const auto pt = RecoDecay::pt(pVecXi, pVecPi1, pVecPi2) + config.ptTolerance; // add tolerance because of no reco decay vertex + if (pt < config.ptMinXicplusLfCasc) { + return false; + } + } + + // invariant mass + if (config.massXiPiPiMin >= 0.f && config.massXiPiPiMax > 0.f) { + const double invMassMin = config.massXiPiPiMin; + const double invMassMax = config.massXiPiPiMax; + const std::array arrMom{pVecXi, pVecPi1, pVecPi2}; + const auto invMass2 = RecoDecay::m2(arrMom, arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi]); + if (invMass2 < invMassMin * invMassMin || invMass2 >= invMassMax * invMassMax) { + return false; + } + } + + return true; + } + + /// Method to perform selections for Xic 3-prong candidates after vertex reconstruction + /// \param pVecCand is the momentum array of the candidate after the reconstruction of the secondary vertex + /// \param secVtx is the secondary vertex + /// \param primVtx is the primary vertex + /// \return selection outcome + template + bool isSelectedCandidateXic(const T1& pVecCand, const T2& secVtx, const T3& primVtx) + { + // pt + if (config.ptMinXicplusLfCasc > 0.f) { + const auto pt = RecoDecay::pt(pVecCand); + if (pt < config.ptMinXicplusLfCasc) { + return false; + } + } + + // CPA + if (config.xicCosPA > -1.f) { + const auto cpa = RecoDecay::cpa(primVtx, secVtx, pVecCand); + if (cpa < config.xicCosPA) { + return false; + } + } + + // decay length + if (config.decayLengthXicMin > 0.f) { + const auto decayLength = RecoDecay::distance(primVtx, secVtx); + if (decayLength < config.decayLengthXicMin) { + return false; + } + } + + return true; + } + void processNoLfCascades(SelectedCollisions const&) { // dummy @@ -3502,19 +3578,16 @@ struct HfTrackIndexSkimCreatorLfCascades { for (const auto& collision : collisions) { // set the magnetic field from CCDB - auto bc = collision.bc_as(); + const auto bc = collision.bc_as(); initCCDB(bc, runNumber, ccdb, config.isRun2 ? config.ccdbPathGrp : config.ccdbPathGrpMag, lut, config.isRun2); - auto magneticField = o2::base::Propagator::Instance()->getNominalBz(); // z component + const auto magneticField = o2::base::Propagator::Instance()->getNominalBz(); // z component df2.setBz(magneticField); df2.setRefitWithMatCorr(config.refitWithMatCorr); - df3.setBz(magneticField); - df3.setRefitWithMatCorr(config.refitWithMatCorr); - // cascade loop - auto thisCollId = collision.globalIndex(); - auto groupedCascades = cascades.sliceBy(cascadesPerCollision, thisCollId); + const auto thisCollId = collision.globalIndex(); + const auto groupedCascades = cascades.sliceBy(cascadesPerCollision, thisCollId); for (const auto& casc : groupedCascades) { @@ -3522,11 +3595,11 @@ struct HfTrackIndexSkimCreatorLfCascades { //----------------accessing particles in the decay chain------------- // cascade daughter - charged particle - auto trackCascDauCharged = casc.bachelor_as(); // meson <- xi track + const auto trackCascDauCharged = casc.bachelor_as(); // meson <- xi track // cascade daughter - V0 - auto trackV0PosDau = casc.posTrack_as(); // p <- V0 track (positive track) 0 + const auto trackV0PosDau = casc.posTrack_as(); // p <- V0 track (positive track) 0 // V0 negative daughter - auto trackV0NegDau = casc.negTrack_as(); // pion <- V0 track (negative track) 1 + const auto trackV0NegDau = casc.negTrack_as(); // pion <- V0 track (negative track) 1 // check that particles come from the same collision if (config.rejDiffCollTrack) { @@ -3546,8 +3619,8 @@ struct HfTrackIndexSkimCreatorLfCascades { continue; } - std::array vertexCasc = {casc.x(), casc.y(), casc.z()}; - std::array pVecCasc = {casc.px(), casc.py(), casc.pz()}; + const std::array vertexCasc = {casc.x(), casc.y(), casc.z()}; + const std::array pVecCasc = {casc.px(), casc.py(), casc.pz()}; std::array covCasc = {0.}; constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component for (int i = 0; i < 6; i++) { @@ -3555,30 +3628,30 @@ struct HfTrackIndexSkimCreatorLfCascades { covCasc[i] = casc.positionCovMat()[i]; } // create cascade track - o2::track::TrackParCov trackCascXi; + o2::track::TrackParCov trackParCovCascXi; if (trackCascDauCharged.sign() > 0) { - trackCascXi = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, 1, true); + trackParCovCascXi = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, 1, true); } else if (trackCascDauCharged.sign() < 0) { - trackCascXi = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, -1, true); + trackParCovCascXi = o2::track::TrackParCov(vertexCasc, pVecCasc, covCasc, -1, true); } else { continue; } - trackCascXi.setAbsCharge(1); + trackParCovCascXi.setAbsCharge(1); - auto trackCascOmega = trackCascXi; + auto trackParCovCascOmega = trackParCovCascXi; - trackCascXi.setPID(o2::track::PID::XiMinus); - trackCascOmega.setPID(o2::track::PID::OmegaMinus); + trackParCovCascXi.setPID(o2::track::PID::XiMinus); + trackParCovCascOmega.setPID(o2::track::PID::OmegaMinus); //--------------combining cascade and pion tracks-------------- - auto groupedBachTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); + const auto groupedBachTrackIndices = trackIndices.sliceBy(trackIndicesPerCollision, thisCollId); for (auto trackIdCharmBachelor1 = groupedBachTrackIndices.begin(); trackIdCharmBachelor1 != groupedBachTrackIndices.end(); ++trackIdCharmBachelor1) { hfFlag = 0; isGoogForXi2Prong = true; isGoogForOmega2Prong = true; - auto trackCharmBachelor1 = trackIdCharmBachelor1.track_as(); + const auto trackCharmBachelor1 = trackIdCharmBachelor1.track_as(); if ((config.rejDiffCollTrack) && (trackCascDauCharged.collisionId() != trackCharmBachelor1.collisionId())) { continue; @@ -3595,12 +3668,12 @@ struct HfTrackIndexSkimCreatorLfCascades { } // primary pion track to be processed with DCAFitter - auto trackParVarCharmBachelor1 = getTrackParCov(trackCharmBachelor1); + const auto trackParCovCharmBachelor1 = getTrackParCov(trackCharmBachelor1); // find charm baryon decay using xi PID hypothesis (xi pi channel) int nVtxFrom2ProngFitterXiHyp = 0; try { - nVtxFrom2ProngFitterXiHyp = df2.process(trackCascXi, trackParVarCharmBachelor1); + nVtxFrom2ProngFitterXiHyp = df2.process(trackParCovCascXi, trackParCovCharmBachelor1); } catch (...) { if (config.fillHistograms) { registry.fill(HIST("hFitterStatusXi2Prong"), 1); @@ -3625,7 +3698,7 @@ struct HfTrackIndexSkimCreatorLfCascades { std::array, 2> arrMomToXi = {pVecXi, pVecPion1XiHyp}; auto mass2ProngXiHyp = RecoDecay::m(arrMomToXi, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::XiczeroOmegaczeroToXiPi]); - if ((std::abs(casc.mXi() - massXi) < config.cascadeMassWindow) && (mass2ProngXiHyp >= config.massXiPiMin) && (mass2ProngXiHyp <= config.massXiPiMax)) { + 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); @@ -3646,7 +3719,7 @@ struct HfTrackIndexSkimCreatorLfCascades { // find charm baryon decay using omega PID hypothesis to be combined with the charm bachelor (either pion or kaon) int nVtxFrom2ProngFitterOmegaHyp = 0; try { - nVtxFrom2ProngFitterOmegaHyp = df2.process(trackCascOmega, trackParVarCharmBachelor1); + nVtxFrom2ProngFitterOmegaHyp = df2.process(trackParCovCascOmega, trackParCovCharmBachelor1); } catch (...) { if (config.fillHistograms) { registry.fill(HIST("hFitterStatusOmega2Prong"), 1); @@ -3673,7 +3746,7 @@ struct HfTrackIndexSkimCreatorLfCascades { auto mass2ProngOmegaPiHyp = RecoDecay::m(arrMomToOmega, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi]); auto mass2ProngOmegaKHyp = RecoDecay::m(arrMomToOmega, arrMass2Prong[hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK]); - if (std::abs(casc.mOmega() - massOmega) < config.cascadeMassWindow) { + if (std::abs(casc.mOmega() - MassOmegaMinus) < config.cascadeMassWindow) { if ((mass2ProngOmegaPiHyp >= config.massOmegaCharmBachelorMin) && (mass2ProngOmegaPiHyp <= config.massOmegaCharmBachelorMax)) { registry.fill(HIST("hRejpTStatusOmegacZeroToOmegaPi"), 0); if (ptOmegac >= config.ptMinOmegacZeroToOmegaPiLfCasc) { @@ -3714,19 +3787,21 @@ struct HfTrackIndexSkimCreatorLfCascades { hfFlag); } - // first loop over tracks + // Xic -> Xi pi pi if (config.do3Prong) { + // Xi mass cut + if (std::abs(casc.mXi() - MassXiMinus) > config.cascadeMassWindow) { + continue; + } - // second loop over positive tracks + // second loop over tracks for (auto trackIdCharmBachelor2 = trackIdCharmBachelor1 + 1; trackIdCharmBachelor2 != groupedBachTrackIndices.end(); ++trackIdCharmBachelor2) { - hfFlag = 0; - if (!TESTBIT(trackIdCharmBachelor2.isSelProng(), CandidateType::CandCascadeBachelor)) { continue; } - auto trackCharmBachelor2 = trackIdCharmBachelor2.track_as(); + const auto trackCharmBachelor2 = trackIdCharmBachelor2.track_as(); if ((config.rejDiffCollTrack) && (trackCascDauCharged.collisionId() != trackCharmBachelor2.collisionId())) { continue; @@ -3742,13 +3817,16 @@ struct HfTrackIndexSkimCreatorLfCascades { continue; } - // primary pion track to be processed with DCAFitter - auto trackParVarPion2 = getTrackParCov(trackCharmBachelor2); + if (!isPreselectedCandidateXic(pVecCasc, trackCharmBachelor1.pVector(), trackCharmBachelor2.pVector())) { + continue; + } // reconstruct Xic with DCAFitter + // Use only bachelor tracks for vertex reconstruction because the Xi track has large uncertainties. int nVtxFrom3ProngFitterXiHyp = 0; try { - nVtxFrom3ProngFitterXiHyp = df3.process(trackCascXi, trackParVarCharmBachelor1, trackParVarPion2); + const auto trackParCovCharmBachelor2 = getTrackParCov(trackCharmBachelor2); + nVtxFrom3ProngFitterXiHyp = df2.process(trackParCovCharmBachelor1, trackParCovCharmBachelor2); } catch (...) { if (config.fillHistograms) { registry.fill(HIST("hFitterStatusXi3Prong"), 1); @@ -3760,48 +3838,44 @@ 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); + } - df3.propagateTracksToVertex(); - - if (df3.isPropagateTracksToVertexDone()) { - - std::array pVec1 = {0.}; - std::array pVec2 = {0.}; - std::array pVec3 = {0.}; - df3.getTrack(0).getPxPyPzGlo(pVec1); // take the momentum at the Xic vertex - df3.getTrack(1).getPxPyPzGlo(pVec2); - df3.getTrack(2).getPxPyPzGlo(pVec3); - float ptXic3Prong = RecoDecay::pt(pVec1, pVec2, pVec3); - - std::array, 3> arr3Mom = {pVec1, pVec2, pVec3}; - auto mass3Prong = RecoDecay::m(arr3Mom, arrMass3Prong[hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi]); - - if ((std::abs(casc.mXi() - massXi) < config.cascadeMassWindow) && (mass3Prong >= config.massXiPiPiMin) && (mass3Prong <= config.massXiPiPiMax)) { - registry.fill(HIST("hRejpTStatusXicPlusToXiPiPi"), 0); - if (ptXic3Prong >= config.ptMinXicplusLfCasc) { - SETBIT(hfFlag, aod::hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi); - registry.fill(HIST("hRejpTStatusXicPlusToXiPiPi"), 1); - } + if (!isSelectedCandidateXic(pVecCand, secondaryVertex, primaryVertex)) { + continue; } // fill histograms - if (config.fillHistograms && (TESTBIT(hfFlag, aod::hf_cand_casc_lf::DecayType3Prong::XicplusToXiPiPi))) { + 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"), ptXic3Prong); + registry.fill(HIST("hPtCutsXicPlusToXiPiPi"), ptCand); } - } else if (df3.isPropagationFailure()) { + + // 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 table row only if a vertex was found - if (hfFlag != 0) { - 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 0288f19cac9..ebfd87c5e46 100644 --- a/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx +++ b/PWGHF/TableProducer/treeCreatorB0ToDPi.cxx @@ -16,17 +16,29 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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::hf_decay::hf_cand_beauty; namespace o2::aod { @@ -177,8 +189,8 @@ struct HfTreeCreatorB0ToDPi { Filter filterSelectCandidates = aod::hf_sel_candidate_b0::isSelB0ToDPi >= selectionFlagB0; - Partition recSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); - Partition recBg = nabs(aod::hf_cand_b0::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi); + Partition recSig = nabs(aod::hf_cand_b0::flagMcMatchRec) == static_cast(DecayChannelMain::B0ToDminusPi); + Partition recBg = nabs(aod::hf_cand_b0::flagMcMatchRec) != static_cast(DecayChannelMain::B0ToDminusPi); void init(InitContext const&) { @@ -361,7 +373,7 @@ struct HfTreeCreatorB0ToDPi { // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_b0::DecayTypeMc::B0ToDplusPiToPiKPiPi)) { + if (std::abs(particle.flagMcMatchGen()) == DecayChannelMain::B0ToDminusPi) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), diff --git a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx index 7b2c1145c3f..cd9665de50c 100644 --- a/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorBplusToD0Pi.cxx @@ -17,17 +17,30 @@ /// /// \author Antonio Palasciano , Università & INFN, Bari -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#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_decay::hf_cand_beauty; namespace o2::aod { @@ -232,8 +245,8 @@ struct HfTreeCreatorBplusToD0Pi { Filter filterSelectCandidates = aod::hf_sel_candidate_bplus::isSelBplusToD0Pi >= selectionFlagBplus; - Partition recSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_bplus::DecayTypeMc::BplusToD0PiToKPiPi); - Partition recBg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_bplus::DecayTypeMc::BplusToD0PiToKPiPi); + Partition recSig = nabs(aod::hf_cand_bplus::flagMcMatchRec) == static_cast(DecayChannelMain::BplusToD0Pi); + Partition recBg = nabs(aod::hf_cand_bplus::flagMcMatchRec) != static_cast(DecayChannelMain::BplusToD0Pi); void init(InitContext const&) { @@ -450,7 +463,7 @@ struct HfTreeCreatorBplusToD0Pi { // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { - if (std::abs(particle.flagMcMatchGen()) == 1 << aod::hf_cand_bplus::DecayTypeMc::BplusToD0PiToKPiPi) { + if (std::abs(particle.flagMcMatchGen()) == DecayChannelMain::BplusToD0Pi) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.mcCollisionId(), diff --git a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx index bdbf09cfbed..3c639967995 100644 --- a/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx +++ b/PWGHF/TableProducer/treeCreatorBsToDsPi.cxx @@ -16,17 +16,29 @@ /// \note Adapted from treeCreatorB0T0DPi.cxx /// \author Phil Stahlhut -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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::hf_decay::hf_cand_beauty; namespace o2::aod { @@ -172,8 +184,8 @@ struct HfTreeCreatorBsToDsPi { Filter filterSelectCandidates = aod::hf_sel_candidate_bs::isSelBsToDsPi >= selectionFlagBs; - Partition recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); - Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != (int8_t)BIT(aod::hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi); + Partition recSig = nabs(aod::hf_cand_bs::flagMcMatchRec) == static_cast(DecayChannelMain::BsToDsPi); + Partition recBg = nabs(aod::hf_cand_bs::flagMcMatchRec) != static_cast(DecayChannelMain::BsToDsPi); void init(InitContext const&) { @@ -351,7 +363,7 @@ struct HfTreeCreatorBsToDsPi { // Filling particle properties rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_bs::DecayTypeMc::BsToDsPiToPhiPiPiToKKPiPi)) { + if (std::abs(particle.flagMcMatchGen()) == DecayChannelMain::BsToDsPi) { rowCandidateFullParticles( particle.mcCollision().bcId(), particle.pt(), diff --git a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx index 233b1055ea6..bda20c52903 100644 --- a/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorD0ToKPi.cxx @@ -17,14 +17,27 @@ /// \author Nicolo' Jacazio , CERN /// \author Andrea Tavira García , IJCLab -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.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; using namespace o2::framework::expressions; @@ -72,6 +85,8 @@ DECLARE_SOA_COLUMN(Ct, ct, float); DECLARE_SOA_COLUMN(ImpactParameterProduct, impactParameterProduct, float); DECLARE_SOA_COLUMN(CosThetaStar, cosThetaStar, float); DECLARE_SOA_COLUMN(FlagMc, flagMc, int8_t); +DECLARE_SOA_COLUMN(FlagMcDecayChanRec, flagMcDecayChanRec, int8_t); +DECLARE_SOA_COLUMN(FlagMcDecayChanGen, flagMcDecayChanGen, int8_t); DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); // is prompt or non-prompt, reco level DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int8_t); // is prompt or non-prompt, Gen level DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCand2Prong, "_0"); @@ -123,6 +138,7 @@ DECLARE_SOA_TABLE(HfCandD0Lites, "AOD", "HFCANDD0LITE", full::Phi, full::Y, full::FlagMc, + full::FlagMcDecayChanRec, full::OriginMcRec) DECLARE_SOA_TABLE(HfCandD0Fulls, "AOD", "HFCANDD0FULL", @@ -185,6 +201,7 @@ DECLARE_SOA_TABLE(HfCandD0Fulls, "AOD", "HFCANDD0FULL", full::Y, full::E, full::FlagMc, + full::FlagMcDecayChanRec, full::OriginMcRec, full::CandidateId); @@ -204,6 +221,7 @@ DECLARE_SOA_TABLE(HfCandD0FullPs, "AOD", "HFCANDD0FULLP", full::Phi, full::Y, full::FlagMc, + full::FlagMcDecayChanGen, full::OriginMcGen, full::McParticleId); @@ -226,6 +244,7 @@ struct HfTreeCreatorD0ToKPi { // 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"}; + Configurable fillCorrBkgs{"fillCorrBkgs", false, "Flag to fill derived tables with correlated background candidates"}; HfHelper hfHelper; @@ -237,17 +256,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(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + 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)); - Partition reconstructedCandSig = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandBkg = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandSigKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandBkgKF = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); + 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 reconstructedCandSigMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandBkgMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandSigKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) == static_cast(BIT(aod::hf_cand_2prong::DecayType::D0ToPiK)); - Partition reconstructedCandBkgKFMl = nabs(aod::hf_cand_2prong::flagMcMatchRec) != static_cast(BIT(aod::hf_cand_2prong::DecayType::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); void init(InitContext const&) { @@ -275,7 +294,7 @@ struct HfTreeCreatorD0ToKPi { template auto fillTable(const T& candidate, int candFlag, double invMass, double topoChi2, - double ct, double y, double e, int8_t flagMc, int8_t origin) + double ct, double y, double e, int8_t flagMc, int8_t flagMcDecay, int8_t origin) { if (fillCandidateLiteTable) { rowCandidateLite( @@ -313,6 +332,7 @@ struct HfTreeCreatorD0ToKPi { candidate.phi(), y, flagMc, + flagMcDecay, origin); } else { double cosThetaStar = candFlag == 0 ? hfHelper.cosThetaStarD0(candidate) : hfHelper.cosThetaStarD0bar(candidate); @@ -376,6 +396,7 @@ struct HfTreeCreatorD0ToKPi { y, e, flagMc, + flagMcDecay, origin, candidate.globalIndex()); } @@ -435,10 +456,10 @@ struct HfTreeCreatorD0ToKPi { massD0bar = hfHelper.invMassD0barToKPi(candidate); } if (candidate.isSelD0()) { - fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, 0, 0); + fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, 0, 0, 0); } if (candidate.isSelD0bar()) { - fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, 0, 0); + fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, 0, 0, 0); } } } @@ -504,7 +525,7 @@ struct HfTreeCreatorD0ToKPi { } for (const auto& candidate : candidates) { if constexpr (onlyBkg) { - if (TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if ((std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && (candidate.flagMcMatchRec() != 0))) { continue; } if (downSampleBkgFactor < 1.) { @@ -515,7 +536,7 @@ struct HfTreeCreatorD0ToKPi { } } if constexpr (onlySig) { - if (!TESTBIT(std::abs(candidate.flagMcMatchRec()), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if ((std::abs(candidate.flagMcMatchRec()) != o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && (candidate.flagMcMatchRec() != 0))) { continue; } } @@ -533,17 +554,17 @@ struct HfTreeCreatorD0ToKPi { massD0bar = hfHelper.invMassD0barToKPi(candidate); } if (candidate.isSelD0()) { - fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); + fillTable(candidate, 0, massD0, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.flagMcDecayChanRec(), candidate.originMcRec()); } if (candidate.isSelD0bar()) { - fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.originMcRec()); + fillTable(candidate, 1, massD0bar, topolChi2PerNdf, ctD, yD, eD, candidate.flagMcMatchRec(), candidate.flagMcDecayChanRec(), candidate.originMcRec()); } } // Filling particle properties rowCandidateFullParticles.reserve(mcParticles.size()); for (const auto& particle : mcParticles) { - if (TESTBIT(std::abs(particle.flagMcMatchGen()), aod::hf_cand_2prong::DecayType::D0ToPiK)) { + if ((std::abs(particle.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) || (fillCorrBkgs && particle.flagMcMatchGen() != 0)) { rowCandidateFullParticles( particle.mcCollisionId(), particle.pt(), @@ -551,6 +572,7 @@ struct HfTreeCreatorD0ToKPi { particle.phi(), RecoDecay::y(particle.pVector(), o2::constants::physics::MassD0), particle.flagMcMatchGen(), + particle.flagMcDecayChanGen(), particle.originMcGen(), particle.globalIndex()); } diff --git a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx index 3d23c0b30ca..cc684c7003f 100644 --- a/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDplusToPiKPi.cxx @@ -16,17 +16,27 @@ /// /// \author Alexandre Bigot , IPHC Strasbourg -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/HfHelper.h" #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 "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::framework; using namespace o2::framework::expressions; @@ -135,12 +145,12 @@ DECLARE_SOA_TABLE(HfCandDpLites, "AOD", "HFCANDDPLITE", full::Phi, full::Y, full::Centrality, + collision::NumContrib, hf_cand_3prong::FlagMcMatchRec, hf_cand_3prong::OriginMcRec, hf_cand_3prong::FlagMcDecayChanRec) DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", - collision::BCId, collision::NumContrib, collision::PosX, collision::PosY, @@ -222,7 +232,6 @@ DECLARE_SOA_TABLE(HfCandDpFulls, "AOD", "HFCANDDPFULL", hf_cand_3prong::FlagMcDecayChanRec); DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", - collision::BCId, collision::NumContrib, collision::PosX, collision::PosY, @@ -231,12 +240,12 @@ DECLARE_SOA_TABLE(HfCandDpFullEvs, "AOD", "HFCANDDPFULLEV", full::RunNumber); DECLARE_SOA_TABLE(HfCandDpFullPs, "AOD", "HFCANDDPFULLP", - collision::BCId, full::Pt, full::Eta, full::Phi, full::Y, - hf_cand_3prong::FlagMcMatchRec, + hf_cand_3prong::FlagMcMatchGen, + hf_cand_3prong::FlagMcDecayChanGen, hf_cand_3prong::OriginMcGen); } // namespace o2::aod @@ -252,6 +261,7 @@ struct HfTreeCreatorDplusToPiKPi { Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; // parameters for production of training samples Configurable fillOnlySignal{"fillOnlySignal", false, "Flag to fill derived tables with signal for ML trainings"}; + Configurable fillCorrBkgs{"fillCorrBkgs", false, "Flag to fill derived tables with correlated background candidates"}; Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; @@ -268,11 +278,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); + 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)); - Partition reconstructedCandSig = nabs(aod::hf_cand_3prong::flagMcMatchRec) == static_cast(hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi) || 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); + 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) || 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::DstarToPiKPi); + 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)); void init(InitContext const&) { @@ -282,7 +292,6 @@ struct HfTreeCreatorDplusToPiKPi { void fillEvent(const T& collision, int isEventReject, int runNumber) { rowCandidateFullEvents( - collision.bcId(), collision.numContrib(), collision.posX(), collision.posY(), @@ -362,13 +371,13 @@ struct HfTreeCreatorDplusToPiKPi { candidate.eta(), candidate.phi(), hfHelper.yDplus(candidate), + coll.numContrib(), cent, flagMc, originMc, channelMc); } else { rowCandidateFull( - coll.bcId(), coll.numContrib(), candidate.posX(), candidate.posY(), @@ -509,11 +518,11 @@ struct HfTreeCreatorDplusToPiKPi { PROCESS_SWITCH(HfTreeCreatorDplusToPiKPi, processDataWCent, "Process data with cent", false); - template + template void fillMcTables(CollType const& collisions, aod::McCollisions const&, - CandType const& candidates, - MatchedGenCandidatesMc const& particles, + CandTypeMcRec const& candidates, + CandTypeMcGen const& particles, TracksWPid const&) { // Filling event properties @@ -542,12 +551,12 @@ struct HfTreeCreatorDplusToPiKPi { rowCandidateFullParticles.reserve(particles.size()); for (const auto& particle : particles) { rowCandidateFullParticles( - particle.mcCollision().bcId(), particle.pt(), particle.eta(), particle.phi(), RecoDecay::y(particle.pVector(), o2::constants::physics::MassDPlus), particle.flagMcMatchGen(), + particle.flagMcDecayChanGen(), particle.originMcGen()); } } diff --git a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx index 7a8547cf32a..de1c9984435 100644 --- a/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorDsToKKPi.cxx @@ -17,17 +17,30 @@ /// \author Stefano Politanò , Politecnico & INFN, Torino /// \author Fabio Catalano , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/HfHelper.h" #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 "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 + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -272,8 +285,6 @@ struct HfTreeCreatorDsToKKPi { using CollisionsWithFT0M = soa::Join; using CollisionsWithNTracksPV = soa::Join; - int offsetDplusDecayChannel = aod::hf_cand_3prong::DecayChannelDToKKPi::DplusToPhiPi - aod::hf_cand_3prong::DecayChannelDToKKPi::DsToPhiPi; // Offset between Dplus and Ds to use the same decay channel. See aod::hf_cand_3prong::DecayChannelDToKKPi - Filter 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) && @@ -283,8 +294,11 @@ struct HfTreeCreatorDsToKKPi { 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 && 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); + 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]); void init(InitContext const&) { @@ -314,42 +328,40 @@ struct HfTreeCreatorDsToKKPi { template void fillCandidateTable(const T& candidate) { - int8_t flagMc = 0; - int8_t originMc = 0; - int8_t channelMc = 0; - int8_t isSwapped = massHypo; // 0 if KKPi, 1 if PiKK - float yCand = 0; - float eCand = 0; - float ctCand = 0; + float invMassDs = 0; + float deltaMassPhiKK = 0; + float absCos3PiKDs = 0; + if constexpr (massHypo == 0) { + invMassDs = hfHelper.invMassDsToKKPi(candidate); + deltaMassPhiKK = hfHelper.deltaMassPhiDsToKKPi(candidate); + absCos3PiKDs = hfHelper.absCos3PiKDsToKKPi(candidate); + } else if constexpr (massHypo == 1) { + invMassDs = hfHelper.invMassDsToPiKK(candidate); + deltaMassPhiKK = hfHelper.deltaMassPhiDsToPiKK(candidate); + absCos3PiKDs = hfHelper.absCos3PiKDsToPiKK(candidate); + } + + int8_t flagMc{0}; + int8_t originMc{0}; + int8_t channelMc{0}; + int8_t isSwapped{massHypo}; // 0 if KKPi, 1 if PiKK + float eCand{0.f}; + float ctCand{0.f}; + float yCand = candidate.y(invMassDs); if constexpr (doMc) { flagMc = candidate.flagMcMatchRec(); originMc = candidate.originMcRec(); channelMc = candidate.flagMcDecayChanRec(); isSwapped = candidate.isCandidateSwapped(); if (fillDplusMc && candidate.flagMcDecayChanRec() == channelsResonant[Mother::Dplus][decayChannel]) { - yCand = hfHelper.yDplus(candidate); eCand = hfHelper.eDplus(candidate); ctCand = hfHelper.ctDplus(candidate); } else { - yCand = hfHelper.yDs(candidate); eCand = hfHelper.eDs(candidate); ctCand = hfHelper.ctDs(candidate); } } - float invMassDs = 0; - float deltaMassPhiKK = 0; - float absCos3PiKDs = 0; - if constexpr (massHypo == 0) { - invMassDs = hfHelper.invMassDsToKKPi(candidate); - deltaMassPhiKK = hfHelper.deltaMassPhiDsToKKPi(candidate); - absCos3PiKDs = hfHelper.absCos3PiKDsToKKPi(candidate); - } else if constexpr (massHypo == 1) { - invMassDs = hfHelper.invMassDsToPiKK(candidate); - deltaMassPhiKK = hfHelper.deltaMassPhiDsToPiKK(candidate); - absCos3PiKDs = hfHelper.absCos3PiKDsToPiKK(candidate); - } - auto const& collision = candidate.template collision_as(); float centrality = o2::hf_centrality::getCentralityColl(collision); @@ -607,7 +619,7 @@ struct HfTreeCreatorDsToKKPi { particle.pt(), particle.eta(), particle.phi(), - RecoDecay::y(particle.pVector(), o2::constants::physics::MassDS), + std::abs(particle.pdgCode()) == o2::constants::physics::Pdg::kDS ? RecoDecay::y(particle.pVector(), o2::constants::physics::MassDS) : RecoDecay::y(particle.pVector(), o2::constants::physics::MassDPlus), particle.flagMcMatchGen(), particle.originMcGen()); } diff --git a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx index 2b838d774b1..18ee43a111b 100644 --- a/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorDstarToD0Pi.cxx @@ -16,13 +16,23 @@ /// /// \author Fabrizio Grosa , CERN -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx b/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx index 38a68453415..a60a7eba661 100644 --- a/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLbToLcPi.cxx @@ -18,13 +18,22 @@ /// \author Panos Christakoglou , Nikhef /// \author Maurice Jongerhuis , University Utrecht -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include +#include +#include +#include +#include + +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx b/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx index 35e15a7cb9f..0012108a45c 100644 --- a/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToK0sP.cxx @@ -17,13 +17,24 @@ /// /// \author Daniel Samitz -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx index 5ad144e472e..90b47824835 100644 --- a/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorLcToPKPi.cxx @@ -17,18 +17,34 @@ /// \author Nicolo' Jacazio , CERN /// \author Luigi Dello Stritto , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.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; @@ -87,6 +103,9 @@ DECLARE_SOA_COLUMN(IsCandidateSwapped, isCandidateSwapped, int8_t); DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfCand3ProngWPidPiKaPr, "_0"); DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); DECLARE_SOA_COLUMN(Channel, channel, int8_t); // direct or resonant +DECLARE_SOA_COLUMN(MlScoreFirstClass, mlScoreFirstClass, float); +DECLARE_SOA_COLUMN(MlScoreSecondClass, mlScoreSecondClass, float); +DECLARE_SOA_COLUMN(MlScoreThirdClass, mlScoreThirdClass, float); // Events DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); DECLARE_SOA_COLUMN(IsEventReject, isEventReject, int); @@ -238,7 +257,10 @@ DECLARE_SOA_TABLE(HfCandLcLites, "AOD", "HFCANDLCLITE", full::OriginMcRec, full::IsCandidateSwapped, full::Channel, - full::MassKPi); + full::MassKPi, + full::MlScoreFirstClass, + full::MlScoreSecondClass, + full::MlScoreThirdClass); DECLARE_SOA_TABLE(HfCollIdLCLite, "AOD", "HFCOLLIDLCLITE", full::CollisionId); @@ -316,7 +338,10 @@ DECLARE_SOA_TABLE(HfCandLcFulls, "AOD", "HFCANDLCFULL", full::IsCandidateSwapped, full::CandidateId, full::Channel, - full::MassKPi); + full::MassKPi, + full::MlScoreFirstClass, + full::MlScoreSecondClass, + full::MlScoreThirdClass); DECLARE_SOA_TABLE(HfCandLcFullEvs, "AOD", "HFCANDLCFULLEV", full::CollisionId, @@ -374,8 +399,10 @@ struct HfTreeCreatorLcToPKPi { Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; Configurable fillCollIdTable{"fillCollIdTable", false, "Fill a single-column table with collision index"}; Configurable fillCandidateMcTable{"fillCandidateMcTable", false, "Switch to fill a table with MC particles matched to candidates"}; + Configurable applyMl{"applyMl", false, "Whether ML was used in candidateSelectorLc"}; Configurable keepOnlySignalMc{"keepOnlySignalMc", false, "Fill MC tree only with signal candidates"}; Configurable keepOnlyBkg{"keepOnlyBkg", false, "Fill MC tree only with background candidates"}; + Configurable keepCorrBkgMC{"keepCorrBkgMC", false, "Flag to keep correlated background sources (Λc+ -> p K− π+ π0, p π− π+, p K− K+ and other charm hadrons)"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of candidates to store in the tree"}; Configurable downSampleBkgPtMax{"downSampleBkgPtMax", 100.f, "Max. pt for background downsampling"}; @@ -553,11 +580,40 @@ struct HfTreeCreatorLcToPKPi { return std::make_pair(invMass, invMassKPi); } + /// \brief function to get ML score values for the current candidate and assign them to input parameters + /// \param candidate candidate instance + /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate + /// \param mlScoreFirstClass ML score for belonging to the first class + /// \param mlScoreSecondClass ML score for belonging to the second class + /// \param mlScoreThirdClass ML score for belonging to the third class + /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used + void assignMlScores(aod::HfMlLcToPKPi::iterator const& candidateMlScore, float& mlScoreFirstClass, float& mlScoreSecondClass, float& mlScoreThirdClass, int candFlag) + { + std::vector mlScores; + if (candFlag == 0) { + std::copy(candidateMlScore.mlProbLcToPKPi().begin(), candidateMlScore.mlProbLcToPKPi().end(), std::back_inserter(mlScores)); + } else { + std::copy(candidateMlScore.mlProbLcToPiKP().begin(), candidateMlScore.mlProbLcToPiKP().end(), std::back_inserter(mlScores)); + } + constexpr int IndexFirstClass{0}; + constexpr int IndexSecondClass{1}; + constexpr int IndexThirdClass{2}; + if (mlScores.size() == 0) { + return; // when candidateSelectorLc rejects a candidate by "usual", non-ML cut, the ml score vector remains empty + } + mlScoreFirstClass = mlScores.at(IndexFirstClass); + mlScoreSecondClass = mlScores.at(IndexSecondClass); + if (mlScores.size() > IndexThirdClass) { + mlScoreThirdClass = mlScores.at(IndexThirdClass); + } + } + /// \brief function to fill lite table /// \param candidate candidate instance + /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used template - void fillLiteTable(CandType const& candidate, int candFlag) + void fillLiteTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); @@ -575,6 +631,14 @@ struct HfTreeCreatorLcToPKPi { functionFlagMcDecayChanRec = candidate.flagMcDecayChanRec(); } + float mlScoreFirstClass{UndefValueFloat}; + float mlScoreSecondClass{UndefValueFloat}; + float mlScoreThirdClass{UndefValueFloat}; + + if (applyMl) { + assignMlScores(candidateMlScore, mlScoreFirstClass, mlScoreSecondClass, mlScoreThirdClass, candFlag); + } + rowCandidateLite( candidate.posX(), candidate.posY(), @@ -618,7 +682,10 @@ struct HfTreeCreatorLcToPKPi { functionOriginMcRec, functionIsCandidateSwapped, functionFlagMcDecayChanRec, - functionInvMassKPi); + functionInvMassKPi, + mlScoreFirstClass, + mlScoreSecondClass, + mlScoreThirdClass); if (fillCollIdTable) { /// save also candidate collision indices @@ -628,9 +695,10 @@ struct HfTreeCreatorLcToPKPi { /// \brief function to fill lite table /// \param candidate candidate instance + /// \param candidateMlScore instance of handler of vectors with ML scores associated with the current candidate /// \param candFlag flag indicating if PKPi (0) or PiKP (1) hypothesis is used template - void fillFullTable(CandType const& candidate, int candFlag) + void fillFullTable(CandType const& candidate, aod::HfMlLcToPKPi::iterator const& candidateMlScore, int candFlag) { auto [functionInvMass, functionInvMassKPi] = evaluateInvariantMasses(candidate, candFlag); const float functionCt = hfHelper.ctLc(candidate); @@ -649,6 +717,14 @@ struct HfTreeCreatorLcToPKPi { functionFlagMcDecayChanRec = candidate.flagMcDecayChanRec(); } + float mlScoreFirstClass{UndefValueFloat}; + float mlScoreSecondClass{UndefValueFloat}; + float mlScoreThirdClass{UndefValueFloat}; + + if (applyMl) { + assignMlScores(candidateMlScore, mlScoreFirstClass, mlScoreSecondClass, mlScoreThirdClass, candFlag); + } + rowCandidateFull( candidate.collisionId(), candidate.posX(), @@ -722,7 +798,10 @@ struct HfTreeCreatorLcToPKPi { functionIsCandidateSwapped, candidate.globalIndex(), functionFlagMcDecayChanRec, - functionInvMassKPi); + functionInvMassKPi, + mlScoreFirstClass, + mlScoreSecondClass, + mlScoreThirdClass); } /// \brief function to fill lite table @@ -839,6 +918,7 @@ struct HfTreeCreatorLcToPKPi { void fillTablesMc(Colls const& collisions, aod::McCollisions const&, CandType const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const&, aod::BCs const&) { @@ -850,7 +930,10 @@ struct HfTreeCreatorLcToPKPi { const size_t candidatesSize = candidates.size(); reserveTables(candidatesSize, IsMc); + int iCand{0}; for (const auto& candidate : candidates) { + auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); + ++iCand; float ptProng0 = candidate.ptProng0(); auto collision = candidate.template collision_as(); auto fillTable = [&](int candFlag) { @@ -859,13 +942,15 @@ struct HfTreeCreatorLcToPKPi { const int sigbgstatus = determineSignalBgStatus(candidate, candFlag); const bool isMcCandidateSignal = (sigbgstatus == Prompt) || (sigbgstatus == NonPrompt); const bool passSelection = functionSelection >= selectionFlagLc; - const bool keepAll = !keepOnlySignalMc && !keepOnlyBkg; + const bool keepAll = !keepOnlySignalMc && !keepOnlyBkg && !keepCorrBkgMC; + const int flag = candidate.flagMcMatchRec(); + const bool isCorrBkg = (std::abs(flag) != 0 && std::abs(flag) != o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi); const bool notSkippedBkg = isMcCandidateSignal || candidate.pt() > downSampleBkgPtMax || pseudoRndm < downSampleBkgFactor; - if (passSelection && notSkippedBkg && (keepAll || (keepOnlySignalMc && isMcCandidateSignal) || (keepOnlyBkg && !isMcCandidateSignal))) { + if (passSelection && notSkippedBkg && (keepAll || (keepOnlySignalMc && isMcCandidateSignal) || (keepOnlyBkg && !isMcCandidateSignal) || (keepCorrBkgMC && isCorrBkg))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -955,10 +1040,11 @@ struct HfTreeCreatorLcToPKPi { void processMcNoCentralityWithDCAFitterN(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcNoCentralityWithDCAFitterN, "Process MC tree writer w/o centrality with DCAFitterN", false); @@ -971,10 +1057,11 @@ struct HfTreeCreatorLcToPKPi { void processMcWithCentralityWithDCAFitterN(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcWithCentralityWithDCAFitterN, "Process MC tree writer with centrality with DCAFitterN", false); @@ -988,10 +1075,11 @@ struct HfTreeCreatorLcToPKPi { void processMcNoCentralityWithKFParticle(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcNoCentralityWithKFParticle, "Process MC tree writer w/o centrality with KFParticle", false); @@ -1004,10 +1092,11 @@ struct HfTreeCreatorLcToPKPi { void processMcWithCentralityWithKFParticle(soa::Join const& collisions, aod::McCollisions const& mcCollisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, soa::Join const& particles, soa::Join const& tracks, aod::BCs const& bcs) { - fillTablesMc(collisions, mcCollisions, candidates, particles, tracks, bcs); + fillTablesMc(collisions, mcCollisions, candidates, candidateMlScores, particles, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processMcWithCentralityWithKFParticle, "Process MC tree writer with centrality with KFParticle", false); @@ -1017,6 +1106,7 @@ struct HfTreeCreatorLcToPKPi { template void fillTablesData(Colls const& collisions, CandType const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const&, aod::BCs const&) { @@ -1029,7 +1119,10 @@ struct HfTreeCreatorLcToPKPi { // Filling candidate properties + int iCand{0}; for (const auto& candidate : candidates) { + auto candidateMlScore = candidateMlScores.rawIteratorAt(iCand); + ++iCand; float ptProng0 = candidate.ptProng0(); auto collision = candidate.template collision_as(); auto fillTable = [&](int candFlag) { @@ -1037,9 +1130,9 @@ struct HfTreeCreatorLcToPKPi { const int functionSelection = candFlag == 0 ? candidate.isSelLcToPKPi() : candidate.isSelLcToPiKP(); if (functionSelection >= selectionFlagLc && (candidate.pt() > downSampleBkgPtMax || (pseudoRndm < downSampleBkgFactor && candidate.pt() < downSampleBkgPtMax))) { if (fillCandidateLiteTable) { - fillLiteTable(candidate, candFlag); + fillLiteTable(candidate, candidateMlScore, candFlag); } else { - fillFullTable(candidate, candFlag); + fillFullTable(candidate, candidateMlScore, candFlag); } if constexpr (reconstructionType == aod::hf_cand::VertexerType::KfParticle) { @@ -1060,9 +1153,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataNoCentralityWithDCAFitterN(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataNoCentralityWithDCAFitterN, "Process data tree writer w/o centrality with DCAFitterN", false); @@ -1073,9 +1167,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataWithCentralityWithDCAFitterN(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataWithCentralityWithDCAFitterN, "Process data tree writer with centrality with DCAFitterN", true); @@ -1086,9 +1181,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataNoCentralityWithKFParticle(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataNoCentralityWithKFParticle, "Process data tree writer w/o centrality with KFParticle", false); @@ -1099,9 +1195,10 @@ struct HfTreeCreatorLcToPKPi { /// \param bcs Bunch-crossing table void processDataWithCentralityWithKFParticle(soa::Join const& collisions, soa::Join const& candidates, + aod::HfMlLcToPKPi const& candidateMlScores, TracksWPid const& tracks, aod::BCs const& bcs) { - fillTablesData(collisions, candidates, tracks, bcs); + fillTablesData(collisions, candidates, candidateMlScores, tracks, bcs); } PROCESS_SWITCH(HfTreeCreatorLcToPKPi, processDataWithCentralityWithKFParticle, "Process data tree writer with centrality with KFParticle", false); }; diff --git a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx index ce441aa45d5..aaa3ee36337 100644 --- a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaKa.cxx @@ -15,13 +15,22 @@ /// /// \author Federica Zanone , Heidelberg University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; @@ -86,7 +95,7 @@ DECLARE_SOA_COLUMN(IsKaonGlbTrkWoDca, isKaonGlbTrkWoDca, bool); DECLARE_SOA_COLUMN(KaonItsNCls, kaonItsNCls, uint8_t); // from creator - MC DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(OriginRec, originRec, int8_t); +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); // from selector DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int); @@ -127,7 +136,7 @@ DECLARE_SOA_TABLE(HfOmegac0ToOmegaKaLites, "AOD", "HFTOOMEKALITE", full::PidTpcInfoStored, full::PidTofInfoStored, full::TpcNSigmaKaFromCharmBaryon, full::TpcNSigmaKaFromCasc, full::TpcNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, full::TofNSigmaKaFromCharmBaryon, full::TofNSigmaKaFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, - full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched); + full::FlagMcMatchRec, full::OriginMcRec, full::CollisionMatched); } // namespace o2::aod @@ -255,7 +264,7 @@ struct HfTreeCreatorOmegac0ToOmegaKa { // Filling candidate properties rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorOmegac0ToOmegaKa, processMcLite, "Process MC", false); diff --git a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx index a1b8a2b3706..4fb9c92235c 100644 --- a/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegac0ToOmegaPi.cxx @@ -18,13 +18,24 @@ /// \author Fabio Catalano , University of Houston /// \author Ruiqi Yin , Fudan University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include using namespace o2; using namespace o2::framework; @@ -90,7 +101,7 @@ DECLARE_SOA_COLUMN(IsPionGlbTrkWoDca, isPionGlbTrkWoDca, bool); DECLARE_SOA_COLUMN(PionItsNCls, pionItsNCls, uint8_t); // from creator - MC DECLARE_SOA_COLUMN(FlagMcMatchRec, flagMcMatchRec, int8_t); // reconstruction level -DECLARE_SOA_COLUMN(OriginRec, originRec, int8_t); +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int8_t); DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); // from selector DECLARE_SOA_COLUMN(PidTpcInfoStored, pidTpcInfoStored, int); @@ -179,7 +190,7 @@ DECLARE_SOA_TABLE(HfOmegac0ToOmegaPiLites, "AOD", "HFTOOMEPILITE", full::PidTpcInfoStored, full::PidTofInfoStored, full::TpcNSigmaPiFromCharmBaryon, full::TpcNSigmaKaFromCasc, full::TpcNSigmaPiFromLambda, full::TpcNSigmaPrFromLambda, full::TofNSigmaPiFromCharmBaryon, full::TofNSigmaKaFromCasc, full::TofNSigmaPiFromLambda, full::TofNSigmaPrFromLambda, - full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched, hf_track_index::HFflag); + full::FlagMcMatchRec, full::OriginMcRec, full::CollisionMatched, hf_track_index::HFflag); DECLARE_SOA_TABLE(HfKfOmegacFulls, "AOD", "HFKFOMEGACFULL", full::NSigmaTPCPiFromOmegac, full::NSigmaTOFPiFromOmegac, full::NSigmaTPCKaFromCasc, full::NSigmaTOFKaFromCasc, @@ -200,7 +211,7 @@ DECLARE_SOA_TABLE(HfKfOmegacFulls, "AOD", "HFKFOMEGACFULL", full::MassV0Ndf, full::MassCascNdf, full::V0Chi2OverNdf, full::CascChi2OverNdf, full::OmegacChi2OverNdf, full::MassV0Chi2OverNdf, full::MassCascChi2OverNdf, full::CascRejectInvmass, - full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched, hf_track_index::HFflag); + full::FlagMcMatchRec, full::OriginMcRec, full::CollisionMatched, hf_track_index::HFflag); DECLARE_SOA_TABLE(HfKfOmegacLites, "AOD", "HFKFOMEGACLITE", full::NSigmaTPCPiFromOmegac, full::NSigmaTOFPiFromOmegac, full::NSigmaTPCKaFromCasc, full::NSigmaTOFKaFromCasc, @@ -214,7 +225,7 @@ DECLARE_SOA_TABLE(HfKfOmegacLites, "AOD", "HFKFOMEGACLITE", full::CosThetaStarPiFromOmegac, full::CtOmegac, full::EtaOmegac, full::V0Chi2OverNdf, full::CascChi2OverNdf, full::OmegacChi2OverNdf, full::CascRejectInvmass, - full::FlagMcMatchRec, full::OriginRec, full::CollisionMatched, hf_track_index::HFflag); + full::FlagMcMatchRec, full::OriginMcRec, full::CollisionMatched, hf_track_index::HFflag); } // namespace o2::aod /// Writes the full information in an output TTree @@ -493,7 +504,7 @@ struct HfTreeCreatorOmegac0ToOmegaPi { // Filling candidate properties rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorOmegac0ToOmegaPi, processMcLite, "Process MC", false); @@ -510,11 +521,11 @@ struct HfTreeCreatorOmegac0ToOmegaPi { rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { if (keepOnlyMcSignal) { - if (candidate.originRec() != 0) { - fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + if (candidate.originMcRec() != 0) { + fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } else { - fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } } @@ -532,11 +543,11 @@ struct HfTreeCreatorOmegac0ToOmegaPi { rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { if (keepOnlyMcSignal) { - if (candidate.originRec() != 0) { - fillKfCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + if (candidate.originMcRec() != 0) { + fillKfCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } else { - fillKfCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillKfCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } } diff --git a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx index 8d2780cd435..1bd4466893e 100644 --- a/PWGHF/TableProducer/treeCreatorOmegacSt.cxx +++ b/PWGHF/TableProducer/treeCreatorOmegacSt.cxx @@ -15,39 +15,56 @@ /// \author Jochen Klein /// \author Tiantian Cheng -#include -#include -#include -#include - -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/Utils/utilsTrkCandHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "CCDB/BasicCCDBManager.h" -#include "CommonConstants/PhysicsConstants.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DCAFitter/DCAFitterN.h" -#include "DetectorsBase/Propagator.h" -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "Common/DataModel/EventSelection.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/Utils/utilsTrkCandHf.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.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; @@ -70,7 +87,7 @@ DECLARE_SOA_COLUMN(DecayLengthCharmedBaryon, decayLengthCharmedBaryon, float); DECLARE_SOA_COLUMN(DecayLengthXYCharmedBaryon, decayLengthXYCharmedBaryon, float); DECLARE_SOA_COLUMN(DecayLengthCasc, decayLengthCasc, float); DECLARE_SOA_COLUMN(DecayLengthXYCasc, decayLengthXYCasc, float); -DECLARE_SOA_COLUMN(OriginGen, originGen, int); +DECLARE_SOA_COLUMN(OriginMcGen, originMcGen, int); DECLARE_SOA_COLUMN(DecayChannel, decayChannel, int); } // namespace hf_st_charmed_baryon_gen @@ -87,7 +104,7 @@ DECLARE_SOA_TABLE(HfStChBarGens, "AOD", "HFSTCHBARGEN", hf_st_charmed_baryon_gen::DecayLengthXYCharmedBaryon, hf_st_charmed_baryon_gen::DecayLengthCasc, hf_st_charmed_baryon_gen::DecayLengthXYCasc, - hf_st_charmed_baryon_gen::OriginGen, + hf_st_charmed_baryon_gen::OriginMcGen, hf_st_charmed_baryon_gen::DecayChannel); // CharmedBaryon -> Casc + Pion/Kaon @@ -147,7 +164,8 @@ DECLARE_SOA_COLUMN(DecayLengthCasc, decayLengthCasc, float); DECLARE_SOA_COLUMN(DecayLengthXYCasc, decayLengthXYCasc, float); DECLARE_SOA_INDEX_COLUMN_FULL(MotherCasc, motherCasc, int, HfStChBarGens, "_Casc"); DECLARE_SOA_INDEX_COLUMN_FULL(MotherPionOrKaon, motherPionOrKaon, int, HfStChBarGens, "_PionOrKaon"); -DECLARE_SOA_COLUMN(OriginRec, originRec, int); +DECLARE_SOA_COLUMN(OriginMcRec, originMcRec, int); +DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); } // namespace hf_st_charmed_baryon DECLARE_SOA_TABLE(HfStChBars, "AOD", "HFSTCHBAR", @@ -203,7 +221,8 @@ DECLARE_SOA_TABLE(HfStChBars, "AOD", "HFSTCHBAR", hf_st_charmed_baryon::DecayLengthXYCasc, hf_st_charmed_baryon::MotherCascId, hf_st_charmed_baryon::MotherPionOrKaonId, - hf_st_charmed_baryon::OriginRec); + hf_st_charmed_baryon::OriginMcRec, + hf_st_charmed_baryon::ToiMask); } // namespace o2::aod struct HfTreeCreatorOmegacSt { @@ -239,6 +258,7 @@ struct HfTreeCreatorOmegacSt { Configurable maxNSigmaPion{"maxNSigmaPion", 5., "Max Nsigma for pion to be paired with Omega"}; Configurable maxNSigmaKaon{"maxNSigmaKaon", 5., "Max Nsigma for kaon to be paired with Omega"}; Configurable bzOnly{"bzOnly", true, "Use B_z instead of full field map"}; + Configurable cfgTriggersOfInterest{"cfgTriggersOfInterest", "fTrackedOmega,fHfCharmBarToXiBach", "Triggers of interest, comma separated for Zorro"}; const int itsNClsMin = 4; const float tpcNclsFindableFraction = 0.8; @@ -369,8 +389,7 @@ struct HfTreeCreatorOmegacSt { } 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!"; + decayChannel = -1; // LOG(warning) << "Decay channel not recognized!"; } if (decayChannel != -1) { int idxDaughter = (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) ? idxPionDaughter : idxKaonDaughter; @@ -430,7 +449,7 @@ struct HfTreeCreatorOmegacSt { if (runNumber == 0) { zorroSummary.setObject(zorro.getZorroSummary()); } - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fTrackedOmega"); + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), cfgTriggersOfInterest.value); zorro.populateHistRegistry(registry, bc.runNumber()); } runNumber = bc.runNumber(); @@ -447,8 +466,15 @@ struct HfTreeCreatorOmegacSt { } df2.setBz(bz); } + uint32_t toiMask = 0; if (skimmedProcessing) { - zorro.isSelected(collision.bc().globalBC()); + bool sel = zorro.isSelected(bc.globalBC()); + if (sel) { + std::vector toivect = zorro.getTriggerOfInterestResults(); + for (size_t i{0}; i < toivect.size(); i++) { + toiMask |= static_cast(toivect[i]) << i; + } + } } const auto primaryVertex = getPrimaryVertex(collision); @@ -662,32 +688,36 @@ struct HfTreeCreatorOmegacSt { // 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); + 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_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); + indexRecCharmBaryon = indexRec; if (indexRec > -1) { - // Lambda → p pi (Lambda match) - indexRec = RecoDecay::getMatchedMCRec(mcParticles->get(), arrayDaughtersV0, +kLambda0, std::array{+kProton, +kPiMinus}, true, &signV0, 1, &nPiToMuV0); - if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaPi) { - if (nPiToMuOmegac0 >= 1 && nKaToPiOmegac0 == 0) { - isMatched = true; - } else if (nPiToMuOmegac0 == 0 && nKaToPiOmegac0 == 0) { - isMatched = true; - } - } else if (decayChannel == o2::aod::hf_cand_casc_lf::DecayType2Prong::OmegaczeroToOmegaK) { - if (nPiToMuOmegac0 == 0 && nKaToPiOmegac0 == 0) { + // 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; } } } } - if (isMatched) { + if (isMatched && indexRecCharmBaryon > -1) { auto particle = mcParticles->get().rawIteratorAt(indexRecCharmBaryon); origin = RecoDecay::getCharmHadronOrigin(mcParticles->get(), particle, false, &idxBhadMothers); } @@ -750,7 +780,8 @@ struct HfTreeCreatorOmegacSt { decayLengthCascXY, trackCascMotherId, trackMotherId, - origin); + origin, + toiMask); } } else { continue; diff --git a/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx b/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx index 84f32851aeb..a59713f4adf 100644 --- a/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx +++ b/PWGHF/TableProducer/treeCreatorTccToD0D0Pi.cxx @@ -14,35 +14,52 @@ /// \author Biao Zhang , Heidelberg University /// \author Fabrizio Grosa , CERN -#include -#include -#include -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/DCA.h" -#include "ReconstructionDataFormats/V0.h" - -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/CollisionAssociationTables.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsBfieldCCDB.h" -#include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/D2H/DataModel/ReducedDataModel.h" #include "PWGHF/Utils/utilsTrkCandHf.h" -#include "PWGHF/D2H/Utils/utilsRedDataFormat.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/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 using namespace o2; using namespace o2::analysis; diff --git a/PWGHF/TableProducer/treeCreatorToXiPi.cxx b/PWGHF/TableProducer/treeCreatorToXiPi.cxx index f19642f5151..01e40cfb2c8 100644 --- a/PWGHF/TableProducer/treeCreatorToXiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorToXiPi.cxx @@ -15,16 +15,26 @@ /// /// \author Federica Zanone , Heidelberg University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/Core/HfHelper.h" #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; @@ -126,7 +136,7 @@ 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(OriginMcRec, originMcRec, int8_t); DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); // from selector DECLARE_SOA_COLUMN(StatusPidLambda, statusPidLambda, bool); @@ -184,7 +194,7 @@ DECLARE_SOA_TABLE(HfToXiPiFulls, "AOD", "HFTOXIPIFULL", 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); + full::FlagMcMatchRec, full::DebugMcRec, full::OriginMcRec, full::CollisionMatched); DECLARE_SOA_TABLE(HfToXiPiLites, "AOD", "HFTOXIPILITE", full::XPv, full::YPv, full::ZPv, full::Centrality, collision::NumContrib, collision::Chi2, @@ -209,7 +219,7 @@ DECLARE_SOA_TABLE(HfToXiPiLites, "AOD", "HFTOXIPILITE", 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); + full::FlagMcMatchRec, full::OriginMcRec, full::CollisionMatched); } // namespace o2::aod @@ -480,7 +490,7 @@ struct HfTreeCreatorToXiPi { // Filling candidate properties rowCandidateFull.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorToXiPi, processMcFullXic0, "Process MC with full information for xic0 w/o centrality", false); @@ -497,7 +507,7 @@ struct HfTreeCreatorToXiPi { // Filling candidate properties rowCandidateFull.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorToXiPi, processMcFullOmegac0, "Process MC with full information for omegac0", false); @@ -582,7 +592,7 @@ struct HfTreeCreatorToXiPi { // Filling candidate properties rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorToXiPi, processMcLiteXic0, "Process MC and produce lite table version for xic0", false); @@ -599,7 +609,7 @@ struct HfTreeCreatorToXiPi { // Filling candidate properties rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorToXiPi, processMcLiteXic0WithFT0C, "Process MC and produce lite table version for Xic0 with FT0C", false); @@ -616,7 +626,7 @@ struct HfTreeCreatorToXiPi { // Filling candidate properties rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorToXiPi, processMcLiteXic0WithFT0M, "Process MC and produce lite table version for Xic0 with FT0M", false); @@ -633,7 +643,7 @@ struct HfTreeCreatorToXiPi { // Filling candidate properties rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorToXiPi, processMcLiteXic0WithNTracksPV, "Process MC and produce lite table version for Xic0 with NTracksPV", false); @@ -650,7 +660,7 @@ struct HfTreeCreatorToXiPi { // Filling candidate properties rowCandidateLite.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originRec(), candidate.collisionMatched()); + fillCandidateLite(candidate, candidate.flagMcMatchRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorToXiPi, processMcLiteOmegac0, "Process MC and produce lite table version for omegac0", false); diff --git a/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx b/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx index 87355a4590b..0e1c06d5965 100644 --- a/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx +++ b/PWGHF/TableProducer/treeCreatorXic0ToXiPiKf.cxx @@ -14,18 +14,28 @@ /// In this file are defined and filled the output tables /// /// \author Ran Tu , Fudan University -/// \author Tao Fang , Central China Normal University -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/Core/HfHelper.h" #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 + +#include + using namespace o2; using namespace o2::framework; @@ -41,11 +51,12 @@ DECLARE_SOA_COLUMN(DcaXYToPvV0Dau0, dcaXYToPvV0Dau0, float); DECLARE_SOA_COLUMN(DcaXYToPvV0Dau1, dcaXYToPvV0Dau1, float); DECLARE_SOA_COLUMN(DcaXYToPvCascDau, dcaXYToPvCascDau, float); DECLARE_SOA_COLUMN(DcaCascDau, dcaCascDau, float); +DECLARE_SOA_COLUMN(DcaV0Dau, dcaV0Dau, float); DECLARE_SOA_COLUMN(DcaCharmBaryonDau, dcaCharmBaryonDau, float); // 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(OriginMcRec, originMcRec, int8_t); DECLARE_SOA_COLUMN(CollisionMatched, collisionMatched, bool); // from selector DECLARE_SOA_COLUMN(TpcNSigmaPiFromCharmBaryon, tpcNSigmaPiFromCharmBaryon, float); @@ -66,7 +77,6 @@ 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); @@ -80,7 +90,6 @@ 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); @@ -104,15 +113,15 @@ 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::DcaCharmBaryonDau, full::KfDcaXYCascToPv, + 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::Xicldl, + 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::CosPaV0ToCasc, full::CosPaV0ToPv, full::CosPaCascToXic, full::CosPaCascToPv, full::InvMassLambda, full::InvMassCascade, full::InvMassCharmBaryon, full::KfRapXic, full::KfptPiFromXic, full::KfptXic, full::CosThetaStarPiFromXic, full::CtXic, full::EtaXic, @@ -120,7 +129,7 @@ DECLARE_SOA_TABLE(HfKfXicFulls, "AOD", "HFKFXICFULL", full::MassV0Ndf, full::MassCascNdf, full::V0Chi2OverNdf, full::CascChi2OverNdf, full::XicChi2OverNdf, full::MassV0Chi2OverNdf, full::MassCascChi2OverNdf, - full::FlagMcMatchRec, full::DebugMcRec, full::OriginRec, full::CollisionMatched); + full::FlagMcMatchRec, full::DebugMcRec, full::OriginMcRec, full::CollisionMatched); } // namespace o2::aod @@ -137,22 +146,31 @@ struct HfTreeCreatorXic0ToXiPiKf { using MyEventTableWithFT0M = soa::Join; using MyEventTableWithNTracksPV = soa::Join; + HistogramRegistry registry{"registry"}; // for QA of selections + void init(InitContext const&) { + registry.add("hPiFromXic0ItsChi2NCls", "hItsChi2NCls;status;entries", {HistType::kTH1D, {{1000, 0.0f, 10.0f}}}); + registry.add("hPiFromCacsItsChi2NCls", "hItsChi2NCls;status;entries", {HistType::kTH1D, {{1000, 0.0f, 10.0f}}}); + registry.add("hV0Dau0ItsChi2NCls", "hItsChi2NCls;status;entries", {HistType::kTH1D, {{1000, 0.0f, 10.0f}}}); + registry.add("hV0Dau1ItsChi2NCls", "hItsChi2NCls;status;entries", {HistType::kTH1D, {{1000, 0.0f, 10.0f}}}); } template void fillKfCandidate(const T& candidate, int8_t flagMc, int8_t debugMc, int8_t originMc, bool collisionMatched) { - if (candidate.resultSelections() && candidate.statusPidCharmBaryon() && candidate.statusInvMassLambda() && candidate.statusInvMassCascade() && candidate.statusInvMassCharmBaryon()) { + if (candidate.resultSelections()) { float centrality = -999.f; if constexpr (useCentrality) { auto const& collision = candidate.template collision_as(); centrality = o2::hf_centrality::getCentralityColl(collision); } - + registry.fill(HIST("hPiFromXic0ItsChi2NCls"), candidate.template bachelorFromCharmBaryon_as().itsChi2NCl()); + registry.fill(HIST("hPiFromCacsItsChi2NCls"), candidate.template bachelor_as().itsChi2NCl()); + registry.fill(HIST("hV0Dau0ItsChi2NCls"), candidate.template posTrack_as().itsChi2NCl()); + registry.fill(HIST("hV0Dau1ItsChi2NCls"), candidate.template negTrack_as().itsChi2NCl()); rowKfCandidate( centrality, candidate.tpcNSigmaPiFromCharmBaryon(), @@ -165,6 +183,7 @@ struct HfTreeCreatorXic0ToXiPiKf { candidate.tofNSigmaPrFromLambda(), candidate.kfDcaXYPiFromXic(), candidate.dcaCascDau(), + candidate.dcaV0Dau(), candidate.dcaCharmBaryonDau(), candidate.kfDcaXYCascToPv(), candidate.dcaXYToPvV0Dau0(), @@ -177,7 +196,6 @@ struct HfTreeCreatorXic0ToXiPiKf { candidate.chi2MassCasc(), candidate.v0ldl(), candidate.cascldl(), - candidate.xicldl(), candidate.chi2TopoV0ToPv(), candidate.chi2TopoCascToPv(), candidate.chi2TopoPiFromXicToPv(), @@ -191,13 +209,12 @@ struct HfTreeCreatorXic0ToXiPiKf { candidate.cosPAV0(), candidate.cosPaCascToXic(), candidate.cosPACasc(), - candidate.cosPACharmBaryon(), candidate.invMassLambda(), candidate.invMassCascade(), candidate.invMassCharmBaryon(), candidate.kfRapXic(), - candidate.kfptPiFromXic(), - candidate.kfptXic(), + RecoDecay::sqrtSumOfSquares(candidate.pxBachFromCharmBaryon(), candidate.pyBachFromCharmBaryon()), + RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()), candidate.cosThetaStarPiFromXic(), candidate.cTauXic(), candidate.etaCharmBaryon(), @@ -263,7 +280,7 @@ struct HfTreeCreatorXic0ToXiPiKf { { rowKfCandidate.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originRec(), candidate.collisionMatched()); + fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorXic0ToXiPiKf, processKfMcXic0, "Process MC with information for xic0", false); @@ -273,7 +290,7 @@ struct HfTreeCreatorXic0ToXiPiKf { { rowKfCandidate.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originRec(), candidate.collisionMatched()); + fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorXic0ToXiPiKf, processKfMCWithFT0C, "Process MC with information for xic0 at FT0C", false); @@ -283,7 +300,7 @@ struct HfTreeCreatorXic0ToXiPiKf { { rowKfCandidate.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originRec(), candidate.collisionMatched()); + fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorXic0ToXiPiKf, processKfMCWithFT0M, "Process MC with information for xic0 at FT0M", false); @@ -293,7 +310,7 @@ struct HfTreeCreatorXic0ToXiPiKf { { rowKfCandidate.reserve(candidates.size()); for (const auto& candidate : candidates) { - fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originRec(), candidate.collisionMatched()); + fillKfCandidate(candidate, candidate.flagMcMatchRec(), candidate.debugMcRec(), candidate.originMcRec(), candidate.collisionMatched()); } } PROCESS_SWITCH(HfTreeCreatorXic0ToXiPiKf, processMCLiteWithNTracksPV, "Process MC with information for xic0 at Ntrack", false); diff --git a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx index b038f28c80e..a7e592d910e 100644 --- a/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToPKPi.cxx @@ -16,14 +16,24 @@ /// \author Himanshu Sharma , INFN Padova /// \author Cristina Terrevoli , INFN Bari -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.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/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx index 5e32ff5c1bf..52a12a02b91 100644 --- a/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXicToXiPiPi.cxx @@ -16,15 +16,24 @@ /// \author Carolina Reetz , Heidelberg University /// \author Jaeyoon Cho , Inha University -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -34,13 +43,13 @@ 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(CandidateSelFlag, candidateSelFlag, int); //! Selection flag of candidate (output of candidateSelector) // vertices -DECLARE_SOA_COLUMN(Chi2Sv, chi2Sv, float); -DECLARE_SOA_COLUMN(Chi2XiVtx, chi2XiVtx, float); -DECLARE_SOA_COLUMN(Chi2LamVtx, chi2LamVtx, float); +DECLARE_SOA_COLUMN(Chi2SV, chi2SV, float); //! Chi2 of candidate vertex +DECLARE_SOA_COLUMN(Chi2GeoXi, chi2GeoXi, float); //! Chi2 of Xi vertex +DECLARE_SOA_COLUMN(Chi2GeoLambda, chi2GeoLambda, float); //! Chi2 of Lambda vertex // properties of XicPlus -DECLARE_SOA_COLUMN(Sign, sign, float); DECLARE_SOA_COLUMN(E, e, float); //! Energy of candidate (GeV) DECLARE_SOA_COLUMN(M, m, float); //! Invariant mass of candidate (GeV/c2) DECLARE_SOA_COLUMN(P, p, float); //! Momentum of candidate (GeV/c) @@ -55,64 +64,25 @@ DECLARE_SOA_COLUMN(DecayLengthNormalised, decayLengthNormalised, float); //! 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(Chi2TopoXicPlusToPVBeforeConstraint, chi2TopoXicPlusToPVBeforeConstraint, float); -DECLARE_SOA_COLUMN(Chi2TopoXicPlusToPV, chi2TopoXicPlusToPV, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlusBeforeConstraint, chi2TopoXiToXicPlusBeforeConstraint, float); -DECLARE_SOA_COLUMN(Chi2TopoXiToXicPlus, chi2TopoXiToXicPlus, float); // properties of daughter tracks -DECLARE_SOA_COLUMN(PtXi, ptXi, float); //! Transverse momentum of Xi (prong0) (GeV/c) -DECLARE_SOA_COLUMN(ImpactParameterXi, impactParameterXi, float); //! Impact parameter of Xi (prong0) -DECLARE_SOA_COLUMN(ImpactParameterNormalisedXi, impactParameterNormalisedXi, float); //! Normalised impact parameter of Xi (prong0) -DECLARE_SOA_COLUMN(PPi0, pPi0, float); +DECLARE_SOA_COLUMN(PtXi, ptXi, float); //! Transverse momentum of Xi (prong0) (GeV/c) +DECLARE_SOA_COLUMN(ImpactParameterXi, impactParameterXi, float); //! Impact parameter of Xi (prong0) +DECLARE_SOA_COLUMN(ImpactParameterNormalisedXi, impactParameterNormalisedXi, float); //! Normalised impact parameter of Xi (prong0) +DECLARE_SOA_COLUMN(PPi0, pPi0, float); //! Momentum of Pi0 (prong1) (GeV/c) DECLARE_SOA_COLUMN(PtPi0, ptPi0, float); //! Transverse momentum of Pi0 (prong1) (GeV/c) DECLARE_SOA_COLUMN(ImpactParameterPi0, impactParameterPi0, float); //! Impact parameter of Pi0 (prong1) DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi0, impactParameterNormalisedPi0, float); //! Normalised impact parameter of Pi0 (prong1) -DECLARE_SOA_COLUMN(PPi1, pPi1, float); +DECLARE_SOA_COLUMN(PPi1, pPi1, float); //! Momentum of Pi1 (prong2) (GeV/c) DECLARE_SOA_COLUMN(PtPi1, ptPi1, float); //! Transverse momentum of Pi1 (prong2) (GeV/c) DECLARE_SOA_COLUMN(ImpactParameterPi1, impactParameterPi1, float); //! Normalised impact parameter of Pi1 (prong2) DECLARE_SOA_COLUMN(ImpactParameterNormalisedPi1, impactParameterNormalisedPi1, float); //! Normalised impact parameter of Pi1 (prong2) DECLARE_SOA_COLUMN(MaxNormalisedDeltaIP, maxNormalisedDeltaIP, float); //! Maximum normalized difference between measured and expected impact parameter of candidate prongs -DECLARE_SOA_COLUMN(CpaXi, cpaXi, float); -DECLARE_SOA_COLUMN(CpaXYXi, cpaXYXi, float); -DECLARE_SOA_COLUMN(CpaLam, cpaLam, float); -DECLARE_SOA_COLUMN(CpaXYLam, cpaXYLam, float); -DECLARE_SOA_COLUMN(CpaLamToXi, cpaLamToXi, float); -DECLARE_SOA_COLUMN(CpaXYLamToXi, cpaXYLamToXi, float); -DECLARE_SOA_COLUMN(DcaXYPi0Pi1, dcaXYPi0Pi1, float); -DECLARE_SOA_COLUMN(DcaXYPi0Xi, dcaXYPi0Xi, float); -DECLARE_SOA_COLUMN(DcaXYPi1Xi, dcaXYPi1Xi, float); -DECLARE_SOA_COLUMN(DcaPi0Pi1, dcaPi0Pi1, float); -DECLARE_SOA_COLUMN(DcaPi0Xi, dcaPi0Xi, float); -DECLARE_SOA_COLUMN(DcaPi1Xi, dcaPi1Xi, float); -DECLARE_SOA_COLUMN(InvMassXi, invMassXi, float); -DECLARE_SOA_COLUMN(InvMassLambda, invMassLambda, float); -DECLARE_SOA_COLUMN(InvMassXiPi0, invMassXiPi0, float); -DECLARE_SOA_COLUMN(InvMassXiPi1, invMassXiPi1, float); -DECLARE_SOA_COLUMN(PBachelorPi, pBachelorPi, float); -DECLARE_SOA_COLUMN(PPiFromLambda, pPiFromLambda, float); -DECLARE_SOA_COLUMN(PPrFromLambda, pPrFromLambda, float); -// residuals and pulls -DECLARE_SOA_COLUMN(PtResidual, ptResidual, float); -DECLARE_SOA_COLUMN(PResidual, pResidual, float); -DECLARE_SOA_COLUMN(XPvResidual, xPvResidual, float); -DECLARE_SOA_COLUMN(YPvResidual, yPvResidual, float); -DECLARE_SOA_COLUMN(ZPvResidual, zPvResidual, float); -DECLARE_SOA_COLUMN(XPvPull, xPvPull, float); -DECLARE_SOA_COLUMN(YPvPull, yPvPull, float); -DECLARE_SOA_COLUMN(ZPvPull, zPvPull, float); -DECLARE_SOA_COLUMN(XSvResidual, xSvResidual, float); -DECLARE_SOA_COLUMN(YSvResidual, ySvResidual, float); -DECLARE_SOA_COLUMN(ZSvResidual, zSvResidual, float); -DECLARE_SOA_COLUMN(XSvPull, xSvPull, float); -DECLARE_SOA_COLUMN(YSvPull, ySvPull, float); -DECLARE_SOA_COLUMN(ZSvPull, zSvPull, float); } // namespace full DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, - hf_cand_xic_to_xi_pi_pi::OriginRec, + full::ParticleFlag, + hf_cand_xic_to_xi_pi_pi::OriginMcRec, full::CandidateSelFlag, - full::Sign, full::Y, full::Eta, full::Phi, @@ -122,11 +92,11 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -134,10 +104,10 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + 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, @@ -147,24 +117,18 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLites, "AOD", "HFXICXI2PILITE", full::MaxNormalisedDeltaIP); DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, - hf_cand_xic_to_xi_pi_pi::OriginRec, + full::ParticleFlag, + hf_cand_xic_to_xi_pi_pi::OriginMcRec, full::CandidateSelFlag, - full::Sign, full::Y, full::Eta, full::Phi, - full::P, full::Pt, full::PtXi, full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -172,10 +136,12 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + 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, + hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, + hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, full::ImpactParameterXi, full::ImpactParameterNormalisedXi, full::ImpactParameterPi0, @@ -183,25 +149,46 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiLiteKfs, "AOD", "HFXICXI2PILITKF", full::ImpactParameterPi1, full::ImpactParameterNormalisedPi1, full::MaxNormalisedDeltaIP, + hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, + hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, + hf_cand_xic_to_xi_pi_pi::DcaXYCascToPV, + hf_cand_xic_to_xi_pi_pi::DcaZCascToPV, + hf_cand_xic_to_xi_pi_pi::DcaBachelorToPV, + hf_cand_xic_to_xi_pi_pi::DcaPosToPV, + hf_cand_xic_to_xi_pi_pi::DcaNegToPV, + // PID information + hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromXicPlus0, + hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromXicPlus1, + hf_cand_xic_to_xi_pi_pi::NSigTpcBachelorPi, + hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromLambda, + hf_cand_xic_to_xi_pi_pi::NSigTpcPrFromLambda, + hf_cand_xic_to_xi_pi_pi::NSigTofPiFromXicPlus0, + hf_cand_xic_to_xi_pi_pi::NSigTofPiFromXicPlus1, + hf_cand_xic_to_xi_pi_pi::NSigTofBachelorPi, + hf_cand_xic_to_xi_pi_pi::NSigTofPiFromLambda, + hf_cand_xic_to_xi_pi_pi::NSigTofPrFromLambda, // KF specific columns - full::Chi2XiVtx, - full::Chi2LamVtx, - full::Chi2TopoXicPlusToPVBeforeConstraint, - full::Chi2TopoXicPlusToPV, - full::Chi2TopoXiToXicPlusBeforeConstraint, - full::Chi2TopoXiToXicPlus, - full::DcaXYPi0Pi1, - full::DcaXYPi0Xi, - full::DcaXYPi1Xi, - full::DcaPi0Pi1, - full::DcaPi0Xi, - full::DcaPi1Xi); + full::Chi2GeoXi, + full::Chi2GeoLambda, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBefConst, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, + hf_cand_xic_to_xi_pi_pi::Chi2PrimXi, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi0, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Pi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Xi, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi1Xi); DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, - hf_cand_xic_to_xi_pi_pi::OriginRec, + full::ParticleFlag, + hf_cand_xic_to_xi_pi_pi::OriginMcRec, full::CandidateSelFlag, - full::Sign, full::Y, full::Eta, full::Phi, @@ -211,11 +198,11 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -223,10 +210,10 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + 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, @@ -235,13 +222,13 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", full::ImpactParameterNormalisedPi1, full::MaxNormalisedDeltaIP, // additional columns only stored in the full candidate table - full::CpaLamToXi, - full::CpaXYLamToXi, + hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, + hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, full::PPi0, full::PPi1, - full::PBachelorPi, - full::PPiFromLambda, - full::PPrFromLambda, + hf_cand_xic_to_xi_pi_pi::PBachelorPi, + hf_cand_xic_to_xi_pi_pi::PPiFromLambda, + hf_cand_xic_to_xi_pi_pi::PPrFromLambda, hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, hf_cand_xic_to_xi_pi_pi::DcaPosToPV, @@ -261,24 +248,18 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFulls, "AOD", "HFXICXI2PIFULL", hf_cand_xic_to_xi_pi_pi::NSigTofPrFromLambda); DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", - hf_cand_xic_to_xi_pi_pi::FlagMcMatchRec, - hf_cand_xic_to_xi_pi_pi::OriginRec, + full::ParticleFlag, + hf_cand_xic_to_xi_pi_pi::OriginMcRec, full::CandidateSelFlag, - full::Sign, full::Y, full::Eta, full::Phi, - full::P, full::Pt, full::PtXi, full::PtPi0, full::PtPi1, full::M, - full::InvMassXi, - full::InvMassLambda, - full::InvMassXiPi0, - full::InvMassXiPi1, - full::Chi2Sv, + full::Chi2SV, full::Ct, full::DecayLength, full::DecayLengthNormalised, @@ -286,10 +267,12 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", full::DecayLengthXYNormalised, full::Cpa, full::CpaXY, - full::CpaXi, - full::CpaXYXi, - full::CpaLam, - full::CpaXYLam, + 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, + hf_cand_xic_to_xi_pi_pi::CpaLambdaToXi, + hf_cand_xic_to_xi_pi_pi::CpaXYLambdaToXi, full::ImpactParameterXi, full::ImpactParameterNormalisedXi, full::ImpactParameterPi0, @@ -297,21 +280,25 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", full::ImpactParameterPi1, full::ImpactParameterNormalisedPi1, full::MaxNormalisedDeltaIP, - // additional columns only stored in the full candidate table - full::CpaLamToXi, - full::CpaXYLamToXi, - full::PPi0, - full::PPi1, - full::PBachelorPi, - full::PPiFromLambda, - full::PPrFromLambda, hf_cand_xic_to_xi_pi_pi::DcaXiDaughters, hf_cand_xic_to_xi_pi_pi::DcaV0Daughters, - hf_cand_xic_to_xi_pi_pi::DcaPosToPV, - hf_cand_xic_to_xi_pi_pi::DcaNegToPV, - hf_cand_xic_to_xi_pi_pi::DcaBachelorToPV, hf_cand_xic_to_xi_pi_pi::DcaXYCascToPV, hf_cand_xic_to_xi_pi_pi::DcaZCascToPV, + hf_cand_xic_to_xi_pi_pi::DcaBachelorToPV, + hf_cand_xic_to_xi_pi_pi::DcaPosToPV, + hf_cand_xic_to_xi_pi_pi::DcaNegToPV, + // additional columns only stored in the full candidate table + hf_cand_xic_to_xi_pi_pi::InvMassXi, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi0, + hf_cand_xic_to_xi_pi_pi::InvMassXiPi1, + hf_cand_xic_to_xi_pi_pi::InvMassLambda, + full::P, + full::PPi0, + full::PPi1, + hf_cand_xic_to_xi_pi_pi::PBachelorPi, + hf_cand_xic_to_xi_pi_pi::PPiFromLambda, + hf_cand_xic_to_xi_pi_pi::PPrFromLambda, + // PID information hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromXicPlus0, hf_cand_xic_to_xi_pi_pi::NSigTpcPiFromXicPlus1, hf_cand_xic_to_xi_pi_pi::NSigTpcBachelorPi, @@ -323,44 +310,31 @@ DECLARE_SOA_TABLE(HfCandXicToXiPiPiFullKfs, "AOD", "HFXICXI2PIFULKF", hf_cand_xic_to_xi_pi_pi::NSigTofPiFromLambda, hf_cand_xic_to_xi_pi_pi::NSigTofPrFromLambda, // KF-specific columns - full::Chi2XiVtx, - full::Chi2LamVtx, - full::Chi2TopoXicPlusToPVBeforeConstraint, - full::Chi2TopoXicPlusToPV, - full::Chi2TopoXiToXicPlusBeforeConstraint, - full::Chi2TopoXiToXicPlus, - full::DcaXYPi0Pi1, - full::DcaXYPi0Xi, - full::DcaXYPi1Xi, - full::DcaPi0Pi1, - full::DcaPi0Xi, - full::DcaPi1Xi); + full::Chi2GeoXi, + full::Chi2GeoLambda, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPVBefConst, + hf_cand_xic_to_xi_pi_pi::Chi2TopoXicPlusToPV, + hf_cand_xic_to_xi_pi_pi::Chi2PrimXi, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi0, + hf_cand_xic_to_xi_pi_pi::Chi2PrimPi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Pi1, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi0Xi, + hf_cand_xic_to_xi_pi_pi::Chi2DevPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaPi0Xi, + hf_cand_xic_to_xi_pi_pi::DcaPi1Xi, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Pi1, + hf_cand_xic_to_xi_pi_pi::DcaXYPi0Xi, + 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::OriginGen, + hf_cand_xic_to_xi_pi_pi::OriginMcGen, hf_cand::PdgBhadMotherPart, full::Pt, full::Eta, full::Phi, full::Y); - -DECLARE_SOA_TABLE(HfCandXicToXiPiPiResiduals, "AOD", "HFXICXI2PIRESID", - hf_cand_xic_to_xi_pi_pi::OriginGen, - full::PResidual, - full::PtResidual, - full::XPvResidual, - full::YPvResidual, - full::ZPvResidual, - full::XPvPull, - full::YPvPull, - full::ZPvPull, - full::XSvResidual, - full::YSvResidual, - full::ZSvResidual, - full::XSvPull, - full::YSvPull, - full::ZSvPull); } // namespace o2::aod /// Writes the full information in an output TTree @@ -370,7 +344,6 @@ struct HfTreeCreatorXicToXiPiPi { Produces rowCandidateFull; Produces rowCandidateFullKf; Produces rowCandidateFullParticles; - Produces rowCandidateResiduals; Configurable selectionFlagXic{"selectionFlagXic", 1, "Selection Flag for Xic"}; Configurable fillCandidateLiteTable{"fillCandidateLiteTable", false, "Switch to fill lite table with candidate properties"}; @@ -380,9 +353,6 @@ struct HfTreeCreatorXicToXiPiPi { Configurable fillOnlyBackground{"fillOnlyBackground", false, "Flag to fill derived tables with background for ML trainings"}; Configurable downSampleBkgFactor{"downSampleBkgFactor", 1., "Fraction of background candidates to keep for ML trainings"}; Configurable ptMaxForDownSample{"ptMaxForDownSample", 10., "Maximum pt for the application of the downsampling factor"}; - // parameters for MC matching in residual process function - Configurable matchDecayedPions{"matchDecayedPions", true, "Match also candidates with daughter pion tracks that decay with kinked topology"}; - Configurable matchInteractionsWithMaterial{"matchInteractionsWithMaterial", true, "Match also candidates with daughter tracks that interact with material"}; using SelectedCandidates = soa::Filtered>; using SelectedCandidatesKf = soa::Filtered>; @@ -405,19 +375,18 @@ struct HfTreeCreatorXicToXiPiPi { template void fillCandidateTable(const T& candidate) { - int8_t flagMc = 0; + int8_t particleFlag = candidate.sign(); int8_t originMc = 0; if constexpr (doMc) { - flagMc = candidate.flagMcMatchRec(); - originMc = candidate.originRec(); + particleFlag = candidate.flagMcMatchRec(); + originMc = candidate.originMcRec(); } if constexpr (!doKf) { if (fillCandidateLiteTable) { rowCandidateLite( - flagMc, + particleFlag, originMc, candidate.isSelXicToXiPiPi(), - candidate.sign(), candidate.y(o2::constants::physics::MassXiCPlus), candidate.eta(), candidate.phi(), @@ -439,10 +408,10 @@ struct HfTreeCreatorXicToXiPiPi { candidate.decayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -452,10 +421,9 @@ struct HfTreeCreatorXicToXiPiPi { candidate.maxNormalisedDeltaIP()); } else { rowCandidateFull( - flagMc, + particleFlag, originMc, candidate.isSelXicToXiPiPi(), - candidate.sign(), candidate.y(o2::constants::physics::MassXiCPlus), candidate.eta(), candidate.phi(), @@ -477,10 +445,10 @@ struct HfTreeCreatorXicToXiPiPi { candidate.decayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -489,8 +457,8 @@ struct HfTreeCreatorXicToXiPiPi { candidate.impactParameterNormalised2(), candidate.maxNormalisedDeltaIP(), // additional columns only stored in the full candidate table - candidate.cosPaLambdaToXi(), - candidate.cosPaXYLambdaToXi(), + candidate.cpaLambdaToXi(), + candidate.cpaXYLambdaToXi(), candidate.pProng1(), candidate.pProng2(), candidate.pBachelorPi(), @@ -517,23 +485,17 @@ struct HfTreeCreatorXicToXiPiPi { } else { if (fillCandidateLiteTable) { rowCandidateLiteKf( - flagMc, + particleFlag, originMc, candidate.isSelXicToXiPiPi(), - candidate.sign(), candidate.y(o2::constants::physics::MassXiCPlus), candidate.eta(), candidate.phi(), - candidate.p(), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), candidate.ptProng2(), candidate.invMassXicPlus(), - candidate.invMassXi(), - candidate.invMassLambda(), - candidate.invMassXiPi0(), - candidate.invMassXiPi1(), candidate.chi2PCA(), candidate.ct(o2::constants::physics::MassXiCPlus), candidate.kfDecayLength(), @@ -542,10 +504,12 @@ struct HfTreeCreatorXicToXiPiPi { candidate.kfDecayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), + candidate.cpaLambdaToXi(), + candidate.cpaXYLambdaToXi(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -553,38 +517,54 @@ struct HfTreeCreatorXicToXiPiPi { candidate.impactParameter2(), candidate.impactParameterNormalised2(), candidate.maxNormalisedDeltaIP(), + candidate.dcaXiDaughters(), + candidate.dcaV0Daughters(), + candidate.dcaXYCascToPV(), + candidate.dcaZCascToPV(), + candidate.dcaBachelorToPV(), + candidate.dcaPosToPV(), + candidate.dcaNegToPV(), + // PID information + candidate.nSigTpcPiFromXicPlus0(), + candidate.nSigTpcPiFromXicPlus1(), + candidate.nSigTpcBachelorPi(), + candidate.nSigTpcPiFromLambda(), + candidate.nSigTpcPrFromLambda(), + candidate.nSigTofPiFromXicPlus0(), + candidate.nSigTofPiFromXicPlus1(), + candidate.nSigTofBachelorPi(), + candidate.nSigTofPiFromLambda(), + candidate.nSigTofPrFromLambda(), // KF-specific columns candidate.kfCascadeChi2(), candidate.kfV0Chi2(), - candidate.chi2TopoXicPlusToPVBeforeConstraint(), + candidate.chi2TopoXicPlusToPVBefConst(), candidate.chi2TopoXicPlusToPV(), - candidate.chi2TopoXiToXicPlusBeforeConstraint(), - candidate.chi2TopoXiToXicPlus(), - candidate.dcaXYPi0Pi1(), - candidate.dcaXYPi0Xi(), - candidate.dcaXYPi1Xi(), + candidate.chi2PrimXi(), + candidate.chi2PrimPi0(), + candidate.chi2PrimPi1(), + candidate.chi2DevPi0Pi1(), + candidate.chi2DevPi0Xi(), + candidate.chi2DevPi1Xi(), candidate.dcaPi0Pi1(), candidate.dcaPi0Xi(), - candidate.dcaPi1Xi()); + candidate.dcaPi1Xi(), + candidate.dcaXYPi0Pi1(), + candidate.dcaXYPi0Xi(), + candidate.dcaXYPi1Xi()); } else { rowCandidateFullKf( - flagMc, + particleFlag, originMc, candidate.isSelXicToXiPiPi(), - candidate.sign(), candidate.y(o2::constants::physics::MassXiCPlus), candidate.eta(), candidate.phi(), - candidate.p(), candidate.pt(), candidate.ptProng0(), candidate.ptProng1(), candidate.ptProng2(), candidate.invMassXicPlus(), - candidate.invMassXi(), - candidate.invMassLambda(), - candidate.invMassXiPi0(), - candidate.invMassXiPi1(), candidate.chi2PCA(), candidate.ct(o2::constants::physics::MassXiCPlus), candidate.kfDecayLength(), @@ -593,10 +573,12 @@ struct HfTreeCreatorXicToXiPiPi { candidate.kfDecayLengthXYNormalised(), candidate.cpa(), candidate.cpaXY(), - candidate.cosPaXi(), - candidate.cosPaXYXi(), - candidate.cosPaLambda(), - candidate.cosPaXYLambda(), + candidate.cpaXi(), + candidate.cpaXYXi(), + candidate.cpaLambda(), + candidate.cpaXYLambda(), + candidate.cpaLambdaToXi(), + candidate.cpaXYLambdaToXi(), candidate.impactParameter0(), candidate.impactParameterNormalised0(), candidate.impactParameter1(), @@ -604,21 +586,25 @@ struct HfTreeCreatorXicToXiPiPi { candidate.impactParameter2(), candidate.impactParameterNormalised2(), candidate.maxNormalisedDeltaIP(), + candidate.dcaXiDaughters(), + candidate.dcaV0Daughters(), + candidate.dcaXYCascToPV(), + candidate.dcaZCascToPV(), + candidate.dcaBachelorToPV(), + candidate.dcaPosToPV(), + candidate.dcaNegToPV(), // additional columns only stored in the full candidate table - candidate.cosPaLambdaToXi(), - candidate.cosPaXYLambdaToXi(), + candidate.invMassXi(), + candidate.invMassXiPi0(), + candidate.invMassXiPi1(), + candidate.invMassLambda(), + candidate.p(), candidate.pProng1(), candidate.pProng2(), candidate.pBachelorPi(), candidate.pPiFromLambda(), candidate.pPrFromLambda(), - candidate.dcaXiDaughters(), - candidate.dcaV0Daughters(), - candidate.dcaPosToPV(), - candidate.dcaNegToPV(), - candidate.dcaBachelorToPV(), - candidate.dcaXYCascToPV(), - candidate.dcaZCascToPV(), + // PID information candidate.nSigTpcPiFromXicPlus0(), candidate.nSigTpcPiFromXicPlus1(), candidate.nSigTpcBachelorPi(), @@ -632,16 +618,20 @@ struct HfTreeCreatorXicToXiPiPi { // KF-specific columns candidate.kfCascadeChi2(), candidate.kfV0Chi2(), - candidate.chi2TopoXicPlusToPVBeforeConstraint(), + candidate.chi2TopoXicPlusToPVBefConst(), candidate.chi2TopoXicPlusToPV(), - candidate.chi2TopoXiToXicPlusBeforeConstraint(), - candidate.chi2TopoXiToXicPlus(), - candidate.dcaXYPi0Pi1(), - candidate.dcaXYPi0Xi(), - candidate.dcaXYPi1Xi(), + candidate.chi2PrimXi(), + candidate.chi2PrimPi0(), + candidate.chi2PrimPi1(), + candidate.chi2DevPi0Pi1(), + candidate.chi2DevPi0Xi(), + candidate.chi2DevPi1Xi(), candidate.dcaPi0Pi1(), candidate.dcaPi0Xi(), - candidate.dcaPi1Xi()); + candidate.dcaPi1Xi(), + candidate.dcaXYPi0Pi1(), + candidate.dcaXYPi0Xi(), + candidate.dcaXYPi1Xi()); } } } @@ -728,7 +718,7 @@ struct HfTreeCreatorXicToXiPiPi { for (const auto& particle : particles) { rowCandidateFullParticles( particle.flagMcMatchGen(), - particle.originGen(), + particle.originMcGen(), particle.pdgBhadMotherPart(), particle.pt(), particle.eta(), @@ -781,7 +771,7 @@ struct HfTreeCreatorXicToXiPiPi { for (const auto& particle : particles) { rowCandidateFullParticles( particle.flagMcMatchGen(), - particle.originGen(), + particle.originMcGen(), particle.pdgBhadMotherPart(), particle.pt(), particle.eta(), @@ -791,102 +781,6 @@ struct HfTreeCreatorXicToXiPiPi { } } PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processMcKf, "Process MC with KF Particle reconstruction", false); - - void processResiduals(SelectedCandidatesMc const&, - aod::TracksWMc const& tracks, - aod::McParticles const& particles, - aod::McCollisions const&) - { - rowCandidateResiduals.reserve(recSig.size()); - - recSig->bindExternalIndices(&tracks); - - std::vector arrDaughIndex; - int indexRecXicPlus; - int origin; - std::array pvResiduals; - std::array svResiduals; - std::array pvPulls; - std::array svPulls; - - for (const auto& candidate : recSig) { - arrDaughIndex.clear(); - indexRecXicPlus = -1; - origin = RecoDecay::OriginType::None; - pvResiduals = {-9999.9}; - svResiduals = {-9999.9}; - pvPulls = {-9999.9}; - svPulls = {-9999.9}; - - auto arrayDaughters = std::array{candidate.pi0_as(), // pi <- Xic - candidate.pi1_as(), // pi <- Xic - candidate.bachelor_as(), // pi <- cascade - candidate.posTrack_as(), // p <- lambda - candidate.negTrack_as()}; // pi <- lambda - - // get XicPlus as MC particle - if (matchDecayedPions && matchInteractionsWithMaterial) { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } else if (matchDecayedPions && !matchInteractionsWithMaterial) { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } else if (!matchDecayedPions && matchInteractionsWithMaterial) { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } else { - indexRecXicPlus = RecoDecay::getMatchedMCRec(particles, arrayDaughters, Pdg::kXiCPlus, std::array{+kPiPlus, +kPiPlus, +kPiMinus, +kProton, +kPiMinus}, true, nullptr, 4); - } - if (indexRecXicPlus == -1) { - continue; - } - auto particleXicPlusGen = particles.rawIteratorAt(indexRecXicPlus); - origin = RecoDecay::getCharmHadronOrigin(particles, particleXicPlusGen, false); - - // get MC collision - auto mcCollision = particleXicPlusGen.mcCollision_as(); - - // get XicPlus daughters as MC particle - RecoDecay::getDaughters(particleXicPlusGen, &arrDaughIndex, std::array{+kXiMinus, +kPiPlus, +kPiPlus}, 2); - auto daugh0XicPlus = particles.rawIteratorAt(arrDaughIndex[0]); - - // calculate residuals and pulls - float pResidual = candidate.p() - particleXicPlusGen.p(); - float ptResidual = candidate.pt() - particleXicPlusGen.pt(); - pvResiduals[0] = candidate.posX() - mcCollision.posX(); - pvResiduals[1] = candidate.posY() - mcCollision.posY(); - pvResiduals[2] = candidate.posZ() - mcCollision.posZ(); - svResiduals[0] = candidate.xSecondaryVertex() - daugh0XicPlus.vx(); - svResiduals[1] = candidate.ySecondaryVertex() - daugh0XicPlus.vy(); - svResiduals[2] = candidate.zSecondaryVertex() - daugh0XicPlus.vz(); - try { - pvPulls[0] = pvResiduals[0] / candidate.xPvErr(); - pvPulls[1] = pvResiduals[1] / candidate.yPvErr(); - pvPulls[2] = pvResiduals[2] / candidate.zPvErr(); - svPulls[0] = svResiduals[0] / candidate.xSvErr(); - svPulls[1] = svResiduals[1] / candidate.ySvErr(); - svPulls[2] = svResiduals[2] / candidate.zSvErr(); - } catch (const std::runtime_error& error) { - LOG(info) << "Run time error found: " << error.what() << ". Set values of vertex pulls to -9999.9."; - } - - // fill table - rowCandidateResiduals( - origin, - pResidual, - ptResidual, - pvResiduals[0], - pvResiduals[1], - pvResiduals[2], - pvPulls[0], - pvPulls[1], - pvPulls[2], - svResiduals[0], - svResiduals[1], - svResiduals[2], - svPulls[0], - svPulls[1], - svPulls[2]); - } // loop over reconstructed signal - } - PROCESS_SWITCH(HfTreeCreatorXicToXiPiPi, processResiduals, "Process Residuals and pulls for both DCAFitter and KFParticle reconstruction", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx b/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx index 2ceeb567de2..56ca3f152c6 100644 --- a/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx +++ b/PWGHF/TableProducer/treeCreatorXiccToPKPiPi.cxx @@ -17,14 +17,24 @@ /// /// \author Jinjoo Seo , Inha University -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" - #include "PWGHF/Core/HfHelper.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseTOF.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::framework; diff --git a/PWGHF/Tasks/taskCharmHadImpactPar.cxx b/PWGHF/Tasks/taskCharmHadImpactPar.cxx index 9671501387f..3000d5bf8c5 100644 --- a/PWGHF/Tasks/taskCharmHadImpactPar.cxx +++ b/PWGHF/Tasks/taskCharmHadImpactPar.cxx @@ -15,20 +15,34 @@ /// \author Fabrizio Grosa , CERN /// \author Antonio Palasciano , INFN Bari -#include -#include - -#include "Common/Core/RecoDecay.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "PWGHF/Core/HfHelper.h" #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/Utils/utilsEvSelHf.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 +#include +#include + using namespace o2; using namespace o2::aod; using namespace o2::analysis; @@ -181,7 +195,7 @@ struct HfTaskCharmHadImpactPar { if (candidate.isSelD0()) { // D0 -> Kpi if constexpr (doMc) { if (fillOnlySignal) { - if (std::abs(candidate.flagMcMatchRec()) != 1 << aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate.flagMcMatchRec()) != o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { return; } } diff --git a/PWGHF/Tasks/taskLcCentrality.cxx b/PWGHF/Tasks/taskLcCentrality.cxx index 274421f8093..d866224d752 100644 --- a/PWGHF/Tasks/taskLcCentrality.cxx +++ b/PWGHF/Tasks/taskLcCentrality.cxx @@ -16,19 +16,28 @@ /// \author Luigi Dello Stritto , University and INFN SALERNO /// \author Vít Kučera , CERN -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/Centrality.h" - +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/Core/HfHelper.h" #include "PWGHF/Core/SelectorCuts.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" #include "PWGHF/DataModel/CandidateSelectionTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + using namespace o2; using namespace o2::analysis; using namespace o2::framework; @@ -40,7 +49,7 @@ void customize(std::vector& workflowOptions) workflowOptions.push_back(optionDoMC); } -#include "Framework/runDataProcessing.h" +#include /// Λc± → p± K∓ π± analysis task struct HfTaskLcCentrality { diff --git a/PWGHF/Tasks/taskMcEfficiency.cxx b/PWGHF/Tasks/taskMcEfficiency.cxx index 410c3d67a8e..6d58957c664 100644 --- a/PWGHF/Tasks/taskMcEfficiency.cxx +++ b/PWGHF/Tasks/taskMcEfficiency.cxx @@ -14,25 +14,42 @@ /// /// \author Jan Fiete Grosse-Oetringhaus, CERN +#include "PWGHF/Core/HfHelper.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.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 "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - using namespace o2; using namespace o2::analysis; using namespace o2::constants::physics; @@ -299,7 +316,7 @@ struct HfTaskMcEfficiency { duplicates[hash]++; } /// end loop on pdg codes - } /// end loop over candidates + } /// end loop over candidates auto hDuplicateCount = registry.get(HIST("hDuplicateCount")); for (const auto& i : duplicates) { @@ -686,7 +703,7 @@ struct HfTaskMcEfficiency { } /// end "if(selected[...])" } /// end loop over MC particles - } /// end loop over PDG codes + } /// end loop over PDG codes } /// end candidate3ProngMcLoop diff --git a/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx b/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx index 01cac4a9028..0550bd5e726 100644 --- a/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx +++ b/PWGHF/Tasks/taskMcEfficiencyToXiPi.cxx @@ -14,24 +14,31 @@ /// /// \author Federica Zanone, Heidelberg University -#include - -#include "TMCProcess.h" // for VMC Particle Production Process - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGHF/Core/SelectorCuts.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // for VMC Particle Production Process +#include + +#include using namespace o2; -using namespace o2::analysis; using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; @@ -47,9 +54,6 @@ struct HfTaskMcEfficiencyToXiPi { Configurable nClustersTpcMin{"nClustersTpcMin", 70, "Minimum number of TPC clusters requirement for pion <-- charm baryon"}; Configurable nClustersItsMin{"nClustersItsMin", 3, "Minimum number of ITS clusters requirement for pion <- charm baryon"}; - ConfigurableAxis axisPt{"axisPt", {200, 0, 20}, "pT axis"}; - ConfigurableAxis axisMass{"axisMass", {900, 2.1, 3}, "m_inv axis"}; - enum HFStep { kHFStepMC = 0, // all generated mothers kHFStepMcInRapidity, // MC mother in rapidity |y| < rapidityCharmBaryonMax=0.5 kHFStepAcceptance, // MC mother where all final state candidates pass eta and pt selection @@ -75,6 +79,9 @@ struct HfTaskMcEfficiencyToXiPi { using ParticleInfoOmegac0 = soa::Join; using BCsInfo = soa::Join; + ConfigurableAxis axisPt{"axisPt", {200, 0, 20}, "pT axis"}; + ConfigurableAxis axisMass{"axisMass", {900, 2.1, 3}, "m_inv axis"}; + HistogramRegistry registry{"registry"}; void init(InitContext&) @@ -142,11 +149,11 @@ struct HfTaskMcEfficiencyToXiPi { pt = RecoDecay::sqrtSumOfSquares(candidate.pxCharmBaryon(), candidate.pyCharmBaryon()); // all candidates (candidateCreator) - hCandidates->Fill(kHFStepTracked, pt, mass, candidate.collisionMatched(), candidate.originRec()); + hCandidates->Fill(kHFStepTracked, pt, mass, candidate.collisionMatched(), candidate.originMcRec()); // check xi-pi candidate passed candidate selector cuts (except PID) if (candidate.resultSelections() && candidate.statusInvMassLambda() && candidate.statusInvMassCascade() && candidate.statusInvMassCharmBaryon()) { - hCandidates->Fill(kHFStepTrackedCuts, pt, mass, candidate.collisionMatched(), candidate.originRec()); + hCandidates->Fill(kHFStepTrackedCuts, pt, mass, candidate.collisionMatched(), candidate.originMcRec()); selectedKine = true; } if (!selectedKine) { @@ -155,7 +162,7 @@ struct HfTaskMcEfficiencyToXiPi { // check xi-pi candidate passed candidate selector cuts (PID included) if (candidate.statusPidCharmBaryon()) { - hCandidates->Fill(kHFStepTrackedSelected, pt, mass, candidate.collisionMatched(), candidate.originRec()); + hCandidates->Fill(kHFStepTrackedSelected, pt, mass, candidate.collisionMatched(), candidate.originMcRec()); selectedPid = true; } if (!selectedPid) { @@ -224,17 +231,17 @@ struct HfTaskMcEfficiencyToXiPi { } // all candidates - hCandidates->Fill(kHFStepMC, mcParticle.pt(), mass, true, mcParticle.originGen()); // set matchedCollision to true by default at gen level + hCandidates->Fill(kHFStepMC, mcParticle.pt(), mass, true, mcParticle.originMcGen()); // set matchedCollision to true by default at gen level // candidates with charm baryon within eta range if (std::abs(mcParticle.y()) < rapidityCharmBaryonMax) { - hCandidates->Fill(kHFStepMcInRapidity, mcParticle.pt(), mass, true, mcParticle.originGen()); + hCandidates->Fill(kHFStepMcInRapidity, mcParticle.pt(), mass, true, mcParticle.originMcGen()); } // exclude cases with undesired decays int cascId = -999; int pionId = -999; - for (auto& dauCharm : mcParticle.template daughters_as()) { + for (auto const& dauCharm : mcParticle.template daughters_as()) { if (std::abs(dauCharm.pdgCode()) == kXiMinus && (dauCharm.getProcess() == TMCProcess::kPDecay || dauCharm.getProcess() == TMCProcess::kPPrimary)) { cascId = dauCharm.globalIndex(); } else if (std::abs(dauCharm.pdgCode()) == kPiPlus && (dauCharm.getProcess() == TMCProcess::kPDecay || dauCharm.getProcess() == TMCProcess::kPPrimary)) { @@ -257,7 +264,7 @@ struct HfTaskMcEfficiencyToXiPi { // first create cascade daughters objects int lambdaId = -999; int pionFromCascadeId = -999; - for (auto& dauCasc : cascade.template daughters_as()) { + for (auto const& dauCasc : cascade.template daughters_as()) { if (std::abs(dauCasc.pdgCode()) == kLambda0 && dauCasc.getProcess() == TMCProcess::kPDecay) { lambdaId = dauCasc.globalIndex(); } else if (std::abs(dauCasc.pdgCode()) == kPiPlus && dauCasc.getProcess() == TMCProcess::kPDecay) { @@ -273,7 +280,7 @@ struct HfTaskMcEfficiencyToXiPi { // then create lambda daughters objects int protonId = -999; int pionFromLambdaId = -999; - for (auto& dauV0 : lambda.template daughters_as()) { + for (auto const& dauV0 : lambda.template daughters_as()) { if (std::abs(dauV0.pdgCode()) == kProton && dauV0.getProcess() == TMCProcess::kPDecay) { protonId = dauV0.globalIndex(); } else if (std::abs(dauV0.pdgCode()) == kPiPlus && dauV0.getProcess() == TMCProcess::kPDecay) { @@ -295,14 +302,14 @@ struct HfTaskMcEfficiencyToXiPi { } // final state candidates pass eta and pt selection if (inAcceptance) { - hCandidates->Fill(kHFStepAcceptance, mcParticle.pt(), mass, true, mcParticle.originGen()); + hCandidates->Fill(kHFStepAcceptance, mcParticle.pt(), mass, true, mcParticle.originMcGen()); } if (tracked[pionId] && tracked[pionFromCascadeId] && tracked[pionFromLambdaId] && tracked[protonId]) { // final state candidates have a mc particleID != 0 - hCandidates->Fill(kHFStepTrackable, mcParticle.pt(), mass, true, mcParticle.originGen()); + hCandidates->Fill(kHFStepTrackable, mcParticle.pt(), mass, true, mcParticle.originMcGen()); if (inAcceptance) { - hCandidates->Fill(kHFStepAcceptanceTrackable, mcParticle.pt(), mass, true, mcParticle.originGen()); + hCandidates->Fill(kHFStepAcceptanceTrackable, mcParticle.pt(), mass, true, mcParticle.originMcGen()); } else { LOGP(debug, "Candidate {} not in acceptance but tracked.", mcParticle.globalIndex()); LOGP(debug, "MC cascade: pt={} eta={}", cascade.pt(), cascade.eta()); @@ -358,13 +365,13 @@ struct HfTaskMcEfficiencyToXiPi { // with pion track cuts (see checkTrackGlbTrk and checkTrkItsTrk) if (selectedIts[pionId]) { - hCandidates->Fill(kHFStepItsTrackableCuts, mcParticle.pt(), mass, true, mcParticle.originGen()); + hCandidates->Fill(kHFStepItsTrackableCuts, mcParticle.pt(), mass, true, mcParticle.originMcGen()); if (!inAcceptance) { LOGP(debug, "Candidate {} has daughters not in acceptance but pion <-- charm tracked and selected (its only)", mcParticle.globalIndex()); } } if (selectedItsTpc[pionId]) { - hCandidates->Fill(kHFStepItsTpcTrackableCuts, mcParticle.pt(), mass, true, mcParticle.originGen()); + hCandidates->Fill(kHFStepItsTpcTrackableCuts, mcParticle.pt(), mass, true, mcParticle.originMcGen()); if (!inAcceptance) { LOGP(debug, "Candidate {} has daughters not in acceptance but pion <-- charm tracked and selected (its & tpc)", mcParticle.globalIndex()); } diff --git a/PWGHF/Tasks/taskMcGenPtRapShapes.cxx b/PWGHF/Tasks/taskMcGenPtRapShapes.cxx index e3e9deda1a9..01c795d0461 100644 --- a/PWGHF/Tasks/taskMcGenPtRapShapes.cxx +++ b/PWGHF/Tasks/taskMcGenPtRapShapes.cxx @@ -14,16 +14,26 @@ /// \author Fabrizio Grosa , CERN -#include -#include +#include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" +#include +#include + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGHF/Tasks/taskMcValidation.cxx b/PWGHF/Tasks/taskMcValidation.cxx index 269cd7b21ea..97b57f150bc 100644 --- a/PWGHF/Tasks/taskMcValidation.cxx +++ b/PWGHF/Tasks/taskMcValidation.cxx @@ -18,30 +18,56 @@ /// \author Fabrizio Grosa , CERN /// \author Fabio Catalano , CERN -#include -#include -#include - -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Common/DataModel/CollisionAssociationTables.h" - -#include "PWGLF/DataModel/mcCentrality.h" - #include "PWGHF/Core/CentralityEstimation.h" -#include "PWGHF/Core/SelectorCuts.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/mcCentrality.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/CollisionAssociationTables.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 +#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; @@ -261,7 +287,7 @@ struct HfTaskMcValidationGen { if (storeOccupancy) { occupancy = getOccupancyGenColl(recoCollisions, OccupancyEstimator::Its); } - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0u}; if constexpr (centEstimator == CentralityEstimator::FT0C) { rejectionMask = hfEvSelMc.getHfMcCollisionRejectionMask(mcCollision, recoCollisions, centrality); } else if constexpr (centEstimator == CentralityEstimator::FT0M) { @@ -1072,7 +1098,7 @@ struct HfTaskMcValidationRec { continue; } int whichHad = -1; - if (isD0Sel && TESTBIT(std::abs(cand2Prong.flagMcMatchRec()), hf_cand_2prong::DecayType::D0ToPiK)) { + if (isD0Sel && std::abs(cand2Prong.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { whichHad = DzeroToKPi; } int whichOrigin; diff --git a/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx b/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx index a7e0515eb2f..3e8537a47d1 100644 --- a/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx +++ b/PWGHF/Tasks/taskMultiplicityEstimatorCorrelation.cxx @@ -14,16 +14,28 @@ /// /// \author Fabrizio Chinu , Università and INFN Torino +#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 - -#include "TPDGCode.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/StaticFor.h" -#include "Common/DataModel/Multiplicity.h" using namespace o2; using namespace o2::framework; diff --git a/PWGHF/Tasks/taskPidStudies.cxx b/PWGHF/Tasks/taskPidStudies.cxx index ad3943a7134..805266b76a9 100644 --- a/PWGHF/Tasks/taskPidStudies.cxx +++ b/PWGHF/Tasks/taskPidStudies.cxx @@ -17,26 +17,35 @@ /// \author Marcello Di Costanzo , Politecnico and INFN Torino /// \author Luca Aglietta , Università and INFN Torino -#include -#include - -#include "TPDGCode.h" - -#include "CCDB/BasicCCDBManager.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Utils/utilsEvSelHf.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/CCDB/ctpRateFetcher.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "PWGHF/Utils/utilsEvSelHf.h" -#include "PWGHF/Core/CentralityEstimation.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.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/PWGHF/Tasks/taskSelOptimisation.cxx b/PWGHF/Tasks/taskSelOptimisation.cxx index 8b701ea5a4c..c91f5d55819 100644 --- a/PWGHF/Tasks/taskSelOptimisation.cxx +++ b/PWGHF/Tasks/taskSelOptimisation.cxx @@ -14,15 +14,30 @@ /// /// \author Fabrizio Grosa , CERN -#include -#include +#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include "Common/Core/RecoDecay.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.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; @@ -272,7 +287,7 @@ struct HfSelOptimisation { bool isPrompt = false, isNonPrompt = false, isBkg = false; for (int iDecay{0}; iDecay < n2Prong; ++iDecay) { if (TESTBIT(cand2Prong.hfflag(), iDecay)) { - if (std::abs(cand2Prong.flagMcMatchRec()) == BIT(iDecay)) { + if (std::abs(cand2Prong.flagMcMatchRec()) == BIT(iDecay)) { // FIXME: Migrate to DecayChannelMain if (cand2Prong.originMcRec() == RecoDecay::OriginType::Prompt) { isPrompt = true; switch (iDecay) { @@ -328,7 +343,7 @@ struct HfSelOptimisation { bool isPrompt = false, isNonPrompt = false, isBkg = false; for (int iDecay{0}; iDecay < n3Prong; ++iDecay) { if (TESTBIT(cand3Prong.hfflag(), iDecay)) { - if (std::abs(cand3Prong.flagMcMatchRec()) == BIT(iDecay)) { + if (std::abs(cand3Prong.flagMcMatchRec()) == BIT(iDecay)) { // FIXME: Migrate to DecayChannelMain if (cand3Prong.originMcRec() == RecoDecay::OriginType::Prompt) { isPrompt = true; switch (iDecay) { diff --git a/PWGHF/Utils/utilsBfieldCCDB.h b/PWGHF/Utils/utilsBfieldCCDB.h index 583e25fd01c..8d7166eca4a 100644 --- a/PWGHF/Utils/utilsBfieldCCDB.h +++ b/PWGHF/Utils/utilsBfieldCCDB.h @@ -16,14 +16,13 @@ #ifndef PWGHF_UTILS_UTILSBFIELDCCDB_H_ #define PWGHF_UTILS_UTILSBFIELDCCDB_H_ -#include - #include #include #include #include #include #include +#include #include // std::string diff --git a/PWGHF/Utils/utilsDerivedData.h b/PWGHF/Utils/utilsDerivedData.h index 23c08d3ac3c..044abed2f90 100644 --- a/PWGHF/Utils/utilsDerivedData.h +++ b/PWGHF/Utils/utilsDerivedData.h @@ -16,18 +16,17 @@ #ifndef PWGHF_UTILS_UTILSDERIVEDDATA_H_ #define PWGHF_UTILS_UTILSDERIVEDDATA_H_ -#include +#include "Common/Core/RecoDecay.h" -#include #include +#include #include +#include #include #include #include -#include "Common/Core/RecoDecay.h" - // Macro to store nSigma for prong _id_ with PID hypothesis _hyp_ in an array #define GET_N_SIGMA_PRONG(_array_, _candidate_, _id_, _hyp_) \ _array_[0] = _candidate_.nSigTpc##_hyp_##_id_(); \ diff --git a/PWGHF/Utils/utilsEvSelHf.h b/PWGHF/Utils/utilsEvSelHf.h index 5d57ffb5eff..5103d5c4d77 100644 --- a/PWGHF/Utils/utilsEvSelHf.h +++ b/PWGHF/Utils/utilsEvSelHf.h @@ -18,30 +18,33 @@ #ifndef PWGHF_UTILS_UTILSEVSELHF_H_ #define PWGHF_UTILS_UTILSEVSELHF_H_ -#include +#include "PWGHF/Core/CentralityEstimation.h" +// +#include "PWGUD/Core/SGCutParHolder.h" +#include "PWGUD/Core/SGSelector.h" -#include -#include -#include +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/RCTSelectionFlags.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" #include #include #include #include #include +#include + +#include +#include + +#include -#include #include +#include #include // std::shared_ptr #include // std::string -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/RCTSelectionFlags.h" -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" - -#include "PWGHF/Core/CentralityEstimation.h" - namespace o2::hf_occupancy { // centrality selection estimators @@ -103,15 +106,17 @@ enum EventRejection { NoSameBunchPileup, Occupancy, NContrib, - Chi2, - PositionZ, NoCollInTimeRangeNarrow, NoCollInTimeRangeStandard, NoCollInRofStandard, + UpcEventCut, + Chi2, + PositionZ, NEventRejection }; o2::framework::AxisSpec axisEvents = {EventRejection::NEventRejection, -0.5f, +EventRejection::NEventRejection - 0.5f, ""}; +o2::framework::AxisSpec axisUpcEvents = {o2::aod::sgselector::DoubleGap + 1, -0.5f, +o2::aod::sgselector::DoubleGap + 0.5f, ""}; /// \brief Function to put labels on monitoring histogram /// \param hRejection monitoring histogram @@ -128,6 +133,7 @@ void setEventRejectionLabels(Histo& hRejection, std::string softwareTriggerLabel hRejection->GetXaxis()->SetBinLabel(EventRejection::TvxTrigger + 1, "TVX Trigger"); hRejection->GetXaxis()->SetBinLabel(EventRejection::TimeFrameBorderCut + 1, "TF border"); hRejection->GetXaxis()->SetBinLabel(EventRejection::ItsRofBorderCut + 1, "ITS ROF border"); + hRejection->GetXaxis()->SetBinLabel(EventRejection::UpcEventCut + 1, "UPC event"); hRejection->GetXaxis()->SetBinLabel(EventRejection::IsGoodZvtxFT0vsPV + 1, "PV #it{z} consistency FT0 timing"); hRejection->GetXaxis()->SetBinLabel(EventRejection::NoSameBunchPileup + 1, "No same-bunch pile-up"); // POTENTIALLY BAD FOR BEAUTY ANALYSES hRejection->GetXaxis()->SetBinLabel(EventRejection::Occupancy + 1, "Occupancy"); @@ -166,12 +172,15 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { o2::framework::Configurable bcMarginForSoftwareTrigger{"bcMarginForSoftwareTrigger", 100, "Number of BCs of margin for software triggers"}; o2::framework::Configurable ccdbPathSoftwareTrigger{"ccdbPathSoftwareTrigger", "Users/m/mpuccio/EventFiltering/OTS/Chunked/", "ccdb path for ZORRO objects"}; o2::framework::ConfigurableAxis th2ConfigAxisCent{"th2ConfigAxisCent", {100, 0., 100.}, ""}; - o2::framework::ConfigurableAxis th2ConfigAxisOccupancy{"th2ConfigAxisOccupancy", {14, 0, 14000}, ""}; + o2::framework::ConfigurableAxis th2ConfigAxisOccupancy{"th2ConfigAxisOccupancy", {100, 0, 100000}, ""}; o2::framework::Configurable requireGoodRct{"requireGoodRct", false, "Flag to require good RCT"}; o2::framework::Configurable rctLabel{"rctLabel", "CBT_hadronPID", "RCT selection flag (CBT, CBT_hadronPID, CBT_electronPID, CCBT_calo, CBT_muon, CBT_muon_glo)"}; o2::framework::Configurable rctCheckZDC{"rctCheckZDC", false, "RCT flag to check whether the ZDC is present or not"}; o2::framework::Configurable rctTreatLimitedAcceptanceAsBad{"rctTreatLimitedAcceptanceAsBad", false, "RCT flag to reject events with limited acceptance for selected detectors"}; + // SG selector + SGSelector sgSelector; + // histogram names static constexpr char NameHistCollisions[] = "hCollisions"; static constexpr char NameHistSelCollisionsCent[] = "hSelCollisionsCent"; @@ -181,8 +190,9 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { static constexpr char NameHistPosYAfterEvSel[] = "hPosYAfterEvSel"; static constexpr char NameHistNumPvContributorsAfterSel[] = "hNumPvContributorsAfterSel"; static constexpr char NameHistCollisionsCentOcc[] = "hCollisionsCentOcc"; + static constexpr char NameHistUpCollisions[] = "hUpCollisions"; - std::shared_ptr hCollisions, hSelCollisionsCent, hPosZBeforeEvSel, hPosZAfterEvSel, hPosXAfterEvSel, hPosYAfterEvSel, hNumPvContributorsAfterSel; + std::shared_ptr hCollisions, hSelCollisionsCent, hPosZBeforeEvSel, hPosZAfterEvSel, hPosXAfterEvSel, hPosYAfterEvSel, hNumPvContributorsAfterSel, hUpCollisions; std::shared_ptr hCollisionsCentOcc; // util to retrieve the RCT info from CCDB @@ -193,6 +203,21 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { o2::framework::OutputObj zorroSummary{"zorroSummary"}; int currentRun{-1}; + /// Set standard preselection gap trigger (values taken from UD group) + SGCutParHolder setSgPreselection() + { + SGCutParHolder sgCuts; + sgCuts.SetNDtcoll(1); // Minimum number of sigma around the collision + sgCuts.SetMinNBCs(2); // Minimum number of bunch crossings + sgCuts.SetNTracks(2, 1000); // Minimum and maximum number of PV contributors + sgCuts.SetMaxFITtime(34.f); // Maximum FIT time in ns + + // Set FIT amplitudes: FV0, FT0A, FT0C, FDDA, FDDC + sgCuts.SetFITAmpLimits({-1.f, 150.f, 50.f, -1.f, -1.f}); + + return sgCuts; + } + /// \brief Adds collision monitoring histograms in the histogram registry. /// \param registry reference to the histogram registry void addHistograms(o2::framework::HistogramRegistry& registry) @@ -203,9 +228,9 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { hPosZAfterEvSel = registry.add(NameHistPosZAfterEvSel, "selected events;#it{z}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{400, -20., 20.}}}); hPosXAfterEvSel = registry.add(NameHistPosXAfterEvSel, "selected events;#it{x}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{200, -0.5, 0.5}}}); hPosYAfterEvSel = registry.add(NameHistPosYAfterEvSel, "selected events;#it{y}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{200, -0.5, 0.5}}}); - hNumPvContributorsAfterSel = registry.add(NameHistNumPvContributorsAfterSel, "selected events;#it{y}_{prim. vtx.} (cm);entries", {o2::framework::HistType::kTH1D, {{500, -0.5, 499.5}}}); + hNumPvContributorsAfterSel = registry.add(NameHistNumPvContributorsAfterSel, "selected events;number of prim. vtx. contributors;entries", {o2::framework::HistType::kTH1D, {{500, -0.5, 499.5}}}); setEventRejectionLabels(hCollisions, softwareTrigger); - + hUpCollisions = registry.add(NameHistUpCollisions, "HF UPC counter;;# of UPC events", {o2::framework::HistType::kTH1D, {axisUpcEvents}}); const o2::framework::AxisSpec th2AxisCent{th2ConfigAxisCent, "Centrality"}; const o2::framework::AxisSpec th2AxisOccupancy{th2ConfigAxisOccupancy, "Occupancy"}; hCollisionsCentOcc = registry.add(NameHistCollisionsCentOcc, "selected events;Centrality; Occupancy", {o2::framework::HistType::kTH2D, {th2AxisCent, th2AxisOccupancy}}); @@ -237,10 +262,10 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { /// \param ccdb ccdb service needed to retrieve the needed info for zorro /// \param registry reference to the histogram registry needed for zorro /// \return bitmask with the event selection criteria not satisfied by the collision - template - uint16_t getHfCollisionRejectionMask(const Coll& collision, float& centrality, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry) + template + uint32_t getHfCollisionRejectionMask(const Coll& collision, float& centrality, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry) { - uint16_t rejectionMask{0}; // 16 bits, in case new ev. selections will be added + uint32_t rejectionMask{0}; // 32 bits, in case new ev. selections will be added if constexpr (centEstimator != o2::hf_centrality::CentralityEstimator::None) { centrality = o2::hf_centrality::getCentralityColl(collision, centEstimator); @@ -316,7 +341,7 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { if (softwareTrigger.value != "") { // we might have to update it from CCDB - auto bc = collision.template bc_as(); + auto bc = collision.template bc_as(); int runNumber = bc.runNumber(); if (runNumber != currentRun) { // We might need to update Zorro from CCDB if the run number changes @@ -341,11 +366,32 @@ struct HfEventSelection : o2::framework::ConfigurableGroup { return rejectionMask; } + template + uint32_t getHfCollisionRejectionMaskWithUpc(const Coll& collision, float& centrality, o2::framework::Service const& ccdb, o2::framework::HistogramRegistry& registry, const BCsType& bcs) + { + auto rejectionMaskWithUpc = getHfCollisionRejectionMask(collision, centrality, ccdb, registry); + + if (useEvSel) { + SGCutParHolder sgCuts = setSgPreselection(); + auto bc = collision.template foundBC_as(); + auto bcRange = udhelpers::compatibleBCs(collision, sgCuts.NDtcoll(), bcs, sgCuts.minNBCs()); + auto sgSelectionResult = sgSelector.IsSelected(sgCuts, collision, bcRange, bc); + int upcEventType = sgSelectionResult.value; + if (upcEventType > o2::aod::sgselector::DoubleGap) { + SETBIT(rejectionMaskWithUpc, EventRejection::UpcEventCut); + } else { + hUpCollisions->Fill(upcEventType); + } + } + + return rejectionMaskWithUpc; + } + /// \brief Fills histograms for monitoring event selections satisfied by the collision. /// \param collision analysed collision /// \param rejectionMask bitmask storing the info about which ev. selections are not satisfied by the collision template - void fillHistograms(Coll const& collision, const uint16_t rejectionMask, float& centrality, float occupancy = -1) + void fillHistograms(Coll const& collision, const uint32_t rejectionMask, float& centrality, float occupancy = -1) { hCollisions->Fill(EventRejection::None); const float posZ = collision.posZ(); @@ -392,8 +438,8 @@ struct HfEventSelectionMc { std::shared_ptr hRecCollisionsCentMc; static constexpr char NameHistNSplitVertices[] = "hNSplitVertices"; std::shared_ptr hNSplitVertices; - static constexpr char NameHistParticles[] = "hParticles"; - std::shared_ptr hParticles; + static constexpr char NameHistGenCollisions[] = "hGenCollisions"; + std::shared_ptr hGenCollisions; /// \brief Adds collision monitoring histograms in the histogram registry. /// \param registry reference to the histogram registry @@ -402,9 +448,9 @@ struct HfEventSelectionMc { hGenCollisionsCent = registry.add(NameHistGenCollisionsCent, "HF event counter;T0M;# of generated collisions", {o2::framework::HistType::kTH1D, {{100, 0., 100.}}}); hRecCollisionsCentMc = registry.add(NameHistRecCollisionsCentMc, "HF event counter;T0M;# of reconstructed collisions", {o2::framework::HistType::kTH1D, {{100, 0., 100.}}}); hNSplitVertices = registry.add(NameHistNSplitVertices, "HF split vertices counter;;# of reconstructed collisions per mc collision", {o2::framework::HistType::kTH1D, {{4, 1., 5.}}}); - hParticles = registry.add(NameHistParticles, "HF particle counter;;# of accepted particles", {o2::framework::HistType::kTH1D, {axisEvents}}); + hGenCollisions = registry.add(NameHistGenCollisions, "HF event counter;;# of accepted collisions", {o2::framework::HistType::kTH1D, {axisEvents}}); // Puts labels on the collision monitoring histogram. - setEventRejectionLabels(hParticles); + setEventRejectionLabels(hGenCollisions); } /// \brief Configures the object from the reco workflow @@ -464,9 +510,9 @@ struct HfEventSelectionMc { /// \param centrality centrality variable to be set in this function /// \return a bitmask with the event selections not satisfied by the analysed collision template - uint16_t getHfMcCollisionRejectionMask(TMcColl const& mcCollision, CCs const& collSlice, float& centrality) + uint32_t getHfMcCollisionRejectionMask(TMcColl const& mcCollision, CCs const& collSlice, float& centrality) { - uint16_t rejectionMask{0}; + uint32_t rejectionMask{0}; float zPv = mcCollision.posZ(); auto bc = mcCollision.template bc_as(); @@ -515,9 +561,9 @@ struct HfEventSelectionMc { /// \param collision analysed collision /// \param rejectionMask bitmask storing the info about which ev. selections are not satisfied by the collision template - void fillHistograms(Coll const& mcCollision, const uint16_t rejectionMask, int nSplitColl = 0) + void fillHistograms(Coll const& mcCollision, const uint32_t rejectionMask, int nSplitColl = 0) { - hParticles->Fill(EventRejection::None); + hGenCollisions->Fill(EventRejection::None); if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0M) { if (!TESTBIT(rejectionMask, EventRejection::TimeFrameBorderCut) && !TESTBIT(rejectionMask, EventRejection::ItsRofBorderCut) && !TESTBIT(rejectionMask, EventRejection::PositionZ)) { @@ -529,7 +575,7 @@ struct HfEventSelectionMc { if (TESTBIT(rejectionMask, reason)) { return; } - hParticles->Fill(reason); + hGenCollisions->Fill(reason); } if constexpr (centEstimator == o2::hf_centrality::CentralityEstimator::FT0M) { diff --git a/PWGHF/Utils/utilsMcGen.h b/PWGHF/Utils/utilsMcGen.h index 73dac888c8e..76152505906 100644 --- a/PWGHF/Utils/utilsMcGen.h +++ b/PWGHF/Utils/utilsMcGen.h @@ -10,185 +10,299 @@ // or submit itself to any jurisdiction. /// \file utilsMcGen.h -/// \brief utility functions for HF Mc gen. workflows +/// \brief utility functions for HF MC gen. workflows /// /// \author Nima Zardoshti, nima.zardoshti@cern.ch, CERN #ifndef PWGHF_UTILS_UTILSMCGEN_H_ #define PWGHF_UTILS_UTILSMCGEN_H_ -#include -#include +#include "PWGHF/Core/DecayChannels.h" +#include "PWGHF/Utils/utilsMcMatching.h" + +#include "Common/Core/RecoDecay.h" #include +#include + +#include #include +#include #include #include -#include "Common/Core/RecoDecay.h" - -#include "PWGHF/Core/DecayChannels.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" - namespace hf_mc_gen { template -void fillMcMatchGen2Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground) +void fillMcMatchGen2Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground, bool matchCorrelatedBackground) { using namespace o2::constants::physics; + using namespace o2::hf_decay::hf_cand_2prong; + + constexpr std::size_t NDaughtersResonant{2u}; // Match generated particles. for (const auto& particle : mcParticlesPerMcColl) { - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelResonant = 0; int8_t origin = 0; int8_t sign = 0; std::vector idxBhadMothers{}; // Reject particles from background events if (particle.fromBackgroundEvent() && rejectBackground) { - rowMcMatchGen(flag, origin, -1); + rowMcMatchGen(flagChannelMain, origin, flagChannelResonant, -1); continue; } + if (matchCorrelatedBackground) { + constexpr int DepthMainMax = 2; // Depth for final state matching + constexpr int DepthResoMax = 1; // Depth for resonant decay matching + bool matched = false; - // D0(bar) → π± K∓ - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { - flag = sign * (1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK); - } + // TODO: J/ψ + for (const auto& [channelMain, finalState] : daughtersD0Main) { + if (finalState.size() == 3) { // o2-linter: disable=magic-number (partially reconstructed 3-prong decays) + std::array arrPdgDaughtersMain3Prongs = std::array{finalState[0], finalState[1], finalState[2]}; + o2::hf_decay::flipPdgSign(particle.pdgCode(), +kPi0, arrPdgDaughtersMain3Prongs); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, arrPdgDaughtersMain3Prongs, true, &sign, DepthMainMax); + } else if (finalState.size() == 2) { // o2-linter: disable=magic-number (fully reconstructed 2-prong decays) + std::array arrPdgDaughtersMain2Prongs = std::array{finalState[0], finalState[1]}; + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, arrPdgDaughtersMain2Prongs, true, &sign, DepthMainMax); + } else { + LOG(fatal) << "Final state size not supported: " << finalState.size(); + return; + } + if (matched) { + flagChannelMain = sign * channelMain; - // J/ψ → e+ e− - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true)) { - flag = 1 << o2::aod::hf_cand_2prong::DecayType::JpsiToEE; + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + RecoDecay::getDaughters(particle, &arrResoDaughIndex, std::array{0}, DepthResoMax); + std::array arrPdgDaughters = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrResoDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPdgDaughters[iProng] = daughI.pdgCode(); + } + flagChannelResonant = o2::hf_decay::getDecayChannelResonant(Pdg::kD0, arrPdgDaughters); + } + break; + } + } + } else { + // D0(bar) → π± K∓ + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kD0, std::array{+kPiPlus, -kKPlus}, true, &sign)) { + flagChannelMain = sign * DecayChannelMain::D0ToPiK; + } + + // J/ψ → e+ e− + if (flagChannelMain == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kElectron, -kElectron}, true)) { + flagChannelMain = DecayChannelMain::JpsiToEE; + } } - } - // J/ψ → μ+ μ− - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { - flag = 1 << o2::aod::hf_cand_2prong::DecayType::JpsiToMuMu; + // J/ψ → μ+ μ− + if (flagChannelMain == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kJPsi, std::array{+kMuonPlus, -kMuonPlus}, true)) { + flagChannelMain = DecayChannelMain::JpsiToMuMu; + } } } // Check whether the particle is non-prompt (from a b quark). - if (flag != 0) { + if (flagChannelMain != 0) { origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } if (origin == RecoDecay::OriginType::NonPrompt) { - rowMcMatchGen(flag, origin, idxBhadMothers[0]); + rowMcMatchGen(flagChannelMain, origin, flagChannelResonant, idxBhadMothers[0]); } else { - rowMcMatchGen(flag, origin, -1); + rowMcMatchGen(flagChannelMain, origin, flagChannelResonant, -1); } } } template -void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground) +void fillMcMatchGen3Prong(T const& mcParticles, U const& mcParticlesPerMcColl, V& rowMcMatchGen, bool rejectBackground, std::vector const& pdgMothersCorrelBkg = {}) { using namespace o2::constants::physics; + using namespace o2::hf_decay::hf_cand_3prong; + constexpr std::size_t NDaughtersResonant{2u}; // Match generated particles. for (const auto& particle : mcParticlesPerMcColl) { - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelResonant = 0; int8_t origin = 0; - int8_t channel = 0; int8_t sign = 0; std::vector arrDaughIndex; std::vector idxBhadMothers{}; - std::array arrPDGDaugh; - std::array arrPDGResonant1 = {kProton, Pdg::kK0Star892}; // Λc± → p± K* - std::array arrPDGResonant2 = {2224, kKPlus}; // Λc± → Δ(1232)±± K∓ - std::array arrPDGResonant3 = {102134, kPiPlus}; // Λc± → Λ(1520) π± - std::array arrPDGResonantDPhiPi = {Pdg::kPhi, kPiPlus}; // Ds± → Phi π± and D± → Phi π± - std::array arrPDGResonantDKstarK = {Pdg::kK0Star892, kKPlus}; // Ds± → K*(892)0bar K± and D± → K*(892)0bar K± + std::array arrPdgDaugResonant; + const std::array arrPdgDaugResonantLcToPKstar0{daughtersLcResonant.at(DecayChannelResonant::LcToPKstar0)}; // Λc± → p± K* + const std::array arrPdgDaugResonantLcToDeltaplusplusK{daughtersLcResonant.at(DecayChannelResonant::LcToDeltaplusplusK)}; // Λc± → Δ(1232)±± K∓ + const std::array arrPdgDaugResonantLcToL1520Pi{daughtersLcResonant.at(DecayChannelResonant::LcToL1520Pi)}; // Λc± → Λ(1520) π± + const std::array arrPdgDaugResonantDToPhiPi{daughtersDsResonant.at(DecayChannelResonant::DsToPhiPi)}; // Ds± → φ π± and D± → φ π± + const std::array arrPdgDaugResonantDToKstar0K{daughtersDsResonant.at(DecayChannelResonant::DsToKstar0K)}; // Ds± → anti-K*(892)0 K± and D± → anti-K*(892)0 K± + // Reject particles from background events if (particle.fromBackgroundEvent() && rejectBackground) { - rowMcMatchGen(flag, origin, channel, -1); + rowMcMatchGen(flagChannelMain, origin, flagChannelResonant, -1); continue; } - // D± → π± K∓ π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKPi; - } - } + if (pdgMothersCorrelBkg.size() > 0) { + for (const auto& pdgMother : pdgMothersCorrelBkg) { + if (std::abs(particle.pdgCode()) != pdgMother) { + continue; // Skip if the particle PDG code does not match the mother PDG code + } + auto finalStates = getDecayChannelsMain(pdgMother); + constexpr int DepthMainMax = 2; // Depth for final state matching + constexpr int DepthResoMax = 1; // Depth for resonant decay matching - // Ds± → K± K∓ π± and D± → K± K∓ π± - if (flag == 0) { - bool isDplus = false; - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - // TODO: move to different and explicit flags - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DsToPiKK; - } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { - // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± - // TODO: move to different and explicit flags - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DplusToPiKK; - isDplus = true; - } - if (flag != 0) { - RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); - arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + int depthMainMax = DepthMainMax; + bool matched = false; + if (pdgMother == Pdg::kDStar) { + depthMainMax = DepthMainMax + 1; // D0 resonant decays are switched on + } + + std::vector arrAllDaughtersIndex; + for (const auto& [channelMain, finalState] : finalStates) { + if (finalState.size() == 5) { // o2-linter: disable=magic-number (partially reconstructed 3-prong decays from 5-prong decays) + std::array arrPdgDaughtersMain5Prongs = std::array{finalState[0], finalState[1], finalState[2], finalState[3], finalState[4]}; + o2::hf_decay::flipPdgSign(particle.pdgCode(), +kPi0, arrPdgDaughtersMain5Prongs); + RecoDecay::getDaughters(particle, &arrAllDaughtersIndex, arrPdgDaughtersMain5Prongs, depthMainMax); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, pdgMother, arrPdgDaughtersMain5Prongs, true, &sign, -1); + } else if (finalState.size() == 4) { // o2-linter: disable=magic-number (partially reconstructed 3-prong decays from 4-prong decays) + std::array arrPdgDaughtersMain4Prongs = std::array{finalState[0], finalState[1], finalState[2], finalState[3]}; + o2::hf_decay::flipPdgSign(particle.pdgCode(), +kPi0, arrPdgDaughtersMain4Prongs); + RecoDecay::getDaughters(particle, &arrAllDaughtersIndex, arrPdgDaughtersMain4Prongs, depthMainMax); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, pdgMother, arrPdgDaughtersMain4Prongs, true, &sign, -1); + } else if (finalState.size() == 3) { // o2-linter: disable=magic-number (fully reconstructed 3-prong decays) + std::array arrPdgDaughtersMain3Prongs = std::array{finalState[0], finalState[1], finalState[2]}; + RecoDecay::getDaughters(particle, &arrAllDaughtersIndex, arrPdgDaughtersMain3Prongs, depthMainMax); + matched = RecoDecay::isMatchedMCGen(mcParticles, particle, pdgMother, arrPdgDaughtersMain3Prongs, true, &sign, depthMainMax); + } else { + LOG(fatal) << "Final state size not supported: " << finalState.size(); + return; } - if ((arrPDGDaugh[0] == arrPDGResonantDPhiPi[0] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[1]) || (arrPDGDaugh[0] == arrPDGResonantDPhiPi[1] && arrPDGDaugh[1] == arrPDGResonantDPhiPi[0])) { - channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToPhiPi : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToPhiPi; - } else if ((arrPDGDaugh[0] == arrPDGResonantDKstarK[0] && arrPDGDaugh[1] == arrPDGResonantDKstarK[1]) || (arrPDGDaugh[0] == arrPDGResonantDKstarK[1] && arrPDGDaugh[1] == arrPDGResonantDKstarK[0])) { - channel = isDplus ? o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DplusToKstar0K : o2::hf_decay::hf_cand_3prong::DecayChannelResonant::DsToKstar0K; + if (matched) { + flagChannelMain = sign * channelMain; + // Flag the resonant decay channel + std::vector arrResoDaughIndex = {}; + if (std::abs(pdgMother) == Pdg::kDStar) { + std::vector arrResoDaughIndexDStar = {}; + RecoDecay::getDaughters(particle, &arrResoDaughIndexDStar, std::array{0}, DepthResoMax); + for (std::size_t iDaug = 0; iDaug < arrResoDaughIndexDStar.size(); iDaug++) { + auto daughDstar = mcParticles.rawIteratorAt(arrResoDaughIndexDStar[iDaug]); + if (std::abs(daughDstar.pdgCode()) == Pdg::kD0 || std::abs(daughDstar.pdgCode()) == Pdg::kDPlus) { + RecoDecay::getDaughters(daughDstar, &arrResoDaughIndex, std::array{0}, DepthResoMax); + break; + } + } + } else { + RecoDecay::getDaughters(particle, &arrResoDaughIndex, std::array{0}, DepthResoMax); + } + std::array arrPdgDaughters = {}; + if (arrResoDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < NDaughtersResonant; ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrResoDaughIndex[iProng]); + arrPdgDaughters[iProng] = daughI.pdgCode(); + } + flagChannelResonant = o2::hf_decay::getDecayChannelResonant(pdgMother, arrPdgDaughters); + } + break; // Exit loop if a match is found } } + if (matched) { + break; // Exit loop if a match is found + } } - } + } else { - // D*± → D0(bar) π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::DstarToPiKPi; + // D± → π± K∓ π± + if (flagChannelMain == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kPiPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flagChannelMain = sign * DecayChannelMain::DplusToPiKPi; + } } - } - // Λc± → p± K∓ π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi; - - // Flagging the different Λc± → p± K∓ π± decay channels - RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); - if (arrDaughIndex.size() == NDaughtersResonant) { - for (auto jProng = 0u; jProng < arrDaughIndex.size(); ++jProng) { - auto daughJ = mcParticles.rawIteratorAt(arrDaughIndex[jProng]); - arrPDGDaugh[jProng] = std::abs(daughJ.pdgCode()); + // Ds± → K± K∓ π± and D± → K± K∓ π± + if (flagChannelMain == 0) { + bool isDplus = false; + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDS, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + // TODO: move to different and explicit flags + flagChannelMain = sign * DecayChannelMain::DsToPiKK; + } else if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDPlus, std::array{+kKPlus, -kKPlus, +kPiPlus}, true, &sign, 2)) { + // DecayType::DsToKKPi is used to flag both Ds± → K± K∓ π± and D± → K± K∓ π± + // TODO: move to different and explicit flags + flagChannelMain = sign * DecayChannelMain::DplusToPiKK; + isDplus = true; + } + if (flagChannelMain != 0) { + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPdgDaugResonant[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPdgDaugResonant[0] == arrPdgDaugResonantDToPhiPi[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToPhiPi[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantDToPhiPi[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToPhiPi[0])) { + flagChannelResonant = isDplus ? DecayChannelResonant::DplusToPhiPi : DecayChannelResonant::DsToPhiPi; + } else if ((arrPdgDaugResonant[0] == arrPdgDaugResonantDToKstar0K[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToKstar0K[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantDToKstar0K[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantDToKstar0K[0])) { + flagChannelResonant = isDplus ? DecayChannelResonant::DplusToKstar0K : DecayChannelResonant::DsToKstar0K; + } } - if ((arrPDGDaugh[0] == arrPDGResonant1[0] && arrPDGDaugh[1] == arrPDGResonant1[1]) || (arrPDGDaugh[0] == arrPDGResonant1[1] && arrPDGDaugh[1] == arrPDGResonant1[0])) { - channel = 1; - } else if ((arrPDGDaugh[0] == arrPDGResonant2[0] && arrPDGDaugh[1] == arrPDGResonant2[1]) || (arrPDGDaugh[0] == arrPDGResonant2[1] && arrPDGDaugh[1] == arrPDGResonant2[0])) { - channel = 2; - } else if ((arrPDGDaugh[0] == arrPDGResonant3[0] && arrPDGDaugh[1] == arrPDGResonant3[1]) || (arrPDGDaugh[0] == arrPDGResonant3[1] && arrPDGDaugh[1] == arrPDGResonant3[0])) { - channel = 3; + } + } + + // D*± → D0(bar) π± + if (flagChannelMain == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kDStar, std::array{+kPiPlus, +kPiPlus, -kKPlus}, true, &sign, 2)) { + flagChannelMain = sign * DecayChannelMain::DstarToPiKPi; + } + } + + // Λc± → p± K∓ π± + if (flagChannelMain == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kLambdaCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flagChannelMain = sign * DecayChannelMain::LcToPKPi; + + // Flagging the different Λc± → p± K∓ π± decay channels + RecoDecay::getDaughters(particle, &arrDaughIndex, std::array{0}, 1); + if (arrDaughIndex.size() == NDaughtersResonant) { + for (auto iProng = 0u; iProng < arrDaughIndex.size(); ++iProng) { + auto daughI = mcParticles.rawIteratorAt(arrDaughIndex[iProng]); + arrPdgDaugResonant[iProng] = std::abs(daughI.pdgCode()); + } + if ((arrPdgDaugResonant[0] == arrPdgDaugResonantLcToPKstar0[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToPKstar0[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantLcToPKstar0[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToPKstar0[0])) { + flagChannelResonant = DecayChannelResonant::LcToPKstar0; + } else if ((arrPdgDaugResonant[0] == arrPdgDaugResonantLcToDeltaplusplusK[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToDeltaplusplusK[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantLcToDeltaplusplusK[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToDeltaplusplusK[0])) { + flagChannelResonant = DecayChannelResonant::LcToDeltaplusplusK; + } else if ((arrPdgDaugResonant[0] == arrPdgDaugResonantLcToL1520Pi[0] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToL1520Pi[1]) || (arrPdgDaugResonant[0] == arrPdgDaugResonantLcToL1520Pi[1] && arrPdgDaugResonant[1] == arrPdgDaugResonantLcToL1520Pi[0])) { + flagChannelResonant = DecayChannelResonant::LcToL1520Pi; + } } } } - } - // Ξc± → p± K∓ π± - if (flag == 0) { - if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { - flag = sign * o2::hf_decay::hf_cand_3prong::DecayChannelMain::XicToPKPi; + // Ξc± → p± K∓ π± + if (flagChannelMain == 0) { + if (RecoDecay::isMatchedMCGen(mcParticles, particle, Pdg::kXiCPlus, std::array{+kProton, -kKPlus, +kPiPlus}, true, &sign, 2)) { + flagChannelMain = sign * DecayChannelMain::XicToPKPi; + } } } // Check whether the particle is non-prompt (from a b quark). - if (flag != 0) { + if (flagChannelMain != 0) { origin = RecoDecay::getCharmHadronOrigin(mcParticles, particle, false, &idxBhadMothers); } if (origin == RecoDecay::OriginType::NonPrompt) { - rowMcMatchGen(flag, origin, channel, idxBhadMothers[0]); + rowMcMatchGen(flagChannelMain, origin, flagChannelResonant, idxBhadMothers[0]); } else { - rowMcMatchGen(flag, origin, channel, -1); + rowMcMatchGen(flagChannelMain, origin, flagChannelResonant, -1); } } } @@ -197,10 +311,12 @@ template void fillMcMatchGenBplus(T const& mcParticles, U& rowMcMatchGen) { using namespace o2::constants::physics; + using namespace o2::hf_decay::hf_cand_beauty; // Match generated particles. for (const auto& particle : mcParticles) { - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelReso = 0; int8_t origin = 0; int8_t signB = 0; int8_t signD0 = 0; @@ -217,10 +333,10 @@ void fillMcMatchGenBplus(T const& mcParticles, U& rowMcMatchGen) } } if (indexGenD0 > -1) { - flag = signB * (1 << o2::aod::hf_cand_bplus::DecayType::BplusToD0Pi); + flagChannelMain = signB * DecayChannelMain::BplusToD0Pi; } } - rowMcMatchGen(flag, origin); + rowMcMatchGen(flagChannelMain, flagChannelReso, origin); } // B candidate } @@ -228,10 +344,12 @@ template void fillMcMatchGenB0(T const& mcParticles, U& rowMcMatchGen) { using namespace o2::constants::physics; + using namespace o2::hf_decay::hf_cand_beauty; // Match generated particles. for (const auto& particle : mcParticles) { - int8_t flag = 0; + int8_t flagChannelMain = 0; + int8_t flagChannelReso = 0; int8_t origin = 0; int8_t sign = 0; // B0 → D- π+ @@ -239,10 +357,10 @@ void fillMcMatchGenB0(T const& mcParticles, U& rowMcMatchGen) // D- → π- K+ π- auto candDMC = mcParticles.rawIteratorAt(particle.daughtersIds().front()); if (RecoDecay::isMatchedMCGen(mcParticles, candDMC, -static_cast(Pdg::kDPlus), std::array{-kPiPlus, +kKPlus, -kPiPlus}, true, &sign)) { - flag = sign * BIT(o2::aod::hf_cand_b0::DecayType::B0ToDPi); + flagChannelMain = sign * DecayChannelMain::B0ToDminusPi; } } - rowMcMatchGen(flag, origin); + rowMcMatchGen(flagChannelMain, flagChannelReso, origin); } // gen } diff --git a/PWGHF/Utils/utilsMcMatching.h b/PWGHF/Utils/utilsMcMatching.h new file mode 100644 index 00000000000..55480879e1a --- /dev/null +++ b/PWGHF/Utils/utilsMcMatching.h @@ -0,0 +1,321 @@ +// 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 utilsMcMatching.h +/// \brief Mapping of MC flags contained in DecayChannels.h +/// \author Marcello Di Costanzo , Polytechnic University of Turin and INFN + +#ifndef PWGHF_UTILS_UTILSMCMATCHING_H_ +#define PWGHF_UTILS_UTILSMCMATCHING_H_ + +#include "PWGHF/Core/DecayChannels.h" + +#include +#include + +#include + +#include +#include +#include +#include +#include + +namespace o2::hf_decay +{ + +namespace hf_cand_2prong +{ + +// D0 + +static const std::unordered_map> daughtersD0Main{ + {DecayChannelMain::D0ToPiK, {+PDG_t::kKMinus, +PDG_t::kPiPlus}}, + {DecayChannelMain::D0ToPiKPi0, {+PDG_t::kKMinus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, + {DecayChannelMain::D0ToPiPi, {+PDG_t::kPiMinus, +PDG_t::kPiPlus}}, + {DecayChannelMain::D0ToPiPiPi0, {+PDG_t::kPiMinus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, + {DecayChannelMain::D0ToKK, {+PDG_t::kKMinus, +PDG_t::kKPlus}}, +}; + +static const std::unordered_map> daughtersD0Resonant{ + {DecayChannelResonant::D0ToRhoplusPi, {+PDG_t::kRho770Plus, +PDG_t::kPiMinus}}, + {DecayChannelResonant::D0ToRhoplusK, {+PDG_t::kRho770Plus, +PDG_t::kKMinus}}, + {DecayChannelResonant::D0ToKstar0Pi0, {-o2::constants::physics::Pdg::kK0Star892, +PDG_t::kPi0}}, + {DecayChannelResonant::D0ToKstarPi, {-o2::constants::physics::Pdg::kKPlusStar892, +PDG_t::kPiPlus}}, +}; + +// J/ψ + +static const std::unordered_map> daughtersJpsiMain{ + {DecayChannelMain::JpsiToEE, {+PDG_t::kElectron, +PDG_t::kPositron}}, + {DecayChannelMain::JpsiToMuMu, {+PDG_t::kMuonMinus, +PDG_t::kMuonPlus}}, +}; +} // namespace hf_cand_2prong + +namespace hf_cand_3prong +{ + +// D± + +static const std::unordered_map> daughtersDplusMain{ + {DecayChannelMain::DplusToPiKPi, {+PDG_t::kKMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus}}, + {DecayChannelMain::DplusToPiKK, {+PDG_t::kKMinus, +PDG_t::kKPlus, +PDG_t::kPiPlus}}, + {DecayChannelMain::DplusToPiKPiPi0, {+PDG_t::kKMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, + {DecayChannelMain::DplusToPiPiPi, {+PDG_t::kPiMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus}}, +}; + +static const std::unordered_map> daughtersDplusResonant{ + {DecayChannelResonant::DplusToPhiPi, {+o2::constants::physics::Pdg::kPhi, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DplusToKstar0K, {-o2::constants::physics::Pdg::kK0Star892, +PDG_t::kKPlus}}, + {DecayChannelResonant::DplusToKstar1430_0K, {-10311, +PDG_t::kKPlus}}, + {DecayChannelResonant::DplusToRho0Pi, {+PDG_t::kRho770_0, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DplusToF2_1270Pi, {+225, +PDG_t::kPiPlus}}, +}; + +// Ds± + +static const std::unordered_map> daughtersDsMain{ + {DecayChannelMain::DsToPiKK, {+PDG_t::kKMinus, +PDG_t::kKPlus, +PDG_t::kPiPlus}}, + {DecayChannelMain::DsToPiKKPi0, {+PDG_t::kKMinus, +PDG_t::kKPlus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, + {DecayChannelMain::DsToPiPiK, {+PDG_t::kKPlus, +PDG_t::kPiPlus, +PDG_t::kPiMinus}}, + {DecayChannelMain::DsToPiPiPi, {+PDG_t::kPiMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus}}, + {DecayChannelMain::DsToPiPiPiPi0, {+PDG_t::kPiMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, +}; + +static const std::unordered_map> daughtersDsResonant{ + {DecayChannelResonant::DsToPhiPi, {+o2::constants::physics::Pdg::kPhi, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DsToPhiRhoplus, {+o2::constants::physics::Pdg::kPhi, +PDG_t::kRho770Plus}}, + {DecayChannelResonant::DsToKstar0K, {-o2::constants::physics::Pdg::kK0Star892, +PDG_t::kKPlus}}, + {DecayChannelResonant::DsToKstar0Pi, {+o2::constants::physics::Pdg::kK0Star892, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DsToRho0Pi, {+PDG_t::kRho770_0, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DsToRho0K, {+PDG_t::kRho770_0, +PDG_t::kKPlus}}, + {DecayChannelResonant::DsToF2_1270Pi, {225, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DsToF0_1370K, {10221, +PDG_t::kKPlus}}, + {DecayChannelResonant::DsToEtaPi, {221, +PDG_t::kPiPlus}}, +}; + +// D*+ + +static const std::unordered_map> daughtersDstarMain{ + {DecayChannelMain::DstarToPiKPi, {+PDG_t::kKMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus}}, + {DecayChannelMain::DstarToPiKPiPi0, {+PDG_t::kKMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, + {DecayChannelMain::DstarToPiKPiPi0Pi0, {+PDG_t::kKMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus, +PDG_t::kPi0, +PDG_t::kPi0}}, + {DecayChannelMain::DstarToPiKK, {+PDG_t::kKMinus, +PDG_t::kKPlus, +PDG_t::kPiPlus}}, + {DecayChannelMain::DstarToPiKKPi0, {+PDG_t::kKMinus, +PDG_t::kKPlus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, + {DecayChannelMain::DstarToPiPiPi, {+PDG_t::kPiMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus}}, + {DecayChannelMain::DstarToPiPiPiPi0, {+PDG_t::kPiMinus, +PDG_t::kPiPlus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, +}; + +static const std::unordered_map> daughtersDstarResonant{ + {DecayChannelResonant::DstarToD0ToRhoplusPi, {+PDG_t::kRho770Plus, +PDG_t::kPiMinus}}, + {DecayChannelResonant::DstarToD0ToRhoplusK, {+PDG_t::kRho770Plus, +PDG_t::kKMinus}}, + {DecayChannelResonant::DstarToD0ToKstar0Pi0, {-o2::constants::physics::Pdg::kK0Star892, +PDG_t::kPi0}}, + {DecayChannelResonant::DstarToD0ToKstarPi, {-o2::constants::physics::Pdg::kKPlusStar892, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DstarToDplusToPhiPi, {+o2::constants::physics::Pdg::kPhi, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DstarToDplusToKstar0K, {-o2::constants::physics::Pdg::kK0Star892, +PDG_t::kKPlus}}, + {DecayChannelResonant::DstarToDplusToKstar1430_0K, {-10311, +PDG_t::kKPlus}}, + {DecayChannelResonant::DstarToDplusToRho0Pi, {+PDG_t::kRho770_0, +PDG_t::kPiPlus}}, + {DecayChannelResonant::DstarToDplusToF2_1270Pi, {+225, +PDG_t::kPiPlus}}, +}; + +// Λc+ + +static const std::unordered_map> daughtersLcMain{ + {DecayChannelMain::LcToPKPi, {+PDG_t::kProton, +PDG_t::kKMinus, +PDG_t::kPiPlus}}, + {DecayChannelMain::LcToPKPiPi0, {+PDG_t::kProton, +PDG_t::kKMinus, +PDG_t::kPiPlus, +PDG_t::kPi0}}, + {DecayChannelMain::LcToPPiPi, {+PDG_t::kProton, +PDG_t::kPiMinus, +PDG_t::kPiPlus}}, + {DecayChannelMain::LcToPKK, {+PDG_t::kProton, +PDG_t::kKMinus, +PDG_t::kKPlus}}}; + +static const std::unordered_map> daughtersLcResonant{ + {DecayChannelResonant::LcToPKstar0, {-o2::constants::physics::Pdg::kK0Star892, +PDG_t::kProton}}, + {DecayChannelResonant::LcToDeltaplusplusK, {+2224, +PDG_t::kKMinus}}, + {DecayChannelResonant::LcToL1520Pi, {+102134, +PDG_t::kPiPlus}}, +}; + +// Ξc+ + +static const std::unordered_map> daughtersXicMain{ + {DecayChannelMain::XicToPKPi, {+PDG_t::kProton, +PDG_t::kKMinus, +PDG_t::kPiPlus}}, + {DecayChannelMain::XicToPKK, {+PDG_t::kProton, +PDG_t::kKMinus, +PDG_t::kKPlus}}, + {DecayChannelMain::XicToSPiPi, {+PDG_t::kSigmaPlus, +PDG_t::kPiMinus, +PDG_t::kPiPlus}}, +}; + +static const std::unordered_map> daughtersXicResonant{ + {DecayChannelResonant::XicToPKstar0, {-o2::constants::physics::Pdg::kK0Star892, +PDG_t::kProton}}, + {DecayChannelResonant::XicToPPhi, {+PDG_t::kProton, +o2::constants::physics::Pdg::kPhi}}, +}; + +/// Returns a map of the possible final states for a specific 3-prong particle specie +/// \param pdgMother PDG code of the mother particle +/// \return a map of final states with their corresponding PDG codes +inline std::unordered_map> getDecayChannelsMain(int pdgMother) +{ + switch (pdgMother) { + case o2::constants::physics::Pdg::kDPlus: + return daughtersDplusMain; + case o2::constants::physics::Pdg::kDS: + return daughtersDsMain; + case o2::constants::physics::Pdg::kDStar: + return daughtersDstarMain; + case o2::constants::physics::Pdg::kLambdaCPlus: + return daughtersLcMain; + case o2::constants::physics::Pdg::kXiCPlus: + return daughtersXicMain; + default: + LOG(fatal) << "Unknown PDG code for 3-prong final states: " << pdgMother; + return {}; + } +} +} // namespace hf_cand_3prong + +namespace hf_cand_reso +{ +const std::unordered_map particlesToDstarK0s = { + {DecayChannelMain::Ds1ToDstarK0s, constants::physics::Pdg::kDS1}, + {DecayChannelMain::Ds2starToDstarK0s, constants::physics::Pdg::kDS2Star}, + {DecayChannelMain::Ds1star2700ToDstarK0s, constants::physics::Pdg::kDS1Star2700}, + {DecayChannelMain::Ds1star2860ToDstarK0s, constants::physics::Pdg::kDS1Star2860}, + {DecayChannelMain::Ds3star2860ToDstarK0s, constants::physics::Pdg::kDS3Star2860}}; +const std::unordered_map particlesToDplusK0s = { + {DecayChannelMain::Ds2starToDplusK0s, constants::physics::Pdg::kDS2Star}}; +const std::unordered_map particlesToDplusLambda = { + {DecayChannelMain::Xic3055plusToDplusLambda, constants::physics::Pdg::kXiC3055Plus}, + {DecayChannelMain::Xic3080plusToDplusLambda, constants::physics::Pdg::kXiC3080Plus}}; +const std::unordered_map particlesToD0Lambda = { + {DecayChannelMain::Xic3055zeroToD0Lambda, constants::physics::Pdg::kXiC3055_0}, + {DecayChannelMain::Xic3080zeroToD0Lambda, constants::physics::Pdg::kXiC3080_0}}; +const std::unordered_map particlesToDstarPi = { + {DecayChannelMain::D1zeroToDstarPi, constants::physics::Pdg::kD10}, + {DecayChannelMain::D2starzeroToDstarPi, constants::physics::Pdg::kD2Star0}}; +const std::unordered_map particlesToDplusPi = { + {DecayChannelMain::D2starzeroToDplusPi, constants::physics::Pdg::kD2Star0}}; +const std::unordered_map particlesToD0Pi = { + {DecayChannelMain::D2starplusToD0Pi, constants::physics::Pdg::kD2StarPlus}, + {DecayChannelMain::DstarToD0Pi, constants::physics::Pdg::kDStar}}; +const std::unordered_map particlesToD0Kplus = { + {DecayChannelMain::Ds2starToD0Kplus, constants::physics::Pdg::kDS2Star}}; + +enum PartialMatchMc : uint8_t { + D0Matched = 0, + DstarMatched, + DplusMatched, + K0Matched, + LambdaMatched, + PionMatched, + KaonMatched, + ProtonMatched, + ResoPartlyMatched +}; +} // namespace hf_cand_reso + +/// Compare an array of PDG codes with an expected array +/// \tparam N size of the arrays to be compared +/// \param arrPdgTested array of PDG codes to be tested +/// \param arrPdgExpected array of the expected PDG codes +/// \return true if the arrays are equal, false otherwise +template +inline bool areSamePdgArrays(std::array const& arrPdgTested, std::array arrPdgExpected) +{ + for (std::size_t i = 0; i < N; i++) { + bool foundPdg = false; + for (std::size_t j = 0; j < N; j++) { + if (std::abs(arrPdgTested[i]) == std::abs(arrPdgExpected[j])) { + arrPdgExpected[j] = -1; // Mark as found + foundPdg = true; + break; + } + } + if (!foundPdg) { + return false; + } + } + return true; +} + +/// Flag the resonant decay channel +/// \tparam N size of the array of daughter PDG codes +/// \param pdgMother PDG code of the mother particle +/// \param arrPdgDaughters array of daughter PDG codes +/// \return the channel for the matched resonant decay channel +template +inline int8_t getDecayChannelResonant(const int pdgMother, std::array const& arrPdgDaughters) +{ + switch (pdgMother) { + case o2::constants::physics::Pdg::kD0: + for (const auto& [channelResonant, arrPdgDaughtersResonant] : hf_cand_2prong::daughtersD0Resonant) { + if (areSamePdgArrays(arrPdgDaughters, arrPdgDaughtersResonant)) { + return channelResonant; + } + } + break; + case o2::constants::physics::Pdg::kDPlus: + for (const auto& [channelResonant, arrPdgDaughtersResonant] : hf_cand_3prong::daughtersDplusResonant) { + if (areSamePdgArrays(arrPdgDaughters, arrPdgDaughtersResonant)) { + return channelResonant; + } + } + break; + case o2::constants::physics::Pdg::kDS: + for (const auto& [channelResonant, arrPdgDaughtersResonant] : hf_cand_3prong::daughtersDsResonant) { + if (areSamePdgArrays(arrPdgDaughters, arrPdgDaughtersResonant)) { + return channelResonant; + } + } + break; + case o2::constants::physics::Pdg::kDStar: + for (const auto& [channelResonant, arrPdgDaughtersResonant] : hf_cand_3prong::daughtersDstarResonant) { + if (areSamePdgArrays(arrPdgDaughters, arrPdgDaughtersResonant)) { + return channelResonant; + } + } + break; + case o2::constants::physics::Pdg::kLambdaCPlus: + for (const auto& [channelResonant, arrPdgDaughtersResonant] : hf_cand_3prong::daughtersLcResonant) { + if (areSamePdgArrays(arrPdgDaughters, arrPdgDaughtersResonant)) { + return channelResonant; + } + } + break; + case o2::constants::physics::Pdg::kXiCPlus: + for (const auto& [channelResonant, arrPdgDaughtersResonant] : hf_cand_3prong::daughtersXicResonant) { + if (areSamePdgArrays(arrPdgDaughters, arrPdgDaughtersResonant)) { + return channelResonant; + } + } + break; + default: + LOG(fatal) << "Unknown PDG code for 3-prong final states: " << pdgMother; + return -1; + } + return 0; +} + +/// Flip the sign of a specific PDG code in an array +/// of PDG codes associated to an antiparticle. +/// \tparam N size of the array of PDG codes +/// \param pdgMother PDG code of the mother particle +/// \param pdgToFlip PDG code to be flipped +/// \param arrPdg array of PDG codes to be modified +template +inline void flipPdgSign(const int pdgMother, const int pdgToFlip, std::array& arrPdg) +{ + if (pdgMother >= 0) { + return; + } + for (auto& pdg : arrPdg) { // o2-linter: disable=const-ref-in-for-loop (arrPdg entries are modified) + if (pdg == pdgToFlip) { + pdg = -pdg; + } + } +} +} // namespace o2::hf_decay + +#endif // PWGHF_UTILS_UTILSMCMATCHING_H_ diff --git a/PWGHF/Utils/utilsPid.h b/PWGHF/Utils/utilsPid.h index 3289e60c737..4590bb50b2c 100644 --- a/PWGHF/Utils/utilsPid.h +++ b/PWGHF/Utils/utilsPid.h @@ -17,13 +17,13 @@ #ifndef PWGHF_UTILS_UTILSPID_H_ #define PWGHF_UTILS_UTILSPID_H_ -#include - -#include - #include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/PIDResponseTPC.h" +#include + +#include + namespace o2::aod::pid_tpc_tof_utils { /// @brief Species of HF-candidate daughter tracks diff --git a/PWGHF/Utils/utilsTrkCandHf.h b/PWGHF/Utils/utilsTrkCandHf.h index 94fa2084370..43db7a21e08 100644 --- a/PWGHF/Utils/utilsTrkCandHf.h +++ b/PWGHF/Utils/utilsTrkCandHf.h @@ -16,10 +16,12 @@ #ifndef PWGHF_UTILS_UTILSTRKCANDHF_H_ #define PWGHF_UTILS_UTILSTRKCANDHF_H_ -#include +#include "PWGHF/Utils/utilsAnalysis.h" #include +#include + #include namespace o2::hf_trkcandsel @@ -58,6 +60,29 @@ int countOnesInBinary(uint8_t num) return count; } +/// Single-track cuts on dcaXY +/// \param trackPar is the track parametrisation +/// \param dca is the 2-D array with track DCAs +/// \param binsPtTrack is the array of pt bins for track selection +/// \param cutsTrackDCA are the cuts for track DCA selection +/// \return true if track passes all cuts +template +bool isSelectedTrackDCA(const T1& trackPar, const T2& dca, const C1& binsPtTrack, const C2& cutsTrackDCA) +{ + auto binPtTrack = o2::analysis::findBin(binsPtTrack, trackPar.getPt()); + if (binPtTrack == -1) { + return false; + } + + if (std::abs(dca[0]) < cutsTrackDCA->get(binPtTrack, "min_dcaxytoprimary")) { + return false; // minimum DCAxy + } + if (std::abs(dca[0]) > cutsTrackDCA->get(binPtTrack, "max_dcaxytoprimary")) { + return false; // maximum DCAxy + } + return true; +} + } // namespace o2::hf_trkcandsel #endif // PWGHF_UTILS_UTILSTRKCANDHF_H_ diff --git a/PWGJE/Core/CMakeLists.txt b/PWGJE/Core/CMakeLists.txt index 95895ddc442..b6ccafb2be2 100644 --- a/PWGJE/Core/CMakeLists.txt +++ b/PWGJE/Core/CMakeLists.txt @@ -14,7 +14,8 @@ o2physics_add_library(PWGJECore SOURCES FastJetUtilities.cxx JetFinder.cxx JetBkgSubUtils.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore FastJet::FastJet FastJet::Contrib ONNXRuntime::ONNXRuntime) + emcalCrossTalkEmulation.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore FastJet::FastJet FastJet::Contrib ONNXRuntime::ONNXRuntime O2::EMCALBase O2::EMCALReconstruction) o2physics_target_root_dictionary(PWGJECore HEADERS JetFinder.h @@ -23,5 +24,7 @@ o2physics_target_root_dictionary(PWGJECore JetTaggingUtilities.h JetBkgSubUtils.h JetDerivedDataUtilities.h + emcalCrossTalkEmulation.h + utilsTrackMatchingEMC.h LINKDEF PWGJECoreLinkDef.h) endif() diff --git a/PWGJE/Core/FastJetUtilities.cxx b/PWGJE/Core/FastJetUtilities.cxx index ba7acabbdf3..ca5956a1554 100644 --- a/PWGJE/Core/FastJetUtilities.cxx +++ b/PWGJE/Core/FastJetUtilities.cxx @@ -11,6 +11,10 @@ #include "FastJetUtilities.h" +#include + +#include + void fastjetutilities::setFastJetUserInfo(std::vector& constituents, int index, int status) { fastjet_user_info* user_info = new fastjet_user_info(status, index); // FIXME: can setting this as a pointer be avoided? diff --git a/PWGJE/Core/FastJetUtilities.h b/PWGJE/Core/FastJetUtilities.h index e6d4b2b3794..aebb41ab5d0 100644 --- a/PWGJE/Core/FastJetUtilities.h +++ b/PWGJE/Core/FastJetUtilities.h @@ -17,15 +17,10 @@ #ifndef PWGJE_CORE_FASTJETUTILITIES_H_ #define PWGJE_CORE_FASTJETUTILITIES_H_ +#include + #include -#include -#include -#include #include -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/Selector.hh" enum class JetConstituentStatus { track = 0, diff --git a/PWGJE/Core/JetBkgSubUtils.cxx b/PWGJE/Core/JetBkgSubUtils.cxx index 281feccc66c..4cc6d202130 100644 --- a/PWGJE/Core/JetBkgSubUtils.cxx +++ b/PWGJE/Core/JetBkgSubUtils.cxx @@ -12,13 +12,26 @@ // jet finder task // // Author: Hadi Hassan, Universiy of Jväskylä, hadi.hassan@cern.ch -#include -#include -#include "Framework/Logger.h" -#include "Common/Core/RecoDecay.h" -#include "PWGJE/Core/JetUtilities.h" + #include "PWGJE/Core/JetBkgSubUtils.h" -#include "PWGJE/Core/FastJetUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include JetBkgSubUtils::JetBkgSubUtils(float jetBkgR_out, float bkgEtaMin_out, float bkgEtaMax_out, float bkgPhiMin_out, float bkgPhiMax_out, float constSubAlpha_out, float constSubRMax_out, int nHardReject_out, fastjet::GhostedAreaSpec ghostAreaSpec_out) : jetBkgR(jetBkgR_out), bkgEtaMin(bkgEtaMin_out), @@ -147,7 +160,7 @@ std::tuple JetBkgSubUtils::estimateRhoPerpCone(const std::vector return std::make_tuple(perpPtDensity, perpMdDensity); } -fastjet::PseudoJet JetBkgSubUtils::doRhoAreaSub(fastjet::PseudoJet& jet, double rhoParam, double rhoMParam) +fastjet::PseudoJet JetBkgSubUtils::doRhoAreaSub(const fastjet::PseudoJet& jet, double rhoParam, double rhoMParam) { fastjet::Subtractor sub = fastjet::Subtractor(rhoParam, rhoMParam); diff --git a/PWGJE/Core/JetBkgSubUtils.h b/PWGJE/Core/JetBkgSubUtils.h index e74aa512b99..81a132c9af9 100644 --- a/PWGJE/Core/JetBkgSubUtils.h +++ b/PWGJE/Core/JetBkgSubUtils.h @@ -17,23 +17,16 @@ #ifndef PWGJE_CORE_JETBKGSUBUTILS_H_ #define PWGJE_CORE_JETBKGSUBUTILS_H_ -#include -#include +#include +#include +#include +#include +#include + #include #include -#include - -#include "PWGJE/Core/FastJetUtilities.h" - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/AreaDefinition.hh" -#include "fastjet/JetDefinition.hh" -#include "fastjet/tools/JetMedianBackgroundEstimator.hh" -#include "fastjet/tools/Subtractor.hh" -#include "fastjet/contrib/ConstituentSubtractor.hh" -#include "Framework/Logger.h" +#include enum class BkgSubEstimator { none = 0, medianRho = 1, @@ -86,7 +79,7 @@ class JetBkgSubUtils /// @param rhoParam the underlying evvent density vs pT (to be set) /// @param rhoParam the underlying evvent density vs jet mass (to be set) /// @return jet, background subtracted jet - fastjet::PseudoJet doRhoAreaSub(fastjet::PseudoJet& jet, double rhoParam, double rhoMParam); + fastjet::PseudoJet doRhoAreaSub(const fastjet::PseudoJet& jet, double rhoParam, double rhoMParam); /// @brief method that subtracts the background from the input particles using the event-wise cosntituent subtractor /// @param inputParticles (all the tracks/clusters/particles in the event) diff --git a/PWGJE/Core/JetCandidateUtilities.h b/PWGJE/Core/JetCandidateUtilities.h index ad7f178b9f0..921b88af9b8 100644 --- a/PWGJE/Core/JetCandidateUtilities.h +++ b/PWGJE/Core/JetCandidateUtilities.h @@ -17,35 +17,12 @@ #ifndef PWGJE_CORE_JETCANDIDATEUTILITIES_H_ #define PWGJE_CORE_JETCANDIDATEUTILITIES_H_ -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/Core/JetV0Utilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" + +#include +#include namespace jetcandidateutilities { @@ -228,11 +205,11 @@ auto matchedParticle(const T& candidate, const U& tracks, const V& particles) * @param candidate candidate that is being checked * @param table the table to be sliced */ -template -auto slicedPerCandidate(T const& table, U const& candidate, V const& perD0Candidate, M const& perDplusCandidate, N const& perLcCandidate, O const& perBplusCandidate, P const& perDielectronCandidate) +template +auto slicedPerCandidate(T const& table, U const& candidate, V const& perD0Candidate, M const& perDplusCandidate, N const& perDstarCandidate, O const& perLcCandidate, P const& perB0Candidate, Q const& perBplusCandidate, R const& perDielectronCandidate) { if constexpr (jethfutilities::isHFCandidate()) { - return jethfutilities::slicedPerHFCandidate(table, candidate, perD0Candidate, perDplusCandidate, perLcCandidate, perBplusCandidate); + return jethfutilities::slicedPerHFCandidate(table, candidate, perD0Candidate, perDplusCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate); } else if constexpr (jetdqutilities::isDielectronCandidate()) { return jetdqutilities::slicedPerDielectronCandidate(table, candidate, perDielectronCandidate); } else { @@ -246,11 +223,11 @@ auto slicedPerCandidate(T const& table, U const& candidate, V const& perD0Candid * @param jet jet that the slice is based on * @param table the table to be sliced */ -template -auto slicedPerJet(T const& table, U const& jet, V const& perD0Jet, M const& perDplusJet, N const& perLcJet, O const& perBplusJet, P const& perDielectronJet) +template +auto slicedPerJet(T const& table, U const& jet, V const& perD0Jet, M const& perDplusJet, N const& perDstarJet, O const& perLcJet, P const& perB0Jet, Q const& perBplusJet, R const& perDielectronJet) { if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { - return jethfutilities::slicedPerHFJet(table, jet, perD0Jet, perDplusJet, perLcJet, perBplusJet); + return jethfutilities::slicedPerHFJet(table, jet, perD0Jet, perDplusJet, perDstarJet, perLcJet, perB0Jet, perBplusJet); } else if constexpr (jetdqutilities::isDielectronTable() || jetdqutilities::isDielectronMcTable()) { return jetdqutilities::slicedPerDielectronJet(table, jet, perDielectronJet); } else { diff --git a/PWGJE/Core/JetDQUtilities.h b/PWGJE/Core/JetDQUtilities.h index c5fb2117e81..6f33ae0749d 100644 --- a/PWGJE/Core/JetDQUtilities.h +++ b/PWGJE/Core/JetDQUtilities.h @@ -17,31 +17,21 @@ #ifndef PWGJE_CORE_JETDQUTILITIES_H_ #define PWGJE_CORE_JETDQUTILITIES_H_ -#include -#include -#include -#include +#include "PWGJE/DataModel/Jet.h" -#include +#include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include +#include namespace jetdqutilities { diff --git a/PWGJE/Core/JetDerivedDataUtilities.h b/PWGJE/Core/JetDerivedDataUtilities.h index b526dc53fc1..c3dc36ab18f 100644 --- a/PWGJE/Core/JetDerivedDataUtilities.h +++ b/PWGJE/Core/JetDerivedDataUtilities.h @@ -17,10 +17,17 @@ #ifndef PWGJE_CORE_JETDERIVEDDATAUTILITIES_H_ #define PWGJE_CORE_JETDERIVEDDATAUTILITIES_H_ -#include -#include -#include "Common/CCDB/TriggerAliases.h" #include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" + +#include + +#include +#include +#include +#include +#include +#include namespace jetderiveddatautilities { @@ -153,9 +160,9 @@ uint16_t setEventSelectionBit(T const& collision) if (collision.sel7()) { SETBIT(bit, JCollisionSel::sel7); } - if (collision.alias_bit(kINT7)) { - SETBIT(bit, JCollisionSel::selKINT7); - } + if (collision.alias_bit(kINT7)) { + SETBIT(bit, JCollisionSel::selKINT7); + } if (collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { SETBIT(bit, JCollisionSel::selTVX); } diff --git a/PWGJE/Core/JetFinder.cxx b/PWGJE/Core/JetFinder.cxx index 03583a9e622..87a71fb19e3 100644 --- a/PWGJE/Core/JetFinder.cxx +++ b/PWGJE/Core/JetFinder.cxx @@ -15,7 +15,13 @@ /// \author Jochen Klein #include "PWGJE/Core/JetFinder.h" -#include "Framework/Logger.h" + +#include +#include +#include +#include + +#include /// Sets the jet finding parameters void JetFinder::setParams() diff --git a/PWGJE/Core/JetFinder.h b/PWGJE/Core/JetFinder.h index 26b4a3c5f0f..94afd0117ec 100644 --- a/PWGJE/Core/JetFinder.h +++ b/PWGJE/Core/JetFinder.h @@ -18,18 +18,18 @@ #ifndef PWGJE_CORE_JETFINDER_H_ #define PWGJE_CORE_JETFINDER_H_ -#include -#include +#include +#include +#include +#include +#include +#include + +#include -#include -#include -#include +#include -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" -#include "fastjet/AreaDefinition.hh" -#include "fastjet/JetDefinition.hh" -#include "fastjet/tools/Subtractor.hh" +#include enum class JetType { full = 0, diff --git a/PWGJE/Core/JetFindingUtilities.h b/PWGJE/Core/JetFindingUtilities.h index ac81338a99d..2bb9b8375b4 100644 --- a/PWGJE/Core/JetFindingUtilities.h +++ b/PWGJE/Core/JetFindingUtilities.h @@ -17,37 +17,31 @@ #ifndef PWGJE_CORE_JETFINDINGUTILITIES_H_ #define PWGJE_CORE_JETFINDINGUTILITIES_H_ -#include -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -// #include "PWGJE/Core/JetBkgSubUtils.h" #include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetCandidateUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/Core/JetCandidateUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +#include namespace jetfindingutilities { diff --git a/PWGJE/Core/JetHFUtilities.h b/PWGJE/Core/JetHFUtilities.h index a5ec07fe157..9c3edc54f13 100644 --- a/PWGJE/Core/JetHFUtilities.h +++ b/PWGJE/Core/JetHFUtilities.h @@ -17,33 +17,18 @@ #ifndef PWGJE_CORE_JETHFUTILITIES_H_ #define PWGJE_CORE_JETHFUTILITIES_H_ -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" +#include "PWGHF/Core/DecayChannels.h" #include "PWGJE/DataModel/Jet.h" +#include +#include + +#include +#include +#include +#include +#include + namespace jethfutilities { @@ -119,6 +104,42 @@ constexpr bool isDplusMcTable() return isDplusMcCandidate() || isDplusMcCandidate(); } +/** + * returns true if the candidate is from a D* table + */ +template +constexpr bool isDstarCandidate() +{ + return std::is_same_v, o2::aod::CandidatesDstarData::iterator> || std::is_same_v, o2::aod::CandidatesDstarData::filtered_iterator> || std::is_same_v, o2::aod::CandidatesDstarMCD::iterator> || std::is_same_v, o2::aod::CandidatesDstarMCD::filtered_iterator>; +} + +/** + * returns true if the particle is from a D* MC table + */ +template +constexpr bool isDstarMcCandidate() +{ + return std::is_same_v, o2::aod::CandidatesDstarMCP::iterator> || std::is_same_v, o2::aod::CandidatesDstarMCP::filtered_iterator>; +} + +/** + * returns true if the table is a D* table + */ +template +constexpr bool isDstarTable() +{ + return isDstarCandidate() || isDstarCandidate(); +} + +/** + * returns true if the table is a D* MC table + */ +template +constexpr bool isDstarMcTable() +{ + return isDstarMcCandidate() || isDstarMcCandidate(); +} + /** * returns true if the candidate is from a Lc table */ @@ -155,6 +176,42 @@ constexpr bool isLcMcTable() return isLcMcCandidate() || isLcMcCandidate(); } +/** + * returns true if the candidate is from a B0 table + */ +template +constexpr bool isB0Candidate() +{ + return std::is_same_v, o2::aod::CandidatesB0Data::iterator> || std::is_same_v, o2::aod::CandidatesB0Data::filtered_iterator> || std::is_same_v, o2::aod::CandidatesB0MCD::iterator> || std::is_same_v, o2::aod::CandidatesB0MCD::filtered_iterator>; +} + +/** + * returns true if the particle is from a B0 MC table + */ +template +constexpr bool isB0McCandidate() +{ + return std::is_same_v, o2::aod::CandidatesB0MCP::iterator> || std::is_same_v, o2::aod::CandidatesB0MCP::filtered_iterator>; +} + +/** + * returns true if the table is a B0 table + */ +template +constexpr bool isB0Table() +{ + return isB0Candidate() || isB0Candidate(); +} + +/** + * returns true if the table is a B0 MC table + */ +template +constexpr bool isB0McTable() +{ + return isB0McCandidate() || isB0McCandidate(); +} + /** * returns true if the candidate is from a Bplus table */ @@ -202,8 +259,12 @@ constexpr bool isHFCandidate() return true; } else if constexpr (isDplusCandidate()) { return true; + } else if constexpr (isDstarCandidate()) { + return true; } else if constexpr (isLcCandidate()) { return true; + } else if constexpr (isB0Candidate()) { + return true; } else if constexpr (isBplusCandidate()) { return true; } else { @@ -222,8 +283,12 @@ constexpr bool isHFMcCandidate() return true; } else if constexpr (isDplusMcCandidate()) { return true; + } else if constexpr (isDstarMcCandidate()) { + return true; } else if constexpr (isLcMcCandidate()) { return true; + } else if constexpr (isB0McCandidate()) { + return true; } else if constexpr (isBplusMcCandidate()) { return true; } else { @@ -241,8 +306,12 @@ constexpr bool isHFTable() return true; } else if constexpr (isDplusCandidate() || isDplusCandidate()) { return true; + } else if constexpr (isDstarCandidate() || isDstarCandidate()) { + return true; } else if constexpr (isLcCandidate() || isLcCandidate()) { return true; + } else if constexpr (isB0Candidate() || isB0Candidate()) { + return true; } else if constexpr (isBplusCandidate() || isBplusCandidate()) { return true; } else { @@ -260,8 +329,12 @@ constexpr bool isHFMcTable() return true; } else if constexpr (isDplusMcCandidate() || isDplusMcCandidate()) { return true; + } else if constexpr (isDstarMcCandidate() || isDstarMcCandidate()) { + return true; } else if constexpr (isLcMcCandidate() || isLcMcCandidate()) { return true; + } else if constexpr (isB0McCandidate() || isB0McCandidate()) { + return true; } else if constexpr (isBplusMcCandidate() || isBplusMcCandidate()) { return true; } else { @@ -277,7 +350,7 @@ template constexpr bool isMatchedHFCandidate(T const& candidate) { if constexpr (isD0Candidate()) { - if (std::abs(candidate.flagMcMatchRec()) == 1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { return true; } else { return false; @@ -288,20 +361,32 @@ constexpr bool isMatchedHFCandidate(T const& candidate) } else { return false; } + } else if constexpr (isDstarCandidate()) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { + return true; + } else { + return false; + } } else if constexpr (isLcCandidate()) { if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { return true; } else { return false; } + } else if constexpr (isB0Candidate()) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_beauty::DecayChannelMain::B0ToDminusPi) { + return true; + } else { + return false; + } } else if constexpr (isBplusCandidate()) { - if (std::abs(candidate.flagMcMatchRec()) == 1 << o2::aod::hf_cand_bplus::DecayType::BplusToD0Pi) { + if (std::abs(candidate.flagMcMatchRec()) == o2::hf_decay::hf_cand_beauty::DecayChannelMain::BplusToD0Pi) { return true; } else { return false; } } else if constexpr (isD0McCandidate()) { - if (std::abs(candidate.flagMcMatchGen()) == 1 << o2::aod::hf_cand_2prong::DecayType::D0ToPiK) { + if (std::abs(candidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK) { return true; } else { return false; @@ -312,14 +397,26 @@ constexpr bool isMatchedHFCandidate(T const& candidate) } else { return false; } + } else if constexpr (isDstarMcCandidate()) { + if (std::abs(candidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_dstar::DecayChannelMain::DstarToPiKPi) { + return true; + } else { + return false; + } } else if constexpr (isLcMcCandidate()) { if (std::abs(candidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_3prong::DecayChannelMain::LcToPKPi) { return true; } else { return false; } + } else if constexpr (isB0McCandidate()) { + if (std::abs(candidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_beauty::DecayChannelMain::B0ToDminusPi) { + return true; + } else { + return false; + } } else if constexpr (isBplusMcCandidate()) { - if (std::abs(candidate.flagMcMatchGen()) == 1 << o2::aod::hf_cand_bplus::DecayType::BplusToD0Pi) { + if (std::abs(candidate.flagMcMatchGen()) == o2::hf_decay::hf_cand_beauty::DecayChannelMain::BplusToD0Pi) { return true; } else { return false; @@ -351,12 +448,24 @@ bool isHFDaughterTrack(T& track, U& candidate, V const& /*tracks*/) } else { return false; } + } else if constexpr (isDstarCandidate()) { + if (candidate.prong0Id() == track.globalIndex() || candidate.prong1Id() == track.globalIndex() || candidate.prong2Id() == track.globalIndex()) { + return true; + } else { + return false; + } } else if constexpr (isLcCandidate()) { if (candidate.prong0Id() == track.globalIndex() || candidate.prong1Id() == track.globalIndex() || candidate.prong2Id() == track.globalIndex()) { return true; } else { return false; } + } else if constexpr (isB0Candidate()) { + if (candidate.prong0Id() == track.globalIndex() || candidate.prong1Id() == track.globalIndex() || candidate.prong2Id() == track.globalIndex() || candidate.prong3Id() == track.globalIndex()) { + return true; + } else { + return false; + } } else if constexpr (isBplusCandidate()) { if (candidate.prong0Id() == track.globalIndex() || candidate.prong1Id() == track.globalIndex() || candidate.prong2Id() == track.globalIndex()) { return true; @@ -402,15 +511,19 @@ auto matchedHFParticle(const T& candidate, const U& /*tracks*/, const V& /*parti * @param candidate HF candidate that is being checked * @param table the table to be sliced */ -template -auto slicedPerHFCandidate(T const& table, U const& candidate, V const& perD0Candidate, M const& perDplusCandidate, N const& perLcCandidate, O const& perBplusCandidate) +template +auto slicedPerHFCandidate(T const& table, U const& candidate, V const& perD0Candidate, M const& perDplusCandidate, N const& perDstarCandidate, O const& perLcCandidate, P const& perB0Candidate, Q const& perBplusCandidate) { if constexpr (isD0Candidate()) { return table.sliceBy(perD0Candidate, candidate.globalIndex()); } else if constexpr (isDplusCandidate()) { return table.sliceBy(perDplusCandidate, candidate.globalIndex()); + } else if constexpr (isDstarCandidate()) { + return table.sliceBy(perDstarCandidate, candidate.globalIndex()); } else if constexpr (isLcCandidate()) { return table.sliceBy(perLcCandidate, candidate.globalIndex()); + } else if constexpr (isB0Candidate()) { + return table.sliceBy(perB0Candidate, candidate.globalIndex()); } else if constexpr (isBplusCandidate()) { return table.sliceBy(perBplusCandidate, candidate.globalIndex()); } else { @@ -425,15 +538,19 @@ auto slicedPerHFCandidate(T const& table, U const& candidate, V const& perD0Cand * @param jet jet that is being sliced based on * @param table the table to be sliced */ -template -auto slicedPerHFJet(T const& table, U const& jet, V const& perD0Jet, M const& perDplusJet, N const& perLcJet, O const& perBplusJet) +template +auto slicedPerHFJet(T const& table, U const& jet, V const& perD0Jet, M const& perDplusJet, N const& perDstarJet, O const& perLcJet, P const& perB0Jet, Q const& perBplusJet) { if constexpr (isD0Table() || isD0McTable()) { return table.sliceBy(perD0Jet, jet.globalIndex()); } else if constexpr (isDplusTable() || isDplusMcTable()) { return table.sliceBy(perDplusJet, jet.globalIndex()); + } else if constexpr (isDstarTable() || isDstarMcTable()) { + return table.sliceBy(perDstarJet, jet.globalIndex()); } else if constexpr (isLcTable() || isLcMcTable()) { return table.sliceBy(perLcJet, jet.globalIndex()); + } else if constexpr (isB0Table() || isB0McTable()) { + return table.sliceBy(perB0Jet, jet.globalIndex()); } else if constexpr (isBplusTable() || isBplusMcTable()) { return table.sliceBy(perBplusJet, jet.globalIndex()); } else { @@ -475,8 +592,12 @@ int getHFCandidatePDG(T const& /*candidate*/) return static_cast(o2::constants::physics::Pdg::kD0); } else if constexpr (isDplusCandidate() || isDplusMcCandidate()) { return static_cast(o2::constants::physics::Pdg::kDPlus); + } else if constexpr (isDstarCandidate() || isDstarMcCandidate()) { + return static_cast(o2::constants::physics::Pdg::kDStar); } else if constexpr (isLcCandidate() || isLcMcCandidate()) { return static_cast(o2::constants::physics::Pdg::kLambdaCPlus); + } else if constexpr (isB0Candidate() || isB0McCandidate()) { + return static_cast(o2::constants::physics::Pdg::kB0); } else if constexpr (isBplusCandidate() || isBplusMcCandidate()) { return static_cast(o2::constants::physics::Pdg::kBPlus); } else { @@ -494,8 +615,12 @@ int getHFTablePDG() return static_cast(o2::constants::physics::Pdg::kD0); } else if constexpr (isDplusTable() || isDplusMcTable()) { return static_cast(o2::constants::physics::Pdg::kDPlus); + } else if constexpr (isDstarTable() || isDstarMcTable()) { + return static_cast(o2::constants::physics::Pdg::kDStar); } else if constexpr (isLcTable() || isLcMcTable()) { return static_cast(o2::constants::physics::Pdg::kLambdaCPlus); + } else if constexpr (isB0Table() || isB0McTable()) { + return static_cast(o2::constants::physics::Pdg::kB0); } else if constexpr (isBplusTable() || isBplusMcTable()) { return static_cast(o2::constants::physics::Pdg::kBPlus); } else { @@ -515,8 +640,12 @@ float getHFCandidatePDGMass(T const& /*candidate*/) return static_cast(o2::constants::physics::MassD0); } else if constexpr (isDplusCandidate() || isDplusMcCandidate()) { return static_cast(o2::constants::physics::MassDPlus); + } else if constexpr (isDstarCandidate() || isDstarMcCandidate()) { + return static_cast(o2::constants::physics::MassDStar); } else if constexpr (isLcCandidate() || isLcMcCandidate()) { return static_cast(o2::constants::physics::MassLambdaCPlus); + } else if constexpr (isB0Candidate() || isB0McCandidate()) { + return static_cast(o2::constants::physics::MassB0); } else if constexpr (isBplusCandidate() || isBplusMcCandidate()) { return static_cast(o2::constants::physics::MassBPlus); } else { @@ -535,8 +664,12 @@ float getHFTablePDGMass() return static_cast(o2::constants::physics::MassD0); } else if constexpr (isDplusTable() || isDplusMcTable()) { return static_cast(o2::constants::physics::MassDPlus); + } else if constexpr (isDstarTable() || isDstarMcTable()) { + return static_cast(o2::constants::physics::MassDStar); } else if constexpr (isLcTable() || isLcMcTable()) { return static_cast(o2::constants::physics::MassLambdaCPlus); + } else if constexpr (isB0Table() || isB0McTable()) { + return static_cast(o2::constants::physics::MassB0); } else if constexpr (isBplusTable() || isBplusMcTable()) { return static_cast(o2::constants::physics::MassBPlus); } else { @@ -696,6 +829,72 @@ void fillDplusCandidateTable(T const& candidate, U& DplusParTable, V& DplusParET } } +template +void fillDstarCandidateTable(T const& candidate, U& DstarParTable, V& DstarParDaughterTable, M& DstarMlTable, N& DstarMCDTable) +{ + + DstarParTable( + candidate.pxProng0(), + candidate.pyProng0(), + candidate.pzProng0(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.signProng1(), + candidate.impactParameter1(), + candidate.impactParameterNormalised1(), + candidate.nSigTpcPi1(), + candidate.nSigTofPi1(), + candidate.nSigTpcTofPi1()); + + DstarParDaughterTable( + candidate.chi2PCACharm(), + candidate.cpaCharm(), + candidate.cpaXYCharm(), + candidate.decayLengthCharm(), + candidate.decayLengthXYCharm(), + candidate.decayLengthNormalisedCharm(), + candidate.decayLengthXYNormalisedCharm(), + candidate.pxProng0Charm(), + candidate.pyProng0Charm(), + candidate.pzProng0Charm(), + candidate.pxProng1Charm(), + candidate.pyProng1Charm(), + candidate.pzProng1Charm(), + candidate.invMassCharm(), + candidate.impactParameter0Charm(), + candidate.impactParameter1Charm(), + candidate.impactParameterNormalised0Charm(), + candidate.impactParameterNormalised1Charm(), + candidate.nSigTpcPi0Charm(), + candidate.nSigTofPi0Charm(), + candidate.nSigTpcTofPi0Charm(), + candidate.nSigTpcKa0Charm(), + candidate.nSigTofKa0Charm(), + candidate.nSigTpcTofKa0Charm(), + candidate.nSigTpcPi1Charm(), + candidate.nSigTofPi1Charm(), + candidate.nSigTpcTofPi1Charm(), + candidate.nSigTpcKa1Charm(), + candidate.nSigTofKa1Charm(), + candidate.nSigTpcTofKa1Charm()); + + std::vector mlScoresVector; + auto mlScoresSpan = candidate.mlScores(); + std::copy(mlScoresSpan.begin(), mlScoresSpan.end(), std::back_inserter(mlScoresVector)); + DstarMlTable(mlScoresVector); + + if constexpr (isMc) { + DstarMCDTable( + candidate.flagMcMatchRec(), + candidate.flagMcMatchRecCharm(), + candidate.originMcRec(), + candidate.ptBhadMotherPart(), + candidate.pdgBhadMotherPart(), + candidate.nTracksDecayed()); + } +} + template void fillLcCandidateTable(T const& candidate, U& LcParTable, V& LcParETable, M& LcMlTable, N& LcMCDTable) { @@ -768,6 +967,91 @@ void fillLcCandidateTable(T const& candidate, U& LcParTable, V& LcParETable, M& } } +// need to update this +template +void fillB0CandidateTable(T const& candidate, U& B0ParTable, V& B0ParETable, M& B0ParD0Table, N& B0MlTable, O& B0MlD0Table, P& B0MCDTable) +{ + + B0ParTable( + candidate.chi2PCA(), + candidate.cpa(), + candidate.cpaXY(), + candidate.decayLength(), + candidate.decayLengthXY(), + candidate.decayLengthNormalised(), + candidate.decayLengthXYNormalised(), + candidate.ptProng0(), + candidate.ptProng1(), + candidate.impactParameter0(), + candidate.impactParameter1(), + candidate.impactParameterNormalised0(), + candidate.impactParameterNormalised1(), + candidate.nSigTpcPiExpPi(), + candidate.nSigTofPiExpPi(), + candidate.nSigTpcTofPiExpPi(), + candidate.nSigTpcKaExpPi(), + candidate.nSigTofKaExpPi(), + candidate.nSigTpcTofKaExpPi(), + candidate.maxNormalisedDeltaIP(), + candidate.impactParameterProduct()); + + B0ParETable( + candidate.xSecondaryVertex(), + candidate.ySecondaryVertex(), + candidate.zSecondaryVertex(), + candidate.errorDecayLength(), + candidate.errorDecayLengthXY(), + candidate.rSecondaryVertex(), + candidate.pProng1(), + candidate.pxProng1(), + candidate.pyProng1(), + candidate.pzProng1(), + candidate.errorImpactParameter1(), + candidate.cosThetaStar(), + candidate.ct()); + + B0ParD0Table( + candidate.chi2PCACharm(), + candidate.nProngsContributorsPVCharm(), + candidate.cpaCharm(), + candidate.cpaXYCharm(), + candidate.decayLengthCharm(), + candidate.decayLengthXYCharm(), + candidate.decayLengthNormalisedCharm(), + candidate.decayLengthXYNormalisedCharm(), + candidate.ptProng0Charm(), + candidate.ptProng1Charm(), + candidate.ptProng2Charm(), + candidate.impactParameter0Charm(), + candidate.impactParameter1Charm(), + candidate.impactParameter2Charm(), + candidate.impactParameterNormalised0Charm(), + candidate.impactParameterNormalised1Charm(), + candidate.impactParameterNormalised2Charm(), + candidate.nSigTpcPi0Charm(), + candidate.nSigTofPi0Charm(), + candidate.nSigTpcTofPi0Charm(), + candidate.nSigTpcKa1Charm(), + candidate.nSigTofKa1Charm(), + candidate.nSigTpcTofKa1Charm(), + candidate.nSigTpcPi2Charm(), + candidate.nSigTofPi2Charm(), + candidate.nSigTpcTofPi2Charm()); + + // B0SelectionFlagTable(candidate.candidateSelFlag()); + + B0MlTable(candidate.mlScoreSig()); + + std::vector mlScoresCharmVector; + auto mlScoresCharmSpan = candidate.mlScoresCharm(); + std::copy(mlScoresCharmSpan.begin(), mlScoresCharmSpan.end(), std::back_inserter(mlScoresCharmVector)); + B0MlD0Table(mlScoresCharmVector); + + if constexpr (isMc) { + B0MCDTable(candidate.flagMcMatchRec(), candidate.originMcRec()); + } +} + // need to update this template void fillBplusCandidateTable(T const& candidate, U& BplusParTable, V& BplusParETable, M& BplusParD0Table, N& BplusMlTable, O& BplusMlD0Table, P& BplusMCDTable) @@ -856,9 +1140,15 @@ void fillHFCandidateTable(T const& candidate, int32_t collisionIndex, U& HFBaseT if constexpr (isDplusCandidate()) { fillDplusCandidateTable(candidate, HFParTable, HFParETable, HFMlTable, HFMCDTable); } + if constexpr (isDstarCandidate()) { + fillDstarCandidateTable(candidate, HFParTable, HFParDaughterTable, HFMlTable, HFMCDTable); + } if constexpr (isLcCandidate()) { fillLcCandidateTable(candidate, HFParTable, HFParETable, HFMlTable, HFMCDTable); } + if constexpr (isB0Candidate()) { + fillB0CandidateTable(candidate, HFParTable, HFParETable, HFParDaughterTable, HFMlTable, HFMlDaughterTable, HFMCDTable); + } if constexpr (isBplusCandidate()) { fillBplusCandidateTable(candidate, HFParTable, HFParETable, HFParDaughterTable, HFMlTable, HFMlDaughterTable, HFMCDTable); } diff --git a/PWGJE/Core/JetMatchingUtilities.h b/PWGJE/Core/JetMatchingUtilities.h index 1c499686638..cf22cad5ff9 100644 --- a/PWGJE/Core/JetMatchingUtilities.h +++ b/PWGJE/Core/JetMatchingUtilities.h @@ -20,27 +20,25 @@ #ifndef PWGJE_CORE_JETMATCHINGUTILITIES_H_ #define PWGJE_CORE_JETMATCHINGUTILITIES_H_ -#include -#include -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" #include "PWGJE/Core/JetCandidateUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include namespace jetmatchingutilities { @@ -742,5 +740,5 @@ void doPairMatching(T const& pairsBase, U const& pairsTag, std::vector -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" - #include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetCandidateUtilities.h" +#include "PWGJE/Core/JetFinder.h" #include "PWGJE/DataModel/Jet.h" -#include "fastjet/contrib/Nsubjettiness.hh" -#include "fastjet/contrib/AxesDefinition.hh" -#include "fastjet/contrib/MeasureDefinition.hh" -#include "fastjet/contrib/SoftDrop.hh" + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include namespace jetsubstructureutilities { diff --git a/PWGJE/Core/JetTaggingUtilities.h b/PWGJE/Core/JetTaggingUtilities.h index ab399bb852d..616929ac1ed 100644 --- a/PWGJE/Core/JetTaggingUtilities.h +++ b/PWGJE/Core/JetTaggingUtilities.h @@ -18,25 +18,31 @@ #ifndef PWGJE_CORE_JETTAGGINGUTILITIES_H_ #define PWGJE_CORE_JETTAGGINGUTILITIES_H_ -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetUtilities.h" + +#include "Common/Core/RecoDecay.h" + +#include +#include + +#include +#include + +#include + #include +#include +#include +#include +#include #include +#include #include #include +#include #include - -#include -#include "CommonConstants/PhysicsConstants.h" - -#include "TF1.h" -#include "Framework/Logger.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGJE/Core/JetUtilities.h" +#include +#include enum JetTaggingSpecies { none = 0, diff --git a/PWGJE/Core/JetUtilities.h b/PWGJE/Core/JetUtilities.h index f1db864ef25..0efaf1fd8f9 100644 --- a/PWGJE/Core/JetUtilities.h +++ b/PWGJE/Core/JetUtilities.h @@ -18,16 +18,19 @@ #ifndef PWGJE_CORE_JETUTILITIES_H_ #define PWGJE_CORE_JETUTILITIES_H_ +#include "Common/Core/RecoDecay.h" + +#include + +#include #include +#include #include -#include +#include #include #include -#include - -#include "Framework/Logger.h" -#include "Common/Core/RecoDecay.h" +#include namespace jetutilities { @@ -73,11 +76,6 @@ std::tuple>, std::vector>> MatchCl throw std::invalid_argument("track collection eta and phi sizes don't match. Check the inputs."); } - // for (std::size_t iTrack = 0; iTrack < nTracks; iTrack++) { - // if (trackEta[iTrack] == 0) - // LOG(warning) << "Track eta is 0!"; - // } - // Build the KD-trees using vectors // We build two trees: // treeBase, which contains the base collection. diff --git a/PWGJE/Core/JetV0Utilities.h b/PWGJE/Core/JetV0Utilities.h index 3d12cd5d0a3..e7495242e01 100644 --- a/PWGJE/Core/JetV0Utilities.h +++ b/PWGJE/Core/JetV0Utilities.h @@ -17,33 +17,20 @@ #ifndef PWGJE_CORE_JETV0UTILITIES_H_ #define PWGJE_CORE_JETV0UTILITIES_H_ -#include -#include -#include -#include +#include "PWGJE/DataModel/Jet.h" + +#include "Common/Core/RecoDecay.h" + +#include #include -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Framework/Logger.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" -#include "PWGHF/DataModel/DerivedTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" +#include + +#include +#include +#include +#include namespace jetv0utilities { diff --git a/PWGJE/Core/MlResponseHfTagging.h b/PWGJE/Core/MlResponseHfTagging.h index 2580c5296df..2b07e1c1c25 100644 --- a/PWGJE/Core/MlResponseHfTagging.h +++ b/PWGJE/Core/MlResponseHfTagging.h @@ -16,18 +16,18 @@ #ifndef PWGJE_CORE_MLRESPONSEHFTAGGING_H_ #define PWGJE_CORE_MLRESPONSEHFTAGGING_H_ -#include -#include -#include - #include "Tools/ML/MlResponse.h" -#include "PWGJE/Core/JetTaggingUtilities.h" -#if __has_include() -#include -#else #include -#endif + +#include + +#include + +#include +#include +#include +#include // Fill the map of available input features // the key is the feature's name (std::string) @@ -329,25 +329,17 @@ class MlResponseHfTagging : public MlResponse class TensorAllocator { protected: -#if !__has_include() Ort::MemoryInfo memInfo; -#endif public: TensorAllocator() -#if !__has_include() : memInfo(Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault)) -#endif { } ~TensorAllocator() = default; template Ort::Value createTensor(std::vector& input, std::vector& inputShape) { -#if __has_include() - return Ort::Experimental::Value::CreateTensor(input.data(), input.size(), inputShape); -#else return Ort::Value::CreateTensor(memInfo, input.data(), input.size(), inputShape.data(), inputShape.size()); -#endif } }; diff --git a/PWGJE/Core/emcalCrossTalkEmulation.cxx b/PWGJE/Core/emcalCrossTalkEmulation.cxx new file mode 100644 index 00000000000..32b08cd13dc --- /dev/null +++ b/PWGJE/Core/emcalCrossTalkEmulation.cxx @@ -0,0 +1,604 @@ +// 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 emcalCrossTalkEmulation.cxx +/// \brief emulation of emcal cross talk for simulations +/// \author Marvin Hemmer , Goethe-University + +#include "emcalCrossTalkEmulation.h" + +#include +#include +#include +#include +#include +#include +#include + +#include // std::find_if +#include +#include // size_t +#include // std::abs +#include // setw +#include // left and right +#include +#include +#include +#include +#include +// #include "Framework/OutputObjHeader.h" + +// #include "Common/CCDB/EventSelectionParams.h" +#include +#include + +#include + +using namespace o2; +using namespace o2::emccrosstalk; +using namespace o2::framework; + +template +auto printArray(std::array const& arr) +{ + std::stringstream ss; + ss << "\n[SM0: " << arr[0]; + for (auto i = 1u; i < N; ++i) { + ss << ", SM" << i << ": " << arr[i]; + } + ss << "]"; + return ss.str(); +} + +template +auto printMatrix(Array2D const& m) +{ + std::stringstream ss; + // Print column headers + ss << std::endl + << std::setw(6) << " " << std::setw(10) << "value1" + << std::setw(10) << "value2" + << std::setw(10) << "value3" + << std::setw(10) << "value4" << std::endl; + + // Print rows with SM labels + for (size_t i = 0; i < m.rows; ++i) { + ss << "SM" << std::left << std::setw(3) << i; // e.g., SM0, SM1... + for (size_t j = 0; j < m.cols; ++j) { + ss << std::right << std::setw(10) << m(i, j); + } + ss << std::endl; + } + + return ss.str(); +} + +void init2DElement(Array2D& matrix, const Array2D& config, const char* name) +{ + int rows = config.rows; + int cols = config.cols; + + if (rows == 0 && cols == 0) { + LOG(info) << name << " has size 0 x 0, so it is disabled!"; + } else if (cols != NNeighbourCases || (rows != 1 && rows != NSM)) { + LOG(error) << name << " must have 4 columns and either 1 or 20 rows!"; + } else { + for (int sm = 0; sm < NSM; ++sm) { + const int row = (rows == 1) ? 0 : sm; + + for (int i = 0; i < cols; ++i) { + matrix[sm][i] = config(row, i); + } + } + } +} + +void init1DElement(std::array& arr, const std::vector& config, const char* name) +{ + size_t confSize = config.size(); + if (confSize == 0) { + LOG(info) << name << " has size 0, so it is disabled!"; + } else if (config.size() != 1 && confSize != NSM) { + LOG(error) << name << " must have either size 1 or 20!"; + } else { + for (int sm = 0; sm < NSM; ++sm) { + const int row = (confSize == 1) ? 0 : sm; + arr[sm] = config[row]; + } + } +} + +o2::framework::AxisSpec axisEnergy = {7000, 0.f, 70.f, "#it{E}_{cell} (GeV)"}; +// For each of the following configurables we will use: +// empty vector == disabled +// vector of size 4 == same for all SM +// vector of vectors with size nSM * 4 == each SM has its own setting +// the 4 values (0-3) correspond to in relative [row,col]: 0: [+-1,0], 1: [+-1,+or-1], 2: [0,+or-1], 3: [+-2, 0 AND +or-1] +// +---+---+-----+---+---+--+--+--+ +// | 3 | 0 | Hit | 0 | 3 | | | | +// +---+---+-----+---+---+--+--+--+ +// | 3 | 1 | 2 | 1 | 3 | | | | +// +---+---+-----+---+---+--+--+--+ + +void EMCCrossTalk::initObjects(const EmcCrossTalkConf& config) +{ + const int run3RunNumber = 223409; + mGeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(run3RunNumber); + if (!mGeometry) { + LOG(error) << "Failure accessing mGeometry"; + } + + // first set the simple run time variables + mTCardCorrClusEnerConserv = config.conserveEnergy.value; + mRandomizeTCard = config.randomizeTCardInducedEnergy.value; + mTCardCorrMinAmp = config.inducedTCardMinimumCellEnergy.value; + mTCardCorrMinInduced = config.inducedTCardMinimum.value; + mTCardCorrMaxInducedELeak = config.inducedTCardMaximumELeak.value; + mTCardCorrMaxInduced = config.inducedTCardMaximum.value; + + // 2nd define the NSM x NNeighbourCases matrices + mTCardCorrInduceEner = Array2D(std::vector(NSM * 4, 0.f), NSM, 4); + mTCardCorrInduceEnerFrac = Array2D(std::vector(NSM * 4, 0.f), NSM, 4); + mTCardCorrInduceEnerFracP1 = Array2D(std::vector(NSM * 4, 0.f), NSM, 4); + mTCardCorrInduceEnerFracWidth = Array2D(std::vector(NSM * 4, 0.f), NSM, 4); + + // now properly init the NSM x NNeighbourCases matrices + // ------------------------------------------------------------------------ + // mTCardCorrInduceEner + init2DElement(mTCardCorrInduceEner, config.inducedEnergyLossConstant.value, "inducedEnergyLossConstant"); + + // mTCardCorrInduceEnerFrac + init2DElement(mTCardCorrInduceEnerFrac, config.inducedEnergyLossFraction.value, "inducedEnergyLossFraction"); + + // mTCardCorrInduceEnerFracP1 + init2DElement(mTCardCorrInduceEnerFracP1, config.inducedEnergyLossFractionP1.value, "inducedEnergyLossFractionP1"); + + // mTCardCorrInduceEnerFracWidth + init2DElement(mTCardCorrInduceEnerFracWidth, config.inducedEnergyLossFractionWidth.value, "inducedEnergyLossFractionWidth"); + // ------------------------------------------------------------------------ + + init1DElement(mTCardCorrInduceEnerFracMax, config.inducedEnergyLossMaximumFraction.value, "inducedEnergyLossMaximumFraction"); + init1DElement(mTCardCorrInduceEnerFracMin, config.inducedEnergyLossMinimumFraction.value, "inducedEnergyLossMinimumFraction"); + init1DElement(mTCardCorrInduceEnerFracMinCentralEta, config.inducedEnergyLossMinimumFractionCentralEta.value, "inducedEnergyLossMinimumFractionCentralEta"); + init1DElement(mTCardCorrInduceEnerProb, config.inducedEnergyLossProbability.value, "inducedEnergyLossProbability"); + + resetArrays(); + + // Print the full matrices and vectors that will be used: + if (config.printConfiguration.value) { + LOGF(info, "inducedEnergyLossConstant: %s", printMatrix((mTCardCorrInduceEner))); + LOGF(info, "inducedEnergyLossFraction: %s", printMatrix((mTCardCorrInduceEnerFrac))); + LOGF(info, "inducedEnergyLossFractionP1: %s", printMatrix((mTCardCorrInduceEnerFracP1))); + LOGF(info, "inducedEnergyLossFractionWidth: %s", printMatrix((mTCardCorrInduceEnerFracWidth))); + LOGF(info, "inducedEnergyLossMaximumFraction: %s", printArray(mTCardCorrInduceEnerFracMax).c_str()); + LOGF(info, "inducedEnergyLossMinimumFraction: %s", printArray(mTCardCorrInduceEnerFracMin).c_str()); + LOGF(info, "inducedEnergyLossMinimumFractionCentralEta: %s", printArray(mTCardCorrInduceEnerFracMinCentralEta).c_str()); + LOGF(info, "inducedEnergyLossProbability: %s", printArray(mTCardCorrInduceEnerProb).c_str()); + } +} + +void EMCCrossTalk::resetArrays() +{ + for (size_t j = 0; j < NCells; j++) { + mTCardCorrCellsEner[j] = 0.; + mTCardCorrCellsNew[j] = false; + } + + mCellsTmp.clear(); +} + +void EMCCrossTalk::setCells(std::vector& cells, std::vector& cellLabels) +{ + mCells = &cells; + mCellsTmp = cells; // a copy since we will need one vector with the changed energies and one with the original ones + mCellLabels = &cellLabels; +} + +void EMCCrossTalk::calculateInducedEnergyInTCardCell(int absId, int absIdRef, int iSM, float ampRef, int cellCase) +{ + // Check that the cell exists + if (absId < 0) { + return; + } + + // Get the fraction + float frac = mTCardCorrInduceEnerFrac[iSM][cellCase] + ampRef * mTCardCorrInduceEnerFracP1[iSM][cellCase]; + + // Use an absolute minimum and maximum fraction if calculated one is out of range + if (frac < mTCardCorrInduceEnerFracMin[iSM]) { + frac = mTCardCorrInduceEnerFracMin[iSM]; + } else if (frac > mTCardCorrInduceEnerFracMax[iSM]) { + frac = mTCardCorrInduceEnerFracMax[iSM]; + } + + // If active, use different absolute minimum fraction for central eta, exclude DCal 2/3 SM + if (mTCardCorrInduceEnerFracMinCentralEta[iSM] > 0 && (iSM < FirstDCal23SM || iSM > LastDCal23SM)) { + // Odd SM + int ietaMin = 32; + int ietaMax = 47; + + // Even SM + if (iSM % 2) { + ietaMin = 0; + ietaMax = 15; + } + + // First get the SM, col-row of this tower + // int imod = -1, iphi =-1, ieta=-1,iTower = -1, iIphi = -1, iIeta = -1; + auto [iSM, iMod, iIphi, iIeta] = mGeometry->GetCellIndex(absId); + auto [iphi, ieta] = mGeometry->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta); + + if (ieta >= ietaMin && ieta <= ietaMax) { + if (frac < mTCardCorrInduceEnerFracMinCentralEta[iSM]) + frac = mTCardCorrInduceEnerFracMinCentralEta[iSM]; + } + } // central eta + + LOGF(debug, "\t fraction %2.3f", frac); + + // Randomize the induced fraction, if requested + if (mRandomizeTCard) { + frac = mRandom.Gaus(frac, mTCardCorrInduceEnerFracWidth[iSM][cellCase]); + LOGF(debug, "\t randomized fraction %2.3f", frac); + } + + // If fraction too small or negative, do nothing else + if (frac < Epsilon) { + return; + } + + // Calculate induced energy + float inducedE = mTCardCorrInduceEner[iSM][cellCase] + ampRef * frac; + + // Check if we induce too much energy, in such case use a constant value + if (mTCardCorrMaxInduced < inducedE) + inducedE = mTCardCorrMaxInduced; + + LOGF(debug, "\t induced E %2.3f", inducedE); + + // Try to find the cell that will get energy induced + float amp = 0.f; + auto itCell = std::find_if((*mCells).begin(), (*mCells).end(), [absId](const o2::emcal::Cell& cell) { + return cell.getTower() == absId; + }); + + if (itCell != (*mCells).end()) { + // We found a cell, so let's get the amplitude of that cell + amp = itCell->getAmplitude(); + } else { + amp = 0.f; // this is a new cell, so the base amp is 0.f + } + + // Check that the induced+amp is large enough to avoid extra linearity effects + // typically of the order of the clusterization cell energy cut + // if inducedTCardMaximumELeak was set to a positive value, then induce the energy as long as its smaller than that value + if ((amp + inducedE) > mTCardCorrMinInduced || inducedE < mTCardCorrMaxInducedELeak) { + mTCardCorrCellsEner[absId] += inducedE; + + // If original energy of cell was null, create new one + if (amp <= Epsilon) { + mTCardCorrCellsNew[absId] = true; + } + } else { + return; + } + + LOGF(debug, "Cell %d is with amplitude %2.3f GeV is inducing %1.3f GeV energy to cell %d which already has %2.3f GeV energy with fraction %1.5f", absIdRef, ampRef, inducedE, absId, amp, frac); + + // Subtract the added energy to main cell, if energy conservation is requested + if (mTCardCorrClusEnerConserv) { + mTCardCorrCellsEner[absIdRef] -= inducedE; + } +} + +void EMCCrossTalk::makeCellTCardCorrelation() +{ + int id = -1; + float amp = -1; + + // Loop on all cells with signal + for (const auto& cell : (*mCells)) { + id = cell.getTower(); + amp = cell.getAmplitude(); + + if (amp <= mTCardCorrMinAmp) { + continue; + } + + // First get the SM, col-row of this tower + auto [iSM, iMod, iIphi, iIeta] = mGeometry->GetCellIndex(id); + auto [iphi, ieta] = mGeometry->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta); + + // Determine randomly if we want to create a correlation for this cell, + // depending the SM number of the cell + if (mTCardCorrInduceEnerProb[iSM] < 1) { + if (mRandom.Uniform(0, 1) > mTCardCorrInduceEnerProb[iSM]) { + continue; + } + } + + LOGF(debug, "Reference cell absId %d, iEta %d, iPhi %d, amp %2.3f", id, ieta, iphi, amp); + + // Get the absId of the cells in the cross and same T-Card + int absIDup = -1; + int absIDdo = -1; + int absIDlr = -1; + int absIDuplr = -1; + int absIDdolr = -1; + + int absIDup2 = -1; + int absIDup2lr = -1; + int absIDdo2 = -1; + int absIDdo2lr = -1; + + // Only 2 columns in the T-Card, +1 for even and -1 for odd with respect reference cell + // Sine we only have full T-Cards, we do not need to make any edge case checks + // There is always either a column (eta direction) below or above + int colShift = +1; + if (ieta % 2) { + colShift = -1; + } + + absIDlr = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi, ieta + colShift); + + // Check if up / down cells from reference cell are not out of SM + // First check if there is space one above + if (iphi < emcal::EMCAL_ROWS - 1) { + absIDup = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi + 1, ieta); + absIDuplr = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi + 1, ieta + colShift); + } + + // 2nd check if there is space one below + if (iphi > 0) { + absIDdo = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi - 1, ieta); + absIDdolr = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi - 1, ieta + colShift); + } + + // 3rd check if there is space two above + if (iphi < emcal::EMCAL_ROWS - 2) { + absIDup2 = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi + 2, ieta); + absIDup2lr = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi + 2, ieta + colShift); + } + + // 4th check if there is space two below + if (iphi > 1) { + absIDdo2 = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi - 2, ieta); + absIDdo2lr = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphi - 2, ieta + colShift); + } + + // Check if those cells are in the same T-Card + int tCard = iphi / 8; + if (tCard != (iphi + 1) / 8) { + absIDup = -1; + absIDuplr = -1; + } + if (tCard != (iphi - 1) / 8) { + absIDdo = -1; + absIDdolr = -1; + } + if (tCard != (iphi + 2) / 8) { + absIDup2 = -1; + absIDup2lr = -1; + } + if (tCard != (iphi - 2) / 8) { + absIDdo2 = -1; + absIDdo2lr = -1; + } + + // Calculate induced energy to T-Card cells + // first check if for the given cell case we actually do induce some energy + if (((std::abs(mTCardCorrInduceEner[iSM][0]) > Epsilon) || (std::abs(mTCardCorrInduceEnerFrac[iSM][0]) > Epsilon)) && (std::abs(mTCardCorrInduceEnerFracP1[iSM][0]) > Epsilon) && (std::abs(mTCardCorrInduceEnerFracWidth[iSM][0]) > Epsilon)) { + if (absIDup >= 0) { + LOGF(debug, "cell up %d:", absIDup); + calculateInducedEnergyInTCardCell(absIDup, id, iSM, amp, 0); + } + if (absIDdo >= 0) { + LOGF(debug, "cell down %d:", absIDdo); + calculateInducedEnergyInTCardCell(absIDdo, id, iSM, amp, 0); + } + } + if (((std::abs(mTCardCorrInduceEner[iSM][1]) > Epsilon) || (std::abs(mTCardCorrInduceEnerFrac[iSM][1]) > Epsilon)) && (std::abs(mTCardCorrInduceEnerFracP1[iSM][1]) > Epsilon) && (std::abs(mTCardCorrInduceEnerFracWidth[iSM][1]) > Epsilon)) { + if (absIDuplr >= 0) { + LOGF(debug, "cell up left-right %d:", absIDuplr); + calculateInducedEnergyInTCardCell(absIDuplr, id, iSM, amp, 1); + } + if (absIDdolr >= 0) { + LOGF(debug, "cell down left-right %d:", absIDdolr); + calculateInducedEnergyInTCardCell(absIDdolr, id, iSM, amp, 1); + } + } + if (((std::abs(mTCardCorrInduceEner[iSM][2]) > Epsilon) || (std::abs(mTCardCorrInduceEnerFrac[iSM][2]) > Epsilon)) && (std::abs(mTCardCorrInduceEnerFracP1[iSM][2]) > Epsilon) && (std::abs(mTCardCorrInduceEnerFracWidth[iSM][2]) > Epsilon)) { + if (absIDlr >= 0) { + LOGF(debug, "cell left-right %d:", absIDlr); + calculateInducedEnergyInTCardCell(absIDlr, id, iSM, amp, 2); + } + } + if (((std::abs(mTCardCorrInduceEner[iSM][3]) > Epsilon) || (std::abs(mTCardCorrInduceEnerFrac[iSM][3]) > Epsilon)) && (std::abs(mTCardCorrInduceEnerFracP1[iSM][3]) > Epsilon) && (std::abs(mTCardCorrInduceEnerFracWidth[iSM][3]) > Epsilon)) { + if (absIDup2 >= 0) { + LOGF(debug, "cell up 2nd row %d:", absIDup2); + calculateInducedEnergyInTCardCell(absIDup2, id, iSM, amp, 3); + } + if (absIDdo2 >= 0) { + LOGF(debug, "cell down 2nd row %d:", absIDdo2); + calculateInducedEnergyInTCardCell(absIDdo2, id, iSM, amp, 3); + } + if (absIDup2lr >= 0) { + LOGF(debug, "cell up left-right 2nd row %d:", absIDup2lr); + calculateInducedEnergyInTCardCell(absIDup2lr, id, iSM, amp, 3); + } + if (absIDdo2lr >= 0) { + LOGF(debug, "cell down left-right 2nd row %d:", absIDdo2lr); + calculateInducedEnergyInTCardCell(absIDdo2lr, id, iSM, amp, 3); + } + } + } // cell loop +} + +void EMCCrossTalk::addInducedEnergiesToExistingCells() +{ + // Add the induced energy to the cells and copy them into a new temporal container + // used in AddInducedEnergiesToNewCells() to refill the default cells list fCaloCells + // Create the data member only once. Done here, not sure where to do this properly in the framework. + + for (auto& cell : mCellsTmp) { // o2-linter: disable=const-ref-in-for-loop (we are changing a value here) + float amp = cell.getAmplitude() + mTCardCorrCellsEner[cell.getTower()]; + // Set new amplitude in new temporal container + cell.setAmplitude(amp); + } +} + +void EMCCrossTalk::addInducedEnergiesToNewCells() +{ + // count how many new cells + size_t nCells = (*mCells).size(); + int nCellsNew = 0; + for (size_t j = 0; j < NCells; j++) { + // Newly created? + if (!mTCardCorrCellsNew[j]) { + continue; + } + // Accept only if at least 10 MeV + if (mTCardCorrCellsEner[j] < MinCellEnergy) { + continue; + } + nCellsNew++; + } + + // reserve more space for new cell entries in original cells and celllabels + (*mCells).reserve(nCells + nCellsNew); + (*mCellLabels).reserve(nCells + nCellsNew); + + // change the amplitude of the original cells using + for (size_t iCell = 0; iCell < mCellsTmp.size(); ++iCell) { + (*mCells)[iCell].setAmplitude(mCellsTmp[iCell].getAmplitude()); + } + + // Add the new cells + int absId = -1; + float amp = -1; + float time = 0; + std::vector mclabel; + + for (size_t j = 0; j < NCells; j++) { + // Newly created? + if (!mTCardCorrCellsNew[j]) { + continue; + } + + // Accept only if at least 10 MeV + if (mTCardCorrCellsEner[j] < MinCellEnergy) { + continue; + } + + // Add new cell + absId = j; + amp = mTCardCorrCellsEner[j]; + time = 615.e-9f; + mclabel = {-1}; + + // Assign as MC label the label of the neighboring cell with highest energy + // within the same T-Card. Follow same approach for time. + // Simplest assumption, not fully correct. + // Still assign 0 as fraction of energy. + + // First get the iphi and ieta of this tower + auto [iSM, iMod, iIphi, iIeta] = mGeometry->GetCellIndex(absId); + auto [iphi, ieta] = mGeometry->GetCellPhiEtaIndexInSModule(iSM, iMod, iIphi, iIeta); + + LOGF(debug, "Trying to add cell %d \t ieta = %d\t iphi = %d\t amplitude = %1.3f", absId, ieta, iphi, amp); + + // Loop on the nearest cells around, check the highest energy one, + // and assign its MC label and the time + float ampMax = 0.f; + for (int ietai = ieta - 1; ietai <= ieta + 1; ++ietai) { + for (int iphii = iphi - 1; iphii <= iphi + 1; ++iphii) { + + // Avoid same cell + if (iphii == iphi && ietai == ieta) { + continue; + } + + // Avoid cells out of SM + if (ietai < 0 || ietai >= NColumns[iSM] || iphii < 0 || iphii >= NRows[iSM]) { + continue; + } + + int absIDi = mGeometry->GetAbsCellIdFromCellIndexes(iSM, iphii, ietai); + // Try to find the cell that will get energy induced + float ampi = 0.f; + size_t indexInCells = 0; + auto itCell = std::find_if((*mCells).begin(), (*mCells).begin() + nCells, [absIDi](const o2::emcal::Cell& cell) { + return cell.getTower() == absIDi; + }); + + if (itCell != (*mCells).begin() + nCells) { + // We found a cell, so let's get the amplitude of that cell + ampi = itCell->getAmplitude(); + if (ampi <= ampMax) { + continue; // early continue if the new amplitude is not the biggest one + } + indexInCells = std::distance((*mCells).begin(), itCell); + LOGF(debug, "Found cell with index %d", indexInCells); + } else { + continue; + } + + // Remove cells with no energy + if (ampi <= MinCellEnergy) { + continue; + } + + // Only same TCard + if (!std::get<0>(mGeometry->areAbsIDsFromSameTCard(absId, absIDi))) { + continue; + } + + std::vector mclabeli = {(*mCellLabels)[indexInCells].GetLeadingMCLabel()}; + float timei = (*mCells)[indexInCells].getTimeStamp(); + + ampMax = ampi; + mclabel = mclabeli; + time = timei; + } // loop phi + } // loop eta + // End Assign MC label + LOGF(debug, "Final ampMax %1.2f\n", ampMax); + LOGF(debug, "--- End : Added cell ID %d, ieta %d, iphi %d, E %1.3f, time %1.3e, mc label %d\n", absId, ieta, iphi, amp, time, mclabel[0]); + + // Add the new cell + (*mCells).emplace_back(absId, amp, time, o2::emcal::intToChannelType(1)); + (*mCellLabels).emplace_back(std::vector{mclabel[0]}, std::vector{0.f}); + } // loop over cells +} + +bool EMCCrossTalk::run() +{ + // START PROCESSING + // Test if cells present + if ((*mCells).size() == 0) { + LOGF(error, "No EMCAL cells found, exiting EMCCrossTalk::run()!"); + return false; + } + + // CELL CROSSTALK EMULATION + // Compute the induced cell energies by T-Card correlation emulation, ONLY MC + makeCellTCardCorrelation(); + + // Add to existing cells the found induced energies in MakeCellTCardCorrelation() if new signal is larger than 10 MeV. + addInducedEnergiesToExistingCells(); + + // Add new cells with found induced energies in MakeCellTCardCorrelation() if new signal is larger than 10 MeV. + addInducedEnergiesToNewCells(); + + resetArrays(); + + return true; +} diff --git a/PWGJE/Core/emcalCrossTalkEmulation.h b/PWGJE/Core/emcalCrossTalkEmulation.h new file mode 100644 index 00000000000..fb84ec7c1ad --- /dev/null +++ b/PWGJE/Core/emcalCrossTalkEmulation.h @@ -0,0 +1,213 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// \file emcalCrossTalkEmulation.h +/// \brief emulation of emcal cross talk for simulations +/// \author Marvin Hemmer , Goethe-University + +#ifndef PWGJE_CORE_EMCALCROSSTALKEMULATION_H_ +#define PWGJE_CORE_EMCALCROSSTALKEMULATION_H_ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +namespace o2::emccrosstalk +{ +// cell types for enegery induction +enum InductionCellType { + UpDown = 0, + UpDownLeftRight, + LeftRight, + Up2Down2, + NInductionCellType +}; + +// default values for cross talk emulation +// small value to use for comarison equal to 0, std::abs(x) > epsilon +static constexpr float Epsilon = 1e-6f; + +// default for inducedEnergyLossConstant +// static constexpr float DefaultIELC[1][4] = {{0.02f, 0.02f, 0.02f, 0.f}}; // default from https://github.com/alisw/AliPhysics/blob/master/PWG/EMCAL/config/AliEmcalCorrectionConfiguration.yaml (but is deactivated per default) +static constexpr float DefaultIELC[1][4] = {{0.f, 0.f, 0.f, 0.f}}; // default from pp 13 TeV + +// default for inducedEnergyLossFraction, default from https://github.com/alisw/AliPhysics/blob/master/PWG/EMCAL/config/AliEmcalCorrectionConfiguration.yaml same as in https://cds.cern.ch/record/2910556/ +static constexpr float DefaultIELF[20][4] = {{1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {1.20e-02, 1.20e-02, 1.20e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {1.20e-02, 1.20e-02, 1.20e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {1.20e-02, 1.20e-02, 1.20e-02, 0.f}, + {0.80e-02, 0.80e-02, 0.80e-02, 0.f}, + {0.80e-02, 0.80e-02, 0.80e-02, 0.f}, + {1.20e-02, 1.20e-02, 1.20e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {0.80e-02, 0.80e-02, 0.80e-02, 0.f}, + {0.80e-02, 0.80e-02, 0.80e-02, 0.f}, + {1.15e-02, 1.15e-02, 1.15e-02, 0.f}, + {0.80e-02, 0.80e-02, 0.80e-02, 0.f}, + {0.80e-02, 0.80e-02, 0.80e-02, 0.f}, + {0.80e-02, 0.80e-02, 0.80e-02, 0.f}}; + +// default for inducedEnergyLossFractionP1, default from https://github.com/alisw/AliPhysics/blob/master/PWG/EMCAL/config/AliEmcalCorrectionConfiguration.yaml same as in https://cds.cern.ch/record/2910556/ +static constexpr float DefaultIELFP1[1][4] = {{-1.1e-03, -1.1e-03, -1.1e-03, 0.f}}; + +// default for inducedEnergyLossFractionWidth, default from https://github.com/alisw/AliPhysics/blob/master/PWG/EMCAL/config/AliEmcalCorrectionConfiguration.yaml same as in https://cds.cern.ch/record/2910556/ +static constexpr float DefaultIELFWidth[1][4] = {{5.0e-03, 5.0e-03, 5.0e-03, 0.f}}; + +// default for inducedEnergyLossMinimumFractionCentralEta, IF someone wants to try it. This is purely to document those test numbers from AliEmcalCorrectionConfiguration.yaml! Default is to not use this! Values from default from https://github.com/alisw/AliPhysics/blob/master/PWG/EMCAL/config/AliEmcalCorrectionConfiguration.yaml +// std::vector DefaultIELMFCE = {6.8e-3, 7.5e-3, 6.8e-3, 9.0e-3, 6.8e-3, 6.8e-3, 6.8e-3, 9.0e-3, 5.2e-3, 5.2e-3, 7.5e-3, 6.8e-3, 6.8e-3, 6.8e-3, 5.2e-3, 5.2e-3, 6.8e-3, 5.2e-3, 5.2e-3, 5.2e-3}; + +struct EmcCrossTalkConf : o2::framework::ConfigurableGroup { + std::string prefix = "emccrosstalk"; + o2::framework::Configurable enableCrossTalk{"enableCrossTalk", false, "Flag to enable cross talk emulation. This should only ever be used for MC!"}; + o2::framework::Configurable createHistograms{"createHistograms", false, "Flag to enable QA histograms."}; + o2::framework::Configurable printConfiguration{"printConfiguration", true, "Flag to print the configuration after initialization."}; + o2::framework::Configurable conserveEnergy{"conserveEnergy", true, "Flag to enable cluster energy conservation."}; + o2::framework::Configurable randomizeTCardInducedEnergy{"randomizeTCardInducedEnergy", true, "Flag to randomize the energy fraction induced by the TCard."}; + o2::framework::Configurable inducedTCardMinimumCellEnergy{"inducedTCardMinimumCellEnergy", 0.01f, "Minimum cell energy in GeV induced by the TCard."}; + o2::framework::Configurable inducedTCardMaximum{"inducedTCardMaximum", 100.f, "Maximum energy in GeV induced by the TCard."}; + o2::framework::Configurable inducedTCardMinimum{"inducedTCardMinimum", 0.1f, "Minimum energy in GeV induced by the TCard + cell energy, IMPORTANT use the same value as the clusterization cell E threshold or not too far from it."}; + o2::framework::Configurable inducedTCardMaximumELeak{"inducedTCardMaximumELeak", 0.f, "Maximum energy in GeV that is going to be leaked independently of what is set with inducedTCardMinimum."}; + // For each of the following Array2D configurables we will use: + // empty vector == disabled + // vector of size 4 == same for all SM + // vector of vectors with size nSM * 4 == each SM has its own setting + // the 4 values (0-3) correspond to in relative [row,col]: 0: [+-1,0], 1: [+-1,+or-1], 2: [0,+or-1], 3: [+-2, 0 AND +or-1] + // +---+---+-----+---+---+--+--+--+ + // | 3 | 0 | Hit | 0 | 3 | | | | + // +---+---+-----+---+---+--+--+--+ + // | 3 | 1 | 2 | 1 | 3 | | | | + // +---+---+-----+---+---+--+--+--+ + // For the std::vector it is similar, empty vector means not used, single value means one value for all SM and 20 values means specifiyng a value for all SM + o2::framework::Configurable> inducedEnergyLossConstant{"inducedEnergyLossConstant", {DefaultIELC[0], 1, 4}, "Constant energy lost by max energy cell in one of T-Card cells. Empty vector == disabled, size 4 vector == enabled. For information on the exact formatting please check the header file."}; + o2::framework::Configurable> inducedEnergyLossFraction{"inducedEnergyLossFraction", {DefaultIELF[0], 20, 4}, "Fraction of energy lost by max energy cell in one of T-Card cells."}; + o2::framework::Configurable> inducedEnergyLossFractionP1{"inducedEnergyLossFractionP1", {DefaultIELFP1[0], 1, 4}, "Slope parameter of fraction of energy lost by max energy cell in one of T-Card cells."}; + o2::framework::Configurable> inducedEnergyLossFractionWidth{"inducedEnergyLossFractionWidth", {DefaultIELFWidth[0], 1, 4}, "Fraction of energy lost by max energy cell in one of T-Card cells, width of random gaussian."}; + // default from https://github.com/alisw/AliPhysics/blob/master/PWG/EMCAL/config/AliEmcalCorrectionConfiguration.yaml : + // o2::framework::Configurable> inducedEnergyLossMinimumFraction{"inducedEnergyLossMinimumFraction", {3.5e-3f, 5.0e-3f, 4.5e-3f, 6.0e-3f, 3.5e-3f, 3.5e-3f, 3.5e-3f, 6.0e-3f, 3.5e-3f, 3.5e-3f, 5.0e-3f, 5.0e-3f, 3.5e-3f, 3.5e-3f, 3.5e-3f, 3.5e-3f, 3.5e-3f, 3.5e-3f, 3.5e-3f, 3.5e-3f}, "Minimum induced energy fraction when linear dependency is set."}; + // value from https://cds.cern.ch/record/2910556/: + o2::framework::Configurable> inducedEnergyLossMinimumFraction{"inducedEnergyLossMinimumFraction", {2.35e-3f, 2.5e-3f, 2.35e-3f, 3.0e-3f, 2.35e-3f, 2.35e-3f, 2.35e-3f, 3.0e-3f, 1.75e-3f, 1.75e-3f, 2.5e-3f, 2.35e-3f, 2.35e-3f, 2.35e-3f, 1.75e-3f, 1.75e-3f, 2.35e-3f, 1.75e-3f, 1.75e-3f, 1.75e-3f}, "Minimum induced energy fraction when linear dependency is set."}; + + o2::framework::Configurable> inducedEnergyLossMinimumFractionCentralEta{"inducedEnergyLossMinimumFractionCentralEta", {}, "Minimum induced energy fraction when linear dependency is set. For |eta| < 0.22, if empty no difference in eta. NOT TUNED for TESTING!"}; + + // default from https://github.com/alisw/AliPhysics/blob/master/PWG/EMCAL/config/AliEmcalCorrectionConfiguration.yaml : + // o2::framework::Configurable> inducedEnergyLossMaximumFraction{"inducedEnergyLossMaximumFraction", {0.018f}, "Maximum induced energy fraction when linear dependency is set."}; + // value from https://cds.cern.ch/record/2910556/: + o2::framework::Configurable> inducedEnergyLossMaximumFraction{"inducedEnergyLossMaximumFraction", {0.016f, 0.016f, 0.016f, 0.018f, 0.016f, 0.016f, 0.016f, 0.018f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f, 0.016f}, "Maximum induced energy fraction when linear dependency is set."}; + o2::framework::Configurable> inducedEnergyLossProbability{"inducedEnergyLossProbability", {1.0f}, "Fraction of times max cell energy correlates with cross cells."}; +}; + +static constexpr int NSM = 20; // Number of Supermodules (12 for EMCal + 8 for DCal) +static constexpr int NCells = 17664; // Number of cells in the EMCal +static constexpr int NNeighbourCases = 4; // 0-same row, diff col, 1-up/down cells left/right col 2-left/righ col, and 2nd row cells +static constexpr int FirstDCal23SM = 12; // index of the first 2/3 DCal SM +static constexpr int LastDCal23SM = 17; // index of the last 2/3 DCal SM +static constexpr float MinCellEnergy = 0.01f; // Minimum energy a new cell needs to be added + +static constexpr int NColumns[NSM] = {48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 32, 32, 32, 32, 32, 32, 48, 48}; +static constexpr int NRows[NSM] = {24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 8, 8, 24, 24, 24, 24, 24, 24, 8, 8}; + +// these labels are for later once labeledArrays work on hyperloop. Currently they sadly only allow fixed size not variable size. +// static const std::vector labelsSM{"SM0/all", "SM1", "SM2", "SM3", "SM4", "SM5", "SM6", "SM7", "SM8", "SM9", "SM10", "SM11", "SM12", "SM13", "SM14", "SM15", "SM16", "SM17", "SM18", "SM19"}; +// static const std::vector labelsCells = {"Up&Down", "Up&Down x Left|Right", "Left|Right", "2Up&Down + 2Up&Down xLeft|Right"}; + +class EMCCrossTalk +{ + + public: + ~EMCCrossTalk() + { + LOG(info) << "Destroying EMCCrossTalk"; + } + + /// \brief Basic init function. + /// \param config configurable group containing the config for the cross talk emulation + void initObjects(const EmcCrossTalkConf& config); + + /// \brief Reset arrays containing information for all possible cells. + /// \details mTCardCorrCellsEner and mTCardCorrCellsNew + void resetArrays(); + + /// \brief Sets the pointer the current vector of cells. + /// \param cells pointer to emcal cells of the current event + /// \param cellLabels pointer to emcal cell labels of the current event + void setCells(std::vector& cells, std::vector& cellLabels); + + /// \brief Main function to call later to perform the full cross talk emulation + /// \return flag if everything went well or not + bool run(); + + /// \brief Recover each cell amplitude and absId and induce energy in cells in cross of the same T-Card + void makeCellTCardCorrelation(); + + /// \brief Add to existing cells the found induced energies in makeCellTCardCorrelation() if new signal is larger than 10 MeV. + /// \details Need to destroy/create the default cells list and do a copy from the old to the new via a temporal array fAODCellsTmp. Not too nice or fast, but it works. + void addInducedEnergiesToExistingCells(); + + /// \brief Add new cells with found induced energies in makeCellTCardCorrelation() if new signal is larger than 10 MeV. + void addInducedEnergiesToNewCells(); + + /// \brief Calculate the induced energy in a cell belonging to thesame T-Card as the reference cell. Used in makeCellTCardCorrelation() + /// \param absId Id number of cell in same T-Card as reference cell + /// \param absIdRef Id number of reference cell + /// \param iSM Supermodule number of cell + /// \param ampRef Amplitude of the reference cell + /// \param cellCase Type of cell with respect reference cell 0: up or down, 1: up or down on the diagonal, 2: left or right, 3: 2nd row up/down both left/right + void calculateInducedEnergyInTCardCell(int absId, int absIdRef, int iSM, float ampRef, int cellCase); + + private: + // T-Card correlation emulation, do on MC + bool mTCardCorrClusEnerConserv; // When making correlation, subtract from the reference cell the induced energy on the neighbour cells + std::array mTCardCorrCellsEner; // Array with induced cell energy in T-Card neighbour cells + std::array mTCardCorrCellsNew; // Array with induced cell energy in T-Card neighbour cells, that before had no signal + + o2::framework::Array2D mTCardCorrInduceEner; // Induced energy loss gauss constant on 0-same row, diff col, 1-up/down cells left/right col 2-left/righ col, and 2nd row cells, param 0 + o2::framework::Array2D mTCardCorrInduceEnerFrac; // Induced energy loss gauss fraction param0 on 0-same row, diff col, 1-up/down cells left/right col 2-left/righ col, and 2nd row cells, param 0 + o2::framework::Array2D mTCardCorrInduceEnerFracP1; // Induced energy loss gauss fraction param1 on 0-same row, diff col, 1-up/down cells left/right col 2-left/righ col, and 2nd row cells, param1 + o2::framework::Array2D mTCardCorrInduceEnerFracWidth; // Induced energy loss gauss witdth on 0-same row, diff col, 1-up/down cells left/right col 2-left/righ col, and 2nd row cells + std::array mTCardCorrInduceEnerFracMax; // In case fTCardCorrInduceEnerFracP1 is non null, restrict the maximum fraction of induced energy per SM + std::array mTCardCorrInduceEnerFracMin; // In case fTCardCorrInduceEnerFracP1 is non null, restrict the minimum fraction of induced energy per SM + std::array mTCardCorrInduceEnerFracMinCentralEta; // In case fTCardCorrInduceEnerFracP1 is non null, restrict the minimum fraction of induced energy per SM. Different at central |eta| < 0.22 + std::array mTCardCorrInduceEnerProb; // Probability to induce energy loss per SM + + TRandom3 mRandom; // Random generator + bool mRandomizeTCard; // Use random induced energy + + float mTCardCorrMinAmp; // Minimum cell energy to induce signal on adjacent cells + float mTCardCorrMinInduced; // Minimum induced energy signal on adjacent cells, sum of induced plus original energy, use same as cell energy clusterization cut + float mTCardCorrMaxInducedELeak; // Maximum value of induced energy signal that is always leaked, ~5-10 MeV + float mTCardCorrMaxInduced; // Maximum induced energy signal on adjacent cells + + std::vector* mCells = nullptr; // Pointer to the original cells of the current event + std::vector* mCellLabels = nullptr; // Pointer to the original cell labels of the current event + std::vector mCellsTmp; // Temporal vector of cells (copy) + + o2::emcal::Geometry* mGeometry; // EMCal geometry +}; + +} // namespace o2::emccrosstalk + +#endif // PWGJE_CORE_EMCALCROSSTALKEMULATION_H_ diff --git a/PWGJE/Core/utilsBcSelEMC.h b/PWGJE/Core/utilsBcSelEMC.h index c613bba70e2..603e5190655 100644 --- a/PWGJE/Core/utilsBcSelEMC.h +++ b/PWGJE/Core/utilsBcSelEMC.h @@ -16,15 +16,21 @@ #ifndef PWGJE_CORE_UTILSBCSELEMC_H_ #define PWGJE_CORE_UTILSBCSELEMC_H_ -#include // std::shared_ptr -#include // std::string +#include "Common/CCDB/EventSelectionParams.h" -#include "Framework/Configurable.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/HistogramSpec.h" -#include "Framework/OutputObjHeader.h" +#include +#include +#include +#include -#include "Common/CCDB/EventSelectionParams.h" +#include + +#include + +#include +#include +#include // std::shared_ptr +#include // std::string namespace o2::emc_evsel { @@ -38,7 +44,7 @@ enum EventRejection { NEventRejection }; -o2::framework::AxisSpec axisEvents = {EventRejection::NEventRejection, -0.5f, +EventRejection::NEventRejection - 0.5f, ""}; +inline o2::framework::AxisSpec axisEvents = {EventRejection::NEventRejection, -0.5f, +EventRejection::NEventRejection - 0.5f, ""}; /// \brief Function to put labels on monitoring histogram /// \param hRejection monitoring histogram diff --git a/PWGJE/Core/utilsTrackMatchingEMC.h b/PWGJE/Core/utilsTrackMatchingEMC.h new file mode 100644 index 00000000000..05790a3fb88 --- /dev/null +++ b/PWGJE/Core/utilsTrackMatchingEMC.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 utilsTrackMatchingEMC.h +/// \brief EMCal track matching related utils +/// \author Marvin Hemmer + +#ifndef PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_ +#define PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_ + +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace tmemcutilities +{ + +struct MatchResult { + std::vector> matchIndexTrack; + std::vector> matchDeltaPhi; + std::vector> matchDeltaEta; +}; + +/** + * 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) + */ +MatchResult matchTracksToCluster( + std::span clusterPhi, + std::span clusterEta, + std::span trackPhi, + std::span trackEta, + double maxMatchingDistance, + int maxNumberMatches) +{ + const std::size_t nClusters = clusterEta.size(); + const std::size_t nTracks = trackEta.size(); + MatchResult result; + + if (nClusters == 0 || nTracks == 0) { + // There are no jets, so nothing to be done. + return result; + } + // 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."); + } + + result.matchIndexTrack.resize(nClusters); + result.matchDeltaPhi.resize(nClusters); + result.matchDeltaEta.resize(nClusters); + + // 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 treeTrack(trackEta.size(), 2, 1); + treeTrack.SetData(0, trackEta.data()); + treeTrack.SetData(1, trackPhi.data()); + treeTrack.Build(); + + // Find the track closest to each cluster. + for (std::size_t iCluster = 0; iCluster < nClusters; iCluster++) { + float point[2] = {clusterEta[iCluster], clusterPhi[iCluster]}; + int index[50]; // size 50 for safety + float 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); + + // allocate enough memory + result.matchIndexTrack[iCluster].reserve(maxNumberMatches); + result.matchDeltaPhi[iCluster].reserve(maxNumberMatches); + result.matchDeltaEta[iCluster].reserve(maxNumberMatches); + + // test whether indices are matching: + for (int m = 0; m < maxNumberMatches; m++) { + if (index[m] >= 0 && distance[m] < maxMatchingDistance) { + result.matchIndexTrack[iCluster].push_back(index[m]); + result.matchDeltaPhi[iCluster].push_back(trackPhi[index[m]] - clusterPhi[iCluster]); + result.matchDeltaEta[iCluster].push_back(trackEta[index[m]] - clusterEta[iCluster]); + } + } + } + return result; +} +}; // namespace tmemcutilities + +#endif // PWGJE_CORE_UTILSTRACKMATCHINGEMC_H_ diff --git a/PWGJE/DataModel/EMCALClusterDefinition.h b/PWGJE/DataModel/EMCALClusterDefinition.h index ead4a14dde7..41e87590449 100644 --- a/PWGJE/DataModel/EMCALClusterDefinition.h +++ b/PWGJE/DataModel/EMCALClusterDefinition.h @@ -17,7 +17,6 @@ #define PWGJE_DATAMODEL_EMCALCLUSTERDEFINITION_H_ #include -#include "Framework/AnalysisDataModel.h" namespace o2::aod { @@ -31,16 +30,16 @@ enum class ClusterAlgorithm_t { /// cell energy, gradient as well as timing cut struct EMCALClusterDefinition { ClusterAlgorithm_t algorithm; - int storageID = -1; // integer ID used to store cluster definition in a flat table - int selectedCellType = 1; // EMCal cell type (CURRENTLY NOT USED TO AVOID MULTIPLE CELL LOOPS) - std::string name = "kUndefined"; // name of the cluster definition - double seedEnergy = 0.1; // seed threshold (GeV) - double minCellEnergy = 0.05; // minimum cell energy (GeV) - double timeMin = -10000.; // minimum time (ns) - double timeMax = 10000.; // maximum time (ns) - double timeDiff = 20000.; // maximum time difference (ns) between seed cell and aggregation cell - bool doGradientCut = true; // apply gradient cut if true - double gradientCut = -1; // gradient cut + int storageID = -1; // integer ID used to store cluster definition in a flat table + int selectedCellType = 1; // EMCal cell type (CURRENTLY NOT USED TO AVOID MULTIPLE CELL LOOPS) + std::string name = "kUndefined"; // name of the cluster definition + double seedEnergy = 0.1; // seed threshold (GeV) + double minCellEnergy = 0.05; // minimum cell energy (GeV) + double timeMin = -10000.; // minimum time (ns) + double timeMax = 10000.; // maximum time (ns) + double timeDiff = 20000.; // maximum time difference (ns) between seed cell and aggregation cell + bool doGradientCut = true; // apply gradient cut if true + double gradientCut = -1; // gradient cut bool recalcShowerShape5x5 = false; // recalculate shower shape using 5x5 cells // default constructor diff --git a/PWGJE/DataModel/EMCALClusters.h b/PWGJE/DataModel/EMCALClusters.h index c634b4b017e..56edf634628 100644 --- a/PWGJE/DataModel/EMCALClusters.h +++ b/PWGJE/DataModel/EMCALClusters.h @@ -16,10 +16,14 @@ #ifndef PWGJE_DATAMODEL_EMCALCLUSTERS_H_ #define PWGJE_DATAMODEL_EMCALCLUSTERS_H_ +#include "EMCALClusterDefinition.h" + +#include +#include // IWYU pragma: keep + +#include #include #include -#include "Framework/AnalysisDataModel.h" -#include "EMCALClusterDefinition.h" namespace o2::aod { @@ -158,10 +162,13 @@ using EMCALClusterCell = EMCALClusterCells::iterator; using EMCALAmbiguousClusterCell = EMCALAmbiguousClusterCells::iterator; namespace emcalmatchedtrack { -DECLARE_SOA_INDEX_COLUMN(Track, track); //! linked to Track table only for tracks that were matched +DECLARE_SOA_INDEX_COLUMN(Track, track); //! linked to Track table only for tracks that were matched +DECLARE_SOA_COLUMN(DeltaPhi, deltaPhi, float); //! difference between matched track and cluster azimuthal angle +DECLARE_SOA_COLUMN(DeltaEta, deltaEta, float); //! difference between matched track and cluster pseudorapidity } // namespace emcalmatchedtrack -DECLARE_SOA_TABLE(EMCALMatchedTracks, "AOD", "EMCMATCHTRACKS", //! - o2::soa::Index<>, emcalclustercell::EMCALClusterId, emcalmatchedtrack::TrackId); //! +DECLARE_SOA_TABLE(EMCALMatchedTracks, "AOD", "EMCMATCHTRACKS", //! + o2::soa::Index<>, emcalclustercell::EMCALClusterId, emcalmatchedtrack::TrackId, + emcalmatchedtrack::DeltaPhi, emcalmatchedtrack::DeltaEta); //! using EMCALMatchedTrack = EMCALMatchedTracks::iterator; } // namespace o2::aod #endif // PWGJE_DATAMODEL_EMCALCLUSTERS_H_ diff --git a/PWGJE/DataModel/EMCALMatchedCollisions.h b/PWGJE/DataModel/EMCALMatchedCollisions.h index 4acaad9dbed..2e93a2c765b 100644 --- a/PWGJE/DataModel/EMCALMatchedCollisions.h +++ b/PWGJE/DataModel/EMCALMatchedCollisions.h @@ -18,9 +18,8 @@ #ifndef PWGJE_DATAMODEL_EMCALMATCHEDCOLLISIONS_H_ #define PWGJE_DATAMODEL_EMCALMATCHEDCOLLISIONS_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "EMCALClusterDefinition.h" +#include +#include // IWYU pragma: keep namespace o2::aod { diff --git a/PWGJE/DataModel/EMCALMatchedTracks.h b/PWGJE/DataModel/EMCALMatchedTracks.h index 1dbbfac7b7a..840a384eba8 100644 --- a/PWGJE/DataModel/EMCALMatchedTracks.h +++ b/PWGJE/DataModel/EMCALMatchedTracks.h @@ -16,9 +16,9 @@ #ifndef PWGJE_DATAMODEL_EMCALMATCHEDTRACKS_H_ #define PWGJE_DATAMODEL_EMCALMATCHEDTRACKS_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "EMCALClusterDefinition.h" +#include + +#include namespace o2::aod { diff --git a/PWGJE/DataModel/GammaJetAnalysisTree.h b/PWGJE/DataModel/GammaJetAnalysisTree.h index cfd58f75773..02a9602ec6e 100644 --- a/PWGJE/DataModel/GammaJetAnalysisTree.h +++ b/PWGJE/DataModel/GammaJetAnalysisTree.h @@ -17,16 +17,45 @@ #ifndef PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ #define PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/Jet.h" +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod::gjanalysis +{ +enum class ClusterOrigin { + kUnknown = 0, + kPhoton, // dominant amount of energy from the cluster is from a photon + kPromptPhoton, + kDirectPromptPhoton, + kFragmentationPhoton, + kDecayPhoton, // the particle that produced the cluster is a decay product + kDecayPhotonPi0, // the cluster was produced by a pi0 decay + kDecayPhotonEta, // the cluster was produced by a eta decay + kMergedPi0, // the cluster was produced by a merged pi0, i.e. two photons contribute to the cluster that both come from pi0 decay + kMergedEta, // the cluster was produced by a merged eta, i.e. two photons contribute to the cluster that both come from eta decay + kConvertedPhoton, // the cluster was produced by a converted photon, i.e. a photon that converted to an electron-positron pair and one of the electrons was detected in the cluster +}; +enum class ParticleOrigin { + kUnknown = 0, + kPromptPhoton, + kDirectPromptPhoton, + kFragmentationPhoton, + kDecayPhoton, + kDecayPhotonPi0, + kDecayPhotonEta, + kDecayPhotonOther, + kPi0 +}; +} // namespace o2::aod::gjanalysis namespace o2::aod { +// Collision level information namespace gjevent -{ // TODO add rho //! event index +{ //! event index DECLARE_SOA_COLUMN(Multiplicity, multiplicity, float); DECLARE_SOA_COLUMN(Centrality, centrality, float); DECLARE_SOA_COLUMN(Rho, rho, float); @@ -38,6 +67,16 @@ DECLARE_SOA_TABLE(GjEvents, "AOD", "GJEVENT", o2::soa::Index<>, gjevent::Multipl using GjEvent = GjEvents::iterator; +// Information about the MC collision that was matched to the reconstructed collision +namespace gjmcevent +{ +DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); +DECLARE_SOA_COLUMN(Weight, weight, double); +DECLARE_SOA_COLUMN(Rho, rho, float); // gen level rho +DECLARE_SOA_COLUMN(IsMultipleAssigned, isMultipleAssigned, bool); // if the corresponding MC collision matched to this rec collision was also matched to other rec collisions (allows to skip those on analysis level ) +} // namespace gjmcevent +DECLARE_SOA_TABLE(GjMCEvents, "AOD", "GJMCEVENT", gjmcevent::GjEventId, gjmcevent::Weight, gjmcevent::Rho, gjmcevent::IsMultipleAssigned) +// Information about EMCal clusters namespace gjgamma { DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); //! event index @@ -60,9 +99,32 @@ DECLARE_SOA_COLUMN(TMtrackP, tmtrackp, float); //! track } // namespace gjgamma DECLARE_SOA_TABLE(GjGammas, "AOD", "GJGAMMA", gjgamma::GjEventId, gjgamma::Energy, gjgamma::Definition, gjgamma::Eta, gjgamma::Phi, gjgamma::M02, gjgamma::M20, gjgamma::NCells, gjgamma::Time, gjgamma::IsExotic, gjgamma::DistanceToBadChannel, gjgamma::NLM, gjgamma::IsoRaw, gjgamma::PerpConeRho, gjgamma::TMdeltaPhi, gjgamma::TMdeltaEta, gjgamma::TMtrackP) -namespace gjchjet + +// MC information for reconstructed EMCal clusters +namespace gjgammamcinfo +{ +DECLARE_SOA_COLUMN(Origin, origin, uint16_t); +DECLARE_SOA_COLUMN(LeadingEnergyFraction, leadingEnergyFraction, float); // fraction of energy from the leading MC particle +} // namespace gjgammamcinfo +DECLARE_SOA_TABLE(GjGammaMCInfos, "AOD", "GJGAMMAMCINFO", gjgamma::GjEventId, gjgammamcinfo::Origin, gjgammamcinfo::LeadingEnergyFraction) + +// Generator level particle information from the MC collision that was matched to the reconstructed collision +namespace gjmcparticle { DECLARE_SOA_INDEX_COLUMN(GjEvent, gjevent); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(PdgCode, pdgCode, ushort); // TODO also add smoe origin of particle? maybe only save original pi0 and eta and photon (not decay photons) +DECLARE_SOA_COLUMN(MCIsolation, mcIsolation, float); // isolation in cone on mc gen level +DECLARE_SOA_COLUMN(Origin, origin, uint16_t); // origin of particle +} // namespace gjmcparticle +DECLARE_SOA_TABLE(GjMCParticles, "AOD", "GJMCPARTICLE", gjmcparticle::GjEventId, gjmcparticle::Energy, gjmcparticle::Eta, gjmcparticle::Phi, gjmcparticle::Pt, gjmcparticle::PdgCode, gjmcparticle::MCIsolation, gjmcparticle::Origin) + +// Reconstructed charged jet information +namespace gjchjet +{ DECLARE_SOA_COLUMN(Pt, pt, float); DECLARE_SOA_COLUMN(Eta, eta, float); DECLARE_SOA_COLUMN(Phi, phi, float); @@ -74,7 +136,30 @@ DECLARE_SOA_COLUMN(LeadingTrackPt, leadingtrackpt, float); DECLARE_SOA_COLUMN(PerpConeRho, perpconerho, float); DECLARE_SOA_COLUMN(NConstituents, nConstituents, ushort); } // namespace gjchjet -DECLARE_SOA_TABLE(GjChargedJets, "AOD", "GJCHJET", gjchjet::GjEventId, gjchjet::Pt, gjchjet::Eta, gjchjet::Phi, gjchjet::Radius, gjchjet::Energy, gjchjet::Mass, gjchjet::Area, gjchjet::LeadingTrackPt, gjchjet::PerpConeRho, gjchjet::NConstituents) +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) + +// MC information for reconstructed charged jet +namespace gjchjetmcinfo +{ +DECLARE_SOA_COLUMN(MatchedJetIndexGeo, matchedJetIndexGeo, int); +DECLARE_SOA_COLUMN(MatchedJetIndexPt, matchedJetIndexPt, int); +} // namespace gjchjetmcinfo +DECLARE_SOA_TABLE(GjChJetMCInfos, "AOD", "GJCHJETMCINFO", gjgamma::GjEventId, gjchjetmcinfo::MatchedJetIndexGeo, gjchjetmcinfo::MatchedJetIndexPt) + +// MC information for generator level jets of associated MC collision +namespace gjmcjet +{ +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Radius, radius, float); +DECLARE_SOA_COLUMN(Energy, energy, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(Area, area, float); +DECLARE_SOA_COLUMN(PerpConeRho, perpconerho, float); +} // namespace gjmcjet +DECLARE_SOA_TABLE(GjMCJets, "AOD", "GJMCJET", gjgamma::GjEventId, gjmcjet::Pt, gjmcjet::Eta, gjmcjet::Phi, gjmcjet::Radius, gjmcjet::Energy, gjmcjet::Mass, gjmcjet::Area, gjmcjet::PerpConeRho) + } // namespace o2::aod #endif // PWGJE_DATAMODEL_GAMMAJETANALYSISTREE_H_ diff --git a/PWGJE/DataModel/Jet.h b/PWGJE/DataModel/Jet.h index 57731df23ba..52939d0b16c 100644 --- a/PWGJE/DataModel/Jet.h +++ b/PWGJE/DataModel/Jet.h @@ -23,20 +23,20 @@ #ifndef PWGJE_DATAMODEL_JET_H_ #define PWGJE_DATAMODEL_JET_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" #include "PWGJE/DataModel/JetReducedDataHF.h" #include "PWGJE/DataModel/JetReducedDataV0.h" -#include "PWGJE/DataModel/JetReducedDataDQ.h" #include "PWGJE/DataModel/JetSubtraction.h" - -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/V0SelectorTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include + +#include +#include namespace o2::aod { @@ -181,7 +181,9 @@ DECLARE_JET_TABLES_LEVELS(Full, JTrackSub, HfD0Bases, HfD0PBases, "F"); DECLARE_JET_TABLES_LEVELS(Neutral, JTrackSub, HfD0Bases, HfD0PBases, "N"); DECLARE_JET_TABLES_LEVELS(D0Charged, JTrackD0Sub, HfD0Bases, HfD0PBases, "D0"); DECLARE_JET_TABLES_LEVELS(DplusCharged, JTrackDplusSub, HfDplusBases, HfDplusPBases, "DP"); +DECLARE_JET_TABLES_LEVELS(DstarCharged, JTrackDstarSub, HfDstarBases, HfDstarPBases, "DST"); DECLARE_JET_TABLES_LEVELS(LcCharged, JTrackLcSub, HfLcBases, HfLcPBases, "Lc"); +DECLARE_JET_TABLES_LEVELS(B0Charged, JTrackB0Sub, HfB0Bases, HfB0PBases, "B0"); DECLARE_JET_TABLES_LEVELS(BplusCharged, JTrackBplusSub, HfBplusBases, HfBplusPBases, "BP"); DECLARE_JET_TABLES_LEVELS(V0Charged, JTrackSub, V0Cores, JV0Mcs, "V0"); DECLARE_JET_TABLES_LEVELS(DielectronCharged, JTrackSub, Dielectrons, JDielectronMcs, "DIEL"); @@ -229,6 +231,14 @@ using JetParticlesSubDplus = JMcParticleDplusSubs; using McCollisionsDplus = o2::soa::Join; using CandidatesDplusMCP = o2::soa::Join; +using CollisionsDstar = o2::soa::Join; +using CandidatesDstarData = o2::soa::Join; +using CandidatesDstarMCD = o2::soa::Join; +using JetTracksSubDstar = JTrackDstarSubs; +using JetParticlesSubDstar = JMcParticleDstarSubs; +using McCollisionsDstar = o2::soa::Join; +using CandidatesDstarMCP = o2::soa::Join; + using CollisionsLc = o2::soa::Join; using CandidatesLcData = o2::soa::Join; using CandidatesLcMCD = o2::soa::Join; @@ -237,6 +247,14 @@ using JetParticlesSubLc = JMcParticleLcSubs; using McCollisionsLc = o2::soa::Join; using CandidatesLcMCP = o2::soa::Join; +using CollisionsB0 = o2::soa::Join; +using CandidatesB0Data = o2::soa::Join; +using CandidatesB0MCD = o2::soa::Join; +using JetTracksSubB0 = JTrackB0Subs; +using JetParticlesSubB0 = JMcParticleB0Subs; +using McCollisionsB0 = o2::soa::Join; +using CandidatesB0MCP = o2::soa::Join; + using CollisionsBplus = o2::soa::Join; using CandidatesBplusData = o2::soa::Join; using CandidatesBplusMCD = o2::soa::Join; diff --git a/PWGJE/DataModel/JetReducedData.h b/PWGJE/DataModel/JetReducedData.h index 5b97e41ab74..fcc3d581862 100644 --- a/PWGJE/DataModel/JetReducedData.h +++ b/PWGJE/DataModel/JetReducedData.h @@ -17,11 +17,15 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATA_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATA_H_ +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" // IWYU pragma: keep + +#include +#include // IWYU pragma: keep + #include +#include #include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" namespace o2::aod { @@ -67,8 +71,20 @@ 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(Multiplicity, multiplicity, float); -DECLARE_SOA_COLUMN(Centrality, centrality, float); +DECLARE_SOA_COLUMN(MultFV0A, multFV0A, float); +DECLARE_SOA_COLUMN(MultFV0C, multFV0C, float); +DECLARE_SOA_DYNAMIC_COLUMN(MultFV0M, multFV0M, + [](float multFV0A, float multFV0C) -> float { return multFV0A + multFV0C; }); +DECLARE_SOA_COLUMN(MultFT0A, multFT0A, float); +DECLARE_SOA_COLUMN(MultFT0C, multFT0C, float); +DECLARE_SOA_DYNAMIC_COLUMN(MultFT0M, multFT0M, + [](float multFT0A, float multFT0C) -> float { return multFT0A + multFT0C; }); +DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); +DECLARE_SOA_COLUMN(CentFV0M, centFV0M, float); // only Run 2 +DECLARE_SOA_COLUMN(CentFT0A, centFT0A, float); +DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(CentFT0CVariant1, centFT0CVariant1, float); DECLARE_SOA_COLUMN(CentralityVariant1, centralityVariant1, float); DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, float); DECLARE_SOA_COLUMN(Weight, weight, float); @@ -95,6 +111,7 @@ DECLARE_SOA_COLUMN(ReadCountsWithTVXAndZVertexAndSel7KINT7, readCountsWithTVXAnd DECLARE_SOA_COLUMN(ReadCountsWithCustom, readCountsWithCustom, std::vector); DECLARE_SOA_COLUMN(IsAmbiguous, isAmbiguous, bool); DECLARE_SOA_COLUMN(IsEMCALReadout, isEmcalReadout, bool); +DECLARE_SOA_COLUMN(IsOutlier, isOutlier, bool); } // namespace jcollision DECLARE_SOA_TABLE_STAGED(JCollisions, "JCOLLISION", @@ -102,9 +119,18 @@ DECLARE_SOA_TABLE_STAGED(JCollisions, "JCOLLISION", jcollision::PosX, jcollision::PosY, jcollision::PosZ, - jcollision::Multiplicity, - jcollision::Centrality, - jcollision::CentralityVariant1, + jcollision::MultFV0A, + jcollision::MultFV0C, + jcollision::MultFV0M, + jcollision::MultFT0A, + jcollision::MultFT0C, + jcollision::MultFT0M, + jcollision::CentFV0A, + jcollision::CentFV0M, + jcollision::CentFT0A, + jcollision::CentFT0C, + jcollision::CentFT0M, + jcollision::CentFT0CVariant1, jcollision::HadronicRate, jcollision::TrackOccupancyInTimeRange, jcollision::EventSel, @@ -118,6 +144,9 @@ DECLARE_SOA_TABLE_STAGED(JCollisionMcInfos, "JCOLLISIONMCINFO", jcollision::Weight, jcollision::SubGeneratorId); +DECLARE_SOA_TABLE_STAGED(JCollisionOutliers, "JCOLLISIONOUTLR", + jcollision::IsOutlier); + DECLARE_SOA_TABLE_STAGED(JEMCCollisionLbs, "JEMCCOLLISIONLB", jcollision::IsAmbiguous, jcollision::IsEMCALReadout); @@ -160,24 +189,41 @@ DECLARE_SOA_INDEX_COLUMN(McCollision, mcCollision); DECLARE_SOA_COLUMN(PosX, posX, float); DECLARE_SOA_COLUMN(PosY, posY, float); DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(MultFV0A, multFV0A, float); +DECLARE_SOA_COLUMN(MultFT0A, multFT0A, float); +DECLARE_SOA_COLUMN(MultFT0C, multFT0C, float); +DECLARE_SOA_COLUMN(CentFV0A, centFV0A, float); +DECLARE_SOA_COLUMN(CentFT0A, centFT0A, float); +DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); +DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); DECLARE_SOA_COLUMN(Weight, weight, float); DECLARE_SOA_COLUMN(SubGeneratorId, subGeneratorId, int); 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(PtHard, ptHard, float); +DECLARE_SOA_COLUMN(IsOutlier, isOutlier, bool); } // namespace jmccollision DECLARE_SOA_TABLE_STAGED(JMcCollisions, "JMCCOLLISION", o2::soa::Index<>, jmccollision::PosX, jmccollision::PosY, jmccollision::PosZ, + jmccollision::MultFV0A, + jmccollision::MultFT0A, + jmccollision::MultFT0C, + jmccollision::CentFV0A, + jmccollision::CentFT0A, + jmccollision::CentFT0C, + jmccollision::CentFT0M, jmccollision::Weight, jmccollision::SubGeneratorId, jmccollision::Accepted, jmccollision::Attempted, jmccollision::XsectGen, - jmccollision::XsectErr); + jmccollision::XsectErr, + jmccollision::PtHard); using JMcCollision = JMcCollisions::iterator; using StoredJMcCollision = StoredJMcCollisions::iterator; @@ -193,6 +239,9 @@ DECLARE_SOA_INDEX_COLUMN(JMcCollision, mcCollision); DECLARE_SOA_TABLE_STAGED(JMcCollisionLbs, "JMCCOLLISIONLB", jmccollisionlb::JMcCollisionId); +DECLARE_SOA_TABLE_STAGED(JMcCollisionOutliers, "JMCCOLLISIONOUTLR", + jmccollision::IsOutlier); + namespace jtrack { DECLARE_SOA_INDEX_COLUMN(JCollision, collision); diff --git a/PWGJE/DataModel/JetReducedDataDQ.h b/PWGJE/DataModel/JetReducedDataDQ.h index bbf2e464cf9..f86754d3a84 100644 --- a/PWGJE/DataModel/JetReducedDataDQ.h +++ b/PWGJE/DataModel/JetReducedDataDQ.h @@ -17,13 +17,15 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATADQ_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATADQ_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataHF.h" +#include +#include // IWYU pragma: keep + +#include +#include + namespace o2::aod { namespace jdielectronmccollision diff --git a/PWGJE/DataModel/JetReducedDataHF.h b/PWGJE/DataModel/JetReducedDataHF.h index cdb2a933d20..f295dbfa398 100644 --- a/PWGJE/DataModel/JetReducedDataHF.h +++ b/PWGJE/DataModel/JetReducedDataHF.h @@ -17,12 +17,16 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATAHF_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATAHF_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALClusters.h" // IWYU pragma: keep #include "PWGJE/DataModel/JetReducedData.h" +#include +#include // IWYU pragma: keep + +#include + +#include + namespace o2::aod { @@ -31,6 +35,8 @@ constexpr uint JMarkerDplus = 2; constexpr uint JMarkerLc = 3; constexpr uint JMarkerBplus = 4; constexpr uint JMarkerDielectron = 5; +constexpr uint JMarkerDstar = 6; +constexpr uint JMarkerB0 = 7; namespace jcandidateindices { @@ -116,6 +122,48 @@ DECLARE_SOA_TABLE(JDumDplusMlDaus, "AOD", "JDUMDPMLDAU", jdummydplus::DummyDplus, o2::soa::Marker<2>); +// might have to update!!!!!!!!!!!!!!!!!!!!!! + +namespace jdstarindices +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, JTracks, "_0"); +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, JTracks, "_1"); +DECLARE_SOA_INDEX_COLUMN_FULL(Prong2, prong2, int, JTracks, "_2"); +} // namespace jdstarindices + +DECLARE_SOA_TABLE_STAGED(JDstarCollisionIds, "JDSTCOLLID", + jcandidateindices::JCollisionId, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(JDstarMcCollisionIds, "JDSTMCCOLLID", + jcandidateindices::JMcCollisionId, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(JDstarIds, "JDSTID", + jcandidateindices::JCollisionId, + jdstarindices::Prong0Id, + jdstarindices::Prong1Id, + jdstarindices::Prong2Id); + +DECLARE_SOA_TABLE_STAGED(JDstarPIds, "JDSTPID", + jcandidateindices::JMcCollisionId, + jcandidateindices::JMcParticleId, + o2::soa::Marker); + +namespace jdummydstar +{ + +DECLARE_SOA_COLUMN(DummyDstar, dummyDstar, bool); + +} // namespace jdummydstar +DECLARE_SOA_TABLE(JDumDstarParEs, "AOD", "JDUMDSTPARE", + jdummydstar::DummyDstar, + o2::soa::Marker<1>); + +DECLARE_SOA_TABLE(JDumDstarMlDaus, "AOD", "JDUMDSTMLDAU", + jdummydstar::DummyDstar, + o2::soa::Marker<2>); + namespace jlcindices { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, JTracks, "_0"); @@ -156,6 +204,34 @@ DECLARE_SOA_TABLE(JDumLcMlDaus, "AOD", "JDUMLCMLDAU", jdummylc::DummyLc, o2::soa::Marker<2>); +namespace jb0indices +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, JTracks, "_0"); +DECLARE_SOA_INDEX_COLUMN_FULL(Prong1, prong1, int, JTracks, "_1"); +DECLARE_SOA_INDEX_COLUMN_FULL(Prong2, prong2, int, JTracks, "_2"); +DECLARE_SOA_INDEX_COLUMN_FULL(Prong3, prong3, int, JTracks, "_3"); +} // namespace jb0indices + +DECLARE_SOA_TABLE_STAGED(JB0CollisionIds, "JB0COLLID", + jcandidateindices::JCollisionId, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(JB0McCollisionIds, "JB0MCCOLLID", + jcandidateindices::JMcCollisionId, + o2::soa::Marker); + +DECLARE_SOA_TABLE_STAGED(JB0Ids, "JB0ID", + jcandidateindices::JCollisionId, + jb0indices::Prong0Id, + jb0indices::Prong1Id, + jb0indices::Prong2Id, + jb0indices::Prong3Id); + +DECLARE_SOA_TABLE_STAGED(JB0PIds, "JB0PID", + jcandidateindices::JMcCollisionId, + jcandidateindices::JMcParticleId, + o2::soa::Marker); + namespace jbplusindices { DECLARE_SOA_INDEX_COLUMN_FULL(Prong0, prong0, int, JTracks, "_0"); diff --git a/PWGJE/DataModel/JetReducedDataSelector.h b/PWGJE/DataModel/JetReducedDataSelector.h index 4e6b07a955b..9529debc58e 100644 --- a/PWGJE/DataModel/JetReducedDataSelector.h +++ b/PWGJE/DataModel/JetReducedDataSelector.h @@ -17,9 +17,9 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATASELECTOR_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATASELECTOR_H_ +#include + #include -#include -#include "Framework/AnalysisDataModel.h" namespace o2::aod { diff --git a/PWGJE/DataModel/JetReducedDataV0.h b/PWGJE/DataModel/JetReducedDataV0.h index d904403b532..433cd885f65 100644 --- a/PWGJE/DataModel/JetReducedDataV0.h +++ b/PWGJE/DataModel/JetReducedDataV0.h @@ -17,12 +17,14 @@ #ifndef PWGJE_DATAMODEL_JETREDUCEDDATAV0_H_ #define PWGJE_DATAMODEL_JETREDUCEDDATAV0_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" #include "PWGJE/DataModel/JetReducedData.h" +#include +#include // IWYU pragma: keep + +#include +#include + namespace o2::aod { diff --git a/PWGJE/DataModel/JetSubstructure.h b/PWGJE/DataModel/JetSubstructure.h index fcbf2987e52..88f0578d469 100644 --- a/PWGJE/DataModel/JetSubstructure.h +++ b/PWGJE/DataModel/JetSubstructure.h @@ -17,22 +17,26 @@ #ifndef PWGJE_DATAMODEL_JETSUBSTRUCTURE_H_ #define PWGJE_DATAMODEL_JETSUBSTRUCTURE_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 + #include +#include #include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" 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(PosZ, posZ, float); //! +DECLARE_SOA_COLUMN(Centrality, centrality, float); //! +DECLARE_SOA_COLUMN(EventSel, eventSel, uint8_t); //! DECLARE_SOA_COLUMN(EventWeight, eventWeight, float); //! } // namespace jetcollision @@ -47,15 +51,15 @@ DECLARE_SOA_COLUMN(EventWeight, eventWeight, float); //! } // namespace jetmccollision namespace jetsubstructure -{ //! -DECLARE_SOA_COLUMN(EnergyMother, energyMother, std::vector); //! -DECLARE_SOA_COLUMN(PtLeading, ptLeading, std::vector); //! -DECLARE_SOA_COLUMN(PtSubLeading, ptSubLeading, std::vector); //! -DECLARE_SOA_COLUMN(Theta, theta, std::vector); //! -DECLARE_SOA_COLUMN(NSub2DR, nSub2DR, float); //! -DECLARE_SOA_COLUMN(NSub1, nSub1, float); //! -DECLARE_SOA_COLUMN(NSub2, nSub2, float); //! -DECLARE_SOA_COLUMN(PairJetPt, pairJetPt, std::vector); //! +{ //! +DECLARE_SOA_COLUMN(EnergyMother, energyMother, std::vector); //! +DECLARE_SOA_COLUMN(PtLeading, ptLeading, std::vector); //! +DECLARE_SOA_COLUMN(PtSubLeading, ptSubLeading, std::vector); //! +DECLARE_SOA_COLUMN(Theta, theta, std::vector); //! +DECLARE_SOA_COLUMN(NSub2DR, nSub2DR, float); //! +DECLARE_SOA_COLUMN(NSub1, nSub1, float); //! +DECLARE_SOA_COLUMN(NSub2, nSub2, float); //! +DECLARE_SOA_COLUMN(PairJetPt, pairJetPt, std::vector); //! DECLARE_SOA_COLUMN(PairJetEnergy, pairJetEnergy, std::vector); //! DECLARE_SOA_COLUMN(PairJetTheta, pairJetTheta, std::vector); //! DECLARE_SOA_COLUMN(PairJetPerpCone1Pt, pairJetPerpCone1Pt, std::vector); //! @@ -67,13 +71,13 @@ DECLARE_SOA_COLUMN(PairPerpCone1PerpCone1Theta, pairPerpCone1PerpCone1Theta, std DECLARE_SOA_COLUMN(PairPerpCone1PerpCone2Pt, pairPerpCone1PerpCone2Pt, std::vector); //! DECLARE_SOA_COLUMN(PairPerpCone1PerpCone2Energy, pairPerpCone1PerpCone2Energy, std::vector); //! DECLARE_SOA_COLUMN(PairPerpCone1PerpCone2Theta, pairPerpCone1PerpCone2Theta, std::vector); //! -DECLARE_SOA_COLUMN(Angularity, angularity, float); //! -DECLARE_SOA_COLUMN(PtLeadingConstituent, ptLeadingConstituent, float); //! -DECLARE_SOA_COLUMN(PerpConeRho, perpConeRho, float); //! -DECLARE_SOA_COLUMN(SplittingMatchingGeo, splittingMatchingGeo, std::vector); //! -DECLARE_SOA_COLUMN(SplittingMatchingPt, splittingMatchingPt, std::vector); //! -DECLARE_SOA_COLUMN(SplittingMatchingHF, splittingMatchingHF, std::vector); //! -DECLARE_SOA_COLUMN(PairMatching, pairMatching, std::vector); //! +DECLARE_SOA_COLUMN(Angularity, angularity, float); //! +DECLARE_SOA_COLUMN(PtLeadingConstituent, ptLeadingConstituent, float); //! +DECLARE_SOA_COLUMN(PerpConeRho, perpConeRho, float); //! +DECLARE_SOA_COLUMN(SplittingMatchingGeo, splittingMatchingGeo, std::vector); //! +DECLARE_SOA_COLUMN(SplittingMatchingPt, splittingMatchingPt, std::vector); //! +DECLARE_SOA_COLUMN(SplittingMatchingHF, splittingMatchingHF, std::vector); //! +DECLARE_SOA_COLUMN(PairMatching, pairMatching, std::vector); //! } // namespace jetsubstructure namespace splitting @@ -256,7 +260,9 @@ DECLARE_SOA_COLUMN(JetNConstituents, jetNConstituents, int); //! JETSUBSTRUCTURE_TABLES_DEF(C, "C", Charged, charged, JTracks, CJetCOs, "CJETCO", JTrackSubs, CEWSJetCOs, "CEWSJETCO", JTracks, CMCDJetCOs, "CMCDJETCO", JMcParticles, CMCPJetCOs, "CMCPJETCO"); JETSUBSTRUCTURE_TABLES_DEF(D0C, "D0C", D0Charged, d0charged, JTracks, HfD0Bases, "HFD0BASE", JTrackD0Subs, HfD0Bases, "HFD0BASE", JTracks, HfD0Bases, "HFD0BASE", JMcParticles, HfD0PBases, "HFD0PBASE"); JETSUBSTRUCTURE_TABLES_DEF(DplusC, "DPC", DplusCharged, dpluscharged, JTracks, HfDplusBases, "HFDPBASE", JTrackDplusSubs, HfDplusBases, "HFDPBASE", JTracks, HfDplusBases, "HFDPBASE", JMcParticles, HfDplusPBases, "HFDPPBASE"); +JETSUBSTRUCTURE_TABLES_DEF(DstarC, "DSTC", DstarCharged, dstarcharged, JTracks, HfDstarBases, "HFDSTBASE", JTrackDstarSubs, HfDstarBases, "HFDSTBASE", JTracks, HfDstarBases, "HFDSTBASE", JMcParticles, HfDstarPBases, "HFDSTPBASE"); JETSUBSTRUCTURE_TABLES_DEF(LcC, "LCC", LcCharged, lccharged, JTracks, HfLcBases, "HFLCBASE", JTrackLcSubs, HfLcBases, "HFLCBASE", JTracks, HfLcBases, "HFLCBASE", JMcParticles, HfLcPBases, "HFLCPBASE"); +JETSUBSTRUCTURE_TABLES_DEF(B0C, "B0C", B0Charged, b0charged, JTracks, HfB0Bases, "HFB0BASE", JTrackB0Subs, HfB0Bases, "HFB0BASE", JTracks, HfB0Bases, "HFB0BASE", JMcParticles, HfB0PBases, "HFB0PBASE"); JETSUBSTRUCTURE_TABLES_DEF(BplusC, "BPC", BplusCharged, bpluscharged, JTracks, HfBplusBases, "HFBPBASE", JTrackBplusSubs, HfBplusBases, "HFBPBASE", JTracks, HfBplusBases, "HFBPBASE", JMcParticles, HfBplusPBases, "HFBPPBASE"); JETSUBSTRUCTURE_TABLES_DEF(DielectronC, "DIELC", DielectronCharged, dielectroncharged, JTracks, Dielectrons, "RTDIELECTRON", JTrackDielectronSubs, Dielectrons, "RTDIELECTRON", JTracks, Dielectrons, "RTDIELECTRON", JMcParticles, JDielectronMcs, "JDIELMC"); diff --git a/PWGJE/DataModel/JetSubtraction.h b/PWGJE/DataModel/JetSubtraction.h index 55879d009c1..d22237380c7 100644 --- a/PWGJE/DataModel/JetSubtraction.h +++ b/PWGJE/DataModel/JetSubtraction.h @@ -18,14 +18,14 @@ #ifndef PWGJE_DATAMODEL_JETSUBTRACTION_H_ #define PWGJE_DATAMODEL_JETSUBTRACTION_H_ -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataDQ.h" -#include "PWGHF/DataModel/DerivedTables.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGDQ/DataModel/ReducedInfoTables.h" + +#include + +#include namespace o2::aod { @@ -62,6 +62,16 @@ namespace bkgdplusmc DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfDplusPBases, "_0"); } // namespace bkgdplusmc +namespace bkgdstar +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfDstarBases, "_0"); +} // namespace bkgdstar + +namespace bkgdstarmc +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfDstarPBases, "_0"); +} // namespace bkgdstarmc + namespace bkglc { DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfLcBases, "_0"); @@ -72,6 +82,16 @@ namespace bkglcmc DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfLcPBases, "_0"); } // namespace bkglcmc +namespace bkgb0 +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfB0Bases, "_0"); +} // namespace bkgb0 + +namespace bkgb0mc +{ +DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfB0PBases, "_0"); +} // namespace bkgb0mc + namespace bkgbplus { DECLARE_SOA_INDEX_COLUMN_FULL(Candidate, candidate, int, HfBplusBases, "_0"); @@ -127,41 +147,65 @@ DECLARE_SOA_TABLE(BkgDplusMcRhos, "AOD", "BkgDPMcRho", bkgrho::RhoM, o2::soa::Marker<5>); +DECLARE_SOA_TABLE(BkgDstarRhos, "AOD", "BkgDSTRho", + o2::soa::Index<>, + bkgrho::Rho, + bkgrho::RhoM, + o2::soa::Marker<6>); + +DECLARE_SOA_TABLE(BkgDstarMcRhos, "AOD", "BkgDSTMcRho", + o2::soa::Index<>, + bkgrho::Rho, + bkgrho::RhoM, + o2::soa::Marker<7>); + DECLARE_SOA_TABLE(BkgLcRhos, "AOD", "BkgLCRho", o2::soa::Index<>, bkgrho::Rho, bkgrho::RhoM, - o2::soa::Marker<4>); + o2::soa::Marker<8>); DECLARE_SOA_TABLE(BkgLcMcRhos, "AOD", "BkgLCMcRho", o2::soa::Index<>, bkgrho::Rho, bkgrho::RhoM, - o2::soa::Marker<5>); + o2::soa::Marker<9>); + +DECLARE_SOA_TABLE(BkgB0Rhos, "AOD", "BkgB0Rho", + o2::soa::Index<>, + bkgrho::Rho, + bkgrho::RhoM, + o2::soa::Marker<10>); + +DECLARE_SOA_TABLE(BkgB0McRhos, "AOD", "BkgB0McRho", + o2::soa::Index<>, + bkgrho::Rho, + bkgrho::RhoM, + o2::soa::Marker<11>); DECLARE_SOA_TABLE(BkgBplusRhos, "AOD", "BkgBPRho", o2::soa::Index<>, bkgrho::Rho, bkgrho::RhoM, - o2::soa::Marker<6>); + o2::soa::Marker<12>); DECLARE_SOA_TABLE(BkgBplusMcRhos, "AOD", "BkgBPMcRho", o2::soa::Index<>, bkgrho::Rho, bkgrho::RhoM, - o2::soa::Marker<7>); + o2::soa::Marker<13>); DECLARE_SOA_TABLE(BkgDielectronRhos, "AOD", "BkgDIELRho", o2::soa::Index<>, bkgrho::Rho, bkgrho::RhoM, - o2::soa::Marker<8>); + o2::soa::Marker<14>); DECLARE_SOA_TABLE(BkgDielectronMcRhos, "AOD", "BkgDIELMcRho", o2::soa::Index<>, bkgrho::Rho, bkgrho::RhoM, - o2::soa::Marker<9>); + o2::soa::Marker<15>); DECLARE_SOA_TABLE(JTrackSubs, "AOD", "JTrackSubs", o2::soa::Index<>, @@ -235,7 +279,7 @@ using JMcParticleD0Sub = JMcParticleD0Subs::iterator; DECLARE_SOA_TABLE(JTrackDplusSubs, "AOD", "JTrackDPSubs", o2::soa::Index<>, - bkglc::CandidateId, + bkgdplus::CandidateId, jtrack::Pt, jtrack::Eta, jtrack::Phi, @@ -250,7 +294,7 @@ using JTrackDplusSub = JTrackDplusSubs::iterator; DECLARE_SOA_TABLE(JMcParticleDplusSubs, "AOD", "JMcPartDPSubs", o2::soa::Index<>, - bkglcmc::CandidateId, + bkgdplusmc::CandidateId, jmcparticle::Pt, jmcparticle::Eta, jmcparticle::Phi, @@ -268,6 +312,41 @@ DECLARE_SOA_TABLE(JMcParticleDplusSubs, "AOD", "JMcPartDPSubs", using JMcParticleDplusSub = JMcParticleDplusSubs::iterator; +DECLARE_SOA_TABLE(JTrackDstarSubs, "AOD", "JTrackDSTSubs", + o2::soa::Index<>, + bkgdstar::CandidateId, + jtrack::Pt, + jtrack::Eta, + jtrack::Phi, + jtrack::TrackSel, + jtrack::Px, + jtrack::Py, + jtrack::Pz, + jtrack::P, + jtrack::Energy); + +using JTrackDstarSub = JTrackDstarSubs::iterator; + +DECLARE_SOA_TABLE(JMcParticleDstarSubs, "AOD", "JMcPartDSTSubs", + o2::soa::Index<>, + bkgdstarmc::CandidateId, + jmcparticle::Pt, + jmcparticle::Eta, + jmcparticle::Phi, + jmcparticle::Y, + jmcparticle::E, + jmcparticle::PdgCode, + jmcparticle::GenStatusCode, + jmcparticle::HepMCStatusCode, + jmcparticle::IsPhysicalPrimary, + jmcparticle::Px, + jmcparticle::Py, + jmcparticle::Pz, + jmcparticle::P, + jmcparticle::Energy); + +using JMcParticleDstarSub = JMcParticleDstarSubs::iterator; + DECLARE_SOA_TABLE(JTrackLcSubs, "AOD", "JTrackLCSubs", o2::soa::Index<>, bkglc::CandidateId, @@ -303,6 +382,41 @@ DECLARE_SOA_TABLE(JMcParticleLcSubs, "AOD", "JMcPartLCSubs", using JMcParticleLcSub = JMcParticleLcSubs::iterator; +DECLARE_SOA_TABLE(JTrackB0Subs, "AOD", "JTrackB0Subs", + o2::soa::Index<>, + bkgb0::CandidateId, + jtrack::Pt, + jtrack::Eta, + jtrack::Phi, + jtrack::TrackSel, + jtrack::Px, + jtrack::Py, + jtrack::Pz, + jtrack::P, + jtrack::Energy); + +using JTrackB0Sub = JTrackB0Subs::iterator; + +DECLARE_SOA_TABLE(JMcParticleB0Subs, "AOD", "JMcPartB0Subs", + o2::soa::Index<>, + bkgb0mc::CandidateId, + jmcparticle::Pt, + jmcparticle::Eta, + jmcparticle::Phi, + jmcparticle::Y, + jmcparticle::E, + jmcparticle::PdgCode, + jmcparticle::GenStatusCode, + jmcparticle::HepMCStatusCode, + jmcparticle::IsPhysicalPrimary, + jmcparticle::Px, + jmcparticle::Py, + jmcparticle::Pz, + jmcparticle::P, + jmcparticle::Energy); + +using JMcParticleB0Sub = JMcParticleB0Subs::iterator; + DECLARE_SOA_TABLE(JTrackBplusSubs, "AOD", "JTrackBPSubs", o2::soa::Index<>, bkgbplus::CandidateId, diff --git a/PWGJE/DataModel/JetTagging.h b/PWGJE/DataModel/JetTagging.h index b84d9f01964..9d8f5eceb80 100644 --- a/PWGJE/DataModel/JetTagging.h +++ b/PWGJE/DataModel/JetTagging.h @@ -18,11 +18,18 @@ #ifndef PWGJE_DATAMODEL_JETTAGGING_H_ #define PWGJE_DATAMODEL_JETTAGGING_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/Jet.h" +#include "RecoDecay.h" + #include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/DataModel/Jet.h" // IWYU pragma: keep + +#include + +#include + +#include +#include +#include namespace o2::aod { diff --git a/PWGJE/DataModel/PhotonChargedTriggerCorrelation.h b/PWGJE/DataModel/PhotonChargedTriggerCorrelation.h new file mode 100644 index 00000000000..53f5e581d82 --- /dev/null +++ b/PWGJE/DataModel/PhotonChargedTriggerCorrelation.h @@ -0,0 +1,132 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \brief table definitions for photon-hadron correlation analyses +/// +/// \author Julius Kinner +/// \file PhotonChargedTriggerCorrelation.h + +#ifndef PWGJE_DATAMODEL_PHOTONCHARGEDTRIGGERCORRELATION_H_ +#define PWGJE_DATAMODEL_PHOTONCHARGEDTRIGGERCORRELATION_H_ + +#include "Framework/AnalysisDataModel.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" + +namespace o2::aod +{ + +// basic correlation particle columns +namespace corr_particle +{ +DECLARE_SOA_INDEX_COLUMN_FULL(JetCollision, jetCollision, int, JCollisions, ""); +DECLARE_SOA_INDEX_COLUMN_FULL(JetMcCollision, jetMcCollision, int, JMcCollisions, ""); +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +} // namespace corr_particle + +// reco + +// collision extension +namespace collision_extra_corr +{ +DECLARE_SOA_COLUMN(SelEv, selEv, bool); +DECLARE_SOA_COLUMN(TrigEv, trigEv, bool); +} // namespace collision_extra_corr +DECLARE_SOA_TABLE(CollisionsExtraCorr, "AOD", "COLLISIONSEXTRACORR", + collision_extra_corr::SelEv, collision_extra_corr::TrigEv); + +// trigger +namespace trigger +{ +DECLARE_SOA_INDEX_COLUMN_FULL(JetTrack, jetTrack, int, JetTracks, ""); +} // namespace trigger +DECLARE_SOA_TABLE(Triggers, "AOD", "TRIGGERS", + o2::soa::Index<>, corr_particle::JetCollisionId, trigger::JetTrackId, + corr_particle::Pt, corr_particle::Phi, corr_particle::Eta); +using Trigger = Triggers::iterator; + +// hadrons (global tracks) +namespace hadron +{ +DECLARE_SOA_INDEX_COLUMN_FULL(JetTrack, jetTrack, int, JetTracks, ""); +} // namespace hadron +DECLARE_SOA_TABLE(Hadrons, "AOD", "HADRONS", + o2::soa::Index<>, corr_particle::JetCollisionId, hadron::JetTrackId, + corr_particle::Pt, corr_particle::Phi, corr_particle::Eta); +using Hadron = Hadrons::iterator; + +// pipm +namespace pipm +{ +DECLARE_SOA_INDEX_COLUMN_FULL(JetTrack, jetTrack, int, JetTracks, ""); +} // namespace pipm +DECLARE_SOA_TABLE(Pipms, "AOD", "PIPMS", + o2::soa::Index<>, corr_particle::JetCollisionId, pipm::JetTrackId, + corr_particle::Pt, corr_particle::Phi, corr_particle::Eta); +using Pipm = Pipms::iterator; + +// photonPCM +namespace photon_pcm +{ +DECLARE_SOA_INDEX_COLUMN_FULL(V0PhotonKF, v0PhotonKF, int, V0PhotonsKF, ""); +DECLARE_SOA_COLUMN(PosTrackId, posTrackId, int); +DECLARE_SOA_COLUMN(NegTrackId, negTrackId, int); +} // namespace photon_pcm +DECLARE_SOA_TABLE(PhotonPCMs, "AOD", "PHOTONPCMS", + o2::soa::Index<>, corr_particle::JetCollisionId, photon_pcm::V0PhotonKFId, + photon_pcm::PosTrackId, photon_pcm::NegTrackId, + corr_particle::Pt, corr_particle::Phi, corr_particle::Eta); +using PhotonPCM = PhotonPCMs::iterator; + +// photonPCM pairs (pi0) +namespace photon_pcm_pair +{ +DECLARE_SOA_INDEX_COLUMN_FULL(V0PhotonKF1, v0PhotonKF1, int, V0PhotonsKF, "_1"); +DECLARE_SOA_INDEX_COLUMN_FULL(V0PhotonKF2, v0PhotonKF2, int, V0PhotonsKF, "_2"); +DECLARE_SOA_COLUMN(PosTrack1Id, posTrack1Id, int); +DECLARE_SOA_COLUMN(NegTrack1Id, negTrack1Id, int); +DECLARE_SOA_COLUMN(PosTrack2Id, posTrack2Id, int); +DECLARE_SOA_COLUMN(NegTrack2Id, negTrack2Id, int); +DECLARE_SOA_COLUMN(Mgg, mgg, float); +} // namespace photon_pcm_pair +DECLARE_SOA_TABLE(PhotonPCMPairs, "AOD", "PHOTONPCMPAIRS", + o2::soa::Index<>, corr_particle::JetCollisionId, photon_pcm_pair::V0PhotonKF1Id, photon_pcm_pair::V0PhotonKF2Id, + photon_pcm_pair::PosTrack1Id, photon_pcm_pair::NegTrack1Id, photon_pcm_pair::PosTrack2Id, photon_pcm_pair::NegTrack2Id, + corr_particle::Pt, corr_particle::Phi, corr_particle::Eta, photon_pcm_pair::Mgg); +using PhotonPCMPair = PhotonPCMPairs::iterator; + +// mc + +// mcCollision extension +namespace mc_collision_extra_corr +{ +DECLARE_SOA_COLUMN(TrigEv, trigEv, bool); +} // namespace mc_collision_extra_corr +DECLARE_SOA_TABLE(McCollisionsExtraCorr, "AOD", "MCCOLLISIONSEXTRACORR", + mc_collision_extra_corr::TrigEv); + +// trigger +namespace trigger_particle +{ +DECLARE_SOA_INDEX_COLUMN_FULL(JetMcParticle, jetMcParticle, int, JetParticles, ""); +} // namespace trigger_particle +DECLARE_SOA_TABLE(TriggerParticles, "AOD", "TRIGGERPARTICLES", + o2::soa::Index<>, corr_particle::JetMcCollisionId, trigger_particle::JetMcParticleId, + corr_particle::Pt, corr_particle::Phi, corr_particle::Eta); +using TriggerParticle = TriggerParticles::iterator; +} // namespace o2::aod + +#endif // PWGJE_DATAMODEL_PHOTONCHARGEDTRIGGERCORRELATION_H_ diff --git a/PWGJE/DataModel/TrackJetQa.h b/PWGJE/DataModel/TrackJetQa.h index 913f43c29b0..2ad30d88a51 100644 --- a/PWGJE/DataModel/TrackJetQa.h +++ b/PWGJE/DataModel/TrackJetQa.h @@ -19,18 +19,12 @@ #ifndef PWGJE_DATAMODEL_TRACKJETQA_H_ #define PWGJE_DATAMODEL_TRACKJETQA_H_ -// O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/Jet.h" -#include "Framework/StaticFor.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" + +#include +#include + +#include // Derived data model for track optimization (and cut variation) namespace o2::aod diff --git a/PWGJE/JetFinders/CMakeLists.txt b/PWGJE/JetFinders/CMakeLists.txt index a050f9d3fef..86052ffbe88 100644 --- a/PWGJE/JetFinders/CMakeLists.txt +++ b/PWGJE/JetFinders/CMakeLists.txt @@ -89,6 +89,21 @@ o2physics_add_dpl_workflow(jet-finder-dplus-mcp-charged PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-finder-dstar-data-charged + SOURCES jetFinderDstarDataCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-dstar-mcd-charged + SOURCES jetFinderDstarMCDCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-dstar-mcp-charged + SOURCES jetFinderDstarMCPCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-finder-lc-data-charged SOURCES jetFinderLcDataCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport @@ -104,6 +119,21 @@ o2physics_add_dpl_workflow(jet-finder-lc-mcp-charged PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-finder-b0-data-charged + SOURCES jetFinderB0DataCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-b0-mcd-charged + SOURCES jetFinderB0MCDCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(jet-finder-b0-mcp-charged + SOURCES jetFinderB0MCPCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-finder-bplus-data-charged SOURCES jetFinderBplusDataCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport diff --git a/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx b/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx index 46f2dd88df8..ac0363bf901 100644 --- a/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx +++ b/PWGJE/JetFinders/Duplicates/jetFinderDataCharged1.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataCharged1 = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx b/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx index 4a13537a48b..49f2ce1d957 100644 --- a/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx +++ b/PWGJE/JetFinders/Duplicates/jetFinderMCDCharged1.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelCharged1 = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx b/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx index 68e3f861ae6..1ae7eed6100 100644 --- a/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx +++ b/PWGJE/JetFinders/Duplicates/jetFinderMCPCharged1.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelCharged1 = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinder.cxx b/PWGJE/JetFinders/jetFinder.cxx index 9d0ff6789b3..990286c61eb 100644 --- a/PWGJE/JetFinders/jetFinder.cxx +++ b/PWGJE/JetFinders/jetFinder.cxx @@ -15,33 +15,33 @@ /// \author Jochen Klein /// \author Raymond Ehlers , ORNL +#include "PWGJE/Core/JetFinder.h" + +#include "PWGJE/Core/JetDerivedDataUtilities.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" + #include #include #include -#include #include #include #include #include -#include // IWYU pragma: keep (needed in tasks) +#include // IWYU pragma: export -#include -#include -#include +#include +#include #include #include -#include -#include - -#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" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -164,7 +164,7 @@ struct JetFinderTask { } aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax && ((skipMBGapEvents.node() == false) || (aod::jcollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap)))); + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax && ((skipMBGapEvents.node() == false) || (aod::jcollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap)))); Filter mcCollisionFilter = ((skipMBGapEvents.node() == false) || (aod::jmccollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap))); // should we add a posZ vtx cut here or leave it to analysers? Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta >= trackEtaMin && aod::jtrack::eta <= trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); // do we need eta cut both here and in globalselection? Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta >= trackEtaMin && aod::jmcparticle::eta <= trackEtaMax && aod::jmcparticle::phi >= trackPhiMin && aod::jmcparticle::phi <= trackPhiMax); diff --git a/PWGJE/JetFinders/jetFinderB0DataCharged.cxx b/PWGJE/JetFinders/jetFinderB0DataCharged.cxx new file mode 100644 index 00000000000..9288465c677 --- /dev/null +++ b/PWGJE/JetFinders/jetFinderB0DataCharged.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. + +// jet finder B0 data charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetFinderHF.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + +using JetFinderB0DataCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsData", true}}}, + TaskName{"jet-finder-b0-data-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetFinderB0MCDCharged.cxx b/PWGJE/JetFinders/jetFinderB0MCDCharged.cxx new file mode 100644 index 00000000000..46de301e549 --- /dev/null +++ b/PWGJE/JetFinders/jetFinderB0MCDCharged.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. + +// jet finder B0 mcd charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetFinderHF.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + +using JetFinderB0MCDetectorLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsMCD", true}}}, + TaskName{"jet-finder-b0-mcd-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetFinderB0MCPCharged.cxx b/PWGJE/JetFinders/jetFinderB0MCPCharged.cxx new file mode 100644 index 00000000000..2966c817cef --- /dev/null +++ b/PWGJE/JetFinders/jetFinderB0MCPCharged.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. + +// jet finder B0 mcp charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetFinderHF.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + +using JetFinderB0MCParticleLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsMCP", true}}}, + TaskName{"jet-finder-b0-mcp-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx b/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx index 402527211fb..087fbc6b37e 100644 --- a/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderBplusDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx b/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx index 4eed52e30b3..9dba69eba51 100644 --- a/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderBplusMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx b/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx index 83a1e7c9d60..639b02bfe2e 100644 --- a/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderBplusMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderD0DataCharged.cxx b/PWGJE/JetFinders/jetFinderD0DataCharged.cxx index 29ab757dbce..70e00c246d4 100644 --- a/PWGJE/JetFinders/jetFinderD0DataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderD0DataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderD0DataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx b/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx index 46847bf8651..62c740a7152 100644 --- a/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderD0MCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderD0MCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx b/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx index a21aceff347..34bee4644ce 100644 --- a/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderD0MCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderD0MCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDataCharged.cxx b/PWGJE/JetFinders/jetFinderDataCharged.cxx index e713eb4fa7c..016d83611bb 100644 --- a/PWGJE/JetFinders/jetFinderDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataCharged = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDataFull.cxx b/PWGJE/JetFinders/jetFinderDataFull.cxx index 07d103d93b2..acf33725099 100644 --- a/PWGJE/JetFinders/jetFinderDataFull.cxx +++ b/PWGJE/JetFinders/jetFinderDataFull.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataFull = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDataNeutral.cxx b/PWGJE/JetFinders/jetFinderDataNeutral.cxx index 28a1b898a15..afb223deb74 100644 --- a/PWGJE/JetFinders/jetFinderDataNeutral.cxx +++ b/PWGJE/JetFinders/jetFinderDataNeutral.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDataNeutral = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx b/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx index 2b040080579..7f4657d1127 100644 --- a/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDielectronDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx b/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx index 105b58d459a..1d14666ca10 100644 --- a/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDielectronMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx b/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx index b6aa797e80e..b0be942e08e 100644 --- a/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDielectronMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx b/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx index a0cdbdf2a24..c684fbc2e8c 100644 --- a/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDplusDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx b/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx index 0a401d330ef..ebdbe27c015 100644 --- a/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDplusMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx b/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx index 4c5cb4a604d..da79b1c2c0e 100644 --- a/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderDplusMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderDstarDataCharged.cxx b/PWGJE/JetFinders/jetFinderDstarDataCharged.cxx new file mode 100644 index 00000000000..0a1b6d104b3 --- /dev/null +++ b/PWGJE/JetFinders/jetFinderDstarDataCharged.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. + +// jet finder D* data charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetFinderHF.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + +using JetFinderDstarDataCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsData", true}}}, + TaskName{"jet-finder-dstar-data-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetFinderDstarMCDCharged.cxx b/PWGJE/JetFinders/jetFinderDstarMCDCharged.cxx new file mode 100644 index 00000000000..42e9c2fb370 --- /dev/null +++ b/PWGJE/JetFinders/jetFinderDstarMCDCharged.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. + +// jet finder D+ mcd charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetFinderHF.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + +using JetFinderDstarMCDetectorLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsMCD", true}}}, + TaskName{"jet-finder-dstar-mcd-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetFinderDstarMCPCharged.cxx b/PWGJE/JetFinders/jetFinderDstarMCPCharged.cxx new file mode 100644 index 00000000000..36ce473fe3c --- /dev/null +++ b/PWGJE/JetFinders/jetFinderDstarMCPCharged.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. + +// jet finder D* mcp charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/JetFinders/jetFinderHF.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + +using JetFinderDstarMCParticleLevelCharged = JetFinderHFTask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{{{"processChargedJetsMCP", true}}}, + TaskName{"jet-finder-dstar-mcp-charged"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/JetFinders/jetFinderHF.cxx b/PWGJE/JetFinders/jetFinderHF.cxx index 68a874e2955..34409335767 100644 --- a/PWGJE/JetFinders/jetFinderHF.cxx +++ b/PWGJE/JetFinders/jetFinderHF.cxx @@ -14,33 +14,32 @@ /// \author Nima Zardoshti /// \author Jochen Klein +#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" +#include "PWGJE/DataModel/JetSubtraction.h" + #include #include #include -#include #include #include #include #include -#include // IWYU pragma: keep (needed in tasks) +#include // IWYU pragma: export -#include -#include +#include +#include #include #include -#include -#include - -#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" -#include "PWGJE/DataModel/JetSubtraction.h" +#include +#include using namespace o2; using namespace o2::framework; @@ -169,7 +168,7 @@ struct JetFinderHFTask { } aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax && ((skipMBGapEvents.node() == false) || (aod::jcollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap)))); + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax && ((skipMBGapEvents.node() == false) || (aod::jcollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap)))); Filter mcCollisionFilter = ((skipMBGapEvents.node() == false) || (aod::jmccollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap))); // should we add a posZ vtx cut here or leave it to analysers? Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta >= trackEtaMin && aod::jtrack::eta <= trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta >= trackEtaMin && aod::jmcparticle::eta <= trackEtaMax && aod::jmcparticle::phi >= trackPhiMin && aod::jmcparticle::phi <= trackPhiMax); @@ -180,8 +179,12 @@ struct JetFinderHFTask { PresliceOptional> perD0McCandidate = aod::bkgd0mc::candidateId; PresliceOptional> perDplusCandidate = aod::bkgdplus::candidateId; PresliceOptional> perDplusMcCandidate = aod::bkgdplusmc::candidateId; + PresliceOptional> perDstarCandidate = aod::bkgdstar::candidateId; + PresliceOptional> perDstarMcCandidate = aod::bkgdstarmc::candidateId; PresliceOptional> perLcCandidate = aod::bkglc::candidateId; PresliceOptional> perLcMcCandidate = aod::bkglcmc::candidateId; + PresliceOptional> perB0Candidate = aod::bkgb0::candidateId; + PresliceOptional> perB0McCandidate = aod::bkgb0mc::candidateId; PresliceOptional> perBplusCandidate = aod::bkgbplus::candidateId; PresliceOptional> perBplusMcCandidate = aod::bkgbplusmc::candidateId; PresliceOptional> perDielectronCandidate = aod::bkgdielectron::candidateId; @@ -251,7 +254,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsData(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, CandidateTableData const& candidates) { for (typename CandidateTableData::iterator const& candidate : candidates) { - analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perLcCandidate, perBplusCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsData, "charged hf jet finding on data with event-wise constituent subtraction", false); @@ -267,7 +270,7 @@ struct JetFinderHFTask { void processChargedEvtWiseSubJetsMCD(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, CandidateTableMCD const& candidates) { for (typename CandidateTableMCD::iterator const& candidate : candidates) { - analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perLcCandidate, perBplusCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); + analyseCharged(collision, jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0Candidate, perDplusCandidate, perDstarCandidate, perLcCandidate, perB0Candidate, perBplusCandidate, perDielectronCandidate), candidate, jetsEvtWiseSubTable, constituentsEvtWiseSubTable, tracks, jetEWSPtMin, jetEWSPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsMCD, "charged hf jet finding on MC detector level with event-wise constituent subtraction", false); @@ -287,7 +290,7 @@ struct JetFinderHFTask { CandidateTableMCP const& candidates) { for (typename CandidateTableMCP::iterator const& candidate : candidates) { - analyseMCP(collision, jetcandidateutilities::slicedPerCandidate(particles, candidate, perD0McCandidate, perDplusMcCandidate, perLcMcCandidate, perBplusMcCandidate, perDielectronMcCandidate), candidate, 1, jetPtMin, jetPtMax); + analyseMCP(collision, jetcandidateutilities::slicedPerCandidate(particles, candidate, perD0McCandidate, perDplusMcCandidate, perDstarMcCandidate, perLcMcCandidate, perB0McCandidate, perBplusMcCandidate, perDielectronMcCandidate), candidate, 1, jetPtMin, jetPtMax); } } PROCESS_SWITCH(JetFinderHFTask, processChargedEvtWiseSubJetsMCP, "hf jet finding on MC particle level", false); diff --git a/PWGJE/JetFinders/jetFinderLcDataCharged.cxx b/PWGJE/JetFinders/jetFinderLcDataCharged.cxx index 821cbd87df8..37af66ca1b4 100644 --- a/PWGJE/JetFinders/jetFinderLcDataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderLcDataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderLcDataCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx b/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx index c25f35c0efb..9172f395fb8 100644 --- a/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderLcMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderLcMCDetectorLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx b/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx index 41607ed57d9..e9a1fd14346 100644 --- a/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderLcMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderHF.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderLcMCParticleLevelCharged = JetFinderHFTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCDCharged.cxx b/PWGJE/JetFinders/jetFinderMCDCharged.cxx index d8558a57770..198d1b87d98 100644 --- a/PWGJE/JetFinders/jetFinderMCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderMCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelCharged = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCDFull.cxx b/PWGJE/JetFinders/jetFinderMCDFull.cxx index 0123b75d823..ce5b8ec42ec 100644 --- a/PWGJE/JetFinders/jetFinderMCDFull.cxx +++ b/PWGJE/JetFinders/jetFinderMCDFull.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelFull = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCDNeutral.cxx b/PWGJE/JetFinders/jetFinderMCDNeutral.cxx index 9e8225b0c5f..e532c3d528b 100644 --- a/PWGJE/JetFinders/jetFinderMCDNeutral.cxx +++ b/PWGJE/JetFinders/jetFinderMCDNeutral.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCDetectorLevelNeutral = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCPCharged.cxx b/PWGJE/JetFinders/jetFinderMCPCharged.cxx index 9cba0092a53..98538de9708 100644 --- a/PWGJE/JetFinders/jetFinderMCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderMCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelCharged = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCPFull.cxx b/PWGJE/JetFinders/jetFinderMCPFull.cxx index ff9c26e4d91..217a1cfe928 100644 --- a/PWGJE/JetFinders/jetFinderMCPFull.cxx +++ b/PWGJE/JetFinders/jetFinderMCPFull.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelFull = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderMCPNeutral.cxx b/PWGJE/JetFinders/jetFinderMCPNeutral.cxx index 8593fb1f644..b2240dbe6e4 100644 --- a/PWGJE/JetFinders/jetFinderMCPNeutral.cxx +++ b/PWGJE/JetFinders/jetFinderMCPNeutral.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinder.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderMCParticleLevelNeutral = JetFinderTask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderV0.cxx b/PWGJE/JetFinders/jetFinderV0.cxx index ece753369d9..6d8b94d905a 100644 --- a/PWGJE/JetFinders/jetFinderV0.cxx +++ b/PWGJE/JetFinders/jetFinderV0.cxx @@ -13,31 +13,29 @@ // /// \author Nima Zardoshti +#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 #include #include -#include #include #include #include #include -#include // IWYU pragma: keep (needed in tasks) +#include // IWYU pragma: export -#include -#include +#include +#include #include #include -#include -#include - -#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 "PWGLF/DataModel/V0SelectorTables.h" +#include +#include using namespace o2; using namespace o2::framework; @@ -159,7 +157,7 @@ struct JetFinderV0Task { registry.add("hJetMCP", "sparse for mcp jets", {HistType::kTHnC, {{jetRadiiBins, ""}, {jetPtBinNumber, jetPtMinDouble, jetPtMaxDouble}, {40, -1.0, 1.0}, {18, 0.0, 7.0}}}); } - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax && ((skipMBGapEvents.node() == false) || (aod::jcollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap)))); + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax && aod::jcollision::trackOccupancyInTimeRange <= trackOccupancyInTimeRangeMax && ((skipMBGapEvents.node() == false) || (aod::jcollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap)))); Filter mcCollisionFilter = ((skipMBGapEvents.node() == false) || (aod::jmccollision::subGeneratorId != static_cast(jetderiveddatautilities::JCollisionSubGeneratorId::mbGap))); // should we add a posZ vtx cut here or leave it to analysers? Filter trackCuts = (aod::jtrack::pt >= trackPtMin && aod::jtrack::pt < trackPtMax && aod::jtrack::eta >= trackEtaMin && aod::jtrack::eta <= trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); Filter partCuts = (aod::jmcparticle::pt >= trackPtMin && aod::jmcparticle::pt < trackPtMax && aod::jmcparticle::eta >= trackEtaMin && aod::jmcparticle::eta <= trackEtaMax && aod::jmcparticle::phi >= trackPhiMin && aod::jmcparticle::phi <= trackPhiMax); diff --git a/PWGJE/JetFinders/jetFinderV0DataCharged.cxx b/PWGJE/JetFinders/jetFinderV0DataCharged.cxx index 7b1ac0a261f..1b239661afd 100644 --- a/PWGJE/JetFinders/jetFinderV0DataCharged.cxx +++ b/PWGJE/JetFinders/jetFinderV0DataCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderV0.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderV0DataCharged = JetFinderV0Task; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx b/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx index 30442208085..890b3334776 100644 --- a/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx +++ b/PWGJE/JetFinders/jetFinderV0MCDCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderV0.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderV0MCDetectorLevelCharged = JetFinderV0Task; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx b/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx index 27de0bdbc3c..3704f8f67b0 100644 --- a/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx +++ b/PWGJE/JetFinders/jetFinderV0MCPCharged.cxx @@ -15,6 +15,15 @@ #include "PWGJE/JetFinders/jetFinderV0.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include + +#include + using JetFinderV0MCParticleLevelCharged = JetFinderV0Task; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/TableProducer/CMakeLists.txt b/PWGJE/TableProducer/CMakeLists.txt index 2a82a7f0466..4644106c740 100644 --- a/PWGJE/TableProducer/CMakeLists.txt +++ b/PWGJE/TableProducer/CMakeLists.txt @@ -53,6 +53,11 @@ o2physics_add_dpl_workflow(jet-eventweight-mcp PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(mc-outlier-rejector + SOURCES mcOutlierRejector.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-track-derived SOURCES jetTrackDerived.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -88,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 + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::DetectorsBase O2::EMCALBase O2::EMCALReconstruction O2::EMCALCalibration O2Physics::PWGJECore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(emcal-matchedtracks-writer diff --git a/PWGJE/TableProducer/Matching/CMakeLists.txt b/PWGJE/TableProducer/Matching/CMakeLists.txt index beab5a4fdd6..e6526d90f1e 100644 --- a/PWGJE/TableProducer/Matching/CMakeLists.txt +++ b/PWGJE/TableProducer/Matching/CMakeLists.txt @@ -39,11 +39,21 @@ o2physics_add_dpl_workflow(jet-matching-mc-dplus-ch PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-matching-mc-dstar-ch + SOURCES jetMatchingMCDstarCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-matching-mc-lc-ch SOURCES jetMatchingMCLcCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-matching-mc-b0-ch + SOURCES jetMatchingMCB0Charged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-matching-mc-bplus-ch SOURCES jetMatchingMCBplusCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport @@ -74,11 +84,21 @@ o2physics_add_dpl_workflow(jet-matching-mc-sub-dplus-ch PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-matching-mc-sub-dstar-ch + SOURCES jetMatchingMCSubDstarCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-matching-mc-sub-lc-ch SOURCES jetMatchingMCSubLcCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-matching-mc-sub-b0-ch + SOURCES jetMatchingMCSubB0Charged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-matching-mc-sub-bplus-ch SOURCES jetMatchingMCSubBplusCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport @@ -104,6 +124,11 @@ o2physics_add_dpl_workflow(jet-matching-sub-dplus-ch PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-matching-sub-dstar-ch + SOURCES jetMatchingSubDstarCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-matching-sub-lc-ch SOURCES jetMatchingSubLcCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport @@ -114,6 +139,11 @@ o2physics_add_dpl_workflow(jet-matching-sub-bplus-ch PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-matching-sub-b0-ch + SOURCES jetMatchingSubB0Charged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-matching-sub-dielectron-ch SOURCES jetMatchingSubDielectronCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx index 1155c169f55..9e7d28ef94f 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx @@ -13,20 +13,17 @@ /// \brief matching duplicate jets /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx index 8115c95bf04..acf6346f615 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedData1.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using Charged1JetDataMatchingDupliacates = JetMatchingDuplicates, soa::Join, aod::ChargedJetsMatchedToCharged1Jets, diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx index 96033d17d4e..b900fb9f0c1 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCD1.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using Charged1JetMCDMatchingDupliacates = JetMatchingDuplicates, soa::Join, aod::ChargedMCDetectorLevelJetsMatchedToCharged1MCDetectorLevelJets, diff --git a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx index 11b39822bcb..f913f810191 100644 --- a/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx +++ b/PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicatesChargedMCP1.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/Duplicates/jetMatchingDuplicates.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using Charged1JetMCPMatchingDupliacates = JetMatchingDuplicates, soa::Join, aod::ChargedMCParticleLevelJetsMatchedToCharged1MCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/Substructure/CMakeLists.txt b/PWGJE/TableProducer/Matching/Substructure/CMakeLists.txt index c507c8995ef..e004a0a52ee 100644 --- a/PWGJE/TableProducer/Matching/Substructure/CMakeLists.txt +++ b/PWGJE/TableProducer/Matching/Substructure/CMakeLists.txt @@ -27,11 +27,21 @@ o2physics_add_dpl_workflow(jet-substructure-matching-mc-dplus-ch PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-substructure-matching-mc-dstar-ch + SOURCES jetSubstructureMatchingMCDstarCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-matching-mc-lc-ch SOURCES jetSubstructureMatchingMCLcCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-substructure-matching-mc-b0-ch + SOURCES jetSubstructureMatchingMCB0Charged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-matching-mc-bplus-ch SOURCES jetSubstructureMatchingMCBplusCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport @@ -57,11 +67,21 @@ o2physics_add_dpl_workflow(jet-substructure-matching-sub-dplus-ch PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-substructure-matching-sub-dstar-ch + SOURCES jetSubstructureMatchingSubDstarCharged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-matching-sub-lc-ch SOURCES jetSubstructureMatchingSubLcCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(jet-substructure-matching-sub-b0-ch + SOURCES jetSubstructureMatchingSubB0Charged.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-matching-sub-bplus-ch SOURCES jetSubstructureMatchingSubBplusCharged.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore O2::FrameworkPhysicsSupport diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx index 6d72dbf880f..02b4c1b87d1 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx @@ -14,36 +14,22 @@ /// \author Nima Zardoshti // -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.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 // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetSubstructureMatching { @@ -75,8 +61,12 @@ struct JetSubstructureMatching { PresliceOptional TagSplittingsPerTagJetD0 = aod::d0chargedmcparticlelevelsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetDplus = aod::dpluschargedmcdetectorlevelsplitting::jetId; PresliceOptional TagSplittingsPerTagJetDplus = aod::dpluschargedmcparticlelevelsplitting::jetId; + PresliceOptional BaseSplittingsPerBaseJetDstar = aod::dstarchargedmcdetectorlevelsplitting::jetId; + PresliceOptional TagSplittingsPerTagJetDstar = aod::dstarchargedmcparticlelevelsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetLc = aod::lcchargedmcdetectorlevelsplitting::jetId; PresliceOptional TagSplittingsPerTagJetLc = aod::lcchargedmcparticlelevelsplitting::jetId; + PresliceOptional BaseSplittingsPerBaseJetB0 = aod::b0chargedmcdetectorlevelsplitting::jetId; + PresliceOptional TagSplittingsPerTagJetB0 = aod::b0chargedmcparticlelevelsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetBplus = aod::bpluschargedmcdetectorlevelsplitting::jetId; PresliceOptional TagSplittingsPerTagJetBplus = aod::bpluschargedmcparticlelevelsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetDielectron = aod::dielectronchargedmcdetectorlevelsplitting::jetId; @@ -88,19 +78,23 @@ struct JetSubstructureMatching { PresliceOptional TagPairsPerTagJetD0 = aod::d0chargedmcparticlelevelpair::jetId; PresliceOptional BasePairsPerBaseJetDplus = aod::dpluschargedmcdetectorlevelpair::jetId; PresliceOptional TagPairsPerTagJetDplus = aod::dpluschargedmcparticlelevelpair::jetId; + PresliceOptional BasePairsPerBaseJetDstar = aod::dstarchargedmcdetectorlevelpair::jetId; + PresliceOptional TagPairsPerTagJetDstar = aod::dstarchargedmcparticlelevelpair::jetId; PresliceOptional BasePairsPerBaseJetLc = aod::lcchargedmcdetectorlevelpair::jetId; PresliceOptional TagPairsPerTagJetLc = aod::lcchargedmcparticlelevelpair::jetId; + PresliceOptional BasePairsPerBaseJetB0 = aod::b0chargedmcdetectorlevelpair::jetId; + PresliceOptional TagPairsPerTagJetB0 = aod::b0chargedmcparticlelevelpair::jetId; PresliceOptional BasePairsPerBaseJetBplus = aod::bpluschargedmcdetectorlevelpair::jetId; PresliceOptional TagPairsPerTagJetBplus = aod::bpluschargedmcparticlelevelpair::jetId; PresliceOptional BasePairsPerBaseJetDielectron = aod::dielectronchargedmcdetectorlevelpair::jetId; PresliceOptional TagPairsPerTagJetDielectron = aod::dielectronchargedmcparticlelevelpair::jetId; // 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& perLcJet, P const& perBplusJet, Q const& perDielectronJet) + template + auto slicedPerJetForMatching(T const& table, U const& jet, V const& perIncluisveJet, M const& perD0Jet, N const& perDplusJet, O const& perDstarJet, P const& perLcJet, Q const& perB0Jet, R const& perBplusJet, S const& perDielectronJet) { if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { - return jethfutilities::slicedPerHFJet(table, jet, perD0Jet, perDplusJet, perLcJet, perBplusJet); + return jethfutilities::slicedPerHFJet(table, jet, perD0Jet, perDplusJet, perDstarJet, perLcJet, perB0Jet, perBplusJet); } else if constexpr (jetdqutilities::isDielectronTable() || jetdqutilities::isDielectronMcTable()) { return jetdqutilities::slicedPerDielectronJet(table, jet, perDielectronJet); } else { @@ -163,14 +157,14 @@ struct JetSubstructureMatching { } if (hasMatchedJet) { // auto const& jetTagSplittings = jetsTagSplittings.sliceBy(TagSplittingsPerTagJet, jetTag.globalIndex()); - auto const& jetTagSplittings = slicedPerJetForMatching(jetsTagSplittings, jetTag, TagSplittingsPerTagJetInclusive, TagSplittingsPerTagJetD0, TagSplittingsPerTagJetDplus, TagSplittingsPerTagJetLc, TagSplittingsPerTagJetBplus, TagSplittingsPerTagJetDielectron); + auto const& jetTagSplittings = slicedPerJetForMatching(jetsTagSplittings, jetTag, TagSplittingsPerTagJetInclusive, TagSplittingsPerTagJetD0, TagSplittingsPerTagJetDplus, TagSplittingsPerTagJetDstar, TagSplittingsPerTagJetLc, TagSplittingsPerTagJetB0, TagSplittingsPerTagJetBplus, TagSplittingsPerTagJetDielectron); int tagSplittingIndex = 0; for (auto const& jetTagSplitting : jetTagSplittings) { jetTagSplittingsMap[jetTagSplitting.globalIndex()] = tagSplittingIndex; tagSplittingIndex++; } // auto const& jetTagPairs = jetsTagPairs.sliceBy(TagPairsPerTagJet, jetTag.globalIndex()); - auto const& jetTagPairs = slicedPerJetForMatching(jetsTagPairs, jetTag, TagPairsPerTagJetInclusive, TagPairsPerTagJetD0, TagPairsPerTagJetDplus, TagPairsPerTagJetLc, TagPairsPerTagJetBplus, TagPairsPerTagJetDielectron); + auto const& jetTagPairs = slicedPerJetForMatching(jetsTagPairs, jetTag, TagPairsPerTagJetInclusive, TagPairsPerTagJetD0, TagPairsPerTagJetDplus, TagPairsPerTagJetDstar, TagPairsPerTagJetLc, TagPairsPerTagJetB0, TagPairsPerTagJetBplus, TagPairsPerTagJetDielectron); int tagPairIndex = 0; for (auto const& jetTagPair : jetTagPairs) { jetTagPairsMap[jetTagPair.globalIndex()] = tagPairIndex; @@ -211,7 +205,7 @@ struct JetSubstructureMatching { } } // auto const& jetBaseSplittings = jetsBaseSplittings.sliceBy(BaseSplittingsPerBaseJet, jetBase.globalIndex()); - auto const& jetBaseSplittings = slicedPerJetForMatching(jetsBaseSplittings, jetBase, BaseSplittingsPerBaseJetInclusive, BaseSplittingsPerBaseJetD0, BaseSplittingsPerBaseJetDplus, BaseSplittingsPerBaseJetLc, BaseSplittingsPerBaseJetBplus, BaseSplittingsPerBaseJetDielectron); + auto const& jetBaseSplittings = slicedPerJetForMatching(jetsBaseSplittings, jetBase, BaseSplittingsPerBaseJetInclusive, BaseSplittingsPerBaseJetD0, BaseSplittingsPerBaseJetDplus, BaseSplittingsPerBaseJetDstar, BaseSplittingsPerBaseJetLc, BaseSplittingsPerBaseJetB0, BaseSplittingsPerBaseJetBplus, BaseSplittingsPerBaseJetDielectron); int baseSplittingIndex = 0; for (auto const& jetBaseSplitting : jetBaseSplittings) { jetBaseSplittingsMap[jetBaseSplitting.globalIndex()] = baseSplittingIndex; @@ -219,7 +213,7 @@ struct JetSubstructureMatching { } jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidatesBase, tracksBase, clustersBase, candidatesTag, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); // auto const& jetBasePairs = jetsBasePairs.sliceBy(BasePairsPerBaseJet, jetBase.globalIndex()); - auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetLc, BasePairsPerBaseJetBplus, BasePairsPerBaseJetDielectron); + auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetDstar, BasePairsPerBaseJetLc, BasePairsPerBaseJetB0, BasePairsPerBaseJetBplus, BasePairsPerBaseJetDielectron); int basePairIndex = 0; for (auto const& jetBasePair : jetBasePairs) { jetBasePairsMap[jetBasePair.globalIndex()] = basePairIndex; diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCB0Charged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCB0Charged.cxx new file mode 100644 index 00000000000..96e3e0081ec --- /dev/null +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCB0Charged.cxx @@ -0,0 +1,51 @@ +// 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. + +// B0 substructure matching mc charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + +using B0ChargedJetSubstructureMatchingMC = JetSubstructureMatching, + soa::Join, + aod::B0ChargedMCDetectorLevelSPsMatchedToB0ChargedMCParticleLevelSPs, + aod::B0ChargedMCParticleLevelSPsMatchedToB0ChargedMCDetectorLevelSPs, + aod::B0ChargedMCDetectorLevelPRsMatchedToB0ChargedMCParticleLevelPRs, + aod::B0ChargedMCParticleLevelPRsMatchedToB0ChargedMCDetectorLevelPRs, + aod::B0ChargedMCDetectorLevelSPs, + aod::B0ChargedMCParticleLevelSPs, + aod::B0ChargedMCDetectorLevelPRs, + aod::B0ChargedMCParticleLevelPRs, + aod::CandidatesB0MCD, + aod::CandidatesB0MCP, + aod::JetTracksMCD, + aod::JetParticles, + aod::JDummys>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-substructure-matching-mc-b0-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx index 06e1fe45729..27bfc4ca22f 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCBplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::BplusChargedMCDetectorLevelSPsMatchedToBplusChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx index 42df0f0bb10..e73fab8c77e 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::ChargedMCDetectorLevelSPsMatchedToChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx index 1781ed34392..82ae0adbb91 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCD0Charged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::D0ChargedMCDetectorLevelSPsMatchedToD0ChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx index f063d263478..395617bed72 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDielectronCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::DielectronChargedMCDetectorLevelSPsMatchedToDielectronChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx index 34f4f145f13..47ee3fb6757 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::DplusChargedMCDetectorLevelSPsMatchedToDplusChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDstarCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDstarCharged.cxx new file mode 100644 index 00000000000..9cff34b1ce7 --- /dev/null +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCDstarCharged.cxx @@ -0,0 +1,51 @@ +// 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. + +// D* substructure matching mc charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + +using DstarChargedJetSubstructureMatchingMC = JetSubstructureMatching, + soa::Join, + aod::DstarChargedMCDetectorLevelSPsMatchedToDstarChargedMCParticleLevelSPs, + aod::DstarChargedMCParticleLevelSPsMatchedToDstarChargedMCDetectorLevelSPs, + aod::DstarChargedMCDetectorLevelPRsMatchedToDstarChargedMCParticleLevelPRs, + aod::DstarChargedMCParticleLevelPRsMatchedToDstarChargedMCDetectorLevelPRs, + aod::DstarChargedMCDetectorLevelSPs, + aod::DstarChargedMCParticleLevelSPs, + aod::DstarChargedMCDetectorLevelPRs, + aod::DstarChargedMCParticleLevelPRs, + aod::CandidatesDstarMCD, + aod::CandidatesDstarMCP, + aod::JetTracksMCD, + aod::JetParticles, + aod::JDummys>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-substructure-matching-mc-dstar-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx index b5b5bb302a5..1744d6b24fe 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingMCLcCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatching.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetSubstructureMatchingMC = JetSubstructureMatching, soa::Join, aod::LcChargedMCDetectorLevelSPsMatchedToLcChargedMCParticleLevelSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx index 5c1382671d2..179a4b96b05 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx @@ -15,36 +15,22 @@ /// \author Nima Zardoshti // -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.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 // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetSubstructureMatchingSub { @@ -76,8 +62,12 @@ struct JetSubstructureMatchingSub { PresliceOptional TagSplittingsPerTagJetD0 = aod::d0chargedeventwisesubtractedsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetDplus = aod::dpluschargedsplitting::jetId; PresliceOptional TagSplittingsPerTagJetDplus = aod::dpluschargedeventwisesubtractedsplitting::jetId; + PresliceOptional BaseSplittingsPerBaseJetDstar = aod::dstarchargedsplitting::jetId; + PresliceOptional TagSplittingsPerTagJetDstar = aod::dstarchargedeventwisesubtractedsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetLc = aod::lcchargedsplitting::jetId; PresliceOptional TagSplittingsPerTagJetLc = aod::lcchargedeventwisesubtractedsplitting::jetId; + PresliceOptional BaseSplittingsPerBaseJetB0 = aod::b0chargedsplitting::jetId; + PresliceOptional TagSplittingsPerTagJetB0 = aod::b0chargedeventwisesubtractedsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetBplus = aod::bpluschargedsplitting::jetId; PresliceOptional TagSplittingsPerTagJetBplus = aod::bpluschargedeventwisesubtractedsplitting::jetId; PresliceOptional BaseSplittingsPerBaseJetDielectron = aod::dielectronchargedsplitting::jetId; @@ -89,19 +79,23 @@ struct JetSubstructureMatchingSub { PresliceOptional TagPairsPerTagJetD0 = aod::d0chargedeventwisesubtractedpair::jetId; PresliceOptional BasePairsPerBaseJetDplus = aod::dpluschargedpair::jetId; PresliceOptional TagPairsPerTagJetDplus = aod::dpluschargedeventwisesubtractedpair::jetId; + PresliceOptional BasePairsPerBaseJetDstar = aod::dstarchargedpair::jetId; + PresliceOptional TagPairsPerTagJetDstar = aod::dstarchargedeventwisesubtractedpair::jetId; PresliceOptional BasePairsPerBaseJetLc = aod::lcchargedpair::jetId; PresliceOptional TagPairsPerTagJetLc = aod::lcchargedeventwisesubtractedpair::jetId; PresliceOptional BasePairsPerBaseJetBplus = aod::bpluschargedpair::jetId; PresliceOptional TagPairsPerTagJetBplus = aod::bpluschargedeventwisesubtractedpair::jetId; + PresliceOptional BasePairsPerBaseJetB0 = aod::b0chargedpair::jetId; + PresliceOptional TagPairsPerTagJetB0 = aod::b0chargedeventwisesubtractedpair::jetId; PresliceOptional BasePairsPerBaseJetDielectron = aod::dielectronchargedpair::jetId; PresliceOptional TagPairsPerTagJetDielectron = aod::dielectronchargedeventwisesubtractedpair::jetId; // 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& perLcJet, P const& perBplusJet, Q const& perDielectronJet) + template + auto slicedPerJetForMatching(T const& table, U const& jet, V const& perIncluisveJet, M const& perD0Jet, N const& perDplusJet, O const& perDstarJet, P const& perLcJet, Q const& perB0Jet, R const& perBplusJet, S const& perDielectronJet) { if constexpr (jethfutilities::isHFTable() || jethfutilities::isHFMcTable()) { - return jethfutilities::slicedPerHFJet(table, jet, perD0Jet, perDplusJet, perLcJet, perBplusJet); + return jethfutilities::slicedPerHFJet(table, jet, perD0Jet, perDplusJet, perDstarJet, perLcJet, perB0Jet, perBplusJet); } else if constexpr (jetdqutilities::isDielectronTable() || jetdqutilities::isDielectronMcTable()) { return jetdqutilities::slicedPerDielectronJet(table, jet, perDielectronJet); } else { @@ -164,14 +158,14 @@ struct JetSubstructureMatchingSub { } if (hasMatchedJet) { // auto const& jetTagSplittings = jetsTagSplittings.sliceBy(TagSplittingsPerTagJet, jetTag.globalIndex()); - auto const& jetTagSplittings = slicedPerJetForMatching(jetsTagSplittings, jetTag, TagSplittingsPerTagJetInclusive, TagSplittingsPerTagJetD0, TagSplittingsPerTagJetDplus, TagSplittingsPerTagJetLc, TagSplittingsPerTagJetBplus, TagSplittingsPerTagJetDielectron); + auto const& jetTagSplittings = slicedPerJetForMatching(jetsTagSplittings, jetTag, TagSplittingsPerTagJetInclusive, TagSplittingsPerTagJetD0, TagSplittingsPerTagJetDplus, TagSplittingsPerTagJetDstar, TagSplittingsPerTagJetLc, TagSplittingsPerTagJetB0, TagSplittingsPerTagJetBplus, TagSplittingsPerTagJetDielectron); int tagSplittingIndex = 0; for (auto const& jetTagSplitting : jetTagSplittings) { jetTagSplittingsMap[jetTagSplitting.globalIndex()] = tagSplittingIndex; tagSplittingIndex++; } // auto const& jetTagPairs = jetsTagPairs.sliceBy(TagPairsPerTagJet, jetTag.globalIndex()); - auto const& jetTagPairs = slicedPerJetForMatching(jetsTagPairs, jetTag, TagPairsPerTagJetInclusive, TagPairsPerTagJetD0, TagPairsPerTagJetDplus, TagPairsPerTagJetLc, TagPairsPerTagJetBplus, TagPairsPerTagJetDielectron); + auto const& jetTagPairs = slicedPerJetForMatching(jetsTagPairs, jetTag, TagPairsPerTagJetInclusive, TagPairsPerTagJetD0, TagPairsPerTagJetDplus, TagPairsPerTagJetDstar, TagPairsPerTagJetLc, TagPairsPerTagJetB0, TagPairsPerTagJetBplus, TagPairsPerTagJetDielectron); int tagPairIndex = 0; for (auto const& jetTagPair : jetTagPairs) { jetTagPairsMap[jetTagPair.globalIndex()] = tagPairIndex; @@ -212,7 +206,7 @@ struct JetSubstructureMatchingSub { } } // auto const& jetBaseSplittings = jetsBaseSplittings.sliceBy(BaseSplittingsPerBaseJet, jetBase.globalIndex()); - auto const& jetBaseSplittings = slicedPerJetForMatching(jetsBaseSplittings, jetBase, BaseSplittingsPerBaseJetInclusive, BaseSplittingsPerBaseJetD0, BaseSplittingsPerBaseJetDplus, BaseSplittingsPerBaseJetLc, BaseSplittingsPerBaseJetBplus, BaseSplittingsPerBaseJetDielectron); + auto const& jetBaseSplittings = slicedPerJetForMatching(jetsBaseSplittings, jetBase, BaseSplittingsPerBaseJetInclusive, BaseSplittingsPerBaseJetD0, BaseSplittingsPerBaseJetDplus, BaseSplittingsPerBaseJetDstar, BaseSplittingsPerBaseJetLc, BaseSplittingsPerBaseJetB0, BaseSplittingsPerBaseJetBplus, BaseSplittingsPerBaseJetDielectron); int baseSplittingIndex = 0; for (auto const& jetBaseSplitting : jetBaseSplittings) { jetBaseSplittingsMap[jetBaseSplitting.globalIndex()] = baseSplittingIndex; @@ -220,7 +214,7 @@ struct JetSubstructureMatchingSub { } jetmatchingutilities::doAllMatching(jetBaseSplittings, jetTagSplittings, jetsBasetoTagSplittingsMatchingGeo, jetsBasetoTagSplittingsMatchingPt, jetsBasetoTagSplittingsMatchingHF, jetsTagtoBaseSplittingsMatchingGeo, jetsTagtoBaseSplittingsMatchingPt, jetsTagtoBaseSplittingsMatchingHF, candidates, tracksBase, clustersBase, candidates, tracksTag, tracksTag, doMatchingGeo, doMatchingHf, doMatchingPt, maxMatchingDistance, minPtFraction); // auto const& jetBasePairs = jetsBasePairs.sliceBy(BasePairsPerBaseJet, jetBase.globalIndex()); - auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetLc, BasePairsPerBaseJetBplus, BasePairsPerBaseJetDielectron); + auto const& jetBasePairs = slicedPerJetForMatching(jetsBasePairs, jetBase, BasePairsPerBaseJetInclusive, BasePairsPerBaseJetD0, BasePairsPerBaseJetDplus, BasePairsPerBaseJetDstar, BasePairsPerBaseJetLc, BasePairsPerBaseJetB0, BasePairsPerBaseJetBplus, BasePairsPerBaseJetDielectron); int basePairIndex = 0; for (auto const& jetBasePair : jetBasePairs) { jetBasePairsMap[jetBasePair.globalIndex()] = basePairIndex; diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubB0Charged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubB0Charged.cxx new file mode 100644 index 00000000000..3ed89997f58 --- /dev/null +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubB0Charged.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. + +// substructure matching event-wise subtracted B0 charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + +using B0ChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, + soa::Join, + aod::B0ChargedSPsMatchedToB0ChargedEventWiseSubtractedSPs, + aod::B0ChargedEventWiseSubtractedSPsMatchedToB0ChargedSPs, + aod::B0ChargedPRsMatchedToB0ChargedEventWiseSubtractedPRs, + aod::B0ChargedEventWiseSubtractedPRsMatchedToB0ChargedPRs, + aod::B0ChargedSPs, + aod::B0ChargedEventWiseSubtractedSPs, + aod::B0ChargedPRs, + aod::B0ChargedEventWiseSubtractedPRs, + aod::CandidatesB0Data, + aod::JetTracks, + aod::JetTracksSubB0, + aod::JDummys>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-substructure-matching-sub-b0-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx index 901ff6226a3..fd7fecd0264 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubBplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::BplusChargedSPsMatchedToBplusChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx index 618d55d7c5b..60fe610ad61 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::ChargedSPsMatchedToChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx index f53ebf3ae39..45e2bcb3ef2 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubD0Charged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::D0ChargedSPsMatchedToD0ChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx index 71fad02021d..d9f748252f5 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDielectronCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::DielectronChargedSPsMatchedToDielectronChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx index 662b227b08a..9d07e6a3bde 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDplusCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::DplusChargedSPsMatchedToDplusChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDstarCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDstarCharged.cxx new file mode 100644 index 00000000000..c301149c647 --- /dev/null +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubDstarCharged.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. + +// substructure matching event-wise subtracted D* charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + +using DstarChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, + soa::Join, + aod::DstarChargedSPsMatchedToDstarChargedEventWiseSubtractedSPs, + aod::DstarChargedEventWiseSubtractedSPsMatchedToDstarChargedSPs, + aod::DstarChargedPRsMatchedToDstarChargedEventWiseSubtractedPRs, + aod::DstarChargedEventWiseSubtractedPRsMatchedToDstarChargedPRs, + aod::DstarChargedSPs, + aod::DstarChargedEventWiseSubtractedSPs, + aod::DstarChargedPRs, + aod::DstarChargedEventWiseSubtractedPRs, + aod::CandidatesDstarData, + aod::JetTracks, + aod::JetTracksSubDstar, + aod::JDummys>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-substructure-matching-sub-dstar-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx index 9ab84673b9c..59f994282a1 100644 --- a/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSubLcCharged.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/TableProducer/Matching/Substructure/jetSubstructureMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubstructure.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetSubstructureMatchingSub = JetSubstructureMatchingSub, soa::Join, aod::LcChargedSPsMatchedToLcChargedEventWiseSubtractedSPs, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMC.cxx b/PWGJE/TableProducer/Matching/jetMatchingMC.cxx index 72206247c50..5faba83064e 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMC.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMC.cxx @@ -17,20 +17,16 @@ /// \author Aimeric Lanodu /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCB0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCB0Charged.cxx new file mode 100644 index 00000000000..27205e0c854 --- /dev/null +++ b/PWGJE/TableProducer/Matching/jetMatchingMCB0Charged.cxx @@ -0,0 +1,42 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet matching mc B0 charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + +using B0ChargedJetMatchingMC = JetMatchingMc, + soa::Join, + aod::B0ChargedMCDetectorLevelJetsMatchedToB0ChargedMCParticleLevelJets, + aod::B0ChargedMCParticleLevelJetsMatchedToB0ChargedMCDetectorLevelJets, + aod::CandidatesB0MCD, + aod::CandidatesB0MCP, + aod::JDummys>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-b0-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx index 8a5705f273f..e9066924fcc 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCBplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::BplusChargedMCDetectorLevelJetsMatchedToBplusChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx index fe951be4566..da8a956efc6 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::ChargedMCDetectorLevelJetsMatchedToChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx index 64abc51c79d..a56a9f21ff5 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCD0Charged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx index 7d284ecbee4..740c30d5f8b 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCDielectronCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::DielectronChargedMCDetectorLevelJetsMatchedToDielectronChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx index 31c3391533b..7032c3a42e9 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCDplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::DplusChargedMCDetectorLevelJetsMatchedToDplusChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCDstarCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCDstarCharged.cxx new file mode 100644 index 00000000000..8eca5d1908e --- /dev/null +++ b/PWGJE/TableProducer/Matching/jetMatchingMCDstarCharged.cxx @@ -0,0 +1,42 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet matching mc D* charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + +using DstarChargedJetMatchingMC = JetMatchingMc, + soa::Join, + aod::DstarChargedMCDetectorLevelJetsMatchedToDstarChargedMCParticleLevelJets, + aod::DstarChargedMCParticleLevelJetsMatchedToDstarChargedMCDetectorLevelJets, + aod::CandidatesDstarMCD, + aod::CandidatesDstarMCP, + aod::JDummys>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-dstar-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx index e4bf6f3979d..a98f0c7c5bb 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCFull.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using FullJetMatchingMC = JetMatchingMc, soa::Join, aod::FullMCDetectorLevelJetsMatchedToFullMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx index 9be7e169e57..ef10653f179 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCLcCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::LcChargedMCDetectorLevelJetsMatchedToLcChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx index 8af1d2513bc..204d0f4afda 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCNeutral.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using NeutralJetMatchingMC = JetMatchingMc, soa::Join, aod::NeutralMCDetectorLevelJetsMatchedToNeutralMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx index 45e57923721..927298a53b5 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx @@ -13,20 +13,16 @@ /// \brief matching event-wise constituent subtracted detector level and unsubtracted generated level jets (this is usseful as a template for embedding matching) /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubB0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubB0Charged.cxx new file mode 100644 index 00000000000..a5de8601581 --- /dev/null +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubB0Charged.cxx @@ -0,0 +1,39 @@ +// 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 matching mc subtracted B0 charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + +using B0ChargedJetMatchingMCSub = JetMatchingMcSub, + soa::Join, + aod::B0ChargedMCDetectorLevelJetsMatchedToB0ChargedMCDetectorLevelEventWiseSubtractedJets, + aod::B0ChargedMCDetectorLevelEventWiseSubtractedJetsMatchedToB0ChargedMCDetectorLevelJets, + aod::CandidatesB0MCD>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-sub-b0-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx index 86db7221aa6..38e0b9034d2 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubBplusCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx index 2b0c5c19992..eb19ef698f3 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::ChargedMCDetectorLevelJetsMatchedToChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx index 92a71c20900..31313b99421 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubD0Charged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::D0ChargedMCDetectorLevelJetsMatchedToD0ChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx index 376e904f473..8d9082f2884 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubDielectronCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::DielectronChargedMCDetectorLevelJetsMatchedToDielectronChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx index d8b0e0aaf50..936b7b8d718 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubDplusCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::DplusChargedMCDetectorLevelJetsMatchedToDplusChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubDstarCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubDstarCharged.cxx new file mode 100644 index 00000000000..f2acd7aedd0 --- /dev/null +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubDstarCharged.cxx @@ -0,0 +1,39 @@ +// 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 matching mc subtracted D* charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" + +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + +using DstarChargedJetMatchingMCSub = JetMatchingMcSub, + soa::Join, + aod::DstarChargedMCDetectorLevelJetsMatchedToDstarChargedMCDetectorLevelEventWiseSubtractedJets, + aod::DstarChargedMCDetectorLevelEventWiseSubtractedJetsMatchedToDstarChargedMCDetectorLevelJets, + aod::CandidatesDstarMCD>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-mc-sub-dstar-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx index 6a9456eb241..d645f297f9c 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCSubLcCharged.cxx @@ -15,6 +15,16 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMCSub.cxx" +#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetMatchingMCSub = JetMatchingMcSub, soa::Join, aod::LcChargedMCDetectorLevelJetsMatchedToLcChargedMCDetectorLevelEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx index d0910abc488..35c569d4651 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingMCV0Charged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingMC.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include +#include +#include +#include +#include + +#include + using V0ChargedJetMatchingMC = JetMatchingMc, soa::Join, aod::V0ChargedMCDetectorLevelJetsMatchedToV0ChargedMCParticleLevelJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSub.cxx b/PWGJE/TableProducer/Matching/jetMatchingSub.cxx index 002fedd3a0d..97ac2461acd 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSub.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSub.cxx @@ -13,20 +13,17 @@ /// \brief matching event-wise constituent subtracted data jets and unsubtracted data jets /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetMatchingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include // IWYU pragma: export -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetMatchingUtilities.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubB0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubB0Charged.cxx new file mode 100644 index 00000000000..87598cc0cc1 --- /dev/null +++ b/PWGJE/TableProducer/Matching/jetMatchingSubB0Charged.cxx @@ -0,0 +1,41 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet matching subtracted B0 charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + +using B0ChargedJetMatchingSub = JetMatchingSub, + soa::Join, + aod::B0ChargedJetsMatchedToB0ChargedEventWiseSubtractedJets, + aod::B0ChargedEventWiseSubtractedJetsMatchedToB0ChargedJets, + aod::JTrackB0Subs, + aod::CandidatesB0Data>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-sub-b0-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx index a24b7c6de6f..bd8591a4340 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubBplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using BplusChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::BplusChargedJetsMatchedToBplusChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx index 4d12c3c0448..406345bc8c2 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubCharged.cxx @@ -15,6 +15,18 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using ChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::ChargedJetsMatchedToChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx index d07f5186d95..2912f249d37 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubD0Charged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using D0ChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::D0ChargedJetsMatchedToD0ChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx index 94960e214d8..1cdd5c20c54 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubDielectronCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using DielectronChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::DielectronChargedJetsMatchedToDielectronChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx index 181bd2a93a2..533b129b598 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubDplusCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using DplusChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::DplusChargedJetsMatchedToDplusChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubDstarCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubDstarCharged.cxx new file mode 100644 index 00000000000..e8d54a30ecb --- /dev/null +++ b/PWGJE/TableProducer/Matching/jetMatchingSubDstarCharged.cxx @@ -0,0 +1,41 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// jet matching subtracted D* charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + +using DstarChargedJetMatchingSub = JetMatchingSub, + soa::Join, + aod::DstarChargedJetsMatchedToDstarChargedEventWiseSubtractedJets, + aod::DstarChargedEventWiseSubtractedJetsMatchedToDstarChargedJets, + aod::JTrackDstarSubs, + aod::CandidatesDstarData>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, TaskName{"jet-matching-sub-dstar-ch"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx b/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx index eabc5209fa8..72ac5bd7253 100644 --- a/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx +++ b/PWGJE/TableProducer/Matching/jetMatchingSubLcCharged.cxx @@ -15,6 +15,17 @@ #include "PWGJE/TableProducer/Matching/jetMatchingSub.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using LcChargedJetMatchingSub = JetMatchingSub, soa::Join, aod::LcChargedJetsMatchedToLcChargedEventWiseSubtractedJets, diff --git a/PWGJE/TableProducer/derivedDataProducer.cxx b/PWGJE/TableProducer/derivedDataProducer.cxx index 3398b33ce42..045c2648acd 100644 --- a/PWGJE/TableProducer/derivedDataProducer.cxx +++ b/PWGJE/TableProducer/derivedDataProducer.cxx @@ -13,49 +13,54 @@ // /// \author Nima Zardoshti -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" - -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsVertexing/PVertexer.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "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" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetReducedDataV0.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" -#include "Common/Core/RecoDecay.h" -#include "Common/CCDB/ctpRateFetcher.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "PWGJE/DataModel/EMCALClusters.h" - -#include "EventFiltering/filterTables.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetV0Utilities.h" -#include "PWGJE/Core/JetDQUtilities.h" +#include "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 "PWGHF/Utils/utilsBfieldCCDB.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -95,10 +100,18 @@ struct JetDerivedDataProducerTask { Produces jDplusMcCollisionIdsTable; Produces jDplusIdsTable; Produces jDplusParticleIdsTable; + Produces jDstarCollisionIdsTable; + Produces jDstarMcCollisionIdsTable; + Produces jDstarIdsTable; + Produces jDstarParticleIdsTable; Produces jLcCollisionIdsTable; Produces jLcMcCollisionIdsTable; Produces jLcIdsTable; Produces jLcParticleIdsTable; + Produces jB0CollisionIdsTable; + Produces jB0McCollisionIdsTable; + Produces jB0IdsTable; + Produces jB0ParticleIdsTable; Produces jBplusCollisionIdsTable; Produces jBplusMcCollisionIdsTable; Produces jBplusIdsTable; @@ -177,7 +190,7 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processBunchCrossings, "produces derived bunch crossing table", false); - void processCollisions(soa::Join::iterator const& collision, soa::Join const&) + void processCollisions(soa::Join::iterator const& collision, soa::Join const&) { auto bc = collision.bc_as>(); if (includeHadronicRate) { @@ -191,7 +204,7 @@ 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(), collision.multFT0C(), collision.centFT0C(), collision.centFT0CVariant1(), hadronicRate, collision.trackOccupancyInTimeRange(), jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), triggerBit); // note change multFT0C to multFT0M when problems with multFT0A are fixed + 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(), hadronicRate, collision.trackOccupancyInTimeRange(), jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), triggerBit); // note change multFT0C to multFT0M when problems with multFT0A are fixed products.jCollisionsParentIndexTable(collision.globalIndex()); products.jCollisionsBunchCrossingIndexTable(collision.bcId()); } @@ -205,15 +218,15 @@ 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, jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), triggerBit); + 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, -1.0, -1, jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_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) + void processCollisionsRun2(soa::Join::iterator const& collision) { - products.jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multFT0C(), collision.centRun2V0M(), -1.0, -1.0, -1, jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), 0); // note change multFT0C to multFT0M when problems with multFT0A are fixed + 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, 1.0, -1, jetderiveddatautilities::setEventSelectionBit(collision), collision.alias_raw(), 0); // note change multFT0C to multFT0M when problems with multFT0A are fixed products.jCollisionsParentIndexTable(collision.globalIndex()); products.jCollisionsBunchCrossingIndexTable(collision.bcId()); } @@ -221,7 +234,7 @@ struct JetDerivedDataProducerTask { void processCollisionsALICE3(aod::Collision const& collision) { - products.jCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), -1.0, -1.0, -1.0, -1.0, -1, -1.0, 0, 0); + 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, -1.0, -1, -1.0, 0, 0); products.jCollisionsParentIndexTable(collision.globalIndex()); products.jCollisionsBunchCrossingIndexTable(-1); } @@ -250,19 +263,33 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionLabels, "produces derived MC collision labels table", false); - void processMcCollisions(aod::McCollision const& mcCollision) + void processMcCollisions(soa::Join::iterator const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.getSubGeneratorId(), 1, 1, 1.0, 1.0); + products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multMCFV0A(), mcCollision.multMCFT0A(), mcCollision.multMCFT0C(), mcCollision.centFV0A(), mcCollision.centFT0A(), mcCollision.centFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.getSubGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisions, "produces derived MC collision table", false); - void processMcCollisionsWithXsection(soa::Join::iterator const& mcCollision) + void processMcCollisionsWithoutCentralityAndMultiplicity(soa::Join::iterator const& mcCollision) { - products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.weight(), mcCollision.getSubGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr()); + products.jMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0, mcCollision.weight(), mcCollision.getSubGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard()); products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); } - PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithXsection, "produces derived MC collision table with cross section information", false); + 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.centFV0A(), mcCollision.centFT0A(), mcCollision.centFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.getSubGeneratorId(), 1, 1, 1.0, 1.0, 999.0); + 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, -1.0, -1.0, -1.0, mcCollision.weight(), mcCollision.getSubGeneratorId(), 1, 1, 1.0, 1.0, 999.0); + products.jMcCollisionsParentIndexTable(mcCollision.globalIndex()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processMcCollisionsWithoutCentralityAndMultiplicityAndXsection, "produces derived MC collision table without centrality, multiplicity and cross section information", false); void processTracks(soa::Join::iterator const& track, aod::Collisions const&) { @@ -465,21 +492,21 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processD0McCollisions, "produces derived index for D0 MC collisions", false); - void processD0(aod::HfD0Ids::iterator const& D0, aod::Tracks const&) + void processD0(aod::HfD0Ids::iterator const& D0Candidate, aod::Tracks const&) { - auto JProng0ID = trackCollisionMapping.find({D0.prong0Id(), D0.prong0_as().collisionId()}); - auto JProng1ID = trackCollisionMapping.find({D0.prong1Id(), D0.prong1_as().collisionId()}); + auto JProng0ID = trackCollisionMapping.find({D0Candidate.prong0Id(), D0Candidate.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({D0Candidate.prong1Id(), D0Candidate.prong1_as().collisionId()}); if (withCollisionAssociator) { - JProng0ID = trackCollisionMapping.find({D0.prong0Id(), D0.collisionId()}); - JProng1ID = trackCollisionMapping.find({D0.prong1Id(), D0.collisionId()}); + JProng0ID = trackCollisionMapping.find({D0Candidate.prong0Id(), D0Candidate.collisionId()}); + JProng1ID = trackCollisionMapping.find({D0Candidate.prong1Id(), D0Candidate.collisionId()}); } - products.jD0IdsTable(D0.collisionId(), JProng0ID->second, JProng1ID->second); + products.jD0IdsTable(D0Candidate.collisionId(), JProng0ID->second, JProng1ID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processD0, "produces derived index for D0 candidates", false); - void processD0MC(aod::HfD0PIds::iterator const& D0) + void processD0MC(aod::HfD0PIds::iterator const& D0Particle) { - products.jD0ParticleIdsTable(D0.mcCollisionId(), D0.mcParticleId()); + products.jD0ParticleIdsTable(D0Particle.mcCollisionId(), D0Particle.mcParticleId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processD0MC, "produces derived index for D0 particles", false); @@ -495,26 +522,58 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processDplusMcCollisions, "produces derived index for Dplus MC collisions", false); - void processDplus(aod::HfDplusIds::iterator const& Dplus, aod::Tracks const&) + void processDplus(aod::HfDplusIds::iterator const& DplusCandidate, aod::Tracks const&) { - auto JProng0ID = trackCollisionMapping.find({Dplus.prong0Id(), Dplus.prong0_as().collisionId()}); - auto JProng1ID = trackCollisionMapping.find({Dplus.prong1Id(), Dplus.prong1_as().collisionId()}); - auto JProng2ID = trackCollisionMapping.find({Dplus.prong2Id(), Dplus.prong2_as().collisionId()}); + auto JProng0ID = trackCollisionMapping.find({DplusCandidate.prong0Id(), DplusCandidate.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({DplusCandidate.prong1Id(), DplusCandidate.prong1_as().collisionId()}); + auto JProng2ID = trackCollisionMapping.find({DplusCandidate.prong2Id(), DplusCandidate.prong2_as().collisionId()}); if (withCollisionAssociator) { - JProng0ID = trackCollisionMapping.find({Dplus.prong0Id(), Dplus.collisionId()}); - JProng1ID = trackCollisionMapping.find({Dplus.prong1Id(), Dplus.collisionId()}); - JProng2ID = trackCollisionMapping.find({Dplus.prong2Id(), Dplus.collisionId()}); + JProng0ID = trackCollisionMapping.find({DplusCandidate.prong0Id(), DplusCandidate.collisionId()}); + JProng1ID = trackCollisionMapping.find({DplusCandidate.prong1Id(), DplusCandidate.collisionId()}); + JProng2ID = trackCollisionMapping.find({DplusCandidate.prong2Id(), DplusCandidate.collisionId()}); } - products.jDplusIdsTable(Dplus.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); + products.jDplusIdsTable(DplusCandidate.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processDplus, "produces derived index for Dplus candidates", false); - void processDplusMC(aod::HfDplusPIds::iterator const& Dplus) + void processDplusMC(aod::HfDplusPIds::iterator const& DplusParticle) { - products.jDplusParticleIdsTable(Dplus.mcCollisionId(), Dplus.mcParticleId()); + products.jDplusParticleIdsTable(DplusParticle.mcCollisionId(), DplusParticle.mcParticleId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processDplusMC, "produces derived index for Dplus particles", false); + void processDstarCollisions(aod::HfDstarCollIds::iterator const& DstarCollision) + { + products.jDstarCollisionIdsTable(DstarCollision.collisionId()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processDstarCollisions, "produces derived index for Dstar collisions", false); + + void processDstarMcCollisions(aod::HfDstarMcCollIds::iterator const& DstarMcCollision) + { + products.jDstarMcCollisionIdsTable(DstarMcCollision.mcCollisionId()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processDstarMcCollisions, "produces derived index for Dstar MC collisions", false); + + void processDstar(aod::HfDstarIds::iterator const& DstarCandidate, aod::Tracks const&) + { + auto JProng0ID = trackCollisionMapping.find({DstarCandidate.prong0Id(), DstarCandidate.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({DstarCandidate.prong1Id(), DstarCandidate.prong1_as().collisionId()}); + auto JProng2ID = trackCollisionMapping.find({DstarCandidate.prong2Id(), DstarCandidate.prong2_as().collisionId()}); + if (withCollisionAssociator) { + JProng0ID = trackCollisionMapping.find({DstarCandidate.prong0Id(), DstarCandidate.collisionId()}); + JProng1ID = trackCollisionMapping.find({DstarCandidate.prong1Id(), DstarCandidate.collisionId()}); + JProng2ID = trackCollisionMapping.find({DstarCandidate.prong2Id(), DstarCandidate.collisionId()}); + } + products.jDstarIdsTable(DstarCandidate.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processDstar, "produces derived index for Dstar candidates", false); + + void processDstarMC(aod::HfDstarPIds::iterator const& DstarParticle) + { + products.jDstarParticleIdsTable(DstarParticle.mcCollisionId(), DstarParticle.mcParticleId()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processDstarMC, "produces derived index for Dstar particles", false); + void processLcCollisions(aod::HfLcCollIds::iterator const& LcCollision) { products.jLcCollisionIdsTable(LcCollision.collisionId()); @@ -527,26 +586,60 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processLcMcCollisions, "produces derived index for Lc MC collisions", false); - void processLc(aod::HfLcIds::iterator const& Lc, aod::Tracks const&) + void processLc(aod::HfLcIds::iterator const& LcCandidate, aod::Tracks const&) { - auto JProng0ID = trackCollisionMapping.find({Lc.prong0Id(), Lc.prong0_as().collisionId()}); - auto JProng1ID = trackCollisionMapping.find({Lc.prong1Id(), Lc.prong1_as().collisionId()}); - auto JProng2ID = trackCollisionMapping.find({Lc.prong2Id(), Lc.prong2_as().collisionId()}); + auto JProng0ID = trackCollisionMapping.find({LcCandidate.prong0Id(), LcCandidate.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({LcCandidate.prong1Id(), LcCandidate.prong1_as().collisionId()}); + auto JProng2ID = trackCollisionMapping.find({LcCandidate.prong2Id(), LcCandidate.prong2_as().collisionId()}); if (withCollisionAssociator) { - JProng0ID = trackCollisionMapping.find({Lc.prong0Id(), Lc.collisionId()}); - JProng1ID = trackCollisionMapping.find({Lc.prong1Id(), Lc.collisionId()}); - JProng2ID = trackCollisionMapping.find({Lc.prong2Id(), Lc.collisionId()}); + JProng0ID = trackCollisionMapping.find({LcCandidate.prong0Id(), LcCandidate.collisionId()}); + JProng1ID = trackCollisionMapping.find({LcCandidate.prong1Id(), LcCandidate.collisionId()}); + JProng2ID = trackCollisionMapping.find({LcCandidate.prong2Id(), LcCandidate.collisionId()}); } - products.jLcIdsTable(Lc.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); + products.jLcIdsTable(LcCandidate.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processLc, "produces derived index for Lc candidates", false); - void processLcMC(aod::HfLcPIds::iterator const& Lc) + void processLcMC(aod::HfLcPIds::iterator const& LcParticle) { - products.jLcParticleIdsTable(Lc.mcCollisionId(), Lc.mcParticleId()); + products.jLcParticleIdsTable(LcParticle.mcCollisionId(), LcParticle.mcParticleId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processLcMC, "produces derived index for Lc particles", false); + void processB0Collisions(aod::HfB0CollIds::iterator const& B0Collision) + { + products.jB0CollisionIdsTable(B0Collision.collisionId()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processB0Collisions, "produces derived index for B0 collisions", false); + + void processB0McCollisions(aod::HfB0McCollIds::iterator const& B0McCollision) + { + products.jB0McCollisionIdsTable(B0McCollision.mcCollisionId()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processB0McCollisions, "produces derived index for B0 MC collisions", false); + + void processB0(aod::HfB0Ids::iterator const& B0Candidate, aod::Tracks const&) + { + auto JProng0ID = trackCollisionMapping.find({B0Candidate.prong0Id(), B0Candidate.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({B0Candidate.prong1Id(), B0Candidate.prong1_as().collisionId()}); + auto JProng2ID = trackCollisionMapping.find({B0Candidate.prong2Id(), B0Candidate.prong2_as().collisionId()}); + auto JProng3ID = trackCollisionMapping.find({B0Candidate.prong3Id(), B0Candidate.prong3_as().collisionId()}); + if (withCollisionAssociator) { + JProng0ID = trackCollisionMapping.find({B0Candidate.prong0Id(), B0Candidate.collisionId()}); + JProng1ID = trackCollisionMapping.find({B0Candidate.prong1Id(), B0Candidate.collisionId()}); + JProng2ID = trackCollisionMapping.find({B0Candidate.prong2Id(), B0Candidate.collisionId()}); + JProng3ID = trackCollisionMapping.find({B0Candidate.prong3Id(), B0Candidate.collisionId()}); + } + products.jB0IdsTable(B0Candidate.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second, JProng3ID->second); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processB0, "produces derived index for B0 candidates", false); + + void processB0MC(aod::HfB0PIds::iterator const& B0Particle) + { + products.jB0ParticleIdsTable(B0Particle.mcCollisionId(), B0Particle.mcParticleId()); + } + PROCESS_SWITCH(JetDerivedDataProducerTask, processB0MC, "produces derived index for B0 particles", false); + void processBplusCollisions(aod::HfBplusCollIds::iterator const& BplusCollision) { products.jBplusCollisionIdsTable(BplusCollision.collisionId()); @@ -559,35 +652,35 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processBplusMcCollisions, "produces derived index for Bplus MC collisions", false); - void processBplus(aod::HfBplusIds::iterator const& Bplus, aod::Tracks const&) + void processBplus(aod::HfBplusIds::iterator const& BplusCandidate, aod::Tracks const&) { - auto JProng0ID = trackCollisionMapping.find({Bplus.prong0Id(), Bplus.prong0_as().collisionId()}); - auto JProng1ID = trackCollisionMapping.find({Bplus.prong1Id(), Bplus.prong1_as().collisionId()}); - auto JProng2ID = trackCollisionMapping.find({Bplus.prong2Id(), Bplus.prong2_as().collisionId()}); + auto JProng0ID = trackCollisionMapping.find({BplusCandidate.prong0Id(), BplusCandidate.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({BplusCandidate.prong1Id(), BplusCandidate.prong1_as().collisionId()}); + auto JProng2ID = trackCollisionMapping.find({BplusCandidate.prong2Id(), BplusCandidate.prong2_as().collisionId()}); if (withCollisionAssociator) { - JProng0ID = trackCollisionMapping.find({Bplus.prong0Id(), Bplus.collisionId()}); - JProng1ID = trackCollisionMapping.find({Bplus.prong1Id(), Bplus.collisionId()}); - JProng2ID = trackCollisionMapping.find({Bplus.prong2Id(), Bplus.collisionId()}); + JProng0ID = trackCollisionMapping.find({BplusCandidate.prong0Id(), BplusCandidate.collisionId()}); + JProng1ID = trackCollisionMapping.find({BplusCandidate.prong1Id(), BplusCandidate.collisionId()}); + JProng2ID = trackCollisionMapping.find({BplusCandidate.prong2Id(), BplusCandidate.collisionId()}); } - products.jBplusIdsTable(Bplus.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); + products.jBplusIdsTable(BplusCandidate.collisionId(), JProng0ID->second, JProng1ID->second, JProng2ID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processBplus, "produces derived index for Bplus candidates", false); - void processBplusMC(aod::HfBplusPIds::iterator const& Bplus) + void processBplusMC(aod::HfBplusPIds::iterator const& BplusParticle) { - products.jBplusParticleIdsTable(Bplus.mcCollisionId(), Bplus.mcParticleId()); + products.jBplusParticleIdsTable(BplusParticle.mcCollisionId(), BplusParticle.mcParticleId()); } PROCESS_SWITCH(JetDerivedDataProducerTask, processBplusMC, "produces derived index for Bplus particles", false); - void processV0(aod::V0Indices::iterator const& V0, aod::Tracks const&) + void processV0(aod::V0Indices::iterator const& V0Candidate, aod::Tracks const&) { - auto JPosTrackID = trackCollisionMapping.find({V0.posTrackId(), V0.posTrack_as().collisionId()}); - auto JNegTrackID = trackCollisionMapping.find({V0.negTrackId(), V0.negTrack_as().collisionId()}); + auto JPosTrackID = trackCollisionMapping.find({V0Candidate.posTrackId(), V0Candidate.posTrack_as().collisionId()}); + auto JNegTrackID = trackCollisionMapping.find({V0Candidate.negTrackId(), V0Candidate.negTrack_as().collisionId()}); if (withCollisionAssociator) { - JPosTrackID = trackCollisionMapping.find({V0.posTrackId(), V0.collisionId()}); - JNegTrackID = trackCollisionMapping.find({V0.negTrackId(), V0.collisionId()}); + JPosTrackID = trackCollisionMapping.find({V0Candidate.posTrackId(), V0Candidate.collisionId()}); + JNegTrackID = trackCollisionMapping.find({V0Candidate.negTrackId(), V0Candidate.collisionId()}); } - products.jV0IdsTable(V0.collisionId(), JPosTrackID->second, JNegTrackID->second); + products.jV0IdsTable(V0Candidate.collisionId(), JPosTrackID->second, JNegTrackID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processV0, "produces derived index for V0 candidates", false); @@ -633,15 +726,15 @@ struct JetDerivedDataProducerTask { } PROCESS_SWITCH(JetDerivedDataProducerTask, processDielectronCollisions, "produces derived index for Dielectron collisions", false); - void processDielectron(aod::DielectronInfo const& Dielectron, aod::Tracks const&) + void processDielectron(aod::DielectronInfo const& DielectronCandidate, aod::Tracks const&) { - auto JProng0ID = trackCollisionMapping.find({Dielectron.prong0Id(), Dielectron.prong0_as().collisionId()}); - auto JProng1ID = trackCollisionMapping.find({Dielectron.prong1Id(), Dielectron.prong1_as().collisionId()}); + auto JProng0ID = trackCollisionMapping.find({DielectronCandidate.prong0Id(), DielectronCandidate.prong0_as().collisionId()}); + auto JProng1ID = trackCollisionMapping.find({DielectronCandidate.prong1Id(), DielectronCandidate.prong1_as().collisionId()}); if (withCollisionAssociator) { - JProng0ID = trackCollisionMapping.find({Dielectron.prong0Id(), Dielectron.collisionId()}); - JProng1ID = trackCollisionMapping.find({Dielectron.prong1Id(), Dielectron.collisionId()}); + JProng0ID = trackCollisionMapping.find({DielectronCandidate.prong0Id(), DielectronCandidate.collisionId()}); + JProng1ID = trackCollisionMapping.find({DielectronCandidate.prong1Id(), DielectronCandidate.collisionId()}); } - products.jDielectronIdsTable(Dielectron.collisionId(), JProng0ID->second, JProng1ID->second); + products.jDielectronIdsTable(DielectronCandidate.collisionId(), JProng0ID->second, JProng1ID->second); } PROCESS_SWITCH(JetDerivedDataProducerTask, processDielectron, "produces derived index for Dielectron candidates", false); diff --git a/PWGJE/TableProducer/derivedDataSelector.cxx b/PWGJE/TableProducer/derivedDataSelector.cxx index f4336b228a2..9e04a6332b4 100644 --- a/PWGJE/TableProducer/derivedDataSelector.cxx +++ b/PWGJE/TableProducer/derivedDataSelector.cxx @@ -16,22 +16,27 @@ /// \author Nima Zardoshti /// \author Jochen Klein -#include -#include -#include -#include - -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetReducedDataSelector.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -55,9 +60,15 @@ struct JetDerivedDataSelector { Configurable thresholdChargedDplusJetPtMin{"thresholdChargedDplusJetPtMin", 0.0, "Minimum charged Dplus jet pt to accept event"}; Configurable thresholdChargedEventWiseSubtractedDplusJetPtMin{"thresholdChargedEventWiseSubtractedDplusJetPtMin", 0.0, "Minimum charged event-wise subtracted Dplus jet pt to accept event"}; Configurable thresholdChargedDplusMCPJetPtMin{"thresholdChargedDplusMCPJetPtMin", 0.0, "Minimum charged Dplus mcp jet pt to accept event"}; + Configurable thresholdChargedDstarJetPtMin{"thresholdChargedDstarJetPtMin", 0.0, "Minimum charged Dstar jet pt to accept event"}; + Configurable thresholdChargedEventWiseSubtractedDstarJetPtMin{"thresholdChargedEventWiseSubtractedDstarJetPtMin", 0.0, "Minimum charged event-wise subtracted Dstar jet pt to accept event"}; + Configurable thresholdChargedDstarMCPJetPtMin{"thresholdChargedDstarMCPJetPtMin", 0.0, "Minimum charged Dstar mcp jet pt to accept event"}; Configurable thresholdChargedLcJetPtMin{"thresholdChargedLcJetPtMin", 0.0, "Minimum charged Lc jet pt to accept event"}; Configurable thresholdChargedEventWiseSubtractedLcJetPtMin{"thresholdChargedEventWiseSubtractedLcJetPtMin", 0.0, "Minimum charged event-wise subtracted Lc jet pt to accept event"}; Configurable thresholdChargedLcMCPJetPtMin{"thresholdChargedLcMCPJetPtMin", 0.0, "Minimum charged Lc mcp jet pt to accept event"}; + Configurable thresholdChargedB0JetPtMin{"thresholdChargedB0JetPtMin", 0.0, "Minimum charged B0 jet pt to accept event"}; + Configurable thresholdChargedEventWiseSubtractedB0JetPtMin{"thresholdChargedEventWiseSubtractedB0JetPtMin", 0.0, "Minimum charged event-wise subtracted B0 jet pt to accept event"}; + Configurable thresholdChargedB0MCPJetPtMin{"thresholdChargedB0MCPJetPtMin", 0.0, "Minimum charged B0 mcp jet pt to accept event"}; Configurable thresholdChargedBplusJetPtMin{"thresholdChargedBplusJetPtMin", 0.0, "Minimum charged Bplus jet pt to accept event"}; Configurable thresholdChargedEventWiseSubtractedBplusJetPtMin{"thresholdChargedEventWiseSubtractedBplusJetPtMin", 0.0, "Minimum charged event-wise subtracted Bplus jet pt to accept event"}; Configurable thresholdChargedBplusMCPJetPtMin{"thresholdChargedBplusMCPJetPtMin", 0.0, "Minimum charged Bplus mcp jet pt to accept event"}; @@ -172,7 +183,7 @@ struct JetDerivedDataSelector { void processDoCollisionSelections(aod::JCollision const& collision) { // can also add event selection like sel8 but goes a little against the derived data idea - if (collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + if (collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { collisionFlag[collision.globalIndex()] = false; } } @@ -207,12 +218,24 @@ struct JetDerivedDataSelector { selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedDplusJetPtMin; } else if constexpr (std::is_same_v, aod::DplusChargedMCParticleLevelJets>) { selectionObjectPtMin = config.thresholdChargedDplusMCPJetPtMin; + } else if constexpr (std::is_same_v, aod::DstarChargedJets> || std::is_same_v, aod::DstarChargedMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdChargedDstarJetPtMin; + } else if constexpr (std::is_same_v, aod::DstarChargedEventWiseSubtractedJets> || std::is_same_v, aod::DstarChargedMCDetectorLevelEventWiseSubtractedJets>) { + selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedDstarJetPtMin; + } else if constexpr (std::is_same_v, aod::DstarChargedMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdChargedDstarMCPJetPtMin; } else if constexpr (std::is_same_v, aod::LcChargedJets> || std::is_same_v, aod::LcChargedMCDetectorLevelJets>) { selectionObjectPtMin = config.thresholdChargedLcJetPtMin; } else if constexpr (std::is_same_v, aod::LcChargedEventWiseSubtractedJets> || std::is_same_v, aod::LcChargedMCDetectorLevelEventWiseSubtractedJets>) { selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedLcJetPtMin; } else if constexpr (std::is_same_v, aod::LcChargedMCParticleLevelJets>) { selectionObjectPtMin = config.thresholdChargedLcMCPJetPtMin; + } else if constexpr (std::is_same_v, aod::B0ChargedJets> || std::is_same_v, aod::B0ChargedMCDetectorLevelJets>) { + selectionObjectPtMin = config.thresholdChargedB0JetPtMin; + } else if constexpr (std::is_same_v, aod::B0ChargedEventWiseSubtractedJets> || std::is_same_v, aod::B0ChargedMCDetectorLevelEventWiseSubtractedJets>) { + selectionObjectPtMin = config.thresholdChargedEventWiseSubtractedB0JetPtMin; + } else if constexpr (std::is_same_v, aod::B0ChargedMCParticleLevelJets>) { + selectionObjectPtMin = config.thresholdChargedB0MCPJetPtMin; } else if constexpr (std::is_same_v, aod::BplusChargedJets> || std::is_same_v, aod::BplusChargedMCDetectorLevelJets>) { selectionObjectPtMin = config.thresholdChargedBplusJetPtMin; } else if constexpr (std::is_same_v, aod::BplusChargedEventWiseSubtractedJets> || std::is_same_v, aod::BplusChargedMCDetectorLevelEventWiseSubtractedJets>) { @@ -252,7 +275,7 @@ struct JetDerivedDataSelector { } } if (isTriggerObject) { - if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets> || std::is_same_v, aod::NeutralMCParticleLevelJets> || std::is_same_v, aod::FullMCParticleLevelJets> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::DplusChargedMCParticleLevelJets> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::BplusChargedMCParticleLevelJets> || std::is_same_v, aod::DielectronChargedMCParticleLevelJets>) { + if constexpr (std::is_same_v, aod::ChargedMCParticleLevelJets> || std::is_same_v, aod::NeutralMCParticleLevelJets> || std::is_same_v, aod::FullMCParticleLevelJets> || std::is_same_v, aod::D0ChargedMCParticleLevelJets> || std::is_same_v, aod::DplusChargedMCParticleLevelJets> || std::is_same_v, aod::DstarChargedMCParticleLevelJets> || std::is_same_v, aod::LcChargedMCParticleLevelJets> || std::is_same_v, aod::B0ChargedMCParticleLevelJets> || std::is_same_v, aod::BplusChargedMCParticleLevelJets> || std::is_same_v, aod::DielectronChargedMCParticleLevelJets>) { if (selectionObject.mcCollisionId() >= 0) { McCollisionFlag[selectionObject.mcCollisionId()] = true; } @@ -291,11 +314,21 @@ struct JetDerivedDataSelector { PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDplusChargedMCDJets, "process Dplus charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDplusChargedMCDetectorLevelEventWiseSubtractedJets, "process Dplus event-wise subtracted charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDplusChargedMCPJets, "process Dplus charged mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDstarChargedJets, "process Dstar charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDstarChargedEventWiseSubtractedJets, "process Dstar event-wise subtracted charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDstarChargedMCDJets, "process Dstar charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDstarChargedMCDetectorLevelEventWiseSubtractedJets, "process Dstar event-wise subtracted charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingDstarChargedMCPJets, "process Dstar charged mcp jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingLcChargedJets, "process Lc charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingLcChargedEventWiseSubtractedJets, "process Lc event-wise subtracted charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingLcChargedMCDJets, "process Lc charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingLcChargedMCDetectorLevelEventWiseSubtractedJets, "process Lc event-wise subtracted charged mcd jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingLcChargedMCPJets, "process Lc charged mcp jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingB0ChargedJets, "process B0 charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingB0ChargedEventWiseSubtractedJets, "process B0 event-wise subtracted charged jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingB0ChargedMCDJets, "process B0 charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingB0ChargedMCDetectorLevelEventWiseSubtractedJets, "process B0 event-wise subtracted charged mcd jets", false); + PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingB0ChargedMCPJets, "process B0 charged mcp jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedJets, "process Bplus charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedEventWiseSubtractedJets, "process Bplus event-wise subtracted charged jets", false); PROCESS_SWITCH_FULL(JetDerivedDataSelector, processSelectionObjects, processSelectingBplusChargedMCDJets, "process Bplus charged mcd jets", false); diff --git a/PWGJE/TableProducer/derivedDataTriggerProducer.cxx b/PWGJE/TableProducer/derivedDataTriggerProducer.cxx index a1a1636dd1b..b90495d0bb6 100644 --- a/PWGJE/TableProducer/derivedDataTriggerProducer.cxx +++ b/PWGJE/TableProducer/derivedDataTriggerProducer.cxx @@ -13,20 +13,20 @@ // /// \author Nima Zardoshti -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "EventFiltering/filterTables.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/derivedDataWriter.cxx b/PWGJE/TableProducer/derivedDataWriter.cxx index dfd1c82b200..d583250d49f 100644 --- a/PWGJE/TableProducer/derivedDataWriter.cxx +++ b/PWGJE/TableProducer/derivedDataWriter.cxx @@ -16,22 +16,33 @@ /// \author Jochen Klein /// \author Nima Zardoshti -#include -#include -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGHF/DataModel/DerivedTables.h" #include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" #include "PWGJE/DataModel/JetReducedDataSelector.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -71,99 +82,153 @@ struct JetDerivedDataWriter { Produces storedJClustersMatchedTracksTable; Produces storedJMcClustersLabelTable; - Produces storedD0CollisionsTable; - Produces storedD0CollisionIdsTable; - Produces storedD0sTable; - Produces storedD0ParsTable; - Produces storedD0ParExtrasTable; - Produces storedD0ParDaughtersDummyTable; - Produces storedD0SelsTable; - Produces storedD0MlsTable; - Produces storedD0MlDughtersDummyTable; - Produces storedD0McsTable; - Produces storedD0IdsTable; - Produces storedD0McCollisionsTable; - Produces storedD0McCollisionIdsTable; - Produces storedD0McCollisionsMatchingTable; - Produces storedD0ParticlesTable; - Produces storedD0ParticleIdsTable; - - Produces storedDplusCollisionsTable; - Produces storedDplusCollisionIdsTable; - Produces storedDplussTable; - Produces storedDplusParsTable; - Produces storedDplusParExtrasTable; - Produces storedDplusParDaughtersDummyTable; - Produces storedDplusSelsTable; - Produces storedDplusMlsTable; - Produces storedDplusMlDughtersDummyTable; - Produces storedDplusMcsTable; - Produces storedDplusIdsTable; - Produces storedDplusMcCollisionsTable; - Produces storedDplusMcCollisionIdsTable; - Produces storedDplusMcCollisionsMatchingTable; - Produces storedDplusParticlesTable; - Produces storedDplusParticleIdsTable; - - Produces storedLcCollisionsTable; - Produces storedLcCollisionIdsTable; - Produces storedLcsTable; - Produces storedLcParsTable; - Produces storedLcParExtrasTable; - Produces storedLcParDaughtersDummyTable; - Produces storedLcSelsTable; - Produces storedLcMlsTable; - Produces storedLcMlDughtersDummyTable; - Produces storedLcMcsTable; - Produces storedLcIdsTable; - Produces storedLcMcCollisionsTable; - Produces storedLcMcCollisionIdsTable; - Produces storedLcMcCollisionsMatchingTable; - Produces storedLcParticlesTable; - Produces storedLcParticleIdsTable; - - Produces storedBplusCollisionsTable; - Produces storedBplusCollisionIdsTable; - Produces storedBplussTable; - Produces storedBplusParsTable; - Produces storedBplusParExtrasTable; - Produces storedBplusParD0sTable; - Produces storedBplusSelsTable; - Produces storedBplusMlsTable; - Produces storedBplusMlD0sTable; - Produces storedBplusMcsTable; - Produces storedBplusIdsTable; - Produces storedBplusMcCollisionsTable; - Produces storedBplusMcCollisionIdsTable; - Produces storedBplusMcCollisionsMatchingTable; - Produces storedBplusParticlesTable; - Produces storedBplusParticleIdsTable; - - Produces storedDielectronCollisionsTable; - Produces storedDielectronCollisionIdsTable; - Produces storedDielectronsTable; - Produces storedDielectronIdsTable; - Produces storedDielectronMcCollisionsTable; - Produces storedDielectronMcCollisionIdsTable; - Produces storedDielectronMcRCollDummysTable; - Produces storedDielectronParticlesTable; - Produces storedDielectronParticleIdsTable; + struct : ProducesGroup { + Produces storedD0CollisionsTable; + Produces storedD0CollisionIdsTable; + Produces storedD0sTable; + Produces storedD0ParsTable; + Produces storedD0ParExtrasTable; + Produces storedD0ParDaughtersDummyTable; + Produces storedD0SelsTable; + Produces storedD0MlsTable; + Produces storedD0MlDughtersDummyTable; + Produces storedD0McsTable; + Produces storedD0IdsTable; + Produces storedD0McCollisionsTable; + Produces storedD0McCollisionIdsTable; + Produces storedD0McCollisionsMatchingTable; + Produces storedD0ParticlesTable; + Produces storedD0ParticleIdsTable; + } productsD0; + + struct : ProducesGroup { + Produces storedDplusCollisionsTable; + Produces storedDplusCollisionIdsTable; + Produces storedDplussTable; + Produces storedDplusParsTable; + Produces storedDplusParExtrasTable; + Produces storedDplusParDaughtersDummyTable; + Produces storedDplusSelsTable; + Produces storedDplusMlsTable; + Produces storedDplusMlDughtersDummyTable; + Produces storedDplusMcsTable; + Produces storedDplusIdsTable; + Produces storedDplusMcCollisionsTable; + Produces storedDplusMcCollisionIdsTable; + Produces storedDplusMcCollisionsMatchingTable; + Produces storedDplusParticlesTable; + Produces storedDplusParticleIdsTable; + } productsDplus; + + struct : ProducesGroup { + Produces storedDstarCollisionsTable; + Produces storedDstarCollisionIdsTable; + Produces storedDstarsTable; + Produces storedDstarParsTable; + Produces storedDstarParExtrasDummyTable; + Produces storedDstarParD0sTable; + Produces storedDstarSelsTable; + Produces storedDstarMlsTable; + Produces storedDstarMlDaughtersDummyTable; + Produces storedDstarMcsTable; + Produces storedDstarIdsTable; + Produces storedDstarMcCollisionsTable; + Produces storedDstarMcCollisionIdsTable; + Produces storedDstarMcCollisionsMatchingTable; + Produces storedDstarParticlesTable; + Produces storedDstarParticleIdsTable; + } productsDstar; + + struct : ProducesGroup { + Produces storedLcCollisionsTable; + Produces storedLcCollisionIdsTable; + Produces storedLcsTable; + Produces storedLcParsTable; + Produces storedLcParExtrasTable; + Produces storedLcParDaughtersDummyTable; + Produces storedLcSelsTable; + Produces storedLcMlsTable; + Produces storedLcMlDughtersDummyTable; + Produces storedLcMcsTable; + Produces storedLcIdsTable; + Produces storedLcMcCollisionsTable; + Produces storedLcMcCollisionIdsTable; + Produces storedLcMcCollisionsMatchingTable; + Produces storedLcParticlesTable; + Produces storedLcParticleIdsTable; + } productsLc; + + struct : ProducesGroup { + Produces storedB0CollisionsTable; + Produces storedB0CollisionIdsTable; + Produces storedB0sTable; + Produces storedB0ParsTable; + Produces storedB0ParExtrasTable; + Produces storedB0ParDplussTable; + Produces storedB0SelsTable; + Produces storedB0MlsTable; + Produces storedB0MlDplussTable; + Produces storedB0McsTable; + Produces storedB0IdsTable; + Produces storedB0McCollisionsTable; + Produces storedB0McCollisionIdsTable; + Produces storedB0McCollisionsMatchingTable; + Produces storedB0ParticlesTable; + Produces storedB0ParticleIdsTable; + } productsB0; + + struct : ProducesGroup { + Produces storedBplusCollisionsTable; + Produces storedBplusCollisionIdsTable; + Produces storedBplussTable; + Produces storedBplusParsTable; + Produces storedBplusParExtrasTable; + Produces storedBplusParD0sTable; + Produces storedBplusSelsTable; + Produces storedBplusMlsTable; + Produces storedBplusMlD0sTable; + Produces storedBplusMcsTable; + Produces storedBplusIdsTable; + Produces storedBplusMcCollisionsTable; + Produces storedBplusMcCollisionIdsTable; + Produces storedBplusMcCollisionsMatchingTable; + Produces storedBplusParticlesTable; + Produces storedBplusParticleIdsTable; + } productsBplus; + + struct : ProducesGroup { + Produces storedDielectronCollisionsTable; + Produces storedDielectronCollisionIdsTable; + Produces storedDielectronsTable; + Produces storedDielectronIdsTable; + Produces storedDielectronMcCollisionsTable; + Produces storedDielectronMcCollisionIdsTable; + Produces storedDielectronMcRCollDummysTable; + Produces storedDielectronParticlesTable; + Produces storedDielectronParticleIdsTable; + } productsDielectron; + } products; - Preslice> TracksPerCollisionData = aod::jtrack::collisionId; - - Preslice> ParticlesPerMcCollision = aod::jmcparticle::mcCollisionId; - Preslice> TracksPerCollision = aod::jtrack::collisionId; - Preslice D0McCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice DplusMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice LcMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice BplusMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice DielectronMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice D0ParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice DplusParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice LcParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; - Preslice BplusParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; - PresliceUnsorted EMCTrackPerTrack = aod::jemctrack::trackId; + struct : PresliceGroup { + Preslice> TracksPerCollision = aod::jtrack::collisionId; + + Preslice> ParticlesPerMcCollision = aod::jmcparticle::mcCollisionId; + Preslice D0McCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice DplusMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice DstarMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice LcMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice B0McCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice BplusMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice DielectronMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice D0ParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice DplusParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice DstarParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice LcParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice B0ParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; + Preslice BplusParticlesPerMcCollision = aod::jcandidateindices::mcCollisionId; + PresliceUnsorted EMCTrackPerTrack = aod::jemctrack::trackId; + } preslices; uint32_t precisionPositionMask; uint32_t precisionMomentumMask; @@ -187,62 +252,93 @@ struct JetDerivedDataWriter { } template - void storeD0(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsD0 const& D0Collisions, T const& D0s) + void storeD0(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsD0 const& D0Collisions, T const& D0Candidates) { if (collision.isCollisionSelected()) { for (const auto& D0Collision : D0Collisions) { // should only ever be one - jethfutilities::fillHFCollisionTable(D0Collision, products.storedD0CollisionsTable); - products.storedD0CollisionIdsTable(collisionMapping[collision.globalIndex()]); + jethfutilities::fillHFCollisionTable(D0Collision, products.productsD0.storedD0CollisionsTable); + products.productsD0.storedD0CollisionIdsTable(collisionMapping[collision.globalIndex()]); } - for (const auto& D0 : D0s) { - jethfutilities::fillHFCandidateTable(D0, products.storedD0CollisionsTable.lastIndex(), products.storedD0sTable, products.storedD0ParsTable, products.storedD0ParExtrasTable, products.storedD0ParDaughtersDummyTable, products.storedD0SelsTable, products.storedD0MlsTable, products.storedD0MlDughtersDummyTable, products.storedD0McsTable); - products.storedD0IdsTable(collisionMapping[collision.globalIndex()], trackMapping[D0.prong0Id()], trackMapping[D0.prong1Id()]); + for (const auto& D0Candidate : D0Candidates) { + jethfutilities::fillHFCandidateTable(D0Candidate, products.productsD0.storedD0CollisionsTable.lastIndex(), products.productsD0.storedD0sTable, products.productsD0.storedD0ParsTable, products.productsD0.storedD0ParExtrasTable, products.productsD0.storedD0ParDaughtersDummyTable, products.productsD0.storedD0SelsTable, products.productsD0.storedD0MlsTable, products.productsD0.storedD0MlDughtersDummyTable, products.productsD0.storedD0McsTable); + products.productsD0.storedD0IdsTable(collisionMapping[collision.globalIndex()], trackMapping[D0Candidate.prong0Id()], trackMapping[D0Candidate.prong1Id()]); } } } template - void storeDplus(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsDplus const& DplusCollisions, T const& Dpluss) + void storeDplus(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsDplus const& DplusCollisions, T const& DplusCandidates) { if (collision.isCollisionSelected()) { for (const auto& DplusCollision : DplusCollisions) { // should only ever be one - jethfutilities::fillHFCollisionTable(DplusCollision, products.storedDplusCollisionsTable); - products.storedDplusCollisionIdsTable(collisionMapping[collision.globalIndex()]); + jethfutilities::fillHFCollisionTable(DplusCollision, products.productsDplus.storedDplusCollisionsTable); + products.productsDplus.storedDplusCollisionIdsTable(collisionMapping[collision.globalIndex()]); + } + for (const auto& DplusCandidate : DplusCandidates) { + jethfutilities::fillHFCandidateTable(DplusCandidate, products.productsDplus.storedDplusCollisionsTable.lastIndex(), products.productsDplus.storedDplussTable, products.productsDplus.storedDplusParsTable, products.productsDplus.storedDplusParExtrasTable, products.productsDplus.storedDplusParDaughtersDummyTable, products.productsDplus.storedDplusSelsTable, products.productsDplus.storedDplusMlsTable, products.productsDplus.storedDplusMlDughtersDummyTable, products.productsDplus.storedDplusMcsTable); + products.productsDplus.storedDplusIdsTable(collisionMapping[collision.globalIndex()], trackMapping[DplusCandidate.prong0Id()], trackMapping[DplusCandidate.prong1Id()], trackMapping[DplusCandidate.prong2Id()]); + } + } + } + + template + void storeDstar(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsDstar const& DstarCollisions, T const& DstarCandidates) + { + + if (collision.isCollisionSelected()) { + for (const auto& DstarCollision : DstarCollisions) { // should only ever be one + jethfutilities::fillHFCollisionTable(DstarCollision, products.productsDstar.storedDstarCollisionsTable); + products.productsDstar.storedDstarCollisionIdsTable(collisionMapping[collision.globalIndex()]); } - for (const auto& Dplus : Dpluss) { - jethfutilities::fillHFCandidateTable(Dplus, products.storedDplusCollisionsTable.lastIndex(), products.storedDplussTable, products.storedDplusParsTable, products.storedDplusParExtrasTable, products.storedDplusParDaughtersDummyTable, products.storedDplusSelsTable, products.storedDplusMlsTable, products.storedDplusMlDughtersDummyTable, products.storedDplusMcsTable); - products.storedDplusIdsTable(collisionMapping[collision.globalIndex()], trackMapping[Dplus.prong0Id()], trackMapping[Dplus.prong1Id()], trackMapping[Dplus.prong2Id()]); + for (const auto& DstarCandidate : DstarCandidates) { + jethfutilities::fillHFCandidateTable(DstarCandidate, products.productsDstar.storedDstarCollisionsTable.lastIndex(), products.productsDstar.storedDstarsTable, products.productsDstar.storedDstarParsTable, products.productsDstar.storedDstarParExtrasDummyTable, products.productsDstar.storedDstarParD0sTable, products.productsDstar.storedDstarSelsTable, products.productsDstar.storedDstarMlsTable, products.productsDstar.storedDstarMlDaughtersDummyTable, products.productsDstar.storedDstarMcsTable); + products.productsDstar.storedDstarIdsTable(collisionMapping[collision.globalIndex()], trackMapping[DstarCandidate.prong0Id()], trackMapping[DstarCandidate.prong1Id()], trackMapping[DstarCandidate.prong2Id()]); } } } template - void storeLc(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsLc const& LcCollisions, T const& Lcs) + void storeLc(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsLc const& LcCollisions, T const& LcCandidates) { if (collision.isCollisionSelected()) { for (const auto& LcCollision : LcCollisions) { // should only ever be one - jethfutilities::fillHFCollisionTable(LcCollision, products.storedLcCollisionsTable); - products.storedLcCollisionIdsTable(collisionMapping[collision.globalIndex()]); + jethfutilities::fillHFCollisionTable(LcCollision, products.productsLc.storedLcCollisionsTable); + products.productsLc.storedLcCollisionIdsTable(collisionMapping[collision.globalIndex()]); + } + for (const auto& LcCandidate : LcCandidates) { + jethfutilities::fillHFCandidateTable(LcCandidate, products.productsLc.storedLcCollisionsTable.lastIndex(), products.productsLc.storedLcsTable, products.productsLc.storedLcParsTable, products.productsLc.storedLcParExtrasTable, products.productsLc.storedLcParDaughtersDummyTable, products.productsLc.storedLcSelsTable, products.productsLc.storedLcMlsTable, products.productsLc.storedLcMlDughtersDummyTable, products.productsLc.storedLcMcsTable); + products.productsLc.storedLcIdsTable(collisionMapping[collision.globalIndex()], trackMapping[LcCandidate.prong0Id()], trackMapping[LcCandidate.prong1Id()], trackMapping[LcCandidate.prong2Id()]); + } + } + } + + template + void storeB0(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsB0 const& B0Collisions, T const& B0Candidates) + { + if (collision.isCollisionSelected()) { + for (const auto& B0Collision : B0Collisions) { // should only ever be one + jethfutilities::fillHFCollisionTable(B0Collision, products.productsB0.storedB0CollisionsTable); + products.productsB0.storedB0CollisionIdsTable(collisionMapping[collision.globalIndex()]); } - for (const auto& Lc : Lcs) { - jethfutilities::fillHFCandidateTable(Lc, products.storedLcCollisionsTable.lastIndex(), products.storedLcsTable, products.storedLcParsTable, products.storedLcParExtrasTable, products.storedLcParDaughtersDummyTable, products.storedLcSelsTable, products.storedLcMlsTable, products.storedLcMlDughtersDummyTable, products.storedLcMcsTable); - products.storedLcIdsTable(collisionMapping[collision.globalIndex()], trackMapping[Lc.prong0Id()], trackMapping[Lc.prong1Id()], trackMapping[Lc.prong2Id()]); + for (const auto& B0Candidate : B0Candidates) { + jethfutilities::fillHFCandidateTable(B0Candidate, products.productsB0.storedB0CollisionsTable.lastIndex(), products.productsB0.storedB0sTable, products.productsB0.storedB0ParsTable, products.productsB0.storedB0ParExtrasTable, products.productsB0.storedB0ParDplussTable, products.productsB0.storedB0SelsTable, products.productsB0.storedB0MlsTable, products.productsB0.storedB0MlDplussTable, products.productsB0.storedB0McsTable); + products.productsB0.storedB0IdsTable(collisionMapping[collision.globalIndex()], trackMapping[B0Candidate.prong0Id()], trackMapping[B0Candidate.prong1Id()], trackMapping[B0Candidate.prong2Id()], trackMapping[B0Candidate.prong3Id()]); } } } template - void storeBplus(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsBplus const& BplusCollisions, T const& Bpluss) + void storeBplus(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsBplus const& BplusCollisions, T const& BplusCandidates) { if (collision.isCollisionSelected()) { for (const auto& BplusCollision : BplusCollisions) { // should only ever be one - jethfutilities::fillHFCollisionTable(BplusCollision, products.storedBplusCollisionsTable); - products.storedBplusCollisionIdsTable(collisionMapping[collision.globalIndex()]); + jethfutilities::fillHFCollisionTable(BplusCollision, products.productsBplus.storedBplusCollisionsTable); + products.productsBplus.storedBplusCollisionIdsTable(collisionMapping[collision.globalIndex()]); } - for (const auto& Bplus : Bpluss) { - jethfutilities::fillHFCandidateTable(Bplus, products.storedBplusCollisionsTable.lastIndex(), products.storedBplussTable, products.storedBplusParsTable, products.storedBplusParExtrasTable, products.storedBplusParD0sTable, products.storedBplusSelsTable, products.storedBplusMlsTable, products.storedBplusMlD0sTable, products.storedBplusMcsTable); - products.storedBplusIdsTable(collisionMapping[collision.globalIndex()], trackMapping[Bplus.prong0Id()], trackMapping[Bplus.prong1Id()], trackMapping[Bplus.prong2Id()]); + for (const auto& BplusCandidate : BplusCandidates) { + jethfutilities::fillHFCandidateTable(BplusCandidate, products.productsBplus.storedBplusCollisionsTable.lastIndex(), products.productsBplus.storedBplussTable, products.productsBplus.storedBplusParsTable, products.productsBplus.storedBplusParExtrasTable, products.productsBplus.storedBplusParD0sTable, products.productsBplus.storedBplusSelsTable, products.productsBplus.storedBplusMlsTable, products.productsBplus.storedBplusMlD0sTable, products.productsBplus.storedBplusMcsTable); + products.productsBplus.storedBplusIdsTable(collisionMapping[collision.globalIndex()], trackMapping[BplusCandidate.prong0Id()], trackMapping[BplusCandidate.prong1Id()], trackMapping[BplusCandidate.prong2Id()]); } } } @@ -260,7 +356,9 @@ struct JetDerivedDataWriter { std::vector particleMapping; std::vector d0McCollisionMapping; std::vector dplusMcCollisionMapping; + std::vector dstarMcCollisionMapping; std::vector lcMcCollisionMapping; + std::vector b0McCollisionMapping; std::vector bplusMcCollisionMapping; std::vector dielectronMcCollisionMapping; @@ -292,7 +390,7 @@ struct JetDerivedDataWriter { for (auto const& collision : collisions) { if (collision.isCollisionSelected()) { - products.storedJCollisionsTable(collision.posX(), collision.posY(), collision.posZ(), collision.multiplicity(), collision.centrality(), collision.centralityVariant1(), collision.hadronicRate(), collision.trackOccupancyInTimeRange(), collision.eventSel(), collision.alias_raw(), collision.triggerSel()); + 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(), collision.hadronicRate(), collision.trackOccupancyInTimeRange(), collision.eventSel(), collision.alias_raw(), collision.triggerSel()); collisionMapping[collision.globalIndex()] = products.storedJCollisionsTable.lastIndex(); products.storedJCollisionMcInfosTable(collision.weight(), collision.subGeneratorId()); products.storedJCollisionsParentIndexTable(collision.collisionId()); @@ -311,7 +409,7 @@ struct JetDerivedDataWriter { for (auto const& collision : collisions) { if (collision.isCollisionSelected()) { - const auto tracksPerCollision = tracks.sliceBy(TracksPerCollisionData, collision.globalIndex()); + const auto tracksPerCollision = tracks.sliceBy(preslices.TracksPerCollision, collision.globalIndex()); for (const auto& track : tracksPerCollision) { if (!trackSelection(track)) { // skips tracks that pass no selections. This might cause a problem with tracks matched with clusters. We should generate a track selection purely for cluster matched tracks so that they are kept. This includes also the track pT selction. continue; @@ -340,7 +438,7 @@ struct JetDerivedDataWriter { std::vector clusterStoredJTrackIDs; for (const auto& clusterTrack : cluster.matchedTracks_as()) { clusterStoredJTrackIDs.push_back(trackMapping[clusterTrack.globalIndex()]); - auto emcTracksPerTrack = emcTracks.sliceBy(EMCTrackPerTrack, clusterTrack.globalIndex()); + auto emcTracksPerTrack = emcTracks.sliceBy(preslices.EMCTrackPerTrack, clusterTrack.globalIndex()); auto emcTrackPerTrack = emcTracksPerTrack.iteratorAt(0); products.storedJTracksEMCalTable(trackMapping[clusterTrack.globalIndex()], emcTrackPerTrack.etaEmcal(), emcTrackPerTrack.phiEmcal()); } @@ -352,64 +450,88 @@ struct JetDerivedDataWriter { //!!!!!!!!!! need to add the hadronic corrected energy and delete the new dummy process function - void processD0Data(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsD0 const& D0Collisions, aod::CandidatesD0Data const& D0s) + void processD0Data(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsD0 const& D0Collisions, aod::CandidatesD0Data const& D0Candidates) { - storeD0(collision, tracks, D0Collisions, D0s); + storeD0(collision, tracks, D0Collisions, D0Candidates); } PROCESS_SWITCH(JetDerivedDataWriter, processD0Data, "write out data output tables for D0", false); - void processD0MCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsD0 const& D0Collisions, aod::CandidatesD0MCD const& D0s) + void processD0MCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsD0 const& D0Collisions, aod::CandidatesD0MCD const& D0Candidates) { - storeD0(collision, tracks, D0Collisions, D0s); + storeD0(collision, tracks, D0Collisions, D0Candidates); } PROCESS_SWITCH(JetDerivedDataWriter, processD0MCD, "write out mcd output tables for D0", false); - void processDplusData(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsDplus const& DplusCollisions, aod::CandidatesDplusData const& Dpluss) + void processDplusData(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsDplus const& DplusCollisions, aod::CandidatesDplusData const& DplusCandidates) { - storeDplus(collision, tracks, DplusCollisions, Dpluss); + storeDplus(collision, tracks, DplusCollisions, DplusCandidates); } PROCESS_SWITCH(JetDerivedDataWriter, processDplusData, "write out data output tables for Dplus", false); - void processDplusMCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsDplus const& DplusCollisions, aod::CandidatesDplusMCD const& Dpluss) + void processDplusMCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsDplus const& DplusCollisions, aod::CandidatesDplusMCD const& DplusCandidates) { - storeDplus(collision, tracks, DplusCollisions, Dpluss); + storeDplus(collision, tracks, DplusCollisions, DplusCandidates); } PROCESS_SWITCH(JetDerivedDataWriter, processDplusMCD, "write out mcd output tables for Dplus", false); - void processLcData(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsLc const& LcCollisions, aod::CandidatesLcData const& Lcs) + void processDstarData(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsDstar const& DstarCollisions, aod::CandidatesDstarData const& DstarCandidates) + { + storeDstar(collision, tracks, DstarCollisions, DstarCandidates); + } + PROCESS_SWITCH(JetDerivedDataWriter, processDstarData, "write out data output tables for Dstar", false); + + void processDstarMCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsDstar const& DstarCollisions, aod::CandidatesDstarMCD const& DstarCandidates) { - storeLc(collision, tracks, LcCollisions, Lcs); + storeDstar(collision, tracks, DstarCollisions, DstarCandidates); + } + PROCESS_SWITCH(JetDerivedDataWriter, processDstarMCD, "write out mcd output tables for Dstar", false); + + void processLcData(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsLc const& LcCollisions, aod::CandidatesLcData const& LcCandidates) + { + storeLc(collision, tracks, LcCollisions, LcCandidates); } PROCESS_SWITCH(JetDerivedDataWriter, processLcData, "write out data output tables for Lc", false); - void processLcMCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsLc const& LcCollisions, aod::CandidatesLcMCD const& Lcs) + void processLcMCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsLc const& LcCollisions, aod::CandidatesLcMCD const& LcCandidates) { - storeLc(collision, tracks, LcCollisions, Lcs); + storeLc(collision, tracks, LcCollisions, LcCandidates); } PROCESS_SWITCH(JetDerivedDataWriter, processLcMCD, "write out mcd output tables for Lc", false); - void processBplusData(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsBplus const& BplusCollisions, aod::CandidatesBplusData const& Bpluss) + void processB0Data(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsB0 const& B0Collisions, aod::CandidatesB0Data const& B0Candidates) { - storeBplus(collision, tracks, BplusCollisions, Bpluss); + storeB0(collision, tracks, B0Collisions, B0Candidates); + } + PROCESS_SWITCH(JetDerivedDataWriter, processB0Data, "write out data output tables for B0", false); + + void processB0MCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsB0 const& B0Collisions, aod::CandidatesB0MCD const& B0Candidates) + { + storeB0(collision, tracks, B0Collisions, B0Candidates); + } + PROCESS_SWITCH(JetDerivedDataWriter, processB0MCD, "write out mcd output tables for B0", false); + + void processBplusData(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsBplus const& BplusCollisions, aod::CandidatesBplusData const& BplusCandidates) + { + storeBplus(collision, tracks, BplusCollisions, BplusCandidates); } PROCESS_SWITCH(JetDerivedDataWriter, processBplusData, "write out data output tables for bplus", false); - void processBplusMCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsBplus const& BplusCollisions, aod::CandidatesBplusMCD const& Bpluss) + void processBplusMCD(soa::Join::iterator const& collision, aod::JTracks const& tracks, aod::CollisionsBplus const& BplusCollisions, aod::CandidatesBplusMCD const& BplusCandidates) { - storeBplus(collision, tracks, BplusCollisions, Bpluss); + storeBplus(collision, tracks, BplusCollisions, BplusCandidates); } PROCESS_SWITCH(JetDerivedDataWriter, processBplusMCD, "write out mcd output tables for bplus", false); - void processDielectron(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsDielectron const& DielectronCollisions, aod::CandidatesDielectronData const& Dielectrons) + void processDielectron(soa::Join::iterator const& collision, aod::JTracks const&, aod::CollisionsDielectron const& DielectronCollisions, aod::CandidatesDielectronData const& DielectronCandidates) { if (collision.isCollisionSelected()) { for (const auto& DielectronCollision : DielectronCollisions) { // should only ever be one - jetdqutilities::fillDielectronCollisionTable(DielectronCollision, products.storedDielectronCollisionsTable); - products.storedDielectronCollisionIdsTable(collisionMapping[collision.globalIndex()]); + jetdqutilities::fillDielectronCollisionTable(DielectronCollision, products.productsDielectron.storedDielectronCollisionsTable); + products.productsDielectron.storedDielectronCollisionIdsTable(collisionMapping[collision.globalIndex()]); } - for (const auto& Dielectron : Dielectrons) { - jetdqutilities::fillDielectronCandidateTable(Dielectron, products.storedDielectronCollisionsTable.lastIndex(), products.storedDielectronsTable); - products.storedDielectronIdsTable(collisionMapping[collision.globalIndex()], trackMapping[Dielectron.prong0Id()], trackMapping[Dielectron.prong1Id()]); + for (const auto& DielectronCandidate : DielectronCandidates) { + jetdqutilities::fillDielectronCandidateTable(DielectronCandidate, products.productsDielectron.storedDielectronCollisionsTable.lastIndex(), products.productsDielectron.storedDielectronsTable); + products.productsDielectron.storedDielectronIdsTable(collisionMapping[collision.globalIndex()], trackMapping[DielectronCandidate.prong0Id()], trackMapping[DielectronCandidate.prong1Id()]); } } } @@ -421,7 +543,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.weight(), mcCollision.subGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr()); + products.storedJMcCollisionsTable(mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), mcCollision.multFV0A(), mcCollision.multFT0A(), mcCollision.multFT0C(), mcCollision.centFV0A(), mcCollision.centFT0A(), mcCollision.centFT0C(), mcCollision.centFT0M(), mcCollision.weight(), mcCollision.subGeneratorId(), mcCollision.accepted(), mcCollision.attempted(), mcCollision.xsectGen(), mcCollision.xsectErr(), mcCollision.ptHard()); products.storedJMcCollisionsParentIndexTable(mcCollision.mcCollisionId()); mcCollisionMapping[mcCollision.globalIndex()] = products.storedJMcCollisionsTable.lastIndex(); } @@ -437,7 +559,7 @@ struct JetDerivedDataWriter { for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - const auto particlesPerMcCollision = particles.sliceBy(ParticlesPerMcCollision, mcCollision.globalIndex()); + const auto particlesPerMcCollision = particles.sliceBy(preslices.ParticlesPerMcCollision, mcCollision.globalIndex()); for (auto particle : particlesPerMcCollision) { particleMapping[particle.globalIndex()] = particleTableIndex; @@ -477,16 +599,16 @@ struct JetDerivedDataWriter { d0McCollisionMapping.resize(D0McCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - const auto d0McCollisionsPerMcCollision = D0McCollisions.sliceBy(D0McCollisionsPerMcCollision, mcCollision.globalIndex()); + const auto d0McCollisionsPerMcCollision = D0McCollisions.sliceBy(preslices.D0McCollisionsPerMcCollision, mcCollision.globalIndex()); for (const auto& d0McCollisionPerMcCollision : d0McCollisionsPerMcCollision) { - jethfutilities::fillHFMcCollisionTable(d0McCollisionPerMcCollision, products.storedD0McCollisionsTable); - products.storedD0McCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); - d0McCollisionMapping[d0McCollisionPerMcCollision.globalIndex()] = products.storedD0McCollisionsTable.lastIndex(); + jethfutilities::fillHFMcCollisionTable(d0McCollisionPerMcCollision, products.productsD0.storedD0McCollisionsTable); + products.productsD0.storedD0McCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); + d0McCollisionMapping[d0McCollisionPerMcCollision.globalIndex()] = products.productsD0.storedD0McCollisionsTable.lastIndex(); } - const auto d0ParticlesPerMcCollision = D0Particles.sliceBy(D0ParticlesPerMcCollision, mcCollision.globalIndex()); + const auto d0ParticlesPerMcCollision = D0Particles.sliceBy(preslices.D0ParticlesPerMcCollision, mcCollision.globalIndex()); for (const auto& D0Particle : d0ParticlesPerMcCollision) { - jethfutilities::fillHFCandidateMcTable(D0Particle, products.storedD0McCollisionsTable.lastIndex(), products.storedD0ParticlesTable); - products.storedD0ParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[D0Particle.mcParticleId()]); + jethfutilities::fillHFCandidateMcTable(D0Particle, products.productsD0.storedD0McCollisionsTable.lastIndex(), products.productsD0.storedD0ParticlesTable); + products.productsD0.storedD0ParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[D0Particle.mcParticleId()]); } } } @@ -499,62 +621,104 @@ struct JetDerivedDataWriter { dplusMcCollisionMapping.resize(DplusMcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - const auto dplusMcCollisionsPerMcCollision = DplusMcCollisions.sliceBy(DplusMcCollisionsPerMcCollision, mcCollision.globalIndex()); + const auto dplusMcCollisionsPerMcCollision = DplusMcCollisions.sliceBy(preslices.DplusMcCollisionsPerMcCollision, mcCollision.globalIndex()); for (const auto& dplusMcCollisionPerMcCollision : dplusMcCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillHFMcCollisionTable(dplusMcCollisionPerMcCollision, products.storedDplusMcCollisionsTable); - products.storedDplusMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); - dplusMcCollisionMapping[dplusMcCollisionPerMcCollision.globalIndex()] = products.storedDplusMcCollisionsTable.lastIndex(); + jethfutilities::fillHFMcCollisionTable(dplusMcCollisionPerMcCollision, products.productsDplus.storedDplusMcCollisionsTable); + products.productsDplus.storedDplusMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); + dplusMcCollisionMapping[dplusMcCollisionPerMcCollision.globalIndex()] = products.productsDplus.storedDplusMcCollisionsTable.lastIndex(); } - const auto dplusParticlesPerMcCollision = DplusParticles.sliceBy(DplusParticlesPerMcCollision, mcCollision.globalIndex()); + const auto dplusParticlesPerMcCollision = DplusParticles.sliceBy(preslices.DplusParticlesPerMcCollision, mcCollision.globalIndex()); for (const auto& DplusParticle : dplusParticlesPerMcCollision) { - jethfutilities::fillHFCandidateMcTable(DplusParticle, products.storedDplusMcCollisionsTable.lastIndex(), products.storedDplusParticlesTable); - products.storedDplusParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DplusParticle.mcParticleId()]); + jethfutilities::fillHFCandidateMcTable(DplusParticle, products.productsDplus.storedDplusMcCollisionsTable.lastIndex(), products.productsDplus.storedDplusParticlesTable); + products.productsDplus.storedDplusParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DplusParticle.mcParticleId()]); } } } } - PROCESS_SWITCH(JetDerivedDataWriter, processDplusMCP, "write out Dplus mcp output tables", false); + void processDstarMCP(soa::Join const& mcCollisions, aod::McCollisionsDstar const& DstarMcCollisions, aod::CandidatesDstarMCP const& DstarParticles) + { + dstarMcCollisionMapping.clear(); + dstarMcCollisionMapping.resize(DstarMcCollisions.size(), -1); + for (auto const& mcCollision : mcCollisions) { + if (mcCollision.isMcCollisionSelected()) { + const auto dstarMcCollisionsPerMcCollision = DstarMcCollisions.sliceBy(preslices.DstarMcCollisionsPerMcCollision, mcCollision.globalIndex()); + for (const auto& dstarMcCollisionPerMcCollision : dstarMcCollisionsPerMcCollision) { + jethfutilities::fillHFMcCollisionTable(dstarMcCollisionPerMcCollision, products.productsDstar.storedDstarMcCollisionsTable); + products.productsDstar.storedDstarMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); + dstarMcCollisionMapping[dstarMcCollisionPerMcCollision.globalIndex()] = products.productsDstar.storedDstarMcCollisionsTable.lastIndex(); + } + const auto dstarParticlesPerMcCollision = DstarParticles.sliceBy(preslices.DstarParticlesPerMcCollision, mcCollision.globalIndex()); + for (const auto& DstarParticle : dstarParticlesPerMcCollision) { + jethfutilities::fillHFCandidateMcTable(DstarParticle, products.productsDstar.storedDstarMcCollisionsTable.lastIndex(), products.productsDstar.storedDstarParticlesTable); + products.productsDstar.storedDstarParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DstarParticle.mcParticleId()]); + } + } + } + } + PROCESS_SWITCH(JetDerivedDataWriter, processDstarMCP, "write out D* mcp output tables", false); + void processLcMCP(soa::Join const& mcCollisions, aod::McCollisionsLc const& LcMcCollisions, aod::CandidatesLcMCP const& LcParticles) { lcMcCollisionMapping.clear(); lcMcCollisionMapping.resize(LcMcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - const auto lcMcCollisionsPerMcCollision = LcMcCollisions.sliceBy(LcMcCollisionsPerMcCollision, mcCollision.globalIndex()); + const auto lcMcCollisionsPerMcCollision = LcMcCollisions.sliceBy(preslices.LcMcCollisionsPerMcCollision, mcCollision.globalIndex()); for (const auto& lcMcCollisionPerMcCollision : lcMcCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillHFMcCollisionTable(lcMcCollisionPerMcCollision, products.storedLcMcCollisionsTable); - products.storedLcMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); - lcMcCollisionMapping[lcMcCollisionPerMcCollision.globalIndex()] = products.storedLcMcCollisionsTable.lastIndex(); + jethfutilities::fillHFMcCollisionTable(lcMcCollisionPerMcCollision, products.productsLc.storedLcMcCollisionsTable); + products.productsLc.storedLcMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); + lcMcCollisionMapping[lcMcCollisionPerMcCollision.globalIndex()] = products.productsLc.storedLcMcCollisionsTable.lastIndex(); } - const auto lcParticlesPerMcCollision = LcParticles.sliceBy(LcParticlesPerMcCollision, mcCollision.globalIndex()); + const auto lcParticlesPerMcCollision = LcParticles.sliceBy(preslices.LcParticlesPerMcCollision, mcCollision.globalIndex()); for (const auto& LcParticle : lcParticlesPerMcCollision) { - jethfutilities::fillHFCandidateMcTable(LcParticle, products.storedLcMcCollisionsTable.lastIndex(), products.storedLcParticlesTable); - products.storedLcParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[LcParticle.mcParticleId()]); + jethfutilities::fillHFCandidateMcTable(LcParticle, products.productsLc.storedLcMcCollisionsTable.lastIndex(), products.productsLc.storedLcParticlesTable); + products.productsLc.storedLcParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[LcParticle.mcParticleId()]); } } } } - PROCESS_SWITCH(JetDerivedDataWriter, processLcMCP, "write out Lc mcp output tables", false); + void processB0MCP(soa::Join const& mcCollisions, aod::McCollisionsB0 const& B0McCollisions, aod::CandidatesB0MCP const& B0Particles) + { + b0McCollisionMapping.clear(); + b0McCollisionMapping.resize(B0McCollisions.size(), -1); + for (auto const& mcCollision : mcCollisions) { + if (mcCollision.isMcCollisionSelected()) { + const auto b0McCollisionsPerMcCollision = B0McCollisions.sliceBy(preslices.B0McCollisionsPerMcCollision, mcCollision.globalIndex()); + for (const auto& b0McCollisionPerMcCollision : b0McCollisionsPerMcCollision) { // should only ever be one + jethfutilities::fillHFMcCollisionTable(b0McCollisionPerMcCollision, products.productsB0.storedB0McCollisionsTable); + products.productsB0.storedB0McCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); + b0McCollisionMapping[b0McCollisionPerMcCollision.globalIndex()] = products.productsB0.storedB0McCollisionsTable.lastIndex(); + } + const auto b0ParticlesPerMcCollision = B0Particles.sliceBy(preslices.B0ParticlesPerMcCollision, mcCollision.globalIndex()); + for (const auto& B0Particle : b0ParticlesPerMcCollision) { + jethfutilities::fillHFCandidateMcTable(B0Particle, products.productsB0.storedB0McCollisionsTable.lastIndex(), products.productsB0.storedB0ParticlesTable); + products.productsB0.storedB0ParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[B0Particle.mcParticleId()]); + } + } + } + } + PROCESS_SWITCH(JetDerivedDataWriter, processB0MCP, "write out B0 mcp output tables", false); + void processBplusMCP(soa::Join const& mcCollisions, aod::McCollisionsBplus const& BplusMcCollisions, aod::CandidatesBplusMCP const& BplusParticles) { bplusMcCollisionMapping.clear(); bplusMcCollisionMapping.resize(BplusMcCollisions.size(), -1); for (auto const& mcCollision : mcCollisions) { if (mcCollision.isMcCollisionSelected()) { - const auto bplusMcCollisionsPerMcCollision = BplusMcCollisions.sliceBy(BplusMcCollisionsPerMcCollision, mcCollision.globalIndex()); + const auto bplusMcCollisionsPerMcCollision = BplusMcCollisions.sliceBy(preslices.BplusMcCollisionsPerMcCollision, mcCollision.globalIndex()); for (const auto& bplusMcCollisionPerMcCollision : bplusMcCollisionsPerMcCollision) { // should only ever be one - jethfutilities::fillHFMcCollisionTable(bplusMcCollisionPerMcCollision, products.storedBplusMcCollisionsTable); - products.storedBplusMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); - bplusMcCollisionMapping[bplusMcCollisionPerMcCollision.globalIndex()] = products.storedBplusMcCollisionsTable.lastIndex(); + jethfutilities::fillHFMcCollisionTable(bplusMcCollisionPerMcCollision, products.productsBplus.storedBplusMcCollisionsTable); + products.productsBplus.storedBplusMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); + bplusMcCollisionMapping[bplusMcCollisionPerMcCollision.globalIndex()] = products.productsBplus.storedBplusMcCollisionsTable.lastIndex(); } - const auto bplusParticlesPerMcCollision = BplusParticles.sliceBy(BplusParticlesPerMcCollision, mcCollision.globalIndex()); + const auto bplusParticlesPerMcCollision = BplusParticles.sliceBy(preslices.BplusParticlesPerMcCollision, mcCollision.globalIndex()); for (const auto& BplusParticle : bplusParticlesPerMcCollision) { - jethfutilities::fillHFCandidateMcTable(BplusParticle, products.storedBplusMcCollisionsTable.lastIndex(), products.storedBplusParticlesTable); - products.storedBplusParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[BplusParticle.mcParticleId()]); + jethfutilities::fillHFCandidateMcTable(BplusParticle, products.productsBplus.storedBplusMcCollisionsTable.lastIndex(), products.productsBplus.storedBplusParticlesTable); + products.productsBplus.storedBplusParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[BplusParticle.mcParticleId()]); } } } @@ -565,14 +729,14 @@ struct JetDerivedDataWriter { { if (mcCollision.isMcCollisionSelected()) { - const auto dielectronMcCollisionsPerMcCollision = DielectronMcCollisions.sliceBy(DielectronMcCollisionsPerMcCollision, mcCollision.globalIndex()); + const auto dielectronMcCollisionsPerMcCollision = DielectronMcCollisions.sliceBy(preslices.DielectronMcCollisionsPerMcCollision, mcCollision.globalIndex()); for (const auto& dielectronMcCollisionPerMcCollision : dielectronMcCollisionsPerMcCollision) { // should only ever be one - jetdqutilities::fillDielectronMcCollisionTable(dielectronMcCollisionPerMcCollision, products.storedDielectronMcCollisionsTable); - products.storedDielectronMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); - products.storedDielectronMcRCollDummysTable(dielectronMcCollisionPerMcCollision.dummyDQ()); + jetdqutilities::fillDielectronMcCollisionTable(dielectronMcCollisionPerMcCollision, products.productsDielectron.storedDielectronMcCollisionsTable); + products.productsDielectron.storedDielectronMcCollisionIdsTable(mcCollisionMapping[mcCollision.globalIndex()]); + products.productsDielectron.storedDielectronMcRCollDummysTable(dielectronMcCollisionPerMcCollision.dummyDQ()); } for (const auto& DielectronParticle : DielectronParticles) { - jetdqutilities::fillDielectronCandidateMcTable(DielectronParticle, products.storedDielectronMcCollisionsTable.lastIndex(), products.storedDielectronParticlesTable); + jetdqutilities::fillDielectronCandidateMcTable(DielectronParticle, products.productsDielectron.storedDielectronMcCollisionsTable.lastIndex(), products.productsDielectron.storedDielectronParticlesTable); std::vector DielectronMothersIds; int DielectronDaughtersId[2]; if (DielectronParticle.has_mothers()) { @@ -590,7 +754,7 @@ struct JetDerivedDataWriter { i++; } } - products.storedDielectronParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DielectronParticle.mcParticleId()], DielectronMothersIds, DielectronDaughtersId); + products.productsDielectron.storedDielectronParticleIdsTable(mcCollisionMapping[mcCollision.globalIndex()], particleMapping[DielectronParticle.mcParticleId()], DielectronMothersIds, DielectronDaughtersId); } } } @@ -646,7 +810,7 @@ struct JetDerivedDataWriter { for (auto const& d0CollisionPerMcCollision : D0McCollision.hfCollBases_as()) { d0CollisionIDs.push_back(d0McCollisionMapping[d0CollisionPerMcCollision.globalIndex()]); } - products.storedD0McCollisionsMatchingTable(d0CollisionIDs); + products.productsD0.storedD0McCollisionsMatchingTable(d0CollisionIDs); } } } @@ -660,12 +824,26 @@ struct JetDerivedDataWriter { for (auto const& dplusCollisionPerMcCollision : DplusMcCollision.hfCollBases_as()) { dplusCollisionIDs.push_back(dplusMcCollisionMapping[dplusCollisionPerMcCollision.globalIndex()]); } - products.storedDplusMcCollisionsMatchingTable(dplusCollisionIDs); + products.productsDplus.storedDplusMcCollisionsMatchingTable(dplusCollisionIDs); } } } PROCESS_SWITCH(JetDerivedDataWriter, processDplusMcCollisionMatch, "write out Dplus McCollision collision label output tables", false); + void processDstarMcCollisionMatch(soa::Join::iterator const& mcCollision, soa::Join const& DstarMcCollisions, aod::CollisionsDstar const&) + { + if (mcCollision.isMcCollisionSelected()) { + for (const auto& DstarMcCollision : DstarMcCollisions) { // should just be one + std::vector dstarCollisionIDs; + for (auto const& dstarCollisionPerMcCollision : DstarMcCollision.hfCollBases_as()) { + dstarCollisionIDs.push_back(dstarMcCollisionMapping[dstarCollisionPerMcCollision.globalIndex()]); + } + products.productsDstar.storedDstarMcCollisionsMatchingTable(dstarCollisionIDs); + } + } + } + PROCESS_SWITCH(JetDerivedDataWriter, processDstarMcCollisionMatch, "write out D* McCollision collision label output tables", false); + void processLcMcCollisionMatch(soa::Join::iterator const& mcCollision, soa::Join const& LcMcCollisions, aod::CollisionsLc const&) { if (mcCollision.isMcCollisionSelected()) { @@ -674,12 +852,26 @@ struct JetDerivedDataWriter { for (auto const& lcCollisionPerMcCollision : LcMcCollision.hfCollBases_as()) { lcCollisionIDs.push_back(lcMcCollisionMapping[lcCollisionPerMcCollision.globalIndex()]); } - products.storedLcMcCollisionsMatchingTable(lcCollisionIDs); + products.productsLc.storedLcMcCollisionsMatchingTable(lcCollisionIDs); } } } PROCESS_SWITCH(JetDerivedDataWriter, processLcMcCollisionMatch, "write out Lc McCollision collision label output tables", false); + void processB0McCollisionMatch(soa::Join::iterator const& mcCollision, soa::Join const& B0McCollisions, aod::CollisionsB0 const&) + { + if (mcCollision.isMcCollisionSelected()) { + for (const auto& B0McCollision : B0McCollisions) { // should just be one + std::vector b0CollisionIDs; + for (auto const& b0CollisionPerMcCollision : B0McCollision.hfCollBases_as()) { + b0CollisionIDs.push_back(b0McCollisionMapping[b0CollisionPerMcCollision.globalIndex()]); + } + products.productsB0.storedB0McCollisionsMatchingTable(b0CollisionIDs); + } + } + } + PROCESS_SWITCH(JetDerivedDataWriter, processB0McCollisionMatch, "write out B0 McCollision collision label output tables", false); + void processBplusMcCollisionMatch(soa::Join::iterator const& mcCollision, soa::Join const& BplusMcCollisions, aod::CollisionsBplus const&) { if (mcCollision.isMcCollisionSelected()) { @@ -688,7 +880,7 @@ struct JetDerivedDataWriter { for (auto const& bplusCollisionPerMcCollision : BplusMcCollision.hfCollBases_as()) { bplusCollisionIDs.push_back(bplusMcCollisionMapping[bplusCollisionPerMcCollision.globalIndex()]); } - products.storedBplusMcCollisionsMatchingTable(bplusCollisionIDs); + products.productsBplus.storedBplusMcCollisionsMatchingTable(bplusCollisionIDs); } } } diff --git a/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx b/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx index 69e1f1051dc..67672c53222 100644 --- a/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalClusterHadronicCorrectionTask.cxx @@ -12,28 +12,26 @@ // **Hadronic Correction in the EMCAL framework: to avoid the double counting of the charged particles' contribution in jets** /// \author Archita Rani Dash -#include -#include -#include -#include -#include -#include -#include "TVector2.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include -#include "DetectorsBase/GeometryManager.h" - -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetUtilities.h" +#include "TVector2.h" +#include -#include "CommonDataFormat/InteractionRecord.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -89,7 +87,7 @@ struct EmcalClusterHadronicCorrectionTask { registry.add("h_Ecluster2", "; Ecluster2 (GeV); entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h_EclusterAll1", "; EclusterAll1 (GeV); entries", {HistType::kTH1F, {{350, 0., 350.}}}); registry.add("h_EclusterAll2", "; EclusterAll2 (GeV); entries", {HistType::kTH1F, {{350, 0., 350.}}}); - registry.add("h_ClsTime", "Cluster time distribution of uncorrected cluster E; #it{t}_{cls} (ns); entries", {HistType::kTH1F, {{500, -250., 250.}}}); + registry.add("h_ClsTime", "Cluster time distribution of uncorrected cluster E; #it{t}_{cls} (ns); entries", {HistType::kTH1F, {{1500, -600., 900.}}}); registry.add("h_ClsM02", "Cluster M02 distribution of uncorrected cluster E; #it{M}_{02}; entries", {HistType::kTH1F, {{400, 0., 5.}}}); registry.add("h2_ClsEvsNmatches", "Original cluster energy vs Nmatches; Cls E w/o correction (GeV); Nmatches", {HistType::kTH2F, {{350, 0., 350.}, {100, -0.5, 21.}}}); registry.add("h2_ClsEvsEcluster1", "; Cls E w/o correction (GeV); Ecluster1 (GeV)", {HistType::kTH2F, {{350, 0., 350.}, {350, 0., 350.}}}); diff --git a/PWGJE/TableProducer/emcalCorrectionTask.cxx b/PWGJE/TableProducer/emcalCorrectionTask.cxx index 1c1261827de..1935748a4a0 100644 --- a/PWGJE/TableProducer/emcalCorrectionTask.cxx +++ b/PWGJE/TableProducer/emcalCorrectionTask.cxx @@ -18,58 +18,67 @@ /// \author Raymond Ehlers (raymond.ehlers@cern.ch) ORNL, Florian Jonas (florian.jonas@cern.ch) /// -#include +#include "PWGJE/Core/emcalCrossTalkEmulation.h" +#include "PWGJE/Core/utilsTrackMatchingEMC.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" + +#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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisHelpers.h" -#include "Framework/ASoA.h" -#include "Framework/Configurable.h" -#include "Framework/Expressions.h" -#include "Framework/HistogramSpec.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/InitContext.h" -#include "Framework/WorkflowSpec.h" - -#include "DetectorsBase/GeometryManager.h" - -#include "PWGJE/DataModel/EMCALClusterDefinition.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/EMCALMatchedCollisions.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "DataFormatsEMCAL/ClusterLabel.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/CellLabel.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "EMCALBase/Geometry.h" -#include "EMCALBase/ClusterFactory.h" -#include "EMCALBase/NonlinearityHandler.h" -#include "EMCALReconstruction/Clusterizer.h" -#include "PWGJE/Core/JetUtilities.h" -#include "GPUROOTCartesianFwd.h" -#include "TVector2.h" -#include "TH1.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::emccrosstalk; +using namespace tmemcutilities; using MyGlobTracks = o2::soa::Join; using BcEvSels = o2::soa::Join; using CollEventSels = o2::soa::Join; @@ -77,6 +86,13 @@ using FilteredCells = o2::soa::Filtered; using McCells = o2::soa::Join; using FilteredMcCells = o2::soa::Filtered; +enum CellScaleMode { + ModeNone = 0, + ModeSMWise = 1, + ModeColumnWise = 2, + NumberModes = 3 +}; + struct EmcalCorrectionTask { Produces clusters; Produces mcclusters; @@ -114,6 +130,19 @@ struct EmcalCorrectionTask { Configurable applyCellTimeCorrection{"applyCellTimeCorrection", true, "apply a correction to the cell time for data and MC: Shift both average cell times to 0 and smear MC time distribution to fit data better. For MC requires isMC to be true"}; Configurable trackMinPt{"trackMinPt", 0.3, "Minimum pT for tracks to perform track matching, to reduce computing time. Tracks below a certain pT will be loopers anyway."}; Configurable fillQA{"fillQA", false, "Switch to turn on QA histograms."}; + Configurable useCCDBAlignment{"useCCDBAlignment", false, "EXPERTS ONLY! Switch to use the alignment object stored in CCDB instead of using the default alignment from the global geometry object."}; + Configurable applyTempCalib{"applyTempCalib", false, "Switch to turn on Temperature calibration."}; + Configurable pathTempCalibCCDB{"pathTempCalibCCDB", "Users/j/jokonig/EMCalTempCalibParams", "Path in the ccdb where slope and intercept for each cell are stored"}; // change to official path as soon as it is available + Configurable useTempCalibMean{"useTempCalibMean", false, "Switch to turn on Temperature mean calculation instead of median."}; + 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)"}; + + // cross talk emulation configs + EmcCrossTalkConf emcCrossTalkConf; + + // cross talk emulation class for handling the cross talk + emccrosstalk::EMCCrossTalk emcCrossTalk; // Require EMCAL cells (CALO type 1) Filter emccellfilter = aod::calo::caloType == selectedCellType; @@ -143,11 +172,20 @@ struct EmcalCorrectionTask { // EMCal geometry o2::emcal::Geometry* geometry; + // EMCal cell temperature calibrator + std::unique_ptr mTempCalibExtractor; + bool mIsTempCalibInitialized = false; + + // Gain calibration + std::array mArrGainCalibDiff; + std::vector> mExtraTimeShiftRunRanges; // Current run number int runNumber{0}; + static constexpr float TrackNotOnEMCal = -900.f; + void init(InitContext const&) { LOG(debug) << "Start init!"; @@ -168,6 +206,18 @@ struct EmcalCorrectionTask { if (!geometry) { LOG(error) << "Failure accessing geometry"; } + if (useCCDBAlignment.value) { + geometry->SetMisalMatrixFromCcdb(); + } + + if (applyTempCalib) { + mTempCalibExtractor = std::make_unique(); + } + + // gain calibration shift initialization + if (applyGainCalibShift) { + initializeGainCalibShift(); + } // read all the cluster definitions specified in the options if (clusterDefinitions->length()) { @@ -213,12 +263,15 @@ struct EmcalCorrectionTask { // Define the cell energy binning std::vector cellEnergyBins; - for (int i = 0; i < 51; i++) + for (int i = 0; i < 51; i++) { // o2-linter: disable=magic-number (just numbers for binning) cellEnergyBins.emplace_back(0.1 * (i - 0) + 0.0); // from 0 to 5 GeV/c, every 0.1 GeV - for (int i = 51; i < 76; i++) + } + for (int i = 51; i < 76; i++) { // o2-linter: disable=magic-number (just numbers for binning) cellEnergyBins.emplace_back(0.2 * (i - 51) + 5.2); // from 5.2 to 10.0 GeV, every 0.2 GeV - for (int i = 76; i < 166; i++) + } + for (int i = 76; i < 166; i++) { // o2-linter: disable=magic-number (just numbers for binning) cellEnergyBins.emplace_back(1. * (i - 76) + 11.); // from 11.0 to 100. GeV, every 1 GeV + } // Setup QA hists. // NOTE: This is not comprehensive. @@ -231,12 +284,14 @@ struct EmcalCorrectionTask { fCrossAxis{100, 0., 1., "F_{+}"}, sigmaLongAxis{100, 0., 1.0, "#sigma^{2}_{long}"}, sigmaShortAxis{100, 0., 1.0, "#sigma^{2}_{short}"}, - nCellAxis{60, -0.5, 59.5, "#it{n}_{cells}"}; + nCellAxis{60, -0.5, 59.5, "#it{n}_{cells}"}, + energyDenseAxis = {7000, 0.f, 70.f, "#it{E}_{cell} (GeV)"}; mHistManager.add("hCellE", "hCellE", O2HistType::kTH1D, {energyAxis}); mHistManager.add("hCellTowerID", "hCellTowerID", O2HistType::kTH1D, {{20000, 0, 20000}}); mHistManager.add("hCellEtaPhi", "hCellEtaPhi", O2HistType::kTH2F, {etaAxis, phiAxis}); mHistManager.add("hHGCellTimeEnergy", "hCellTime", O2HistType::kTH2F, {{300, -30, 30}, cellEnergyBins}); // Cell time vs energy for high gain cells (low energies) mHistManager.add("hLGCellTimeEnergy", "hCellTime", O2HistType::kTH2F, {{300, -30, 30}, cellEnergyBins}); // Cell time vs energy for low gain cells (high energies) + mHistManager.add("hTempCalibCorrection", "hTempCalibCorrection", O2HistType::kTH1F, {{5000, 0.5, 1.5}}); // NOTE: Reversed column and row because it's more natural for presentation. mHistManager.add("hCellRowCol", "hCellRowCol;Column;Row", O2HistType::kTH2D, {{96, -0.5, 95.5}, {208, -0.5, 207.5}}); mHistManager.add("hClusterE", "hClusterE", O2HistType::kTH1D, {energyAxis}); @@ -283,6 +338,14 @@ struct EmcalCorrectionTask { mHistManager.add("hClusterFCrossSigmaShortE", "hClusterFCrossSigmaShortE", O2HistType::kTH3F, {energyAxis, fCrossAxis, sigmaShortAxis}); } + if (isMC.value && emcCrossTalkConf.enableCrossTalk.value) { + emcCrossTalk.initObjects(emcCrossTalkConf); + if (emcCrossTalkConf.createHistograms.value) { + mHistManager.add("hCellEnergyDistBefore", "Cell energy before cross-talk emulation", {o2::framework::HistType::kTH1D, {energyDenseAxis}}); + mHistManager.add("hCellEnergyDistAfter", "Cell energy after cross-talk emulation", {o2::framework::HistType::kTH1D, {energyDenseAxis}}); + } + } + // For some runs, LG cells require an extra time shift of 2 * 8.8ns due to problems in the time calibration // Affected run ranges (inclusive) are initialised here (min,max) mExtraTimeShiftRunRanges.emplace_back(535365, 535645); // LHC23g-LHC23h @@ -314,6 +377,11 @@ struct EmcalCorrectionTask { // get run number runNumber = bc.runNumber(); + if (applyTempCalib && !mIsTempCalibInitialized) { // needs to be called once + mTempCalibExtractor->InitializeFromCCDB(pathTempCalibCCDB, static_cast(runNumber)); + mIsTempCalibInitialized = true; + } + // Convert aod::Calo to o2::emcal::Cell which can be used with the clusterizer. // In particular, we need to filter only EMCAL cells. @@ -341,6 +409,14 @@ struct EmcalCorrectionTask { if (applyCellAbsScale) { amplitude *= getAbsCellScale(cell.cellNumber()); } + if (applyGainCalibShift) { + amplitude *= mArrGainCalibDiff[cell.cellNumber()]; + } + if (applyTempCalib) { + float tempCalibFactor = mTempCalibExtractor->getGainCalibFactor(static_cast(cell.cellNumber())); + amplitude /= tempCalibFactor; + mHistManager.fill(HIST("hTempCalibCorrection"), tempCalibFactor); + } cellsBC.emplace_back(cell.cellNumber(), amplitude, cell.time() + getCellTimeShift(cell.cellNumber(), amplitude, o2::emcal::intToChannelType(cell.cellType()), runNumber), @@ -352,12 +428,6 @@ struct EmcalCorrectionTask { fillQAHistogram(cellsBC); - // TODO: Helpful for now, but should be removed. - LOG(debug) << "Converted EMCAL cells"; - for (const auto& cell : cellsBC) { - LOG(debug) << cell.getTower() << ": E: " << cell.getEnergy() << ", time: " << cell.getTimeStamp() << ", type: " << cell.getType(); - } - LOG(debug) << "Converted cells. Contains: " << cellsBC.size() << ". Originally " << cellsInBC.size() << ". About to run clusterizer."; // this is a test // Run the clusterizers @@ -382,9 +452,9 @@ struct EmcalCorrectionTask { std::vector> clusterToTrackIndexMap; std::vector> trackToClusterIndexMap; - std::tuple>, std::vector>> indexMapPair{clusterToTrackIndexMap, trackToClusterIndexMap}; + MatchResult indexMapPair; std::vector trackGlobalIndex; - doTrackMatching(col, tracks, indexMapPair, vertexPos, trackGlobalIndex); + doTrackMatching(col, tracks, indexMapPair, trackGlobalIndex); // Store the clusters in the table where a matching collision could // be identified. @@ -466,30 +536,68 @@ struct EmcalCorrectionTask { mHistManager.fill(HIST("hContributors"), cell.mcParticle_as().size()); auto cellParticles = cell.mcParticle_as(); for (const auto& cellparticle : cellParticles) { + const auto& ids = cell.mcParticleIds(); + const auto& amps = cell.amplitudeA(); + + if (ids.empty() || amps.empty()) { + LOGF(warning, "Skipping cell with empty MC info: absId=%d", cell.cellNumber()); + continue; + } mHistManager.fill(HIST("hMCParticleEnergy"), cellparticle.e()); } auto amplitude = cell.amplitude(); if (static_cast(hasShaperCorrection) && emcal::intToChannelType(cell.cellType()) == emcal::ChannelType_t::LOW_GAIN) { // Apply shaper correction to LG cells amplitude = o2::emcal::NonlinearityHandler::evaluateShaperCorrectionCellEnergy(amplitude); } + if (mcCellEnergyShift != 1.) { + amplitude *= mcCellEnergyShift; // Fine tune the MC cell energy + } + if (mcCellEnergyResolutionBroadening != 0.) { + amplitude *= (1. + normalgaus(rdgen) * mcCellEnergyResolutionBroadening); // Fine tune the MC cell energy resolution + } cellsBC.emplace_back(cell.cellNumber(), amplitude, cell.time() + getCellTimeShift(cell.cellNumber(), amplitude, o2::emcal::intToChannelType(cell.cellType()), runNumber), o2::emcal::intToChannelType(cell.cellType())); cellIndicesBC.emplace_back(cell.globalIndex()); - cellLabels.emplace_back(cell.mcParticleIds(), cell.amplitudeA()); + cellLabels.emplace_back(std::vector{cell.mcParticleIds().begin(), cell.mcParticleIds().end()}, std::vector{cell.amplitudeA().begin(), cell.amplitudeA().end()}); + } + if (isMC.value && emcCrossTalkConf.enableCrossTalk.value) { + if (emcCrossTalkConf.createHistograms.value) { + for (const auto& cell : cellsBC) { + mHistManager.fill(HIST("hCellEnergyDistBefore"), cell.getAmplitude()); + } + } + emcCrossTalk.setCells(cellsBC, cellLabels); + bool isOkCrossTalk = emcCrossTalk.run(); + if (!isOkCrossTalk) { + LOG(info) << "Cross talk emulation failed!"; + } else { + // When we get new cells we also need to add additional entries into cellIndicesBC. + // Adding -1 and later when filling the clusterID<->cellID table skip all cases where this is -1 + if (cellIndicesBC.size() < cellsBC.size()) { + cellIndicesBC.reserve(cellsBC.size()); + size_t nMissing = cellsBC.size() - cellIndicesBC.size(); + cellIndicesBC.insert(cellIndicesBC.end(), nMissing, -1); + } + if (emcCrossTalkConf.createHistograms.value) { + for (const auto& cell : cellsBC) { + mHistManager.fill(HIST("hCellEnergyDistAfter"), cell.getAmplitude()); + } + } + } // cross talk emulation was okay + } // if (isMC.value && emcCrossTalkConf.enableCrossTalk.value) + // shaper correction has to come AFTER cross talk + for (auto& cell : cellsBC) { // o2-linter: disable=const-ref-in-for-loop (we are changing a value here) + if (cell.getLowGain()) { + cell.setAmplitude(o2::emcal::NonlinearityHandler::evaluateShaperCorrectionCellEnergy(cell.getAmplitude())); + } } LOG(detail) << "Number of cells for BC (CF): " << cellsBC.size(); nCellsProcessed += cellsBC.size(); fillQAHistogram(cellsBC); - // TODO: Helpful for now, but should be removed. - LOG(debug) << "Converted EMCAL cells"; - for (const auto& cell : cellsBC) { - LOG(debug) << cell.getTower() << ": E: " << cell.getEnergy() << ", time: " << cell.getTimeStamp() << ", type: " << cell.getType(); - } - LOG(debug) << "Converted cells. Contains: " << cellsBC.size() << ". Originally " << cellsInBC.size() << ". About to run clusterizer."; // this is a test // Run the clusterizers @@ -513,9 +621,9 @@ struct EmcalCorrectionTask { std::vector> clusterToTrackIndexMap; std::vector> trackToClusterIndexMap; - std::tuple>, std::vector>> indexMapPair{clusterToTrackIndexMap, trackToClusterIndexMap}; + MatchResult indexMapPair; std::vector trackGlobalIndex; - doTrackMatching(col, tracks, indexMapPair, vertexPos, trackGlobalIndex); + doTrackMatching(col, tracks, indexMapPair, trackGlobalIndex); // Store the clusters in the table where a matching collision could // be identified. @@ -575,6 +683,11 @@ struct EmcalCorrectionTask { // get run number runNumber = bc.runNumber(); + if (applyTempCalib && !mIsTempCalibInitialized) { // needs to be called once + mTempCalibExtractor->InitializeFromCCDB(pathTempCalibCCDB, static_cast(runNumber)); + mIsTempCalibInitialized = true; + } + auto collisionsInBC = collisions.sliceBy(collisionsPerBC, bc.globalIndex()); auto cellsInBC = cells.sliceBy(cellsPerFoundBC, bc.globalIndex()); @@ -588,9 +701,21 @@ struct EmcalCorrectionTask { std::vector cellsBC; std::vector cellIndicesBC; for (const auto& cell : cellsInBC) { + auto amplitude = cell.amplitude(); + if (static_cast(hasShaperCorrection) && emcal::intToChannelType(cell.cellType()) == emcal::ChannelType_t::LOW_GAIN) { // Apply shaper correction to LG cells + amplitude = o2::emcal::NonlinearityHandler::evaluateShaperCorrectionCellEnergy(amplitude); + } + if (applyGainCalibShift) { + amplitude *= mArrGainCalibDiff[cell.cellNumber()]; + } + if (applyTempCalib) { + float tempCalibFactor = mTempCalibExtractor->getGainCalibFactor(static_cast(cell.cellNumber())); + amplitude /= tempCalibFactor; + mHistManager.fill(HIST("hTempCalibCorrection"), tempCalibFactor); + } cellsBC.emplace_back(cell.cellNumber(), - cell.amplitude(), - cell.time() + getCellTimeShift(cell.cellNumber(), cell.amplitude(), o2::emcal::intToChannelType(cell.cellType()), runNumber), + amplitude, + cell.time() + getCellTimeShift(cell.cellNumber(), amplitude, o2::emcal::intToChannelType(cell.cellType()), runNumber), o2::emcal::intToChannelType(cell.cellType())); cellIndicesBC.emplace_back(cell.globalIndex()); } @@ -599,12 +724,6 @@ struct EmcalCorrectionTask { fillQAHistogram(cellsBC); - // TODO: Helpful for now, but should be removed. - LOG(debug) << "Converted EMCAL cells"; - for (const auto& cell : cellsBC) { - LOG(debug) << cell.getTower() << ": E: " << cell.getEnergy() << ", time: " << cell.getTimeStamp() << ", type: " << cell.getType(); - } - LOG(debug) << "Converted cells. Contains: " << cellsBC.size() << ". Originally " << cellsInBC.size() << ". About to run clusterizer."; // this is a test @@ -688,16 +807,16 @@ struct EmcalCorrectionTask { } template - void fillClusterTable(Collision const& col, math_utils::Point3D const& vertexPos, size_t iClusterizer, const gsl::span cellIndicesBC, const std::tuple>, std::vector>>* indexMapPair = nullptr, const std::vector* trackGlobalIndex = nullptr) + void fillClusterTable(Collision const& col, math_utils::Point3D const& vertexPos, size_t iClusterizer, const gsl::span cellIndicesBC, MatchResult* indexMapPair = nullptr, const std::vector* trackGlobalIndex = nullptr) { // average number of cells per cluster, only used the reseve a reasonable amount for the clustercells table - const size_t NAvgNcells = 3; + const size_t nAvgNcells = 3; // we found a collision, put the clusters into the none ambiguous table clusters.reserve(mAnalysisClusters.size()); if (!mClusterLabels.empty()) { mcclusters.reserve(mClusterLabels.size()); } - clustercells.reserve(mAnalysisClusters.size() * NAvgNcells); + clustercells.reserve(mAnalysisClusters.size() * nAvgNcells); // get the clusterType once const auto clusterType = static_cast(mClusterDefinitions[iClusterizer]); @@ -741,7 +860,9 @@ struct EmcalCorrectionTask { for (int ncell = 0; ncell < cluster.getNCells(); ncell++) { cellindex = cluster.getCellIndex(ncell); LOG(debug) << "trying to find cell index " << cellindex << " in map"; - clustercells(clusters.lastIndex(), cellIndicesBC[cellindex]); + if (cellIndicesBC[cellindex] >= 0) { + clustercells(clusters.lastIndex(), cellIndicesBC[cellindex]); + } } // end of cells of cluser loop // fill histograms mHistManager.fill(HIST("hClusterE"), energy); @@ -755,10 +876,12 @@ struct EmcalCorrectionTask { mHistManager.fill(HIST("hClusterFCrossSigmaShortE"), cluster.E(), cluster.getFCross(), cluster.getM20()); } if (indexMapPair && trackGlobalIndex) { - for (unsigned int iTrack = 0; iTrack < std::get<0>(*indexMapPair)[iCluster].size(); iTrack++) { - if (std::get<0>(*indexMapPair)[iCluster][iTrack] >= 0) { - LOG(debug) << "Found track " << (*trackGlobalIndex)[std::get<0>(*indexMapPair)[iCluster][iTrack]] << " in cluster " << cluster.getID(); - matchedTracks(clusters.lastIndex(), (*trackGlobalIndex)[std::get<0>(*indexMapPair)[iCluster][iTrack]]); + if (iCluster < indexMapPair->matchIndexTrack.size() && indexMapPair->matchIndexTrack.size() > 0) { + for (unsigned int iTrack = 0; iTrack < indexMapPair->matchIndexTrack[iCluster].size(); iTrack++) { + if (indexMapPair->matchIndexTrack[iCluster][iTrack] >= 0) { + LOG(debug) << "Found track " << (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]] << " in cluster " << cluster.getID(); + matchedTracks(clusters.lastIndex(), (*trackGlobalIndex)[indexMapPair->matchIndexTrack[iCluster][iTrack]], indexMapPair->matchDeltaPhi[iCluster][iTrack], indexMapPair->matchDeltaEta[iCluster][iTrack]); + } } } } @@ -770,13 +893,13 @@ struct EmcalCorrectionTask { void fillAmbigousClusterTable(BC const& bc, size_t iClusterizer, const gsl::span cellIndicesBC, bool hasCollision) { // average number of cells per cluster, only used the reseve a reasonable amount for the clustercells table - const size_t NAvgNcells = 3; + const size_t nAvgNcells = 3; int cellindex = -1; clustersAmbiguous.reserve(mAnalysisClusters.size()); if (mClusterLabels.size() > 0) { mcclustersAmbiguous.reserve(mClusterLabels.size()); } - clustercellsambiguous.reserve(mAnalysisClusters.size() * NAvgNcells); + clustercellsambiguous.reserve(mAnalysisClusters.size() * nAvgNcells); unsigned int iCluster = 0; float energy = 0.f; for (const auto& cluster : mAnalysisClusters) { @@ -821,12 +944,12 @@ struct EmcalCorrectionTask { } template - void doTrackMatching(Collision const& col, MyGlobTracks const& tracks, std::tuple>, std::vector>>& indexMapPair, math_utils::Point3D& vertexPos, std::vector& trackGlobalIndex) + void doTrackMatching(Collision const& col, MyGlobTracks const& tracks, MatchResult& indexMapPair, std::vector& trackGlobalIndex) { auto groupedTracks = tracks.sliceBy(perCollision, col.globalIndex()); int nTracksInCol = groupedTracks.size(); - std::vector trackPhi; - std::vector trackEta; + std::vector trackPhi; + std::vector trackEta; // reserve memory to reduce on the fly memory allocation trackPhi.reserve(nTracksInCol); trackEta.reserve(nTracksInCol); @@ -834,8 +957,8 @@ struct EmcalCorrectionTask { fillTrackInfo(groupedTracks, trackPhi, trackEta, trackGlobalIndex); int nClusterInCol = mAnalysisClusters.size(); - std::vector clusterPhi; - std::vector clusterEta; + std::vector clusterPhi; + std::vector clusterEta; clusterPhi.reserve(nClusterInCol); clusterEta.reserve(nClusterInCol); @@ -845,40 +968,33 @@ struct EmcalCorrectionTask { // Determine the cluster eta, phi, correcting for the vertex // position. auto pos = cluster.getGlobalPosition(); - pos = pos - vertexPos; - // Normalize the vector and rescale by energy. - pos *= (cluster.E() / std::sqrt(pos.Mag2())); clusterPhi.emplace_back(TVector2::Phi_0_2pi(pos.Phi())); clusterEta.emplace_back(pos.Eta()); } - indexMapPair = - jetutilities::MatchClustersAndTracks(clusterPhi, clusterEta, - trackPhi, trackEta, - maxMatchingDistance, 20); + indexMapPair = matchTracksToCluster(clusterPhi, clusterEta, trackPhi, trackEta, maxMatchingDistance, 20); } template - void fillTrackInfo(Tracks const& tracks, std::vector& trackPhi, std::vector& trackEta, std::vector& trackGlobalIndex) + void fillTrackInfo(Tracks const& tracks, std::vector& trackPhi, std::vector& trackEta, std::vector& trackGlobalIndex) { int nTrack = 0; for (const auto& track : tracks) { - // TODO only consider tracks in current emcal/dcal acceptanc if (!track.isGlobalTrack()) { // only global tracks continue; } // Tracks that do not point to the EMCal/DCal/PHOS get default values of -999 // This way we can cut out tracks that do not point to the EMCal+DCal - if (track.trackEtaEmcal() < -900 || track.trackPhiEmcal() < -900) { + if (track.trackEtaEmcal() < TrackNotOnEMCal || track.trackPhiEmcal() < TrackNotOnEMCal) { continue; } if (trackMinPt > 0 && track.pt() < trackMinPt) { continue; } nTrack++; - trackPhi.emplace_back(TVector2::Phi_0_2pi(track.trackPhiEmcal())); + trackPhi.emplace_back(RecoDecay::constrainAngle(track.trackPhiEmcal())); trackEta.emplace_back(track.trackEtaEmcal()); mHistManager.fill(HIST("hGlobalTrackEtaPhi"), track.trackEtaEmcal(), - TVector2::Phi_0_2pi(track.trackPhiEmcal())); + RecoDecay::constrainAngle(track.trackPhiEmcal())); trackGlobalIndex.emplace_back(track.globalIndex()); } mHistManager.fill(HIST("hGlobalTrackMult"), nTrack); @@ -929,12 +1045,12 @@ struct EmcalCorrectionTask { { // Apply cell scale based on SM types (Full, Half (not used), EMC 1/3, DCal, DCal 1/3) // Same as in Run2 data - if (applyCellAbsScale == 1) { + if (applyCellAbsScale == CellScaleMode::ModeSMWise) { int iSM = mClusterizers.at(0)->getGeometry()->GetSuperModuleNumber(cellID); return cellAbsScaleFactors.value[mClusterizers.at(0)->getGeometry()->GetSMType(iSM)]; // Apply cell scale based on columns to accoutn for material of TRD structures - } else if (applyCellAbsScale == 2) { + } else if (applyCellAbsScale == CellScaleMode::ModeColumnWise) { auto res = mClusterizers.at(0)->getGeometry()->GlobalRowColFromIndex(cellID); return cellAbsScaleFactors.value[std::get<1>(res)]; } else { @@ -952,6 +1068,9 @@ struct EmcalCorrectionTask { } float timeshift = 0.f; float timesmear = 0.f; + const float minLeaderEnergy = 0.3f; + const float lowEnergyRegime = 4.f; + const float highEnergyRegime = 30.f; if (isMC) { // ---> MC // Shift the time to 0, as the TOF was simulated -> eta dependent shift (as larger eta values are further away from collision point) // Use distance between vertex and EMCal (at eta = 0) and distance on EMCal surface (cell size times column) to calculate distance to cell @@ -960,7 +1079,7 @@ struct EmcalCorrectionTask { timeshift = -std::sqrt(215.f + timeCol * timeCol); // 215 is 14.67ns^2 (time it takes to get the cell at eta = 0) // Also smear the time to account for the broader time resolution in data than in MC - if (cellEnergy < 0.3) // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration + if (cellEnergy < minLeaderEnergy) // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration timesmear = 0.; // They will therefore not be smeared and only get their shift else if (cellType == emcal::ChannelType_t::HIGH_GAIN) // High gain cells -> Low energies timesmear = normalgaus(rdgen) * (1.6 + 9.5 * std::exp(-3. * cellEnergy)); // Parameters extracted from LHC24f3b & LHC22o (pp), but also usable for other periods @@ -968,15 +1087,15 @@ struct EmcalCorrectionTask { timesmear = normalgaus(rdgen) * (5.0); // Parameters extracted from LHC24g4 & LHC24aj (pp), but also usable for other periods } else { // ---> Data - if (cellEnergy < 0.3) { // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration + if (cellEnergy < minLeaderEnergy) { // Cells with tless than 300 MeV cannot be the leading cell in the cluster, so their time does not require precise calibration timeshift = 0.; // In data they will not be shifted (they are close to 0 anyways) } else if (cellType == emcal::ChannelType_t::HIGH_GAIN) { // High gain cells -> Low energies - if (cellEnergy < 4.) // Low energy regime + if (cellEnergy < lowEnergyRegime) // Low energy regime timeshift = 0.8 * std::log(2.7 * cellEnergy); // Parameters extracted from LHC22o (pp), but also usable for other periods else // Medium energy regime timeshift = 1.5 * std::log(0.9 * cellEnergy); // Parameters extracted from LHC22o (pp), but also usable for other periods } else if (cellType == emcal::ChannelType_t::LOW_GAIN) { // Low gain cells -> High energies - if (cellEnergy < 30.) // High energy regime + if (cellEnergy < highEnergyRegime) // High energy regime timeshift = 1.9 * std::log(0.09 * cellEnergy); // Parameters extracted from LHC24aj (pp), but also usable for other periods else // Very high energy regime timeshift = 1.9; // Parameters extracted from LHC24aj (pp), but also usable for other periods @@ -993,6 +1112,18 @@ struct EmcalCorrectionTask { } return timeshift + timesmear; }; + + void initializeGainCalibShift() + { + auto& ccdbMgr = o2::ccdb::BasicCCDBManager::instance(); + uint64_t tsOld = 1634853602000; // timestamp corresponding to LHC22o old gain calib object + o2::emcal::GainCalibrationFactors* paramsOld = ccdbMgr.getForTimeStamp("EMC/Calib/GainCalibFactors", tsOld); + uint64_t tsNew = 1734853602000; // timestamp corresponding to new gain calib object (new cell compression) + o2::emcal::GainCalibrationFactors* paramsNew = ccdbMgr.getForTimeStamp("EMC/Calib/GainCalibFactors", tsNew); + for (uint16_t i = 0; i < mArrGainCalibDiff.size(); ++i) { + mArrGainCalibDiff[i] = paramsNew->getGainCalibFactors(i) == 0 ? 1. : paramsOld->getGainCalibFactors(i) / paramsNew->getGainCalibFactors(i); + } + } }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/TableProducer/emcalMatchedTracksTask.cxx b/PWGJE/TableProducer/emcalMatchedTracksTask.cxx index 4134b8455e3..55781eb6bc4 100644 --- a/PWGJE/TableProducer/emcalMatchedTracksTask.cxx +++ b/PWGJE/TableProducer/emcalMatchedTracksTask.cxx @@ -9,34 +9,36 @@ // 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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedTracks.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "CommonDataFormat/InteractionRecord.h" #include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/EMCALMatchedTracks.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.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 "CommonDataFormat/InteractionRecord.h" +#include + +#include +#include +#include +#include +#include // \struct EmcalMatchedTracksTask /// \brief Simple table producer task for EMCal matched tracks diff --git a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx index 476fa4157d7..f840a339534 100644 --- a/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx +++ b/PWGJE/TableProducer/eventwiseConstituentSubtractor.cxx @@ -13,17 +13,25 @@ // /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#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 "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "Framework/runDataProcessing.h" +#include + +#include +#include using namespace o2; using namespace o2::framework; @@ -36,8 +44,12 @@ struct eventWiseConstituentSubtractorTask { Produces particleSubtractedD0Table; Produces trackSubtractedDplusTable; Produces particleSubtractedDplusTable; + Produces trackSubtractedDstarTable; + Produces particleSubtractedDstarTable; Produces trackSubtractedLcTable; Produces particleSubtractedLcTable; + Produces trackSubtractedB0Table; + Produces particleSubtractedB0Table; Produces trackSubtractedBplusTable; Produces particleSubtractedBplusTable; Produces trackSubtractedDielectronTable; @@ -172,6 +184,18 @@ struct eventWiseConstituentSubtractorTask { } PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processDplusMcCollisions, "Fill table of subtracted tracks for collisions with Dplus MCP candidates", false); + void processDstarCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHF(tracks, candidates, trackSubtractedDstarTable); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processDstarCollisions, "Fill table of subtracted tracks for collisions with D* candidates", false); + + void processDstarMcCollisions(aod::JetMcCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHFMc(tracks, candidates, particleSubtractedDstarTable); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processDstarMcCollisions, "Fill table of subtracted tracks for collisions with D* MCP candidates", false); + void processLcCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) { analyseHF(tracks, candidates, trackSubtractedLcTable); @@ -184,17 +208,29 @@ struct eventWiseConstituentSubtractorTask { } PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processLcMcCollisions, "Fill table of subtracted tracks for collisions with Lc MCP candidates", false); - void processBplusCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) - { - analyseHF(tracks, candidates, trackSubtractedBplusTable); - } - PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusCollisions, "Fill table of subtracted tracks for collisions with Bplus candidates", false); + void processB0Collisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHF(tracks, candidates, trackSubtractedB0Table); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processB0Collisions, "Fill table of subtracted tracks for collisions with B0 candidates", false); - void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) - { - analyseHFMc(tracks, candidates, particleSubtractedBplusTable); - } - PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusMcCollisions, "Fill table of subtracted tracks for collisions with Bplus MCP candidates", false); + void processB0McCollisions(aod::JetMcCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHFMc(tracks, candidates, particleSubtractedB0Table); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processB0McCollisions, "Fill table of subtracted tracks for collisions with B0 MCP candidates", false); + + void processBplusCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHF(tracks, candidates, trackSubtractedBplusTable); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusCollisions, "Fill table of subtracted tracks for collisions with Bplus candidates", false); + + void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) + { + analyseHFMc(tracks, candidates, particleSubtractedBplusTable); + } + PROCESS_SWITCH(eventWiseConstituentSubtractorTask, processBplusMcCollisions, "Fill table of subtracted tracks for collisions with Bplus MCP candidates", false); void processDielectronCollisions(aod::JetCollision const&, soa::Filtered const& tracks, soa::Join const& candidates) { diff --git a/PWGJE/TableProducer/heavyFlavourDefinition.cxx b/PWGJE/TableProducer/heavyFlavourDefinition.cxx index f28368b10dc..a9f52f96a35 100644 --- a/PWGJE/TableProducer/heavyFlavourDefinition.cxx +++ b/PWGJE/TableProducer/heavyFlavourDefinition.cxx @@ -13,19 +13,19 @@ /// \brief Task to produce a table joinable to the jet tables for a flavour definition on MC /// \author Hanseo Park -#include -#include +#include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetTaggingUtilities.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/jetEventWeightMCD.cxx b/PWGJE/TableProducer/jetEventWeightMCD.cxx index 40ea278c51e..7036f5407f6 100644 --- a/PWGJE/TableProducer/jetEventWeightMCD.cxx +++ b/PWGJE/TableProducer/jetEventWeightMCD.cxx @@ -13,19 +13,22 @@ // /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetEventWeightMCDTask { @@ -57,7 +60,9 @@ using NeutralMCJetsEventWeight = JetEventWeightMCDTask; using D0ChargedMCJetsEventWeight = JetEventWeightMCDTask; using DplusChargedMCJetsEventWeight = JetEventWeightMCDTask; +using DstarChargedMCJetsEventWeight = JetEventWeightMCDTask; using LcChargedMCJetsEventWeight = JetEventWeightMCDTask; +using B0ChargedMCJetsEventWeight = JetEventWeightMCDTask; using BplusChargedMCJetsEventWeight = JetEventWeightMCDTask; using V0ChargedMCJetsEventWeight = JetEventWeightMCDTask; @@ -86,10 +91,18 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-dplus-eventweight-mcd-charged"})); + tasks.emplace_back( + adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, TaskName{"jet-dstar-eventweight-mcd-charged"})); + tasks.emplace_back( adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-lc-eventweight-mcd-charged"})); + tasks.emplace_back( + adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, TaskName{"jet-b0-eventweight-mcd-charged"})); + tasks.emplace_back( adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-bplus-eventweight-mcd-charged"})); diff --git a/PWGJE/TableProducer/jetEventWeightMCP.cxx b/PWGJE/TableProducer/jetEventWeightMCP.cxx index 5727cf57a43..ba2efb56ced 100644 --- a/PWGJE/TableProducer/jetEventWeightMCP.cxx +++ b/PWGJE/TableProducer/jetEventWeightMCP.cxx @@ -13,19 +13,20 @@ // /// \author Nima Zardoshti +#include "PWGJE/DataModel/Jet.h" + #include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - template struct JetEventWeightMCPTask { @@ -48,7 +49,9 @@ using NeutralMCJetsEventWeight = JetEventWeightMCPTask; using D0ChargedMCJetsEventWeight = JetEventWeightMCPTask; using DplusChargedMCJetsEventWeight = JetEventWeightMCPTask; +using DstarChargedMCJetsEventWeight = JetEventWeightMCPTask; using LcChargedMCJetsEventWeight = JetEventWeightMCPTask; +using B0ChargedMCJetsEventWeight = JetEventWeightMCPTask; using BplusChargedMCJetsEventWeight = JetEventWeightMCPTask; using V0ChargedMCJetsEventWeight = JetEventWeightMCPTask; @@ -77,10 +80,18 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-dplus-eventweight-mcp-charged"})); + tasks.emplace_back( + adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, TaskName{"jet-dstar-eventweight-mcp-charged"})); + tasks.emplace_back( adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-lc-eventweight-mcp-charged"})); + tasks.emplace_back( + adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, TaskName{"jet-b0-eventweight-mcp-charged"})); + tasks.emplace_back( adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-bplus-eventweight-mcp-charged"})); diff --git a/PWGJE/TableProducer/jetTaggerHF.cxx b/PWGJE/TableProducer/jetTaggerHF.cxx index 2a37871c970..6e336d9516b 100644 --- a/PWGJE/TableProducer/jetTaggerHF.cxx +++ b/PWGJE/TableProducer/jetTaggerHF.cxx @@ -16,27 +16,43 @@ /// \author Hanseo Park /// \author Hadi Hassan , University of Jyväskylä -#include -#include -#include -#include -#include +#include "MlResponse.h" + +#include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/Core/MlResponseHfTagging.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" + +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetTaggingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/MlResponseHfTagging.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/jetTrackDerived.cxx b/PWGJE/TableProducer/jetTrackDerived.cxx index 827ec6c1c15..9111ae36c3c 100644 --- a/PWGJE/TableProducer/jetTrackDerived.cxx +++ b/PWGJE/TableProducer/jetTrackDerived.cxx @@ -17,23 +17,32 @@ /// // O2 includes -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/AnalysisDataModel.h" -#include "PWGJE/DataModel/Jet.h" -#include "Framework/StaticFor.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" +#include "PWGJE/DataModel/TrackJetQa.h" + #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" -#include "PWGJE/DataModel/TrackJetQa.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #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 + +#include using namespace o2; -using namespace o2::track; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/TableProducer/luminosityCalculator.cxx b/PWGJE/TableProducer/luminosityCalculator.cxx index b1d509ab321..8767ae604e2 100644 --- a/PWGJE/TableProducer/luminosityCalculator.cxx +++ b/PWGJE/TableProducer/luminosityCalculator.cxx @@ -14,13 +14,21 @@ /// /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include -#include "PWGJE/DataModel/JetReducedData.h" +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/TableProducer/luminosityProducer.cxx b/PWGJE/TableProducer/luminosityProducer.cxx index 6877da8a812..455ab4e5910 100644 --- a/PWGJE/TableProducer/luminosityProducer.cxx +++ b/PWGJE/TableProducer/luminosityProducer.cxx @@ -14,14 +14,27 @@ /// /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "JetDerivedDataUtilities.h" #include "PWGJE/DataModel/Jet.h" #include "PWGJE/DataModel/JetReducedData.h" +#include "Common/CCDB/EventSelectionParams.h" + +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.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/PWGJE/TableProducer/mcOutlierRejector.cxx b/PWGJE/TableProducer/mcOutlierRejector.cxx new file mode 100644 index 00000000000..427a5afdfad --- /dev/null +++ b/PWGJE/TableProducer/mcOutlierRejector.cxx @@ -0,0 +1,132 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +// Task to produce a table joinable to the jcollision table which contains an outlier rejector +// +/// \author Nima Zardoshti + +#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 + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct McOutlierRejectorTask { + Produces collisionOutliers; + Produces mcCollisionOutliers; + + Configurable checkmcCollisionForCollision{"checkmcCollisionForCollision", true, "additionally reject collision based on mcCollision"}; + Configurable ptHatMax{"ptHatMax", 4.0, "maximum factor of pt hat the leading jet in the event is allowed"}; + + std::vector collisionFlag; + std::vector mcCollisionFlag; + + void processSetupCollisionSelection(aod::JCollisions const& collisions) + { + collisionFlag.clear(); + collisionFlag.resize(collisions.size(), false); + } + PROCESS_SWITCH(McOutlierRejectorTask, processSetupCollisionSelection, "Setup collision processing", true); + + void processSetupMcCollisionSelection(aod::JMcCollisions const& mcCollisions) + { + mcCollisionFlag.clear(); + mcCollisionFlag.resize(mcCollisions.size(), false); + } + PROCESS_SWITCH(McOutlierRejectorTask, processSetupMcCollisionSelection, "Setup MC Collision processing", true); + + template + void collisionSelection(int32_t collisionIndex, T const& selectionObjects, float ptHard, std::vector& flagArray) + { + + if (selectionObjects.size() != 0) { + float maxSelectionObjectPt = 0.0; + if constexpr (std::is_same_v, aod::JetTracks> || std::is_same_v, aod::JetParticles>) { + for (auto selectionObject : selectionObjects) { + if (selectionObject.pt() > maxSelectionObjectPt) { + maxSelectionObjectPt = selectionObject.pt(); + } + } + } else { + maxSelectionObjectPt = selectionObjects.iteratorAt(0).pt(); + } + + if (maxSelectionObjectPt > ptHatMax * ptHard) { + flagArray[collisionIndex] = true; // Currently if running multiple different jet finders, then a single type of jet can veto an event for others. Decide if this is the best way + } + } + } + + template + void processSelectionObjects(aod::JetCollisionMCD const& collision, T const& selectionObjects, aod::JetMcCollisions const&) + { + auto mcCollision = collision.mcCollision_as(); + collisionSelection(collision.globalIndex(), selectionObjects, mcCollision.ptHard(), collisionFlag); + } + + template + void processSelectionMcObjects(aod::JetMcCollision const& mcCollision, T const& selectionMcObjects) + { + collisionSelection(mcCollision.globalIndex(), selectionMcObjects, mcCollision.ptHard(), mcCollisionFlag); + } + + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingChargedMCDetectorLevelJets, "process mc detector level charged jets", true); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingNeutralMCDetectorLevelJets, "process mc detector level neutral jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingFullMCDetectorLevelJets, "process mc detector level full jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingD0ChargedMCDetectorLevelJets, "process mc detector level D0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingDplusChargedMCDetectorLevelJets, "process mc detector level Dplus charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingDstarChargedMCDetectorLevelJets, "process mc detector level Dstar charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingLcChargedMCDetectorLevelJets, "process mc detector level Lc charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingB0ChargedMCDetectorLevelJets, "process mc detector level B0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingBplusChargedMCDetectorLevelJets, "process mc detector level Bplus charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingDielectronChargedMCDetectorLevelJets, "process mc detector level Dielectron charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionObjects, processSelectingTracks, "process tracks", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingChargedMCParticleLevelJets, "process mc particle level charged jets", true); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingNeutralMCParticleLevelJets, "process mc particle level neutral jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingFullMCParticleLevelJets, "process mc particle level full jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingD0ChargedMCParticleLevelJets, "process mc particle level D0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingDplusChargedMCParticleLevelJets, "process mc particle level Dplus charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingDstarChargedMCParticleLevelJets, "process mc particle level Dstar charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingLcChargedMCParticleLevelJets, "process mc particle level Lc charged jets", false); + // PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingB0ChargedMCParticleLevelJets, "process mc particle level B0 charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingBplusChargedMCParticleLevelJets, "process mc particle level Bplus charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingDielectronChargedMCParticleLevelJets, "process mc particle level Dielectron charged jets", false); + PROCESS_SWITCH_FULL(McOutlierRejectorTask, processSelectionMcObjects, processSelectingParticles, "process mc particles", false); + + void processStoreCollisionDecision(aod::JetCollisionMCD const& collision) + { + bool rejectCollision = collisionFlag[collision.globalIndex()]; + if (!rejectCollision && checkmcCollisionForCollision && collision.has_mcCollision()) { + rejectCollision = mcCollisionFlag[collision.mcCollisionId()]; + } + collisionOutliers(rejectCollision); + } + PROCESS_SWITCH(McOutlierRejectorTask, processStoreCollisionDecision, "write out decision of rejecting collision", true); + + void processStoreMcCollisionDecision(aod::JetMcCollision const& mcCollision) + { + mcCollisionOutliers(mcCollisionFlag[mcCollision.globalIndex()]); + } + PROCESS_SWITCH(McOutlierRejectorTask, processStoreMcCollisionDecision, "write out decision of rejecting mcCollision", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"mc-outlier-rejector"})}; } diff --git a/PWGJE/TableProducer/rhoEstimator.cxx b/PWGJE/TableProducer/rhoEstimator.cxx index a64a2d90e5d..b6026e46291 100644 --- a/PWGJE/TableProducer/rhoEstimator.cxx +++ b/PWGJE/TableProducer/rhoEstimator.cxx @@ -13,20 +13,29 @@ // /// \author Nima Zardoshti -#include -#include +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "Framework/runDataProcessing.h" +#include +#include + +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; @@ -39,10 +48,14 @@ struct RhoEstimatorTask { Produces rhoD0McTable; Produces rhoDplusTable; Produces rhoDplusMcTable; + Produces rhoDstarTable; + Produces rhoDstarMcTable; Produces rhoLcTable; Produces rhoLcMcTable; Produces rhoBplusTable; Produces rhoBplusMcTable; + Produces rhoB0Table; + Produces rhoB0McTable; Produces rhoDielectronTable; Produces rhoDielectronMcTable; @@ -178,7 +191,7 @@ struct RhoEstimatorTask { void processChargedCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { rhoChargedTable(0.0, 0.0); return; } @@ -213,7 +226,7 @@ struct RhoEstimatorTask { void processD0Collisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesD0Data const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { rhoD0Table(0.0, 0.0); continue; } @@ -241,7 +254,7 @@ struct RhoEstimatorTask { void processDplusCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesDplusData const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { rhoDplusTable(0.0, 0.0); continue; } @@ -266,10 +279,38 @@ struct RhoEstimatorTask { } PROCESS_SWITCH(RhoEstimatorTask, processDplusMcCollisions, "Fill rho tables for collisions with Dplus MCP candidates", false); + void processDstarCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesDstarData const& candidates) + { + for (auto& candidate : candidates) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + rhoDstarTable(0.0, 0.0); + continue; + } + inputParticles.clear(); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.trackingEfficiency, &candidate); + + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoDstarTable(rho, rhoM); + } + } + PROCESS_SWITCH(RhoEstimatorTask, processDstarCollisions, "Fill rho tables for collisions with Dstar candidates", false); + + void processDstarMcCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesDstarMCP const& candidates) + { + for (auto& candidate : candidates) { + inputParticles.clear(); + jetfindingutilities::analyseParticles(inputParticles, particleSelection, 1, particles, pdgDatabase, &candidate); + + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoDstarMcTable(rho, rhoM); + } + } + PROCESS_SWITCH(RhoEstimatorTask, processDstarMcCollisions, "Fill rho tables for collisions with Dstar MCP candidates", false); + void processLcCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesLcData const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { rhoLcTable(0.0, 0.0); continue; } @@ -294,10 +335,38 @@ struct RhoEstimatorTask { } PROCESS_SWITCH(RhoEstimatorTask, processLcMcCollisions, "Fill rho tables for collisions with Lc MCP candidates", false); + void processB0Collisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesB0Data const& candidates) + { + for (auto& candidate : candidates) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + rhoB0Table(0.0, 0.0); + continue; + } + inputParticles.clear(); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.trackingEfficiency, &candidate); + + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoB0Table(rho, rhoM); + } + } + PROCESS_SWITCH(RhoEstimatorTask, processB0Collisions, "Fill rho tables for collisions with B0 candidates", false); + + void processB0McCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesB0MCP const& candidates) + { + for (auto& candidate : candidates) { + inputParticles.clear(); + jetfindingutilities::analyseParticles(inputParticles, particleSelection, 1, particles, pdgDatabase, &candidate); + + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoB0McTable(rho, rhoM); + } + } + PROCESS_SWITCH(RhoEstimatorTask, processB0McCollisions, "Fill rho tables for collisions with B0 MCP candidates", false); + void processBplusCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesBplusData const& candidates) { for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { rhoBplusTable(0.0, 0.0); continue; } @@ -308,34 +377,34 @@ struct RhoEstimatorTask { rhoBplusTable(rho, rhoM); } } - PROCESS_SWITCH(RhoEstimatorTask, processBplusCollisions, "Fill rho tables for collisions with Bplus candidates", false); + PROCESS_SWITCH(RhoEstimatorTask, processBplusCollisions, "Fill rho tables for collisions with Bplus candidates", false); - void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesBplusMCP const& candidates) - { - for (auto& candidate : candidates) { - inputParticles.clear(); - jetfindingutilities::analyseParticles(inputParticles, particleSelection, 1, particles, pdgDatabase, &candidate); + void processBplusMcCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesBplusMCP const& candidates) + { + for (auto& candidate : candidates) { + inputParticles.clear(); + jetfindingutilities::analyseParticles(inputParticles, particleSelection, 1, particles, pdgDatabase, &candidate); - auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); - rhoBplusMcTable(rho, rhoM); - } + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoBplusMcTable(rho, rhoM); } - PROCESS_SWITCH(RhoEstimatorTask, processBplusMcCollisions, "Fill rho tables for collisions with Bplus MCP candidates", false); - - void processDielectronCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesDielectronData const& candidates) - { - for (auto& candidate : candidates) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centrality() < config.centralityMin || collision.centrality() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { - rhoDielectronTable(0.0, 0.0); - continue; - } - inputParticles.clear(); - jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.trackingEfficiency, &candidate); + } + PROCESS_SWITCH(RhoEstimatorTask, processBplusMcCollisions, "Fill rho tables for collisions with Bplus MCP candidates", false); - auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); - rhoDielectronTable(rho, rhoM); + void processDielectronCollisions(aod::JetCollision const& collision, soa::Filtered const& tracks, aod::CandidatesDielectronData const& candidates) + { + for (auto& candidate : candidates) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || collision.centFT0M() < config.centralityMin || collision.centFT0M() >= config.centralityMax || collision.trackOccupancyInTimeRange() > config.trackOccupancyInTimeRangeMax || std::abs(collision.posZ()) > config.vertexZCut) { + rhoDielectronTable(0.0, 0.0); + continue; } + inputParticles.clear(); + jetfindingutilities::analyseTracks(inputParticles, tracks, trackSelection, config.trackingEfficiency, &candidate); + + auto [rho, rhoM] = bkgSub.estimateRhoAreaMedian(inputParticles, config.doSparse); + rhoDielectronTable(rho, rhoM); } + } PROCESS_SWITCH(RhoEstimatorTask, processDielectronCollisions, "Fill rho tables for collisions with Dielectron candidates", false); void processDielectronMcCollisions(aod::JetMcCollision const&, soa::Filtered const& particles, aod::CandidatesDielectronMCP const& candidates) diff --git a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx index c1f7598d176..8bab0ea0c05 100644 --- a/PWGJE/TableProducer/secondaryVertexReconstruction.cxx +++ b/PWGJE/TableProducer/secondaryVertexReconstruction.cxx @@ -13,31 +13,42 @@ /// \brief Task to produce a SV indices table joinable to the jet tables and 3/2-prong SV for hf jet tagging /// \author Hadi Hassan -#include -#include -#include -#include +#include "PWGHF/Utils/utilsBfieldCCDB.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include -#include +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" #include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/RecoDecay.h" - +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "ReconstructionDataFormats/DCA.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" - -#include "PWGHF/Utils/utilsBfieldCCDB.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; @@ -199,8 +210,6 @@ struct SecondaryVertexReconstruction { auto chi2PCA = df.getChi2AtPCACandidate(); auto covMatrixPCA = df.calcPCACovMatrixFlat(); - registry.fill(HIST("hDispersion"), dispersion, numProngs); - // get track impact parameters // This modifies track momenta! auto primaryVertex = getPrimaryVertex(collision); @@ -277,6 +286,7 @@ struct SecondaryVertexReconstruction { double decayLengthNormalised = RecoDecay::distance(std::array{primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, std::array{secondaryVertex[0], secondaryVertex[1], secondaryVertex[2]}) / errorDecayLength; double decayLengthXYNormalised = RecoDecay::distanceXY(std::array{primaryVertex.getX(), primaryVertex.getY()}, std::array{secondaryVertex[0], secondaryVertex[1]}) / errorDecayLengthXY; + registry.fill(HIST("hDispersion"), dispersion, numProngs); registry.fill(HIST("hMassNProngs"), massSV, numProngs); registry.fill(HIST("hLxySNProngs"), decayLengthXYNormalised, numProngs); registry.fill(HIST("hLSNProngs"), decayLengthNormalised, numProngs); diff --git a/PWGJE/Tasks/CMakeLists.txt b/PWGJE/Tasks/CMakeLists.txt index 0e39c04445a..3b0d896108c 100644 --- a/PWGJE/Tasks/CMakeLists.txt +++ b/PWGJE/Tasks/CMakeLists.txt @@ -50,6 +50,14 @@ o2physics_add_dpl_workflow(photon-isolation-qa SOURCES photonIsolationQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2::EMCALCalib O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(photon-charged-trigger-correlation + SOURCES photonChargedTriggerCorrelation.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(task-emc-extensive-mc-qa + SOURCES taskEmcExtensiveMcQa.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2::EMCALBase O2Physics::AnalysisCore O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) if(FastJet_FOUND) o2physics_add_dpl_workflow(jet-background-analysis @@ -72,10 +80,18 @@ if(FastJet_FOUND) SOURCES jetSubstructureDplus.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-dstar + SOURCES jetSubstructureDstar.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-lc SOURCES jetSubstructureLc.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-b0 + SOURCES jetSubstructureB0.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-bplus SOURCES jetSubstructureBplus.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -92,10 +108,18 @@ if(FastJet_FOUND) SOURCES jetSubstructureDplusOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-dstar-output + SOURCES jetSubstructureDstarOutput.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-lc-output SOURCES jetSubstructureLcOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-substructure-b0-output + SOURCES jetSubstructureB0Output.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-substructure-bplus-output SOURCES jetSubstructureBplusOutput.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -132,10 +156,18 @@ if(FastJet_FOUND) SOURCES jetFinderDplusQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-finder-dstar-qa + SOURCES jetFinderDstarQA.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-finder-lc-qa SOURCES jetFinderLcQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(jet-finder-b0-qa + SOURCES jetFinderB0QA.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(jet-finder-bplus-qa SOURCES jetFinderBplusQA.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore @@ -244,6 +276,7 @@ if(FastJet_FOUND) o2physics_add_dpl_workflow(full-jet-spectra SOURCES fullJetSpectra.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::PWGJECore O2Physics::AnalysisCore + O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(bjet-tagging-ml SOURCES bjetTaggingML.cxx diff --git a/PWGJE/Tasks/bjetTaggingGnn.cxx b/PWGJE/Tasks/bjetTaggingGnn.cxx index 9cc4e89088a..1e74fb21ff3 100644 --- a/PWGJE/Tasks/bjetTaggingGnn.cxx +++ b/PWGJE/Tasks/bjetTaggingGnn.cxx @@ -14,30 +14,25 @@ /// /// \author Changhwan Choi , Pusan National University -#include -#include -#include -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetTaggingUtilities.h" -#include "PWGJE/DataModel/JetTagging.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/RecoDecay.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Framework/Logger.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/bjetTaggingML.cxx b/PWGJE/Tasks/bjetTaggingML.cxx index afa34a243e6..64536cb0c15 100644 --- a/PWGJE/Tasks/bjetTaggingML.cxx +++ b/PWGJE/Tasks/bjetTaggingML.cxx @@ -14,28 +14,32 @@ /// /// \author Hadi Hassan , University of Jyväskylä -#include -#include -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetTaggingUtilities.h" -#include "PWGJE/DataModel/JetTagging.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetTagging.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.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; @@ -47,7 +51,6 @@ struct BJetTaggingML { // event level configurables Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; - Configurable useEventWeight{"useEventWeight", true, "Flag whether to scale histograms with the event weight"}; 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"}; @@ -71,6 +74,7 @@ struct BJetTaggingML { Configurable jetEtaMax{"jetEtaMax", 99.0, "maximum jet pseudorapidity"}; Configurable nJetConst{"nJetConst", 10, "maximum number of jet consistuents to be used for ML evaluation"}; Configurable useDb{"useDb", false, "Flag whether to use the Db instead of the score for tagging"}; + Configurable callSumw2{"callSumw2", false, "Flag whether to use sum weight squared for THnSparse error calculation"}; Configurable doDataDriven{"doDataDriven", false, "Flag whether to use fill THnSpase for data driven methods"}; @@ -109,15 +113,15 @@ struct BJetTaggingML { registry.add("h2_SVMass_jetpT", "Secondary vertex mass;#it{p}_{T,jet} (GeV/#it{c});#it{m}_{SV} (GeV/#it{c}^{2})", {HistType::kTH2F, {{200, 0., 200.}, {50, 0, 10}}}); if (doDataDriven) { - registry.add("hSparse_Incljets", "Inclusive jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); - if (doprocessMCJets) { - registry.add("hSparse_bjets", "Tagged b-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); - registry.add("hSparse_cjets", "Tagged c-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); - registry.add("hSparse_lfjets", "Tagged lf-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}); + registry.add("hSparse_Incljets", "Inclusive jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); + if (doprocessMCJets || doprocessMCJetsWeighted) { + registry.add("hSparse_bjets", "Tagged b-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); + registry.add("hSparse_cjets", "Tagged c-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); + registry.add("hSparse_lfjets", "Tagged lf-jets Info;#it{p}_{T,jet} (GeV/#it{c});Score;-log(1-score);#it{m}_{jet} (GeV/#it{c}^{2});-log(JP);#it{m}_{SV} (GeV/#it{c}^{2});SVfE;", {HistType::kTHnSparseF, {{200, 0., 200.}, useDb ? axisDb : axisScore, axisLogScore, {50, 0, 50}, {375, 0, 30}, {50, 0, 10}, {50, 0, 1}}}, callSumw2); } } - if (doprocessMCJets) { + if (doprocessMCJets || doprocessMCJetsWeighted || doprocessMCTruthJets || doprocessMCTruthJetsWeighted) { registry.add("h2_score_jetpT_bjet", "ML scores for b-jets;#it{p}_{T,jet} (GeV/#it{c});Score", {HistType::kTH2F, {{200, 0., 200.}, useDb ? axisDb : axisScore}}); registry.add("h2_logscore_jetpT_bjet", "ML scores for b-jets;#it{p}_{T,jet} (GeV/#it{c});- log(1 - Score)", {HistType::kTH2F, {{200, 0., 200.}, axisLogScore}}); @@ -159,9 +163,9 @@ struct BJetTaggingML { registry.add("h_jetpT_particle_cjet", "Jet transverse momentum particle level c-jets;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); registry.add("h_jetpT_particle_lfjet", "Jet transverse momentum particle level lf-jet;#it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH1F, {{200, 0., 200.0}}}); - registry.add("h2_Response_DetjetpT_PartjetpT_bjet", "Response matrix b-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h2_Response_DetjetpT_PartjetpT_cjet", "Response matrix c-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); - registry.add("h2_Response_DetjetpT_PartjetpT_lfjet", "Response matrix lf-jet;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}); + registry.add("h2_Response_DetjetpT_PartjetpT_bjet", "Response matrix b-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}, callSumw2); + registry.add("h2_Response_DetjetpT_PartjetpT_cjet", "Response matrix c-jets;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}, callSumw2); + registry.add("h2_Response_DetjetpT_PartjetpT_lfjet", "Response matrix lf-jet;#it{p}_{T,jet}^{det} (GeV/#it{c});#it{p}_{T,jet}^{part} (GeV/#it{c})", {HistType::kTH2F, {{200, 0., 200.}, {200, 0., 200.}}}, callSumw2); } } @@ -211,7 +215,7 @@ struct BJetTaggingML { registry.fill(HIST("h2_Dispersion_jetpT"), myJet.pt(), candSV.dispersion(), eventweight); registry.fill(HIST("h2_SVMass_jetpT"), myJet.pt(), massSV, eventweight); - if (doprocessMCJets) { + if (doprocessMCJets || doprocessMCJetsWeighted) { if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h2_LxyS_jetpT_bjet"), myJet.pt(), candSV.decayLengthXY() / candSV.errorDecayLengthXY(), eventweight); registry.fill(HIST("h2_Dispersion_jetpT_bjet"), myJet.pt(), candSV.dispersion(), eventweight); @@ -249,7 +253,7 @@ struct BJetTaggingML { registry.fill(HIST("h2_SIPs2D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); registry.fill(HIST("h2_SIPs3D_jetpT"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); - if (doprocessMCJets) { + if (doprocessMCJets || doprocessMCJetsWeighted) { if (jetFlavor == JetTaggingSpecies::beauty) { registry.fill(HIST("h2_SIPs2D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXY()) / constituent.sigmadcaXY(), eventweight); registry.fill(HIST("h2_SIPs3D_jetpT_bjet"), analysisJet.pt(), sign * std::abs(constituent.dcaXYZ()) / constituent.sigmadcaXYZ(), eventweight); @@ -274,6 +278,94 @@ struct BJetTaggingML { tracksParams.resize(nJetConst); } + template + void processJetInfo(AnalysisJet const& myJet, AnyTracks const& allTracks, SecondaryVertices const& allSVs, int8_t jetFlavor = 0, double eventWeight = 1.0) + { + std::vector tracksParams; + std::vector svsParams; + + analyzeJetSVInfo(myJet, allSVs, svsParams, jetFlavor, eventWeight); + analyzeJetTrackInfo(myJet, allTracks, tracksParams, jetFlavor, eventWeight); + + int nSVs = myJet.template secondaryVertices_as().size(); + int nTracks = myJet.template tracks_as().size(); + + registry.fill(HIST("h2_nTracks_jetpT"), myJet.pt(), nTracks); + registry.fill(HIST("h2_nSV_jetpT"), myJet.pt(), nSVs < 250 ? nSVs : 249); + + registry.fill(HIST("h2_score_jetpT"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT"), myJet.pt(), myJet.mass(), eventWeight); + + if (doDataDriven) { + registry.fill(HIST("hSparse_Incljets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + if (doprocessMCJets || doprocessMCJetsWeighted) { + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("hSparse_bjets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("hSparse_cjets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + } else { + registry.fill(HIST("hSparse_lfjets"), myJet.pt(), myJet.scoreML(), useDb ? 0 : -1 * std::log(1 - myJet.scoreML()), myJet.mass(), -1 * std::log(myJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); + } + } + } + + if (doprocessMCJets || doprocessMCJetsWeighted) { + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h2_score_jetpT_bjet"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT_bjet"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT_bjet"), myJet.pt(), myJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_bjet"), myJet.pt(), eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h2_score_jetpT_cjet"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT_cjet"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT_cjet"), myJet.pt(), myJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_cjet"), myJet.pt(), eventWeight); + } else { + registry.fill(HIST("h2_score_jetpT_lfjet"), myJet.pt(), myJet.scoreML(), eventWeight); + if (!useDb) { + registry.fill(HIST("h2_logscore_jetpT_lfjet"), myJet.pt(), -1 * std::log(1 - myJet.scoreML()), eventWeight); + } + registry.fill(HIST("h2_jetMass_jetpT_lfjet"), myJet.pt(), myJet.mass(), eventWeight); + registry.fill(HIST("h_jetpT_detector_lfjet"), myJet.pt(), eventWeight); + } + } + } + + template + void fillMCPHistograms(AnalysisJetMCP const& mcpjet, bool detColl = false, double eventWeight = 1.0) + { + int8_t jetFlavor = mcpjet.origin(); + + if (detColl) { + + registry.fill(HIST("h_jetpT_particle_DetColl"), mcpjet.pt(), eventWeight); + + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h_jetpT_particle_DetColl_bjet"), mcpjet.pt(), eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h_jetpT_particle_DetColl_cjet"), mcpjet.pt(), eventWeight); + } else { + registry.fill(HIST("h_jetpT_particle_DetColl_lfjet"), mcpjet.pt(), eventWeight); + } + } else { + + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h_jetpT_particle_bjet"), mcpjet.pt(), eventWeight); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h_jetpT_particle_cjet"), mcpjet.pt(), eventWeight); + } else { + registry.fill(HIST("h_jetpT_particle_lfjet"), mcpjet.pt(), eventWeight); + } + } + } + void processDummy(FilteredCollision::iterator const& /*collision*/) { } @@ -301,39 +393,18 @@ struct BJetTaggingML { continue; } - std::vector tracksParams; - std::vector svsParams; - - analyzeJetSVInfo(analysisJet, allSVs, svsParams); - analyzeJetTrackInfo(analysisJet, allTracks, tracksParams); - - int nSVs = analysisJet.template secondaryVertices_as().size(); - int nTracks = analysisJet.template tracks_as().size(); - - registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), nTracks); - registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); - - registry.fill(HIST("h2_score_jetpT"), analysisJet.pt(), analysisJet.scoreML()); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML())); - } - - registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass()); - - if (doDataDriven) { - registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE); - } + processJetInfo(analysisJet, allTracks, allSVs); } } PROCESS_SWITCH(BJetTaggingML, processDataJets, "jet information in Data", false); - using MCDJetTable = soa::Filtered>; - using MCPJetTable = soa::Filtered>; + using MCDJetTableWeighted = soa::Filtered>; + using MCPJetTableWeighted = soa::Filtered>; using FilteredCollisionMCD = soa::Filtered>; - Preslice mcpJetsPerCollision = aod::jet::mcCollisionId; + Preslice mcpJetsPerCollisionWeighted = aod::jet::mcCollisionId; - void processMCJets(FilteredCollisionMCD::iterator const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, aod::JetParticles const& /*MCParticles*/, aod::MCDSecondaryVertex3Prongs const& allSVs) + void processMCJetsWeighted(FilteredCollisionMCD::iterator const& collision, MCDJetTableWeighted const& MCDjets, MCPJetTableWeighted const& MCPjets, JetTracksMCDwID const& allTracks, aod::JetParticles const& /*MCParticles*/, aod::MCDSecondaryVertex3Prongs const& allSVs) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; @@ -341,7 +412,7 @@ struct BJetTaggingML { registry.fill(HIST("h_vertexZ"), collision.posZ()); - auto const mcPJetsPerColl = MCPjets.sliceBy(mcpJetsPerCollision, collision.mcCollisionId()); + auto const mcPJetsPerColl = MCPjets.sliceBy(mcpJetsPerCollisionWeighted, collision.mcCollisionId()); for (const auto& analysisJet : MCDjets) { @@ -357,67 +428,17 @@ struct BJetTaggingML { continue; } - float eventWeight = useEventWeight ? analysisJet.eventWeight() : 1.0; + float eventWeight = analysisJet.eventWeight(); float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (analysisJet.pt() > pTHatMaxMCD * pTHat) { continue; } - std::vector tracksParams; - std::vector svsParams; - int jetFlavor = analysisJet.origin(); - analyzeJetSVInfo(analysisJet, allSVs, svsParams, jetFlavor, eventWeight); - analyzeJetTrackInfo(analysisJet, allTracks, tracksParams, jetFlavor, eventWeight); - - int nSVs = analysisJet.template secondaryVertices_as().size(); - int nTracks = analysisJet.template tracks_as().size(); - - registry.fill(HIST("h2_nTracks_jetpT"), analysisJet.pt(), nTracks); - registry.fill(HIST("h2_nSV_jetpT"), analysisJet.pt(), nSVs < 250 ? nSVs : 249); + processJetInfo(analysisJet, allTracks, allSVs, jetFlavor, eventWeight); - registry.fill(HIST("h2_score_jetpT"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT"), analysisJet.pt(), analysisJet.mass(), eventWeight); - - if (doDataDriven) { - registry.fill(HIST("hSparse_Incljets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("hSparse_bjets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("hSparse_cjets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - } else { - registry.fill(HIST("hSparse_lfjets"), analysisJet.pt(), analysisJet.scoreML(), useDb ? 0 : -1 * std::log(1 - analysisJet.scoreML()), analysisJet.mass(), -1 * std::log(analysisJet.jetProb()), svsParams[0].svMass, svsParams[0].svfE, eventWeight); - } - } - - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h2_score_jetpT_bjet"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT_bjet"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT_bjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); - registry.fill(HIST("h_jetpT_detector_bjet"), analysisJet.pt(), eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h2_score_jetpT_cjet"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT_cjet"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT_cjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); - registry.fill(HIST("h_jetpT_detector_cjet"), analysisJet.pt(), eventWeight); - } else { - registry.fill(HIST("h2_score_jetpT_lfjet"), analysisJet.pt(), analysisJet.scoreML(), eventWeight); - if (!useDb) { - registry.fill(HIST("h2_logscore_jetpT_lfjet"), analysisJet.pt(), -1 * std::log(1 - analysisJet.scoreML()), eventWeight); - } - registry.fill(HIST("h2_jetMass_jetpT_lfjet"), analysisJet.pt(), analysisJet.mass(), eventWeight); - registry.fill(HIST("h_jetpT_detector_lfjet"), analysisJet.pt(), eventWeight); - } - - for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { if (mcpjet.pt() > pTHatMaxMCP * pTHat) { continue; } @@ -447,31 +468,85 @@ struct BJetTaggingML { continue; } - float eventWeight = useEventWeight ? mcpjet.eventWeight() : 1.0; + float eventWeight = mcpjet.eventWeight(); float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (mcpjet.pt() > pTHatMaxMCP * pTHat) { continue; } - int8_t jetFlavor = mcpjet.origin(); + fillMCPHistograms(mcpjet, true, eventWeight); + } + } + PROCESS_SWITCH(BJetTaggingML, processMCJetsWeighted, "jet information in MC with event weight", false); - registry.fill(HIST("h_jetpT_particle_DetColl"), mcpjet.pt(), eventWeight); + using MCDJetTable = soa::Filtered>; + using MCPJetTable = soa::Filtered>; - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h_jetpT_particle_DetColl_bjet"), mcpjet.pt(), eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h_jetpT_particle_DetColl_cjet"), mcpjet.pt(), eventWeight); - } else { - registry.fill(HIST("h_jetpT_particle_DetColl_lfjet"), mcpjet.pt(), eventWeight); + Preslice mcpJetsPerCollision = aod::jet::mcCollisionId; + + void processMCJets(FilteredCollisionMCD::iterator const& collision, MCDJetTable const& MCDjets, MCPJetTable const& MCPjets, JetTracksMCDwID const& allTracks, aod::JetParticles const& /*MCParticles*/, aod::MCDSecondaryVertex3Prongs const& allSVs) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + + registry.fill(HIST("h_vertexZ"), collision.posZ()); + + auto const mcPJetsPerColl = MCPjets.sliceBy(mcpJetsPerCollision, collision.mcCollisionId()); + + for (const auto& analysisJet : MCDjets) { + + bool jetIncluded = false; + for (const auto& jetR : jetRadiiValues) { + if (analysisJet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; + } + + int jetFlavor = analysisJet.origin(); + + processJetInfo(analysisJet, allTracks, allSVs, jetFlavor); + + for (const auto& mcpjet : analysisJet.template matchedJetGeo_as()) { + if (jetFlavor == JetTaggingSpecies::beauty) { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_bjet"), analysisJet.pt(), mcpjet.pt()); + } else if (jetFlavor == JetTaggingSpecies::charm) { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_cjet"), analysisJet.pt(), mcpjet.pt()); + } else { + registry.fill(HIST("h2_Response_DetjetpT_PartjetpT_lfjet"), analysisJet.pt(), mcpjet.pt()); + } + } + } + + // For filling histograms used for the jet matching efficiency + for (const auto& mcpjet : mcPJetsPerColl) { + + bool jetIncluded = false; + for (const auto& jetR : jetRadiiValues) { + if (mcpjet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } + } + + if (!jetIncluded) { + continue; } + + fillMCPHistograms(mcpjet, true); } } - PROCESS_SWITCH(BJetTaggingML, processMCJets, "jet information in MC", false); + PROCESS_SWITCH(BJetTaggingML, processMCJets, "jet information in MC without event weight", false); Filter mccollisionFilter = nabs(aod::jmccollision::posZ) < vertexZCut; using FilteredCollisionMCP = soa::Filtered; - void processMCTruthJets(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTable const& MCPjets, aod::JetParticles const& /*MCParticles*/) + void processMCTruthJetsWeighted(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTableWeighted const& MCPjets, aod::JetParticles const& /*MCParticles*/) { for (const auto& mcpjet : MCPjets) { @@ -488,24 +563,38 @@ struct BJetTaggingML { continue; } - float eventWeight = useEventWeight ? mcpjet.eventWeight() : 1.0; + float eventWeight = mcpjet.eventWeight(); float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (mcpjet.pt() > pTHatMaxMCP * pTHat) { continue; } - int8_t jetFlavor = mcpjet.origin(); + fillMCPHistograms(mcpjet, false, eventWeight); + } + } + PROCESS_SWITCH(BJetTaggingML, processMCTruthJetsWeighted, "truth jet information with event weight", false); - if (jetFlavor == JetTaggingSpecies::beauty) { - registry.fill(HIST("h_jetpT_particle_bjet"), mcpjet.pt(), eventWeight); - } else if (jetFlavor == JetTaggingSpecies::charm) { - registry.fill(HIST("h_jetpT_particle_cjet"), mcpjet.pt(), eventWeight); - } else { - registry.fill(HIST("h_jetpT_particle_lfjet"), mcpjet.pt(), eventWeight); + void processMCTruthJets(FilteredCollisionMCP::iterator const& /*collision*/, MCPJetTable const& MCPjets, aod::JetParticles const& /*MCParticles*/) + { + + for (const auto& mcpjet : MCPjets) { + + bool jetIncluded = false; + for (const auto& jetR : jetRadiiValues) { + if (mcpjet.r() == static_cast(jetR * 100)) { + jetIncluded = true; + break; + } } + + if (!jetIncluded) { + continue; + } + + fillMCPHistograms(mcpjet); } } - PROCESS_SWITCH(BJetTaggingML, processMCTruthJets, "truth jet information", false); + PROCESS_SWITCH(BJetTaggingML, processMCTruthJets, "truth jet information without event weight", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/bjetTreeCreator.cxx b/PWGJE/Tasks/bjetTreeCreator.cxx index ba7c8e49c6d..103de117469 100644 --- a/PWGJE/Tasks/bjetTreeCreator.cxx +++ b/PWGJE/Tasks/bjetTreeCreator.cxx @@ -15,30 +15,39 @@ /// /// \author Hadi Hassan , University of Jyväskylä -#include -#include -#include -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFinder.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetTaggingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "PWGJE/DataModel/JetTagging.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/RecoDecay.h" +#include "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 +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/dijetFinderQA.cxx b/PWGJE/Tasks/dijetFinderQA.cxx index d2697e614bf..b5410727b7c 100644 --- a/PWGJE/Tasks/dijetFinderQA.cxx +++ b/PWGJE/Tasks/dijetFinderQA.cxx @@ -13,32 +13,30 @@ // /// \author Dongguk Kim -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/emcCellMonitor.cxx b/PWGJE/Tasks/emcCellMonitor.cxx index bb1d8fb3f9f..880ce14e490 100644 --- a/PWGJE/Tasks/emcCellMonitor.cxx +++ b/PWGJE/Tasks/emcCellMonitor.cxx @@ -9,25 +9,31 @@ // 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 #include +#include #include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" - -#include "DataFormatsEMCAL/Constants.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "CommonDataFormat/InteractionRecord.h" - /// \struct CellMonitor /// \brief Simple monitoring task for cell related quantities /// \author Markus Fasel , Oak Ridge National Laoratory diff --git a/PWGJE/Tasks/emcClusterMonitor.cxx b/PWGJE/Tasks/emcClusterMonitor.cxx index 37ee979cc67..fbb8885c5be 100644 --- a/PWGJE/Tasks/emcClusterMonitor.cxx +++ b/PWGJE/Tasks/emcClusterMonitor.cxx @@ -9,33 +9,39 @@ // 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 "PWGJE/DataModel/EMCALClusters.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#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 "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" +#include +#include +#include -#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 -#include "CommonDataFormat/InteractionRecord.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include // \struct ClusterMonitor /// \brief Simple monitoring task for EMCal clusters diff --git a/PWGJE/Tasks/emcEventSelectionQA.cxx b/PWGJE/Tasks/emcEventSelectionQA.cxx index 53bc21b56b4..8ba3f5168c8 100644 --- a/PWGJE/Tasks/emcEventSelectionQA.cxx +++ b/PWGJE/Tasks/emcEventSelectionQA.cxx @@ -13,16 +13,25 @@ /// \brief Monitoring task for EMCAL event selection /// \author Markus Fasel , Oak Ridge National Laoratory -#include +#include "PWGJE/Core/utilsBcSelEMC.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "PWGJE/Core/utilsBcSelEMC.h" +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -136,7 +145,7 @@ struct EmcEventSelectionQA { if (bc.runNumber() > mRun3MinNumber) { // in case of run3 not all BCs contain EMCAL data, require trigger selection also for min. bias // in addition select also L0/L1 triggers as triggers with EMCAL in reaodut - if (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kDG1) || bc.alias_bit(kDG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2) || bc.alias_bit(kDJ1) || bc.alias_bit(kDJ2)) { + if (bc.alias_bit(kTVXinEMC) || bc.alias_bit(kEMC7) || bc.alias_bit(kDMC7) || bc.alias_bit(kEG1) || bc.alias_bit(kEG2) || bc.alias_bit(kDG1) || bc.alias_bit(kDG2) || bc.alias_bit(kEJ1) || bc.alias_bit(kEJ2) || bc.alias_bit(kDJ1) || bc.alias_bit(kDJ2)) { isEMCALreadout = true; } } else { diff --git a/PWGJE/Tasks/emcTmMonitor.cxx b/PWGJE/Tasks/emcTmMonitor.cxx index 3a191cba635..3d6baefda3b 100644 --- a/PWGJE/Tasks/emcTmMonitor.cxx +++ b/PWGJE/Tasks/emcTmMonitor.cxx @@ -9,35 +9,7 @@ // 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 "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 "Common/DataModel/TrackSelectionTables.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 TrackMatchingMonitor +/// \file emcTmMonitor.cxx /// \brief Simple monitoring task for EMCal clusters /// \author Marvin Hemmer /// \since 24.02.2023 @@ -50,14 +22,41 @@ /// Simple event selection using the flag doEventSel is provided, which selects INT7 events if set to 1 /// For pilot beam data, instead of relying on the event selection, one can veto specific BC IDS using the flag /// fDoVetoBCID. + +#include "PWGJE/DataModel/EMCALClusters.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 +#include +#include +#include +#include + using namespace o2::framework; using namespace o2::framework::expressions; -using collisionEvSelIt = o2::soa::Join::iterator; -using bcEvSelIt = o2::soa::Join::iterator; -using selectedClusters = o2::soa::Filtered; -using selectedAmbiguousClusters = o2::soa::Filtered; -using tracksPID = o2::soa::Join; -struct TrackMatchingMonitor { +using CollisionEvSelIt = o2::soa::Join::iterator; +using BcEvSelIt = o2::soa::Join::iterator; +using SelectedClusters = o2::soa::Filtered; +using TracksPID = o2::soa::Join; +struct EmcTmMonitor { HistogramRegistry mHistManager{"TrackMatchingMonitorHistograms", {}, OutputObjHandlingPolicy::AnalysisObject}; o2::emcal::Geometry* mGeometry = nullptr; @@ -65,14 +64,13 @@ struct TrackMatchingMonitor { Preslice perClusterAmb = o2::aod::emcalclustercell::emcalambiguousclusterId; Preslice perClusterMatchedTracks = o2::aod::emcalclustercell::emcalclusterId; // configurable parameters - // TODO adapt mDoEventSel switch to also allow selection of other triggers (e.g. EMC7) - Configurable mDoEventSel{"doEventSel", 0, "demand kINT7"}; - Configurable mVetoBCID{"vetoBCID", "", "BC ID(s) to be excluded, this should be used as an alternative to the event selection"}; - Configurable mSelectBCID{"selectBCID", "all", "BC ID(s) to be included, this should be used as an alternative to the event selection"}; - Configurable mVertexCut{"vertexCut", -1, "apply z-vertex cut with value in cm"}; - Configurable mClusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"}; - ConfigurableAxis mClusterTimeBinning{"clustertime-binning", {1500, -600, 900}, ""}; - Configurable hasPropagatedTracks{"hasPropagatedTracks", false, "temporary flag, only set to true when running over data which has the tracks propagated to EMCal/PHOS!"}; + // TODO adapt doEventSel switch to also allow selection of other triggers (e.g. EMC7) + Configurable doEventSel{"doEventSel", 0, "demand kINT7"}; + Configurable vetoBCID{"vetoBCID", "", "BC ID(s) to be excluded, this should be used as an alternative to the event selection"}; + Configurable selectBCID{"selectBCID", "all", "BC ID(s) to be included, this should be used as an alternative to the event selection"}; + Configurable vertexCut{"vertexCut", -1, "apply z-vertex cut with value in cm"}; + Configurable clusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"}; + ConfigurableAxis clusterTimeBinning{"clusterTimeBinning", {1500, -600, 900}, ""}; Configurable usePionRejection{"usePionRejection", false, "demand pion rection for electron signal with TPC PID"}; Configurable> tpcNsigmaElectron{"tpcNsigmaElectron", {-1., +3.}, "TPC PID NSigma range for electron signal (first <= NSigma <= second)"}; Configurable> tpcNsigmaBack{"tpcNsigmaBack", {-10., -4.}, "TPC PID NSigma range for electron background (first <= NSigma <= second)"}; @@ -82,7 +80,7 @@ struct TrackMatchingMonitor { Configurable minM02{"minM02", 0.1, "Minimum M02 for M02 cut"}; Configurable maxM02{"maxM02", 0.9, "Maximum M02 for M02 cut"}; Configurable maxM02HighPt{"maxM02HighPt", 0.6, "Maximum M02 for M02 cut for high pT"}; - Configurable M02highPt{"M02highPt", 15., "pT threshold for maxM02HighPt cut. Set to negative value to disable it!"}; + Configurable m02highPt{"m02highPt", 15., "pT threshold for maxM02HighPt cut. Set to negative value to disable it!"}; Configurable minDEta{"minDEta", 0.01, "Minimum dEta between track and cluster"}; Configurable minDPhi{"minDPhi", 0.01, "Minimum dPhi between track and cluster"}; Configurable> eOverPRange{"eOverPRange", {0.9, 1.2}, "E/p range where one would search for electrons (first <= E/p <= second)"}; @@ -94,101 +92,98 @@ struct TrackMatchingMonitor { /// \brief Create output histograms and initialize geometry void init(InitContext const&) { - // create histograms - using o2HistType = HistType; - using o2Axis = AxisSpec; - // load geometry just in case we need it mGeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); // create common axes LOG(info) << "Creating histograms"; - const o2Axis bcAxis{3501, -0.5, 3500.5}; - const o2Axis energyAxis{makeEnergyBinningAliPhysics(), "E_{clus} (GeV)"}; - const o2Axis amplitudeAxisLarge{1000, 0., 100., "amplitudeLarge", "Amplitude (GeV)"}; - const o2Axis dEtaAxis{100, -1.f * minDEta, minDEta, "d#it{#eta}"}; - const o2Axis dPhiAxis{100, -1.f * minDPhi, minDPhi, "d#it{#varphi} (rad)"}; - const o2Axis dRAxis{150, 0.0, 0.015, "d#it{R}"}; - const o2Axis eoverpAxis{500, 0, 10, "#it{E}_{cluster}/#it{p}_{track}"}; - const o2Axis nSigmaAxis{400, -10., +30., "N#sigma"}; - const o2Axis trackptAxis{makePtBinning(), "#it{p}_{T,track}"}; - const o2Axis trackpAxis{200, 0, 100, "#it{p}_{track}"}; - const o2Axis clusterptAxis{makePtBinning(), "#it{p}_{T}"}; - const o2Axis etaAxis{160, -0.8, 0.8, "#eta"}; - const o2Axis phiAxis{72, 0, 2 * 3.14159, "#varphi (rad)"}; - const o2Axis smAxis{20, -0.5, 19.5, "SM"}; - o2Axis timeAxis{mClusterTimeBinning, "t_{cl} (ns)"}; + const AxisSpec bcAxis{3501, -0.5, 3500.5}; + const AxisSpec energyAxis{makeEnergyBinningAliPhysics(), "E_{clus} (GeV)"}; + const AxisSpec amplitudeAxisLarge{1000, 0., 100., "amplitudeLarge", "Amplitude (GeV)"}; + const AxisSpec dEtaAxis{100, -1.f * minDEta, minDEta, "d#it{#eta}"}; + const AxisSpec dPhiAxis{100, -1.f * minDPhi, minDPhi, "d#it{#varphi} (rad)"}; + const AxisSpec dRAxis{150, 0.0, 0.015, "d#it{R}"}; + const AxisSpec eoverpAxis{500, 0, 10, "#it{E}_{cluster}/#it{p}_{track}"}; + const AxisSpec nSigmaAxis{400, -10., +30., "N#sigma"}; + const AxisSpec trackptAxis{makePtBinning(), "#it{p}_{T,track}"}; + const AxisSpec trackpAxis{200, 0, 100, "#it{p}_{track}"}; + const AxisSpec clusterptAxis{makePtBinning(), "#it{p}_{T}"}; + const AxisSpec etaAxis{160, -0.8, 0.8, "#eta"}; + const AxisSpec phiAxis{72, 0, 2 * 3.14159, "#varphi (rad)"}; + const AxisSpec smAxis{20, -0.5, 19.5, "SM"}; + AxisSpec timeAxis{clusterTimeBinning, "t_{cl} (ns)"}; - int MaxMatched = 20; // maximum number of matched tracks, hardcoded in emcalCorrectionTask.cxx! - const o2Axis nmatchedtrack{MaxMatched, -0.5, MaxMatched + 0.5}; + const int maxMatched = 20; // maximum number of matched tracks, hardcoded in emcalCorrectionTask.cxx! + const AxisSpec nmatchedtrack{maxMatched, -0.5, maxMatched + 0.5}; + // create histograms // event properties - mHistManager.add("eventsAll", "Number of events", o2HistType::kTH1F, {{1, 0.5, 1.5}}); - mHistManager.add("eventsSelected", "Number of events", o2HistType::kTH1F, {{1, 0.5, 1.5}}); - mHistManager.add("eventVertexZAll", "z-vertex of event (all events)", o2HistType::kTH1F, {{200, -20, 20}}); - mHistManager.add("eventVertexZSelected", "z-vertex of event (selected events)", o2HistType::kTH1F, {{200, -20, 20}}); + mHistManager.add("eventsAll", "Number of events", HistType::kTH1F, {{1, 0.5, 1.5}}); + mHistManager.add("eventsSelected", "Number of events", HistType::kTH1F, {{1, 0.5, 1.5}}); + 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}}); // cluster properties (matched clusters) - mHistManager.add("TrackEtaPhi", "#eta vs #varphi of all selected tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected tracks - mHistManager.add("TrackEtaPhi_Neg", "#eta vs #varphi of all selected negative tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative tracks - mHistManager.add("TrackEtaPhi_Pos", "#eta vs #varphi of all selected positive tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive tracks - mHistManager.add("clusterEMatched", "Energy of cluster (with match)", o2HistType::kTH1F, {energyAxis}); // energy of matched clusters - mHistManager.add("MatchedTrackEtaPhi_BeforeCut", "#eta vs #varphi of all selected matched tracks before d#eta and #dvarphi cut", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks before dEta and dPhi cut - mHistManager.add("MatchedTrackEtaPhi_Neg_BeforeCut", "#eta vs #varphi of all selected negative matched tracks before d#eta and #dvarphi cut", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks before dEta and dPhi cut - mHistManager.add("MatchedTrackEtaPhi_Pos_BeforeCut", "#eta vs #varphi of all selected positive matched tracks before d#eta and #dvarphi cut", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks before dEta and dPhi cut - mHistManager.add("MatchedTrackEtaPhi", "#eta vs #varphi of all selected matched tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks - mHistManager.add("MatchedTrackEtaPhi_Neg", "#eta vs #varphi of all selected negative matched tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks - mHistManager.add("MatchedTrackEtaPhi_Pos", "#eta vs #varphi of all selected positive matched tracks", o2HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks - mHistManager.add("clusterTM_dEtadPhi", "cluster trackmatching dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM - mHistManager.add("clusterTM_dEtadPhi_ASide", "cluster trackmatching in A-Side dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in A-Aside - mHistManager.add("clusterTM_dEtadPhi_CSide", "cluster trackmatching in C-Side tracks dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in C-Side - mHistManager.add("clusterTM_PosdEtadPhi", "cluster trackmatching positive tracks dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track - mHistManager.add("clusterTM_NegdEtadPhi", "cluster trackmatching negative tracks dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track - mHistManager.add("clusterTM_PosdEtadPhi_Pl0_75", "cluster trackmatching positive tracks, p < 0.75 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p < 0.75 GeV/c - mHistManager.add("clusterTM_NegdEtadPhi_Pl0_75", "cluster trackmatching negative tracks, p < 0.75 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p < 0.75 GeV/c - mHistManager.add("clusterTM_PosdEtadPhi_0_75leqPl1_25", "cluster trackmatching positive tracks, 0.75 <= p < 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with 0.75 <= p < 1.25 GeV/c - mHistManager.add("clusterTM_NegdEtadPhi_0_75leqPl1_25", "cluster trackmatching negative tracks, 0.75 <= p < 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with 0.75 <= p < 1.25 GeV/c - mHistManager.add("clusterTM_PosdEtadPhi_Pgeq1_25", "cluster trackmatching positive tracks, p >= 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p >= 1.25 GeV/c - mHistManager.add("clusterTM_NegdEtadPhi_Pgeq1_25", "cluster trackmatching negative tracks, p >= 1.25 dEta/dPhi", o2HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p >= 1.25 GeV/c - mHistManager.add("clusterTM_dEtaPt", "cluster trackmatching dEta/#it{p}_{T};d#it{#eta};#it{p}_{T} (GeV/#it{c})", o2HistType::kTH3F, {dEtaAxis, clusterptAxis, smAxis}); // dEta vs pT per SM - mHistManager.add("clusterTM_PosdPhiPt", "cluster trackmatching positive tracks dPhi/#it{p}_{T}", o2HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM positive track - mHistManager.add("clusterTM_NegdPhiPt", "cluster trackmatching negative tracks dPh/#it{p}_{T}", o2HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM negative track - mHistManager.add("clusterTM_dEtaTN", "cluster trackmatching dEta/TN;d#it{#eta};#it{N}_{matched tracks}", o2HistType::kTH2F, {dEtaAxis, nmatchedtrack}); // dEta compared to the Nth closest track - mHistManager.add("clusterTM_dPhiTN", "cluster trackmatching dPhi/TN;d#it{#varphi} (rad);#it{N}_{matched tracks}", o2HistType::kTH2F, {dPhiAxis, nmatchedtrack}); // dPhi compared to the Nth closest track - mHistManager.add("clusterTM_dRTN", "cluster trackmatching dR/TN;d#it{R};#it{N}_{matched tracks}", o2HistType::kTH2F, {dRAxis, nmatchedtrack}); // dR compared to the Nth closest track - mHistManager.add("clusterTM_NTrack", "cluster trackmatching NMatchedTracks", o2HistType::kTH1I, {nmatchedtrack}); // how many tracks are matched - mHistManager.add("clusterTM_EoverP_E", "E/p ", o2HistType::kTH3F, {eoverpAxis, energyAxis, nmatchedtrack}); // E/p vs p for the Nth closest track - mHistManager.add("clusterTM_EoverP_Pt", "E/p vs track pT", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E/p vs track pT for the Nth closest track - mHistManager.add("clusterTM_EvsP", "cluster E/track p", o2HistType::kTH3F, {energyAxis, trackpAxis, nmatchedtrack}); // E vs p for the Nth closest track - mHistManager.add("clusterTM_EoverP_ep", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track - mHistManager.add("clusterTM_EoverP_e", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron track - mHistManager.add("clusterTM_EoverP_p", "cluster E/electron p", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positron track - mHistManager.add("clusterTM_EoverP_electron_ASide", "cluster E/electron p in A-Side", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in A-Side - mHistManager.add("clusterTM_EoverP_electron_CSide", "cluster E/electron p in C-Side", o2HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in C-Side - mHistManager.add("clusterTM_NSigma_BeforeCut", "electron NSigma for matched tracks before d#eta and #dvarphi cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track before dEta and dPhi cut - mHistManager.add("clusterTM_NSigma_neg_BeforeCut", "electron NSigma for matched negative tracks before d#eta and #dvarphi cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks before dEta and dPhi cut - mHistManager.add("clusterTM_NSigma_pos_BeforeCut", "electron NSigma for matched positive tracks before d#eta and #dvarphi cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks before dEta and dPhi cut - mHistManager.add("clusterTM_NSigma", "electron NSigma for matched track", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track - mHistManager.add("clusterTM_NSigma_neg", "electron NSigma for matched negative track", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks - mHistManager.add("clusterTM_NSigma_pos", "electron NSigma for matched positive track", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks - mHistManager.add("clusterTM_NSigma_cut", "electron NSigma for matched track with cuts", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track with cuts on E/p and cluster cuts - mHistManager.add("clusterTM_NSigma_e", "NSigma electron", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track - mHistManager.add("clusterTM_NSigma_p", "NSigma positron", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track - mHistManager.add("clusterTM_NSigma_e_cut", "NSigma electron with E over p cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track with E/p cut - mHistManager.add("clusterTM_NSigma_p_cut", "NSigma positron with E over p cut", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track with E/p cut - mHistManager.add("TrackTM_NSigma", "electron NSigma for global tracks", o2HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma_electron vs track pT for global track - mHistManager.add("TrackTM_NSigma_e", "NSigma e for global negative tracks", o2HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for negative global track - mHistManager.add("TrackTM_NSigma_p", "NSigma e for global positive tracks", o2HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for positive global track - mHistManager.add("clusterTM_NSigma_electron_ASide", "NSigma electron in A-Side", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in A-Side - mHistManager.add("clusterTM_NSigma_electron_CSide", "NSigma positron in C-Side", o2HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in C-Side - mHistManager.add("clusterTM_EoverP_hadron", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track - mHistManager.add("clusterTM_EoverP_hn", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest negative hadron track - mHistManager.add("clusterTM_EoverP_hp", "cluster E/hadron p", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positive hadron track - mHistManager.add("clusterTM_EoverP_hadron_ASide", "cluster E/hadron p in A-Side", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in A-Side - mHistManager.add("clusterTM_EoverP_hadron_CSide", "cluster E/hadron p in C-Side", o2HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in C-Side + mHistManager.add("TrackEtaPhi", "#eta vs #varphi of all selected tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected tracks + mHistManager.add("TrackEtaPhi_Neg", "#eta vs #varphi of all selected negative tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative tracks + mHistManager.add("TrackEtaPhi_Pos", "#eta vs #varphi of all selected positive tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive tracks + mHistManager.add("clusterEMatched", "Energy of cluster (with match)", HistType::kTH1F, {energyAxis}); // energy of matched clusters + mHistManager.add("MatchedTrackEtaPhi_BeforeCut", "#eta vs #varphi of all selected matched tracks before d#eta and #dvarphi cut", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks before dEta and dPhi cut + mHistManager.add("MatchedTrackEtaPhi_Neg_BeforeCut", "#eta vs #varphi of all selected negative matched tracks before d#eta and #dvarphi cut", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks before dEta and dPhi cut + mHistManager.add("MatchedTrackEtaPhi_Pos_BeforeCut", "#eta vs #varphi of all selected positive matched tracks before d#eta and #dvarphi cut", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks before dEta and dPhi cut + mHistManager.add("MatchedTrackEtaPhi", "#eta vs #varphi of all selected matched tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected matched tracks + mHistManager.add("MatchedTrackEtaPhi_Neg", "#eta vs #varphi of all selected negative matched tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected negative matched tracks + mHistManager.add("MatchedTrackEtaPhi_Pos", "#eta vs #varphi of all selected positive matched tracks", HistType::kTH2F, {etaAxis, phiAxis}); // eta vs phi of all selected positive matched tracks + mHistManager.add("clusterTM_dEtadPhi", "cluster trackmatching dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM + mHistManager.add("clusterTM_dEtadPhi_ASide", "cluster trackmatching in A-Side dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in A-Aside + mHistManager.add("clusterTM_dEtadPhi_CSide", "cluster trackmatching in C-Side tracks dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM in C-Side + mHistManager.add("clusterTM_PosdEtadPhi", "cluster trackmatching positive tracks dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track + mHistManager.add("clusterTM_NegdEtadPhi", "cluster trackmatching negative tracks dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track + mHistManager.add("clusterTM_PosdEtadPhi_Pl0_75", "cluster trackmatching positive tracks, p < 0.75 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p < 0.75 GeV/c + mHistManager.add("clusterTM_NegdEtadPhi_Pl0_75", "cluster trackmatching negative tracks, p < 0.75 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p < 0.75 GeV/c + mHistManager.add("clusterTM_PosdEtadPhi_0_75leqPl1_25", "cluster trackmatching positive tracks, 0.75 <= p < 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with 0.75 <= p < 1.25 GeV/c + mHistManager.add("clusterTM_NegdEtadPhi_0_75leqPl1_25", "cluster trackmatching negative tracks, 0.75 <= p < 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with 0.75 <= p < 1.25 GeV/c + mHistManager.add("clusterTM_PosdEtadPhi_Pgeq1_25", "cluster trackmatching positive tracks, p >= 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM positive track with p >= 1.25 GeV/c + mHistManager.add("clusterTM_NegdEtadPhi_Pgeq1_25", "cluster trackmatching negative tracks, p >= 1.25 dEta/dPhi", HistType::kTH3F, {dEtaAxis, dPhiAxis, smAxis}); // dEta dPhi per SM negative track with p >= 1.25 GeV/c + mHistManager.add("clusterTM_dEtaPt", "cluster trackmatching dEta/#it{p}_{T};d#it{#eta};#it{p}_{T} (GeV/#it{c})", HistType::kTH3F, {dEtaAxis, clusterptAxis, smAxis}); // dEta vs pT per SM + mHistManager.add("clusterTM_PosdPhiPt", "cluster trackmatching positive tracks dPhi/#it{p}_{T}", HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM positive track + mHistManager.add("clusterTM_NegdPhiPt", "cluster trackmatching negative tracks dPh/#it{p}_{T}", HistType::kTH3F, {dPhiAxis, clusterptAxis, smAxis}); // dPhi vs pT per SM negative track + mHistManager.add("clusterTM_dEtaTN", "cluster trackmatching dEta/TN;d#it{#eta};#it{N}_{matched tracks}", HistType::kTH2F, {dEtaAxis, nmatchedtrack}); // dEta compared to the Nth closest track + mHistManager.add("clusterTM_dPhiTN", "cluster trackmatching dPhi/TN;d#it{#varphi} (rad);#it{N}_{matched tracks}", HistType::kTH2F, {dPhiAxis, nmatchedtrack}); // dPhi compared to the Nth closest track + mHistManager.add("clusterTM_dRTN", "cluster trackmatching dR/TN;d#it{R};#it{N}_{matched tracks}", HistType::kTH2F, {dRAxis, nmatchedtrack}); // dR compared to the Nth closest track + mHistManager.add("clusterTM_NTrack", "cluster trackmatching NMatchedTracks", HistType::kTH1I, {nmatchedtrack}); // how many tracks are matched + mHistManager.add("clusterTM_EoverP_E", "E/p ", HistType::kTH3F, {eoverpAxis, energyAxis, nmatchedtrack}); // E/p vs p for the Nth closest track + mHistManager.add("clusterTM_EoverP_Pt", "E/p vs track pT", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E/p vs track pT for the Nth closest track + mHistManager.add("clusterTM_EvsP", "cluster E/track p", HistType::kTH3F, {energyAxis, trackpAxis, nmatchedtrack}); // E vs p for the Nth closest track + mHistManager.add("clusterTM_EoverP_ep", "cluster E/electron p", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track + mHistManager.add("clusterTM_EoverP_e", "cluster E/electron p", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron track + mHistManager.add("clusterTM_EoverP_p", "cluster E/electron p", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positron track + mHistManager.add("clusterTM_EoverP_electron_ASide", "cluster E/electron p in A-Side", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in A-Side + mHistManager.add("clusterTM_EoverP_electron_CSide", "cluster E/electron p in C-Side", HistType::kTH3F, {eoverpAxis, trackptAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest electron/positron track in C-Side + mHistManager.add("clusterTM_NSigma_BeforeCut", "electron NSigma for matched tracks before d#eta and #dvarphi cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track before dEta and dPhi cut + mHistManager.add("clusterTM_NSigma_neg_BeforeCut", "electron NSigma for matched negative tracks before d#eta and #dvarphi cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks before dEta and dPhi cut + mHistManager.add("clusterTM_NSigma_pos_BeforeCut", "electron NSigma for matched positive tracks before d#eta and #dvarphi cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks before dEta and dPhi cut + mHistManager.add("clusterTM_NSigma", "electron NSigma for matched track", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track + mHistManager.add("clusterTM_NSigma_neg", "electron NSigma for matched negative track", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest negative tracks + mHistManager.add("clusterTM_NSigma_pos", "electron NSigma for matched positive track", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest positive tracks + mHistManager.add("clusterTM_NSigma_cut", "electron NSigma for matched track with cuts", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma_electron vs track pT for the Nth closest track with cuts on E/p and cluster cuts + mHistManager.add("clusterTM_NSigma_e", "NSigma electron", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track + mHistManager.add("clusterTM_NSigma_p", "NSigma positron", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track + mHistManager.add("clusterTM_NSigma_e_cut", "NSigma electron with E over p cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron track with E/p cut + mHistManager.add("clusterTM_NSigma_p_cut", "NSigma positron with E over p cut", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest positron track with E/p cut + mHistManager.add("TrackTM_NSigma", "electron NSigma for global tracks", HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma_electron vs track pT for global track + mHistManager.add("TrackTM_NSigma_e", "NSigma e for global negative tracks", HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for negative global track + mHistManager.add("TrackTM_NSigma_p", "NSigma e for global positive tracks", HistType::kTH2F, {nSigmaAxis, trackptAxis}); // NSigma vs track pT for positive global track + mHistManager.add("clusterTM_NSigma_electron_ASide", "NSigma electron in A-Side", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in A-Side + mHistManager.add("clusterTM_NSigma_electron_CSide", "NSigma positron in C-Side", HistType::kTH3F, {nSigmaAxis, trackptAxis, nmatchedtrack}); // NSigma vs track pT for the Nth closest electron/positron track in C-Side + mHistManager.add("clusterTM_EoverP_hadron", "cluster E/hadron p", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track + mHistManager.add("clusterTM_EoverP_hn", "cluster E/hadron p", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest negative hadron track + mHistManager.add("clusterTM_EoverP_hp", "cluster E/hadron p", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest positive hadron track + mHistManager.add("clusterTM_EoverP_hadron_ASide", "cluster E/hadron p in A-Side", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in A-Side + mHistManager.add("clusterTM_EoverP_hadron_CSide", "cluster E/hadron p in C-Side", HistType::kTH3F, {eoverpAxis, trackpAxis, nmatchedtrack}); // E over p vs track pT for the Nth closest hadron track in C-Side - if (mVetoBCID->length()) { - std::stringstream parser(mVetoBCID.value); + if (vetoBCID->length()) { + std::stringstream parser(vetoBCID.value); std::string token; int bcid; while (std::getline(parser, token, ',')) { @@ -197,8 +192,8 @@ struct TrackMatchingMonitor { mVetoBCIDs.push_back(bcid); } } - if (mSelectBCID.value != "all") { - std::stringstream parser(mSelectBCID.value); + if (selectBCID.value != "all") { + std::stringstream parser(selectBCID.value); std::string token; int bcid; while (std::getline(parser, token, ',')) { @@ -212,19 +207,22 @@ struct TrackMatchingMonitor { // define cluster filter. It selects only those clusters which are of the type // sadly passing of the string at runtime is not possible for technical region so cluster definition is // an integer instead - Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == mClusterDefinition) && (o2::aod::emcalcluster::time >= minTime) && (o2::aod::emcalcluster::time <= maxTime) && (o2::aod::emcalcluster::m02 > minM02) && (o2::aod::emcalcluster::m02 < maxM02); + Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == clusterDefinition) && (o2::aod::emcalcluster::time >= minTime) && (o2::aod::emcalcluster::time <= maxTime) && (o2::aod::emcalcluster::m02 > minM02) && (o2::aod::emcalcluster::m02 < maxM02); /// \brief Process EMCAL clusters that are matched to a collisions - void processCollisions(collisionEvSelIt const& theCollision, selectedClusters const& clusters, o2::aod::EMCALClusterCells const&, o2::aod::Calos const&, o2::aod::EMCALMatchedTracks const& matchedtracks, tracksPID const& alltracks) + void processCollisions(CollisionEvSelIt const& theCollision, SelectedClusters const& clusters, o2::aod::EMCALClusterCells const&, o2::aod::Calos const&, o2::aod::EMCALMatchedTracks const& matchedtracks, TracksPID const& alltracks) { mHistManager.fill(HIST("eventsAll"), 1); - // do event selection if mDoEventSel is specified + // do event selection if doEventSel is specified // currently the event selection is hard coded to kINT7 // but other selections are possible that are defined in TriggerAliases.h bool isSelected = true; - if (mDoEventSel) { - if (theCollision.bc().runNumber() < 300000) { + const int beginningRun3 = 300000; + float lowP = 0.75f; + float midP = 1.25f; + if (doEventSel) { + if (theCollision.bc().runNumber() < beginningRun3) { if (!theCollision.alias_bit(kINT7)) { isSelected = false; } @@ -239,8 +237,8 @@ struct TrackMatchingMonitor { return; } mHistManager.fill(HIST("eventVertexZAll"), theCollision.posZ()); - if (mVertexCut > 0 && TMath::Abs(theCollision.posZ()) > mVertexCut) { - LOG(debug) << "Event not selected because of z-vertex cut z= " << theCollision.posZ() << " > " << mVertexCut << " cm, skipping"; + if (vertexCut > 0 && std::abs(theCollision.posZ()) > vertexCut) { + LOG(debug) << "Event not selected because of z-vertex cut z= " << theCollision.posZ() << " > " << vertexCut << " cm, skipping"; return; } mHistManager.fill(HIST("eventsSelected"), 1); @@ -248,13 +246,8 @@ struct TrackMatchingMonitor { for (const auto& alltrack : alltracks) { double trackEta, trackPhi; - if (hasPropagatedTracks) { // only temporarily while not every data has the tracks propagated to EMCal/PHOS - trackEta = alltrack.trackEtaEmcal(); - trackPhi = alltrack.trackPhiEmcal(); - } else { - trackEta = alltrack.eta(); - trackPhi = alltrack.phi(); - } + trackEta = alltrack.trackEtaEmcal(); + trackPhi = alltrack.trackPhiEmcal(); if (alltrack.isGlobalTrack()) { // NSigma of all global tracks without matching mHistManager.fill(HIST("TrackTM_NSigma"), alltrack.tpcNSigmaEl(), alltrack.pt()); mHistManager.fill(HIST("TrackEtaPhi"), trackEta, trackPhi); @@ -291,7 +284,7 @@ struct TrackMatchingMonitor { // match.track_as() with // using globTracks = o2::soa::Join; // In this example the counter t is just used to only look at the closest match - double dEta, dPhi, pT, abs_p, trackEta, trackPhi, NSigmaEl; + float dEta, dPhi, pT, abs_p, trackEta, trackPhi, nSigmaEl; int supermoduleID; try { supermoduleID = mGeometry->SuperModuleNumberFromEtaPhi(cluster.eta(), cluster.phi()); @@ -301,40 +294,35 @@ struct TrackMatchingMonitor { continue; } - pT = cluster.energy() / cosh(cluster.eta()); - if (M02highPt > 0. && cluster.m02() >= maxM02HighPt && pT >= M02highPt) { // high pT M02 cut + pT = cluster.energy() / std::cosh(cluster.eta()); + if (m02highPt > 0. && cluster.m02() >= maxM02HighPt && pT >= m02highPt) { // high pT M02 cut continue; } auto tracksofcluster = matchedtracks.sliceBy(perClusterMatchedTracks, cluster.globalIndex()); int t = 0; for (const auto& match : tracksofcluster) { - NSigmaEl = match.track_as().tpcNSigmaEl(); + nSigmaEl = match.track_as().tpcNSigmaEl(); // exmple of how to access any property of the matched tracks (tracks are sorted by how close they are to cluster) - LOG(debug) << "Pt of match" << match.track_as().pt(); - abs_p = abs(match.track_as().p()); + LOG(debug) << "Pt of match" << match.track_as().pt(); + abs_p = std::abs(match.track_as().p()); // only consider closest match - if (hasPropagatedTracks) { // only temporarily while not every data has the tracks propagated to EMCal/PHOS - trackEta = match.track_as().trackEtaEmcal(); - trackPhi = match.track_as().trackPhiEmcal(); - } else { - trackEta = match.track_as().eta(); - trackPhi = match.track_as().phi(); - } - dPhi = trackPhi - cluster.phi(); - dEta = trackEta - cluster.eta(); + trackEta = match.track_as().trackEtaEmcal(); + trackPhi = match.track_as().trackPhiEmcal(); + dPhi = match.deltaPhi(); + dEta = match.deltaEta(); mHistManager.fill(HIST("MatchedTrackEtaPhi_BeforeCut"), trackEta, trackPhi); - mHistManager.fill(HIST("clusterTM_NSigma_BeforeCut"), NSigmaEl, match.track_as().pt(), t); - if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_NSigma_BeforeCut"), nSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { mHistManager.fill(HIST("MatchedTrackEtaPhi_Neg_BeforeCut"), trackEta, trackPhi); - mHistManager.fill(HIST("clusterTM_NSigma_neg_BeforeCut"), NSigmaEl, match.track_as().pt(), t); - } else if (match.track_as().sign() == 1) { + mHistManager.fill(HIST("clusterTM_NSigma_neg_BeforeCut"), nSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == 1) { mHistManager.fill(HIST("MatchedTrackEtaPhi_Pos_BeforeCut"), trackEta, trackPhi); - mHistManager.fill(HIST("clusterTM_NSigma_pos_BeforeCut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_pos_BeforeCut"), nSigmaEl, match.track_as().pt(), t); } - if (fabs(dEta) >= minDEta || fabs(dPhi) >= minDPhi) { // dEta and dPhi cut + if (std::abs(dEta) >= minDEta || std::abs(dPhi) >= minDPhi) { // dEta and dPhi cut continue; } - if (hasTRD && !(match.track_as().hasTRD())) { // request TRD hit cut + if (hasTRD && !(match.track_as().hasTRD())) { // request TRD hit cut continue; } // only fill these for the first matched track: @@ -350,105 +338,105 @@ struct TrackMatchingMonitor { mHistManager.fill(HIST("clusterTM_dEtadPhi"), dEta, dPhi, t); mHistManager.fill(HIST("clusterEMatched"), cluster.energy(), t); mHistManager.fill(HIST("clusterTM_EvsP"), cluster.energy(), abs_p, t); - mHistManager.fill(HIST("clusterTM_EoverP_Pt"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_Pt"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma"), nSigmaEl, match.track_as().pt(), t); mHistManager.fill(HIST("MatchedTrackEtaPhi"), trackEta, trackPhi); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_cut"), nSigmaEl, match.track_as().pt(), t); } // A- and C-side - if (match.track_as().eta() > 0.0 && t == 0) { + if (match.track_as().eta() > 0.0 && t == 0) { mHistManager.fill(HIST("clusterTM_dEtadPhi_ASide"), dEta, dPhi, supermoduleID); - } else if (match.track_as().eta() < 0.0 && t == 0) { + } else if (match.track_as().eta() < 0.0 && t == 0) { mHistManager.fill(HIST("clusterTM_dEtadPhi_CSide"), dEta, dPhi, supermoduleID); } // positive and negative tracks seperate, with three different track momentum ranges - if (match.track_as().sign() == 1) { - mHistManager.fill(HIST("clusterTM_NSigma_pos"), NSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == 1) { + mHistManager.fill(HIST("clusterTM_NSigma_pos"), nSigmaEl, match.track_as().pt(), t); mHistManager.fill(HIST("MatchedTrackEtaPhi_Pos"), trackEta, trackPhi); if (t == 0) { mHistManager.fill(HIST("clusterTM_PosdPhiPt"), dPhi, pT, supermoduleID); mHistManager.fill(HIST("clusterTM_PosdEtadPhi"), dEta, dPhi, supermoduleID); - if (abs_p < 0.75) { + if (abs_p < lowP) { mHistManager.fill(HIST("clusterTM_PosdEtadPhi_Pl0_75"), dEta, dPhi, supermoduleID); - } else if (abs_p >= 1.25) { + } else if (abs_p >= midP) { mHistManager.fill(HIST("clusterTM_PosdEtadPhi_Pgeq1_25"), dEta, dPhi, supermoduleID); } else { mHistManager.fill(HIST("clusterTM_PosdEtadPhi_0_75leqPl1_25"), dEta, dPhi, supermoduleID); } } - } else if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_NSigma_neg"), NSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_NSigma_neg"), nSigmaEl, match.track_as().pt(), t); mHistManager.fill(HIST("MatchedTrackEtaPhi_Neg"), trackEta, trackPhi); if (t == 0) { mHistManager.fill(HIST("clusterTM_NegdPhiPt"), dPhi, pT, supermoduleID); mHistManager.fill(HIST("clusterTM_NegdEtadPhi"), dEta, dPhi, supermoduleID); - if (abs_p < 0.75) { + if (abs_p < lowP) { mHistManager.fill(HIST("clusterTM_NegdEtadPhi_Pl0_75"), dEta, dPhi, supermoduleID); - } else if (abs_p >= 1.25) { + } else if (abs_p >= midP) { mHistManager.fill(HIST("clusterTM_NegdEtadPhi_Pgeq1_25"), dEta, dPhi, supermoduleID); } else { mHistManager.fill(HIST("clusterTM_NegdEtadPhi_0_75leqPl1_25"), dEta, dPhi, supermoduleID); } } } - if (tpcNsigmaElectron->at(0) <= NSigmaEl && NSigmaEl <= tpcNsigmaElectron->at(1)) { // E/p for e+/e- - if (usePionRejection && (tpcNsigmaPion->at(0) <= match.track_as().tpcNSigmaPi() || match.track_as().tpcNSigmaPi() <= tpcNsigmaPion->at(1))) { // with pion rejection - mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); - if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), NSigmaEl, match.track_as().pt(), t); + if (tpcNsigmaElectron->at(0) <= nSigmaEl && nSigmaEl <= tpcNsigmaElectron->at(1)) { // E/p for e+/e- + if (usePionRejection && (tpcNsigmaPion->at(0) <= match.track_as().tpcNSigmaPi() || match.track_as().tpcNSigmaPi() <= tpcNsigmaPion->at(1))) { // with pion rejection + mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); + if (match.track_as().eta() >= 0.) { + mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), nSigmaEl, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), nSigmaEl, match.track_as().pt(), t); } - if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_e"), NSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), nSigmaEl, match.track_as().pt(), t); } - } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_p"), NSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == +1) { + mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), nSigmaEl, match.track_as().pt(), t); } } } else { // without pion rejection - mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); - if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_ep"), eOverP, match.track_as().pt(), t); + if (match.track_as().eta() >= 0.) { + mHistManager.fill(HIST("clusterTM_EoverP_electron_ASide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_ASide"), nSigmaEl, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_electron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_electron_CSide"), nSigmaEl, match.track_as().pt(), t); } - if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_e"), NSigmaEl, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_EoverP_e"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_e_cut"), nSigmaEl, match.track_as().pt(), t); } - } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); - mHistManager.fill(HIST("clusterTM_NSigma_p"), NSigmaEl, match.track_as().pt(), t); + } else if (match.track_as().sign() == +1) { + mHistManager.fill(HIST("clusterTM_EoverP_p"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p"), nSigmaEl, match.track_as().pt(), t); if (eOverPRange->at(0) <= eOverP && eOverP <= eOverPRange->at(1)) { - mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), NSigmaEl, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_NSigma_p_cut"), nSigmaEl, match.track_as().pt(), t); } } } - } else if (tpcNsigmaBack->at(0) <= NSigmaEl && NSigmaEl <= tpcNsigmaBack->at(1)) { // E/p for hadrons / background - mHistManager.fill(HIST("clusterTM_EoverP_hadron"), eOverP, match.track_as().pt(), t); - if (match.track_as().eta() >= 0.) { - mHistManager.fill(HIST("clusterTM_EoverP_hadron_ASide"), eOverP, match.track_as().pt(), t); + } else if (tpcNsigmaBack->at(0) <= nSigmaEl && nSigmaEl <= tpcNsigmaBack->at(1)) { // E/p for hadrons / background + mHistManager.fill(HIST("clusterTM_EoverP_hadron"), eOverP, match.track_as().pt(), t); + if (match.track_as().eta() >= 0.) { + mHistManager.fill(HIST("clusterTM_EoverP_hadron_ASide"), eOverP, match.track_as().pt(), t); } else { - mHistManager.fill(HIST("clusterTM_EoverP_hadron_CSide"), eOverP, match.track_as().pt(), t); + mHistManager.fill(HIST("clusterTM_EoverP_hadron_CSide"), eOverP, match.track_as().pt(), t); } - if (match.track_as().sign() == -1) { - mHistManager.fill(HIST("clusterTM_EoverP_hn"), eOverP, match.track_as().pt(), t); - } else if (match.track_as().sign() == +1) { - mHistManager.fill(HIST("clusterTM_EoverP_hp"), eOverP, match.track_as().pt(), t); + if (match.track_as().sign() == -1) { + mHistManager.fill(HIST("clusterTM_EoverP_hn"), eOverP, match.track_as().pt(), t); + } else if (match.track_as().sign() == +1) { + mHistManager.fill(HIST("clusterTM_EoverP_hp"), eOverP, match.track_as().pt(), t); } } t++; @@ -456,12 +444,11 @@ struct TrackMatchingMonitor { mHistManager.fill(HIST("clusterTM_NTrack"), t); } } - PROCESS_SWITCH(TrackMatchingMonitor, processCollisions, "Process clusters from collision", true); + PROCESS_SWITCH(EmcTmMonitor, processCollisions, "Process clusters from collision", true); /// \brief Create binning for cluster energy axis (variable bin size) /// \return vector with bin limits - std::vector - makeEnergyBinning() const + std::vector makeEnergyBinning() const { auto fillBinLimits = [](std::vector& binlimits, double max, double binwidth) { auto current = *binlimits.rbegin(); @@ -488,26 +475,27 @@ struct TrackMatchingMonitor { { std::vector result; - Int_t nBinsClusterE = 235; - for (Int_t i = 0; i < nBinsClusterE + 1; i++) { - if (i < 1) + int nBinsClusterE = 235; + for (int i = 0; i < nBinsClusterE + 1; i++) { + if (i < 1) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(0.3 * i); - else if (i < 55) + } else if (i < 55) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(0.3 + 0.05 * (i - 1)); - else if (i < 105) + } else if (i < 105) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(3. + 0.1 * (i - 55)); - else if (i < 140) + } else if (i < 140) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(8. + 0.2 * (i - 105)); - else if (i < 170) + } else if (i < 170) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(15. + 0.5 * (i - 140)); - else if (i < 190) + } else if (i < 190) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(30. + 1.0 * (i - 170)); - else if (i < 215) + } else if (i < 215) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(50. + 2.0 * (i - 190)); - else if (i < 235) + } else if (i < 235) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(100. + 5.0 * (i - 215)); - else if (i < 245) + } else if (i < 245) { // o2-linter: disable=magic-number (just numbers for binning) result.emplace_back(200. + 10.0 * (i - 235)); + } } return result; } @@ -521,20 +509,21 @@ struct TrackMatchingMonitor { result.reserve(1000); double epsilon = 1e-6; double valGammaPt = 0; - for (int i = 0; i < 1000; ++i) { + for (int i = 0; i < 1000; ++i) { // o2-linter: disable=magic-number (just numbers for binning) result.push_back(valGammaPt); - if (valGammaPt < 1.0 - epsilon) + if (valGammaPt < 1.0 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 0.1; - else if (valGammaPt < 5 - epsilon) + } else if (valGammaPt < 5 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 0.2; - else if (valGammaPt < 10 - epsilon) + } else if (valGammaPt < 10 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 0.5; - else if (valGammaPt < 50 - epsilon) + } else if (valGammaPt < 50 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 1; - else if (valGammaPt < 100 - epsilon) + } else if (valGammaPt < 100 - epsilon) { // o2-linter: disable=magic-number (just numbers for binning) valGammaPt += 5; - else + } else { break; + } } return result; } @@ -543,6 +532,6 @@ struct TrackMatchingMonitor { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ - adaptAnalysisTask(cfgc, TaskName{"emc-tmmonitor"})}; + adaptAnalysisTask(cfgc)}; return workflow; } diff --git a/PWGJE/Tasks/emcVertexSelectionQA.cxx b/PWGJE/Tasks/emcVertexSelectionQA.cxx index 1ec997d4edd..eb579326966 100644 --- a/PWGJE/Tasks/emcVertexSelectionQA.cxx +++ b/PWGJE/Tasks/emcVertexSelectionQA.cxx @@ -13,18 +13,26 @@ // /// \author Nicolas Strangmann , Goethe University Frankfurt / Oak Ridge National Laoratory -#include -#include -#include +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/TriggerAliases.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/emcalGammaGammaBcWise.cxx b/PWGJE/Tasks/emcalGammaGammaBcWise.cxx index 7007f94bc15..d9674888aed 100644 --- a/PWGJE/Tasks/emcalGammaGammaBcWise.cxx +++ b/PWGJE/Tasks/emcalGammaGammaBcWise.cxx @@ -16,17 +16,29 @@ /// \author Nicolas Strangmann (nicolas.strangmann@cern.ch) - Goethe University Frankfurt /// +#include "PWGJE/DataModel/EMCALClusters.h" + +#include "Common/CCDB/EventSelectionParams.h" +#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 "TLorentzVector.h" #include "TVector3.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/EventSelection.h" -#include "EMCALBase/Geometry.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx index bb1abd5a986..273907b8056 100644 --- a/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx +++ b/PWGJE/Tasks/emcalPi0EnergyScaleCalib.cxx @@ -9,35 +9,40 @@ // 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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/EMCALMatchedCollisions.h" +#include "Common/CCDB/TriggerAliases.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" #include "EMCALBase/Geometry.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" - -#include "CommonDataFormat/InteractionRecord.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include #include "TLorentzVector.h" #include "TVector3.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /// \brief Simple pi0 reconstruction task used to scale the cell energy based on the difference in mass position in data and MC /// \author Nicolas Strangmann , Goethe University Frankfurt / Oak Ridge National Laoratory diff --git a/PWGJE/Tasks/fullJetSpectra.cxx b/PWGJE/Tasks/fullJetSpectra.cxx index 40e233f9a90..cdb14a1aa1c 100644 --- a/PWGJE/Tasks/fullJetSpectra.cxx +++ b/PWGJE/Tasks/fullJetSpectra.cxx @@ -13,46 +13,44 @@ /// \brief Task for full jet spectra studies in pp collisions. /// \author Archita Rani Dash -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/CCDB/TriggerAliases.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" -#include "CommonConstants/PhysicsConstants.h" +#include "CCDB/BasicCCDBManager.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/Logger.h" +#include +#include +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGHF/Core/HfHelper.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace std; using namespace o2; -using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; -// using namespace jetderiveddatautilities; struct FullJetSpectra { @@ -69,8 +67,10 @@ struct FullJetSpectra { Configurable centralityMax{"centralityMax", 999.0, "maximum centrality"}; Configurable doEMCALEventWorkaround{"doEMCALEventWorkaround", false, "apply the workaround to read the EMC trigger bit by requiring a cell content in the EMCAL"}; Configurable doMBGapTrigger{"doMBGapTrigger", true, "set to true only when using MB-Gap Trigger JJ MC to reject MB events at the collision and track level"}; - // Configurable doMBMC{"doMBMC", false, "set to true only when using MB MC"}; - Configurable checkMcCollisionIsMatched{"checkMcCollisionIsMatched", false, "0: count whole MCcollisions, 1: select MCcollisions which only have their correspond collisions"}; + + // Software Trigger configurables + Configurable doSoftwareTriggerSelection{"doSoftwareTriggerSelection", false, "set to true when using triggered datasets"}; + Configurable triggerMasks{"triggerMasks", "fJetFullHighPt", "possible JE Trigger masks: fJetChLowPt,fJetChHighPt,fEMCALReadout,fJetFullHighPt,fJetFullLowPt"}; // Jet configurables Configurable selectedJetsRadius{"selectedJetsRadius", 0.4, "resolution parameter for histograms without radius"}; @@ -82,7 +82,12 @@ struct FullJetSpectra { Configurable jetPhiMin{"jetPhiMin", 1.80, "minimum jet phi"}; // phi_jet_min for R = 0.4 is 1.80 Configurable jetPhiMax{"jetPhiMax", 2.86, "maximum jet phi"}; // phi_jet_min for R = 0.4 is 2.86 Configurable jetAreaFractionMin{"jetAreaFractionMin", -99.0, "used to make a cut on the jet areas"}; - Configurable leadingConstituentPtMin{"leadingConstituentPtMin", -99.0, "minimum pT selection on jet constituent"}; + + // Leading track and cluster pT configurables + Configurable leadingTrackPtMin{"leadingTrackPtMin", -99.0, "minimum pT selection on jet tracks"}; + Configurable leadingTrackPtMax{"leadingTrackPtMax", 999.0, "maximum pT selection on jet tracks"}; + Configurable leadingClusterPtMin{"leadingClusterPtMin", -99.0, "minimum pT selection on jet clusters"}; + Configurable leadingClusterPtMax{"leadingClusterPtMax", 999.0, "maximum pT selection on jet clusters"}; // Track configurables Configurable trackpTMin{"trackpTMin", 0.15, "minimum track pT"}; @@ -113,14 +118,41 @@ struct FullJetSpectra { int trackSelection = -1; const float kJetAreaFractionMinThreshold = -98.0f; - const float kLeadingConstituentPtMinThreshold = -98.0f; + const float kLeadingTrackPtMinThreshold = -98.0f; + const float kLeadingTrackPtMaxThreshold = 9998.0f; + const float kLeadingClusterPtMinThreshold = -98.0f; + const float kLeadingClusterPtMaxThreshold = 9998.0f; + std::vector eventSelectionBits; std::vector filledJetR; std::vector jetRadiiValues; - + std::vector triggerMaskBits; std::string particleSelection; Service pdgDatabase; + Service ccdb; + + // Instantiate the Zorro processor for skimmed data and define an output object + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + // Multiplicity Utilities + // struct CentClass { + // const char* name; + // float min; + // float max; + // }; + // // Define multiplicity classes here (example: MB(0-100), HM(0-1), 1-10, 10-20, 20-40, 40-60, 60-100) + // static constexpr int nCentClasses = 4; + // CentClass centClasses[nCentClasses] = { + // {"MB", 0.0, 100.0}, + // {"HM", 0.0, 1.0}, + // {"1_10", 1.0, 10.0}, + // {"10_20", 10.0, 20.0}, + // {"20_40", 20.0, 40.0}, + // {"40_60", 40.0, 60.0}, + // {"60_100", 60.0, 100.0} + // }; // Random splitter instance /* TRandom3 randGen; @@ -179,6 +211,24 @@ struct FullJetSpectra { hDetcollisionCounter->GetXaxis()->SetBinLabel(8, "EMCAcceptedDetColl"); } + if (doprocessJetsTriggeredData) { + auto hDetTrigcollisionCounter = registry.get(HIST("hDetTrigcollisionCounter")); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(1, "allDetTrigColl"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(2, "DetTrigCollAfterZorroSelection"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(3, "DetTrigCollWithVertexZ"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(4, "EventsNotSatisfyingEventSelection"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(5, "EMCreadoutDetTrigEventsWithkTVXinEMC"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(6, "OnlyHighPt+NoLowPt+NoMB"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(7, "OnlyLowPt+NoMB"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(8, "OnlyMB"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(9, "FullJetHighPt+FullJetLowPt"); + // hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedDetTrigCollWithLow+HighFullJetTriggers"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(10, "FullJetHighPt+MB"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(11, "FullJetLowPt+MB"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(12, "AllRejectedTrigOverlaps"); + hDetTrigcollisionCounter->GetXaxis()->SetBinLabel(13, "EMCAcceptedDetTrigColl"); + } + if (doprocessJetsMCP || doprocessJetsMCPWeighted) { auto hPartcollisionCounter = registry.get(HIST("hPartcollisionCounter")); hPartcollisionCounter->GetXaxis()->SetBinLabel(1, "allMcColl"); @@ -205,15 +255,52 @@ struct FullJetSpectra { hMatchedcollisionCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedDetColl"); } - if (doprocessMBCollisionsDATAWithMultiplicity || doprocessMBCollisionsWithMultiplicity || doprocessCollisionsWeightedWithMultiplicity) { + if (doprocessMBCollisionsDATAWithMultiplicity || doprocessMBMCDCollisionsWithMultiplicity) { auto hEventmultiplicityCounter = registry.get(HIST("hEventmultiplicityCounter")); hEventmultiplicityCounter->GetXaxis()->SetBinLabel(1, "allDetColl"); hEventmultiplicityCounter->GetXaxis()->SetBinLabel(2, "DetCollWithVertexZ"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(3, "EventsNotSatisfyingEventSelection"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(4, "EMCreadoutDetEventsWithkTVXinEMC"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(5, "AllRejectedEventsAfterEMCEventSelection"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(6, "EMCAcceptedDetColl"); + } + + if (doprocessMCDCollisionsWeightedWithMultiplicity) { + auto hEventmultiplicityCounter = registry.get(HIST("hEventmultiplicityCounter")); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(1, "allWeightedDetColl"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(2, "WeightedDetCollWithVertexZ"); hEventmultiplicityCounter->GetXaxis()->SetBinLabel(3, "MBRejectedDetEvents"); - hEventmultiplicityCounter->GetXaxis()->SetBinLabel(4, "EventsNotSatisfyingEventSelection"); - hEventmultiplicityCounter->GetXaxis()->SetBinLabel(5, "EMCreadoutDetEventsWithkTVXinEMC"); - hEventmultiplicityCounter->GetXaxis()->SetBinLabel(6, "AllRejectedEventsAfterEMCEventSelection"); - hEventmultiplicityCounter->GetXaxis()->SetBinLabel(7, "EMCAcceptedDetColl"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(4, "WeightedEventsNotSatisfyingEventSelection"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(5, "EMCreadoutWeightedDetEventsWithkTVXinEMC"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(6, "AllRejectedWeightedEventsAfterEMCEventSelection"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(7, "EMCAcceptedWeightedDetColl"); + hEventmultiplicityCounter->GetXaxis()->SetBinLabel(8, "EMCAcceptedWeightedCollAfterTrackSel"); + } + + if (doprocessMBMCPCollisionsWithMultiplicity) { + auto hPartEventmultiplicityCounter = registry.get(HIST("hPartEventmultiplicityCounter")); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(1, "allMcColl"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(2, "McCollWithVertexZ"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(3, "RejectedPartCollWithOutliers"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(4, "MBRejectedPartEvents"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(5, "RejectedPartCollForDetCollWithSize0or<1"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(6, "AcceptedPartCollWithSize>=1"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(7, "EMCreadoutDetEventsWithkTVXinEMC"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(8, "AllRejectedPartEventsAfterEMCEventSelection"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedPartColl"); + } + + if (doprocessMBMCPCollisionsWeightedWithMultiplicity) { + auto hPartEventmultiplicityCounter = registry.get(HIST("hPartEventmultiplicityCounter")); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(1, "allWeightedMcColl"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(2, "WeightedMcCollWithVertexZ"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(3, "RejectedWeightedPartCollWithOutliers"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(4, "MBRejectedPartEvents"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(5, "RejectedWeightedPartCollForDetCollWithSize0or<1"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(6, "AcceptedWeightedPartCollWithSize>=1"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(7, "EMCreadoutDetEventsWithkTVXinEMC"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(8, "AllRejectedWeightedPartEventsAfterEMCEventSelection"); + hPartEventmultiplicityCounter->GetXaxis()->SetBinLabel(9, "EMCAcceptedWeightedPartColl"); } } @@ -227,8 +314,10 @@ struct FullJetSpectra { */ void init(o2::framework::InitContext&) { + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); particleSelection = static_cast(particleSelections); jetRadiiValues = (std::vector)jetRadii; @@ -325,8 +414,12 @@ struct FullJetSpectra { registry.add("h2_track_etaphi", "jet_track #eta vs jet_track #varphi; #eta_{track};#varphi_{track}", {HistType::kTH2F, {{500, -5., 5.}, {160, -1., 7.}}}); registry.add("h2_jet_etaphi", "jet #eta vs jet #varphi; #eta_{jet};#varphi_{jet}", {HistType::kTH2F, {{100, -1., 1.}, {160, -1., 7.}}}); } + if (doprocessJetsTriggeredData) { + registry.add("hDetTrigcollisionCounter", "event status;;entries", {HistType::kTH1F, {{14, 0.0, 14.}}}); + } if (doprocessJetsMCP || doprocessJetsMCPWeighted) { registry.add("hPartcollisionCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.add("hRecoMatchesPerMcCollision", "split vertices QA;;entries", {HistType::kTH1F, {{5, 0.0, 5.0}}}); registry.add("h_full_mcpjet_tablesize", "", {HistType::kTH1F, {{4, 0., 5.}}}); registry.add("h_full_mcpjet_ntracks", "", {HistType::kTH1F, {{200, -0.5, 200.}}}); @@ -394,23 +487,96 @@ struct FullJetSpectra { registry.add("h2_full_matchedmcpjet_pt", "Matched MCP jet in EMC Fiducial Acceptance #it{p}_{T,part};#it{p}_{T,part} (GeV/c); Ncounts", {HistType::kTH2F, {{350, 0., 350.}, {10000, 0., 10000.}}}); // Response Matrix - registry.add("h_full_jet_ResponseMatrix", "Full Jets Response Matrix; p_{T,det} (GeV/c); p_{T,part} (GeV/c)", {HistType::kTH2F, {{350, 0., 350.}, {350, 0., 350.}}}); + registry.add("h_full_jet_ResponseMatrix", "Full Jets Response Matrix; p_{T,det} (GeV/c); p_{T,part} (GeV/c)", {HistType::kTH2F, {{500, 0., 500.}, {500, 0., 500.}}}); } - if (doprocessCollisionsWeightedWithMultiplicity || doprocessMBCollisionsWithMultiplicity || doprocessMBCollisionsDATAWithMultiplicity) { + if (doprocessMBCollisionsDATAWithMultiplicity || doprocessMBMCDCollisionsWithMultiplicity || doprocessMCDCollisionsWeightedWithMultiplicity) { registry.add("hEventmultiplicityCounter", "event status;event status;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); registry.add("h_FT0Mults_occupancy", "", {HistType::kTH1F, {{3500, 0., 3500.}}}); - registry.add("h2_full_jet_FT0Amplitude", "; FT0C Amplitude; Counts", {HistType::kTH1F, {{3500, 0., 3500.}}}); - registry.add("h2_full_jet_jetpTDetVsFT0Mults", "; p_{T,det} (GeV/c); FT0C Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); - registry.add("h3_full_jet_jetpTDet_FT0Mults_nef", "; p_{T,det} (GeV/c); FT0C Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {3500, 0., 3500.}, {105, 0.0, 1.05}}}); + + registry.add("h_all_fulljet_Njets", "Full Jet Multiplicity (per Event)", {HistType::kTH1F, {{20, 0., 20.}}}); + registry.add("h_Leading_full_jet_pt", "#it{p}_{T,leading jet};#it{p}_{T_leading jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h2_full_jet_leadingJetPt_vs_counts", ";#it{p}_{T_leading jet} (GeV/#it{c}); Counts", {HistType::kTH2F, {{350, 0., 350.}, {20, 0., 20.}}}); + registry.add("h_SubLeading_full_jet_pt", "#it{p}_{T,leading jet};#it{p}_{T_leading jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h2_full_jet_subLeadingJetPt_vs_counts", ";#it{p}_{T_leading jet} (GeV/#it{c}); Counts", {HistType::kTH2F, {{350, 0., 350.}, {20, 0., 20.}}}); + // Inside Jet Loop: + // CASE 1: + registry.add("h_all_fulljet_pt", "#it{p}_{T,fulljet};#it{p}_{T_fulljet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_all_fulljet_Nch", ";N_{ch};", {HistType::kTH1F, {{50, 0., 50.}}}); + registry.add("h_all_fulljet_NEF", ";NEF;", {HistType::kTH1F, {{105, 0., 1.05}}}); + registry.add("h2_all_fulljet_jetpTDet_vs_FT0Mults", "; p_{T,det} (GeV/c); FT0M Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); + registry.add("h2_all_fulljet_jetpTDet_vs_Nch", ";#it{p}_{T_fulljet} (GeV/#it{c}); N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {50, 0., 50.}}}); + registry.add("h3_full_jet_jetpTDet_FT0Mults_nef", "; p_{T,det} (GeV/c); FT0M Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {50, 0., 50.}, {105, 0.0, 1.05}}}); + // CASE 2: + registry.add("h_leading_fulljet_pt", "#it{p}_{T,Leading fulljet};#it{p}_{T_Leadingfulljet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_leading_fulljet_Nch", ";N_{ch};", {HistType::kTH1F, {{50, 0., 50.}}}); + registry.add("h_leading_fulljet_NEF", ";NEF;", {HistType::kTH1F, {{105, 0., 1.05}}}); + registry.add("h2_leading_fulljet_jetpTDet_vs_FT0Mults", ";Leading p_{T,det} (GeV/c); FT0M Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); + registry.add("h2_leading_fulljet_jetpTDet_vs_Nch", ";#it{p}_{T_Leadingfulljet} (GeV/#it{c}); N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {50, 0., 50.}}}); + registry.add("h3_leading_fulljet_jetpTDet_FT0Mults_nef", "; Leading p_{T,det} (GeV/c); FT0M Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {50, 0., 50.}, {105, 0.0, 1.05}}}); + // CASE 3: + registry.add("h_subleading_fulljet_pt", "#it{p}_{T,SubLeading fulljet};#it{p}_{T_SubLeadingfulljet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_subleading_fulljet_Nch", ";N_{ch};", {HistType::kTH1F, {{50, 0., 50.}}}); + registry.add("h_subleading_fulljet_NEF", ";NEF;", {HistType::kTH1F, {{105, 0., 1.05}}}); + registry.add("h2_subleading_fulljet_jetpTDet_vs_FT0Mults", ";SubLeading p_{T,det} (GeV/c); FT0M Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); + registry.add("h2_subleading_fulljet_jetpTDet_vs_Nch", ";#it{p}_{T_SubLeadingfulljet} (GeV/#it{c}); N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {50, 0., 50.}}}); + registry.add("h3_subleading_fulljet_jetpTDet_FT0Mults_nef", "; SubLeading p_{T,det} (GeV/c); FT0M Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {50, 0., 50.}, {105, 0.0, 1.05}}}); + } + + if (doprocessMBMCPCollisionsWithMultiplicity || doprocessMBMCPCollisionsWeightedWithMultiplicity) { + registry.add("hPartEventmultiplicityCounter", "event status;event status;entries", {HistType::kTH1F, {{11, 0.0, 11.0}}}); + registry.add("hRecoMatchesPerMcCollisionMult", "split vertices QA;;entries", {HistType::kTH1F, {{5, 0.0, 5.0}}}); + registry.add("hMCCollMatchedFT0Mult", "", {HistType::kTH1F, {{3500, 0., 3500.}}}); + registry.add("hMCCollMatchedFT0Cent", "", {HistType::kTH1F, {{105, 0., 105.}}}); + + registry.add("h_all_fulljet_Njets_part", "Full Jet Multiplicity (per Event)", {HistType::kTH1F, {{20, 0., 20.}}}); + registry.add("h_Leading_full_jet_pt_part", "#it{p}_{T,leading jet};#it{p}_{T_leading jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h2_full_jet_leadingJetPt_vs_counts_part", ";#it{p}_{T_leading jet} (GeV/#it{c}); Counts", {HistType::kTH2F, {{350, 0., 350.}, {20, 0., 20.}}}); + registry.add("h_SubLeading_full_jet_pt_part", "#it{p}_{T,leading jet};#it{p}_{T_leading jet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h2_full_jet_subLeadingJetPt_vs_counts_part", ";#it{p}_{T_leading jet} (GeV/#it{c}); Counts", {HistType::kTH2F, {{350, 0., 350.}, {20, 0., 20.}}}); + + // Inside Jet Loop: + // CASE 1: + registry.add("h_all_fulljet_pt_part", "#it{p}_{T,fulljet};#it{p}_{T_fulljet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_all_fulljet_Nch_part", ";N_{ch};", {HistType::kTH1F, {{50, 0., 50.}}}); + registry.add("h_all_fulljet_Nne_part", ";N_{ne};", {HistType::kTH1F, {{100, 0., 100.}}}); + registry.add("h_all_fulljet_NEF_part", ";NEF;", {HistType::kTH1F, {{105, 0., 1.05}}}); + registry.add("h2_all_fulljet_jetpT_vs_FT0Mults_part", "; p_{T,part} (GeV/c); FT0M Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); + registry.add("h2_all_fulljet_jetpT_vs_Nch_part", ";#it{p}_{T_fulljet} (GeV/#it{c}); N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {50, 0., 50.}}}); + registry.add("h3_full_jet_jetpT_FT0Mults_nef_part", "; p_{T,part} (GeV/c); FT0M Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {50, 0., 50.}, {105, 0.0, 1.05}}}); + // CASE 2: + registry.add("h_leading_fulljet_pt_part", "#it{p}_{T,Leading fulljet};#it{p}_{T_Leadingfulljet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_leading_fulljet_Nch_part", ";N_{ch};", {HistType::kTH1F, {{50, 0., 50.}}}); + registry.add("h_leading_fulljet_Nne_part", ";N_{ne};", {HistType::kTH1F, {{100, 0., 100.}}}); + registry.add("h_leading_fulljet_NEF_part", ";NEF;", {HistType::kTH1F, {{105, 0., 1.05}}}); + registry.add("h2_leading_fulljet_jetpT_vs_FT0Mults_part", ";Leading p_{T,part} (GeV/c); FT0M Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); + registry.add("h2_leading_fulljet_jetpT_vs_Nch_part", ";#it{p}_{T_Leadingfulljet} (GeV/#it{c}); N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {50, 0., 50.}}}); + registry.add("h3_leading_fulljet_jetpT_FT0Mults_nef_part", "; Leading p_{T,part} (GeV/c); FT0M Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {50, 0., 50.}, {105, 0.0, 1.05}}}); + // CASE 3: + registry.add("h_subleading_fulljet_pt_part", "#it{p}_{T,SubLeading fulljet};#it{p}_{T_SubLeadingfulljet} (GeV/#it{c});entries", {HistType::kTH1F, {{350, 0., 350.}}}); + registry.add("h_subleading_fulljet_Nch_part", ";N_{ch};", {HistType::kTH1F, {{50, 0., 50.}}}); + registry.add("h_subleading_fulljet_Nne_part", ";N_{ne};", {HistType::kTH1F, {{100, 0., 100.}}}); + registry.add("h_subleading_fulljet_NEF_part", ";NEF;", {HistType::kTH1F, {{105, 0., 1.05}}}); + registry.add("h2_subleading_fulljet_jetpT_vs_FT0Mults_part", ";SubLeading p_{T,part} (GeV/c); FT0M Multiplicity", {HistType::kTH2F, {{350, 0., 350.}, {3500, 0., 3500.}}}); + registry.add("h2_subleading_fulljet_jetpT_vs_Nch_part", ";#it{p}_{T_SubLeadingfulljet} (GeV/#it{c}); N_{ch}", {HistType::kTH2F, {{350, 0., 350.}, {50, 0., 50.}}}); + registry.add("h3_subleading_fulljet_jetpT_FT0Mults_nef_part", "; SubLeading p_{T,part} (GeV/c); FT0M Multiplicity, nef", {HistType::kTH3F, {{350, 0., 350.}, {50, 0., 50.}, {105, 0.0, 1.05}}}); } // Label the histograms labelCollisionHistograms(registry); // labelMCSplitHistogram(registry); - } // init + // Initialize CCDB access and histogram registry for Zorro processing + template + void initCCDB(const BCType& bc) + { + if (doSoftwareTriggerSelection) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerMasks.value); + zorro.populateHistRegistry(registry, bc.runNumber()); + } + } + // Get or generate random value for a specific MC collision /* float getMCCollisionRandomValue(int64_t mcCollisionId) { if (!doMcClosure) return 0.0f; @@ -433,7 +599,9 @@ struct FullJetSpectra { return randomVal; } */ - using EMCCollisionsData = o2::soa::Join; // JetCollisions with EMCAL Collision Labels + using EMCCollisionsData = o2::soa::Join; // JetCollisions with EMCAL Collision Labels + using EMCCollisionsTriggeredData = o2::soa::Join; + using EMCCollisionsMCD = o2::soa::Join; // where, JetCollisionsMCD = JetCollisions+JMcCollisionLbs using FullJetTableDataJoined = soa::Join; @@ -450,7 +618,7 @@ struct FullJetSpectra { // Applying some cuts(filters) on collisions, tracks, clusters - Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); // Filter EMCeventCuts = (nabs(aod::collision::posZ) < vertexZCut && aod::collision::centrality >= centralityMin && aod::collision::centrality < centralityMax); Filter trackCuts = (aod::jtrack::pt >= trackpTMin && aod::jtrack::pt < trackpTMax && aod::jtrack::eta > trackEtaMin && aod::jtrack::eta < trackEtaMax && aod::jtrack::phi >= trackPhiMin && aod::jtrack::phi <= trackPhiMax); aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); @@ -458,30 +626,81 @@ struct FullJetSpectra { Preslice JetMCPPerMcCollision = aod::jet::mcCollisionId; PresliceUnsorted> CollisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; - template - bool isAcceptedJet(U const& jet) + template + bool isAcceptedRecoJet(U const& jet) { + // if (jetAreaFractionMin > kJetAreaFractionMinThreshold) { + // if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { + // return false; + // } + // } - if (jetAreaFractionMin > kJetAreaFractionMinThreshold) { - if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.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(); + // Reject if ANY track fails min or max cut + if ((leadingTrackPtMin > kLeadingTrackPtMinThreshold && pt < leadingTrackPtMin) || + (leadingTrackPtMax < kLeadingTrackPtMaxThreshold && pt > leadingTrackPtMax)) { + return false; + } + hasValidTrack = true; // At least one track exists (if needed) + } + // Reject if no tracks exist (edge case) + if (leadingTrackPtMin > kLeadingTrackPtMinThreshold && !hasValidTrack) { return false; } } - if (leadingConstituentPtMin > kLeadingConstituentPtMinThreshold) { - bool isMinleadingConstituent = false; - for (const auto& constituent : jet.template tracks_as()) { - if (constituent.pt() >= leadingConstituentPtMin) { - isMinleadingConstituent = true; - break; + + // --- 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()); + // Reject if ANY cluster fails min or max cut + if ((leadingClusterPtMin > kLeadingClusterPtMinThreshold && pt < leadingClusterPtMin) || + (leadingClusterPtMax < kLeadingClusterPtMaxThreshold && pt > leadingClusterPtMax)) { + return false; } + hasValidCluster = true; // At least one cluster exists } + // Reject if no clusters exist (edge case) + if (leadingClusterPtMin > kLeadingClusterPtMinThreshold && !hasValidCluster) { + return false; + } + } + return true; + } // isAcceptedRecoJet ends - if (!isMinleadingConstituent) { + template + bool isAcceptedPartJet(U const& jet) + { + // if (jetAreaFractionMin > kJetAreaFractionMinThreshold) { + // if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { + // return false; + // } + // } + // track pt Min cut at the Part level: 0 < pT <= 200 or 150 GeV/c + if (leadingTrackPtMin > kLeadingTrackPtMinThreshold || leadingTrackPtMax < kLeadingTrackPtMaxThreshold) { + bool hasValidParticle = false; + for (const auto& constituent : jet.template tracks_as()) { + const float pt = constituent.pt(); + // Reject if ANY particle fails min or max cut + if ((leadingTrackPtMin > kLeadingTrackPtMinThreshold && pt < leadingTrackPtMin) || + (leadingTrackPtMax < kLeadingTrackPtMaxThreshold && pt > leadingTrackPtMax)) { + return false; + } + hasValidParticle = true; // At least one track exists (if needed) + } + // Reject if no particle exist (edge case) + if (leadingTrackPtMin > kLeadingTrackPtMinThreshold && !hasValidParticle) { return false; } } return true; } + template void fillJetHistograms(T const& jet, float weight = 1.0) { @@ -674,8 +893,6 @@ struct FullJetSpectra { void processJetsData(soa::Filtered::iterator const& collision, FullJetTableDataJoined const& jets, aod::JetTracks const&, aod::JetClusters const&) { bool eventAccepted = false; - double weight = 1.0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); registry.fill(HIST("hDetcollisionCounter"), 0.5); // allDetColl if (std::fabs(collision.posZ()) > vertexZCut) { @@ -683,23 +900,6 @@ struct FullJetSpectra { } registry.fill(HIST("hDetcollisionCounter"), 1.5); // DetCollWithVertexZ - // outlier check: for every outlier jet, reject the whole event - for (auto const& jet : jets) { - if (jet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // for MCD jets only to remove outliers; setting pTHatMaxMCD = 1 improves purity - registry.fill(HIST("hDetcollisionCounter"), 2.5); // RejectedDetCollWithOutliers - return; - } - // this cut only to be used for calculating Jet Purity and not for Response Matrix - // this is mainly applied to remove all high weight jets causing big fluctuations - if (jet.pt() > 1 * pTHat) { - registry.fill(HIST("h_full_jet_pt_pTHatcut"), jet.pt(), weight); - } - } - - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { - registry.fill(HIST("hDetcollisionCounter"), 3.5); // MBRejectedDetEvents - return; - } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { registry.fill(HIST("hDetcollisionCounter"), 4.5); // EventsNotSatisfyingEventSelection return; @@ -720,7 +920,7 @@ struct FullJetSpectra { if (!eventAccepted) { for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedJet(jet)) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedRecoJet(jet)) { fillRejectedJetHistograms(jet, 1.0); } } @@ -736,7 +936,7 @@ struct FullJetSpectra { if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { continue; } - if (!isAcceptedJet(jet)) { + if (!isAcceptedRecoJet(jet)) { continue; } fillJetHistograms(jet); @@ -744,6 +944,126 @@ struct FullJetSpectra { } PROCESS_SWITCH(FullJetSpectra, processJetsData, "Full Jets Data", false); + void processJetsTriggeredData(soa::Filtered::iterator const& collision, FullJetTableDataJoined const& /*jets*/, + aod::JetTracks const&, aod::JetClusters const&, aod::JBCs const&) + { + // bool eventAccepted = false; + + registry.fill(HIST("hDetTrigcollisionCounter"), 0.5); // allDetTrigColl + + // Get BC info associated with the collision before applying any event selections + auto bc = collision.bc_as(); + // Initialize CCDB objects using the BC info + initCCDB(bc); + // If SoftwareTriggerSelection (i.e. skimming) is enabled, skip this event unless it passes Zorro selection + if (doSoftwareTriggerSelection && !zorro.isSelected(bc.globalBC())) { + return; + } + registry.fill(HIST("hDetTrigcollisionCounter"), 1.5); // DetTrigCollAfterZorroSelection + + if (std::fabs(collision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("hDetTrigcollisionCounter"), 2.5); // DetTrigCollWithVertexZ + + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits) || !jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + registry.fill(HIST("hDetTrigcollisionCounter"), 3.5); // EventsNotSatisfyingEvent+TriggerSelection + return; + } + //- should this kTVX HW trigger be still in place?? + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + // eventAccepted = true; + registry.fill(HIST("hDetTrigcollisionCounter"), 4.5); // EMCreadoutDetTrigEventsWithkTVXinEMC + } + // split event selections based on selected triggers - + // make sure there're no trigger overlaps: when analysing JetFullHighPt-> check no JetFullLowPt and kTVXinEMC are fired + // when analysing JetFullLowPt, check kTVXinEMC isn't fired! + // apply exclusive trigger bit selections for event selection + // use a flag and fill QA for trigger overlap - + // - how often you reject a higher pT trig because lower trigs were fired : 5 cases -> 2D hist as a funtn of jet pT + // - check how often the ChJet Trigs were fired for every fullJetTrig fired.(don't reject these events but only for QA) + + // Get trigger status + bool hasFullJetHighPt = jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetFullHighPt); + bool hasFullJetLowPt = jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetFullLowPt); + bool hasMB = jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::EMCALReadout); + + //*****Step 1: Check for pure triggers (NO overlaps)***** + + // Case 1: hasFullJetHighPt && !hasFullJetLowPt && !hasMB : Pure FullJetHighPt + // i.e. for every JetFullHighPt trig that was fired, check the low triggers weren't fired + if (hasFullJetHighPt && !hasFullJetLowPt && !hasMB) { + registry.fill(HIST("hDetTrigcollisionCounter"), 5.5); // OnlyHighPt+NoLowPt+NoMB + } + // Case 2: hasFullJetLowPt && !hasMB : Pure FullJetLowPt + // i.e. for every hasFullJetLowPt trig that was fired, check the MB trig wasn't fired + if (hasFullJetLowPt && !hasMB) { + registry.fill(HIST("hDetTrigcollisionCounter"), 6.5); // OnlyLowPt+NoMB + } + // Case 3: hasMB && !hasFullJetLowPt && !hasFullJetHighPt : Pure MB + // i.e. for every MB trig that was fired, check the higher trigs weren't fired + if (hasMB && !hasFullJetLowPt && !hasFullJetHighPt) { + registry.fill(HIST("hDetTrigcollisionCounter"), 7.5); // OnlyMB + } + + //*****Step 2: Check for trigger overlap cases (for QA):***** + + if (hasFullJetHighPt && hasFullJetLowPt) { + registry.fill(HIST("hDetTrigcollisionCounter"), 8.5); // FullJetHighPt+FullJetLowPt + } + if (hasFullJetHighPt && hasMB) { + registry.fill(HIST("hDetTrigcollisionCounter"), 9.5); // FullJetHighPt+MB + } + if (hasFullJetLowPt && hasMB) { + registry.fill(HIST("hDetTrigcollisionCounter"), 10.5); // FullJetLowPt+MB + } + + //*****Step 3: Reject ALL overlapping events by applying EXCLUSIVE Trigger Selections ***** + // Skip further processing if ANY overlaps exist + if ((hasFullJetHighPt && (hasFullJetLowPt || hasMB)) || (hasFullJetLowPt && hasMB)) { + registry.fill(HIST("hDetTrigcollisionCounter"), 11.5); // AllRejectedTrigOverlaps + return; + } + registry.fill(HIST("hDetTrigcollisionCounter"), 12.5); // EMCAcceptedDetTrigColl + // if (!eventAccepted) { + // // for (auto const& jet : jets) { + // // if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedRecoJet(jet)) { + // // fillRejectedJetHistograms(jet, 1.0); + // // } + // // } + // registry.fill(HIST("hDetTrigcollisionCounter"), 4.5); // AllRejectedDetTrigEventsAfterEMCEventSelection + // return; + // } + // registry.fill(HIST("hDetTrigcollisionCounter"), 5.5); // EMCAcceptedDetTrigCollWithkTVXinEMC + // + + // if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChLowPt)) { + // registry.fill(HIST("hDetTrigcollisionCounter"), 8.5); // EMCAcceptedDetTrigCollWithLowChargedJetTriggers + // eventAccepted = true; + // } + // if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetChHighPt)) { + // registry.fill(HIST("hDetTrigcollisionCounter"), 9.5); // EMCAcceptedDetTrigCollWithHighChargedJetTriggers + // eventAccepted = true; + // } + + // if (jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetFullLowPt) && jetderiveddatautilities::selectTrigger(collision, jetderiveddatautilities::JTrigSel::JetFullHighPt)) { + // registry.fill(HIST("hDetTrigcollisionCounter"), 8.5); // EMCAcceptedDetTrigCollWithLow+HighFullJetTriggers + // } + // for (auto const& jet : jets) { + // if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + // continue; + // } + // if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { + // continue; + // } + // if (!isAcceptedRecoJet(jet)) { + // continue; + // } + // fillJetHistograms(jet); + // } + } + PROCESS_SWITCH(FullJetSpectra, processJetsTriggeredData, "Full Jets Triggered Data", false); + void processJetsMCD(soa::Filtered::iterator const& collision, JetTableMCDJoined const& jets, aod::JetTracks const&, aod::JetClusters const&) { bool eventAccepted = false; @@ -802,8 +1122,8 @@ struct FullJetSpectra { } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hDetcollisionCounter"), 5.5); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -816,7 +1136,7 @@ struct FullJetSpectra { if (!eventAccepted) { for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedJet(jet)) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedRecoJet(jet)) { fillRejectedJetHistograms(jet, 1.0); } } @@ -832,7 +1152,7 @@ struct FullJetSpectra { if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { continue; } - if (!isAcceptedJet(jet)) { + if (!isAcceptedRecoJet(jet)) { continue; } fillJetHistograms(jet); @@ -896,8 +1216,8 @@ struct FullJetSpectra { } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hDetcollisionCounter"), 5.5, collision.mcCollision().weight()); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -910,7 +1230,7 @@ struct FullJetSpectra { if (!eventAccepted) { for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedJet(jet)) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax) || !isAcceptedRecoJet(jet)) { fillRejectedJetHistograms(jet, collision.mcCollision().weight()); } } @@ -926,7 +1246,7 @@ struct FullJetSpectra { if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { continue; } - if (!isAcceptedJet(jet)) { + if (!isAcceptedRecoJet(jet)) { continue; } fillJetHistograms(jet, collision.mcCollision().weight()); @@ -972,38 +1292,38 @@ struct FullJetSpectra { return; } registry.fill(HIST("hPartcollisionCounter"), 1.5); // McCollWithVertexZ - if (collisions.size() < 1) { - return; - } - registry.fill(HIST("hPartcollisionCounter"), 2.5); // PartCollWithSize>1 - - if (collisions.size() == 0) { - registry.fill(HIST("hPartcollisionCounter"), 3.5); // RejectedPartCollForDetCollWithSize0 - return; - } // outlier check: for every outlier jet, reject the whole event for (auto const& jet : jets) { if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { - registry.fill(HIST("hPartcollisionCounter"), 4.5); // RejectedPartCollWithOutliers + registry.fill(HIST("hPartcollisionCounter"), 2.5); // RejectedPartCollWithOutliers return; } } if (doMBGapTrigger && mccollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { // Fill rejected MB events; - registry.fill(HIST("hPartcollisionCounter"), 5.5); // MBRejectedPartEvents + registry.fill(HIST("hPartcollisionCounter"), 3.5); // MBRejectedPartEvents + return; + } + + auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, mccollision.globalIndex()); + registry.fill(HIST("hRecoMatchesPerMcCollision"), collisionspermcpjet.size()); // for split vertices QA + + if (collisionspermcpjet.size() == 0 || collisionspermcpjet.size() < 1) { + registry.fill(HIST("hPartcollisionCounter"), 4.5); // RejectedPartCollForDetCollWithSize0or<1 return; } + registry.fill(HIST("hPartcollisionCounter"), 5.5); // AcceptedPartCollWithSize>=1 - for (auto const& collision : collisions) { + for (auto const& collision : collisionspermcpjet) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - return; + continue; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hPartcollisionCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -1018,24 +1338,16 @@ struct FullJetSpectra { registry.fill(HIST("hPartcollisionCounter"), 7.5); // AllRejectedPartEventsAfterEMCEventSelection return; } - registry.fill(HIST("hPartcollisionCounter"), 8.5); // EMCAcceptedWeightedPartColl + registry.fill(HIST("hPartcollisionCounter"), 8.5); // EMCAcceptedPartColl for (auto const& jet : jets) { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - if (!isAcceptedJet(jet)) { + if (!isAcceptedPartJet(jet)) { continue; } - if (checkMcCollisionIsMatched) { // basically checks if the same collisions are generated at the Part level as those at the Det level - auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, jet.mcCollisionId()); - if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelectionBits)) { - // Now here for every matched collision, I fill the corresponding jet histograms. - fillMCPHistograms(jet); - } - } else { - fillMCPHistograms(jet); - } + fillMCPHistograms(jet); } } PROCESS_SWITCH(FullJetSpectra, processJetsMCP, "Full Jets at Particle Level", false); @@ -1077,45 +1389,45 @@ struct FullJetSpectra { return; } registry.fill(HIST("hPartcollisionCounter"), 1.5, mccollision.weight()); // McCollWithVertexZ - if (collisions.size() < 1) { - return; - } - registry.fill(HIST("hPartcollisionCounter"), 2.5, mccollision.weight()); // PartCollWithSize>1 - - if (collisions.size() == 0) { - registry.fill(HIST("hPartcollisionCounter"), 3.5, mccollision.weight()); // RejectedPartCollForDetCollWithSize0 - return; - } // outlier check: for every outlier jet, reject the whole event for (auto const& jet : jets) { if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { - registry.fill(HIST("hPartcollisionCounter"), 4.5, mccollision.weight()); // RejectedPartCollWithOutliers + registry.fill(HIST("hPartcollisionCounter"), 2.5, mccollision.weight()); // RejectedPartCollWithOutliers return; } } if (doMBGapTrigger && mccollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { // Fill rejected MB events - registry.fill(HIST("hPartcollisionCounter"), 5.5, mccollision.weight()); // MBRejectedPartEvents + registry.fill(HIST("hPartcollisionCounter"), 3.5, mccollision.weight()); // MBRejectedPartEvents return; } - for (auto const& collision : collisions) { + auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, mccollision.globalIndex()); + registry.fill(HIST("hRecoMatchesPerMcCollision"), collisionspermcpjet.size(), mccollision.weight()); // for split vertices QA + + if (collisionspermcpjet.size() == 0 || collisionspermcpjet.size() < 1) { + registry.fill(HIST("hPartcollisionCounter"), 4.5, mccollision.weight()); // RejectedPartCollForDetCollWithSize0or<1 + return; + } + registry.fill(HIST("hPartcollisionCounter"), 5.5, mccollision.weight()); // AcceptedPartCollWithSize>=1 + + for (auto const& collision : collisionspermcpjet) { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - return; + continue; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("hPartcollisionCounter"), 6.5, mccollision.weight()); // EMCreadoutDetJJEventsWithkTVXinEMC + eventAccepted = true; + registry.fill(HIST("hPartcollisionCounter"), 6.5, mccollision.weight()); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; - registry.fill(HIST("hPartcollisionCounter"), 6.5, mccollision.weight()); // EMCreadoutDetJJEventsWithkTVXinEMC + registry.fill(HIST("hPartcollisionCounter"), 6.5, mccollision.weight()); // EMCreadoutDetEventsWithkTVXinEMC } } } @@ -1130,22 +1442,13 @@ struct FullJetSpectra { if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { return; } - if (!isAcceptedJet(jet)) { + if (!isAcceptedPartJet(jet)) { return; } if (doMBGapTrigger && jet.eventWeight() == 1) { return; } - - if (checkMcCollisionIsMatched) { - auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, jet.mcCollisionId()); - - if (collisionspermcpjet.size() >= 1 && jetderiveddatautilities::selectCollision(collisionspermcpjet.begin(), eventSelectionBits)) { - fillMCPHistograms(jet, jet.eventWeight()); - } - } else { - fillMCPHistograms(jet, jet.eventWeight()); - } + fillMCPHistograms(jet, jet.eventWeight()); } } PROCESS_SWITCH(FullJetSpectra, processJetsMCPWeighted, "Full Jets at Particle Level on weighted events", false); @@ -1217,8 +1520,8 @@ struct FullJetSpectra { } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hMatchedcollisionCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -1235,6 +1538,9 @@ struct FullJetSpectra { registry.fill(HIST("hMatchedcollisionCounter"), 8.5); // EMCAcceptedDetColl for (const auto& mcdjet : mcdjets) { + if (!isAcceptedRecoJet(mcdjet)) { + continue; + } if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } @@ -1244,10 +1550,11 @@ struct FullJetSpectra { registry.fill(HIST("h2_full_fakemcdjets"), mcdjet.pt(), fakeMcdJet, 1.0); continue; } - if (!isAcceptedJet(mcdjet)) { - continue; - } + for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + if (!isAcceptedPartJet(mcpjet)) { + return; + } // apply emcal fiducial cuts to the matched particle level jets if (mcpjet.eta() > jetEtaMax || mcpjet.eta() < jetEtaMin || mcpjet.phi() > jetPhiMax || mcpjet.phi() < jetPhiMin) { fakeMcpJet++; @@ -1333,8 +1640,8 @@ struct FullJetSpectra { } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hMatchedcollisionCounter"), 6.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } @@ -1351,6 +1658,9 @@ struct FullJetSpectra { registry.fill(HIST("hMatchedcollisionCounter"), 8.5, eventWeight); // EMCAcceptedDetColl for (const auto& mcdjet : mcdjets) { + if (!isAcceptedRecoJet(mcdjet)) { + continue; + } // 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++; @@ -1360,11 +1670,11 @@ struct FullJetSpectra { if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { continue; } - if (!isAcceptedJet(mcdjet)) { - continue; - } for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + if (!isAcceptedPartJet(mcpjet)) { + return; + } // apply emcal fiducial cuts to the matched particle level jets - if the matched mcp jet lies outside of the EMCAL fiducial, flag it as a fake jet if (mcpjet.eta() > jetEtaMax || mcpjet.eta() < jetEtaMin || mcpjet.phi() > jetPhiMax || mcpjet.phi() < jetPhiMin) { fakeMcpJet++; @@ -1410,8 +1720,6 @@ struct FullJetSpectra { void processDataTracks(soa::Filtered::iterator const& collision, soa::Filtered const& tracks, soa::Filtered const& clusters) { bool eventAccepted = false; - double weight = 1.0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); registry.fill(HIST("hCollisionsUnweighted"), 0.5); // allDetColl if (std::fabs(collision.posZ()) > vertexZCut) { @@ -1419,12 +1727,6 @@ struct FullJetSpectra { } registry.fill(HIST("hCollisionsUnweighted"), 1.5); // DetCollWithVertexZ - // for (auto const& track : tracks) { - if (pTHat < pTHatAbsoluteMin) { // Track outlier rejection: should this be for every track iteration or for every collision? - return; - } - // } - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { registry.fill(HIST("hCollisionsUnweighted"), 2.5); // MBRejectedDetEvents return; @@ -1442,8 +1744,8 @@ struct FullJetSpectra { if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hCollisionsUnweighted"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -1501,8 +1803,8 @@ struct FullJetSpectra { if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hCollisionsUnweighted"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC } } @@ -1565,9 +1867,9 @@ struct FullJetSpectra { if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; fillTrackHistograms(tracks, clusters, eventWeight); if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; registry.fill(HIST("hCollisionsWeighted"), 4.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC } } @@ -1595,89 +1897,168 @@ struct FullJetSpectra { } PROCESS_SWITCH(FullJetSpectra, processTracksWeighted, "Full Jet tracks weighted", false); - void processCollisionsWeightedWithMultiplicity(soa::Filtered>::iterator const& collision, JetTableMCDWeightedJoined const& mcdjets, aod::JMcCollisions const&, soa::Filtered const& tracks, soa::Filtered const& clusters) + void processMBCollisionsDATAWithMultiplicity(soa::Filtered::iterator const& collision, FullJetTableDataJoined const& jets, aod::JetTracks const& /*tracks*/, aod::JetClusters const& /*clusters*/) { bool eventAccepted = false; - float eventWeight = collision.mcCollision().weight(); - float neutralEnergy = 0.0; - registry.fill(HIST("hEventmultiplicityCounter"), 0.5, eventWeight); // allDetColl + registry.fill(HIST("hEventmultiplicityCounter"), 0.5); // allDetColl if (std::fabs(collision.posZ()) > vertexZCut) { - registry.fill(HIST("hEventmultiplicityCounter"), 1.5, eventWeight); // DetCollWithVertexZ - return; - } - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { - registry.fill(HIST("hEventmultiplicityCounter"), 2.5, eventWeight); // MBRejectedDetEvents return; } + registry.fill(HIST("hEventmultiplicityCounter"), 1.5); // DetCollWithVertexZ + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - registry.fill(HIST("hEventmultiplicityCounter"), 3.5, eventWeight); // EventsNotSatisfyingEventSelection - return; - } - if (doMBGapTrigger && eventWeight == 1) { - registry.fill(HIST("hEventmultiplicityCounter"), 2.5, eventWeight); // MBRejectedDetEvents + registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // EventsNotSatisfyingEventSelection return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content - eventAccepted = true; - fillTrackHistograms(tracks, clusters, eventWeight); if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("hEventmultiplicityCounter"), 4.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC + eventAccepted = true; + registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; - registry.fill(HIST("hEventmultiplicityCounter"), 4.5, eventWeight); // EMCreadoutDetJJEventsWithkTVXinEMC + registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EMCreadoutDetEventsWithkTVXinEMC } } if (!eventAccepted) { - registry.fill(HIST("hEventmultiplicityCounter"), 5.5, eventWeight); // AllRejectedDetEventsAfterEMCEventSelection + registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("hCollisionsWeighted"), 6.5); // EMCAcceptedWeightedDetColl + registry.fill(HIST("hEventmultiplicityCounter"), 5.5); // EMCAcceptedDetColl - for (auto const& track : tracks) { - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + registry.fill(HIST("h_FT0Mults_occupancy"), collision.multFT0M()); + + // Jet processing - NEW IMPLEMENTATION + std::vector::iterator> selectedJets; + // static int eventCounter = 0; + int nJetsThisEvent = 0; + // Debug output + // std::cout << "===== Event " << ++eventCounter << " (Collision ID: " << collision.globalIndex() << ") =====" << std::endl; + + // Verify jet-collision association + for (auto const& jet : jets) { + if (jet.collisionId() != collision.globalIndex()) { + std::cout << "WARNING: Jet with pT " << jet.pt() << " belongs to collision " << jet.collisionId() + << " but processing collision " << collision.globalIndex() << std::endl; continue; } - } - registry.fill(HIST("hEventmultiplicityCounter"), 7.5, eventWeight); // EMCAcceptedWeightedCollAfterTrackSel - registry.fill(HIST("h_FT0Mults_occupancy"), collision.multiplicity(), eventWeight); - for (auto const& mcdjet : mcdjets) { - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); - if (mcdjet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // MCD jets outlier rejection - return; - } - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; - } - if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax) { + if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) continue; - } - if (!isAcceptedJet(mcdjet)) { + if (!isAcceptedRecoJet(jet)) continue; + + selectedJets.push_back(jet); + nJetsThisEvent++; + // std::cout << "Selected jet pT: " << jet.pt() << " (collision ID: " << jet.collisionId() << ")" << std::endl; + } + // 1. Sort selected jets by pT before processing + std::sort(selectedJets.begin(), selectedJets.end(), + [](auto const& a, auto const& b) { return (*a).pt() > (*b).pt(); }); + + // std::cout << "Number of selected jets: " << selectedJets.size() << std::endl; + + // // 2. Reset counters for each event + // int numberOfChargedParticles = 0; + // int totalNumberOfChargedParticles = 0; + // int leadingJetCount = 0; + // + // std::cout << "Number of selected jets per event: " << selectedJets.size() << std::endl; + // for (const auto& jetIter : selectedJets) { + // std::cout << "Jet pT of selectedJets: " << (*jetIter).pt() << std::endl; + // } + // //Checking Event Counter + // static int eventCounter = 0; + // std::cout << "===== Event " << ++eventCounter << " =====" << std::endl; + // std::cout << "******************************************** " << std::endl; + if (selectedJets.size() == 0) { // no jets = no leading jet + return; + } + + if (selectedJets.size() > 0) { + // Jet multiplicity per event + registry.fill(HIST("h_all_fulljet_Njets"), selectedJets.size(), 1.0); + + // Select Leading Jet for N_ch calculation (for every leading jet that is found). There's always one leading jet per event! + auto const& leadingJet = *selectedJets[0]; + auto const& leadingJetPt = leadingJet.pt(); // jet pT distribution of the leading jet + // std::cout << "Leading Jet pT: " << leadingJetPt << std::endl; + registry.fill(HIST("h_Leading_full_jet_pt"), leadingJetPt, 1.0); + registry.fill(HIST("h2_full_jet_leadingJetPt_vs_counts"), leadingJetPt, nJetsThisEvent, 1.0); + } + + if (selectedJets.size() > 1) { + auto const& subLeadingJet = *selectedJets[1]; + auto const& subLeadingJetPt = subLeadingJet.pt(); // jet pT distribution of the subleading jet i.e. 2nd leading jet + registry.fill(HIST("h_SubLeading_full_jet_pt"), subLeadingJetPt, 1.0); + registry.fill(HIST("h2_full_jet_subLeadingJetPt_vs_counts"), subLeadingJetPt, nJetsThisEvent, 1.0); + } + // Process ALL selected jets (not just leading) + for (size_t i = 0; i < selectedJets.size(); i++) { + auto const& jet = *selectedJets[i]; + float jetPt = jet.pt(); + bool isLeading = (i == 0); + bool isSubLeading = (i == 1 && selectedJets.size() > 1); // first sub-leading jet + + // Count charged particles(NCh) for this jet + int numberOfChargedParticles = 0; + for (const auto& jettrack : jet.tracks_as()) { + if (jetderiveddatautilities::selectTrack(jettrack, trackSelection)) { + numberOfChargedParticles++; + } else + continue; } - registry.fill(HIST("h2_full_jet_jetpTDetVsFT0Mults"), mcdjet.pt(), collision.multiplicity(), eventWeight); - for (auto const& cluster : clusters) { - neutralEnergy += cluster.energy(); + // Calculate neutral energy fraction for this jet + float neutralEnergy = 0.0; + for (const auto& jetcluster : jet.clusters_as()) { + neutralEnergy += jetcluster.energy(); + } + float nef = neutralEnergy / jet.energy(); + + // CASE 1: Fill histograms for ALL selected jets + registry.fill(HIST("h_all_fulljet_pt"), jetPt, 1.0); + registry.fill(HIST("h_all_fulljet_Nch"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_all_fulljet_NEF"), nef, 1.0); + registry.fill(HIST("h2_all_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), 1.0); + registry.fill(HIST("h2_all_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, 1.0); + + // CASE 2: Additional leading jet processing + if (isLeading) { + registry.fill(HIST("h_leading_fulljet_pt"), jetPt, 1.0); + registry.fill(HIST("h_leading_fulljet_Nch"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_leading_fulljet_NEF"), nef, 1.0); + registry.fill(HIST("h2_leading_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), 1.0); + registry.fill(HIST("h2_leading_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_leading_fulljet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, 1.0); + } + + // CASE 3: Additional first sub-leading jet processing + if (isSubLeading) { + registry.fill(HIST("h_subleading_fulljet_pt"), jetPt, 1.0); + registry.fill(HIST("h_subleading_fulljet_Nch"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_subleading_fulljet_NEF"), nef, 1.0); + registry.fill(HIST("h2_subleading_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), 1.0); + registry.fill(HIST("h2_subleading_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_subleading_fulljet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, 1.0); } - auto nef = neutralEnergy / mcdjet.energy(); - registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), mcdjet.pt(), collision.multiplicity(), nef, eventWeight); } } - PROCESS_SWITCH(FullJetSpectra, processCollisionsWeightedWithMultiplicity, "Weighted Collisions for Full Jets Multiplicity Studies", false); + PROCESS_SWITCH(FullJetSpectra, processMBCollisionsDATAWithMultiplicity, "MB DATA Collisions for Full Jets Multiplicity Studies", false); - void processMBCollisionsWithMultiplicity(soa::Filtered>::iterator const& collision, JetTableMCDJoined const& mcdjets, aod::JMcCollisions const&, soa::Filtered const& tracks, soa::Filtered const& clusters) + void processMBMCDCollisionsWithMultiplicity(soa::Filtered::iterator const& collision, JetTableMCDJoined const& mcdjets, aod::JMcCollisions const&, aod::JetTracks const& /*tracks*/, aod::JetClusters const& /*clusters*/) { bool eventAccepted = false; - float pTHat = 10. / (std::pow(1.0, 1.0 / pTHatExponent)); - float neutralEnergy = 0.0; + // float pTHat = 10. / (std::pow(1.0, 1.0 / pTHatExponent)); registry.fill(HIST("hEventmultiplicityCounter"), 0.5); // allDetColl if (std::fabs(collision.posZ()) > vertexZCut) { @@ -1685,136 +2066,628 @@ struct FullJetSpectra { } registry.fill(HIST("hEventmultiplicityCounter"), 1.5); // DetCollWithVertexZ - if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { - registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // MBRejectedDetEvents - return; - } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EventsNotSatisfyingEventSelection + registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // EventsNotSatisfyingEventSelection return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; - fillTrackHistograms(tracks, clusters, 1.0); + // fillTrackHistograms(tracks, clusters, 1.0); if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EMCreadoutDetEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; - registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EMCreadoutDetEventsWithkTVXinEMC } } if (!eventAccepted) { - registry.fill(HIST("hEventmultiplicityCounter"), 5.5); // AllRejectedDetEventsAfterEMCEventSelection + registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // AllRejectedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("hEventmultiplicityCounter"), 6.5); // EMCAcceptedDetColl + registry.fill(HIST("hEventmultiplicityCounter"), 5.5); // EMCAcceptedDetColl - for (auto const& track : tracks) { - if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { - continue; - } - } - registry.fill(HIST("hEventmultiplicityCounter"), 7.5); // EMCAcceptedCollAfterTrackSel - registry.fill(HIST("h_FT0Mults_occupancy"), collision.multiplicity()); + registry.fill(HIST("h_FT0Mults_occupancy"), collision.multFT0M()); + + std::vector::iterator> selectedJets; + // static int eventCounter = 0; + int nJetsThisEvent = 0; + // Debug output + // std::cout << "===== Event " << ++eventCounter << " (Collision ID: " << collision.globalIndex() << ") =====" << std::endl; + // Verify jet-collision association for (auto const& mcdjet : mcdjets) { - if (mcdjet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // MCD (Detector Level) Outlier Rejection - return; - } - if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + if (mcdjet.collisionId() != collision.globalIndex()) { + std::cout << "WARNING: Jet with pT " << mcdjet.pt() << " belongs to collision " << mcdjet.collisionId() + << " but processing collision " << collision.globalIndex() << std::endl; continue; } - if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax) { + + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) continue; - } - if (!isAcceptedJet(mcdjet)) { + if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax) + continue; + if (!isAcceptedRecoJet(mcdjet)) continue; + + selectedJets.push_back(mcdjet); + nJetsThisEvent++; + // std::cout << "Selected jet pT: " << jet.pt() << " (collision ID: " << jet.collisionId() << ")" << std::endl; + } + // 1. Sort selected jets by pT before processing + std::sort(selectedJets.begin(), selectedJets.end(), + [](auto const& a, auto const& b) { return (*a).pt() > (*b).pt(); }); + + if (selectedJets.size() == 0) { // no jets = no leading jet + return; + } + + if (selectedJets.size() > 0) { + // Jet multiplicity per event + registry.fill(HIST("h_all_fulljet_Njets"), selectedJets.size(), 1.0); + + // Select Leading Jet for N_ch calculation (for every leading jet that is found). There's always one leading jet per event! + auto const& leadingJet = *selectedJets[0]; + auto const& leadingJetPt = leadingJet.pt(); // jet pT distribution of the leading jet + // std::cout << "Leading Jet pT: " << leadingJetPt << std::endl; + registry.fill(HIST("h_Leading_full_jet_pt"), leadingJetPt, 1.0); + registry.fill(HIST("h2_full_jet_leadingJetPt_vs_counts"), leadingJetPt, nJetsThisEvent, 1.0); + } + + if (selectedJets.size() > 1) { + auto const& subLeadingJet = *selectedJets[1]; + auto const& subLeadingJetPt = subLeadingJet.pt(); // jet pT distribution of the subleading jet i.e. 2nd leading jet + registry.fill(HIST("h_SubLeading_full_jet_pt"), subLeadingJetPt, 1.0); + registry.fill(HIST("h2_full_jet_subLeadingJetPt_vs_counts"), subLeadingJetPt, nJetsThisEvent, 1.0); + } + // Process ALL selected jets (not just leading) + for (size_t i = 0; i < selectedJets.size(); i++) { + auto const& jet = *selectedJets[i]; + float jetPt = jet.pt(); + bool isLeading = (i == 0); + bool isSubLeading = (i == 1 && selectedJets.size() > 1); // first sub-leading jet + + // Count charged particles(NCh) for this jet + int numberOfChargedParticles = 0; + for (const auto& jettrack : jet.tracks_as()) { + if (jetderiveddatautilities::selectTrack(jettrack, trackSelection)) { + numberOfChargedParticles++; + } else + continue; } - registry.fill(HIST("h2_full_jet_jetpTDetVsFT0Mults"), mcdjet.pt(), collision.multiplicity(), 1.0); - for (auto const& cluster : clusters) { - neutralEnergy += cluster.energy(); + // Calculate neutral energy fraction for this jet + float neutralEnergy = 0.0; + for (const auto& jetcluster : jet.clusters_as()) { + neutralEnergy += jetcluster.energy(); + } + float nef = neutralEnergy / jet.energy(); + + // CASE 1: Fill histograms for ALL selected jets + registry.fill(HIST("h_all_fulljet_pt"), jetPt, 1.0); + registry.fill(HIST("h_all_fulljet_Nch"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_all_fulljet_NEF"), nef, 1.0); + registry.fill(HIST("h2_all_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), 1.0); + registry.fill(HIST("h2_all_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, 1.0); + + // CASE 2: Additional leading jet processing + if (isLeading) { + registry.fill(HIST("h_leading_fulljet_pt"), jetPt, 1.0); + registry.fill(HIST("h_leading_fulljet_Nch"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_leading_fulljet_NEF"), nef, 1.0); + registry.fill(HIST("h2_leading_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), 1.0); + registry.fill(HIST("h2_leading_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_leading_fulljet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, 1.0); + } + + // CASE 3: Additional first sub-leading jet processing + if (isSubLeading) { + registry.fill(HIST("h_subleading_fulljet_pt"), jetPt, 1.0); + registry.fill(HIST("h_subleading_fulljet_Nch"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_subleading_fulljet_NEF"), nef, 1.0); + registry.fill(HIST("h2_subleading_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), 1.0); + registry.fill(HIST("h2_subleading_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_subleading_fulljet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, 1.0); } - auto nef = neutralEnergy / mcdjet.energy(); - registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), mcdjet.pt(), collision.multiplicity(), nef, 1.0); } } - PROCESS_SWITCH(FullJetSpectra, processMBCollisionsWithMultiplicity, "MB MCD Collisions for Full Jets Multiplicity Studies", false); + PROCESS_SWITCH(FullJetSpectra, processMBMCDCollisionsWithMultiplicity, "MB MCD Collisions for Full Jets Multiplicity Studies", false); - void processMBCollisionsDATAWithMultiplicity(soa::Filtered>::iterator const& collision, FullJetTableDataJoined const& jets, soa::Filtered const& tracks, soa::Filtered const& clusters) + void processMCDCollisionsWeightedWithMultiplicity(soa::Filtered::iterator const& collision, JetTableMCDWeightedJoined const& mcdjets, aod::JMcCollisions const&, aod::JetTracks const& tracks, aod::JetClusters const& clusters) { bool eventAccepted = false; - float neutralEnergy = 0.0; + float eventWeight = collision.mcCollision().weight(); - registry.fill(HIST("hEventmultiplicityCounter"), 0.5); // allDetColl + registry.fill(HIST("hEventmultiplicityCounter"), 0.5, eventWeight); // allWeightedDetColl if (std::fabs(collision.posZ()) > vertexZCut) { return; } - registry.fill(HIST("hEventmultiplicityCounter"), 1.5); // DetCollWithVertexZ + registry.fill(HIST("hEventmultiplicityCounter"), 1.5, eventWeight); // WeightedDetCollWithVertexZ + if (doMBGapTrigger && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { - registry.fill(HIST("hEventmultiplicityCounter"), 2.5); // MBRejectedDetEvents + registry.fill(HIST("hEventmultiplicityCounter"), 2.5, eventWeight); // MBRejectedDetEvents return; } if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { - registry.fill(HIST("hEventmultiplicityCounter"), 3.5); // EventsNotSatisfyingEventSelection + registry.fill(HIST("hEventmultiplicityCounter"), 3.5, eventWeight); // WeightedEventsNotSatisfyingEventSelection + return; + } + if (doMBGapTrigger && eventWeight == 1) { + registry.fill(HIST("hEventmultiplicityCounter"), 2.5, eventWeight); // MBRejectedDetEvents return; } if (doEMCALEventWorkaround) { if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content eventAccepted = true; - fillTrackHistograms(tracks, clusters, 1.0); + fillTrackHistograms(tracks, clusters, eventWeight); if (collision.alias_bit(kTVXinEMC)) { - registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + registry.fill(HIST("hEventmultiplicityCounter"), 4.5, eventWeight); // EMCreadoutWeightedDetJJEventsWithkTVXinEMC } } } else { if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { eventAccepted = true; - registry.fill(HIST("hEventmultiplicityCounter"), 4.5); // EMCreadoutDetEventsWithkTVXinEMC + registry.fill(HIST("hEventmultiplicityCounter"), 4.5, eventWeight); // EMCreadoutWeightedDetJJEventsWithkTVXinEMC } } if (!eventAccepted) { - registry.fill(HIST("hEventmultiplicityCounter"), 5.5); // AllRejectedDetEventsAfterEMCEventSelection + registry.fill(HIST("hEventmultiplicityCounter"), 5.5, eventWeight); // AllRejectedWeightedDetEventsAfterEMCEventSelection return; } - registry.fill(HIST("hEventmultiplicityCounter"), 6.5); // EMCAcceptedDetColl - + registry.fill(HIST("hEventmultiplicityCounter"), 6.5, eventWeight); // EMCAcceptedWeightedDetColl for (auto const& track : tracks) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } } - registry.fill(HIST("hEventmultiplicityCounter"), 7.5); // EMCAcceptedCollAfterTrackSel - registry.fill(HIST("h_FT0Mults_occupancy"), collision.multiplicity()); + registry.fill(HIST("hEventmultiplicityCounter"), 7.5, eventWeight); // EMCAcceptedWeightedCollAfterTrackSel + + registry.fill(HIST("h_FT0Mults_occupancy"), collision.multFT0M(), eventWeight); + + std::vector::iterator> selectedJets; + int nJetsThisEvent = 0; + + for (auto const& mcdjet : mcdjets) { + float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + + if (mcdjet.collisionId() != collision.globalIndex()) { + std::cout << "WARNING: Jet with pT " << mcdjet.pt() << " belongs to collision " << mcdjet.collisionId() + << " but processing collision " << collision.globalIndex() << std::endl; + continue; + } + + if (mcdjet.pt() > pTHatMaxMCD * pTHat || pTHat < pTHatAbsoluteMin) { // MCD jets outlier rejection + return; + } + if (!jetfindingutilities::isInEtaAcceptance(mcdjet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (mcdjet.phi() < jetPhiMin || mcdjet.phi() > jetPhiMax) { + continue; + } + if (!isAcceptedRecoJet(mcdjet)) { + continue; + } + selectedJets.push_back(mcdjet); + nJetsThisEvent++; + } + // 1. Sort selected jets by pT before processing + std::sort(selectedJets.begin(), selectedJets.end(), + [](auto const& a, auto const& b) { return (*a).pt() > (*b).pt(); }); + if (selectedJets.size() == 0) { // no jets = no leading jet + return; + } + if (selectedJets.size() > 0) { + // Jet multiplicity per event + registry.fill(HIST("h_all_fulljet_Njets"), selectedJets.size(), eventWeight); + + // Select Leading Jet for N_ch calculation (for every leading jet that is found). There's always one leading jet per event! + auto const& leadingJet = *selectedJets[0]; + auto const& leadingJetPt = leadingJet.pt(); // jet pT distribution of the leading jet + // std::cout << "Leading Jet pT: " << leadingJetPt << std::endl; + registry.fill(HIST("h_Leading_full_jet_pt"), leadingJetPt, eventWeight); + registry.fill(HIST("h2_full_jet_leadingJetPt_vs_counts"), leadingJetPt, nJetsThisEvent, eventWeight); + } + + if (selectedJets.size() > 1) { + auto const& subLeadingJet = *selectedJets[1]; + auto const& subLeadingJetPt = subLeadingJet.pt(); // jet pT distribution of the subleading jet i.e. 2nd leading jet + registry.fill(HIST("h_SubLeading_full_jet_pt"), subLeadingJetPt, eventWeight); + registry.fill(HIST("h2_full_jet_subLeadingJetPt_vs_counts"), subLeadingJetPt, nJetsThisEvent, eventWeight); + } + // Process ALL selected jets (not just leading) + for (size_t i = 0; i < selectedJets.size(); i++) { + auto const& jet = *selectedJets[i]; + float jetPt = jet.pt(); + bool isLeading = (i == 0); + bool isSubLeading = (i == 1 && selectedJets.size() > 1); // first sub-leading jet + + // Count charged particles(NCh) for this jet + int numberOfChargedParticles = 0; + for (const auto& jettrack : jet.tracks_as()) { + if (jetderiveddatautilities::selectTrack(jettrack, trackSelection)) { + numberOfChargedParticles++; + } else + continue; + } + + // Calculate neutral energy fraction for this jet + float neutralEnergy = 0.0; + for (const auto& jetcluster : jet.clusters_as()) { + neutralEnergy += jetcluster.energy(); + } + float nef = neutralEnergy / jet.energy(); + + // CASE 1: Fill histograms for ALL selected jets + registry.fill(HIST("h_all_fulljet_pt"), jetPt, eventWeight); + registry.fill(HIST("h_all_fulljet_Nch"), numberOfChargedParticles, eventWeight); + registry.fill(HIST("h_all_fulljet_NEF"), nef, eventWeight); + registry.fill(HIST("h2_all_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), eventWeight); + registry.fill(HIST("h2_all_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, eventWeight); + registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, eventWeight); + + // CASE 2: Additional leading jet processing + if (isLeading) { + registry.fill(HIST("h_leading_fulljet_pt"), jetPt, eventWeight); + registry.fill(HIST("h_leading_fulljet_Nch"), numberOfChargedParticles, eventWeight); + registry.fill(HIST("h_leading_fulljet_NEF"), nef, eventWeight); + registry.fill(HIST("h2_leading_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), eventWeight); + registry.fill(HIST("h2_leading_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, eventWeight); + registry.fill(HIST("h3_leading_fulljet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, eventWeight); + } + + // CASE 3: Additional first sub-leading jet processing + if (isSubLeading) { + registry.fill(HIST("h_subleading_fulljet_pt"), jetPt, eventWeight); + registry.fill(HIST("h_subleading_fulljet_Nch"), numberOfChargedParticles, eventWeight); + registry.fill(HIST("h_subleading_fulljet_NEF"), nef, eventWeight); + registry.fill(HIST("h2_subleading_fulljet_jetpTDet_vs_FT0Mults"), jetPt, collision.multFT0M(), eventWeight); + registry.fill(HIST("h2_subleading_fulljet_jetpTDet_vs_Nch"), jetPt, numberOfChargedParticles, eventWeight); + registry.fill(HIST("h3_subleading_fulljet_jetpTDet_FT0Mults_nef"), jetPt, collision.multFT0M(), nef, eventWeight); + } + } + } + PROCESS_SWITCH(FullJetSpectra, processMCDCollisionsWeightedWithMultiplicity, "Weighted MCD Collisions for Full Jets Multiplicity Studies", false); + + void processMBMCPCollisionsWithMultiplicity(aod::JetMcCollision const& mccollision, + JetTableMCPJoined const& jets, aod::JetParticles const& /*particles*/, + soa::SmallGroups const& collisions) + { + bool eventAccepted = false; + double weight = 1.0; + float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + float mcpMult = 0.0f; + float mcpCent = 0.0f; + + registry.fill(HIST("hPartEventmultiplicityCounter"), 0.5); // allMcColl + if (std::fabs(mccollision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("hPartEventmultiplicityCounter"), 1.5); // McCollWithVertexZ + + // outlier check: for every outlier jet, reject the whole event for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + registry.fill(HIST("hPartEventmultiplicityCounter"), 2.5); // RejectedPartCollWithOutliers + return; + } + } + + if (doMBGapTrigger && mccollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + // Fill rejected MB events; + registry.fill(HIST("hPartEventmultiplicityCounter"), 3.5); // MBRejectedPartEvents + return; + } + + // Perform MC Collision matching, i.e. match the current MC collision to its associated reco (MCD) collision + // to get the corresponding FT0M component at the particle level + auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, mccollision.globalIndex()); + registry.fill(HIST("hRecoMatchesPerMcCollisionMult"), collisionspermcpjet.size()); // for split vertices QA + + if (collisionspermcpjet.size() == 0 || collisionspermcpjet.size() < 1) { + registry.fill(HIST("hPartEventmultiplicityCounter"), 4.5); // RejectedPartCollForDetCollWithSize0or<1 + return; + } + registry.fill(HIST("hPartEventmultiplicityCounter"), 5.5); // AcceptedPartCollWithSize>1 + + for (auto const& collision : collisionspermcpjet) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { continue; } - if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) { + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hPartEventmultiplicityCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hPartEventmultiplicityCounter"), 6.5); // EMCreadoutDetEventsWithkTVXinEMC + } + } + mcpMult += collision.multFT0M(); + mcpCent += collision.centFT0M(); + } // collision loop ends + + if (!eventAccepted) { + registry.fill(HIST("hPartEventmultiplicityCounter"), 7.5); // AllRejectedPartEventsAfterEMCEventSelection + return; + } + registry.fill(HIST("hPartEventmultiplicityCounter"), 8.5); // EMCAcceptedPartColl + registry.fill(HIST("hMCCollMatchedFT0Mult"), mcpMult); + registry.fill(HIST("hMCCollMatchedFT0Cent"), mcpCent); + + std::vector::iterator> selectedJets; + int nJetsThisEvent = 0; + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) + continue; + if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) + continue; + if (!isAcceptedPartJet(jet)) continue; + + selectedJets.push_back(jet); + nJetsThisEvent++; + } + // 1. Sort selected jets by pT before processing + std::sort(selectedJets.begin(), selectedJets.end(), + [](auto const& a, auto const& b) { return (*a).pt() > (*b).pt(); }); + + if (selectedJets.size() == 0) { // no jets = no leading jet + return; + } + + if (selectedJets.size() > 0) { + // Jet multiplicity per event + registry.fill(HIST("h_all_fulljet_Njets_part"), selectedJets.size(), 1.0); + + // Select Leading Jet for N_ch calculation (for every leading jet that is found). There's always one leading jet per event! + auto const& leadingJet = *selectedJets[0]; + auto const& leadingJetPt = leadingJet.pt(); // jet pT distribution of the leading jet + // std::cout << "Leading Jet pT: " << leadingJetPt << std::endl; + registry.fill(HIST("h_Leading_full_jet_pt_part"), leadingJetPt, 1.0); + registry.fill(HIST("h2_full_jet_leadingJetPt_vs_counts_part"), leadingJetPt, nJetsThisEvent, 1.0); + } + + if (selectedJets.size() > 1) { + auto const& subLeadingJet = *selectedJets[1]; + auto const& subLeadingJetPt = subLeadingJet.pt(); // jet pT distribution of the subleading jet i.e. 2nd leading jet + registry.fill(HIST("h_SubLeading_full_jet_pt_part"), subLeadingJetPt, 1.0); + registry.fill(HIST("h2_full_jet_subLeadingJetPt_vs_counts_part"), subLeadingJetPt, nJetsThisEvent, 1.0); + } + // Process ALL selected jets (not just leading) + for (size_t i = 0; i < selectedJets.size(); i++) { + auto const& jet = *selectedJets[i]; + float jetPt = jet.pt(); + bool isLeading = (i == 0); + bool isSubLeading = (i == 1 && selectedJets.size() > 1); // first sub-leading jet + + // Count charged particles(NCh) and neutral particles (NNe) for this jet + int numberOfChargedParticles = 0; + int numberOfNeutralParticles = 0; + float neutralEnergy = 0.0f; + for (const auto& constituent : jet.tracks_as()) { + auto pdgParticle = pdgDatabase->GetParticle(constituent.pdgCode()); + if (pdgParticle->Charge() == 0) { + numberOfNeutralParticles++; + neutralEnergy += constituent.e(); + } else { + numberOfChargedParticles++; + } + } + float nef = neutralEnergy / jet.energy(); + + // CASE 1: Fill histograms for ALL selected jets + registry.fill(HIST("h_all_fulljet_pt_part"), jetPt, 1.0); + registry.fill(HIST("h_all_fulljet_Nch_part"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_all_fulljet_Nne_part"), numberOfNeutralParticles, 1.0); + registry.fill(HIST("h_all_fulljet_NEF_part"), nef, 1.0); + registry.fill(HIST("h2_all_fulljet_jetpT_vs_FT0Mults_part"), jetPt, mcpMult, 1.0); + registry.fill(HIST("h2_all_fulljet_jetpT_vs_Nch_part"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_full_jet_jetpT_FT0Mults_nef_part"), jetPt, mcpMult, nef, 1.0); + + // CASE 2: Additional leading jet processing + if (isLeading) { + registry.fill(HIST("h_leading_fulljet_pt_part"), jetPt, 1.0); + registry.fill(HIST("h_leading_fulljet_Nch_part"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_leading_fulljet_Nne_part"), numberOfNeutralParticles, 1.0); + registry.fill(HIST("h_leading_fulljet_NEF_part"), nef, 1.0); + registry.fill(HIST("h2_leading_fulljet_jetpT_vs_FT0Mults_part"), jetPt, mcpMult, 1.0); + registry.fill(HIST("h2_leading_fulljet_jetpT_vs_Nch_part"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_leading_fulljet_jetpT_FT0Mults_nef_part"), jetPt, mcpMult, nef, 1.0); + } + + // CASE 3: Additional first sub-leading jet processing + if (isSubLeading) { + registry.fill(HIST("h_subleading_fulljet_pt_part"), jetPt, 1.0); + registry.fill(HIST("h_subleading_fulljet_Nch_part"), numberOfChargedParticles, 1.0); + registry.fill(HIST("h_subleading_fulljet_Nne_part"), numberOfNeutralParticles, 1.0); + registry.fill(HIST("h_subleading_fulljet_NEF_part"), nef, 1.0); + registry.fill(HIST("h2_subleading_fulljet_jetpT_vs_FT0Mults_part"), jetPt, mcpMult, 1.0); + registry.fill(HIST("h2_subleading_fulljet_jetpT_vs_Nch_part"), jetPt, numberOfChargedParticles, 1.0); + registry.fill(HIST("h3_subleading_fulljet_jetpT_FT0Mults_nef_part"), jetPt, mcpMult, nef, 1.0); + } + } + } + PROCESS_SWITCH(FullJetSpectra, processMBMCPCollisionsWithMultiplicity, "MB MCP Collisions for Full Jets Multiplicity Studies", false); + + void processMBMCPCollisionsWeightedWithMultiplicity(aod::JetMcCollision const& mccollision, + JetTableMCPWeightedJoined const& jets, aod::JetParticles const& /*particles*/, + soa::SmallGroups const& collisions) + { + bool eventAccepted = false; + float pTHat = 10. / (std::pow(mccollision.weight(), 1.0 / pTHatExponent)); + float mcpMult = 0.0f; + float mcpCent = 0.0f; + + registry.fill(HIST("hPartEventmultiplicityCounter"), 0.5, mccollision.weight()); // allWeightedMcColl + if (std::fabs(mccollision.posZ()) > vertexZCut) { + return; + } + registry.fill(HIST("hPartEventmultiplicityCounter"), 1.5, mccollision.weight()); // WeightedMcCollWithVertexZ + + // outlier check: for every outlier jet, reject the whole event + for (auto const& jet : jets) { + if (jet.pt() > pTHatMaxMCP * pTHat || pTHat < pTHatAbsoluteMin) { + registry.fill(HIST("hPartEventmultiplicityCounter"), 2.5, mccollision.weight()); // RejectedWeightedPartCollWithOutliers + return; } - if (!isAcceptedJet(jet)) { + } + + if (doMBGapTrigger && mccollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + // Fill rejected MB events; + registry.fill(HIST("hPartEventmultiplicityCounter"), 3.5, mccollision.weight()); // MBRejectedPartEvents + return; + } + + // Perform MC Collision matching, i.e. match the current MC collision to its associated reco (MCD) collision + // to get the corresponding FT0M component at the particle level + auto collisionspermcpjet = collisions.sliceBy(CollisionsPerMCPCollision, mccollision.globalIndex()); + registry.fill(HIST("hRecoMatchesPerMcCollisionMult"), collisionspermcpjet.size(), mccollision.weight()); // for split vertices QA + + if (collisionspermcpjet.size() == 0 || collisionspermcpjet.size() < 1) { + registry.fill(HIST("hPartEventmultiplicityCounter"), 4.5, mccollision.weight()); // RejectedWeightedPartCollForDetCollWithSize0or<1 + return; + } + registry.fill(HIST("hPartEventmultiplicityCounter"), 5.5, mccollision.weight()); // AcceptedWeightedPartCollWithSize>1 + + for (auto const& collision : collisionspermcpjet) { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, doMBGapTrigger)) { continue; } - registry.fill(HIST("h2_full_jet_jetpTDetVsFT0Mults"), jet.pt(), collision.multiplicity(), 1.0); + if (doEMCALEventWorkaround) { + if (collision.isEmcalReadout() && !collision.isAmbiguous()) { // i.e. EMCAL has a cell content + if (collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hPartEventmultiplicityCounter"), 6.5, mccollision.weight()); // EMCreadoutDetEventsWithkTVXinEMC + } + } + } else { + if (!collision.isAmbiguous() && jetderiveddatautilities::eventEMCAL(collision) && collision.alias_bit(kTVXinEMC)) { + eventAccepted = true; + registry.fill(HIST("hPartEventmultiplicityCounter"), 6.5, mccollision.weight()); // EMCreadoutDetEventsWithkTVXinEMC + } + } + mcpMult += collision.multFT0M(); + mcpCent += collision.centFT0M(); + } // collision loop ends - for (auto const& cluster : clusters) { - neutralEnergy += cluster.energy(); + if (!eventAccepted) { + registry.fill(HIST("hPartEventmultiplicityCounter"), 7.5, mccollision.weight()); // AllRejectedWeightedPartEventsAfterEMCEventSelection + return; + } + registry.fill(HIST("hPartEventmultiplicityCounter"), 8.5, mccollision.weight()); // EMCAcceptedWeightedPartColl + registry.fill(HIST("hMCCollMatchedFT0Mult"), mcpMult, mccollision.weight()); + registry.fill(HIST("hMCCollMatchedFT0Cent"), mcpCent, mccollision.weight()); + + std::vector::iterator> selectedJets; + int nJetsThisEvent = 0; + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) + continue; + if (jet.phi() < jetPhiMin || jet.phi() > jetPhiMax) + continue; + if (!isAcceptedPartJet(jet)) + continue; + + selectedJets.push_back(jet); + nJetsThisEvent++; + } + // 1. Sort selected jets by pT before processing + std::sort(selectedJets.begin(), selectedJets.end(), + [](auto const& a, auto const& b) { return (*a).pt() > (*b).pt(); }); + + if (selectedJets.size() == 0) { // no jets = no leading jet + return; + } + + if (selectedJets.size() > 0) { + // Jet multiplicity per event + registry.fill(HIST("h_all_fulljet_Njets_part"), selectedJets.size(), mccollision.weight()); + + // Select Leading Jet for N_ch calculation (for every leading jet that is found). There's always one leading jet per event! + auto const& leadingJet = *selectedJets[0]; + auto const& leadingJetPt = leadingJet.pt(); // jet pT distribution of the leading jet + // std::cout << "Leading Jet pT: " << leadingJetPt << std::endl; + registry.fill(HIST("h_Leading_full_jet_pt_part"), leadingJetPt, mccollision.weight()); + registry.fill(HIST("h2_full_jet_leadingJetPt_vs_counts_part"), leadingJetPt, nJetsThisEvent, mccollision.weight()); + } + + if (selectedJets.size() > 1) { + auto const& subLeadingJet = *selectedJets[1]; + auto const& subLeadingJetPt = subLeadingJet.pt(); // jet pT distribution of the subleading jet i.e. 2nd leading jet + registry.fill(HIST("h_SubLeading_full_jet_pt_part"), subLeadingJetPt, mccollision.weight()); + registry.fill(HIST("h2_full_jet_subLeadingJetPt_vs_counts_part"), subLeadingJetPt, nJetsThisEvent, mccollision.weight()); + } + // Process ALL selected jets (not just leading) + for (size_t i = 0; i < selectedJets.size(); i++) { + auto const& jet = *selectedJets[i]; + float jetPt = jet.pt(); + bool isLeading = (i == 0); + bool isSubLeading = (i == 1 && selectedJets.size() > 1); // first sub-leading jet + + // Count charged particles(NCh) and neutral particles (NNe) for this jet + int numberOfChargedParticles = 0; + int numberOfNeutralParticles = 0; + float neutralEnergy = 0.0f; + for (const auto& constituent : jet.tracks_as()) { + auto pdgParticle = pdgDatabase->GetParticle(constituent.pdgCode()); + if (pdgParticle->Charge() == 0) { + numberOfNeutralParticles++; + neutralEnergy += constituent.e(); + } else { + numberOfChargedParticles++; + } + } + float nef = neutralEnergy / jet.energy(); + + // CASE 1: Fill histograms for ALL selected jets + registry.fill(HIST("h_all_fulljet_pt_part"), jetPt, mccollision.weight()); + registry.fill(HIST("h_all_fulljet_Nch_part"), numberOfChargedParticles, mccollision.weight()); + registry.fill(HIST("h_all_fulljet_Nne_part"), numberOfNeutralParticles, mccollision.weight()); + registry.fill(HIST("h_all_fulljet_NEF_part"), nef, mccollision.weight()); + registry.fill(HIST("h2_all_fulljet_jetpT_vs_FT0Mults_part"), jetPt, mcpMult, mccollision.weight()); + registry.fill(HIST("h2_all_fulljet_jetpT_vs_Nch_part"), jetPt, numberOfChargedParticles, mccollision.weight()); + registry.fill(HIST("h3_full_jet_jetpT_FT0Mults_nef_part"), jetPt, mcpMult, nef, mccollision.weight()); + + // CASE 2: Additional leading jet processing + if (isLeading) { + registry.fill(HIST("h_leading_fulljet_pt_part"), jetPt, mccollision.weight()); + registry.fill(HIST("h_leading_fulljet_Nch_part"), numberOfChargedParticles, mccollision.weight()); + registry.fill(HIST("h_leading_fulljet_Nne_part"), numberOfNeutralParticles, mccollision.weight()); + registry.fill(HIST("h_leading_fulljet_NEF_part"), nef, mccollision.weight()); + registry.fill(HIST("h2_leading_fulljet_jetpT_vs_FT0Mults_part"), jetPt, mcpMult, mccollision.weight()); + registry.fill(HIST("h2_leading_fulljet_jetpT_vs_Nch_part"), jetPt, numberOfChargedParticles, mccollision.weight()); + registry.fill(HIST("h3_leading_fulljet_jetpT_FT0Mults_nef_part"), jetPt, mcpMult, nef, mccollision.weight()); + } + + // CASE 3: Additional first sub-leading jet processing + if (isSubLeading) { + registry.fill(HIST("h_subleading_fulljet_pt_part"), jetPt, mccollision.weight()); + registry.fill(HIST("h_subleading_fulljet_Nch_part"), numberOfChargedParticles, mccollision.weight()); + registry.fill(HIST("h_subleading_fulljet_Nne_part"), numberOfNeutralParticles, mccollision.weight()); + registry.fill(HIST("h_subleading_fulljet_NEF_part"), nef, mccollision.weight()); + registry.fill(HIST("h2_subleading_fulljet_jetpT_vs_FT0Mults_part"), jetPt, mcpMult, mccollision.weight()); + registry.fill(HIST("h2_subleading_fulljet_jetpT_vs_Nch_part"), jetPt, numberOfChargedParticles, mccollision.weight()); + registry.fill(HIST("h3_subleading_fulljet_jetpT_FT0Mults_nef_part"), jetPt, mcpMult, nef, mccollision.weight()); } - auto nef = neutralEnergy / jet.energy(); - registry.fill(HIST("h3_full_jet_jetpTDet_FT0Mults_nef"), jet.pt(), collision.multiplicity(), nef, 1.0); } } - PROCESS_SWITCH(FullJetSpectra, processMBCollisionsDATAWithMultiplicity, "MB DATA Collisions for Full Jets Multiplicity Studies", false); + PROCESS_SWITCH(FullJetSpectra, processMBMCPCollisionsWeightedWithMultiplicity, "MB MCP Weighted Collisions for Full Jets Multiplicity Studies", false); }; // struct diff --git a/PWGJE/Tasks/fullJetTriggerQATask.cxx b/PWGJE/Tasks/fullJetTriggerQATask.cxx index bbab8a61f0d..1831a3c3372 100644 --- a/PWGJE/Tasks/fullJetTriggerQATask.cxx +++ b/PWGJE/Tasks/fullJetTriggerQATask.cxx @@ -13,25 +13,41 @@ // /// \author Gijs van Weelden // -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/EMCALClusterDefinition.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "TH1F.h" -#include "TTree.h" +#include "Common/CCDB/TriggerAliases.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" +#include "TTree.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include -#include "EventFiltering/filterTables.h" +#include +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/gammaJetTreeProducer.cxx b/PWGJE/Tasks/gammaJetTreeProducer.cxx index 351742682d0..a054a8e97b8 100644 --- a/PWGJE/Tasks/gammaJetTreeProducer.cxx +++ b/PWGJE/Tasks/gammaJetTreeProducer.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// 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. // @@ -9,40 +9,46 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. +/// \file gammaJetTreeProducer.cxx +/// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged jets +/// \author Florian Jonas , UC Berkeley/LBNL +/// \since 02.08.2024 + // C++ system headers first +#include + #include #include #include // Framework and other headers after -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/GammaJetAnalysisTree.h" +#include "PWGJE/DataModel/Jet.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 "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/GammaJetAnalysisTree.h" - -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/EMCALClusters.h" +#include "CommonDataFormat/InteractionRecord.h" +#include "DataFormatsEMCAL/AnalysisCluster.h" #include "DataFormatsEMCAL/Cell.h" #include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "TVector2.h" - -#include "CommonDataFormat/InteractionRecord.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 "EventFiltering/filterTables.h" +#include "TVector2.h" // \struct GammaJetTreeProducer /// \brief Task to produce a tree for gamma-jet analysis, including photons (and information of isolation) and charged and full jets @@ -54,6 +60,7 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; using emcClusters = o2::soa::Join; +using emcMCClusters = o2::soa::Join; #include "Framework/runDataProcessing.h" @@ -61,12 +68,19 @@ struct GammaJetTreeProducer { // analysis tree // charged jets // photon candidates - Produces chargedJetsTable; - Produces eventsTable; - Produces gammasTable; + 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 HistogramRegistry mHistograms{"GammaJetTreeProducerHisto"}; + Service pdg; + // --------------- // Configureables // --------------- @@ -83,13 +97,27 @@ struct GammaJetTreeProducer { Configurable perpConeJetR{"perpConeJetR", 0.4, "perpendicular cone radius used to calculate perp cone rho for jet"}; 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"}; int mRunNumber = 0; std::vector eventSelectionBits; int trackSelection = -1; + const int kMaxRecursionDepth = 100; std::unordered_map collisionMapping; + std::unordered_map mcJetIndexMapping; // maps the global index to the index in the mc jets table (per event). This is because later we want to later construct all trees on a per event level, and we need to know at what position in the table per event this is stored std::vector triggerMaskBits; + std::vector mcCollisionsMultiRecCollisions; // used for MC. global index of MC collisions that have multiple matched rec collisions + + // kd tree for tracks and mc particles (used for fast isolation calculation) + std::vector trackEta; + std::vector trackPhi; + std::vector trackPt; + std::vector mcParticleEta; + std::vector mcParticlePhi; + std::vector mcParticlePt; + TKDTree* trackTree = nullptr; + TKDTree* mcParticleTree = nullptr; void init(InitContext const&) { @@ -104,25 +132,152 @@ struct GammaJetTreeProducer { LOG(info) << "Creating histograms"; const o2Axis ptAxis{100, 0, 200, "p_{T} (GeV/c)"}; + const o2Axis ptRecAxis{100, 0, 200, "p_{T}^{rec} (GeV/c)"}; + const o2Axis ptGenAxis{100, 0, 200, "p_{T}^{gen} (GeV/c)"}; const o2Axis energyAxis{100, 0, 100, "E (GeV)"}; const o2Axis m02Axis{100, 0, 3, "m02"}; const o2Axis etaAxis{100, -1, 1, "#eta"}; - const o2Axis phiAxis{100, 0, 2 * TMath::Pi(), "#phi"}; + const o2Axis phiAxis{100, 0, o2::constants::math::TwoPI, "#phi"}; + const o2Axis dRAxis{100, 0, 1, "dR"}; const o2Axis occupancyAxis{300, 0, 30000, "occupancy"}; + const o2Axis nCollisionsAxis{10, -0.5, 9.5, "nCollisions"}; mHistograms.add("clusterE", "Energy of cluster", o2HistType::kTH1F, {energyAxis}); mHistograms.add("trackPt", "pT of track", o2HistType::kTH1F, {ptAxis}); mHistograms.add("chjetPt", "pT of charged jet", o2HistType::kTH1F, {ptAxis}); mHistograms.add("chjetPtEtaPhi", "pT of charged jet", o2HistType::kTHnSparseF, {ptAxis, etaAxis, phiAxis}); - mHistograms.add("chjetpt_vs_constpt", "pT of charged jet vs pT of constituents", o2HistType::kTH2F, {ptAxis, ptAxis}); + mHistograms.add("chjetpt_vs_constpt", "pT of charged jet vs pT of constituents", o2HistType::kTH2F, {ptRecAxis, ptGenAxis}); // track QA THnSparse mHistograms.add("trackPtEtaPhi", "Track QA", o2HistType::kTHnSparseF, {ptAxis, etaAxis, phiAxis}); mHistograms.add("trackPtEtaOccupancy", "Track QA vs occupancy", o2HistType::kTHnSparseF, {ptAxis, etaAxis, occupancyAxis}); + + // QA for MC collisions to rec collision matching + // number of reconstructed and matched collisions for each MC collision vs mc gen photon energy + mHistograms.add("numberRecCollisionsVsPhotonPt", "Number of rec collisions vs photon energy", o2HistType::kTH2F, {nCollisionsAxis, energyAxis}); + + // Cluster MC histograms + mHistograms.add("clusterMC_E_All", "Cluster energy for photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_Photon", "Cluster energy for photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_PromptPhoton", "Cluster energy for prompt photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DirectPromptPhoton", "Cluster energy for direct prompt photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_FragmentationPhoton", "Cluster energy for fragmentation photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DecayPhoton", "Cluster energy for decay photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DecayPhotonPi0", "Cluster energy for decay photons from pi0", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_DecayPhotonEta", "Cluster energy for decay photons from eta", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_MergedPi0", "Cluster energy for merged pi0s", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_MergedEta", "Cluster energy for merged etas", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_E_ConvertedPhoton", "Cluster energy for converted photons", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("clusterMC_m02_Photon", "M02 for photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_PromptPhoton", "M02 for prompt photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DirectPromptPhoton", "M02 for direct prompt photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_FragmentationPhoton", "M02 for fragmentation photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DecayPhoton", "M02 for decay photons", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DecayPhotonPi0", "M02 for decay photons from pi0", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_DecayPhotonEta", "M02 for decay photons from eta", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_MergedPi0", "M02 for merged pi0s", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_MergedEta", "M02 for merged etas", o2HistType::kTH1F, {m02Axis}); + mHistograms.add("clusterMC_m02_ConvertedPhoton", "M02 for converted photons", o2HistType::kTH1F, {m02Axis}); + + // MC Gen trigger particle histograms + mHistograms.add("mcGenTrigger_Eta", "eta of mc gen trigger particle", o2HistType::kTH1F, {etaAxis}); + mHistograms.add("mcGenTrigger_Phi", "phi of mc gen trigger particle", o2HistType::kTH1F, {phiAxis}); + mHistograms.add("mcGenTrigger_Pt", "pT of mc gen trigger particle", o2HistType::kTH1F, {ptAxis}); + mHistograms.add("mcGenTrigger_E", "E of mc gen trigger particle", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_PromptPhoton", "E of mc gen trigger prompt photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DirectPromptPhoton", "E of mc gen trigger direct prompt photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_FragmentationPhoton", "E of mc gen trigger fragmentation photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhoton", "E of mc gen trigger decay photon", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhotonPi0", "E of mc gen trigger decay photon from pi0", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhotonEta", "E of mc gen trigger decay photon from eta", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_DecayPhotonOther", "E of mc gen trigger decay photon from other", o2HistType::kTH1F, {energyAxis}); + mHistograms.add("mcGenTrigger_E_Pi0", "E of mc gen trigger pi0", o2HistType::kTH1F, {energyAxis}); + + // MC Particle level jet histograms + mHistograms.add("mcpJetPt", "pT of mc particle level jet", o2HistType::kTH1F, {ptAxis}); + + // MC Detector level jet matching jet histograms + mHistograms.add("mcdJetPtVsTrueJetPtMatchingGeo", "pT rec (x-axis) of detector level jets vs pT true (y-axis) of mc particle level jet (geo matching)", o2HistType::kTH2F, {ptRecAxis, ptGenAxis}); + mHistograms.add("mcdJetPtVsTrueJetPtMatchingPt", "pT rec (x-axis) of detector level jets vs pT true (y-axis) of mc particle level jet (pt matching)", o2HistType::kTH2F, {ptRecAxis, ptGenAxis}); + + // Event QA histogram + const int nEventBins = 8; + const TString eventLabels[nEventBins] = {"All", "AfterVertexCut", "AfterCollisionSelection", "AfterTriggerSelection", "AfterEMCALSelection", "AfterClusterESelection", "Has MC collision", "is not MB Gap"}; + mHistograms.add("eventQA", "Event QA", o2HistType::kTH1F, {{nEventBins, -0.5, 7.5}}); + for (int iBin = 0; iBin < nEventBins; iBin++) { + mHistograms.get(HIST("eventQA"))->GetXaxis()->SetBinLabel(iBin + 1, eventLabels[iBin]); + } + + // MC collisions QA histograms) + const int nRecCollisionBins = 4; + const TString recCollisionLabels[nRecCollisionBins] = {"All", "1 Rec collision", "More than 1 rec collisions", "No rec collisions"}; + mHistograms.add("mcCollisionsWithRecCollisions", "MC collisions with rec collisions", o2HistType::kTH1F, {{nRecCollisionBins, -0.5, 3.5}}); + for (int iBin = 0; iBin < nRecCollisionBins; iBin++) { + mHistograms.get(HIST("mcCollisionsWithRecCollisions"))->GetXaxis()->SetBinLabel(iBin + 1, recCollisionLabels[iBin]); + } } // --------------------- // Helper functions // --------------------- + + /// \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) + { + trackEta.clear(); + trackPhi.clear(); + trackPt.clear(); + mcParticleEta.clear(); + mcParticlePhi.clear(); + mcParticlePt.clear(); + + // if the track type is aod::JetTracks, we need to build the kd tree for the tracks + if constexpr (std::is_same_v, aod::JetTracks>) { + for (const auto& track : objects) { + if (!isTrackSelected(track)) { + continue; + } + trackEta.push_back(track.eta()); + trackPhi.push_back(track.phi()); + trackPt.push_back(track.pt()); + } + if (trackEta.size() > 0) { + delete trackTree; + trackTree = new TKDTree(trackEta.size(), 2, 1); + trackTree->SetData(0, trackEta.data()); + trackTree->SetData(1, trackPhi.data()); + trackTree->Build(); + } + } + // if the track type is aod::JetParticles, we need to build the kd tree for the mc particles + if constexpr (std::is_same_v, aod::JetParticles>) { + for (const auto& particle : objects) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (!isCharged(particle)) { + continue; + } + if (particle.pt() < trackMinPt) { + continue; + } + mcParticleEta.push_back(particle.eta()); + mcParticlePhi.push_back(particle.phi()); + mcParticlePt.push_back(particle.pt()); + } + if (mcParticleEta.size() > 0) { + delete mcParticleTree; + mcParticleTree = new TKDTree(mcParticleEta.size(), 2, 1); + mcParticleTree->SetData(0, mcParticleEta.data()); + mcParticleTree->SetData(1, mcParticlePhi.data()); + mcParticleTree->Build(); + } + } + } + /// \brief Checks if a track passes the selection criteria + /// \param track The track to be checked + /// \return true if track passes all selection criteria, false otherwise bool isTrackSelected(const auto& track) { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { @@ -135,6 +290,9 @@ struct GammaJetTreeProducer { return true; } + /// \brief Gets the stored collision index from the collision mapping + /// \param collision The collision to look up + /// \return The stored collision index, or -1 if not found int getStoredColIndex(const auto& collision) { int32_t storedColIndex = -1; @@ -144,50 +302,149 @@ struct GammaJetTreeProducer { return storedColIndex; } + /// \brief Checks if an event passes all selection criteria + /// \param collision The collision to check + /// \param clusters The EMCAL clusters in the event + /// \return true if event passes all selection criteria, false otherwise bool isEventAccepted(const auto& collision, const auto& clusters) { + mHistograms.fill(HIST("eventQA"), 0); if (collision.posZ() > mVertexCut) { return false; } + mHistograms.fill(HIST("eventQA"), 1); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return false; } + mHistograms.fill(HIST("eventQA"), 2); if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return false; } + mHistograms.fill(HIST("eventQA"), 3); if (!jetderiveddatautilities::eventEMCAL(collision)) { return false; } + mHistograms.fill(HIST("eventQA"), 4); // Check if event contains a cluster with energy > minClusterETrigger - for (auto cluster : clusters) { + for (const auto& cluster : clusters) { if (cluster.energy() > minClusterETrigger) { + mHistograms.fill(HIST("eventQA"), 5); return true; } } return false; } - double ch_iso_in_cone(const auto& cluster, aod::JetTracks const& tracks, float radius = 0.4) + /// \brief Checks if a particle is charged + /// \param particle The MC particle to check + /// \return true if particle has non-zero charge, false otherwise + bool isCharged(const auto& particle) + { + return std::abs(pdg->GetParticle(particle.pdgCode())->Charge()) >= 1.; + } + + /// \brief Calculates the charged particle isolation in a cone of given size using a pre-built kd tree + /// \param particle The particle to calculate the isolation for + /// \param radius The cone radius + /// \param mcGenIso Whether to use the mc gen particle tree (if false, use the track tree) + /// \return The charged particle isolation + template + double ch_iso_in_cone(const T& particle, float radius = 0.4, bool mcGenIso = false) { double iso = 0; - for (auto track : tracks) { - if (!isTrackSelected(track)) { - continue; + float point[2] = {particle.eta(), particle.phi()}; + std::vector indices; + + if (!mcGenIso) { + if (trackTree) { + trackTree->FindInRange(point, radius, indices); + for (const auto& index : indices) { + iso += trackPt[index]; + } + } else { + LOG(error) << "Track tree not found"; + return 0; } - // make dR function live somwhere else - float dR = jetutilities::deltaR(cluster, track); - if (dR < radius) { - iso += track.pt(); + } else { + if (mcParticleTree) { + mcParticleTree->FindInRange(point, radius, indices); + for (const auto& index : indices) { + iso += mcParticlePt[index]; + } + } else { + LOG(error) << "MC particle tree not found"; + return 0; } } return iso; } + /// \brief Calculates the charged particle density in perpendicular cones + /// \param object The reference object (cluster or jet) + /// \param tracks The tracks to check + /// \param radius The cone radius for density calculation + /// \return The average charged particle density in the perpendicular cones + template + double ch_perp_cone_rho(const T& object, float radius = 0.4, bool mcGenIso = false) + { + double ptSumLeft = 0; + double ptSumRight = 0; + + double cPhi = TVector2::Phi_0_2pi(object.phi()); + + // rotate cone left by 90 degrees + float cPhiLeft = cPhi - o2::constants::math::PIHalf; + float cPhiRight = cPhi + o2::constants::math::PIHalf; + + float pointLeft[2] = {object.eta(), cPhiLeft}; + float pointRight[2] = {object.eta(), cPhiRight}; + + std::vector indicesLeft; + std::vector indicesRight; + + if (!mcGenIso) { + if (trackTree) { + trackTree->FindInRange(pointLeft, radius, indicesLeft); + trackTree->FindInRange(pointRight, radius, indicesRight); + } else { + LOG(error) << "Track tree not found"; + return 0; + } + + for (const auto& index : indicesLeft) { + ptSumLeft += trackPt[index]; + } + for (const auto& index : indicesRight) { + ptSumRight += trackPt[index]; + } + } else { + if (mcParticleTree) { + mcParticleTree->FindInRange(pointLeft, radius, indicesLeft); + mcParticleTree->FindInRange(pointRight, radius, indicesRight); + } else { + LOG(error) << "MC particle tree not found"; + return 0; + } + for (const auto& index : indicesLeft) { + ptSumLeft += mcParticlePt[index]; + } + for (const auto& index : indicesRight) { + ptSumRight += mcParticlePt[index]; + } + } + + float rho = (ptSumLeft + ptSumRight) / (o2::constants::math::TwoPI * radius * radius); + return rho; + } + + /// \brief Fills track QA histograms for a given collision + /// \param collision The collision containing the tracks + /// \param tracks The tracks to analyze void runTrackQA(const auto& collision, aod::JetTracks const& tracks) { - for (auto track : tracks) { + for (const auto& track : tracks) { if (!isTrackSelected(track)) { continue; } @@ -197,59 +454,538 @@ struct GammaJetTreeProducer { } } - double ch_perp_cone_rho(const auto& object, aod::JetTracks const& tracks, float radius = 0.4) + /// \brief Finds the top-most copy of a particle in the decay chain (following carbon copies) + /// \param particle The particle to start from + /// \return The top-most copy of the particle + template + T iTopCopy(const T& particle) const { - double ptSumLeft = 0; - double ptSumRight = 0; + 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; + } - double cPhi = TVector2::Phi_0_2pi(object.phi()); + /// \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; + } + /// \brief Checks if a particle is a decay photon from pi0 + /// \param particle The particle to check + /// \return true if particle is a decay photon from pi0, false otherwise + template + bool isDecayPhotonPi0(const T& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + // check if it has mothers that are pi0s + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == PDG_t::kPi0) { + return true; + } + } + } + return false; + } + /// \brief Checks if a particle is a decay photon from eta + /// \param particle The particle to check + /// \return true if particle is a decay photon from eta, false otherwise + template + bool isDecayPhotonEta(const T& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + // check if it has mothers that are etas + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == 221) { + return true; + } + } + } + return false; + } + /// \brief Checks if a particle is a decay photon from other sources + /// \param particle The particle to check + /// \return true if particle is a decay photon from other sources, false otherwise + template + bool isDecayPhotonOther(const T& particle) + { + if (particle.pdgCode() == PDG_t::kGamma && particle.isPhysicalPrimary() && std::abs(particle.getGenStatusCode()) >= 90) { + // check if you find a pi0 mother or a eta mother + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == PDG_t::kPi0 || mother.pdgCode() == 221) { + return false; + } + } + return true; + } + return false; + } + /// \brief Checks if a particle is a pi0 + /// \param particle The particle to check + /// \return true if particle is a pi0, false otherwise + bool isPi0(const auto& particle) + { + if (particle.pdgCode() == PDG_t::kPi0) { + return true; + } + return false; + } - // rotate cone left by 90 degrees - float cPhiLeft = cPhi - TMath::Pi() / 2; - float cPhiRight = cPhi + TMath::Pi() / 2; + /// \brief Gets the bitmap for a MC particle that indicated what type of particle it is + /// \param particle The particle to check + /// \return A bitmap indicating the particle's origin + uint16_t getMCParticleOrigin(const auto& particle) + { + uint16_t origin = 0; + if (isPromptPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kPromptPhoton)); + } + if (isDirectPromptPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDirectPromptPhoton)); + } + if (isFragmentationPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kFragmentationPhoton)); + } + if (isDecayPhoton(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhoton)); + } + if (isDecayPhotonPi0(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhotonPi0)); + } + if (isDecayPhotonEta(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhotonEta)); + } + if (isDecayPhotonOther(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kDecayPhotonOther)); + } + if (isPi0(particle)) { + SETBIT(origin, static_cast(gjanalysis::ParticleOrigin::kPi0)); + } + return origin; + } - // loop over tracks - float dRLeft, dRRight; - for (auto track : tracks) { - if (!isTrackSelected(track)) { - continue; + /// \brief Gets the index of a mother particle with specific PDG code in the decay chain (upwards) + /// \param particle The particle to start from + /// \param mcParticles The MC particles collection + /// \param pdgCode The PDG code to search for + /// \return The index of the mother particle, or -1 if not found + template + int getIndexMotherChain(const T& particle, aod::JMcParticles const& mcParticles, int pdgCode, int depth = 0) + { + // Limit recursion depth to avoid infinite loops + if (depth > kMaxRecursionDepth) { // 100 generations should be more than enough + return -1; + } + const auto& mothers = particle.template mothers_as(); + for (const auto& mother : mothers) { + if (mother.pdgCode() == pdgCode) { + return mother.globalIndex(); + } else { + return getIndexMotherChain(mother, mcParticles, pdgCode, depth + 1); } - dRLeft = jetutilities::deltaR(object.eta(), cPhiLeft, track.eta(), track.phi()); - dRRight = jetutilities::deltaR(object.eta(), cPhiRight, track.eta(), track.phi()); + } + return -1; + } + // return recursive list of all daughter IDs + /// \brief Gets all daughter particle IDs in the decay chain + /// \param particle The particle to start from + /// \return Vector of daughter particle IDs + template + void getDaughtersInChain(const T& particle, std::vector& daughters, int depth = 0) + { + // Limit recursion depth to avoid infinite loops + if (depth > kMaxRecursionDepth) { // 100 generations should be more than enough + return; + } - if (dRLeft < radius) { - ptSumLeft += track.pt(); + if (!particle.has_daughters()) { + return; + } + + const auto& daughterParticles = particle.template daughters_as(); + for (const auto& daughter : daughterParticles) { + daughters.push_back(daughter.globalIndex()); + getDaughtersInChain(daughter, daughters, depth + 1); + } + return; + } + /// \brief Finds the first physical primary particle in the decay chain (upwards) + /// \param particle The particle to start from + /// \return The index of the first physical primary particle, or -1 if not found + template + int findPhysicalPrimaryInChain(const T& particle, int depth = 0) + { + // Limit recursion depth to avoid infinite loops + if (depth > kMaxRecursionDepth) { // 100 generations should be more than enough + return -1; + } + + // first check if current particle is physical primary + if (particle.isPhysicalPrimary()) { + return particle.globalIndex(); + } + + // check if the particle has mothers + if (!particle.has_mothers()) + return -1; + + // now get mothers + const auto mothers = particle.template mothers_as(); + if (mothers.size() == 0) + return -1; + + // get first mother + for (const auto& mother : mothers) { + int primaryIndex = findPhysicalPrimaryInChain(mother, depth + 1); + if (primaryIndex >= 0) { + return primaryIndex; } - if (dRRight < radius) { - ptSumRight += track.pt(); + break; // only check first mother + } + + return -1; + } + + /// \brief Checks if a cluster is merged from particles of a specific PDG decay to two gammas. A cluster is considered merged if the leading and subleading contribution to a cluster come from two photons that are part of a pi0 decay + /// \param cluster The cluster to check + /// \param mcParticles The MC particles collection + /// \param pdgCode The PDG code to check for + /// \return true if cluster is merged from the specified decay, false otherwise + template + bool isMergedFromPDGDecay(const T& cluster, U const& mcParticles, int pdgCode) + { + auto inducerIDs = cluster.mcParticlesIds(); + if (inducerIDs.size() < 2) { // it can not me "merged" if it has less than 2 inducers + return false; + } + + bool isMerged = false; + int motherIndex = getIndexMotherChain(mcParticles.iteratorAt(inducerIDs[0]), mcParticles, pdgCode); + if (motherIndex != -1) { + const auto& mother = mcParticles.iteratorAt(motherIndex); + + // get daughters of pi0 mother + auto daughtersMother = mother.template daughters_as(); + // check if there are two daughters that are both photons + if (daughtersMother.size() == 2) { + const auto& daughter1 = daughtersMother.iteratorAt(0); + const auto& daughter2 = daughtersMother.iteratorAt(1); + if (daughter1.pdgCode() == PDG_t::kGamma && daughter2.pdgCode() == PDG_t::kGamma) { + // get the full stack of particles that these daughters create + std::vector fullDecayChain1; + std::vector fullDecayChain2; + getDaughtersInChain(daughter1, fullDecayChain1); + getDaughtersInChain(daughter2, fullDecayChain2); + bool photon1Found = false; + bool photon2Found = false; + + // check if any of the particles in the fullDecayChain are leading or subleading in the cluster + for (const auto& particleID : fullDecayChain1) { + if (particleID == inducerIDs[0] || particleID == inducerIDs[1]) { + photon1Found = true; + } + } + for (const auto& particleID : fullDecayChain2) { + if (particleID == inducerIDs[0] || particleID == inducerIDs[1]) { + photon2Found = true; + } + } + if (photon1Found && photon2Found) { + isMerged = true; + } + } } } + return isMerged; + } - float rho = (ptSumLeft + ptSumRight) / (2 * TMath::Pi() * radius * radius); - return rho; + // determine cluster origin + /// \brief Gets the origin bitmap for a cluster + /// \param cluster The cluster to check + /// \param mcParticles The MC particles collection + /// \return A bitmap indicating the cluster's origin + template + uint16_t getClusterOrigin(const T& cluster, U const& mcParticles) + { + uint16_t origin = 0; + auto inducerIDs = cluster.mcParticlesIds(); + if (inducerIDs.size() == 0) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kUnknown)); + return origin; + } + + // loop over all inducers and print their energy + LOG(debug) << "Cluster with energy: " << cluster.energy() << " and nInducers: " << inducerIDs.size(); + LOG(debug) << "Number of stored amplitudes: " << cluster.amplitudeA().size(); + int aCounter = 0; + for (const auto& inducerID : inducerIDs) { + const auto& inducer = mcParticles.iteratorAt(inducerID); + int motherPDG = -1; + if (inducer.has_mothers()) { + motherPDG = inducer.template mothers_as()[0].pdgCode(); + } + LOG(debug) << "Inducer energy: " << inducer.energy() << " amplitude: " << cluster.amplitudeA()[aCounter] << " and PDG: " << inducer.pdgCode() << " isPhysicalPrimary: " << inducer.isPhysicalPrimary() << " motherPDG: " << motherPDG; + aCounter++; + } + + // check if leading energy contribution is from a photon + const auto& leadingParticle = mcParticles.iteratorAt(inducerIDs[0]); + LOG(debug) << "Leading particle: PDG" << leadingParticle.pdgCode(); + // leading particle primary ID + int leadingParticlePrimaryID = findPhysicalPrimaryInChain(leadingParticle); + LOG(debug) << "Leading particle primary ID: " << leadingParticlePrimaryID; + if (leadingParticlePrimaryID == -1) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kUnknown)); + return origin; + } + const auto& leadingParticlePrimary = mcParticles.iteratorAt(leadingParticlePrimaryID); + LOG(debug) << "Leading particle primary PDG: " << leadingParticlePrimary.pdgCode(); + if (leadingParticlePrimary.pdgCode() == PDG_t::kGamma) { + LOG(debug) << "Leading particle primary is a photon"; + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kPhoton)); + } + if (isPromptPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kPromptPhoton)); + LOG(debug) << "Leading particle primary is a prompt photon"; + } + if (isDirectPromptPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDirectPromptPhoton)); + LOG(debug) << "Leading particle primary is a direct prompt photon"; + } + if (isFragmentationPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kFragmentationPhoton)); + LOG(debug) << "Leading particle primary is a fragmentation photon"; + } + if (isDecayPhoton(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDecayPhoton)); + LOG(debug) << "Leading particle primary is a decay photon"; + } + if (isDecayPhotonPi0(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDecayPhotonPi0)); + LOG(debug) << "Leading particle primary is a decay photon from pi0"; + } + if (isDecayPhotonEta(leadingParticlePrimary)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kDecayPhotonEta)); + LOG(debug) << "Leading particle primary is a decay photon from eta"; + } + + // Do checks if a cluster is a merged pi0 decay + // we classify a cluster as merged pi0 if the leading and subleading contribution to a cluster come from two photons that are part of a pi0 decay + if (isMergedFromPDGDecay(cluster, mcParticles, PDG_t::kPi0)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kMergedPi0)); + LOG(debug) << "Cluster is a merged pi0"; + } + if (isMergedFromPDGDecay(cluster, mcParticles, 221)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kMergedEta)); + LOG(debug) << "Cluster is a merged eta"; + } + + // check if photon conversion + // check that leading contribution is an electron or positron + LOG(debug) << "Checking if cluster is a converted photon"; + if (std::abs(leadingParticle.pdgCode()) == PDG_t::kElectron) { + // make sure this electron is not a physicsl primary and has mothers + if (!leadingParticle.isPhysicalPrimary() && leadingParticle.has_mothers()) { + const auto mothers = leadingParticle.template mothers_as(); + if (mothers.size() > 0) { + LOG(debug) << "Got the mother"; + const auto& mother = mothers[0]; + if (mother.pdgCode() == PDG_t::kGamma && mother.has_daughters()) { + LOG(debug) << "Got the mother with PDG 22 and daughters"; + const auto& daughters = mother.template daughters_as(); + // check that mother has exactly two daughters which are e+ and e- + if (daughters.size() == 2) { + LOG(debug) << "Got the daughters"; + if ((daughters.iteratorAt(0).pdgCode() == PDG_t::kElectron && daughters.iteratorAt(1).pdgCode() == PDG_t::kPositron) || (daughters.iteratorAt(0).pdgCode() == -PDG_t::kPositron && daughters.iteratorAt(1).pdgCode() == PDG_t::kElectron)) { + SETBIT(origin, static_cast(gjanalysis::ClusterOrigin::kConvertedPhoton)); + LOG(debug) << "Cluster is a converted photon"; + } + } + } + } + } + } + // display bit origin + LOG(debug) << "Origin bits: " << std::bitset<16>(origin); + return origin; } // --------------------- // Processing functions // --------------------- // WARNING: This function always has to run first in the processing chain + /// \brief Clears collision mapping at the start of each dataframe + /// \param collisions The collisions collection void processClearMaps(aod::JetCollisions const&) { collisionMapping.clear(); + mcCollisionsMultiRecCollisions.clear(); + mcJetIndexMapping.clear(); } PROCESS_SWITCH(GammaJetTreeProducer, processClearMaps, "process function that clears all the maps in each dataframe", true); // WARNING: This function always has to run second in the processing chain - void processEvent(soa::Join::iterator const& collision, emcClusters const& clusters) + /// \brief Processes MC event matching QA + /// \param mcCollision The MC collision to process + /// \param collisions The rec collisions collection + /// \param mcgenparticles The MC particles collection + void processMCCollisionsMatching(aod::JetMcCollision const& mcCollision, soa::SmallGroups const& collisions, aod::JetParticles const& mcgenparticles) + { + if (mcCollision.weight() == 0) { + return; + } + + // determine number of rec collisions + int nRecCollisions = 0; + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 0); + for (auto const& collision : collisions) { + if (collision.posZ() > mVertexCut) { + continue; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + continue; + } + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + continue; + } + if (!jetderiveddatautilities::eventEMCAL(collision)) { + continue; + } + nRecCollisions++; + } + if (nRecCollisions == 0) { + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 3); + } + if (nRecCollisions == 1) { + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 1); + } + if (nRecCollisions > 1) { + mHistograms.fill(HIST("mcCollisionsWithRecCollisions"), 2); + } + if (nRecCollisions > 1) { + mcCollisionsMultiRecCollisions.push_back(mcCollision.globalIndex()); + } + + // loop over mcgenparticles + for (auto const& particle : mcgenparticles) { + if (!particle.isPhysicalPrimary()) { + continue; + } + if (particle.pdgCode() != PDG_t::kGamma) { + continue; + } + mHistograms.fill(HIST("numberRecCollisionsVsPhotonPt"), nRecCollisions, particle.pt()); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processMCCollisionsMatching, "Process MC event matching QA", false); + + /// \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) { if (!isEventAccepted(collision, clusters)) { return; } - eventsTable(collision.multiplicity(), collision.centrality(), collision.rho(), collision.eventSel(), collision.trackOccupancyInTimeRange(), collision.alias_raw()); + eventsTable(collision.multFT0M(), collision.centFT0M(), collision.rho(), collision.eventSel(), collision.trackOccupancyInTimeRange(), collision.alias_raw()); collisionMapping[collision.globalIndex()] = eventsTable.lastIndex(); } - PROCESS_SWITCH(GammaJetTreeProducer, processEvent, "Process event", true); + PROCESS_SWITCH(GammaJetTreeProducer, processEventData, "Process event data", true); + + using MCCol = o2::soa::Join; + + /// \brief Processes MC events and fills rec and MC event tables (disable processEventData) + /// \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&) + { + if (!isEventAccepted(collision, clusters)) { + return; + } + + // check that this event has a MC collision + if (!collision.has_mcCollision()) { + return; + } + mHistograms.fill(HIST("eventQA"), 6); + + // check if this event is not MB gap event + if (collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return; + } + mHistograms.fill(HIST("eventQA"), 7); + + // fill rec collision table + eventsTable(collision.multFT0M(), collision.centFT0M(), collision.rho(), collision.eventSel(), collision.trackOccupancyInTimeRange(), collision.alias_raw()); + + // fill collision mapping + collisionMapping[collision.globalIndex()] = eventsTable.lastIndex(); + + auto mcCollision = collision.mcCollision_as(); + + bool isMultipleAssigned = false; + // check if we are dealing with a rec collision matched to a MC collision that was matched to multiple rec collisions + if (std::find(mcCollisionsMultiRecCollisions.begin(), mcCollisionsMultiRecCollisions.end(), mcCollision.globalIndex()) != mcCollisionsMultiRecCollisions.end()) { + isMultipleAssigned = true; + } + mcEventsTable(eventsTable.lastIndex(), mcCollision.weight(), mcCollision.rho(), isMultipleAssigned); + } + PROCESS_SWITCH(GammaJetTreeProducer, processEventMC, "Process MC event MC", false); // --------------------- // Processing functions can be safely added below this line @@ -260,6 +996,11 @@ struct GammaJetTreeProducer { // an integer instead PresliceUnsorted EMCTrackPerTrack = aod::jemctrack::trackId; // Process clusters + /// \brief Processes clusters and fills cluster table + /// \param collision The collision to process + /// \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) { // event selection @@ -267,20 +1008,20 @@ struct GammaJetTreeProducer { if (storedColIndex == -1) return; - // eventsTable(collision.multiplicity(), collision.centrality(), collision.rho(), collision.eventSel(), collision.trackOccupancyInTimeRange(), collision.alias_raw()); - // collisionMapping[collision.globalIndex()] = eventsTable.lastIndex(); - // loop over tracks one time for QA runTrackQA(collision, tracks); + // build kd tree for tracks and mc particles + buildKdTree(tracks); + // loop over clusters - for (auto cluster : clusters) { + for (const auto& cluster : clusters) { // fill histograms mHistograms.fill(HIST("clusterE"), cluster.energy()); - double isoraw = ch_iso_in_cone(cluster, tracks, isoR); - double perpconerho = ch_perp_cone_rho(cluster, tracks, isoR); + double isoraw = ch_iso_in_cone(cluster, isoR, false); + double perpconerho = ch_perp_cone_rho(cluster, isoR, false); // find closest matched track double dEta = 0; @@ -290,7 +1031,7 @@ struct GammaJetTreeProducer { // do track matching auto tracksofcluster = cluster.matchedTracks_as(); - for (auto track : tracksofcluster) { + for (const auto& track : tracksofcluster) { if (!isTrackSelected(track)) { continue; } @@ -301,7 +1042,7 @@ struct GammaJetTreeProducer { continue; } else { dEta = cluster.eta() - emcTrack.etaEmcal(); - dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(emcTrack.phiEmcal(), -M_PI) - RecoDecay::constrainAngle(cluster.phi(), -M_PI), -M_PI); + dPhi = RecoDecay::constrainAngle(RecoDecay::constrainAngle(emcTrack.phiEmcal(), -o2::constants::math::PI) - RecoDecay::constrainAngle(cluster.phi(), -o2::constants::math::PI), -o2::constants::math::PI); p = track.p(); break; } @@ -310,47 +1051,262 @@ struct GammaJetTreeProducer { } // dummy loop over tracks - for (auto track : tracks) { + for (const auto& track : tracks) { mHistograms.fill(HIST("trackPt"), track.pt()); } } PROCESS_SWITCH(GammaJetTreeProducer, processClusters, "Process EMCal clusters", true); - Filter jetCuts = aod::jet::pt > jetPtMin; - // Process charged jets - void processChargedJets(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, aod::JetTracks const& tracks) + /// \brief Processes MC cluster information (rec level) + /// \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) { // event selection int32_t storedColIndex = getStoredColIndex(collision); if (storedColIndex == -1) return; - float leadingTrackPt = 0; + // loop over mcClusters + // TODO: add weights + for (const auto& mcCluster : mcClusters) { + mHistograms.fill(HIST("clusterMC_E_All"), mcCluster.energy()); + uint16_t origin = getClusterOrigin(mcCluster, mcParticles); + float leadingEnergyFraction = mcCluster.amplitudeA()[0] / mcCluster.energy(); + // Fill MC origin QA histograms + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kPhoton))) { + mHistograms.fill(HIST("clusterMC_E_Photon"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_Photon"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kPromptPhoton))) { + mHistograms.fill(HIST("clusterMC_E_PromptPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_PromptPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDirectPromptPhoton))) { + mHistograms.fill(HIST("clusterMC_E_DirectPromptPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DirectPromptPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kFragmentationPhoton))) { + mHistograms.fill(HIST("clusterMC_E_FragmentationPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_FragmentationPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDecayPhoton))) { + mHistograms.fill(HIST("clusterMC_E_DecayPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DecayPhoton"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDecayPhotonPi0))) { + mHistograms.fill(HIST("clusterMC_E_DecayPhotonPi0"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DecayPhotonPi0"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kDecayPhotonEta))) { + mHistograms.fill(HIST("clusterMC_E_DecayPhotonEta"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_DecayPhotonEta"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kMergedPi0))) { + mHistograms.fill(HIST("clusterMC_E_MergedPi0"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_MergedPi0"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kMergedEta))) { + mHistograms.fill(HIST("clusterMC_E_MergedEta"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_MergedEta"), mcCluster.m02()); + } + if (origin & (1 << static_cast(gjanalysis::ClusterOrigin::kConvertedPhoton))) { + mHistograms.fill(HIST("clusterMC_E_ConvertedPhoton"), mcCluster.energy()); + mHistograms.fill(HIST("clusterMC_m02_ConvertedPhoton"), mcCluster.m02()); + } + // fill table + gammaMCInfosTable(storedColIndex, origin, leadingEnergyFraction); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processClustersMCInfo, "Process MC cluster information", false); + + /// \brief Fills the charged jet table with jet information and calculates jet properties + /// \param storedColIndex The stored collision index + /// \param jet The jet to process + /// \param tracks The tracks collection + template + void fillChargedJetTable(int32_t storedColIndex, T const& jet, U const& /*tracks*/) + { + if (jet.pt() < jetPtMin) { + return; + } ushort nconst = 0; + float leadingTrackPt = 0; + for (const auto& constituent : jet.template tracks_as()) { + mHistograms.fill(HIST("chjetpt_vs_constpt"), jet.pt(), constituent.pt()); + nconst++; + if (constituent.pt() > leadingTrackPt) { + leadingTrackPt = constituent.pt(); + } + } + double perpconerho = ch_perp_cone_rho(jet, perpConeJetR, false); + chargedJetsTable(storedColIndex, jet.pt(), jet.eta(), jet.phi(), jet.r(), jet.energy(), jet.mass(), jet.area(), leadingTrackPt, perpconerho, nconst); + mHistograms.fill(HIST("chjetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + mHistograms.fill(HIST("chjetPt"), jet.pt()); + } + + 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) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; // loop over charged jets - for (auto jet : chargedJets) { - if (jet.pt() < jetPtMin) + for (const auto& jet : chargedJets) { + fillChargedJetTable(storedColIndex, jet, tracks); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processChargedJetsData, "Process charged jets", true); + + Preslice ParticlesPerMCCollisions = aod::jmcparticle::mcCollisionId; + /// \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&) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; + + if (!collision.has_mcCollision()) { + return; + } + + // only storing MC particles if we found a reconstructed collision + auto particlesPerMcCollision = mcgenparticles.sliceBy(ParticlesPerMCCollisions, collision.mcCollisionId()); + + // build kd tree for mc particles + buildKdTree(particlesPerMcCollision); + + // Now we want to store every pi0 and every prompt photon that we find on generator level + for (const auto& particle : particlesPerMcCollision) { + // only store particles above a given threshold + if (particle.pt() < minMCGenPt) { + continue; + } + // Test if a particle is a physical primary according to the following definition: + // Particles produced in the collision including products of strong and + // electromagnetic decay and excluding feed-down from weak decays of strange + // particles. + if (!(particle.isPhysicalPrimary() || particle.pdgCode() == PDG_t::kPi0)) { continue; - nconst = 0; - leadingTrackPt = 0; - // loop over constituents - for (auto& constituent : jet.template tracks_as()) { - mHistograms.fill(HIST("chjetpt_vs_constpt"), jet.pt(), constituent.pt()); - nconst++; - if (constituent.pt() > leadingTrackPt) { - leadingTrackPt = constituent.pt(); - } } - // calculate perp cone rho - double perpconerho = ch_perp_cone_rho(jet, tracks, perpConeJetR); - mHistograms.fill(HIST("chjetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); - chargedJetsTable(storedColIndex, jet.pt(), jet.eta(), jet.phi(), jet.r(), jet.energy(), jet.mass(), jet.area(), leadingTrackPt, perpconerho, nconst); - // fill histograms - mHistograms.fill(HIST("chjetPt"), jet.pt()); + // only store photons and pi0s in mcgen stack + if (particle.pdgCode() != PDG_t::kPi0 && particle.pdgCode() != PDG_t::kGamma) { + continue; + } + // check the origin of the particle + uint16_t origin = getMCParticleOrigin(particle); + double mcIsolation = ch_iso_in_cone(particle, isoR, true); + mcParticlesTable(storedColIndex, particle.energy(), particle.eta(), particle.phi(), particle.pt(), particle.pdgCode(), mcIsolation, origin); + + // fill mc gen trigger particle histograms + mHistograms.fill(HIST("mcGenTrigger_E"), particle.energy()); + mHistograms.fill(HIST("mcGenTrigger_Eta"), particle.eta()); + mHistograms.fill(HIST("mcGenTrigger_Phi"), particle.phi()); + mHistograms.fill(HIST("mcGenTrigger_Pt"), particle.pt()); + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kPromptPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_PromptPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDirectPromptPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_DirectPromptPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kFragmentationPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_FragmentationPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhoton))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhoton"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonPi0))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhotonPi0"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonEta))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhotonEta"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kDecayPhotonOther))) { + mHistograms.fill(HIST("mcGenTrigger_E_DecayPhotonOther"), particle.energy()); + } + if (origin & (1 << static_cast(gjanalysis::ParticleOrigin::kPi0))) { + mHistograms.fill(HIST("mcGenTrigger_E_Pi0"), particle.energy()); + } + } + } + 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 ) + 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 mcCollisions The MC collisions collection + void processChargedJetsMCP(soa::Join::iterator const& collision, soa::Filtered> const& chargedJets, MCCol const&) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; + // loop over charged jets + if (!collision.has_mcCollision()) { + return; + } + int localIndex = 0; + auto pjetsPerMcCollision = chargedJets.sliceBy(PJetsPerMCCollisions, collision.mcCollisionId()); + for (const auto& pjet : pjetsPerMcCollision) { + // fill MC particle level jet table + float perpconerho = ch_perp_cone_rho(pjet, perpConeJetR, true); + mcJetsTable(storedColIndex, pjet.pt(), pjet.eta(), pjet.phi(), pjet.r(), pjet.energy(), pjet.mass(), pjet.area(), perpconerho); + mcJetIndexMapping[pjet.globalIndex()] = localIndex; + localIndex++; + mHistograms.fill(HIST("mcpJetPt"), pjet.pt()); } } - PROCESS_SWITCH(GammaJetTreeProducer, processChargedJets, "Process charged jets", true); + PROCESS_SWITCH(GammaJetTreeProducer, processChargedJetsMCP, "Process MC particle level jets", false); + + // NOTE: It is important that this function runs after the processChargedJetsMCP function (where the mc jet index mapping is built) + using JetMCPTable = soa::Filtered>; + Filter jetCutsMCD = aod::jet::pt > jetPtMin; + /// \brief Processes MC detector level charged jets and fills jet matching information + /// \param collision The collision to process + /// \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*/) + { + // event selection + int32_t storedColIndex = getStoredColIndex(collision); + if (storedColIndex == -1) + return; + // loop over charged jets + for (const auto& jet : chargedJets) { + fillChargedJetTable(storedColIndex, jet, tracks); + + // Fill Matching information + int iLocalIndexGeo = -1; + int iLocalIndexPt = -1; + // We will always store the information for both in our tree + if (jet.has_matchedJetGeo()) { + const auto& pjet = jet.template matchedJetGeo_first_as(); + iLocalIndexGeo = mcJetIndexMapping[pjet.globalIndex()]; + mHistograms.fill(HIST("mcdJetPtVsTrueJetPtMatchingGeo"), jet.pt(), pjet.pt()); + } + if (jet.has_matchedJetPt()) { + const auto& pjet = jet.template matchedJetPt_first_as(); + iLocalIndexPt = mcJetIndexMapping[pjet.globalIndex()]; + mHistograms.fill(HIST("mcdJetPtVsTrueJetPtMatchingPt"), jet.pt(), pjet.pt()); + } + chJetMCInfosTable(storedColIndex, iLocalIndexGeo, iLocalIndexPt); + } + } + PROCESS_SWITCH(GammaJetTreeProducer, processChargedJetsMCD, "Process MC detector level jets", false); }; + WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { WorkflowSpec workflow{ diff --git a/PWGJE/Tasks/hadronPhotonCorrelation.cxx b/PWGJE/Tasks/hadronPhotonCorrelation.cxx index 70850130b5c..bd6496f2296 100644 --- a/PWGJE/Tasks/hadronPhotonCorrelation.cxx +++ b/PWGJE/Tasks/hadronPhotonCorrelation.cxx @@ -16,40 +16,36 @@ /// for hadrons and photons to compute angular correlations /// -#include -#include -#include -#include +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.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/Configurable.h" #include "Framework/Expressions.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" +#include "Framework/HistogramRegistry.h" #include "Framework/HistogramSpec.h" -#include "Framework/Configurable.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include -#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 "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CommonConstants/MathConstants.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/Core/JetUtilities.h" - -#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" -#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::aod; diff --git a/PWGJE/Tasks/hfFragmentationFunction.cxx b/PWGJE/Tasks/hfFragmentationFunction.cxx index 9100e78391a..b3790cda8cd 100644 --- a/PWGJE/Tasks/hfFragmentationFunction.cxx +++ b/PWGJE/Tasks/hfFragmentationFunction.cxx @@ -16,36 +16,36 @@ /// /// The task store data relevant to the calculation of hadronization observables radial /// profile and/or jet momentum fraction for charmed hadrons -#include -#include -#include "TVector3.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +// +#include "PWGHF/Core/DecayChannels.h" -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "TVector3.h" +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetUtilities.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -327,7 +327,7 @@ struct HfFragmentationFunction { // reflection information for storage: D0 = +1, D0bar = -1, neither = 0 int matchedFrom = 0; - int decayChannel = 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; + int decayChannel = o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; int selectedAs = 0; if (mcdd0cand.flagMcMatchRec() == decayChannel) { // matched to D0 on truth level @@ -418,7 +418,7 @@ struct HfFragmentationFunction { // reflection information for storage: D0 = +1, D0bar = -1, neither = 0 int matchedFrom = 0; - int decayChannel = 1 << aod::hf_cand_2prong::DecayType::D0ToPiK; + int decayChannel = o2::hf_decay::hf_cand_2prong::DecayChannelMain::D0ToPiK; int selectedAs = 0; if (mcdd0cand.flagMcMatchRec() == decayChannel) { // matched to D0 on truth level diff --git a/PWGJE/Tasks/jetBackgroundAnalysis.cxx b/PWGJE/Tasks/jetBackgroundAnalysis.cxx index ece360113ec..8e93fc305d0 100644 --- a/PWGJE/Tasks/jetBackgroundAnalysis.cxx +++ b/PWGJE/Tasks/jetBackgroundAnalysis.cxx @@ -14,33 +14,29 @@ /// \author Aimeric Landou /// \author Nima Zardoshti -#include -#include -#include -#include -#include "TLorentzVector.h" +#include "RecoDecay.h" + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::framework; @@ -103,7 +99,7 @@ struct JetBackgroundAnalysisTask { } 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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); template bool trackIsInJet(TTracks const& track, TJets const& jet) @@ -132,7 +128,7 @@ struct JetBackgroundAnalysisTask { } } } - registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles randomConePt = 0; @@ -145,7 +141,7 @@ struct JetBackgroundAnalysisTask { } } } - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); // removing the leading jet from the random cone if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet @@ -173,7 +169,7 @@ struct JetBackgroundAnalysisTask { } } } - registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles, removing tracks from 2 leading jets double randomConePtWithoutOneLeadJet = 0; @@ -194,8 +190,8 @@ struct JetBackgroundAnalysisTask { } } } - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets"), collision.centrality(), randomConePtWithoutOneLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), collision.centrality(), randomConePtWithoutTwoLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets"), collision.centFT0M(), randomConePtWithoutOneLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), collision.centFT0M(), randomConePtWithoutTwoLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); } void processRho(soa::Filtered>::iterator const& collision, soa::Filtered const& tracks) @@ -212,11 +208,11 @@ struct JetBackgroundAnalysisTask { nTracks++; } } - registry.fill(HIST("h2_centrality_ntracks"), collision.centrality(), nTracks); + registry.fill(HIST("h2_centrality_ntracks"), collision.centFT0M(), nTracks); registry.fill(HIST("h2_ntracks_rho"), nTracks, collision.rho()); registry.fill(HIST("h2_ntracks_rhom"), nTracks, collision.rhoM()); - registry.fill(HIST("h2_centrality_rho"), collision.centrality(), collision.rho()); - registry.fill(HIST("h2_centrality_rhom"), collision.centrality(), collision.rhoM()); + registry.fill(HIST("h2_centrality_rho"), collision.centFT0M(), collision.rho()); + registry.fill(HIST("h2_centrality_rhom"), collision.centFT0M(), collision.rhoM()); } PROCESS_SWITCH(JetBackgroundAnalysisTask, processRho, "QA for rho-area subtracted jets", false); diff --git a/PWGJE/Tasks/jetChCorr.cxx b/PWGJE/Tasks/jetChCorr.cxx index 43486b4567c..4311fc5c7d8 100644 --- a/PWGJE/Tasks/jetChCorr.cxx +++ b/PWGJE/Tasks/jetChCorr.cxx @@ -14,38 +14,35 @@ /// Mriganka Mouli Mondal originally modified from Nima Zardoshti // -#include -#include -#include -#include -#include -#include -#include - -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.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 "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include // #include "PWGLF/DataModel/LFResonanceTables.h" -#include "Framework/runDataProcessing.h" +#include +#include +#include +#include +#include using namespace std; using namespace o2; diff --git a/PWGJE/Tasks/jetChargedV2.cxx b/PWGJE/Tasks/jetChargedV2.cxx index 6133cc19a27..4c5cd82ed25 100644 --- a/PWGJE/Tasks/jetChargedV2.cxx +++ b/PWGJE/Tasks/jetChargedV2.cxx @@ -13,70 +13,60 @@ /// \file jetChargedV2.cxx /// \brief This file contains the implementation for the Charged Jet v2 analysis in the ALICE experiment -#include -#include -#include -#include -#include -#include -#include -#include -#include -// o2Physics includes. -#include "CommonConstants/MathConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPMagField.h" - -#include "Framework/runDataProcessing.h" - -#include "Common/DataModel/FT0Corrected.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/CCDB/ctpRateFetcher.h" - -//< evt pln .h >// -#include "Framework/ASoAHelpers.h" -#include "Framework/RunningWorkflowInfo.h" -#include "Framework/StaticFor.h" +#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 "Common/DataModel/Qvectors.h" #include "Common/Core/EventPlaneHelper.h" -//< evt pln .h | end >// - -// o2 includes. -#include "DetectorsCommonDataFormats/AlignParam.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" +#include "Common/DataModel/EventSelection.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/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/StaticFor.h" +#include "Framework/runDataProcessing.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "EventFiltering/filterTables.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; struct JetChargedV2 { + using McParticleCollision = soa::Join; + using ChargedMCDMatchedJets = soa::Join; + using ChargedMCPMatchedJets = soa::Join; + HistogramRegistry registry; HistogramRegistry histosQA{"histosQA", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; Configurable eventSelections{"eventSelections", "sel8", "choose event selection"}; Configurable trackSelections{"trackSelections", "globalTracks", "set track selections"}; - Configurable> jetRadii{"jetRadii", std::vector{0.4}, "jet resolution parameters"}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; @@ -95,6 +85,7 @@ struct JetChargedV2 { Configurable jetPtMax{"jetPtMax", 200.0, "maximum pT acceptance for jets"}; Configurable jetEtaMin{"jetEtaMin", -0.9, "minimum eta acceptance for jets"}; Configurable jetEtaMax{"jetEtaMax", 0.9, "maximum eta acceptance for jets"}; + Configurable nBinsEta{"nBinsEta", 200, "number of bins for eta axes"}; Configurable jetRadius{"jetRadius", 0.2, "jet resolution parameters"}; 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 "}; @@ -104,6 +95,7 @@ struct JetChargedV2 { Configurable randomConeR{"randomConeR", 0.4, "size of random Cone for estimating background fluctuations"}; 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)"}; + //=====================< evt pln >=====================// Configurable cfgAddEvtSel{"cfgAddEvtSel", true, "event selection"}; Configurable> cfgnMods{"cfgnMods", {2}, "Modulation of interest"}; @@ -124,6 +116,17 @@ struct JetChargedV2 { int refAId; int refBId; + //=====================< jetSpectraConfig to this analysis >=====================// + Configurable pTHatExponent{"pTHatExponent", 6.0, "exponent of the event weight for the calculation of pTHat"}; + 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 pTHatAbsoluteMin{"pTHatAbsoluteMin", -99.0, "minimum value of pTHat"}; + 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 checkMcCollisionIsMatched{"checkMcCollisionIsMatched", false, "0: count whole MCcollisions, 1: select MCcollisions which only have their correspond collisions"}; + 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 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 cfgChkFitQuality{"cfgChkFitQuality", false, "check fit quality"}; + template int getDetId(const T& name) { @@ -148,7 +151,7 @@ struct JetChargedV2 { return 0; } } - //=====================< evt pln | end >=====================// + //=====================< evt p615ln | end >=====================// Configurable selectedJetsRadius{"selectedJetsRadius", 0.2, "resolution parameter for histograms without radius"}; @@ -160,7 +163,13 @@ struct JetChargedV2 { double evtnum = 0; double accptTrack = 0; double fitTrack = 0; + float collQvecAmpDetId = 1e-8; TH1F* hPtsumSumptFit = nullptr; + TH1F* hPtsumSumptFitMCP = nullptr; + TF1* fFitModulationV2v3 = 0x0; + TF1* fFitModulationV2v3P = 0x0; + TH1F* hPtsumSumptFitRM = nullptr; + TF1* fFitModulationRM = 0x0; void init(o2::framework::InitContext&) { @@ -173,6 +182,12 @@ struct JetChargedV2 { refAId = 4; refBId = 5; } + auto jetRadiiBins = (std::vector)jetRadii; + if (jetRadiiBins.size() > 1) { + jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + (std::abs(jetRadiiBins[jetRadiiBins.size() - 1] - jetRadiiBins[jetRadiiBins.size() - 2]))); + } else { + jetRadiiBins.push_back(jetRadiiBins[jetRadiiBins.size() - 1] + 0.1); + } auto jetPtTemp = 0.0; jetPtBins.push_back(jetPtTemp); @@ -200,8 +215,14 @@ struct JetChargedV2 { } std::sort(jetPtBinsRhoAreaSub.begin(), jetPtBinsRhoAreaSub.end()); - AxisSpec jetPtAxis = {jetPtBins, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec jetPtAxisRhoAreaSub = {jetPtBinsRhoAreaSub, "#it{p}_{T} (GeV/#it{c})"}; + //< MCAxis >// + 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"}; AxisSpec axisPt = {40, 0.0, 4.0}; AxisSpec axisEta = {32, -0.8, 0.8}; @@ -211,157 +232,208 @@ struct JetChargedV2 { eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); - //< Track efficiency plots >// - 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, {{120, -10., 110.}, {4, 0.0, 4.0}}}); - registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, {200, 0., 200.}}}); - registry.add("h2_centrality_track_eta", "centrality vs track #eta; centrality; #eta_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {100, -1.0, 1.0}}}); - registry.add("h2_centrality_track_phi", "centrality vs track #varphi; centrality; #varphi_{track}", {HistType::kTH2F, {{1200, -10.0, 110.0}, {160, -1.0, 7.}}}); - registry.add("h2_centrality_track_energy", "centrality vs track energy; centrality; Energy GeV", {HistType::kTH2F, {{120, -10., 110.}, {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}}}); - - //< \sigma p_T at local rho test plot > - registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); - registry.add("h_accept_Track_init", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); - registry.add("h_accept_Track_Fit", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); - - registry.add("h_ptsum_collnum", "ptsum collnum;collnum;entries", {HistType::kTH1F, {{40, 0.0, 40}}}); - registry.add("h_ptsum_sumpt", "jet sumpt;sum p_{T};entries", {HistType::kTH1F, {{40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_phi_track_eta", "phi vs track eta; #eta (GeV/#it{c}); #varphi", {HistType::kTH2F, {{100, -1.0, 1.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_centrality_phi_w_pt", "centrality vs jet #varphi; centrality; entries", {HistType::kTH2F, {{100, 0.0, 100.0}, {40, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_evtnum_phi_w_pt", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTH2F, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}}}); - - //< fit quality >// - registry.add("h_PvalueCDF_CombinFit", "cDF #chi^{2}; entries", {HistType::kTH1F, {{50, 0, 1}}}); - registry.add("h2_PvalueCDFCent_CombinFit", "p-value cDF vs centrality; centrality; p-value", {HistType::kTH2F, {{100, 0, 100}, {40, 0, 1}}}); - registry.add("h2_Chi2Cent_CombinFit", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 5}}}); - registry.add("h2_PChi2_CombinFit", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); - - registry.add("Thn_PChi2_CombinFitCent", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTHnSparseF, {{100, 0.0, 100.0}, {100, 0, 1}, {100, 0, 5}}}); - registry.add("h2_PChi2_CombinFitA", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); - registry.add("h2_PChi2_CombinFitB", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); - - registry.add("h_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_evtnum_NTrk", "eventNumber vs Number of Track ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - - registry.add("Thn_evtnum_phi_centrality", "eventNumber vs jet #varphi; #eventNumber; entries", {HistType::kTHnSparseF, {{1000, 0.0, 1000}, {40, 0., o2::constants::math::TwoPI}, {100, 0.0, 100.0}}}); - - registry.add("h2_evt_fitpara", "event vs fit parameter; evtnum; parameter", {HistType::kTH2F, {cfgAxisEvtfit, {5, 0., 5}}}); - - registry.add("h_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); - registry.add("h_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); - - registry.add("h_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparav2obs_evtnum", "fitparameter v2obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - registry.add("h_fitparav3obs_evtnum", "fitparameter v3obs vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); - - registry.add("h2_fitParaZero_cent", "#varphi vs #rho(#varphi); #cent; #fitParameter[0] ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rhophi", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho_{ch}(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); - registry.add("h2_phi_rholocal_cent", "#varphi vs #rho(#varphi); #cent; #rho(#varphi) ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); - registry.add("h3_centrality_localrho_phi", "centrality; #rho_{local}; #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); - - registry.add("h3_centrality_rhovsphi_phi", "centrality; #rho(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{120, -10.0, 110.0}, {200, 0.0, 200.0}, {40, 0., o2::constants::math::TwoPI}}}); - //< \sigma p_T at local rho test plot | end > - - registry.add("h_jet_pt_rhoareasubtracted", "jet pT rhoareasubtracted;#it{p}_{T,jet} (GeV/#it{c}); entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - - registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs #it{p}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{1200, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - - registry.add("leadJetPt", "leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); - registry.add("leadJetPhi", "leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); - registry.add("leadJetEta", "leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); - - //< RC test plots >// - registry.add("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - registry.add("h2_centrality_deltapT_RandomCornPhi_RCprocess_rhorandomconewithoutleadingjet", "#it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH2F, {{400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - - registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); - //< bkg sub plot | end >// - //< median rho >// - registry.add("h_jet_pt_in_plane_v2", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v2", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_in_plane_v3", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v3", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - - registry.add("h2_centrality_jet_pt_in_plane_v2", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v2", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_in_plane_v3", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v3", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - //< rho(phi) >// - registry.add("h_jet_pt_inclusive_v2_rho", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - registry.add("h_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); - - registry.add("h2_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - registry.add("h2_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); - - //=====================< evt pln plot >=====================// - AxisSpec axisCent{cfgAxisCent, "centrality"}; - AxisSpec axisQvec{cfgAxisQvec, "Q"}; - AxisSpec axisQvecF{cfgAxisQvecF, "Q"}; - - AxisSpec axisEvtPl{360, -constants::math::PI, constants::math::PI}; - - histosQA.add("histCent", "Centrality TrkProcess", HistType::kTH1F, {axisCent}); - - for (uint i = 0; i < cfgnMods->size(); i++) { - histosQA.add(Form("histQvecUncorV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add(Form("histQvecRectrV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add(Form("histQvecTwistV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); - histosQA.add(Form("histQvecFinalV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); - - histosQA.add(Form("histEvtPlUncorV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add(Form("histEvtPlRectrV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add(Form("histEvtPlTwistV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add(Form("histEvtPlFinalV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + 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}}}); + + if (doprocessInOutJetV2 || doprocessInOutJetV2MCD || doprocessSigmaPt || doprocessSigmaPtMCD) { + //=====================< evt pln plot >=====================// + AxisSpec axisCent{cfgAxisCent, "centrality"}; + AxisSpec axisQvec{cfgAxisQvec, "Q"}; + AxisSpec axisQvecF{cfgAxisQvecF, "Q"}; + AxisSpec axisEvtPl{360, -constants::math::PI, constants::math::PI}; + for (uint i = 0; i < cfgnMods->size(); i++) { + histosQA.add(Form("histQvecUncorV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecRectrV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecTwistV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvecF, axisQvecF, axisCent}}); + histosQA.add(Form("histQvecFinalV%d", cfgnMods->at(i)), "", {HistType::kTH3F, {axisQvec, axisQvec, axisCent}}); + + histosQA.add(Form("histEvtPlUncorV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRectrV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlTwistV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlFinalV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + + histosQA.add(Form("histEvtPlRes_SigRefAV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRes_SigRefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + histosQA.add(Form("histEvtPlRes_RefARefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + } + histosQA.add("histCent", "Centrality TrkProcess", HistType::kTH1F, {axisCent}); + //< Track efficiency plots >// + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + //< fit quality >// + registry.add("h_PvalueCDF_CombinFit", "cDF #chi^{2}; entries", {HistType::kTH1F, {{50, 0, 1}}}); + registry.add("h2_PvalueCDFCent_CombinFit", "p-value cDF vs centrality; centrality; p-value", {HistType::kTH2F, {{100, 0, 100}, {40, 0, 1}}}); + registry.add("h2_Chi2Cent_CombinFit", "Chi2 vs centrality; centrality; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 100}, {100, 0, 5}}}); + registry.add("h2_PChi2_CombinFit", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); + + registry.add("h2_PChi2_CombinFitA", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); + registry.add("h2_PChi2_CombinFitB", "p-value vs #tilde{#chi^{2}}; p-value; #tilde{#chi^{2}}", {HistType::kTH2F, {{100, 0, 1}, {100, 0, 5}}}); + + registry.add("h_evtnum_NTrk", "eventNumber vs Number of Track ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + + registry.add("h_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + + registry.add("h2_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); + registry.add("h2_rholocal_cent", "#varphi vs #rho(#varphi); #cent; #rho(#varphi) ", {HistType::kTH2F, {{100, 0., 100}, {210, -10.0, 200.0}}}); + //< \sigma p_T at local rho test plot | end > + + registry.add("h_jet_pt_rhoareasubtracted", "jet pT rhoareasubtracted;#it{p}_{T,jet} (GeV/#it{c}); entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("leadJetPt", "leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("leadJetPhi", "leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("leadJetEta", "leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + + //< RC test plots >// + registry.add("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + + registry.add("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + //< bkg sub plot | end >// + //< median rho >// + registry.add("h_jet_pt_in_plane_v2", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v2", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_in_plane_v3", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v3", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("h2_centrality_jet_pt_in_plane_v2", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_out_of_plane_v2", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + //< rho(phi) >// + registry.add("h_jet_pt_inclusive_v2_rho", "jet pT;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("h2_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + + registry.add("h2_centrality_jet_pt_rhoareasubtracted", "centrality vs. jet pT;centrality; #it{p}_{T,jet} (GeV/#it{c}); counts", {HistType::kTH2F, {centralityAxis, jetPtAxisRhoAreaSub}}); + registry.add("h2_centrality_jet_eta_rhoareasubtracted", "centrality vs. jet eta;centrality; #eta; counts", {HistType::kTH2F, {centralityAxis, jetEtaAxis}}); + registry.add("h2_centrality_jet_phi_rhoareasubtracted", "centrality vs. jet phi;centrality; #varphi; counts", {HistType::kTH2F, {centralityAxis, phiAxis}}); + registry.add("h2_jet_pt_track_pt_rhoareasubtracted", "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, {jetPtAxisRhoAreaSub, trackPtAxis}}); + } - histosQA.add(Form("histEvtPlRes_SigRefAV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add(Form("histEvtPlRes_SigRefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); - histosQA.add(Form("histEvtPlRes_RefARefBV%d", cfgnMods->at(i)), "", {HistType::kTH2F, {axisEvtPl, axisCent}}); + if (doprocessSigmaPtMCP) { + 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, {jetEtaAxis}}); + registry.add("h_jet_phi_part_rhoareasubtracted", "part jet #varphi;#varphi^{part}; counts", {HistType::kTH1F, {phiAxis}}); + + registry.add("leadJetPtMCP", "MCP leadJet Pt ", {HistType::kTH1F, {{200, 0., 200.0}}}); + registry.add("leadJetPhiMCP", "MCP leadJet constituent #phi ", {HistType::kTH1F, {{80, -1.0, 7.}}}); + registry.add("leadJetEtaMCP", "MCP leadJet constituent #eta ", {HistType::kTH1F, {{100, -1.0, 1.0}}}); + + registry.add("h2_mcp_phi_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{40, 0., o2::constants::math::TwoPI}, {210, -10.0, 200.0}}}); + registry.add("h2_mcp_centrality_rholocal", "#varphi vs #rho(#varphi); #varphi - #Psi_{EP,2}; #rho(#varphi) ", {HistType::kTH2F, {{120, -10.0, 110.0}, {210, -10.0, 200.0}}}); + registry.add("h_mcp_jet_pt_rholocal", "jet pT rholocal;#it{p}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + //< MCP fit test >// + registry.add("h_mcp_evtnum_centrlity", "eventNumber vs centrality ; #eventNumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_v2obs_centrality", "fitparameter v2obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_mcp_v3obs_centrality", "fitparameter v3obs vs centrality ; #centrality", {HistType::kTProfile, {cfgAxisVnCent}}); + registry.add("h_mcp_fitparaRho_evtnum", "fitparameter #rho_{0} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparaPsi2_evtnum", "fitparameter #Psi_{2} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + registry.add("h_mcp_fitparaPsi3_evtnum", "fitparameter #Psi_{3} vs evtnum ; #eventnumber", {HistType::kTH1F, {{1000, 0.0, 1000}}}); + + registry.add("h_mcp_jet_pt_in_plane_v2_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_out_of_plane_v2_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_in_plane_v3_rho", "jet pT;#it{p}^{in-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + registry.add("h_mcp_jet_pt_out_of_plane_v3_rho", "jet pT;#it{p}^{out-of-plane}_{T,jet} (GeV/#it{c});entries", {HistType::kTH1F, {jetPtAxisRhoAreaSub}}); + + registry.add("h2_mcp_centrality_jet_pt_in_plane_v2_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v2_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_in_plane_v3_rho", "centrality vs #it{p}^{in-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + registry.add("h2_mcp_centrality_jet_pt_out_of_plane_v3_rho", "centrality vs #it{p}^{out-of-plane}_{T,jet}; centrality; #it{p}_{T,jet} (GeV/#it{c})", {HistType::kTH2F, {{120, -10.0, 110.0}, jetPtAxisRhoAreaSub}}); + + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphi", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}; #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + registry.add("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet", "centrality; #it{p}_{T,random cone} - #it{area, random cone} * #it{rho}(#varphi); #Delta#varphi_{jet}", {HistType::kTH3F, {{100, 0.0, 100.0}, {400, -200.0, 200.0}, {100, 0., o2::constants::math::TwoPI}}}); + + registry.add("h_mcColl_counts_areasub", " number of mc events; event status; entries", {HistType::kTH1F, {{10, 0, 10}}}); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(1, "allMcColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(2, "vertexZ"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(3, "noRecoColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(4, "splitColl"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(5, "recoEvtSel"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(6, "centralitycut"); + registry.get(HIST("h_mcColl_counts_areasub"))->GetXaxis()->SetBinLabel(7, "occupancycut"); + registry.add("h_mcColl_rho", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, 0.0, 500.0}}}); + + //< \sigma p_T at local rho test plot > + registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(1, "acceptTrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(2, "acceptTrkInFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(3, "beforeSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(4, "afterSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(5, "getNtrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(6, "getNtrkMCP"); } - //=====================< evt pln plot | end >=====================// - } - Preslice jetsPerJCollision = o2::aod::jet::collisionId; - Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; + if (doprocessJetsMatchedSubtracted) { + registry.add("h_mc_collisions_matched", "mc collisions status;event status;entries", {HistType::kTH1F, {{5, 0.0, 5.0}}}); + registry.add("h_mcd_events_matched", "mcd event status;event status;entries", {HistType::kTH1F, {{6, 0.0, 6.0}}}); + registry.add("h_mc_rho_matched", "mc collision rho;#rho (GeV/#it{c}); counts", {HistType::kTH1F, {{500, -100.0, 500.0}}}); + registry.add("h_accept_Track_Match", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_in_rhoareasubtracted_mcdetaconstraint", "corr pT mcd vs. corr cpT mcp in-plane;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}); + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_in_rhoareasubtracted_mcpetaconstraint", "corr pT mcd vs. corr cpT mcp in-plane;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}); + registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_in_rhoareasubtracted", "jet mcp corr pT vs. corr delta pT / jet mcp corr pt in-plane;#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}}}); + registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_in_rhoareasubtracted", "jet mcd corr pT vs. corr delta pT / jet mcd corr pt in-plane;#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}}}); + registry.add("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo_in_rhoareasubtracted", "jet mcp corr pT vs. jet mcd corr pT / jet mcp corr pt in-plane;#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}}}); + + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_out_rhoareasubtracted_mcdetaconstraint", "corr pT mcd vs. corr cpT mcp out-of-plane;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}); + registry.add("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_out_rhoareasubtracted_mcpetaconstraint", "corr pT mcd vs. corr cpT mcp out-of-plane;#it{p}_{T,jet}^{mcd} (GeV/#it{c});#it{p}_{T,jet}^{mcp} (GeV/#it{c})", {HistType::kTH2F, {jetPtAxisRhoAreaSub, jetPtAxisRhoAreaSub}}); + registry.add("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_out_rhoareasubtracted", "jet mcp corr pT vs. corr delta pT / jet mcp corr pt out-of-plane;#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}}}); + registry.add("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_out_rhoareasubtracted", "jet mcd corr pT vs. corr delta pT / jet mcd corr pt out-of-plane;#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}}}); + registry.add("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo_out_rhoareasubtracted", "jet mcp corr pT vs. jet mcd corr pT / jet mcp corr pt out-of-plane;#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}}}); + } + registry.add("h_accept_Track", "all and accept track;Track;entries", {HistType::kTH1F, {{10, 0.0, 10.0}}}); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(1, "acceptTrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(2, "acceptTrkInFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(3, "beforeSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(4, "afterSumptFit"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(5, "getNtrk"); + registry.get(HIST("h_accept_Track"))->GetXaxis()->SetBinLabel(6, "getNtrkMCP"); + + //< track test >// + 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, phiAxis}}); + } 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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); + Preslice tracksPerJCollision = o2::aod::jtrack::collisionId; + Preslice mcdjetsPerJCollision = o2::aod::jet::collisionId; + PresliceUnsorted> collisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; - template - bool isAcceptedJet(U const& jet) + template + bool isAcceptedJet(TJets const& jet, bool mcLevelIsParticleLevel = false) { - double jetAreaFractionMinCfgMin = -98.0; - double jetAreaFractionMinCfgMax = 9998.0; - if (jetAreaFractionMin > jetAreaFractionMinCfgMin) { + double jetAreaFractionMinAcc = -98.0; + double leadingConstituentPtMinAcc = -98.0; + double leadingConstituentPtMaxAcc = 9998.0; + if (jetAreaFractionMin > jetAreaFractionMinAcc) { if (jet.area() < jetAreaFractionMin * o2::constants::math::PI * (jet.r() / 100.0) * (jet.r() / 100.0)) { return false; } } bool checkConstituentPt = true; - bool checkConstituentMinPt = (leadingConstituentPtMin > jetAreaFractionMinCfgMin); - bool checkConstituentMaxPt = (leadingConstituentPtMax < jetAreaFractionMinCfgMax); + bool checkConstituentMinPt = (leadingConstituentPtMin > leadingConstituentPtMinAcc); + bool checkConstituentMaxPt = (leadingConstituentPtMax < leadingConstituentPtMaxAcc); if (!checkConstituentMinPt && !checkConstituentMaxPt) { checkConstituentPt = false; } + if (mcLevelIsParticleLevel && !checkLeadConstituentPtForMcpJets) { + checkConstituentPt = false; + } if (checkConstituentPt) { bool isMinLeadingConstituent = !checkConstituentMinPt; bool isMaxLeadingConstituent = true; - for (const auto& constituent : jet.template tracks_as()) { + for (const auto& constituent : jet.template tracks_as()) { double pt = constituent.pt(); if (checkConstituentMinPt && pt >= leadingConstituentPtMin) { @@ -373,177 +445,18 @@ struct JetChargedV2 { } return isMinLeadingConstituent && isMaxLeadingConstituent; } - return true; } - template - bool trackIsInJet(T const& track, U const& jet) - { - for (auto const& constituentId : jet.tracksIds()) { - if (constituentId == track.globalIndex()) { - return true; - } - } - return false; - } - - template - void fillTrackHistograms(T const& collision, U const& tracks, float weight = 1.0) - { - for (auto const& track : tracks) { - if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { - continue; - } - registry.fill(HIST("h2_centrality_track_pt"), collision.centrality(), track.pt(), weight); - registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); - registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); - registry.fill(HIST("h2_centrality_track_energy"), collision.centrality(), track.energy(), weight); - registry.fill(HIST("h2_track_pt_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); - registry.fill(HIST("h2_track_pt_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); - registry.fill(HIST("h2_track_pt_high_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); - registry.fill(HIST("h2_track_pt_high_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); - } - } - - void fillLeadingJetQA(double leadingJetPt, double leadingJetPhi, double leadingJetEta) - { - registry.fill(HIST("leadJetPt"), leadingJetPt); - registry.fill(HIST("leadJetPhi"), leadingJetPhi); - registry.fill(HIST("leadJetEta"), leadingJetEta); - } - double chiSquareCDF(int nDF, double x) { return TMath::Gamma(nDF / 2., x / 2.); } - void processInOutJetV2(soa::Filtered>::iterator const& collision, - soa::Join const& jets, - aod::JetTracks const&) - { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// - histosQA.fill(HIST("histCent"), collision.cent()); - for (uint i = 0; i < cfgnMods->size(); i++) { - int nmode = cfgnMods->at(i); - int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int cfgNmodA = 2; - int cfgNmodB = 3; - int evtPlnAngleA = 7; - int evtPlnAngleB = 3; - int evtPlnAngleC = 5; - if (nmode == cfgNmodA) { - if (collision.qvecAmp()[detId] > 1e-8 || collision.qvecAmp()[refAId] < 1e-8 || collision.qvecAmp()[refBId] < 1e-8) { - histosQA.fill(HIST("histQvecUncorV2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); - histosQA.fill(HIST("histQvecRectrV2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); - histosQA.fill(HIST("histQvecTwistV2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); - histosQA.fill(HIST("histQvecFinalV2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); - - histosQA.fill(HIST("histEvtPlUncorV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlRectrV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlTwistV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlFinalV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); - - histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); - } - } else if (nmode == cfgNmodB) { - histosQA.fill(HIST("histQvecUncorV3"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); - histosQA.fill(HIST("histQvecRectrV3"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); - histosQA.fill(HIST("histQvecTwistV3"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); - histosQA.fill(HIST("histQvecFinalV3"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); - - histosQA.fill(HIST("histEvtPlUncorV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlRectrV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlTwistV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlFinalV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); - - histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); - histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); - } - - if (nmode == cfgNmodA) { - double phiMinusPsi2; - if (collision.qvecAmp()[detId] < 1e-8) { - continue; - } - float ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); - for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { - continue; - } - if (!isAcceptedJet(jet)) { - continue; - } - if (jet.r() != round(selectedJetsRadius * 100.0f)) { - continue; - } - registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_rhoareasubtracted"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); - - phiMinusPsi2 = jet.phi() - ep2; - if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { - registry.fill(HIST("h_jet_pt_in_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); - } else { - registry.fill(HIST("h_jet_pt_out_of_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); - } - } - } else if (nmode == cfgNmodB) { - double phiMinusPsi3; - float ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); - for (auto const& jet : jets) { - if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { - continue; - } - if (!isAcceptedJet(jet)) { - continue; - } - if (jet.r() != round(selectedJetsRadius * 100.0f)) { - continue; - } - phiMinusPsi3 = jet.phi() - ep3; - - if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { - registry.fill(HIST("h_jet_pt_in_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); - } else { - registry.fill(HIST("h_jet_pt_out_of_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3"), collision.centrality(), jet.pt() - (collision.rho() * jet.area()), 1.0); - } - } - } - } - } - PROCESS_SWITCH(JetChargedV2, processInOutJetV2, "Jet V2 in and out of plane", true); - - void processSigmaPt(soa::Filtered>::iterator const& collision, - soa::Join const& jets, - aod::JetTracks const& tracks) + // leading jet fill + template + void fillLeadingJetQA(T const& jets, double& leadingJetPt, double& leadingJetPhi, double& leadingJetEta) { - registry.fill(HIST("h_collisions"), 0.5); - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - registry.fill(HIST("h_collisions"), 1.5); - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { - return; - } - registry.fill(HIST("h_collisions"), 2.5); - double leadingJetPt = -1; - double leadingJetPhi = -1; - double leadingJetEta = -1; for (const auto& jet : jets) { if (jet.pt() > leadingJetPt) { leadingJetPt = jet.pt(); @@ -551,52 +464,67 @@ struct JetChargedV2 { leadingJetPhi = jet.phi(); } } - fillLeadingJetQA(leadingJetPt, leadingJetPhi, leadingJetEta); + registry.fill(HIST("leadJetPt"), leadingJetPt); + registry.fill(HIST("leadJetPhi"), leadingJetPhi); + registry.fill(HIST("leadJetEta"), leadingJetEta); + } - int nTrk = 0; + // create h_ptsum_sumpt_fit, with number of Track + template + void getNtrk(T const& tracks, U const& jets, int& nTrk, double& evtnum, double& leadingJetEta) + { if (jets.size() > 0) { for (auto const& track : tracks) { if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { - registry.fill(HIST("h_accept_Track"), 2.5); + registry.fill(HIST("h_accept_Track"), 4.5); nTrk += 1; } } registry.fill(HIST("h_evtnum_NTrk"), evtnum, nTrk); } + } - if (nTrk <= 0) { - return; - } - - hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); - + // fill nTrk plot for fit rho(varphi) + template + void fillNtrkCheck(U const& tracks, J const& jets, TH1F* hPtsumSumptFit, double& leadingJetEta) + { if (jets.size() > 0) { for (auto const& trackfit : tracks) { registry.fill(HIST("h_accept_Track"), 0.5); if (jetderiveddatautilities::selectTrack(trackfit, trackSelection) && (std::fabs(trackfit.eta() - leadingJetEta) > jetRadius) && trackfit.pt() >= localRhoFitPtMin && trackfit.pt() <= localRhoFitPtMax) { - registry.fill(HIST("h_accept_Track_Fit"), 0.5); - fitTrack += 1; + registry.fill(HIST("h_accept_Track"), 1.5); } } for (auto const& track : tracks) { - registry.fill(HIST("h_accept_Track"), 1.5); + registry.fill(HIST("h_accept_Track"), 2.5); if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { - accptTrack += 1; - registry.fill(HIST("h_accept_Track"), 2.5); + registry.fill(HIST("h_accept_Track"), 3.5); hPtsumSumptFit->Fill(track.phi(), track.pt()); - registry.fill(HIST("h2_phi_track_eta"), track.eta(), track.phi()); - registry.fill(HIST("h_ptsum_sumpt"), track.phi(), track.pt()); - registry.fill(HIST("h2_centrality_phi_w_pt"), collision.centrality(), track.phi(), track.pt()); - registry.fill(HIST("h2_evtnum_phi_w_pt"), evtnum, track.phi(), track.pt()); - registry.fill(HIST("Thn_evtnum_phi_centrality"), evtnum, track.phi(), collision.centrality()); - registry.fill(HIST("h_accept_Track_init"), accptTrack); - registry.fill(HIST("h_accept_Track_Fit"), 1.5); } } } - registry.fill(HIST("h_ptsum_collnum"), 0.5); + } + + // MCP leading jet fill + template + void fillLeadingJetQAMCP(T const& jets, double& leadingJetPt, double& leadingJetPhi, double& leadingJetEta) + { + for (const auto& jet : jets) { + if (jet.pt() > leadingJetPt) { + leadingJetPt = jet.pt(); + leadingJetEta = jet.eta(); + leadingJetPhi = jet.phi(); + } + } + registry.fill(HIST("leadJetPtMCP"), leadingJetPt); + registry.fill(HIST("leadJetPhiMCP"), leadingJetPhi); + registry.fill(HIST("leadJetEtaMCP"), leadingJetEta); + } + template + void fitFncMCP(U const& collision, T const& tracks, J const& jets, TH1F* hPtsumSumptFitMCP, double leadingJetEta, bool mcLevelIsParticleLevel, float weight = 1.0) + { double ep2 = 0.; double ep3 = 0.; int cfgNmodA = 2; @@ -608,69 +536,821 @@ struct JetChargedV2 { int nmode = cfgnMods->at(i); int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); if (nmode == cfgNmodA) { - if (collision.qvecAmp()[detId] > 1e-8) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); } } else if (nmode == cfgNmodB) { - if (collision.qvecAmp()[detId] > 1e-8) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); } } } - TF1* fFitModulationV2v3 = 0x0; - const char* fitFunctionV2v3 = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; - fFitModulationV2v3 = new TF1("fit_kV3", fitFunctionV2v3, 0, o2::constants::math::TwoPI); + const char* fitFunctionV2v3P = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; + fFitModulationV2v3P = new TF1("fit_kV3", fitFunctionV2v3P, 0, o2::constants::math::TwoPI); //=========================< set parameter >=========================// - fFitModulationV2v3->SetParameter(0, 1.); - fFitModulationV2v3->SetParameter(1, 0.01); - fFitModulationV2v3->SetParameter(3, 0.01); + fFitModulationV2v3P->SetParameter(0, 1.); + fFitModulationV2v3P->SetParameter(1, 0.01); + fFitModulationV2v3P->SetParameter(3, 0.01); double ep2fix = 0.; double ep3fix = 0.; if (ep2 < 0) { ep2fix = RecoDecay::constrainAngle(ep2); - fFitModulationV2v3->FixParameter(2, ep2fix); + fFitModulationV2v3P->FixParameter(2, ep2fix); } else { - fFitModulationV2v3->FixParameter(2, ep2); + fFitModulationV2v3P->FixParameter(2, ep2); } if (ep3 < 0) { ep3fix = RecoDecay::constrainAngle(ep3); - fFitModulationV2v3->FixParameter(4, ep3fix); + fFitModulationV2v3P->FixParameter(4, ep3fix); } else { - fFitModulationV2v3->FixParameter(4, ep3); + fFitModulationV2v3P->FixParameter(4, ep3); } - hPtsumSumptFit->Fit(fFitModulationV2v3, "Q", "ep", 0, o2::constants::math::TwoPI); + hPtsumSumptFitMCP->Fit(fFitModulationV2v3P, "Q", "ep", 0, o2::constants::math::TwoPI); + // int paraNum = 5; double temppara[5]; - temppara[0] = fFitModulationV2v3->GetParameter(0); - temppara[1] = fFitModulationV2v3->GetParameter(1); - temppara[2] = fFitModulationV2v3->GetParameter(2); - temppara[3] = fFitModulationV2v3->GetParameter(3); - temppara[4] = fFitModulationV2v3->GetParameter(4); - int paraNum = 5; - for (int i = 1; i <= paraNum; i++) { - registry.fill(HIST("h2_evt_fitpara"), evtnum, i - 0.5, temppara[i - 1]); - } - - registry.fill(HIST("h_fitparaRho_evtnum"), evtnum, temppara[0]); - registry.fill(HIST("h_fitparav2obs_evtnum"), evtnum, temppara[1]); - registry.fill(HIST("h_fitparaPsi2_evtnum"), evtnum, temppara[2]); - registry.fill(HIST("h_fitparav3obs_evtnum"), evtnum, temppara[3]); - registry.fill(HIST("h_fitparaPsi3_evtnum"), evtnum, temppara[4]); - - registry.fill(HIST("h_v2obs_centrality"), collision.centrality(), temppara[1]); - registry.fill(HIST("h_v3obs_centrality"), collision.centrality(), temppara[3]); - registry.fill(HIST("h_evtnum_centrlity"), evtnum, collision.centrality()); - + temppara[0] = fFitModulationV2v3P->GetParameter(0); + temppara[1] = fFitModulationV2v3P->GetParameter(1); + temppara[2] = fFitModulationV2v3P->GetParameter(2); + temppara[3] = fFitModulationV2v3P->GetParameter(3); + temppara[4] = fFitModulationV2v3P->GetParameter(4); if (temppara[0] == 0) { return; } - registry.fill(HIST("h2_fitParaZero_cent"), collision.centrality(), temppara[0], 1.0); + registry.fill(HIST("h_mcp_fitparaRho_evtnum"), evtnum, temppara[0]); + registry.fill(HIST("h_mcp_fitparaPsi2_evtnum"), evtnum, temppara[2]); + registry.fill(HIST("h_mcp_fitparaPsi3_evtnum"), evtnum, temppara[4]); + registry.fill(HIST("h_mcp_v2obs_centrality"), collision.centFT0M(), temppara[1]); + registry.fill(HIST("h_mcp_v3obs_centrality"), collision.centFT0M(), temppara[3]); + registry.fill(HIST("h_mcp_evtnum_centrlity"), evtnum, collision.centFT0M()); - int nDF = 1; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + + double integralValue = fFitModulationV2v3P->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); + double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; + registry.fill(HIST("h2_mcp_phi_rholocal"), jet.phi() - ep2, rholocal, weight); + registry.fill(HIST("h2_mcp_centrality_rholocal"), collision.centFT0M(), rholocal, weight); + if (nmode == cfgNmodA) { + registry.fill(HIST("h_mcp_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), weight); + + double phiMinusPsi2; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + phiMinusPsi2 = jet.phi() - ep2; + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_mcp_jet_pt_in_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_in_plane_v2_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), weight); + } else { + registry.fill(HIST("h_mcp_jet_pt_out_of_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_out_of_plane_v2_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), weight); + } + } else if (nmode == cfgNmodB) { + double phiMinusPsi3; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + phiMinusPsi3 = jet.phi() - ep3; + + if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_mcp_jet_pt_in_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_in_plane_v3_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), weight); + } else { + registry.fill(HIST("h_mcp_jet_pt_out_of_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), weight); + registry.fill(HIST("h2_mcp_centrality_jet_pt_out_of_plane_v3_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), weight); + } + } + } + } + // RCpT + for (uint i = 0; i < cfgnMods->size(); i++) { + TRandom3 randomNumber(0); + float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); + float randomConePt = 0; + double integralValueRC = fFitModulationV2v3P->Integral(randomConePhi - randomConeR, randomConePhi + randomConeR); + double rholocalRC = collision.rho() / (2 * randomConeR * temppara[0]) * integralValueRC; + + int nmode = cfgnMods->at(i); + if (nmode == cfgNmodA) { + double rcPhiPsi2; + rcPhiPsi2 = randomConePhi - ep2; + + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + 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(); + } + } + } + registry.fill(HIST("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphi"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, weight); + + // removing the leading jet from the random cone + if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet + float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + + bool jetWasInCone = false; + while ((randomConeLeadJetDeltaR <= 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR)) || (randomConeLeadJetDeltaR > 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < randomConeLeadJetDeltaR))) { + jetWasInCone = true; + randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); + dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + } + if (jetWasInCone) { + randomConePt = 0.0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > randomConeR)) { // 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(); + } + } + } + } + } + registry.fill(HIST("h3_mcp_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, weight); + registry.fill(HIST("h3_mcp_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, weight); + } else if (nmode == cfgNmodB) { + continue; + } + } + } + + 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) { + return; + } + if (jet.r() == round(selectedJetsRadius * 100.0f)) { + // fill mcp jet histograms + double jetcorrpt = jet.pt() - (rho * jet.area()); + registry.fill(HIST("h_jet_pt_part_rhoareasubtracted"), jetcorrpt, weight); + if (jetcorrpt > 0) { + registry.fill(HIST("h_jet_eta_part_rhoareasubtracted"), jet.eta(), weight); + registry.fill(HIST("h_jet_phi_part_rhoareasubtracted"), jet.phi(), weight); + } + } + } + + 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 fillGeoMatchedCorrHistograms(TBase const& jetMCD, TF1* fFitModulationRM, float tempparaA, double ep2, float rho, float mcrho = 0.0, float weight = 1.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) { + continue; + } + if (jetMCD.r() == round(selectedJetsRadius * 100.0f)) { + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + double integralValue = fFitModulationRM->Integral(jetMCD.phi() - jetRadius, jetMCD.phi() + jetRadius); + double rholocal = rho / (2 * jetRadius * tempparaA) * integralValue; + double corrTagjetpt = jetMCP.pt() - (mcrho * jetMCP.area()); + double corrBasejetpt = jetMCD.pt() - (rholocal * jetMCD.area()); + double dcorrpt = corrTagjetpt - corrBasejetpt; + double phiMinusPsi2 = jetMCD.phi() - ep2; + if (jetfindingutilities::isInEtaAcceptance(jetMCD, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_in_rhoareasubtracted_mcdetaconstraint"), corrBasejetpt, corrTagjetpt, weight); + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_in_rhoareasubtracted"), corrBasejetpt, dcorrpt / corrBasejetpt, weight); + } else { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_out_rhoareasubtracted_mcdetaconstraint"), corrBasejetpt, corrTagjetpt, weight); + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_diff_matchedgeo_out_rhoareasubtracted"), corrBasejetpt, dcorrpt / corrBasejetpt, weight); + } + } + if (jetfindingutilities::isInEtaAcceptance(jetMCP, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_in_rhoareasubtracted_mcpetaconstraint"), corrBasejetpt, corrTagjetpt, weight); + registry.fill(HIST("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_in_rhoareasubtracted"), corrTagjetpt, dcorrpt / corrTagjetpt, weight); + registry.fill(HIST("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo_in_rhoareasubtracted"), corrTagjetpt, corrBasejetpt / corrTagjetpt, weight); + } else { + registry.fill(HIST("h2_jet_pt_mcd_jet_pt_mcp_matchedgeo_out_rhoareasubtracted_mcpetaconstraint"), corrBasejetpt, corrTagjetpt, weight); + registry.fill(HIST("h2_jet_pt_mcp_jet_pt_diff_matchedgeo_out_rhoareasubtracted"), corrTagjetpt, dcorrpt / corrTagjetpt, weight); + registry.fill(HIST("h2_jet_pt_mcp_jet_pt_ratio_matchedgeo_out_rhoareasubtracted"), corrTagjetpt, corrBasejetpt / corrTagjetpt, weight); + } + } + } + } + } + } + + //=======================================[ process area ]=============================================// + void processInOutJetV2(soa::Filtered>::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const&) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// + histosQA.fill(HIST("histCent"), collision.cent()); + + //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// + int cfgNmodA = 2; + int cfgNmodB = 3; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId || collision.qvecAmp()[refAId] < collQvecAmpDetId || collision.qvecAmp()[refBId] < collQvecAmpDetId) { + histosQA.fill(HIST("histQvecUncorV2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); + histosQA.fill(HIST("histQvecRectrV2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); + histosQA.fill(HIST("histQvecTwistV2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); + histosQA.fill(HIST("histQvecFinalV2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); + + histosQA.fill(HIST("histEvtPlUncorV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRectrV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlTwistV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlFinalV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + } + } else if (nmode == cfgNmodB) { + histosQA.fill(HIST("histQvecUncorV3"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); + histosQA.fill(HIST("histQvecRectrV3"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); + histosQA.fill(HIST("histQvecTwistV3"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); + histosQA.fill(HIST("histQvecFinalV3"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); + + histosQA.fill(HIST("histEvtPlUncorV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRectrV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlTwistV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlFinalV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + } + } + + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + if (nmode == cfgNmodA) { + double phiMinusPsi2; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + float ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jet.pt() - (collision.rho() * jet.area()), 1.0); + + phiMinusPsi2 = jet.phi() - ep2; + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2"), collision.centFT0M(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2"), collision.centFT0M(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } + } + } else if (nmode == cfgNmodB) { + double phiMinusPsi3; + float ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + phiMinusPsi3 = jet.phi() - ep3; + + if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); + } + } + } + } + } + PROCESS_SWITCH(JetChargedV2, processInOutJetV2, "Jet V2 in and out of plane", false); + + void processInOutJetV2MCD(soa::Filtered>::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const&) + { + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// + histosQA.fill(HIST("histCent"), collision.cent()); + //=====================< evt pln [n=2->\Psi_2, n=3->\Psi_3] >=====================// + int cfgNmodA = 2; + int cfgNmodB = 3; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int refAInd = refAId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + int refBInd = refBId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId || collision.qvecAmp()[refAId] < collQvecAmpDetId || collision.qvecAmp()[refBId] < collQvecAmpDetId) { + histosQA.fill(HIST("histQvecUncorV2"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); + histosQA.fill(HIST("histQvecRectrV2"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); + histosQA.fill(HIST("histQvecTwistV2"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); + histosQA.fill(HIST("histQvecFinalV2"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); + + histosQA.fill(HIST("histEvtPlUncorV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRectrV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlTwistV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlFinalV2"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV2"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + } + } else if (nmode == cfgNmodB) { + histosQA.fill(HIST("histQvecUncorV3"), collision.qvecRe()[detInd], collision.qvecIm()[detInd], collision.cent()); + histosQA.fill(HIST("histQvecRectrV3"), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], collision.cent()); + histosQA.fill(HIST("histQvecTwistV3"), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], collision.cent()); + histosQA.fill(HIST("histQvecFinalV3"), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], collision.cent()); + + histosQA.fill(HIST("histEvtPlUncorV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRectrV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlTwistV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2], nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlFinalV3"), helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), collision.cent()); + + histosQA.fill(HIST("histEvtPlRes_SigRefAV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_SigRefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + histosQA.fill(HIST("histEvtPlRes_RefARefBV3"), helperEP.GetResolution(helperEP.GetEventPlane(collision.qvecRe()[refAInd + 3], collision.qvecIm()[refAInd + 3], nmode), helperEP.GetEventPlane(collision.qvecRe()[refBInd + 3], collision.qvecIm()[refBInd + 3], nmode), nmode), collision.cent()); + } + } + + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + if (nmode == cfgNmodA) { + double phiMinusPsi2; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + float ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + registry.fill(HIST("h_jet_pt_rhoareasubtracted"), jet.pt() - (collision.rho() * jet.area()), 1.0); + + phiMinusPsi2 = jet.phi() - ep2; + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2"), collision.centFT0M(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v2"), jet.pt() - (collision.rho() * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2"), collision.centFT0M(), jet.pt() - (collision.rho() * jet.area()), 1.0); + } + } + } else if (nmode == cfgNmodB) { + double phiMinusPsi3; + float ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + phiMinusPsi3 = jet.phi() - ep3; + + if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v3"), jet.pt() - (collision.rho() * jet.area()), 1.0); + } + } + } + } + } + PROCESS_SWITCH(JetChargedV2, processInOutJetV2MCD, "Jet V2 in and out of plane MCD", false); + + void processSigmaPt(soa::Filtered>::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const& tracks) + { + registry.fill(HIST("h_collisions"), 0.5); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + registry.fill(HIST("h_collisions"), 2.5); + + double leadingJetPt = -1; + double leadingJetPhi = -1; + double leadingJetEta = -1; + fillLeadingJetQA(jets, leadingJetPt, leadingJetPhi, leadingJetEta); + + int nTrk = 0; + getNtrk(tracks, jets, nTrk, evtnum, leadingJetEta); + if (nTrk <= 0) { + return; + } + hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); + + fillNtrkCheck(tracks, jets, hPtsumSumptFit, leadingJetEta); + + double ep2 = 0.; + double ep3 = 0.; + int cfgNmodA = 2; + int cfgNmodB = 3; + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } else if (nmode == cfgNmodB) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } + } + + const char* fitFunctionV2v3 = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; + fFitModulationV2v3 = new TF1("fit_kV3", fitFunctionV2v3, 0, o2::constants::math::TwoPI); + //=========================< set parameter >=========================// + fFitModulationV2v3->SetParameter(0, 1.); + fFitModulationV2v3->SetParameter(1, 0.01); + fFitModulationV2v3->SetParameter(3, 0.01); + + double ep2fix = 0.; + double ep3fix = 0.; + + if (ep2 < 0) { + ep2fix = RecoDecay::constrainAngle(ep2); + fFitModulationV2v3->FixParameter(2, ep2fix); + } else { + fFitModulationV2v3->FixParameter(2, ep2); + } + if (ep3 < 0) { + ep3fix = RecoDecay::constrainAngle(ep3); + fFitModulationV2v3->FixParameter(4, ep3fix); + } else { + fFitModulationV2v3->FixParameter(4, ep3); + } + + hPtsumSumptFit->Fit(fFitModulationV2v3, "Q", "ep", 0, o2::constants::math::TwoPI); + + double temppara[5]; + temppara[0] = fFitModulationV2v3->GetParameter(0); + temppara[1] = fFitModulationV2v3->GetParameter(1); + temppara[2] = fFitModulationV2v3->GetParameter(2); + temppara[3] = fFitModulationV2v3->GetParameter(3); + temppara[4] = fFitModulationV2v3->GetParameter(4); + + registry.fill(HIST("h_fitparaRho_evtnum"), evtnum, temppara[0]); + registry.fill(HIST("h_fitparaPsi2_evtnum"), evtnum, temppara[2]); + registry.fill(HIST("h_fitparaPsi3_evtnum"), evtnum, temppara[4]); + registry.fill(HIST("h_v2obs_centrality"), collision.centFT0M(), temppara[1]); + registry.fill(HIST("h_v3obs_centrality"), collision.centFT0M(), temppara[3]); + registry.fill(HIST("h_evtnum_centrlity"), evtnum, collision.centFT0M()); + + if (temppara[0] == 0) { + return; + } + + int nDF = 1; + int numOfFreePara = 2; + nDF = static_cast(fFitModulationV2v3->GetXaxis()->GetNbins()) - numOfFreePara; + if (nDF == 0 || static_cast(nDF) <= 0.) + return; + double chi2 = 0.; + for (int i = 0; i < hPtsumSumptFit->GetXaxis()->GetNbins(); i++) { + if (hPtsumSumptFit->GetBinContent(i + 1) <= 0.) + continue; + chi2 += std::pow((hPtsumSumptFit->GetBinContent(i + 1) - fFitModulationV2v3->Eval(hPtsumSumptFit->GetXaxis()->GetBinCenter(1 + i))), 2) / hPtsumSumptFit->GetBinContent(i + 1); + } + + double chiSqr = 999.; + double cDF = 1.; + + chiSqr = chi2; + cDF = 1. - chiSquareCDF(nDF, chiSqr); + + int evtCentAreaMin = 0; + int evtCentAreaMax = 5; + int evtMidAreaMin = 30; + int evtMidAreaMax = 50; + double evtcent = collision.centFT0M(); + if (cfgChkFitQuality) { + registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); + registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centFT0M(), cDF); + registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centFT0M(), chiSqr / (static_cast(nDF))); + registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); + if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } + if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } + } + + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + if (jet.r() != round(selectedJetsRadius * 100.0f)) { + continue; + } + + double integralValue = fFitModulationV2v3->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); + double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; + registry.fill(HIST("h2_rholocal_cent"), collision.centFT0M(), rholocal, 1.0); + + if (nmode == cfgNmodA) { + double phiMinusPsi2; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + phiMinusPsi2 = jet.phi() - ep2; + + registry.fill(HIST("h2_phi_rholocal"), jet.phi() - ep2, rholocal, 1.0); + registry.fill(HIST("h_jet_pt_inclusive_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + + if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), 1.0); + } + } else if (nmode == cfgNmodB) { + double phiMinusPsi3; + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { + continue; + } + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); + phiMinusPsi3 = jet.phi() - ep3; + + if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { + registry.fill(HIST("h_jet_pt_in_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + } else { + registry.fill(HIST("h_jet_pt_out_of_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); + } + } + } + } + // RCpT + for (uint i = 0; i < cfgnMods->size(); i++) { + TRandom3 randomNumber(0); + float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); + float randomConePt = 0; + double integralValueRC = fFitModulationV2v3->Integral(randomConePhi - randomConeR, randomConePhi + randomConeR); + double rholocalRC = collision.rho() / (2 * randomConeR * temppara[0]) * integralValueRC; + + int nmode = cfgnMods->at(i); + if (nmode == cfgNmodA) { + double rcPhiPsi2; + rcPhiPsi2 = randomConePhi - ep2; + + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection)) { + 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(); + } + } + } + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphi"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); + + // removing the leading jet from the random cone + if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet + float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + + bool jetWasInCone = false; + while ((randomConeLeadJetDeltaR <= 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR)) || (randomConeLeadJetDeltaR > 0 && (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < randomConeLeadJetDeltaR))) { + jetWasInCone = true; + randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); + randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); + dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); + dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + } + if (jetWasInCone) { + randomConePt = 0.0; + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > randomConeR)) { // 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(); + } + } + } + } + } + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, 1.0); + } else if (nmode == cfgNmodB) { + continue; + } + } + delete hPtsumSumptFit; + delete fFitModulationV2v3; + evtnum += 1; + } + PROCESS_SWITCH(JetChargedV2, processSigmaPt, "Sigma pT and bkg as fcn of phi", false); + + void processSigmaPtMCD(soa::Filtered>::iterator const& collision, + soa::Join const& jets, + aod::JetTracks const& tracks) + { + registry.fill(HIST("h_collisions"), 0.5); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + registry.fill(HIST("h_collisions"), 1.5); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + registry.fill(HIST("h_collisions"), 2.5); + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet)) { + continue; + } + } + + double leadingJetPt = -1; + double leadingJetPhi = -1; + double leadingJetEta = -1; + fillLeadingJetQA(jets, leadingJetPt, leadingJetPhi, leadingJetEta); + + int nTrk = 0; + getNtrk(tracks, jets, nTrk, evtnum, leadingJetEta); + if (nTrk <= 0) { + return; + } + hPtsumSumptFit = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); + + fillNtrkCheck(tracks, jets, hPtsumSumptFit, leadingJetEta); + + double ep2 = 0.; + double ep3 = 0.; + int cfgNmodA = 2; + int cfgNmodB = 3; + int evtPlnAngleA = 7; + int evtPlnAngleB = 3; + int evtPlnAngleC = 5; + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } else if (nmode == cfgNmodB) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } + } + + const char* fitFunctionV2v3 = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; + fFitModulationV2v3 = new TF1("fit_kV3", fitFunctionV2v3, 0, o2::constants::math::TwoPI); + //=========================< set parameter >=========================// + fFitModulationV2v3->SetParameter(0, 1.); + fFitModulationV2v3->SetParameter(1, 0.01); + fFitModulationV2v3->SetParameter(3, 0.01); + + double ep2fix = 0.; + double ep3fix = 0.; + + if (ep2 < 0) { + ep2fix = RecoDecay::constrainAngle(ep2); + fFitModulationV2v3->FixParameter(2, ep2fix); + } else { + fFitModulationV2v3->FixParameter(2, ep2); + } + if (ep3 < 0) { + ep3fix = RecoDecay::constrainAngle(ep3); + fFitModulationV2v3->FixParameter(4, ep3fix); + } else { + fFitModulationV2v3->FixParameter(4, ep3); + } + + hPtsumSumptFit->Fit(fFitModulationV2v3, "Q", "ep", 0, o2::constants::math::TwoPI); + + double temppara[5]; + temppara[0] = fFitModulationV2v3->GetParameter(0); + temppara[1] = fFitModulationV2v3->GetParameter(1); + temppara[2] = fFitModulationV2v3->GetParameter(2); + temppara[3] = fFitModulationV2v3->GetParameter(3); + temppara[4] = fFitModulationV2v3->GetParameter(4); + + registry.fill(HIST("h_fitparaRho_evtnum"), evtnum, temppara[0]); + registry.fill(HIST("h_fitparaPsi2_evtnum"), evtnum, temppara[2]); + registry.fill(HIST("h_fitparaPsi3_evtnum"), evtnum, temppara[4]); + registry.fill(HIST("h_v2obs_centrality"), collision.centFT0M(), temppara[1]); + registry.fill(HIST("h_v3obs_centrality"), collision.centFT0M(), temppara[3]); + registry.fill(HIST("h_evtnum_centrlity"), evtnum, collision.centFT0M()); + + if (temppara[0] == 0) { + return; + } + + int nDF = 1; int numOfFreePara = 2; nDF = static_cast(fFitModulationV2v3->GetXaxis()->GetNbins()) - numOfFreePara; if (nDF == 0 || static_cast(nDF) <= 0.) @@ -688,21 +1368,24 @@ struct JetChargedV2 { chiSqr = chi2; cDF = 1. - chiSquareCDF(nDF, chiSqr); - registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); - registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centrality(), cDF); - registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centrality(), chiSqr / (static_cast(nDF))); - registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); - registry.fill(HIST("Thn_PChi2_CombinFitCent"), collision.centrality(), cDF, chiSqr / (static_cast(nDF))); - double evtcent = collision.centrality(); int evtCentAreaMin = 0; int evtCentAreaMax = 5; int evtMidAreaMin = 30; int evtMidAreaMax = 50; - if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { - registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); - } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { - registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + double evtcent = collision.centFT0M(); + if (cfgChkFitQuality) { + registry.fill(HIST("h_PvalueCDF_CombinFit"), cDF); + registry.fill(HIST("h2_PvalueCDFCent_CombinFit"), collision.centFT0M(), cDF); + registry.fill(HIST("h2_Chi2Cent_CombinFit"), collision.centFT0M(), chiSqr / (static_cast(nDF))); + registry.fill(HIST("h2_PChi2_CombinFit"), cDF, chiSqr / (static_cast(nDF))); + if (evtcent >= evtCentAreaMin && evtcent <= evtCentAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitA"), cDF, chiSqr / (static_cast(nDF))); + + } else if (evtcent >= evtMidAreaMin && evtcent <= evtMidAreaMax) { + registry.fill(HIST("h2_PChi2_CombinFitB"), cDF, chiSqr / (static_cast(nDF))); + } } + for (uint i = 0; i < cfgnMods->size(); i++) { int nmode = cfgnMods->at(i); int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); @@ -720,17 +1403,11 @@ struct JetChargedV2 { double integralValue = fFitModulationV2v3->Integral(jet.phi() - jetRadius, jet.phi() + jetRadius); double rholocal = collision.rho() / (2 * jetRadius * temppara[0]) * integralValue; - registry.fill(HIST("h2_phi_rhophi"), jet.phi() - ep2, fFitModulationV2v3->Eval(jet.phi()), 1.0); - registry.fill(HIST("h3_centrality_rhovsphi_phi"), collision.centrality(), fFitModulationV2v3->Eval(jet.phi()), jet.phi() - ep2); - - registry.fill(HIST("h2_phi_rholocal_cent"), collision.centrality(), rholocal, 1.0); - registry.fill(HIST("h3_centrality_localrho_phi"), collision.centrality(), rholocal, jet.phi() - ep2); + registry.fill(HIST("h2_rholocal_cent"), collision.centFT0M(), rholocal, 1.0); if (nmode == cfgNmodA) { - registry.fill(HIST("h_jet_pt_rholocal"), jet.pt() - (rholocal * jet.area()), 1.0); - double phiMinusPsi2; - if (collision.qvecAmp()[detId] < 1e-8) { + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { continue; } phiMinusPsi2 = jet.phi() - ep2; @@ -740,14 +1417,14 @@ struct JetChargedV2 { if ((phiMinusPsi2 < o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi2 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi2 < evtPlnAngleC * o2::constants::math::PIQuarter)) { registry.fill(HIST("h_jet_pt_in_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_in_plane_v2_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), 1.0); } else { registry.fill(HIST("h_jet_pt_out_of_plane_v2_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); + registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v2_rho"), collision.centFT0M(), jet.pt() - (rholocal * jet.area()), 1.0); } } else if (nmode == cfgNmodB) { double phiMinusPsi3; - if (collision.qvecAmp()[detId] < 1e-8) { + if (collision.qvecAmp()[detId] < collQvecAmpDetId) { continue; } ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); @@ -755,10 +1432,8 @@ struct JetChargedV2 { if ((phiMinusPsi3 < o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleA * o2::constants::math::PIQuarter) || (phiMinusPsi3 >= evtPlnAngleB * o2::constants::math::PIQuarter && phiMinusPsi3 < evtPlnAngleC * o2::constants::math::PIQuarter)) { registry.fill(HIST("h_jet_pt_in_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_in_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); } else { registry.fill(HIST("h_jet_pt_out_of_plane_v3_rho"), jet.pt() - (rholocal * jet.area()), 1.0); - registry.fill(HIST("h2_centrality_jet_pt_out_of_plane_v3_rho"), collision.centrality(), jet.pt() - (rholocal * jet.area()), 1.0); } } } @@ -786,7 +1461,7 @@ struct JetChargedV2 { } } } - registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphi"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphi"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); // 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 @@ -814,102 +1489,269 @@ struct JetChargedV2 { } } } - registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); - registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, 1.0); + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_localrhovsphiwithoutleadingjet"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rholocalRC, rcPhiPsi2, 1.0); + registry.fill(HIST("h3_centrality_deltapT_RandomCornPhi_rhorandomconewithoutleadingjet"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, 1.0); } else if (nmode == cfgNmodB) { continue; } } delete hPtsumSumptFit; + delete fFitModulationV2v3; evtnum += 1; } - PROCESS_SWITCH(JetChargedV2, processSigmaPt, "Sigma pT and bkg as fcn of phi", true); + PROCESS_SWITCH(JetChargedV2, processSigmaPtMCD, "jet spectra with rho-area subtraction for MCD", false); - void processRandomConeDataV2(soa::Filtered>::iterator const& collision, - soa::Join const& jets, - soa::Filtered const& tracks) + void processSigmaPtMCP(McParticleCollision::iterator const& mccollision, + soa::SmallGroups> const& collisions, + soa::Join const& jets, + aod::JetTracks const& tracks, + aod::JetParticles const&) { - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + bool mcLevelIsParticleLevel = true; + int acceptSplitCollInMCP = 2; + + registry.fill(HIST("h_mcColl_counts_areasub"), 0.5); + if (std::abs(mccollision.posZ()) > vertexZCut) { return; } - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { + registry.fill(HIST("h_mcColl_counts_areasub"), 1.5); + if (collisions.size() < 1) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 2.5); + if (acceptSplitCollisions == 0 && collisions.size() > 1) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 3.5); + + bool hasSel8Coll = false; + bool centralityIsGood = false; + bool occupancyIsGood = false; + if (acceptSplitCollisions == acceptSplitCollInMCP) { + if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { + hasSel8Coll = true; + } + if ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax)) { + centralityIsGood = true; + } + if ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { + occupancyIsGood = true; + } + } else { + for (auto const& collision : collisions) { + if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + hasSel8Coll = true; + } + if ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax)) { + centralityIsGood = true; + } + if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { + occupancyIsGood = true; + } + } + } + if (!hasSel8Coll) { return; } + registry.fill(HIST("h_mcColl_counts_areasub"), 4.5); - for (uint i = 0; i < cfgnMods->size(); i++) { - TRandom3 randomNumber(0); - float randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); - float randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); - float randomConePt = 0; + if (!centralityIsGood) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 5.5); - int nmode = cfgnMods->at(i); - int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); - int cfgNmodA = 2; - int cfgNmodB = 3; - if (nmode == cfgNmodA) { - double rcPhiPsi2; - float evtPl2 = helperEP.GetEventPlane(collision.qvecRe()[detInd], collision.qvecIm()[detInd], nmode); - rcPhiPsi2 = randomConePhi - evtPl2; + if (!occupancyIsGood) { + return; + } + registry.fill(HIST("h_mcColl_counts_areasub"), 6.5); + registry.fill(HIST("h_mcColl_rho"), mccollision.rho()); - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { - 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(); - } + for (auto const& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, jetEtaMin, jetEtaMax, trackEtaMin, trackEtaMax)) { + continue; + } + if (!isAcceptedJet(jet, mcLevelIsParticleLevel)) { + continue; + } + fillMCPAreaSubHistograms(jet, mccollision.rho()); + } + + double leadingJetPt = -1; + double leadingJetPhi = -1; + double leadingJetEta = -1; + int nTrk = 0; + for (auto const& collision : collisions) { + auto collTracks = tracks.sliceBy(tracksPerJCollision, collision.globalIndex()); + fillLeadingJetQAMCP(jets, leadingJetPt, leadingJetPhi, leadingJetEta); + + if (jets.size() > 0) { + for (auto const& track : collTracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + nTrk += 1; } } - // removing the leading jet from the random cone - if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet - float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); - float dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + } + if (nTrk <= 0) { + return; + } + hPtsumSumptFitMCP = new TH1F("h_ptsum_sumpt_fit", "h_ptsum_sumpt fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); - bool jetWasInCone = false; - while (std::sqrt(dEtaLeadingJet * dEtaLeadingJet + dPhiLeadingJet * dPhiLeadingJet) < jets.iteratorAt(0).r() / 100.0 + randomConeR) { - jetWasInCone = true; - randomConeEta = randomNumber.Uniform(trackEtaMin + randomConeR, trackEtaMax - randomConeR); - randomConePhi = randomNumber.Uniform(0.0, o2::constants::math::TwoPI); - dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, static_cast(-o2::constants::math::PI)); - dEtaLeadingJet = jets.iteratorAt(0).eta() - randomConeEta; + if (jets.size() > 0) { + for (auto const& track : collTracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + hPtsumSumptFitMCP->Fill(track.phi(), track.pt()); } - if (jetWasInCone) { - randomConePt = 0.0; - for (auto const& track : tracks) { - if (jetderiveddatautilities::selectTrack(track, trackSelection)) { - 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(); - } - } + } + } + fitFncMCP(collision, tracks, jets, hPtsumSumptFitMCP, leadingJetEta, mcLevelIsParticleLevel); + } + + delete hPtsumSumptFitMCP; + delete fFitModulationV2v3P; + evtnum += 1; + } + PROCESS_SWITCH(JetChargedV2, processSigmaPtMCP, "jet spectra with area-based subtraction for MC particle level", false); + + void processJetsMatchedSubtracted(McParticleCollision::iterator const& mccollision, + soa::SmallGroups> const& collisions, + ChargedMCDMatchedJets const& mcdjets, + ChargedMCPMatchedJets const&, + aod::JetTracks const& tracks, aod::JetParticles const&) + { + registry.fill(HIST("h_mc_collisions_matched"), 0.5); + if (mccollision.size() < 1) { + return; + } + registry.fill(HIST("h_mc_collisions_matched"), 1.5); + if (!(std::abs(mccollision.posZ()) < vertexZCut)) { + return; + } + registry.fill(HIST("h_mc_collisions_matched"), 2.5); + double mcrho = mccollision.rho(); + registry.fill(HIST("h_mc_rho_matched"), mcrho); + for (const auto& collision : collisions) { + registry.fill(HIST("h_mcd_events_matched"), 0.5); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents) || !(std::abs(collision.posZ()) < vertexZCut)) { + continue; + } + registry.fill(HIST("h_mcd_events_matched"), 1.5); + if (collision.centFT0M() < centralityMin || collision.centFT0M() > centralityMax) { + continue; + } + registry.fill(HIST("h_mcd_events_matched"), 2.5); + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + registry.fill(HIST("h_mcd_events_matched"), 3.5); + + auto collmcdjets = mcdjets.sliceBy(mcdjetsPerJCollision, collision.globalIndex()); + for (const auto& mcdjet : collmcdjets) { + if (!isAcceptedJet(mcdjet)) { + continue; + } + + double leadingJetPt = -1; + double leadingJetEta = -1; + + if (mcdjet.pt() > leadingJetPt) { + leadingJetPt = mcdjet.pt(); + leadingJetEta = mcdjet.eta(); + } + int nTrk = 0; + if (mcdjet.size() > 0) { + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + registry.fill(HIST("h_accept_Track"), 4.5); + nTrk += 1; } } } - registry.fill(HIST("h2_centrality_deltapT_RandomCornPhi_RCprocess_rhorandomconewithoutleadingjet"), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho(), rcPhiPsi2, 1.0); - } else if (nmode == cfgNmodB) { - continue; + if (nTrk <= 0) { + return; + } + hPtsumSumptFitRM = new TH1F("h_ptsum_sumpt_fit_RM", "h_ptsum_sumpt_RM fit use", TMath::CeilNint(std::sqrt(nTrk)), 0., o2::constants::math::TwoPI); + for (auto const& track : tracks) { + if (jetderiveddatautilities::selectTrack(track, trackSelection) && (std::fabs(track.eta() - leadingJetEta) > jetRadius) && track.pt() >= localRhoFitPtMin && track.pt() <= localRhoFitPtMax) { + registry.fill(HIST("h_accept_Track_Match"), 0.5); + hPtsumSumptFitRM->Fill(track.phi(), track.pt()); + } + } + + double ep2 = 0.; + double ep3 = 0.; + int cfgNmodA = 2; + int cfgNmodB = 3; + + for (uint i = 0; i < cfgnMods->size(); i++) { + int nmode = cfgnMods->at(i); + int detInd = detId * 4 + cfgnTotalSystem * 4 * (nmode - 2); + if (nmode == cfgNmodA) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep2 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } else if (nmode == cfgNmodB) { + if (collision.qvecAmp()[detId] > collQvecAmpDetId) { + ep3 = helperEP.GetEventPlane(collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3], nmode); + } + } + } + + const char* fitFunctionRM = "[0] * (1. + 2. * ([1] * std::cos(2. * (x - [2])) + [3] * std::cos(3. * (x - [4]))))"; + fFitModulationRM = new TF1("fit_kV3", fitFunctionRM, 0, o2::constants::math::TwoPI); + //=========================< set parameter >=========================// + fFitModulationRM->SetParameter(0, 1.); + fFitModulationRM->SetParameter(1, 0.01); + fFitModulationRM->SetParameter(3, 0.01); + + double ep2fix = 0.; + double ep3fix = 0.; + + if (ep2 < 0) { + ep2fix = RecoDecay::constrainAngle(ep2); + fFitModulationRM->FixParameter(2, ep2fix); + } else { + fFitModulationRM->FixParameter(2, ep2); + } + if (ep3 < 0) { + ep3fix = RecoDecay::constrainAngle(ep3); + fFitModulationRM->FixParameter(4, ep3fix); + } else { + fFitModulationRM->FixParameter(4, ep3); + } + + hPtsumSumptFitRM->Fit(fFitModulationRM, "Q", "ep", 0, o2::constants::math::TwoPI); + + float tempparaA; + tempparaA = fFitModulationRM->GetParameter(0); + + if (tempparaA == 0) { + return; + } + + fillGeoMatchedCorrHistograms(mcdjet, fFitModulationRM, tempparaA, ep2, collision.rho(), mcrho); + delete hPtsumSumptFitRM; + delete fFitModulationRM; + evtnum += 1; } } } - PROCESS_SWITCH(JetChargedV2, processRandomConeDataV2, "QA for random cone estimation of background fluctuations in data", true); + PROCESS_SWITCH(JetChargedV2, processJetsMatchedSubtracted, "matched mcp and mcd jets after subtraction", false); void processTracksQA(soa::Filtered>::iterator const& collision, soa::Filtered> const& tracks) { - registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 0.5); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { return; } - registry.fill(HIST("h_collisions"), 1.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 1.5); if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } - registry.fill(HIST("h_collisions"), 2.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); - fillTrackHistograms(collision, tracks); + for (auto const& track : tracks) { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + fillTrackHistograms(track); + } } PROCESS_SWITCH(JetChargedV2, processTracksQA, "QA for charged tracks", false); }; diff --git a/PWGJE/Tasks/jetFinderB0QA.cxx b/PWGJE/Tasks/jetFinderB0QA.cxx new file mode 100644 index 00000000000..8935968ac5b --- /dev/null +++ b/PWGJE/Tasks/jetFinderB0QA.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. + +// jet finder B0 charged QA task +// +/// \author Nima Zardoshti + +#include "PWGJE/Tasks/jetFinderHFQA.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + +using JetFinderB0QATask = JetFinderHFQATask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-charged-b0-qa"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/jetFinderBplusQA.cxx b/PWGJE/Tasks/jetFinderBplusQA.cxx index 4b7c42b4580..a713c3a767e 100644 --- a/PWGJE/Tasks/jetFinderBplusQA.cxx +++ b/PWGJE/Tasks/jetFinderBplusQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderBplusQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderD0QA.cxx b/PWGJE/Tasks/jetFinderD0QA.cxx index 2db58308d87..1ebe0ec649b 100644 --- a/PWGJE/Tasks/jetFinderD0QA.cxx +++ b/PWGJE/Tasks/jetFinderD0QA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderD0QATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderDielectronQA.cxx b/PWGJE/Tasks/jetFinderDielectronQA.cxx index 516f4501a7b..296ede5979a 100644 --- a/PWGJE/Tasks/jetFinderDielectronQA.cxx +++ b/PWGJE/Tasks/jetFinderDielectronQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderDielectronQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderDplusQA.cxx b/PWGJE/Tasks/jetFinderDplusQA.cxx index bf5468eae57..877cbf60d8a 100644 --- a/PWGJE/Tasks/jetFinderDplusQA.cxx +++ b/PWGJE/Tasks/jetFinderDplusQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderDplusQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderDstarQA.cxx b/PWGJE/Tasks/jetFinderDstarQA.cxx new file mode 100644 index 00000000000..b8fc0808521 --- /dev/null +++ b/PWGJE/Tasks/jetFinderDstarQA.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. + +// jet finder D* charged QA task +// +/// \author Nima Zardoshti + +#include "PWGJE/Tasks/jetFinderHFQA.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + +using JetFinderDstarQATask = JetFinderHFQATask; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-finder-charged-dstar-qa"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/jetFinderFullQA.cxx b/PWGJE/Tasks/jetFinderFullQA.cxx index 9b01d787959..85989036f3e 100644 --- a/PWGJE/Tasks/jetFinderFullQA.cxx +++ b/PWGJE/Tasks/jetFinderFullQA.cxx @@ -13,28 +13,35 @@ // /// \author Nima Zardoshti -#include "CommonConstants/PhysicsConstants.h" +#include "PWGJE/Core/JetDerivedDataUtilities.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" + #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 "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGHF/Core/HfHelper.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; -using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; @@ -245,7 +252,7 @@ struct JetFinderFullQATask { using JetTableMCPMatchedWeightedJoined = soa::Join; 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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); aod::EMCALClusterDefinition clusterDefinition = aod::emcalcluster::getClusterDefinitionFromString(clusterDefinitionS.value); Filter clusterFilter = (aod::jcluster::definition == static_cast(clusterDefinition) && aod::jcluster::eta > clusterEtaMin && aod::jcluster::eta < clusterEtaMax && aod::jcluster::phi >= clusterPhiMin && aod::jcluster::phi <= clusterPhiMax && aod::jcluster::energy >= clusterEnergyMin && aod::jcluster::time > clusterTimeMin && aod::jcluster::time < clusterTimeMax && (clusterRejectExotics && aod::jcluster::isExotic != true)); @@ -473,7 +480,7 @@ struct JetFinderFullQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderFullQATask, processJetsData, "jet finder HF QA data", false); @@ -487,7 +494,7 @@ struct JetFinderFullQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderFullQATask, processJetsMCD, "jet finder HF QA mcd", false); @@ -501,7 +508,7 @@ struct JetFinderFullQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality(), jet.eventWeight()); + fillHistograms(jet, collision.centFT0M(), jet.eventWeight()); } } PROCESS_SWITCH(JetFinderFullQATask, processJetsMCDWeighted, "jet finder HF QA mcd on weighted events", false); @@ -587,12 +594,12 @@ struct JetFinderFullQATask { return; } registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h_centrality_collisions"), collision.centrality(), 0.5); + registry.fill(HIST("h_centrality_collisions"), collision.centFT0M(), 0.5); if (!jetderiveddatautilities::eventEMCAL(collision)) { return; } registry.fill(HIST("h_collisions"), 1.5); - registry.fill(HIST("h_centrality_collisions"), collision.centrality(), 1.5); + registry.fill(HIST("h_centrality_collisions"), collision.centFT0M(), 1.5); fillTrackHistograms(tracks, clusters); } PROCESS_SWITCH(JetFinderFullQATask, processTracks, "QA for charged tracks", false); diff --git a/PWGJE/Tasks/jetFinderHFQA.cxx b/PWGJE/Tasks/jetFinderHFQA.cxx index a63cbef6563..fee889a62ea 100644 --- a/PWGJE/Tasks/jetFinderHFQA.cxx +++ b/PWGJE/Tasks/jetFinderHFQA.cxx @@ -13,31 +13,34 @@ // /// \author Nima Zardoshti -#include +#include "RecoDecay.h" + +#include "PWGHF/Core/HfHelper.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.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 "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::analysis; @@ -482,7 +485,7 @@ struct JetFinderHFQATask { using JetTableMCPMatchedWeightedJoined = soa::Join; 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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); // Filter candidateCutsD0 = (aod::hf_sel_candidate_d0::isSelD0 >= selectionFlagD0 || aod::hf_sel_candidate_d0::isSelD0bar >= selectionFlagD0bar); // Filter candidateCutsLc = (aod::hf_sel_candidate_lc::isSelLcToPKPi >= selectionFlagLcToPKPi || aod::hf_sel_candidate_lc::isSelLcToPiKP >= selectionFlagLcToPiPK); @@ -490,7 +493,9 @@ struct JetFinderHFQATask { PresliceOptional> perD0CandidateTracks = aod::bkgd0::candidateId; PresliceOptional> perDplusCandidateTracks = aod::bkgdplus::candidateId; + PresliceOptional> perDstarCandidateTracks = aod::bkgdstar::candidateId; PresliceOptional> perLcCandidateTracks = aod::bkglc::candidateId; + PresliceOptional> perB0CandidateTracks = aod::bkgb0::candidateId; PresliceOptional> perBplusCandidateTracks = aod::bkgbplus::candidateId; PresliceOptional> perDielectronCandidateTracks = aod::bkgdielectron::candidateId; @@ -940,8 +945,8 @@ struct JetFinderHFQATask { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } - registry.fill(HIST("h3_centrality_track_pt_track_phi"), collision.centrality(), track.pt(), track.phi(), weight); - registry.fill(HIST("h3_centrality_track_pt_track_eta"), collision.centrality(), track.pt(), track.eta(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_phi"), collision.centFT0M(), track.pt(), track.phi(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_eta"), collision.centFT0M(), track.pt(), track.eta(), weight); registry.fill(HIST("h3_track_pt_track_eta_track_phi"), track.pt(), track.eta(), track.phi(), weight); } } @@ -967,7 +972,7 @@ struct JetFinderHFQATask { } } } - registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * candidate.rho()); + registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * candidate.rho()); // removing the leading jet from the random cone if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet @@ -995,7 +1000,7 @@ struct JetFinderHFQATask { } } } - registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * candidate.rho()); + registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * candidate.rho()); break; // currently only fills it for the first candidate in the event (not pT ordered). Jet is pT ordered so results for excluding leading jet might not be as expected } } @@ -1014,7 +1019,7 @@ struct JetFinderHFQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsData, "jet finder HF QA data", false); @@ -1032,7 +1037,7 @@ struct JetFinderHFQATask { continue; } auto const candidate = jet.template candidates_first_as>(); - fillRhoAreaSubtractedHistograms(jet, collision.centrality(), candidate.rho()); + fillRhoAreaSubtractedHistograms(jet, collision.centFT0M(), candidate.rho()); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsRhoAreaSubData, "jet finder HF QA for rho-area subtracted jets", false); @@ -1050,7 +1055,7 @@ struct JetFinderHFQATask { continue; } auto const candidate = jet.template candidates_first_as>(); - fillRhoAreaSubtractedHistograms(jet, collision.centrality(), candidate.rho()); + fillRhoAreaSubtractedHistograms(jet, collision.centFT0M(), candidate.rho()); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsRhoAreaSubMCD, "jet finder HF QA for rho-area subtracted mcd jets", false); @@ -1064,7 +1069,7 @@ struct JetFinderHFQATask { if (!isAcceptedJet(jet)) { continue; } - fillEventWiseConstituentSubtractedHistograms(jet, collision.centrality()); + fillEventWiseConstituentSubtractedHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderHFQATask, processEvtWiseConstSubJetsData, "jet finder HF QA for eventwise constituent-subtracted jets data", false); @@ -1095,7 +1100,7 @@ struct JetFinderHFQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCD, "jet finder HF QA mcd", false); @@ -1109,7 +1114,7 @@ struct JetFinderHFQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality(), jet.eventWeight()); + fillHistograms(jet, collision.centFT0M(), jet.eventWeight()); } } PROCESS_SWITCH(JetFinderHFQATask, processJetsMCDWeighted, "jet finder HF QA mcd on weighted events", false); @@ -1477,12 +1482,12 @@ struct JetFinderHFQATask { return; } registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 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.centrality(), 1.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 1.5); fillTrackHistograms(collision, tracks); } PROCESS_SWITCH(JetFinderHFQATask, processTracks, "QA for charged tracks", false); @@ -1518,9 +1523,9 @@ struct JetFinderHFQATask { } for (auto const& candidate : candidates) { - for (auto const& track : jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0CandidateTracks, perDplusCandidateTracks, perLcCandidateTracks, perBplusCandidateTracks, perDielectronCandidateTracks)) { - registry.fill(HIST("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.phi()); - registry.fill(HIST("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.eta()); + for (auto const& track : jetcandidateutilities::slicedPerCandidate(tracks, candidate, perD0CandidateTracks, perDplusCandidateTracks, perDstarCandidateTracks, perLcCandidateTracks, perB0CandidateTracks, perBplusCandidateTracks, perDielectronCandidateTracks)) { + registry.fill(HIST("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted"), collision.centFT0M(), track.pt(), track.phi()); + registry.fill(HIST("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted"), collision.centFT0M(), track.pt(), track.eta()); registry.fill(HIST("h3_track_pt_track_eta_track_phi_eventwiseconstituentsubtracted"), track.pt(), track.eta(), track.phi()); } break; // currently only fills it for the first candidate in the event (not pT ordered) @@ -1543,11 +1548,11 @@ struct JetFinderHFQATask { nTracks++; } } - registry.fill(HIST("h2_centrality_ntracks"), collision.centrality(), nTracks); + registry.fill(HIST("h2_centrality_ntracks"), collision.centFT0M(), nTracks); registry.fill(HIST("h2_ntracks_rho"), nTracks, candidate.rho()); registry.fill(HIST("h2_ntracks_rhom"), nTracks, candidate.rhoM()); - registry.fill(HIST("h2_centrality_rho"), collision.centrality(), candidate.rho()); - registry.fill(HIST("h2_centrality_rhom"), collision.centrality(), candidate.rhoM()); + registry.fill(HIST("h2_centrality_rho"), collision.centFT0M(), candidate.rho()); + registry.fill(HIST("h2_centrality_rhom"), collision.centFT0M(), candidate.rhoM()); break; // currently only fills it for the first candidate in the event (not pT ordered) } } @@ -1579,7 +1584,7 @@ struct JetFinderHFQATask { registry.fill(HIST("h_candidate_pt"), candidate.pt()); registry.fill(HIST("h_candidate_y"), candidate.y()); } - registry.fill(HIST("h2_centrality_ncandidates"), collision.centrality(), candidates.size()); + registry.fill(HIST("h2_centrality_ncandidates"), collision.centFT0M(), candidates.size()); } PROCESS_SWITCH(JetFinderHFQATask, processCandidates, "HF candidate QA", false); }; diff --git a/PWGJE/Tasks/jetFinderLcQA.cxx b/PWGJE/Tasks/jetFinderLcQA.cxx index 311086c86c8..4986d583707 100644 --- a/PWGJE/Tasks/jetFinderLcQA.cxx +++ b/PWGJE/Tasks/jetFinderLcQA.cxx @@ -15,6 +15,16 @@ #include "PWGJE/Tasks/jetFinderHFQA.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include + +#include + using JetFinderLcQATask = JetFinderHFQATask; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetFinderQA.cxx b/PWGJE/Tasks/jetFinderQA.cxx index 1a6cd948200..4273efd027c 100644 --- a/PWGJE/Tasks/jetFinderQA.cxx +++ b/PWGJE/Tasks/jetFinderQA.cxx @@ -13,33 +13,34 @@ // /// \author Nima Zardoshti -#include -#include -#include -#include -#include +#include "RecoDecay.h" + +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; using namespace o2::framework; @@ -371,7 +372,7 @@ struct JetFinderQATask { } 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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); PresliceUnsorted> CollisionsPerMCPCollision = aod::jmccollisionlb::mcCollisionId; template @@ -677,9 +678,9 @@ struct JetFinderQATask { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } - registry.fill(HIST("h3_centrality_track_pt_track_phi"), collision.centrality(), track.pt(), track.phi(), weight); - registry.fill(HIST("h3_centrality_track_pt_track_eta"), collision.centrality(), track.pt(), track.eta(), weight); - registry.fill(HIST("h3_centrality_track_pt_track_dcaxy"), collision.centrality(), track.pt(), track.dcaXY(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_phi"), collision.centFT0M(), track.pt(), track.phi(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_eta"), collision.centFT0M(), track.pt(), track.eta(), weight); + registry.fill(HIST("h3_centrality_track_pt_track_dcaxy"), collision.centFT0M(), track.pt(), track.dcaXY(), weight); registry.fill(HIST("h3_track_pt_track_eta_track_phi"), track.pt(), track.eta(), track.phi(), weight); } } @@ -706,7 +707,7 @@ struct JetFinderQATask { } } } - registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomcone"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles randomConePt = 0; @@ -719,7 +720,7 @@ struct JetFinderQATask { } } } - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirection"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); // removing the leading jet from the random cone if (jets.size() > 0) { // if there are no jets in the acceptance (from the jetfinder cuts) then there can be no leading jet @@ -748,7 +749,7 @@ struct JetFinderQATask { } } - registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centrality(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconewithoutleadingjet"), collision.centFT0M(), randomConePt - M_PI * randomConeR * randomConeR * collision.rho()); // randomised eta,phi for tracks, to assess part of fluctuations coming from statistically independently emitted particles, removing tracks from 2 leading jets double randomConePtWithoutOneLeadJet = 0; @@ -767,8 +768,8 @@ struct JetFinderQATask { } } } - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets"), collision.centrality(), randomConePtWithoutOneLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); - registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), collision.centrality(), randomConePtWithoutTwoLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithoutoneleadingjets"), collision.centFT0M(), randomConePtWithoutOneLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("h2_centrality_rhorandomconerandomtrackdirectionwithouttwoleadingjets"), collision.centFT0M(), randomConePtWithoutTwoLeadJet - M_PI * randomConeR * randomConeR * collision.rho()); } void processJetsData(soa::Filtered::iterator const& collision, soa::Join const& jets, aod::JetTracks const&) @@ -783,7 +784,7 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), collision.hadronicRate()); + fillHistograms(jet, collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.hadronicRate()); } } PROCESS_SWITCH(JetFinderQATask, processJetsData, "jet finder QA data", false); @@ -802,7 +803,7 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillRhoAreaSubtractedHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), collision.rho()); + fillRhoAreaSubtractedHistograms(jet, collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.rho()); } } PROCESS_SWITCH(JetFinderQATask, processJetsRhoAreaSubData, "jet finder QA for rho-area subtracted jets", false); @@ -821,7 +822,7 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillRhoAreaSubtractedHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), collision.rho()); + fillRhoAreaSubtractedHistograms(jet, collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.rho()); } } PROCESS_SWITCH(JetFinderQATask, processJetsRhoAreaSubMCD, "jet finder QA for rho-area subtracted mcd jets", false); @@ -838,7 +839,7 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillEventWiseConstituentSubtractedHistograms(jet, collision.centrality()); + fillEventWiseConstituentSubtractedHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderQATask, processEvtWiseConstSubJetsData, "jet finder QA for eventwise constituent-subtracted jets data", false); @@ -855,7 +856,7 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillEventWiseConstituentSubtractedHistograms(jet, collision.centrality()); + fillEventWiseConstituentSubtractedHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderQATask, processEvtWiseConstSubJetsMCD, "jet finder QA for eventwise constituent-subtracted mcd jets", false); @@ -898,7 +899,7 @@ struct JetFinderQATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), collision.hadronicRate()); + fillHistograms(jet, collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.hadronicRate()); } } PROCESS_SWITCH(JetFinderQATask, processJetsMCD, "jet finder QA mcd", false); @@ -921,7 +922,7 @@ struct JetFinderQATask { registry.fill(HIST("h_jet_ptcut"), jet.pt(), N * 0.25, jet.eventWeight()); } } - fillHistograms(jet, collision.centrality(), collision.trackOccupancyInTimeRange(), collision.hadronicRate(), jet.eventWeight()); + fillHistograms(jet, collision.centFT0M(), collision.trackOccupancyInTimeRange(), collision.hadronicRate(), jet.eventWeight()); } } PROCESS_SWITCH(JetFinderQATask, processJetsMCDWeighted, "jet finder QA mcd with weighted events", false); @@ -1172,17 +1173,17 @@ struct JetFinderQATask { return; } registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 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.centrality(), 1.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 1.5); if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } registry.fill(HIST("h_collisions"), 2.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 2.5); fillTrackHistograms(collision, tracks); } PROCESS_SWITCH(JetFinderQATask, processTracks, "QA for charged tracks", false); @@ -1224,8 +1225,8 @@ struct JetFinderQATask { return; } for (auto const& track : tracks) { - registry.fill(HIST("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.phi()); - registry.fill(HIST("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted"), collision.centrality(), track.pt(), track.eta()); + registry.fill(HIST("h3_centrality_track_pt_track_phi_eventwiseconstituentsubtracted"), collision.centFT0M(), track.pt(), track.phi()); + registry.fill(HIST("h3_centrality_track_pt_track_eta_eventwiseconstituentsubtracted"), collision.centFT0M(), track.pt(), track.eta()); registry.fill(HIST("h3_track_pt_track_eta_track_phi_eventwiseconstituentsubtracted"), track.pt(), track.eta(), track.phi()); } } @@ -1248,11 +1249,11 @@ struct JetFinderQATask { nTracks++; } } - registry.fill(HIST("h2_centrality_ntracks"), collision.centrality(), nTracks); + registry.fill(HIST("h2_centrality_ntracks"), collision.centFT0M(), nTracks); registry.fill(HIST("h2_ntracks_rho"), nTracks, collision.rho()); registry.fill(HIST("h2_ntracks_rhom"), nTracks, collision.rhoM()); - registry.fill(HIST("h2_centrality_rho"), collision.centrality(), collision.rho()); - registry.fill(HIST("h2_centrality_rhom"), collision.centrality(), collision.rhoM()); + registry.fill(HIST("h2_centrality_rho"), collision.centFT0M(), collision.rho()); + registry.fill(HIST("h2_centrality_rhom"), collision.centFT0M(), collision.rhoM()); } PROCESS_SWITCH(JetFinderQATask, processRho, "QA for rho-area subtracted jets", false); diff --git a/PWGJE/Tasks/jetFinderV0QA.cxx b/PWGJE/Tasks/jetFinderV0QA.cxx index 9c681fa3bce..a80ee0eea25 100644 --- a/PWGJE/Tasks/jetFinderV0QA.cxx +++ b/PWGJE/Tasks/jetFinderV0QA.cxx @@ -13,37 +13,30 @@ // /// \author Nima Zardoshti -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.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 "PWGHF/Core/HfHelper.h" -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetV0Utilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include +#include +#include -#include "EventFiltering/filterTables.h" +#include using namespace o2; -using namespace o2::analysis; using namespace o2::framework; using namespace o2::framework::expressions; @@ -166,7 +159,7 @@ struct JetFinderV0QATask { using JetTableMCPMatchedWeightedJoined = soa::Join; 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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); template bool isAcceptedJet(V const& jet) @@ -299,10 +292,10 @@ struct JetFinderV0QATask { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } - registry.fill(HIST("h2_centrality_track_pt"), collision.centrality(), track.pt(), weight); - registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); - registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); - registry.fill(HIST("h2_centrality_track_energy"), collision.centrality(), track.energy(), weight); + registry.fill(HIST("h2_centrality_track_pt"), collision.centFT0M(), track.pt(), weight); + registry.fill(HIST("h2_centrality_track_eta"), collision.centFT0M(), track.eta(), weight); + registry.fill(HIST("h2_centrality_track_phi"), collision.centFT0M(), track.phi(), weight); + registry.fill(HIST("h2_centrality_track_energy"), collision.centFT0M(), track.energy(), weight); } } @@ -320,7 +313,7 @@ struct JetFinderV0QATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderV0QATask, processJetsData, "jet finder HF QA data", false); @@ -334,7 +327,7 @@ struct JetFinderV0QATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality()); + fillHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetFinderV0QATask, processJetsMCD, "jet finder HF QA mcd", false); @@ -348,7 +341,7 @@ struct JetFinderV0QATask { if (!isAcceptedJet(jet)) { continue; } - fillHistograms(jet, collision.centrality(), jet.eventWeight()); + fillHistograms(jet, collision.centFT0M(), jet.eventWeight()); } } PROCESS_SWITCH(JetFinderV0QATask, processJetsMCDWeighted, "jet finder HF QA mcd on weighted events", false); @@ -387,12 +380,12 @@ struct JetFinderV0QATask { soa::Filtered const& tracks) { registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 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.centrality(), 1.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 1.5); fillTrackHistograms(collision, tracks); } PROCESS_SWITCH(JetFinderV0QATask, processTracks, "QA for charged tracks", false); @@ -423,7 +416,7 @@ struct JetFinderV0QATask { registry.fill(HIST("h_candidate_pt"), candidate.pt()); registry.fill(HIST("h_candidate_y"), candidate.y()); } - registry.fill(HIST("h2_centrality_ncandidates"), collision.centrality(), candidates.size()); + registry.fill(HIST("h2_centrality_ncandidates"), collision.centFT0M(), candidates.size()); } PROCESS_SWITCH(JetFinderV0QATask, processCandidates, "HF candidate QA", false); }; diff --git a/PWGJE/Tasks/jetFragmentation.cxx b/PWGJE/Tasks/jetFragmentation.cxx index 18d5dea2c56..5a6104ad872 100644 --- a/PWGJE/Tasks/jetFragmentation.cxx +++ b/PWGJE/Tasks/jetFragmentation.cxx @@ -14,27 +14,35 @@ /// /// \author Gijs van Weelden -#include -#include -#include "TH1F.h" -#include "TTree.h" +#include "JetDerivedDataUtilities.h" +#include "RecoDecay.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "CommonConstants/PhysicsConstants.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGLF/DataModel/V0SelectorTables.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -77,6 +85,15 @@ struct JetFragmentation { Configurable nV0Classes{"nV0Classes", 2, "Must be 2 or 4! Number of V0 signal/bkg classes"}; Configurable doCorrectionWithTracks{"doCorrectionWithTracks", false, "add tracks during background subtraction"}; + Configurable> ptBinsK0S{"ptBinsK0S", {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 40.0}, "K0S pt Vals"}; + Configurable> ptBinsLambda{"ptBinsLambda", {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0, 25.0}, "Lambda pt Vals"}; + Configurable> ptBinsAntiLambda{"ptBinsAntiLambda", {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0, 25.0}, "AntiLambda pt Vals"}; + + // NB: these must be one shorter than ptbin vectors! + Configurable> signalProbK0S{"signalProbK0S", {0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "K0S signal probability per pt bin"}; + Configurable> signalProbLambda{"signalProbLambda", {0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "Lambda signal probability per pt bin"}; + Configurable> signalProbAntiLambda{"signalProbAntiLambda", {0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9}, "AntiLambda signal probability per pt bin"}; + Configurable vertexZCut{"vertexZCut", 10.f, "vertex z cut"}; Configurable v0EtaMin{"v0EtaMin", -0.75, "minimum data V0 eta"}; Configurable v0EtaMax{"v0EtaMax", 0.75, "maximum data V0 eta"}; @@ -124,7 +141,7 @@ struct JetFragmentation { ConfigurableAxis binK0SMass{"binK0SMass", {400, 0.400f, 0.600f}, "Inv. Mass (GeV/c^{2})"}; ConfigurableAxis binK0SMassWide{"binK0SMassWide", {400, 0.400f, 0.800f}, "Inv. Mass (GeV/c^{2})"}; // Wider version for high pt - ConfigurableAxis binLambdaMass{"binLambdaMass", {200, 1.015f, 1.215f}, "Inv. Mass (GeV/c^{2})"}; + ConfigurableAxis binLambdaMass{"binLambdaMass", {200, 1.075f, 1.215f}, "Inv. Mass (GeV/c^{2})"}; ConfigurableAxis binLambdaMassDiff{"binLambdaMassDiff", {200, -0.199f, 0.201f}, "M(#Lambda) - M(#bar{#Lambda})"}; ConfigurableAxis binLambdaMassRatio{"binLambdaMassRatio", {50, -0.05f, 4.95f}, "M(#bar{#Lambda}) / M(#Lambda)"}; ConfigurableAxis binLambdaMassRelDiff{"binLambdaMassRelDiff", {200, -0.995f, 1.005f}, "(M(#Lambda) - M(#bar{#Lambda})) / M(#Lambda)"}; @@ -769,8 +786,15 @@ struct JetFragmentation { registry.add("matching/jets/V0/missJetPtV0TrackProj", "Misses", HistType::kTH2D, {partJetPtAxis, partZAxis}, true); // Matching - Matched K0S - registry.add("matching/jets/V0/matchDetJetPtK0STrackProjPartJetPtK0STrackProj", "Matched", HistType::kTHnSparseD, {detJetPtAxis, detZAxis, partJetPtAxis, partZAxis}, true); - registry.add("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPt", "matched jet Pt, K_{S}^{0} Pt", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPt", "Matched Pt and pt", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProj", "Matched pt and z", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + + registry.add("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtRightCollision", "Matched Pt, right collision", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProjRightCollision", "Matched pt and z, right collision", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + + registry.add("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtWrongCollision", "Matched Pt, wrong collision", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProjWrongCollision", "Matched pt and z, wrong collision", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + // Matching - Matched K0S: pt registry.add("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtCtauLambda", "matched jet Pt, K^{0}_{S} Pt, Ctau #Lambda^{0}", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis, v0CtauAxis}, true); registry.add("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtCtauAntiLambda", "matched jet Pt, K^{0}_{S} Pt, Ctau #bar{#Lambda}^{0}", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis, v0CtauAxis}, true); @@ -816,8 +840,15 @@ struct JetFragmentation { registry.add("matching/jets/V0/missJetPtK0STrackProj", "Misses", HistType::kTH2D, {partJetPtAxis, partZAxis}, true); // Matching - Matched Lambda - registry.add("matching/jets/V0/matchDetJetPtLambdaTrackProjPartJetPtLambdaTrackProj", "Matched", HistType::kTHnSparseD, {detJetPtAxis, detZAxis, partJetPtAxis, partZAxis}, true); - registry.add("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPt", "matched jet Pt, #Lambda^{0} Pt", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPt", "matched Pt", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtLambdaTrackProjDetJetPtLambdaTrackProj", "Matched pt and z", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + + registry.add("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtRightCollision", "matched Pt, right collision", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtLambdaTrackProjDetJetPtLambdaTrackProjRightCollision", "Matched pt and z, right collision", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + + registry.add("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtWrongCollision", "matched Pt, Wrong collision", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtLambdaTrackProjDetJetPtLambdaTrackProjWrongCollision", "Matched pt and z, Wrong collision", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + // Matching - Matched Lambda: pt registry.add("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtCtauK0S", "matched jet Pt, #{K}^{0}_{S} Pt, Ctau #{K}^{0}_{S}", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis, v0CtauAxis}, true); registry.add("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtCtauLambda", "matched jet Pt, #Lambda^{0} Pt, Ctau #Lambda^{0}", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis, v0CtauAxis}, true); @@ -866,8 +897,15 @@ struct JetFragmentation { registry.add("matching/jets/V0/missJetPtLambdaTrackProj", "Misses", HistType::kTH2D, {partJetPtAxis, partZAxis}, true); // Matching - Matched AntiLambda - registry.add("matching/jets/V0/matchDetJetPtAntiLambdaTrackProjPartJetPtAntiLambdaTrackProj", "Matched", HistType::kTHnSparseD, {detJetPtAxis, detZAxis, partJetPtAxis, partZAxis}, true); - registry.add("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPt", "matched jet Pt, #bar{#Lambda}^{0} Pt", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPt", "matched Pt", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtAntiLambdaTrackProjDetJetPtAntiLambdaTrackProj", "Matched pt and z", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + + registry.add("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtRightCollision", "matched Pt, right collision", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtAntiLambdaTrackProjDetJetPtAntiLambdaTrackProjRightCollision", "Matched pt and z, right collision", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + + registry.add("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtWrongCollision", "matched Pt, Wrong collision", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis}, true); + registry.add("matching/jets/V0/partJetPtAntiLambdaTrackProjDetJetPtAntiLambdaTrackProjWrongCollision", "Matched pt and z, Wrong collision", HistType::kTHnSparseD, {partJetPtAxis, partZAxis, detJetPtAxis, detZAxis}, true); + // Matching - Matched AntiLambda: pt registry.add("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtCtauK0S", "matched jet Pt, #{K}^{0}_{S} Pt, Ctau #{K}^{0}_{S}", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis, v0CtauAxis}, true); registry.add("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtCtauLambda", "matched jet Pt, #bar{#Lambda}^{0} Pt, Ctau #Lambda^{0}", HistType::kTHnSparseD, {partJetPtAxis, v0PtAxis, detJetPtAxis, v0PtAxis, v0CtauAxis}, true); @@ -1064,26 +1102,45 @@ struct JetFragmentation { // Implementation of background subtraction at runtime // --------------------------------------------------- - // Return probability for a V0 to be signal (or background) + int getPtBin(float pt, std::vector ptBins) + { + if (pt < ptBins.at(0)) + return -1; + if (pt > ptBins.at(ptBins.size() - 1)) + return -2; + + for (unsigned int i = 0; i < ptBins.size() - 1; i++) { + if (pt >= ptBins.at(i) && pt < ptBins.at(i + 1)) { + return i; + } + } + return -3; + } + + // Return probability for a V0 to be signal + // Assumes V0 can only be of one type! + // Assumes V0 is not rejected! template float getV0SignalProb(V const& v0) { - // TODO: This is filled with dummy values for now - // Assumes a V0 can only be of one type! - // Should be made to return purity for a V0 based on species and pt + double purity = 0.; if (v0.isK0SCandidate()) { - // return 1.; - return 0.5; - } - if (v0.isLambdaCandidate()) { - // return 1.; - return 0.5; - } - if (v0.isAntiLambdaCandidate()) { - // return 1.; - return 0.5; + int ptBin = getPtBin(v0.pt(), ptBinsK0S); + if (ptBin >= 0) { + purity = signalProbK0S->at(ptBin); + } + } else if (v0.isLambdaCandidate()) { + int ptBin = getPtBin(v0.pt(), ptBinsLambda); + if (ptBin >= 0) { + purity = signalProbLambda->at(ptBin); + } + } else if (v0.isAntiLambdaCandidate()) { + int ptBin = getPtBin(v0.pt(), ptBinsAntiLambda); + if (ptBin >= 0) { + purity = signalProbAntiLambda->at(ptBin); + } } - return 0.; // Background + return purity; } // Return a 2-length std::vector of probabilities for a particle to correspond to signal or background template @@ -1264,20 +1321,17 @@ struct JetFragmentation { // If V0 is Lambda, posTrack = proton, negTrack = pion // In that case, we assign pion mass to posTrack and proton mass to negTrack to calculate the reflection // Vice versa for AntiLambda - double negM = (isLambda ? constants::physics::MassProton : constants::physics::MassPionCharged); - double posM = (isLambda ? constants::physics::MassPionCharged : constants::physics::MassProton); - double negPsq = v0.pxneg() * v0.pxneg() + v0.pyneg() * v0.pyneg() + v0.pzneg() * v0.pzneg(); - double posPsq = v0.pxpos() * v0.pxpos() + v0.pypos() * v0.pypos() + v0.pzpos() * v0.pzpos(); - double negE = std::sqrt(negM * negM + negPsq); - double posE = std::sqrt(posM * posM + posPsq); - double Esquared = (negE + posE) * (negE + posE); - double psquared = v0.p() * v0.p(); - return std::sqrt(Esquared - psquared); + float negM = (isLambda ? constants::physics::MassProton : constants::physics::MassPionCharged); + float posM = (isLambda ? constants::physics::MassPionCharged : constants::physics::MassProton); + std::array, 2> momenta = {std::array{v0.pxpos(), v0.pypos(), v0.pzpos()}, std::array{v0.pxneg(), v0.pyneg(), v0.pzneg()}}; + std::array masses = {posM, negM}; + return RecoDecay::m(momenta, masses); } template double getMomFrac(Jet const& jet, Constituent const& constituent) { - if (jet.pt() < 1e-5) + double divByZeroProtect = 1e-5; + if (jet.pt() < divByZeroProtect) return -1.; else return constituent.pt() / jet.pt(); @@ -1285,7 +1339,8 @@ struct JetFragmentation { template double getMomProj(Jet const& jet, Constituent const& constituent) { - if (jet.p() < 1e-5) + double divByZeroProtect = 1e-5; + if (jet.p() < divByZeroProtect) return -1.; double trackProj = constituent.px() * jet.px() + constituent.py() * jet.py() + constituent.pz() * jet.pz(); @@ -1500,18 +1555,21 @@ struct JetFragmentation { template void fillDataPerpConeHists(T const& coll, U const& jet, V const& v0s) { + const int nCones = 2; double perpConeR = jet.r() * 1e-2; - double conePhi[2] = {RecoDecay::constrainAngle(jet.phi() - constants::math::PIHalf, -constants::math::PI), - RecoDecay::constrainAngle(jet.phi() + constants::math::PIHalf, -constants::math::PI)}; - double conePt[2] = {0., 0.}; - int nV0sinCone[2] = {0, 0}; + double conePhi[nCones] = {RecoDecay::constrainAngle(jet.phi() - constants::math::PIHalf, -constants::math::PI), + RecoDecay::constrainAngle(jet.phi() + constants::math::PIHalf, -constants::math::PI)}; + double conePt[nCones] = {0., 0.}; + int nV0sinCone[nCones] = {0, 0}; for (const auto& v0 : v0s) { - // Need to check if v0 passed jet finder selection/preselector cuts + if (v0.isRejectedCandidate()) + continue; + bool v0InCones = false; double dEta = v0.eta() - jet.eta(); - double dPhi[2] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -constants::math::PI), - RecoDecay::constrainAngle(v0.phi() - conePhi[1], -constants::math::PI)}; - for (int i = 0; i < 2; i++) { + double dPhi[nCones] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -constants::math::PI), + RecoDecay::constrainAngle(v0.phi() - conePhi[1], -constants::math::PI)}; + for (int i = 0; i < nCones; i++) { if (std::sqrt(dEta * dEta + dPhi[i] * dPhi[i]) < perpConeR) { conePt[i] += v0.pt(); nV0sinCone[i]++; @@ -1566,8 +1624,8 @@ struct JetFragmentation { registry.fill(HIST("data/PC/K0SPtDCAd"), v0.pt(), v0.dcaV0daughters()); } } - // Fill hist for Ncones: nv0s, conePt, coneEta, conePhi - for (int i = 0; i < 2; i++) { + // Fill hist for nCones: nv0s, conePt, coneEta, conePhi + for (int i = 0; i < nCones; i++) { registry.fill(HIST("data/PC/nV0sConePtEta"), nV0sinCone[i], conePt[i], jet.eta()); registry.fill(HIST("data/PC/ConePtEtaPhi"), conePt[i], jet.eta(), conePhi[i]); registry.fill(HIST("data/PC/JetPtEtaConePt"), jet.pt(), jet.eta(), conePt[i]); @@ -1767,13 +1825,13 @@ struct JetFragmentation { int pdg = pv0.pdgCode(); nV0s += 1; registry.fill(HIST("mcp/V0/V0PtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); - if (std::abs(pdg) == 310) + if (std::abs(pdg) == PDG_t::kK0Short) registry.fill(HIST("mcp/V0/K0SPtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); - if (pdg == 3122) + if (pdg == PDG_t::kLambda0) registry.fill(HIST("mcp/V0/LambdaPtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); - if (pdg == -3122) + if (pdg == PDG_t::kLambda0Bar) registry.fill(HIST("mcp/V0/AntiLambdaPtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); } registry.fill(HIST("mcp/V0/nV0sEventAcc"), nV0s); @@ -1863,19 +1921,20 @@ struct JetFragmentation { template void fillMcPerpConeHists(T const& coll, U const& mcdjet, V const& v0s, W const& /* V0 particles */, double weight = 1.) { + const int nCones = 2; double perpConeR = mcdjet.r() * 1e-2; - double conePhi[2] = {RecoDecay::constrainAngle(mcdjet.phi() - constants::math::PIHalf, -constants::math::PI), - RecoDecay::constrainAngle(mcdjet.phi() + constants::math::PIHalf, -constants::math::PI)}; - double coneMatchedPt[2] = {0., 0.}; - double coneFakePt[2] = {0., 0.}; - int nMatchedV0sinCone[2] = {0, 0}; - int nFakeV0sinCone[2] = {0, 0}; + double conePhi[nCones] = {RecoDecay::constrainAngle(mcdjet.phi() - constants::math::PIHalf, -constants::math::PI), + RecoDecay::constrainAngle(mcdjet.phi() + constants::math::PIHalf, -constants::math::PI)}; + double coneMatchedPt[nCones] = {0., 0.}; + double coneFakePt[nCones] = {0., 0.}; + int nMatchedV0sinCone[nCones] = {0, 0}; + int nFakeV0sinCone[nCones] = {0, 0}; for (const auto& v0 : v0s) { double dEta = v0.eta() - mcdjet.eta(); - double dPhi[2] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -constants::math::PI), - RecoDecay::constrainAngle(v0.phi() - conePhi[1], -constants::math::PI)}; - for (int i = 0; i < 2; i++) { + double dPhi[nCones] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -constants::math::PI), + RecoDecay::constrainAngle(v0.phi() - conePhi[1], -constants::math::PI)}; + for (int i = 0; i < nCones; i++) { if (std::sqrt(dEta * dEta + dPhi[i] * dPhi[i]) > perpConeR) { continue; } @@ -1908,17 +1967,17 @@ struct JetFragmentation { registry.fill(HIST("mcd/PC/matchedV0PtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); auto particle = v0.template mcParticle_as(); - if (std::abs(particle.pdgCode()) == 310) { // K0S + if (std::abs(particle.pdgCode()) == PDG_t::kK0Short) { // K0S registry.fill(HIST("mcd/PC/matchedJetPtK0SPtMass"), mcdjet.pt(), v0.pt(), v0.mK0Short(), weight); - } else if (particle.pdgCode() == 3122) { // Lambda + } else if (particle.pdgCode() == PDG_t::kLambda0) { // Lambda registry.fill(HIST("mcd/PC/matchedJetPtLambdaPtMass"), mcdjet.pt(), v0.pt(), v0.mLambda(), weight); - } else if (particle.pdgCode() == -3122) { + } else if (particle.pdgCode() == PDG_t::kLambda0Bar) { registry.fill(HIST("mcd/PC/matchedJetPtAntiLambdaPtMass"), mcdjet.pt(), v0.pt(), v0.mAntiLambda(), weight); } } // if v0 has mcParticle } // for cone } // for v0s - for (int i = 0; i < 2; i++) { + for (int i = 0; i < nCones; i++) { registry.fill(HIST("mcd/PC/matchednV0sConePtEta"), nMatchedV0sinCone[i], coneMatchedPt[i], mcdjet.eta(), weight); registry.fill(HIST("mcd/PC/matchedConePtEtaPhi"), coneMatchedPt[i], mcdjet.eta(), conePhi[i], weight); registry.fill(HIST("mcd/PC/matchedJetPtEtaConePt"), mcdjet.pt(), mcdjet.eta(), coneMatchedPt[i], weight); @@ -1932,19 +1991,20 @@ struct JetFragmentation { template void fillMcPerpConeHists(T const& coll, U const& mcdjet, V const& mcpjet, W const& v0s, X const& /* V0 particles */, double weight = 1.) { + const int nCones = 2; double perpConeR = mcdjet.r() * 1e-2; - double conePhi[2] = {RecoDecay::constrainAngle(mcdjet.phi() - constants::math::PIHalf, -constants::math::PI), - RecoDecay::constrainAngle(mcdjet.phi() + constants::math::PIHalf, -constants::math::PI)}; - double coneMatchedPt[2] = {0., 0.}; - double coneFakePt[2] = {0., 0.}; - int nMatchedV0sinCone[2] = {0, 0}; - int nFakeV0sinCone[2] = {0, 0}; + double conePhi[nCones] = {RecoDecay::constrainAngle(mcdjet.phi() - constants::math::PIHalf, -constants::math::PI), + RecoDecay::constrainAngle(mcdjet.phi() + constants::math::PIHalf, -constants::math::PI)}; + double coneMatchedPt[nCones] = {0., 0.}; + double coneFakePt[nCones] = {0., 0.}; + int nMatchedV0sinCone[nCones] = {0, 0}; + int nFakeV0sinCone[nCones] = {0, 0}; for (const auto& v0 : v0s) { double dEta = v0.eta() - mcdjet.eta(); - double dPhi[2] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -constants::math::PI), - RecoDecay::constrainAngle(v0.phi() - conePhi[1], -constants::math::PI)}; - for (int i = 0; i < 2; i++) { + double dPhi[nCones] = {RecoDecay::constrainAngle(v0.phi() - conePhi[0], -constants::math::PI), + RecoDecay::constrainAngle(v0.phi() - conePhi[1], -constants::math::PI)}; + for (int i = 0; i < nCones; i++) { if (std::sqrt(dEta * dEta + dPhi[i] * dPhi[i]) > perpConeR) { continue; } @@ -1979,20 +2039,20 @@ struct JetFragmentation { registry.fill(HIST("matching/PC/matchedV0PtDCAd"), v0.pt(), v0.dcaV0daughters(), weight); auto particle = v0.template mcParticle_as(); - if (std::abs(particle.pdgCode()) == 310) { // K0S + if (std::abs(particle.pdgCode()) == PDG_t::kK0Short) { // K0S registry.fill(HIST("matching/PC/matchedJetPtK0SPtMass"), mcdjet.pt(), v0.pt(), v0.mK0Short(), weight); registry.fill(HIST("matching/PC/matchedJetsPtK0SPtMass"), mcpjet.pt(), mcdjet.pt(), v0.pt(), v0.mK0Short(), weight); - } else if (particle.pdgCode() == 3122) { // Lambda + } else if (particle.pdgCode() == PDG_t::kLambda0) { // Lambda registry.fill(HIST("matching/PC/matchedJetPtLambdaPtMass"), mcdjet.pt(), v0.pt(), v0.mLambda(), weight); registry.fill(HIST("matching/PC/matchedJetsPtLambdaPtMass"), mcpjet.pt(), mcdjet.pt(), v0.pt(), v0.mLambda(), weight); - } else if (particle.pdgCode() == -3122) { + } else if (particle.pdgCode() == PDG_t::kLambda0Bar) { registry.fill(HIST("matching/PC/matchedJetPtAntiLambdaPtMass"), mcdjet.pt(), v0.pt(), v0.mAntiLambda(), weight); registry.fill(HIST("matching/PC/matchedJetsPtAntiLambdaPtMass"), mcpjet.pt(), mcdjet.pt(), v0.pt(), v0.mAntiLambda(), weight); } } // if v0 has mcParticle } // for cone } // for v0s - for (int i = 0; i < 2; i++) { + for (int i = 0; i < nCones; i++) { registry.fill(HIST("matching/PC/matchednV0sConePtEta"), nMatchedV0sinCone[i], coneMatchedPt[i], mcdjet.eta(), weight); registry.fill(HIST("matching/PC/matchedConePtEtaPhi"), coneMatchedPt[i], mcdjet.eta(), conePhi[i], weight); registry.fill(HIST("matching/PC/matchedJetPtEtaConePt"), mcdjet.pt(), mcdjet.eta(), coneMatchedPt[i], weight); @@ -2015,14 +2075,14 @@ struct JetFragmentation { registry.fill(HIST("matching/V0/V0PartPtDetPt"), particle.pt(), v0.pt(), weight); registry.fill(HIST("matching/V0/V0PartPtRatioPtRelDiffPt"), particle.pt(), v0.pt() / particle.pt(), (v0.pt() - particle.pt()) / particle.pt(), weight); - if (std::abs(particle.pdgCode()) == 310) { // K0S + if (std::abs(particle.pdgCode()) == PDG_t::kK0Short) { // K0S registry.fill(HIST("matching/V0/K0SPtEtaPhi"), particle.pt(), v0.pt(), v0.eta(), v0.phi(), weight); registry.fill(HIST("matching/V0/K0SPtCtauMass"), particle.pt(), v0.pt(), ctauK0s, v0.mK0Short(), weight); registry.fill(HIST("matching/V0/K0SPtRadiusCosPA"), particle.pt(), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); registry.fill(HIST("matching/V0/K0SPtDCAposneg"), particle.pt(), v0.pt(), v0.dcapostopv(), v0.dcanegtopv(), weight); registry.fill(HIST("matching/V0/K0SPtDCAd"), particle.pt(), v0.pt(), v0.dcaV0daughters(), weight); registry.fill(HIST("matching/V0/K0SPtMass"), particle.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); - } else if (particle.pdgCode() == 3122) { // Lambda + } else if (particle.pdgCode() == PDG_t::kLambda0) { // Lambda registry.fill(HIST("matching/V0/LambdaPtEtaPhi"), particle.pt(), v0.pt(), v0.eta(), v0.phi(), weight); registry.fill(HIST("matching/V0/LambdaPtCtauMass"), particle.pt(), v0.pt(), ctauLambda, v0.mLambda(), weight); registry.fill(HIST("matching/V0/LambdaPtRadiusCosPA"), particle.pt(), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); @@ -2033,7 +2093,7 @@ struct JetFragmentation { // Reflection double reflectedMass = getReflectedMass(v0, true); registry.fill(HIST("matching/V0/LambdaReflection"), particle.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), reflectedMass, weight); - } else if (particle.pdgCode() == -3122) { // AntiLambda + } else if (particle.pdgCode() == PDG_t::kLambda0Bar) { // AntiLambda registry.fill(HIST("matching/V0/AntiLambdaPtEtaPhi"), particle.pt(), v0.pt(), v0.eta(), v0.phi(), weight); registry.fill(HIST("matching/V0/AntiLambdaPtCtauMass"), particle.pt(), v0.pt(), ctauAntiLambda, v0.mAntiLambda(), weight); registry.fill(HIST("matching/V0/AntiLambdaPtRadiusCosPA"), particle.pt(), v0.pt(), v0.v0radius(), v0.v0cosPA(), weight); @@ -2056,11 +2116,11 @@ struct JetFragmentation { registry.fill(HIST("matching/V0/V0PosPartPtRatioPtRelDiffPt"), posPart.pt(), posTrack.pt() / posPart.pt(), (posTrack.pt() - posPart.pt()) / posPart.pt(), weight); registry.fill(HIST("matching/V0/V0NegPartPtRatioPtRelDiffPt"), negPart.pt(), negTrack.pt() / negPart.pt(), (negTrack.pt() - negPart.pt()) / negPart.pt(), weight); - if (std::abs(v0.pdgCode()) == 310) { // K0S + if (std::abs(v0.pdgCode()) == PDG_t::kK0Short) { // K0S registry.fill(HIST("matching/V0/K0SPosNegPtMass"), pv0.pt(), posPart.pt(), negPart.pt(), v0.mK0Short(), weight); - } else if (v0.pdgCode() == 3122) { // Lambda + } else if (v0.pdgCode() == PDG_t::kLambda0) { // Lambda registry.fill(HIST("matching/V0/LambdaPosNegPtMass"), pv0.pt(), posPart.pt(), negPart.pt(), v0.mLambda(), weight); - } else if (v0.pdgCode() == -3122) { // AntiLambda + } else if (v0.pdgCode() == PDG_t::kLambda0Bar) { // AntiLambda registry.fill(HIST("matching/V0/AntiLambdaPosNegPtMass"), pv0.pt(), posPart.pt(), negPart.pt(), v0.mAntiLambda(), weight); } } @@ -2086,6 +2146,7 @@ struct JetFragmentation { template // Reconstructed signal for in-jet V0s void fillMatchingV0FragHistograms(CollisionType const& collision, DetJetType const& detJet, PartJetType const& partJet, V0Type const& v0, ParticleType const& particle, double weight = 1.) { + bool correctCollision = (collision.mcCollisionId() == particle.mcCollisionId()); double detTrackProj = getMomFrac(detJet, v0); double partTrackProj = getMomFrac(partJet, particle); @@ -2120,9 +2181,16 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/V0/partJetPtV0TrackProjDetJetPtV0TrackProjDCAposneg"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.dcapostopv(), v0.dcanegtopv(), weight); registry.fill(HIST("matching/jets/V0/partJetPtV0TrackProjDetJetPtV0TrackProjDCAd"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.dcaV0daughters(), weight); - if (std::abs(particle.pdgCode()) == 310) { // K0S - registry.fill(HIST("matching/jets/V0/matchDetJetPtK0STrackProjPartJetPtK0STrackProj"), detJet.pt(), detTrackProj, partJet.pt(), partTrackProj, weight); + if (std::abs(particle.pdgCode()) == PDG_t::kK0Short) { // K0S registry.fill(HIST("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPt"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProj"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + if (correctCollision) { + registry.fill(HIST("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtRightCollision"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProjRightCollision"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + } else { + registry.fill(HIST("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtWrongCollision"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProjWrongCollision"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + } registry.fill(HIST("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtCtauLambda"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), ctauLambda, weight); registry.fill(HIST("matching/jets/V0/partJetPtK0SPtDetJetPtK0SPtCtauAntiLambda"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), ctauAntiLambda, weight); @@ -2147,9 +2215,16 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProjCosPA"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.v0cosPA(), weight); registry.fill(HIST("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProjDCAposneg"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.dcapostopv(), v0.dcanegtopv(), weight); registry.fill(HIST("matching/jets/V0/partJetPtK0STrackProjDetJetPtK0STrackProjDCAd"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.dcaV0daughters(), weight); - } else if (particle.pdgCode() == 3122) { // Lambda - registry.fill(HIST("matching/jets/V0/matchDetJetPtLambdaTrackProjPartJetPtLambdaTrackProj"), detJet.pt(), detTrackProj, partJet.pt(), partTrackProj, weight); + } else if (particle.pdgCode() == PDG_t::kLambda0) { // Lambda registry.fill(HIST("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPt"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtLambdaTrackProjDetJetPtLambdaTrackProj"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + if (correctCollision) { + registry.fill(HIST("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtRightCollision"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtLambdaTrackProjDetJetPtLambdaTrackProjRightCollision"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + } else { + registry.fill(HIST("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtWrongCollision"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtLambdaTrackProjDetJetPtLambdaTrackProjWrongCollision"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + } registry.fill(HIST("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtCtauLambda"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), ctauLambda, weight); registry.fill(HIST("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtCtauAntiLambda"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), ctauAntiLambda, weight); @@ -2179,9 +2254,16 @@ struct JetFragmentation { double reflectedMass = getReflectedMass(v0, true); registry.fill(HIST("matching/jets/V0/partJetPtLambdaPtDetJetPtLambdaPtLambdaReflection"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), reflectedMass, weight); registry.fill(HIST("matching/jets/V0/partJetPtLambdaTrackProjDetJetPtLambdaTrackProjLambdaReflection"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), reflectedMass, weight); - } else if (particle.pdgCode() == -3122) { // AntiLambda - registry.fill(HIST("matching/jets/V0/matchDetJetPtAntiLambdaTrackProjPartJetPtAntiLambdaTrackProj"), detJet.pt(), detTrackProj, partJet.pt(), partTrackProj, weight); + } else if (particle.pdgCode() == PDG_t::kLambda0Bar) { // AntiLambda registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPt"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaTrackProjDetJetPtAntiLambdaTrackProj"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + if (correctCollision) { + registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtRightCollision"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaTrackProjDetJetPtAntiLambdaTrackProjRightCollision"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + } else { + registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtWrongCollision"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), weight); + registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaTrackProjDetJetPtAntiLambdaTrackProjWrongCollision"), partJet.pt(), partTrackProj, detJet.pt(), detTrackProj, weight); + } registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtCtauLambda"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), ctauLambda, weight); registry.fill(HIST("matching/jets/V0/partJetPtAntiLambdaPtDetJetPtAntiLambdaPtCtauAntiLambda"), partJet.pt(), particle.pt(), detJet.pt(), v0.pt(), ctauAntiLambda, weight); @@ -2229,11 +2311,11 @@ struct JetFragmentation { { int pdg = pv0.pdgCode(); registry.fill(HIST("matching/V0/missV0PtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); - if (std::abs(pdg) == 310) { // K0S + if (std::abs(pdg) == PDG_t::kK0Short) { // K0S registry.fill(HIST("matching/V0/missK0SPtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); - } else if (pdg == 3122) { // Lambda + } else if (pdg == PDG_t::kLambda0) { // Lambda registry.fill(HIST("matching/V0/missLambdaPtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); - } else if (pdg == -3122) { // AntiLambda + } else if (pdg == PDG_t::kLambda0Bar) { // AntiLambda registry.fill(HIST("matching/V0/missAntiLambdaPtEtaPhi"), pv0.pt(), pv0.eta(), pv0.phi(), weight); } } @@ -2244,13 +2326,13 @@ struct JetFragmentation { registry.fill(HIST("matching/jets/V0/missJetPtV0TrackProj"), jet.pt(), trackProj, weight); registry.fill(HIST("matching/jets/V0/missJetPtV0PtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi(), weight); - if (std::abs(v0.pdgCode()) == 310) { // K0S + if (std::abs(v0.pdgCode()) == PDG_t::kK0Short) { // K0S registry.fill(HIST("matching/jets/V0/missJetPtK0SPtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi(), weight); registry.fill(HIST("matching/jets/V0/missJetPtK0STrackProj"), jet.pt(), trackProj, weight); - } else if (v0.pdgCode() == 3122) { // Lambda + } else if (v0.pdgCode() == PDG_t::kLambda0) { // Lambda registry.fill(HIST("matching/jets/V0/missJetPtLambdaPtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi(), weight); registry.fill(HIST("matching/jets/V0/missJetPtLambdaTrackProj"), jet.pt(), trackProj, weight); - } else if (v0.pdgCode() == -3122) { // AntiLambda + } else if (v0.pdgCode() == PDG_t::kLambda0Bar) { // AntiLambda registry.fill(HIST("matching/jets/V0/missJetPtAntiLambdaPtEtaPhi"), jet.pt(), v0.pt(), v0.eta(), v0.phi(), weight); registry.fill(HIST("matching/jets/V0/missJetPtAntiLambdaTrackProj"), jet.pt(), trackProj, weight); } @@ -2388,11 +2470,11 @@ struct JetFragmentation { double pt = posDecayed ? negMom.pt() : posMom.pt(); int pdg = posDecayed ? negMom.pdgCode() : posMom.pdgCode(); - if (std::abs(pdg) == 310) { + if (std::abs(pdg) == PDG_t::kK0Short) { registry.fill(HIST("matching/V0/decayedK0SV0PtMass"), pt, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); - } else if (pdg == 3122) { + } else if (pdg == PDG_t::kLambda0) { registry.fill(HIST("matching/V0/decayedLambdaV0PtMass"), pt, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); - } else if (pdg == -3122) { + } else if (pdg == PDG_t::kLambda0Bar) { registry.fill(HIST("matching/V0/decayedAntiLambdaV0PtMass"), pt, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); } else { registry.fill(HIST("matching/V0/decayedOtherPtV0PtMass"), pt, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); @@ -2546,17 +2628,17 @@ struct JetFragmentation { } } - if (std::abs(pdg) == 310) { + if (std::abs(pdg) == PDG_t::kK0Short) { registry.fill(HIST("matching/jets/V0/decayedK0SV0PtMass"), partJet.pt(), detJet.pt(), pt, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); if (partIsInJet) { registry.fill(HIST("matching/jets/V0/decayedK0SV0TrackProjMass"), partJet.pt(), detJet.pt(), z, zv0, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); } - } else if (pdg == 3122) { + } else if (pdg == PDG_t::kLambda0) { registry.fill(HIST("matching/jets/V0/decayedLambdaV0PtMass"), partJet.pt(), detJet.pt(), pt, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); if (partIsInJet) { registry.fill(HIST("matching/jets/V0/decayedLambdaV0TrackProjMass"), partJet.pt(), detJet.pt(), z, zv0, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); } - } else if (pdg == -3122) { + } else if (pdg == PDG_t::kLambda0Bar) { registry.fill(HIST("matching/jets/V0/decayedAntiLambdaV0PtMass"), partJet.pt(), detJet.pt(), pt, v0.pt(), v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); if (partIsInJet) { registry.fill(HIST("matching/jets/V0/decayedAntiLambdaV0TrackProjMass"), partJet.pt(), detJet.pt(), z, zv0, v0.mK0Short(), v0.mLambda(), v0.mAntiLambda(), weight); @@ -2613,20 +2695,20 @@ struct JetFragmentation { if (v0.isRejectedCandidate()) continue; - float purity = getV0SignalProb(v0); + float signalProb = getV0SignalProb(v0); nV0inJet++; - wV0inJet += purity; + wV0inJet += signalProb; if (v0.isK0SCandidate()) { nK0SinJet++; - wK0SinJet += purity; + wK0SinJet += signalProb; } if (v0.isLambdaCandidate()) { nLambdainJet++; - wLambdainJet += purity; + wLambdainJet += signalProb; } if (v0.isAntiLambdaCandidate()) { nAntiLambdainJet++; - wAntiLambdainJet += purity; + wAntiLambdainJet += signalProb; } fillDataV0FragHistograms(jcoll, jet, v0); @@ -2652,9 +2734,9 @@ struct JetFragmentation { std::vector state = convertState(M, nV0inJet, nV0Classes); std::vector corrected; if (doCorrectionWithTracks) - corrected = correctedValues(state, values); - else corrected = correctedValuesPlusTracks(state, jet); + else + corrected = correctedValues(state, values); double ws = stateWeight(state, weights); double jetpt = corrected[nV0inJet]; @@ -2772,11 +2854,11 @@ struct JetFragmentation { fillMatchingV0FragHistograms(jcoll, detJet, partJet, detV0, partV0, weight); fillMatchingV0DauJetHistograms(detJet, partJet, detV0, partV0, weight); - if (std::abs(partV0.pdgCode()) == 310) { + if (std::abs(partV0.pdgCode()) == PDG_t::kK0Short) { nK0SinJet++; - } else if (partV0.pdgCode() == 3122) { + } else if (partV0.pdgCode() == PDG_t::kLambda0) { nLambdainJet++; - } else if (partV0.pdgCode() == -3122) { + } else if (partV0.pdgCode() == PDG_t::kLambda0Bar) { nAntiLambdainJet++; } break; @@ -2834,7 +2916,7 @@ struct JetFragmentation { } PROCESS_SWITCH(JetFragmentation, processMcMatchedV0JetsFrag, "Matched V0 jets fragmentation", false); - void processMcV0PerpCone(soa::Filtered::iterator const& jcoll, aod::JetMcCollisions const&, MatchedMCDV0Jets const& v0jets, CandidatesV0MCDWithLabelsAndFlags const& v0s, aod::McParticles const& particles) + void processMcV0PerpCone(soa::Filtered::iterator const& jcoll, aod::JetMcCollisions const&, MatchedMCDV0Jets const& v0jets, CandidatesV0MCDWithLabelsAndFlags const& v0s, aod::McParticles const& particles, MatchedMCPV0Jets const&) { if (!jetderiveddatautilities::selectCollision(jcoll, eventSelectionBits)) { return; diff --git a/PWGJE/Tasks/jetHadronRecoil.cxx b/PWGJE/Tasks/jetHadronRecoil.cxx index 71946c49aee..731e8a7c78b 100644 --- a/PWGJE/Tasks/jetHadronRecoil.cxx +++ b/PWGJE/Tasks/jetHadronRecoil.cxx @@ -13,34 +13,38 @@ /// \brief Task for analysing hadron triggered events. /// \author Daniel Jones -#include -#include +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "TRandom3.h" +#include "Common/Core/RecoDecay.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "CommonConstants/MathConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "TRandom3.h" -#include "EventFiltering/filterTables.h" +#include +#include +#include -#include "PWGJE/DataModel/JetSubstructure.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -68,14 +72,15 @@ struct JetHadronRecoil { Configurable ptTTsigMax{"ptTTsigMax", 50, "signal maximum trigger track pt"}; Configurable fracSig{"fracSig", 0.9, "fraction of events to use for signal"}; Configurable jetR{"jetR", 0.4, "jet resolution parameter"}; - Configurable pTHatExponent{"pTHatExponent", 4.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 pTHatTrackMaxMCD{"pTHatTrackMaxMCD", 999.0, "maximum fraction of hard scattering for track acceptance in detector MC"}; Configurable pTHatTrackMaxMCP{"pTHatTrackMaxMCP", 999.0, "maximum fraction of hard scattering for track acceptance in particle MC"}; + Configurable pTHatMinEvent{"pTHatMinEvent", -1.0, "minimum absolute event pTHat"}; Configurable rhoReferenceShift{"rhoReferenceShift", 0.0, "shift in rho calculated in reference events for consistency with signal events"}; 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 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 outlierRejectEvent{"outlierRejectEvent", true, "where outliers are found, reject event (true) or just reject the single track/jet (false)"}; Configurable wtaMethod{"wtaMethod", 1, "method for WTA axis definition: 0 = matching closest WTA jet (incorrect), 1 = recluster original jet"}; Preslice> partJetsPerCollision = aod::jet::mcCollisionId; @@ -85,7 +90,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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); 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, @@ -124,7 +129,7 @@ struct JetHadronRecoil { {"hEtaTrack", "Track #eta;#eta;entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"hPhiTrack", "Track #phi;#phi;entries", {HistType::kTH1F, {{100, 0.0, o2::constants::math::TwoPI}}}}, {"hTrack3D", "3D tracks histogram;p_{T};#eta;#phi", {HistType::kTH3F, {{200, 0, 200}, {100, -1.0, 1.0}, {100, 0.0, o2::constants::math::TwoPI}}}}, - {"hPtTrackPtHard", "Track p_{T} vs #hat{p};p_{T};#frac{p_{T}}{#hat{p}}", {HistType::kTH2F, {{200, 0, 200}, {20, 0, 5}}}}, + {"hPtTrackPtHard", "Tracks vs pThard;#frac{p_{T}}{#hat{p}};p_{T}", {HistType::kTH2F, {{20, 0, 5}, {200, 0, 200}}}}, {"hConstituents3D", "3D constituents histogram;p_{T};#eta;#phi", {HistType::kTH3F, {{200, 0, 200}, {100, -1.0, 1.0}, {100, 0.0, o2::constants::math::TwoPI}}}}, {"hReferencePtDPhi", "jet p_{T} vs DPhi;#Delta#phi;p_{T,jet}", {HistType::kTH2F, {{100, 0, o2::constants::math::TwoPI}, {500, -100, 400}}}}, {"hReferencePtDPhiShifts", "rho shifts;#Delta#phi;p_{T,jet};shifts", {HistType::kTH3F, {{100, 0, o2::constants::math::TwoPI}, {500, -100, 400}, {20, 0.0, 2.0}}}}, @@ -141,6 +146,8 @@ struct JetHadronRecoil { {"hJetEta", "jet #eta;#eta_{jet};entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"hJetPhi", "jet #phi;#phi_{jet};entries", {HistType::kTH1F, {{100, 0.0, o2::constants::math::TwoPI}}}}, {"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}}}}, + {"hTracksvsJets", "comparing leading tracks and jets;p_{T,track};p_{T,jet};#hat{p}", {HistType::kTH3F, {{200, 0, 200}, {500, -100, 400}, {195, 5, 200}}}}, + {"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}}}}, {"hPtPart", "Particle p_{T};p_{T};entries", {HistType::kTH1F, {{200, 0, 200}}}}, {"hEtaPart", "Particle #eta;#eta;entries", {HistType::kTH1F, {{100, -1.0, 1.0}}}}, {"hPhiPart", "Particle #phi;#phi;entries", {HistType::kTH1F, {{100, 0.0, o2::constants::math::TwoPI}}}}, @@ -172,7 +179,7 @@ struct JetHadronRecoil { {"hPtMatched1d", "p_{T} matching 1d;p_{T,part}", {HistType::kTH1F, {{400, 0, 400}}}}, {"hDeltaRMatched1d", "#DeltaR matching 1d;#DeltaR_{part}", {HistType::kTH1F, {dRAxisPart}}}, {"hPtResolution", "p_{T} resolution;p_{T,part};Relative Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -5.0, 5.0}}}}, - {"hPhiResolution", "#phi resolution;#p{T,part};Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -7.0, 7.0}}}}, + {"hPhiResolution", "#phi resolution;#p_{T,part};Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -7.0, 7.0}}}}, {"hDeltaRResolution", "#DeltaR Resolution;p_{T,part};Resolution", {HistType::kTH2F, {{400, 0, 400}, {1000, -0.15, 0.15}}}}, {"hFullMatching", "Full 6D matching;p_{T,det};p_{T,part};#phi_{det};#phi_{part};#DeltaR_{det};#DeltaR_{part}", {HistType::kTHnSparseD, {ptAxisDet, ptAxisPart, phiAxisDet, phiAxisPart, dRAxisDet, dRAxisPart}}}}}; @@ -200,7 +207,7 @@ struct JetHadronRecoil { } template - void fillHistograms(T const& jets, W const& jetsWTA, U const& tracks, float weight = 1.0, float rho = 0.0) + void fillHistograms(T const& jets, W const& jetsWTA, U const& tracks, float weight = 1.0, float rho = 0.0, float pTHat = 999.0) { bool isSigCol; std::vector phiTTAr; @@ -210,7 +217,8 @@ struct JetHadronRecoil { int trigNumber = 0; int nTT = 0; double leadingPT = 0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); + double leadingTrackPt = 0; + double leadingJetPt = 0; float rhoReference = rho + rhoReferenceShift; float dice = rand->Rndm(); @@ -223,8 +231,15 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { continue; } + if (track.pt() > leadingTrackPt) { + leadingTrackPt = track.pt(); + } if (track.pt() > pTHatTrackMaxMCD * pTHat) { - return; + if (outlierRejectEvent) { + return; + } else { + continue; + } } if (isSigCol && track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { phiTTAr.push_back(track.phi()); @@ -265,10 +280,16 @@ struct JetHadronRecoil { registry.fill(HIST("hReferenceTriggersPtHard"), ptTT / pTHat, weight); } } - for (const auto& jet : jets) { + if (jet.pt() > leadingJetPt) { + leadingJetPt = jet.pt(); + } if (jet.pt() > pTHatMaxMCD * pTHat) { - return; + if (outlierRejectEvent) { + return; + } else { + continue; + } } for (const auto& constituent : jet.template tracks_as()) { if (constituent.pt() > leadingPT) { @@ -324,10 +345,11 @@ struct JetHadronRecoil { } } } + registry.fill(HIST("hTracksvsJets"), leadingTrackPt, leadingJetPt, pTHat, weight); } template - void fillMCPHistograms(T const& jets, W const& jetsWTA, U const& particles, float weight = 1.0) + void fillMCPHistograms(T const& jets, W const& jetsWTA, U const& particles, float weight = 1.0, float pTHat = 999.0) { bool isSigCol; std::vector phiTTAr; @@ -336,8 +358,8 @@ struct JetHadronRecoil { double ptTT = 0; int trigNumber = 0; int nTT = 0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); - + double leadingPartPt = 0; + double leadingJetPt = 0; float dice = rand->Rndm(); if (dice < fracSig) isSigCol = true; @@ -345,8 +367,15 @@ struct JetHadronRecoil { isSigCol = false; for (const auto& particle : particles) { + if (particle.pt() > leadingPartPt) { + leadingPartPt = particle.pt(); + } if (particle.pt() > pTHatTrackMaxMCD * pTHat) { - return; + if (outlierRejectEvent) { + return; + } else { + continue; + } } auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle) { @@ -389,8 +418,15 @@ struct JetHadronRecoil { } for (const auto& jet : jets) { + if (jet.pt() > leadingJetPt) { + leadingJetPt = jet.pt(); + } if (jet.pt() > pTHatMaxMCP * pTHat) { - return; + if (outlierRejectEvent) { + return; + } else { + continue; + } } for (const auto& constituent : jet.template tracks_as()) { registry.fill(HIST("hConstituents3D"), constituent.pt(), constituent.eta(), constituent.phi()); @@ -432,29 +468,22 @@ struct JetHadronRecoil { } } } + registry.fill(HIST("hPartvsJets"), leadingPartPt, leadingJetPt, pTHat, weight); } template - void fillMatchedHistograms(T const& jetsBase, V const& mcdjetsWTA, W const& mcpjetsWTA, U const&, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0) + void fillMatchedHistograms(T const& jetsBase, V const& mcdjetsWTA, W const& mcpjetsWTA, U const&, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0, float pTHat = 999.0) { for (const auto& jetBase : jetsBase) { double dR = 0; double dRp = 0; - float pTHat = 10. / (std::pow(weight, 1.0 / pTHatExponent)); if (jetBase.pt() > pTHatMaxMCD * pTHat) { - return; - } - - for (const auto& mcdjetWTA : mcdjetsWTA) { - double djet = RecoDecay::sqrtSumOfSquares(RecoDecay::constrainAngle(jetBase.phi() - mcdjetWTA.phi(), -o2::constants::math::PI), jetBase.eta() - mcdjetWTA.eta()); - if (mcdjetWTA.pt() > pTHatMaxMCD * pTHat) { + if (outlierRejectEvent) { + return; + } else { continue; } - if (djet < 0.6 * jetR) { - dR = djet; - break; - } } dR = getWTAaxisDifference(jetBase, mcdjetsWTA, tracks, true); @@ -462,7 +491,11 @@ struct JetHadronRecoil { if (jetBase.has_matchedJetGeo()) { for (const auto& jetTag : jetBase.template matchedJetGeo_as>()) { if (jetTag.pt() > pTHatMaxMCP * pTHat) { - return; + if (outlierRejectEvent) { + return; + } else { + continue; + } } dRp = getWTAaxisDifference(jetTag, mcpjetsWTA, particles, true); @@ -481,6 +514,89 @@ struct JetHadronRecoil { } } + template + void fillRecoilJetMatchedHistograms(T const& jetsBase, V const& mcdjetsWTA, W const& mcpjetsWTA, U const&, X const& tracks, Y const& particles, float weight = 1.0, float rho = 0.0, float pTHat = 999.0) + { + std::vector phiTTAr; + std::vector phiTTArPart; + double phiTT = 0; + double phiTTPart = 0; + int trigNumber = 0; + int nTT = 0; + + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; + } + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) { + continue; + } + if (track.pt() > pTHatTrackMaxMCD * pTHat) { + if (outlierRejectEvent) { + return; + } else { + continue; + } + } + if (track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { + phiTTAr.push_back(track.phi()); + nTT++; + auto particle = track.template mcParticle_as(); + phiTTArPart.push_back(particle.phi()); + } + } + + if (nTT > 0) { + trigNumber = rand->Integer(nTT); + phiTT = phiTTAr[trigNumber]; + phiTTPart = phiTTAr[trigNumber]; + } else { + return; + } + + for (const auto& jetBase : jetsBase) { + double dR = 0; + double dRp = 0; + + if (jetBase.pt() > pTHatMaxMCD * pTHat) { + if (outlierRejectEvent) { + return; + } else { + continue; + } + } + + float dphi = RecoDecay::constrainAngle(jetBase.phi() - phiTT); + dR = getWTAaxisDifference(jetBase, mcdjetsWTA, tracks, true); + + if (jetBase.has_matchedJetGeo()) { + for (const auto& jetTag : jetBase.template matchedJetGeo_as>()) { + if (jetTag.pt() > pTHatMaxMCP * pTHat) { + if (outlierRejectEvent) { + return; + } else { + continue; + } + } + + float dphip = RecoDecay::constrainAngle(jetTag.phi() - phiTTPart); + dRp = getWTAaxisDifference(jetTag, mcpjetsWTA, particles, true); + if ((std::abs(dphi - o2::constants::math::PI) < 0.6) || (std::abs(dphip - o2::constants::math::PI) < 0.6)) { + registry.fill(HIST("hPtMatched"), jetBase.pt() - (rho * jetBase.area()), jetTag.pt(), weight); + registry.fill(HIST("hPhiMatched"), dphi, dphip, weight); + registry.fill(HIST("hPtResolution"), jetTag.pt(), (jetTag.pt() - (jetBase.pt() - (rho * jetBase.area()))) / jetTag.pt(), weight); + registry.fill(HIST("hPhiResolution"), jetTag.pt(), dphip - dphi, 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(), dphi, dphip, dR, dRp, weight); + registry.fill(HIST("hPtMatched1d"), jetTag.pt(), weight); + registry.fill(HIST("hDeltaRMatched1d"), dRp, weight); + } + } + } + } + } + void processData(soa::Filtered::iterator const& collision, soa::Filtered> const& jets, soa::Filtered> const& jetsWTA, @@ -513,7 +629,8 @@ struct JetHadronRecoil { } PROCESS_SWITCH(JetHadronRecoil, processDataWithRhoSubtraction, "process data with rho subtraction", false); - void processMCD(soa::Filtered::iterator const& collision, + void processMCD(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& jets, soa::Filtered> const& jetsWTA, soa::Filtered const& tracks) @@ -527,12 +644,16 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); - fillHistograms(jets, jetsWTA, tracks); + fillHistograms(jets, jetsWTA, tracks, 1.0, 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCD, "process MC detector level", false); - void processMCDWithRhoSubtraction(soa::Filtered>::iterator const& collision, + void processMCDWithRhoSubtraction(soa::Filtered>::iterator const& collision, + aod::JMcCollisions const&, soa::Filtered> const& jets, soa::Filtered> const& jetsWTA, soa::Filtered const& tracks) @@ -546,8 +667,11 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); - fillHistograms(jets, jetsWTA, tracks, 1.0, collision.rho()); + fillHistograms(jets, jetsWTA, tracks, 1.0, collision.rho(), collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWithRhoSubtraction, "process MC detector level with rho subtraction", false); @@ -566,8 +690,11 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.mcCollision().weight()); - fillHistograms(jets, jetsWTA, tracks, collision.mcCollision().weight()); + fillHistograms(jets, jetsWTA, tracks, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWeighted, "process MC detector level with event weights", false); @@ -586,8 +713,11 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.mcCollision().weight()); - fillHistograms(jets, jetsWTA, tracks, collision.mcCollision().weight(), collision.rho()); + fillHistograms(jets, jetsWTA, tracks, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCDWeightedWithRhoSubtraction, "process MC detector level with event weights and rho subtraction", false); @@ -602,8 +732,11 @@ struct JetHadronRecoil { if (skipMBGapEvents && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { return; } + if (collision.ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); - fillMCPHistograms(jets, jetsWTA, particles); + fillMCPHistograms(jets, jetsWTA, particles, 1.0, collision.ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCP, "process MC particle level", false); @@ -618,12 +751,15 @@ struct JetHadronRecoil { if (skipMBGapEvents && collision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { return; } + if (collision.ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ(), collision.weight()); - fillMCPHistograms(jets, jetsWTA, particles, collision.weight()); + fillMCPHistograms(jets, jetsWTA, particles, collision.weight(), collision.ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processMCPWeighted, "process MC particle level with event weights", false); - void processJetsMCPMCDMatched(soa::Filtered::iterator const& collision, + void processJetsMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, @@ -638,13 +774,16 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatched, "process MC matched (inc jets)", false); - void processJetsMCPMCDMatchedWithRhoSubtraction(soa::Filtered>::iterator const& collision, + void processJetsMCPMCDMatchedWithRhoSubtraction(soa::Filtered>::iterator const& collision, soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, @@ -659,13 +798,16 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles); + fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, 1.0, 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatchedWithRhoSubtraction, "process MC matched (inc jets) with rho subtraction", false); - void processJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, + void processJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, @@ -680,13 +822,16 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight()); + fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatchedWeighted, "process MC matched with event weights (inc jets)", false); - void processJetsMCPMCDMatchedWeightedWithRhoSubtraction(soa::Filtered>::iterator const& collision, + void processJetsMCPMCDMatchedWeightedWithRhoSubtraction(soa::Filtered>::iterator const& collision, soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, @@ -701,17 +846,20 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight(), collision.rho()); + fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight(), collision.rho(), collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processJetsMCPMCDMatchedWeightedWithRhoSubtraction, "process MC matched with event weights (inc jets) and rho subtraction", false); - void processRecoilJetsMCPMCDMatched(soa::Filtered::iterator const& collision, + void processRecoilJetsMCPMCDMatched(soa::Filtered>::iterator const& collision, soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, - soa::Filtered const& tracks, + soa::Filtered const& tracks, soa::Filtered const& particles, aod::JetMcCollisions const&, soa::Filtered> const& mcpjets) @@ -722,26 +870,20 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - bool ishJetEvent = false; - for (const auto& track : tracks) { - if (track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { - ishJetEvent = true; - break; - } - } - if (ishJetEvent) { - fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles); - } + fillRecoilJetMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, 1.0, 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatched, "process MC matched (recoil jets)", false); - void processRecoilJetsMCPMCDMatchedWeighted(soa::Filtered::iterator const& collision, + void processRecoilJetsMCPMCDMatchedWeighted(soa::Filtered>::iterator const& collision, soa::Filtered> const& mcdjets, soa::Filtered> const& mcdjetsWTA, soa::Filtered> const& mcpjetsWTA, - soa::Filtered const& tracks, + soa::Filtered const& tracks, soa::Filtered const& particles, aod::JetMcCollisions const&, soa::Filtered> const& mcpjets) @@ -752,18 +894,12 @@ struct JetHadronRecoil { if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { return; } + if (collision.mcCollision().ptHard() < pTHatMinEvent) { + return; + } registry.fill(HIST("hZvtxSelected"), collision.posZ()); const auto& mcpjetsWTACut = mcpjetsWTA.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - bool ishJetEvent = false; - for (const auto& track : tracks) { - if (track.pt() < ptTTsigMax && track.pt() > ptTTsigMin) { - ishJetEvent = true; - break; - } - } - if (ishJetEvent) { - fillMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight()); - } + fillRecoilJetMatchedHistograms(mcdjets, mcdjetsWTA, mcpjetsWTACut, mcpjets, tracks, particles, collision.mcCollision().weight(), 0.0, collision.mcCollision().ptHard()); } PROCESS_SWITCH(JetHadronRecoil, processRecoilJetsMCPMCDMatchedWeighted, "process MC matched with event weights (recoil jets)", false); diff --git a/PWGJE/Tasks/jetLundReclustering.cxx b/PWGJE/Tasks/jetLundReclustering.cxx index c18053343cf..b78c6f2b6ef 100644 --- a/PWGJE/Tasks/jetLundReclustering.cxx +++ b/PWGJE/Tasks/jetLundReclustering.cxx @@ -17,35 +17,30 @@ // Task performing jet reclustering and producing primary Lund Plane histograms // -#include -#include -#include -#include -#include - -#include "fastjet/contrib/LundGenerator.hh" -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" -#include "TDatabasePDG.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include -#include "Common/Core/RecoDecay.h" +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include using namespace o2; using namespace o2::track; diff --git a/PWGJE/Tasks/jetMatchingQA.cxx b/PWGJE/Tasks/jetMatchingQA.cxx index e752b47e2a5..6770d42e47e 100644 --- a/PWGJE/Tasks/jetMatchingQA.cxx +++ b/PWGJE/Tasks/jetMatchingQA.cxx @@ -15,14 +15,21 @@ /// \author Jochen Klein /// \author Aimeric Lanodu -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "PWGJE/DataModel/Jet.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include + +#include + +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/Tasks/jetPlanarFlow.cxx b/PWGJE/Tasks/jetPlanarFlow.cxx index d54ebea1ac2..673d4eebffe 100644 --- a/PWGJE/Tasks/jetPlanarFlow.cxx +++ b/PWGJE/Tasks/jetPlanarFlow.cxx @@ -14,26 +14,30 @@ /// \author Nima Zardoshti // -#include -#include - -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/Logger.h" -#include "Framework/HistogramRegistry.h" +#include "JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#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 "fastjet/contrib/AxesDefinition.hh" -#include "fastjet/contrib/MeasureDefinition.hh" + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -127,7 +131,7 @@ struct JetPlanarFlowTask { } // jet pT, tau2/tau1, jetdR, track pt, phi', eta', dR, isInJet - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + 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) diff --git a/PWGJE/Tasks/jetShape.cxx b/PWGJE/Tasks/jetShape.cxx index d7e1f2f0557..9a7c857e256 100644 --- a/PWGJE/Tasks/jetShape.cxx +++ b/PWGJE/Tasks/jetShape.cxx @@ -13,14 +13,10 @@ /// \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 -#include -#include - -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" @@ -28,28 +24,64 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" - +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include +#include +#include + using namespace o2; using namespace o2::framework; 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 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 pMax{"pMax", 7.0f, "Max value of p"}; + Configurable ptMax{"ptMax", 5.0f, "Max value of pT"}; + 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"}; + Configurable tpcNSigmaPrMin{"tpcNSigmaPrMin", -3.5f, "Min value of tpcNsigmaProton"}; + Configurable tpcNSigmaPrMax{"tpcNSigmaPrMax", 0.5f, "Max value of tpcNsigmaProton"}; + Configurable tpcNSigmaPiMin{"tpcNSigmaPiMin", -0.5f, "Min value of tpcNsigmaPion"}; + Configurable tpcNSigmaPiMax{"tpcNSigmaPiMax", 3.5f, "Max value of tpcNsigmaPion"}; + HistogramRegistry registry{"registry", - {{"tpcTofPi", "tpcTofPi", {HistType::kTHnSparseD, {{101, -10.1f, 10.1f}, {20, -10, 10}, {25, 0, 5}, {14, 0, 7}}}}, - {"tpcPi", "tpcPi", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, - {"tofPi", "tofPi", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, - {"tpcTofPr", "tpcTofPr", {HistType::kTHnSparseD, {{101, -10.1f, 10.1f}, {20, -10, 10}, {25, 0, 5}, {14, 0, 7}}}}, - {"tpcPr", "tpcPr", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, - {"tofPr", "tofPr", {HistType::kTH2F, {{100, 0, 5}, {401, -10.025f, 10.025f}}}}, - {"tpcDedx", "tpcDedx", {HistType::kTH2F, {{500, 0, 5}, {1000, 0, 1000}}}}, - {"tofBeta", "tofBeta", {HistType::kTH2F, {{500, 0, 5}, {450, 0.2, 1.1}}}}, - {"tofMass", "tofMass", {HistType::kTH1F, {{3000, 0, 3}}}}, + {{"tpcTofPi", "tpcTofPi", {HistType::kTHnSparseD, {{35, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsDistance, 0, distanceMax}}}}, + {"tpcTofPr", "tpcTofPr", {HistType::kTHnSparseD, {{35, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}, {nBinsDistance, 0, distanceMax}}}}, + {"tpcTofPiOutOfJet", "tpcTofPiOutOfJet", {HistType::kTH2F, {{35, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, + {"tpcTofPrOutOfJet", "tpcTofPrOutOfJet", {HistType::kTH2F, {{35, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, + {"tpcPi", "tpcPi", {HistType::kTH2F, {{70, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, + {"tofPi", "tofPi", {HistType::kTH2F, {{50, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, + {"tpcPr", "tpcPr", {HistType::kTH2F, {{70, 0, pMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, + {"tofPr", "tofPr", {HistType::kTH2F, {{50, 0, ptMax}, {nBinsNSigma, nSigmaMin, nSigmaMax}}}}, + {"tpcDedx", "tpcDedx", {HistType::kTHnSparseD, {{nBinsPForDedx, 0, pMax}, {nBinsTpcDedx, 0, 1000}, {nBinsDistance, 0, distanceMax}}}}, + {"tpcDedxOutOfJet", "tpcDedxOutOfJet", {HistType::kTH2F, {{nBinsPForDedx, 0, pMax}, {nBinsTpcDedx, 0, 1000}}}}, + {"tofBeta", "tofBeta", {HistType::kTH2F, {{nBinsPForBeta, 0, pMax}, {nBinsTofBeta, 0.4, 1.1}}}}, + {"pVsPtForPr", "pVsPtForPr", {HistType::kTHnSparseD, {{70, 0, pMax}, {50, 0, ptMax}, {nBinsDistance, 0, distanceMax}}}}, + {"pVsPtForPi", "pVsPtPi", {HistType::kTHnSparseD, {{70, 0, pMax}, {50, 0, ptMax}, {nBinsDistance, 0, distanceMax}}}}, + {"pVsPtForPrOutOfJet", "pVsPtForPrOutOfJet", {HistType::kTH2F, {{70, 0, pMax}, {50, 0, ptMax}}}}, + {"pVsPtForPiOutOfJet", "pVsPtPionOutOfJet", {HistType::kTH2F, {{70, 0, pMax}, {50, 0, ptMax}}}}, + {"tofMass", "tofMass", {HistType::kTH1F, {{300, 0, 3}}}}, + {"trackPhi", "trackPhi", {HistType::kTH1F, {{80, -1, 7}}}}, + {"trackEta", "trackEta", {HistType::kTH1F, {{100, -1, 1}}}}, + {"trackTpcNClsCrossedRows", "trackTpcNClsCrossedRows", {HistType::kTH1F, {{50, 0, 200}}}}, + {"trackDcaXY", "trackDcaXY", {HistType::kTH1F, {{40, -10, 10}}}}, + {"trackItsChi2NCl", "trackItsChi2NCl", {HistType::kTH1F, {{60, 0, 30}}}}, + {"trackTpcChi2NCl", "trackTpcChi2NCl", {HistType::kTH1F, {{100, 0, 50}}}}, + {"trackTpcNClsFound", "trackTpcNClsFound", {HistType::kTH1F, {{100, 0, 200}}}}, + {"trackItsNCls", "trackItsNCls", {HistType::kTH1F, {{10, 0, 10}}}}, {"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.}}}}, @@ -61,6 +93,7 @@ struct JetShapeTask { {"ptSum", "ptSum", {HistType::kTH2F, {{14, 0, 0.7}, {300, 0, 300}}}}, {"ptSumBg1", "ptSumBg1", {HistType::kTH2F, {{14, 0, 0.7}, {300, 0, 300}}}}, {"ptSumBg2", "ptSumBg2", {HistType::kTH2F, {{14, 0, 0.7}, {300, 0, 300}}}}, + {"event/vertexz", ";Vtx_{z} (cm);Entries", {HistType::kTH1F, {{100, -20, 20}}}}, {"ptVsCentrality", "ptvscentrality", {HistType::kTH2F, {{100, 0, 100}, {300, 0, 300}}}}}}; Configurable vertexZCut{"vertexZCut", 10.0f, "Accepted z-vertex range"}; @@ -79,9 +112,13 @@ struct JetShapeTask { Configurable> distanceCategory{"distanceCategory", {0.00f, 0.05f, 0.10f, 0.15f, 0.20f, 0.25f, 0.30f, 0.35f, 0.40f, 0.45f, 0.50f, 0.55f, 0.60f, 0.65f, 0.70f}, "distance of category"}; // for ppi production - Configurable maxTpcNClsCrossedRows{"maxTpcNClsCrossedRows", 70, ""}; - Configurable maxDcaXY{"maxDcaXY", 0.2, ""}; - Configurable maxItsNCls{"maxItsNCls", 2, ""}; + Configurable etaTrUp{"etaTrUp", 0.7f, "maximum track eta"}; + Configurable dcaxyMax{"dcaxyMax", 2.0f, "mximum 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"}; + Configurable nclTpcMin{"nclTpcMin", 100.0f, "tpc # if cluster cut"}; + Configurable nclcrossTpcMin{"nclcrossTpcMin", 70.0f, "tpc # of crossedRows cut"}; 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"}; @@ -145,18 +182,10 @@ struct JetShapeTask { void processJetShape(soa::Filtered>::iterator const& collision, aod::JetTracks const& tracks, soa::Join const& jets) { - if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) { - return; - } - std::vector ptDensity; - std::vector ptDensityBg1; - std::vector ptDensityBg2; - ptDensity.reserve(distanceCategory->size() - 1); - ptDensityBg1.reserve(distanceCategory->size() - 1); - ptDensityBg2.reserve(distanceCategory->size() - 1); - - // std::cout << collision.centrality() << std::endl; + std::vector ptDensity(distanceCategory->size() - 1, 0.f); + std::vector ptDensityBg1(distanceCategory->size() - 1, 0.f); + std::vector ptDensityBg2(distanceCategory->size() - 1, 0.f); for (auto const& jet : jets) { if (!isAcceptedJet(jet)) { @@ -167,6 +196,7 @@ struct JetShapeTask { float ptCorr = jet.pt() - collision.rho() * jet.area(); for (const auto& track : tracks) { + float preDeltaPhi1 = track.phi() - jet.phi(); float deltaPhi1 = RecoDecay::constrainAngle(preDeltaPhi1); float deltaEta = track.eta() - jet.eta(); @@ -175,33 +205,31 @@ struct JetShapeTask { float distance = std::sqrt(deltaEta * deltaEta + deltaPhi1 * deltaPhi1); registry.fill(HIST("ptCorrVsDistance"), distance, ptCorr); - registry.fill(HIST("ptVsCentrality"), collision.centrality(), track.pt()); + registry.fill(HIST("ptVsCentrality"), collision.centFT0M(), track.pt()); // calculate compornents of jetshapefunction rho(r) - std::vector trackPtSum; - std::vector trackPtSumBg1; - std::vector trackPtSumBg2; - trackPtSum.reserve(distanceCategory->size() - 1); - trackPtSumBg1.reserve(distanceCategory->size() - 1); - trackPtSumBg2.reserve(distanceCategory->size() - 1); + std::vector trackPtSum(distanceCategory->size() - 1, 0.f); + std::vector trackPtSumBg1(distanceCategory->size() - 1, 0.f); + std::vector trackPtSumBg2(distanceCategory->size() - 1, 0.f); + float phiBg1 = jet.phi() + (o2::constants::math::PIHalf); float phiBg2 = jet.phi() - (o2::constants::math::PIHalf); float preDeltaPhiBg1 = track.phi() - phiBg1; float preDeltaPhiBg2 = track.phi() - phiBg2; - float deltaPhiBg1 = RecoDecay::constrainAngle(preDeltaPhiBg1); - float deltaPhiBg2 = RecoDecay::constrainAngle(preDeltaPhiBg2); + float deltaPhiBg1 = RecoDecay::constrainAngle(preDeltaPhiBg1, -o2::constants::math::PI); + float deltaPhiBg2 = RecoDecay::constrainAngle(preDeltaPhiBg2, -o2::constants::math::PI); float distanceBg1 = std::sqrt(deltaEta * deltaEta + deltaPhiBg1 * deltaPhiBg1); float distanceBg2 = std::sqrt(deltaEta * deltaEta + deltaPhiBg2 * deltaPhiBg2); for (size_t i = 0; i < distanceCategory->size() - 1; i++) { - if (distance < distanceCategory->at(i + 1)) + if (distanceCategory->at(i) <= distance && distance < distanceCategory->at(i + 1)) trackPtSum[i] += track.pt(); - if (distanceBg1 < distanceCategory->at(i + 1)) + if (distanceCategory->at(i) <= distanceBg1 && distanceBg1 < distanceCategory->at(i + 1)) trackPtSumBg1[i] += track.pt(); - if (distanceBg2 < distanceCategory->at(i + 1)) + if (distanceCategory->at(i) <= distanceBg2 && distanceBg2 < distanceCategory->at(i + 1)) trackPtSumBg2[i] += track.pt(); } @@ -221,9 +249,9 @@ struct JetShapeTask { for (size_t i = 0; i < distanceCategory->size() - 1; i++) { double jetX = (distanceCategory->at(i + 1) - distanceCategory->at(i)) * i + (distanceCategory->at(i + 1) - distanceCategory->at(i)) / 2; - double jetShapeFunction = ptDensity[i + 1]; - double jetShapeFunctionBg1 = ptDensityBg1[i + 1]; - double jetShapeFunctionBg2 = ptDensityBg2[i + 1]; + double jetShapeFunction = ptDensity[i]; + double jetShapeFunctionBg1 = ptDensityBg1[i]; + double jetShapeFunctionBg2 = ptDensityBg2[i]; registry.fill(HIST("ptSum"), jetX, jetShapeFunction); registry.fill(HIST("ptSumBg1"), jetX, jetShapeFunctionBg1); registry.fill(HIST("ptSumBg2"), jetX, jetShapeFunctionBg2); @@ -238,6 +266,8 @@ struct JetShapeTask { return; } + registry.fill(HIST("event/vertexz"), collision.posZ()); + for (auto const& jet : jets) { if (!isAcceptedJet(jet)) { continue; @@ -245,23 +275,36 @@ struct JetShapeTask { // tracks conditions for (const auto& track : tracks) { - if (track.tpcNClsCrossedRows() < maxTpcNClsCrossedRows) + + registry.fill(HIST("trackTpcNClsCrossedRows"), track.tpcNClsCrossedRows()); + registry.fill(HIST("trackDcaXY"), track.dcaXY()); + registry.fill(HIST("trackItsChi2NCl"), track.itsChi2NCl()); + registry.fill(HIST("trackTpcChi2NCl"), track.tpcChi2NCl()); + registry.fill(HIST("trackTpcNClsFound"), track.tpcNClsFound()); + registry.fill(HIST("trackItsNCls"), track.itsNCls()); + registry.fill(HIST("trackEta"), track.eta()); + registry.fill(HIST("trackPhi"), track.phi()); + + if (std::abs(track.eta()) > etaTrUp) continue; - if (std::fabs(track.dcaXY()) > maxDcaXY) + if (track.tpcNClsCrossedRows() < nclcrossTpcMin) continue; - if (track.itsNCls() < maxItsNCls) { + if (std::abs(track.dcaXY()) > dcaxyMax) + continue; + if (track.itsChi2NCl() > chi2ItsMax) + continue; + if (track.tpcChi2NCl() > chi2TpcMax) + continue; + if (track.tpcNClsFound() < nclTpcMin) + continue; + if (track.itsNCls() < nclItsMin) continue; - } // PID check - registry.fill(HIST("tpcDedx"), track.pt(), track.tpcSignal()); - registry.fill(HIST("tofBeta"), track.pt(), track.beta()); registry.fill(HIST("tofMass"), track.mass()); - - // for calculate purity - registry.fill(HIST("tpcPi"), track.pt(), track.tpcNSigmaPi()); + registry.fill(HIST("tpcPi"), track.p(), track.tpcNSigmaPi()); registry.fill(HIST("tofPi"), track.pt(), track.tofNSigmaPi()); - registry.fill(HIST("tpcPr"), track.pt(), track.tpcNSigmaPr()); + registry.fill(HIST("tpcPr"), track.p(), track.tpcNSigmaPr()); registry.fill(HIST("tofPr"), track.pt(), track.tofNSigmaPr()); // for calculate distance @@ -272,9 +315,55 @@ struct JetShapeTask { // calculate distance from jet axis float distance = std::sqrt(deltaEta * deltaEta + deltaPhi1 * deltaPhi1); + // Define perpendicular cone axes in phi + float phiBg1 = jet.phi() + (o2::constants::math::PIHalf); + float phiBg2 = jet.phi() - (o2::constants::math::PIHalf); + + // Calculate delta phi for background cones + float preDeltaPhiBg1 = track.phi() - phiBg1; + float preDeltaPhiBg2 = track.phi() - phiBg2; + float deltaPhiBg1 = RecoDecay::constrainAngle(preDeltaPhiBg1, -o2::constants::math::PI); + float deltaPhiBg2 = RecoDecay::constrainAngle(preDeltaPhiBg2, -o2::constants::math::PI); + + // Calculate distance to background cone axes + float distanceBg1 = std::sqrt(deltaEta * deltaEta + deltaPhiBg1 * deltaPhiBg1); + float distanceBg2 = std::sqrt(deltaEta * deltaEta + deltaPhiBg2 * deltaPhiBg2); + + // Fill histogram if track is inside one of the perpendicular cones + if (distanceBg1 < jetR || distanceBg2 < jetR) { + registry.fill(HIST("tpcDedxOutOfJet"), track.p(), track.tpcSignal()); + + if (std::abs(track.tofNSigmaPi()) < nSigmaTofCut) { + registry.fill(HIST("tpcTofPiOutOfJet"), track.p(), track.tpcNSigmaPi()); + if (track.tpcNSigmaPi() > tpcNSigmaPiMin && track.tpcNSigmaPi() < tpcNSigmaPiMax) { + registry.fill(HIST("pVsPtForPiOutOfJet"), track.p(), track.pt()); + } + } + if (std::abs(track.tofNSigmaPr()) < nSigmaTofCut) { + registry.fill(HIST("tpcTofPrOutOfJet"), track.p(), track.tpcNSigmaPr()); + if (track.tpcNSigmaPr() > tpcNSigmaPrMin && track.tpcNSigmaPr() < tpcNSigmaPrMax) { + registry.fill(HIST("pVsPtForPrOutOfJet"), track.p(), track.pt()); + } + } + } + registry.fill(HIST("distanceVsTrackpt"), distance, track.pt()); - registry.fill(HIST("tpcTofPi"), track.tpcNSigmaPi(), track.tofNSigmaPi(), track.pt(), distance); - registry.fill(HIST("tpcTofPr"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt(), distance); + registry.fill(HIST("tpcDedx"), track.p(), track.tpcSignal(), distance); + registry.fill(HIST("tofBeta"), track.p(), track.beta()); + + if (std::abs(track.tofNSigmaPr()) < nSigmaTofCut) { + registry.fill(HIST("tpcTofPr"), track.p(), track.tpcNSigmaPr(), distance); + if (track.tpcNSigmaPr() > tpcNSigmaPrMin && track.tpcNSigmaPr() < tpcNSigmaPrMax) { + registry.fill(HIST("pVsPtForPr"), track.p(), track.pt(), distance); + } + } + + if (std::abs(track.tofNSigmaPi()) < nSigmaTofCut) { + registry.fill(HIST("tpcTofPi"), track.p(), track.tpcNSigmaPi(), distance); + if (track.tpcNSigmaPi() > tpcNSigmaPiMin && track.tpcNSigmaPi() < tpcNSigmaPiMax) { + registry.fill(HIST("pVsPtForPi"), track.p(), track.pt(), distance); + } + } } } } diff --git a/PWGJE/Tasks/jetSpectraCharged.cxx b/PWGJE/Tasks/jetSpectraCharged.cxx index f1dfda25418..70f73484b79 100644 --- a/PWGJE/Tasks/jetSpectraCharged.cxx +++ b/PWGJE/Tasks/jetSpectraCharged.cxx @@ -13,34 +13,27 @@ /// \brief Charged-particle jet spectra task /// \author Nima Zardoshti , Aimeric Landou , Wenhui Feng -#include -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include +#include +#include +#include +#include -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" - -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include -#include "EventFiltering/filterTables.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -251,7 +244,7 @@ struct JetSpectraCharged { } 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::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); Preslice mcdjetsPerJCollision = o2::aod::jet::collisionId; template @@ -556,7 +549,7 @@ struct JetSpectraCharged { if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { return; } - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + if (std::abs(collision.posZ()) > vertexZCut) { return; } for (auto const& track : tracks) { @@ -579,7 +572,7 @@ struct JetSpectraCharged { return; } registry.fill(HIST("h_collisions"), 2.5); - registry.fill(HIST("h2_centrality_occupancy"), collision.centrality(), collision.trackOccupancyInTimeRange()); + registry.fill(HIST("h2_centrality_occupancy"), collision.centFT0M(), collision.trackOccupancyInTimeRange()); registry.fill(HIST("h_collisions_Zvertex"), collision.posZ()); } PROCESS_SWITCH(JetSpectraCharged, processCollisions, "collisions Data and MCD", true); @@ -598,12 +591,12 @@ struct JetSpectraCharged { } registry.fill(HIST("h_collisions"), 1.5); registry.fill(HIST("h_collisions_weighted"), 1.5, eventWeight); - if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + if (std::abs(collision.posZ()) > vertexZCut) { return; } registry.fill(HIST("h_collisions"), 2.5); registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); - registry.fill(HIST("h2_centrality_occupancy"), collision.centrality(), collision.trackOccupancyInTimeRange()); + registry.fill(HIST("h2_centrality_occupancy"), collision.centFT0M(), collision.trackOccupancyInTimeRange()); registry.fill(HIST("h_collisions_Zvertex"), collision.posZ(), eventWeight); } PROCESS_SWITCH(JetSpectraCharged, processCollisionsWeighted, "weighted collsions for MCD", false); @@ -625,7 +618,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetHistograms(jet, collision.centrality()); + fillJetHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraData, "jet spectra for Data", false); @@ -647,7 +640,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetHistograms(jet, collision.centrality()); + fillJetHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraMCD, "jet spectra for MCD", false); @@ -669,7 +662,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetAreaSubHistograms(jet, collision.centrality(), collision.rho()); + fillJetAreaSubHistograms(jet, collision.centFT0M(), collision.rho()); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubData, "jet spectra with rho-area subtraction for Data", false); @@ -691,7 +684,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillJetAreaSubHistograms(jet, collision.centrality(), collision.rho()); + fillJetAreaSubHistograms(jet, collision.centFT0M(), collision.rho()); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraAreaSubMCD, "jet spectra with rho-area subtraction for MCD", false); @@ -720,7 +713,7 @@ struct JetSpectraCharged { } registry.fill(HIST("h_jet_phat"), pTHat); registry.fill(HIST("h_jet_phat_weighted"), pTHat, jetweight); - fillJetHistograms(jet, collision.centrality(), jetweight); + fillJetHistograms(jet, collision.centFT0M(), jetweight); } } PROCESS_SWITCH(JetSpectraCharged, processSpectraMCDWeighted, "jet finder QA mcd with weighted events", false); @@ -753,7 +746,7 @@ struct JetSpectraCharged { if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { hasSel8Coll = true; } - if ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax)) { + if ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax)) { centralityIsGood = true; } if ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -764,7 +757,7 @@ struct JetSpectraCharged { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { hasSel8Coll = true; } - if ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax)) { + if ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax)) { centralityIsGood = true; } if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -823,7 +816,7 @@ struct JetSpectraCharged { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { hasSel8Coll = true; } - if ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax)) { + if ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax)) { centralityIsGood = true; } if ((trackOccupancyInTimeRangeMin < collision.trackOccupancyInTimeRange()) && (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax)) { @@ -876,6 +869,7 @@ struct JetSpectraCharged { } registry.fill(HIST("h_mcColl_counts"), 2.5); registry.fill(HIST("h_mcColl_counts_weight"), 2.5, eventWeight); + registry.fill(HIST("h_mc_zvertex"), mccollision.posZ(), eventWeight); bool hasSel8Coll = false; for (auto const& collision : collisions) { @@ -926,7 +920,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillEventWiseConstituentSubtractedHistograms(jet, collision.centrality()); + fillEventWiseConstituentSubtractedHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetSpectraCharged, processEvtWiseConstSubJetsData, "jet spectrum for eventwise constituent-subtracted jets data", false); @@ -948,7 +942,7 @@ struct JetSpectraCharged { if (!isAcceptedJet(jet)) { continue; } - fillEventWiseConstituentSubtractedHistograms(jet, collision.centrality()); + fillEventWiseConstituentSubtractedHistograms(jet, collision.centFT0M()); } } PROCESS_SWITCH(JetSpectraCharged, processEvtWiseConstSubJetsMCD, "jet spectrum for eventwise constituent-subtracted mcd jets", false); @@ -1017,7 +1011,7 @@ struct JetSpectraCharged { continue; } registry.fill(HIST("h_mcd_events_matched"), 1.5); - if (collision.centrality() < centralityMin || collision.centrality() > centralityMax) { + if (collision.centFT0M() < centralityMin || collision.centFT0M() > centralityMax) { continue; } registry.fill(HIST("h_mcd_events_matched"), 2.5); diff --git a/PWGJE/Tasks/jetSpectraEseTask.cxx b/PWGJE/Tasks/jetSpectraEseTask.cxx index 81741c3b0e1..007b2ea511d 100644 --- a/PWGJE/Tasks/jetSpectraEseTask.cxx +++ b/PWGJE/Tasks/jetSpectraEseTask.cxx @@ -14,39 +14,44 @@ /// /// \author Joachim C. K. B. Hansen, Lund University -#include -#include -#include -#include - -#include -#include - -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" #include "PWGJE/Core/JetDerivedDataUtilities.h" #include "PWGJE/Core/JetFindingUtilities.h" #include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" +#include "Common/Core/RecoDecay.h" #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 using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct JetSpectraEseTask { ConfigurableAxis binJetPt{"binJetPt", {250, -50., 200.}, ""}; ConfigurableAxis bindPhi{"bindPhi", {180, -o2::constants::math::PI, o2::constants::math::PI}, ""}; @@ -306,7 +311,7 @@ struct JetSpectraEseTask { return; registry.fill(HIST("hEventCounter"), counter++); - auto centrality = cfgCentVariant ? collision.centralityVariant1() : collision.centrality(); + auto centrality = cfgCentVariant ? collision.centFT0CVariant1() : collision.centFT0M(); if (cfgSelCentrality && !isCentralitySelected(centrality)) return; registry.fill(HIST("hCentralitySel"), centrality); @@ -389,7 +394,7 @@ struct JetSpectraEseTask { const auto qPerc{collision.qPERCFT0C()}; auto occupancy{collision.trackOccupancyInTimeRange()}; - registry.fill(HIST("hPsiOccupancy"), collision.centrality(), psi.psi2, occupancy); + registry.fill(HIST("hPsiOccupancy"), collision.centFT0M(), psi.psi2, occupancy); registry.fill(HIST("hOccupancy"), occupancy); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) @@ -400,11 +405,11 @@ struct JetSpectraEseTask { if (!jetderiveddatautilities::selectTrack(track, trackSelection)) continue; - registry.fill(HIST("hTrackPt"), collision.centrality(), track.pt(), qPerc[0], occupancy); + registry.fill(HIST("hTrackPt"), collision.centFT0M(), track.pt(), qPerc[0], occupancy); if (track.pt() < cfgOccupancyPtCut->at(0) || track.pt() > cfgOccupancyPtCut->at(1)) continue; - registry.fill(HIST("hTrackEta"), collision.centrality(), track.eta(), occupancy); - registry.fill(HIST("hTrackPhi"), collision.centrality(), track.phi(), occupancy); + registry.fill(HIST("hTrackEta"), collision.centFT0M(), track.eta(), occupancy); + registry.fill(HIST("hTrackPhi"), collision.centFT0M(), track.phi(), occupancy); } } PROCESS_SWITCH(JetSpectraEseTask, processESEOccupancy, "process occupancy", false); @@ -430,7 +435,7 @@ struct JetSpectraEseTask { bool eventSel = true; for (const auto& col : collisions) { if (cfgisPbPb) - centrality = col.centrality(); + centrality = col.centFT0M(); if (cfgEvSelOccupancy && !isOccupancyAccepted(col)) fOccupancy = false; if (!jetderiveddatautilities::selectCollision(col, eventSelectionBits)) @@ -469,7 +474,7 @@ struct JetSpectraEseTask { return; } - auto centrality = cfgisPbPb ? collision.centrality() : -1; + auto centrality = cfgisPbPb ? collision.centFT0M() : -1; registry.fill(HIST("mcd/hCentralitySel"), centrality); jetLoopMCD(mcdjets, centrality, collision.rho()); @@ -514,7 +519,7 @@ struct JetSpectraEseTask { return; registry.fill(HIST("mcm/hMCDMatchedEventCounter"), secCount++); - auto centrality = cfgisPbPb ? collision.centrality() : -1; + auto centrality = cfgisPbPb ? collision.centFT0M() : -1; if (cfgisPbPb) if (centrality < centRange->at(0) || centrality > centRange->at(1)) registry.fill(HIST("mcm/hMCDMatchedEventCounter"), secCount++); @@ -567,9 +572,9 @@ struct JetSpectraEseTask { { // static constexpr std::string CosList[] = {"hCosPsi2AmC", "hCosPsi2AmB", "hCosPsi2BmC"}; // (registry.fill(HIST(CosList[Idx]), col.centrality(), Corr[Idx], col.qPERCFT0C()[0]), ...); - registry.fill(HIST("hCosPsi2AmC"), col.centrality(), Corr[0], col.qPERCFT0C()[0]); - registry.fill(HIST("hCosPsi2AmB"), col.centrality(), Corr[1], col.qPERCFT0C()[0]); - registry.fill(HIST("hCosPsi2BmC"), col.centrality(), Corr[2], col.qPERCFT0C()[0]); + registry.fill(HIST("hCosPsi2AmC"), col.centFT0M(), Corr[0], col.qPERCFT0C()[0]); + registry.fill(HIST("hCosPsi2AmB"), col.centFT0M(), Corr[1], col.qPERCFT0C()[0]); + registry.fill(HIST("hCosPsi2BmC"), col.centFT0M(), Corr[2], col.qPERCFT0C()[0]); } template @@ -577,11 +582,11 @@ struct JetSpectraEseTask { { // static constexpr std::string_view EpList[] = {"hPsi2FT0A", "hPsi2FV0A", "hPsi2FT0C", "hPsi2TPCpos", "hPsi2TPCneg"}; // (registry.fill(HIST(EpList[Idx]), col.centrality(), epMap.at(std::string(RemovePrefix(EpList[Idx])))), ...); - registry.fill(HIST("hPsi2FT0A"), col.centrality(), epMap.at("FT0A")); - registry.fill(HIST("hPsi2FV0A"), col.centrality(), epMap.at("FV0A")); - registry.fill(HIST("hPsi2FT0C"), col.centrality(), epMap.at("FT0C")); - registry.fill(HIST("hPsi2TPCpos"), col.centrality(), epMap.at("TPCpos")); - registry.fill(HIST("hPsi2TPCneg"), col.centrality(), epMap.at("TPCneg")); + registry.fill(HIST("hPsi2FT0A"), col.centFT0M(), epMap.at("FT0A")); + registry.fill(HIST("hPsi2FV0A"), col.centFT0M(), epMap.at("FV0A")); + registry.fill(HIST("hPsi2FT0C"), col.centFT0M(), epMap.at("FT0C")); + registry.fill(HIST("hPsi2TPCpos"), col.centFT0M(), epMap.at("TPCpos")); + registry.fill(HIST("hPsi2TPCneg"), col.centFT0M(), epMap.at("TPCneg")); } constexpr std::string_view RemovePrefix(std::string_view str) { @@ -618,13 +623,13 @@ struct JetSpectraEseTask { int detInd{detId * 4 + cfgnTotalSystem * 4 * (nmode - 2)}; if constexpr (fill) { if (collision.qvecAmp()[detInd] > 1e-8) { - registry.fill(HIST("hQvecUncorV2"), collision.centrality(), collision.qvecRe()[detInd], collision.qvecIm()[detInd]); - registry.fill(HIST("hQvecRectrV2"), collision.centrality(), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1]); - registry.fill(HIST("hQvecTwistV2"), collision.centrality(), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2]); - registry.fill(HIST("hQvecFinalV2"), collision.centrality(), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3]); - registry.fill(HIST("hEPUncorV2"), collision.centrality(), 0.5 * std::atan2(collision.qvecIm()[detInd], collision.qvecRe()[detInd])); - registry.fill(HIST("hEPRectrV2"), collision.centrality(), 0.5 * std::atan2(collision.qvecIm()[detInd + 1], collision.qvecRe()[detInd + 1])); - registry.fill(HIST("hEPTwistV2"), collision.centrality(), 0.5 * std::atan2(collision.qvecIm()[detInd + 2], collision.qvecRe()[detInd + 2])); + registry.fill(HIST("hQvecUncorV2"), collision.centFT0M(), collision.qvecRe()[detInd], collision.qvecIm()[detInd]); + registry.fill(HIST("hQvecRectrV2"), collision.centFT0M(), collision.qvecRe()[detInd + 1], collision.qvecIm()[detInd + 1]); + registry.fill(HIST("hQvecTwistV2"), collision.centFT0M(), collision.qvecRe()[detInd + 2], collision.qvecIm()[detInd + 2]); + registry.fill(HIST("hQvecFinalV2"), collision.centFT0M(), collision.qvecRe()[detInd + 3], collision.qvecIm()[detInd + 3]); + registry.fill(HIST("hEPUncorV2"), collision.centFT0M(), 0.5 * std::atan2(collision.qvecIm()[detInd], collision.qvecRe()[detInd])); + registry.fill(HIST("hEPRectrV2"), collision.centFT0M(), 0.5 * std::atan2(collision.qvecIm()[detInd + 1], collision.qvecRe()[detInd + 1])); + registry.fill(HIST("hEPTwistV2"), collision.centFT0M(), 0.5 * std::atan2(collision.qvecIm()[detInd + 2], collision.qvecRe()[detInd + 2])); } } std::vector qVec{}; @@ -704,11 +709,11 @@ struct JetSpectraEseTask { hPhiPt->Fit(modulationFit.get(), "Q", "", 0, o2::constants::math::TwoPI); if constexpr (fillHist) { - registry.fill(HIST("hfitPar0"), col.centrality(), modulationFit->GetParameter(0)); - registry.fill(HIST("hfitPar1"), col.centrality(), modulationFit->GetParameter(1)); - registry.fill(HIST("hfitPar2"), col.centrality(), modulationFit->GetParameter(2)); - registry.fill(HIST("hfitPar3"), col.centrality(), modulationFit->GetParameter(3)); - registry.fill(HIST("hfitPar4"), col.centrality(), modulationFit->GetParameter(4)); + registry.fill(HIST("hfitPar0"), col.centFT0M(), modulationFit->GetParameter(0)); + registry.fill(HIST("hfitPar1"), col.centFT0M(), modulationFit->GetParameter(1)); + registry.fill(HIST("hfitPar2"), col.centFT0M(), modulationFit->GetParameter(2)); + registry.fill(HIST("hfitPar3"), col.centFT0M(), modulationFit->GetParameter(3)); + registry.fill(HIST("hfitPar4"), col.centFT0M(), modulationFit->GetParameter(4)); } if (modulationFit->GetParameter(0) <= 0) @@ -730,8 +735,8 @@ struct JetSpectraEseTask { auto cDF = 1. - TMath::Gamma(nDF, chi2); if constexpr (fillHist) { - registry.fill(HIST("hPValueCentCDF"), col.centrality(), cDF); - registry.fill(HIST("hCentChi2Ndf"), col.centrality(), chi2 / (static_cast(nDF))); + registry.fill(HIST("hPValueCentCDF"), col.centFT0M(), cDF); + registry.fill(HIST("hCentChi2Ndf"), col.centFT0M(), chi2 / (static_cast(nDF))); } return modulationFit; @@ -772,7 +777,7 @@ struct JetSpectraEseTask { } } } - registry.fill(HIST("hCentRhoRandomCone"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("hCentRhoRandomCone"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); randomConePt = 0; for (auto const& track : tracks) { @@ -784,7 +789,7 @@ struct JetSpectraEseTask { } } } - registry.fill(HIST("hCentRhoRandomConeRandomTrackDir"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); + registry.fill(HIST("hCentRhoRandomConeRandomTrackDir"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * collision.rho()); if (jets.size() > 0) { float dPhiLeadingJet = RecoDecay::constrainAngle(jets.iteratorAt(0).phi() - randomConePhi, -o2::constants::math::PI); @@ -820,7 +825,7 @@ struct JetSpectraEseTask { rho = evalRho(rhoFit.get(), randomConeR, randomConePhi, rho); } float dPhi{RecoDecay::constrainAngle(randomConePhi - psi.psi2, -o2::constants::math::PI)}; - registry.fill(HIST("hCentRhoRandomConewoLeadingJet"), collision.centrality(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rho, dPhi, qPerc[0]); + registry.fill(HIST("hCentRhoRandomConewoLeadingJet"), collision.centFT0M(), randomConePt - o2::constants::math::PI * randomConeR * randomConeR * rho, dPhi, qPerc[0]); double randomConePtWithoutOneLeadJet = 0; double randomConePtWithoutTwoLeadJet = 0; @@ -840,8 +845,8 @@ struct JetSpectraEseTask { } } } - registry.fill(HIST("hCentRhoRandomConeRndTrackDirwoOneLeadingJet"), collision.centrality(), randomConePtWithoutOneLeadJet - o2::constants::math::PI * randomConeR * randomConeR * rho, dPhi, qPerc[0]); - registry.fill(HIST("hCentRhoRandomConeRndTrackDirwoTwoLeadingJet"), collision.centrality(), randomConePtWithoutTwoLeadJet - o2::constants::math::PI * randomConeR * randomConeR * rho, dPhi, qPerc[0]); + registry.fill(HIST("hCentRhoRandomConeRndTrackDirwoOneLeadingJet"), collision.centFT0M(), randomConePtWithoutOneLeadJet - o2::constants::math::PI * randomConeR * randomConeR * rho, dPhi, qPerc[0]); + registry.fill(HIST("hCentRhoRandomConeRndTrackDirwoTwoLeadingJet"), collision.centFT0M(), randomConePtWithoutTwoLeadJet - o2::constants::math::PI * randomConeR * randomConeR * rho, dPhi, qPerc[0]); } template bool isTrackInJet(TTracks const& track, TJets const& jet) diff --git a/PWGJE/Tasks/jetSubstructure.cxx b/PWGJE/Tasks/jetSubstructure.cxx index f6cd4c9dd72..9980893e4e5 100644 --- a/PWGJE/Tasks/jetSubstructure.cxx +++ b/PWGJE/Tasks/jetSubstructure.cxx @@ -14,36 +14,44 @@ /// \author Nima Zardoshti // -#include -#include +#include "PWGJE/DataModel/JetSubstructure.h" -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "RecoDecay.h" + +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct JetSubstructureTask { Produces jetSubstructureDataTable; Produces jetSubstructureMCDTable; diff --git a/PWGJE/Tasks/jetSubstructureB0.cxx b/PWGJE/Tasks/jetSubstructureB0.cxx new file mode 100644 index 00000000000..aedac757bf8 --- /dev/null +++ b/PWGJE/Tasks/jetSubstructureB0.cxx @@ -0,0 +1,39 @@ +// 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 B0 charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/Tasks/jetSubstructureHF.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + +using JetSubstructureB0 = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesB0Data, aod::CandidatesB0MCP, aod::B0CJetSSs, aod::B0ChargedSPs, aod::B0ChargedPRs, aod::B0CMCDJetSSs, aod::B0ChargedMCDetectorLevelSPs, aod::B0ChargedMCDetectorLevelPRs, aod::B0CMCPJetSSs, aod::B0ChargedMCParticleLevelSPs, aod::B0ChargedMCParticleLevelPRs, aod::B0CEWSJetSSs, aod::B0ChargedEventWiseSubtractedSPs, aod::B0ChargedEventWiseSubtractedPRs, aod::JTrackB0Subs>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-b0"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/jetSubstructureB0Output.cxx b/PWGJE/Tasks/jetSubstructureB0Output.cxx new file mode 100644 index 00000000000..4cac5ffcf2c --- /dev/null +++ b/PWGJE/Tasks/jetSubstructureB0Output.cxx @@ -0,0 +1,39 @@ +// 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 output B0 charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" + +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + +using JetSubstructureOutputB0 = JetSubstructureHFOutputTask, aod::McCollisionsB0, aod::CandidatesB0Data, aod::CandidatesB0MCD, aod::CandidatesB0MCP, aod::BkgB0Rhos, aod::BkgB0McRhos, aod::JTrackB0Subs, soa::Join, soa::Join, soa::Join, soa::Join, aod::B0CJetCOs, aod::B0CJetOs, aod::B0CJetSSOs, aod::B0CJetMOs, soa::Join, soa::Join, soa::Join, aod::B0CMCDJetCOs, aod::B0CMCDJetOs, aod::B0CMCDJetSSOs, aod::B0CMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::B0CMCPJetCOs, aod::B0CMCPJetMCCOs, aod::B0CMCPJetOs, aod::B0CMCPJetSSOs, aod::B0CMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::B0CEWSJetCOs, aod::B0CEWSJetOs, aod::B0CEWSJetSSOs, aod::B0CEWSJetMOs, aod::StoredHfB0CollBase, aod::StoredHfB0Bases, aod::StoredHfB0Pars, aod::StoredHfB0ParEs, aod::StoredHfB0ParDpluss, aod::StoredHfB0Sels, aod::StoredHfB0Mls, aod::StoredHfB0MlDpluss, aod::StoredHfB0Mcs, aod::StoredHfB0McCollBases, aod::StoredHfB0McRCollIds, aod::StoredHfB0PBases>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-b0-output"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/jetSubstructureBplus.cxx b/PWGJE/Tasks/jetSubstructureBplus.cxx index 2d6d60f3d5a..527429af742 100644 --- a/PWGJE/Tasks/jetSubstructureBplus.cxx +++ b/PWGJE/Tasks/jetSubstructureBplus.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureBplus = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesBplusData, aod::CandidatesBplusMCP, aod::BplusCJetSSs, aod::BplusChargedSPs, aod::BplusChargedPRs, aod::BplusCMCDJetSSs, aod::BplusChargedMCDetectorLevelSPs, aod::BplusChargedMCDetectorLevelPRs, aod::BplusCMCPJetSSs, aod::BplusChargedMCParticleLevelSPs, aod::BplusChargedMCParticleLevelPRs, aod::BplusCEWSJetSSs, aod::BplusChargedEventWiseSubtractedSPs, aod::BplusChargedEventWiseSubtractedPRs, aod::JTrackBplusSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureBplusOutput.cxx b/PWGJE/Tasks/jetSubstructureBplusOutput.cxx index fec4c2a27ec..04a2585d5bc 100644 --- a/PWGJE/Tasks/jetSubstructureBplusOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureBplusOutput.cxx @@ -13,9 +13,21 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputBplus = JetSubstructureHFOutputTask, aod::McCollisionsBplus, aod::CandidatesBplusData, aod::CandidatesBplusMCD, aod::CandidatesBplusMCP, aod::BkgBplusRhos, aod::BkgBplusMcRhos, aod::JTrackBplusSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::BplusCJetCOs, aod::BplusCJetOs, aod::BplusCJetSSOs, aod::BplusCJetMOs, soa::Join, soa::Join, soa::Join, aod::BplusCMCDJetCOs, aod::BplusCMCDJetOs, aod::BplusCMCDJetSSOs, aod::BplusCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::BplusCMCPJetCOs, aod::BplusCMCPJetMCCOs, aod::BplusCMCPJetOs, aod::BplusCMCPJetSSOs, aod::BplusCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::BplusCEWSJetCOs, aod::BplusCEWSJetOs, aod::BplusCEWSJetSSOs, aod::BplusCEWSJetMOs, aod::StoredHfBplusCollBase, aod::StoredHfBplusBases, aod::StoredHfBplusPars, aod::StoredHfBplusParEs, aod::StoredHfBplusParD0s, aod::StoredHfBplusSels, aod::StoredHfBplusMls, aod::StoredHfBplusMlD0s, aod::StoredHfBplusMcs, aod::StoredHfBplusMcCollBases, aod::StoredHfBplusMcRCollIds, aod::StoredHfBplusPBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureD0.cxx b/PWGJE/Tasks/jetSubstructureD0.cxx index 593c5294a9c..cf77baa7ffd 100644 --- a/PWGJE/Tasks/jetSubstructureD0.cxx +++ b/PWGJE/Tasks/jetSubstructureD0.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureD0 = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesD0Data, aod::CandidatesD0MCP, aod::D0CJetSSs, aod::D0ChargedSPs, aod::D0ChargedPRs, aod::D0CMCDJetSSs, aod::D0ChargedMCDetectorLevelSPs, aod::D0ChargedMCDetectorLevelPRs, aod::D0CMCPJetSSs, aod::D0ChargedMCParticleLevelSPs, aod::D0ChargedMCParticleLevelPRs, aod::D0CEWSJetSSs, aod::D0ChargedEventWiseSubtractedSPs, aod::D0ChargedEventWiseSubtractedPRs, aod::JTrackD0Subs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureD0Output.cxx b/PWGJE/Tasks/jetSubstructureD0Output.cxx index 43b909a3688..d8bdaaf06d1 100644 --- a/PWGJE/Tasks/jetSubstructureD0Output.cxx +++ b/PWGJE/Tasks/jetSubstructureD0Output.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputD0 = JetSubstructureHFOutputTask, aod::McCollisionsD0, aod::CandidatesD0Data, aod::CandidatesD0MCD, aod::CandidatesD0MCP, aod::BkgD0Rhos, aod::BkgD0McRhos, aod::JTrackD0Subs, soa::Join, soa::Join, soa::Join, soa::Join, aod::D0CJetCOs, aod::D0CJetOs, aod::D0CJetSSOs, aod::D0CJetMOs, soa::Join, soa::Join, soa::Join, aod::D0CMCDJetCOs, aod::D0CMCDJetOs, aod::D0CMCDJetSSOs, aod::D0CMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::D0CMCPJetCOs, aod::D0CMCPJetMCCOs, aod::D0CMCPJetOs, aod::D0CMCPJetSSOs, aod::D0CMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::D0CEWSJetCOs, aod::D0CEWSJetOs, aod::D0CEWSJetSSOs, aod::D0CEWSJetMOs, aod::StoredHfD0CollBase, aod::StoredHfD0Bases, aod::StoredHfD0Pars, aod::StoredHfD0ParEs, aod::JDumD0ParDaus, aod::StoredHfD0Sels, aod::StoredHfD0Mls, aod::JDumD0MlDaus, aod::StoredHfD0Mcs, aod::StoredHfD0McCollBases, aod::StoredHfD0McRCollIds, aod::StoredHfD0PBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDielectron.cxx b/PWGJE/Tasks/jetSubstructureDielectron.cxx index 665d0f2f636..5ba3468727c 100644 --- a/PWGJE/Tasks/jetSubstructureDielectron.cxx +++ b/PWGJE/Tasks/jetSubstructureDielectron.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureDielectron = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesDielectronData, aod::CandidatesDielectronMCP, aod::DielectronCJetSSs, aod::DielectronChargedSPs, aod::DielectronChargedPRs, aod::DielectronCMCDJetSSs, aod::DielectronChargedMCDetectorLevelSPs, aod::DielectronChargedMCDetectorLevelPRs, aod::DielectronCMCPJetSSs, aod::DielectronChargedMCParticleLevelSPs, aod::DielectronChargedMCParticleLevelPRs, aod::DielectronCEWSJetSSs, aod::DielectronChargedEventWiseSubtractedSPs, aod::DielectronChargedEventWiseSubtractedPRs, aod::JTrackDielectronSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx b/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx index 8c8d7a8980d..84ef77afc4e 100644 --- a/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureDielectronOutput.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGDQ/DataModel/ReducedInfoTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataDQ.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputDielectron = JetSubstructureHFOutputTask, aod::McCollisionsDielectron, aod::CandidatesDielectronData, aod::CandidatesDielectronMCD, aod::CandidatesDielectronMCP, aod::BkgDielectronRhos, aod::BkgDielectronMcRhos, aod::JTrackDielectronSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DielectronCJetCOs, aod::DielectronCJetOs, aod::DielectronCJetSSOs, aod::DielectronCJetMOs, soa::Join, soa::Join, soa::Join, aod::DielectronCMCDJetCOs, aod::DielectronCMCDJetOs, aod::DielectronCMCDJetSSOs, aod::DielectronCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DielectronCMCPJetCOs, aod::DielectronCMCPJetMCCOs, aod::DielectronCMCPJetOs, aod::DielectronCMCPJetSSOs, aod::DielectronCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::DielectronCEWSJetCOs, aod::DielectronCEWSJetOs, aod::DielectronCEWSJetSSOs, aod::DielectronCEWSJetMOs, aod::StoredReducedEvents, aod::StoredDielectrons, aod::JDielectron1Dummys, aod::JDielectron2Dummys, aod::JDielectron3Dummys, aod::JDielectron4Dummys, aod::JDielectron5Dummys, aod::JDielectron6Dummys, aod::JDielectron7Dummys, aod::StoredJDielectronMcCollisions, aod::JDielectronMcRCollDummys, aod::StoredJDielectronMcs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDplus.cxx b/PWGJE/Tasks/jetSubstructureDplus.cxx index 1aee6336c8d..e1550673039 100644 --- a/PWGJE/Tasks/jetSubstructureDplus.cxx +++ b/PWGJE/Tasks/jetSubstructureDplus.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureDplus = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesDplusData, aod::CandidatesDplusMCP, aod::DplusCJetSSs, aod::DplusChargedSPs, aod::DplusChargedPRs, aod::DplusCMCDJetSSs, aod::DplusChargedMCDetectorLevelSPs, aod::DplusChargedMCDetectorLevelPRs, aod::DplusCMCPJetSSs, aod::DplusChargedMCParticleLevelSPs, aod::DplusChargedMCParticleLevelPRs, aod::DplusCEWSJetSSs, aod::DplusChargedEventWiseSubtractedSPs, aod::DplusChargedEventWiseSubtractedPRs, aod::JTrackDplusSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDplusOutput.cxx b/PWGJE/Tasks/jetSubstructureDplusOutput.cxx index e45dfc5833c..22a869bfcfa 100644 --- a/PWGJE/Tasks/jetSubstructureDplusOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureDplusOutput.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputDplus = JetSubstructureHFOutputTask, aod::McCollisionsDplus, aod::CandidatesDplusData, aod::CandidatesDplusMCD, aod::CandidatesDplusMCP, aod::BkgDplusRhos, aod::BkgDplusMcRhos, aod::JTrackDplusSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DplusCJetCOs, aod::DplusCJetOs, aod::DplusCJetSSOs, aod::DplusCJetMOs, soa::Join, soa::Join, soa::Join, aod::DplusCMCDJetCOs, aod::DplusCMCDJetOs, aod::DplusCMCDJetSSOs, aod::DplusCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DplusCMCPJetCOs, aod::DplusCMCPJetMCCOs, aod::DplusCMCPJetOs, aod::DplusCMCPJetSSOs, aod::DplusCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::DplusCEWSJetCOs, aod::DplusCEWSJetOs, aod::DplusCEWSJetSSOs, aod::DplusCEWSJetMOs, aod::StoredHfDplusCollBase, aod::StoredHfDplusBases, aod::StoredHfDplusPars, aod::StoredHfDplusParEs, aod::JDumDplusParDaus, aod::StoredHfDplusSels, aod::StoredHfDplusMls, aod::JDumDplusMlDaus, aod::StoredHfDplusMcs, aod::StoredHfDplusMcCollBases, aod::StoredHfDplusMcRCollIds, aod::StoredHfDplusPBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureDstar.cxx b/PWGJE/Tasks/jetSubstructureDstar.cxx new file mode 100644 index 00000000000..02c95adbbda --- /dev/null +++ b/PWGJE/Tasks/jetSubstructureDstar.cxx @@ -0,0 +1,39 @@ +// 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 D* charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/Tasks/jetSubstructureHF.cxx" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + +using JetSubstructureDstar = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesDstarData, aod::CandidatesDstarMCP, aod::DstarCJetSSs, aod::DstarChargedSPs, aod::DstarChargedPRs, aod::DstarCMCDJetSSs, aod::DstarChargedMCDetectorLevelSPs, aod::DstarChargedMCDetectorLevelPRs, aod::DstarCMCPJetSSs, aod::DstarChargedMCParticleLevelSPs, aod::DstarChargedMCParticleLevelPRs, aod::DstarCEWSJetSSs, aod::DstarChargedEventWiseSubtractedSPs, aod::DstarChargedEventWiseSubtractedPRs, aod::JTrackDstarSubs>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, + SetDefaultProcesses{}, + TaskName{"jet-substructure-dstar"})); + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/jetSubstructureDstarOutput.cxx b/PWGJE/Tasks/jetSubstructureDstarOutput.cxx new file mode 100644 index 00000000000..d7ced94f0ad --- /dev/null +++ b/PWGJE/Tasks/jetSubstructureDstarOutput.cxx @@ -0,0 +1,40 @@ +// 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 output D* charged task +// +/// \author Nima Zardoshti + +#include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" + +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + +using JetSubstructureOutputDstar = JetSubstructureHFOutputTask, aod::McCollisionsDstar, aod::CandidatesDstarData, aod::CandidatesDstarMCD, aod::CandidatesDstarMCP, aod::BkgDstarRhos, aod::BkgDstarMcRhos, aod::JTrackDstarSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DstarCJetCOs, aod::DstarCJetOs, aod::DstarCJetSSOs, aod::DstarCJetMOs, soa::Join, soa::Join, soa::Join, aod::DstarCMCDJetCOs, aod::DstarCMCDJetOs, aod::DstarCMCDJetSSOs, aod::DstarCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::DstarCMCPJetCOs, aod::DstarCMCPJetMCCOs, aod::DstarCMCPJetOs, aod::DstarCMCPJetSSOs, aod::DstarCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::DstarCEWSJetCOs, aod::DstarCEWSJetOs, aod::DstarCEWSJetSSOs, aod::DstarCEWSJetMOs, aod::StoredHfDstarCollBase, aod::StoredHfDstarBases, aod::StoredHfDstarPars, aod::JDumDstarParEs, aod::HfDstarParD0s, aod::StoredHfDstarSels, aod::StoredHfDstarMls, aod::JDumDstarMlDaus, aod::StoredHfDstarMcs, aod::StoredHfDstarMcCollBases, aod::StoredHfDstarMcRCollIds, aod::StoredHfDstarPBases>; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + std::vector tasks; + tasks.emplace_back(adaptAnalysisTask(cfgc, SetDefaultProcesses{}, TaskName{"jet-substructure-dstar-output"})); + + return WorkflowSpec{tasks}; +} diff --git a/PWGJE/Tasks/jetSubstructureHF.cxx b/PWGJE/Tasks/jetSubstructureHF.cxx index 3cbdbf6fd34..c098236dae7 100644 --- a/PWGJE/Tasks/jetSubstructureHF.cxx +++ b/PWGJE/Tasks/jetSubstructureHF.cxx @@ -14,39 +14,44 @@ /// \author Nima Zardoshti // -#include -#include +#include "RecoDecay.h" -#include "fastjet/PseudoJet.hh" -#include "fastjet/ClusterSequenceArea.hh" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDQUtilities.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetHFUtilities.h" +#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetHFUtilities.h" -#include "PWGJE/Core/JetDQUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "fastjet/ClusterSequenceArea.hh" +#include "fastjet/PseudoJet.hh" +#include + +#include +#include +#include +#include + +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! -#include "Framework/runDataProcessing.h" template struct JetSubstructureHFTask { @@ -125,20 +130,26 @@ struct JetSubstructureHFTask { Preslice TracksPerCollision = aod::jtrack::collisionId; PresliceOptional TracksPerD0DataSub = aod::bkgd0::candidateId; PresliceOptional TracksPerDplusDataSub = aod::bkgdplus::candidateId; + PresliceOptional TracksPerDstarDataSub = aod::bkgdstar::candidateId; PresliceOptional TracksPerLcDataSub = aod::bkglc::candidateId; + PresliceOptional TracksPerB0DataSub = aod::bkgb0::candidateId; PresliceOptional TracksPerBplusDataSub = aod::bkgbplus::candidateId; PresliceOptional TracksPerDielectronDataSub = aod::bkgdielectron::candidateId; Preslice ParticlesPerMcCollision = aod::jmcparticle::mcCollisionId; - template - auto selectSlicer(T const& D0Slicer, U const& DplusSlicer, V const& LcSlicer, M const& BplusSlicer, N const& DielectronSlicer) + template + auto selectSlicer(T const& D0Slicer, U const& DplusSlicer, V const& DstarSlicer, M const& LcSlicer, N const& B0Slicer, O const& BplusSlicer, P const& DielectronSlicer) { if constexpr (jethfutilities::isD0Table()) { return D0Slicer; } else if constexpr (jethfutilities::isDplusTable()) { return DplusSlicer; + } else if constexpr (jethfutilities::isDstarTable()) { + return DstarSlicer; } else if constexpr (jethfutilities::isLcTable()) { return LcSlicer; + } else if constexpr (jethfutilities::isB0Table()) { + return B0Slicer; } else if constexpr (jethfutilities::isBplusTable()) { return BplusSlicer; } else if constexpr (jetdqutilities::isDielectronTable()) { @@ -430,7 +441,7 @@ struct JetSubstructureHFTask { CandidateTable const& candidates, TracksSub const& tracks) { - analyseCharged(jet, tracks, candidates, selectSlicer(TracksPerD0DataSub, TracksPerDplusDataSub, TracksPerLcDataSub, TracksPerBplusDataSub, TracksPerDielectronDataSub), jetSubstructureDataSubTable, jetSplittingsDataSubTable, jetPairsDataSubTable); + analyseCharged(jet, tracks, candidates, selectSlicer(TracksPerD0DataSub, TracksPerDplusDataSub, TracksPerDstarDataSub, TracksPerLcDataSub, TracksPerB0DataSub, TracksPerBplusDataSub, TracksPerDielectronDataSub), jetSubstructureDataSubTable, jetSplittingsDataSubTable, jetPairsDataSubTable); } PROCESS_SWITCH(JetSubstructureHFTask, processChargedJetsDataSub, "HF jet substructure on data", false); diff --git a/PWGJE/Tasks/jetSubstructureHFOutput.cxx b/PWGJE/Tasks/jetSubstructureHFOutput.cxx index 8a781d84bfb..ee3aaebc142 100644 --- a/PWGJE/Tasks/jetSubstructureHFOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureHFOutput.cxx @@ -14,36 +14,30 @@ /// \author Nima Zardoshti // -#include -#include -#include -#include +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include -#include "PWGHF/DataModel/CandidateReconstructionTables.h" -#include "PWGHF/DataModel/CandidateSelectionTables.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! -#include "Framework/runDataProcessing.h" template struct JetSubstructureHFOutputTask { @@ -131,60 +125,83 @@ struct JetSubstructureHFOutputTask { jetRadiiValues = (std::vector)configs.jetRadii; } - PresliceUnsorted> CollisionsPerMcCollision = aod::jmccollisionlb::mcCollisionId; - PresliceOptional CandidateCollisionsPerCollision = aod::jcandidateindices::collisionId; - PresliceOptional CandidateMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; - PresliceOptional CandidateMcCollisionsPerMcCollisionMCPOnly = aod::jcandidateindices::mcCollisionId; - - PresliceOptional> D0SplittingsPerJetData = aod::d0chargedsplitting::jetId; - PresliceOptional> D0SplittingsPerJetDataSub = aod::d0chargedeventwisesubtractedsplitting::jetId; - PresliceOptional> D0SplittingsPerJetMCD = aod::d0chargedmcdetectorlevelsplitting::jetId; - PresliceOptional> D0SplittingsPerJetMCP = aod::d0chargedmcparticlelevelsplitting::jetId; - - PresliceOptional> D0PairsPerJetData = aod::d0chargedpair::jetId; - PresliceOptional> D0PairsPerJetDataSub = aod::d0chargedeventwisesubtractedpair::jetId; - PresliceOptional> D0PairsPerJetMCD = aod::d0chargedmcdetectorlevelpair::jetId; - PresliceOptional> D0PairsPerJetMCP = aod::d0chargedmcparticlelevelpair::jetId; - - PresliceOptional> DplusSplittingsPerJetData = aod::dpluschargedsplitting::jetId; - PresliceOptional> DplusSplittingsPerJetDataSub = aod::dpluschargedeventwisesubtractedsplitting::jetId; - PresliceOptional> DplusSplittingsPerJetMCD = aod::dpluschargedmcdetectorlevelsplitting::jetId; - PresliceOptional> DplusSplittingsPerJetMCP = aod::dpluschargedmcparticlelevelsplitting::jetId; - - PresliceOptional> DplusPairsPerJetData = aod::dpluschargedpair::jetId; - PresliceOptional> DplusPairsPerJetDataSub = aod::dpluschargedeventwisesubtractedpair::jetId; - PresliceOptional> DplusPairsPerJetMCD = aod::dpluschargedmcdetectorlevelpair::jetId; - PresliceOptional> DplusPairsPerJetMCP = aod::dpluschargedmcparticlelevelpair::jetId; - - PresliceOptional> LcSplittingsPerJetData = aod::lcchargedsplitting::jetId; - PresliceOptional> LcSplittingsPerJetDataSub = aod::lcchargedeventwisesubtractedsplitting::jetId; - PresliceOptional> LcSplittingsPerJetMCD = aod::lcchargedmcdetectorlevelsplitting::jetId; - PresliceOptional> LcSplittingsPerJetMCP = aod::lcchargedmcparticlelevelsplitting::jetId; - - PresliceOptional> LcPairsPerJetData = aod::lcchargedpair::jetId; - PresliceOptional> LcPairsPerJetDataSub = aod::lcchargedeventwisesubtractedpair::jetId; - PresliceOptional> LcPairsPerJetMCD = aod::lcchargedmcdetectorlevelpair::jetId; - PresliceOptional> LcPairsPerJetMCP = aod::lcchargedmcparticlelevelpair::jetId; - - PresliceOptional> BplusSplittingsPerJetData = aod::bpluschargedsplitting::jetId; - PresliceOptional> BplusSplittingsPerJetDataSub = aod::bpluschargedeventwisesubtractedsplitting::jetId; - PresliceOptional> BplusSplittingsPerJetMCD = aod::bpluschargedmcdetectorlevelsplitting::jetId; - PresliceOptional> BplusSplittingsPerJetMCP = aod::bpluschargedmcparticlelevelsplitting::jetId; - - PresliceOptional> BplusPairsPerJetData = aod::bpluschargedpair::jetId; - PresliceOptional> BplusPairsPerJetDataSub = aod::bpluschargedeventwisesubtractedpair::jetId; - PresliceOptional> BplusPairsPerJetMCD = aod::bpluschargedmcdetectorlevelpair::jetId; - PresliceOptional> BplusPairsPerJetMCP = aod::bpluschargedmcparticlelevelpair::jetId; - - PresliceOptional> DielectronSplittingsPerJetData = aod::dielectronchargedsplitting::jetId; - PresliceOptional> DielectronSplittingsPerJetDataSub = aod::dielectronchargedeventwisesubtractedsplitting::jetId; - PresliceOptional> DielectronSplittingsPerJetMCD = aod::dielectronchargedmcdetectorlevelsplitting::jetId; - PresliceOptional> DielectronSplittingsPerJetMCP = aod::dielectronchargedmcparticlelevelsplitting::jetId; - - PresliceOptional> DielectronPairsPerJetData = aod::dielectronchargedpair::jetId; - PresliceOptional> DielectronPairsPerJetDataSub = aod::dielectronchargedeventwisesubtractedpair::jetId; - PresliceOptional> DielectronPairsPerJetMCD = aod::dielectronchargedmcdetectorlevelpair::jetId; - PresliceOptional> DielectronPairsPerJetMCP = aod::dielectronchargedmcparticlelevelpair::jetId; + struct : PresliceGroup { + PresliceUnsorted> CollisionsPerMcCollision = aod::jmccollisionlb::mcCollisionId; + PresliceOptional CandidateCollisionsPerCollision = aod::jcandidateindices::collisionId; + PresliceOptional CandidateMcCollisionsPerMcCollision = aod::jcandidateindices::mcCollisionId; + PresliceOptional CandidateMcCollisionsPerMcCollisionMCPOnly = aod::jcandidateindices::mcCollisionId; + + PresliceOptional> D0SplittingsPerJetData = aod::d0chargedsplitting::jetId; + PresliceOptional> D0SplittingsPerJetDataSub = aod::d0chargedeventwisesubtractedsplitting::jetId; + PresliceOptional> D0SplittingsPerJetMCD = aod::d0chargedmcdetectorlevelsplitting::jetId; + PresliceOptional> D0SplittingsPerJetMCP = aod::d0chargedmcparticlelevelsplitting::jetId; + + PresliceOptional> D0PairsPerJetData = aod::d0chargedpair::jetId; + PresliceOptional> D0PairsPerJetDataSub = aod::d0chargedeventwisesubtractedpair::jetId; + PresliceOptional> D0PairsPerJetMCD = aod::d0chargedmcdetectorlevelpair::jetId; + PresliceOptional> D0PairsPerJetMCP = aod::d0chargedmcparticlelevelpair::jetId; + + PresliceOptional> DplusSplittingsPerJetData = aod::dpluschargedsplitting::jetId; + PresliceOptional> DplusSplittingsPerJetDataSub = aod::dpluschargedeventwisesubtractedsplitting::jetId; + PresliceOptional> DplusSplittingsPerJetMCD = aod::dpluschargedmcdetectorlevelsplitting::jetId; + PresliceOptional> DplusSplittingsPerJetMCP = aod::dpluschargedmcparticlelevelsplitting::jetId; + + PresliceOptional> DplusPairsPerJetData = aod::dpluschargedpair::jetId; + PresliceOptional> DplusPairsPerJetDataSub = aod::dpluschargedeventwisesubtractedpair::jetId; + PresliceOptional> DplusPairsPerJetMCD = aod::dpluschargedmcdetectorlevelpair::jetId; + PresliceOptional> DplusPairsPerJetMCP = aod::dpluschargedmcparticlelevelpair::jetId; + + PresliceOptional> DstarSplittingsPerJetData = aod::dstarchargedsplitting::jetId; + PresliceOptional> DstarSplittingsPerJetDataSub = aod::dstarchargedeventwisesubtractedsplitting::jetId; + PresliceOptional> DstarSplittingsPerJetMCD = aod::dstarchargedmcdetectorlevelsplitting::jetId; + PresliceOptional> DstarSplittingsPerJetMCP = aod::dstarchargedmcparticlelevelsplitting::jetId; + + PresliceOptional> DstarPairsPerJetData = aod::dstarchargedpair::jetId; + PresliceOptional> DstarPairsPerJetDataSub = aod::dstarchargedeventwisesubtractedpair::jetId; + PresliceOptional> DstarPairsPerJetMCD = aod::dstarchargedmcdetectorlevelpair::jetId; + PresliceOptional> DstarPairsPerJetMCP = aod::dstarchargedmcparticlelevelpair::jetId; + + PresliceOptional> LcSplittingsPerJetData = aod::lcchargedsplitting::jetId; + PresliceOptional> LcSplittingsPerJetDataSub = aod::lcchargedeventwisesubtractedsplitting::jetId; + PresliceOptional> LcSplittingsPerJetMCD = aod::lcchargedmcdetectorlevelsplitting::jetId; + PresliceOptional> LcSplittingsPerJetMCP = aod::lcchargedmcparticlelevelsplitting::jetId; + + PresliceOptional> LcPairsPerJetData = aod::lcchargedpair::jetId; + PresliceOptional> LcPairsPerJetDataSub = aod::lcchargedeventwisesubtractedpair::jetId; + PresliceOptional> LcPairsPerJetMCD = aod::lcchargedmcdetectorlevelpair::jetId; + PresliceOptional> LcPairsPerJetMCP = aod::lcchargedmcparticlelevelpair::jetId; + + PresliceOptional> B0SplittingsPerJetData = aod::b0chargedsplitting::jetId; + PresliceOptional> B0SplittingsPerJetDataSub = aod::b0chargedeventwisesubtractedsplitting::jetId; + PresliceOptional> B0SplittingsPerJetMCD = aod::b0chargedmcdetectorlevelsplitting::jetId; + PresliceOptional> B0SplittingsPerJetMCP = aod::b0chargedmcparticlelevelsplitting::jetId; + + PresliceOptional> B0PairsPerJetData = aod::b0chargedpair::jetId; + PresliceOptional> B0PairsPerJetDataSub = aod::b0chargedeventwisesubtractedpair::jetId; + PresliceOptional> B0PairsPerJetMCD = aod::b0chargedmcdetectorlevelpair::jetId; + PresliceOptional> B0PairsPerJetMCP = aod::b0chargedmcparticlelevelpair::jetId; + + PresliceOptional> BplusSplittingsPerJetData = aod::bpluschargedsplitting::jetId; + PresliceOptional> BplusSplittingsPerJetDataSub = aod::bpluschargedeventwisesubtractedsplitting::jetId; + PresliceOptional> BplusSplittingsPerJetMCD = aod::bpluschargedmcdetectorlevelsplitting::jetId; + PresliceOptional> BplusSplittingsPerJetMCP = aod::bpluschargedmcparticlelevelsplitting::jetId; + + PresliceOptional> BplusPairsPerJetData = aod::bpluschargedpair::jetId; + PresliceOptional> BplusPairsPerJetDataSub = aod::bpluschargedeventwisesubtractedpair::jetId; + PresliceOptional> BplusPairsPerJetMCD = aod::bpluschargedmcdetectorlevelpair::jetId; + PresliceOptional> BplusPairsPerJetMCP = aod::bpluschargedmcparticlelevelpair::jetId; + + PresliceOptional> DielectronSplittingsPerJetData = aod::dielectronchargedsplitting::jetId; + PresliceOptional> DielectronSplittingsPerJetDataSub = aod::dielectronchargedeventwisesubtractedsplitting::jetId; + PresliceOptional> DielectronSplittingsPerJetMCD = aod::dielectronchargedmcdetectorlevelsplitting::jetId; + PresliceOptional> DielectronSplittingsPerJetMCP = aod::dielectronchargedmcparticlelevelsplitting::jetId; + + PresliceOptional> DielectronPairsPerJetData = aod::dielectronchargedpair::jetId; + PresliceOptional> DielectronPairsPerJetDataSub = aod::dielectronchargedeventwisesubtractedpair::jetId; + PresliceOptional> DielectronPairsPerJetMCD = aod::dielectronchargedmcdetectorlevelpair::jetId; + PresliceOptional> DielectronPairsPerJetMCP = aod::dielectronchargedmcparticlelevelpair::jetId; + + } preslices; template auto candidateMCCollisionSlicer(T const& McCollisionsPerMcCollision, U const& McCollisionsPerMcCollisionMCPOnly) @@ -313,7 +330,7 @@ struct JetSubstructureHFOutputTask { float centrality = -1.0; uint8_t eventSel = 0.0; if constexpr (!isMCP) { - centrality = collision.centrality(); + centrality = collision.centFT0M(); eventSel = collision.eventSel(); } collisionOutputTable(collision.posZ(), centrality, eventSel, eventWeight); @@ -366,8 +383,8 @@ struct JetSubstructureHFOutputTask { } } - template - void analyseSubstructureMatched(T const& jets, U const& allSplittings, V const& allPairs, M const& D0SplittingsPerJet, N const DplusSplittingsPerJet, O const& LcSplittingsPerJet, P const& BplusSplittingsPerJet, Q const& DielectronSplittingsPerJet, R const& D0PairsPerJet, S const DplusPairsPerJet, A const& LcPairsPerJet, B const& BplusPairsPerJet, C const& DielectronPairsPerJet, std::vector>& splittingMatchesGeoVecVec, std::vector>& splittingMatchesPtVecVec, std::vector>& splittingMatchesHFVecVec, std::vector>& pairMatchesVecVec, float jetPtMin) + template + void analyseSubstructureMatched(T const& jets, U const& allSplittings, V const& allPairs, M const& D0SplittingsPerJet, N const DplusSplittingsPerJet, O const DstarSplittingsPerJet, P const& LcSplittingsPerJet, Q const& B0SplittingsPerJet, R const& BplusSplittingsPerJet, S const& DielectronSplittingsPerJet, A const& D0PairsPerJet, B const DplusPairsPerJet, C const& DstarPairsPerJet, D const& LcPairsPerJet, E const& B0PairsPerJet, F const& BplusPairsPerJet, G const& DielectronPairsPerJet, std::vector>& splittingMatchesGeoVecVec, std::vector>& splittingMatchesPtVecVec, std::vector>& splittingMatchesHFVecVec, std::vector>& pairMatchesVecVec, float jetPtMin) { for (const auto& jet : jets) { if (jet.pt() < jetPtMin) { @@ -378,9 +395,9 @@ struct JetSubstructureHFOutputTask { } for (const auto& jetRadiiValue : jetRadiiValues) { if (jet.r() == round(jetRadiiValue * 100.0f)) { - auto splittings = jetcandidateutilities::slicedPerJet(allSplittings, jet, D0SplittingsPerJet, DplusSplittingsPerJet, LcSplittingsPerJet, BplusSplittingsPerJet, DielectronSplittingsPerJet); + auto splittings = jetcandidateutilities::slicedPerJet(allSplittings, jet, D0SplittingsPerJet, DplusSplittingsPerJet, DstarSplittingsPerJet, LcSplittingsPerJet, B0SplittingsPerJet, BplusSplittingsPerJet, DielectronSplittingsPerJet); fillSplittingMatchingVectors(splittings, jet.globalIndex(), splittingMatchesGeoVecVec, splittingMatchesPtVecVec, splittingMatchesHFVecVec); - auto pairs = jetcandidateutilities::slicedPerJet(allPairs, jet, D0PairsPerJet, DplusPairsPerJet, LcPairsPerJet, BplusPairsPerJet, DielectronPairsPerJet); + auto pairs = jetcandidateutilities::slicedPerJet(allPairs, jet, D0PairsPerJet, DplusPairsPerJet, DstarPairsPerJet, LcPairsPerJet, B0PairsPerJet, BplusPairsPerJet, DielectronPairsPerJet); fillPairMatchingVectors(pairs, jet.globalIndex(), pairMatchesVecVec); } } @@ -482,7 +499,7 @@ struct JetSubstructureHFOutputTask { mcCollisionFlag[jetMCP.mcCollisionId()] = true; if constexpr (!isMCPOnly) { - const auto collisionsPerMcCollision = collisions.sliceBy(CollisionsPerMcCollision, jetMCP.mcCollisionId()); + const auto collisionsPerMcCollision = collisions.sliceBy(preslices.CollisionsPerMcCollision, jetMCP.mcCollisionId()); for (auto collision : collisionsPerMcCollision) { collisionFlag[collision.globalIndex()] = true; } @@ -494,7 +511,7 @@ struct JetSubstructureHFOutputTask { if constexpr (!isMCPOnly) { for (const auto& collision : collisions) { if (collisionFlag[collision.globalIndex()]) { - const auto hfCollisionsPerCollision = hfCollisions.sliceBy(CandidateCollisionsPerCollision, collision.globalIndex()); + const auto hfCollisionsPerCollision = hfCollisions.sliceBy(preslices.CandidateCollisionsPerCollision, collision.globalIndex()); for (const auto& hfCollisionPerCollision : hfCollisionsPerCollision) { // should only ever be one auto hfCollisionTableIndex = candidateCollisionMapping.find(hfCollisionPerCollision.globalIndex()); if (hfCollisionTableIndex != candidateCollisionMapping.end()) { @@ -509,7 +526,7 @@ struct JetSubstructureHFOutputTask { if constexpr (isMC) { for (const auto& mcCollision : mcCollisions) { if (mcCollisionFlag[mcCollision.globalIndex()]) { - const auto hfMcCollisionsPerMcCollision = hfMcCollisions.sliceBy(candidateMCCollisionSlicer(CandidateMcCollisionsPerMcCollision, CandidateMcCollisionsPerMcCollisionMCPOnly), mcCollision.globalIndex()); + const auto hfMcCollisionsPerMcCollision = hfMcCollisions.sliceBy(candidateMCCollisionSlicer(preslices.CandidateMcCollisionsPerMcCollision, preslices.CandidateMcCollisionsPerMcCollisionMCPOnly), mcCollision.globalIndex()); for (const auto& hfMcCollisionPerMcCollision : hfMcCollisionsPerMcCollision) { // should only ever be one auto hfMcCollisionTableIndex = candidateMcCollisionMapping.find(hfMcCollisionPerMcCollision.globalIndex()); if (hfMcCollisionTableIndex != candidateMcCollisionMapping.end()) { @@ -639,12 +656,12 @@ struct JetSubstructureHFOutputTask { splittingMatchesPtVecVecData.assign(jets.size(), {}); splittingMatchesHFVecVecData.assign(jets.size(), {}); pairMatchesVecVecData.assign(jets.size(), {}); - analyseSubstructureMatched(jets, splittingsData, pairsData, D0SplittingsPerJetData, DplusSplittingsPerJetData, LcSplittingsPerJetData, BplusSplittingsPerJetData, DielectronSplittingsPerJetData, D0PairsPerJetData, DplusPairsPerJetData, LcPairsPerJetData, BplusPairsPerJetData, DielectronPairsPerJetData, splittingMatchesGeoVecVecData, splittingMatchesPtVecVecData, splittingMatchesHFVecVecData, pairMatchesVecVecData, configs.jetPtMinData); + analyseSubstructureMatched(jets, splittingsData, pairsData, preslices.D0SplittingsPerJetData, preslices.DplusSplittingsPerJetData, preslices.DstarSplittingsPerJetData, preslices.LcSplittingsPerJetData, preslices.B0SplittingsPerJetData, preslices.BplusSplittingsPerJetData, preslices.DielectronSplittingsPerJetData, preslices.D0PairsPerJetData, preslices.DplusPairsPerJetData, preslices.DstarPairsPerJetData, preslices.LcPairsPerJetData, preslices.B0PairsPerJetData, preslices.BplusPairsPerJetData, preslices.DielectronPairsPerJetData, splittingMatchesGeoVecVecData, splittingMatchesPtVecVecData, splittingMatchesHFVecVecData, pairMatchesVecVecData, configs.jetPtMinData); splittingMatchesGeoVecVecDataSub.assign(jetsSub.size(), {}); splittingMatchesPtVecVecDataSub.assign(jetsSub.size(), {}); splittingMatchesHFVecVecDataSub.assign(jetsSub.size(), {}); pairMatchesVecVecDataSub.assign(jetsSub.size(), {}); - analyseSubstructureMatched(jetsSub, splittingsDataSub, pairsDataSub, D0SplittingsPerJetDataSub, DplusSplittingsPerJetDataSub, LcSplittingsPerJetDataSub, BplusSplittingsPerJetDataSub, DielectronSplittingsPerJetDataSub, D0PairsPerJetDataSub, DplusPairsPerJetDataSub, LcPairsPerJetDataSub, BplusPairsPerJetDataSub, DielectronPairsPerJetDataSub, splittingMatchesGeoVecVecDataSub, splittingMatchesPtVecVecDataSub, splittingMatchesHFVecVecDataSub, pairMatchesVecVecDataSub, configs.jetPtMinDataSub); + analyseSubstructureMatched(jetsSub, splittingsDataSub, pairsDataSub, preslices.D0SplittingsPerJetDataSub, preslices.DplusSplittingsPerJetDataSub, preslices.DstarSplittingsPerJetDataSub, preslices.LcSplittingsPerJetDataSub, preslices.B0SplittingsPerJetDataSub, preslices.BplusSplittingsPerJetDataSub, preslices.DielectronSplittingsPerJetDataSub, preslices.D0PairsPerJetDataSub, preslices.DplusPairsPerJetDataSub, preslices.DstarPairsPerJetDataSub, preslices.LcPairsPerJetDataSub, preslices.B0PairsPerJetDataSub, preslices.BplusPairsPerJetDataSub, preslices.DielectronPairsPerJetDataSub, splittingMatchesGeoVecVecDataSub, splittingMatchesPtVecVecDataSub, splittingMatchesHFVecVecDataSub, pairMatchesVecVecDataSub, configs.jetPtMinDataSub); } PROCESS_SWITCH(JetSubstructureHFOutputTask, processOutputSubstructureMatchingData, "jet substructure matching output Data", false); @@ -685,12 +702,12 @@ struct JetSubstructureHFOutputTask { splittingMatchesPtVecVecMCD.assign(jetsMCD.size(), {}); splittingMatchesHFVecVecMCD.assign(jetsMCD.size(), {}); pairMatchesVecVecMCD.assign(jetsMCD.size(), {}); - analyseSubstructureMatched(jetsMCD, splittingsMCD, pairsMCD, D0SplittingsPerJetMCD, DplusSplittingsPerJetMCD, LcSplittingsPerJetMCD, BplusSplittingsPerJetMCD, DielectronSplittingsPerJetMCD, D0PairsPerJetMCD, DplusPairsPerJetMCD, LcPairsPerJetMCD, BplusPairsPerJetMCD, DielectronPairsPerJetMCD, splittingMatchesGeoVecVecMCD, splittingMatchesPtVecVecMCD, splittingMatchesHFVecVecMCD, pairMatchesVecVecMCD, configs.jetPtMinMCD); + analyseSubstructureMatched(jetsMCD, splittingsMCD, pairsMCD, preslices.D0SplittingsPerJetMCD, preslices.DplusSplittingsPerJetMCD, preslices.DstarSplittingsPerJetMCD, preslices.LcSplittingsPerJetMCD, preslices.B0SplittingsPerJetMCD, preslices.BplusSplittingsPerJetMCD, preslices.DielectronSplittingsPerJetMCD, preslices.D0PairsPerJetMCD, preslices.DplusPairsPerJetMCD, preslices.DstarPairsPerJetMCD, preslices.LcPairsPerJetMCD, preslices.B0PairsPerJetMCD, preslices.BplusPairsPerJetMCD, preslices.DielectronPairsPerJetMCD, splittingMatchesGeoVecVecMCD, splittingMatchesPtVecVecMCD, splittingMatchesHFVecVecMCD, pairMatchesVecVecMCD, configs.jetPtMinMCD); splittingMatchesGeoVecVecMCP.assign(jetsMCP.size(), {}); splittingMatchesPtVecVecMCP.assign(jetsMCP.size(), {}); splittingMatchesHFVecVecMCP.assign(jetsMCP.size(), {}); pairMatchesVecVecMCP.assign(jetsMCP.size(), {}); - analyseSubstructureMatched(jetsMCP, splittingsMCP, pairsMCP, D0SplittingsPerJetMCP, DplusSplittingsPerJetMCP, LcSplittingsPerJetMCP, BplusSplittingsPerJetMCP, DielectronSplittingsPerJetMCP, D0PairsPerJetMCP, DplusPairsPerJetMCP, LcPairsPerJetMCP, BplusPairsPerJetMCP, DielectronPairsPerJetMCP, splittingMatchesGeoVecVecMCP, splittingMatchesPtVecVecMCP, splittingMatchesHFVecVecMCP, pairMatchesVecVecMCP, configs.jetPtMinMCP); + analyseSubstructureMatched(jetsMCP, splittingsMCP, pairsMCP, preslices.D0SplittingsPerJetMCP, preslices.DplusSplittingsPerJetMCP, preslices.DstarSplittingsPerJetMCP, preslices.LcSplittingsPerJetMCP, preslices.B0SplittingsPerJetMCP, preslices.BplusSplittingsPerJetMCP, preslices.DielectronSplittingsPerJetMCP, preslices.D0PairsPerJetMCP, preslices.DplusPairsPerJetMCP, preslices.DstarPairsPerJetMCP, preslices.LcPairsPerJetMCP, preslices.B0PairsPerJetMCP, preslices.BplusPairsPerJetMCP, preslices.DielectronPairsPerJetMCP, splittingMatchesGeoVecVecMCP, splittingMatchesPtVecVecMCP, splittingMatchesHFVecVecMCP, pairMatchesVecVecMCP, configs.jetPtMinMCP); } PROCESS_SWITCH(JetSubstructureHFOutputTask, processOutputSubstructureMatchingMC, "jet substructure matching output MC", false); diff --git a/PWGJE/Tasks/jetSubstructureLc.cxx b/PWGJE/Tasks/jetSubstructureLc.cxx index 4f2350bb0a6..6f8260ab2c5 100644 --- a/PWGJE/Tasks/jetSubstructureLc.cxx +++ b/PWGJE/Tasks/jetSubstructureLc.cxx @@ -13,9 +13,20 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHF.cxx" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureLc = JetSubstructureHFTask, soa::Join, soa::Join, soa::Join, aod::CandidatesLcData, aod::CandidatesLcMCP, aod::LcCJetSSs, aod::LcChargedSPs, aod::LcChargedPRs, aod::LcCMCDJetSSs, aod::LcChargedMCDetectorLevelSPs, aod::LcChargedMCDetectorLevelPRs, aod::LcCMCPJetSSs, aod::LcChargedMCParticleLevelSPs, aod::LcChargedMCParticleLevelPRs, aod::LcCEWSJetSSs, aod::LcChargedEventWiseSubtractedSPs, aod::LcChargedEventWiseSubtractedPRs, aod::JTrackLcSubs>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureLcOutput.cxx b/PWGJE/Tasks/jetSubstructureLcOutput.cxx index 992dc6e2259..e25c204b580 100644 --- a/PWGJE/Tasks/jetSubstructureLcOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureLcOutput.cxx @@ -13,9 +13,22 @@ // /// \author Nima Zardoshti -#include #include "PWGJE/Tasks/jetSubstructureHFOutput.cxx" +#include "PWGHF/DataModel/DerivedTables.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedDataHF.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#include +#include +#include +#include +#include + +#include + using JetSubstructureOutputLc = JetSubstructureHFOutputTask, aod::McCollisionsLc, aod::CandidatesLcData, aod::CandidatesLcMCD, aod::CandidatesLcMCP, aod::BkgLcRhos, aod::BkgLcMcRhos, aod::JTrackLcSubs, soa::Join, soa::Join, soa::Join, soa::Join, aod::LcCJetCOs, aod::LcCJetOs, aod::LcCJetSSOs, aod::LcCJetMOs, soa::Join, soa::Join, soa::Join, aod::LcCMCDJetCOs, aod::LcCMCDJetOs, aod::LcCMCDJetSSOs, aod::LcCMCDJetMOs, soa::Join, soa::Join, soa::Join, soa::Join, aod::LcCMCPJetCOs, aod::LcCMCPJetMCCOs, aod::LcCMCPJetOs, aod::LcCMCPJetSSOs, aod::LcCMCPJetMOs, soa::Join, soa::Join, soa::Join, aod::LcCEWSJetCOs, aod::LcCEWSJetOs, aod::LcCEWSJetSSOs, aod::LcCEWSJetMOs, aod::StoredHfLcCollBase, aod::StoredHfLcBases, aod::StoredHfLcPars, aod::StoredHfLcParEs, aod::JDumLcParDaus, aod::StoredHfLcSels, aod::StoredHfLcMls, aod::JDumLcMlDaus, aod::StoredHfLcMcs, aod::StoredHfLcMcCollBases, aod::StoredHfLcMcRCollIds, aod::StoredHfLcPBases>; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/jetSubstructureOutput.cxx b/PWGJE/Tasks/jetSubstructureOutput.cxx index 9d2df7c032a..39f1e1518cd 100644 --- a/PWGJE/Tasks/jetSubstructureOutput.cxx +++ b/PWGJE/Tasks/jetSubstructureOutput.cxx @@ -14,35 +14,31 @@ /// \author Nima Zardoshti // -#include -#include -#include -#include +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetSubstructure.h" +#include "PWGJE/DataModel/JetSubtraction.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "TDatabasePDG.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include +#include +#include +#include -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetSubstructure.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; // NB: runDataProcessing.h must be included after customize! -#include "Framework/runDataProcessing.h" struct JetSubstructureOutputTask { @@ -224,7 +220,7 @@ struct JetSubstructureOutputTask { float centrality = -1.0; uint8_t eventSel = 0.0; if constexpr (!isMCP) { - centrality = collision.centrality(); + centrality = collision.centFT0M(); eventSel = collision.eventSel(); } collisionOutputTable(collision.posZ(), centrality, eventSel, eventWeight); diff --git a/PWGJE/Tasks/jetTaggerHFQA.cxx b/PWGJE/Tasks/jetTaggerHFQA.cxx index 7e2efeceaa3..52a36b2c6e5 100644 --- a/PWGJE/Tasks/jetTaggerHFQA.cxx +++ b/PWGJE/Tasks/jetTaggerHFQA.cxx @@ -14,28 +14,30 @@ /// /// \author Hanseo Park -#include -#include -#include -#include - -#include "TF1.h" +#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/JetTagging.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/runDataProcessing.h" -#include "Common/Core/trackUtilities.h" - -#include "PWGHF/DataModel/CandidateReconstructionTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetTagging.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetTaggingUtilities.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetTriggerChargedQa.cxx b/PWGJE/Tasks/jetTriggerChargedQa.cxx index 3cbb9e18070..f1cb9309cd1 100644 --- a/PWGJE/Tasks/jetTriggerChargedQa.cxx +++ b/PWGJE/Tasks/jetTriggerChargedQa.cxx @@ -14,33 +14,26 @@ /// \file jetTriggerChargedQa.cxx /// \brief QA of trigger performance for charged jets -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#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/runDataProcessing.h" - -#include "EventFiltering/filterTables.h" - -#include "CommonConstants/MathConstants.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/JetFindingUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/DataModel/Jet.h" - #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/jetTutorial.cxx b/PWGJE/Tasks/jetTutorial.cxx index cdc02e582f1..42f3153dc65 100644 --- a/PWGJE/Tasks/jetTutorial.cxx +++ b/PWGJE/Tasks/jetTutorial.cxx @@ -14,31 +14,34 @@ /// \author Nima Zardoshti // -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/Core/JetUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" + +#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 "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#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 JetTutorialTask { HistogramRegistry registry{"registry", {{"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}}, diff --git a/PWGJE/Tasks/jetTutorialSkeleton.cxx b/PWGJE/Tasks/jetTutorialSkeleton.cxx index df2098539e8..eeccd409d26 100644 --- a/PWGJE/Tasks/jetTutorialSkeleton.cxx +++ b/PWGJE/Tasks/jetTutorialSkeleton.cxx @@ -14,31 +14,24 @@ /// \author Nima Zardoshti // -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" - +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct JetTutorialSkeletonTask { HistogramRegistry registry{"registry", {{"h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}}, diff --git a/PWGJE/Tasks/jetValidationQA.cxx b/PWGJE/Tasks/jetValidationQA.cxx index 9facbcaf6e9..bf4c8348c10 100644 --- a/PWGJE/Tasks/jetValidationQA.cxx +++ b/PWGJE/Tasks/jetValidationQA.cxx @@ -12,18 +12,23 @@ /// \author Johanna Lömker // \since Dec 2022 -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.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 "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/mcGeneratorStudies.cxx b/PWGJE/Tasks/mcGeneratorStudies.cxx index 53d9ef15ef0..a1bfe3a5500 100644 --- a/PWGJE/Tasks/mcGeneratorStudies.cxx +++ b/PWGJE/Tasks/mcGeneratorStudies.cxx @@ -13,21 +13,29 @@ // /// \author Nicolas Strangmann , Goethe University Frankfurt / Oak Ridge National Laoratory -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" - #include "PWGJE/DataModel/EMCALMatchedCollisions.h" -#include "DetectorsBase/GeometryManager.h" -#include "EMCALBase/Geometry.h" - -#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/CCDB/EventSelectionParams.h" +#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 "TDatabasePDG.h" +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; @@ -52,6 +60,7 @@ struct MCGeneratorStudies { Configurable mRequireNoSameBunchPileup{"mRequireNoSameBunchPileup", true, "require no same bunch pileup in event cut"}; Configurable mRequireGoodZvtxFT0vsPV{"mRequireGoodZvtxFT0vsPV", true, "require good Zvtx between FT0 vs. PV in event cut"}; Configurable mRequireEMCReadoutInMB{"mRequireEMCReadoutInMB", true, "require the EMC to be read out in an MB collision (kTVXinEMC)"}; + Configurable mRequireEMCReadoutInL0{"mRequireEMCReadoutInL0", false, "require the EMC to be read out by L0 trigger"}; void init(InitContext const&) { @@ -151,7 +160,7 @@ struct MCGeneratorStudies { continue; else if (mSelectOnlyChargedParticles && TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode())->Charge()) continue; - if (fabs(mcParticle.y()) > mRapidityCut) + if (std::abs(mcParticle.y()) > mRapidityCut) continue; if (!mcParticle.isPhysicalPrimary() && !mcParticle.producedByGenerator()) continue; @@ -178,7 +187,7 @@ struct MCGeneratorStudies { continue; else if (mSelectOnlyChargedParticles && TDatabasePDG::Instance()->GetParticle(mcParticle.pdgCode())->Charge()) continue; - if (fabs(mcParticle.y()) > mRapidityCut) + if (std::abs(mcParticle.y()) > mRapidityCut) continue; if (!mcParticle.isPhysicalPrimary() && !mcParticle.producedByGenerator()) continue; @@ -190,7 +199,7 @@ struct MCGeneratorStudies { mHistManager.fill(HIST("Yield_Accepted"), mcParticle.pt()); if (!mRequireTVX || collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { mHistManager.fill(HIST("Yield_T"), mcParticle.pt()); - if (abs(collision.posZ()) < mVertexCut) { + if (std::abs(collision.posZ()) < mVertexCut) { mHistManager.fill(HIST("Yield_TZ"), mcParticle.pt()); if (!mRequireSel8 || collision.sel8()) { mHistManager.fill(HIST("Yield_TZS"), mcParticle.pt()); @@ -199,9 +208,11 @@ struct MCGeneratorStudies { if (!mRequireNoSameBunchPileup || collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { mHistManager.fill(HIST("Yield_TZSGU"), mcParticle.pt()); if (!mRequireEMCReadoutInMB || (mRequireEMCCellContent ? collision.isemcreadout() : collision.alias_bit(kTVXinEMC))) { - mHistManager.fill(HIST("Yield_TZSGUE"), mcParticle.pt()); - if (isAccepted(mcParticle, mcParticles)) - mHistManager.fill(HIST("Yield_TZSGUE_Accepted"), mcParticle.pt()); + if (!mRequireEMCReadoutInL0 || (collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7))) { + mHistManager.fill(HIST("Yield_TZSGUE"), mcParticle.pt()); + if (isAccepted(mcParticle, mcParticles)) + mHistManager.fill(HIST("Yield_TZSGUE_Accepted"), mcParticle.pt()); + } } } } @@ -263,7 +274,7 @@ struct MCGeneratorStudies { fRegistry->fill(HIST("hEMCollisionCounter"), 7.0); if (collision.sel8()) fRegistry->fill(HIST("hEMCollisionCounter"), 8.0); - if (abs(collision.posZ()) < 10.0) + if (std::abs(collision.posZ()) < 10.0) fRegistry->fill(HIST("hEMCollisionCounter"), 9.0); if (collision.alias_bit(kTVXinEMC)) fRegistry->fill(HIST("hEMCollisionCounter"), 10.0); @@ -276,7 +287,7 @@ struct MCGeneratorStudies { fRegistry->fill(HIST("hCollisionCounter"), 1); if (!mRequireTVX || collision.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { fRegistry->fill(HIST("hCollisionCounter"), 2); - if (abs(collision.posZ()) < mVertexCut) { + if (std::abs(collision.posZ()) < mVertexCut) { fRegistry->fill(HIST("hCollisionCounter"), 3); if (!mRequireSel8 || collision.sel8()) { fRegistry->fill(HIST("hCollisionCounter"), 4); @@ -284,8 +295,11 @@ struct MCGeneratorStudies { fRegistry->fill(HIST("hCollisionCounter"), 5); if (!mRequireNoSameBunchPileup || collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { fRegistry->fill(HIST("hCollisionCounter"), 6); - if (!mRequireEMCReadoutInMB || (mRequireEMCCellContent ? collision.isemcreadout() : collision.alias_bit(kTVXinEMC))) - fRegistry->fill(HIST("hCollisionCounter"), 7); + if (!mRequireEMCReadoutInMB || (mRequireEMCCellContent ? collision.isemcreadout() : collision.alias_bit(kTVXinEMC))) { + if (!mRequireEMCReadoutInL0 || (collision.alias_bit(kEMC7) || collision.alias_bit(kDMC7))) { + fRegistry->fill(HIST("hCollisionCounter"), 7); + } + } } } } diff --git a/PWGJE/Tasks/nsubjettiness.cxx b/PWGJE/Tasks/nsubjettiness.cxx index 1eabf7c6c50..133e1e6323b 100644 --- a/PWGJE/Tasks/nsubjettiness.cxx +++ b/PWGJE/Tasks/nsubjettiness.cxx @@ -15,23 +15,27 @@ /// \author Aimeric Landou /// \author Nima Zardoshti -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGJE/Core/JetFinder.h" +#include "PWGJE/Core/JetSubstructureUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + #include "Framework/ASoA.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/Logger.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include +#include + +#include +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/Core/JetSubstructureUtilities.h" #include "fastjet/contrib/AxesDefinition.hh" -#include "fastjet/contrib/MeasureDefinition.hh" +#include + +#include using namespace o2; using namespace o2::framework; @@ -177,7 +181,7 @@ struct NSubjettinessTask { } Filter jetCuts = aod::jet::r == nround(jetR.node() * 100.0f); - Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter collisionFilter = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); template void processJet(T const& jet, U const& tracks, float weight = 1.0) diff --git a/PWGJE/Tasks/nucleiInJets.cxx b/PWGJE/Tasks/nucleiInJets.cxx index 0d620b1986f..37fb0764947 100644 --- a/PWGJE/Tasks/nucleiInJets.cxx +++ b/PWGJE/Tasks/nucleiInJets.cxx @@ -11,46 +11,55 @@ // author: Arvind Khuntia (arvind.khuntia@cern.ch) INFN Bologna, Italy -#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 "Framework/runDataProcessing.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" -#include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/LFParticleIdentification.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 "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/JetReducedDataSelector.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::constants::physics; struct nucleiInJets { enum Particle { @@ -80,19 +89,19 @@ struct nucleiInJets { case -2212: // antip return -Particle::kProton; - case 1000010020: // Deuteron + case Pdg::kDeuteron: // Deuteron return Particle::kDeuteron; - case -1000010020: // AntiDeuteron + case -Pdg::kDeuteron: // AntiDeuteron return -Particle::kDeuteron; - case 1000010030: // Triton + case Pdg::kTriton: // Triton return Particle::kTriton; - case -1000010030: // AntiTriton + case -Pdg::kTriton: // AntiTriton return -Particle::kTriton; - case 1000020030: // Helium + case Pdg::kHelium3: // Helium return Particle::kHelium; - case -1000020030: // AntiHelium + case -Pdg::kHelium3: // AntiHelium return -Particle::kHelium; default: return 0; // Default case for unknown or unmapped PDG codes @@ -104,6 +113,7 @@ struct nucleiInJets { Configurable isWithJetEvents{"isWithJetEvents", true, "Events with at least one jet"}; Configurable isWithLeadingJet{"isWithLeadingJet", true, "Events with leading jet"}; Configurable useLfTpcPid{"useLfTpcPid", true, "Events with custom TPC parameters"}; + Configurable centralityType{"centralityType", 0, "0: FT0M, 1: FT0C, 2: FV0A"}; Configurable cfgtrkMinPt{"cfgtrkMinPt", 0.15, "set track min pT"}; Configurable cfgtrkMaxEta{"cfgtrkMaxEta", 0.8, "set track max Eta"}; @@ -142,6 +152,7 @@ struct nucleiInJets { Configurable useLeadingJetDetLevelValue{"useLeadingJetDetLevelValue", false, "true: use det level value for leading jet, false: use part level value"}; Configurable useDcaxyPtDepCut{"useDcaxyPtDepCut", true, "true: use pt dependent DCAxy cut, false: use constant DCAxy cut"}; Configurable useTOFNsigmaPreSel{"useTOFNsigmaPreSel", true, "true: use TOF nsgma preselection, false: no TOF nsgma preselection"}; + Configurable useTOFVeto{"useTOFVeto", false, "true: use TOF veto, false: no TOF veto"}; Configurable isRequireHitsInITSLayers{"isRequireHitsInITSLayers", true, "true: at least one hit in the its inner layes"}; Configurable useMcC{"useMcC", true, "use mcC"}; @@ -160,16 +171,9 @@ struct nucleiInJets { Configurable applySkim{"applySkim", false, "Apply skimming"}; Configurable cfgSkim{"cfgSkim", "fHighFt0Mult", "Configurable for skimming"}; - static constexpr float gMassProton = 0.93827208f; - static constexpr float gMassDeuteron = 1.87561f; - static constexpr float gMassTriton = 2.80892f; - static constexpr float gMassHelium = 2.80839f; - static constexpr int PDGProton = 2212; - static constexpr int PDGDeuteron = 1000010020; - static constexpr int PDGTriton = 1000010030; - static constexpr int PDGHelium = 1000020030; - - using EventCandidates = soa::Join; // , aod::CentFT0Ms, aod::CentFT0As, aod::CentFT0Cs + // using EventTable = soa::Join; + using EventTable = aod::JetCollisions; + using EventTableMC = soa::Join; using TrackCandidates = soa::Join; @@ -181,6 +185,11 @@ struct nucleiInJets { aod::pidTOFFullKa, aod::pidTOFFullPr, aod::pidTOFFullDe, aod::pidTOFFullTr, aod::pidTOFFullHe, aod::TOFSignal /*, aod::McTrackLabels*/>; + using TrackCandidatesIncMC = soa::Join; + Filter jetCuts = aod::jet::pt > cfgjetPtMin&& aod::jet::r == nround(cfgjetR.node() * 100.0f); using chargedJetstrack = soa::Filtered>; @@ -194,7 +203,6 @@ struct nucleiInJets { OutputObj zorroSummary{"zorroSummary"}; Service ccdb; TRandom3 randUniform; - void init(o2::framework::InitContext&) { @@ -205,9 +213,11 @@ struct nucleiInJets { const AxisSpec PtJetAxis = {100, 0, 100.0}; const AxisSpec MultAxis = {100, 0, 100}; const AxisSpec dRAxis = {100, 0, 3.6}; + const AxisSpec CentAxis = {100, 0, 100}; const AxisSpec dcaxyAxis{binsDCA, "DCAxy (cm)"}; const AxisSpec dcazAxis{binsDCA, "DCAz (cm)"}; const AxisSpec dedxAxis{binsdEdx, "d#it{E}/d#it{x} A.U."}; + const AxisSpec vzAxis{300, -15.f, 15.f, "Vz (cm)"}; const AxisSpec betaAxis{binsBeta, "TOF #beta"}; const AxisSpec ptZHeAxis{binsPtZHe, "#it{p}_{T}"}; @@ -217,14 +227,25 @@ struct nucleiInJets { const AxisSpec massTrAxis{binsMassTr, ""}; const AxisSpec massHeAxis{binsMassHe, ""}; - if (applySkim) { - jetHist.add("hNEvents", "hNEvents", {HistType::kTH1D, {{6, 0.f, 6.f}}}); - jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "All"); - jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "Skimmed"); - jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "|Vz|<10"); - jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "Sel8+|Vz|<10"); - jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "nJets>0"); - } + jetHist.add("hNEvents", "hNEvents", {HistType::kTH1D, {{6, 0.f, 6.f}}}); + jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "All"); + jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "Skimmed"); + jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "|Vz|<10"); + jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "Sel8+|Vz|<10"); + jetHist.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "nJets>0"); + + jetHist.add("hNEventsInc", "hNEventsInc", {HistType::kTH1D, {{4, 0.f, 4.f}}}); + jetHist.get(HIST("hNEventsInc"))->GetXaxis()->SetBinLabel(1, "All"); + jetHist.get(HIST("hNEventsInc"))->GetXaxis()->SetBinLabel(2, "Sel8"); + jetHist.get(HIST("hNEventsInc"))->GetXaxis()->SetBinLabel(3, "|Vz|<10"); + + jetHist.add("hNEventsIncVsCent", "hNEventsIncVsCent", {HistType::kTH2D, {{vzAxis}, {CentAxis}}}); + + // TPC nSigma vs pT (inclusive) + jetHist.add("tracksInc/proton/h3PtVsProtonNSigmaTPCVsPt", "pT(p) vs NSigmaTPC (p) vs centrality; #it{p}_{T} (GeV/#it{c}); NSigmaTPC; centrality", HistType::kTH3F, {PtAxis, {200, -10, 10}, CentAxis}); + jetHist.add("tracksInc/antiProton/h3PtVsantiProtonNSigmaTPCVsPt", "pT(#bar{p}) vs NSigmaTPC (#bar{p}) vs centrality; #it{p}_{T} (GeV/#it{c}); NSigmaTPC; centrality", HistType::kTH3F, {PtAxis, {200, -10, 10}, CentAxis}); + jetHist.add("tracksInc/deuteron/h3PtVsDeuteronNSigmaTPCVsPt", "pT(d) vs NSigmaTPC (d) vs centrality; #it{p}_{T} (GeV/#it{c}); NSigmaTPC; centrality", HistType::kTH3F, {PtAxis, {200, -10, 10}, CentAxis}); + jetHist.add("tracksInc/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPt", "pT(#bar{d}) vs NSigmaTPC (#bar{d}) vs centrality; #it{p}_{T} (GeV/#it{c}); NSigmaTPC; centrality", HistType::kTH3F, {PtAxis, {200, -10, 10}, CentAxis}); // jet property jetHist.add("jet/h1JetPt", "jet_{p_{T}}", kTH1F, {PtJetAxis}); @@ -234,9 +255,9 @@ struct nucleiInJets { jetHist.add("jet/nJetsPerEvent", "nJetsPerEvent", kTH1F, {{15, .0, 15.}}); jetHist.add("mcpJet/nJetsPerEvent", "nJetsPerEvent", kTH1F, {{15, .0, 15.}}); jetHist.add("mcdJet/nJetsPerEvent", "nJetsPerEvent", kTH1F, {{15, .0, 15.}}); - jetHist.add("jet/vertexZ", "vertexZ (Jet flag)", kTH1F, {{100, -15.0, 15.0}}); - jetHist.add("vertexZ", "vertexZ (all)", kTH1F, {{100, -15.0, 15.0}}); - jetHist.add("jetOut/vertexZ", "vertexZ (without z-flag)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("jet/vertexZ", "vertexZ (Jet flag)", kTH1F, {{vzAxis}}); + jetHist.add("vertexZ", "vertexZ (all)", kTH1F, {{vzAxis}}); + jetHist.add("jetOut/vertexZ", "vertexZ (without z-flag)", kTH1F, {{vzAxis}}); //////////////////////////// // MC //////////////////////////// @@ -247,8 +268,8 @@ struct nucleiInJets { h->GetXaxis()->SetBinLabel(3, "vz < 10"); h->GetXaxis()->SetBinLabel(4, "ingt0"); - jetHist.add("mcpJet/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); - jetHist.add("mcdJet/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("mcpJet/vertexZ", "vertexZ (All)", kTH1F, {{vzAxis}}); + jetHist.add("mcdJet/vertexZ", "vertexZ (All)", kTH1F, {{vzAxis}}); jetHist.add("mcdJet/eventStat", "vertexZ (All)", kTH1F, {{5, .0, 5.0}}); auto h1 = jetHist.get(HIST("mcdJet/eventStat")); h1->GetXaxis()->SetBinLabel(1, "All"); @@ -256,8 +277,8 @@ struct nucleiInJets { h1->GetXaxis()->SetBinLabel(3, "vz< 10"); h1->GetXaxis()->SetBinLabel(4, "ingt0"); - jetHist.add("recmatched/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); - jetHist.add("genmatched/vertexZ", "vertexZ (All)", kTH1F, {{100, -15.0, 15.0}}); + jetHist.add("recmatched/vertexZ", "vertexZ (All)", kTH1F, {{vzAxis}}); + jetHist.add("genmatched/vertexZ", "vertexZ (All)", kTH1F, {{vzAxis}}); ////////////////////////////////////////////// // inside jet @@ -389,14 +410,18 @@ struct nucleiInJets { if (cEnableProtonQA) { jetHist.add("tracks/proton/dca/after/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracksInc/proton/dca/after/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH3F, {{dcaxyAxis}, {PtAxis}, {CentAxis}}); jetHist.add("tracks/antiProton/dca/after/hDCAxyVsPtantiProton", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); jetHist.add("tracks/proton/dca/after/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracksInc/proton/dca/after/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH3F, {{dcazAxis}, {PtAxis}, {CentAxis}}); jetHist.add("tracks/antiProton/dca/after/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); } if (cEnableDeuteronQA) { jetHist.add("tracks/deuteron/dca/after/hDCAxyVsPtDeuteron", "DCAxy vs Pt (d)", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); + jetHist.add("tracksInc/deuteron/dca/after/hDCAxyVsPtDeuteron", "DCAxy vs Pt (d)", HistType::kTH3F, {{dcaxyAxis}, {PtAxis}, {CentAxis}}); jetHist.add("tracks/antiDeuteron/dca/after/hDCAxyVsPtantiDeuteron", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{dcaxyAxis}, {PtAxis}}); jetHist.add("tracks/deuteron/dca/after/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); + jetHist.add("tracksInc/deuteron/dca/after/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH3F, {{dcazAxis}, {PtAxis}, {CentAxis}}); jetHist.add("tracks/antiDeuteron/dca/after/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{dcazAxis}, {PtAxis}}); } if (cEnableTritonQA) { @@ -433,6 +458,21 @@ struct nucleiInJets { jetHist.add("tracks/helium/h2TOFmass2HeliumVsPt", "#Delta M^{2} (t) vs #it{p}_{T}t; TOFmass2; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); jetHist.add("tracks/antiHelium/h2TOFmass2antiHeliumVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{massHeAxis}, {ptZHeAxis}}); + jetHist.add("tracksInc/proton/h2TOFmassProtonVsPt", "h2TOFmassProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH3F, {{80, 0.4, 4.}, {50, 0., 5.}, {CentAxis}}); + jetHist.add("tracksInc/antiProton/h2TOFmassantiProtonVsPt", "h2TOFmassantiProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH3F, {{80, 0.4, 4.}, {50, 0., 5.}, {CentAxis}}); + jetHist.add("tracksInc/deuteron/h2TOFmassDeuteronVsPt", "h2TOFmassDeuteronVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH3F, {{80, 0.4, 4.}, {50, 0., 5.}, {CentAxis}}); + jetHist.add("tracksInc/antiDeuteron/h2TOFmassantiDeuteronVsPt", "h2TOFmassantiDeuteronVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH3F, {{80, 0.4, 4.}, {50, 0., 5.}, {CentAxis}}); + + jetHist.add("tracksInc/proton/h2TOFmass2ProtonVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH3F, {{massPrAxis}, {250, 0., 5.}, {CentAxis}}); + jetHist.add("tracksInc/antiProton/h2TOFmass2antiProtonVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH3F, {{massPrAxis}, {250, 0., 5.}, {CentAxis}}); + jetHist.add("tracksInc/deuteron/h2TOFmass2DeuteronVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH3F, {{massDeAxis}, {250, 0., 5.}, {CentAxis}}); + jetHist.add("tracksInc/antiDeuteron/h2TOFmass2antiDeuteronVsPt", "#Delta M^{2} (t) vs #it{p}_{T}; TOFmass2; #it{p}_{T} (GeV)", HistType::kTH3F, {{massDeAxis}, {250, 0., 5.}, {CentAxis}}); + + jetHist.add("tracksInc/proton/h2TofNsigmaProtonVsPt", "h2TofNsigmaProtonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH3F, {{100, -5, 5}, {100, 0., 10.}, {CentAxis}}); + jetHist.add("tracksInc/antiProton/h2TofNsigmaantiProtonVsPt", "h2TofNsigmaantiProtonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH3F, {{100, -5, 5}, {100, 0., 10.}, {CentAxis}}); + jetHist.add("tracksInc/deuteron/h2TofNsigmaDeuteronVsPt", "h2TofNsigmaDeuteronVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH3F, {{100, -5, 5}, {100, 0., 10.}, {CentAxis}}); + jetHist.add("tracksInc/antiDeuteron/h2TofNsigmaantiDeuteronVsPt", "h2TofNsigmaantiDeuteronVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH3F, {{100, -5, 5}, {100, 0., 10.}, {CentAxis}}); + // TOF hist nSigma jetHist.add("tracks/proton/h2TofNsigmaProtonVsPt", "h2TofNsigmaProtonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); jetHist.add("tracks/antiProton/h2TofNsigmaantiProtonVsPt", "h2TofNsigmaantiProtonVsPt; TofNsigma; #it{p}_{T} (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); @@ -444,6 +484,17 @@ struct nucleiInJets { jetHist.add("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt", "h2TofNsigmaantiHeliumVsPt; TofNsigma; #it{p}_{T}/z (GeV)", HistType::kTH2F, {{100, -5, 5}, {50, 0., 5.}}); if (isMC) { + // inc + jetHist.add("recInc/eventStat", "Event statistics (inclusive)", HistType::kTH1F, {{6, 0.f, 6.f}}); + jetHist.get(HIST("recInc/eventStat"))->GetXaxis()->SetBinLabel(1, "All"); + jetHist.get(HIST("recInc/eventStat"))->GetXaxis()->SetBinLabel(2, "Sel8"); + jetHist.get(HIST("recInc/eventStat"))->GetXaxis()->SetBinLabel(3, "|Vz|<10"); + + jetHist.add("recInc/vertexZ", "vertexZ (inclusive)", HistType::kTH2F, {{vzAxis}, {CentAxis}}); + jetHist.add("recInc/pt/PtParticleTypeTPC", "Pt vs ParticleType vs Centrality (TPC)", HistType::kTH3F, {{100, 0.f, 10.f}, {14, -7, 7}, {100, 0, 100}}); + jetHist.add("recInc/pt/PtParticleTypeTPCTOF", "Pt vs ParticleType vs Centrality (TPC+TOF)", HistType::kTH3F, {{100, 0.f, 10.f}, {14, -7, 7}, {100, 0, 100}}); + jetHist.add("recInc/pt/PtParticleTypeTPCTOFVeto", "Pt vs ParticleType vs Centrality (TPC+TOF Veto)", HistType::kTH3F, {{100, 0.f, 10.f}, {14, -7, 7}, {100, 0, 100}}); + jetHist.add("genInc/pt/PtParticleType", "Pt vs ParticleType vs Centrality (gen)", HistType::kTH3F, {{100, 0.f, 10.f}, {14, -7, 7}, {100, 0, 100}}); // inside jet jetHist.add("tracks/mc/proton/h3PtVsProtonNSigmaTPCVsPtJet_jet", "pT(p) vs NSigmaTPC (p) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); jetHist.add("tracks/mc/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet_jet", "pT(#bar{p}) vs NSigmaTPC (#bar{p}) vs jet pT; #it{p}_{T} (GeV/#it{c}; NSigmaTPC; p^{jet}_{T}", HistType::kTH3F, {{PtAxis}, {200, -10, 10}, {PtJetAxis}}); @@ -546,13 +597,15 @@ struct nucleiInJets { jetHist.add("eff/recmatched/pt/PtParticleTypeTPC", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); jetHist.add("eff/recmatched/pt/PtParticleTypeTOF", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); jetHist.add("eff/recmatched/pt/PtParticleTypeTPCTOF", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); + jetHist.add("eff/recmatched/pt/PtParticleTypeTPCTOFVeto", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); + jetHist.add("eff/recmatched/perpCone/pt/PtParticleType", "Pt (p) vs particletype", HistType::kTH2D, {{100, 0.f, 10.f}, {14, -7, 7}}); jetHist.add("eff/recmatched/perpCone/mcC/pt/PtParticleType", "Pt (rec) vs Pt (true) vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {100, 0.f, 10.f}, {14, -7, 7}}); jetHist.add("eff/recmatched/perpCone/mcCSpectra/pt/PtParticleType", "Pt (rec) vs Pt (true) vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {100, 0.f, 10.f}, {14, -7, 7}}); jetHist.add("eff/recmatched/perpCone/pt/PtParticleTypeTPC", "Pt (p) vs particletype", HistType::kTH2D, {{100, 0.f, 10.f}, {14, -7, 7}}); jetHist.add("eff/recmatched/perpCone/pt/PtParticleTypeTOF", "Pt (p) vs particletype", HistType::kTH2D, {{100, 0.f, 10.f}, {14, -7, 7}}); jetHist.add("eff/recmatched/perpCone/pt/PtParticleTypeTPCTOF", "Pt (p) vs particletype", HistType::kTH2D, {{100, 0.f, 10.f}, {14, -7, 7}}); - + jetHist.add("eff/recmatched/perpCone/pt/PtParticleTypeTPCTOFVeto", "Pt (p) vs particletype", HistType::kTH2D, {{100, 0.f, 10.f}, {14, -7, 7}}); jetHist.add("eff/recmatched/gen/pt/PtParticleType", "Pt (p) vs jetflag vs particletype", HistType::kTH3D, {{100, 0.f, 10.f}, {2, 0, 2}, {14, -7, 7}}); jetHist.add("eff/recmatched/gen/perpCone/pt/PtParticleType", "Pt (p) vs particletype", HistType::kTH2D, {{100, 0.f, 10.f}, {14, -7, 7}}); // gen matched @@ -585,8 +638,8 @@ struct nucleiInJets { { std::array PerpendicularConeAxisPhi = {-999.0f, -999.0f}; // build 2 perp cones in phi around the leading jet (right and left of the jet) - PerpendicularConeAxisPhi[0] = RecoDecay::constrainAngle(jetPhi + (M_PI / 2.)); // This will contrain the angel between 0-2Pi - PerpendicularConeAxisPhi[1] = RecoDecay::constrainAngle(jetPhi - (M_PI / 2.)); // This will contrain the angel between 0-2Pi + PerpendicularConeAxisPhi[0] = RecoDecay::constrainAngle(jetPhi + (o2::constants::math::PIHalf)); // This will contrain the angel between 0-2Pi + PerpendicularConeAxisPhi[1] = RecoDecay::constrainAngle(jetPhi - (o2::constants::math::PIHalf)); // This will contrain the angel between 0-2Pi return PerpendicularConeAxisPhi; } @@ -653,7 +706,7 @@ struct nucleiInJets { if (isWithLeadingJet) { double delPhi = TVector2::Phi_mpi_pi(leadingJetPtEtaPhi[2] - trk.phi()); double delEta = leadingJetPtEtaPhi[1] - trk.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sumOfSquares(delEta, delPhi); if (R < cfgjetR) jetFlag = true; jetPt = leadingJetPtEtaPhi[0]; @@ -661,15 +714,15 @@ struct nucleiInJets { std::array perpConePhiJet = getPerpendicuarPhi(leadingJetPtEtaPhi[2]); double delPhiPerpCone1 = TVector2::Phi_mpi_pi(perpConePhiJet[0] - trk.phi()); double delPhiPerpCone2 = TVector2::Phi_mpi_pi(perpConePhiJet[1] - trk.phi()); - double RPerpCone1 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone1 * delPhiPerpCone1)); - double RPerpCone2 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone2 * delPhiPerpCone2)); + double RPerpCone1 = RecoDecay::sumOfSquares(delEta, delPhiPerpCone1); + double RPerpCone2 = RecoDecay::sumOfSquares(delEta, delPhiPerpCone2); if (RPerpCone1 < cfgjetR || RPerpCone2 < cfgjetR) jetFlagPerpCone = true; } else { for (auto const& jet : jets) { double delPhi = TVector2::Phi_mpi_pi(jet.phi() - trk.phi()); double delEta = jet.eta() - trk.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sumOfSquares(delEta, delPhi); if (R < cfgjetR) jetFlag = true; jetPt = jet.pt(); @@ -679,7 +732,7 @@ struct nucleiInJets { // tof float massTOF = -999; if (trk.hasTOF()) { - massTOF = trk.p() * TMath::Sqrt(1.f / (trk.beta() * trk.beta()) - 1.f); + massTOF = trk.p() * std::sqrt(1.f / (trk.beta() * trk.beta()) - 1.f); } if (addTOFplots && trk.hasTOF()) { @@ -705,12 +758,42 @@ struct nucleiInJets { jetHist.fill(HIST("tracks/helium/h3PtVsHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) jetHist.fill(HIST("tracks/triton/h3PtVsTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); - } else if (!useTOFNsigmaPreSel) { + } else if (!useTOFNsigmaPreSel && !useTOFVeto) { jetHist.fill(HIST("tracks/proton/h3PtVsProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); jetHist.fill(HIST("tracks/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); jetHist.fill(HIST("tracks/helium/h3PtVsHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); jetHist.fill(HIST("tracks/triton/h3PtVsTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + } else if (!useTOFNsigmaPreSel && useTOFVeto) { + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) { + jetHist.fill(HIST("tracks/proton/h3PtVsProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/proton/h3PtVsProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) { + jetHist.fill(HIST("tracks/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaHe()) < cfgnTPCPIDHeTOF) { + jetHist.fill(HIST("tracks/helium/h3PtVsHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/helium/h3PtVsHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) { + jetHist.fill(HIST("tracks/triton/h3PtVsTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/triton/h3PtVsTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + } } + if (cEnableProtonQA && std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { jetHist.fill(HIST("tracks/proton/dca/after/hDCAxyVsPtProton_jet"), trk.dcaXY(), trk.pt()); jetHist.fill(HIST("tracks/proton/dca/after/hDCAzVsPtProton_jet"), trk.dcaZ(), trk.pt()); @@ -731,13 +814,13 @@ struct nucleiInJets { if (addTOFplots && trk.hasTOF()) { if (!useTPCpreSel) { jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_jet"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_jet"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_jet"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_jet"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); @@ -747,24 +830,24 @@ struct nucleiInJets { } else { if (std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_jet"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); jetHist.fill(HIST("tracks/proton/h3TpcNsigmaTofNsigmaProtonVsPt_jet"), trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.pt()); } if (std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_jet"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); jetHist.fill(HIST("tracks/deuteron/h3TpcNsigmaTofNsigmaDeuteronVsPt_jet"), trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.pt()); } if (std::abs(trk.tpcNSigmaTr()) < cfgnTPCPIDTr) { jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_jet"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/triton/h2TofNsigmaTritonVsPt_jet"), trk.tofNSigmaTr(), trk.pt()); } if (std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_jet"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); } } @@ -791,11 +874,40 @@ struct nucleiInJets { jetHist.fill(HIST("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) jetHist.fill(HIST("tracks/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); - } else if (!useTOFNsigmaPreSel) { + } else if (!useTOFNsigmaPreSel && !useTOFVeto) { jetHist.fill(HIST("tracks/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); jetHist.fill(HIST("tracks/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); jetHist.fill(HIST("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); jetHist.fill(HIST("tracks/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + } else if (!useTOFNsigmaPreSel && useTOFVeto) { + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) { + jetHist.fill(HIST("tracks/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) { + jetHist.fill(HIST("tracks/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaHe()) < cfgnTPCPIDHeTOF) { + jetHist.fill(HIST("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) { + jetHist.fill(HIST("tracks/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + } + } else { + jetHist.fill(HIST("tracks/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet_jet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); + } } if (cEnableProtonQA && std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { @@ -818,43 +930,41 @@ struct nucleiInJets { if (addTOFplots && trk.hasTOF()) { if (!useTPCpreSel) { jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt_jet"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); jetHist.fill(HIST("tracks/antiProton/h3TpcNsigmaTofNsigmaantiProtonVsPt_jet"), trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.pt()); - jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt_jet"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); jetHist.fill(HIST("tracks/antiDeuteron/h3TpcNsigmaTofNsigmaantiDeuteronVsPt_jet"), trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.pt()); jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt_jet"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt_jet"), trk.tofNSigmaTr(), trk.pt()); - jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt_jet"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); } else { if (std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt_jet"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt_jet"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt_jet"), trk.tofNSigmaPr(), trk.pt()); jetHist.fill(HIST("tracks/antiProton/h3TpcNsigmaTofNsigmaantiProtonVsPt_jet"), trk.tpcNSigmaPr(), trk.tofNSigmaPr(), trk.pt()); } if (std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt_jet"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt_jet"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt_jet"), trk.tofNSigmaDe(), trk.pt()); jetHist.fill(HIST("tracks/antiDeuteron/h3TpcNsigmaTofNsigmaantiDeuteronVsPt_jet"), trk.tpcNSigmaDe(), trk.tofNSigmaDe(), trk.pt()); } if (std::abs(trk.tpcNSigmaTr()) < cfgnTPCPIDTr) { jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt_jet"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt_jet"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt_jet"), trk.tofNSigmaTr(), trk.pt()); } if (std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt_jet"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt_jet"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt_jet"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt_jet"), trk.tofNSigmaHe(), trk.pt()); } } @@ -900,11 +1010,40 @@ struct nucleiInJets { jetHist.fill(HIST("tracks/perpCone/helium/h3PtVsHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) jetHist.fill(HIST("tracks/perpCone/triton/h3PtVsTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr - } else if (!useTOFNsigmaPreSel) { + } else if (!useTOFNsigmaPreSel && !useTOFVeto) { jetHist.fill(HIST("tracks/perpCone/proton/h3PtVsProtonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); // Pr jetHist.fill(HIST("tracks/perpCone/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); // De jetHist.fill(HIST("tracks/perpCone/helium/h3PtVsHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He jetHist.fill(HIST("tracks/perpCone/triton/h3PtVsTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr + } else if (!useTOFNsigmaPreSel && useTOFVeto) { + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) { + jetHist.fill(HIST("tracks/perpCone/proton/h3PtVsProtonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); // Pr + } + } else { + jetHist.fill(HIST("tracks/perpCone/proton/h3PtVsProtonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); // Pr + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) { + jetHist.fill(HIST("tracks/perpCone/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); // De + } + } else { + jetHist.fill(HIST("tracks/perpCone/deuteron/h3PtVsDeuteronNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); // De + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaHe()) < cfgnTPCPIDHeTOF) { + jetHist.fill(HIST("tracks/perpCone/helium/h3PtVsHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He + } + } else { + jetHist.fill(HIST("tracks/perpCone/helium/h3PtVsHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) { + jetHist.fill(HIST("tracks/perpCone/triton/h3PtVsTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr + } + } else { + jetHist.fill(HIST("tracks/perpCone/triton/h3PtVsTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr + } } } @@ -927,45 +1066,45 @@ struct nucleiInJets { if (addTOFplots && trk.hasTOF()) { if (!useTPCpreSel) { jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/triton/h2TofNsigmaTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); } else { if (std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { jetHist.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/proton/h2TofNsigmaProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/proton/h2TofNsigmaProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); } if (std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { jetHist.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/deuteron/h2TofNsigmaDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/deuteron/h2TofNsigmaDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); } if (std::abs(trk.tpcNSigmaTr()) < cfgnTPCPIDTr) { jetHist.fill(HIST("tracks/triton/h2TOFmassTritonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/triton/h2TofNsigmaTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/triton/h2TofNsigmaTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); } if (std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { jetHist.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/helium/h2TofNsigmaHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/helium/h2TofNsigmaHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); @@ -989,11 +1128,40 @@ struct nucleiInJets { jetHist.fill(HIST("tracks/perpCone/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) jetHist.fill(HIST("tracks/perpCone/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr - } else if (!useTOFNsigmaPreSel) { + } else if (!useTOFNsigmaPreSel && !useTOFVeto) { jetHist.fill(HIST("tracks/perpCone/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); // Pr jetHist.fill(HIST("tracks/perpCone/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); // De jetHist.fill(HIST("tracks/perpCone/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He jetHist.fill(HIST("tracks/perpCone/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr + } else if (!useTOFNsigmaPreSel && useTOFVeto) { + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) { + jetHist.fill(HIST("tracks/perpCone/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); // Pr + } + } else { + jetHist.fill(HIST("tracks/perpCone/antiProton/h3PtVsantiProtonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaPr(), jetPt); // Pr + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) { + jetHist.fill(HIST("tracks/perpCone/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); // De + } + } else { + jetHist.fill(HIST("tracks/perpCone/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaDe(), jetPt); // De + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaHe()) < cfgnTPCPIDHeTOF) { + jetHist.fill(HIST("tracks/perpCone/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He + } + } else { + jetHist.fill(HIST("tracks/perpCone/antiHelium/h3PtVsantiHeliumNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaHe(), jetPt); // He + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaTr()) < cfgnTPCPIDTrTOF) { + jetHist.fill(HIST("tracks/perpCone/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr + } + } else { + jetHist.fill(HIST("tracks/perpCone/antiTriton/h3PtVsantiTritonNSigmaTPCVsPtJet"), trk.pt(), trk.tpcNSigmaTr(), jetPt); // Tr + } } } @@ -1016,45 +1184,45 @@ struct nucleiInJets { if (addTOFplots && trk.hasTOF()) { if (!useTPCpreSel) { jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); } else { if (std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { jetHist.fill(HIST("tracks/antiProton/h2TOFmassantiProtonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - gMassProton * gMassProton, trk.pt()); + jetHist.fill(HIST("tracks/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt()); jetHist.fill(HIST("tracks/antiProton/h2TofNsigmaantiProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/antiProton/h2TofNsigmaantiProtonVsPt"), trk.tofNSigmaPr(), trk.pt()); } if (std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmassantiDeuteronVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - gMassDeuteron * gMassDeuteron, trk.pt()); + jetHist.fill(HIST("tracks/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt()); jetHist.fill(HIST("tracks/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt()); } if (std::abs(trk.tpcNSigmaTr()) < cfgnTPCPIDTr) { jetHist.fill(HIST("tracks/antiTriton/h2TOFmassantiTritonVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - gMassTriton * gMassTriton, trk.pt()); + jetHist.fill(HIST("tracks/antiTriton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - MassTriton * MassTriton, trk.pt()); jetHist.fill(HIST("tracks/antiTriton/h2TofNsigmaantiTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/antiTriton/h2TofNsigmaantiTritonVsPt"), trk.tofNSigmaTr(), trk.pt()); } if (std::abs(trk.tpcNSigmaHe()) < cfgnTPCPIDHe) { jetHist.fill(HIST("tracks/antiHelium/h2TOFmassantiHeliumVsPt"), massTOF, trk.pt()); - jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt"), massTOF * massTOF - gMassHelium * gMassHelium, trk.pt()); + jetHist.fill(HIST("tracks/antiHelium/h2TOFmass2antiHeliumVsPt"), massTOF * massTOF - MassHelium3 * MassHelium3, trk.pt()); jetHist.fill(HIST("tracks/antiHelium/h2TofNsigmaantiHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); if (jetFlagPerpCone && isWithLeadingJet) jetHist.fill(HIST("tracks/perpCone/antiHelium/h2TofNsigmaantiHeliumVsPt"), trk.tofNSigmaHe(), trk.pt()); @@ -1112,7 +1280,7 @@ struct nucleiInJets { if (isWithJetEvents && nJets == 0) return; jetHist.fill(HIST("jet/h1JetEvents"), 0.5); - for (auto& track : tracks) { + for (const auto& track : tracks) { auto trk = track.track_as(); fillTrackInfo(trk, chargedjets, leadingJetWithPtEtaPhi); } @@ -1134,6 +1302,7 @@ struct nucleiInJets { if (std::abs(collision.posZ()) > 10) return; jetHist.fill(HIST("hNEvents"), 2.5); + if (!jetderiveddatautilities::selectCollision(collision, jetderiveddatautilities::initialiseEventSelectionBits("sel8"))) return; jetHist.fill(HIST("hNEvents"), 3.5); @@ -1168,6 +1337,156 @@ struct nucleiInJets { } } + void processDataInc(EventTable::iterator const& coll, soa::Join const& tracks, TrackCandidates const&) + { + jetHist.fill(HIST("hNEventsInc"), 0.5); + + if (!jetderiveddatautilities::selectCollision(coll, jetderiveddatautilities::initialiseEventSelectionBits("sel8"))) + return; + + jetHist.fill(HIST("hNEventsInc"), 1.5); + if (std::abs(coll.posZ()) > 10) // bad vertex + return; + jetHist.fill(HIST("hNEventsInc"), 2.5); + float centrality = -999; + switch (centralityType) { + case 0: // FT0M + centrality = coll.centFT0M(); + break; + case 1: // FT0C + centrality = coll.centFT0C(); + break; + case 2: // V0A + centrality = coll.centFV0A(); + break; + default: + centrality = -999; + } + jetHist.fill(HIST("hNEventsIncVsCent"), coll.posZ(), centrality); + for (const auto& track : tracks) { + auto trk = track.track_as(); + if (!isTrackSelected(trk)) { + continue; + } + if (std::fabs(trk.eta()) > cfgtrkMaxEta) + continue; + if (trk.sign() > 0) { // particle info + if (useTOFNsigmaPreSel && trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) + jetHist.fill(HIST("tracksInc/proton/h3PtVsProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) + jetHist.fill(HIST("tracksInc/deuteron/h3PtVsDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + } else if (!useTOFNsigmaPreSel && !useTOFVeto) { + jetHist.fill(HIST("tracksInc/proton/h3PtVsProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + jetHist.fill(HIST("tracksInc/deuteron/h3PtVsDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + + } else if (!useTOFNsigmaPreSel && useTOFVeto) { + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) { + jetHist.fill(HIST("tracksInc/proton/h3PtVsProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + } + } else { + jetHist.fill(HIST("tracksInc/proton/h3PtVsProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) { + jetHist.fill(HIST("tracksInc/deuteron/h3PtVsDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + } + } else { + jetHist.fill(HIST("tracksInc/deuteron/h3PtVsDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + } + } + float massTOF = -999; + if (addTOFplots && trk.hasTOF()) { + massTOF = trk.p() * std::sqrt(1.f / (trk.beta() * trk.beta()) - 1.f); + if (!useTPCpreSel) { + jetHist.fill(HIST("tracksInc/proton/h2TOFmassProtonVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/proton/h2TofNsigmaProtonVsPt"), trk.tofNSigmaPr(), trk.pt(), centrality); + + jetHist.fill(HIST("tracksInc/deuteron/h2TOFmassDeuteronVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/deuteron/h2TofNsigmaDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt(), centrality); + } else { + if (std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { + jetHist.fill(HIST("tracksInc/proton/h2TOFmassProtonVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/proton/h2TofNsigmaProtonVsPt"), trk.tofNSigmaPr(), trk.pt(), centrality); + } + if (std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { + jetHist.fill(HIST("tracksInc/deuteron/h2TOFmassDeuteronVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/deuteron/h2TofNsigmaDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt(), centrality); + } + } + } + + if (cEnableProtonQA && std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { + jetHist.fill(HIST("tracksInc/proton/dca/after/hDCAxyVsPtProton"), trk.dcaXY(), trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/proton/dca/after/hDCAzVsPtProton"), trk.dcaZ(), trk.pt(), centrality); + } + if (cEnableDeuteronQA && std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { + jetHist.fill(HIST("tracksInc/deuteron/dca/after/hDCAxyVsPtDeuteron"), trk.dcaXY(), trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/deuteron/dca/after/hDCAzVsPtDeuteron"), trk.dcaZ(), trk.pt(), centrality); + } + + } else { // anti-particle info + if (useTOFNsigmaPreSel && trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) + jetHist.fill(HIST("tracksInc/antiProton/h3PtVsantiProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) + jetHist.fill(HIST("tracksInc/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + } else if (!useTOFNsigmaPreSel && !useTOFVeto) { + jetHist.fill(HIST("tracksInc/antiProton/h3PtVsantiProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + jetHist.fill(HIST("tracksInc/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + } else if (!useTOFNsigmaPreSel && useTOFVeto) { + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaPr()) < cfgnTPCPIDPrTOF) { + jetHist.fill(HIST("tracksInc/antiProton/h3PtVsantiProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + } + } else { + jetHist.fill(HIST("tracksInc/antiProton/h3PtVsantiProtonNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaPr(), centrality); + } + if (trk.hasTOF()) { + if (std::abs(trk.tofNSigmaDe()) < cfgnTPCPIDDeTOF) { + jetHist.fill(HIST("tracksInc/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + } + } else { + jetHist.fill(HIST("tracksInc/antiDeuteron/h3PtVsantiDeuteronNSigmaTPCVsPt"), trk.pt(), trk.tpcNSigmaDe(), centrality); + } + } + float massTOF = -999; + if (addTOFplots && trk.hasTOF()) { + massTOF = trk.p() * std::sqrt(1.f / (trk.beta() * trk.beta()) - 1.f); + if (!useTPCpreSel) { + jetHist.fill(HIST("tracksInc/antiProton/h2TOFmassantiProtonVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiProton/h2TofNsigmaantiProtonVsPt"), trk.tofNSigmaPr(), trk.pt(), centrality); + + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TOFmassantiDeuteronVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt(), centrality); + } else { + if (std::abs(trk.tpcNSigmaPr()) < cfgnTPCPIDPr) { + jetHist.fill(HIST("tracksInc/antiProton/h2TOFmassantiProtonVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiProton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - MassProton * MassProton, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiProton/h2TofNsigmaantiProtonVsPt"), trk.tofNSigmaPr(), trk.pt(), centrality); + } + if (std::abs(trk.tpcNSigmaDe()) < cfgnTPCPIDDe) { + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TOFmassantiDeuteronVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt(), centrality); + } else { + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TOFmassantiDeuteronVsPt"), massTOF, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - MassDeuteron * MassDeuteron, trk.pt(), centrality); + jetHist.fill(HIST("tracksInc/antiDeuteron/h2TofNsigmaantiDeuteronVsPt"), trk.tofNSigmaDe(), trk.pt(), centrality); + } + } + } + } // anti-particle info end + } // track + } + void processMCGen(o2::aod::JetMcCollision const& collision, /*soa::SmallGroups> const& recoColls,*/ aod::JetParticles const& mcParticles, soa::Filtered const& mcpjets) { jetHist.fill(HIST("mcpJet/eventStat"), 0.5); @@ -1192,7 +1511,7 @@ struct nucleiInJets { jetHist.fill(HIST("mcpJet/eventStat"), 3.5); int nJets = 0; - for (auto& mcpjet : mcpjets) { + for (const auto& mcpjet : mcpjets) { jetHist.fill(HIST("mcpJet/hJetPt"), mcpjet.pt()); jetHist.fill(HIST("mcpJet/hJetEta"), mcpjet.eta()); jetHist.fill(HIST("mcpJet/hJetPhi"), mcpjet.phi()); @@ -1210,10 +1529,10 @@ struct nucleiInJets { bool jetFlag = false; // float jetPt = -999.; - for (auto& mcpjet : mcpjets) { + for (const auto& mcpjet : mcpjets) { double delPhi = TVector2::Phi_mpi_pi(mcpjet.phi() - mcParticle.phi()); double delEta = mcpjet.eta() - mcParticle.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) jetFlag = true; // jetPt = mcpjet.pt(); @@ -1266,7 +1585,7 @@ struct nucleiInJets { jetHist.fill(HIST("mcdJet/nJetsPerEvent"), nJets); if (isWithJetEvents && nJets == 0) return; - for (auto& track : tracks) { + for (const auto& track : tracks) { auto fullTrack = track.track_as(); if (!isTrackSelected(fullTrack)) continue; @@ -1283,21 +1602,21 @@ struct nucleiInJets { if (isWithLeadingJet) { double delPhi = TVector2::Phi_mpi_pi(leadingJetWithPtEtaPhi[2] - track.phi()); double delEta = leadingJetWithPtEtaPhi[1] - track.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) jetFlag = true; std::array perpConePhiJet = getPerpendicuarPhi(leadingJetWithPtEtaPhi[2]); double delPhiPerpCone1 = TVector2::Phi_mpi_pi(perpConePhiJet[0] - track.phi()); double delPhiPerpCone2 = TVector2::Phi_mpi_pi(perpConePhiJet[1] - track.phi()); - double RPerpCone1 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone1 * delPhiPerpCone1)); - double RPerpCone2 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone2 * delPhiPerpCone2)); + double RPerpCone1 = RecoDecay::sqrtSumOfSquares(delEta, delPhiPerpCone1); + double RPerpCone2 = RecoDecay::sqrtSumOfSquares(delEta, delPhiPerpCone2); if (RPerpCone1 < cfgjetR || RPerpCone2 < cfgjetR) jetFlagPerpCone = true; } else { - for (auto& mcdjet : mcdjets) { + for (const auto& mcdjet : mcdjets) { double delPhi = TVector2::Phi_mpi_pi(mcdjet.phi() - track.phi()); double delEta = mcdjet.eta() - track.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) jetFlag = true; // jetPt = mcdjet.pt(); @@ -1347,10 +1666,10 @@ struct nucleiInJets { if (mcdjets.size() == 0) return; std::vector leadingJetWithPtEtaPhi(3); - for (auto& mcdjet : mcdjets) { + for (const auto& mcdjet : mcdjets) { if (!mcdjet.has_matchedJetGeo()) continue; - for (auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { if (!mcpjet.has_matchedJetGeo()) continue; @@ -1416,30 +1735,29 @@ struct nucleiInJets { bool isTpcPassed(true); bool isTof(completeTrack.hasTOF()); bool isTOFAndTPCPreSel(completeTrack.hasTOF() && - (completeTrack.tpcNSigmaPr() < cfgnTPCPIDPrTOF || completeTrack.tpcNSigmaDe() < cfgnTPCPIDDeTOF || - completeTrack.tpcNSigmaHe() < cfgnTPCPIDHeTOF || completeTrack.tpcNSigmaTr() < cfgnTPCPIDTrTOF)); + (std::abs(completeTrack.tpcNSigmaPr()) < cfgnTPCPIDPrTOF || std::abs(completeTrack.tpcNSigmaDe()) < cfgnTPCPIDDeTOF || + std::abs(completeTrack.tpcNSigmaHe()) < cfgnTPCPIDHeTOF || std::abs(completeTrack.tpcNSigmaTr()) < cfgnTPCPIDTrTOF)); bool jetFlag = false; bool jetFlagPerpCone = false; if (isWithLeadingJet) { double delPhi = TVector2::Phi_mpi_pi(leadingJetWithPtEtaPhi[2] - track.phi()); double delEta = leadingJetWithPtEtaPhi[1] - track.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) jetFlag = true; std::array perpConePhiJet = getPerpendicuarPhi(leadingJetWithPtEtaPhi[2]); double delPhiPerpCone1 = TVector2::Phi_mpi_pi(perpConePhiJet[0] - track.phi()); double delPhiPerpCone2 = TVector2::Phi_mpi_pi(perpConePhiJet[1] - track.phi()); - double RPerpCone1 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone1 * delPhiPerpCone1)); - double RPerpCone2 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone2 * delPhiPerpCone2)); + double RPerpCone1 = RecoDecay::sqrtSumOfSquares(delEta, delPhiPerpCone1); + double RPerpCone2 = RecoDecay::sqrtSumOfSquares(delEta, delPhiPerpCone2); if (RPerpCone1 < cfgjetR || RPerpCone2 < cfgjetR) jetFlagPerpCone = true; } else { - for (std::size_t iDJet = 0; iDJet < mcdJetPt.size(); iDJet++) { double delPhi = TVector2::Phi_mpi_pi(mcdJetPhi[iDJet] - track.phi()); double delEta = mcdJetEta[iDJet] - track.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) { jetFlag = true; @@ -1460,8 +1778,12 @@ struct nucleiInJets { jetHist.fill(HIST("eff/recmatched/pt/PtParticleTypeTPC"), mcTrack.pt(), jetFlag, mapPDGToValue(mcTrack.pdgCode())); if (isTof) jetHist.fill(HIST("eff/recmatched/pt/PtParticleTypeTOF"), mcTrack.pt(), jetFlag, mapPDGToValue(mcTrack.pdgCode())); - if (isTOFAndTPCPreSel) + if (isTOFAndTPCPreSel) { jetHist.fill(HIST("eff/recmatched/pt/PtParticleTypeTPCTOF"), mcTrack.pt(), jetFlag, mapPDGToValue(mcTrack.pdgCode())); + jetHist.fill(HIST("eff/recmatched/pt/PtParticleTypeTPCTOFVeto"), mcTrack.pt(), jetFlag, mapPDGToValue(mcTrack.pdgCode())); + } else { + jetHist.fill(HIST("eff/recmatched/pt/PtParticleTypeTPCTOFVeto"), mcTrack.pt(), jetFlag, mapPDGToValue(mcTrack.pdgCode())); + } if (jetFlagPerpCone) { jetHist.fill(HIST("eff/recmatched/perpCone/pt/PtParticleType"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode())); @@ -1475,8 +1797,12 @@ struct nucleiInJets { jetHist.fill(HIST("eff/recmatched/perpCone/pt/PtParticleTypeTPC"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode())); if (isTof) jetHist.fill(HIST("eff/recmatched/perpCone/pt/PtParticleTypeTOF"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode())); - if (isTOFAndTPCPreSel) + if (isTOFAndTPCPreSel) { jetHist.fill(HIST("eff/recmatched/perpCone/pt/PtParticleTypeTPCTOF"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode())); + jetHist.fill(HIST("eff/recmatched/perpCone/pt/PtParticleTypeTPCTOFVeto"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode())); + } + } else { + jetHist.fill(HIST("eff/recmatched/perpCone/pt/PtParticleTypeTPCTOFVeto"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode())); } } } // tracks @@ -1494,14 +1820,14 @@ struct nucleiInJets { if (isWithLeadingJet) { double delPhi = TVector2::Phi_mpi_pi(leadingJetWithPtEtaPhi[2] - mcParticle.phi()); double delEta = leadingJetWithPtEtaPhi[1] - mcParticle.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) jetFlagMC = true; std::array perpConePhiJet = getPerpendicuarPhi(leadingJetWithPtEtaPhi[2]); double delPhiPerpCone1 = TVector2::Phi_mpi_pi(perpConePhiJet[0] - mcParticle.phi()); double delPhiPerpCone2 = TVector2::Phi_mpi_pi(perpConePhiJet[1] - mcParticle.phi()); - double RPerpCone1 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone1 * delPhiPerpCone1)); - double RPerpCone2 = TMath::Sqrt((delEta * delEta) + (delPhiPerpCone2 * delPhiPerpCone2)); + double RPerpCone1 = RecoDecay::sqrtSumOfSquares(delEta, delPhiPerpCone1); + double RPerpCone2 = RecoDecay::sqrtSumOfSquares(delEta, delPhiPerpCone2); if (RPerpCone1 < cfgjetR || RPerpCone2 < cfgjetR) jetFlagPerpConeMC = true; } else { @@ -1509,7 +1835,7 @@ struct nucleiInJets { for (std::size_t iDJet = 0; iDJet < mcdJetPt.size(); iDJet++) { double delPhi = TVector2::Phi_mpi_pi(mcdJetPhi[iDJet] - mcParticle.phi()); double delEta = mcdJetEta[iDJet] - mcParticle.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) { jetFlagMC = true; break; @@ -1523,7 +1849,6 @@ struct nucleiInJets { jetHist.fill(HIST("eff/recmatched/gen/perpCone/pt/PtParticleType"), mcParticle.pt(), mapPDGToValue(mcParticle.pdgCode())); } } - } // mcParticle } // process @@ -1579,7 +1904,7 @@ struct nucleiInJets { jetHist.fill(HIST("genmatched/leadingJet/hGenJetPt"), leadingMCPJet.pt()); if (leadingMCPJet.has_matchedJetGeo()) { jetHist.fill(HIST("genmatched/leadingJet/hGenJetPtMatched"), leadingMCPJet.pt()); - for (auto& mcdjet : leadingMCPJet.template matchedJetGeo_as()) { + for (const auto& mcdjet : leadingMCPJet.template matchedJetGeo_as()) { // Assuming matchedJetGeo_as returns valid MCD jets; no redundant has check needed // Store jet properties mcdJetPt.push_back(mcdjet.pt()); @@ -1618,7 +1943,7 @@ struct nucleiInJets { for (std::size_t iDJet = 0; iDJet < mcpJetPt.size(); iDJet++) { double delPhi = TVector2::Phi_mpi_pi(mcpJetPhi[iDJet] - mcParticle.phi()); double delEta = mcpJetEta[iDJet] - mcParticle.eta(); - double R = TMath::Sqrt((delEta * delEta) + (delPhi * delPhi)); + double R = RecoDecay::sqrtSumOfSquares(delEta, delPhi); if (R < cfgjetR) { jetFlag = true; @@ -1631,8 +1956,76 @@ struct nucleiInJets { } // jet constituents } // process + void processRecInc(EventTableMC::iterator const& coll, TrackCandidatesIncMC const& tracks, aod::JetParticles const& particleTracks, aod::JMcCollisions const&) + { + jetHist.fill(HIST("recInc/eventStat"), 0.5); + if (!jetderiveddatautilities::selectCollision(coll, jetderiveddatautilities::initialiseEventSelectionBits("sel8"))) + return; + jetHist.fill(HIST("recInc/eventStat"), 1.5); + if (std::abs(coll.posZ()) > 10) // bad vertex + return; + jetHist.fill(HIST("recInc/eventStat"), 2.5); + + float centrality = -999; + switch (centralityType) { + case 0: // FT0M + centrality = coll.centFT0M(); + break; + case 1: // FT0C + centrality = coll.centFT0C(); + break; + case 2: // FV0A + centrality = coll.centFV0A(); + break; + default: + centrality = -999; + } + jetHist.fill(HIST("recInc/vertexZ"), coll.posZ(), centrality); + for (const auto& track : tracks) { + if (!isTrackSelected(track)) { + continue; + } + if (!track.has_mcParticle()) + continue; + if (std::fabs(track.eta()) > cfgtrkMaxEta) + continue; + auto mcTrack = track.mcParticle_as(); + if (!mcTrack.isPhysicalPrimary()) + continue; + bool isTOFAndTPCPreSel(track.hasTOF() && + (std::abs(track.tpcNSigmaPr()) < cfgnTPCPIDPrTOF || std::abs(track.tpcNSigmaDe()) < cfgnTPCPIDDeTOF)); + + if (mapPDGToValue(mcTrack.pdgCode()) != 0) { + jetHist.fill(HIST("recInc/pt/PtParticleTypeTPC"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode()), centrality); + + if (isTOFAndTPCPreSel) { + jetHist.fill(HIST("recInc/pt/PtParticleTypeTPCTOF"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode()), centrality); + jetHist.fill(HIST("recInc/pt/PtParticleTypeTPCTOFVeto"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode()), centrality); + } else { + jetHist.fill(HIST("recInc/pt/PtParticleTypeTPCTOFVeto"), mcTrack.pt(), mapPDGToValue(mcTrack.pdgCode()), centrality); + } + } + } // track + + // loop over particles + auto mcParticles_per_coll = particleTracks.sliceBy(perMCCol, coll.mcCollision().globalIndex()); + for (const auto& mcParticle : mcParticles_per_coll) { + if (!mcParticle.isPhysicalPrimary()) + continue; + if (std::fabs(mcParticle.eta()) > cfgtrkMaxEta) + continue; + if (std::fabs(mcParticle.y()) > cfgtrkMaxRap) + continue; + if (mapPDGToValue(mcParticle.pdgCode()) != 0) { + jetHist.fill(HIST("genInc/pt/PtParticleType"), mcParticle.pt(), mapPDGToValue(mcParticle.pdgCode()), centrality); + } + } // mc particles + } + PROCESS_SWITCH(nucleiInJets, processJetTracksData, "nuclei in Jets data", true); PROCESS_SWITCH(nucleiInJets, processJetTracksDataLfPid, "nuclei in Jets data", false); + PROCESS_SWITCH(nucleiInJets, processDataInc, "nuclei-data", false); + PROCESS_SWITCH(nucleiInJets, processRecInc, "nuclei MC", false); PROCESS_SWITCH(nucleiInJets, processMCRec, "nuclei in Jets for detectorlevel Jets", false); PROCESS_SWITCH(nucleiInJets, processMCGen, "nuclei in Jets MC particlelevel Jets", false); PROCESS_SWITCH(nucleiInJets, processRecMatched, "nuclei in Jets rec matched", false); diff --git a/PWGJE/Tasks/phiInJets.cxx b/PWGJE/Tasks/phiInJets.cxx index 88a09016b44..821169310b0 100644 --- a/PWGJE/Tasks/phiInJets.cxx +++ b/PWGJE/Tasks/phiInJets.cxx @@ -15,36 +15,46 @@ /// /// \author Adrian Fereydon Nassirpour -#include -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "TRandom.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 "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 "Common/Core/RecoDecay.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" +#include "TRandom.h" +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include -#include "PWGLF/DataModel/LFResonanceTables.h" +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/photonChargedTriggerCorrelation.cxx b/PWGJE/Tasks/photonChargedTriggerCorrelation.cxx new file mode 100644 index 00000000000..8c62845a145 --- /dev/null +++ b/PWGJE/Tasks/photonChargedTriggerCorrelation.cxx @@ -0,0 +1,1618 @@ +// 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 photonChargedTriggerCorrelation.cxx +/// \author Julius Kinner +/// \brief photon-jet correlation analysis +/// +/// Analysis for angular correlations between jets and photons via two-particle correlations with charged high-pt triggers +/// Associated hadrons (tracks), pipm, photons (PCM), pi0 (PCM) +/// Also contains checks and monte-carlo (efficiency, purity, mc-true correlation,...) +/// End goal of studying correlations between direct photons and jets + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "TMath.h" +#include "Math/Vector4D.h" + +#include "CCDB/BasicCCDBManager.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "Framework/AnalysisTask.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/Core/TableHelper.h" + +#include "PWGEM/PhotonMeson/DataModel/gammaTables.h" +#include "PWGEM/PhotonMeson/Utils/PCMUtilities.h" + +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/PhotonChargedTriggerCorrelation.h" + +const double absEtaMax = 0.8; +#define DPHI_SCALE constants::math::TwoPI - constants::math::PIHalf +#define DETA_SCALE 4 * absEtaMax - 2 * absEtaMax + +using namespace o2; +using namespace o2::framework; + +using CorrCollisions = soa::Join; +using CorrCollision = CorrCollisions::iterator; +using CorrMcDCollisions = soa::Join; +using CorrMcDCollision = CorrMcDCollisions::iterator; +using CorrMcCollisions = soa::Join; +using CorrMcCollision = CorrMcCollisions::iterator; + +using BinningZPvMult = ColumnBinningPolicy; + +// correlation derived data =================================================================================================================================================================== + +struct CorrelationTableProducer { + // reco + Produces collisionExtraCorrTable; + Produces triggerTable; + Produces hadronTable; + Produces pipmTable; + Produces photonPCMTable; + Produces photonPCMPairTable; + // mc + Produces mcCollisionExtraCorrTable; + Produces triggerParticleTable; + + Configurable zPvMax{"zPvMax", 7, "maximum absZ primary-vertex cut"}; + Configurable occupancyMin{"occupancyMin", 0, "minimum occupancy cut"}; + Configurable occupancyMax{"occupancyMax", 2000, "maximum occupancy cut"}; + Configurable etaMax{"etaMax", 1 * absEtaMax, "maximum absEta cut"}; + + Configurable eventSelections{"eventSelections", "sel8", "JE framework - event selection"}; + Configurable trackSelections{"trackSelections", "globalTracks", "JE framework - track selections"}; + Configurable triggerMasks{"triggerMasks", "", "JE framework - skimmed data trigger masks (relevent for correlation: fTrackLowPt,fTrackHighPt)"}; + + Configurable piPIDLowPt{"piPIDLowPt", 0.5, "max pt value for pipm PID without tof"}; + Configurable piPIDHighPt{"piPIDHighPt", 2.5, "min pt value for pipm PID without tof in relativistic rise of Bethe-Bloch"}; + Configurable> nSigmaPiTpcLowPt{"nSigmaPiTpcLowPt", {-2, 2}, "minimum-maximum nSigma for pipm in tpc at low pt"}; + Configurable> nSigmaPiTpcMidPt{"nSigmaPiTpcMidPt", {-1, 1}, "minimum-maximum nSigma for pipm in tpc at mid pt"}; + Configurable> nSigmaPiTof{"nSigmaPiTof", {-1, 2}, "minimum-maximum nSigma for pipm in tof"}; + Configurable> nSigmaPiRelRise{"nSigmaPiRelRise", {0, 2}, "minimum-maximum nSigma pipm tpc at high pt"}; + + Configurable ptTrigMin{"ptTrigMin", 5, "minimum pT of triggers"}; + + // derivatives of configurables + + std::vector eventSelectionBits; + int trackSelection = -1; + std::vector triggerMaskBits; + + // for mc + Service pdg; + + // partitions++ + SliceCache cache; + Partition partitionTriggerTracks = aod::jtrack::pt > ptTrigMin; + Partition partitionTriggerParticles = aod::jmcparticle::pt > ptTrigMin; + + Preslice perColTracks = aod::jtrack::collisionId; + Preslice perColMcParticles = aod::jmcparticle::mcCollisionId; + + Preslice perColV0Photons = aod::v0photonkf::collisionId; + + // functions ================================================================================================================================================================================ + + // selections /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // event selection + template + bool checkEventSelection(T_collision const& collision) + { + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) + return false; + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits)) + return false; + if (std::abs(collision.posZ()) > zPvMax) + return false; + if (collision.trackOccupancyInTimeRange() < occupancyMin || collision.trackOccupancyInTimeRange() > occupancyMax) + return false; + return true; + } + + // checks global track cuts + template + bool checkGlobalTrackEta(T_track const& track) + { + if (!jetderiveddatautilities::selectTrack(track, trackSelection)) + return false; + if (!jetderiveddatautilities::applyTrackKinematics(track, 0.1, 1000, -1 * etaMax, etaMax)) + return false; + return true; + } + + // checks pipm selection (just PID (no additional track cuts)) + template + bool checkPipmTPCTOF(T_track const& track) + { + // too low for tof + if (track.pt() < piPIDLowPt) { + if (track.tpcNSigmaPi() > nSigmaPiTpcLowPt.value[0] && track.tpcNSigmaPi() < nSigmaPiTpcLowPt.value[1]) { + return true; + } + return false; + } + // Bethe-Bloch overlap (-> tpc + tof) + if (track.pt() < piPIDHighPt) { + if (track.hasTOF()) { // has to stay inside pt-if due to return-layout of function + if (track.tpcNSigmaPi() > nSigmaPiTpcMidPt.value[0] && track.tpcNSigmaPi() < nSigmaPiTpcMidPt.value[1] && + track.tofNSigmaPi() > nSigmaPiTof.value[0] && track.tofNSigmaPi() < nSigmaPiTof.value[1]) { + return true; + } + } + return false; + } + // Bethe-Bloch rel rise (too high for tof) + if (track.tpcNSigmaPi() > nSigmaPiRelRise.value[0] && track.tpcNSigmaPi() < nSigmaPiRelRise.value[1]) { + return true; + } + return false; + } + + // checks pipm selection (just PID (no additional track cuts)) + template + bool checkPipmTPC(T_track const& track) + { + // Bethe-Bloch rel rise + if (track.pt() > piPIDHighPt) { + if (track.tpcNSigmaPi() > nSigmaPiRelRise.value[0] && track.tpcNSigmaPi() < nSigmaPiRelRise.value[1]) { + return true; + } + } + return false; + } + + // analysis ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void init(InitContext const&) + { + eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(eventSelections)); + trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trackSelections)); + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); + } + + void processRecoCollisionTrigger(aod::JetCollision const& collision, aod::JetTracks const&) + { + // event selection + const bool isSelectedEvent = checkEventSelection(collision); + // trigger event check + bool isTriggerEvent = false; + + if (isSelectedEvent) { + // group collision + auto const triggers = partitionTriggerTracks->sliceByCached(aod::jtrack::collisionId, collision.globalIndex(), cache); + + // trigger loop + for (auto const& trigger : triggers) { + // track selection + if (!checkGlobalTrackEta(trigger)) + continue; + + // detect trigger event + isTriggerEvent = true; + + // trigger info + triggerTable(trigger.collisionId(), trigger.globalIndex(), trigger.pt(), trigger.phi(), trigger.eta()); + } + } + + // collision info + collisionExtraCorrTable(isSelectedEvent, isTriggerEvent); + } + PROCESS_SWITCH(CorrelationTableProducer, processRecoCollisionTrigger, "process correlation collision_extra and trigger table (reconstructed)", false); + + void processRecoPipmTPCTOF(aod::JetCollision const& collision, + soa::Join const& tracks, soa::Join const&) + { + // event selection + if (!checkEventSelection(collision)) + return; + + // hadron/pipm + for (auto const& track : tracks) { + // track selection + if (!checkGlobalTrackEta(track)) + continue; + + // hadron + hadronTable(track.collisionId(), track.globalIndex(), track.pt(), track.phi(), track.eta()); + + // pipm selection + auto const& trackPID = track.track_as>(); + if (!checkPipmTPCTOF(trackPID)) + continue; + + // pipm + pipmTable(track.collisionId(), track.globalIndex(), track.pt(), track.phi(), track.eta()); + } + } + PROCESS_SWITCH(CorrelationTableProducer, processRecoPipmTPCTOF, "process pipm (TPC-TOF) table (reconstructed)", false); + + void processRecoPipmTPC(aod::JetCollision const& collision, + soa::Join const& tracks, soa::Join const&) + { + // event selection + if (!checkEventSelection(collision)) + return; + + // hadron/pipm + for (auto const& track : tracks) { + // track selection + if (!checkGlobalTrackEta(track)) + continue; + + // hadron + hadronTable(track.collisionId(), track.globalIndex(), track.pt(), track.phi(), track.eta()); + + // pipm selection + auto const& trackPID = track.track_as>(); + if (!checkPipmTPC(trackPID)) + continue; + + // pipm + pipmTable(track.collisionId(), track.globalIndex(), track.pt(), track.phi(), track.eta()); + } + } + PROCESS_SWITCH(CorrelationTableProducer, processRecoPipmTPC, "process pipm (TPC) table (reconstructed)", false); + + void processRecoPhotonPCM(soa::Join::iterator const& collision, aod::Collisions const&, + aod::V0PhotonsKF const& v0Photons, aod::V0Legs const&) + { + // event selection + if (!checkEventSelection(collision)) + return; + + // photonsPCM (for some reason collsionId not an index column (?)) + auto const v0PhotonsThisEvent = v0Photons.sliceBy(perColV0Photons, collision.collisionId()); + + // photonPCM + for (auto const& v0Photon : v0PhotonsThisEvent) { + // photon selection + if (std::abs(v0Photon.eta()) > etaMax) + continue; + + // photon PCM + photonPCMTable(v0Photon.collisionId(), v0Photon.globalIndex(), + v0Photon.posTrack().trackId(), v0Photon.negTrack().trackId(), v0Photon.pt(), v0Photon.phi(), v0Photon.eta()); + } + + // photonPCm pairs + for (auto const& [v0Photon1, v0Photon2] : soa::combinations(soa::CombinationsStrictlyUpperIndexPolicy(v0PhotonsThisEvent, v0PhotonsThisEvent))) { + // get kinematics + ROOT::Math::PtEtaPhiMVector const p4V0PCM1(v0Photon1.pt(), v0Photon1.eta(), v0Photon1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector const p4V0PCM2(v0Photon2.pt(), v0Photon2.eta(), v0Photon2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector const p4V0PCMPair = p4V0PCM1 + p4V0PCM2; + + // pi0 selection + if (std::abs(p4V0PCMPair.Eta()) > etaMax) + continue; + + // save info + photonPCMPairTable(v0Photon1.collisionId(), v0Photon1.globalIndex(), v0Photon2.globalIndex(), + v0Photon1.posTrack().trackId(), v0Photon1.negTrack().trackId(), v0Photon2.posTrack().trackId(), v0Photon2.negTrack().trackId(), + p4V0PCMPair.Pt(), p4V0PCMPair.Phi() + constants::math::PI, p4V0PCMPair.Eta(), p4V0PCMPair.M()); + } + } + PROCESS_SWITCH(CorrelationTableProducer, processRecoPhotonPCM, "process photonPCM table (reconstructed)", false); + + void processMcCorrTables(aod::JetMcCollision const& mcCollision, aod::JetParticles const&) + { + // group collision + auto const triggers = partitionTriggerParticles->sliceByCached(aod::jmcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + // trigger event check + bool isTriggerEvent = false; + + // trigger loop + for (auto const& trigger : triggers) { + // track selection + auto const pdgParticle = pdg->GetParticle(trigger.pdgCode()); + if (!pdgParticle || pdgParticle->Charge() == 0) + continue; + if (!trigger.isPhysicalPrimary()) + continue; + if (std::abs(trigger.eta()) > etaMax) + continue; + + // detect trigger event + isTriggerEvent = true; + + // trigger info + triggerParticleTable(mcCollision.globalIndex(), trigger.globalIndex(), trigger.pt(), trigger.phi(), trigger.eta()); + } + + // collision info + mcCollisionExtraCorrTable(isTriggerEvent); + } + PROCESS_SWITCH(CorrelationTableProducer, processMcCorrTables, "process table production (mc)", false); +}; + +// correlation analysis ======================================================================================================================================================================= + +struct PhotonChargedTriggerCorrelation { + // configurables + + // general (kenobi) + Configurable pathCcdbEff{"pathCcdbEff", "Users/j/jkinner/efficiency/set_in_config", "base path to the ccdb efficiencies"}; + Configurable urlCcdb{"urlCcdb", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable noLaterThanCcdb{"noLaterThanCcdb", + std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), + "latest acceptable timestamp of creation for the object"}; + + // analysis + Configurable doEffCorrectionTrigger{"doEffCorrectionTrigger", false, "whether to do on-the-fly mixing correction for triggers"}; + Configurable doEffCorrectionHadron{"doEffCorrectionHadron", false, "whether to do on-the-fly mixing correction for hadrons"}; + Configurable doEffCorrectionPipm{"doEffCorrectionPipm", false, "whether to do on-the-fly mixing correction for pipm"}; + Configurable doEffCorrectionPhotonPCM{"doEffCorrectionPhotonPCM", false, "whether to do on-the-fly mixing correction for photonPCM"}; + + Configurable doTrigEvMixing{"doTrigEvMixing", false, "whether to use trigger events for trigger mixing"}; + Configurable doTrigEvEff{"doTrigEvEff", false, "whether to use trigger events for efficiency histograms"}; + Configurable nTriggerSavedForMixing{"nTriggerSavedForMixing", 2048, "number of triggers that are saved for mixing with other events"}; + Configurable nTriggerMixingHadron{"nTriggerMixingHadron", 64, "number of triggers that are used for hadron mixing"}; + Configurable nTriggerMixingPipm{"nTriggerMixingPipm", 64, "number of triggers that are used for pipm mixing"}; + Configurable nTriggerMixingPhotonPCM{"nTriggerMixingPhotonPCM", 64, "number of triggers that are saved for photonPCM mixing"}; + Configurable nTriggerMixingPi0PCM{"nTriggerMixingPi0PCM", 64, "number of triggers that are saved for pi0PCM mixing"}; + Configurable nNeighboursMixingPi0PCMPair{"nNeighboursMixingPi0PCMPair", 64, "number neighbours used for for pi0PCM pair mixing"}; + Configurable> pi0PCMMassRange{"pi0PCMMassRange", {0.10, 0.15}, "photon-pair mass integration range for pi0PCM"}; + Configurable> pi0PCMSideMassRange{"pi0PCMSideMassRange", {0.16, 0.24}, "photon-pair mass integration range outside outside pi0PCM region"}; + + Configurable requireSingleCollisionPurity{"requireSingleCollisionPurity", true, "whether particle from single chosen MC-col associated to reco-col (else just type/kin match)"}; + + // for histograms + Configurable nBinsZPv{"nBinsZPv", 100, "number zPv bins in histos for QA"}; + Configurable nBinsZPvSmol{"nBinsZPvSmol", 28, "number zPv bins but smaller"}; + Configurable nBinsMult{"nBinsMult", 200, "number multiplicity bins in histos for QA"}; + Configurable nBinsMultSmol{"nBinsMultSmol", 20, "number multiplicity bins but smaller"}; + Configurable nBinsOccupancy{"nBinsOccupancy", 2000, "number occupancy bins in histos for QA"}; + + Configurable nBinsPhi{"nBinsPhi", 72, "number phi bins"}; + Configurable nBinsEta{"nBinsEta", 40, "number eta bins"}; + Configurable nBinsMgg{"nBinsMgg", 160, "number mass-photon-pair bins"}; + + Configurable> binsPtTrig{"binsPtTrig", {5, 10, 25, 50}, "correlation ptTrig bins"}; + Configurable> binsPtAssoc{"binsPtAssoc", + {0.2, 0.5, 0.75, 1.0, 1.25, 1.5, 1.75, 2.0, 2.25, 2.5, 2.75, 3.0, 3.5, 4.0, 4.5, 5.0, 5.5, 6.0, 7.0, 8.0, 9.0, 10, 12.5, 15, 17.5, 20, 30, 40}, + "correlation ptAssoc bins"}; + Configurable> binsDPhi{"binsDPhi", + {0.00 * DPHI_SCALE, + 0.04 * DPHI_SCALE, 0.08 * DPHI_SCALE, 0.11 * DPHI_SCALE, 0.14 * DPHI_SCALE, + 0.16 * DPHI_SCALE, 0.18 * DPHI_SCALE, 0.20 * DPHI_SCALE, 0.22 * DPHI_SCALE, + 0.23 * DPHI_SCALE, 0.24 * DPHI_SCALE, 0.25 * DPHI_SCALE, 0.26 * DPHI_SCALE, 0.27 * DPHI_SCALE, 0.28 * DPHI_SCALE, + 0.30 * DPHI_SCALE, 0.32 * DPHI_SCALE, 0.34 * DPHI_SCALE, 0.36 * DPHI_SCALE, + 0.39 * DPHI_SCALE, 0.42 * DPHI_SCALE, 0.46 * DPHI_SCALE, 0.50 * DPHI_SCALE, + 0.54 * DPHI_SCALE, 0.58 * DPHI_SCALE, 0.61 * DPHI_SCALE, 0.64 * DPHI_SCALE, + 0.66 * DPHI_SCALE, 0.68 * DPHI_SCALE, 0.70 * DPHI_SCALE, 0.72 * DPHI_SCALE, + 0.74 * DPHI_SCALE, 0.76 * DPHI_SCALE, 0.78 * DPHI_SCALE, + 0.80 * DPHI_SCALE, 0.82 * DPHI_SCALE, 0.84 * DPHI_SCALE, 0.86 * DPHI_SCALE, + 0.89 * DPHI_SCALE, 0.92 * DPHI_SCALE, 0.96 * DPHI_SCALE, 1.00 * DPHI_SCALE}, + "correlation bins DeltaPhi"}; + Configurable> binsDEta{"binsDEta", + {0 / 32. * DETA_SCALE, + 1 / 32. * DETA_SCALE, 2 / 32. * DETA_SCALE, 3 / 32. * DETA_SCALE, 4 / 32. * DETA_SCALE, + 5 / 32. * DETA_SCALE, 6 / 32. * DETA_SCALE, 7 / 32. * DETA_SCALE, 8 / 32. * DETA_SCALE, + 9 / 32. * DETA_SCALE, 10 / 32. * DETA_SCALE, 11 / 32. * DETA_SCALE, 12 / 32. * DETA_SCALE, 13 / 32. * DETA_SCALE, 14 / 32. * DETA_SCALE, + 59 / 128. * DETA_SCALE, 62 / 128. * DETA_SCALE, 64 / 128. * DETA_SCALE, 66 / 128. * DETA_SCALE, 69 / 128. * DETA_SCALE, 18 / 32. * DETA_SCALE, + 19 / 32. * DETA_SCALE, 20 / 32. * DETA_SCALE, 21 / 32. * DETA_SCALE, 22 / 32. * DETA_SCALE, 23 / 32. * DETA_SCALE, 24 / 32. * DETA_SCALE, + 25 / 32. * DETA_SCALE, 26 / 32. * DETA_SCALE, 27 / 32. * DETA_SCALE, 28 / 32. * DETA_SCALE, + 29 / 32. * DETA_SCALE, 30 / 32. * DETA_SCALE, 31 / 32. * DETA_SCALE, 32 / 32. * DETA_SCALE}, + "correlation bins DeltaEta"}; + Configurable> binsZPv{"binsZPv", + {-7, -5, -3, -1, 1, 3, 5, 7}, + "zPv mixing bins"}; + Configurable> binsMult{"binsMult", + {-0.5, 9.5, 14.5, 19.5, 25.5, 32}, + "multiplicity mixing bins"}; + + // configurables from other tasks + + double etaMax; + + // objects to hold histograms + HistogramRegistry histos{"histogramRegistry", {}, OutputObjHandlingPolicy::AnalysisObject, false, false}; + + // ccdb calls + Service ccdb; + // for mc + Service pdg; + + // random number generation + static constexpr unsigned int SeedRandomEngine = 12345; + std::mt19937 randomEngine{SeedRandomEngine}; + + // partitions + SliceCache cache; + + // prepare for per collision slicing + Preslice perColTracks = aod::jtrack::collisionId; + Preslice perColTriggers = aod::corr_particle::jetCollisionId; + Preslice perColHadrons = aod::corr_particle::jetCollisionId; + Preslice perColPipms = aod::corr_particle::jetCollisionId; + Preslice perColPhotonPCMs = aod::corr_particle::jetCollisionId; + Preslice perColMcParticles = aod::jmcparticle::mcCollisionId; + Preslice perColTriggerParticles = aod::corr_particle::jetMcCollisionId; + + // combinations binning + // cumbersome, but still better than having extra configurable or figuring out how to init binningZPvMult later while declaring it here + std::function(std::vector const&, double)> prependValueToVector = + [](std::vector const& vec, double const value) { + std::vector resultVec = {value}; + resultVec.insert(resultVec.end(), vec.begin(), vec.end()); + return resultVec; + }; + BinningZPvMult binningZPvMult{{prependValueToVector(binsZPv.value, VARIABLE_WIDTH), prependValueToVector(binsMult.value, VARIABLE_WIDTH)}, true}; + + // declare analysis variables + + // efficiency histograms + TH1D* h1PtInvEffTrigger; + TH1D* h1PtInvEffHadron; + TH1D* h1PtInvEffPipm; + TH1D* h1PtInvEffPhotonPCM; + + // mixing trigger memory + int nTriggersThisDataFrame; + // organised as zPv- and mult-bin matrix of deques to save trigger info beyond single dataframe + // extra bin for mult overflow + // with ajusted zVtx (see triggerBinValuesZPv in init) and mult overflow -> all events accounted for + // (possibly replace by some advanced derived data method and O2 event mixing in future?) + std::vector triggerBinValuesZPv; + std::vector triggerBinValuesMult; + std::vector>> savedTriggersZPvMultPt; + std::vector>> savedTriggersZPvMultPhi; + std::vector>> savedTriggersZPvMultEta; + + // functions ================================================================================================================================================================================ + + // general (kenobi) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // get histograms from ccdb + // save efficiencies from ccdb in histogram registry + void initCcdbHistograms() + { + // trigger + h1PtInvEffTrigger = nullptr; + if (doEffCorrectionTrigger) { + h1PtInvEffTrigger = ccdb->getForTimeStamp(pathCcdbEff.value + "/trigger", noLaterThanCcdb.value); + + const double* effBinsTrigger = h1PtInvEffTrigger->GetXaxis()->GetXbins()->GetArray(); + const AxisSpec axisPtEffTrigger{std::vector(effBinsTrigger, effBinsTrigger + h1PtInvEffTrigger->GetNbinsX() + 1), "#it{p}_{T}"}; + histos.add("usedEff/h1_pt_invEff_trigger_ccdb", "h1_pt_invEff_trigger_ccdb", kTH1D, {axisPtEffTrigger}, true); + for (int iBin = 1; iBin <= h1PtInvEffTrigger->GetNbinsX(); iBin++) { + histos.get(HIST("usedEff/h1_pt_invEff_trigger_ccdb"))->SetBinContent(iBin, h1PtInvEffTrigger->GetBinContent(iBin)); + histos.get(HIST("usedEff/h1_pt_invEff_trigger_ccdb"))->SetBinError(iBin, h1PtInvEffTrigger->GetBinError(iBin)); + } + } + // hadron + h1PtInvEffHadron = nullptr; + if (doEffCorrectionHadron) { + h1PtInvEffHadron = ccdb->getForTimeStamp(pathCcdbEff.value + "/hadron", noLaterThanCcdb.value); + + const double* effBinsHadron = h1PtInvEffHadron->GetXaxis()->GetXbins()->GetArray(); + const AxisSpec axisPtEffHadron{std::vector(effBinsHadron, effBinsHadron + h1PtInvEffHadron->GetNbinsX() + 1), "#it{p}_{T}"}; + histos.add("usedEff/h1_pt_invEff_hadron_ccdb", "h1_pt_invEff_hadron_ccdb", kTH1D, {axisPtEffHadron}, true); + for (int iBin = 1; iBin <= h1PtInvEffHadron->GetNbinsX(); iBin++) { + histos.get(HIST("usedEff/h1_pt_invEff_hadron_ccdb"))->SetBinContent(iBin, h1PtInvEffHadron->GetBinContent(iBin)); + histos.get(HIST("usedEff/h1_pt_invEff_hadron_ccdb"))->SetBinError(iBin, h1PtInvEffHadron->GetBinError(iBin)); + } + } + // pipm + h1PtInvEffPipm = nullptr; + if (doEffCorrectionPipm) { + h1PtInvEffPipm = ccdb->getForTimeStamp(pathCcdbEff.value + "/pipm", noLaterThanCcdb.value); + + const double* effBinsPipm = h1PtInvEffPipm->GetXaxis()->GetXbins()->GetArray(); + const AxisSpec axisPtEffPipm{std::vector(effBinsPipm, effBinsPipm + h1PtInvEffPipm->GetNbinsX() + 1), "#it{p}_{T}"}; + histos.add("usedEff/h1_pt_invEff_pipm_ccdb", "h1_pt_invEff_pipm_ccdb", kTH1D, {axisPtEffPipm}, true); + for (int iBin = 1; iBin <= h1PtInvEffPipm->GetNbinsX(); iBin++) { + histos.get(HIST("usedEff/h1_pt_invEff_pipm_ccdb"))->SetBinContent(iBin, h1PtInvEffPipm->GetBinContent(iBin)); + histos.get(HIST("usedEff/h1_pt_invEff_pipm_ccdb"))->SetBinError(iBin, h1PtInvEffPipm->GetBinError(iBin)); + } + } + // photonPCM + h1PtInvEffPhotonPCM = nullptr; + if (doEffCorrectionPhotonPCM) { + h1PtInvEffPhotonPCM = ccdb->getForTimeStamp(pathCcdbEff.value + "/photonPCM", noLaterThanCcdb.value); + + const double* effBinsPhotonPCM = h1PtInvEffPhotonPCM->GetXaxis()->GetXbins()->GetArray(); + const AxisSpec axisPtEffPhotonPCM{std::vector(effBinsPhotonPCM, effBinsPhotonPCM + h1PtInvEffPhotonPCM->GetNbinsX() + 1), "#it{p}_{T}"}; + histos.add("usedEff/h1_pt_invEff_photonPCM_ccdb", "h1_pt_invEff_photonPCM_ccdb", kTH1D, {axisPtEffPhotonPCM}, true); + for (int iBin = 1; iBin <= h1PtInvEffPhotonPCM->GetNbinsX(); iBin++) { + histos.get(HIST("usedEff/h1_pt_invEff_photonPCM_ccdb"))->SetBinContent(iBin, h1PtInvEffPhotonPCM->GetBinContent(iBin)); + histos.get(HIST("usedEff/h1_pt_invEff_photonPCM_ccdb"))->SetBinError(iBin, h1PtInvEffPhotonPCM->GetBinError(iBin)); + } + } + } + + // create histograms + void initHistograms() + { + // define axes + const AxisSpec axisN{1, 0., 1., "#it{N}_{something}"}; + const AxisSpec axisCategories{16, 0., 16., "categories"}; + + const AxisSpec axisZPv{nBinsZPv, -10, 10, "#it{z}_{pv}"}; + const AxisSpec axisZPvSmol{nBinsZPvSmol, -7, 7, "#it{z}_{pv}"}; + const AxisSpec axisMult{nBinsMult + 1, -0.5, nBinsMult + 0.5, "multiplicity"}; + const AxisSpec axisMultSmol{nBinsMultSmol + 1, -0.5, nBinsMultSmol + 0.5, "multiplicity"}; + const AxisSpec axisOccupancy{nBinsOccupancy + 1, -0.5, nBinsOccupancy + 0.5, "occupancy"}; + + const AxisSpec axisPhi{nBinsPhi, 0, constants::math::TwoPI, "#it{#varphi}"}; + const AxisSpec axisEta{nBinsEta, -etaMax, etaMax, "#it{#eta}"}; + const AxisSpec axisMgg{nBinsMgg, 0, 0.8, "#it{m}_{#gamma#gamma}"}; + + const AxisSpec axisPtTrig{binsPtTrig, "#it{p}_{T}^{trig}"}; + const AxisSpec axisPtAssoc{binsPtAssoc, "#it{p}_{T}^{assoc}"}; + const AxisSpec axisDPhi{binsDPhi, "#Delta#it{#varphi}"}; + const AxisSpec axisDEta{binsDEta, "#Delta#it{#eta}"}; + const AxisSpec axisZPvBinning{binsZPv, "#it{z}_{pv} correlation binning"}; + const AxisSpec axisMultBinning{binsMult, "multiplicity correlation binning"}; + + // reco info + histos.add("reco/info/h1_nEvents", "h1_nEvents", kTH1D, {axisCategories}); + histos.get(HIST("reco/info/h1_nEvents"))->GetXaxis()->SetBinLabel(1, "#it{N}_{ev}^{sel}"); + histos.get(HIST("reco/info/h1_nEvents"))->GetXaxis()->SetBinLabel(2, "#it{N}_{ev}"); + histos.get(HIST("reco/info/h1_nEvents"))->GetXaxis()->SetBinLabel(3, "#it{N}_{ev}^{trig}"); + + histos.add("reco/info/h2_zPvMult", "h2_zPvMult", kTHnSparseD, {axisZPv, axisMult}, true); + histos.add("reco/info/h1_occupancy", "h1_occupancy", kTH1D, {axisOccupancy}, true); + + // reco (correlation) analysis + histos.add("reco/info/h2_zPvMult_trigEv", "h2_zPvMult_trigEv", kTHnSparseD, {axisZPv, axisMult}, true); + histos.add("reco/info/h1_occupancy_trigEv", "h1_occupancy_trigEv", kTH1D, {axisOccupancy}, true); + histos.add("reco/corr/h3_ptPhiEta_trig", "h3_ptPhiEta_trig", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + + // hadron + histos.add("reco/plain/h3_ptPhiEta_hadron", "h3_ptPhiEta_hadron", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add("reco/corr/h3_ptPhiEta_assoc_hadron", "h3_ptPhiEta_assoc_hadron", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add("reco/corr/h6_corr_hadron", "h6_corr_hadron", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/corr/h6_mix_hadron", "h6_mix_hadron", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + // pipm + histos.add("reco/plain/h3_ptPhiEta_pipm", "h3_ptPhiEta_pipm", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add("reco/corr/h3_ptPhiEta_assoc_pipm", "h3_ptPhiEta_assoc_pipm", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add("reco/corr/h6_corr_pipm", "h6_corr_pipm", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/corr/h6_mix_pipm", "h6_mix_pipm", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + // photonPCM + histos.add("reco/plain/h3_ptPhiEta_photonPCM", "h3_ptPhiEta_photonPCM", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add("reco/corr/h3_ptPhiEta_assoc_photonPCM", "h3_ptPhiEta_assoc_photonPCM", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add("reco/corr/h6_corr_photonPCM", "h6_corr_photonPCM", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/corr/h6_mix_photonPCM", "h6_mix_photonPCM", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + // photonPCM pairs + histos.add("reco/plain/h4_ptMggZPvMult_photonPCMPair", "h4_ptMggZPvMult_photonPCMPair", kTHnSparseD, {axisPtAssoc, axisMgg, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/plain/h3_ptPhiEta_pi0PCMPeak", "h3_ptPhiEta_pi0PCMPeak", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add("reco/corr/h4_ptMggZPvMult_assoc_photonPCMPair", "h4_ptMggZPvMult_assoc_photonPCMPair", kTHnSparseD, {axisPtAssoc, axisMgg, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/corr/h3_ptPhiEta_assoc_pi0PCMPeak", "h3_ptPhiEta_assoc_pi0PCMPeak", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + // peak (mgg) + histos.add("reco/corr/h6_corr_pi0PCMPeak", "h6_corr_pi0PCMPeak", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/corr/h6_mix_pi0PCMPeak", "h6_mix_pi0PCMPeak", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + // side (mgg) + histos.add("reco/corr/h6_corr_pi0PCMSide", "h6_corr_pi0PCMSide", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/corr/h6_mix_pi0PCMSide", "h6_mix_pi0PCMSide", + kTHnSparseF, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc, axisZPvBinning, axisMultBinning}, true); + // event mixing for photon pairs + histos.add("reco/plain/h2_zPvMult_photonPCMPair_evMix", "h2_zPvMult_photonPCMPair_evMix", kTHnSparseD, {axisZPv, axisMult}, true); + histos.add("reco/plain/h4_ptMggZPvMult_photonPCMPair_evMix", "h4_ptMggZPvMult_photonPCMPair_evMix", kTHnSparseD, {axisPtAssoc, axisMgg, axisZPvBinning, axisMultBinning}, true); + histos.add("reco/plain/h3_ptPhiEta_pi0PCMPeak_evMix", "h3_ptPhiEta_pi0PCMPeak_evMix", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + + // mc info + histos.add("mc/info/h1_nEvents_mcTrue", "h1_nEvents_mcTrue", kTH1D, {axisN}); + histos.add("mc/info/h1_nTriggerEvents_mcTrue", "h1_nTriggerEvents_mcTrue", kTH1D, {axisN}); + + histos.add("mc/info/h1_zPv_mcTrue", "h1_zPv_mcTrue", kTH1D, {axisZPv}, true); + histos.add("mc/info/h1_mult_mcTrue", "h1_mult_mcTrue", kTH1D, {axisMult}, true); + + // reco and true collision correlations + for (auto const& collision_type : {"true", "true_reco"}) { + histos.add(std::format("mc/{}/corr/h3_ptPhiEta_trig", collision_type).data(), "h3_ptPhiEta_trig", kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + // hadron + histos.add(std::format("mc/{}/corr/h3_ptPhiEta_assoc_hadron", collision_type).data(), "h3_ptPhiEta_assoc_hadron", + kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add(std::format("mc/{}/corr/h4_corr_hadron", collision_type).data(), "h4_corr_hadron", + kTHnSparseD, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc}, true); + // pipm + histos.add(std::format("mc/{}/corr/h3_ptPhiEta_assoc_pipm", collision_type).data(), "h3_ptPhiEta_assoc_pipm", + kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add(std::format("mc/{}/corr/h4_corr_pipm", collision_type).data(), "h4_corr_pipm", + kTHnSparseD, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc}, true); + // photon + histos.add(std::format("mc/{}/corr/h3_ptPhiEta_assoc_photon", collision_type).data(), "h3_ptPhiEta_assoc_photon", + kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add(std::format("mc/{}/corr/h4_corr_photon", collision_type).data(), "h4_corr_photon", + kTHnSparseD, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc}, true); + // pi0 + histos.add(std::format("mc/{}/corr/h3_ptPhiEta_assoc_pi0", collision_type).data(), "h3_ptPhiEta_assoc_pi0", + kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add(std::format("mc/{}/corr/h4_corr_pi0", collision_type).data(), "h4_corr_pi0", + kTHnSparseD, {axisDPhi, axisDEta, axisPtTrig, axisPtAssoc}, true); + } + + // mc efficiency/purity + std::function add_effHists = + [&](std::string name_id) { + histos.add(std::format("mc/eff/h3_ptPhiEta_{}", name_id).data(), "h3_ptPhiEta_mcReco_hadron", + kTHnSparseD, {axisPtAssoc, axisPhi, axisEta}, true); + histos.add(std::format("mc/eff/h3_ptZPvMult_{}", name_id).data(), "h3_ptZPvMult_mcReco_hadron", + kTHnSparseD, {axisPtAssoc, axisZPvSmol, axisMultSmol}, true); + }; + // mc tracks + add_effHists("mcReco_hadron"); + add_effHists("mcReco_hasCorrectMc_hadron"); + add_effHists("mcTrue_hadron"); + add_effHists("mcTrue_recoCol_hadron"); + // mc pipm PID + add_effHists("mcReco_pipm"); + add_effHists("mcReco_hasCorrectMc_pipm"); + add_effHists("mcTrue_pipm"); + add_effHists("mcTrue_recoCol_pipm"); + // mc photonPCM + add_effHists("mcReco_photonPCM"); + add_effHists("mcReco_hasCorrectMc_photonPCM"); + add_effHists("mcTrue_photon"); + add_effHists("mcTrue_recoCol_photon"); + // mc pi0PCM + add_effHists("mcReco_pi0PCM"); + add_effHists("mcReco_hasCorrectMc_pi0PCM"); + add_effHists("mcTrue_pi0"); + add_effHists("mcTrue_recoCol_pi0"); + + // test of the test while testing another test. featuring a test + histos.add("test/h2_mult_comp", "h2_mult_comp", kTH2D, {axisMult, axisMult}, true); + histos.add("test/h2_tracks_zPvMultDep", "h2_tracks_zPvMultDep", kTH2D, {axisZPv, axisMult}, true); + histos.add("test/h2_globalTracks_zPvMultDep", "h2_globalTracks_zPvMultDep", kTH2D, {axisZPv, axisMult}, true); + } + + // selections /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // checks if mcParticle is charged + template + bool checkChargedMc(T_mcParticle const& mcParticle) + { + auto const pdgParticle = pdg->GetParticle(mcParticle.pdgCode()); + if (!pdgParticle || pdgParticle->Charge() == 0) + return false; + return true; + } + // checks if mcParticle should be detected (physicalPrimary, |eta|) + template + bool checkPrimaryEtaMc(T_mcParticle const& mcParticle) + { + if (!mcParticle.isPhysicalPrimary()) + return false; + if (std::abs(mcParticle.eta()) > etaMax) + return false; + return true; + } + // checks if mcParticle should be detected as primary track (physicalPrimary, charge, |eta|) + template + bool checkPrimaryTrackMc(T_mcParticle const& mcParticle) + { + if (!checkPrimaryEtaMc(mcParticle)) + return false; + if (!checkChargedMc(mcParticle)) + return false; + return true; + } + // checks if mcParticle should be detected as 'primary' pi0->gg (|eta| not checked) + template + bool checkPi0ToGG(T_mcParticle const& mcParticle) + { + if (mcParticle.pdgCode() != PDG_t::kPi0) + return false; + // identify primary pi0 (account for 0 daughters for some reason) + if (mcParticle.template daughters_as().size() == 0) + return false; + for (auto const& pi0_daughter : mcParticle.template daughters_as()) { + if (!pi0_daughter.isPhysicalPrimary()) + return false; + } + // select pi0 -> gg + constexpr int NDaughtersPi0ToGG = 2; + if (mcParticle.template daughters_as().size() != NDaughtersPi0ToGG) + return false; + return true; + } + + // analysis helpers ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + template + double getH1ValueAt(T_h1 const* const h1, double const value) + { + return h1->GetBinContent(h1->FindFixBin(value)); + } + // efficiency helpers + // define enum class for particle type + enum class ParticleType { Trigger, + Hadron, + Pipm, + PhotonPCM }; + // efficiency function + template + double getInvEff(double const value) + { + if constexpr (T == ParticleType::Trigger) { + return doEffCorrectionTrigger ? getH1ValueAt(h1PtInvEffTrigger, value) : 1; + } else if constexpr (T == ParticleType::Hadron) { + return doEffCorrectionHadron ? getH1ValueAt(h1PtInvEffHadron, value) : 1; + } else if constexpr (T == ParticleType::Pipm) { + return doEffCorrectionPipm ? getH1ValueAt(h1PtInvEffPipm, value) : 1; + } else if constexpr (T == ParticleType::PhotonPCM) { + return doEffCorrectionPhotonPCM ? getH1ValueAt(h1PtInvEffPhotonPCM, value) : 1; + } else { + return 1; + } + } + + // performs 'phi1 - phi2' and pushes it into the interval [-pi/2, 3pi/2] + inline double getDeltaPhi(double const phi1, double const phi2) + { + return RecoDecay::constrainAngle(phi1 - phi2, -1 * constants::math::PIHalf); + } + + // finds bin that value belongs to (assumes ordered bins) (starts at 0; includes underflow (return -1) and overlflow (return bins.size() - 1)) + // should be faster than some std binary search due to small number of bins (zPv, mult) + int findIntervalBin(double value, const std::vector& bins) + { + const int n = bins.size() - 1; + if (value < bins[0]) + return -1; // underflow + for (int i_bin = 0; i_bin < n; i_bin++) + if (value < bins[i_bin + 1]) + return i_bin; + return n; // overflow + } + + // checks that two values belong to the same category (assumes ordered bins) + // returns -1 for negative result (also for under/overflow values) and bin number (starting at 0) otherwise + int checkSameBin(double const value1, double const value2, std::vector const& bins) + { + // reject underflow + if (value1 < bins[0]) + return -1; + // loop over bins + const int n = bins.size() - 1; + for (int i_bin = 0; i_bin < n; i_bin++) { + if (value1 < bins[i_bin + 1]) { + if (value2 < bins[i_bin + 1] && value2 >= bins[i_bin]) { + return i_bin; + } + return -1; + } + } + // reject overflow + return -1; + } + + // analysis ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // generalised correlation functions + // per collision + + // plain info + template + void corrProcessPlain(T_collision const& collision, T_associatedThisEvent const& associatedThisEvent, + T_funcPlain&& funcPlain) + { + // normal spectra (per event - not per trigger) + for (auto const& associated : associatedThisEvent) { + funcPlain(collision, associated); + } + } + + // correlation + template + void corrProcessCorrelation(T_collision const& collision, T_triggersThisEvent const& triggersThisEvent, T_associatedThisEvent const& associatedThisEvent, + T_funcCorrelation&& funcCorrelation) + { + // correlation combinations + for (auto const& [trigger, associated] : soa::combinations(soa::CombinationsFullIndexPolicy(triggersThisEvent, associatedThisEvent))) { + funcCorrelation(collision, trigger, associated); + } + } + + // mixing + template + void corrProcessMixing(T_collision const& collision, T_associatedThisEvent const& associatedThisEvent, + T_funcMixing&& funcMixing, + size_t const nTriggerMixing) + { + // skip if event does not contain valid trigger + if (doTrigEvMixing && !collision.trigEv()) + return; + + // mixing loops (more efficient than O2 mixing (for now)) + // prepare zPv-mult binned saved triggers + const int iBinCorrZPv = findIntervalBin(collision.posZ(), triggerBinValuesZPv); + const int iBinCorrMult = findIntervalBin(collision.multNTracksGlobal(), triggerBinValuesMult); + auto const& savedTriggersPt = savedTriggersZPvMultPt[iBinCorrZPv][iBinCorrMult]; + auto const& savedTriggersPhi = savedTriggersZPvMultPhi[iBinCorrZPv][iBinCorrMult]; + auto const& savedTriggersEta = savedTriggersZPvMultEta[iBinCorrZPv][iBinCorrMult]; + // number of triggers + const int mixUpToTriggerN = std::min(savedTriggersPt.size(), nTriggerMixing + nTriggersThisDataFrame); + const float perTriggerWeight = 1. / (mixUpToTriggerN - nTriggersThisDataFrame); // mixUpToTriggerN <= nTriggersThisDataFrame not problematic since no loop then + // mixing loops + for (int i_mixingTrigger = nTriggersThisDataFrame; i_mixingTrigger < mixUpToTriggerN; i_mixingTrigger++) { + for (auto const& associated : associatedThisEvent) { + funcMixing(collision, savedTriggersPt[i_mixingTrigger], savedTriggersPhi[i_mixingTrigger], savedTriggersEta[i_mixingTrigger], associated, perTriggerWeight); + } + } + } + + void init(InitContext& initContext) + { + // analysis info + ccdb->setURL(urlCcdb.value); + // enabling object caching (otherwise each call goes to CCDB server) + ccdb->setCaching(true); + // ccdb->setLocalObjectValidityChecking(); + // not later than now, will be replaced by the value of train creation (avoids replacing objects while a train is running) + ccdb->setCreatedNotAfter(noLaterThanCcdb.value); + + // init analysis variables + + // get variabels from other tasks + getTaskOptionValue(initContext, "correlation-table-producer", "etaMax", etaMax, false); + + // mixing trigger memory + triggerBinValuesZPv = binsZPv; + triggerBinValuesMult = binsMult; + // prevent rounding errors in bin finding (multiplicity accounted for by it going to 0 and already considering overflow separately) + triggerBinValuesZPv.front() *= 1.0001; + triggerBinValuesZPv.back() *= 1.0001; + // init correct size of zPv-mult matrix + savedTriggersZPvMultPt.resize(binsZPv.value.size() - 1); + savedTriggersZPvMultPhi.resize(binsZPv.value.size() - 1); + savedTriggersZPvMultEta.resize(binsZPv.value.size() - 1); + for (size_t i_zPv = 0; i_zPv < binsZPv.value.size() - 1; i_zPv++) { + savedTriggersZPvMultPt[i_zPv].resize(binsMult.value.size()); + savedTriggersZPvMultPhi[i_zPv].resize(binsMult.value.size()); + savedTriggersZPvMultEta[i_zPv].resize(binsMult.value.size()); + } + + // histograms from ccdb + initCcdbHistograms(); + + // create analysis histograms + initHistograms(); + } + + // reconstructed //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void processInfo(CorrCollision const& collision) + { + // trigger events + if (collision.trigEv()) { + histos.fill(HIST("reco/info/h1_nEvents"), 2.5); + } + + // event selection + histos.fill(HIST("reco/info/h1_nEvents"), 1.5); + if (!collision.selEv()) + return; + histos.fill(HIST("reco/info/h1_nEvents"), 0.5); + + // QA + histos.fill(HIST("reco/info/h2_zPvMult"), collision.posZ(), collision.multNTracksGlobal()); + histos.fill(HIST("reco/info/h1_occupancy"), collision.trackOccupancyInTimeRange()); + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processInfo, "process general info on collisions and tracks for analysis and qa", false); + + void processCorrFirst(CorrCollisions const& collisions, aod::Triggers const& triggers) + { + // do at beginning of each data frame (before other correlation process functions) + // (PROCESS_SWITCH of this process has to be declared first) + + // set trigger counter + nTriggersThisDataFrame = triggers.size(); + + for (auto const& collision : collisions) { + // event selection + if (!collision.selEv()) + continue; + + // group collision + auto const triggersThisEvent = triggers.sliceBy(perColTriggers, collision.globalIndex()); + + // trigger loop + for (auto const& trigger : triggersThisEvent) { + // trigger info + histos.fill(HIST("reco/corr/h3_ptPhiEta_trig"), trigger.pt(), trigger.phi(), trigger.eta(), + getInvEff(trigger.pt())); + + // save triggers for mixing + const int iBinCorrZPv = findIntervalBin(collision.posZ(), triggerBinValuesZPv); + const int iBinCorrMult = findIntervalBin(collision.multNTracksGlobal(), triggerBinValuesMult); + // special cases (floating point precision errors, mult overflow) should be taken care of by triggerBinValuesZPv and triggerBinValuesMult + savedTriggersZPvMultPt[iBinCorrZPv][iBinCorrMult].push_front(trigger.pt()); + savedTriggersZPvMultPhi[iBinCorrZPv][iBinCorrMult].push_front(trigger.phi()); + savedTriggersZPvMultEta[iBinCorrZPv][iBinCorrMult].push_front(trigger.eta()); + if (static_cast(savedTriggersZPvMultPt[iBinCorrZPv][iBinCorrMult].size()) > nTriggerSavedForMixing) { + savedTriggersZPvMultPt[iBinCorrZPv][iBinCorrMult].pop_back(); + savedTriggersZPvMultPhi[iBinCorrZPv][iBinCorrMult].pop_back(); + savedTriggersZPvMultEta[iBinCorrZPv][iBinCorrMult].pop_back(); + } + } + + // trigger event info + if (collision.trigEv()) { + histos.fill(HIST("reco/info/h2_zPvMult_trigEv"), collision.posZ(), collision.multNTracksGlobal()); + histos.fill(HIST("reco/info/h1_occupancy_trigEv"), collision.trackOccupancyInTimeRange()); + } + } + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processCorrFirst, "process to gather info before correlation processes", false); + + void processCorrHadron(CorrCollision const& collision, aod::Triggers const& triggers, aod::Hadrons const& hadrons) + { + // event selection + if (!collision.selEv()) + return; + + auto const funcPlain = [this]([[maybe_unused]] auto const& collision, auto const& associated) { + histos.fill(HIST("reco/plain/h3_ptPhiEta_hadron"), + associated.pt(), associated.phi(), associated.eta(), + getInvEff(associated.pt())); + }; + corrProcessPlain(collision, hadrons, funcPlain); + + auto const funcCorrelation = [this](auto const& collision, auto const& trigger, auto const& associated) { + // exclude self correlation + if (trigger.jetTrackId() == associated.jetTrackId()) + return; + + histos.fill(HIST("reco/corr/h3_ptPhiEta_assoc_hadron"), + associated.pt(), associated.phi(), associated.eta(), + getInvEff(trigger.pt()) * getInvEff(associated.pt())); + histos.fill(HIST("reco/corr/h6_corr_hadron"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + getInvEff(trigger.pt()) * getInvEff(associated.pt())); + }; + corrProcessCorrelation(collision, triggers, hadrons, funcCorrelation); + + auto const funcMixing = [this](auto const& collision, + float const mixingTriggerPt, float const mixingTriggerPhi, float const mixingTriggerEta, auto const& associated, auto const perTriggerWeight) { + histos.fill(HIST("reco/corr/h6_mix_hadron"), + getDeltaPhi(mixingTriggerPhi, associated.phi()), + mixingTriggerEta - associated.eta(), + mixingTriggerPt, associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + perTriggerWeight * getInvEff(mixingTriggerPt) * getInvEff(associated.pt())); + }; + corrProcessMixing(collision, hadrons, funcMixing, nTriggerMixingHadron); + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processCorrHadron, "process standard correlation for associated hardons", false); + + void processCorrPipm(CorrCollision const& collision, aod::Triggers const& triggers, aod::Pipms const& pipms) + { + // event selection + if (!collision.selEv()) + return; + + auto const funcPlain = [this]([[maybe_unused]] auto const& collision, auto const& associated) { + histos.fill(HIST("reco/plain/h3_ptPhiEta_pipm"), + associated.pt(), associated.phi(), associated.eta(), + getInvEff(associated.pt())); + }; + corrProcessPlain(collision, pipms, funcPlain); + + auto const funcCorrelation = [this](auto const& collision, auto const& trigger, auto const& associated) { + // exclude self correlation + if (trigger.jetTrackId() == associated.jetTrackId()) + return; + + histos.fill(HIST("reco/corr/h3_ptPhiEta_assoc_pipm"), + associated.pt(), associated.phi(), associated.eta(), + getInvEff(trigger.pt()) * getInvEff(associated.pt())); + histos.fill(HIST("reco/corr/h6_corr_pipm"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + getInvEff(trigger.pt()) * getInvEff(associated.pt())); + }; + corrProcessCorrelation(collision, triggers, pipms, funcCorrelation); + + auto const funcMixing = [this](auto const& collision, + float const mixingTriggerPt, float const mixingTriggerPhi, float const mixingTriggerEta, auto const& associated, auto const perTriggerWeight) { + histos.fill(HIST("reco/corr/h6_mix_pipm"), + getDeltaPhi(mixingTriggerPhi, associated.phi()), + mixingTriggerEta - associated.eta(), + mixingTriggerPt, associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + perTriggerWeight * getInvEff(mixingTriggerPt) * getInvEff(associated.pt())); + }; + corrProcessMixing(collision, pipms, funcMixing, nTriggerMixingPipm); + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processCorrPipm, "process standard correlation for associated pipm", false); + + void processCorrPhotonPCM(CorrCollision const& collision, aod::Triggers const& triggers, aod::PhotonPCMs const& photonPCMs) + { + // event selection + if (!collision.selEv()) + return; + + auto const funcPlain = [this]([[maybe_unused]] auto const& collision, auto const& associated) { + histos.fill(HIST("reco/plain/h3_ptPhiEta_photonPCM"), + associated.pt(), associated.phi(), associated.eta(), + getInvEff(associated.pt())); + }; + corrProcessPlain(collision, photonPCMs, funcPlain); + + auto const funcCorrelation = [this](auto const& collision, auto const& trigger, auto const& associated) { + // exclude self correlation + if (trigger.jetTrackId() == associated.posTrackId() || trigger.jetTrackId() == associated.negTrackId()) + return; + + histos.fill(HIST("reco/corr/h3_ptPhiEta_assoc_photonPCM"), + associated.pt(), associated.phi(), associated.eta(), + getInvEff(trigger.pt()) * getInvEff(associated.pt())); + histos.fill(HIST("reco/corr/h6_corr_photonPCM"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + getInvEff(trigger.pt()) * getInvEff(associated.pt())); + }; + corrProcessCorrelation(collision, triggers, photonPCMs, funcCorrelation); + + auto const funcMixing = [this](auto const& collision, + float const mixingTriggerPt, float const mixingTriggerPhi, float const mixingTriggerEta, auto const& associated, auto const perTriggerWeight) { + histos.fill(HIST("reco/corr/h6_mix_photonPCM"), + getDeltaPhi(mixingTriggerPhi, associated.phi()), + mixingTriggerEta - associated.eta(), + mixingTriggerPt, associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + perTriggerWeight * getInvEff(mixingTriggerPt) * getInvEff(associated.pt())); + }; + corrProcessMixing(collision, photonPCMs, funcMixing, nTriggerMixingPhotonPCM); + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processCorrPhotonPCM, "process standard correlation for associated photonPCM", false); + + void processCorrPi0PCM(CorrCollision const& collision, aod::Triggers const& triggers, aod::PhotonPCMPairs const& photonPCMPairs) + { + // event selection + if (!collision.selEv()) + return; + + auto const funcPlain = [this](auto const& collision, auto const& associated) { + histos.fill(HIST("reco/plain/h4_ptMggZPvMult_photonPCMPair"), associated.pt(), associated.mgg(), collision.posZ(), collision.multNTracksGlobal()); + // pi0 mass range + if (associated.mgg() > pi0PCMMassRange.value[0] && associated.mgg() < pi0PCMMassRange.value[1]) { + histos.fill(HIST("reco/plain/h3_ptPhiEta_pi0PCMPeak"), associated.pt(), associated.phi(), associated.eta()); + } + }; + corrProcessPlain(collision, photonPCMPairs, funcPlain); + + auto const funcCorrelation = [this](auto const& collision, auto const& trigger, auto const& associated) { + // exclude self correlation + if (trigger.jetTrackId() == associated.posTrack1Id() || trigger.jetTrackId() == associated.negTrack1Id() || + trigger.jetTrackId() == associated.negTrack2Id() || trigger.jetTrackId() == associated.posTrack2Id()) + return; + + histos.fill(HIST("reco/corr/h4_ptMggZPvMult_assoc_photonPCMPair"), + associated.pt(), associated.mgg(), collision.posZ(), collision.multNTracksGlobal(), + getInvEff(trigger.pt())); + + if (associated.mgg() > pi0PCMMassRange.value[0] && associated.mgg() < pi0PCMMassRange.value[1]) { + // pi0 mass range + histos.fill(HIST("reco/corr/h3_ptPhiEta_assoc_pi0PCMPeak"), + associated.pt(), associated.phi(), associated.eta(), + getInvEff(trigger.pt())); + histos.fill(HIST("reco/corr/h6_corr_pi0PCMPeak"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + getInvEff(trigger.pt())); + } else if (associated.mgg() > pi0PCMSideMassRange.value[0] && associated.mgg() < pi0PCMSideMassRange.value[1]) { + // pi0 mass side range + histos.fill(HIST("reco/corr/h6_corr_pi0PCMSide"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + getInvEff(trigger.pt())); + } + }; + corrProcessCorrelation(collision, triggers, photonPCMPairs, funcCorrelation); + + auto const funcMixing = [this](auto const& collision, + float const mixingTriggerPt, float const mixingTriggerPhi, float const mixingTriggerEta, auto const& associated, auto const perTriggerWeight) { + if (associated.mgg() > pi0PCMMassRange.value[0] && associated.mgg() < pi0PCMMassRange.value[1]) { + // pi0 mass range + histos.fill(HIST("reco/corr/h6_mix_pi0PCMPeak"), + getDeltaPhi(mixingTriggerPhi, associated.phi()), + mixingTriggerEta - associated.eta(), + mixingTriggerPt, associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + perTriggerWeight * getInvEff(mixingTriggerPt)); + } else if (associated.mgg() > pi0PCMSideMassRange.value[0] && associated.mgg() < pi0PCMSideMassRange.value[1]) { + // pi0 mass side range + histos.fill(HIST("reco/corr/h6_mix_pi0PCMSide"), + getDeltaPhi(mixingTriggerPhi, associated.phi()), + mixingTriggerEta - associated.eta(), + mixingTriggerPt, associated.pt(), collision.posZ(), collision.multNTracksGlobal(), + perTriggerWeight * getInvEff(mixingTriggerPt)); + } + }; + corrProcessMixing(collision, photonPCMPairs, funcMixing, nTriggerMixingPi0PCM); + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processCorrPi0PCM, "process standard correlation for associated pi0PCM", false); + + void processCorrPi0PCMMix(CorrCollisions const& collisions, aod::PhotonPCMs const& photonPCMs) + { + auto photonPCMsTuple = std::make_tuple(photonPCMs); + SameKindPair pairs{binningZPvMult, nNeighboursMixingPi0PCMPair, -1, collisions, photonPCMsTuple, &cache}; + + // mixed events + for (auto pair = pairs.begin(); pair != pairs.end(); pair++) { + auto const& [collision1, photonPCMs1, collision2, photonPCMs2] = *pair; + + // // check that current und mixing-trigger event are from the same zPv/mult bins + // if (checkSameBin(collision1.posZ(), collision2.posZ(), binsZPv) == -1) { + // std::printf("ERROR: zPv bins do not match\n"); continue; + // } + // if (checkSameBin(collision1.multNTracksGlobal(), collision2.multNTracksGlobal(), binsMult) == -1) { + // std::printf("ERROR: multiplicity bins do not match\n"); continue; + // } + + // event selection + if (!collision1.selEv()) + continue; + if (!collision2.selEv()) + continue; + + // event info + histos.fill(HIST("reco/plain/h2_zPvMult_photonPCMPair_evMix"), collision1.posZ(), collision1.multNTracksGlobal()); + + // mixing loop + for (auto const& [photonPCM1, photonPCM2] : soa::combinations(soa::CombinationsFullIndexPolicy(photonPCMs1, photonPCMs2))) { + ROOT::Math::PtEtaPhiMVector const p4photonPCM1(photonPCM1.pt(), photonPCM1.eta(), photonPCM1.phi(), 0.); + ROOT::Math::PtEtaPhiMVector const p4photonPCM2(photonPCM2.pt(), photonPCM2.eta(), photonPCM2.phi(), 0.); + ROOT::Math::PtEtaPhiMVector const p4photonPCMPair = p4photonPCM1 + p4photonPCM2; + + // plain + histos.fill(HIST("reco/plain/h4_ptMggZPvMult_photonPCMPair_evMix"), p4photonPCMPair.pt(), p4photonPCMPair.M(), collision1.posZ(), collision1.multNTracksGlobal()); + // pi0 mass range + if (p4photonPCMPair.M() > pi0PCMMassRange.value[0] && p4photonPCMPair.M() < pi0PCMMassRange.value[1]) { + histos.fill(HIST("reco/plain/h3_ptPhiEta_pi0PCMPeak_evMix"), p4photonPCMPair.pt(), p4photonPCMPair.phi() + constants::math::PI, p4photonPCMPair.eta()); + } + } + } + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processCorrPi0PCMMix, "process gamma-gamma mixing for photonPCM", false); + + // mc /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void processMcInfo(CorrMcCollision const& mcCollision) + { + // event counter + histos.fill(HIST("mc/info/h1_nEvents_mcTrue"), 0.5); + // trigger events + if (mcCollision.trigEv()) { + histos.fill(HIST("mc/info/h1_nTriggerEvents_mcTrue"), 0.5); + } + + // QA + histos.fill(HIST("mc/info/h1_zPv_mcTrue"), mcCollision.posZ()); + histos.fill(HIST("mc/info/h1_mult_mcTrue"), mcCollision.multMCNParticlesEta08()); + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processMcInfo, "process general info on mc collisions and tracks for analysis and qa", false); + + void processMcTrueCorr(CorrMcCollision const&, aod::TriggerParticles const& triggerParticles, aod::JetParticles const& mcParticles) + { + // trigger pairing loop + for (auto const& trigger : triggerParticles) { + // trigger info + histos.fill(HIST("mc/true/corr/h3_ptPhiEta_trig"), trigger.pt(), trigger.phi(), trigger.eta()); + + // hadrons (tracks) and pipm + for (auto const& associated : mcParticles) { + // exclude self correlation + if (trigger.jetMcParticleId() == associated.globalIndex()) + continue; + + // standard particles (marked physical primary) + if (checkPrimaryEtaMc(associated)) { + // charged primary ('hadron') selection + if (checkChargedMc(associated)) { + histos.fill(HIST("mc/true/corr/h3_ptPhiEta_assoc_hadron"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true/corr/h4_corr_hadron"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + + // pipm selection + if (std::abs(associated.pdgCode()) == PDG_t::kPiPlus) { + histos.fill(HIST("mc/true/corr/h3_ptPhiEta_assoc_pipm"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true/corr/h4_corr_pipm"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + + // photon selection + if (associated.pdgCode() == PDG_t::kGamma) { + histos.fill(HIST("mc/true/corr/h3_ptPhiEta_assoc_photon"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true/corr/h4_corr_photon"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + } + + // decaying particles (not marked physical primary) + if ((std::abs(associated.eta()) < etaMax)) { + // pi0 selection + if (checkPi0ToGG(associated)) { + histos.fill(HIST("mc/true/corr/h3_ptPhiEta_assoc_pi0"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true/corr/h4_corr_pi0"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + } + } + } + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processMcTrueCorr, "process mc-true (all collisions) correlation for multiple associated particles", false); + + void processMcTrueRecoColCorr(CorrMcDCollision const& collision, aod::JetMcCollisions const&, aod::TriggerParticles const& triggerParticles, aod::JetParticles const& mcParticles) + { + // event selection + if (!collision.selEv()) + return; + + // group collision + auto const triggerParticlesThisEvent = triggerParticles.sliceBy(perColTriggerParticles, collision.mcCollisionId()); + auto const mcParticlesThisEvent = mcParticles.sliceBy(perColMcParticles, collision.mcCollisionId()); + + // trigger pairing loop + for (auto const& trigger : triggerParticlesThisEvent) { + // trigger info + histos.fill(HIST("mc/true_reco/corr/h3_ptPhiEta_trig"), trigger.pt(), trigger.phi(), trigger.eta()); + + // hadrons (tracks) and pipm + for (auto const& associated : mcParticlesThisEvent) { + // exclude self correlation + if (trigger.jetMcParticleId() == associated.globalIndex()) + continue; + + // standard particles (marked physical primary) + if (checkPrimaryEtaMc(associated)) { + // charged primary ('hadron') selection + if (checkChargedMc(associated)) { + histos.fill(HIST("mc/true_reco/corr/h3_ptPhiEta_assoc_hadron"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true_reco/corr/h4_corr_hadron"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + + // pipm selection + if (std::abs(associated.pdgCode()) == PDG_t::kPiPlus) { + histos.fill(HIST("mc/true_reco/corr/h3_ptPhiEta_assoc_pipm"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true_reco/corr/h4_corr_pipm"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + + // photon selection + if (associated.pdgCode() == PDG_t::kGamma) { + histos.fill(HIST("mc/true_reco/corr/h3_ptPhiEta_assoc_photon"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true_reco/corr/h4_corr_photon"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + } + + // decaying particles (not marked physical primary) + if ((std::abs(associated.eta()) < etaMax)) { + // pi0 selection + if (checkPi0ToGG(associated)) { + histos.fill(HIST("mc/true_reco/corr/h3_ptPhiEta_assoc_pi0"), associated.pt(), associated.phi(), associated.eta()); + histos.fill(HIST("mc/true_reco/corr/h4_corr_pi0"), + getDeltaPhi(trigger.phi(), associated.phi()), + trigger.eta() - associated.eta(), + trigger.pt(), associated.pt()); + } + } + } + } + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processMcTrueRecoColCorr, "process mc-true (reco collisions) correlation for multiple associated particles", false); + + void processMcTrueEff(CorrMcCollision const& mcCollision, aod::JetParticles const& mcParticles) + { + // event selection + if (doTrigEvEff && !mcCollision.trigEv()) + return; + + for (auto const& mcParticle : mcParticles) { + // standard particles (marked physical primary) + if (checkPrimaryEtaMc(mcParticle)) { + // hadrons + if (checkChargedMc(mcParticle)) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_hadron"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_hadron"), mcParticle.pt(), mcCollision.posZ(), mcCollision.multMCNParticlesEta08()); + } + // pipm + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_pipm"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_pipm"), mcParticle.pt(), mcCollision.posZ(), mcCollision.multMCNParticlesEta08()); + } + // photons + if (mcParticle.pdgCode() == PDG_t::kGamma) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_photon"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_photon"), mcParticle.pt(), mcCollision.posZ(), mcCollision.multMCNParticlesEta08()); + } + } + + // decaying particles (not marked physical primary) + if ((std::abs(mcParticle.eta()) < etaMax)) { + // pi0 + if (checkPi0ToGG(mcParticle)) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_pi0"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_pi0"), mcParticle.pt(), mcCollision.posZ(), mcCollision.multMCNParticlesEta08()); + } + } + } + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processMcTrueEff, "process MC-true data (all collisions) to calculate efficiencies", false); + + void processMcRecoColEff(CorrMcDCollision const& collision, aod::JetMcCollisions const&, aod::JetTracksMCD const& tracks, + aod::Triggers const& triggers, aod::Hadrons const& hadrons, aod::Pipms const& pipms, + aod::PhotonPCMs const& photonPCMs, aod::PhotonPCMPairs const& photonPCMPairs, + aod::JetParticles const& mcParticles) + { + int excludeTriggerTrackId = -1; + int excludeTriggerParticleId = -1; + + // event selection + if (!collision.selEv()) + return; + if (doTrigEvEff && !collision.trigEv()) + return; + + auto const mcParticlesThisEvent = mcParticles.sliceBy(perColMcParticles, collision.mcCollisionId()); + + // random trigger + if (doTrigEvEff) { + std::uniform_int_distribution intDistribution(0, static_cast(triggers.size()) - 1); + auto const& excludeTrigger = triggers.rawIteratorAt(intDistribution(randomEngine)); + if (excludeTrigger.jetTrack_as().has_mcParticle()) { + excludeTriggerParticleId = excludeTrigger.jetTrack_as().mcParticleId(); + excludeTriggerTrackId = excludeTrigger.jetTrack_as().globalIndex(); + } + } + + // hadrons + for (auto const& hadron : hadrons) { + if (doTrigEvEff && hadron.jetTrackId() == excludeTriggerTrackId) + continue; + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_hadron"), hadron.pt(), hadron.phi(), hadron.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_hadron"), hadron.pt(), collision.posZ(), collision.multNTracksGlobal()); + // purity + if (!hadron.jetTrack_as().has_mcParticle()) + continue; + auto const hadronParticle = hadron.jetTrack_as().mcParticle(); + if (!checkPrimaryTrackMc(hadronParticle)) + continue; + if (requireSingleCollisionPurity && hadronParticle.mcCollisionId() != collision.mcCollisionId()) + continue; + + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_hasCorrectMc_hadron"), hadron.pt(), hadron.phi(), hadron.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_hasCorrectMc_hadron"), hadron.pt(), collision.posZ(), collision.multNTracksGlobal()); + } + + // pipm + for (auto const& pipm : pipms) { + if (doTrigEvEff && pipm.jetTrackId() == excludeTriggerTrackId) + continue; + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_pipm"), pipm.pt(), pipm.phi(), pipm.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_pipm"), pipm.pt(), collision.posZ(), collision.multNTracksGlobal()); + // purity + if (!pipm.jetTrack_as().has_mcParticle()) + continue; + auto const pipmParticle = pipm.jetTrack_as().mcParticle(); + if (std::abs(pipmParticle.pdgCode()) != PDG_t::kPiPlus || !checkPrimaryEtaMc(pipmParticle)) + continue; + if (requireSingleCollisionPurity && pipmParticle.mcCollisionId() != collision.mcCollisionId()) + continue; + + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_hasCorrectMc_pipm"), pipm.pt(), pipm.phi(), pipm.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_hasCorrectMc_pipm"), pipm.pt(), collision.posZ(), collision.multNTracksGlobal()); + } + + // photon mc checks + + auto const isConversionPhoton = [&](auto const& posTrack, auto const& negTrack) { + // check same mother + auto const& posMothers = posTrack.mcParticle().template mothers_as(); + auto const& negMothers = negTrack.mcParticle().template mothers_as(); + if (posMothers.size() != 1 || negMothers.size() != 1) + return false; + if (posMothers.begin()->globalIndex() != negMothers.begin()->globalIndex()) + return false; + // check photon + if (posMothers.begin()->pdgCode() != PDG_t::kGamma) + return false; + + return true; + }; + auto const isGGFromPi0 = [&](auto const& posTrack1, auto const& negTrack1, auto const& posTrack2, auto const& negTrack2) { + if (!isConversionPhoton(posTrack1, negTrack1) || !isConversionPhoton(posTrack2, negTrack2)) + return false; + // check same mother + auto const& mothers1 = (*(posTrack1.mcParticle().template mothers_as().begin())).template mothers_as(); + auto const& mothers2 = (*(posTrack2.mcParticle().template mothers_as().begin())).template mothers_as(); + constexpr int NMothersPhotonFromPi0 = 2; // for some reason two mothers (same particle) for pi0 decays (contradicts PYTHIA documentation, but whatever) + if (mothers1.size() != NMothersPhotonFromPi0 || mothers2.size() != NMothersPhotonFromPi0) + return false; + if (mothers1.begin()->globalIndex() != mothers2.begin()->globalIndex()) + return false; + // check pi0 + if (mothers1.begin()->pdgCode() != PDG_t::kPi0) + return false; + + return true; + }; + + // photonPCM + for (auto const& photonPCM : photonPCMs) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_photonPCM"), photonPCM.pt(), photonPCM.phi(), photonPCM.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_photonPCM"), photonPCM.pt(), collision.posZ(), collision.multNTracksGlobal()); + + // purity + // (V0Legs does not have the tracks reference as index column (just int)??) + auto const& posTrack = tracks.rawIteratorAt(photonPCM.posTrackId() - tracks.offset()); + auto const& negTrack = tracks.rawIteratorAt(photonPCM.negTrackId() - tracks.offset()); + if (!posTrack.has_mcParticle() || !negTrack.has_mcParticle()) + continue; + if (!isConversionPhoton(posTrack, negTrack) || !checkPrimaryEtaMc(*(posTrack.mcParticle().mothers_as().begin()))) + continue; + if (requireSingleCollisionPurity && posTrack.mcParticle().mcCollisionId() != collision.mcCollisionId()) + continue; + + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_hasCorrectMc_photonPCM"), photonPCM.pt(), photonPCM.phi(), photonPCM.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_hasCorrectMc_photonPCM"), photonPCM.pt(), collision.posZ(), collision.multNTracksGlobal()); + } + + // pi0PCM + for (auto const& photonPCMPair : photonPCMPairs) { + if (photonPCMPair.mgg() < pi0PCMMassRange.value[0] || photonPCMPair.mgg() > pi0PCMMassRange.value[1]) + continue; + + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_pi0PCM"), photonPCMPair.pt(), photonPCMPair.phi(), photonPCMPair.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_pi0PCM"), photonPCMPair.pt(), collision.posZ(), collision.multNTracksGlobal()); + + // purity + auto const& posTrack1 = tracks.rawIteratorAt(photonPCMPair.posTrack1Id() - tracks.offset()); + auto const& negTrack1 = tracks.rawIteratorAt(photonPCMPair.negTrack1Id() - tracks.offset()); + auto const& posTrack2 = tracks.rawIteratorAt(photonPCMPair.posTrack2Id() - tracks.offset()); + auto const& negTrack2 = tracks.rawIteratorAt(photonPCMPair.negTrack2Id() - tracks.offset()); + if (!posTrack1.has_mcParticle() || !negTrack1.has_mcParticle() || !posTrack2.has_mcParticle() || !negTrack2.has_mcParticle()) + continue; + if (!isGGFromPi0(posTrack1, negTrack1, posTrack2, negTrack2) || + std::abs((*(posTrack1.mcParticle().mothers_as().begin())).mothers_as().begin()->eta()) > etaMax) + continue; + if (requireSingleCollisionPurity && + (posTrack1.mcParticle().mcCollisionId() != collision.mcCollisionId() || posTrack2.mcParticle().mcCollisionId() != collision.mcCollisionId())) + continue; + + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcReco_hasCorrectMc_pi0PCM"), photonPCMPair.pt(), photonPCMPair.phi(), photonPCMPair.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcReco_hasCorrectMc_pi0PCM"), photonPCMPair.pt(), collision.posZ(), collision.multNTracksGlobal()); + } + + // mcParticle loop + for (auto const& mcParticle : mcParticlesThisEvent) { + // standard particles (marked physical primary) + if (checkPrimaryEtaMc(mcParticle)) { + // hadrons + if (checkChargedMc(mcParticle) && (!doTrigEvEff || mcParticle.globalIndex() != excludeTriggerParticleId)) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_recoCol_hadron"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_recoCol_hadron"), mcParticle.pt(), collision.mcCollision().posZ(), collision.multNTracksGlobal()); + } + // pipm + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus && (!doTrigEvEff || mcParticle.globalIndex() != excludeTriggerParticleId)) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_recoCol_pipm"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_recoCol_pipm"), mcParticle.pt(), collision.mcCollision().posZ(), collision.multNTracksGlobal()); + } + // photons + if (mcParticle.pdgCode() == PDG_t::kGamma) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_recoCol_photon"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_recoCol_photon"), mcParticle.pt(), collision.mcCollision().posZ(), collision.multNTracksGlobal()); + } + } + + // decaying particles (not marked physical primary) + if ((std::abs(mcParticle.eta()) < etaMax)) { + // pi0 + if (checkPi0ToGG(mcParticle)) { + histos.fill(HIST("mc/eff/h3_ptPhiEta_mcTrue_recoCol_pi0"), mcParticle.pt(), mcParticle.phi(), mcParticle.eta()); + histos.fill(HIST("mc/eff/h3_ptZPvMult_mcTrue_recoCol_pi0"), mcParticle.pt(), collision.mcCollision().posZ(), collision.multNTracksGlobal()); + } + } + } + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processMcRecoColEff, "process MC data to calculate efficiencies and purities", false); + + // test ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + void processTest(CorrCollision const& collision, + soa::Join const& tracks, soa::Join const&, + aod::Hadrons const& hadrons) + { + // event selection + if (!collision.selEv()) + return; + + histos.fill(HIST("test/h2_mult_comp"), collision.multNTracksGlobal(), hadrons.size()); + + for (auto const& track : tracks) { + auto const fullTrack = track.track_as>(); + + constexpr float Mincrossedrows = 40; + constexpr float Maxchi2tpc = 5.0; + constexpr float Maxchi2its = 6.0; + constexpr float MaxR = 83.1; + constexpr float MinPtTrackiu = 0.1; + + if (!fullTrack.hasITS() && !fullTrack.hasTPC()) + continue; + if (fullTrack.x() * fullTrack.x() + fullTrack.y() * fullTrack.y() > MaxR * MaxR || fullTrack.pt() < MinPtTrackiu) + continue; + if (fullTrack.hasTPC()) { + if (fullTrack.tpcNClsCrossedRows() < Mincrossedrows || fullTrack.tpcChi2NCl() > Maxchi2tpc) + continue; + } + if (fullTrack.hasITS()) { + if (fullTrack.itsChi2NCl() > Maxchi2its) + continue; + } + + histos.fill(HIST("test/h2_tracks_zPvMultDep"), collision.posZ(), collision.multNTracksGlobal()); + } + + histos.fill(HIST("test/h2_globalTracks_zPvMultDep"), collision.posZ(), collision.multNTracksGlobal(), hadrons.size()); + } + PROCESS_SWITCH(PhotonChargedTriggerCorrelation, processTest, "process just to test things", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& configContext) +{ + return WorkflowSpec{ + adaptAnalysisTask(configContext), + adaptAnalysisTask(configContext)}; +} diff --git a/PWGJE/Tasks/photonIsolationQA.cxx b/PWGJE/Tasks/photonIsolationQA.cxx index 7bac1ce3d5b..1738fef952f 100644 --- a/PWGJE/Tasks/photonIsolationQA.cxx +++ b/PWGJE/Tasks/photonIsolationQA.cxx @@ -9,38 +9,37 @@ // 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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/HistogramRegistry.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" #include "EMCALBase/Geometry.h" #include "EMCALCalib/BadChannelMap.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetDerivedDataUtilities.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 "DataFormatsEMCAL/Cell.h" -#include "DataFormatsEMCAL/Constants.h" -#include "DataFormatsEMCAL/AnalysisCluster.h" -#include "CommonDataFormat/InteractionRecord.h" +#include // \struct PhotonIsolationQA /// \brief Task to select emcal clusters originating from promt photons diff --git a/PWGJE/Tasks/recoilJets.cxx b/PWGJE/Tasks/recoilJets.cxx index f39d1c9fe25..ebf69f44e10 100644 --- a/PWGJE/Tasks/recoilJets.cxx +++ b/PWGJE/Tasks/recoilJets.cxx @@ -1,4 +1,4 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// Copyright 2020-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. // @@ -13,99 +13,138 @@ /// \file recoilJets.cxx /// \brief hadron-jet correlation analysis -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGJE/DataModel/JetSubtraction.h" -#include "TRandom3.h" -#include "TVector2.h" +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Multiplicity.h" +#include "CommonConstants/MathConstants.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "CommonConstants/MathConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/Core/RecoDecay.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "TRandom3.h" +#include +#include -#include "EventFiltering/filterTables.h" +#include +#include +#include +#include +#include +#include using namespace o2; 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 FilteredJets = soa::Filtered>; -using FilteredJetsDetLevel = soa::Filtered>; -using FilteredJetsPartLevel = soa::Filtered>; - -using FilteredMatchedJetsDetLevel = soa::Filtered>; -using FilteredMatchedJetsPartLevel = soa::Filtered>; +using FilteredColl = + soa::Filtered>::iterator; +using FilteredCollPartLevel = + soa::Filtered>::iterator; +using FilteredCollDetLevelGetWeight = + soa::Filtered>::iterator; +using FilteredEventMultiplicity = + 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; struct RecoilJets { // List of configurable parameters Configurable evSel{"evSel", "sel8", "Choose event selection"}; - Configurable trkSel{"trkSel", "globalTracks", "Set track 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 bGetMissJets{"bGetMissJets", false, "Flag to get miss histo for particle level jets"}; + 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 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 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 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.0, "Mean value of FT0A"}; + + Configurable meanFT0C{"meanFT0C", -1.0, "Mean value of FT0C"}; + + Configurable meanFT0M{"meanFT0M", -1.0, "Mean value of FT0M"}; // List of configurable parameters for MC - Configurable pTHatExponent{"pTHatExponent", 4.0, "Exponent of the event weight for the calculation of pTHat"}; - Configurable pTHatMax{"pTHatMax", 999.0, "Maximum fraction of hard scattering for jet acceptance in MC"}; - Configurable pTHatMaxTrack{"pTHatMaxTrack", 999.0, "Maximum fraction of hard scattering for track acceptance in MC"}; + Configurable pTHatExponent{"pTHatExponent", 4.0, + "Exponent of the event weight for the calculation of pTHat"}; + Configurable pTHatMax{"pTHatMax", 999.0, + "Maximum fraction of hard scattering for jet acceptance in MC"}; // Parameters for recoil jet selection - Configurable ptTTrefMin{"ptTTrefMin", 5., "Minimum pT of reference TT"}; - Configurable ptTTrefMax{"ptTTrefMax", 7., "Maximum pT of reference TT"}; + Configurable ptTTrefMin{"ptTTrefMin", 5., + "Minimum pT of reference TT"}; + Configurable ptTTrefMax{"ptTTrefMax", 7., + "Maximum pT of reference TT"}; Configurable ptTTsigMin{"ptTTsigMin", 20., "Minimum pT of signal TT"}; Configurable ptTTsigMax{"ptTTsigMax", 50., "Maximum pT of signal TT"}; - Configurable recoilRegion{"recoilRegion", 0.6, "Width of recoil acceptance"}; + Configurable recoilRegion{"recoilRegion", 0.6, + "Width of recoil acceptance"}; // List of configurable parameters for histograms - Configurable histJetPt{"histJetPt", 100, "Maximum value of jet pT shown in histograms"}; + Configurable histJetPt{"histJetPt", 100, + "Maximum value of jet pT shown in histograms"}; // Axes specification AxisSpec pT{histJetPt, 0.0, histJetPt * 1.0, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec jetPTcorr{histJetPt + 20, -20., histJetPt * 1.0, "#it{p}_{T, jet}^{ch, corr} (GeV/#it{c})"}; + AxisSpec jetPTcorr{histJetPt + 20, -20., histJetPt * 1.0, + "#it{p}_{T, jet}^{ch, corr} (GeV/#it{c})"}; AxisSpec phiAngle{40, 0.0, constants::math::TwoPI, "#it{#varphi} (rad)"}; - AxisSpec deltaPhiAngle{52, 0.0, constants::math::PI, "#Delta#it{#varphi} (rad)"}; + AxisSpec deltaPhiAngle{52, 0.0, constants::math::PI, + "#Delta#it{#varphi} (rad)"}; AxisSpec pseudorap{40, -1., 1., "#it{#eta}"}; AxisSpec pseudorapJets{20, -0.5, 0.5, "#it{#eta}_{jet}"}; AxisSpec jetArea{50, 0.0, 5., "Area_{jet}"}; AxisSpec rhoArea{60, 0.0, 60., "#it{#rho} #times Area_{jet}"}; AxisSpec rho{50, 0.0, 50., "#it{#rho}"}; - Preslice partJetsPerCollision = aod::jet::mcCollisionId; + Preslice partJetsPerCollision = + aod::jet::mcCollisionId; TRandom3* rand = new TRandom3(0); @@ -113,8 +152,10 @@ struct RecoilJets { Filter collisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; Filter collisionFilterMC = nabs(aod::jmccollision::posZ) < vertexZCut; - // 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&& aod::jtrack::pt < trkPtMax&& nabs(aod::jtrack::eta) < trkEtaCut; + // 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&& aod::jtrack::pt < + trkPtMax&& nabs(aod::jtrack::eta) < trkEtaCut; Filter partFilter = nabs(aod::jmcparticle::eta) < trkEtaCut; // Declare filter on jets @@ -130,127 +171,312 @@ struct RecoilJets { void init(InitContext const&) { - eventSelectionBits = jetderiveddatautilities::initialiseEventSelectionBits(static_cast(evSel)); - trackSelection = jetderiveddatautilities::initialiseTrackSelection(static_cast(trkSel)); - triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); + std::string evSelToString = static_cast(evSel); + std::string trkSelToString = static_cast(trkSel); + + eventSelectionBits = + jetderiveddatautilities::initialiseEventSelectionBits(evSelToString); + trackSelection = + jetderiveddatautilities::initialiseTrackSelection(trkSelToString); + triggerMaskBits = + jetderiveddatautilities::initialiseTriggerMaskBits(triggerMasks); // List of raw and MC det. distributions if (doprocessData || doprocessMCDetLevel || doprocessMCDetLevelWeighted) { - spectra.add("vertexZ", "Z vertex of collisions", kTH1F, {{60, -12., 12.}}); - spectra.add("hHasAssocMcCollision", "Has det. level coll. associat. MC coll.", kTH1F, {{2, 0.0, 2.}}); - spectra.get(HIST("hHasAssocMcCollision"))->GetXaxis()->SetBinLabel(1, "Yes"); - spectra.get(HIST("hHasAssocMcCollision"))->GetXaxis()->SetBinLabel(2, "No"); - - spectra.add("hTrackPtEtaPhi", "Charact. of tracks", kTH3F, {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("hNtrig", "Total number of selected triggers per class", kTH1F, {{2, 0.0, 2.}}); + spectra.add("hEventSelectionCount", "Count # of events in the analysis", + kTH1F, {{3, 0.0, 3.}}); + 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 w. outlier"); + + spectra.add("vertexZ", "Z vertex of collisions", kTH1F, + {{60, -12., 12.}}); + spectra.add("hHasAssocMcCollision", + "Has det. level coll. associat. MC coll.", kTH1F, + {{2, 0.0, 2.}}); + spectra.get(HIST("hHasAssocMcCollision")) + ->GetXaxis() + ->SetBinLabel(1, "Yes"); + spectra.get(HIST("hHasAssocMcCollision")) + ->GetXaxis() + ->SetBinLabel(2, "No"); + + 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("hTrackPtEtaPhi", "Charact. of tracks", kTH3F, + {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("hNtrig", "Total number of selected triggers per class", + kTH1F, {{2, 0.0, 2.}}); spectra.get(HIST("hNtrig"))->GetXaxis()->SetBinLabel(1, "TT_{ref}"); spectra.get(HIST("hNtrig"))->GetXaxis()->SetBinLabel(2, "TT_{sig}"); - spectra.add("hTTRef_per_event", "Number of TT_{Ref} per event", kTH1F, {{15, 0.5, 15.5}}); - spectra.add("hTTSig_per_event", "Number of TT_{Sig} per event", kTH1F, {{10, 0.5, 10.5}}); - - spectra.add("hJetPtEtaPhiRhoArea", "Charact. of inclusive jets", kTHnSparseF, {pT, pseudorapJets, phiAngle, rho, jetArea}); - - spectra.add("hDPhi_JetPt_Corr_TTRef", "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, jetPTcorr}); - spectra.add("hDPhi_JetPt_Corr_TTSig", "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, jetPTcorr}); - spectra.add("hDPhi_JetPt_TTRef", "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, pT}); - spectra.add("hDPhi_JetPt_TTSig", "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, pT}); - - spectra.add("hRecoil_JetPt_Corr_TTRef", "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, {jetPTcorr}); - spectra.add("hRecoil_JetPt_Corr_TTSig", "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, {jetPTcorr}); - spectra.add("hRecoil_JetPt_TTRef", "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, {pT}); - spectra.add("hRecoil_JetPt_TTSig", "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, {pT}); - - 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("hTTRef_per_event", "Number of TT_{Ref} per event", kTH1F, + {{15, 0.5, 15.5}}); + spectra.add("hTTSig_per_event", "Number of TT_{Sig} per event", kTH1F, + {{10, 0.5, 10.5}}); + + spectra.add("hJetPtEtaPhiRhoArea", "Charact. of inclusive jets", + kTHnSparseF, {pT, pseudorapJets, phiAngle, rho, jetArea}); + + spectra.add("hDPhi_JetPt_Corr_TTRef", + "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, jetPTcorr}); + spectra.add("hDPhi_JetPt_Corr_TTSig", + "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, jetPTcorr}); + spectra.add("hDPhi_JetPt_TTRef", + "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, pT}); + spectra.add("hDPhi_JetPt_TTSig", + "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, pT}); + + spectra.add("hRecoil_JetPt_Corr_TTRef", + "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, + {jetPTcorr}); + spectra.add("hRecoil_JetPt_Corr_TTSig", + "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, + {jetPTcorr}); + spectra.add("hRecoil_JetPt_TTRef", + "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, {pT}); + spectra.add("hRecoil_JetPt_TTSig", + "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, {pT}); + + 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}); } // List of MC particle level distributions if (doprocessMCPartLevel || doprocessMCPartLevelWeighted) { - spectra.add("vertexZMC", "Z vertex of jmccollision", kTH1F, {{60, -12., 12.}}); + spectra.add("vertexZMC", "Z vertex of jmccollision", kTH1F, + {{60, -12., 12.}}); spectra.add("ptHat", "Distribution of pT hat", kTH1F, {{500, 0.0, 100.}}); - spectra.add("hPartPtEtaPhi", "Charact. of particles", kTH3F, {pT, pseudorap, phiAngle}); - spectra.add("hNtrig_Part", "Total number of selected triggers per class", kTH1F, {{2, 0.0, 2.}}); - spectra.get(HIST("hNtrig_Part"))->GetXaxis()->SetBinLabel(1, "TT_{ref}"); - spectra.get(HIST("hNtrig_Part"))->GetXaxis()->SetBinLabel(2, "TT_{sig}"); - - spectra.add("hTTRef_per_event_Part", "Number of TT_{Ref} per event", kTH1F, {{15, 0.5, 15.5}}); - spectra.add("hTTSig_per_event_Part", "Number of TT_{Sig} per event", kTH1F, {{10, 0.5, 10.5}}); - - spectra.add("hJetPtEtaPhiRhoArea_Part", "Charact. of inclusive part. level jets", kTHnSparseF, {pT, pseudorapJets, phiAngle, rho, jetArea}); - - spectra.add("hDPhi_JetPt_Corr_TTRef_Part", "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, jetPTcorr}); - spectra.add("hDPhi_JetPt_Corr_TTSig_Part", "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, jetPTcorr}); - spectra.add("hDPhi_JetPt_TTRef_Part", "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, pT}); - spectra.add("hDPhi_JetPt_TTSig_Part", "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", kTH2F, {deltaPhiAngle, pT}); - - spectra.add("hRecoil_JetPt_Corr_TTRef_Part", "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, {jetPTcorr}); - spectra.add("hRecoil_JetPt_Corr_TTSig_Part", "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, {jetPTcorr}); - spectra.add("hRecoil_JetPt_TTRef_Part", "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, {pT}); - spectra.add("hRecoil_JetPt_TTSig_Part", "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, {pT}); - - 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("hEventSelectionCountPartLevel", + "Count # of events in the part. level analysis", kTH1F, + {{2, 0.0, 2.}}); + spectra.get(HIST("hEventSelectionCountPartLevel")) + ->GetXaxis() + ->SetBinLabel(1, "Total # of events"); + spectra.get(HIST("hEventSelectionCountPartLevel")) + ->GetXaxis() + ->SetBinLabel(2, "# of events w. outlier"); + + spectra.add("hCountNumberOutliersFrameWork", + "Count # of outlier events based on flag from JE fw", kTH1F, + {{1, 0.0, 1.}}); + spectra.get(HIST("hCountNumberOutliersFrameWork")) + ->GetXaxis() + ->SetBinLabel(1, "Oulier flag true"); + + spectra.add("hPartPtEtaPhi", "Charact. of particles", kTH3F, + {pT, pseudorap, phiAngle}); + spectra.add("hNtrig_Part", "Total number of selected triggers per class", + kTH1F, {{2, 0.0, 2.}}); + spectra.get(HIST("hNtrig_Part")) + ->GetXaxis() + ->SetBinLabel(1, "TT_{ref}"); + spectra.get(HIST("hNtrig_Part")) + ->GetXaxis() + ->SetBinLabel(2, "TT_{sig}"); + + spectra.add("hTTRef_per_event_Part", "Number of TT_{Ref} per event", + kTH1F, {{15, 0.5, 15.5}}); + spectra.add("hTTSig_per_event_Part", "Number of TT_{Sig} per event", + kTH1F, {{10, 0.5, 10.5}}); + + spectra.add("hJetPtEtaPhiRhoArea_Part", + "Charact. of inclusive part. level jets", kTHnSparseF, + {pT, pseudorapJets, phiAngle, rho, jetArea}); + + spectra.add("hDPhi_JetPt_Corr_TTRef_Part", + "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, jetPTcorr}); + spectra.add("hDPhi_JetPt_Corr_TTSig_Part", + "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, jetPTcorr}); + spectra.add("hDPhi_JetPt_TTRef_Part", + "Events w. TT_{Ref}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, pT}); + spectra.add("hDPhi_JetPt_TTSig_Part", + "Events w. TT_{Sig}: #Delta#varphi & #it{p}_{T, jet}^{ch}", + kTH2F, {deltaPhiAngle, pT}); + + spectra.add("hRecoil_JetPt_Corr_TTRef_Part", + "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, + {jetPTcorr}); + spectra.add("hRecoil_JetPt_Corr_TTSig_Part", + "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, + {jetPTcorr}); + spectra.add("hRecoil_JetPt_TTRef_Part", + "Events w. TT_{Ref}: #it{p}_{T} of recoil jets", kTH1F, {pT}); + spectra.add("hRecoil_JetPt_TTSig_Part", + "Events w. TT_{Sig}: #it{p}_{T} of recoil jets", kTH1F, {pT}); + + 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("hDiffInOutlierRemove", + "Difference between pT hat from code and fw", kTH1F, + {{502, -0.2, 50.}}); } // 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}); - - if (bGetMissJets) { - 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}); - } else { - 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("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 taged jets per 1 base jet vs. jet pT", kTH2F, + {{10, 0.5, 10.5}, {100, 0.0, 100.}}); + } - spectra.add("hNumberMatchedJetsPerOneBaseJet", "# of taged jets per 1 base jet vs. jet pT", kTH2F, {{10, 0.5, 10.5}, {100, 0.0, 100.}}); + if (doprocessMultiplicity) { + spectra.add("hMultFT0A", "Mult. signal from FTOA", kTH1F, + {{1500, 0.0, 30000.}}); + spectra.add("hMultFT0C", "Mult. signal from FTOC", kTH1F, + {{1500, 0.0, 30000.}}); + spectra.add("hMultFT0M", "Total mult. signal from FT0A & FTOC", kTH1F, + {{3000, 0.0, 60000.}}); + + spectra.add("hScaleMultFT0A", "Scaled mult. signal from FTOA", kTH1F, + {{200, 0.0, 20.}}); + spectra.add("hScaleMultFT0C", "Scaled mult. signal from FTOC", kTH1F, + {{200, 0.0, 20.}}); + spectra.add("hScaleMultFT0M", "Scaled total mult. signal from FT0A & FTOC", kTH1F, + {{200, 0.0, 20.}}); + spectra.add("hScaleMultFT0M_v2", "Scaled total mult. signal from FT0A & FTOC", kTH1F, + {{200, 0.0, 20.}}); + + spectra.add("hMultZNA", "Mult. signal from ZDC A-side", kTH1F, + {{500, 0.0, 10000.}}); + spectra.add("hMultZNC", "Mult. signal from ZDC C-side", kTH1F, + {{500, 0.0, 10000.}}); + spectra.add("hMultZNM", "Total mult. signal from ZDCs", kTH1F, + {{1000, 0.0, 20000.}}); + + // Correlations + spectra.add("hMultFT0A_vs_ZNA", "Correlation of signals FTOA vs ZNA", + kTH2F, {{1500, 0.0, 30000.}, {500, 0.0, 10000.}}); + spectra.add("hMultFT0C_vs_ZNC", "Correlation of signals FTOC vs ZNC", + kTH2F, {{1500, 0.0, 30000.}, {500, 0.0, 10000.}}); + spectra.add("hMultFT0M_vs_ZNM", "Correlation of signals FTOM vs ZNM", + kTH2F, {{3000, 0.0, 60000.}, {1000, 0.0, 20000.}}); + spectra.add("hScaleMultFT0A_vs_ZNA", "Correlation of signals FT0A/meanFT0A vs ZNA", + kTH2F, {{200, 0.0, 20.}, {500, 0.0, 10000.}}); + spectra.add("hScaleMultFT0C_vs_ZNC", "Correlation of signals FT0C/meanFT0C vs ZNC", + kTH2F, {{200, 0.0, 20.}, {500, 0.0, 10000.}}); + spectra.add("hScaleMultFT0M_vs_ZNM", "Correlation of signals FT0M/meanTF0M vs ZNM", + kTH2F, {{200, 0.0, 20.}, {1000, 0.0, 20000.}}); + spectra.add("hScaleMultFT0Mv2_vs_ZNM", "Correlation of signals FT0M/meanTF0M v2 vs ZNM", + kTH2F, {{200, 0.0, 20.}, {1000, 0.0, 20000.}}); } } // Fill histograms with raw or MC det. level data template - void fillHistograms(Collision const& collision, Jets const& jets, Tracks const& tracks, bool bIsMC = false, float weight = 1.) + void fillHistograms(Collision const& collision, Jets const& jets, + Tracks const& tracks, float weight = 1.) { - bool bSigEv = false; std::vector vPhiOfTT; double phiTT = 0.; int nTT = 0; - float pTHat = 0.; - if (bIsMC) - pTHat = getPtHat(weight); + float pTHat = getPtHat(weight); auto dice = rand->Rndm(); if (dice < fracSig) bSigEv = true; + // Remove whole event if jet passes the outlier removal condition + for (const auto& jet : jets) { + if (jet.pt() > pTHatMax * pTHat) { + spectra.fill(HIST("hEventSelectionCount"), 2.5); + return; + } + } + for (const auto& track : tracks) { - if (skipTrack(track)) - continue; + spectra.fill(HIST("hTrackSelectionCount"), 0.5); - if (bIsMC && (track.pt() > pTHatMaxTrack * pTHat)) + if (skipTrack(track)) continue; - spectra.fill(HIST("hTrackPtEtaPhi"), track.pt(), track.eta(), track.phi(), weight); + spectra.fill(HIST("hTrackSelectionCount"), 1.5); + spectra.fill(HIST("hTrackPtEtaPhi"), track.pt(), track.eta(), track.phi(), + weight); // Search for TT candidate if (bSigEv && (track.pt() > ptTTsigMin && track.pt() < ptTTsigMax)) { @@ -279,33 +505,36 @@ struct RecoilJets { } for (const auto& jet : jets) { - - if (bIsMC && (jet.pt() > pTHatMax * pTHat)) - continue; - - spectra.fill(HIST("hJetPtEtaPhiRhoArea"), jet.pt(), jet.eta(), jet.phi(), collision.rho(), jet.area(), weight); + spectra.fill(HIST("hJetPtEtaPhiRhoArea"), jet.pt(), jet.eta(), jet.phi(), + collision.rho(), jet.area(), weight); if (nTT > 0) { auto [dphi, bRecoilJet] = isRecoilJet(jet, phiTT); if (bSigEv) { - spectra.fill(HIST("hDPhi_JetPt_Corr_TTSig"), dphi, jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hDPhi_JetPt_Corr_TTSig"), dphi, + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hDPhi_JetPt_TTSig"), dphi, jet.pt(), weight); - spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig"), jet.area(), jet.pt(), collision.rho(), weight); + spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig"), jet.area(), jet.pt(), + collision.rho(), weight); if (bRecoilJet) { - spectra.fill(HIST("hRecoil_JetPt_Corr_TTSig"), jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hRecoil_JetPt_Corr_TTSig"), + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hRecoil_JetPt_TTSig"), jet.pt(), weight); } } else { - spectra.fill(HIST("hDPhi_JetPt_Corr_TTRef"), dphi, jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hDPhi_JetPt_Corr_TTRef"), dphi, + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hDPhi_JetPt_TTRef"), dphi, jet.pt(), weight); - spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef"), jet.area(), jet.pt(), collision.rho(), weight); + spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef"), jet.area(), jet.pt(), + collision.rho(), weight); if (bRecoilJet) { - spectra.fill(HIST("hRecoil_JetPt_Corr_TTRef"), jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hRecoil_JetPt_Corr_TTRef"), + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hRecoil_JetPt_TTRef"), jet.pt(), weight); } } @@ -314,7 +543,8 @@ struct RecoilJets { } template - void fillMCPHistograms(Collision const& collision, Jets const& jets, Particles const& particles, float weight = 1.) + void fillMCPHistograms(Collision const& collision, Jets const& jets, + Particles const& particles, float weight = 1.) { bool bSigEv = false; std::vector vPhiOfTT; @@ -327,6 +557,13 @@ struct RecoilJets { if (dice < fracSig) bSigEv = true; + for (const auto& jet : jets) { + if (jet.pt() > pTHatMax * pTHat) { + spectra.fill(HIST("hEventSelectionCountPartLevel"), 1.5); + return; + } + } + for (const auto& particle : particles) { auto pdgParticle = pdg->GetParticle(particle.pdgCode()); if (!pdgParticle) @@ -337,17 +574,17 @@ struct RecoilJets { if (bParticleNeutral || !particle.isPhysicalPrimary()) continue; - if (particle.pt() > pTHatMaxTrack * pTHat) - continue; - - spectra.fill(HIST("hPartPtEtaPhi"), particle.pt(), particle.eta(), particle.phi(), weight); + spectra.fill(HIST("hPartPtEtaPhi"), particle.pt(), particle.eta(), + particle.phi(), weight); - if (bSigEv && (particle.pt() > ptTTsigMin && particle.pt() < ptTTsigMax)) { + if (bSigEv && + (particle.pt() > ptTTsigMin && particle.pt() < ptTTsigMax)) { vPhiOfTT.push_back(particle.phi()); ++nTT; } - if (!bSigEv && (particle.pt() > ptTTrefMin && particle.pt() < ptTTrefMax)) { + if (!bSigEv && + (particle.pt() > ptTTrefMin && particle.pt() < ptTTrefMax)) { vPhiOfTT.push_back(particle.phi()); ++nTT; } @@ -367,11 +604,8 @@ struct RecoilJets { } for (const auto& jet : jets) { - - if (jet.pt() > pTHatMax * pTHat) - continue; - - spectra.fill(HIST("hJetPtEtaPhiRhoArea_Part"), jet.pt(), jet.eta(), jet.phi(), collision.rho(), jet.area(), weight); + spectra.fill(HIST("hJetPtEtaPhiRhoArea_Part"), jet.pt(), jet.eta(), + jet.phi(), collision.rho(), jet.area(), weight); if (nTT > 0) { @@ -379,23 +613,29 @@ struct RecoilJets { if (bSigEv) { - spectra.fill(HIST("hDPhi_JetPt_Corr_TTSig_Part"), dphi, jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hDPhi_JetPt_Corr_TTSig_Part"), dphi, + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hDPhi_JetPt_TTSig_Part"), dphi, jet.pt(), weight); - spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig_Part"), jet.area(), jet.pt(), collision.rho(), weight); + spectra.fill(HIST("hJetArea_JetPt_Rho_TTSig_Part"), jet.area(), + jet.pt(), collision.rho(), weight); if (bRecoilJet) { - spectra.fill(HIST("hRecoil_JetPt_Corr_TTSig_Part"), jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hRecoil_JetPt_Corr_TTSig_Part"), + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hRecoil_JetPt_TTSig_Part"), jet.pt(), weight); } } else { - spectra.fill(HIST("hDPhi_JetPt_Corr_TTRef_Part"), dphi, jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hDPhi_JetPt_Corr_TTRef_Part"), dphi, + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hDPhi_JetPt_TTRef_Part"), dphi, jet.pt(), weight); - spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef_Part"), jet.area(), jet.pt(), collision.rho(), weight); + spectra.fill(HIST("hJetArea_JetPt_Rho_TTRef_Part"), jet.area(), + jet.pt(), collision.rho(), weight); if (bRecoilJet) { - spectra.fill(HIST("hRecoil_JetPt_Corr_TTRef_Part"), jet.pt() - collision.rho() * jet.area(), weight); + spectra.fill(HIST("hRecoil_JetPt_Corr_TTRef_Part"), + jet.pt() - collision.rho() * jet.area(), weight); spectra.fill(HIST("hRecoil_JetPt_TTRef_Part"), jet.pt(), weight); } } @@ -404,19 +644,23 @@ struct RecoilJets { } template - void fillMatchedHistograms(TracksTable const& tracks, JetsBase const& jetsBase, JetsTag const& jetsTag, float weight = 1.) + void fillMatchedHistograms(TracksTable const& tracks, + JetsBase const& jetsBase, JetsTag const& jetsTag, + float weight = 1.) { std::vector vPhiOfTT; double phiTTSig = 0.; float pTHat = getPtHat(weight); + for (const auto& jetBase : jetsBase) { + if (jetBase.pt() > pTHatMax * pTHat) + return; + } + for (const auto& track : tracks) { if (skipTrack(track)) continue; - if (track.pt() > pTHatMaxTrack * pTHat) - continue; - if (track.pt() > ptTTsigMin && track.pt() < ptTTsigMax) { vPhiOfTT.push_back(track.phi()); } @@ -428,21 +672,63 @@ struct RecoilJets { phiTTSig = getPhiTT(vPhiOfTT); for (const auto& jetBase : jetsBase) { - if (jetBase.pt() > pTHatMax * pTHat) - continue; - - bool bIsBaseJetRecoil = get<1>(isRecoilJet(jetBase, phiTTSig)) && bIsThereTTSig; + bool bIsBaseJetRecoil = + get<1>(isRecoilJet(jetBase, phiTTSig)) && bIsThereTTSig; dataForUnfolding(jetBase, jetsTag, bIsBaseJetRecoil, weight); } } - void processData(FilteredColl const& collision, - FilteredTracks const& tracks, + template + void fillMultiplicityHistograms(Collision const& collision, + float weight = 1.0) + { + + spectra.fill(HIST("hMultFT0A"), collision.multFT0A(), weight); + spectra.fill(HIST("hMultFT0C"), collision.multFT0C(), weight); + spectra.fill(HIST("hMultFT0M"), collision.multFT0M(), weight); + + float scaledFT0Mv2 = 0.5 * (collision.multFT0A() / meanFT0A + collision.multFT0C() / meanFT0C); + + spectra.fill(HIST("hScaleMultFT0A"), collision.multFT0A() / meanFT0A, weight); + spectra.fill(HIST("hScaleMultFT0C"), collision.multFT0C() / meanFT0C, weight); + spectra.fill(HIST("hScaleMultFT0M"), collision.multFT0M() / meanFT0M, weight); + spectra.fill(HIST("hScaleMultFT0M_v2"), scaledFT0Mv2, + weight); + + spectra.fill(HIST("hMultZNA"), collision.multZNA(), weight); + spectra.fill(HIST("hMultZNC"), collision.multZNC(), weight); + spectra.fill(HIST("hMultZNM"), collision.multZNA() + collision.multZNC(), + weight); + + // Correlations + spectra.fill(HIST("hMultFT0A_vs_ZNA"), collision.multFT0A(), + collision.multZNA(), weight); + spectra.fill(HIST("hMultFT0C_vs_ZNC"), collision.multFT0C(), + collision.multZNC(), weight); + spectra.fill(HIST("hMultFT0M_vs_ZNM"), collision.multFT0M(), + collision.multZNA() + collision.multZNC(), weight); + spectra.fill(HIST("hScaleMultFT0A_vs_ZNA"), collision.multFT0A() / meanFT0A, + collision.multZNA(), weight); + spectra.fill(HIST("hScaleMultFT0C_vs_ZNC"), collision.multFT0C() / meanFT0C, + collision.multZNC(), weight); + spectra.fill(HIST("hScaleMultFT0M_vs_ZNM"), collision.multFT0M() / meanFT0M, + collision.multZNA() + collision.multZNC(), weight); + spectra.fill(HIST("hScaleMultFT0Mv2_vs_ZNM"), scaledFT0Mv2, + collision.multZNA() + collision.multZNC(), weight); + } + + //------------------------------------------------------------------------------ + // Process functions + void processData(FilteredColl const& collision, FilteredTracks const& tracks, FilteredJets const& jets) { + spectra.fill(HIST("hEventSelectionCount"), 0.5); + if (skipEvent(collision)) return; + spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("vertexZ"), collision.posZ()); fillHistograms(collision, jets, tracks); } @@ -452,22 +738,29 @@ struct RecoilJets { FilteredTracks const& tracks, FilteredJetsDetLevel const& jets) { + spectra.fill(HIST("hEventSelectionCount"), 0.5); if (skipEvent(collision) || skipMBGapEvent(collision)) return; + spectra.fill(HIST("hEventSelectionCount"), 1.5); + spectra.fill(HIST("vertexZ"), collision.posZ()); - fillHistograms(collision, jets, tracks, true); + fillHistograms(collision, jets, tracks); } - PROCESS_SWITCH(RecoilJets, processMCDetLevel, "process MC detector level", false); + PROCESS_SWITCH(RecoilJets, processMCDetLevel, "process MC detector level", + false); void processMCDetLevelWeighted(FilteredCollDetLevelGetWeight const& collision, aod::JetMcCollisions const&, FilteredTracks const& tracks, FilteredJetsDetLevel const& jets) { + spectra.fill(HIST("hEventSelectionCount"), 0.5); if (skipEvent(collision) || skipMBGapEvent(collision)) return; + spectra.fill(HIST("hEventSelectionCount"), 1.5); + auto weight = collision.mcCollision().weight(); spectra.fill(HIST("vertexZ"), collision.posZ(), weight); @@ -477,34 +770,48 @@ struct RecoilJets { spectra.fill(HIST("hHasAssocMcCollision"), 1.5, weight); } - fillHistograms(collision, jets, tracks, true, weight); + fillHistograms(collision, jets, tracks, weight); } - PROCESS_SWITCH(RecoilJets, processMCDetLevelWeighted, "process MC detector level with event weight", false); + PROCESS_SWITCH(RecoilJets, processMCDetLevelWeighted, + "process MC detector level with event weight", false); void processMCPartLevel(FilteredCollPartLevel const& collision, - aod::JetParticles const& particles, + FilteredParticles const& particles, FilteredJetsPartLevel const& jets) { + spectra.fill(HIST("hEventSelectionCountPartLevel"), 0.5); if (skipMBGapEvent(collision)) return; spectra.fill(HIST("vertexZMC"), collision.posZ()); fillMCPHistograms(collision, jets, particles); } - PROCESS_SWITCH(RecoilJets, processMCPartLevel, "process MC particle level", false); + PROCESS_SWITCH(RecoilJets, processMCPartLevel, "process MC particle level", + false); void processMCPartLevelWeighted(FilteredCollPartLevel const& collision, - aod::JetParticles const& particles, + FilteredParticles const& particles, FilteredJetsPartLevel const& jets) { + spectra.fill(HIST("hEventSelectionCountPartLevel"), 0.5); if (skipMBGapEvent(collision)) return; auto weight = collision.weight(); + + auto calcPtHat = getPtHat(weight); + auto pThatFromFW = collision.ptHard(); + spectra.fill(HIST("hDiffInOutlierRemove"), calcPtHat - pThatFromFW); + if (collision.isOutlier()) + spectra.fill(HIST("hCountNumberOutliersFrameWork"), 0.5); + + // LOG(debug) << "Difference between pT hat: " << calcPtHat - pThatFromFW; + spectra.fill(HIST("vertexZMC"), collision.posZ(), weight); fillMCPHistograms(collision, jets, particles, weight); } - PROCESS_SWITCH(RecoilJets, processMCPartLevelWeighted, "process MC particle level with event weight", false); + PROCESS_SWITCH(RecoilJets, processMCPartLevelWeighted, + "process MC particle level with event weight", false); void processJetsMatched(FilteredCollDetLevelGetWeight const& collision, aod::JetMcCollisions const&, @@ -515,35 +822,42 @@ struct RecoilJets { if (skipEvent(collision) || skipMBGapEvent(collision)) return; - auto mcpjetsPerMCCollision = mcpjets.sliceBy(partJetsPerCollision, collision.mcCollisionId()); + auto mcpjetsPerMCCollision = + mcpjets.sliceBy(partJetsPerCollision, collision.mcCollisionId()); - if (bGetMissJets) { - fillMatchedHistograms(tracks, mcpjetsPerMCCollision, mcdjets); - } else { - fillMatchedHistograms(tracks, mcdjets, mcpjetsPerMCCollision); - } + fillMatchedHistograms(tracks, mcpjetsPerMCCollision, mcdjets); } - PROCESS_SWITCH(RecoilJets, processJetsMatched, "process matching of MC jets (no weight)", false); - - void processJetsMatchedWeighted(FilteredCollDetLevelGetWeight const& collision, - aod::JetMcCollisions const&, - FilteredTracks const& tracks, - FilteredMatchedJetsDetLevel const& mcdjets, - FilteredMatchedJetsPartLevel const& mcpjets) + PROCESS_SWITCH(RecoilJets, processJetsMatched, + "process matching of MC jets (no weight)", false); + + void + processJetsMatchedWeighted(FilteredCollDetLevelGetWeight const& collision, + aod::JetMcCollisions const&, + FilteredTracks const& tracks, + FilteredMatchedJetsDetLevel const& mcdjets, + FilteredMatchedJetsPartLevel const& mcpjets) { if (skipEvent(collision) || skipMBGapEvent(collision)) return; - auto mcpjetsPerMCCollision = mcpjets.sliceBy(partJetsPerCollision, collision.mcCollisionId()); + auto mcpjetsPerMCCollision = + mcpjets.sliceBy(partJetsPerCollision, collision.mcCollisionId()); auto weight = collision.mcCollision().weight(); - if (bGetMissJets) { - fillMatchedHistograms(tracks, mcpjetsPerMCCollision, mcdjets, weight); - } else { - fillMatchedHistograms(tracks, mcdjets, mcpjetsPerMCCollision, weight); - } + fillMatchedHistograms(tracks, mcpjetsPerMCCollision, mcdjets, weight); + } + PROCESS_SWITCH(RecoilJets, processJetsMatchedWeighted, + "process matching of MC jets (weighted)", false); + + void processMultiplicity(FilteredEventMultiplicity const& collision) + { + if (skipEvent(collision)) + return; + + fillMultiplicityHistograms(collision); } - PROCESS_SWITCH(RecoilJets, processJetsMatchedWeighted, "process matching of MC jets (weighted)", false); + PROCESS_SWITCH(RecoilJets, processMultiplicity, "process multiplicity", + false); //------------------------------------------------------------------------------ // Auxiliary functions @@ -551,13 +865,17 @@ 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) || + !jetderiveddatautilities::selectTrigger(coll, triggerMaskBits); } template bool skipMBGapEvent(const Collision& coll) { - return skipMBGapEvents && coll.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap; + return skipMBGapEvents && + coll.subGeneratorId() == + jetderiveddatautilities::JCollisionSubGeneratorId::mbGap; } template @@ -567,10 +885,10 @@ struct RecoilJets { } template - std::tuple isRecoilJet(const Jet& jet, - double phiTT) + std::tuple isRecoilJet(const Jet& jet, double phiTT) { - double dphi = std::fabs(RecoDecay::constrainAngle(jet.phi() - phiTT, -constants::math::PI)); + double dphi = std::fabs( + RecoDecay::constrainAngle(jet.phi() - phiTT, -constants::math::PI)); return {dphi, (constants::math::PI - recoilRegion) < dphi}; } @@ -585,54 +903,58 @@ struct RecoilJets { return 10. / (std::pow(weight, 1.0 / pTHatExponent)); } - template - void dataForUnfolding(JetBase const& jetBase, JetsTag const&, bool bIsBaseJetRecoil, float weight = 1.0) + template + void dataForUnfolding(PartJet const& partJet, DetJet const& detJets, + bool bIsBaseJetRecoil, float weight = 1.0) { - bool bIsThereMatchedJet = jetBase.has_matchedJetGeo(); + bool bIsThereMatchedJet = partJet.has_matchedJetGeo(); + if (bIsThereMatchedJet) { - const auto& jetsMatched = jetBase.template matchedJetGeo_as>(); + const auto& jetsMatched = + partJet.template matchedJetGeo_as>(); for (const auto& jetMatched : jetsMatched) { - spectra.fill(HIST("hNumberMatchedJetsPerOneBaseJet"), jetsMatched.size(), jetMatched.pt(), weight); - - if (bGetMissJets) { - // Mean that base jet is particle level jet - spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel"), jetMatched.pt(), jetBase.pt(), weight); - spectra.fill(HIST("hJetPt_resolution"), (jetBase.pt() - jetMatched.pt()) / jetBase.pt(), jetBase.pt(), weight); - spectra.fill(HIST("hJetPhi_resolution"), jetBase.phi() - jetMatched.phi(), jetBase.pt(), weight); - - if (bIsBaseJetRecoil) { - spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel_RecoilJets"), jetMatched.pt(), jetBase.pt(), weight); - spectra.fill(HIST("hJetPt_resolution_RecoilJets"), (jetBase.pt() - jetMatched.pt()) / jetBase.pt(), jetBase.pt(), weight); - spectra.fill(HIST("hJetPhi_resolution_RecoilJets"), jetBase.phi() - jetMatched.phi(), jetBase.pt(), weight); - } - } else { - // Mean that base jet is detector level jet - spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel"), jetBase.pt(), jetMatched.pt(), weight); - spectra.fill(HIST("hJetPt_resolution"), (jetMatched.pt() - jetBase.pt()) / jetMatched.pt(), jetMatched.pt(), weight); - spectra.fill(HIST("hJetPhi_resolution"), jetMatched.phi() - jetBase.phi(), jetMatched.phi(), weight); - - if (bIsBaseJetRecoil) { - spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel_RecoilJets"), jetBase.pt(), jetMatched.pt(), weight); - spectra.fill(HIST("hJetPt_resolution_RecoilJets"), (jetMatched.pt() - jetBase.pt()) / jetMatched.pt(), jetMatched.pt(), weight); - spectra.fill(HIST("hJetPhi_resolution_RecoilJets"), jetMatched.phi() - jetBase.phi(), jetMatched.phi(), weight); - } + spectra.fill(HIST("hNumberMatchedJetsPerOneBaseJet"), + jetsMatched.size(), jetMatched.pt(), weight); + spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel"), jetMatched.pt(), + partJet.pt(), weight); + spectra.fill(HIST("hJetPt_resolution"), + (partJet.pt() - jetMatched.pt()) / partJet.pt(), + partJet.pt(), weight); + spectra.fill(HIST("hJetPhi_resolution"), + partJet.phi() - jetMatched.phi(), partJet.pt(), weight); + + if (bIsBaseJetRecoil) { + spectra.fill(HIST("hJetPt_DetLevel_vs_PartLevel_RecoilJets"), + jetMatched.pt(), partJet.pt(), weight); + spectra.fill(HIST("hJetPt_resolution_RecoilJets"), + (partJet.pt() - jetMatched.pt()) / partJet.pt(), + partJet.pt(), weight); + spectra.fill(HIST("hJetPhi_resolution_RecoilJets"), + partJet.phi() - jetMatched.phi(), partJet.pt(), weight); } } } else { - // No closest jet - if (bGetMissJets) { - spectra.fill(HIST("hMissedJets_pT"), jetBase.pt(), weight); - if (bIsBaseJetRecoil) - spectra.fill(HIST("hMissedJets_pT_RecoilJets"), jetBase.pt(), weight); - } else { - spectra.fill(HIST("hFakeJets_pT"), jetBase.pt(), weight); + // Miss jets + spectra.fill(HIST("hMissedJets_pT"), partJet.pt(), weight); + if (bIsBaseJetRecoil) + spectra.fill(HIST("hMissedJets_pT_RecoilJets"), partJet.pt(), weight); + } + + // Fake jets + for (const auto& detJet : detJets) { + bIsThereMatchedJet = detJet.has_matchedJetGeo(); + if (!bIsThereMatchedJet) { + spectra.fill(HIST("hFakeJets_pT"), detJet.pt(), weight); if (bIsBaseJetRecoil) - spectra.fill(HIST("hFakeJets_pT_RecoilJets"), jetBase.pt(), weight); + spectra.fill(HIST("hFakeJets_pT_RecoilJets"), detJet.pt(), weight); } } } }; -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; } +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGJE/Tasks/statPromptPhoton.cxx b/PWGJE/Tasks/statPromptPhoton.cxx index 62d9bf72b97..977b94741c5 100644 --- a/PWGJE/Tasks/statPromptPhoton.cxx +++ b/PWGJE/Tasks/statPromptPhoton.cxx @@ -13,56 +13,54 @@ /// \brief Reconstruction of Phi yield through track-track Minv correlations for resonance hadrochemistry analysis. /// /// -/// \author Adrian Fereydon Nassirpour -#include - -#include -#include -#include -#include +/// \author Adrian Fereydon Nassirpour -#include -#include - -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "ReconstructionDataFormats/Track.h" +#include "PWGJE/Core/FastJetUtilities.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/EMCALClusters.h" +#include "PWGJE/DataModel/Jet.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "EMCALBase/Geometry.h" -#include "EMCALCalib/BadChannelMap.h" +#include "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 "DataFormatsEMCAL/AnalysisCluster.h" -#include "DataFormatsParameters/GRPObject.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 "CommonDataFormat/InteractionRecord.h" +#include +#include + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; struct statPromptPhoton { + SliceCache cache; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; Configurable cfgMaxDCArToPVcut{"cfgMaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; @@ -101,8 +99,11 @@ struct statPromptPhoton { Configurable cfgGenHistograms{"cfgGenHistograms", false, "Enables Generated histograms"}; 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"}; Configurable cfgDebug{"cfgDebug", false, "Enables debug information for local running"}; + int trackFilter = -1; + std::vector triggerMaskBits; // INIT void init(InitContext const&) @@ -110,6 +111,7 @@ struct statPromptPhoton { std::vector ptBinning = {0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0, 2.5, 3.0, 4.0, 5.0, 6.0, 8.0, 12.0, 16.0, 20.0, 25.0, 30.0, 40.0, 50.0, 75.0, 100.0, 150.0, 200.0, 300.0, 500.0}; AxisSpec pthadAxis = {ptBinning, "#it{p}_{T}^{had sum} [GeV/c]"}; + triggerMaskBits = jetderiveddatautilities::initialiseTriggerMaskBits(cfgTriggerMasks); if (cfgJETracks) { trackFilter = jetderiveddatautilities::initialiseTrackSelection(static_cast(cfgTrackFilter)); } @@ -251,8 +253,11 @@ struct statPromptPhoton { using jMCClusters = o2::soa::Join; using jClusters = o2::soa::Join; - using jselectedCollisions = 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; using jfilteredClusters = soa::Filtered; @@ -604,7 +609,7 @@ struct statPromptPhoton { PresliceUnsorted EMCTrackPerTrack = aod::jemctrack::trackId; int nEventsRecMC_JE = 0; - void processMCRec_JE(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, aod::JMcParticles const&, BcCandidates const&, jEMCtracks const& emctracks) + void processMCRec_JE(jfilteredCollisions::iterator const& collision, jfilteredMCClusters const& mcclusters, jTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, aod::JMcParticles const&, BcCandidates const&, jEMCtracks const& emctracks, aod::JetMcCollisions const&) { nEventsRecMC_JE++; @@ -629,6 +634,17 @@ struct statPromptPhoton { } histos.fill(HIST("REC_nEvents"), 2.5); + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return; + } + + histos.fill(HIST("REC_nEvents"), 3.5); + + double weight = 1; + if (collision.has_mcCollision()) { + weight = collision.mcCollision().weight(); + } + bool noTrk = true; for (auto& track : tracks) { if (cfgJETracks) { @@ -844,9 +860,9 @@ struct statPromptPhoton { histos.fill(HIST("REC_Cluster_QA"), 4.5); clustertrigger = true; double pthadsum = GetPtHadSum(tracks, mccluster, cfgMinR, cfgMaxR, false, false, true); - histos.fill(HIST("REC_Trigger_V_PtHadSum_Photon"), mccluster.energy(), pthadsum); - histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum); - histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy()); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Photon"), mccluster.energy(), pthadsum, weight); + histos.fill(HIST("REC_PtHadSum_Photon"), pthadsum, weight); + histos.fill(HIST("REC_Trigger_Energy"), mccluster.energy(), weight); } auto ClusterParticles = mccluster.mcParticles_as(); @@ -855,11 +871,6 @@ struct statPromptPhoton { bool goodgentrigger = true; double chPe = 0; for (auto& clusterparticle : ClusterParticles) { - // double etaP = clusterparticle.eta(); - // double etaC = mccluster.eta(); - // double phiP = clusterparticle.phi(); - // double phiC = mccluster.phi(); - // double ptP = clusterparticle.pt(); int cindex = clusterparticle.globalIndex(); double pdgcode = fabs(clusterparticle.pdgCode()); if (!clusterparticle.isPhysicalPrimary()) { @@ -900,8 +911,6 @@ struct statPromptPhoton { histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Phi"), clusterparticle.phi()); histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Eta"), clusterparticle.eta()); histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Pt_Phi"), clusterparticle.pt(), clusterparticle.phi()); - // if (phiPrimeP > (0.12/ptP + TMath::Pi()/18. + 0.035) || - // phiPrimeP < (0.1/ptP/ptP + TMath::Pi()/18. - 0.025) ) { histos.fill(HIST("REC_Cluster_ParticleWITHtrack_Pt_PhiPrime"), ptP, phiPrimeP); if (photontrigger) { histos.fill(HIST("REC_Impurity_ParticleWITHtrack_Pt_PhiPrime"), ptP, phiPrimeP); @@ -920,8 +929,6 @@ struct statPromptPhoton { histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Phi"), clusterparticle.phi()); histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Eta"), clusterparticle.eta()); histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Pt_Phi"), clusterparticle.pt(), clusterparticle.phi()); - // if (phiPrimeP > (0.12/ptP + TMath::Pi()/18. + 0.035) || - // phiPrimeP < (0.1/ptP/ptP + TMath::Pi()/18. - 0.025) ) { histos.fill(HIST("REC_Cluster_ParticleWITHOUTtrack_Pt_PhiPrime"), ptP, phiPrimeP); if (photontrigger) { histos.fill(HIST("REC_Impurity_ParticleWITHOUTtrack_Pt_PhiPrime"), ptP, phiPrimeP); @@ -980,12 +987,12 @@ struct statPromptPhoton { std::cout << "Photon mom 2: " << mom2 << std::endl; } if (std::abs(clusterparticle.getGenStatusCode()) > 19 && std::abs(clusterparticle.getGenStatusCode()) < 90) { - histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e()); + histos.fill(HIST("REC_True_Prompt_Trigger_Energy"), clusterparticle.e(), weight); TLorentzVector lRealPhoton; lRealPhoton.SetPxPyPzE(clusterparticle.px(), clusterparticle.py(), clusterparticle.pz(), clusterparticle.e()); double truepthadsum = GetPtHadSum(tracks, lRealPhoton, cfgMinR, cfgMaxR, false, false, false); truephotonPt = clusterparticle.e(); - histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum); + histos.fill(HIST("REC_TrueTrigger_V_PtHadSum_Photon"), truephotonPt, truepthadsum, weight); } } // photon check } // clusterparticle loop @@ -1016,39 +1023,6 @@ struct statPromptPhoton { } } // cluster loop - // auto bc = collision.bc_as(); - // int rnr = bc.runNumber(); - - // std::string rnrstring = std::to_string(rnr); - // if (runs.find(rnrstring) == std::string::npos) { - // std::cout<<"++++++++++++++++++++++++++++++++"<getForTimeStamp(ccdbpath, bc.timestamp()); - // if(grpmag) { - // bfield = std::lround(5.f * grpmag->getL3Current() / 30000.f); - // std::cout<<"++++++++++++++++++++++++++++++++"<getForTimeStamp(ccdbpath, bc.timestamp()); - // if(!grpo) { - // std::cout<<"WE CAN NEITHER FETCH GRPMAG OR GRPO!!! SHIT IS SCREWED"<getNominalL3Field(); - // } - // bfield = 5; - // runs += rnrstring; - // std::cout << "++++++++++++++++++++++++++++++++" << std::endl; - // std::cout << "Run is now appended to string: " << runs << std::endl; - // std::cout << "++++++++++++++++++++++++++++++++" << std::endl; - - // } // check mag field for current run number: done! - // clusters done, now we do the sternheimer tracks for (auto& track : tracks) { bool sterntrigger = false; @@ -1073,19 +1047,9 @@ struct statPromptPhoton { phiPrime = 2 * TMath::Pi() - phiPrime; } - // if (bfield < 0) { - // phiPrime = 2 * TMath::Pi() - phiPrime; - // } - phiPrime = phiPrime + TMath::Pi() / 18.; phiPrime = fmod(phiPrime, 2 * TMath::Pi() / 18.); - // double pt = track.pt(); - // if (phiPrime > (0.12/pt + TMath::Pi()/18. + 0.035) || - // phiPrime < (0.1/pt/pt + TMath::Pi()/18. - 0.025) ) { histos.fill(HIST("REC_Track_PhiPrime_Pt"), phiPrime, track.pt()); - // }//geo cut - // Done with geometric cuts - histos.fill(HIST("REC_Track_Pt"), track.pt()); histos.fill(HIST("REC_Track_Phi"), track.phi()); if (clustertrigger) { @@ -1099,12 +1063,12 @@ struct statPromptPhoton { } } double pthadsum = GetPtHadSum(tracks, track, cfgMinR, cfgMaxR, true, false, true); - histos.fill(HIST("REC_Trigger_V_PtHadSum_Nch"), sternPt, pthadsum); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Nch"), sternPt, pthadsum, weight); if (sterntrigger) { bool doStern = true; double sterncount = 1.0; while (doStern) { - histos.fill(HIST("REC_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, 2.0 / sternPt); + histos.fill(HIST("REC_Trigger_V_PtHadSum_Stern"), sterncount, pthadsum, (2.0 / sternPt) * weight); if (sterncount < sternPt) { sterncount++; } else { @@ -1119,9 +1083,8 @@ struct statPromptPhoton { PROCESS_SWITCH(statPromptPhoton, processMCRec_JE, "processJE MC data", false); int nEventsData = 0; - void processData(jfilteredCollisions::iterator const& collision, jfilteredClusters const& clusters, jDataTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, BcCandidates const&, jEMCtracks const& emctracks) + void processData(jfilteredDataCollisions::iterator const& collision, jfilteredClusters const& clusters, jDataTrackCandidates const& tracks, soa::Join const&, TrackCandidates const&, BcCandidates const&, jEMCtracks const& emctracks) { - nEventsData++; if (cfgDebug) { if (nEventsData == 1) { @@ -1129,8 +1092,12 @@ struct statPromptPhoton { } if ((nEventsData + 1) % 10000 == 0) { std::cout << "Processed Data Events: " << nEventsData << std::endl; + std::cout << "Events Trigger Bit: " << collision.triggerSel() << std::endl; + std::cout << "Trigger Mask Bit: " << triggerMaskBits[0] << std::endl; + std::cout << "Trigger Mask Cfg Line: " << cfgTriggerMasks << std::endl; } } + histos.fill(HIST("DATA_nEvents"), 0.5); // required cuts @@ -1140,13 +1107,19 @@ struct statPromptPhoton { return; histos.fill(HIST("DATA_nEvents"), 1.5); - if (cfgEmcTrigger) { if (!collision.isEmcalReadout()) return; } + histos.fill(HIST("DATA_nEvents"), 2.5); + if (!jetderiveddatautilities::selectTrigger(collision, triggerMaskBits)) { + return; + } + + histos.fill(HIST("DATA_nEvents"), 3.5); + bool noTrk = true; for (auto& track : tracks) { @@ -1347,10 +1320,6 @@ struct statPromptPhoton { phiPrime = 2 * TMath::Pi() - phiPrime; } - // if (bfield < 0) { - // phiPrime = 2 * TMath::Pi() - phiPrime; - // } - phiPrime = phiPrime + TMath::Pi() / 18.; phiPrime = fmod(phiPrime, 2 * TMath::Pi() / 18.); double pt = track.pt(); diff --git a/PWGJE/Tasks/taskEmcExtensiveMcQa.cxx b/PWGJE/Tasks/taskEmcExtensiveMcQa.cxx new file mode 100644 index 00000000000..9c2002c9a11 --- /dev/null +++ b/PWGJE/Tasks/taskEmcExtensiveMcQa.cxx @@ -0,0 +1,229 @@ +// 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 taskEmcExtensiveMcQa.cxx +/// \brief Exensive monitoring task for EMCal clusters in MC +/// \author Marvin Hemmer , Goethe University Frankfurt +/// \since 31.07.2025 + +#include "PWGJE/DataModel/EMCALClusters.h" +// HF headers for event selection +#include "PWGHF/Core/CentralityEstimation.h" +#include "PWGHF/Utils/utilsEvSelHf.h" + +#include "Common/CCDB/ctpRateFetcher.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::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants; +using namespace o2::hf_evsel; +using namespace o2::hf_centrality; +using CollisionEvSels = o2::soa::Join; +using BcEvSelIt = o2::soa::Join::iterator; +using SelectedClusters = o2::soa::Filtered>; + +namespace poi +{ +enum PoI { + kPhoton = 0, + kElectronPrim = 1, + kElectronSec = 2, + kMuon = 3, + kHadronCharge = 4, + kHadronNeutral = 5, + kNPoI = 6 +}; +} // namespace poi + +/// \struct TaskEmcExtensiveMcQa +struct TaskEmcExtensiveMcQa { + + static constexpr int NSM = 20; // there 20 supermodlues for the EMCal + std::array arrPDGHadronNeutral = {kNeutron, kK0Short, kK0Long, kLambda0, physics::kXi0, kSigma0}; + + SliceCache cache; + Preslice psClusterPerCollision = o2::aod::emcalcluster::collisionId; + Preslice perCluster = o2::aod::emcalclustercell::emcalclusterId; + + HistogramRegistry mHistManager{"EMCalExtensiveMCQAHistograms"}; + + o2::emcal::Geometry* mGeometry = nullptr; + o2::framework::Service ccdb; + + ctpRateFetcher rateFetcher; + HfEventSelection hfEvSel; + HfEventSelectionMc hfEvSelMc; + + // configurable parameters + Configurable applyEvSels{"applyEvSels", true, "Flag to apply event selection."}; + Configurable clusterDefinition{"clusterDefinition", 10, "cluster definition to be selected, e.g. 10=kV3Default"}; + Configurable ctpFetcherSource{"ctpFetcherSource", "T0VTX", "Source for CTP rate fetching, e.g. T0VTX, T0CE, T0SC, ZNC (hadronic)"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + + // configurable axis + ConfigurableAxis nClustersBinning{"nClustersBinning", {201, -0.5, 200.5}, "binning for the number of clusters"}; + + ConfigurableAxis clusterEnergy{"clusterEnergy", {100, 0., 10}, "binning for the cluster energy in GeV"}; + ConfigurableAxis clusterM02{"clusterM02", {100, 0., 2.0}, "binning for the cluster M02"}; + ConfigurableAxis clusterM20{"clusterM20", {100, 0., 2.0}, "binning for the cluster M20"}; + ConfigurableAxis clusterNCellBinning{"clusterNCellBinning", {100, 0.5, 100.5}, "binning for the number of cells per cluster"}; + ConfigurableAxis clusterOriginRadius{"clusterOriginRadius", {225, 0., 450}, "binning for the radial original point of the main contributor of a cluster"}; + ConfigurableAxis clusterNContributor{"clusterNContributor", {20, 0.5, 20.5}, "binning for the number of contributor of a cluster"}; + ConfigurableAxis clusterEnergyRatio{"clusterEnergyRatio", {100, 0., 10.}, "binning for ratio of the deposited energy of the leading particle to its generated momentum cluster"}; + ConfigurableAxis collisionCent{"collisionCent", {10, 0., 100.}, "binning for the event centrality"}; + + std::vector mCellTime; + + /// \brief Create output histograms and initialize geometry + void init(InitContext const&) + { + // load geometry just in case we need it + mGeometry = o2::emcal::Geometry::GetInstanceFromRunNumber(300000); + + // create common axes + const AxisSpec numberClustersAxis{nClustersBinning, "#it{N}_{cl}/ #it{N}_{event}"}; + const AxisSpec axisParticle = {poi::kNPoI, -0.5f, +poi::kNPoI - 0.5f, ""}; + const AxisSpec axisEnergy{clusterEnergy, "#it{E}_{cl} (GeV)"}; + const AxisSpec axisM02{clusterM02, "#it{M}_{02}"}; + const AxisSpec axisM20{clusterM20, "#it{M}_{20}"}; + const AxisSpec axisNCell{clusterNCellBinning, "#it{N}_{cells}"}; + const AxisSpec axisRadius{clusterOriginRadius, "#it{R}_{origin} (cm)"}; + const AxisSpec axisNContributor{clusterNContributor, "#it{N}_{particles}"}; + const AxisSpec axisCent{collisionCent, "cent (%)"}; + const AxisSpec axisLeadingEnergy{clusterEnergy, "#it{E}_{lead} (GeV)"}; + const AxisSpec axisLeadingGenMomentum{clusterEnergy, "#it{p}_{lead, gen} (GeV/#it{c})"}; + const AxisSpec axisLeadingRatio{clusterEnergy, "#it{E}_{lead}/#it{p}_{lead, gen} (#it{c})"}; + + // create histograms + + // event properties + mHistManager.add("numberOfClustersEvents", "number of clusters per event (selected events)", HistType::kTH1D, {numberClustersAxis}); + + // cluster properties (matched clusters) + mHistManager.add("hSparseClusterQA", "THnSparse for Cluster QA", HistType::kTHnSparseF, {axisEnergy, axisM02, axisM20, axisNCell, axisRadius, axisParticle, axisNContributor, axisCent}); + mHistManager.add("hSparseClusterContributors", "THnSparse with cluster contributors and energies", HistType::kTHnSparseF, {axisEnergy, axisParticle, axisNContributor, axisLeadingEnergy, axisLeadingGenMomentum, axisLeadingRatio, axisCent}); + mHistManager.add("clusterEtaPhi", "Eta and phi of cluster", HistType::kTH2F, {{140, -0.7, 0.7}, {360, 0, o2::constants::math::TwoPI}}); + + hfEvSel.addHistograms(mHistManager); + + ccdb->setURL(ccdbUrl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + } + + template + bool isCollSelected(const Coll& coll, float& cent) + { + const auto rejectionMask = hfEvSel.getHfCollisionRejectionMask(coll, cent, ccdb, mHistManager); + /// monitor the satisfied event selections + hfEvSel.fillHistograms(coll, rejectionMask, cent); + return rejectionMask == 0; + } + + /// \brief returns the PoI type of a mcparticle + /// \param mcparticle is the mcparticle we want to find the PoI type + /// \param mcparticles table containing the mcparticles + /// \return PoI type of the given mcparticle + template + int findPoIType(T const& mcparticle) + { + auto pdgValue = std::abs(mcparticle.pdgCode()); + switch (pdgValue) { + case kGamma: { + return poi::kPhoton; + } + case kElectron: { + if (mcparticle.isPhysicalPrimary()) { + return poi::kElectronPrim; + } else { + return poi::kElectronSec; + } + } + case kMuonMinus: { + return poi::kMuon; + } + default: { + auto it = std::find(arrPDGHadronNeutral.begin(), arrPDGHadronNeutral.end(), pdgValue); + if (it != arrPDGHadronNeutral.end()) { + return poi::kHadronNeutral; + } + return poi::kHadronCharge; + } + } + } + + Filter clusterDefinitionSelection = (o2::aod::emcalcluster::definition == clusterDefinition); + + /// \brief Process EMCAL clusters that are matched to a collisions + void processCollisions(CollisionEvSels const& collisions, SelectedClusters const& clusters, McParticles const& /*mcparticles*/) + { + + for (const auto& collision : collisions) { + float cent = -1.f; + if (applyEvSels && !isCollSelected(collision, cent)) { + continue; + } + + auto groupedClusters = clusters.sliceBy(psClusterPerCollision, collision.globalIndex()); + mHistManager.fill(HIST("numberOfClustersEvents"), groupedClusters.size()); + + for (const auto& cluster : groupedClusters) { + mHistManager.fill(HIST("clusterEtaPhi"), cluster.eta(), cluster.phi()); + // axisEnergy, axisTime, axisM02, axisNCell, axisRadius, axisParticle + if (cluster.mcParticle().size() == 0) { + LOG(info) << "Somehow cluster.mcParticle().size() == 0!"; + continue; + } + auto mainMcParticle = cluster.mcParticle_as()[0]; + float radius = std::hypot(mainMcParticle.vx(), mainMcParticle.vy()); + float momentum = mainMcParticle.p(); + float leadingEnergy = cluster.energy() * cluster.amplitudeA()[0]; + float leadingFraction = leadingEnergy / momentum; + mHistManager.fill(HIST("hSparseClusterQA"), cluster.energy(), cluster.m02(), cluster.m20(), cluster.nCells(), radius, findPoIType(mainMcParticle), cluster.mcParticle().size(), cent); + mHistManager.fill(HIST("hSparseClusterContributors"), cluster.energy(), findPoIType(mainMcParticle), cluster.mcParticle().size(), leadingEnergy, momentum, leadingFraction, cent); + } + } + } + PROCESS_SWITCH(TaskEmcExtensiveMcQa, processCollisions, "Process clusters from collision", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{ + adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGJE/Tasks/trackEfficiency.cxx b/PWGJE/Tasks/trackEfficiency.cxx index a591c32f958..b82a1ee229a 100644 --- a/PWGJE/Tasks/trackEfficiency.cxx +++ b/PWGJE/Tasks/trackEfficiency.cxx @@ -13,31 +13,27 @@ /// \author Aimeric Landou /// \brief task that creates the histograms necessary for computation of efficiency and purity functions in offline postprocess macros; also can make mcparticle and track QC histograms -#include -#include -#include -#include -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include +#include +#include +#include +#include +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGJE/DataModel/Jet.h" +#include -#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -57,6 +53,7 @@ struct TrackEfficiency { // Tracking efficiency process function configurables: Configurable checkPrimaryPart{"checkPrimaryPart", true, "0: doesn't check mcparticle.isPhysicalPrimary() - 1: checks particle.isPhysicalPrimary()"}; Configurable checkCentrality{"checkCentrality", false, ""}; + Configurable checkOccupancy{"checkOccupancy", false, "check occupancy only in general purpose Pb-Pb MC, default as false"}; Configurable acceptSplitCollisions{"acceptSplitCollisions", 0, "0: only look at mcCollisions that are not split; 1: accept split mcCollisions, 2: accept split mcCollisions but only look at the first reco collision associated with it"}; Configurable trackEtaAcceptanceCountQA{"trackEtaAcceptanceCountQA", 0.9, "eta acceptance"}; // removed from actual cuts for now because all the histograms have an eta axis Configurable centralityMin{"centralityMin", -999, ""}; @@ -82,6 +79,10 @@ struct TrackEfficiency { 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 pTHatMaxFractionMCD{"pTHatMaxFractionMCD", 999.0, "maximum fraction of hard scattering for reconstructed track 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"}; std::vector eventSelectionBits; int trackSelection = -1; @@ -103,34 +104,45 @@ struct TrackEfficiency { return std::abs(charge) >= chargeUnit; } - template - void fillTrackHistograms(T const& collision, U const& tracks, float weight = 1.0) + template + void fillTrackHistograms(TCollision const& collision, TTracks const& tracks, float weight = 1.0) { for (auto const& track : tracks) { if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { continue; } - registry.fill(HIST("h2_centrality_track_pt"), collision.centrality(), track.pt(), weight); - registry.fill(HIST("h2_centrality_track_eta"), collision.centrality(), track.eta(), weight); - registry.fill(HIST("h2_centrality_track_phi"), collision.centrality(), track.phi(), weight); - registry.fill(HIST("h2_centrality_track_energy"), collision.centrality(), track.energy(), weight); + + float simPtRef = 10.; + float pTHat = simPtRef / (std::pow(weight, 1.0 / pTHatExponent)); + if (track.pt() > pTHatMaxFractionMCD * pTHat) { + continue; + } + + registry.fill(HIST("h2_centrality_track_pt"), collision.centFT0M(), track.pt(), weight); + registry.fill(HIST("h2_centrality_track_eta"), collision.centFT0M(), track.eta(), weight); + registry.fill(HIST("h2_centrality_track_phi"), collision.centFT0M(), track.phi(), weight); + registry.fill(HIST("h2_centrality_track_energy"), collision.centFT0M(), track.energy(), weight); registry.fill(HIST("h2_track_pt_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); registry.fill(HIST("h2_track_pt_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); registry.fill(HIST("h2_track_pt_high_track_sigma1overpt"), track.pt(), track.sigma1Pt(), weight); registry.fill(HIST("h2_track_pt_high_track_sigmapt"), track.pt(), track.sigma1Pt() * track.pt(), weight); - registry.fill(HIST("h3_intrate_centrality_track_pt"), collision.hadronicRate(), collision.centrality(), track.pt(), weight); + registry.fill(HIST("h3_intrate_centrality_track_pt"), collision.hadronicRate(), collision.centFT0M(), track.pt(), weight); } } - template - void fillParticlesHistograms(T const& collision, U const& mcparticles, float weight = 1.0) + template + void fillParticlesHistograms(TCollision const& collision, TParticles const& mcparticles, TTracks tracks, float weight = 1.0) { for (auto const& mcparticle : mcparticles) { - registry.fill(HIST("h2_centrality_particle_pt"), collision.centrality(), mcparticle.pt(), weight); - registry.fill(HIST("h2_centrality_particle_eta"), collision.centrality(), mcparticle.eta(), weight); - registry.fill(HIST("h2_centrality_particle_phi"), collision.centrality(), mcparticle.phi(), weight); - registry.fill(HIST("h2_centrality_particle_energy"), collision.centrality(), mcparticle.energy(), weight); - registry.fill(HIST("h3_intrate_centrality_particle_pt"), collision.hadronicRate(), collision.centrality(), mcparticle.pt(), weight); + registry.fill(HIST("h2_centrality_particle_pt"), collision.centFT0M(), mcparticle.pt(), weight); + registry.fill(HIST("h2_centrality_particle_eta"), collision.centFT0M(), mcparticle.eta(), weight); + registry.fill(HIST("h2_centrality_particle_phi"), collision.centFT0M(), mcparticle.phi(), weight); + registry.fill(HIST("h2_centrality_particle_energy"), collision.centFT0M(), mcparticle.energy(), weight); + registry.fill(HIST("h3_intrate_centrality_particle_pt"), collision.hadronicRate(), collision.centFT0M(), mcparticle.pt(), weight); + for (auto const& track : tracks) { + registry.fill(HIST("h2_particle_pt_track_pt_deltapt"), mcparticle.pt(), mcparticle.pt() - track.pt(), weight); + registry.fill(HIST("h2_particle_pt_track_pt_deltaptoverparticlept"), mcparticle.pt(), (mcparticle.pt() - track.pt()) / mcparticle.pt(), weight); + } } } @@ -153,6 +165,9 @@ struct TrackEfficiency { registry.get(HIST("hMcCollCutsCounts"))->GetXaxis()->SetBinLabel(5, "recoCollEvtSel"); registry.get(HIST("hMcCollCutsCounts"))->GetXaxis()->SetBinLabel(6, "centralityCut"); registry.get(HIST("hMcCollCutsCounts"))->GetXaxis()->SetBinLabel(7, "ptHatCut"); + if (checkOccupancy) { + registry.get(HIST("hMcCollCutsCounts"))->GetXaxis()->SetBinLabel(8, "occupancyCut"); + } registry.add("hMcPartCutsCounts", "McPart cuts count checks", {HistType::kTH1F, {{10, 0., 10.}}}); registry.get(HIST("hMcPartCutsCounts"))->GetXaxis()->SetBinLabel(1, "allPartsInSelMcColl"); @@ -164,8 +179,16 @@ struct TrackEfficiency { registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(1, "allTracksInSelColl"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(2, "trackSel"); registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(3, "hasMcParticle"); - registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "mcPartIsPrimary"); - registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing + + if (doprocessEFficiencyPurity) { + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "mcPartIsPrimary"); + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing + } + if (doprocessEFficiencyPurityWeighted) { + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(4, "ptHatMaxFraction"); + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(5, "mcPartIsPrimary"); + registry.get(HIST("hTrackCutsCounts"))->GetXaxis()->SetBinLabel(6, "etaAcc"); // not actually applied here but it will give an idea of what will be done in the post processing + } AxisSpec ptAxisEff = {nBinsLowPt, 0., 10., "#it{p}_{T} (GeV/#it{c})"}; AxisSpec ptAxisHighEff = {18, 10., 100., "#it{p}_{T} (GeV/#it{c})"}; @@ -206,7 +229,7 @@ struct TrackEfficiency { registry.add("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary", "(#it{p}_{T, mcpart} - #it{p}_{T, track}) / #it{p}_{T, mcpart}; #it{p}_{T, mcpart} (GeV/#it{c})", {HistType::kTH2F, {ptAxisHighEff, {200, -1., 1.}}}); } - if (doprocessTracks || doprocessTracksMc || doprocessTracksMcWeighted) { + if (doprocessTracksFromData || doprocessTracksFromMc || doprocessTracksFromMcWeighted) { AxisSpec centAxis = {centralityBinning, "centrality (%)"}; AxisSpec intRateAxis = {intRateNBins, 0., intRateMax, "int. rate (kHz)"}; registry.add("h2_centrality_track_pt", "centrality vs track pT; centrality; #it{p}_{T,track} (GeV/#it{c})", {HistType::kTH2F, {centAxis, {200, 0., 200.}}}); @@ -218,9 +241,6 @@ struct TrackEfficiency { 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("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.}}}); - - registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); - registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); } if (doprocessParticles || doprocessParticlesWeighted) { @@ -231,20 +251,33 @@ struct TrackEfficiency { registry.add("h2_centrality_particle_phi", "centrality vs particle #varphi; centrality; #varphi_{part}", {HistType::kTH2F, {centAxis, {160, -1.0, 7.}}}); registry.add("h2_centrality_particle_energy", "centrality vs particle energy; centrality; Energy GeV", {HistType::kTH2F, {centAxis, {100, 0.0, 100.0}}}); registry.add("h3_intrate_centrality_particle_pt", "interaction rate vs centrality vs particle pT; int. rate; centrality; #it{p}_{T,part} (GeV/#it{c})", {HistType::kTH3F, {intRateAxis, centAxis, {200, 0., 200.}}}); + } + if (doprocessCollisionsFromData || doprocessCollisionsFromMc || doprocessCollisionsFromMcWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; + registry.add("h_collisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_collisions", "centrality vs collisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + } + if (doprocessMcCollisions || doprocessMcCollisionsWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; registry.add("h_mccollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); registry.add("h2_centrality_mccollisions", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + 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}}}); } - if (doprocessTracksMc || doprocessTracksMcWeighted) { - AxisSpec centAxis = {centralityBinning, "centrality (%)"}; + if (doprocessCollisionsFromMc || doprocessCollisionsFromMcWeighted) { registry.add("h_fakecollisions", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); } - if (doprocessTracksMcWeighted) { + if (doprocessCollisionsFromMcWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; registry.add("h_collisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_collisions_weighted", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); } - if (doprocessParticlesWeighted) { + if (doprocessMcCollisionsWeighted) { + AxisSpec centAxis = {centralityBinning, "centrality (%)"}; registry.add("h_mccollisions_weighted", "event status;event status;entries", {HistType::kTH1F, {{4, 0.0, 4.0}}}); + registry.add("h2_centrality_mccollisions_weighted", "centrality vs mccollisions; centrality; collisions", {HistType::kTH2F, {centAxis, {4, 0.0, 4.0}}}); + 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}}}); } } @@ -253,9 +286,10 @@ struct TrackEfficiency { // filters for processTracks QA functions only: Filter trackCuts = (aod::jtrack::pt >= trackQAPtMin && aod::jtrack::pt < trackQAPtMax && aod::jtrack::eta > trackQAEtaMin && aod::jtrack::eta < trackQAEtaMax); Filter particleCuts = (aod::jmcparticle::pt >= trackQAPtMin && aod::jmcparticle::pt < trackQAPtMax && aod::jmcparticle::eta > trackQAEtaMin && aod::jmcparticle::eta < trackQAEtaMax); - Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centrality >= centralityMin && aod::jcollision::centrality < centralityMax); + Filter eventCuts = (nabs(aod::jcollision::posZ) < vertexZCut && aod::jcollision::centFT0M >= centralityMin && aod::jcollision::centFT0M < centralityMax); - void processEFficiencyPurity(aod::JetMcCollision const& mcCollision, + void processEFficiencyPurity(soa::Join::iterator const& mcCollision, + soa::Join const&, 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, JetParticlesWithOriginal const& jMcParticles) @@ -285,21 +319,28 @@ 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 not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } + if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC + occupancyCheck = true; + } } 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 hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } + if (!checkOccupancy || ((trackOccupancyInTimeRangeMin < collisions.begin().trackOccupancyInTimeRange()) && (collisions.begin().trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMax))) { // check occupancy only in GP Pb-Pb MC + occupancyCheck = true; + } } } if (!hasSel8Coll) { @@ -312,12 +353,19 @@ 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 = 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } registry.fill(HIST("hMcCollCutsCounts"), 6.5); // ptHat condition + if (checkOccupancy) { + if (!occupancyCheck) { + return; + } + registry.fill(HIST("hMcCollCutsCounts"), 7.5); + } + for (auto const& jMcParticle : jMcParticles) { registry.fill(HIST("hMcPartCutsCounts"), 0.5); // allPartsInSelMcColl @@ -338,7 +386,7 @@ struct TrackEfficiency { registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi()); 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); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing + registry.fill(HIST("hMcPartCutsCounts"), 3.5); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing } } @@ -421,7 +469,8 @@ struct TrackEfficiency { } PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurity, "Histograms for efficiency and purity quantities", true); - void processEFficiencyPurityWeighted(aod::JetMcCollision const& mcCollision, + void processEFficiencyPurityWeighted(soa::Join::iterator const& mcCollision, + soa::Join const&, 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, JetParticlesWithOriginal const& jMcParticles) @@ -432,22 +481,22 @@ struct TrackEfficiency { // * dividing in centrality bins // I should maybe introduce the sel8 cuts on the collisoins (reco, but what about mccoll? maybe not htat way included in efficiency) - registry.fill(HIST("hMcCollCutsCounts"), 0.5); // all mcCollisions + registry.fill(HIST("hMcCollCutsCounts"), 0.5, mcCollision.weight()); // all mcCollisions if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 1.5); // mcCollision.posZ() condition + registry.fill(HIST("hMcCollCutsCounts"), 1.5, mcCollision.weight()); // mcCollision.posZ() condition if (collisions.size() < 1) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 2.5); // mcCollisions with at least one reconstructed collision + registry.fill(HIST("hMcCollCutsCounts"), 2.5, mcCollision.weight()); // mcCollisions with at least one reconstructed collision if (acceptSplitCollisions == NonSplitOnly && collisions.size() > 1) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 3.5); // split mcCollisions condition + registry.fill(HIST("hMcCollCutsCounts"), 3.5, mcCollision.weight()); // split mcCollisions condition bool hasSel8Coll = false; bool centralityCheck = false; @@ -455,7 +504,7 @@ struct TrackEfficiency { if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks @@ -463,7 +512,7 @@ struct TrackEfficiency { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } } @@ -471,41 +520,42 @@ struct TrackEfficiency { if (!hasSel8Coll) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 4.5); // at least one of the reconstructed collisions associated with this mcCollision is selected + registry.fill(HIST("hMcCollCutsCounts"), 4.5, mcCollision.weight()); // at least one of the reconstructed collisions associated with this mcCollision is selected if (!centralityCheck) { return; } - registry.fill(HIST("hMcCollCutsCounts"), 5.5); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality + registry.fill(HIST("hMcCollCutsCounts"), 5.5, mcCollision.weight()); // at least one of the reconstructed collisions associated with this mcCollision is selected with regard to centrality - float eventWeight = mcCollision.weight(); - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float simPtRef = 10.; + float mcCollEventWeight = mcCollision.weight(); + float pTHat = simPtRef / (std::pow(mcCollEventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } - registry.fill(HIST("hMcCollCutsCounts"), 6.5); // ptHat condition + registry.fill(HIST("hMcCollCutsCounts"), 6.5, mcCollision.weight()); // ptHat condition for (auto const& jMcParticle : jMcParticles) { - registry.fill(HIST("hMcPartCutsCounts"), 0.5); // allPartsInSelMcColl + registry.fill(HIST("hMcPartCutsCounts"), 0.5, mcCollision.weight()); // allPartsInSelMcColl if (!isChargedParticle(jMcParticle.pdgCode())) { continue; } - registry.fill(HIST("hMcPartCutsCounts"), 1.5); // isCharged + registry.fill(HIST("hMcPartCutsCounts"), 1.5, mcCollision.weight()); // isCharged - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpart_nonprimary"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), eventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpart_nonprimary"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); if (checkPrimaryPart && !jMcParticle.isPhysicalPrimary()) { // global tracks should be mostly primaries continue; } - registry.fill(HIST("hMcPartCutsCounts"), 2.5); // isPrimary + registry.fill(HIST("hMcPartCutsCounts"), 2.5, mcCollision.weight()); // isPrimary - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), eventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), mcCollEventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_mcpartofinterest"), jMcParticle.pt(), jMcParticle.eta(), jMcParticle.phi(), eventWeight); + 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 - registry.fill(HIST("hMcPartCutsCounts"), 3.5); // etaAccept // not actually applied here but it will give an idea of what will be done in the post processing + 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 } } @@ -524,35 +574,44 @@ struct TrackEfficiency { auto collTracks = jetTracks.sliceBy(tracksPerJCollision, collision.globalIndex()); for (auto const& track : collTracks) { - registry.fill(HIST("hTrackCutsCounts"), 0.5); + registry.fill(HIST("hTrackCutsCounts"), 0.5, mcCollision.weight()); if (!(jetderiveddatautilities::selectTrack(track, trackSelection) && jetderiveddatautilities::selectTrackDcaZ(track, trackDcaZmax))) { // if track selection is uniformTrack, dcaZ cuts need to be added as they aren't in the selection so that they can be studied here continue; } - registry.fill(HIST("hTrackCutsCounts"), 1.5); + registry.fill(HIST("hTrackCutsCounts"), 1.5, mcCollision.weight()); if (!track.has_mcParticle()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), mcCollEventWeight); // weight attribution here not trivial; I use the one of the current mcCollision, but track belongs to no collision; what should be its weight? could be a moot point but algo has complained about invalid index for mcParticle if I put th etrueTrackCollEventWeight before this cut - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_nonassociatedtrack"), track.pt(), track.eta(), track.phi(), mcCollEventWeight); continue; } - registry.fill(HIST("hTrackCutsCounts"), 2.5); + registry.fill(HIST("hTrackCutsCounts"), 2.5, mcCollision.weight()); + + if (track.pt() > pTHatMaxFractionMCD * pTHat) { + continue; + } + registry.fill(HIST("hTrackCutsCounts"), 3.5, mcCollision.weight()); + + auto mcParticle = track.mcParticle_as(); + auto trueTrackMcCollision = mcParticle.mcCollision_as(); + float trueTrackCollEventWeight = useTrueTrackWeight ? trueTrackMcCollision.weight() : mcCollEventWeight; // test1 auto jMcParticleFromTrack = track.mcParticle_as(); if (!jMcParticleFromTrack.isPhysicalPrimary()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + 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); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_nonprimary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_nonprimary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); } else { seenMcParticlesVector.push_back(jMcParticleFromTrack.globalIndex()); } @@ -560,89 +619,256 @@ struct TrackEfficiency { continue; } - registry.fill(HIST("hTrackCutsCounts"), 3.5); + registry.fill(HIST("hTrackCutsCounts"), 4.5, mcCollision.weight()); - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); - registry.fill(HIST("h2_particle_pt_track_pt_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h2_particle_pt_track_pt_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), trueTrackCollEventWeight); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); - registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h2_particle_pt_high_track_pt_high_residual_associatedtrack_primary"), jMcParticleFromTrack.pt(), (jMcParticleFromTrack.pt() - track.pt()) / jMcParticleFromTrack.pt(), trueTrackCollEventWeight); if (std::find(seenMcParticlesVector.begin(), seenMcParticlesVector.end(), jMcParticleFromTrack.globalIndex()) != seenMcParticlesVector.end()) { - registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); - registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), eventWeight); - registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), eventWeight); + registry.fill(HIST("h3_track_pt_high_track_eta_track_phi_associatedtrack_split_primary"), track.pt(), track.eta(), track.phi(), trueTrackCollEventWeight); + registry.fill(HIST("h3_particle_pt_high_particle_eta_particle_phi_associatedtrack_split_primary"), jMcParticleFromTrack.pt(), jMcParticleFromTrack.eta(), jMcParticleFromTrack.phi(), trueTrackCollEventWeight); } else { seenMcParticlesVector.push_back(jMcParticleFromTrack.globalIndex()); } if (std::abs(jMcParticleFromTrack.eta()) < trackEtaAcceptanceCountQA) { // not actually applied here but it will give an idea of what will be done in the post processing - registry.fill(HIST("hTrackCutsCounts"), 4.5); + registry.fill(HIST("hTrackCutsCounts"), 5.5, mcCollision.weight()); } } } } PROCESS_SWITCH(TrackEfficiency, processEFficiencyPurityWeighted, "Histograms for efficiency and purity quantities for weighted simulations", false); - void processTracks(soa::Filtered::iterator const& collision, - soa::Filtered> const& tracks) + void processTracksFromData(soa::Filtered::iterator const& collision, + soa::Filtered> const& tracks) + { + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + + fillTrackHistograms(collision, tracks); + } + PROCESS_SWITCH(TrackEfficiency, processTracksFromData, "QA for charged tracks in data", false); + + void processTracksFromMc(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&, + soa::Filtered> const& tracks) + { + 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)) { + return; + } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + fillTrackHistograms(collision, tracks); + } + PROCESS_SWITCH(TrackEfficiency, processTracksFromMc, "QA for charged tracks in MC without weights", false); + + void processTracksFromMcWeighted(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&, + soa::Filtered> const& tracks) + { + 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().weight(); + if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { + return; + } + if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + fillTrackHistograms(collision, tracks, eventWeight); + } + PROCESS_SWITCH(TrackEfficiency, processTracksFromMcWeighted, "QA for charged tracks in weighted MC", false); + + void processParticles(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions, + soa::Filtered const& mcparticles, + soa::Filtered const& tracks) + { + + if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + if (collisions.size() < 1) { + return; + } + if (acceptSplitCollisions == NonSplitOnly && collisions.size() > 1) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + 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 not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } 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 + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } + } + if (!hasSel8Coll) { + return; + } + if (!centralityCheck) { + return; + } + + fillParticlesHistograms(collisions.begin(), mcparticles, tracks); + } + PROCESS_SWITCH(TrackEfficiency, processParticles, "QA for charged particles", false); + + void processParticlesWeighted(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions, + soa::Filtered const& mcparticles, + soa::Filtered const& tracks) + { + if (skipMBGapEvents && mcCollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { + return; + } + + float eventWeight = mcCollision.weight(); + + if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { + return; + } + if (collisions.size() < 1) { + return; + } + if (acceptSplitCollisions == NonSplitOnly && collisions.size() > 1) { + return; + } + + float pTHat = getPtHatFromHepMCXSection ? mcCollision.mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max + return; + } + + 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 not a single selected reconstructed collision ; effect unclear if mcColl is split + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } 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 + hasSel8Coll = true; + } + if (!checkCentrality || ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax))) { // effect unclear if mcColl is split + centralityCheck = true; + } + } + } + if (!hasSel8Coll) { + return; + } + if (!centralityCheck) { + return; + } + + fillParticlesHistograms(collisions.begin(), mcparticles, tracks, eventWeight); + } + PROCESS_SWITCH(TrackEfficiency, processParticlesWeighted, "QA for charged particles weighted", false); + + void processCollisionsFromData(soa::Filtered::iterator const& collision) { registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 0.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 0.5); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { return; } registry.fill(HIST("h_collisions"), 1.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 1.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 1.5); if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } registry.fill(HIST("h_collisions"), 2.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); - - fillTrackHistograms(collision, tracks); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 2.5); } - PROCESS_SWITCH(TrackEfficiency, processTracks, "QA for charged tracks in data", false); + PROCESS_SWITCH(TrackEfficiency, processCollisionsFromData, "QA for reconstructed collisions in data", false); - void processTracksMc(soa::Join::iterator const& collision, - aod::JetMcCollisions const&, - soa::Filtered> const& tracks) + void processCollisionsFromMc(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called registry.fill(HIST("h_fakecollisions"), 0.5); return; } registry.fill(HIST("h_collisions"), 0.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 0.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 0.5); if (!jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { return; } registry.fill(HIST("h_collisions"), 1.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 1.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 1.5); if (collision.trackOccupancyInTimeRange() < trackOccupancyInTimeRangeMin || trackOccupancyInTimeRangeMax < collision.trackOccupancyInTimeRange()) { return; } registry.fill(HIST("h_collisions"), 2.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 2.5); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 2.5); - float pTHat = 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(collision.mcCollision().weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } registry.fill(HIST("h_collisions"), 3.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 3.5); - - fillTrackHistograms(collision, tracks); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 3.5); } - PROCESS_SWITCH(TrackEfficiency, processTracksMc, "QA for charged tracks in MC without weights", false); + PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMc, "QA for reconstructed collisions in MC without weights", false); - void processTracksMcWeighted(soa::Join::iterator const& collision, - aod::JetMcCollisions const&, - soa::Filtered> const& tracks) + void processCollisionsFromMcWeighted(soa::Join::iterator const& collision, + soa::Join const&, + soa::Join const&) { if (!collision.has_mcCollision()) { // the collision is fake and has no associated mc coll; skip as .mccollision() cannot be called registry.fill(HIST("h_fakecollisions"), 0.5); @@ -662,23 +888,25 @@ struct TrackEfficiency { registry.fill(HIST("h_collisions"), 2.5); registry.fill(HIST("h_collisions_weighted"), 2.5, eventWeight); - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); + float pTHat = getPtHatFromHepMCXSection ? collision.mcCollision_as>().mcCollision_as>().ptHard() : 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } registry.fill(HIST("h_collisions"), 3.5); - registry.fill(HIST("h2_centrality_collisions"), collision.centrality(), 3.5); - - fillTrackHistograms(collision, tracks, eventWeight); + registry.fill(HIST("h2_centrality_collisions"), collision.centFT0M(), 3.5, eventWeight); } - PROCESS_SWITCH(TrackEfficiency, processTracksMcWeighted, "QA for charged tracks in weighted MC", false); + PROCESS_SWITCH(TrackEfficiency, processCollisionsFromMcWeighted, "QA for reconstructed collisions in weighted MC", false); - void processParticles(aod::JetMcCollision const& mcCollision, - soa::SmallGroups const& collisions, - soa::Filtered const& mcparticles) + void processMcCollisions(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions) { + 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("h_mccollisions"), 0.5); - registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centrality(), 0.5); + registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centFT0M(), 0.5); if (!(std::abs(mcCollision.posZ()) < vertexZCut)) { return; @@ -690,12 +918,11 @@ struct TrackEfficiency { return; } - float pTHat = 10. / (std::pow(mcCollision.weight(), 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } registry.fill(HIST("h_mccollisions"), 1.5); - registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centrality(), 1.5); + registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centFT0M(), 1.5); bool hasSel8Coll = false; bool centralityCheck = false; @@ -703,7 +930,7 @@ struct TrackEfficiency { if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks @@ -711,7 +938,7 @@ struct TrackEfficiency { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } } @@ -723,21 +950,23 @@ struct TrackEfficiency { return; } registry.fill(HIST("h_mccollisions"), 2.5); - registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centrality(), 2.5); - - fillParticlesHistograms(collisions.begin(), mcparticles); + registry.fill(HIST("h2_centrality_mccollisions"), collisions.begin().centFT0M(), 2.5); } - PROCESS_SWITCH(TrackEfficiency, processParticles, "QA for charged particles", false); + PROCESS_SWITCH(TrackEfficiency, processMcCollisions, "QA for McCollisions in MC without weights", false); - void processParticlesWeighted(aod::JetMcCollision const& mcCollision, - soa::SmallGroups const& collisions, - soa::Filtered const& mcparticles) + void processMcCollisionsWeighted(soa::Join::iterator const& mcCollision, + soa::Join const&, + soa::SmallGroups const& collisions) { if (skipMBGapEvents && mcCollision.subGeneratorId() == jetderiveddatautilities::JCollisionSubGeneratorId::mbGap) { return; } 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); + registry.fill(HIST("h_mccollisions"), 0.5); registry.fill(HIST("h_mccollisions_weighted"), 0.5, eventWeight); @@ -751,7 +980,6 @@ struct TrackEfficiency { return; } - float pTHat = 10. / (std::pow(eventWeight, 1.0 / pTHatExponent)); if (pTHat < ptHatMin || pTHat > ptHatMax) { // only allows mcCollisions with weight in between min and max return; } @@ -764,7 +992,7 @@ struct TrackEfficiency { if (jetderiveddatautilities::selectCollision(collisions.begin(), eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collisions.begin().centrality()) && (collisions.begin().centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collisions.begin().centFT0M()) && (collisions.begin().centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } } else if (acceptSplitCollisions == SplitOkCheckAnyAssocColl) { // check that at least one of the reconstructed collisions passes the checks @@ -772,7 +1000,7 @@ struct TrackEfficiency { if (jetderiveddatautilities::selectCollision(collision, eventSelectionBits, skipMBGapEvents)) { // Skipping MC events that have not a single selected reconstructed collision ; effect unclear if mcColl is split hasSel8Coll = true; } - if (!checkCentrality || ((centralityMin < collision.centrality()) && (collision.centrality() < centralityMax))) { // effect unclear if mcColl is split + if (!checkCentrality || ((centralityMin < collision.centFT0M()) && (collision.centFT0M() < centralityMax))) { // effect unclear if mcColl is split centralityCheck = true; } } @@ -785,10 +1013,8 @@ struct TrackEfficiency { } registry.fill(HIST("h_mccollisions"), 2.5); registry.fill(HIST("h_mccollisions_weighted"), 2.5, eventWeight); - - fillParticlesHistograms(collisions.begin(), mcparticles, eventWeight); } - PROCESS_SWITCH(TrackEfficiency, processParticlesWeighted, "QA for charged particles weighted", false); + PROCESS_SWITCH(TrackEfficiency, processMcCollisionsWeighted, "QA for McCollisions in weighted MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/trackJetQA.cxx b/PWGJE/Tasks/trackJetQA.cxx index f0549a0a0e3..2f3c9a51eb6 100644 --- a/PWGJE/Tasks/trackJetQA.cxx +++ b/PWGJE/Tasks/trackJetQA.cxx @@ -15,27 +15,29 @@ /// \since 2023-10-02 /// \brief Task producing jet tracking qa histograms /// -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Framework/ASoA.h" +#include "PWGJE/DataModel/TrackJetQa.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.h" - -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/DataModel/TrackJetQa.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" - #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #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 using namespace o2; -using namespace o2::track; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/PWGJE/Tasks/triggerCorrelations.cxx b/PWGJE/Tasks/triggerCorrelations.cxx index bb2d43e1f95..2d7b54707bb 100644 --- a/PWGJE/Tasks/triggerCorrelations.cxx +++ b/PWGJE/Tasks/triggerCorrelations.cxx @@ -13,33 +13,26 @@ // /// \author Nima Zardoshti -#include +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "EMCALBase/Geometry.h" #include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" #include "Framework/HistogramRegistry.h" +#include +#include +#include +#include -#include "Common/Core/TrackSelection.h" -#include "Common/Core/TrackSelectionDefaults.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/CCDB/TriggerAliases.h" +#include -#include "PWGJE/Core/FastJetUtilities.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/EMCALClusters.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/DataModel/Jet.h" +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -#include "Framework/runDataProcessing.h" - struct TriggerCorrelationsTask { HistogramRegistry registry; @@ -79,6 +72,12 @@ struct TriggerCorrelationsTask { fillCorrelationsHistogram(collision); } PROCESS_SWITCH(TriggerCorrelationsTask, processTriggeredCorrelations, "QA for trigger correlations", true); + + void processTriggeredCorrelationsOffline(aod::JCollision const& collision) + { + fillCorrelationsHistogram(collision); + } + PROCESS_SWITCH(TriggerCorrelationsTask, processTriggeredCorrelationsOffline, "QA for trigger correlations in offline analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGJE/Tasks/v0JetSpectra.cxx b/PWGJE/Tasks/v0JetSpectra.cxx index 700f0b33b54..95081bad725 100644 --- a/PWGJE/Tasks/v0JetSpectra.cxx +++ b/PWGJE/Tasks/v0JetSpectra.cxx @@ -14,27 +14,23 @@ /// \author Gijs van Weelden // -#include -#include +#include "JetDerivedDataUtilities.h" -#include "TH1F.h" -#include "TTree.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" - -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include -#include "CommonConstants/PhysicsConstants.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" +#include +#include using namespace o2; using namespace o2::framework; diff --git a/PWGJE/Tasks/v0QA.cxx b/PWGJE/Tasks/v0QA.cxx index 8d8d0ab2cfc..3fb2215b51f 100644 --- a/PWGJE/Tasks/v0QA.cxx +++ b/PWGJE/Tasks/v0QA.cxx @@ -14,28 +14,31 @@ /// /// \author Gijs van Weelden -#include -#include +#include "JetDerivedDataUtilities.h" -#include "TH1F.h" -#include "TTree.h" +#include "PWGJE/Core/JetFindingUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/V0SelectorTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/RunningWorkflowInfo.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" +#include "Framework/ASoA.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include +#include +#include +#include +#include +#include -#include "CommonConstants/PhysicsConstants.h" +#include -#include "PWGJE/DataModel/Jet.h" -#include "PWGJE/Core/JetFinder.h" -#include "PWGJE/Core/JetUtilities.h" -#include "PWGJE/Core/JetFindingUtilities.h" -#include "PWGLF/DataModel/V0SelectorTables.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -54,45 +57,40 @@ using MCPV0JetsWithConstituents = soa::Join; using MatchedMCPV0JetsWithConstituents = soa::Join; +using JetMcCollisionsWithPIs = soa::Join; + struct V0QA { HistogramRegistry registry{"registry"}; Configurable evSel{"evSel", "sel8WithoutTimeFrameBorderCut", "choose event selection"}; - Configurable v0cospaMin{"v0cospaMin", 0.995, "Minimum V0 cosine of pointing angle"}; - Configurable v0radiusMin{"v0radiusMin", 0.5, "Minimum V0 radius (cm)"}; - Configurable dcav0dauMax{"dcav0dauMax", 1.0, "Maximum DCA between V0 daughters (cm)"}; - Configurable dcapiMin{"dcapiMin", 0.1, "Minimum DCA of pion daughter to PV (cm)"}; - Configurable dcaprMin{"dcaprMin", 0.1, "Minimum DCA of proton daughter to PV (cm)"}; - Configurable yK0SMax{"yK0SMax", 0.5, "Maximum rapidity of K0S"}; - Configurable yLambdaMax{"yLambdaMax", 0.5, "Maximum rapidity of Lambda(bar)"}; - Configurable lifetimeK0SMax{"lifetimeK0SMax", 20.0, "Maximum lifetime of K0S (cm)"}; - Configurable lifetimeLambdaMax{"lifetimeLambdaMax", 30.0, "Maximum lifetime of Lambda (cm)"}; Configurable yPartMax{"yPartMax", 0.5, "Maximum rapidity of particles"}; Configurable vertexZCut{"vertexZCut", 10.0, "Vertex Z cut"}; + Configurable v0Fraction{"v0Fraction", 1.0, "Fraction of V0s to be kept inside jets"}; Filter jetCollisionFilter = nabs(aod::jcollision::posZ) < vertexZCut; - ConfigurableAxis binPtJet{"ptJet", {100., 0.0f, 50.0f}, ""}; - ConfigurableAxis binPtV0{"ptV0", {100., 0.0f, 50.0f}, ""}; + ConfigurableAxis binPtJet{"binPtJet", {100., 0.0f, 50.0f}, ""}; + ConfigurableAxis binPtV0{"binPtV0", {100., 0.0f, 50.0f}, ""}; + ConfigurableAxis binZV0{"binZV0", {100., 1e-3f, 1 + 1e-3f}, ""}; ConfigurableAxis binEta{"binEta", {100, -1.0f, 1.0f}, ""}; ConfigurableAxis binPhi{"binPhi", {constants::math::PI * 10 / 2, 0.0f, constants::math::TwoPI}, ""}; ConfigurableAxis binInvMassK0S{"binInvMassK0S", {200, 0.4f, 0.6f}, ""}; ConfigurableAxis binInvMassLambda{"binInvMassLambda", {200, 1.07f, 1.17f}, ""}; - ConfigurableAxis binV0Radius{"R", {100., 0.0f, 50.0f}, ""}; - ConfigurableAxis binV0CosPA{"cosPA", {50., 0.95f, 1.0f}, ""}; + ConfigurableAxis binV0Radius{"binV0Radius", {100., 0.0f, 50.0f}, ""}; + ConfigurableAxis binV0CosPA{"binV0CosPA", {50., 0.95f, 1.0f}, ""}; ConfigurableAxis binsDcaXY{"binsDcaXY", {100, -0.5f, 0.5f}, ""}; ConfigurableAxis binsDcaZ{"binsDcaZ", {100, -5.f, 5.f}, ""}; - ConfigurableAxis binPtDiff{"ptdiff", {200., -49.5f, 50.5f}, ""}; - ConfigurableAxis binPtRelDiff{"ptreldiff", {100., -1.0f, 1.0f}, ""}; - ConfigurableAxis binITSNCl{"ITSNCl", {8, -0.5, 7.5}, ""}; - ConfigurableAxis binITSChi2NCl{"ITSChi2NCl", {100, 0, 40}, ""}; + ConfigurableAxis binPtDiff{"binPtDiff", {200., -49.5f, 50.5f}, ""}; + ConfigurableAxis binPtRelDiff{"binPtRelDiff", {100., -1.0f, 1.0f}, ""}; + ConfigurableAxis binITSNCl{"binITSNCl", {8, -0.5, 7.5}, ""}; + ConfigurableAxis binITSChi2NCl{"binITSChi2NCl", {100, 0, 40}, ""}; - ConfigurableAxis binTPCNCl{"TPCNCl", {165, -0.5, 164.5}, ""}; - ConfigurableAxis binTPCChi2NCl{"TPCChi2NCl", {100, 0, 10}, ""}; - ConfigurableAxis binTPCNClSharedFraction{"sharedFraction", {100, 0., 1.}, ""}; - ConfigurableAxis binTPCCrossedRowsOverFindableCl{"crossedOverFindable", {120, 0.0, 1.2}, ""}; + ConfigurableAxis binTPCNCl{"binTPCNCl", {165, -0.5, 164.5}, ""}; + ConfigurableAxis binTPCChi2NCl{"binTPCChi2NCl", {100, 0, 10}, ""}; + ConfigurableAxis binTPCNClSharedFraction{"binTPCNClSharedFraction", {100, 0., 1.}, ""}; + ConfigurableAxis binTPCCrossedRowsOverFindableCl{"binTPCCrossedRowsOverFindableCl", {120, 0.0, 1.2}, ""}; std::vector eventSelectionBits; @@ -102,6 +100,7 @@ struct V0QA { const AxisSpec axisJetPt{binPtJet, "Jet Pt (GeV/c)"}; const AxisSpec axisV0Pt{binPtV0, "V0 Pt (GeV/c)"}; + const AxisSpec axisV0Z{binZV0, "z_{V0} = #it{p}_{T, V0} / #it{p}_{T, jet}"}; const AxisSpec axisEta{binEta, "Eta"}; const AxisSpec axisPhi{binPhi, "Phi"}; const AxisSpec axisV0Radius{binV0Radius, "V0 Radius (cm)"}; @@ -130,18 +129,55 @@ struct V0QA { } if (doprocessMcD) { registry.add("inclusive/hEvents", "Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); + registry.add("inclusive/K0SPtEtaMass", "K0S Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisK0SM}); registry.add("inclusive/InvMassK0STrue", "Invariant mass of K0S", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisK0SM}); - registry.add("inclusive/InvMassLambdaTrue", "Invariant mass of Lambda", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisLambdaM}); + registry.add("inclusive/K0SPtEtaMassWrongCollision", "K0S Pt, Eta, Mass (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisK0SM}); registry.add("inclusive/LambdaPtEtaMass", "Lambda Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisLambdaM}); - registry.add("inclusive/InvMassAntiLambdaTrue", "Invariant mass of AntiLambda", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisAntiLambdaM}); + registry.add("inclusive/InvMassLambdaTrue", "Invariant mass of Lambda", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisLambdaM}); + registry.add("inclusive/LambdaPtEtaMassWrongCollision", "Lambda Pt, Eta, Mass (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisLambdaM}); registry.add("inclusive/AntiLambdaPtEtaMass", "AntiLambda Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisAntiLambdaM}); + registry.add("inclusive/InvMassAntiLambdaTrue", "Invariant mass of AntiLambda", HistType::kTH3D, {axisV0Pt, axisV0Radius, axisAntiLambdaM}); + registry.add("inclusive/AntiLambdaPtEtaMassWrongCollision", "AntiLambda Pt, Eta, Mass (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisAntiLambdaM}); + + registry.add("jets/JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetPtEtaK0SZ", "Jet Pt, Eta, K0S Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetPtEtaK0SPtWrongCollision", "Jet Pt, Eta, K0S Pt (Wrong Collision)", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetPtEtaK0SZWrongCollision", "Jet Pt, Eta, K0S Z (Wrong Collision)", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetPtEtaLambdaZ", "Jet Pt, Eta, Lambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetPtEtaLambdaPtWrongCollision", "Jet Pt, Eta, Lambda Pt (Wrong Collision)", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetPtEtaLambdaZWrongCollision", "Jet Pt, Eta, Lambda Z (Wrong Collision)", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetPtEtaAntiLambdaZ", "Jet Pt, Eta, AntiLambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetPtEtaAntiLambdaPtWrongCollision", "Jet Pt, Eta, AntiLambda Pt (Wrong Collision)", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetPtEtaAntiLambdaZWrongCollision", "Jet Pt, Eta, AntiLambda Z (Wrong Collision)", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + + registry.add("jets/JetsPtEtaK0SPt", "Matched Jet Pt, Eta, K0S Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetsPtEtaK0SZ", "Matched Jet Pt, Eta, K0S Z", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetsPtEtaK0SPtWrongCollision", "Matched Jet Pt, Eta, K0S Pt (Wrong Collision)", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetsPtEtaK0SZWrongCollision", "Matched Jet Pt, Eta, K0S Z (Wrong Collision)", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetsPtEtaLambdaPt", "Matched Jet Pt, Eta, Lambda Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetsPtEtaLambdaZ", "Matched Jet Pt, Eta, Lambda Z", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetsPtEtaLambdaPtWrongCollision", "Matched Jet Pt, Eta, Lambda Pt (Wrong Collision)", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetsPtEtaLambdaZWrongCollision", "Matched Jet Pt, Eta, Lambda Z (Wrong Collision)", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetsPtEtaAntiLambdaPt", "Matched Jet Pt, Eta, AntiLambda Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetsPtEtaAntiLambdaZ", "Matched Jet Pt, Eta, AntiLambda Z", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z}); + registry.add("jets/JetsPtEtaAntiLambdaPtWrongCollision", "Matched Jet Pt, Eta, AntiLambda Pt (Wrong Collision)", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/JetsPtEtaAntiLambdaZWrongCollision", "Matched Jet Pt, Eta, AntiLambda Z (Wrong Collision)", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z}); } if (doprocessMcP) { registry.add("inclusive/hMcEvents", "MC Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); registry.add("inclusive/GeneratedK0S", "Generated K0S", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Radius}); registry.add("inclusive/GeneratedLambda", "Generated Lambda", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Radius}); registry.add("inclusive/GeneratedAntiLambda", "Generated AntiLambda", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Radius}); + + registry.add("jets/GeneratedJetK0S", "Generated Jet K0S", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/GeneratedJetK0SFrag", "Generated Jet K0S", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("jets/GeneratedJetLambda", "Generated Jet Lambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/GeneratedJetLambdaFrag", "Generated Jet Lambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("jets/GeneratedJetAntiLambda", "Generated Jet AntiLambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/GeneratedJetAntiLambdaFrag", "Generated Jet AntiLambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); } if (doprocessMcDJets) { registry.add("jets/hJetEvents", "Jet Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); @@ -164,33 +200,42 @@ struct V0QA { if (doprocessMcPJets) { registry.add("jets/hMcJetEvents", "MC Jet Events", {HistType::kTH1D, {{2, 0.0f, 2.0f}}}); registry.add("jets/GeneratedJetK0S", "Generated Jet K0S", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/GeneratedJetK0SFrag", "Generated Jet K0S", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); registry.add("jets/GeneratedJetLambda", "Generated Jet Lambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/GeneratedJetLambdaFrag", "Generated Jet Lambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); registry.add("jets/GeneratedJetAntiLambda", "Generated Jet AntiLambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("jets/GeneratedJetAntiLambdaFrag", "Generated Jet AntiLambda", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); } if (doprocessCollisionAssociation) { registry.add("collisions/V0PtEta", "V0 Pt, Eta", HistType::kTH2D, {axisV0Pt, axisEta}); - registry.add("collisions/V0PtEtaWrongColl", "V0 Pt, Eta, wrong collision", HistType::kTH2D, {axisV0Pt, axisEta}); + registry.add("collisions/V0PtEtaWrongColl", "V0 Pt, Eta, (Wrong Collision)", HistType::kTH2D, {axisV0Pt, axisEta}); registry.add("collisions/K0SPtEtaMass", "K0S Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisK0SM}); - registry.add("collisions/K0SPtEtaMassWrongColl", "K0S Pt, Eta, Mass, wrong collision", HistType::kTH3D, {axisV0Pt, axisEta, axisK0SM}); + registry.add("collisions/K0SPtEtaMassWrongColl", "K0S Pt, Eta, Mass, (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisK0SM}); registry.add("collisions/LambdaPtEtaMass", "Lambda Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisLambdaM}); - registry.add("collisions/LambdaPtEtaMassWrongColl", "Lambda Pt, Eta, Mass, wrong collision", HistType::kTH3D, {axisV0Pt, axisEta, axisLambdaM}); + registry.add("collisions/LambdaPtEtaMassWrongColl", "Lambda Pt, Eta, Mass, (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisLambdaM}); registry.add("collisions/AntiLambdaPtEtaMass", "AntiLambda Pt, Eta, Mass", HistType::kTH3D, {axisV0Pt, axisEta, axisAntiLambdaM}); - registry.add("collisions/AntiLambdaPtEtaMassWrongColl", "AntiLambda Pt, Eta, Mass, wrong collision", HistType::kTH3D, {axisV0Pt, axisEta, axisAntiLambdaM}); + registry.add("collisions/AntiLambdaPtEtaMassWrongColl", "AntiLambda Pt, Eta, Mass, (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisAntiLambdaM}); registry.add("collisions/XiMinusPtYLambdaPt", "#Xi^{-} Pt, Y, #Lambda Pt", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Pt}); - registry.add("collisions/XiMinusPtYLambdaPtWrongColl", "#Xi^{-} Pt, Y, #Lambda Pt, wrong collision", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Pt}); + registry.add("collisions/XiMinusPtYLambdaPtWrongColl", "#Xi^{-} Pt, Y, #Lambda Pt, (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Pt}); registry.add("collisions/XiPlusPtYAntiLambdaPt", "#Xi^{+} Pt, Y, #bar{#Lambda} Pt", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Pt}); - registry.add("collisions/XiPlusPtYAntiLambdaPtWrongColl", "#Xi^{+} Pt, Y, #bar{#Lambda} Pt, wrong collision", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Pt}); + registry.add("collisions/XiPlusPtYAntiLambdaPtWrongColl", "#Xi^{+} Pt, Y, #bar{#Lambda} Pt, (Wrong Collision)", HistType::kTH3D, {axisV0Pt, axisEta, axisV0Pt}); } if (doprocessCollisionAssociationJets) { registry.add("collisions/JetPtEtaV0Pt", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); registry.add("collisions/JetPtEtaV0PtWrongColl", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); registry.add("collisions/JetPtEtaK0SPtMass", "Jet Pt, Eta, K0S Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisK0SM}); + registry.add("collisions/JetPtEtaK0SFragMass", "Jet Pt, Eta, K0S Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Z, axisK0SM}); registry.add("collisions/JetPtEtaK0SPtMassWrongColl", "Jet Pt, Eta, K0S Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisK0SM}); + registry.add("collisions/JetPtEtaK0SFragMassWrongColl", "Jet Pt, Eta, K0S Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Z, axisK0SM}); registry.add("collisions/JetPtEtaLambdaPtMass", "Jet Pt, Eta, Lambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisLambdaM}); + registry.add("collisions/JetPtEtaLambdaFragMass", "Jet Pt, Eta, Lambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Z, axisLambdaM}); registry.add("collisions/JetPtEtaLambdaPtMassWrongColl", "Jet Pt, Eta, Lambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisLambdaM}); + registry.add("collisions/JetPtEtaLambdaFragMassWrongColl", "Jet Pt, Eta, Lambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Z, axisLambdaM}); registry.add("collisions/JetPtEtaAntiLambdaPtMass", "Jet Pt, Eta, AntiLambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisAntiLambdaM}); + registry.add("collisions/JetPtEtaAntiLambdaFragMass", "Jet Pt, Eta, AntiLambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Z, axisAntiLambdaM}); registry.add("collisions/JetPtEtaAntiLambdaPtMassWrongColl", "Jet Pt, Eta, AntiLambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisAntiLambdaM}); + registry.add("collisions/JetPtEtaAntiLambdaFragMassWrongColl", "Jet Pt, Eta, AntiLambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Z, axisAntiLambdaM}); registry.add("collisions/JetPtEtaXiMinusPtLambdaPt", "Jet Pt, #Xi^{-} Pt, #Lambda Pt", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisV0Pt}); registry.add("collisions/JetPtEtaXiMinusPtLambdaPtWrongColl", "Jet Pt, #Xi^{-} Pt, #Lambda Pt", HistType::kTHnSparseD, {axisJetPt, axisEta, axisV0Pt, axisV0Pt}); @@ -201,11 +246,16 @@ struct V0QA { registry.add("collisions/JetsPtEtaV0Pt", "Jets Pt, Eta, V0 Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); registry.add("collisions/JetsPtEtaV0PtWrongColl", "Jets Pt, Eta, V0 Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt}); registry.add("collisions/JetsPtEtaK0SPtMass", "Jets Pt, Eta, K0S Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisK0SM}); - registry.add("collisions/JetsPtEtaK0SPtMassWrongColl", "Jets Pt, Eta, K0S Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisK0SM}); + registry.add("collisions/JetsPtEtaK0SFragMass", "Jets Pt, Eta, K0S Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z, axisK0SM}); + registry.add("collisions/JetsPtEtaK0SFragMassWrongColl", "Jets Pt, Eta, K0S Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z, axisK0SM}); registry.add("collisions/JetsPtEtaLambdaPtMass", "Jets Pt, Eta, Lambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisLambdaM}); + registry.add("collisions/JetsPtEtaLambdaFragMass", "Jets Pt, Eta, Lambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z, axisLambdaM}); registry.add("collisions/JetsPtEtaLambdaPtMassWrongColl", "Jets Pt, Eta, Lambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisLambdaM}); + registry.add("collisions/JetsPtEtaLambdaFragMassWrongColl", "Jets Pt, Eta, Lambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z, axisLambdaM}); registry.add("collisions/JetsPtEtaAntiLambdaPtMass", "Jets Pt, Eta, AntiLambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisAntiLambdaM}); + registry.add("collisions/JetsPtEtaAntiLambdaFragMass", "Jets Pt, Eta, AntiLambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z, axisAntiLambdaM}); registry.add("collisions/JetsPtEtaAntiLambdaPtMassWrongColl", "Jets Pt, Eta, AntiLambda Pt Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisAntiLambdaM}); + registry.add("collisions/JetsPtEtaAntiLambdaFragMassWrongColl", "Jets Pt, Eta, AntiLambda Frag Mass", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Z, axisAntiLambdaM}); registry.add("collisions/JetsPtEtaXiMinusPtLambdaPt", "Jets Pt, Eta, #Xi^{-} Pt, #Lambda Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisV0Pt}); registry.add("collisions/JetsPtEtaXiMinusPtLambdaPtWrongColl", "Jets Pt, Eta, #Xi^{-} Pt, #Lambda Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisEta, axisV0Pt, axisV0Pt}); @@ -224,6 +274,38 @@ struct V0QA { registry.add("feeddown/JetsPtXiMinusPtLambdaPt", "Jets Pt, #Xi^{-} Pt, #Lambda Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisV0Pt, axisV0Pt}); registry.add("feeddown/JetsPtXiPlusPtAntiLambdaPt", "Jets Pt, #Xi^{+} Pt, #bar{#Lambda} Pt", HistType::kTHnSparseD, {axisJetPt, axisJetPt, axisV0Pt, axisV0Pt}); } + if (doprocessTestWeightedJetFinder) { + registry.add("tests/weighted/JetPtEtaPhi", "Jet Pt, Eta, Phi", HistType::kTH3D, {axisJetPt, axisEta, axisPhi}); + registry.add("tests/weighted/JetPtEtaV0Pt", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaV0Z", "Jet Pt, Eta, V0 Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/weighted/JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaK0SZ", "Jet Pt, Eta, K0S Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/weighted/JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaLambdaZ", "Jet Pt, Eta, Lambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/weighted/JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/weighted/JetPtEtaAntiLambdaZ", "Jet Pt, Eta, AntiLambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + } + if (doprocessTestSubtractedJetFinder) { + registry.add("tests/nosub/JetPtEtaPhi", "Jet Pt, Eta, Phi", HistType::kTH3D, {axisJetPt, axisEta, axisPhi}); + registry.add("tests/nosub/JetPtEtaV0Pt", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaV0Z", "Jet Pt, Eta, V0 Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/nosub/JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaK0SZ", "Jet Pt, Eta, K0S Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/nosub/JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaLambdaZ", "Jet Pt, Eta, Lambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/nosub/JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/nosub/JetPtEtaAntiLambdaZ", "Jet Pt, Eta, AntiLambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + + registry.add("tests/sub/JetPtEtaPhi", "Jet Pt, Eta, Phi", HistType::kTH3D, {axisJetPt, axisEta, axisPhi}); + registry.add("tests/sub/JetPtEtaV0Pt", "Jet Pt, Eta, V0 Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaV0Z", "Jet Pt, Eta, V0 Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/sub/JetPtEtaK0SPt", "Jet Pt, Eta, K0S Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaK0SZ", "Jet Pt, Eta, K0S Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/sub/JetPtEtaLambdaPt", "Jet Pt, Eta, Lambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaLambdaZ", "Jet Pt, Eta, Lambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + registry.add("tests/sub/JetPtEtaAntiLambdaPt", "Jet Pt, Eta, AntiLambda Pt", HistType::kTH3D, {axisJetPt, axisEta, axisV0Pt}); + registry.add("tests/sub/JetPtEtaAntiLambdaZ", "Jet Pt, Eta, AntiLambda Z", HistType::kTH3D, {axisJetPt, axisEta, axisV0Z}); + } if (doprocessV0TrackQA) { registry.add("tracks/Pos", "pos", HistType::kTHnSparseD, {axisV0Pt, axisV0Pt, axisEta, axisPhi}); registry.add("tracks/Neg", "neg", HistType::kTHnSparseD, {axisV0Pt, axisV0Pt, axisEta, axisPhi}); @@ -427,6 +509,86 @@ struct V0QA { return (track.itsClusterMap() & (1 << ibit)); } + template + void fillMcDV0(T const& v0, bool correctCollision, double weight) + { + int pdg = v0.mcParticle().pdgCode(); + if (std::abs(pdg) == PDG_t::kK0Short) { + registry.fill(HIST("inclusive/K0SPtEtaMass"), v0.pt(), v0.eta(), v0.mK0Short(), weight); + registry.fill(HIST("inclusive/InvMassK0STrue"), v0.pt(), v0.v0radius(), v0.mK0Short(), weight); + if (!correctCollision) + registry.fill(HIST("inclusive/K0SPtEtaMassWrongCollision"), v0.pt(), v0.eta(), v0.mK0Short(), weight); + } else if (pdg == PDG_t::kLambda0) { + registry.fill(HIST("inclusive/LambdaPtEtaMass"), v0.pt(), v0.eta(), v0.mLambda(), weight); + registry.fill(HIST("inclusive/InvMassLambdaTrue"), v0.pt(), v0.v0radius(), v0.mLambda(), weight); + if (!correctCollision) + registry.fill(HIST("inclusive/LambdaPtEtaMassWrongCollision"), v0.pt(), v0.eta(), v0.mLambda(), weight); + } else if (pdg == PDG_t::kLambda0Bar) { + registry.fill(HIST("inclusive/AntiLambdaPtEtaMass"), v0.pt(), v0.eta(), v0.mAntiLambda(), weight); + registry.fill(HIST("inclusive/InvMassAntiLambdaTrue"), v0.pt(), v0.v0radius(), v0.mAntiLambda(), weight); + if (!correctCollision) + registry.fill(HIST("inclusive/AntiLambdaPtEtaMassWrongCollision"), v0.pt(), v0.eta(), v0.mAntiLambda(), weight); + } + } + + template + void fillMcDV0InJets(T const& mcdjet, U const& v0, bool correctCollision, double weight) + { + int pdg = v0.mcParticle().pdgCode(); + double z = v0.pt() / mcdjet.pt(); + if (std::abs(pdg) == PDG_t::kK0Short) { + registry.fill(HIST("jets/JetPtEtaK0SPt"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetPtEtaK0SZ"), mcdjet.pt(), mcdjet.eta(), z, weight); + if (!correctCollision) { + registry.fill(HIST("jets/JetPtEtaK0SPtWrongCollision"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetPtEtaK0SZWrongCollision"), mcdjet.pt(), mcdjet.eta(), z, weight); + } + } else if (pdg == PDG_t::kLambda0) { + registry.fill(HIST("jets/JetPtEtaLambdaPt"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetPtEtaLambdaZ"), mcdjet.pt(), mcdjet.eta(), z, weight); + if (!correctCollision) { + registry.fill(HIST("jets/JetPtEtaLambdaPtWrongCollision"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetPtEtaLambdaZWrongCollision"), mcdjet.pt(), mcdjet.eta(), z, weight); + } + } else if (pdg == PDG_t::kLambda0Bar) { + registry.fill(HIST("jets/JetPtEtaAntiLambdaPt"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetPtEtaAntiLambdaZ"), mcdjet.pt(), mcdjet.eta(), z, weight); + if (!correctCollision) { + registry.fill(HIST("jets/JetPtEtaAntiLambdaPtWrongCollision"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetPtEtaAntiLambdaZWrongCollision"), mcdjet.pt(), mcdjet.eta(), z, weight); + } + } + } + + template + void fillMcDV0InMatchedJets(T const& mcpjet, U const& mcdjet, V const& v0, bool correctCollision, double weight) + { + int pdg = v0.mcParticle().pdgCode(); + double z = v0.pt() / mcdjet.pt(); + if (std::abs(pdg) == PDG_t::kK0Short) { + registry.fill(HIST("jets/JetsPtEtaK0SPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetsPtEtaK0SZ"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), z, weight); + if (!correctCollision) { + registry.fill(HIST("jets/JetsPtEtaK0SPtWrongCollision"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetsPtEtaK0SZWrongCollision"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), z, weight); + } + } else if (pdg == PDG_t::kLambda0) { + registry.fill(HIST("jets/JetsPtEtaLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetsPtEtaLambdaZ"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), z, weight); + if (!correctCollision) { + registry.fill(HIST("jets/JetsPtEtaLambdaPtWrongCollision"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetsPtEtaLambdaZWrongCollision"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), z, weight); + } + } else if (pdg == PDG_t::kLambda0Bar) { + registry.fill(HIST("jets/JetsPtEtaAntiLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetsPtEtaAntiLambdaZ"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), z, weight); + if (!correctCollision) { + registry.fill(HIST("jets/JetsPtEtaAntiLambdaPtWrongCollision"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); + registry.fill(HIST("jets/JetsPtEtaAntiLambdaZWrongCollision"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), z, weight); + } + } + } + template void fillTrackQa(V const& v0) { @@ -684,42 +846,46 @@ struct V0QA { } PROCESS_SWITCH(V0QA, processFlags, "V0 flags", false); - void processMcD(soa::Filtered::iterator const& jcoll, aod::JetMcCollisions const&, CandidatesV0MCDWithFlags const& v0s, aod::McParticles const&) + void processMcD(soa::Filtered::iterator const& jcoll, CandidatesV0MCDWithFlags const& v0s, aod::McParticles const&, MatchedMCDV0JetsWithConstituents const& mcdjets, MatchedMCPV0JetsWithConstituents const&, aod::CandidatesV0MCP const&, aod::JetTracksMCD const& jTracks, JetMcCollisionsWithPIs const&, aod::McCollisions const&) { registry.fill(HIST("inclusive/hEvents"), 0.5); if (!isCollisionReconstructed(jcoll, eventSelectionBits)) { return; } registry.fill(HIST("inclusive/hEvents"), 1.5); - double weight = jcoll.mcCollision().weight(); + auto mcColl = jcoll.template mcCollision_as(); + double weight = mcColl.weight(); for (const auto& v0 : v0s) { - if (!v0.has_mcParticle()) + if (!v0.has_mcParticle() || v0.isRejectedCandidate()) continue; - if (v0.isRejectedCandidate()) - continue; + bool correctCollision = (mcColl.mcCollisionId() == v0.mcParticle().mcCollisionId()); + fillMcDV0(v0, correctCollision, weight); + } // v0 loop - int pdg = v0.mcParticle().pdgCode(); - // K0S - if (std::abs(pdg) == 310) { - registry.fill(HIST("inclusive/K0SPtEtaMass"), v0.pt(), v0.eta(), v0.mK0Short(), weight); - registry.fill(HIST("inclusive/InvMassK0STrue"), v0.pt(), v0.v0radius(), v0.mK0Short(), weight); - } - // Lambda - if (pdg == 3122) { - registry.fill(HIST("inclusive/LambdaPtEtaMass"), v0.pt(), v0.eta(), v0.mLambda(), weight); - registry.fill(HIST("inclusive/InvMassLambdaTrue"), v0.pt(), v0.v0radius(), v0.mLambda(), weight); - } - if (pdg == -3122) { - registry.fill(HIST("inclusive/AntiLambdaPtEtaMass"), v0.pt(), v0.eta(), v0.mAntiLambda(), weight); - registry.fill(HIST("inclusive/InvMassAntiLambdaTrue"), v0.pt(), v0.v0radius(), v0.mAntiLambda(), weight); - } - } + for (const auto& mcdjet : mcdjets) { + for (const auto& v0 : mcdjet.template candidates_as()) { + if (!v0.has_mcParticle() || v0.isRejectedCandidate()) + continue; + + bool correctCollision = (mcColl.mcCollisionId() == v0.mcParticle().mcCollisionId()); + fillMcDV0InJets(mcdjet, v0, correctCollision, weight); + + for (const auto& mcpjet : mcdjet.template matchedJetGeo_as()) { + for (const auto& pv0 : mcpjet.template candidates_as()) { + if (!v0sAreMatched(v0, pv0, jTracks)) + continue; + + fillMcDV0InMatchedJets(mcpjet, mcdjet, v0, correctCollision, weight); + } // v0 particle loop + } // mcpjet loop + } // v0 loop + } // mcd jet loop } PROCESS_SWITCH(V0QA, processMcD, "Reconstructed true V0s", false); - void processMcP(aod::JetMcCollision const& mccoll, aod::CandidatesV0MCP const& pv0s, soa::SmallGroups const& collisions) + void processMcP(aod::JetMcCollision const& mccoll, soa::SmallGroups const& collisions, MCPV0JetsWithConstituents const& jets, aod::CandidatesV0MCP const& pv0s) { registry.fill(HIST("inclusive/hMcEvents"), 0.5); bool isReconstructed = false; @@ -741,24 +907,47 @@ struct V0QA { double weight = mccoll.weight(); for (const auto& pv0 : pv0s) { - if (!pv0.has_daughters()) - continue; - if (!pv0.isPhysicalPrimary()) + if (!pv0.has_daughters() || !pv0.isPhysicalPrimary()) continue; if (std::abs(pv0.y()) > yPartMax) continue; // Can calculate this from aod::CandidatesV0MCD (contains decay vertex) - double r_Decay = 1.0; + double rDecay = 1.0; - if (pv0.pdgCode() == 310) { - registry.fill(HIST("inclusive/GeneratedK0S"), pv0.pt(), pv0.eta(), r_Decay, weight); + if (pv0.pdgCode() == PDG_t::kK0Short) { + registry.fill(HIST("inclusive/GeneratedK0S"), pv0.pt(), pv0.eta(), rDecay, weight); } - if (pv0.pdgCode() == 3122) { - registry.fill(HIST("inclusive/GeneratedLambda"), pv0.pt(), pv0.eta(), r_Decay, weight); + if (pv0.pdgCode() == PDG_t::kLambda0) { + registry.fill(HIST("inclusive/GeneratedLambda"), pv0.pt(), pv0.eta(), rDecay, weight); } - if (pv0.pdgCode() == -3122) { - registry.fill(HIST("inclusive/GeneratedAntiLambda"), pv0.pt(), pv0.eta(), r_Decay, weight); + if (pv0.pdgCode() == PDG_t::kLambda0Bar) { + registry.fill(HIST("inclusive/GeneratedAntiLambda"), pv0.pt(), pv0.eta(), rDecay, weight); + } + } + + for (const auto& jet : jets) { + if (!jetfindingutilities::isInEtaAcceptance(jet, -99., -99., -1. * yPartMax, yPartMax)) + continue; + + for (const auto& pv0 : jet.template candidates_as()) { + if (!pv0.has_daughters() || !pv0.isPhysicalPrimary()) + continue; + + double z = pv0.pt() / jet.pt(); + + if (pv0.pdgCode() == PDG_t::kK0Short) { + registry.fill(HIST("jets/GeneratedJetK0S"), jet.pt(), jet.eta(), pv0.pt(), weight); + registry.fill(HIST("jets/GeneratedJetK0SFrag"), jet.pt(), jet.eta(), z, weight); + } + if (pv0.pdgCode() == PDG_t::kLambda0) { + registry.fill(HIST("jets/GeneratedJetLambda"), jet.pt(), jet.eta(), pv0.pt(), weight); + registry.fill(HIST("jets/GeneratedJetLambdaFrag"), jet.pt(), jet.eta(), z, weight); + } + if (pv0.pdgCode() == PDG_t::kLambda0Bar) { + registry.fill(HIST("jets/GeneratedJetAntiLambda"), jet.pt(), jet.eta(), pv0.pt(), weight); + registry.fill(HIST("jets/GeneratedJetAntiLambdaFrag"), jet.pt(), jet.eta(), z, weight); + } } } } @@ -786,16 +975,16 @@ struct V0QA { continue; // K0S - if (std::abs(pdg) == 310) { + if (std::abs(pdg) == PDG_t::kK0Short) { registry.fill(HIST("jets/JetPtEtaK0SPt"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); registry.fill(HIST("jets/InvMassJetK0STrue"), mcdjet.pt(), v0.pt(), v0.mK0Short(), weight); } // Lambda - if (pdg == 3122) { + if (pdg == PDG_t::kLambda0) { registry.fill(HIST("jets/JetPtEtaLambdaPt"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); registry.fill(HIST("jets/InvMassJetLambdaTrue"), mcdjet.pt(), v0.pt(), v0.mLambda(), weight); } - if (pdg == -3122) { + if (pdg == PDG_t::kLambda0Bar) { registry.fill(HIST("jets/JetPtEtaAntiLambdaPt"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); registry.fill(HIST("jets/InvMassJetAntiLambdaTrue"), mcdjet.pt(), v0.pt(), v0.mAntiLambda(), weight); } @@ -830,16 +1019,16 @@ struct V0QA { continue; // K0S - if (std::abs(pdg) == 310) { + if (std::abs(pdg) == PDG_t::kK0Short) { registry.fill(HIST("jets/JetsPtEtaK0SPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); registry.fill(HIST("jets/InvMassJetsK0STrue"), mcpjet.pt(), mcdjet.pt(), v0.pt(), v0.mK0Short(), weight); } // Lambda - if (pdg == 3122) { + if (pdg == PDG_t::kLambda0) { registry.fill(HIST("jets/JetsPtEtaLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); registry.fill(HIST("jets/InvMassJetsLambdaTrue"), mcpjet.pt(), mcdjet.pt(), v0.pt(), v0.mLambda(), weight); } - if (pdg == -3122) { + if (pdg == PDG_t::kLambda0Bar) { registry.fill(HIST("jets/JetsPtEtaAntiLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); registry.fill(HIST("jets/InvMassJetsAntiLambdaTrue"), mcpjet.pt(), mcdjet.pt(), v0.pt(), v0.mAntiLambda(), weight); } @@ -881,27 +1070,30 @@ struct V0QA { if (!pv0.isPhysicalPrimary()) continue; - if (pv0.pdgCode() == 310) { + if (pv0.pdgCode() == PDG_t::kK0Short) { registry.fill(HIST("jets/GeneratedJetK0S"), jet.pt(), jet.eta(), pv0.pt(), weight); + registry.fill(HIST("jets/GeneratedJetK0SFrag"), jet.pt(), jet.eta(), pv0.pt() / jet.pt(), weight); } - if (pv0.pdgCode() == 3122) { + if (pv0.pdgCode() == PDG_t::kLambda0) { registry.fill(HIST("jets/GeneratedJetLambda"), jet.pt(), jet.eta(), pv0.pt(), weight); + registry.fill(HIST("jets/GeneratedJetLambdaFrag"), jet.pt(), jet.eta(), pv0.pt() / jet.pt(), weight); } - if (pv0.pdgCode() == -3122) { + if (pv0.pdgCode() == PDG_t::kLambda0Bar) { registry.fill(HIST("jets/GeneratedJetAntiLambda"), jet.pt(), jet.eta(), pv0.pt(), weight); + registry.fill(HIST("jets/GeneratedJetAntiLambdaFrag"), jet.pt(), jet.eta(), pv0.pt() / jet.pt(), weight); } } } } PROCESS_SWITCH(V0QA, processMcPJets, "Particle level V0s in jets", false); - void processCollisionAssociation(soa::Filtered::iterator const& jcoll, CandidatesV0MCDWithFlags const& v0s, soa::Join const&, aod::McCollisions const&, aod::McParticles const&) + void processCollisionAssociation(soa::Filtered::iterator const& jcoll, CandidatesV0MCDWithFlags const& v0s, JetMcCollisionsWithPIs const&, aod::McCollisions const&, aod::McParticles const&) { // Based on PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx if (!jcoll.has_mcCollision()) return; - auto mcColl = jcoll.template mcCollision_as>(); + auto mcColl = jcoll.template mcCollision_as(); double weight = mcColl.weight(); for (const auto& v0 : v0s) { @@ -920,19 +1112,19 @@ struct V0QA { if (!correctCollision) { registry.fill(HIST("collisions/V0PtEtaWrongColl"), pv0.pt(), pv0.eta(), weight); } - if (std::abs(pdg) == 310) { + if (std::abs(pdg) == PDG_t::kK0Short) { registry.fill(HIST("collisions/K0SPtEtaMass"), pv0.pt(), pv0.eta(), v0.mK0Short(), weight); if (!correctCollision) { registry.fill(HIST("collisions/K0SPtEtaMassWrongColl"), pv0.pt(), pv0.eta(), v0.mK0Short(), weight); } } - if (pdg == 3122) { + if (pdg == PDG_t::kLambda0) { registry.fill(HIST("collisions/LambdaPtEtaMass"), pv0.pt(), pv0.eta(), v0.mLambda(), weight); if (!correctCollision) { registry.fill(HIST("collisions/LambdaPtEtaMassWrongColl"), pv0.pt(), pv0.eta(), v0.mLambda(), weight); } } - if (pdg == -3122) { + if (pdg == PDG_t::kLambda0Bar) { registry.fill(HIST("collisions/AntiLambdaPtEtaMass"), pv0.pt(), pv0.eta(), v0.mAntiLambda(), weight); if (!correctCollision) { registry.fill(HIST("collisions/AntiLambdaPtEtaMassWrongColl"), pv0.pt(), pv0.eta(), v0.mAntiLambda(), weight); @@ -946,13 +1138,13 @@ struct V0QA { pdg = mother.pdgCode(); correctCollision = (mcColl.mcCollisionId() == mother.mcCollisionId()); - if (pdg == 3312) { // Xi- + if (pdg == PDG_t::kXiMinus) { registry.fill(HIST("collisions/XiMinusPtYLambdaPt"), mother.pt(), mother.y(), pv0.pt(), weight); if (!correctCollision) { registry.fill(HIST("collisions/XiMinusPtYLambdaPtWrongColl"), mother.pt(), mother.y(), pv0.pt(), weight); } } - if (pdg == -3312) { // Xi+ + if (pdg == PDG_t::kXiPlusBar) { registry.fill(HIST("collisions/XiPlusPtYAntiLambdaPt"), mother.pt(), mother.y(), pv0.pt(), weight); if (!correctCollision) { registry.fill(HIST("collisions/XiPlusPtYAntiLambdaPtWrongColl"), mother.pt(), mother.y(), pv0.pt(), weight); @@ -962,12 +1154,12 @@ struct V0QA { } PROCESS_SWITCH(V0QA, processCollisionAssociation, "V0 collision association", false); - void processCollisionAssociationJets(soa::Filtered::iterator const& jcoll, MCDV0JetsWithConstituents const& mcdjets, CandidatesV0MCDWithFlags const&, soa::Join const&, aod::McCollisions const&, aod::McParticles const&) + void processCollisionAssociationJets(soa::Filtered::iterator const& jcoll, MCDV0JetsWithConstituents const& mcdjets, CandidatesV0MCDWithFlags const&, JetMcCollisionsWithPIs const&, aod::McCollisions const&, aod::McParticles const&) { - if (!jcoll.has_mcCollision()) + if (!isCollisionReconstructed(jcoll, eventSelectionBits)) return; - auto mcColl = jcoll.template mcCollision_as>(); + auto mcColl = jcoll.template mcCollision_as(); double weight = mcColl.weight(); for (const auto& mcdjet : mcdjets) { @@ -979,31 +1171,38 @@ struct V0QA { auto pv0 = v0.mcParticle(); bool correctCollision = (mcColl.mcCollisionId() == pv0.mcCollisionId()); int pdg = pv0.pdgCode(); + double z = v0.pt() / mcdjet.pt(); // Check V0 decay kinematics if (v0.isRejectedCandidate()) continue; - registry.fill(HIST("collisions/JetPtEtaV0Pt"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetPtEtaV0Pt"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetPtEtaV0PtWrongColl"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetPtEtaV0PtWrongColl"), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); } - if (std::abs(pdg) == 310) { - registry.fill(HIST("collisions/JetPtEtaK0SPtMass"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mK0Short(), weight); + if (std::abs(pdg) == PDG_t::kK0Short) { + registry.fill(HIST("collisions/JetPtEtaK0SPtMass"), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mK0Short(), weight); + registry.fill(HIST("collisions/JetPtEtaK0SFragMass"), mcdjet.pt(), mcdjet.eta(), z, v0.mK0Short(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetPtEtaK0SPtMassWrongColl"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mK0Short(), weight); + registry.fill(HIST("collisions/JetPtEtaK0SPtMassWrongColl"), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mK0Short(), weight); + registry.fill(HIST("collisions/JetPtEtaK0SFragMassWrongColl"), mcdjet.pt(), mcdjet.eta(), z, v0.mK0Short(), weight); } } - if (pdg == 3122) { - registry.fill(HIST("collisions/JetPtEtaLambdaPtMass"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mLambda(), weight); + if (pdg == PDG_t::kLambda0) { + registry.fill(HIST("collisions/JetPtEtaLambdaPtMass"), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mLambda(), weight); + registry.fill(HIST("collisions/JetPtEtaLambdaFragMass"), mcdjet.pt(), mcdjet.eta(), z, v0.mLambda(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetPtEtaLambdaPtMassWrongColl"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mLambda(), weight); + registry.fill(HIST("collisions/JetPtEtaLambdaPtMassWrongColl"), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mLambda(), weight); + registry.fill(HIST("collisions/JetPtEtaLambdaFragMassWrongColl"), mcdjet.pt(), mcdjet.eta(), z, v0.mLambda(), weight); } } - if (pdg == -3122) { - registry.fill(HIST("collisions/JetPtEtaAntiLambdaPtMass"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mAntiLambda(), weight); + if (pdg == PDG_t::kLambda0Bar) { + registry.fill(HIST("collisions/JetPtEtaAntiLambdaPtMass"), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mAntiLambda(), weight); + registry.fill(HIST("collisions/JetPtEtaAntiLambdaFragMass"), mcdjet.pt(), mcdjet.eta(), z, v0.mAntiLambda(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetPtEtaAntiLambdaPtMassWrongColl"), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mAntiLambda(), weight); + registry.fill(HIST("collisions/JetPtEtaAntiLambdaPtMassWrongColl"), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mAntiLambda(), weight); + registry.fill(HIST("collisions/JetPtEtaAntiLambdaFragMassWrongColl"), mcdjet.pt(), mcdjet.eta(), z, v0.mAntiLambda(), weight); } } @@ -1013,16 +1212,16 @@ struct V0QA { auto mother = v0.mcMotherParticle(); pdg = mother.pdgCode(); correctCollision = (mcColl.mcCollisionId() == mother.mcCollisionId()); - if (pdg == 3312) { // Xi- - registry.fill(HIST("collisions/JetPtEtaXiMinusPtLambdaPt"), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + if (pdg == PDG_t::kXiMinus) { + registry.fill(HIST("collisions/JetPtEtaXiMinusPtLambdaPt"), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetPtEtaXiMinusPtLambdaPtWrongColl"), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetPtEtaXiMinusPtLambdaPtWrongColl"), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); } } - if (pdg == -3312) { // Xi+ - registry.fill(HIST("collisions/JetPtEtaXiPlusPtAntiLambdaPt"), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + if (pdg == PDG_t::kXiPlusBar) { + registry.fill(HIST("collisions/JetPtEtaXiPlusPtAntiLambdaPt"), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetPtEtaXiPlusPtAntiLambdaPtWrongColl"), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetPtEtaXiPlusPtAntiLambdaPtWrongColl"), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); } } } // for v0s @@ -1030,12 +1229,12 @@ struct V0QA { } PROCESS_SWITCH(V0QA, processCollisionAssociationJets, "V0 in jets collision association", false); - void processCollisionAssociationMatchedJets(soa::Filtered::iterator const& jcoll, MatchedMCDV0JetsWithConstituents const& mcdjets, MatchedMCPV0JetsWithConstituents const&, CandidatesV0MCDWithFlags const&, aod::CandidatesV0MCP const&, soa::Join const&, aod::McCollisions const&, aod::McParticles const&, aod::JetTracksMCD const& jTracks) + void processCollisionAssociationMatchedJets(soa::Filtered::iterator const& jcoll, MatchedMCDV0JetsWithConstituents const& mcdjets, MatchedMCPV0JetsWithConstituents const&, CandidatesV0MCDWithFlags const&, aod::CandidatesV0MCP const&, JetMcCollisionsWithPIs const&, aod::McCollisions const&, aod::McParticles const&, aod::JetTracksMCD const& jTracks) { if (!jcoll.has_mcCollision()) return; - auto mcColl = jcoll.template mcCollision_as>(); + auto mcColl = jcoll.template mcCollision_as(); double weight = mcColl.weight(); for (const auto& mcdjet : mcdjets) { @@ -1050,31 +1249,38 @@ struct V0QA { int pdg = pv0.pdgCode(); bool correctCollision = (mcColl.mcCollisionId() == pv0.mcCollisionId()); + double z = v0.pt() / mcdjet.pt(); // Check V0 decay kinematics if (v0.isRejectedCandidate()) continue; - registry.fill(HIST("collisions/JetsPtEtaV0Pt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetsPtEtaV0Pt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetsPtEtaV0PtWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetsPtEtaV0PtWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), weight); } - if (std::abs(pdg) == 310) { - registry.fill(HIST("collisions/JetsPtEtaK0SPtMass"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mK0Short(), weight); + if (std::abs(pdg) == PDG_t::kK0Short) { + registry.fill(HIST("collisions/JetsPtEtaK0SPtMass"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mK0Short(), weight); + registry.fill(HIST("collisions/JetsPtEtaK0SFragMass"), mcpjet.pt(), mcdjet.eta(), z, v0.mK0Short(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetsPtEtaK0SPtMassWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mK0Short(), weight); + registry.fill(HIST("collisions/JetsPtEtaK0SPtMassWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mK0Short(), weight); + registry.fill(HIST("collisions/JetsPtEtaK0SFragMassWrongColl"), mcpjet.pt(), mcdjet.eta(), z, v0.mK0Short(), weight); } } - if (pdg == 3122) { - registry.fill(HIST("collisions/JetsPtEtaLambdaPtMass"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mLambda(), weight); + if (pdg == PDG_t::kLambda0) { + registry.fill(HIST("collisions/JetsPtEtaLambdaPtMass"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mLambda(), weight); + registry.fill(HIST("collisions/JetsPtEtaLambdaFragMass"), mcpjet.pt(), mcdjet.eta(), z, v0.mLambda(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetsPtEtaLambdaPtMassWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mLambda(), weight); + registry.fill(HIST("collisions/JetsPtEtaLambdaPtMassWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mLambda(), weight); + registry.fill(HIST("collisions/JetsPtEtaLambdaFragMassWrongColl"), mcpjet.pt(), mcdjet.eta(), z, v0.mLambda(), weight); } } - if (pdg == -3122) { - registry.fill(HIST("collisions/JetsPtEtaAntiLambdaPtMass"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mAntiLambda(), weight); + if (pdg == PDG_t::kLambda0Bar) { + registry.fill(HIST("collisions/JetsPtEtaAntiLambdaPtMass"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mAntiLambda(), weight); + registry.fill(HIST("collisions/JetsPtEtaAntiLambdaFragMass"), mcpjet.pt(), mcdjet.eta(), z, v0.mAntiLambda(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetsPtEtaAntiLambdaPtMassWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), pv0.pt(), v0.mAntiLambda(), weight); + registry.fill(HIST("collisions/JetsPtEtaAntiLambdaPtMassWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), v0.pt(), v0.mAntiLambda(), weight); + registry.fill(HIST("collisions/JetsPtEtaAntiLambdaFragMassWrongColl"), mcpjet.pt(), mcdjet.eta(), z, v0.mAntiLambda(), weight); } } @@ -1084,16 +1290,16 @@ struct V0QA { auto mother = v0.mcMotherParticle(); pdg = mother.pdgCode(); correctCollision = (mcColl.mcCollisionId() == mother.mcCollisionId()); - if (pdg == 3312) { // Xi- - registry.fill(HIST("collisions/JetsPtEtaXiMinusPtLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + if (pdg == PDG_t::kXiMinus) { + registry.fill(HIST("collisions/JetsPtEtaXiMinusPtLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetsPtEtaXiMinusPtLambdaPtWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetsPtEtaXiMinusPtLambdaPtWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); } } - if (pdg == -3312) { // Xi+ - registry.fill(HIST("collisions/JetsPtEtaXiPlusPtAntiLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + if (pdg == PDG_t::kXiPlusBar) { + registry.fill(HIST("collisions/JetsPtEtaXiPlusPtAntiLambdaPt"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); if (!correctCollision) { - registry.fill(HIST("collisions/JetsPtEtaXiPlusPtAntiLambdaPtWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), pv0.pt(), weight); + registry.fill(HIST("collisions/JetsPtEtaXiPlusPtAntiLambdaPtWrongColl"), mcpjet.pt(), mcdjet.pt(), mcdjet.eta(), mother.pt(), v0.pt(), weight); } } } // for pv0 @@ -1103,13 +1309,13 @@ struct V0QA { } PROCESS_SWITCH(V0QA, processCollisionAssociationMatchedJets, "V0 in matched jets collision association", false); - void processFeeddown(soa::Filtered::iterator const& jcoll, CandidatesV0MCDWithFlags const& v0s, aod::CandidatesV0MCP const&, soa::Join const&, aod::McCollisions const&, aod::McParticles const&) + void processFeeddown(soa::Filtered::iterator const& jcoll, CandidatesV0MCDWithFlags const& v0s, aod::CandidatesV0MCP const&, JetMcCollisionsWithPIs const&, aod::McCollisions const&, aod::McParticles const&) { // Based on PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx if (!jcoll.has_mcCollision()) return; - auto mcColl = jcoll.template mcCollision_as>(); + auto mcColl = jcoll.template mcCollision_as(); double weight = mcColl.weight(); for (const auto& v0 : v0s) { @@ -1129,23 +1335,23 @@ struct V0QA { auto mother = v0.mcMotherParticle(); pdg = mother.pdgCode(); - if (pdg == 3312) { // Xi- + if (pdg == PDG_t::kXiMinus) { registry.fill(HIST("feeddown/XiMinusPtYLambdaPt"), mother.pt(), mother.y(), pv0.pt(), weight); } - if (pdg == -3312) { // Xi+ + if (pdg == PDG_t::kXiPlusBar) { registry.fill(HIST("feeddown/XiPlusPtYAntiLambdaPt"), mother.pt(), mother.y(), pv0.pt(), weight); } } } PROCESS_SWITCH(V0QA, processFeeddown, "Inclusive feeddown", false); - void processFeeddownJets(soa::Filtered::iterator const& jcoll, MCDV0JetsWithConstituents const& mcdjets, CandidatesV0MCDWithFlags const&, aod::CandidatesV0MCP const&, soa::Join const&, aod::McCollisions const&, aod::McParticles const&) + void processFeeddownJets(soa::Filtered::iterator const& jcoll, MCDV0JetsWithConstituents const& mcdjets, CandidatesV0MCDWithFlags const&, aod::CandidatesV0MCP const&, JetMcCollisionsWithPIs const&, aod::McCollisions const&, aod::McParticles const&) { // Based on PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx if (!jcoll.has_mcCollision()) return; - auto mcColl = jcoll.template mcCollision_as>(); + auto mcColl = jcoll.template mcCollision_as(); double weight = mcColl.weight(); for (const auto& mcdjet : mcdjets) { @@ -1166,10 +1372,10 @@ struct V0QA { auto mother = v0.mcMotherParticle(); pdg = mother.pdgCode(); - if (pdg == 3312) { // Xi- + if (pdg == PDG_t::kXiMinus) { registry.fill(HIST("feeddown/JetPtXiMinusPtLambdaPt"), mcdjet.pt(), mother.pt(), pv0.pt(), weight); } - if (pdg == -3312) { // Xi+ + if (pdg == PDG_t::kXiPlusBar) { registry.fill(HIST("feeddown/JetPtXiPlusPtAntiLambdaPt"), mcdjet.pt(), mother.pt(), pv0.pt(), weight); } } @@ -1177,13 +1383,13 @@ struct V0QA { } PROCESS_SWITCH(V0QA, processFeeddownJets, "Jets feeddown", false); - void processFeeddownMatchedJets(soa::Filtered::iterator const& jcoll, MatchedMCDV0JetsWithConstituents const& mcdjets, aod::JetTracksMCD const& jTracks, MatchedMCPV0JetsWithConstituents const&, CandidatesV0MCDWithFlags const&, aod::CandidatesV0MCP const&, soa::Join const&, aod::McCollisions const&, aod::McParticles const&) + void processFeeddownMatchedJets(soa::Filtered::iterator const& jcoll, MatchedMCDV0JetsWithConstituents const& mcdjets, aod::JetTracksMCD const& jTracks, MatchedMCPV0JetsWithConstituents const&, CandidatesV0MCDWithFlags const&, aod::CandidatesV0MCP const&, JetMcCollisionsWithPIs const&, aod::McCollisions const&, aod::McParticles const&) { // Based on PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx if (!jcoll.has_mcCollision()) return; - auto mcColl = jcoll.template mcCollision_as>(); + auto mcColl = jcoll.template mcCollision_as(); double weight = mcColl.weight(); for (const auto& mcdjet : mcdjets) { @@ -1206,10 +1412,10 @@ struct V0QA { auto mother = v0.mcMotherParticle(); pdg = mother.pdgCode(); - if (pdg == 3312) { // Xi- + if (pdg == PDG_t::kXiMinus) { registry.fill(HIST("feeddown/JetsPtXiMinusPtLambdaPt"), mcpjet.pt(), mcdjet.pt(), mother.pt(), pv0.pt(), weight); } - if (pdg == -3312) { // Xi+ + if (pdg == PDG_t::kXiPlusBar) { registry.fill(HIST("feeddown/JetsPtXiPlusPtAntiLambdaPt"), mcpjet.pt(), mcdjet.pt(), mother.pt(), pv0.pt(), weight); } } @@ -1219,6 +1425,110 @@ struct V0QA { } PROCESS_SWITCH(V0QA, processFeeddownMatchedJets, "Jets feeddown", false); + // Test the difference between excluding V0s from jet finding and subtracting V0s from jets afterwards + void processTestWeightedJetFinder(soa::Filtered::iterator const& jcoll, soa::Join const& jets, aod::CandidatesV0Data const&) + { + if (!jetderiveddatautilities::selectCollision(jcoll, eventSelectionBits)) + return; + + for (const auto& jet : jets) { + registry.fill(HIST("tests/weighted/JetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + + for (const auto& v0 : jet.template candidates_as()) { + if (v0.isRejectedCandidate()) + continue; + + double z = v0.pt() / jet.pt(); + + registry.fill(HIST("tests/weighted/JetPtEtaV0Pt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaV0Z"), jet.pt(), jet.eta(), z); + + if (v0.isK0SCandidate()) { + registry.fill(HIST("tests/weighted/JetPtEtaK0SPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaK0SZ"), jet.pt(), jet.eta(), z); + } + if (v0.isLambdaCandidate()) { + registry.fill(HIST("tests/weighted/JetPtEtaLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaLambdaZ"), jet.pt(), jet.eta(), z); + } + if (v0.isAntiLambdaCandidate()) { + registry.fill(HIST("tests/weighted/JetPtEtaAntiLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/weighted/JetPtEtaAntiLambdaZ"), jet.pt(), jet.eta(), z); + } + } + } + } + PROCESS_SWITCH(V0QA, processTestWeightedJetFinder, "Test weighted jet finder", false); + + void processTestSubtractedJetFinder(soa::Filtered::iterator const& jcoll, soa::Join const& jets, aod::CandidatesV0Data const&) + { + if (!jetderiveddatautilities::selectCollision(jcoll, eventSelectionBits)) + return; + + for (const auto& jet : jets) { + registry.fill(HIST("tests/nosub/JetPtEtaPhi"), jet.pt(), jet.eta(), jet.phi()); + + std::vector v0Pt; + std::vector v0Type; + double ptjetsub = jet.pt(); + + for (const auto& v0 : jet.template candidates_as()) { + double z = v0.pt() / jet.pt(); + + registry.fill(HIST("tests/nosub/JetPtEtaV0Pt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaV0Z"), jet.pt(), jet.eta(), z); + + if (v0.isK0SCandidate()) { + registry.fill(HIST("tests/nosub/JetPtEtaK0SPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaK0SZ"), jet.pt(), jet.eta(), z); + } + if (v0.isLambdaCandidate()) { + registry.fill(HIST("tests/nosub/JetPtEtaLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaLambdaZ"), jet.pt(), jet.eta(), z); + } + if (v0.isAntiLambdaCandidate()) { + registry.fill(HIST("tests/nosub/JetPtEtaAntiLambdaPt"), jet.pt(), jet.eta(), v0.pt()); + registry.fill(HIST("tests/nosub/JetPtEtaAntiLambdaZ"), jet.pt(), jet.eta(), z); + } + + if (gRandom->Uniform() > v0Fraction) { // Rejected V0 + ptjetsub -= v0.pt(); + } else { // Accepted V0 + v0Pt.push_back(v0.pt()); + if (v0.isK0SCandidate()) { + v0Type.push_back(PDG_t::kK0Short); + } else if (v0.isLambdaCandidate()) { + v0Type.push_back(PDG_t::kLambda0); + } else if (v0.isAntiLambdaCandidate()) { + v0Type.push_back(PDG_t::kLambda0Bar); + } + } + } // V0s in jet loop + + registry.fill(HIST("tests/sub/JetPtEtaPhi"), ptjetsub, jet.eta(), jet.phi()); + for (unsigned int i = 0; i < v0Pt.size(); ++i) { + int type = v0Type[i]; + double pt = v0Pt[i]; + double z = pt / ptjetsub; + + registry.fill(HIST("tests/sub/JetPtEtaV0Pt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaV0Z"), ptjetsub, jet.eta(), z); + + if (type == PDG_t::kK0Short) { + registry.fill(HIST("tests/sub/JetPtEtaK0SPt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaK0SZ"), ptjetsub, jet.eta(), z); + } else if (type == PDG_t::kLambda0) { + registry.fill(HIST("tests/sub/JetPtEtaLambdaPt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaLambdaZ"), ptjetsub, jet.eta(), z); + } else if (type == PDG_t::kLambda0Bar) { + registry.fill(HIST("tests/sub/JetPtEtaAntiLambdaPt"), ptjetsub, jet.eta(), pt); + registry.fill(HIST("tests/sub/JetPtEtaAntiLambdaZ"), ptjetsub, jet.eta(), z); + } + } // Accepted V0s in jet loop + } // Jets loop + } + PROCESS_SWITCH(V0QA, processTestSubtractedJetFinder, "Test subtracted jet finder", false); + using DaughterJTracks = soa::Join; using DaughterTracks = soa::Join; void processV0TrackQA(aod::JetCollision const& /*jcoll*/, aod::CandidatesV0Data const& v0s, DaughterJTracks const&, DaughterTracks const&) diff --git a/PWGLF/DataModel/LFCKSSpinalignmentTables.h b/PWGLF/DataModel/LFCKSSpinalignmentTables.h new file mode 100644 index 00000000000..6593d22fe6b --- /dev/null +++ b/PWGLF/DataModel/LFCKSSpinalignmentTables.h @@ -0,0 +1,108 @@ +// 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 LFCKSSpinalignmentTables.h +/// \brief DataModel for Charged KStar spin alignment +/// +/// \author Prottay Das + +#ifndef PWGLF_DATAMODEL_LFCKSSPINALIGNMENTTABLES_H_ +#define PWGLF_DATAMODEL_LFCKSSPINALIGNMENTTABLES_H_ + +#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 + +namespace o2::aod +{ +namespace kshortpionevent +{ +DECLARE_SOA_COLUMN(Cent, cent, float); +DECLARE_SOA_COLUMN(Posz, posz, 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); +} // namespace kshortpionevent +DECLARE_SOA_TABLE(KShortpionEvents, "AOD", "KSHORTPIONEVENT", + o2::soa::Index<>, + kshortpionevent::Cent, + kshortpionevent::Posz, + kshortpionevent::CollIndex, + kshortpionevent::PsiFT0C, + kshortpionevent::PsiFT0A, + kshortpionevent::PsiTPC) +using KShortpionEvent = KShortpionEvents::iterator; + +namespace kshortpionpair +{ +DECLARE_SOA_INDEX_COLUMN(KShortpionEvent, kshortpionevent); +DECLARE_SOA_COLUMN(V0Cospa, v0Cospa, float); //! V0 Cospa +DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); //! V0 Radius +DECLARE_SOA_COLUMN(DcaPositive, dcaPositive, float); //! DCA Positive +DECLARE_SOA_COLUMN(DcaNegative, dcaNegative, float); //! DCA Negative +DECLARE_SOA_COLUMN(DcaBetweenDaughter, dcaBetweenDaughter, float); //! DCA between daughters +DECLARE_SOA_COLUMN(V0Lifetime, v0Lifetime, float); //! KShort lifetime +DECLARE_SOA_COLUMN(KShortPx, kShortPx, float); //! KShort Px +DECLARE_SOA_COLUMN(KShortPy, kShortPy, float); //! KShort Py +DECLARE_SOA_COLUMN(KShortPz, kShortPz, float); //! KShort Pz +DECLARE_SOA_COLUMN(KShortMass, kShortMass, float); //! KShort Mass +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(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 +} // namespace kshortpionpair +DECLARE_SOA_TABLE(KShortTracks, "AOD", "KSHORTTRACK", + o2::soa::Index<>, + kshortpionpair::KShortpionEventId, + kshortpionpair::V0Cospa, + kshortpionpair::V0Radius, + kshortpionpair::DcaPositive, + kshortpionpair::DcaNegative, + kshortpionpair::DcaBetweenDaughter, + kshortpionpair::V0Lifetime, + // kshortpionpair::Armenteros, + kshortpionpair::KShortPx, + kshortpionpair::KShortPy, + kshortpionpair::KShortPz, + kshortpionpair::KShortMass, + kshortpionpair::PionIndex1, + kshortpionpair::PionIndex2); + +using KShortTrack = KShortTracks::iterator; + +DECLARE_SOA_TABLE(PionTracks, "AOD", "PIONTRACK", + o2::soa::Index<>, + kshortpionpair::KShortpionEventId, + kshortpionpair::PionBachPx, + kshortpionpair::PionBachPy, + kshortpionpair::PionBachPz, + // kshortpionpair::PionBachSign, + kshortpionpair::PionBachTPC, + kshortpionpair::PionBachTOFHit, + kshortpionpair::PionBachTOF, + kshortpionpair::PionBachIndex); + +using PionTrack = PionTracks::iterator; +} // namespace o2::aod +#endif // PWGLF_DATAMODEL_LFCKSSPINALIGNMENTTABLES_H_ diff --git a/PWGLF/DataModel/LFClusterStudiesTable.h b/PWGLF/DataModel/LFClusterStudiesTable.h index 88ca35a85d3..5c4755bbfcc 100644 --- a/PWGLF/DataModel/LFClusterStudiesTable.h +++ b/PWGLF/DataModel/LFClusterStudiesTable.h @@ -11,8 +11,8 @@ // // Author: Giorgio Alberto Lucia -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" #ifndef PWGLF_DATAMODEL_LFCLUSTERSTUDIESTABLE_H_ #define PWGLF_DATAMODEL_LFCLUSTERSTUDIESTABLE_H_ @@ -79,36 +79,10 @@ DECLARE_SOA_TABLE( DECLARE_SOA_TABLE( ClStTableMc, "AOD", "CLSTTABLEMC", - LFClusterStudiesTables::P, - LFClusterStudiesTables::Eta, - LFClusterStudiesTables::Phi, - LFClusterStudiesTables::ItsClusterSize, - LFClusterStudiesTables::PartID, LFClusterStudiesTables::PartIDMc); DECLARE_SOA_TABLE( ClStTableExtra, "AOD", "CLSTTABLEEXTRA", - LFClusterStudiesTables::P, - LFClusterStudiesTables::Eta, - LFClusterStudiesTables::Phi, - LFClusterStudiesTables::ItsClusterSize, - LFClusterStudiesTables::PartID, - LFClusterStudiesTables::PTPC, - LFClusterStudiesTables::PIDinTrk, - LFClusterStudiesTables::TpcNSigma, - LFClusterStudiesTables::TofNSigma, - LFClusterStudiesTables::TofMass, - LFClusterStudiesTables::CosPAMother, - LFClusterStudiesTables::MassMother); - -DECLARE_SOA_TABLE( - ClStTableMcExt, "AOD", "CLSTTABLEMCEXT", - LFClusterStudiesTables::P, - LFClusterStudiesTables::Eta, - LFClusterStudiesTables::Phi, - LFClusterStudiesTables::ItsClusterSize, - LFClusterStudiesTables::PartID, - LFClusterStudiesTables::PartIDMc, LFClusterStudiesTables::PTPC, LFClusterStudiesTables::PIDinTrk, LFClusterStudiesTables::TpcNSigma, diff --git a/PWGLF/DataModel/LFEbyeTables.h b/PWGLF/DataModel/LFEbyeTables.h index d7ff437ece4..59876ae59c1 100644 --- a/PWGLF/DataModel/LFEbyeTables.h +++ b/PWGLF/DataModel/LFEbyeTables.h @@ -24,8 +24,8 @@ DECLARE_SOA_COLUMN(Centrality, centrality, uint8_t); DECLARE_SOA_COLUMN(Zvtx, zvtx, float); DECLARE_SOA_COLUMN(ZvtxMask, zvtxMask, int8_t); DECLARE_SOA_COLUMN(TriggerMask, triggerMask, uint8_t); -DECLARE_SOA_COLUMN(Ntracklets, ntracklets, uint8_t); -DECLARE_SOA_COLUMN(V0Multiplicity, v0Multiplicity, uint8_t); +DECLARE_SOA_COLUMN(CBMultiplicity, cbMultiplicity, uint8_t); +DECLARE_SOA_COLUMN(Ntracks, ntracks, uint8_t); } // namespace LFEbyeCollTable DECLARE_SOA_TABLE(CollEbyeTables, "AOD", "COLLEBYETABLE", @@ -38,8 +38,9 @@ DECLARE_SOA_TABLE(MiniCollTables, "AOD", "MINICOLLTABLE", o2::soa::Index<>, LFEbyeCollTable::ZvtxMask, LFEbyeCollTable::TriggerMask, - LFEbyeCollTable::Ntracklets, - LFEbyeCollTable::V0Multiplicity); + LFEbyeCollTable::CBMultiplicity, + LFEbyeCollTable::Centrality, + LFEbyeCollTable::Ntracks); using MiniCollTable = MiniCollTables::iterator; namespace LFEbyeTable diff --git a/PWGLF/DataModel/LFHStrangeCorrelationTables.h b/PWGLF/DataModel/LFHStrangeCorrelationTables.h index 62b50667263..cbeedbdb66c 100644 --- a/PWGLF/DataModel/LFHStrangeCorrelationTables.h +++ b/PWGLF/DataModel/LFHStrangeCorrelationTables.h @@ -22,10 +22,15 @@ #ifndef PWGLF_DATAMODEL_LFHSTRANGECORRELATIONTABLES_H_ #define PWGLF_DATAMODEL_LFHSTRANGECORRELATIONTABLES_H_ -#include -#include "Framework/AnalysisDataModel.h" +/// this data model uses the LF one, add here +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/RecoDecay.h" + #include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisDataModel.h" + +#include // Simple checker #define bitcheck(var, nbit) ((var) & (1 << (nbit))) diff --git a/PWGLF/DataModel/LFHyperNucleiKinkTables.h b/PWGLF/DataModel/LFHyperNucleiKinkTables.h new file mode 100644 index 00000000000..a661e4dec32 --- /dev/null +++ b/PWGLF/DataModel/LFHyperNucleiKinkTables.h @@ -0,0 +1,126 @@ +// 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 LFHyperNucleiKinkTables.h +/// \brief Slim hypernuclei kink tables +/// \author Yuanzhe Wang + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + +#ifndef PWGLF_DATAMODEL_LFHYPERNUCLEIKINKTABLES_H_ +#define PWGLF_DATAMODEL_LFHYPERNUCLEIKINKTABLES_H_ + +namespace o2::aod +{ + +namespace hyperkink +{ +DECLARE_SOA_COLUMN(MagPolarity, magPolarity, int8_t); //! Magnetic field polarity +DECLARE_SOA_COLUMN(XPV, xPV, float); //! Primary vertex of the candidate (x direction) +DECLARE_SOA_COLUMN(YPV, yPV, float); //! Primary vertex of the candidate (y direction) +DECLARE_SOA_COLUMN(ZPV, zPV, float); //! Primary vertex of the candidate (z direction) +DECLARE_SOA_COLUMN(XSV, xSV, float); //! Decay vertex of the candidate (x direction) +DECLARE_SOA_COLUMN(YSV, ySV, float); //! Decay vertex of the candidate (y direction) +DECLARE_SOA_COLUMN(ZSV, zSV, float); //! Decay vertex of the candidate (z direction) +DECLARE_SOA_COLUMN(XMothIU, xMothIU, float); //! X of the mother track at the radii of ITS layer which has the outermost update +DECLARE_SOA_COLUMN(YMothIU, yMothIU, float); //! Y of the mother track at the radii of ITS layer which has the outermost update +DECLARE_SOA_COLUMN(ZMothIU, zMothIU, float); //! Z of the mother track at the radii of ITS layer which has the outermost update +DECLARE_SOA_COLUMN(PxMothSV, pxMothSV, float); //! Px of the mother track at the decay vertex +DECLARE_SOA_COLUMN(PyMothSV, pyMothSV, float); //! Py of the mother track at the decay vertex +DECLARE_SOA_COLUMN(PzMothSV, pzMothSV, float); //! Pz of the mother track at the decay vertex +DECLARE_SOA_COLUMN(RefitPxMothPV, refitPxMothPV, float); //! Refit Px of the mother track at the primary vertex +DECLARE_SOA_COLUMN(RefitPyMothPV, refitPyMothPV, float); //! Refit Py of the mother track at the primary vertex +DECLARE_SOA_COLUMN(RefitPzMothPV, refitPzMothPV, float); //! Refit Pz of the mother track at the primary vertex +DECLARE_SOA_COLUMN(RefitPxMothSV, refitPxMothSV, float); //! Refit Px of the mother track at the decay vertex +DECLARE_SOA_COLUMN(RefitPyMothSV, refitPyMothSV, float); //! Refit Py of the mother track at the decay vertex +DECLARE_SOA_COLUMN(RefitPzMothSV, refitPzMothSV, float); //! Refit Pz of the mother track at the decay vertex +DECLARE_SOA_COLUMN(PxDaugSV, pxDaugSV, float); //! Px of the daughter track at the decay vertex +DECLARE_SOA_COLUMN(PyDaugSV, pyDaugSV, float); //! Py of the daughter track at the decay vertex +DECLARE_SOA_COLUMN(PzDaugSV, pzDaugSV, float); //! Pz of the daughter track at the decay vertex +DECLARE_SOA_COLUMN(IsMatter, isMatter, bool); //! bool: true for matter +DECLARE_SOA_COLUMN(DcaMothPv, dcaMothPv, float); //! DCA of the mother to the primary vertex +DECLARE_SOA_COLUMN(DcaDaugPv, dcaDaugPv, float); //! DCA of the daughter kink to the primary vertex +DECLARE_SOA_COLUMN(DcaKinkTopo, dcaKinkTopo, float); //! DCA of the kink topology +DECLARE_SOA_COLUMN(ItsChi2Moth, itsChi2Moth, float); //! ITS chi2 of the mother track +DECLARE_SOA_COLUMN(ItsClusterSizesMoth, itsClusterSizesMoth, uint32_t); //! ITS cluster size of the mother track +DECLARE_SOA_COLUMN(ItsClusterSizesDaug, itsClusterSizesDaug, uint32_t); //! ITS cluster size of the daughter track +DECLARE_SOA_COLUMN(NSigmaTPCDaug, nSigmaTPCDaug, float); //! Number of tpc sigmas of the daughter track +DECLARE_SOA_COLUMN(NSigmaITSDaug, nSigmaITSDaug, float); //! Number of ITS sigmas of the daughter track +DECLARE_SOA_COLUMN(NSigmaTOFDaug, nSigmaTOFDaug, float); //! Number of TOF sigmas of the daughter track + +DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); //! bool: true for hyperhelium4signal +DECLARE_SOA_COLUMN(IsSignalReco, isSignalReco, bool); //! bool: true if the signal is reconstructed +DECLARE_SOA_COLUMN(IsCollReco, isCollReco, bool); //! bool: true if the collision is reconstructed +DECLARE_SOA_COLUMN(IsSurvEvSelection, isSurvEvSelection, bool); //! bool: true for the collision passed the event selection +DECLARE_SOA_COLUMN(TrueXSV, trueXSV, float); //! true x decay vertex +DECLARE_SOA_COLUMN(TrueYSV, trueYSV, float); //! true y decay vertex +DECLARE_SOA_COLUMN(TrueZSV, trueZSV, float); //! true z decay vertex +DECLARE_SOA_COLUMN(TruePxMothPV, truePxMothPV, float); //! Generated px of the mother track +DECLARE_SOA_COLUMN(TruePyMothPV, truePyMothPV, float); //! Generated py of the mother track +DECLARE_SOA_COLUMN(TruePzMothPV, truePzMothPV, float); //! Generated pz of the mother track +DECLARE_SOA_COLUMN(TruePxMothSV, truePxMothSV, float); //! true px of the mother track at the decay vertex +DECLARE_SOA_COLUMN(TruePyMothSV, truePyMothSV, float); //! true py of the mother track at the decay vertex +DECLARE_SOA_COLUMN(TruePzMothSV, truePzMothSV, float); //! true pz of the mother track at the decay vertex +DECLARE_SOA_COLUMN(TruePxDaugSV, truePxDaugSV, float); //! true px of the daughter track at the decay vertex +DECLARE_SOA_COLUMN(TruePyDaugSV, truePyDaugSV, float); //! true py of the daughter track at the decay vertex +DECLARE_SOA_COLUMN(TruePzDaugSV, truePzDaugSV, float); //! true pz of the daughter track at the decay vertex +DECLARE_SOA_COLUMN(IsMothReco, isMothReco, bool); //! bool: true if the mother track is reconstructed +DECLARE_SOA_COLUMN(PxMothPV, pxMothPV, float); //! reconstructed px of the mother track at the primary vertex +DECLARE_SOA_COLUMN(PyMothPV, pyMothPV, float); //! reconstructed py of the mother track at the primary vertex +DECLARE_SOA_COLUMN(PzMothPV, pzMothPV, float); //! reconstructed pz of the mother track at the primary vertex +DECLARE_SOA_COLUMN(UpdatePxMothPV, updatePxMothPV, float); //! updated px of the mother track at the primary vertex after update using PV +DECLARE_SOA_COLUMN(UpdatePyMothPV, updatePyMothPV, float); //! updated py of the mother track at the primary vertex after update using PV +DECLARE_SOA_COLUMN(UpdatePzMothPV, updatePzMothPV, float); //! updated pz of the mother track at the primary vertex after update using PV +} // namespace hyperkink + +DECLARE_SOA_TABLE(HypKinkCand, "AOD", "HYPKINKCANDS", + o2::soa::Index<>, + hyperkink::MagPolarity, + hyperkink::XPV, hyperkink::YPV, hyperkink::ZPV, + hyperkink::XSV, hyperkink::YSV, hyperkink::ZSV, + hyperkink::IsMatter, + hyperkink::XMothIU, hyperkink::YMothIU, hyperkink::ZMothIU, + hyperkink::PxMothSV, hyperkink::PyMothSV, hyperkink::PzMothSV, + hyperkink::RefitPxMothPV, hyperkink::RefitPyMothPV, hyperkink::RefitPzMothPV, + hyperkink::RefitPxMothSV, hyperkink::RefitPyMothSV, hyperkink::RefitPzMothSV, + hyperkink::PxDaugSV, hyperkink::PyDaugSV, hyperkink::PzDaugSV, + hyperkink::DcaMothPv, hyperkink::DcaDaugPv, hyperkink::DcaKinkTopo, + hyperkink::ItsChi2Moth, hyperkink::ItsClusterSizesMoth, hyperkink::ItsClusterSizesDaug, + hyperkink::NSigmaTPCDaug, hyperkink::NSigmaITSDaug, hyperkink::NSigmaTOFDaug, + hyperkink::PxMothPV, hyperkink::PyMothPV, hyperkink::PzMothPV, + hyperkink::UpdatePxMothPV, hyperkink::UpdatePyMothPV, hyperkink::UpdatePzMothPV); + +DECLARE_SOA_TABLE(MCHypKinkCand, "AOD", "MCHYPKINKCANDS", + o2::soa::Index<>, + hyperkink::MagPolarity, + hyperkink::XPV, hyperkink::YPV, hyperkink::ZPV, + hyperkink::XSV, hyperkink::YSV, hyperkink::ZSV, + hyperkink::IsMatter, + hyperkink::XMothIU, hyperkink::YMothIU, hyperkink::ZMothIU, + hyperkink::PxMothSV, hyperkink::PyMothSV, hyperkink::PzMothSV, + hyperkink::RefitPxMothPV, hyperkink::RefitPyMothPV, hyperkink::RefitPzMothPV, + hyperkink::RefitPxMothSV, hyperkink::RefitPyMothSV, hyperkink::RefitPzMothSV, + hyperkink::PxDaugSV, hyperkink::PyDaugSV, hyperkink::PzDaugSV, + hyperkink::DcaMothPv, hyperkink::DcaDaugPv, hyperkink::DcaKinkTopo, + hyperkink::ItsChi2Moth, hyperkink::ItsClusterSizesMoth, hyperkink::ItsClusterSizesDaug, + hyperkink::NSigmaTPCDaug, hyperkink::NSigmaITSDaug, hyperkink::NSigmaTOFDaug, + hyperkink::IsSignal, hyperkink::IsSignalReco, hyperkink::IsCollReco, hyperkink::IsSurvEvSelection, + hyperkink::TrueXSV, hyperkink::TrueYSV, hyperkink::TrueZSV, + hyperkink::TruePxMothPV, hyperkink::TruePyMothPV, hyperkink::TruePzMothPV, + hyperkink::TruePxMothSV, hyperkink::TruePyMothSV, hyperkink::TruePzMothSV, + hyperkink::TruePxDaugSV, hyperkink::TruePyDaugSV, hyperkink::TruePzDaugSV, + hyperkink::IsMothReco, hyperkink::PxMothPV, hyperkink::PyMothPV, hyperkink::PzMothPV, + hyperkink::UpdatePxMothPV, hyperkink::UpdatePyMothPV, hyperkink::UpdatePzMothPV); + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFHYPERNUCLEIKINKTABLES_H_ diff --git a/PWGLF/DataModel/LFHyperhelium4sigmaTables.h b/PWGLF/DataModel/LFHyperhelium4sigmaTables.h deleted file mode 100644 index 71e04a281cf..00000000000 --- a/PWGLF/DataModel/LFHyperhelium4sigmaTables.h +++ /dev/null @@ -1,93 +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 LFHyperhelium4sigmaTables.h -/// \brief Slim hyperhelium4sigma tables -/// \author Yuanzhe Wang - -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" - -#ifndef PWGLF_DATAMODEL_LFHYPERHELIUM4SIGMATABLES_H_ -#define PWGLF_DATAMODEL_LFHYPERHELIUM4SIGMATABLES_H_ - -namespace o2::aod -{ - -namespace he4scand -{ -DECLARE_SOA_COLUMN(XPrimVtx, xPrimVtx, float); // Primary vertex of the candidate (x direction) -DECLARE_SOA_COLUMN(YPrimVtx, yPrimVtx, float); // Primary vertex of the candidate (y direction) -DECLARE_SOA_COLUMN(ZPrimVtx, zPrimVtx, float); // Primary vertex of the candidate (z direction) -DECLARE_SOA_COLUMN(XDecVtx, xDecVtx, float); // Decay vertex of the candidate (x direction) -DECLARE_SOA_COLUMN(YDecVtx, yDecVtx, float); // Decay vertex of the candidate (y direction) -DECLARE_SOA_COLUMN(ZDecVtx, zDecVtx, float); // Decay vertex of the candidate (z direction) -DECLARE_SOA_COLUMN(PxMoth, pxMoth, float); //! Px of the mother track at the decay vertex -DECLARE_SOA_COLUMN(PyMoth, pyMoth, float); //! Py of the mother track at the decay vertex -DECLARE_SOA_COLUMN(PzMoth, pzMoth, float); //! Pz of the mother track at the decay vertex -DECLARE_SOA_COLUMN(PxAlpha, pxAlpha, float); //! Px of the daughter alpha track at the decay vertex -DECLARE_SOA_COLUMN(PyAlpha, pyAlpha, float); //! Py of the daughter alpha track at the decay vertex -DECLARE_SOA_COLUMN(PzAlpha, pzAlpha, float); //! Pz of the daughter alpha track at the decay vertex -DECLARE_SOA_COLUMN(IsMatter, isMatter, bool); // bool: true for matter -DECLARE_SOA_COLUMN(DcaMothPv, dcaMothPv, float); //! DCA of the mother to the primary vertex -DECLARE_SOA_COLUMN(DcaAlphaPv, dcaAlphaPv, float); //! DCA of the daughter kink to the primary vertex -DECLARE_SOA_COLUMN(DcaKinkTopo, dcaKinkTopo, float); //! DCA of the kink topology -DECLARE_SOA_COLUMN(ItsChi2Moth, itsChi2Moth, float); // ITS chi2 of the mother track -DECLARE_SOA_COLUMN(ItsClusterSizesMoth, itsClusterSizesMoth, uint32_t); // ITS cluster size of the mother track -DECLARE_SOA_COLUMN(ItsClusterSizesAlpha, itsClusterSizesAlpha, uint32_t); // ITS cluster size of the daughter alpha track -DECLARE_SOA_COLUMN(NSigmaTPCAlpha, nSigmaTPCAlpha, float); // Number of tpc sigmas of the daughter alpha track - -DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); // bool: true for hyperhelium4signal -DECLARE_SOA_COLUMN(IsSignalReco, isSignalReco, bool); // bool: true if the signal is reconstructed -DECLARE_SOA_COLUMN(IsCollReco, isCollReco, bool); // bool: true if the collision is reconstructed -DECLARE_SOA_COLUMN(IsSurvEvSelection, isSurvEvSelection, bool); // bool: true for the collision passed the event selection -DECLARE_SOA_COLUMN(TrueXDecVtx, trueXDecVtx, float); // true x decay vertex -DECLARE_SOA_COLUMN(TrueYDecVtx, trueYDecVtx, float); // true y decay vertex -DECLARE_SOA_COLUMN(TrueZDecVtx, trueZDecVtx, float); // true z decay vertex -DECLARE_SOA_COLUMN(GenPxMoth, genPxMoth, float); // Generated px of the mother track -DECLARE_SOA_COLUMN(GenPyMoth, genPyMoth, float); // Generated py of the mother track -DECLARE_SOA_COLUMN(GenPzMoth, genPzMoth, float); // Generated pz of the mother track -DECLARE_SOA_COLUMN(GenPxAlpha, genPxAlpha, float); // true px of the daughter alpha track -DECLARE_SOA_COLUMN(GenPyAlpha, genPyAlpha, float); // true py of the daughter alpha track -DECLARE_SOA_COLUMN(GenPzAlpha, genPzAlpha, float); // true pz of the daughter alpha track -DECLARE_SOA_COLUMN(IsMothReco, isMothReco, bool); // bool: true if the mother track is reconstructed -DECLARE_SOA_COLUMN(RecoPtMoth, recoPtMoth, float); // reconstructed pt of the mother track -DECLARE_SOA_COLUMN(RecoPzMoth, recoPzMoth, float); // reconstructed pz of the mother track -} // namespace he4scand - -DECLARE_SOA_TABLE(He4S2BCands, "AOD", "HE4S2BCANDS", - o2::soa::Index<>, - he4scand::XPrimVtx, he4scand::YPrimVtx, he4scand::ZPrimVtx, - he4scand::XDecVtx, he4scand::YDecVtx, he4scand::ZDecVtx, - he4scand::IsMatter, he4scand::PxMoth, he4scand::PyMoth, he4scand::PzMoth, - he4scand::PxAlpha, he4scand::PyAlpha, he4scand::PzAlpha, - he4scand::DcaMothPv, he4scand::DcaAlphaPv, he4scand::DcaKinkTopo, - he4scand::ItsChi2Moth, he4scand::ItsClusterSizesMoth, he4scand::ItsClusterSizesAlpha, - he4scand::NSigmaTPCAlpha); - -DECLARE_SOA_TABLE(MCHe4S2BCands, "AOD", "MCHE4S2BCANDS", - o2::soa::Index<>, - he4scand::XPrimVtx, he4scand::YPrimVtx, he4scand::ZPrimVtx, - he4scand::XDecVtx, he4scand::YDecVtx, he4scand::ZDecVtx, - he4scand::IsMatter, he4scand::PxMoth, he4scand::PyMoth, he4scand::PzMoth, - he4scand::PxAlpha, he4scand::PyAlpha, he4scand::PzAlpha, - he4scand::DcaMothPv, he4scand::DcaAlphaPv, he4scand::DcaKinkTopo, - he4scand::ItsChi2Moth, he4scand::ItsClusterSizesMoth, he4scand::ItsClusterSizesAlpha, - he4scand::NSigmaTPCAlpha, - he4scand::IsSignal, he4scand::IsSignalReco, he4scand::IsCollReco, he4scand::IsSurvEvSelection, - he4scand::TrueXDecVtx, he4scand::TrueYDecVtx, he4scand::TrueZDecVtx, - he4scand::GenPxMoth, he4scand::GenPyMoth, he4scand::GenPzMoth, - he4scand::GenPxAlpha, he4scand::GenPyAlpha, he4scand::GenPzAlpha, - he4scand::IsMothReco, he4scand::RecoPtMoth, he4scand::RecoPzMoth); - -} // namespace o2::aod - -#endif // PWGLF_DATAMODEL_LFHYPERHELIUM4SIGMATABLES_H_ diff --git a/PWGLF/DataModel/LFHypernucleiTables.h b/PWGLF/DataModel/LFHypernucleiTables.h index eeccdcdf26f..f0f37bf4d86 100644 --- a/PWGLF/DataModel/LFHypernucleiTables.h +++ b/PWGLF/DataModel/LFHypernucleiTables.h @@ -55,9 +55,13 @@ DECLARE_SOA_COLUMN(CosPA, cosPA, double); // Cosine DECLARE_SOA_COLUMN(NSigmaHe, nSigmaHe, float); // Number of sigmas of the He daughter DECLARE_SOA_COLUMN(NTPCclusHe, nTPCclusHe, uint8_t); // Number of TPC clusters of the He daughter 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(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 +DECLARE_SOA_COLUMN(ITSChi2He, itsChi2He, float); // ITS chi2 of the He daughter +DECLARE_SOA_COLUMN(ITSChi2Pi, itsChi2Pi, float); // ITS chi2 of the Pi daughter DECLARE_SOA_COLUMN(TrackedClSize, trackedClSize, int); // int: zero for non-tracked candidates DECLARE_SOA_COLUMN(Flags, flags, uint8_t); // Flags for PID in tracking (bits [0, 3] for negative daughter, [4,7] for positive daughter) DECLARE_SOA_COLUMN(TPCmomHe, tpcMomHe, float); // TPC momentum of the He daughter @@ -91,8 +95,8 @@ 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::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, hyperrec::Flags, hyperrec::TrackedClSize); @@ -110,8 +114,8 @@ 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::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, hyperrec::Flags, hyperrec::TrackedClSize); @@ -126,8 +130,8 @@ 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::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, + hyperrec::NSigmaHe, hyperrec::NTPCclusHe, hyperrec::NTPCclusPi, hyperrec::NTPCpidClusHe, hyperrec::NTPCpidClusPi, + hyperrec::TPCmomHe, hyperrec::TPCmomPi, hyperrec::TPCsignalHe, hyperrec::TPCsignalPi, hyperrec::TPCChi2He, hyperrec::ITSChi2He, hyperrec::ITSChi2Pi, hyperrec::TOFMass, hyperrec::ITSclusterSizesHe, hyperrec::ITSclusterSizesPi, hyperrec::Flags, hyperrec::TrackedClSize, diff --git a/PWGLF/DataModel/LFKinkDecayTables.h b/PWGLF/DataModel/LFKinkDecayTables.h index 5f8798856d5..d8df2eb865f 100644 --- a/PWGLF/DataModel/LFKinkDecayTables.h +++ b/PWGLF/DataModel/LFKinkDecayTables.h @@ -15,10 +15,11 @@ /// \author Francesco Mazzaschi /// -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "Common/Core/RecoDecay.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + #ifndef PWGLF_DATAMODEL_LFKINKDECAYTABLES_H_ #define PWGLF_DATAMODEL_LFKINKDECAYTABLES_H_ @@ -46,6 +47,21 @@ DECLARE_SOA_COLUMN(DcaMothPv, dcaMothPv, float); //! DCA of the mother to th DECLARE_SOA_COLUMN(DcaDaugPv, dcaDaugPv, float); //! DCA of the daughter kink to the primary vertex DECLARE_SOA_COLUMN(DcaKinkTopo, dcaKinkTopo, float); //! DCA of the kink topology +DECLARE_SOA_COLUMN(NSigmaTPCPi, nSigmaTPCPi, float); //! Number of sigmas for the pion candidate from Sigma kink in TPC +DECLARE_SOA_COLUMN(NSigmaTPCPr, nSigmaTPCPr, float); //! Number of sigmas for the proton candidate from Sigma kink in TPC +DECLARE_SOA_COLUMN(NSigmaTPCKa, nSigmaTPCKa, float); //! Number of sigmas for the kaon candidate from Sigma kink in TPC +DECLARE_SOA_COLUMN(NSigmaTOFPi, nSigmaTOFPi, float); //! Number of sigmas for the pion candidate from Sigma kink in TOF +DECLARE_SOA_COLUMN(NSigmaTOFPr, nSigmaTOFPr, float); //! Number of sigmas for the proton candidate from Sigma kink in TOF +DECLARE_SOA_COLUMN(NSigmaTOFKa, nSigmaTOFKa, float); //! Number of sigmas for the kaon candidate from Sigma kink in TOF + +// MC Columns +DECLARE_SOA_COLUMN(MothPdgCode, mothPdgCode, int); //! PDG code of the Sigma daughter +DECLARE_SOA_COLUMN(DaugPdgCode, daugPdgCode, int); //! PDG code of the kink daughter +DECLARE_SOA_COLUMN(PtMC, ptMC, float); //! pT of the candidate in MC +DECLARE_SOA_COLUMN(MassMC, massMC, float); //! Invariant mass of the candidate in MC +DECLARE_SOA_COLUMN(DecayRadiusMC, decayRadiusMC, float); //! Decay radius of the candidate in MC +DECLARE_SOA_COLUMN(CollisionIdCheck, collisionIdCheck, bool); //! Check if mcDaughter collision ID matches the reconstructed collision ID + // DYNAMIC COLUMNS DECLARE_SOA_DYNAMIC_COLUMN(PxDaugNeut, pxDaugNeut, //! Px of the daughter neutral particle @@ -77,6 +93,13 @@ DECLARE_SOA_DYNAMIC_COLUMN(MSigmaPlus, mSigmaPlus, //! mass under sigma plus hyp float pzneut = pzmoth - pzch; return RecoDecay::m(std::array{std::array{pxch, pych, pzch}, std::array{pxneut, pyneut, pzneut}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionNeutral}); }); +DECLARE_SOA_DYNAMIC_COLUMN(MXiMinus, mXiMinus, //! mass under Xi minus hypothesis + [](float pxmoth, float pymoth, float pzmoth, float pxch, float pych, float pzch) -> float { + float pxneut = pxmoth - pxch; + float pyneut = pymoth - pych; + float pzneut = pzmoth - pzch; + return RecoDecay::m(std::array{std::array{pxch, pych, pzch}, std::array{pxneut, pyneut, pzneut}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassLambda}); }); + } // namespace kinkcand DECLARE_SOA_TABLE(KinkCands, "AOD", "KINKCANDS", @@ -93,7 +116,44 @@ DECLARE_SOA_TABLE(KinkCands, "AOD", "KINKCANDS", kinkcand::PtMoth, kinkcand::PtDaug, kinkcand::MSigmaMinus, - kinkcand::MSigmaPlus); + kinkcand::MSigmaPlus, + kinkcand::MXiMinus); + +DECLARE_SOA_TABLE(KinkCandsUnbound, "AOD", "UBKINKCANDS", + o2::soa::Index<>, kinkcand::XDecVtx, kinkcand::YDecVtx, kinkcand::ZDecVtx, + kinkcand::MothSign, kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, + kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, + kinkcand::DcaMothPv, kinkcand::DcaDaugPv, kinkcand::DcaKinkTopo, + + // dynamic columns + kinkcand::PxDaugNeut, + kinkcand::PyDaugNeut, + kinkcand::PzDaugNeut, + kinkcand::PtMoth, + kinkcand::PtDaug, + kinkcand::MSigmaMinus, + kinkcand::MSigmaPlus, + kinkcand::MXiMinus); + +DECLARE_SOA_TABLE(SlimKinkCands, "AOD", "SLIMKINKCANDS", + kinkcand::XDecVtx, kinkcand::YDecVtx, kinkcand::ZDecVtx, + kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, + kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, + kinkcand::DcaMothPv, kinkcand::DcaDaugPv, kinkcand::DcaKinkTopo, + kinkcand::MothSign, + kinkcand::NSigmaTPCPi, kinkcand::NSigmaTPCPr, kinkcand::NSigmaTPCKa, + kinkcand::NSigmaTOFPi, kinkcand::NSigmaTOFPr, kinkcand::NSigmaTOFKa); + +DECLARE_SOA_TABLE(SlimKinkCandsMC, "AOD", "SLIMKINKCANDSMC", + kinkcand::XDecVtx, kinkcand::YDecVtx, kinkcand::ZDecVtx, + kinkcand::PxMoth, kinkcand::PyMoth, kinkcand::PzMoth, + kinkcand::PxDaug, kinkcand::PyDaug, kinkcand::PzDaug, + kinkcand::DcaMothPv, kinkcand::DcaDaugPv, kinkcand::DcaKinkTopo, + kinkcand::MothSign, + kinkcand::NSigmaTPCPi, kinkcand::NSigmaTPCPr, kinkcand::NSigmaTPCKa, + kinkcand::NSigmaTOFPi, kinkcand::NSigmaTOFPr, kinkcand::NSigmaTOFKa, + kinkcand::MothPdgCode, kinkcand::DaugPdgCode, + kinkcand::PtMC, kinkcand::MassMC, kinkcand::DecayRadiusMC, kinkcand::CollisionIdCheck); } // namespace o2::aod diff --git a/PWGLF/DataModel/LFLambda1405Table.h b/PWGLF/DataModel/LFLambda1405Table.h new file mode 100644 index 00000000000..1425a345375 --- /dev/null +++ b/PWGLF/DataModel/LFLambda1405Table.h @@ -0,0 +1,88 @@ +// 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 LFLambda1405Tables.h +/// \brief Slim tables for Lambda(1405) candidates +/// \author Francesco Mazzaschi +/// + +#include "Common/Core/RecoDecay.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + +#ifndef PWGLF_DATAMODEL_LFLAMBDA1405TABLES_H_ +#define PWGLF_DATAMODEL_LFLAMBDA1405TABLES_H_ + +namespace o2::aod +{ + +namespace lambda1405 +{ + +DECLARE_SOA_COLUMN(Px, px, float); //! Px of the candidate +DECLARE_SOA_COLUMN(Py, py, float); //! Py of the candidate +DECLARE_SOA_COLUMN(Pz, pz, float); //! Pz of the candidate +DECLARE_SOA_COLUMN(Mass, mass, float); //! Invariant mass of the candidate +DECLARE_SOA_COLUMN(MassXi1530, massXi1530, float); //! Invariant mass of the Xi(1530) candidate +DECLARE_SOA_COLUMN(SigmaMinusMass, sigmaMinusMass, float); //! Invariant mass of the Sigma- candidate +DECLARE_SOA_COLUMN(SigmaPlusMass, sigmaPlusMass, float); //! Invariant mass of the Sigma+ candidate +DECLARE_SOA_COLUMN(XiMinusMass, xiMinusMass, float); //! Invariant mass of the Xi- candidate +DECLARE_SOA_COLUMN(PtSigma, ptSigma, float); //! Signed pT of the Sigma daughter +DECLARE_SOA_COLUMN(AlphaAPSigma, alphaAPSigma, float); //! Alpha of the Sigma +DECLARE_SOA_COLUMN(QtAPSigma, qtAPSigma, float); //! qT of the Sigma +DECLARE_SOA_COLUMN(RadiusSigma, radiusSigma, float); //! Radius of the Sigma decay vertex +DECLARE_SOA_COLUMN(PtKink, ptKink, float); //! pT of the kink daughter +DECLARE_SOA_COLUMN(NSigmaTPCPiKink, nSigmaTPCPiKink, float); //! Number of sigmas for the pion candidate from Sigma kink in TPC +DECLARE_SOA_COLUMN(NSigmaTOFPiKink, nSigmaTOFPiKink, float); //! Number of sigmas for the pion candidate from Sigma kink in TOF +DECLARE_SOA_COLUMN(NSigmaTPCPrKink, nSigmaTPCPrKink, float); //! Number of sigmas for the proton candidate from Sigma kink in TPC +DECLARE_SOA_COLUMN(NSigmaTOFPrKink, nSigmaTOFPrKink, float); //! Number of sigmas for the proton candidate from Sigma kink in TOF +DECLARE_SOA_COLUMN(DCAKinkDauToPV, dcaKinkDauToPV, float); //! DCA of the kink daughter to the primary vertex +DECLARE_SOA_COLUMN(NSigmaTPCPiDau, nSigmaTPCPiDau, float); //! Number of sigmas for the lambda1405 pion daughter in TPC +DECLARE_SOA_COLUMN(NSigmaTOFPiDau, nSigmaTOFPiDau, float); //! Number of sigmas for the lambda1405 pion daughter in TOF + +// MC Columns +DECLARE_SOA_COLUMN(PtMC, ptMC, float); //! pT of the candidate in MC +DECLARE_SOA_COLUMN(MassMC, massMC, float); //! Invariant mass of the candidate in MC +DECLARE_SOA_COLUMN(SigmaPdgCode, sigmaPdgCode, int); //! PDG code of the Sigma daughter +DECLARE_SOA_COLUMN(KinkDauPdgCode, kinkDauPdgCode, int); //! PDG code of the kink daughter + +} // namespace lambda1405 + +DECLARE_SOA_TABLE(Lambda1405Cands, "AOD", "LAMBDA1405", + o2::soa::Index<>, + lambda1405::Px, lambda1405::Py, lambda1405::Pz, + lambda1405::Mass, lambda1405::MassXi1530, + lambda1405::SigmaMinusMass, lambda1405::SigmaPlusMass, lambda1405::XiMinusMass, + lambda1405::PtSigma, lambda1405::AlphaAPSigma, lambda1405::QtAPSigma, lambda1405::RadiusSigma, + lambda1405::PtKink, + lambda1405::NSigmaTPCPiKink, lambda1405::NSigmaTOFPiKink, + lambda1405::NSigmaTPCPrKink, lambda1405::NSigmaTOFPrKink, + lambda1405::DCAKinkDauToPV, + lambda1405::NSigmaTPCPiDau, lambda1405::NSigmaTOFPiDau); + +DECLARE_SOA_TABLE(Lambda1405CandsMC, "AOD", "MCLAMBDA1405", + o2::soa::Index<>, + lambda1405::Px, lambda1405::Py, lambda1405::Pz, + lambda1405::Mass, lambda1405::MassXi1530, + lambda1405::SigmaMinusMass, lambda1405::SigmaPlusMass, lambda1405::XiMinusMass, + lambda1405::PtSigma, lambda1405::AlphaAPSigma, lambda1405::QtAPSigma, lambda1405::RadiusSigma, + lambda1405::PtKink, + lambda1405::NSigmaTPCPiKink, lambda1405::NSigmaTOFPiKink, + lambda1405::NSigmaTPCPrKink, lambda1405::NSigmaTOFPrKink, + lambda1405::DCAKinkDauToPV, + lambda1405::NSigmaTPCPiDau, lambda1405::NSigmaTOFPiDau, + lambda1405::PtMC, lambda1405::MassMC, lambda1405::SigmaPdgCode, lambda1405::KinkDauPdgCode); + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFLAMBDA1405TABLES_H_ diff --git a/PWGLF/DataModel/LFNonPromptCascadeTables.h b/PWGLF/DataModel/LFNonPromptCascadeTables.h index 177167d5997..b698164abd4 100644 --- a/PWGLF/DataModel/LFNonPromptCascadeTables.h +++ b/PWGLF/DataModel/LFNonPromptCascadeTables.h @@ -119,6 +119,8 @@ DECLARE_SOA_COLUMN(MultFT0M, multFT0M, float); DECLARE_SOA_COLUMN(CentFT0C, centFT0C, float); DECLARE_SOA_COLUMN(CentFT0A, centFT0A, float); DECLARE_SOA_COLUMN(CentFT0M, centFT0M, float); +DECLARE_SOA_COLUMN(MultNTracksGlobal, multNTracksGlobal, int); +DECLARE_SOA_COLUMN(ToiMask, toiMask, uint32_t); } // namespace NPCascadeTable DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", @@ -183,7 +185,9 @@ DECLARE_SOA_TABLE(NPCascTable, "AOD", "NPCASCTABLE", NPCascadeTable::MultFT0M, NPCascadeTable::CentFT0C, NPCascadeTable::CentFT0A, - NPCascadeTable::CentFT0M) + NPCascadeTable::CentFT0M, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", NPCascadeTable::MatchingChi2, @@ -247,7 +251,9 @@ DECLARE_SOA_TABLE(NPCascTableNT, "AOD", "NPCASCTABLENT", NPCascadeTable::MultFT0M, NPCascadeTable::CentFT0C, NPCascadeTable::CentFT0A, - NPCascadeTable::CentFT0M) + NPCascadeTable::CentFT0M, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::MatchingChi2, @@ -330,7 +336,9 @@ DECLARE_SOA_TABLE(NPCascTableMC, "AOD", "NPCASCTABLEMC", NPCascadeTable::DCAzMC, NPCascadeTable::MCcollisionMatch, NPCascadeTable::HasFakeReassociation, - NPCascadeTable::MotherDecayDaughters) + NPCascadeTable::MotherDecayDaughters, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", NPCascadeTable::MatchingChi2, @@ -413,7 +421,9 @@ DECLARE_SOA_TABLE(NPCascTableMCNT, "AOD", "NPCASCTABLEMCNT", NPCascadeTable::DCAzMC, NPCascadeTable::MCcollisionMatch, NPCascadeTable::HasFakeReassociation, - NPCascadeTable::MotherDecayDaughters) + NPCascadeTable::MotherDecayDaughters, + NPCascadeTable::MultNTracksGlobal, + NPCascadeTable::ToiMask) DECLARE_SOA_TABLE(NPCascTableGen, "AOD", "NPCASCTABLEGen", NPCascadeTable::gPt, diff --git a/PWGLF/DataModel/LFNucleiTables.h b/PWGLF/DataModel/LFNucleiTables.h index 2fcd940d070..1cd9ba76c93 100644 --- a/PWGLF/DataModel/LFNucleiTables.h +++ b/PWGLF/DataModel/LFNucleiTables.h @@ -62,6 +62,8 @@ DECLARE_SOA_DYNAMIC_COLUMN(Rapidity, rapidity, const auto energy = sqrt(p * p + mass * mass); return 0.5f * log((energy + pz) / (energy - pz)); }); +// ITS +DECLARE_SOA_COLUMN(ITSClusterSizes, itsClusterSizes, uint32_t); //! ITS cluster sizes per layer // TPC DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNSigmaPi, float); DECLARE_SOA_COLUMN(TPCNSigmaKa, tpcNSigmaKa, float); @@ -181,6 +183,7 @@ DECLARE_SOA_TABLE(LfCandNucleus, "AOD", "LFNUCL", full::IsPVContributor, full::P, full::Rapidity, + full::ITSClusterSizes, track::TPCNClsFound, track::TPCNClsCrossedRows, track::TPCCrossedRowsOverFindableCls, @@ -211,6 +214,7 @@ DECLARE_SOA_TABLE_VERSIONED(LfCandNucleusDummy, "AOD", "LFNUCL", 1, track::ITSClusterMap, full::IsPVContributor, full::P, + full::ITSClusterSizes, dummy::TPCNSigmaPi, dummy::TPCNSigmaKa, dummy::TPCNSigmaPr, dummy::TPCNSigmaTr, dummy::TPCNSigmaAl, dummy::TOFNSigmaPi, dummy::TOFNSigmaKa, dummy::TOFNSigmaPr, diff --git a/PWGLF/DataModel/LFPIDTOFGenericTables.h b/PWGLF/DataModel/LFPIDTOFGenericTables.h new file mode 100644 index 00000000000..3a52a8a8ca5 --- /dev/null +++ b/PWGLF/DataModel/LFPIDTOFGenericTables.h @@ -0,0 +1,59 @@ +// 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 LFPIDTOFGenericTables.h +/// \brief Table for event time without remving track bias +/// \author Yuanzhe Wang + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + +#ifndef PWGLF_DATAMODEL_LFPIDTOFGENERICTABLES_H_ +#define PWGLF_DATAMODEL_LFPIDTOFGENERICTABLES_H_ +#include "Common/Core/PID/PIDTOF.h" + +#include "CommonDataFormat/InteractionRecord.h" + +namespace o2::aod +{ +namespace evtime +{ + +DECLARE_SOA_COLUMN(EvTime, evTime, float); //! Event time. Can be obtained via a combination of detectors e.g. TOF, FT0A, FT0C +DECLARE_SOA_COLUMN(EvTimeErr, evTimeErr, float); //! Error of event time. Can be obtained via a combination of detectors e.g. TOF, FT0A, FT0C +DECLARE_SOA_COLUMN(EvTimeTOF, evTimeTOF, float); //! Event time computed with the TOF detector +DECLARE_SOA_COLUMN(EvTimeTOFErr, evTimeTOFErr, float); //! Error of the event time computed with the TOF detector +DECLARE_SOA_COLUMN(EvTimeFT0, evTimeFT0, float); //! Event time computed with the FT0 detector +DECLARE_SOA_COLUMN(EvTimeFT0Err, evTimeFT0Err, float); //! Error of the event time computed with the FT0 detector +} // namespace evtime + +DECLARE_SOA_TABLE(EvTimeTOFFT0, "AOD", "EvTimeTOFFT0", //! Table of the event time. One entry per collision. + evtime::EvTime, + evtime::EvTimeErr, + evtime::EvTimeTOF, + evtime::EvTimeTOFErr, + evtime::EvTimeFT0, + evtime::EvTimeFT0Err); + +namespace tracktime +{ + +DECLARE_SOA_COLUMN(EvTimeForTrack, evTimeForTrack, float); //! Event time. Removed the bias for the specific track +DECLARE_SOA_COLUMN(EvTimeErrForTrack, evTimeErrForTrack, float); //! Error of event time. Removed the bias for the specific track +} // namespace tracktime + +DECLARE_SOA_TABLE(EvTimeTOFFT0ForTrack, "AOD", "EvTimeForTrack", //! Table of the event time. One entry per track. + tracktime::EvTimeForTrack, + tracktime::EvTimeErrForTrack); + +} // namespace o2::aod + +#endif // PWGLF_DATAMODEL_LFPIDTOFGENERICTABLES_H_ diff --git a/PWGLF/DataModel/LFResonanceTables.h b/PWGLF/DataModel/LFResonanceTables.h index 6d0b909a695..67e1fb013c5 100644 --- a/PWGLF/DataModel/LFResonanceTables.h +++ b/PWGLF/DataModel/LFResonanceTables.h @@ -332,7 +332,7 @@ DECLARE_SOA_DYNAMIC_COLUMN(Sign, sign, } // namespace resodaughter -namespace resodmciroaughter +namespace resomicrodaughter { // micro track for primary pion @@ -471,7 +471,7 @@ struct ResoMicroTrackSelFlag { }; DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); -} // namespace resodmciroaughter +} // namespace resomicrodaughter DECLARE_SOA_TABLE(ResoTracks, "AOD", "RESOTRACK", o2::soa::Index<>, @@ -525,13 +525,13 @@ DECLARE_SOA_TABLE(ResoMicroTracks, "AOD", "RESOMICROTRACK", resodaughter::Px, resodaughter::Py, resodaughter::Pz, - resodmciroaughter::PidNSigmaPiFlag, - resodmciroaughter::PidNSigmaKaFlag, - resodmciroaughter::PidNSigmaPrFlag, - resodmciroaughter::TrackSelectionFlags, + resomicrodaughter::PidNSigmaPiFlag, + resomicrodaughter::PidNSigmaKaFlag, + resomicrodaughter::PidNSigmaPrFlag, + resomicrodaughter::TrackSelectionFlags, resodaughter::TrackFlags, // Dynamic columns - resodmciroaughter::Pt, + resomicrodaughter::Pt, resodaughter::Eta, resodaughter::Phi, resodaughter::PassedITSRefit, @@ -540,7 +540,7 @@ DECLARE_SOA_TABLE(ResoMicroTracks, "AOD", "RESOMICROTRACK", resodaughter::IsGlobalTrack, resodaughter::IsPrimaryTrack, resodaughter::IsPVContributor, - resodmciroaughter::HasTOF, + resomicrodaughter::HasTOF, resodaughter::Sign); using ResoMicroTrack = ResoMicroTracks::iterator; diff --git a/PWGLF/DataModel/LFSlimHeLambda.h b/PWGLF/DataModel/LFSlimHeLambda.h new file mode 100644 index 00000000000..8745ac1838a --- /dev/null +++ b/PWGLF/DataModel/LFSlimHeLambda.h @@ -0,0 +1,88 @@ +// 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 LFSlimNucleiTables.h +/// \brief Slim nuclei tables +/// + +#ifndef PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ +#define PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + +#include + +namespace o2::aod +{ +namespace lfv0he3 +{ +DECLARE_SOA_COLUMN(Z, z, float); +DECLARE_SOA_COLUMN(CentT0C, centT0C, float); +} // namespace lfv0he3 +DECLARE_SOA_TABLE(LFEvents, "AOD", "LFEVENT", o2::soa::Index<>, lfv0he3::Z, lfv0he3::CentT0C); + +namespace lfv0he3 +{ +DECLARE_SOA_INDEX_COLUMN(LFEvent, lfEvent); // Collision ID for the event +DECLARE_SOA_COLUMN(Pt, pt, float); +DECLARE_SOA_COLUMN(Eta, eta, float); +DECLARE_SOA_COLUMN(Phi, phi, float); +DECLARE_SOA_COLUMN(Mass, mass, float); +DECLARE_SOA_COLUMN(CosPA, cosPA, float); +DECLARE_SOA_COLUMN(DCAxy, dcaXY, float); +DECLARE_SOA_COLUMN(DCAz, dcaZ, float); +DECLARE_SOA_COLUMN(TPCnCls, tpcNCls, int); +DECLARE_SOA_COLUMN(TPCnClsPID, tpcNClsPID, int); +DECLARE_SOA_COLUMN(ITSClusterSizes, itsClusterSizes, uint32_t); +DECLARE_SOA_COLUMN(NsigmaTPCPion, nSigmaTPCPion, float); +DECLARE_SOA_COLUMN(NsigmaTPCProton, nSigmaTPCProton, float); +DECLARE_SOA_COLUMN(NsigmaTPC, nSigmaTPC, float); +DECLARE_SOA_COLUMN(DCAdaughters, dcaDaughters, float); +DECLARE_SOA_COLUMN(DCAPVProton, dcaPVProton, float); +DECLARE_SOA_COLUMN(DCAPVPion, dcaPVPion, float); +DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); +DECLARE_SOA_COLUMN(Sign, sign, int8_t); +} // namespace lfv0he3 +DECLARE_SOA_TABLE_VERSIONED(LFHe3_000, "AOD", "LFHE3V0", 0, lfv0he3::LFEventId, lfv0he3::Pt, lfv0he3::Eta, lfv0he3::Phi, lfv0he3::DCAxy, lfv0he3::DCAz, lfv0he3::TPCnCls, lfv0he3::ITSClusterSizes, lfv0he3::NsigmaTPC, lfv0he3::Sign); +DECLARE_SOA_TABLE_VERSIONED(LFLambda_000, "AOD", "LFLAMBDA", 0, lfv0he3::LFEventId, lfv0he3::Pt, lfv0he3::Eta, lfv0he3::Phi, lfv0he3::Mass, lfv0he3::CosPA, lfv0he3::DCAdaughters, lfv0he3::DCAPVProton, lfv0he3::DCAPVPion, lfv0he3::V0Radius, lfv0he3::Sign); + +DECLARE_SOA_TABLE_VERSIONED(LFHe3_001, "AOD", "LFHE3V0", 1, lfv0he3::LFEventId, lfv0he3::Pt, lfv0he3::Eta, lfv0he3::Phi, lfv0he3::DCAxy, lfv0he3::DCAz, lfv0he3::TPCnCls, lfv0he3::TPCnClsPID, lfv0he3::ITSClusterSizes, lfv0he3::NsigmaTPC, lfv0he3::Sign); +DECLARE_SOA_TABLE_VERSIONED(LFLambda_001, "AOD", "LFLAMBDA", 1, lfv0he3::LFEventId, lfv0he3::Pt, lfv0he3::Eta, lfv0he3::Phi, lfv0he3::Mass, lfv0he3::CosPA, lfv0he3::DCAdaughters, lfv0he3::DCAPVProton, lfv0he3::DCAPVPion, lfv0he3::V0Radius, lfv0he3::NsigmaTPCProton, lfv0he3::NsigmaTPCPion, lfv0he3::Sign); +} // namespace o2::aod + +struct he3Candidate { + ROOT::Math::LorentzVector> momentum; // 4-momentum of the He3 candidate + float nSigmaTPC = -999.f; // TPC nSigma for He3 + float dcaXY = -999.f; + float dcaZ = -999.f; + int tpcNClsFound = 0; // Number of TPC clusters found + int tpcNClsPID = 0; // Number of TPC clusters used for PID + int itsNCls = 0; // Number of ITS clusters + uint32_t itsClusterSizes = 0; // ITS cluster sizes + int8_t sign = 0; // Charge sign of the He3 candidate +}; + +struct lambdaCandidate { + ROOT::Math::LorentzVector> momentum; + float mass = -1.f; // Lambda mass + float cosPA = -2.f; // Cosine of pointing angle + float dcaV0Daughters = -999.f; // DCA between V0 daughters + float dcaProtonToPV = -999.f; // DCA of the proton to primary vertex + float dcaPionToPV = -999.f; // DCA of the pion to primary vertex + float v0Radius = -1.f; // V0 radius + float protonNSigmaTPC = -999.f; // Proton TPC nSigma + float pionNSigmaTPC = -999.f; // Pion TPC nSigma + int8_t sign = 0; // Charge sign of the Lambda candidate +}; + +#endif // PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ diff --git a/PWGLF/DataModel/LFSlimNucleiTables.h b/PWGLF/DataModel/LFSlimNucleiTables.h index e562c35ddc6..e1c0e0eb364 100644 --- a/PWGLF/DataModel/LFSlimNucleiTables.h +++ b/PWGLF/DataModel/LFSlimNucleiTables.h @@ -14,10 +14,11 @@ /// \brief Slim nuclei tables /// -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" #include "Common/DataModel/Centrality.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" + #ifndef PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ #define PWGLF_DATAMODEL_LFSLIMNUCLEITABLES_H_ @@ -31,6 +32,7 @@ DECLARE_SOA_COLUMN(Phi, phi, float); DECLARE_SOA_COLUMN(TPCInnerParam, tpcInnerParam, float); DECLARE_SOA_COLUMN(Beta, beta, float); DECLARE_SOA_COLUMN(Zvertex, zVertex, float); +DECLARE_SOA_COLUMN(NContrib, nContrib, int); DECLARE_SOA_COLUMN(DCAxy, dcaxy, float); DECLARE_SOA_COLUMN(DCAz, dcaz, float); DECLARE_SOA_COLUMN(TPCsignal, tpcSignal, float); @@ -102,6 +104,7 @@ DECLARE_SOA_TABLE(NucleiTable, "AOD", "NUCLEITABLE", NucleiTableNS::TPCInnerParam, NucleiTableNS::Beta, NucleiTableNS::Zvertex, + NucleiTableNS::NContrib, NucleiTableNS::DCAxy, NucleiTableNS::DCAz, NucleiTableNS::TPCsignal, @@ -139,6 +142,7 @@ DECLARE_SOA_TABLE(NucleiTableMC, "AOD", "NUCLEITABLEMC", NucleiTableNS::TPCInnerParam, NucleiTableNS::Beta, NucleiTableNS::Zvertex, + NucleiTableNS::NContrib, NucleiTableNS::DCAxy, NucleiTableNS::DCAz, NucleiTableNS::TPCsignal, diff --git a/PWGLF/DataModel/LFSpincorrelationTables.h b/PWGLF/DataModel/LFSpincorrelationTables.h new file mode 100644 index 00000000000..f875736d794 --- /dev/null +++ b/PWGLF/DataModel/LFSpincorrelationTables.h @@ -0,0 +1,138 @@ +// 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 Sourav Kundu + +#ifndef PWGLF_DATAMODEL_LFSPINCORRELATIONTABLES_H_ +#define PWGLF_DATAMODEL_LFSPINCORRELATIONTABLES_H_ + +#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 + +namespace o2::aod +{ +namespace lambdaevent +{ +DECLARE_SOA_COLUMN(Cent, cent, float); +DECLARE_SOA_COLUMN(Posz, posz, float); +} // namespace lambdaevent +DECLARE_SOA_TABLE(LambdaEvents, "AOD", "LAMBDAEVENT", + o2::soa::Index<>, + lambdaevent::Cent, + lambdaevent::Posz) +using LambdaEvent = LambdaEvents::iterator; + +namespace lambdapair +{ +DECLARE_SOA_INDEX_COLUMN(LambdaEvent, lambdaevent); +DECLARE_SOA_COLUMN(V0Status, v0Status, int); //! Lambda or Anti-Lambda status +DECLARE_SOA_COLUMN(DoubleStatus, doubleStatus, bool); //! Double status +DECLARE_SOA_COLUMN(V0Cospa, v0Cospa, float); //! V0 Cospa +DECLARE_SOA_COLUMN(V0Radius, v0Radius, float); //! V0 Radius +DECLARE_SOA_COLUMN(DcaPositive, dcaPositive, float); //! DCA Positive +DECLARE_SOA_COLUMN(DcaNegative, dcaNegative, float); //! DCA Negative +DECLARE_SOA_COLUMN(DcaBetweenDaughter, dcaBetweenDaughter, float); //! DCA between daughters +DECLARE_SOA_COLUMN(LambdaPt, lambdaPt, float); //! Lambda Pt +DECLARE_SOA_COLUMN(LambdaEta, lambdaEta, float); //! Lambda Eta +DECLARE_SOA_COLUMN(LambdaPhi, lambdaPhi, float); //! Lambda Phi +DECLARE_SOA_COLUMN(LambdaMass, lambdaMass, float); //! Lambda Mass +DECLARE_SOA_COLUMN(ProtonPt, protonPt, float); //! Proton Pt +DECLARE_SOA_COLUMN(ProtonEta, protonEta, float); //! Proton Eta +DECLARE_SOA_COLUMN(ProtonPhi, protonPhi, float); //! Proton Phi +DECLARE_SOA_COLUMN(ProtonIndex, protonIndex, int); //! Proton index +DECLARE_SOA_COLUMN(PionIndex, pionIndex, int); //! Pion index +} // namespace lambdapair +DECLARE_SOA_TABLE(LambdaPairs, "AOD", "LAMBDAPAIR", + o2::soa::Index<>, + lambdapair::LambdaEventId, + lambdapair::V0Status, + lambdapair::DoubleStatus, + lambdapair::V0Cospa, + lambdapair::V0Radius, + lambdapair::DcaPositive, + lambdapair::DcaNegative, + lambdapair::DcaBetweenDaughter, + lambdapair::LambdaPt, + lambdapair::LambdaEta, + lambdapair::LambdaPhi, + lambdapair::LambdaMass, + lambdapair::ProtonPt, + lambdapair::ProtonEta, + lambdapair::ProtonPhi, + lambdapair::ProtonIndex, + lambdapair::PionIndex); + +using LambdaPair = LambdaPairs::iterator; + +namespace lambdaeventmc +{ +DECLARE_SOA_COLUMN(Centmc, centmc, float); +DECLARE_SOA_COLUMN(Poszmc, poszmc, float); +} // namespace lambdaeventmc +DECLARE_SOA_TABLE(LambdaEventmcs, "AOD", "LAMBDAEVENTMC", + o2::soa::Index<>, + lambdaeventmc::Centmc, + lambdaeventmc::Poszmc) +using LambdaEventmc = LambdaEventmcs::iterator; + +namespace lambdapairmc +{ +DECLARE_SOA_INDEX_COLUMN(LambdaEventmc, lambdaeventmc); +DECLARE_SOA_COLUMN(V0Statusmc, v0Statusmc, int); //! Lambda or Anti-Lambda status in montecarlo +DECLARE_SOA_COLUMN(DoubleStatusmc, doubleStatusmc, bool); //! Double status in montecarlo +DECLARE_SOA_COLUMN(V0Cospamc, v0Cospamc, float); //! V0 Cospa in montecarlo +DECLARE_SOA_COLUMN(V0Radiusmc, v0Radiusmc, float); //! V0 Radius in montecarlo +DECLARE_SOA_COLUMN(DcaPositivemc, dcaPositivemc, float); //! DCA Positive in montecarlo +DECLARE_SOA_COLUMN(DcaNegativemc, dcaNegativemc, float); //! DCA Negative in montecarlo +DECLARE_SOA_COLUMN(DcaBetweenDaughtermc, dcaBetweenDaughtermc, float); //! DCA between daughters in montecarlo +DECLARE_SOA_COLUMN(LambdaPtmc, lambdaPtmc, float); //! Lambda Pt in montecarlo +DECLARE_SOA_COLUMN(LambdaEtamc, lambdaEtamc, float); //! Lambda Eta in montecarlo +DECLARE_SOA_COLUMN(LambdaPhimc, lambdaPhimc, float); //! Lambda Phi in montecarlo +DECLARE_SOA_COLUMN(LambdaMassmc, lambdaMassmc, float); //! Lambda Mass in montecarlo +DECLARE_SOA_COLUMN(ProtonPtmc, protonPtmc, float); //! Proton Pt in montecarlo +DECLARE_SOA_COLUMN(ProtonEtamc, protonEtamc, float); //! Proton Eta in montecarlo +DECLARE_SOA_COLUMN(ProtonPhimc, protonPhimc, float); //! Proton Phi in montecarlo +DECLARE_SOA_COLUMN(ProtonIndexmc, protonIndexmc, int); //! Proton index in montecarlo +DECLARE_SOA_COLUMN(PionIndexmc, pionIndexmc, int); //! Pion index in montecarlo +} // namespace lambdapairmc +DECLARE_SOA_TABLE(LambdaPairmcs, "AOD", "LAMBDAPAIRMC", + o2::soa::Index<>, + lambdapairmc::LambdaEventmcId, + lambdapairmc::V0Statusmc, + lambdapairmc::DoubleStatusmc, + lambdapairmc::V0Cospamc, + lambdapairmc::V0Radiusmc, + lambdapairmc::DcaPositivemc, + lambdapairmc::DcaNegativemc, + lambdapairmc::DcaBetweenDaughtermc, + lambdapairmc::LambdaPtmc, + lambdapairmc::LambdaEtamc, + lambdapairmc::LambdaPhimc, + lambdapairmc::LambdaMassmc, + lambdapairmc::ProtonPtmc, + lambdapairmc::ProtonEtamc, + lambdapairmc::ProtonPhimc, + lambdapairmc::ProtonIndexmc, + lambdapairmc::PionIndexmc); + +using LambdaPairmc = LambdaPairmcs::iterator; + +} // namespace o2::aod +#endif // PWGLF_DATAMODEL_LFSPINCORRELATIONTABLES_H_ diff --git a/PWGLF/DataModel/LFStrangenessTables.h b/PWGLF/DataModel/LFStrangenessTables.h index ce2e9e65eda..ca58973dff8 100644 --- a/PWGLF/DataModel/LFStrangenessTables.h +++ b/PWGLF/DataModel/LFStrangenessTables.h @@ -8,22 +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. + #ifndef PWGLF_DATAMODEL_LFSTRANGENESSTABLES_H_ #define PWGLF_DATAMODEL_LFSTRANGENESSTABLES_H_ -#include -#include -#include "Framework/AnalysisDataModel.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/Core/RecoDecay.h" -#include "CommonConstants/PhysicsConstants.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/McCollisionExtra.h" // IWYU pragma: keep (FIXME: not used, remove asap) #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" #include "Common/DataModel/Qvectors.h" -#include "Common/DataModel/McCollisionExtra.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/SPCalibrationTables.h" -#include "PWGUD/DataModel/UDTables.h" + +#include +#include +#include +#include + +#include +#include +#include +#include namespace o2::aod { @@ -702,11 +710,38 @@ DECLARE_SOA_DYNAMIC_COLUMN(PFracNeg, pfracneg, // Calculated on the fly with mass assumption + dynamic tables DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, //! mass under lambda hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); }); + [](int v0type, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + if ((v0type & (0x1 << o2::dataformats::V0Index::kPhotonOnly)) != 0) { + return 0.0f; // provide mass only if NOT a photon with TPC-only tracks (special handling) + }; + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + }); DECLARE_SOA_DYNAMIC_COLUMN(MAntiLambda, mAntiLambda, //! mass under antilambda hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); }); + [](int v0type, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + if ((v0type & (0x1 << o2::dataformats::V0Index::kPhotonOnly)) != 0) { + return 0.0f; // provide mass only if NOT a photon with TPC-only tracks (special handling) + }; + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); + }); DECLARE_SOA_DYNAMIC_COLUMN(MK0Short, mK0Short, //! mass under K0short hypothesis - [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); }); + [](int v0type, float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + if ((v0type & (0x1 << o2::dataformats::V0Index::kPhotonOnly)) != 0) { + return 0.0f; // provide mass only if NOT a photon with TPC-only tracks (special handling) + }; + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); + }); +DECLARE_SOA_DYNAMIC_COLUMN(MLambda_unchecked, mLambda_unchecked, //! mass under lambda hypothesis without v0 type check (will include TPC only and potentially duplicates! use with care) + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + }); +DECLARE_SOA_DYNAMIC_COLUMN(MAntiLambda_unchecked, mAntiLambda_unchecked, //! mass under antilambda hypothesis without v0 type check (will include TPC only and potentially duplicates! use with care) + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); + }); +DECLARE_SOA_DYNAMIC_COLUMN(MK0Short_unchecked, mK0Short_unchecked, //! mass under K0short hypothesis without v0 type check (will include TPC only and potentially duplicates! use with care) + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); + }); DECLARE_SOA_DYNAMIC_COLUMN(MGamma, mGamma, //! mass under gamma hypothesis [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassElectron, o2::constants::physics::MassElectron}); }); // Account for rigidity in case of hypertriton @@ -765,12 +800,12 @@ DECLARE_SOA_DYNAMIC_COLUMN(PositiveEta, positiveeta, //! positive daughter eta DECLARE_SOA_DYNAMIC_COLUMN(PositivePhi, positivephi, //! positive daughter phi [](float PxPos, float PyPos) -> float { return RecoDecay::phi(PxPos, PyPos); }); -DECLARE_SOA_DYNAMIC_COLUMN(IsStandardV0, isStandardV0, //! is standard V0 - [](uint8_t V0Type) -> bool { return V0Type == 1; }); +DECLARE_SOA_DYNAMIC_COLUMN(IsStandardV0, isStandardV0, //! is standard V0 - note: photons excluded via '==' + [](uint8_t V0Type) -> bool { return V0Type == o2::dataformats::V0Index::kStandaloneV0; }); DECLARE_SOA_DYNAMIC_COLUMN(IsPhotonTPConly, isPhotonTPConly, //! is tpc-only photon V0 - [](uint8_t V0Type) -> bool { return V0Type & (1 << 1); }); + [](uint8_t V0Type) -> bool { return V0Type & (1 << o2::dataformats::V0Index::kPhotonOnly); }); DECLARE_SOA_DYNAMIC_COLUMN(IsCollinear, isCollinear, //! is collinear V0 - [](uint8_t V0Type) -> bool { return V0Type & (1 << 2); }); + [](uint8_t V0Type) -> bool { return V0Type & (1 << o2::dataformats::V0Index::kCollinear); }); DECLARE_SOA_DYNAMIC_COLUMN(RapidityMC, rapidityMC, //! rapidity (0:K0, 1:L, 2:Lbar) [](float PxMC, float PyMC, float PzMC, int value) -> float { @@ -787,6 +822,24 @@ DECLARE_SOA_DYNAMIC_COLUMN(PositivePtMC, positiveptMC, //! positive daughter pT [](float pxposMC, float pyposMC) -> float { return RecoDecay::sqrtSumOfSquares(pxposMC, pyposMC); }); DECLARE_SOA_DYNAMIC_COLUMN(PtMC, ptMC, //! V0 pT [](float pxMC, float pyMC) -> float { return RecoDecay::sqrtSumOfSquares(pxMC, pyMC); }); + +// declare legacy mass getters in v0data legacy name space +// caution: these do not have intrinsic protection against photon candidates +namespace legacy +{ +DECLARE_SOA_DYNAMIC_COLUMN(MLambda, mLambda, //! mass under lambda hypothesis without v0 type check (will include TPC only and potentially duplicates! use with care) + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + }); +DECLARE_SOA_DYNAMIC_COLUMN(MAntiLambda, mAntiLambda, //! mass under antilambda hypothesis without v0 type check (will include TPC only and potentially duplicates! use with care) + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); + }); +DECLARE_SOA_DYNAMIC_COLUMN(MK0Short, mK0Short, //! mass under K0short hypothesis without v0 type check (will include TPC only and potentially duplicates! use with care) + [](float pxpos, float pypos, float pzpos, float pxneg, float pyneg, float pzneg) -> float { + return RecoDecay::m(std::array{std::array{pxpos, pypos, pzpos}, std::array{pxneg, pyneg, pzneg}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); + }); +} // namespace legacy } // namespace v0data DECLARE_SOA_TABLE(V0Indices, "AOD", "V0INDEX", //! index table when using AO2Ds @@ -828,9 +881,12 @@ DECLARE_SOA_TABLE_STAGED(V0CoresBase, "V0CORE", //! core information about decay v0data::PFracNeg, // 24 // Invariant masses - v0data::MLambda, - v0data::MAntiLambda, - v0data::MK0Short, + v0data::MLambda, + v0data::MAntiLambda, + v0data::MK0Short, + v0data::MLambda_unchecked, + v0data::MAntiLambda_unchecked, + v0data::MK0Short_unchecked, v0data::MGamma, v0data::MHypertriton, v0data::MAntiHypertriton, @@ -909,9 +965,9 @@ DECLARE_SOA_TABLE_FULL(StoredV0fCCores, "V0fCCores", "AOD", "V0FCCORE", //! core v0data::PFracNeg, // 24 // Invariant masses - v0data::MLambda, - v0data::MAntiLambda, - v0data::MK0Short, + v0data::MLambda, + v0data::MAntiLambda, + v0data::MK0Short, v0data::MGamma, v0data::MHypertriton, v0data::MAntiHypertriton, diff --git a/PWGLF/DataModel/LFhe3HadronTables.h b/PWGLF/DataModel/LFhe3HadronTables.h index 9074fb8b20c..07ce17853ea 100644 --- a/PWGLF/DataModel/LFhe3HadronTables.h +++ b/PWGLF/DataModel/LFhe3HadronTables.h @@ -36,6 +36,7 @@ DECLARE_SOA_COLUMN(DCAxyHe3, dcaxyHe3, float); DECLARE_SOA_COLUMN(DCAzHe3, dcazHe3, float); DECLARE_SOA_COLUMN(DCAxyHad, dcaxyHad, float); DECLARE_SOA_COLUMN(DCAzHad, dcazHad, float); +DECLARE_SOA_COLUMN(DCApair, dcapair, float); DECLARE_SOA_COLUMN(SignalTPCHe3, signalTPCHe3, float); DECLARE_SOA_COLUMN(InnerParamTPCHe3, innerParamTPCHe3, float); @@ -75,6 +76,13 @@ DECLARE_SOA_COLUMN(Multiplicity, multiplicity, uint16_t); DECLARE_SOA_COLUMN(CentralityFT0C, centFT0C, float); DECLARE_SOA_COLUMN(MultiplicityFT0C, multiplicityFT0C, float); +/* Flags: 0 - both primary, + 1 - both from Li4, + 2 - both from hypertriton, + 3 - mixed pair (a primary and one from Li4/hypertriton/material/other decays or any other combination) +*/ +DECLARE_SOA_COLUMN(Flags, flags, uint8_t); + } // namespace he3HadronTablesNS DECLARE_SOA_TABLE(he3HadronTable, "AOD", "HE3HADTABLE", @@ -88,6 +96,7 @@ DECLARE_SOA_TABLE(he3HadronTable, "AOD", "HE3HADTABLE", he3HadronTablesNS::DCAzHe3, he3HadronTablesNS::DCAxyHad, he3HadronTablesNS::DCAzHad, + he3HadronTablesNS::DCApair, he3HadronTablesNS::SignalTPCHe3, he3HadronTablesNS::InnerParamTPCHe3, he3HadronTablesNS::SignalTPCHad, @@ -115,7 +124,8 @@ DECLARE_SOA_TABLE(he3HadronTableMC, "AOD", "HE3HADTABLEMC", he3HadronTablesNS::EtaMCHad, he3HadronTablesNS::PhiMCHad, he3HadronTablesNS::SignedPtMC, - he3HadronTablesNS::MassMC) + he3HadronTablesNS::MassMC, + he3HadronTablesNS::Flags) DECLARE_SOA_TABLE(he3HadronMult, "AOD", "HE3HADMULT", he3HadronTablesNS::CollisionId, he3HadronTablesNS::ZVertex, diff --git a/PWGLF/DataModel/Reduced3BodyTables.h b/PWGLF/DataModel/Reduced3BodyTables.h index 51fff63c81d..3b221d17539 100644 --- a/PWGLF/DataModel/Reduced3BodyTables.h +++ b/PWGLF/DataModel/Reduced3BodyTables.h @@ -83,8 +83,10 @@ DECLARE_SOA_TABLE_FULL(StoredRedIUTracks, "RedIUTracks", "AOD", "REDIUTRACK", // // tracks extra track::PIDForTracking, track::IsPVContributor, + track::HasITS, track::HasTPC, track::HasTOF, + track::HasTRD, track::TPCNClsFound, track::TPCNClsCrossedRows, track::v001::ITSClsSizeInLayer, @@ -120,29 +122,22 @@ DECLARE_SOA_INDEX_COLUMN_FULL(Track0, track0, int, RedIUTracks, "_0"); //! DECLARE_SOA_INDEX_COLUMN_FULL(Track1, track1, int, RedIUTracks, "_1"); //! Track 1 index DECLARE_SOA_INDEX_COLUMN_FULL(Track2, track2, int, RedIUTracks, "_2"); //! Track 2 index DECLARE_SOA_INDEX_COLUMN_FULL(Collision, collision, int, RedCollisions, ""); //! Collision index -DECLARE_SOA_COLUMN(Phi, phi, float); //! decay3body radius -DECLARE_SOA_COLUMN(Radius, radius, float); //! decay3body phi -DECLARE_SOA_COLUMN(PosZ, posz, float); //! decay3body z position +DECLARE_SOA_COLUMN(RadiusKF, radiusKF, float); //! phi of momentum of mother particle calculated by KF +DECLARE_SOA_COLUMN(PhiKF, phiKF, float); //! SV radius in x-y plane calculated by KF +DECLARE_SOA_COLUMN(PosZKF, poszKF, float); //! z position of SV calculated by KF +DECLARE_SOA_COLUMN(RadiusDCA, radiusDCA, float); //! phi of momentum of mother particle calculated by dcaFitter +DECLARE_SOA_COLUMN(PhiDCA, phiDCA, float); //! SV radius in x-y plane calculated by dcaFitter +DECLARE_SOA_COLUMN(PosZDCA, poszDCA, float); //! z position of SV calculated by dcaFitter +DECLARE_SOA_COLUMN(TrackedClSize, trackedClSize, float); //! average ITS cluster size (if tracked) } // namespace reduceddecay3body DECLARE_SOA_TABLE(RedDecay3Bodys, "AOD", "REDDECAY3BODY", //! reduced 3-body decay table o2::soa::Index<>, reduceddecay3body::CollisionId, reduceddecay3body::Track0Id, reduceddecay3body::Track1Id, reduceddecay3body::Track2Id); -using ReducedDecay3BodysLinked = soa::Join; -using ReducedDecay3BodyLinked = ReducedDecay3BodysLinked::iterator; - DECLARE_SOA_TABLE(Red3BodyInfo, "AOD", "RED3BODYINFO", //! joinable with RedDecay3Bodys - reduceddecay3body::Radius, reduceddecay3body::Phi, reduceddecay3body::PosZ); - -namespace dcafittersvinfo -{ -DECLARE_SOA_COLUMN(SVRadius, svRadius, float); //! SV radius in x-y plane calculated by dcaFitter -DECLARE_SOA_COLUMN(MomPhi, momPhi, float); //! phi of momentum of mother particle calculated from dcaFitter -DECLARE_SOA_COLUMN(SVPosZ, svPosZ, float); //! z position of SV calculated by dcaFitter -} // namespace dcafittersvinfo - -DECLARE_SOA_TABLE_FULL(DCAFitterSVInfo, "FitSVInfo", "AOD", "FITSVINFO", //! joinable with RedDecay3Bodys - dcafittersvinfo::SVRadius, dcafittersvinfo::MomPhi, dcafittersvinfo::SVPosZ); + reduceddecay3body::RadiusKF, reduceddecay3body::PhiKF, reduceddecay3body::PosZKF, + reduceddecay3body::RadiusDCA, reduceddecay3body::PhiDCA, reduceddecay3body::PosZDCA, + reduceddecay3body::TrackedClSize); } // namespace o2::aod diff --git a/PWGLF/DataModel/Vtx3BodyTables.h b/PWGLF/DataModel/Vtx3BodyTables.h index 9ae43bb0255..55bdea60789 100644 --- a/PWGLF/DataModel/Vtx3BodyTables.h +++ b/PWGLF/DataModel/Vtx3BodyTables.h @@ -10,64 +10,142 @@ // or submit itself to any jurisdiction. /// \file Vtx3BodyTables.h -/// \brief Definitions of reduced tables for 3body decayed hypertriton +/// \brief Definitions of analysis tables for 3body decayed hypertriton /// \author Yuanzhe Wang /// \author Carolina Reetz #ifndef PWGLF_DATAMODEL_VTX3BODYTABLES_H_ #define PWGLF_DATAMODEL_VTX3BODYTABLES_H_ -#include -#include "Framework/AnalysisDataModel.h" #include "Common/Core/RecoDecay.h" + #include "CommonConstants/PhysicsConstants.h" +#include "Framework/AnalysisDataModel.h" + +#include namespace o2::aod { namespace vtx3body { -DECLARE_SOA_INDEX_COLUMN_FULL(Track0, track0, int, Tracks, "_0"); //! -DECLARE_SOA_INDEX_COLUMN_FULL(Track1, track1, int, Tracks, "_1"); //! -DECLARE_SOA_INDEX_COLUMN_FULL(Track2, track2, int, Tracks, "_2"); //! -DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! -DECLARE_SOA_INDEX_COLUMN(Decay3Body, decay3body); //! - -// General 3 body Vtx properties: position, momentum -DECLARE_SOA_COLUMN(PxTrack0, pxtrack0, float); //! track0 px at min -DECLARE_SOA_COLUMN(PyTrack0, pytrack0, float); //! track0 py at min -DECLARE_SOA_COLUMN(PzTrack0, pztrack0, float); //! track0 pz at min -DECLARE_SOA_COLUMN(PxTrack1, pxtrack1, float); //! track1 px at min -DECLARE_SOA_COLUMN(PyTrack1, pytrack1, float); //! track1 py at min -DECLARE_SOA_COLUMN(PzTrack1, pztrack1, float); //! track1 pz at min -DECLARE_SOA_COLUMN(PxTrack2, pxtrack2, float); //! track2 px at min -DECLARE_SOA_COLUMN(PyTrack2, pytrack2, float); //! track2 py at min -DECLARE_SOA_COLUMN(PzTrack2, pztrack2, float); //! track2 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 - -// Saved from finding: DCAs -DECLARE_SOA_COLUMN(DCAVtxDaughters, dcaVtxdaughters, float); //! DCA among daughters -DECLARE_SOA_COLUMN(DCAXYTrack0ToPV, dcaXYtrack0topv, float); //! DCAXY of prong0 to PV -DECLARE_SOA_COLUMN(DCAXYTrack1ToPV, dcaXYtrack1topv, float); //! DCAXY of prong1 to PV -DECLARE_SOA_COLUMN(DCAXYTrack2ToPV, dcaXYtrack2topv, float); //! DCAXY of prong2 to PV -DECLARE_SOA_COLUMN(DCATrack0ToPV, dcatrack0topv, float); //! DCA of prong0 to PV -DECLARE_SOA_COLUMN(DCATrack1ToPV, dcatrack1topv, float); //! DCA of prong1 to PV -DECLARE_SOA_COLUMN(DCATrack2ToPV, dcatrack2topv, float); //! DCA of prong2 to PV - -// Recalculated TOF PID information of bachelor -DECLARE_SOA_COLUMN(TOFNSigmaBachDe, tofNSigmaBachDe, float); //! Recalculated Nsigma seperation with TOF for deuteron +// indices +DECLARE_SOA_INDEX_COLUMN_FULL(TrackPr, trackPr, int, Tracks, "_pr"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(TrackPi, trackPi, int, Tracks, "_pi"); //! +DECLARE_SOA_INDEX_COLUMN_FULL(TrackDe, trackDe, int, Tracks, "_de"); //! +DECLARE_SOA_INDEX_COLUMN(Collision, collision); //! +DECLARE_SOA_INDEX_COLUMN(Decay3Body, decay3body); //! + +// General 3 body Vtx properties +DECLARE_SOA_COLUMN(Mass, mass, float); //! candidate mass (with H3L or Anti-H3L mass hypothesis depending on deuteron charge) +DECLARE_SOA_COLUMN(Sign, sign, float); //! candidate sign +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 +DECLARE_SOA_COLUMN(Px, px, float); //! momentum X +DECLARE_SOA_COLUMN(Py, py, float); //! momentum Y +DECLARE_SOA_COLUMN(Pz, pz, float); //! momentum Z +DECLARE_SOA_COLUMN(Chi2, chi2, float); //! KFParticle: chi2geo/ndf or chi2topo/ndf of vertex fit, DCA fitter: Chi2AtPCACandidate value + +// daughter properties +DECLARE_SOA_COLUMN(MassV0, massV0, float); //! V0 mass (with H3L or Anti-H3L mass hypothesis depending on deuteron charge) +DECLARE_SOA_COLUMN(PxTrackPr, pxTrackPr, float); //! track0 px at min +DECLARE_SOA_COLUMN(PyTrackPr, pyTrackPr, float); //! track0 py at min +DECLARE_SOA_COLUMN(PzTrackPr, pzTrackPr, float); //! track0 pz at min +DECLARE_SOA_COLUMN(PxTrackPi, pxTrackPi, float); //! track1 px at min +DECLARE_SOA_COLUMN(PyTrackPi, pyTrackPi, float); //! track1 py at min +DECLARE_SOA_COLUMN(PzTrackPi, pzTrackPi, float); //! track1 pz at min +DECLARE_SOA_COLUMN(PxTrackDe, pxTrackDe, float); //! track2 px at min +DECLARE_SOA_COLUMN(PyTrackDe, pyTrackDe, float); //! track2 py at min +DECLARE_SOA_COLUMN(PzTrackDe, pzTrackDe, float); //! track2 pz at min + +// DCAs to PV +DECLARE_SOA_COLUMN(DCAXYTrackPrToPV, dcaXYtrackPrToPv, float); //! DCAXY of proton to PV +DECLARE_SOA_COLUMN(DCAXYTrackPiToPV, dcaXYtrackPiToPv, float); //! DCAXY of pion to PV +DECLARE_SOA_COLUMN(DCAXYTrackDeToPV, dcaXYtrackDeToPv, float); //! DCAXY of deuteron to PV +DECLARE_SOA_COLUMN(DCAZTrackPrToPV, dcaZtrackPrToPv, float); //! DCAZ of proton to PV +DECLARE_SOA_COLUMN(DCAZTrackPiToPV, dcaZtrackPiToPv, float); //! DCAZ of pion to PV +DECLARE_SOA_COLUMN(DCAZTrackDeToPV, dcaZtrackDeToPv, float); //! DCAZ of deuteron to PV + +// DCAs to SV +DECLARE_SOA_COLUMN(DCATrackPrToSV, dcaTrackPrToSv, float); //! DCA of proton to SV +DECLARE_SOA_COLUMN(DCATrackPiToSV, dcaTrackPiToSv, float); //! DCA of pion to SV +DECLARE_SOA_COLUMN(DCATrackDeToSV, dcaTrackDeToSv, float); //! DCA of deuteron to SV +DECLARE_SOA_COLUMN(DCAVtxToDaughtersAv, dcaVtxToDaughtersAv, float); //! Quadratic sum of DCA between daughters at SV + +// CosPA +DECLARE_SOA_COLUMN(CosPA, cosPA, float); //! Cosine of pointing angle of the 3body candidate + +// Ct +DECLARE_SOA_COLUMN(Ct, ct, float); //! Reconstruction Ct of 3body candidate + +// Strangeness tracking +DECLARE_SOA_COLUMN(TrackedClSize, trackedClSize, float); //! Average ITS cluster size of strangeness tracked 3body + +// PID +DECLARE_SOA_COLUMN(TPCNSigmaPr, tpcNSigmaPr, float); //! nsigma proton of TPC PID of the proton daughter +DECLARE_SOA_COLUMN(TPCNSigmaPi, tpcNSigmaPi, float); //! nsigma pion of TPC PID of the pion daughter +DECLARE_SOA_COLUMN(TPCNSigmaDe, tpcNSigmaDe, float); //! nsigma deuteron of TPC PID of the bachelor daughter +DECLARE_SOA_COLUMN(TPCNSigmaPiBach, tpcNSigmaPiBach, float); //! nsigma pion of TPC PID of the bachelor daughter +DECLARE_SOA_COLUMN(TOFNSigmaDe, tofNSigmaDe, float); //! nsigma deuteron of TOF PID of the bachelor daughter +DECLARE_SOA_COLUMN(PIDTrackingDe, pidTrackingDe, uint32_t); //! PID during tracking of bachelor daughter + +// Daughter track quality +DECLARE_SOA_COLUMN(TPCNClTrackPr, tpcNClTrackPr, int); //! Number of TPC clusters of proton daughter +DECLARE_SOA_COLUMN(TPCNClTrackPi, tpcNClTrackPi, int); //! Number of TPC clusters of pion daughter +DECLARE_SOA_COLUMN(TPCNClTrackDe, tpcNClTrackDe, int); //! Number of TPC clusters of deuteron daughter +DECLARE_SOA_COLUMN(ITSClSizePr, itsClsizePr, double); //! average ITS cluster size of proton daughter +DECLARE_SOA_COLUMN(ITSClSizePi, itsClsizePi, double); //! average ITS cluster size of pion daughter +DECLARE_SOA_COLUMN(ITSClSizeDe, itsClsizeDe, double); //! average ITS cluster size of deuteron daughter + +// Covariance matrices +DECLARE_SOA_COLUMN(CovProton, covProton, float[21]); //! covariance matrix elements of proton daughter track +DECLARE_SOA_COLUMN(CovPion, covPion, float[21]); //! covariance matrix elements of pion daughter track +DECLARE_SOA_COLUMN(CovDeuteron, covDeuteron, float[21]); //! covariance matrix elements of deuteron daughter track +DECLARE_SOA_COLUMN(VtxCovMat, vtxCovMat, float[21]); //! covariance matrix elements of candidate + +// Monte Carlo info +DECLARE_SOA_COLUMN(GenPx, genPx, float); // generated Px of the hypertriton in GeV/c +DECLARE_SOA_COLUMN(GenPy, genPy, float); // generated Py of the hypertriton in GeV/c +DECLARE_SOA_COLUMN(GenPz, genPz, float); // generated Pz of the hypertriton in GeV/c +DECLARE_SOA_COLUMN(GenX, genX, float); // generated decay vtx position X of the hypertriton +DECLARE_SOA_COLUMN(GenY, genY, float); // generated decay vtx position Y of the hypertriton +DECLARE_SOA_COLUMN(GenZ, genZ, float); // generated decay vtx position Z of the hypertriton +DECLARE_SOA_COLUMN(GenCt, genCt, float); // generated Ct of the hypertriton +DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // generated Phi of the hypertriton +DECLARE_SOA_COLUMN(GenEta, genEta, float); // Eta of the hypertriton +DECLARE_SOA_COLUMN(GenRap, genRap, float); // generated rapidity of the hypertriton +DECLARE_SOA_COLUMN(GenPPr, genPPr, float); //! generated momentum proton daughter particle +DECLARE_SOA_COLUMN(GenPPi, genPPi, float); //! generated momentum pion daughter particle +DECLARE_SOA_COLUMN(GenPDe, genPDe, float); //! generated momentum deuteron daughter particle +DECLARE_SOA_COLUMN(GenPtPr, genPtPr, float); //! generated transverse momentum proton daughter particle +DECLARE_SOA_COLUMN(GenPtPi, genPtPi, float); //! generated transverse momentum pion daughter particle +DECLARE_SOA_COLUMN(GenPtDe, genPtDe, float); //! generated transverse momentum deuteron daughter particle +DECLARE_SOA_COLUMN(IsTrueH3L, isTrueH3l, bool); //! flag for true hypertriton candidate +DECLARE_SOA_COLUMN(IsTrueAntiH3L, isTrueAntiH3l, bool); //! flag for true anti-hypertriton candidate +DECLARE_SOA_COLUMN(MotherPdgCode, motherPdgCode, int); //! PDG code of the mother particle +DECLARE_SOA_COLUMN(PrPdgCode, prPdgCode, int); //! MC particle proton PDG code +DECLARE_SOA_COLUMN(PiPdgCode, piPdgCode, int); //! MC particle pion PDG code +DECLARE_SOA_COLUMN(DePdgCode, dePdgCode, int); //! MC particle deuteron PDG code +DECLARE_SOA_COLUMN(IsDePrimary, isDePrimary, bool); //! flag for deuteron daughter primary +DECLARE_SOA_COLUMN(IsSurvEvSel, isSurvEvSel, int); //! flag if reco collision survived event selection +DECLARE_SOA_COLUMN(IsReco, isreco, int); //! flag if candidate was reconstructed // Derived expressions // Momenta -DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! 3 body p - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0 + pxtrack1 + pxtrack2, pytrack0 + pytrack1 + pytrack2, pztrack0 + pztrack1 + pztrack2); }); -DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! 3 body pT - [](float pxtrack0, float pytrack0, float pxtrack1, float pytrack1, float pxtrack2, float pytrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0 + pxtrack1 + pxtrack2, pytrack0 + pytrack1 + pytrack2); }); +DECLARE_SOA_DYNAMIC_COLUMN(Pt, pt, //! 3 body pT in GeV/c + [](float px, float py) -> float { return RecoDecay::sqrtSumOfSquares(px, py); }); +DECLARE_SOA_DYNAMIC_COLUMN(P, p, //! 3 body total momentum in GeV/c + [](float px, float py, float pz) -> float { return RecoDecay::sqrtSumOfSquares(px, py, pz); }); +DECLARE_SOA_DYNAMIC_COLUMN(GenPt, genPt, //! 3 body pT in GeV/c + [](float genPx, float genPy) -> float { return RecoDecay::sqrtSumOfSquares(genPx, genPy); }); +DECLARE_SOA_DYNAMIC_COLUMN(GenP, genP, //! 3 body total momentum in GeV/c + [](float genPx, float genPy, float genPz) -> float { return RecoDecay::sqrtSumOfSquares(genPx, genPy, genPz); }); // Length quantities DECLARE_SOA_DYNAMIC_COLUMN(VtxRadius, vtxradius, //! 3 body decay radius (2D, centered at zero) [](float x, float y) -> float { return RecoDecay::sqrtSumOfSquares(x, y); }); +DECLARE_SOA_DYNAMIC_COLUMN(GenRadius, genRadius, //! 3 body decay radius (2D, centered at zero) + [](float genX, float genY) -> float { return RecoDecay::sqrtSumOfSquares(genX, genY); }); // Distance Over To Mom DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to 3 body decay distance over total momentum @@ -76,9 +154,6 @@ DECLARE_SOA_DYNAMIC_COLUMN(DistOverTotMom, distovertotmom, //! PV to 3 body deca return std::sqrt(std::pow(X - pvX, 2) + std::pow(Y - pvY, 2) + std::pow(Z - pvZ, 2)) / (P + 1E-10); }); -// CosPA -DECLARE_SOA_DYNAMIC_COLUMN(VtxCosPA, vtxcosPA, //! 3 body vtx CosPA - [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{X, Y, Z}, std::array{Px, Py, Pz}); }); // Dca to PV DECLARE_SOA_DYNAMIC_COLUMN(DCAVtxToPV, dcavtxtopv, //! DCA of 3 body vtx to PV [](float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) -> float { return std::sqrt((std::pow((pvY - Y) * Pz - (pvZ - Z) * Py, 2) + std::pow((pvX - X) * Pz - (pvZ - Z) * Px, 2) + std::pow((pvX - X) * Py - (pvY - Y) * Px, 2)) / (Px * Px + Py * Py + Pz * Pz)); }); @@ -89,532 +164,152 @@ DECLARE_SOA_DYNAMIC_COLUMN(Eta, eta, //! 3 body vtx eta DECLARE_SOA_DYNAMIC_COLUMN(Phi, phi, //! 3 body vtx phi [](float Px, float Py) -> float { return RecoDecay::phi(Px, Py); }); -// Calculated on the fly with mother particle hypothesis -DECLARE_SOA_DYNAMIC_COLUMN(MHypertriton, mHypertriton, //! mass under Hypertriton hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); }); -DECLARE_SOA_DYNAMIC_COLUMN(MAntiHypertriton, mAntiHypertriton, //! mass under antiHypertriton hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); }); - -DECLARE_SOA_DYNAMIC_COLUMN(MHyperHelium4, mHyperHelium4, //! mass under HyperHelium4 hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassHelium3}); }); -DECLARE_SOA_DYNAMIC_COLUMN(MAntiHyperHelium4, mAntiHyperHelium4, //! mass under antiHyperHelium4 hypothesis - [](float pxtrack0, float pytrack0, float pztrack0, float pxtrack1, float pytrack1, float pztrack1, float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::m(std::array{std::array{pxtrack0, pytrack0, pztrack0}, std::array{pxtrack1, pytrack1, pztrack1}, std::array{pxtrack2, pytrack2, pztrack2}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassHelium3}); }); - -DECLARE_SOA_DYNAMIC_COLUMN(YHypertriton, yHypertriton, //! 3 body vtx y with hypertriton or antihypertriton hypothesis +// Rapidity +DECLARE_SOA_DYNAMIC_COLUMN(Rap, rap, //! 3 body vtx y with hypertriton or antihypertriton hypothesis [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassHyperTriton); }); -DECLARE_SOA_DYNAMIC_COLUMN(YHyperHelium4, yHyperHelium4, //! 3 body vtx y with hyperhelium4 or antihyperhelium4 hypothesis - [](float Px, float Py, float Pz) -> float { return RecoDecay::y(std::array{Px, Py, Pz}, o2::constants::physics::MassHyperHelium4); }); - -// kinematic information of daughter tracks -DECLARE_SOA_DYNAMIC_COLUMN(Track0Pt, track0pt, //! daughter0 pT - [](float pxtrack0, float pytrack0) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack0, pytrack0); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track1Pt, track1pt, //! daughter1 pT - [](float pxtrack1, float pytrack1) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack1, pytrack1); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track2Pt, track2pt, //! daughter2 pT - [](float pxtrack2, float pytrack2) -> float { return RecoDecay::sqrtSumOfSquares(pxtrack2, pytrack2); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track0Eta, track0eta, //! daughter0 eta - [](float pxtrack0, float pytrack0, float pztrack0) -> float { return RecoDecay::eta(std::array{pxtrack0, pytrack0, pztrack0}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track0Phi, track0phi, //! daughter0 phi - [](float pxtrack0, float pytrack0) -> float { return RecoDecay::phi(pxtrack0, pytrack0); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track1Eta, track1eta, //! daughter1 eta - [](float pxtrack1, float pytrack1, float pztrack1) -> float { return RecoDecay::eta(std::array{pxtrack1, pytrack1, pztrack1}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track1Phi, track1phi, //! daughter1 phi - [](float pxtrack1, float pytrack1) -> float { return RecoDecay::phi(pxtrack1, pytrack1); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track2Eta, track2eta, //! daughter2 eta - [](float pxtrack2, float pytrack2, float pztrack2) -> float { return RecoDecay::eta(std::array{pxtrack2, pytrack2, pztrack2}); }); -DECLARE_SOA_DYNAMIC_COLUMN(Track2Phi, track2phi, //! daughter2 phi - [](float pxtrack2, float pytrack2) -> float { return RecoDecay::phi(pxtrack2, pytrack2); }); - -DECLARE_SOA_EXPRESSION_COLUMN(Px, px, //! 3 body vtx px - float, 1.f * aod::vtx3body::pxtrack0 + 1.f * aod::vtx3body::pxtrack1 + 1.f * aod::vtx3body::pxtrack2); -DECLARE_SOA_EXPRESSION_COLUMN(Py, py, //! 3 body vtx py - float, 1.f * aod::vtx3body::pytrack0 + 1.f * aod::vtx3body::pytrack1 + 1.f * aod::vtx3body::pytrack2); -DECLARE_SOA_EXPRESSION_COLUMN(Pz, pz, //! 3 body vtx pz - float, 1.f * aod::vtx3body::pztrack0 + 1.f * aod::vtx3body::pztrack1 + 1.f * aod::vtx3body::pztrack2); -} // namespace vtx3body - -DECLARE_SOA_TABLE_FULL(StoredVtx3BodyDatas, "Vtx3BodyDatas", "AOD", "Vtx3BodyDATA", //! - o2::soa::Index<>, vtx3body::Track0Id, vtx3body::Track1Id, vtx3body::Track2Id, vtx3body::CollisionId, vtx3body::Decay3BodyId, - vtx3body::X, vtx3body::Y, vtx3body::Z, - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, - vtx3body::DCAVtxDaughters, - vtx3body::DCAXYTrack0ToPV, vtx3body::DCAXYTrack1ToPV, vtx3body::DCAXYTrack2ToPV, - vtx3body::DCATrack0ToPV, vtx3body::DCATrack1ToPV, vtx3body::DCATrack2ToPV, - vtx3body::TOFNSigmaBachDe, - - // Dynamic columns - vtx3body::P, - vtx3body::Pt, - vtx3body::VtxRadius, - vtx3body::DistOverTotMom, - vtx3body::VtxCosPA, - vtx3body::DCAVtxToPV, - - // Invariant masses - vtx3body::MHypertriton, - vtx3body::MAntiHypertriton, - vtx3body::MHyperHelium4, - vtx3body::MAntiHyperHelium4, - - // Longitudinal - vtx3body::YHypertriton, - vtx3body::YHyperHelium4, - vtx3body::Eta, - vtx3body::Phi, - vtx3body::Track0Pt, - vtx3body::Track0Eta, - vtx3body::Track0Phi, - vtx3body::Track1Pt, - vtx3body::Track1Eta, - vtx3body::Track1Phi, - vtx3body::Track2Pt, - vtx3body::Track2Eta, - vtx3body::Track2Phi); - -// extended table with expression columns that can be used as arguments of dynamic columns -DECLARE_SOA_EXTENDED_TABLE_USER(Vtx3BodyDatas, StoredVtx3BodyDatas, "Vtx3BodyDATAEXT", //! - vtx3body::Px, vtx3body::Py, vtx3body::Pz); - -using Vtx3BodyData = Vtx3BodyDatas::iterator; -namespace vtx3body -{ -DECLARE_SOA_INDEX_COLUMN(Vtx3BodyData, vtx3BodyData); //! Index to Vtx3BodyData entry -} - -DECLARE_SOA_TABLE(Decay3BodyDataLink, "AOD", "DECAY3BODYLINK", //! Joinable table with Decay3bodys which links to Vtx3BodyData which is not produced for all entries - vtx3body::Vtx3BodyDataId); - -using Decay3BodysLinked = soa::Join; -using Decay3BodyLinked = Decay3BodysLinked::iterator; - -// Definition of labels for Vtx3BodyDatas -namespace mcvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Vtx3BodyDatas -} // namespace mcvtx3bodylabel -DECLARE_SOA_TABLE(McVtx3BodyLabels, "AOD", "MCVTXLABEL", //! Table joinable with Vtx3BodyData containing the MC labels - mcvtx3bodylabel::McParticleId); -using McVtx3BodyLabel = McVtx3BodyLabels::iterator; - -// Definition of labels for Decay3Bodys // Full table, joinable with Decay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) -namespace mcfullvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Decay3Bodys -} // namespace mcfullvtx3bodylabel - -DECLARE_SOA_TABLE(McFullVtx3BodyLabels, "AOD", "MCFULLVTXLABEL", //! Table joinable with Decay3Bodys - mcfullvtx3bodylabel::McParticleId); -using McFullVtx3BodyLabel = McFullVtx3BodyLabels::iterator; +// Kinematic information of daughter tracks +DECLARE_SOA_DYNAMIC_COLUMN(TrackPrPt, trackPrPt, //! daughter0 pT + [](float pxTrackPr, float pyTrackPr) -> float { return RecoDecay::sqrtSumOfSquares(pxTrackPr, pyTrackPr); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPiPt, trackPiPt, //! daughter1 pT + [](float pxTrackPi, float pyTrackPi) -> float { return RecoDecay::sqrtSumOfSquares(pxTrackPi, pyTrackPi); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackDePt, trackDePt, //! daughter2 pT + [](float pxTrackDe, float pyTrackDe) -> float { return RecoDecay::sqrtSumOfSquares(pxTrackDe, pyTrackDe); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPrEta, trackPrEta, //! daughter0 eta + [](float pxTrackPr, float pyTrackPr, float pzTrackPr) -> float { return RecoDecay::eta(std::array{pxTrackPr, pyTrackPr, pzTrackPr}); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPrPhi, trackPrPhi, //! daughter0 phi + [](float pxTrackPr, float pyTrackPr) -> float { return RecoDecay::phi(pxTrackPr, pyTrackPr); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPiEta, trackPiEta, //! daughter1 eta + [](float pxTrackPi, float pyTrackPi, float pzTrackPi) -> float { return RecoDecay::eta(std::array{pxTrackPi, pyTrackPi, pzTrackPi}); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackPiPhi, trackPiPhi, //! daughter1 phi + [](float pxTrackPi, float pyTrackPi) -> float { return RecoDecay::phi(pxTrackPi, pyTrackPi); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackDeEta, trackDeEta, //! daughter2 eta + [](float pxTrackDe, float pyTrackDe, float pzTrackDe) -> float { return RecoDecay::eta(std::array{pxTrackDe, pyTrackDe, pzTrackDe}); }); +DECLARE_SOA_DYNAMIC_COLUMN(TrackDePhi, trackDePhi, //! daughter2 phi + [](float pxTrackDe, float pyTrackDe) -> float { return RecoDecay::phi(pxTrackDe, pyTrackDe); }); +} // namespace vtx3body -// output table for ML studies -namespace hyp3body -{ -// collision -DECLARE_SOA_COLUMN(Centrality, centrality, float); //! centrality -// reconstruced candidate -DECLARE_SOA_COLUMN(IsMatter, isMatter, bool); //! bool: true for matter -DECLARE_SOA_COLUMN(M, m, float); //! invariant mass -DECLARE_SOA_COLUMN(P, p, float); //! p -DECLARE_SOA_COLUMN(Pt, pt, float); //! pT -DECLARE_SOA_COLUMN(Ct, ct, float); //! ct -DECLARE_SOA_COLUMN(CosPA, cospa, float); -DECLARE_SOA_COLUMN(DCADaughters, dcaDaughters, float); //! DCA among daughters -DECLARE_SOA_COLUMN(DCACandToPV, dcaCandtopv, float); //! DCA of the reconstructed track to pv -DECLARE_SOA_COLUMN(VtxRadius, vtxRadius, float); //! Radius of SV -// kinematic infomation of daughter tracks -DECLARE_SOA_COLUMN(PtProton, ptProton, float); //! pT of the proton daughter -DECLARE_SOA_COLUMN(EtaProton, etaProton, float); //! eta of the proton daughter -DECLARE_SOA_COLUMN(PhiProton, phiProton, float); //! phi of the proton daughter -DECLARE_SOA_COLUMN(RadiusProton, radiusProton, float); //! radius of innermost hit of the proton daughter -DECLARE_SOA_COLUMN(PtPion, ptPion, float); //! pT of the pion daughter -DECLARE_SOA_COLUMN(EtaPion, etaPion, float); //! eta of the pion daughter -DECLARE_SOA_COLUMN(PhiPion, phiPion, float); //! phi of the pion daughter -DECLARE_SOA_COLUMN(RadiusPion, radiusPion, float); //! radius of innermost hit of the pion daughter -DECLARE_SOA_COLUMN(PtBachelor, ptBachelor, float); //! pT of the bachelor daughter -DECLARE_SOA_COLUMN(EtaBachelor, etaBachelor, float); //! eta of the bachelor daughter -DECLARE_SOA_COLUMN(PhiBachelor, phiBachelor, float); //! phi of the bachelor daughter -DECLARE_SOA_COLUMN(RadiusBachelor, radiusBachelor, float); //! radius of innermost hit of the bachelor daughter -// track quality -DECLARE_SOA_COLUMN(TPCNclusProton, tpcNclusProton, uint8_t); //! number of TPC clusters of the proton daughter -DECLARE_SOA_COLUMN(TPCNclusPion, tpcNclusPion, uint8_t); //! number of TPC clusters of the pion daughter -DECLARE_SOA_COLUMN(TPCNclusBachelor, tpcNclusBachelor, uint8_t); //! number of TPC clusters of the bachelor daughter -DECLARE_SOA_COLUMN(ITSNclusSizeProton, itsNclusSizeProton, uint8_t); //! average ITS cluster size of the proton daughter -DECLARE_SOA_COLUMN(ITSNclusSizePion, itsNclusSizePion, uint8_t); //! average ITS cluster size of the pion daughter -DECLARE_SOA_COLUMN(ITSNclusSizeBachelor, itsNclusSizeBachelor, uint8_t); //! average ITS cluster size of the bachelor daughter -// PID -DECLARE_SOA_COLUMN(TPCNSigmaProton, tpcNSigmaProton, float); //! nsigma of TPC PID of the proton daughter -DECLARE_SOA_COLUMN(TPCNSigmaPion, tpcNSigmaPion, float); //! nsigma of TPC PID of the pion daughter -DECLARE_SOA_COLUMN(TPCNSigmaBachelor, tpcNSigmaBachelor, float); //! nsigma of TPC PID of the bachelor daughter -DECLARE_SOA_COLUMN(TOFNSigmaBachelor, tofNSigmaBachelor, float); //! nsigma of TOF PID of the bachelor daughter -// DCA to PV -DECLARE_SOA_COLUMN(DCAXYProtonToPV, dcaxyProtontoPV, float); //! DCAXY of the proton daughter to pv -DECLARE_SOA_COLUMN(DCAXYPionToPV, dcaxyPiontoPV, float); //! DCAXY of the pion daughter to pv -DECLARE_SOA_COLUMN(DCAXYBachelorToPV, dcaxyBachelortoPV, float); //! DCAXY of the bachelor daughter to pv -DECLARE_SOA_COLUMN(DCAProtonToPV, dcaProtontoPV, float); //! DCA of the proton daughter to pv -DECLARE_SOA_COLUMN(DCAPionToPV, dcaPiontoPV, float); //! DCA of the pion daughter to pv -DECLARE_SOA_COLUMN(DCABachelorToPV, dcaBachelortoPV, float); //! DCA of the bachelor daughter to pv -DECLARE_SOA_COLUMN(IsBachPrimary, isbachprimary, bool); //! flag for bachelor daughter primary -// for MC -DECLARE_SOA_COLUMN(GenP, genP, float); // P of the hypertriton -DECLARE_SOA_COLUMN(GenPt, genPt, float); // pT of the hypertriton -DECLARE_SOA_COLUMN(GenCt, genCt, float); // ct of the hypertriton -DECLARE_SOA_COLUMN(GenPhi, genPhi, float); // Phi of the hypertriton -DECLARE_SOA_COLUMN(GenEta, genEta, float); // Eta of the hypertriton -DECLARE_SOA_COLUMN(GenRapidity, genRapidity, float); // Rapidity of the hypertriton -DECLARE_SOA_COLUMN(IsReco, isReco, bool); // bool: true for reco -DECLARE_SOA_COLUMN(IsSignal, isSignal, bool); // bool: true for signal -DECLARE_SOA_COLUMN(PdgCode, pdgCode, int); // pdgCode of the mcparticle, -1 for fake pair -DECLARE_SOA_COLUMN(SurvivedEventSelection, survivedEventSelection, bool); // bool: true for survived event selection -} // namespace hyp3body - -// output table for data -DECLARE_SOA_TABLE(Hyp3BodyCands, "AOD", "HYP3BODYCANDS", +// index table +DECLARE_SOA_TABLE(Decay3BodyIndices, "AOD", "3BodyINDEX", //! o2::soa::Index<>, - hyp3body::Centrality, - // secondary vertex and reconstruced candidate - hyp3body::IsMatter, - hyp3body::M, - hyp3body::P, - hyp3body::Pt, - hyp3body::Ct, - hyp3body::CosPA, - hyp3body::DCADaughters, - hyp3body::DCACandToPV, - hyp3body::VtxRadius, - // daughter tracks - hyp3body::PtProton, hyp3body::EtaProton, hyp3body::PhiProton, hyp3body::RadiusProton, - hyp3body::PtPion, hyp3body::EtaPion, hyp3body::PhiPion, hyp3body::RadiusPion, - hyp3body::PtBachelor, hyp3body::EtaBachelor, hyp3body::PhiBachelor, hyp3body::RadiusBachelor, - hyp3body::TPCNclusProton, hyp3body::TPCNclusPion, hyp3body::TPCNclusBachelor, - hyp3body::ITSNclusSizeProton, hyp3body::ITSNclusSizePion, hyp3body::ITSNclusSizeBachelor, - hyp3body::TPCNSigmaProton, hyp3body::TPCNSigmaPion, hyp3body::TPCNSigmaBachelor, - hyp3body::TOFNSigmaBachelor, - hyp3body::DCAXYProtonToPV, hyp3body::DCAXYPionToPV, hyp3body::DCAXYBachelorToPV, - hyp3body::DCAProtonToPV, hyp3body::DCAPionToPV, hyp3body::DCABachelorToPV); - -// output table for MC -DECLARE_SOA_TABLE(MCHyp3BodyCands, "AOD", "MCHYP3BODYCANDS", - o2::soa::Index<>, - hyp3body::Centrality, - // secondary vertex and reconstruced candidate - hyp3body::IsMatter, - hyp3body::M, - hyp3body::P, - hyp3body::Pt, - hyp3body::Ct, - hyp3body::CosPA, - hyp3body::DCADaughters, - hyp3body::DCACandToPV, - hyp3body::VtxRadius, - // daughter tracks - hyp3body::PtProton, hyp3body::EtaProton, hyp3body::PhiProton, hyp3body::RadiusProton, - hyp3body::PtPion, hyp3body::EtaPion, hyp3body::PhiPion, hyp3body::RadiusPion, - hyp3body::PtBachelor, hyp3body::EtaBachelor, hyp3body::PhiBachelor, hyp3body::RadiusBachelor, - hyp3body::TPCNclusProton, hyp3body::TPCNclusPion, hyp3body::TPCNclusBachelor, - hyp3body::ITSNclusSizeProton, hyp3body::ITSNclusSizePion, hyp3body::ITSNclusSizeBachelor, - hyp3body::TPCNSigmaProton, hyp3body::TPCNSigmaPion, hyp3body::TPCNSigmaBachelor, - hyp3body::TOFNSigmaBachelor, - hyp3body::DCAXYProtonToPV, hyp3body::DCAXYPionToPV, hyp3body::DCAXYBachelorToPV, - hyp3body::DCAProtonToPV, hyp3body::DCAPionToPV, hyp3body::DCABachelorToPV, - hyp3body::IsBachPrimary, - // MC information - hyp3body::GenP, - hyp3body::GenPt, - hyp3body::GenCt, - hyp3body::GenPhi, - hyp3body::GenEta, - hyp3body::GenRapidity, - hyp3body::IsSignal, - hyp3body::IsReco, - hyp3body::PdgCode, - hyp3body::SurvivedEventSelection); - -//______________________________________________________ -// DATAMODEL FOR KFPARTICLE DECAY3BODYS - -namespace kfvtx3body -{ -// General 3 body Vtx properties: mass, momentum, charge -DECLARE_SOA_COLUMN(Mass, mass, float); //! candidate mass (PID hypothesis depending on bachelor charge) -DECLARE_SOA_COLUMN(XErr, xerr, float); //! candidate position x error at decay position -DECLARE_SOA_COLUMN(YErr, yerr, float); //! candidate position y error at decay position -DECLARE_SOA_COLUMN(ZErr, zerr, float); //! candidate position z error at decay position -DECLARE_SOA_COLUMN(Px, px, float); //! candidate px at decay position -DECLARE_SOA_COLUMN(Py, py, float); //! candidate py at decay position -DECLARE_SOA_COLUMN(Pz, pz, float); //! candidate pz at decay position -DECLARE_SOA_COLUMN(Pt, pt, float); //! candidate pt at decay position -DECLARE_SOA_COLUMN(PxErr, pxerr, float); //! candidate px error at decay position -DECLARE_SOA_COLUMN(PyErr, pyerr, float); //! candidate py error at decay position -DECLARE_SOA_COLUMN(PzErr, pzerr, float); //! candidate pz error at decay position -DECLARE_SOA_COLUMN(PtErr, pterr, float); //! candidate pt error at decay position -DECLARE_SOA_COLUMN(Sign, sign, float); //! candidate sign - -// topological properties -DECLARE_SOA_COLUMN(VtxCosPAKF, vtxcospakf, float); //! 3 body vtx CosPA from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(VtxCosXYPAKF, vtxcosxypakf, float); //! 3 body vtx CosPA from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(VtxCosPAKFtopo, vtxcospakftopo, float); //! 3 body vtx CosPA from KFParticle after topological constraint (using kfpPV) -DECLARE_SOA_COLUMN(VtxCosXYPAKFtopo, vtxcosxypakftopo, float); //! 3 body vtx CosPA from KFParticle after topological constraint (using kfpPV) -DECLARE_SOA_COLUMN(DCAVtxToPVKF, dcavtxtopvkf, float); //! 3 body vtx DCA to PV from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(DCAXYVtxToPVKF, dcaxyvtxtopvkf, float); //! 3 body vtx DCAxy to PV from KFParticle (using kfpPV) -DECLARE_SOA_COLUMN(DecayLKF, decaylkf, float); //! 3 body vtx decay length from KFParticle (using kfpPV after topological constraint) -DECLARE_SOA_COLUMN(DecayLXYKF, decaylxykf, float); //! 3 body vtx decay length XY from KFParticle (using kfpPV after topological constraint) -DECLARE_SOA_COLUMN(DecayLDeltaL, decayldeltal, float); //! 3 body vtx l/dl from KFParticle (using kfpPV after topological constraint) -DECLARE_SOA_COLUMN(Chi2geoNDF, chi2geondf, float); //! 3 body vtx chi2geo from geometrical KFParticle fit -DECLARE_SOA_COLUMN(Chi2topoNDF, chi2topondf, float); //! 3 body vtx chi2topo from KFParticle topological constraint to the PV (using kfpPV) -DECLARE_SOA_COLUMN(CTauKFtopo, ctaukftopo, float); //! 3 body vtx ctau from KFParticle after topological constraint - -// Strangeness tracking -DECLARE_SOA_COLUMN(TrackedClSize, trackedclsize, int); //! Cluster size of strangeness tracked 3body - -// daughters -DECLARE_SOA_COLUMN(DCATrack0ToPVKF, dcatrack0topvkf, float); //! DCA of proton prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCATrack1ToPVKF, dcatrack1topvkf, float); //! DCA of pion prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCATrack2ToPVKF, dcatrack2topvkf, float); //! DCA of deuteron prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack0ToPVKF, dcaxytrack0topvkf, float); //! DCAxy of proton prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack1ToPVKF, dcaxytrack1topvkf, float); //! DCAxy of pion prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack2ToPVKF, dcaxytrack2topvkf, float); //! DCAxy of deuteron prong to PV from KFParticle -DECLARE_SOA_COLUMN(DCATrackPosToPV, dcatrackpostopv, float); //! DCA of positive track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCATrackNegToPV, dcatracknegtopv, float); //! DCA of negative track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCATrackBachToPV, dcatrackbachtopv, float); //! DCA of bachelor track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrackPosToPV, dcaxytrackpostopv, float); //! DCAxy of positive track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrackNegToPV, dcaxytracknegtopv, float); //! DCAxy of negative track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrackBachToPV, dcaxytrackbachtopv, float); //! DCAxy of bachelor track to PV (propagated before vtx fit) -DECLARE_SOA_COLUMN(DCAxyTrack0ToSVKF, dcaxytrack0tosvkf, float); //! DCAxy of proton prong to SV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack1ToSVKF, dcaxytrack1tosvkf, float); //! DCAxy of pion prong to SV from KFParticle -DECLARE_SOA_COLUMN(DCAxyTrack2ToSVKF, dcaxytrack2tosvkf, float); //! DCAxy of deuteron prong to SV from KFParticle -DECLARE_SOA_COLUMN(DCATrack0ToTrack1KF, dcatrack0totrack1kf, float); //! DCAxy of proton prong to pion from KFParticle -DECLARE_SOA_COLUMN(DCATrack0ToTrack2KF, dcatrack0totrack2kf, float); //! DCAxy of proton prong to deuteron from KFParticle -DECLARE_SOA_COLUMN(DCATrack1ToTrack2KF, dcatrack1totrack2kf, float); //! DCAxy of pion prong to deuteron from KFParticle -DECLARE_SOA_COLUMN(DCAVtxDaughtersKF, dcavtxdaughterskf, float); //! sum of DCAs between daughters in 3D from KFParticle -DECLARE_SOA_COLUMN(Track0Sign, track0sign, float); //! sign of proton daughter track -DECLARE_SOA_COLUMN(Track1Sign, track1sign, float); //! sign of pion daughter track -DECLARE_SOA_COLUMN(Track2Sign, track2sign, float); //! sign of deuteron daughter track -DECLARE_SOA_COLUMN(TPCInnerParamTrack0, tpcinnerparamtrack0, float); //! momentum at inner wall of TPC of proton daughter -DECLARE_SOA_COLUMN(TPCInnerParamTrack1, tpcinnerparamtrack1, float); //! momentum at inner wall of TPC of pion daughter -DECLARE_SOA_COLUMN(TPCInnerParamTrack2, tpcinnerparamtrack2, float); //! momentum at inner wall of TPC of deuteron daughter -DECLARE_SOA_COLUMN(TPCNClTrack0, tpcncltrack0, int); //! Number of TPC clusters of proton daughter -DECLARE_SOA_COLUMN(TPCNClTrack1, tpcncltrack1, int); //! Number of TPC clusters of pion daughter -DECLARE_SOA_COLUMN(TPCNClTrack2, tpcncltrack2, int); //! Number of TPC clusters of deuteron daughter -DECLARE_SOA_COLUMN(TPCChi2NClDeuteron, tpcchi2ncldeuteron, float); //! TPC Chi2 / cluster of deuteron daughter -DECLARE_SOA_COLUMN(DeltaPhiDeuteron, deltaphideuteron, float); //! phi before track rotation - phi after track rotation for deuteron track -DECLARE_SOA_COLUMN(DeltaPhiProton, deltaphiproton, float); //! phi before track rotation - phi after track rotation for proton track -// PID -DECLARE_SOA_COLUMN(TPCNSigmaProton, tpcnsigmaproton, float); //! nsigma proton of TPC PID of the proton daughter -DECLARE_SOA_COLUMN(TPCNSigmaPion, tpcnsigmapion, float); //! nsigma pion of TPC PID of the pion daughter -DECLARE_SOA_COLUMN(TPCNSigmaDeuteron, tpcnsigmadeuteron, float); //! nsigma deuteron of TPC PID of the bachelor daughter -DECLARE_SOA_COLUMN(TPCNSigmaPionBach, tpcnsigmapionbach, float); //! nsigma pion of TPC PID of the bachelor daughter -DECLARE_SOA_COLUMN(TPCdEdxProton, tpcdedxproton, float); //! TPC dEdx of the proton daughter -DECLARE_SOA_COLUMN(TPCdEdxPion, tpcdedxpion, float); //! TPC dEdx of the pion daughter -DECLARE_SOA_COLUMN(TPCdEdxDeuteron, tpcdedxdeuteron, float); //! TPC dEdx of the bachelor daughter -DECLARE_SOA_COLUMN(TOFNSigmaDeuteron, tofnsigmadeuteron, float); //! nsigma of TOF PID of the bachelor daughter -DECLARE_SOA_COLUMN(ITSClusSizeDeuteron, itsclussizedeuteron, double); //! average ITS cluster size of bachelor daughter -DECLARE_SOA_COLUMN(PIDTrackingDeuteron, pidtrackingdeuteron, uint32_t); //! PID during tracking of bachelor daughter - -// Monte Carlo -DECLARE_SOA_COLUMN(GenP, genp, float); //! generated momentum -DECLARE_SOA_COLUMN(GenPt, genpt, float); //! generated transverse momentum -DECLARE_SOA_COLUMN(GenDecVtxX, gendecvtxx, double); //! generated decay vertex position x -DECLARE_SOA_COLUMN(GenDecVtxY, gendecvtxy, double); //! generated decay vertex position y -DECLARE_SOA_COLUMN(GenDecVtxZ, gendecvtxz, double); //! generated decay vertex position z -DECLARE_SOA_COLUMN(GenCtau, genctau, double); //! generated ctau -DECLARE_SOA_COLUMN(GenPhi, genphi, float); //! generated phi -DECLARE_SOA_COLUMN(GenEta, geneta, float); //! generated eta -DECLARE_SOA_COLUMN(GenRapidity, genrapidity, float); //! generated rapidity -DECLARE_SOA_COLUMN(GenPosP, genposp, float); //! generated momentum pos daughter particle -DECLARE_SOA_COLUMN(GenPosPt, genpospt, float); //! generated transverse momentum pos daughter particle -DECLARE_SOA_COLUMN(GenNegP, gennegp, float); //! generated momentum neg daughter particle -DECLARE_SOA_COLUMN(GenNegPt, gennegpt, float); //! generated transverse momentum neg daughter particle -DECLARE_SOA_COLUMN(GenBachP, genbachp, float); //! generated momentum bachelor daughter particle -DECLARE_SOA_COLUMN(GenBachPt, genbachpt, float); //! generated transverse momentum bachelor daughter particle -DECLARE_SOA_COLUMN(IsTrueH3L, istrueh3l, bool); //! flag for true hypertriton candidate -DECLARE_SOA_COLUMN(IsTrueAntiH3L, istrueantih3l, bool); //! flag for true anti-hypertriton candidate -DECLARE_SOA_COLUMN(PdgCodeDau0, pdgcodedau0, int); //! MC particle daughter 0 PDG code -DECLARE_SOA_COLUMN(PdgCodeDau1, pdgcodedau1, int); //! MC particle daughter 1 PDG code -DECLARE_SOA_COLUMN(PdgCodeDau2, pdgcodedau2, int); //! MC particle daughter 2 PDG code -DECLARE_SOA_COLUMN(IsBachPrimary, isbachprimary, bool); //! flag for bachelor daughter primary -DECLARE_SOA_COLUMN(SurvEvSel, survevsel, int); //! flag if reco collision survived event selection -DECLARE_SOA_COLUMN(IsReco, isreco, int); //! flag if candidate was reconstructed + vtx3body::Decay3BodyId, + vtx3body::TrackPrId, vtx3body::TrackPiId, vtx3body::TrackDeId, + vtx3body::CollisionId); -// V0 -DECLARE_SOA_COLUMN(MassV0, massv0, float); //! proton, pion vertex mass -DECLARE_SOA_COLUMN(Chi2MassV0, chi2massv0, float); //! chi2 of proton, pion mass constraint to Lambda mass -DECLARE_SOA_COLUMN(CosPAV0, cospav0, float); //! proton, pion vertex mass - -} // namespace kfvtx3body - -DECLARE_SOA_TABLE(KFVtx3BodyDatas, "AOD", "KFVTX3BODYDATA", - o2::soa::Index<>, vtx3body::CollisionId, vtx3body::Track0Id, vtx3body::Track1Id, vtx3body::Track2Id, vtx3body::Decay3BodyId, - - // hypertriton candidate - kfvtx3body::Mass, - vtx3body::X, vtx3body::Y, vtx3body::Z, - kfvtx3body::XErr, kfvtx3body::YErr, kfvtx3body::ZErr, - kfvtx3body::Px, kfvtx3body::Py, kfvtx3body::Pz, kfvtx3body::Pt, - kfvtx3body::PxErr, kfvtx3body::PyErr, kfvtx3body::PzErr, kfvtx3body::PtErr, - kfvtx3body::Sign, - kfvtx3body::DCAVtxToPVKF, kfvtx3body::DCAXYVtxToPVKF, - kfvtx3body::VtxCosPAKF, kfvtx3body::VtxCosXYPAKF, - kfvtx3body::VtxCosPAKFtopo, kfvtx3body::VtxCosXYPAKFtopo, - kfvtx3body::DecayLKF, kfvtx3body::DecayLXYKF, kfvtx3body::DecayLDeltaL, - kfvtx3body::Chi2geoNDF, kfvtx3body::Chi2topoNDF, - kfvtx3body::CTauKFtopo, kfvtx3body::TrackedClSize, - - // V0 - kfvtx3body::MassV0, kfvtx3body::Chi2MassV0, - kfvtx3body::CosPAV0, - - // daughters - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, // proton - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, // pion - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, // deuteron - kfvtx3body::TPCInnerParamTrack0, kfvtx3body::TPCInnerParamTrack1, kfvtx3body::TPCInnerParamTrack2, // proton, pion, deuteron - kfvtx3body::TPCNClTrack0, kfvtx3body::TPCNClTrack1, kfvtx3body::TPCNClTrack2, // proton, pion, deuteron - kfvtx3body::TPCChi2NClDeuteron, - kfvtx3body::DeltaPhiDeuteron, kfvtx3body::DeltaPhiProton, - kfvtx3body::DCATrack0ToPVKF, kfvtx3body::DCATrack1ToPVKF, kfvtx3body::DCATrack2ToPVKF, kfvtx3body::DCAxyTrack0ToPVKF, kfvtx3body::DCAxyTrack1ToPVKF, kfvtx3body::DCAxyTrack2ToPVKF, - kfvtx3body::DCAxyTrack0ToSVKF, kfvtx3body::DCAxyTrack1ToSVKF, kfvtx3body::DCAxyTrack2ToSVKF, - kfvtx3body::DCATrack0ToTrack1KF, kfvtx3body::DCATrack0ToTrack2KF, kfvtx3body::DCATrack1ToTrack2KF, - kfvtx3body::DCAVtxDaughtersKF, - kfvtx3body::DCAxyTrackPosToPV, kfvtx3body::DCAxyTrackNegToPV, kfvtx3body::DCAxyTrackBachToPV, - kfvtx3body::DCATrackPosToPV, kfvtx3body::DCATrackNegToPV, kfvtx3body::DCATrackBachToPV, - kfvtx3body::Track0Sign, kfvtx3body::Track1Sign, kfvtx3body::Track2Sign, // track sing: proton, pion, deuteron - kfvtx3body::TPCNSigmaProton, kfvtx3body::TPCNSigmaPion, kfvtx3body::TPCNSigmaDeuteron, kfvtx3body::TPCNSigmaPionBach, - kfvtx3body::TPCdEdxProton, kfvtx3body::TPCdEdxPion, kfvtx3body::TPCdEdxDeuteron, - kfvtx3body::TOFNSigmaDeuteron, - kfvtx3body::ITSClusSizeDeuteron, - kfvtx3body::PIDTrackingDeuteron); - -using KFVtx3BodyData = KFVtx3BodyDatas::iterator; -namespace kfvtx3body -{ -DECLARE_SOA_INDEX_COLUMN(KFVtx3BodyData, kfvtx3BodyData); //! Index to KFVtx3BodyData entry -} - -DECLARE_SOA_TABLE(KFDecay3BodyDataLink, "AOD", "KF3BODYLINK", //! Joinable table with Decay3bodys which links to KFVtx3BodyData which is not produced for all entries - kfvtx3body::KFVtx3BodyDataId); - -using KFDecay3BodysLinked = soa::Join; -using KFDecay3BodyLinked = KFDecay3BodysLinked::iterator; - -// Lite data candidate table for analysis -DECLARE_SOA_TABLE(KFVtx3BodyDatasLite, "AOD", "KF3BODYLITE", +// reconstructed candidate table for analysis +DECLARE_SOA_TABLE(Vtx3BodyDatas, "AOD", "VTX3BODYDATA", //! o2::soa::Index<>, - // hypertriton candidate - kfvtx3body::Mass, + vtx3body::Sign, + vtx3body::Mass, vtx3body::MassV0, vtx3body::X, vtx3body::Y, vtx3body::Z, - kfvtx3body::Px, kfvtx3body::Py, kfvtx3body::Pz, kfvtx3body::Pt, - kfvtx3body::Sign, - kfvtx3body::DCAVtxToPVKF, kfvtx3body::DCAXYVtxToPVKF, - kfvtx3body::VtxCosPAKF, kfvtx3body::VtxCosXYPAKF, - kfvtx3body::DecayLKF, kfvtx3body::DecayLXYKF, kfvtx3body::DecayLDeltaL, - kfvtx3body::Chi2geoNDF, kfvtx3body::Chi2topoNDF, - kfvtx3body::CTauKFtopo, kfvtx3body::TrackedClSize, - - // V0 - kfvtx3body::MassV0, - kfvtx3body::CosPAV0, - - // daughters - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, // proton - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, // pion - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, // deuteron - kfvtx3body::TPCInnerParamTrack0, kfvtx3body::TPCInnerParamTrack1, kfvtx3body::TPCInnerParamTrack2, // proton, pion, deuteron - kfvtx3body::TPCNClTrack0, kfvtx3body::TPCNClTrack1, kfvtx3body::TPCNClTrack2, // proton, pion, deuteron - kfvtx3body::TPCChi2NClDeuteron, - kfvtx3body::DeltaPhiDeuteron, kfvtx3body::DeltaPhiProton, - kfvtx3body::DCATrack0ToPVKF, kfvtx3body::DCATrack1ToPVKF, kfvtx3body::DCATrack2ToPVKF, kfvtx3body::DCAxyTrack0ToPVKF, kfvtx3body::DCAxyTrack1ToPVKF, kfvtx3body::DCAxyTrack2ToPVKF, - kfvtx3body::DCAxyTrack0ToSVKF, kfvtx3body::DCAxyTrack1ToSVKF, kfvtx3body::DCAxyTrack2ToSVKF, - kfvtx3body::DCATrack0ToTrack1KF, kfvtx3body::DCATrack0ToTrack2KF, kfvtx3body::DCATrack1ToTrack2KF, - kfvtx3body::DCAVtxDaughtersKF, - kfvtx3body::Track0Sign, kfvtx3body::Track1Sign, kfvtx3body::Track2Sign, // track sing: proton, pion, deuteron - kfvtx3body::TPCNSigmaProton, kfvtx3body::TPCNSigmaPion, kfvtx3body::TPCNSigmaDeuteron, kfvtx3body::TPCNSigmaPionBach, - kfvtx3body::TOFNSigmaDeuteron, - kfvtx3body::ITSClusSizeDeuteron, - kfvtx3body::PIDTrackingDeuteron); - -using KFVtx3BodyDataLite = KFVtx3BodyDatasLite::iterator; + vtx3body::Px, vtx3body::Py, vtx3body::Pz, + vtx3body::Chi2, + vtx3body::TrackedClSize, + vtx3body::PxTrackPr, vtx3body::PyTrackPr, vtx3body::PzTrackPr, + vtx3body::PxTrackPi, vtx3body::PyTrackPi, vtx3body::PzTrackPi, + vtx3body::PxTrackDe, vtx3body::PyTrackDe, vtx3body::PzTrackDe, + vtx3body::DCAXYTrackPrToPV, vtx3body::DCAXYTrackPiToPV, vtx3body::DCAXYTrackDeToPV, + vtx3body::DCAZTrackPrToPV, vtx3body::DCAZTrackPiToPV, vtx3body::DCAZTrackDeToPV, + vtx3body::DCATrackPrToSV, vtx3body::DCATrackPiToSV, vtx3body::DCATrackDeToSV, + vtx3body::DCAVtxToDaughtersAv, + vtx3body::CosPA, vtx3body::Ct, + vtx3body::TPCNSigmaPr, vtx3body::TPCNSigmaPi, vtx3body::TPCNSigmaDe, vtx3body::TPCNSigmaPiBach, + vtx3body::TOFNSigmaDe, + vtx3body::ITSClSizePr, vtx3body::ITSClSizePi, vtx3body::ITSClSizeDe, + vtx3body::TPCNClTrackPr, vtx3body::TPCNClTrackPi, vtx3body::TPCNClTrackDe, + vtx3body::PIDTrackingDe, + + // Dynamic columns + vtx3body::P, + vtx3body::Pt, + vtx3body::VtxRadius, + vtx3body::DistOverTotMom, + vtx3body::DCAVtxToPV, + + // Longitudinal + vtx3body::Rap, + vtx3body::Eta, + vtx3body::Phi, + vtx3body::TrackPrPt, + vtx3body::TrackPrEta, + vtx3body::TrackPrPhi, + vtx3body::TrackPiPt, + vtx3body::TrackPiEta, + vtx3body::TrackPiPhi, + vtx3body::TrackDePt, + vtx3body::TrackDeEta, + vtx3body::TrackDePhi); + +// covariance matrix table +DECLARE_SOA_TABLE(Vtx3BodyCovs, "AOD", "VTX3BODYCOV", //! + vtx3body::CovProton, vtx3body::CovPion, vtx3body::CovDeuteron, + vtx3body::VtxCovMat); // MC candidate table for analysis -DECLARE_SOA_TABLE(McKFVtx3BodyDatas, "AOD", "MCKF3BODYDATAS", +DECLARE_SOA_TABLE(McVtx3BodyDatas, "AOD", "MC3BODYDATA", //! o2::soa::Index<>, - // hypertriton candidate - kfvtx3body::Mass, + vtx3body::Sign, + vtx3body::Mass, vtx3body::MassV0, vtx3body::X, vtx3body::Y, vtx3body::Z, - kfvtx3body::XErr, kfvtx3body::YErr, kfvtx3body::ZErr, - kfvtx3body::Px, kfvtx3body::Py, kfvtx3body::Pz, kfvtx3body::Pt, - kfvtx3body::PxErr, kfvtx3body::PyErr, kfvtx3body::PzErr, kfvtx3body::PtErr, - kfvtx3body::Sign, - kfvtx3body::DCAVtxToPVKF, kfvtx3body::DCAXYVtxToPVKF, - kfvtx3body::VtxCosPAKF, kfvtx3body::VtxCosXYPAKF, - kfvtx3body::VtxCosPAKFtopo, kfvtx3body::VtxCosXYPAKFtopo, - kfvtx3body::DecayLKF, kfvtx3body::DecayLXYKF, kfvtx3body::DecayLDeltaL, - kfvtx3body::Chi2geoNDF, kfvtx3body::Chi2topoNDF, - kfvtx3body::CTauKFtopo, kfvtx3body::TrackedClSize, - - // V0 - kfvtx3body::MassV0, kfvtx3body::Chi2MassV0, - kfvtx3body::CosPAV0, - - // daughters - vtx3body::PxTrack0, vtx3body::PyTrack0, vtx3body::PzTrack0, // proton - vtx3body::PxTrack1, vtx3body::PyTrack1, vtx3body::PzTrack1, // pion - vtx3body::PxTrack2, vtx3body::PyTrack2, vtx3body::PzTrack2, // deuteron - kfvtx3body::TPCInnerParamTrack0, kfvtx3body::TPCInnerParamTrack1, kfvtx3body::TPCInnerParamTrack2, // proton, pion, deuteron - kfvtx3body::TPCNClTrack0, kfvtx3body::TPCNClTrack1, kfvtx3body::TPCNClTrack2, // proton, pion, deuteron - kfvtx3body::TPCChi2NClDeuteron, - kfvtx3body::DeltaPhiDeuteron, kfvtx3body::DeltaPhiProton, - kfvtx3body::DCATrack0ToPVKF, kfvtx3body::DCATrack1ToPVKF, kfvtx3body::DCATrack2ToPVKF, kfvtx3body::DCAxyTrack0ToPVKF, kfvtx3body::DCAxyTrack1ToPVKF, kfvtx3body::DCAxyTrack2ToPVKF, - kfvtx3body::DCAxyTrack0ToSVKF, kfvtx3body::DCAxyTrack1ToSVKF, kfvtx3body::DCAxyTrack2ToSVKF, - kfvtx3body::DCATrack0ToTrack1KF, kfvtx3body::DCATrack0ToTrack2KF, kfvtx3body::DCATrack1ToTrack2KF, - kfvtx3body::DCAVtxDaughtersKF, - kfvtx3body::DCAxyTrackPosToPV, kfvtx3body::DCAxyTrackNegToPV, kfvtx3body::DCAxyTrackBachToPV, - kfvtx3body::DCATrackPosToPV, kfvtx3body::DCATrackNegToPV, kfvtx3body::DCATrackBachToPV, - kfvtx3body::Track0Sign, kfvtx3body::Track1Sign, kfvtx3body::Track2Sign, // track sing: proton, pion, deuteron - kfvtx3body::TPCNSigmaProton, kfvtx3body::TPCNSigmaPion, kfvtx3body::TPCNSigmaDeuteron, kfvtx3body::TPCNSigmaPionBach, - kfvtx3body::TPCdEdxProton, kfvtx3body::TPCdEdxPion, kfvtx3body::TPCdEdxDeuteron, - kfvtx3body::TOFNSigmaDeuteron, - kfvtx3body::ITSClusSizeDeuteron, - kfvtx3body::PIDTrackingDeuteron, - - // MC information - kfvtx3body::GenP, - kfvtx3body::GenPt, - kfvtx3body::GenDecVtxX, kfvtx3body::GenDecVtxY, kfvtx3body::GenDecVtxZ, - kfvtx3body::GenCtau, - kfvtx3body::GenPhi, - kfvtx3body::GenEta, - kfvtx3body::GenRapidity, - kfvtx3body::GenPosP, kfvtx3body::GenPosPt, - kfvtx3body::GenNegP, kfvtx3body::GenNegPt, - kfvtx3body::GenBachP, kfvtx3body::GenBachPt, - kfvtx3body::IsTrueH3L, kfvtx3body::IsTrueAntiH3L, - kfvtx3body::PdgCodeDau0, kfvtx3body::PdgCodeDau1, kfvtx3body::PdgCodeDau2, - kfvtx3body::IsBachPrimary, - kfvtx3body::IsReco, - kfvtx3body::SurvEvSel); - -// Definition of labels for KFVtx3BodyDatas -namespace mckfvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for KF Vtx3BodyDatas -} // namespace mckfvtx3bodylabel - -DECLARE_SOA_TABLE(McKFVtx3BodyLabels, "AOD", "MCKFVTXLABEL", //! Table joinable with KFVtx3BodyData containing the MC labels - mckfvtx3bodylabel::McParticleId); -using McKFVtx3BodyLabel = McKFVtx3BodyLabels::iterator; - -// Definition of labels for KFDecay3Bodys // Full table, joinable with KFDecay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) -namespace mcfullkfvtx3bodylabel -{ -DECLARE_SOA_INDEX_COLUMN(McParticle, mcParticle); //! MC particle for Decay3Bodys -} // namespace mcfullkfvtx3bodylabel + vtx3body::Px, vtx3body::Py, vtx3body::Pz, + vtx3body::Chi2, + vtx3body::TrackedClSize, + vtx3body::PxTrackPr, vtx3body::PyTrackPr, vtx3body::PzTrackPr, + vtx3body::PxTrackPi, vtx3body::PyTrackPi, vtx3body::PzTrackPi, + vtx3body::PxTrackDe, vtx3body::PyTrackDe, vtx3body::PzTrackDe, + vtx3body::DCAXYTrackPrToPV, vtx3body::DCAXYTrackPiToPV, vtx3body::DCAXYTrackDeToPV, + vtx3body::DCAZTrackPrToPV, vtx3body::DCAZTrackPiToPV, vtx3body::DCAZTrackDeToPV, + vtx3body::DCATrackPrToSV, vtx3body::DCATrackPiToSV, vtx3body::DCATrackDeToSV, + vtx3body::DCAVtxToDaughtersAv, + vtx3body::CosPA, vtx3body::Ct, + vtx3body::TPCNSigmaPr, vtx3body::TPCNSigmaPi, vtx3body::TPCNSigmaDe, vtx3body::TPCNSigmaPiBach, + vtx3body::TOFNSigmaDe, + vtx3body::ITSClSizePr, vtx3body::ITSClSizePi, vtx3body::ITSClSizeDe, + vtx3body::TPCNClTrackPr, vtx3body::TPCNClTrackPi, vtx3body::TPCNClTrackDe, + vtx3body::PIDTrackingDe, + + // Monte Carlo information + vtx3body::GenPx, vtx3body::GenPy, vtx3body::GenPz, + vtx3body::GenX, vtx3body::GenY, vtx3body::GenZ, + vtx3body::GenCt, + vtx3body::GenPhi, vtx3body::GenEta, vtx3body::GenRap, + vtx3body::GenPPr, vtx3body::GenPPi, vtx3body::GenPDe, + vtx3body::GenPtPr, vtx3body::GenPtPi, vtx3body::GenPtDe, + vtx3body::IsTrueH3L, vtx3body::IsTrueAntiH3L, + vtx3body::IsReco, + vtx3body::MotherPdgCode, + vtx3body::PrPdgCode, vtx3body::PiPdgCode, vtx3body::DePdgCode, + vtx3body::IsDePrimary, + vtx3body::IsSurvEvSel, + + // Dynamic columns + vtx3body::P, + vtx3body::Pt, + vtx3body::GenP, + vtx3body::GenPt, + vtx3body::VtxRadius, + vtx3body::GenRadius, + vtx3body::DistOverTotMom, + vtx3body::DCAVtxToPV, + + // Longitudinal + vtx3body::Rap, + vtx3body::Eta, + vtx3body::Phi, + vtx3body::TrackPrPt, + vtx3body::TrackPrEta, + vtx3body::TrackPrPhi, + vtx3body::TrackPiPt, + vtx3body::TrackPiEta, + vtx3body::TrackPiPhi, + vtx3body::TrackDePt, + vtx3body::TrackDeEta, + vtx3body::TrackDePhi); + +// Define joins +using Vtx3BodyDatasCovs = soa::Join; +using Vtx3BodyDatasCovsIndexed = soa::Join; -DECLARE_SOA_TABLE(McFullKFVtx3BodyLabels, "AOD", "MCFULLKFLABEL", //! Table joinable with Decay3Bodys (CAUTION: NOT WITH Vtx3BodyDATA) - mcfullkfvtx3bodylabel::McParticleId); -using McFullKFVtx3BodyLabel = McFullKFVtx3BodyLabels::iterator; } // namespace o2::aod #endif // PWGLF_DATAMODEL_VTX3BODYTABLES_H_ diff --git a/PWGLF/DataModel/pidTOFGeneric.h b/PWGLF/DataModel/pidTOFGeneric.h deleted file mode 100644 index a0d287a7643..00000000000 --- a/PWGLF/DataModel/pidTOFGeneric.h +++ /dev/null @@ -1,220 +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. - -#ifndef PWGLF_DATAMODEL_PIDTOFGENERIC_H_ -#define PWGLF_DATAMODEL_PIDTOFGENERIC_H_ -#include "CommonDataFormat/InteractionRecord.h" -#include "Common/Core/PID/PIDTOF.h" - -namespace o2::aod -{ -namespace evtime -{ - -DECLARE_SOA_COLUMN(EvTime, evTime, float); //! Event time. Can be obtained via a combination of detectors e.g. TOF, FT0A, FT0C -DECLARE_SOA_COLUMN(EvTimeErr, evTimeErr, float); //! Error of event time. Can be obtained via a combination of detectors e.g. TOF, FT0A, FT0C -DECLARE_SOA_COLUMN(EvTimeTOF, evTimeTOF, float); //! Event time computed with the TOF detector -DECLARE_SOA_COLUMN(EvTimeTOFErr, evTimeTOFErr, float); //! Error of the event time computed with the TOF detector -DECLARE_SOA_COLUMN(EvTimeFT0, evTimeFT0, float); //! Event time computed with the FT0 detector -DECLARE_SOA_COLUMN(EvTimeFT0Err, evTimeFT0Err, float); //! Error of the event time computed with the FT0 detector -} // namespace evtime - -DECLARE_SOA_TABLE(EvTimeTOFFT0, "AOD", "EvTimeTOFFT0", //! Table of the event time. One entry per collision. - evtime::EvTime, - evtime::EvTimeErr, - evtime::EvTimeTOF, - evtime::EvTimeTOFErr, - evtime::EvTimeFT0, - evtime::EvTimeFT0Err); - -namespace tracktime -{ - -DECLARE_SOA_COLUMN(EvTimeForTrack, evTimeForTrack, float); //! Event time. Removed the bias for the specific track -DECLARE_SOA_COLUMN(EvTimeErrForTrack, evTimeErrForTrack, float); //! Error of event time. Removed the bias for the specific track -} // namespace tracktime - -DECLARE_SOA_TABLE(EvTimeTOFFT0ForTrack, "AOD", "EvTimeForTrack", //! Table of the event time. One entry per track. - tracktime::EvTimeForTrack, - tracktime::EvTimeErrForTrack); - -namespace pidtofgeneric -{ - -static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps - -template -class TofPidNewCollision -{ - public: - TofPidNewCollision() = default; - ~TofPidNewCollision() = default; - - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - o2::track::PID::ID pidType; - - template - using ResponseImplementation = o2::pid::tof::ExpTimes; - static constexpr auto responseEl = ResponseImplementation(); - static constexpr auto responseMu = ResponseImplementation(); - static constexpr auto responsePi = ResponseImplementation(); - static constexpr auto responseKa = ResponseImplementation(); - static constexpr auto responsePr = ResponseImplementation(); - static constexpr auto responseDe = ResponseImplementation(); - static constexpr auto responseTr = ResponseImplementation(); - static constexpr auto responseHe = ResponseImplementation(); - static constexpr auto responseAl = ResponseImplementation(); - - void SetParams(o2::pid::tof::TOFResoParamsV2 const& para) - { - mRespParamsV2.setParameters(para); - } - - void SetPidType(o2::track::PID::ID pidId) - { - pidType = pidId; - } - - template - float GetTOFNSigma(o2::track::PID::ID pidId, TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D = true); - - template - float GetTOFNSigma(TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D = true); - - float GetTOFNSigma(TTrack const& track); - float GetTOFNSigma(o2::track::PID::ID pidId, TTrack const& track); - - float CalculateTOFNSigma(o2::track::PID::ID pidId, TTrack const& track, double tofsignal, double evTime, double evTimeErr) - { - - float expSigma, tofNsigma = -999; - - switch (pidId) { - case 0: - expSigma = responseEl.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responseEl.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 1: - expSigma = responseMu.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responseMu.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 2: - expSigma = responsePi.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responsePi.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 3: - expSigma = responseKa.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responseKa.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 4: - expSigma = responsePr.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responsePr.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 5: - expSigma = responseDe.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 6: - expSigma = responseTr.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responseTr.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 7: - expSigma = responseHe.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responseHe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - case 8: - expSigma = responseAl.GetExpectedSigma(mRespParamsV2, track, tofsignal, evTimeErr); - tofNsigma = (tofsignal - evTime - responseAl.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - break; - default: - LOG(fatal) << "Wrong particle ID in TofPidSecondary class"; - return -999; - } - - return tofNsigma; - } -}; - -template -template -float TofPidNewCollision::GetTOFNSigma(o2::track::PID::ID pidId, TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D) -{ - - if (!track.has_collision() || !track.hasTOF()) { - return -999; - } - - float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; - float expTime = track.length() * sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - - float evTime = correctedcol.evTime(); - float evTimeErr = correctedcol.evTimeErr(); - float tofsignal = track.trackTime() * 1000 + expTime; // in ps - - if (originalcol.globalIndex() == correctedcol.globalIndex()) { - evTime = track.evTimeForTrack(); - evTimeErr = track.evTimeErrForTrack(); - } else { - if (EnableBCAO2D) { - auto originalbc = originalcol.template bc_as(); - auto correctedbc = correctedcol.template bc_as(); - o2::InteractionRecord originalIR = o2::InteractionRecord::long2IR(originalbc.globalBC()); - o2::InteractionRecord correctedIR = o2::InteractionRecord::long2IR(correctedbc.globalBC()); - tofsignal += originalIR.differenceInBCNS(correctedIR) * 1000; - } else { - auto originalbc = originalcol.template foundBC_as(); - auto correctedbc = correctedcol.template foundBC_as(); - o2::InteractionRecord originalIR = o2::InteractionRecord::long2IR(originalbc.globalBC()); - o2::InteractionRecord correctedIR = o2::InteractionRecord::long2IR(correctedbc.globalBC()); - tofsignal += originalIR.differenceInBCNS(correctedIR) * 1000; - } - } - - float tofNsigma = CalculateTOFNSigma(pidId, track, tofsignal, evTime, evTimeErr); - return tofNsigma; -} - -template -template -float TofPidNewCollision::GetTOFNSigma(TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D) -{ - return GetTOFNSigma(pidType, track, originalcol, correctedcol, EnableBCAO2D); -} - -template -float TofPidNewCollision::GetTOFNSigma(o2::track::PID::ID pidId, TTrack const& track) -{ - - if (!track.has_collision() || !track.hasTOF()) { - return -999; - } - - float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; - float expTime = track.length() * sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - - float evTime = track.evTimeForTrack(); - float evTimeErr = track.evTimeErrForTrack(); - float tofsignal = track.trackTime() * 1000 + expTime; // in ps - - float tofNsigma = CalculateTOFNSigma(pidId, track, tofsignal, evTime, evTimeErr); - return tofNsigma; -} - -template -float TofPidNewCollision::GetTOFNSigma(TTrack const& track) -{ - return GetTOFNSigma(pidType, track); -} - -} // namespace pidtofgeneric -} // namespace o2::aod - -#endif // PWGLF_DATAMODEL_PIDTOFGENERIC_H_ diff --git a/PWGLF/TableProducer/Common/epvector.cxx b/PWGLF/TableProducer/Common/epvector.cxx index 8d57d3711fd..6b79401dcd7 100644 --- a/PWGLF/TableProducer/Common/epvector.cxx +++ b/PWGLF/TableProducer/Common/epvector.cxx @@ -19,42 +19,46 @@ /// // C++/ROOT includes. +#include #include +#include + #include +#include #include #include -#include -#include -#include // o2Physics includes. -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" #include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" #include "FT0Base/Geometry.h" #include "FV0Base/Geometry.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + #include "TF1.h" // #include "Common/Core/EventPlaneHelper.h" // #include "Common/DataModel/Qvectors.h" // o2 includes. -#include "CCDB/CcdbApi.h" #include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "DetectorsCommonDataFormats/AlignParam.h" using namespace o2; @@ -93,10 +97,16 @@ struct epvector { Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; Configurable cfgITScluster{"cfgITScluster", 4, "Number of ITS cluster"}; // Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; + Configurable cfgHarmonic{"cfgHarmonic", 2, "Harmonic for event plane calculation"}; Configurable useGainCallib{"useGainCallib", true, "use gain calibration"}; Configurable useRecentere{"useRecentere", true, "use Recentering"}; Configurable useShift{"useShift", false, "use Shift"}; Configurable useShift2{"useShift2", false, "use Shift for others"}; + Configurable useEventSelection{"useEventSelection", true, "Apply event selection centrality wise"}; + Configurable useTimeFrameCut{"useTimeFrameCut", true, "Reject Time Frame border events"}; + Configurable useITSFrameCut{"useITSFrameCut", true, "Reject ITS RO Frame border events"}; + Configurable usePileupCut{"usePileupCut", false, "Reject same bunch pileup"}; + Configurable useITSLayerCut{"useITSLayerCut", false, "Require good ITS layers"}; Configurable ConfGainPath{"ConfGainPath", "Users/s/skundu/My/Object/test100", "Path to gain calibration"}; Configurable ConfRecentere{"ConfRecentere", "Users/s/skundu/My/Object/Finaltest2/recenereall", "Path for recentere"}; Configurable ConfShift{"ConfShift", "Users/s/skundu/My/Object/Finaltest2/recenereall", "Path for Shift"}; @@ -228,26 +238,28 @@ struct epvector { return TMath::ATan2(chPos.Y() + offsetY, chPos.X() + offsetX); } - double GetPhiInRange(double phi) + double GetPhiInRange(double phi, double harmonic = 2) { double result = phi; + double period = 2. * TMath::Pi() / harmonic; while (result < 0) { - result = result + 2. * TMath::Pi() / 2; + result = result + period; } - while (result > 2. * TMath::Pi() / 2) { - result = result - 2. * TMath::Pi() / 2; + while (result > period) { + result = result - period; } return result; } - double GetDeltaPsiSubInRange(double psi1, double psi2) + double GetDeltaPsiSubInRange(double psi1, double psi2, double harmonic = 2) { double delta = psi1 - psi2; - if (TMath::Abs(delta) > TMath::Pi() / 2) { + double period = TMath::Pi() / harmonic; + if (TMath::Abs(delta) > period) { if (delta > 0.) - delta -= 2. * TMath::Pi() / 2; + delta -= 2. * period; else - delta += 2. * TMath::Pi() / 2; + delta += 2. * period; } return delta; } @@ -297,7 +309,7 @@ struct epvector { auto qyTPCL = 0.0; auto qxTPCR = 0.0; auto qyTPCR = 0.0; - if (coll.sel8() && centrality < cfgCutCentrality && TMath::Abs(vz) < cfgCutVertex && coll.has_foundFT0() && eventSelected(coll, centrality) && coll.selection_bit(aod::evsel::kNoTimeFrameBorder) && coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + if (coll.sel8() && centrality < cfgCutCentrality && TMath::Abs(vz) < cfgCutVertex && coll.has_foundFT0() && (!useEventSelection || eventSelected(coll, centrality)) && (!useTimeFrameCut || coll.selection_bit(aod::evsel::kNoTimeFrameBorder)) && (!useITSFrameCut || coll.selection_bit(aod::evsel::kNoITSROFrameBorder)) && (!usePileupCut || coll.selection_bit(aod::evsel::kNoSameBunchPileup)) && (!useITSLayerCut || coll.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll))) { triggerevent = true; if (useGainCallib && (currentRunNumber != lastRunNumber)) { gainprofile = ccdb->getForTimeStamp(ConfGainPath.value, bc.timestamp()); @@ -320,12 +332,11 @@ struct epvector { float ampl = gainequal * ft0.amplitudeA()[iChA]; histos.fill(HIST("FT0Amp"), chanelid, ampl); auto phiA = GetPhiFT0(chanelid, offsetFT0Ax, offsetFT0Ay); - qxFT0A = qxFT0A + ampl * TMath::Cos(2.0 * phiA); - qyFT0A = qyFT0A + ampl * TMath::Sin(2.0 * phiA); + qxFT0A = qxFT0A + ampl * TMath::Cos(cfgHarmonic.value * phiA); + qyFT0A = qyFT0A + ampl * TMath::Sin(cfgHarmonic.value * phiA); } for (std::size_t iChC = 0; iChC < ft0.channelC().size(); iChC++) { auto chanelid = ft0.channelC()[iChC] + 96; - // printf("Offset for FT0A: x = %d y = %d\n", chanelid, chanelid-96); auto gainequal = 1.0; if (useGainCallib) { gainequal = 1 / gainprofile->GetBinContent(gainprofile->FindBin(chanelid)); @@ -333,23 +344,23 @@ struct epvector { float ampl = gainequal * ft0.amplitudeC()[iChC]; histos.fill(HIST("FT0Amp"), chanelid, ampl); auto phiC = GetPhiFT0(chanelid, offsetFT0Cx, offsetFT0Cy); - qxFT0C = qxFT0C + ampl * TMath::Cos(2.0 * phiC); - qyFT0C = qyFT0C + ampl * TMath::Sin(2.0 * phiC); + qxFT0C = qxFT0C + ampl * TMath::Cos(cfgHarmonic.value * phiC); + qyFT0C = qyFT0C + ampl * TMath::Sin(cfgHarmonic.value * phiC); } for (auto& trk : tracks) { if (!selectionTrack(trk) || TMath::Abs(trk.eta()) > 0.8 || trk.pt() > cfgCutPTMax || TMath::Abs(trk.eta()) < cfgMinEta) { continue; } - qxTPC = qxTPC + trk.pt() * TMath::Cos(2.0 * trk.phi()); - qyTPC = qyTPC + trk.pt() * TMath::Sin(2.0 * trk.phi()); + qxTPC = qxTPC + trk.pt() * TMath::Cos(cfgHarmonic.value * trk.phi()); + qyTPC = qyTPC + trk.pt() * TMath::Sin(cfgHarmonic.value * trk.phi()); if (trk.eta() < 0.0) { - qxTPCL = qxTPCL + trk.pt() * TMath::Cos(2.0 * trk.phi()); - qyTPCL = qyTPCL + trk.pt() * TMath::Sin(2.0 * trk.phi()); + qxTPCL = qxTPCL + trk.pt() * TMath::Cos(cfgHarmonic.value * trk.phi()); + qyTPCL = qyTPCL + trk.pt() * TMath::Sin(cfgHarmonic.value * trk.phi()); } if (trk.eta() > 0.0) { - qxTPCR = qxTPCR + trk.pt() * TMath::Cos(2.0 * trk.phi()); - qyTPCR = qyTPCR + trk.pt() * TMath::Sin(2.0 * trk.phi()); + qxTPCR = qxTPCR + trk.pt() * TMath::Cos(cfgHarmonic.value * trk.phi()); + qyTPCR = qyTPCR + trk.pt() * TMath::Sin(cfgHarmonic.value * trk.phi()); } } if (useRecentere && (currentRunNumber != lastRunNumber)) { @@ -367,11 +378,11 @@ struct epvector { qxTPCR = (qxTPCR - hrecentere->GetBinContent(hrecentere->FindBin(centrality, 8.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, 8.5)); qyTPCR = (qyTPCR - hrecentere->GetBinContent(hrecentere->FindBin(centrality, 9.5))) / hrecentere->GetBinError(hrecentere->FindBin(centrality, 9.5)); } - psiFT0C = 0.5 * TMath::ATan2(qyFT0C, qxFT0C); - psiFT0A = 0.5 * TMath::ATan2(qyFT0A, qxFT0A); - psiTPC = 0.5 * TMath::ATan2(qyTPC, qxTPC); - psiTPCL = 0.5 * TMath::ATan2(qyTPCL, qxTPCL); - psiTPCR = 0.5 * TMath::ATan2(qyTPCR, qxTPCR); + psiFT0C = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyFT0C, qxFT0C); + psiFT0A = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyFT0A, qxFT0A); + psiTPC = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyTPC, qxTPC); + psiTPCL = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyTPCL, qxTPCL); + psiTPCR = (1.0 / cfgHarmonic.value) * TMath::ATan2(qyTPCR, qxTPCR); if (useShift && (currentRunNumber != lastRunNumber)) { shiftprofile = ccdb->getForTimeStamp(ConfShift.value, bc.timestamp()); @@ -391,7 +402,7 @@ struct epvector { for (int ishift = 1; ishift <= 10; ishift++) { auto coeffshiftxFT0C = shiftprofile->GetBinContent(shiftprofile->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyFT0C = shiftprofile->GetBinContent(shiftprofile->FindBin(centrality, 1.5, ishift - 0.5)); - deltapsiFT0C = deltapsiFT0C + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0C * TMath::Cos(ishift * 2.0 * psiFT0C) + coeffshiftyFT0C * TMath::Sin(ishift * 2.0 * psiFT0C))); + deltapsiFT0C = deltapsiFT0C + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0C * TMath::Cos(ishift * cfgHarmonic.value * psiFT0C) + coeffshiftyFT0C * TMath::Sin(ishift * cfgHarmonic.value * psiFT0C))); if (useShift2) { auto coeffshiftxFT0A = shiftprofile2->GetBinContent(shiftprofile2->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyFT0A = shiftprofile2->GetBinContent(shiftprofile2->FindBin(centrality, 1.5, ishift - 0.5)); @@ -404,10 +415,10 @@ struct epvector { auto coeffshiftxTPCR = shiftprofile5->GetBinContent(shiftprofile5->FindBin(centrality, 0.5, ishift - 0.5)); auto coeffshiftyTPCR = shiftprofile5->GetBinContent(shiftprofile5->FindBin(centrality, 1.5, ishift - 0.5)); - deltapsiFT0A = deltapsiFT0A + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0A * TMath::Cos(ishift * 2.0 * psiFT0A) + coeffshiftyFT0A * TMath::Sin(ishift * 2.0 * psiFT0A))); - deltapsiTPC = deltapsiTPC + ((1 / (1.0 * ishift)) * (-coeffshiftxTPC * TMath::Cos(ishift * 2.0 * psiTPC) + coeffshiftyTPC * TMath::Sin(ishift * 2.0 * psiTPC))); - deltapsiTPCL = deltapsiTPCL + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCL * TMath::Cos(ishift * 2.0 * psiTPCL) + coeffshiftyTPCL * TMath::Sin(ishift * 2.0 * psiTPCL))); - deltapsiTPCR = deltapsiTPCR + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCR * TMath::Cos(ishift * 2.0 * psiTPCR) + coeffshiftyTPCR * TMath::Sin(ishift * 2.0 * psiTPCR))); + deltapsiFT0A = deltapsiFT0A + ((1 / (1.0 * ishift)) * (-coeffshiftxFT0A * TMath::Cos(ishift * cfgHarmonic.value * psiFT0A) + coeffshiftyFT0A * TMath::Sin(ishift * cfgHarmonic.value * psiFT0A))); + deltapsiTPC = deltapsiTPC + ((1 / (1.0 * ishift)) * (-coeffshiftxTPC * TMath::Cos(ishift * cfgHarmonic.value * psiTPC) + coeffshiftyTPC * TMath::Sin(ishift * cfgHarmonic.value * psiTPC))); + deltapsiTPCL = deltapsiTPCL + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCL * TMath::Cos(ishift * cfgHarmonic.value * psiTPCL) + coeffshiftyTPCL * TMath::Sin(ishift * cfgHarmonic.value * psiTPCL))); + deltapsiTPCR = deltapsiTPCR + ((1 / (1.0 * ishift)) * (-coeffshiftxTPCR * TMath::Cos(ishift * cfgHarmonic.value * psiTPCR) + coeffshiftyTPCR * TMath::Sin(ishift * cfgHarmonic.value * psiTPCR))); } } psiFT0C = psiFT0C + deltapsiFT0C; @@ -432,12 +443,12 @@ struct epvector { histos.fill(HIST("QyTPCR"), centrality, qyTPCR); histos.fill(HIST("PsiTPCR"), centrality, psiTPCR); - histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(2.0 * (psiFT0C - psiFT0A)), occupancy); - histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPC)), occupancy); - histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(2.0 * (psiFT0A - psiTPC)), occupancy); - histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCL)), occupancy); - histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(2.0 * (psiFT0C - psiTPCR)), occupancy); - histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(2.0 * (psiTPCR - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CFT0A"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiFT0A)), occupancy); + histos.fill(HIST("ResFT0CTPC"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPC)), occupancy); + histos.fill(HIST("ResFT0ATPC"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0A - psiTPC)), occupancy); + histos.fill(HIST("ResFT0CTPCL"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CTPCR"), centrality, TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCR)), occupancy); + histos.fill(HIST("ResTPCRTPCL"), centrality, TMath::Cos(cfgHarmonic.value * (psiTPCR - psiTPCL)), occupancy); double qFT0Cmag = TMath::Sqrt(qxFT0C * qxFT0C + qyFT0C * qyFT0C); double qFT0Amag = TMath::Sqrt(qxFT0A * qxFT0A + qyFT0A * qyFT0A); @@ -451,28 +462,28 @@ struct epvector { histos.fill(HIST("QFT0C"), centrality, qFT0Cmag, occupancy); histos.fill(HIST("QFT0A"), centrality, qFT0Amag, occupancy); - histos.fill(HIST("ResFT0CFT0ASP"), centrality, qFT0Cmag * qFT0Amag * TMath::Cos(2.0 * (psiFT0C - psiFT0A)), occupancy); - histos.fill(HIST("ResFT0CTPCSP"), centrality, qFT0Cmag * qTPCmag * TMath::Cos(2.0 * (psiFT0C - psiTPC)), occupancy); - histos.fill(HIST("ResFT0ATPCSP"), centrality, qFT0Amag * qTPCmag * TMath::Cos(2.0 * (psiFT0A - psiTPC)), occupancy); - histos.fill(HIST("ResFT0CTPCLSP"), centrality, qFT0Cmag * qTPCLmag * TMath::Cos(2.0 * (psiFT0C - psiTPCL)), occupancy); - histos.fill(HIST("ResFT0CTPCRSP"), centrality, qFT0Cmag * qTPCRmag * TMath::Cos(2.0 * (psiFT0C - psiTPCR)), occupancy); - histos.fill(HIST("ResTPCRTPCLSP"), centrality, qTPCRmag * qTPCLmag * TMath::Cos(2.0 * (psiTPCR - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CFT0ASP"), centrality, qFT0Cmag * qFT0Amag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiFT0A)), occupancy); + histos.fill(HIST("ResFT0CTPCSP"), centrality, qFT0Cmag * qTPCmag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPC)), occupancy); + histos.fill(HIST("ResFT0ATPCSP"), centrality, qFT0Amag * qTPCmag * TMath::Cos(cfgHarmonic.value * (psiFT0A - psiTPC)), occupancy); + histos.fill(HIST("ResFT0CTPCLSP"), centrality, qFT0Cmag * qTPCLmag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCL)), occupancy); + histos.fill(HIST("ResFT0CTPCRSP"), centrality, qFT0Cmag * qTPCRmag * TMath::Cos(cfgHarmonic.value * (psiFT0C - psiTPCR)), occupancy); + histos.fill(HIST("ResTPCRTPCLSP"), centrality, qTPCRmag * qTPCLmag * TMath::Cos(cfgHarmonic.value * (psiTPCR - psiTPCL)), occupancy); for (int ishift = 1; ishift <= 10; ishift++) { - histos.fill(HIST("ShiftFT0C"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiFT0C)); - histos.fill(HIST("ShiftFT0C"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiFT0C)); + histos.fill(HIST("ShiftFT0C"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiFT0C)); + histos.fill(HIST("ShiftFT0C"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiFT0C)); - histos.fill(HIST("ShiftFT0A"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiFT0A)); - histos.fill(HIST("ShiftFT0A"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiFT0A)); + histos.fill(HIST("ShiftFT0A"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiFT0A)); + histos.fill(HIST("ShiftFT0A"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiFT0A)); - histos.fill(HIST("ShiftTPC"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiTPC)); - histos.fill(HIST("ShiftTPC"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiTPC)); + histos.fill(HIST("ShiftTPC"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiTPC)); + histos.fill(HIST("ShiftTPC"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiTPC)); - histos.fill(HIST("ShiftTPCL"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiTPCL)); - histos.fill(HIST("ShiftTPCL"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiTPCL)); + histos.fill(HIST("ShiftTPCL"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiTPCL)); + histos.fill(HIST("ShiftTPCL"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiTPCL)); - histos.fill(HIST("ShiftTPCR"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * 2.0 * psiTPCR)); - histos.fill(HIST("ShiftTPCR"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * 2.0 * psiTPCR)); + histos.fill(HIST("ShiftTPCR"), centrality, 0.5, ishift - 0.5, TMath::Sin(ishift * cfgHarmonic.value * psiTPCR)); + histos.fill(HIST("ShiftTPCR"), centrality, 1.5, ishift - 0.5, TMath::Cos(ishift * cfgHarmonic.value * psiTPCR)); } lastRunNumber = currentRunNumber; } diff --git a/PWGLF/TableProducer/Common/kinkBuilder.cxx b/PWGLF/TableProducer/Common/kinkBuilder.cxx index d2b25be26a0..eb68fe85b39 100644 --- a/PWGLF/TableProducer/Common/kinkBuilder.cxx +++ b/PWGLF/TableProducer/Common/kinkBuilder.cxx @@ -13,30 +13,31 @@ /// \brief Builder task for kink decay topologies using ITS standalone tracks for the mother /// \author Francesco Mazzaschi -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/Utils/svPoolCreator.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.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 "PWGLF/DataModel/LFParticleIdentification.h" -#include "PWGLF/Utils/svPoolCreator.h" -#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -90,12 +91,16 @@ struct kinkCandidate { struct kinkBuilder { enum PartType { kSigmaMinus = 0, + kHypertriton, kHyperhelium4sigma }; Produces outputDataTable; + Produces outputDataTableUB; + Service ccdb; Configurable hypoMoth{"hypoMoth", kSigmaMinus, "Mother particle hypothesis"}; + Configurable fillDebugTable{"fillDebugTable", false, "If true, fill the debug table with all candidates unbound"}; // Selection criteria Configurable maxDCAMothToPV{"maxDCAMothToPV", 0.1, "Max DCA of the mother to the PV"}; Configurable minDCADaugToPV{"minDCADaugToPV", 0., "Min DCA of the daughter to the PV"}; @@ -106,6 +111,8 @@ struct kinkBuilder { Configurable etaMax{"etaMax", 1., "eta daughter"}; Configurable nTPCClusMinDaug{"nTPCClusMinDaug", 80, "daug NTPC clusters cut"}; Configurable askTOFforDaug{"askTOFforDaug", false, "If true, ask for TOF signal"}; + Configurable doSVRadiusCut{"doSVRadiusCut", true, "If true, apply the cut on the radius of the secondary vertex and tracksIU"}; + Configurable updateMothTrackUsePV{"updateMothTrackUsePV", false, "If true, update the mother track parameters using the primary vertex"}; o2::vertexing::DCAFitterN<2> fitter; o2::base::MatLayerCylSet* lut = nullptr; @@ -155,6 +162,11 @@ struct kinkBuilder { mothMass = o2::constants::physics::MassSigmaMinus; chargedDauMass = o2::constants::physics::MassPiMinus; neutDauMass = o2::constants::physics::MassNeutron; + } else if (hypoMoth == kHypertriton) { + charge = 1; + mothMass = o2::constants::physics::MassHyperTriton; + chargedDauMass = o2::constants::physics::MassTriton; + neutDauMass = o2::constants::physics::MassPi0; } else if (hypoMoth == kHyperhelium4sigma) { charge = 2; mothMass = o2::constants::physics::MassHyperHelium4; @@ -193,6 +205,8 @@ struct kinkBuilder { AxisSpec massAxis(100, 1.1, 1.4, "m (GeV/#it{c}^{2})"); if (hypoMoth == kSigmaMinus) { massAxis = AxisSpec{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; + } else if (hypoMoth == kHypertriton) { + massAxis = AxisSpec{100, 2.94, 3.2, "m (GeV/#it{c}^{2})"}; } else if (hypoMoth == kHyperhelium4sigma) { massAxis = AxisSpec{100, 3.85, 4.25, "m (GeV/#it{c}^{2})"}; } @@ -308,6 +322,14 @@ struct kinkBuilder { continue; } + if (updateMothTrackUsePV) { + // update the mother track parameters using the primary vertex + trackParCovMoth = trackParCovMothPV; + if (!trackParCovMoth.update(primaryVertex)) { + continue; + } + } + int nCand = 0; try { nCand = fitter.process(trackParCovMoth, trackParCovDaug); @@ -329,7 +351,7 @@ struct kinkBuilder { // cut on decay radius to 17 cm float decRad2 = kinkCand.decVtx[0] * kinkCand.decVtx[0] + kinkCand.decVtx[1] * kinkCand.decVtx[1]; - if (decRad2 < LayerRadii[3] * LayerRadii[3]) { + if (doSVRadiusCut && decRad2 < LayerRadii[3] * LayerRadii[3]) { continue; } @@ -348,11 +370,11 @@ struct kinkBuilder { } } - if (lastLayerMoth >= firstLayerDaug) { + if (doSVRadiusCut && lastLayerMoth >= firstLayerDaug) { continue; } - if (decRad2 < LayerRadii[lastLayerMoth] * LayerRadii[lastLayerMoth]) { + if (doSVRadiusCut && decRad2 < LayerRadii[lastLayerMoth] * LayerRadii[lastLayerMoth]) { continue; } @@ -429,11 +451,18 @@ struct kinkBuilder { std::sort(kinkCandidates.begin(), kinkCandidates.end(), [](const kinkCandidate& a, const kinkCandidate& b) { return a.collisionID < b.collisionID; }); for (const auto& kinkCand : kinkCandidates) { - outputDataTable(kinkCand.collisionID, kinkCand.mothTrackID, kinkCand.daugTrackID, - kinkCand.decVtx[0], kinkCand.decVtx[1], kinkCand.decVtx[2], - kinkCand.mothSign, kinkCand.momMoth[0], kinkCand.momMoth[1], kinkCand.momMoth[2], - kinkCand.momDaug[0], kinkCand.momDaug[1], kinkCand.momDaug[2], - kinkCand.dcaXYmoth, kinkCand.dcaXYdaug, kinkCand.dcaKinkTopo); + if (fillDebugTable) { + outputDataTableUB(kinkCand.decVtx[0], kinkCand.decVtx[1], kinkCand.decVtx[2], + kinkCand.mothSign, kinkCand.momMoth[0], kinkCand.momMoth[1], kinkCand.momMoth[2], + kinkCand.momDaug[0], kinkCand.momDaug[1], kinkCand.momDaug[2], + kinkCand.dcaXYmoth, kinkCand.dcaXYdaug, kinkCand.dcaKinkTopo); + } else { + outputDataTable(kinkCand.collisionID, kinkCand.mothTrackID, kinkCand.daugTrackID, + kinkCand.decVtx[0], kinkCand.decVtx[1], kinkCand.decVtx[2], + kinkCand.mothSign, kinkCand.momMoth[0], kinkCand.momMoth[1], kinkCand.momMoth[2], + kinkCand.momDaug[0], kinkCand.momDaug[1], kinkCand.momDaug[2], + kinkCand.dcaXYmoth, kinkCand.dcaXYdaug, kinkCand.dcaKinkTopo); + } } } }; diff --git a/PWGLF/TableProducer/Common/spvector.cxx b/PWGLF/TableProducer/Common/spvector.cxx index 99a54d63c64..e5940962e1f 100644 --- a/PWGLF/TableProducer/Common/spvector.cxx +++ b/PWGLF/TableProducer/Common/spvector.cxx @@ -13,54 +13,57 @@ // \email: prottay.das@cern.ch // C++/ROOT includes. -#include -#include -#include -#include +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" #include +#include #include + #include +#include #include #include -#include "Math/Vector4D.h" -#include "TRandom3.h" -#include "TF1.h" +#include +#include // o2Physics includes. -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/runDataProcessing.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "CommonConstants/PhysicsConstants.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" + +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/PID/PIDTOF.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/FT0Corrected.h" -#include "FT0Base/Geometry.h" -#include "FV0Base/Geometry.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Common/Core/EventPlaneHelper.h" #include "Common/DataModel/Qvectors.h" -#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/TableProducer/PID/pidTOFBase.h" + +#include "CommonConstants/PhysicsConstants.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.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/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/SPCalibrationTables.h" // #include "SPCalibrationTableswrite.h" // o2 includes. -#include "CCDB/CcdbApi.h" #include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "DetectorsCommonDataFormats/AlignParam.h" using namespace o2; @@ -227,6 +230,7 @@ struct spvector { AxisSpec basisAxis = {2, 0, 2, "basis"}; AxisSpec VxyAxis = {2, 0, 2, "Vxy"}; + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); histos.add("hCentrality", "hCentrality", kTH1F, {{centfineAxis}}); histos.add("Vz", "Vz", kTH1F, {vzfineAxis}); histos.add("hpQxZDCAC", "hpQxZDCAC", kTProfile, {centfineAxis}); @@ -410,6 +414,7 @@ struct spvector { void process(MyCollisions::iterator const& collision, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0s*/, BCsRun3 const& bcs, aod::Zdcs const&) { + histos.fill(HIST("hEvtSelInfo"), 0.5); auto centrality = collision.centFT0C(); bool triggerevent = false; @@ -439,6 +444,8 @@ struct spvector { return; } + histos.fill(HIST("hEvtSelInfo"), 1.5); + auto zdc = bc.zdc(); auto zncEnergy = zdc.energySectorZNC(); auto znaEnergy = zdc.energySectorZNA(); @@ -451,35 +458,47 @@ struct spvector { return; } + histos.fill(HIST("hEvtSelInfo"), 2.5); + if (znaEnergy[0] <= 0.0 || znaEnergy[1] <= 0.0 || znaEnergy[2] <= 0.0 || znaEnergy[3] <= 0.0) { triggerevent = false; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); 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; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); return; } + histos.fill(HIST("hEvtSelInfo"), 4.5); + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { triggerevent = false; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); return; } + histos.fill(HIST("hEvtSelInfo"), 5.5); + if (additionalEvSel && (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { triggerevent = false; spcalibrationtable(triggerevent, currentRunNumber, centrality, vx, vy, vz, znaEnergycommon, zncEnergycommon, znaEnergy[0], znaEnergy[1], znaEnergy[2], znaEnergy[3], zncEnergy[0], zncEnergy[1], zncEnergy[2], zncEnergy[3], qxZDCA, qxZDCC, qyZDCA, qyZDCC, psiZDCC, psiZDCA); return; } + histos.fill(HIST("hEvtSelInfo"), 6.5); + if (collision.sel8() && centrality > cfgCutCentralityMin && centrality < cfgCutCentralityMax && TMath::Abs(vz) < cfgCutVertex && collision.has_foundFT0() && collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { triggerevent = true; if (useGainCallib && (currentRunNumber != lastRunNumber)) { gainprofile = ccdb->getForTimeStamp(ConfGainPath.value, bc.timestamp()); } + histos.fill(HIST("hEvtSelInfo"), 7.5); + auto gainequal = 1.0; auto alphaZDC = 0.395; constexpr double x[4] = {-1.75, 1.75, -1.75, 1.75}; @@ -547,6 +566,7 @@ struct spvector { return; } + histos.fill(HIST("hEvtSelInfo"), 8.5); histos.fill(HIST("hCentrality"), centrality); histos.fill(HIST("Vz"), vz); diff --git a/PWGLF/TableProducer/Nuspex/CMakeLists.txt b/PWGLF/TableProducer/Nuspex/CMakeLists.txt index f8f62f22925..98dac784da5 100644 --- a/PWGLF/TableProducer/Nuspex/CMakeLists.txt +++ b/PWGLF/TableProducer/Nuspex/CMakeLists.txt @@ -11,7 +11,7 @@ o2physics_add_dpl_workflow(decay3bodybuilder SOURCES decay3bodybuilder.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter KFParticle::KFParticle O2Physics::AnalysisCore O2::TOFBase O2Physics::EventFilteringUtils O2::DetectorsVertexing + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2::TOFBase O2Physics::EventFilteringUtils O2::DetectorsVertexing COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(hyhefour-builder @@ -29,11 +29,6 @@ o2physics_add_dpl_workflow(lnn-reco-task PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(hypertriton3bodyfinder - SOURCES hypertriton3bodyfinder.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(nucleustreecreator SOURCES LFTreeCreatorNuclei.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -59,11 +54,6 @@ o2physics_add_dpl_workflow(threebodymcfinder PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(threebody-reco-task - SOURCES threebodyRecoTask.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore O2Physics::EventFilteringUtils - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(ebye-maker SOURCES ebyeMaker.cxx PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore @@ -79,11 +69,6 @@ o2physics_add_dpl_workflow(pidtof-generic PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFBase COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(threebody-kf-task - SOURCES threebodyKFTask.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(hypernuclei-kf-reco-task SOURCES hypKfRecoTask.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore KFParticle::KFParticle @@ -109,7 +94,12 @@ o2physics_add_dpl_workflow(nuclei-flow-trees PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsBase O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(hyperhelium4sigma-reco-task - SOURCES hyperhelium4sigmaRecoTask.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore +o2physics_add_dpl_workflow(hyperkink-reco-task + SOURCES hyperkinkRecoTask.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::TOFBase + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(he3-lambda-analysis + SOURCES he3LambdaAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Nuspex/LFTreeCreatorClusterStudies.cxx b/PWGLF/TableProducer/Nuspex/LFTreeCreatorClusterStudies.cxx index d8df6f0bbf6..ffa41989881 100644 --- a/PWGLF/TableProducer/Nuspex/LFTreeCreatorClusterStudies.cxx +++ b/PWGLF/TableProducer/Nuspex/LFTreeCreatorClusterStudies.cxx @@ -14,45 +14,45 @@ // // Author: Giorgio Alberto Lucia -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFClusterStudiesTable.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/Core/PID/PIDTOF.h" -#include "Common/TableProducer/PID/pidTOFBase.h" #include "Common/Core/PID/TPCPIDResponse.h" +#include "Common/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/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" -#include "DCAFitter/DCAFitterN.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/TableProducer/PID/pidTOFBase.h" -#include "PWGLF/DataModel/LFClusterStudiesTable.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 "TDatabasePDG.h" #include "TPDGCode.h" +#include +#include +#include +#include +#include +#include +#include + using namespace ::o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -138,6 +138,22 @@ enum PartID { he }; +struct Candidate { + float p = -999.f; // momentum * charge + float eta = -999.f; + float phi = -999.f; + uint32_t itsClusterSize = 0; + uint8_t partID = PartID::none; + float pTPC = -999.f; + uint32_t pidInTrk = 0; // PID in tracking + float nsigmaTPC = -999.f; + float nsigmaTOF = -999.f; + float tofMass = -999.f; + float cosPAMother = -999.f; // Cosine of the pointing angle of the mother + float massMother = -999.f; // Invariant mass of the mother + int pdgCode = 0; +}; + struct LfTreeCreatorClusterStudies { Service m_ccdb; @@ -180,6 +196,8 @@ struct LfTreeCreatorClusterStudies { Configurable v0setting_nsigmatpcPr{"v0setting_nsigmaTPCPr", 2.f, "Number of sigmas for the TPC PID for protons"}; Configurable lambdasetting_qtAPcut{"lambdasetting_qtAPcut", 0.02f, "Cut on the qt for the Armenteros-Podolanski plot for photon rejection"}; Configurable lambdasetting_pmin{"lambdasetting_pmin", 0.0f, "Minimum momentum for the V0 daughters"}; + Configurable electronsetting_conversion_rmin{"electron_conversion_rmin", 1.76f, "Minimum radius for the photon conversion (cm)"}; + Configurable electronsetting_conversion_rmax{"electron_conversion_rmax", 19.77f, "Maximum radius for the photon conversion (cm)"}; Configurable cascsetting_dcaCascDaughters{"casc_setting_dcaV0daughters", 0.1f, "DCA between the V0 daughters"}; Configurable cascsetting_cosPA{"casc_setting_cosPA", 0.99f, "Cosine of the pointing angle of the V0"}; @@ -223,6 +241,7 @@ struct LfTreeCreatorClusterStudies { {"photon_radiusV0", "Photon conversion radius (xy) V0; radius (cm); counts", {HistType::kTH1F, {{100, 0., 100.}}}}, {"photon_conversion_position", "Photon conversion position; x (cm); y (cm)", {HistType::kTH2F, {{250, -5.f, 5.f}, {250, -5.f, 5.f}}}}, {"photon_conversion_position_layer", "Photon conversion position (ITS layers); x (cm); y (cm)", {HistType::kTH2F, {{100, -5.f, 5.f}, {100, -5.f, 5.f}}}}, + {"casc_dca_daughter_pairs", "DCA (xy) for cascade daughter pairs; DCAxy (cm); counts", {HistType::kTH1F, {{100, -0.1, 0.1}}}}, {"Xi_vs_Omega", "Mass Xi vs Omega; mass Omega (GeV/#it{c}^{2}); mass Xi (GeV/#it{c}^{2})", {HistType::kTH2F, {{50, 1.f, 2.f}, {50, 1.f, 2.f}}}}, {"massOmega", "Mass #Omega; signed #it{p}_{T} (GeV/#it{c}); mass (GeV/#it{c}^{2})", {HistType::kTH2F, {{100, -5.f, 5.f}, {100, 1.62f, 1.72f}}}}, {"massOmegaWithBkg", "Mass Omega with Background; mass Omega (GeV/#it{c}^{2}); counts", {HistType::kTH1F, {{100, 1.62f, 1.72f}}}}, @@ -256,7 +275,6 @@ struct LfTreeCreatorClusterStudies { Produces m_ClusterStudiesTable; Produces m_ClusterStudiesTableExtra; Produces m_ClusterStudiesTableMc; - Produces m_ClusterStudiesTableMcExtra; struct V0TrackParCov { int64_t globalIndex; @@ -403,6 +421,7 @@ struct LfTreeCreatorClusterStudies { bool qualitySelectionCascade(const double dcaCascDaughters, const double cosPA) { + m_hAnalysis.fill(HIST("casc_dca_daughter_pairs"), dcaCascDaughters); if (std::abs(dcaCascDaughters) > cascsetting_dcaCascDaughters) { return false; } @@ -414,6 +433,155 @@ struct LfTreeCreatorClusterStudies { return true; } + uint8_t selectV0MotherHypothesis(float massK0sV0, float massLambdaV0, float massAntiLambdaV0, float alphaAP, const o2::aod::V0& v0) + { + uint8_t v0Bitmask(0); + if (v0.isPhotonV0()) { + SETBIT(v0Bitmask, Photon); + } + if (std::abs(massK0sV0 - o2::constants::physics::MassK0Short) < v0setting_massWindowK0s) { + SETBIT(v0Bitmask, K0s); + } + if ((std::abs(massLambdaV0 - o2::constants::physics::MassLambda0) < v0setting_massWindowLambda) && (alphaAP > 0)) { + SETBIT(v0Bitmask, Lambda); + } + if ((std::abs(massAntiLambdaV0 - o2::constants::physics::MassLambda0) < v0setting_massWindowLambda) && (alphaAP < 0)) { + SETBIT(v0Bitmask, AntiLambda); + } + return v0Bitmask; + } + + template + bool selectPidV0Daughters(Candidate& candidatePos, Candidate& candidateNeg, const T& posTrack, + const T& negTrack, const std::array& momMother, const std::array& decayVtx, + float qtAP, float radiusV0, uint8_t v0Bitmask) + { + if (TESTBIT(v0Bitmask, Lambda)) { + if (qtAP < lambdasetting_qtAPcut) + return false; + if (std::abs(posTrack.tpcNSigmaPr()) > v0setting_nsigmatpcPr || std::abs(negTrack.tpcNSigmaPi()) > v0setting_nsigmatpcPi) + return false; + if (std::hypot(momMother[0], momMother[1], momMother[2]) < lambdasetting_pmin) + return false; + candidatePos.partID = PartID::pr; + candidateNeg.partID = PartID::pi; + candidatePos.nsigmaTPC = posTrack.tpcNSigmaPr(); + candidateNeg.nsigmaTPC = negTrack.tpcNSigmaPi(); + m_hAnalysis.fill(HIST("v0_type"), V0Type::Lambda); + + } else if (TESTBIT(v0Bitmask, AntiLambda)) { + if (qtAP < lambdasetting_qtAPcut) + return false; + if (std::abs(posTrack.tpcNSigmaPi()) > v0setting_nsigmatpcPi || std::abs(negTrack.tpcNSigmaPr()) > v0setting_nsigmatpcPr) + return false; + if (std::hypot(momMother[0], momMother[1], momMother[2]) < lambdasetting_pmin) + return false; + candidatePos.partID = PartID::pi; + candidateNeg.partID = PartID::pr; + candidatePos.nsigmaTPC = posTrack.tpcNSigmaPi(); + candidateNeg.nsigmaTPC = negTrack.tpcNSigmaPr(); + m_hAnalysis.fill(HIST("v0_type"), V0Type::AntiLambda); + + } else if (TESTBIT(v0Bitmask, K0s)) { + m_hAnalysis.fill(HIST("v0_type"), V0Type::K0s); + return false; // K0s not implemented + + } else if (TESTBIT(v0Bitmask, Photon)) { + // require photon conversion to happen in one of the Inner Tracker layers (± 0.5 cm resolution) + m_hAnalysis.fill(HIST("photon_conversion_position"), decayVtx[0], decayVtx[1]); + m_hAnalysis.fill(HIST("photon_radiusV0"), radiusV0); + if (!(radiusV0 > electronsetting_conversion_rmin && radiusV0 < electronsetting_conversion_rmax)) + return false; + if (std::abs(posTrack.tpcNSigmaEl()) > v0setting_nsigmatpcEl || std::abs(negTrack.tpcNSigmaEl()) > v0setting_nsigmatpcEl) + return false; + m_hAnalysis.fill(HIST("photon_conversion_position_layer"), decayVtx[0], decayVtx[1]); + candidatePos.partID = PartID::el; + candidateNeg.partID = PartID::el; + candidatePos.nsigmaTPC = posTrack.tpcNSigmaEl(); + candidateNeg.nsigmaTPC = negTrack.tpcNSigmaEl(); + m_hAnalysis.fill(HIST("v0_type"), V0Type::Photon); + + } else { + return false; + } + + return true; + } + + /** + * Fill the histograms for the V0 candidate and return the mass of the V0 + */ + float fillHistogramsV0(float massLambdaV0, float massAntiLambdaV0, + const std::array& momMother, + const Candidate& candidatePos, const Candidate& candidateNeg, float alphaAP, float qtAP, float radiusV0, uint8_t v0Bitmask) + { + float massV0{0.f}; + m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0DaughterDCAtoPV); + if (TESTBIT(v0Bitmask, Lambda)) { + massV0 = massLambdaV0; + m_hAnalysis.fill(HIST("massLambda"), std::hypot(momMother[0], momMother[1], momMother[2]), massLambdaV0); + m_hAnalysis.fill(HIST("armenteros_plot_lambda"), alphaAP, qtAP); + m_hAnalysis.fill(HIST("nSigmaTPCPr"), candidatePos.p, candidatePos.nsigmaTPC); + m_hAnalysis.fill(HIST("nSigmaITSPr"), candidatePos.p, m_responseITS.nSigmaITS(candidatePos.itsClusterSize, candidatePos.p, candidatePos.eta)); + m_hAnalysis.fill(HIST("nSigmaTPCPi"), candidateNeg.p, candidateNeg.nsigmaTPC); + m_hAnalysis.fill(HIST("nSigmaITSPi"), candidateNeg.p, m_responseITS.nSigmaITS(candidateNeg.itsClusterSize, candidateNeg.p, candidateNeg.eta)); + m_hAnalysis.fill(HIST("pmatchingPr"), candidatePos.pTPC, (candidatePos.pTPC - candidatePos.p) / candidatePos.pTPC); + m_hAnalysis.fill(HIST("pmatchingPi"), -candidateNeg.pTPC, (candidateNeg.pTPC - candidateNeg.p) / candidateNeg.pTPC); + + } else if (TESTBIT(v0Bitmask, AntiLambda)) { + massV0 = massAntiLambdaV0; + m_hAnalysis.fill(HIST("massLambda"), std::hypot(momMother[0], momMother[1], momMother[2]) * -1.f, massAntiLambdaV0); + // "signed" pt for antimatter + m_hAnalysis.fill(HIST("armenteros_plot_lambda"), alphaAP, qtAP); + m_hAnalysis.fill(HIST("nSigmaTPCPi"), candidatePos.p, candidatePos.nsigmaTPC); + m_hAnalysis.fill(HIST("nSigmaITSPi"), candidatePos.p, m_responseITS.nSigmaITS(candidatePos.itsClusterSize, candidatePos.p, candidatePos.eta)); + m_hAnalysis.fill(HIST("nSigmaTPCPr"), candidateNeg.p, candidateNeg.nsigmaTPC); + m_hAnalysis.fill(HIST("nSigmaITSPr"), candidateNeg.p, m_responseITS.nSigmaITS(candidateNeg.itsClusterSize, candidateNeg.p, candidateNeg.eta)); + m_hAnalysis.fill(HIST("pmatchingPi"), candidatePos.pTPC, (candidatePos.pTPC - candidatePos.p) / candidatePos.pTPC); + m_hAnalysis.fill(HIST("pmatchingPr"), -candidateNeg.pTPC, (candidateNeg.pTPC - candidateNeg.p) / candidateNeg.pTPC); + + } else if (TESTBIT(v0Bitmask, Photon)) { + massV0 = 0.f; + m_hAnalysis.fill(HIST("nSigmaTPCEl"), candidatePos.p, candidatePos.nsigmaTPC); + m_hAnalysis.fill(HIST("nSigmaTPCEl"), candidateNeg.p, candidateNeg.nsigmaTPC); + m_hAnalysis.fill(HIST("nSigmaITSEl"), candidatePos.p, m_responseITS.nSigmaITS(candidatePos.itsClusterSize, candidatePos.p, candidatePos.eta)); + m_hAnalysis.fill(HIST("nSigmaITSEl"), candidateNeg.p, m_responseITS.nSigmaITS(candidateNeg.itsClusterSize, candidateNeg.p, candidateNeg.eta)); + m_hAnalysis.fill(HIST("armenteros_plot_gamma"), alphaAP, qtAP); + m_hAnalysis.fill(HIST("pmatchingEl"), candidatePos.pTPC, (candidatePos.pTPC - candidatePos.p) / candidatePos.pTPC); + m_hAnalysis.fill(HIST("pmatchingEl"), -candidateNeg.pTPC, (candidateNeg.pTPC - candidateNeg.p) / candidateNeg.pTPC); + } + m_hAnalysis.fill(HIST("radiusV0"), radiusV0); + m_hAnalysis.fill(HIST("armenteros_plot"), alphaAP, qtAP); + + return massV0; + } + + template + void fillTable(const Candidate& candidate) + { + m_ClusterStudiesTable( + candidate.p, // p + candidate.eta, // eta + candidate.phi, // phi + candidate.itsClusterSize, // itsClsize + static_cast(candidate.partID)); // partID + if (!setting_smallTable) { + m_ClusterStudiesTableExtra( + candidate.pTPC, // pTPC + candidate.pidInTrk, // pidInTrk + candidate.nsigmaTPC, // TpcNSigma + candidate.nsigmaTOF, // TofNSigma + candidate.tofMass, // TofMass + candidate.cosPAMother, // cosPA + candidate.massMother); // massMother + } + + if constexpr (isMC) { + m_ClusterStudiesTableMc( + candidate.pdgCode); // pdgCod + } + } + // ========================================================================================================= template @@ -450,7 +618,7 @@ struct LfTreeCreatorClusterStudies { { float beta = o2::pid::tof::Beta::GetBeta(candidate); beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); /// sometimes beta > 1 or < 0, to be checked - return candidate.tpcInnerParam() * 2.f * std::sqrt(1.f / (beta * beta) - 1.f); + return candidate.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f); } // ========================================================================================================= @@ -622,61 +790,22 @@ struct LfTreeCreatorClusterStudies { m_hAnalysis.fill(HIST("Lambda_vs_K0s"), massK0sV0, massLambdaV0); // float massPhotonV0 = computeMassMother(o2::constants::physics::MassElectron, o2::constants::physics::MassElectron, momPos, momNeg, momMother); - uint8_t v0Bitmask(0); - if (v0.isPhotonV0()) { - SETBIT(v0Bitmask, Photon); - } - if (std::abs(massK0sV0 - o2::constants::physics::MassK0Short) < v0setting_massWindowK0s) { - SETBIT(v0Bitmask, K0s); - } - if ((std::abs(massLambdaV0 - o2::constants::physics::MassLambda0) < v0setting_massWindowLambda) && (alphaAP > 0)) { - SETBIT(v0Bitmask, Lambda); - } - if ((std::abs(massAntiLambdaV0 - o2::constants::physics::MassLambda0) < v0setting_massWindowLambda) && (alphaAP < 0)) { - SETBIT(v0Bitmask, AntiLambda); - } + uint8_t v0Bitmask = selectV0MotherHypothesis(massK0sV0, massLambdaV0, massAntiLambdaV0, alphaAP, v0); if (v0Bitmask == 0 || (v0Bitmask & (v0Bitmask - 1)) != 0) { return; } m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0PID); - uint8_t partID_pos{0}, partID_neg{0}; - if (TESTBIT(v0Bitmask, Lambda)) { - if (qtAP < lambdasetting_qtAPcut) - return; - if (std::abs(posTrack.tpcNSigmaPr()) > v0setting_nsigmatpcPr || std::abs(negTrack.tpcNSigmaPi()) > v0setting_nsigmatpcPi) - return; - if (std::hypot(momMother[0], momMother[1], momMother[2]) < lambdasetting_pmin) - return; - partID_pos = PartID::pr; - partID_neg = PartID::pi; - m_hAnalysis.fill(HIST("v0_type"), V0Type::Lambda); - } else if (TESTBIT(v0Bitmask, AntiLambda)) { - if (qtAP < lambdasetting_qtAPcut) - return; - if (std::abs(posTrack.tpcNSigmaPi()) > v0setting_nsigmatpcPr || std::abs(negTrack.tpcNSigmaPr()) > v0setting_nsigmatpcPi) - return; - if (std::hypot(momMother[0], momMother[1], momMother[2]) < lambdasetting_pmin) - return; - partID_pos = PartID::pi; - partID_neg = PartID::pr; - m_hAnalysis.fill(HIST("v0_type"), V0Type::AntiLambda); - } else if (TESTBIT(v0Bitmask, K0s)) { - m_hAnalysis.fill(HIST("v0_type"), V0Type::K0s); - return; // K0s not implemented - } else if (TESTBIT(v0Bitmask, Photon)) { - // require photon conversion to happen in one of the Inner Tracker layers (± 0.5 cm resolution) - m_hAnalysis.fill(HIST("photon_conversion_position"), decayVtx[0], decayVtx[1]); - m_hAnalysis.fill(HIST("photon_radiusV0"), radiusV0); - if (!(radiusV0 > 1.76 && radiusV0 < 4.71)) - return; - if (std::abs(posTrack.tpcNSigmaEl()) > v0setting_nsigmatpcEl || std::abs(negTrack.tpcNSigmaEl()) > v0setting_nsigmatpcEl) - return; - m_hAnalysis.fill(HIST("photon_conversion_position_layer"), decayVtx[0], decayVtx[1]); - partID_pos = PartID::el; - partID_neg = PartID::el; - m_hAnalysis.fill(HIST("v0_type"), V0Type::Photon); - } else { + Candidate candidatePos(std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), + RecoDecay::eta(momPos), RecoDecay::phi(momPos), posTrack.itsClusterSizes(), + 0, posTrack.tpcInnerParam() * posTrack.sign(), posTrack.pidForTracking(), + -999.f, -999.f, -999.f, cosPA, -999.f, 0); + Candidate candidateNeg(std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), + RecoDecay::eta(momNeg), RecoDecay::phi(momNeg), negTrack.itsClusterSizes(), + 0, negTrack.tpcInnerParam() * negTrack.sign(), negTrack.pidForTracking(), + -999.f, -999.f, -999.f, cosPA, -999.f, 0); + + if (!selectPidV0Daughters(candidatePos, candidateNeg, posTrack, negTrack, momMother, decayVtx, qtAP, radiusV0, v0Bitmask)) { return; } @@ -689,44 +818,10 @@ struct LfTreeCreatorClusterStudies { return; } - float massV0{0.f}; - m_hAnalysis.fill(HIST("v0_selections"), V0Selections::kV0DaughterDCAtoPV); - if (TESTBIT(v0Bitmask, Lambda)) { - massV0 = massLambdaV0; - m_hAnalysis.fill(HIST("massLambda"), std::hypot(momMother[0], momMother[1], momMother[2]), massLambdaV0); - m_hAnalysis.fill(HIST("armenteros_plot_lambda"), alphaAP, qtAP); - m_hAnalysis.fill(HIST("nSigmaTPCPr"), std::hypot(momPos[0], momPos[1], momPos[2]), posTrack.tpcNSigmaPr()); - m_hAnalysis.fill(HIST("nSigmaITSPr"), std::hypot(momPos[0], momPos[1], momPos[2]), m_responseITS.nSigmaITS(posTrack.itsClusterSizes(), posTrack.p(), posTrack.eta())); - m_hAnalysis.fill(HIST("nSigmaTPCPi"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, negTrack.tpcNSigmaPi()); - m_hAnalysis.fill(HIST("nSigmaITSPi"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, m_responseITS.nSigmaITS(negTrack.itsClusterSizes(), negTrack.p(), negTrack.eta())); - m_hAnalysis.fill(HIST("pmatchingPr"), posTrack.tpcInnerParam(), (posTrack.tpcInnerParam() - posTrack.p()) / posTrack.tpcInnerParam()); - m_hAnalysis.fill(HIST("pmatchingPi"), -negTrack.tpcInnerParam(), (negTrack.tpcInnerParam() - negTrack.p()) / negTrack.tpcInnerParam()); - - } else if (TESTBIT(v0Bitmask, AntiLambda)) { - massV0 = massAntiLambdaV0; - m_hAnalysis.fill(HIST("massLambda"), std::hypot(momMother[0], momMother[1], momMother[2]) * -1.f, massAntiLambdaV0); - // "signed" pt for antimatter - m_hAnalysis.fill(HIST("armenteros_plot_lambda"), alphaAP, qtAP); - m_hAnalysis.fill(HIST("nSigmaTPCPi"), std::hypot(momPos[0], momPos[1], momPos[2]), posTrack.tpcNSigmaPi()); - m_hAnalysis.fill(HIST("nSigmaITSPi"), std::hypot(momPos[0], momPos[1], momPos[2]), m_responseITS.nSigmaITS(posTrack.itsClusterSizes(), posTrack.p(), posTrack.eta())); - m_hAnalysis.fill(HIST("nSigmaTPCPr"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, negTrack.tpcNSigmaPr()); - m_hAnalysis.fill(HIST("nSigmaITSPr"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, m_responseITS.nSigmaITS(negTrack.itsClusterSizes(), negTrack.p(), negTrack.eta())); - m_hAnalysis.fill(HIST("pmatchingPi"), posTrack.tpcInnerParam(), (posTrack.tpcInnerParam() - posTrack.p()) / posTrack.tpcInnerParam()); - m_hAnalysis.fill(HIST("pmatchingPr"), -negTrack.tpcInnerParam(), (negTrack.tpcInnerParam() - negTrack.p()) / negTrack.tpcInnerParam()); - - } else if (TESTBIT(v0Bitmask, Photon)) { - massV0 = 0.f; - m_hAnalysis.fill(HIST("nSigmaTPCEl"), std::hypot(momPos[0], momPos[1], momPos[2]), posTrack.tpcNSigmaEl()); - m_hAnalysis.fill(HIST("nSigmaTPCEl"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, negTrack.tpcNSigmaEl()); - m_hAnalysis.fill(HIST("nSigmaITSEl"), std::hypot(momPos[0], momPos[1], momPos[2]), m_responseITS.nSigmaITS(posTrack.itsClusterSizes(), posTrack.p(), posTrack.eta())); - m_hAnalysis.fill(HIST("nSigmaITSEl"), std::hypot(momNeg[0], momNeg[1], momNeg[2]) * -1.f, m_responseITS.nSigmaITS(negTrack.itsClusterSizes(), negTrack.p(), negTrack.eta())); - m_hAnalysis.fill(HIST("armenteros_plot_gamma"), alphaAP, qtAP); - m_hAnalysis.fill(HIST("pmatchingEl"), posTrack.tpcInnerParam(), (posTrack.tpcInnerParam() - posTrack.p()) / posTrack.tpcInnerParam()); - m_hAnalysis.fill(HIST("pmatchingEl"), -negTrack.tpcInnerParam(), (negTrack.tpcInnerParam() - negTrack.p()) / negTrack.tpcInnerParam()); - } - m_hAnalysis.fill(HIST("radiusV0"), radiusV0); - m_hAnalysis.fill(HIST("armenteros_plot"), alphaAP, qtAP); - m_v0TrackParCovs.push_back(v0TrackParCov); + m_v0TrackParCovs.emplace_back(v0TrackParCov); + float massV0 = fillHistogramsV0(massLambdaV0, massAntiLambdaV0, momMother, candidatePos, candidateNeg, alphaAP, qtAP, radiusV0, v0Bitmask); + candidatePos.massMother = massV0; + candidateNeg.massMother = massV0; if (!setting_fillV0) { return; @@ -740,95 +835,13 @@ struct LfTreeCreatorClusterStudies { auto posMcParticle = posTrack.mcParticle(); auto negMcParticle = negTrack.mcParticle(); - if (setting_smallTable) { - m_ClusterStudiesTableMc( - std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos - RecoDecay::eta(momPos), // eta_pos - RecoDecay::phi(momPos), // phi_pos - posTrack.itsClusterSizes(), // itsClsize_pos - partID_pos, // partID_pos - posMcParticle.pdgCode()); // pdgCode_pos - m_ClusterStudiesTableMc( - std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg - RecoDecay::eta(momNeg), // eta_neg - RecoDecay::phi(momNeg), // phi_neg - negTrack.itsClusterSizes(), // itsClsize_neg - partID_neg, // partID_neg - negMcParticle.pdgCode()); // pdgCode_neg - } else { - m_ClusterStudiesTableMcExtra( - std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos - RecoDecay::eta(momPos), // eta_pos - RecoDecay::phi(momPos), // phi_pos - posTrack.itsClusterSizes(), // itsClsize_pos - partID_pos, // partID_pos - posMcParticle.pdgCode(), // pdgCode_pos - posTrack.tpcInnerParam() * posTrack.sign(), // pTPC_pos - posTrack.pidForTracking(), // pidInTrk_pos - -999.f, // TpcNSigma_pos - -999.f, // TofNSigma_pos - -999.f, // TofMass_pos - cosPA, // cosPA - massV0); // massV0 - m_ClusterStudiesTableMcExtra( - std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg - RecoDecay::eta(momNeg), // eta_neg - RecoDecay::phi(momNeg), // phi_neg - negTrack.itsClusterSizes(), // itsClsize_neg - partID_neg, // partID_neg - negMcParticle.pdgCode(), // pdgCode_pos - negTrack.tpcInnerParam() * negTrack.sign(), // pTPC_neg - negTrack.pidForTracking(), // pidInTrk_neg - -999.f, // TpcNSigma_neg - -999.f, // TofNSigma_neg - -999.f, // TofMass_neg - cosPA, // cosPA - massV0); // massV0 - } - } else { // data - if (setting_smallTable) { - m_ClusterStudiesTable( - std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos - RecoDecay::eta(momPos), // eta_pos - RecoDecay::phi(momPos), // phi_pos - posTrack.itsClusterSizes(), // itsClsize_pos - partID_pos); // partID_pos - m_ClusterStudiesTable( - std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg - RecoDecay::eta(momNeg), // eta_neg - RecoDecay::phi(momNeg), // phi_neg - negTrack.itsClusterSizes(), // itsClsize_neg - partID_neg); // partID_neg - } else { - m_ClusterStudiesTableExtra( - std::hypot(momPos[0], momPos[1], momPos[2]) * posTrack.sign(), // p_pos - RecoDecay::eta(momPos), // eta_pos - RecoDecay::phi(momPos), // phi_pos - posTrack.itsClusterSizes(), // itsClsize_pos - partID_pos, // partID_pos - posTrack.tpcInnerParam() * posTrack.sign(), // pTPC_pos - posTrack.pidForTracking(), // pidInTrk_pos - -999.f, // TpcNSigma_pos - -999.f, // TofNSigma_pos - -999.f, // TofMass_pos - cosPA, // cosPA - massV0); // massV0 - m_ClusterStudiesTableExtra( - std::hypot(momNeg[0], momNeg[1], momNeg[2]) * negTrack.sign(), // p_neg - RecoDecay::eta(momNeg), // eta_neg - RecoDecay::phi(momNeg), // phi_neg - negTrack.itsClusterSizes(), // itsClsize_neg - partID_neg, // partID_neg - negTrack.tpcInnerParam() * negTrack.sign(), // pTPC_neg - negTrack.pidForTracking(), // pidInTrk_neg - -999.f, // TpcNSigma_neg - -999.f, // TofNSigma_neg - -999.f, // TofMass_neg - cosPA, // cosPA - massV0); // massV0 - } + candidatePos.pdgCode = posMcParticle.pdgCode(); + candidateNeg.pdgCode = negMcParticle.pdgCode(); } + fillTable(candidatePos); + fillTable(candidateNeg); + m_hAnalysis.fill(HIST("isPositive"), true); m_hAnalysis.fill(HIST("isPositive"), false); } @@ -891,59 +904,31 @@ struct LfTreeCreatorClusterStudies { uint8_t partID_bachelor = PartID::ka; + m_ClusterStudiesTable( + std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K + RecoDecay::eta(momBachelor), // eta_K + RecoDecay::phi(momBachelor), // phi_K + bachelorTrack.itsClusterSizes(), // itsClSize_K + partID_bachelor); // partID_K + if (!setting_smallTable) { + m_ClusterStudiesTableExtra( + bachelorTrack.tpcInnerParam() * bachelorTrack.sign(), // pTPC_K + bachelorTrack.pidForTracking(), // PIDinTrk_K + -999.f, // TpcNSigma_K + -999.f, // TofNSigma_K + -999.f, // TofMass_K + cosPA, // cosPA + massOmega); + } + if constexpr (isMC) { if (!bachelorTrack.has_mcParticle()) { return; } auto mcParticle = bachelorTrack.mcParticle(); - if (setting_smallTable) { - m_ClusterStudiesTableMc( - std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K - RecoDecay::eta(momBachelor), // eta_K - RecoDecay::phi(momBachelor), // phi_K - bachelorTrack.itsClusterSizes(), // itsClSize_K - partID_bachelor, // partID_K - mcParticle.pdgCode()); // pdgCode_K - } else { - m_ClusterStudiesTableMcExtra( - std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K - RecoDecay::eta(momBachelor), // eta_K - RecoDecay::phi(momBachelor), // phi_K - bachelorTrack.itsClusterSizes(), // itsClSize_K - partID_bachelor, // partID_K - mcParticle.pdgCode(), // pdgCode_K - bachelorTrack.tpcInnerParam() * bachelorTrack.sign(), // pTPC_K - bachelorTrack.pidForTracking(), // PIDinTrk_K - -999.f, // TpcNSigma_K - -999.f, // TofNSigma_K - -999.f, // TofMass_K - cosPA, // cosPA - massOmega); // massMother - } - } else { - if (setting_smallTable) { - m_ClusterStudiesTable( - std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K - RecoDecay::eta(momBachelor), // eta_K - RecoDecay::phi(momBachelor), // phi_K - bachelorTrack.itsClusterSizes(), // itsClSize_K - partID_bachelor); // partID_K - } else { - m_ClusterStudiesTableExtra( - std::hypot(momBachelor[0], momBachelor[1], momBachelor[2]) * bachelorTrack.sign(), // p_K - RecoDecay::eta(momBachelor), // eta_K - RecoDecay::phi(momBachelor), // phi_K - bachelorTrack.itsClusterSizes(), // itsClSize_K - partID_bachelor, // partID_K - bachelorTrack.tpcInnerParam() * bachelorTrack.sign(), // pTPC_K - bachelorTrack.pidForTracking(), // PIDinTrk_K - -999.f, // TpcNSigma_K - -999.f, // TofNSigma_K - -999.f, // TofMass_K - cosPA, // cosPA - massOmega); - } + m_ClusterStudiesTableMc( + mcParticle.pdgCode()); // pdgCode_K } m_hAnalysis.fill(HIST("isPositive"), bachelorTrack.p() > 0); @@ -960,7 +945,7 @@ struct LfTreeCreatorClusterStudies { return; } m_hAnalysis.fill(HIST("de_selections"), DeSelections::kDeNClsIts); - if (!selectionPIDtpcDe(track)) { + if (std::abs(track.tpcNSigmaDe()) > desetting_nsigmatpc) { return; } m_hAnalysis.fill(HIST("de_selections"), DeSelections::kDePIDtpc); @@ -968,7 +953,7 @@ struct LfTreeCreatorClusterStudies { return; } m_hAnalysis.fill(HIST("de_selections"), DeSelections::kDePIDtof); - m_hAnalysis.fill(HIST("nSigmaTPCDe"), track.p() * track.sign(), computeNSigmaDe(track)); + m_hAnalysis.fill(HIST("nSigmaTPCDe"), track.p() * track.sign(), track.tpcNSigmaDe()); m_hAnalysis.fill(HIST("nSigmaITSDe"), track.p() * track.sign(), m_responseITS.nSigmaITS(track.itsClusterSizes(), track.p(), track.eta())); m_hAnalysis.fill(HIST("nSigmaTOFDe"), track.p() * track.sign(), track.tofNSigmaDe()); m_hAnalysis.fill(HIST("TOFmassDe"), track.p() * track.sign(), computeTOFmassDe(track)); @@ -976,6 +961,23 @@ struct LfTreeCreatorClusterStudies { uint8_t partID = PartID::de; + m_ClusterStudiesTable( + track.p() * track.sign(), // p_De, + track.eta(), // eta_De, + track.phi(), // phi_De, + track.itsClusterSizes(), // itsClSize_De, + partID); // partID_De + if (!setting_smallTable) { + m_ClusterStudiesTableExtra( + track.tpcInnerParam() * track.sign(), // pTPC_De, + track.pidForTracking(), // PIDinTrk_De, + track.tpcNSigmaDe(), // TpcNSigma_De, + track.tofNSigmaDe(), // TofNSigma_De, + computeTOFmassDe(track), // TofMass_De, + -999.f, // cosPA, + -999.f); // massMother + } + if constexpr (isMC) { if (!track.has_mcParticle() || track.sign() > 0) { return; @@ -983,53 +985,8 @@ struct LfTreeCreatorClusterStudies { auto mcParticle = track.mcParticle(); - if (setting_smallTable) { - m_ClusterStudiesTableMc( - track.p() * track.sign(), // p_De, - track.eta(), // eta_De, - track.phi(), // phi_De, - track.itsClusterSizes(), // itsClSize_De, - partID, // pdgCode_De, - mcParticle.pdgCode()); // pdgCodeMc_De - } else { - m_ClusterStudiesTableMcExtra( - track.p() * track.sign(), // p_De, - track.eta(), // eta_De, - track.phi(), // phi_De, - track.itsClusterSizes(), // itsClSize_De, - partID, // pdgCode_De, - mcParticle.pdgCode(), // pdgCodeMc_De - track.tpcInnerParam() * track.sign(), // pTPC_De, - track.pidForTracking(), // PIDinTrk_De, - computeNSigmaDe(track), // TpcNSigma_De, - track.tofNSigmaDe(), // TofNSigma_De, - computeTOFmassDe(track), // TofMass_De, - -999.f, // cosPA, - -999.f); // massMother - } - } else { - if (setting_smallTable) { - m_ClusterStudiesTable( - track.p() * track.sign(), // p_De, - track.eta(), // eta_De, - track.phi(), // phi_De, - track.itsClusterSizes(), // itsClSize_De, - partID); // pdgCode_De - } else { - m_ClusterStudiesTableExtra( - track.p() * track.sign(), // p_De, - track.eta(), // eta_De, - track.phi(), // phi_De, - track.itsClusterSizes(), // itsClSize_De, - partID, // pdgCode_De, - track.tpcInnerParam() * track.sign(), // pTPC_De, - track.pidForTracking(), // PIDinTrk_De, - computeNSigmaDe(track), // TpcNSigma_De, - track.tofNSigmaDe(), // TofNSigma_De, - computeTOFmassDe(track), // TofMass_De, - -999.f, // cosPA, - -999.f); // massMother - } + m_ClusterStudiesTableMc( + mcParticle.pdgCode()); // pdgCode_De } m_hAnalysis.fill(HIST("isPositive"), track.sign() > 0); @@ -1062,60 +1019,31 @@ struct LfTreeCreatorClusterStudies { m_hAnalysis.fill(HIST("TOFmassHe"), track.p() * track.sign(), tofMass); m_hAnalysis.fill(HIST("pmatchingHe"), track.sign() * correctedTPCinnerParam, (correctedTPCinnerParam - track.p()) / correctedTPCinnerParam); + m_ClusterStudiesTable( + track.p() * track.sign(), // p_He3, + track.eta(), // eta_He3, + track.phi(), // phi_He3, + track.itsClusterSizes(), // itsClSize_He3, + partID); // partID_He3 + if (!setting_smallTable) { + m_ClusterStudiesTableExtra( + correctedTPCinnerParam * track.sign(), // pTPC_He3, + track.pidForTracking(), // PIDinTrk_He3, + computeNSigmaHe3(track), // TpcNSigma_He3, + -999.f, // TofNSigma_He3, + tofMass, // TofMass_He3, + -999.f, // cosPA, + -999.f); // massMother + } + if constexpr (isMC) { if (!track.has_mcParticle()) { return; } auto mcParticle = track.mcParticle(); - if (setting_smallTable) { - m_ClusterStudiesTableMc( - track.p() * track.sign(), // p_He3, - track.eta(), // eta_He3, - track.phi(), // phi_He3, - track.itsClusterSizes(), // itsClSize_He3, - partID, // pdgCode_He3, - mcParticle.pdgCode()); // pdgCodeMc_He3 - } else { - m_ClusterStudiesTableMcExtra( - track.p() * track.sign(), // p_He3 - track.eta(), // eta_He3 - track.phi(), // phi_He3 - track.itsClusterSizes(), // itsClSize_He3 - partID, // pdgCode_He3 - mcParticle.pdgCode(), // pdgCodeMc_He3 - correctedTPCinnerParam * track.sign(), // pTPC_He3 - track.pidForTracking(), // PIDinTrk_He3 - computeNSigmaHe3(track), // TpcNSigma_He3 - -999.f, // TofNSigma_He3 - tofMass, // TofMass_He3 - -999.f, // cosPA_He3 - -999.f); // massMother_He3 - } - - } else { - if (setting_smallTable) { - m_ClusterStudiesTable( - track.p() * track.sign(), // p_He3, - track.eta(), // eta_He3, - track.phi(), // phi_He3, - track.itsClusterSizes(), // itsClSize_He3, - partID); // pdgCode_He3 - } else { - m_ClusterStudiesTableExtra( - track.p() * track.sign(), // p_He3, - track.eta(), // eta_He3, - track.phi(), // phi_He3, - track.itsClusterSizes(), // itsClSize_He3, - partID, // pdgCode_He3, - correctedTPCinnerParam * track.sign(), // pTPC_He3, - track.pidForTracking(), // PIDinTrk_He3, - computeNSigmaHe3(track), // TpcNSigma_He3, - -999.f, // TofNSigma_He3, - tofMass, // TofMass_He3, - -999.f, // cosPA, - -999.f); // massMother - } + m_ClusterStudiesTableMc( + mcParticle.pdgCode()); // pdgCodeMc_He3 } m_hAnalysis.fill(HIST("isPositive"), track.sign() > 0); @@ -1141,20 +1069,14 @@ struct LfTreeCreatorClusterStudies { return; } - if (setting_smallTable) { - m_ClusterStudiesTable( - track.p() * track.sign(), - track.eta(), - track.phi(), - track.itsClusterSizes(), - partID); - } else { + m_ClusterStudiesTable( + track.p() * track.sign(), + track.eta(), + track.phi(), + track.itsClusterSizes(), + partID); + if (!setting_smallTable) { m_ClusterStudiesTableExtra( - track.p() * track.sign(), // p, - track.eta(), // eta, - track.phi(), // phi, - track.itsClusterSizes(), // itsClSize, - partID, // pdgCode, track.tpcInnerParam() * track.sign(), // pTPC, track.pidForTracking(), // PIDinTrk, tpcNSigma, // TpcNSigma, diff --git a/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx b/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx index dda78a26c64..ca3f8a525b2 100644 --- a/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx +++ b/PWGLF/TableProducer/Nuspex/LFTreeCreatorNuclei.cxx @@ -20,26 +20,27 @@ #include "PWGLF/DataModel/LFNucleiTables.h" #include "PWGLF/DataModel/LFParticleIdentification.h" -#include -#include -#include - -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/HistogramRegistry.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/CCDB/EventSelectionParams.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/TrackSelectionDefaults.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/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 +#include +#include // #include @@ -249,6 +250,7 @@ struct LfTreeCreatorNuclei { track.tpcSignal(), track.pt(), track.eta(), track.phi(), track.sign(), + track.itsClusterSizes(), track.itsNCls(), track.tpcNClsFindable(), track.tpcNClsFindableMinusFound(), diff --git a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx index b7b643bca21..7757cbc72a1 100644 --- a/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx +++ b/PWGLF/TableProducer/Nuspex/decay3bodybuilder.cxx @@ -8,647 +8,509 @@ // In applying this license CERN does 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 decay3bodybuilder.cxx -/// \brief Builder task for 3-body decay reconstruction (p + pion + bachelor) +/// \brief Builder task for 3-body hypertriton decay reconstruction (proton + pion + deuteron) /// \author Yuanzhe Wang -/// \author Carolina Reetz (KFParticle specific part) +/// \author Carolina Reetz +// ======================== -#include -#include -#include -#include -#include -#include -#include -#include +#include "TableHelper.h" -#include -#include +#include "PWGLF/DataModel/LFPIDTOFGenericTables.h" +#include "PWGLF/DataModel/Reduced3BodyTables.h" +#include "PWGLF/DataModel/Vtx3BodyTables.h" +#include "PWGLF/Utils/decay3bodyBuilderHelper.h" +#include "PWGLF/Utils/pidTOFGeneric.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" -#include "DetectorsVertexing/SVertexHypothesis.h" +#include "Common/Core/PID/PIDTOF.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Reduced3BodyTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "PWGLF/DataModel/pidTOFGeneric.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "TableHelper.h" -#include "Tools/KFparticle/KFUtilities.h" - #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" +#include "Tools/KFparticle/KFUtilities.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" #include "CCDB/BasicCCDBManager.h" -#include "DataFormatsTPC/BetheBlochAleph.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 +#include +#include +#include +#include +#include +#include +#include #ifndef HomogeneousField #define HomogeneousField #endif // includes KFParticle -#include "KFParticle.h" #include "KFPTrack.h" #include "KFPVertex.h" +#include "KFParticle.h" #include "KFParticleBase.h" #include "KFVertex.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using std::array; - -using FullTracksExtIU = soa::Join; -using FullTracksExtPIDIU = soa::Join; -using ColwithEvTimes = o2::soa::Join; -using ColwithEvTimesMults = o2::soa::Join; -using TrackExtIUwithEvTimes = soa::Join; -using TrackExtPIDIUwithEvTimes = soa::Join; +o2::common::core::MetadataHelper metadataInfo; -using MCLabeledTracksIU = soa::Join; +static constexpr int nParameters = 1; +static const std::vector tableNames{ + "Decay3BodyIndices", + "Vtx3BodyDatas", + "Vtx3BodyCovs", + "McVtx3BodyDatas"}; -using ReducedCollisionsMults = soa::Join; -using ReducedCollisionsMultsCents = soa::Join; - -namespace -{ -const float pidCutsLambda[o2::vertexing::SVertexHypothesis::NPIDParams] = {0., 20, 0., 5.0, 0.0, 1.09004e-03, 2.62291e-04, 8.93179e-03, 2.83121}; // Lambda -} // namespace - -struct VtxCandidate { - int track0Id; - int track1Id; - int track2Id; - int collisionId; - int decay3bodyId; - float vtxPos[3]; - float track0P[3]; - float track1P[3]; - float track2P[3]; - float dcadaughters; - float daudcaxytopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float daudcatopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float bachelortofNsigma; -}; +static constexpr int nTablesConst = 4; -struct kfCandidate { - // hypertriton - int collisionID; - int trackPosID; - int trackNegID; - int trackBachID; - int decay3bodyID; - float mass; - float pos[3]; - float posErr[3]; - float mom[4]; - float momErr[4]; - float charge; - float dcaToPV[2]; // 3D, xy - float cpaToPV[2]; // 3D, xy - float cpaToPVtopo[2]; // 3D, xy - float decLen[2]; // 3D, xy - float ldl; - float chi2geoNDF; - float chi2topoNDF; - float ctau; - float trackedClSize; - float DeltaPhiRotDeuteron; - float DeltaPhiRotProton; - // V0 - float massV0; - float chi2massV0; - float cpaV0ToPV; - // daughter momenta - float protonMom[3]; - float pionMom[3]; - float deuteronMom[3]; - float tpcInnerParam[3]; // proton, pion, deuteron - // daughter track quality - int tpcNClDaughters[3]; // proton, pion, deuteron - float tpcChi2NClDeuteron; - // daughter DCAs KF - float DCAdaughterToPV[3]; // proton, pion, deuteron - float DCAdaughterToPVxy[3]; // proton, pion, deuteron - float DCAdaughterToSVxy[3]; // proton, pion, deuteron - float DCAprotonToPion; - float DCAprotonToDeuteron; - float DCApionToDeuteron; - float DCAvtxDaughters3D; - // daughter DCAs to PV propagated with material - float trackDCAxy[3]; // pos, neg, bach - float trackDCA[3]; // pos, neg, bach - // daughter signs - float daughterCharge[3]; // proton, pion, deuteron - // daughter PID - float tpcNsigma[4]; // proton, pion, deuteron, bach with pion hyp - float tpcdEdx[3]; // proton, pion, deuteron - float tofNsigmaDeuteron; - float averageClusterSizeDeuteron; - float pidForTrackingDeuteron; +static const std::vector parameterNames{"enable"}; +static const int defaultParameters[nTablesConst][nParameters]{ + {0}, // Decay3BodyIndices + {0}, // Vtx3BodyDatas + {0}, // Vtx3BodyCovs + {0} // McVtx3BodyDatas }; -struct decay3bodyBuilder { - - Produces vtx3bodydata; - Produces kfvtx3bodydata; - Produces kfvtx3bodydatalite; - Service ccdb; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - std::vector VtxCandidates; +using TracksExtPIDIUwithEvTimes = soa::Join; +using TracksExtPIDIUwithEvTimesLabeled = soa::Join; - std::unordered_map ccdbCache; // Maps runNumber -> d_bz - std::unordered_map> grpMagCache; // Maps runNumber -> grpmap +using ColswithEvTimes = o2::soa::Join; +using ColswithEvTimesLabeled = o2::soa::Join; - Zorro zorro; - OutputObj zorroSummary{"zorroSummary"}; +struct decay3bodyBuilder { - std::vector fTrackedClSizeVector; + // helper object + o2::pwglf::decay3bodyBuilderHelper helper; + + // table index : match order above + enum tableIndex { kDecay3BodyIndices = 0, + kVtx3BodyDatas, + kVtx3BodyCovs, + kMcVtx3BodyDatas, + nTables }; + + struct : ProducesGroup { + Produces decay3bodyindices; + Produces vtx3bodydatas; + Produces vtx3bodycovs; + Produces mcvtx3bodydatas; + } products; + + // enablde tables + Configurable> enabledTables{"enabledTables", + {defaultParameters[0], nTables, nParameters, tableNames, parameterNames}, + "Produce this table: 0 - false, 1 - true"}; + std::vector mEnabledTables; // Vector of enabled tables + + // general options + Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; + Configurable doTrackQA{"doTrackQA", false, "Flag to fill QA histograms for daughter tracks of (selected) decay3body candidates."}; + Configurable doVertexQA{"doVertexQA", false, "Flag to fill QA histograms for PV of (selected) events."}; + Configurable doSel8selection{"doSel8selection", true, "flag for sel8 event selection"}; + Configurable doPosZselection{"doPosZselection", true, "flag for posZ event selection"}; - // Configurables - Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; - - enum Hyp3Body { kH3L = 0, - kH4L, - kHe4L, - kHe5L, - kNHyp3body }; - - enum VtxStep { kVtxAll = 0, - kVtxTPCNcls, - kVtxPIDCut, - kVtxhasSV, - kVtxDcaDau, - kVtxCosPA, - kNVtxSteps }; - - enum kfvtxstep { kKfVtxAll = 0, - kKfVtxCharge, - kKfVtxEta, - kKfVtxTPCNcls, - kKfVtxTPCRows, - kKfVtxTPCPID, - kKfVtxDCAxyPV, - kKfVtxDCAzPV, - kKfVtxV0MassConst, - kKfVtxhasSV, - kKfVtxDcaDau, - kKfVtxDcaDauVtx, - kKfVtxDauPt, - kKfVtxRap, - kKfVtxPt, - kKfVtxMass, - kKfVtxCosPA, - kKfVtxCosPAXY, - kKfVtxChi2geo, - kKfVtxTopoConstr, - kKfVtxChi2topo, - kKfNVtxSteps }; - - HistogramRegistry registry{"registry", {}}; - - // hypothesis - Configurable motherhyp{"motherhyp", 0, "hypothesis of the 3body decayed particle"}; // corresponds to Hyp3Body - int bachelorcharge = 1; // to be updated in Init base on the hypothesis - o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; // to be updated in Init base on the hypothesis - - // Selection criteria - Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; - Configurable mintpcNCls{"mintpcNCls", 70, "min tpc Nclusters"}; - Configurable minCosPA3body{"minCosPA3body", 0.9, "minCosPA3body"}; - Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; - Configurable enablePidCut{"enablePidCut", 0, "enable function checkPIDH3L"}; - Configurable TofPidNsigmaMin{"TofPidNsigmaMin", -5, "TofPidNsigmaMin"}; - Configurable TofPidNsigmaMax{"TofPidNsigmaMax", 5, "TofPidNsigmaMax"}; - Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; - Configurable minBachPUseTOF{"minBachPUseTOF", 1, "minBachP Enable TOF PID"}; + // 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"}; + Configurable onlyKeepInterestedTrigger{"onlyKeepInterestedTrigger", false, "Flag to keep only interested trigger"}; + Configurable doLikeSign{"doLikeSign", false, "Flag to produce like-sign background. If true, require the sign of pion is as same as deuteron but not proton."}; - Configurable useMatCorrType{"useMatCorrType", 0, "0: none, 1: TGeo, 2: LUT"}; // CCDB options - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; - Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - // CCDB TOF PID paras - Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; - Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; - Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; - Configurable passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; - Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; - Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; - // for KFParticle reconstruction struct : ConfigurableGroup { - Configurable cfgSkimmedProcessing{"kfparticleConfigurations.cfgSkimmedProcessing", false, "Flag for skimmed dataset processing"}; - Configurable triggerList{"kfparticleConfigurations.triggerList", "fH3L3Body", "List of triggers used to select events"}; - Configurable cfgOnlyKeepInterestedTrigger{"kfparticleConfigurations.cfgOnlyKeepInterestedTrigger", false, "Flag to keep only interested trigger"}; - Configurable fillCandidateFullTable{"kfparticleConfigurations.fillCandidateFullTable", false, "Switch to fill full table with candidate properties"}; - Configurable doSel8selection{"kfparticleConfigurations.doSel8selection", true, "flag for sel8 event selection"}; - Configurable doPosZselection{"kfparticleConfigurations.doPosZselection", true, "flag for posZ event selection"}; - Configurable doDCAFitterPreMinimum{"kfparticleConfigurations.doDCAFitterPreMinimum", false, "do DCAFitter pre-optimization before KF fit to include material corrections for decay3body vertex"}; - Configurable doTrackQA{"kfparticleConfigurations.doTrackQA", false, "Flag to fill QA histograms for daughter tracks."}; - Configurable doVertexQA{"kfparticleConfigurations.doVertexQA", false, "Flag to fill QA histograms for KFParticle PV."}; - Configurable useLambdaMassConstraint{"kfparticleConfigurations.useLambdaMassConstraint", false, "Apply Lambda mass constraint on proton-pion vertex"}; - Configurable doDCAPreSel{"kfparticleConfigurations.doDCAPreSel", false, "Apply selection on DCA of daughter tracks to PV"}; - Configurable maxEta{"kfparticleConfigurations.maxEta", 1.0, "Maximum eta for proton and pion daughter tracks"}; - Configurable maxEtaDeuteron{"kfparticleConfigurations.maxEtaDeuteron", 0.9, "Maximum eta for deuteron daughter track"}; - Configurable useTPCforPion{"kfparticleConfigurations.useTPCforPion", true, "Flag to ask for TPC info for pion track (PID, nClusters), false: pion track can be ITS only"}; - Configurable mintpcNClsProton{"kfparticleConfigurations.mintpcNClsProton", 70, "Minimum number of TPC clusters for proton track"}; - Configurable mintpcNClsPion{"kfparticleConfigurations.mintpcNClsPion", 70, "Minimum number of TPC clusters for pion track"}; - Configurable mintpcNClsBach{"kfparticleConfigurations.mintpcNClsBach", 70, "Minimum number of TPC clusters for bachelor track"}; - Configurable mintpcCrossedRows{"kfparticleConfigurations.mintpcCrossedRows", 70, "Minimum number of TPC crossed rows for proton and deuteron track"}; - Configurable mintpcCrossedRowsPion{"kfparticleConfigurations.mintpcCrossedRowsPion", 70, "Minimum number of TPC crossed rows for pion track"}; - Configurable minPtProton{"kfparticleConfigurations.minPtProton", 0.1, "Minimum pT of proton track"}; - Configurable maxPtProton{"kfparticleConfigurations.maxPtProton", 10, "Maximum pT of proton track"}; - Configurable minPtPion{"kfparticleConfigurations.minPtPion", 0.1, "Minimum pT of pion track"}; - Configurable maxPtPion{"kfparticleConfigurations.maxPtPion", 10, "Maximum pT of pion track"}; - Configurable minPtDeuteron{"kfparticleConfigurations.minPtDeuteron", 0.1, "Minimum pT of deuteron track"}; - Configurable maxPtDeuteron{"kfparticleConfigurations.maxPtDeuteron", 10, "Maximum pT of deuteron track"}; - Configurable mindcaXYPionPV{"kfparticleConfigurations.mindcaXYPionPV", 0.1, "Minimum DCA XY of the pion daughter track to the PV"}; - Configurable mindcaXYProtonPV{"kfparticleConfigurations.mindcaXYProtonPV", 0.1, "Minimum DCA XY of the proton daughter track to the PV"}; - Configurable mindcaZPionPV{"kfparticleConfigurations.mindcaZPionPV", 0.1, "Minimum DCA Z of the pion daughter track to the PV"}; - Configurable mindcaZProtonPV{"kfparticleConfigurations.mindcaZProtonPV", 0.1, "Minimum DCA Z of the proton daughter track to the PV"}; - Configurable maxtpcnSigma{"kfparticleConfigurations.maxtpcnSigma", 5., "Maximum nSigma TPC for daughter tracks"}; - Configurable maxDcaProDeu{"kfparticleConfigurations.maxDcaProDeu", 1000., "Maximum geometrical distance between proton and deuteron at the SV in 3D with KFParticle"}; - Configurable maxDcaProPi{"kfparticleConfigurations.maxDcaProPi", 1000., "Maximum geometrical distance between proton and pion at the SV in 3D with KFParticle"}; - Configurable maxDcaPiDe{"kfparticleConfigurations.maxDcaPiDe", 1000., "Maximum geometrical distance between pion and deuteron at the SV in 3D with KFParticle"}; - Configurable maxDcaXYSVDau{"kfparticleConfigurations.maxDcaXYSVDau", 1.0, "Maximum geometrical distance of daughter tracks from the SV in XY with KFParticle"}; - Configurable maxRapidityHt{"kfparticleConfigurations.maxRapidityHt", 1., "Maximum rapidity for Hypertriton candidates with KFParticle"}; - Configurable minPtHt{"kfparticleConfigurations.minPtHt", 0.01, "Minimum momentum for Hypertriton candidates with KFParticle (0.01 applied in SVertexer)"}; - Configurable maxPtHt{"kfparticleConfigurations.maxPtHt", 36., "Maximum momentum for Hypertriton candidates with KFParticle"}; - Configurable minMassHt{"kfparticleConfigurations.minMassHt", 2.96, "Minimum candidate mass with KFParticle"}; - Configurable maxMassHt{"kfparticleConfigurations.maxMassHt", 3.05, "Maximum candidate mass with KFParticle"}; - Configurable maxctauHt{"kfparticleConfigurations.maxctauHt", 40., "Maximum candidate ctau with KFParticle before topological constraint"}; - Configurable maxChi2geo{"kfparticleConfigurations.maxChi2geo", 1000., "Maximum chi2 geometrical with KFParticle"}; - Configurable minCosPA{"kfparticleConfigurations.minCosPA", 0.8, "Minimum cosine pointing angle with KFParticle (0.8 applied in SVertexer)"}; - Configurable minCosPAxy{"kfparticleConfigurations.minCosPAxy", 0.8, "Minimum cosine pointing angle in xy with KFParticle"}; - Configurable applyTopoSel{"kfparticleConfigurations.applyTopoSel", false, "Apply selection constraining the mother to the PV with KFParticle"}; - Configurable maxChi2topo{"kfparticleConfigurations.maxChi2topo", 1000., "Maximum chi2 topological with KFParticle"}; - Configurable nEvtMixing{"kfparticleConfigurations.nEvtMixing", 5, "Number of events to mix"}; - ConfigurableAxis binsVtxZ{"kfparticleConfigurations.binsVtxZ", {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 binsMultiplicity{"kfparticleConfigurations.binsMultiplicity", {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 - multiplicity"}; - // 3body mixing - Configurable mixingType{"kfparticleConfigurations.mixingType", 0, "0: mix V0 from one event with bachelor from another, 1: mix pion and bachelor from one event with proton from another "}; - Configurable applySVertexerV0Cuts{"kfparticleConfigurations.applySVertexerV0Cuts", false, "Apply virtual V0 cuts applied in SVertexer in case of proton mixing"}; - ConfigurableAxis bins3BodyRadius{"kfparticleConfigurations.bins3BodyRadius", {VARIABLE_WIDTH, 0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f, 14.0f, 16.0f, 18.0f, 20.0f, 30.0f, 1000.0}, "Mixing bins - 3body radius"}; - // ConfigurableAxis bins3BodyPhi{"kfparticleConfigurations.bins3BodyPhi", {VARIABLE_WIDTH, -180.0f*TMath::Pi()/180, -170.0f*TMath::Pi()/180, -160.0f*TMath::Pi()/180, -150.0f*TMath::Pi()/180, -140.0f*TMath::Pi()/180, -130.0f*TMath::Pi()/180, -120.0f*TMath::Pi()/180, -110.0f*TMath::Pi()/180, -100.0f*TMath::Pi()/180, -90.0f*TMath::Pi()/180, -80.0f*TMath::Pi()/180, -70.0f*TMath::Pi()/180, -60.0f*TMath::Pi()/180, -50.0f*TMath::Pi()/180, -40.0f*TMath::Pi()/180, -30.0f*TMath::Pi()/180, -20.0f*TMath::Pi()/180, -10.0f*TMath::Pi()/180, 0.0f, 10.0f*TMath::Pi()/180, 20.0f*TMath::Pi()/180, 30.0f*TMath::Pi()/180, 40.0f*TMath::Pi()/180, 50.0f*TMath::Pi()/180, 60.0f*TMath::Pi()/180, 70.0f*TMath::Pi()/180, 80.0f*TMath::Pi()/180, 90.0f*TMath::Pi()/180, 100.0f*TMath::Pi()/180, 110.0f*TMath::Pi()/180, 120.0f*TMath::Pi()/180, 130.0f*TMath::Pi()/180, 140.0f*TMath::Pi()/180, 150.0f*TMath::Pi()/180, 160.0f*TMath::Pi()/180, 170.0f*TMath::Pi()/180, 180.0f*TMath::Pi()/180}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPhi{"kfparticleConfigurations.bins3BodyPhi", {VARIABLE_WIDTH, -180.0f * TMath::Pi() / 180, -160.0f * TMath::Pi() / 180, -140.0f * TMath::Pi() / 180, -120.0f * TMath::Pi() / 180, -100.0f * TMath::Pi() / 180, -80.0f * TMath::Pi() / 180, -60.0f * TMath::Pi() / 180, -40.0f * TMath::Pi() / 180, -20.0f * TMath::Pi() / 180, 0.0f, 20.0f * TMath::Pi() / 180, 40.0f * TMath::Pi() / 180, 60.0f * TMath::Pi() / 180, 80.0f * TMath::Pi() / 180, 100.0f * TMath::Pi() / 180, 120.0f * TMath::Pi() / 180, 140.0f * TMath::Pi() / 180, 160.0f * TMath::Pi() / 180, 180.0f * TMath::Pi() / 180}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPosZ{"kfparticleConfigurations.bins3BodyPosZ", {VARIABLE_WIDTH, -300.0f, -42.0f, -13.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 13.0f, 42.0f, 300.0f}, "Mixing bins - 3body z position"}; - Configurable selectVtxZ3bodyMixing{"kfparticleConfigurations.selectVtxZ3bodyMixing", true, "Select same VtxZ events in case of 3body mixing"}; - Configurable VtxZBin3bodyMixing{"kfparticleConfigurations.VtxZBin3bodyMixing", 1., "Bin width for event vtx z position in case of 3body mixing"}; - } kfparticleConfigurations; - - //------------------------------------------------------------------ - // Sets for DCAFitter event mixing + std::string prefix = "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 lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + } ccdbConfigurations; + + // Decay3body building options struct : ConfigurableGroup { - Configurable nUseMixed{"dcaFitterEMSel.nUseMixed", 5, "nUseMixed"}; - Configurable mMinPt2V0{"dcaFitterEMSel.mMinPt2V0", 0.5, "mMinPt2V0"}; // minimum pT^2 of V0 - Configurable mMaxTgl2V0{"dcaFitterEMSel.mMaxTgl2V0", 4, "mMaxTgl2V0"}; // maximum tgLambda^2 of V0 - Configurable mMaxDCAXY2ToMeanVertex3bodyV0{"dcaFitterEMSel.mMaxDCAXY2ToMeanVertex3bodyV0", 4, "mMaxDCAXY2ToMeanVertex3bodyV0"}; // max DCA^2 of 2 body decay to mean vertex of 3 body decay in XY - Configurable minCosPAXYMeanVertex3bodyV0{"dcaFitterEMSel.minCosPAXYMeanVertex3bodyV0", 0.9, "minCosPAXYMeanVertex3bodyV0"}; // min CosPA of 2 body decay to mean vertex of 3 body decay in XY - Configurable minCosPA3bodyV0{"dcaFitterEMSel.minCosPA3bodyV0", 0.8, "minCosPA3bodyV0"}; // min CosPA of 3 body decay to PV - Configurable maxRDiffV03body{"dcaFitterEMSel.maxRDiffV03body", 3, "maxRDiffV03body"}; // Maximum difference between virtual V0 and 3body radius - Configurable minPt3Body = {"dcaFitterEMSel.minPt3Body", 0.01, ""}; // minimum pT of 3body Vertex - Configurable maxTgl3Body = {"dcaFitterEMSel.maxTgl3Body", 2, ""}; // maximum tgLambda of 3body Vertex - Configurable maxDCAXY3Body{"dcaFitterEMSel.maxDCAXY3Body", 0.5, "DCAXY H3L to PV"}; // max DCA of 3 body decay to PV in XY - Configurable maxDCAZ3Body{"dcaFitterEMSel.maxDCAZ3Body", 1.0, "DCAZ H3L to PV"}; // max DCA of 3 body decay to PV in Z - // Binning for mixing events - ConfigurableAxis binsVtxZ{"dcaFitterEMSel.binsVtxZ", {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 binsMultiplicity{"dcaFitterEMSel.binsMultiplicity", {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 - multiplicity"}; - Configurable maxDeltaRadiusColMixing{"dcaFitterEMSel.maxDeltaRadiusColMixing", 2., "max difference between pv z position in case of collision mixing"}; - Configurable maxDeltaPhiColMixing{"dcaFitterEMSel.maxDeltaPhiColMixing", 30., "max difference between Phi of monther particle in case of collision mixing (degree)"}; - // Configurations for mixing decay3bodys - // Configurable cfgUseDCAFitterInfo{"dcaFitterEMSel.cfgUseDCAFitterInfo", true, ""}; // if use information from dcatFitter while mixing reduced 3bodys - Configurable cfgMix3BodyMethod{"dcaFitterEMSel.cfgMix3BodyMethod", 0, ""}; // 0: bachelor, 1: pion, 2: proton - Configurable cfgApplyV0Cut{"dcaFitterEMSel.cfgApplyV0Cut", true, "if apply V0 cut while performing event-mixing"}; - ConfigurableAxis bins3BodyRadius{"dcaFitterEMSel.bins3BodyRadius", {VARIABLE_WIDTH, 0.0f, 2.0f, 4.0f, 7.0f, 10.0f, 14.0f, 18.0f, 22.0f, 30.0f, 40.0f}, "Mixing bins - 3body radius"}; - ConfigurableAxis bins3BodyPhi{"dcaFitterEMSel.bins3BodyPhi", {VARIABLE_WIDTH, -3.15, -2.15, -1, 0, 1, 2.15, 3.15}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPhiDegree{"dcaFitterEMSel.bins3BodyPhiDegree", {VARIABLE_WIDTH, -180, -120, -60, 0, 60, 120, 180}, "Mixing bins - 3body phi"}; - ConfigurableAxis bins3BodyPosZ{"dcaFitterEMSel.bins3BodyPosZ", {VARIABLE_WIDTH, -500.0f, -200.0f, -100.0f, -70.0f, -60.0f, -50.0f, -40.0f, -35.0f, -30.0f, -25.0f, -20.0f, -15.0f, -13.0f, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 13.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f, 60.0f, 70.0f, 100.0f, 200.0f, 500.0f}, "3body SV z position"}; - Configurable selectPVPosZ3bodyMixing{"dcaFitterEMSel.selectPVPosZ3bodyMixing", true, "Select same pvPosZ events in case of 3body mixing"}; - Configurable maxDeltaPVPosZ3bodyMixing{"dcaFitterEMSel.maxDeltaPVPosZ3bodyMixing", 1., "max difference between pv z position in case of 3body mixing"}; - } dcaFitterEMSel; - - SliceCache cache; - using BinningTypeColEM = ColumnBinningPolicy; - using Binning3BodyDCAFitter = ColumnBinningPolicy; - using Binning3BodyKFInfo = ColumnBinningPolicy; - - // KF event mixing - using BinningTypeKF = ColumnBinningPolicy; - - // 3body mixing - // using Binning3Body = ColumnBinningPolicy; - using Binning3Body = ColumnBinningPolicy; + std::string prefix = "decay3bodyBuilderOpts"; + // building options + Configurable useKFParticle{"useKFParticle", false, "Use KFParticle for decay3body building"}; + Configurable kfSetTopologicalConstraint{"kfSetTopologicalConstraint", false, "Set topological vertex constraint in case of KFParticle reconstruction"}; + Configurable buildOnlyTracked{"buildOnlyTracked", false, "Build only tracked decay3bodys"}; + Configurable useSelections{"useSelections", true, "Apply selections during decay3body building"}; + Configurable useChi2Selection{"useChi2Selection", true, "Apply chi2 selection during decay3body building"}; + Configurable useTPCforPion{"useTPCforPion", false, "Flag to ask for TPC info for pion track (PID, nClusters), false: pion track can be ITS only"}; + Configurable acceptTPCOnly{"acceptTPCOnly", false, "Accept TPC only tracks as daughters"}; + Configurable askOnlyITSMatch{"askOnlyITSMatch", true, "ask only ITS match to distinguish TPC only tracks"}; + Configurable calculateCovariance{"calculateCovariance", true, "Calculate candidate and daughter covariance matrices"}; + // daughter track selections + Configurable maxEtaDaughters{"maxEtaDaughters", 0.9, "Max eta of daughters"}; + Configurable minTPCNClProton{"minTPCNClProton", 90, "Min TPC NClusters of proton daughter"}; + Configurable minTPCNClPion{"minTPCNClPion", 70, "Min TPC NClusters of pion daughter"}; + Configurable minTPCNClDeuteron{"minTPCNClDeuteron", 100, "Min TPC NClusters of deuteron daughter"}; + Configurable minDCAProtonToPV{"minDCAProtonToPV", 0.1, "Min DCA of proton to PV"}; + Configurable minDCAPionToPV{"minDCAPionToPV", 0.1, "Min DCA of pion to PV"}; + Configurable minDCADeuteronToPV{"minDCADeuteronToPV", 0.1, "Min DCA of deuteron to PV"}; + Configurable minPtProton{"minPtProton", 0.3, "Min Pt of proton daughter"}; + Configurable minPtPion{"minPtPion", 0.1, "Min Pt of pion daughter"}; + Configurable minPtDeuteron{"minPtDeuteron", 0.6, "Min Pt of deuteron daughter"}; + Configurable maxPtProton{"maxPtProton", 5.0, "Max Pt of proton daughter"}; + Configurable maxPtPion{"maxPtPion", 1.2, "Max Pt of pion daughter"}; + Configurable maxPtDeuteron{"maxPtDeuteron", 10.0, "Max Pt of deuteron daughter"}; + Configurable maxTPCnSigma{"maxTPCnSigma", 5.0, "Min/max TPC nSigma of daughter tracks"}; + Configurable minTOFnSigmaDeuteron{"minTOFnSigmaDeuteron", -5.0, "Min TOF nSigma of deuteron daughter"}; + Configurable maxTOFnSigmaDeuteron{"maxTOFnSigmaDeuteron", 5.0, "Max TOF nSigma of deuteron daughter"}; + Configurable minPDeuteronUseTOF{"minPDeuteronUseTOF", 1.0, "Min P of deuteron to use TOF PID"}; + Configurable maxDCADauToSVaverage{"maxDCADauToSVaverage", 0.5, "Max DCA of daughters to SV (quadratic sum of daughter DCAs to SV / 3)"}; + // candidate selections + Configurable maxRapidity{"maxRapidity", 1.0, "Max rapidity of decay3body vertex"}; + Configurable minPt{"minPt", 2.0, "Min Pt of decay3body candidate"}; + Configurable maxPt{"maxPt", 5.0, "Max Pt of decay3body candidate"}; + Configurable minMass{"minMass", 2.96, "Min mass of decay3body candidate"}; + Configurable maxMass{"maxMass", 3.04, "Max mass of decay3body candidate"}; + Configurable minCtau{"minCtau", 0.0, "Min ctau of decay3body candidate"}; + Configurable maxCtau{"maxCtau", 100.0, "Max ctau of decay3body candidate"}; + Configurable minCosPA{"minCosPA", 0.9, "Min cosPA of decay3body candidate"}; + Configurable maxChi2{"maxChi2", 100.0, "Max chi2 of decay3body candidate"}; + } decay3bodyBuilderOpts; - // Filters and slices - Preslice perCollision = o2::aod::decay3body::collisionId; - Preslice perReducedCollision = o2::aod::reduceddecay3body::collisionId; + struct : ConfigurableGroup { + std::string prefix = "mixingOpts"; + Configurable n3bodyMixing{"n3bodyMixing", 0, "Number of decay3bodys to mix: 0 - value set to maximum bin entry in hDecay3BodyRadiusPhi, > 0 - manual setting"}; + Configurable mixingType{"mixingType", 0, "0: mix V0 from one event with bachelor from another, 1: mix pion and bachelor from one event with proton from another, 1: mix proton and bachelor from one event with pion from another "}; + ConfigurableAxis bins3BodyRadius{"mixingOpts.bins3BodyRadius", {VARIABLE_WIDTH, 0.0f, 2.0f, 4.0f, 7.0f, 10.0f, 14.0f, 18.0f, 22.0f, 30.0f, 40.0f}, "Mixing bins - 3body radius"}; + ConfigurableAxis bins3BodyPhi{"mixingOpts.bins3BodyPhi", {VARIABLE_WIDTH, -180 * o2::constants::math::Deg2Rad, -120 * o2::constants::math::Deg2Rad, -60 * o2::constants::math::Deg2Rad, 0, 60 * o2::constants::math::Deg2Rad, 120 * o2::constants::math::Deg2Rad, 180 * o2::constants::math::Deg2Rad}, "Mixing bins - 3body phi (rad)"}; + ConfigurableAxis bins3BodyPhiDegree{"mixingOpts.bins3BodyPhiDegree", {VARIABLE_WIDTH, -180, -120, -60, 0, 60, 120, 180}, "Mixing bins - 3body phi (degree)"}; + ConfigurableAxis bins3BodyPosZ{"mixingOpts.bins3BodyPosZ", {VARIABLE_WIDTH, -500.0f, -200.0f, -100.0f, -70.0f, -60.0f, -50.0f, -40.0f, -35.0f, -30.0f, -25.0f, -20.0f, -15.0f, -13.0f, -10.0f, -8.0f, -6.0f, -4.0f, -2.0f, 0.0f, 2.0f, 4.0f, 6.0f, 8.0f, 10.0f, 13.0f, 15.0f, 20.0f, 25.0f, 30.0f, 35.0f, 40.0f, 50.0f, 60.0f, 70.0f, 100.0f, 200.0f, 500.0f}, "3body SV z position"}; + Configurable selectPVPosZ3bodyMixing{"selectPVPosZ3bodyMixing", true, "Select same pvPosZ events in case of 3body mixing"}; + Configurable maxDeltaPVPosZ3bodyMixing{"maxDeltaPVPosZ3bodyMixing", 1., "max difference between PV z position in case of 3body mixing"}; + // SVertexer selections + Configurable minPt2V0{"minPt2V0", 0.5, "Min Pt squared of V0"}; + Configurable maxTgl2V0{"maxTgl2V0", 4, "Max tgl squared of V0"}; + Configurable maxDCAXY2ToMeanVertex3bodyV0{"maxDCAXY2ToMeanVertex3bodyV0", 4, "Max DCA XY squared of V0 to mean vertex"}; + Configurable minCosPAXYMeanVertex3bodyV0{"minCosPAXYMeanVertex3bodyV0", 0.9, "Min cosPA XY of V0 to mean vertex"}; + Configurable minCosPA3bodyV0{"minCosPA3bodyV0", 0.8, "Min cosPA of V0"}; + Configurable maxRDiffV03body{"maxRDiffV03body", 3, "Max RDiff of V0 to 3body"}; + Configurable minPt3Body{"minPt3Body", 0.5, "Min Pt of 3body"}; + Configurable maxTgl3Body{"maxTgl3Body", 0.01, "Max tgl of 3body"}; + Configurable maxDCAXY3Body{"maxDCAXY3Body", 0.5, "Max DCA XY of 3body"}; + Configurable maxDCAZ3Body{"maxDCAZ3Body", 1.0, "Max DCA Z of 3body"}; + } mixingOpts; + + // Helper struct to contain MC information prior to filling + struct mc3Bodyinfo { + int label; + std::array genDecVtx{0.f}; + std::array genMomentum{0.f}; + float genCt; + float genPhi; + float genEta; + float genRapidity; + float genMomProton; + float genMomPion; + float genMomDeuteron; + float genPtProton; + float genPtPion; + float genPtDeuteron; + bool isTrueH3L; + bool isTrueAntiH3L; + bool isReco; + int motherPdgCode; + int daughterPrPdgCode; + int daughterPiPdgCode; + int daughterDePdgCode; + bool isDeuteronPrimary; + bool survivedEventSel; + }; + mc3Bodyinfo this3BodyMCInfo; + // CCDB and magnetic field int mRunNumber; float d_bz; - float maxSnp; // max sine phi for propagation - float maxStep; // max step size (cm) for propagation + Service ccdb; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; + std::unordered_map ccdbCache; // Maps runNumber -> d_bz o2::base::MatLayerCylSet* lut = nullptr; - o2::vertexing::DCAFitterN<2> fitterV0; - o2::vertexing::DCAFitterN<3> fitter3body; - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - std::array mV0Hyps; // 0 - Lambda, 1 - AntiLambda - bool doUpdateGRPMagField = false; // if initialize magnetic field for each bc - o2::dataformats::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; - - void init(InitContext&) + + // histogram registry + HistogramRegistry registry{"Registry", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // bachelor TOF PID + o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; // to be updated in Init based on the hypothesis + o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPIDLabeled; // to be updated in Init based on the hypothesis + // TOF response and input parameters + o2::pid::tof::TOFResoParamsV3 mRespParamsV3; + o2::aod::pidtofgeneric::TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration + + // 3body mixing + using Binning3BodyKF = ColumnBinningPolicy; + using Binning3BodyDCAfitter = ColumnBinningPolicy; + + // skimmed processing + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + // tracked cluster size + std::vector fTrackedClSizeVector; + + // trigger info + std::vector isTriggeredCollision; + // MC info + std::vector isGoodCollision; + + void init(InitContext& initContext) { zorroSummary.setObject(zorro.getZorroSummary()); mRunNumber = 0; d_bz = 0; - maxSnp = 0.85f; // could be changed later - maxStep = 2.00f; // could be changed later - - // set hypothesis corresponds to Hyp3Body, tpcpid to be implemented - switch (motherhyp) { - case Hyp3Body::kH3L: - bachelorcharge = 1; - bachelorTOFPID.SetPidType(o2::track::PID::Deuteron); - break; - case Hyp3Body::kH4L: - bachelorcharge = 1; - bachelorTOFPID.SetPidType(o2::track::PID::Triton); - break; - case Hyp3Body::kHe4L: - bachelorcharge = 2; - bachelorTOFPID.SetPidType(o2::track::PID::Helium3); - break; - case Hyp3Body::kHe5L: - bachelorcharge = 2; - bachelorTOFPID.SetPidType(o2::track::PID::Alpha); - break; - default: - LOG(fatal) << "Wrong hypothesis for decay3body"; - return; - } - fitterV0.setPropagateToPCA(true); - fitterV0.setMaxR(200.); - fitterV0.setMinParamChange(1e-3); - fitterV0.setMinRelChi2Change(0.9); - fitterV0.setMaxDZIni(1e9); - fitterV0.setMaxChi2(1e9); - fitterV0.setUseAbsDCA(d_UseAbsDCA); - - fitter3body.setPropagateToPCA(true); - fitter3body.setMaxR(200.); //->maxRIni3body - fitter3body.setMinParamChange(1e-3); - fitter3body.setMinRelChi2Change(0.9); - fitter3body.setMaxDZIni(1e9); - fitter3body.setMaxChi2(1e9); - fitter3body.setUseAbsDCA(d_UseAbsDCA); - - // Material correction in the DCA fitter - ccdb->setURL(ccdburl); + mEnabledTables.resize(nTables, 0); + + // CCDB options + ccdb->setURL(ccdbConfigurations.ccdburl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + // TOF PID parameters initialization + mTOFCalibConfig.metadataInfo = metadataInfo; + mTOFCalibConfig.inheritFromBaseTask(initContext); + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); + + // Set material correction if (useMatCorrType == 1) { LOGF(info, "TGeo correction requested, loading geometry"); if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); + ccdb->get(ccdbConfigurations.geoPath); } + matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; } if (useMatCorrType == 2) { LOGF(info, "LUT correction requested, loading LUT"); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); - } - - // Material correction in the DCA fitter - if (useMatCorrType == 1) - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - if (useMatCorrType == 2) + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(ccdbConfigurations.lutPath)); matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; - - fitterV0.setMatCorrType(matCorr); - fitter3body.setMatCorrType(matCorr); - - // Add histograms separately for different process functions - if (doprocessRun3 == true || doprocessRun3Reduced) { - registry.add("hEventCounter", "hEventCounter", HistType::kTH1F, {{1, 0.0f, 1.0f}}); - } - - if (doprocessRun3 == true || doprocessRun3Reduced || doprocessRun3ReducedEM == true || doprocessRun3Reduced3bodyMixing == true || doprocessRun3Reduced3bodyMixingKFInfo == true) { - auto hVtx3BodyCounter = registry.add("hVtx3BodyCounter", "hVtx3BodyCounter", HistType::kTH1D, {{6, 0.0f, 6.0f}}); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(1, "Total"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(2, "TPCNcls"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(3, "PIDCut"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(4, "HasSV"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(5, "DcaDau"); - hVtx3BodyCounter->GetXaxis()->SetBinLabel(6, "CosPA"); - registry.add("hBachelorTOFNSigmaDe", "", HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}); - } - - if (doprocessRun3ReducedEM == true) { - registry.add("hEventCount", "hEventCount", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hEventPairs", "hEventPairs", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hDecay3BodyPairsBeforeCut", "hDecay3BodyPairsBeforeCut", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hDecay3BodyPairsAfterCut", "hDecay3BodyPairsAfterCut", HistType::kTH2F, {dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}); - registry.add("hRadius0", "hRadius0", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("hRadius1", "hRadius1", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("hDeltaRadius", "hDeltaRadius", HistType::kTH1F, {{400, -20.0f, 20.0f, "#Delta Radius (cm)"}}); - registry.add("hPhi0", "hPhi0", HistType::kTH1F, {{360, -180.0f, 180.0f, "#phi (degree)"}}); - registry.add("hPhi1", "hPhi1", HistType::kTH1F, {{360, -180.0f, 180.0f, "#phi (degree)"}}); - registry.add("hDeltaPhi", "hDeltaPhi", HistType::kTH1F, {{360, -180.0f, 180.0f, "#Delta #phi (degree)"}}); - } - - if (doprocessRun3Reduced3bodyMixing == true || doprocessRun3Reduced3bodyMixingKFInfo == true) { - registry.add("hDecay3BodyRadiusPhi", "hDecay3BodyRadiusPhi", HistType::kTH2F, {dcaFitterEMSel.bins3BodyRadius, dcaFitterEMSel.bins3BodyPhi}); - registry.add("hDecay3BodyPosZ", "hDecay3BodyPosZ", HistType::kTH1F, {dcaFitterEMSel.bins3BodyPosZ}); - auto h3bodyCombinationCounter = registry.add("h3bodyCombinationCounter", "h3bodyCombinationCounter", HistType::kTH1D, {{4, 0.0f, 4.0f}}); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(1, "total"); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(2, "bach sign/ID"); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(3, "not same collision"); - h3bodyCombinationCounter->GetXaxis()->SetBinLabel(4, "collision VtxZ"); - } - - if (doprocessRun3ReducedEM == true || doprocessRun3Reduced3bodyMixing == true || doprocessRun3Reduced3bodyMixingKFInfo == true) { - doUpdateGRPMagField = true; - registry.add("h3bodyEMCutCounter", "h3bodyEMCutCounter", HistType::kTH1D, {{14, 0.0f, 14.0f}}); - } - - if (doprocessRun3withKFParticle == true || doprocessRun3withKFParticleStrangenessTracking == true || doprocessRun3withKFParticleReduced == true || doprocessRun3withKFParticleReducedEM == true || doprocessRun3withKFParticleReduced3bodyMixing == true) { - auto hEventCounterZorro = registry.add("Counters/hEventCounterZorro", "hEventCounterZorro", HistType::kTH1D, {{2, -0.5, 1.5}}); - hEventCounterZorro->GetXaxis()->SetBinLabel(1, "Zorro before evsel"); - hEventCounterZorro->GetXaxis()->SetBinLabel(2, "Zorro after evsel"); - auto hEventCounterKFParticle = registry.add("Counters/hEventCounterKFParticle", "hEventCounterKFParticle", HistType::kTH1D, {{4, 0.0f, 4.0f}}); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(1, "total"); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(2, "sel8"); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(3, "vertexZ"); - hEventCounterKFParticle->GetXaxis()->SetBinLabel(4, "has candidate"); - hEventCounterKFParticle->LabelsOption("v"); - auto hVtx3BodyCounterKFParticle = registry.add("Counters/hVtx3BodyCounterKFParticle", "hVtx3BodyCounterKFParticle", HistType::kTH1D, {{21, 0.0f, 21.0f}}); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(1, "Total"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(2, "Charge"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(3, "Eta"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(4, "TPCNcls"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(5, "TPCRows"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(6, "TPCpid"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(7, "DCAxyPV"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(8, "DCAzPV"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(9, "V0MassConst"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(10, "HasSV"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(11, "DcaDau"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(12, "DCADauVtx"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(13, "DauPt"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(14, "Rapidity"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(15, "Pt"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(16, "Mass"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(17, "CosPA"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(18, "CosPAXY"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(19, "Chi2geo"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(20, "TopoConstr"); - hVtx3BodyCounterKFParticle->GetXaxis()->SetBinLabel(21, "Chi2topo"); - hVtx3BodyCounterKFParticle->LabelsOption("v"); - - registry.add("QA/Tracks/hTrackPosTPCNcls", "hTrackPosTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); - registry.add("QA/Tracks/hTrackNegTPCNcls", "hTrackNegTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); - registry.add("QA/Tracks/hTrackBachTPCNcls", "hTrackBachTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); - registry.add("QA/Tracks/hTrackPosHasTPC", "hTrackPosHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); - registry.add("QA/Tracks/hTrackNegHasTPC", "hTrackNegHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); - registry.add("QA/Tracks/hTrackBachHasTPC", "hTrackBachHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); - registry.add("QA/Tracks/hTrackBachITSClusSizes", "hTrackBachITSClusSizes", HistType::kTH1F, {{10, 0., 10., "ITS cluster sizes"}}); - registry.add("QA/Tracks/hTrackProtonTPCPID", "hTrackProtonTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); - registry.add("QA/Tracks/hTrackPionTPCPID", "hTrackPionTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); - registry.add("QA/Tracks/hTrackBachTPCPID", "hTrackBachTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); - registry.add("QA/Tracks/hTrackProtonPt", "hTrackProtonPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); - registry.add("QA/Tracks/hTrackPionPt", "hTrackPionPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); - registry.add("QA/Tracks/hTrackBachPt", "hTrackBachPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); - registry.add("QA/Event/hAllSelEventsVtxZ", "hAllSelEventsVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); - registry.add("QA/Event/hVtxXKF", "hVtxXKF", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV X (cm)"}}); - registry.add("QA/Event/hVtxYKF", "hVtxYKF", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV Y (cm)"}}); - registry.add("QA/Event/hVtxZKF", "hVtxZKF", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); - registry.add("QA/Event/hVtxCovXXKF", "hVtxCovXXKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XX) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYYKF", "hVtxCovYYKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovZZKF", "hVtxCovZZKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(ZZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXYKF", "hVtxCovXYKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXZKF", "hVtxCovXZKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYZKF", "hVtxCovYZKF", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxX", "hVtxX", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV X (cm)"}}); - registry.add("QA/Event/hVtxY", "hVtxY", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV Y (cm)"}}); - registry.add("QA/Event/hVtxZ", "hVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); - registry.add("QA/Event/hVtxCovXX", "hVtxCovXX", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XX) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYY", "hVtxCovYY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovZZ", "hVtxCovZZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(ZZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXY", "hVtxCovXY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XY) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovXZ", "hVtxCovXZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XZ) (cm^{2})"}}); - registry.add("QA/Event/hVtxCovYZ", "hVtxCovYZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YZ) (cm^{2})"}}); } - if (doprocessRun3withKFParticleReducedEM == true) { - registry.add("QA/EM/hPairCounterMixing", "hPairCounterMixing", HistType::kTH1D, {{1, 0.0f, 1.0f}}); - auto hCombinationCounterMixing = registry.add("QA/EM/hCombinationCounterMixing", "hCombinationCounterMixing", HistType::kTH1D, {{3, 0.0f, 3.0f}}); - hCombinationCounterMixing->GetXaxis()->SetBinLabel(1, "total"); - hCombinationCounterMixing->GetXaxis()->SetBinLabel(2, "bach sign/ID"); - hCombinationCounterMixing->GetXaxis()->SetBinLabel(3, "radius, phi"); - hCombinationCounterMixing->LabelsOption("v"); - - registry.add("QA/EM/hEventBinCounts", "hEventBinCounts", HistType::kTH2D, {{10, 0, 10, "bins VtxZ"}, {13, 0, 13, "bins mult"}}); - registry.add("QA/EM/h3bodyBinCounts", "h3bodyBinCounts", HistType::kTH2D, {{10, 0, 10, "bins VtxZ"}, {13, 0, 13, "bins mult"}}); - registry.add("QA/EM/hPairBinCounts", "hPairBinCounts", HistType::kTH2D, {{10, 0, 10, "bins VtxZ"}, {13, 0, 13, "bins mult"}}); - - registry.add("QA/EM/hRadius1", "hRadius1", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("QA/EM/hRadius2", "hRadius2", HistType::kTH1F, {{200, 0.0f, 20.0f, "Radius (cm)"}}); - registry.add("QA/EM/hPhi1", "hPhi1", HistType::kTH1F, {{360, 0.0f, 360.0f, "#phi (degree)"}}); - registry.add("QA/EM/hPhi2", "hPhi2", HistType::kTH1F, {{360, 0.0f, 360.0f, "#phi (degree)"}}); - registry.add("QA/EM/hDeltaRadius", "hDeltaRadius", HistType::kTH1F, {{200, 0.0f, 10.0f, "#Delta Radius (cm)"}}); - registry.add("QA/EM/hDeltaPhi", "hDeltaPhi", HistType::kTH1F, {{360, 0.0f, 360.0f, "#Delta #phi (degree)"}}); + helper.fitterV0.setMatCorrType(matCorr); + helper.fitter3body.setMatCorrType(matCorr); + + // set bachelor PID + bachelorTOFPID.SetPidType(o2::track::PID::Deuteron); + bachelorTOFPIDLabeled.SetPidType(o2::track::PID::Deuteron); + + // set decay3body parameters in the helper + helper.decay3bodyselections.maxEtaDaughters = decay3bodyBuilderOpts.maxEtaDaughters; + helper.decay3bodyselections.minTPCNClProton = decay3bodyBuilderOpts.minTPCNClProton; + helper.decay3bodyselections.minTPCNClPion = decay3bodyBuilderOpts.minTPCNClPion; + helper.decay3bodyselections.minTPCNClDeuteron = decay3bodyBuilderOpts.minTPCNClDeuteron; + helper.decay3bodyselections.minDCAProtonToPV = decay3bodyBuilderOpts.minDCAProtonToPV; + helper.decay3bodyselections.minDCAPionToPV = decay3bodyBuilderOpts.minDCAPionToPV; + helper.decay3bodyselections.minDCADeuteronToPV = decay3bodyBuilderOpts.minDCADeuteronToPV; + helper.decay3bodyselections.minPtProton = decay3bodyBuilderOpts.minPtProton; + helper.decay3bodyselections.minPtPion = decay3bodyBuilderOpts.minPtPion; + helper.decay3bodyselections.minPtDeuteron = decay3bodyBuilderOpts.minPtDeuteron; + helper.decay3bodyselections.maxPtProton = decay3bodyBuilderOpts.maxPtProton; + helper.decay3bodyselections.maxPtPion = decay3bodyBuilderOpts.maxPtPion; + helper.decay3bodyselections.maxPtDeuteron = decay3bodyBuilderOpts.maxPtDeuteron; + helper.decay3bodyselections.maxTPCnSigma = decay3bodyBuilderOpts.maxTPCnSigma; + helper.decay3bodyselections.minTOFnSigmaDeuteron = decay3bodyBuilderOpts.minTOFnSigmaDeuteron; + helper.decay3bodyselections.maxTOFnSigmaDeuteron = decay3bodyBuilderOpts.maxTOFnSigmaDeuteron; + helper.decay3bodyselections.minPDeuteronUseTOF = decay3bodyBuilderOpts.minPDeuteronUseTOF; + helper.decay3bodyselections.maxDCADauToSVaverage = decay3bodyBuilderOpts.maxDCADauToSVaverage; + helper.decay3bodyselections.maxRapidity = decay3bodyBuilderOpts.maxRapidity; + helper.decay3bodyselections.minPt = decay3bodyBuilderOpts.minPt; + helper.decay3bodyselections.maxPt = decay3bodyBuilderOpts.maxPt; + helper.decay3bodyselections.minMass = decay3bodyBuilderOpts.minMass; + helper.decay3bodyselections.maxMass = decay3bodyBuilderOpts.maxMass; + helper.decay3bodyselections.minCtau = decay3bodyBuilderOpts.minCtau; + helper.decay3bodyselections.maxCtau = decay3bodyBuilderOpts.maxCtau; + helper.decay3bodyselections.minCosPA = decay3bodyBuilderOpts.minCosPA; + helper.decay3bodyselections.maxChi2 = decay3bodyBuilderOpts.maxChi2; + + // set SVertexer selection parameters in the helper + helper.svertexerselections.minPt2V0 = mixingOpts.minPt2V0; + helper.svertexerselections.maxTgl2V0 = mixingOpts.maxTgl2V0; + helper.svertexerselections.maxDCAXY2ToMeanVertex3bodyV0 = mixingOpts.maxDCAXY2ToMeanVertex3bodyV0; + helper.svertexerselections.minCosPAXYMeanVertex3bodyV0 = mixingOpts.minCosPAXYMeanVertex3bodyV0; + helper.svertexerselections.minCosPA3bodyV0 = mixingOpts.minCosPA3bodyV0; + helper.svertexerselections.maxRDiffV03body = mixingOpts.maxRDiffV03body; + helper.svertexerselections.minPt3Body = mixingOpts.minPt3Body; + helper.svertexerselections.maxTgl3Body = mixingOpts.maxTgl3Body; + helper.svertexerselections.maxDCAXY3Body = mixingOpts.maxDCAXY3Body; + helper.svertexerselections.maxDCAZ3Body = mixingOpts.maxDCAZ3Body; + + // list enabled process functions + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + LOGF(info, " Decay3body builder: basic configuration listing"); + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + + if (doprocessRealData) { + LOGF(info, " ===> process function enabled: processRealData"); + } + if (doprocessRealDataReduced) { + LOGF(info, " ===> process function enabled: processRealDataReduced"); + } + if (doprocessRealDataReduced3bodyMixing) { + LOGF(info, " ===> process function enabled: processRealDataReduced3bodyMixing"); + } + if (doprocessMonteCarlo) { + LOGF(info, " ===> process function enabled: processMonteCarlo"); + } + + // list enabled tables + for (int i = 0; i < nTables; i++) { + if (mEnabledTables[i]) { + LOGF(info, " -~> Table enabled: %s", tableNames[i]); + } + } + + // print base cuts + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + LOGF(info, "-~> max daughter eta ..............: %f", decay3bodyBuilderOpts.maxEtaDaughters.value); + LOGF(info, "-~> min TPC ncls proton ...........: %i", decay3bodyBuilderOpts.minTPCNClProton.value); + LOGF(info, "-~> min TPC ncls pion .............: %i", decay3bodyBuilderOpts.minTPCNClPion.value); + LOGF(info, "-~> min TPC ncls bach .............: %i", decay3bodyBuilderOpts.minTPCNClDeuteron.value); + LOGF(info, "-~> min DCA proton to PV ..........: %f", decay3bodyBuilderOpts.minDCAProtonToPV.value); + LOGF(info, "-~> min DCA pion to PV ............: %f", decay3bodyBuilderOpts.minDCAPionToPV.value); + LOGF(info, "-~> min DCA bach to PV ............: %f", decay3bodyBuilderOpts.minDCADeuteronToPV.value); + LOGF(info, "-~> min pT proton .................: %f", decay3bodyBuilderOpts.minPtProton.value); + LOGF(info, "-~> min pT pion ...................: %f", decay3bodyBuilderOpts.minPtPion.value); + LOGF(info, "-~> min pT bach ...................: %f", decay3bodyBuilderOpts.minPtDeuteron.value); + LOGF(info, "-~> max pT proton .................: %f", decay3bodyBuilderOpts.maxPtProton.value); + LOGF(info, "-~> max pT pion ...................: %f", decay3bodyBuilderOpts.maxPtPion.value); + LOGF(info, "-~> max pT bach ...................: %f", decay3bodyBuilderOpts.maxPtDeuteron.value); + LOGF(info, "-~> max TPC nSigma ...............: %f", decay3bodyBuilderOpts.maxTPCnSigma.value); + LOGF(info, "-~> min TOF nSigma deuteron ......: %f", decay3bodyBuilderOpts.minTOFnSigmaDeuteron.value); + LOGF(info, "-~> max TOF nSigma deuteron ......: %f", decay3bodyBuilderOpts.maxTOFnSigmaDeuteron.value); + LOGF(info, "-~> min p bach use TOF ...........: %f", decay3bodyBuilderOpts.minPDeuteronUseTOF.value); + LOGF(info, "-~> max DCA dau at SV ............: %f", decay3bodyBuilderOpts.maxDCADauToSVaverage.value); + LOGF(info, "-~> max rapidity .................: %f", decay3bodyBuilderOpts.maxRapidity.value); + LOGF(info, "-~> min pT .......................: %f", decay3bodyBuilderOpts.minPt.value); + LOGF(info, "-~> max pT .......................: %f", decay3bodyBuilderOpts.maxPt.value); + LOGF(info, "-~> min mass .....................: %f", decay3bodyBuilderOpts.minMass.value); + LOGF(info, "-~> max mass .....................: %f", decay3bodyBuilderOpts.maxMass.value); + LOGF(info, "-~> min ctau .....................: %f", decay3bodyBuilderOpts.minCtau.value); + LOGF(info, "-~> max ctau .....................: %f", decay3bodyBuilderOpts.maxCtau.value); + LOGF(info, "-~> min cosPA ....................: %f", decay3bodyBuilderOpts.minCosPA.value); + LOGF(info, "-~> max chi2 .....................: %f", decay3bodyBuilderOpts.maxChi2.value); + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + + // bookkeeping histograms + auto h = registry.add("Counters/hTableBuildingStatistics", "hTableBuildingStatistics", kTH1D, {{nTablesConst, -0.5f, static_cast(nTablesConst)}}); + auto h2 = registry.add("Counters/hInputStatistics", "hInputStatistics", kTH1D, {{nTablesConst, -0.5f, static_cast(nTablesConst)}}); + h2->SetTitle("Input table sizes"); + + // configure tables to generate + for (int i = 0; i < nTables; i++) { + h->GetXaxis()->SetBinLabel(i + 1, tableNames[i].c_str()); + h2->GetXaxis()->SetBinLabel(i + 1, tableNames[i].c_str()); + h->SetBinContent(i + 1, 0); // mark all as disabled to start + + int f = enabledTables->get(tableNames[i].c_str(), "enable"); + if (f == 1) { + mEnabledTables[i] = 1; + h->SetBinContent(i + 1, 1); // mark enabled + } + } + + if (mEnabledTables[kVtx3BodyDatas] && mEnabledTables[kMcVtx3BodyDatas]) { + LOG(fatal) << "Tables Vtx3BodyDatas and McVtx3BodyDatas cannot both be enabled at the same time. Choose one!"; } - if (doprocessRun3withKFParticleReduced3bodyMixing == true) { - auto h3bodyCombinationCounter = registry.add("QA/EM/h3bodyCombinationCounter", "h3bodyCombinationCounter", HistType::kTH1D, {{4, 0.0f, 4.0f}}); + // Add histograms separately for different process functions + if (doprocessRealData == true || doprocessMonteCarlo == true) { + auto hEventCounter = registry.add("Counters/hEventCounter", "hEventCounter", HistType::kTH1D, {{3, 0.0f, 3.0f}}); + hEventCounter->GetXaxis()->SetBinLabel(1, "total"); + hEventCounter->GetXaxis()->SetBinLabel(2, "sel8"); + hEventCounter->GetXaxis()->SetBinLabel(3, "vertexZ"); + hEventCounter->LabelsOption("v"); + } + + if (doprocessRealData == true || doprocessRealDataReduced == true || doprocessMonteCarlo == true) { + if (doTrackQA) { // histograms for all daughter tracks of (selected) 3body candidates + registry.add("QA/Tracks/hTrackProtonTPCNcls", "hTrackProtonTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); + registry.add("QA/Tracks/hTrackPionTPCNcls", "hTrackPionTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); + registry.add("QA/Tracks/hTrackDeuteronTPCNcls", "hTrackDeuteronTPCNcls", HistType::kTH1F, {{152, 0, 152, "# TPC clusters"}}); + registry.add("QA/Tracks/hTrackProtonHasTPC", "hTrackProtonHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); + registry.add("QA/Tracks/hTrackPionHasTPC", "hTrackPionHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); + registry.add("QA/Tracks/hTrackDeuteronHasTPC", "hTrackDeuteronHasTPC", HistType::kTH1F, {{2, -0.5, 1.5, "has TPC"}}); + registry.add("QA/Tracks/hTrackDeuteronITSClusSizes", "hTrackDeuteronITSClusSizes", HistType::kTH1F, {{10, 0., 10., "ITS cluster sizes"}}); + registry.add("QA/Tracks/hTrackProtonTPCPID", "hTrackProtonTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); + registry.add("QA/Tracks/hTrackPionTPCPID", "hTrackPionTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); + registry.add("QA/Tracks/hTrackDeuteronTPCPID", "hTrackDeuteronTPCPID", HistType::kTH2F, {{100, -10.0f, 10.0f, "p/z (GeV/c)"}, {100, -10.0f, 10.0f, "TPC n#sigma"}}); + registry.add("QA/Tracks/hTrackProtonPt", "hTrackProtonPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); + registry.add("QA/Tracks/hTrackPionPt", "hTrackPionPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); + registry.add("QA/Tracks/hTrackDeuteronPt", "hTrackDeuteronPt", HistType::kTH1F, {{100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}); + } + if (doVertexQA) { + registry.add("QA/Event/hAllSelEventsVtxZ", "hAllSelEventsVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); + registry.add("QA/Event/hVtxX", "hVtxX", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV X (cm)"}}); + registry.add("QA/Event/hVtxY", "hVtxY", HistType::kTH1F, {{500, -0.1f, 0.1f, "PV Y (cm)"}}); + registry.add("QA/Event/hVtxZ", "hVtxZ", HistType::kTH1F, {{500, -15.0f, 15.0f, "PV Z (cm)"}}); + registry.add("QA/Event/hVtxCovXX", "hVtxCovXX", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XX) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovYY", "hVtxCovYY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YY) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovZZ", "hVtxCovZZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(ZZ) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovXY", "hVtxCovXY", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XY) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovXZ", "hVtxCovXZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(XZ) (cm^{2})"}}); + registry.add("QA/Event/hVtxCovYZ", "hVtxCovYZ", HistType::kTH1F, {{200, -0.0001f, 0.0001f, "PV cov(YZ) (cm^{2})"}}); + } + } + + if (doprocessRealDataReduced3bodyMixing == true) { + auto h3bodyCombinationCounter = registry.add("Mixing/h3bodyCombinationCounter", "h3bodyCombinationCounter", HistType::kTH1D, {{4, 0.0f, 4.0f}}); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(1, "total"); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(2, "not same collision"); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(3, "collision VtxZ"); h3bodyCombinationCounter->GetXaxis()->SetBinLabel(4, "bach sign/ID"); h3bodyCombinationCounter->LabelsOption("v"); - // registry.add("QA/EM/h3bodyBinCounts", "h3bodyBinCounts", HistType::kTH3D, {{16, 0, 16, "bins radius"}, {36, 0, 36, "bins phi"}, {12, 0, 12, "bins pos Z"}}); - registry.add("QA/EM/h3bodyBinCounts", "h3bodyBinCounts", HistType::kTH2D, {{16, 0, 16, "bins radius"}, {18, 0, 18, "bins phi"}}); - - AxisSpec radiusAxis = {kfparticleConfigurations.bins3BodyRadius, "Radius (cm)"}; - AxisSpec phiAxis = {kfparticleConfigurations.bins3BodyPhi, "#phi (degree)"}; - AxisSpec posZAxis = {kfparticleConfigurations.bins3BodyPosZ, "position in z (cm)"}; - - registry.add("QA/EM/hRadius", "hRadius", HistType::kTH1F, {radiusAxis}); - registry.add("QA/EM/hPhi", "hPhi", HistType::kTH1F, {phiAxis}); - registry.add("QA/EM/hPosZ", "hPosZ", HistType::kTH1F, {posZAxis}); + registry.add("Mixing/hDecay3BodyRadiusPhi", "hDecay3BodyRadiusPhi", HistType::kTH2F, {mixingOpts.bins3BodyRadius, mixingOpts.bins3BodyPhi}); + registry.add("Mixing/hDecay3BodyPosZ", "hDecay3BodyPosZ", HistType::kTH1F, {mixingOpts.bins3BodyPosZ}); } } - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + template + bool initCCDB(aod::BCsWithTimestamps const& bcs, TCollisions const& collisions) { - if (mRunNumber == bc.runNumber()) { - return; + auto bc = collisions.size() ? collisions.begin().template bc_as() : bcs.begin(); + if (!bcs.size()) { + LOGF(warn, "No BC found, skipping this DF."); + return false; // signal to skip this DF } - if (kfparticleConfigurations.cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), kfparticleConfigurations.triggerList); - zorro.populateHistRegistry(registry, bc.runNumber()); + + if (mRunNumber == bc.runNumber()) { + return true; } - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - fitterV0.setBz(d_bz); - fitter3body.setBz(d_bz); -#ifdef HomogeneousField - KFParticle::SetField(d_bz); -#endif - 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 = bc.runNumber(); - return; + if (doSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); + zorro.populateHistRegistry(registry, bc.runNumber()); } - auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); + auto timestamp = bc.timestamp(); o2::parameters::GRPMagField* grpmag = 0x0; - 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); - d_bz = o2::base::Propagator::Instance()->getNominalBz(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = bc.runNumber(); - // Set magnetic field value once known - fitterV0.setBz(d_bz); - fitter3body.setBz(d_bz); + grpmag = ccdb->getForTimeStamp(ccdbConfigurations.grpmagPath, timestamp); + if (!grpmag) { + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField for timestamp " << timestamp; + } + o2::base::Propagator::initFieldFromGRP(grpmag); + // Fetch magnetic field from ccdb for current collision + auto d_bz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << d_bz << " kG"; + + // set magnetic field value for DCA fitter + helper.fitterV0.setBz(d_bz); + helper.fitter3body.setBz(d_bz); // Set magnetic field for KF vertexing #ifdef HomogeneousField KFParticle::SetField(d_bz); @@ -657,1853 +519,813 @@ struct decay3bodyBuilder { if (useMatCorrType == 2) { // setMatLUT only after magfield has been initalized // (setMatLUT has implicit and problematic init field call if not) + LOG(info) << "Loading material look-up table for timestamp: " << timestamp; + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->getForTimeStamp(ccdbConfigurations.lutPath, timestamp)); o2::base::Propagator::Instance()->setMatLUT(lut); } - // Initial TOF PID Paras, copied from PIDTOF.h - timestamp.value = bc.timestamp(); - ccdb->setTimestamp(timestamp.value); - // Not later than now objects - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - // TODO: implement the automatic pass name detection from metadata - if (passName.value == "") { - passName.value = "unanchored"; // temporary default - LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; - } - LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; - - const std::string fname = paramFileName.value; - if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; - if (1) { - o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, parametrizationPath.value); - LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { - mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } else { - mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); - } - } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); - paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { // Attempt at loading the parameters with the pass defined - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { // Pass is available, load non standard parameters - mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } - mRespParamsV2.print(); - if (timeShiftCCDBPath.value != "") { - if (timeShiftCCDBPath.value.find(".root") != std::string::npos) { - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); - } else { - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); - } - } + // mark run as configured + mRunNumber = bc.runNumber(); + + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, bc); - bachelorTOFPID.SetParams(mRespParamsV2); + return true; } - void initCCDBfromRunNumber(int runNumber) + float getMagFieldFromRunNumber(int runNumber) { - // set magnetic field only when run number changes - if (mRunNumber == runNumber) { - LOG(debug) << "CCDB initialized for run " << mRunNumber; - return; - } - mRunNumber = runNumber; // Update the last run number - + float magField; // Check if the CCDB data for this run is already cached if (ccdbCache.find(runNumber) != ccdbCache.end()) { LOG(debug) << "CCDB data already cached for run " << runNumber; - d_bz = ccdbCache[runNumber]; - if (doUpdateGRPMagField == true) { - o2::base::Propagator::initFieldFromGRP(grpMagCache[runNumber].get()); - } + magField = ccdbCache[runNumber]; + // if not, retrieve it from CCDB } else { - std::shared_ptr grpmag = std::make_shared(*ccdb->getForRun(grpmagPath, runNumber)); + std::shared_ptr grpmag = std::make_shared(*ccdb->getForRun(ccdbConfigurations.grpmagPath, runNumber)); if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for run number " << runNumber; + LOG(fatal) << "Got nullptr from CCDB for path " << ccdbConfigurations.grpmagPath << " of object GRPMagField and " << ccdbConfigurations.grpPath << " of object GRPObject for run number " << runNumber; } o2::base::Propagator::initFieldFromGRP(grpmag.get()); // Fetch magnetic field from ccdb for current collision - d_bz = o2::base::Propagator::Instance()->getNominalBz(); + magField = o2::base::Propagator::Instance()->getNominalBz(); LOG(info) << "Retrieved GRP for run number " << runNumber << " with magnetic field of " << d_bz << " kZG"; - ccdbCache[runNumber] = d_bz; - grpMagCache[runNumber] = grpmag; + // cache magnetic field info + ccdbCache[runNumber] = magField; + } + return magField; + } + + void initFittersWithMagField(int runNumber, float magField) + { + // set magnetic field only when run number changes + if (mRunNumber == runNumber) { + LOG(debug) << "CCDB initialized for run " << mRunNumber; + return; } + mRunNumber = runNumber; // Update the last run number + + // update propagator + o2::base::Propagator::Instance()->setNominalBz(magField); // Set magnetic field for KF vertexing #ifdef HomogeneousField - KFParticle::SetField(d_bz); + KFParticle::SetField(magField); #endif // Set field for DCAfitter - fitterV0.setBz(d_bz); - fitter3body.setBz(d_bz); - - mV0Hyps[0].set(o2::track::PID::Lambda, o2::track::PID::Proton, o2::track::PID::Pion, pidCutsLambda, d_bz); - mV0Hyps[1].set(o2::track::PID::Lambda, o2::track::PID::Pion, o2::track::PID::Proton, pidCutsLambda, d_bz); + helper.fitterV0.setBz(magField); + helper.fitter3body.setBz(magField); if (useMatCorrType == 2) { - // setMatLUT only after magfield has been initalized + // setMatLUT only after magfield has been initalized (setMatLUT has implicit and problematic init field call if not) o2::base::Propagator::Instance()->setMatLUT(lut); } - - // cache magnetic field info - ccdbCache[runNumber] = d_bz; } - //------------------------------------------------------------------ - //-------------------- DCA fitter reconstruction ------------------- - //------------------------------------------------------------------ - // Select decay3body candidate based on daughter track PID - template - bool checkPID(TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackBachelor, const double& tofNSigmaBach) - { - if ((tofNSigmaBach < TofPidNsigmaMin || tofNSigmaBach > TofPidNsigmaMax) && trackBachelor.p() > minBachPUseTOF) { - return false; - } - if (std::abs(trackProton.tpcNSigmaPr()) > TpcPidNsigmaCut) { - return false; - } - if (std::abs(trackPion.tpcNSigmaPi()) > TpcPidNsigmaCut) { - return false; - } - return true; - } - // PID check for H3L - template - bool checkPIDH3L(TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackBachelor, const double& tofNSigmaBach) + // ______________________________________________________________ + // function to build decay3body candidates + template + void buildCandidates(TBCs const&, + TCollisions const& collisions, + T3Bodys const& decay3bodys, + TMCParticles const& mcParticles, + TMCCollisions const& mcCollisions) { - if ((std::abs(trackBachelor.tpcNSigmaDe()) > TpcPidNsigmaCut) || !checkPID(trackProton, trackPion, trackBachelor, tofNSigmaBach)) { - return false; + if (!(mEnabledTables[kVtx3BodyDatas] || mEnabledTables[kMcVtx3BodyDatas])) { + LOG(info) << "No request for candidate analysis table in place, skipping candidate building." << std::endl; + return; // don't do if no request for decay3bodys in place } - return true; - } - //------------------------------------------------------------------ - // 3body candidate builder - template - void fillVtxCand(TCollisionTable const& collision, TTrackTable const& t0, TTrackTable const& t1, TTrackTable const& t2, int64_t decay3bodyId, int bachelorcharge = 1, double tofNSigmaBach = -999, bool saveInTable = true) - { - registry.fill(HIST("hVtx3BodyCounter"), kVtxAll); + // prepare MC container (not necessarily used) + std::vector mcParticleIsReco; - if (t0.tpcNClsFound() < mintpcNCls || t1.tpcNClsFound() < mintpcNCls || t2.tpcNClsFound() < mintpcNCls) { - return; + if constexpr (soa::is_table) { + isTriggeredCollision.clear(); + isTriggeredCollision.resize(collisions.size(), false); } - registry.fill(HIST("hVtx3BodyCounter"), kVtxTPCNcls); - - if (enablePidCut) { - if (t2.sign() > 0) { - if (!checkPIDH3L(t0, t1, t2, tofNSigmaBach)) - return; - } else { - if (!checkPIDH3L(t1, t0, t2, tofNSigmaBach)) - return; - } + // clear and reserve size for MC info vectors + if constexpr (soa::is_table) { + isGoodCollision.clear(); + mcParticleIsReco.clear(); + isGoodCollision.resize(mcCollisions.size(), false); + mcParticleIsReco.resize(mcParticles.size(), false); } - registry.fill(HIST("hVtx3BodyCounter"), kVtxPIDCut); - - // Calculate DCA with respect to the collision associated to the V0, not individual tracks - std::array dcaInfo; - - auto Track0Par = getTrackPar(t0); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track0Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track0dcaXY = dcaInfo[0]; - auto Track0dca = std::sqrt(Track0dcaXY * Track0dcaXY + dcaInfo[1] * dcaInfo[1]); - - auto Track1Par = getTrackPar(t1); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track1Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track1dcaXY = dcaInfo[0]; - auto Track1dca = std::sqrt(Track1dcaXY * Track1dcaXY + dcaInfo[1] * dcaInfo[1]); - - auto Track2Par = getTrackPar(t2); - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, Track2Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track2dcaXY = dcaInfo[0]; - auto Track2dca = std::sqrt(Track2dcaXY * Track2dcaXY + dcaInfo[1] * dcaInfo[1]); + // Loop over collisions for vertex QA + for (const auto& collision : collisions) { + if constexpr (soa::is_table) { // only do if NOT running over reduced data (already done in reducedCreator) + // Zorro event counting + bool isZorroSelected = false; + if (doSkimmedProcessing) { + isZorroSelected = zorro.isSelected(collision.template bc_as().globalBC()); + if (!isZorroSelected && onlyKeepInterestedTrigger) { + continue; + } + } - auto Track0 = getTrackParCov(t0); - auto Track1 = getTrackParCov(t1); - auto Track2 = getTrackParCov(t2); - int n3bodyVtx = fitter3body.process(Track0, Track1, Track2); - if (n3bodyVtx == 0) { // discard this pair - return; - } - registry.fill(HIST("hVtx3BodyCounter"), kVtxhasSV); + isTriggeredCollision[collision.globalIndex()] = true; + // event counting + registry.fill(HIST("Counters/hEventCounter"), 0.5); + if (doSel8selection && !collision.sel8()) { + continue; + } + registry.fill(HIST("Counters/hEventCounter"), 1.5); + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { + continue; + } + registry.fill(HIST("Counters/hEventCounter"), 2.5); + } + + // vertex QA and counting + if (doVertexQA) { + registry.fill(HIST("QA/Event/hAllSelEventsVtxZ"), collision.posZ()); + registry.fill(HIST("QA/Event/hVtxX"), collision.posX()); + registry.fill(HIST("QA/Event/hVtxY"), collision.posY()); + registry.fill(HIST("QA/Event/hVtxZ"), collision.posZ()); + registry.fill(HIST("QA/Event/hVtxCovXX"), collision.covXX()); + registry.fill(HIST("QA/Event/hVtxCovYY"), collision.covYY()); + registry.fill(HIST("QA/Event/hVtxCovZZ"), collision.covZZ()); + registry.fill(HIST("QA/Event/hVtxCovXY"), collision.covXY()); + registry.fill(HIST("QA/Event/hVtxCovXZ"), collision.covXZ()); + registry.fill(HIST("QA/Event/hVtxCovYZ"), collision.covYZ()); + } + + // In case of MC: reco collision survived event selection filter --> fill value for MC collision if collision is "true" MC collision + if constexpr (soa::is_table) { + if (collision.mcCollisionId() >= 0) { + isGoodCollision[collision.mcCollisionId()] = true; + } + } + } // loop over collisions - std::array pos = {0.}; - const auto& vtxXYZ = fitter3body.getPCACandidate(); - for (int i = 0; i < 3; i++) { - pos[i] = vtxXYZ[i]; - } + // Loop over all decay3bodys in same time frame + registry.fill(HIST("Counters/hInputStatistics"), kVtx3BodyDatas, decay3bodys.size()); + int lastRunNumber = -1; + for (const auto& decay3body : decay3bodys) { + // only build tracked decay3body if aksed + if (decay3bodyBuilderOpts.buildOnlyTracked && fTrackedClSizeVector[decay3body.globalIndex()] == 0) { + continue; + } - std::array p0 = {0.}, p1 = {0.}, p2{0.}; - const auto& propagatedTrack0 = fitter3body.getTrack(0); - const auto& propagatedTrack1 = fitter3body.getTrack(1); - const auto& propagatedTrack2 = fitter3body.getTrack(2); - propagatedTrack0.getPxPyPzGlo(p0); - propagatedTrack1.getPxPyPzGlo(p1); - propagatedTrack2.getPxPyPzGlo(p2); - for (int i = 0; i < 3; i++) { - p2[i] *= bachelorcharge; - } - std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; + // skip decay3body without assigned collision + /// TODO: do we want this?? + if (decay3body.collisionId() < 0) { + continue; + } - if (fitter3body.getChi2AtPCACandidate() > dcavtxdau) { - return; - } - registry.fill(HIST("hVtx3BodyCounter"), kVtxDcaDau); + // aquire collision + auto const& collision = collisions.rawIteratorAt(decay3body.collisionId()); - float VtxcosPA = RecoDecay::cpa(std::array{collision.posX(), collision.posY(), collision.posZ()}, std::array{pos[0], pos[1], pos[2]}, std::array{p3B[0], p3B[1], p3B[2]}); - if (VtxcosPA < minCosPA3body) { - return; - } - registry.fill(HIST("hVtx3BodyCounter"), kVtxCosPA); - registry.fill(HIST("hBachelorTOFNSigmaDe"), t2.sign() * t2.p(), tofNSigmaBach); - - // additional cut for EM - if (decay3bodyId == -1) { - registry.fill(HIST("h3bodyEMCutCounter"), 0.5); - auto v0Track0 = getTrackParCov(t0); - auto v0Track1 = getTrackParCov(t1); - int nV0 = fitterV0.process(v0Track0, v0Track1); - if (nV0 == 0) { - return; + // initialise CCDB from run number saved in reduced collisions table when running over reduced data + if constexpr (!soa::is_table) { // only do if running over reduced data (otherwise CCDB is initialised in process function) + if (collision.runNumber() != lastRunNumber) { + initFittersWithMagField(collision.runNumber(), getMagFieldFromRunNumber(collision.runNumber())); + lastRunNumber = collision.runNumber(); // Update the last run number + LOG(debug) << "CCDB initialized for run " << lastRunNumber; + } } - registry.fill(HIST("h3bodyEMCutCounter"), 1.5); - std::array v0pos = {0.}; - const auto& v0vtxXYZ = fitterV0.getPCACandidate(); - for (int i = 0; i < 3; i++) { - v0pos[i] = v0vtxXYZ[i]; - } - const int cand = 0; - if (!fitterV0.isPropagateTracksToVertexDone(cand) && !fitterV0.propagateTracksToVertex(cand)) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 2.5); - - const auto& trPProp = fitterV0.getTrack(0, cand); - const auto& trNProp = fitterV0.getTrack(1, cand); - std::array pP{}, pN{}; - trPProp.getPxPyPzGlo(pP); - trNProp.getPxPyPzGlo(pN); - std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; - // Cut for Virtual V0 - float dxv0 = v0pos[0] - mMeanVertex.getX(), dyv0 = v0pos[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; - float rv0 = std::sqrt(r2v0); - float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; - if (dcaFitterEMSel.cfgApplyV0Cut && pt2V0 <= dcaFitterEMSel.mMinPt2V0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 3.5); - if (dcaFitterEMSel.cfgApplyV0Cut && pV0[2] * pV0[2] / pt2V0 > dcaFitterEMSel.mMaxTgl2V0) { // tgLambda cut - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 4.5); - - float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); - // apply mass selections - float p2Pos = pP[0] * pP[0] + pP[1] * pP[1] + pP[2] * pP[2], p2Neg = pN[0] * pN[0] + pN[1] * pN[1] + pN[2] * pN[2]; - bool good3bodyV0Hyp = false; - for (int ipid = 0; ipid < 2; ipid++) { - float massForLambdaHyp = mV0Hyps[ipid].calcMass(p2Pos, p2Neg, p2V0); - if (massForLambdaHyp - mV0Hyps[ipid].getMassV0Hyp() < mV0Hyps[ipid].getMargin(ptV0)) { - good3bodyV0Hyp = true; - break; + // event selection + if constexpr (soa::is_table) { // only when NOT running over reduced data + if (doSel8selection && !collision.sel8()) { + continue; + } + if (onlyKeepInterestedTrigger && !isTriggeredCollision[collision.globalIndex()]) { + continue; } } - if (dcaFitterEMSel.cfgApplyV0Cut && !good3bodyV0Hyp) { - return; + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { + continue; } - registry.fill(HIST("h3bodyEMCutCounter"), 5.5); - float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; - float cosPAXY = prodXYv0 / rv0 * ptV0; - if (dcaFitterEMSel.cfgApplyV0Cut && dca2 > dcaFitterEMSel.mMaxDCAXY2ToMeanVertex3bodyV0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 6.5); - // FIXME: V0 cosPA cut to be investigated - if (dcaFitterEMSel.cfgApplyV0Cut && cosPAXY < dcaFitterEMSel.minCosPAXYMeanVertex3bodyV0) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 7.5); - // Check: CosPA Cut of Virtual V0 may not be used since the V0 may be based on another PV - float dx = v0pos[0] - collision.posX(), dy = v0pos[1] - collision.posY(), dz = v0pos[2] - collision.posZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; - float v0CosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); - if (dcaFitterEMSel.cfgApplyV0Cut && v0CosPA < dcaFitterEMSel.minCosPA3bodyV0) { - return; + // aquire tracks + auto trackPos = decay3body.template track0_as(); + auto trackNeg = decay3body.template track1_as(); + auto trackDeuteron = decay3body.template track2_as(); + int protonSign = doLikeSign ? -trackDeuteron.sign() : trackDeuteron.sign(); + auto trackProton = protonSign > 0 ? trackPos : trackNeg; + auto trackPion = protonSign > 0 ? trackNeg : trackPos; + + // get deuteron TOF PID + float tofNSigmaDeuteron; + if constexpr (!soa::is_table) { // running over derived data + tofNSigmaDeuteron = trackDeuteron.tofNSigmaDe(); + } else if constexpr (soa::is_table) { // running over AO2Ds + if constexpr (soa::is_table) { // running over MC (track table with labels) + tofNSigmaDeuteron = getTOFnSigma(mRespParamsV3, collision, trackDeuteron); + } else { // running over real data + tofNSigmaDeuteron = getTOFnSigma(mRespParamsV3, collision, trackDeuteron); + } } - registry.fill(HIST("h3bodyEMCutCounter"), 8.5); - float r3body = std::hypot(pos[0], pos[1]); - if (r3body < 0.5) { - return; + /// build Decay3body candidate + if (!helper.buildDecay3BodyCandidate(collision, + trackProton, + trackPion, + trackDeuteron, + decay3body.globalIndex(), + tofNSigmaDeuteron, + fTrackedClSizeVector[decay3body.globalIndex()], + decay3bodyBuilderOpts.useKFParticle, + decay3bodyBuilderOpts.kfSetTopologicalConstraint, + decay3bodyBuilderOpts.useSelections, + decay3bodyBuilderOpts.useChi2Selection, + decay3bodyBuilderOpts.useTPCforPion, + decay3bodyBuilderOpts.acceptTPCOnly, + decay3bodyBuilderOpts.askOnlyITSMatch, + decay3bodyBuilderOpts.calculateCovariance, + false /*isEventMixing*/)) { + continue; } - registry.fill(HIST("h3bodyEMCutCounter"), 9.5); - // Cut for the compatibility of V0 and 3body vertex - float deltaR = std::abs(rv0 - r3body); - if (deltaR > dcaFitterEMSel.maxRDiffV03body) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 10.5); + // fill QA histograms + if (doTrackQA) { // histograms filled for daughter tracks of (selected) 3body candidates + registry.fill(HIST("QA/Tracks/hTrackProtonTPCNcls"), trackProton.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackPionTPCNcls"), trackPion.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronTPCNcls"), trackDeuteron.tpcNClsFound()); + registry.fill(HIST("QA/Tracks/hTrackProtonHasTPC"), trackProton.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackPionHasTPC"), trackPion.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronHasTPC"), trackDeuteron.hasTPC()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronITSClusSizes"), trackDeuteron.itsClusterSizes()); + registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackProton.sign() * trackProton.tpcInnerParam(), trackProton.tpcNSigmaPr()); + registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackPion.sign() * trackPion.tpcInnerParam(), trackPion.tpcNSigmaPi()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronTPCPID"), trackDeuteron.sign() * trackDeuteron.tpcInnerParam(), trackDeuteron.tpcNSigmaDe()); + registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackProton.pt()); + registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackPion.pt()); + registry.fill(HIST("QA/Tracks/hTrackDeuteronPt"), trackDeuteron.pt()); + } + + // generate analysis tables with current candidate (only Vtx3BodyDatas is filled here, McVtx3BodyDatas table is filled later) + if (!mEnabledTables[kMcVtx3BodyDatas]) { + fillAnalysisTables(); + } + + // ___________________________________________________________ + // MC handling part: matching of reconstructed candidates + // ___________________________________________________________ + // fill MC table with reco MC candidate information and gen information if matched to MC particle + if constexpr (soa::is_table) { + // MC info + resetMCInfo(this3BodyMCInfo); + this3BodyMCInfo.isReco = true; + + // check if daughters have MC particle + if (!trackProton.has_mcParticle() || !trackPion.has_mcParticle() || !trackDeuteron.has_mcParticle()) { + continue; + } - float pt3B = std::hypot(p3B[0], p3B[1]); - if (pt3B < dcaFitterEMSel.minPt3Body) { // pt cut - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 11.5); - if (p3B[2] / pt3B > dcaFitterEMSel.maxTgl3Body) { // tgLambda cut - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 12.5); - - // H3L DCA Check - const auto& vertexXYZ = fitter3body.getPCACandidatePos(); - auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, t2.sign()); - o2::dataformats::DCA dca; - if (!track3B.propagateToDCA({{collision.posX(), collision.posY(), collision.posZ()}, {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}}, fitter3body.getBz(), &dca, 5.) || - std::abs(dca.getY()) > dcaFitterEMSel.maxDCAXY3Body || std::abs(dca.getZ()) > dcaFitterEMSel.maxDCAZ3Body) { - return; - } - registry.fill(HIST("h3bodyEMCutCounter"), 13.5); - } + // 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; + } - VtxCandidate candVtx; - candVtx.track0Id = t0.globalIndex(); - candVtx.track1Id = t1.globalIndex(); - candVtx.track2Id = t2.globalIndex(); - candVtx.collisionId = collision.globalIndex(); - candVtx.decay3bodyId = decay3bodyId; - candVtx.vtxPos[0] = pos[0]; - candVtx.vtxPos[1] = pos[1]; - candVtx.vtxPos[2] = pos[2]; - candVtx.track0P[0] = p0[0]; - candVtx.track0P[1] = p0[1]; - candVtx.track0P[2] = p0[2]; - candVtx.track1P[0] = p1[0]; - candVtx.track1P[1] = p1[1]; - candVtx.track1P[2] = p1[2]; - candVtx.track2P[0] = p2[0]; - candVtx.track2P[1] = p2[1]; - candVtx.track2P[2] = p2[2]; - candVtx.dcadaughters = fitter3body.getChi2AtPCACandidate(); - candVtx.daudcaxytopv[0] = Track0dcaXY; - candVtx.daudcaxytopv[1] = Track1dcaXY; - candVtx.daudcaxytopv[2] = Track2dcaXY; - candVtx.daudcatopv[0] = Track0dca; - candVtx.daudcatopv[1] = Track1dca; - candVtx.daudcatopv[2] = Track2dca; - candVtx.bachelortofNsigma = tofNSigmaBach; - if (saveInTable) { - fillVtx3BodyTable(candVtx); - } else { - VtxCandidates.push_back(candVtx); - } + // fill analysis tables (only McVtx3BodyDatas is filled here) + fillAnalysisTables(); + + // mark mcParticle as reconstructed + if (this3BodyMCInfo.label > -1) { + mcParticleIsReco[this3BodyMCInfo.label] = true; + } + } // constexpr requires mcParticles check + } // decay3body loop + + // ____________________________________________________________________ + // MC handling part: generated information of non-reco candidates + // ____________________________________________________________________ + if constexpr (soa::is_table) { + for (const auto& mcparticle : mcParticles) { + // MC info + resetMCInfo(this3BodyMCInfo); + + // skip MC particle if reconstructed and already filled previously + if (mcParticleIsReco[mcparticle.globalIndex()] == true) { + continue; + } + this3BodyMCInfo.isReco = false; + + // set flag if corresponding MC collision has matched reconstructed collision which passed event selection + this3BodyMCInfo.survivedEventSel = isGoodCollision[mcparticle.mcCollisionId()]; + + // check if MC particle is hypertriton + if (std::abs(mcparticle.pdgCode()) != o2::constants::physics::Pdg::kHyperTriton) { + continue; + } + + // check daughter identities + bool haveProton = false, havePion = false, haveDeuteron = false; + bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; + for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { + if (mcparticleDaughter.pdgCode() == PDG_t::kProton) + haveProton = true; + if (mcparticleDaughter.pdgCode() == PDG_t::kProtonBar) + haveAntiProton = true; + if (mcparticleDaughter.pdgCode() == PDG_t::kPiPlus) + havePion = true; + if (mcparticleDaughter.pdgCode() == PDG_t::kPiMinus) + haveAntiPion = true; + if (mcparticleDaughter.pdgCode() == o2::constants::physics::Pdg::kDeuteron) + haveDeuteron = true; + if (mcparticleDaughter.pdgCode() == -o2::constants::physics::Pdg::kDeuteron) + haveAntiDeuteron = true; + } + + // check if hypertriton decayed via 3-body decay and is particle or anti-particle + if ((haveProton && haveAntiPion && haveDeuteron && !(haveAntiProton || havePion || haveAntiDeuteron)) || (haveAntiProton && havePion && haveAntiDeuteron && !(haveProton || haveAntiPion || haveDeuteron))) { + if (mcparticle.pdgCode() > 0) { + this3BodyMCInfo.isTrueH3L = true; + } else if (mcparticle.pdgCode() < 0) { + this3BodyMCInfo.isTrueAntiH3L = true; + } + // get daughters + for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { + if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kProton) { // proton + this3BodyMCInfo.genMomProton = mcparticleDaughter.p(); + this3BodyMCInfo.genPtProton = mcparticleDaughter.pt(); + this3BodyMCInfo.daughterPrPdgCode = mcparticleDaughter.pdgCode(); + this3BodyMCInfo.genDecVtx = {mcparticleDaughter.vx(), mcparticleDaughter.vy(), mcparticleDaughter.vz()}; + } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kPiPlus) { // pion + this3BodyMCInfo.genMomPion = mcparticleDaughter.p(); + this3BodyMCInfo.genPtPion = mcparticleDaughter.pt(); + this3BodyMCInfo.daughterPiPdgCode = mcparticleDaughter.pdgCode(); + } else if (std::abs(mcparticleDaughter.pdgCode()) == o2::constants::physics::Pdg::kDeuteron) { // deuteron + this3BodyMCInfo.genMomDeuteron = mcparticleDaughter.p(); + this3BodyMCInfo.genPtDeuteron = mcparticleDaughter.pt(); + this3BodyMCInfo.daughterDePdgCode = mcparticleDaughter.pdgCode(); + this3BodyMCInfo.isDeuteronPrimary = mcparticleDaughter.isPhysicalPrimary(); + } + } + } else { + continue; // stop if particle is not decayed via 3-body decay + } + + // calculate ctau + this3BodyMCInfo.genCt = RecoDecay::sqrtSumOfSquares(this3BodyMCInfo.genDecVtx[0] - mcparticle.vx(), this3BodyMCInfo.genDecVtx[1] - mcparticle.vy(), this3BodyMCInfo.genDecVtx[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); + + // fill MCDecay3BodyCores table if requested + if (mEnabledTables[kMcVtx3BodyDatas]) { + products.mcvtx3bodydatas(-1, // sign + -1., -1., // mass, massV0 + -1., -1., -1., // position + -1., -1., -1., // momentum + -1., // chi2 + -1., // trackedClSize + -1., -1., -1., // momProton + -1., -1., -1., // momPion + -1., -1., -1., // momDeuteron + -1., -1., -1., // trackDCAxyToPV: 0 - proton, 1 - pion, 2 - deuteron + -1., -1., -1., // trackDCAzToPV: 0 - proton, 1 - pion, 2 - deuteron + -1., -1., -1., // daughterDCAtoSV: 0 - proton, 1 - pion, 2 - deuteron + -1., // daughterDCAtoSVaverage + -1., -1., // cosPA, ctau + -1., -1., -1., -1., // tpcNsigma: 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + -1., // tofNsigmaDeuteron + -1., -1., -1., // average ITS cluster sizes: proton, pion, deuteron + -1., -1., -1., // TPCNCl: proton, pion, deuteron + -1., // pidForTrackingDeuteron + // MC information + mcparticle.px(), mcparticle.py(), mcparticle.pz(), + this3BodyMCInfo.genDecVtx[0], this3BodyMCInfo.genDecVtx[1], this3BodyMCInfo.genDecVtx[2], + this3BodyMCInfo.genCt, + mcparticle.phi(), mcparticle.eta(), mcparticle.y(), + this3BodyMCInfo.genMomProton, this3BodyMCInfo.genMomPion, this3BodyMCInfo.genMomDeuteron, + this3BodyMCInfo.genPtProton, this3BodyMCInfo.genPtPion, this3BodyMCInfo.genPtDeuteron, + this3BodyMCInfo.isTrueH3L, this3BodyMCInfo.isTrueAntiH3L, + this3BodyMCInfo.isReco, + mcparticle.pdgCode(), + this3BodyMCInfo.daughterPrPdgCode, this3BodyMCInfo.daughterPiPdgCode, this3BodyMCInfo.daughterDePdgCode, + this3BodyMCInfo.isDeuteronPrimary, + this3BodyMCInfo.survivedEventSel); + } // enabled table check + } // mcParticles loop + } // constexpr requires mcParticles check } - //------------------------------------------------------------------ - // event mixing - template - void doMixed3Body(TMixed3bodys decay3bodys, TBinningType binningType) + + // ______________________________________________________________ + // function to build mixed decay3body candidates + template + void buildMixedCandidates(TRedDecay3Bodys const& decay3bodys, TBinningType const& binningType) { + if (!mEnabledTables[kVtx3BodyDatas]) { + return; // don't do if no request for decay3bodys in place + } + // Strictly upper index policy for decay3body objects binned by radius, phi - for (const auto& [decay3body0, decay3body1] : selfCombinations(binningType, dcaFitterEMSel.nUseMixed, -1, decay3bodys, decay3bodys)) { - auto tpos0 = decay3body0.template track0_as(); - auto tneg0 = decay3body0.template track1_as(); - auto tbach0 = decay3body0.template track2_as(); - auto tpos1 = decay3body1.template track0_as(); - auto tneg1 = decay3body1.template track1_as(); - auto tbach1 = decay3body1.template track2_as(); - - registry.fill(HIST("h3bodyCombinationCounter"), 0.5); - - // ---------- selections ---------- - if ((tbach0.sign() > 0 && !(tbach1.sign() > 0)) || (tbach0.sign() < 0 && !(tbach1.sign() < 0)) || tbach0.globalIndex() == tbach1.globalIndex()) { // only combine if tbach1 has correct sign and is not same as tbach0 + for (const auto& [decay3body0, decay3body1] : selfPairCombinations(binningType, mixingOpts.n3bodyMixing, -1, decay3bodys)) { + auto trackPos0 = decay3body0.template track0_as(); + auto trackNeg0 = decay3body0.template track1_as(); + auto trackDeuteron0 = decay3body0.template track2_as(); + auto trackPos1 = decay3body1.template track0_as(); + auto trackNeg1 = decay3body1.template track1_as(); + auto trackDeuteron1 = decay3body1.template track2_as(); + + // assign tracks + auto trackProton0 = trackPos0; + auto trackPion0 = trackNeg0; + auto trackProton1 = trackPos1; + auto trackPion1 = trackNeg1; + if (trackDeuteron0.sign() < 0) { + trackProton0 = trackNeg0; + trackPion0 = trackPos0; + } + if (trackDeuteron1.sign() < 0) { + trackProton1 = trackNeg1; + trackPion1 = trackPos1; + } + + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 0.5); + + // only combine if from different event + if (decay3body0.collisionId() == decay3body1.collisionId()) { continue; } - registry.fill(HIST("h3bodyCombinationCounter"), 1.5); + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 1.5); + + // collision vertex selection + auto collision0 = decay3body0.template collision_as(); + auto collision1 = decay3body1.template collision_as(); - if (decay3body0.collisionId() == decay3body1.collisionId()) { // only combine if from different event + // get b_z value for each collision (from CCDB or cache) and cache it for that run number + float magFieldCol0 = getMagFieldFromRunNumber(collision0.runNumber()); + float magFieldCol1 = getMagFieldFromRunNumber(collision1.runNumber()); + + // only combine if collision similar in VtxZ + if (mixingOpts.selectPVPosZ3bodyMixing && std::abs(collision0.posZ() - collision1.posZ()) > mixingOpts.maxDeltaPVPosZ3bodyMixing) { continue; } - registry.fill(HIST("h3bodyCombinationCounter"), 2.5); + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 2.5); - auto c0 = decay3body0.template collision_as(); - auto c1 = decay3body1.template collision_as(); + // Charge selections + // same magnetic fields --> mix matter with matter + if ((magFieldCol0 / std::abs(magFieldCol0)) == (magFieldCol1 / std::abs(magFieldCol1))) { + if (trackDeuteron0.sign() != trackDeuteron1.sign()) { + continue; + } + } + // opposite magnetic fields --> mix matter with anti-matter + if ((magFieldCol0 / std::abs(magFieldCol0)) != (magFieldCol1 / std::abs(magFieldCol1))) { + if (trackDeuteron0.sign() == trackDeuteron1.sign()) { + continue; + } + } - if (dcaFitterEMSel.selectPVPosZ3bodyMixing && std::abs(c0.posZ() - c1.posZ()) > dcaFitterEMSel.maxDeltaPVPosZ3bodyMixing) { // only combine if collision similar in PV posZ + // don't mix 3body with itself + if ((trackDeuteron0.globalIndex() == trackDeuteron1.globalIndex()) || (trackProton0.globalIndex() == trackProton1.globalIndex()) || (trackPion0.globalIndex() == trackPion1.globalIndex())) { continue; } - registry.fill(HIST("h3bodyCombinationCounter"), 3.5); - - initCCDBfromRunNumber(c0.runNumber()); - - if (dcaFitterEMSel.cfgMix3BodyMethod == 0) { // mix bachelor (deuteron) - fillVtxCand(c0, tpos0, tneg0, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - fillVtxCand(c1, tpos1, tneg1, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); - } else if ((dcaFitterEMSel.cfgMix3BodyMethod == 1 && tbach0.sign() > 0) || (dcaFitterEMSel.cfgMix3BodyMethod == 2 && tbach0.sign() < 0)) { // mix piMinus or proton - fillVtxCand(c0, tpos0, tneg1, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); - fillVtxCand(c1, tpos1, tneg0, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - } else if ((dcaFitterEMSel.cfgMix3BodyMethod == 1 && tbach0.sign() < 0) || (dcaFitterEMSel.cfgMix3BodyMethod == 2 && tbach0.sign() > 0)) { // mix piPlus or anti-proton - fillVtxCand(c0, tpos1, tneg0, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); - fillVtxCand(c1, tpos0, tneg1, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - } + registry.fill(HIST("Mixing/h3bodyCombinationCounter"), 3.5); - VtxCandidates.clear(); - } // end decay3body combinations loop - } - //------------------------------------------------------------------ - // fill the StoredVtx3BodyDatas table - void fillVtx3BodyTable(VtxCandidate const& candVtx) - { - vtx3bodydata( - candVtx.track0Id, candVtx.track1Id, candVtx.track2Id, candVtx.collisionId, candVtx.decay3bodyId, - candVtx.vtxPos[0], candVtx.vtxPos[1], candVtx.vtxPos[2], - candVtx.track0P[0], candVtx.track0P[1], candVtx.track0P[2], candVtx.track1P[0], candVtx.track1P[1], candVtx.track1P[2], candVtx.track2P[0], candVtx.track2P[1], candVtx.track2P[2], - candVtx.dcadaughters, - candVtx.daudcaxytopv[0], candVtx.daudcaxytopv[1], candVtx.daudcaxytopv[2], - candVtx.daudcatopv[0], candVtx.daudcatopv[1], candVtx.daudcatopv[2], - candVtx.bachelortofNsigma); - } - - //------------------------------------------------------------------ - //-------------------- KFParticle reconstruction ------------------- - //------------------------------------------------------------------ - // function to select daughter track PID - template - bool selectTPCPID(TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackDeuteron) - { - if (std::abs(trackProton.tpcNSigmaPr()) > kfparticleConfigurations.maxtpcnSigma) { - return false; - } - if (std::abs(trackDeuteron.tpcNSigmaDe()) > kfparticleConfigurations.maxtpcnSigma) { - return false; - } - if (kfparticleConfigurations.useTPCforPion && std::abs(trackPion.tpcNSigmaPi()) > kfparticleConfigurations.maxtpcnSigma) { - return false; - } - return true; + // candidate analysis + // mix deuteron + if (mixingOpts.mixingType == 0) { + doMixing(collision0, trackProton0, trackPion0, trackDeuteron1, magFieldCol0); + doMixing(collision1, trackProton1, trackPion1, trackDeuteron0, magFieldCol1); + } + // mix proton + if (mixingOpts.mixingType == 1) { + doMixing(collision0, trackProton1, trackPion0, trackDeuteron0, magFieldCol0); + doMixing(collision1, trackProton0, trackPion1, trackDeuteron1, magFieldCol1); + } + // mix pion + if (mixingOpts.mixingType == 2) { + doMixing(collision0, trackProton0, trackPion1, trackDeuteron0, magFieldCol0); + doMixing(collision1, trackProton1, trackPion0, trackDeuteron1, magFieldCol1); + } + } // end decay3body combinations loop } - template - double getTOFnSigma(TCollision const& collision, TTrack const& track, bool isEventMixing) + // ______________________________________________________________ + // function to calculate correct TOF nSigma for deuteron track + template + double getTOFnSigma(o2::pid::tof::TOFResoParamsV3 const& parameters, TCollision const& collision, TTrack const& track) { - // TOF PID of deuteron (set motherhyp correctly) - double tofNSigmaDeuteron = -999; + // TOF PID of deuteron if (track.has_collision() && track.hasTOF()) { - if (isEventMixing) { - tofNSigmaDeuteron = bachelorTOFPID.GetTOFNSigma(track, collision, collision); + auto originalcol = track.template collision_as(); + if constexpr (isMC) { + return bachelorTOFPIDLabeled.GetTOFNSigma(parameters, track, originalcol, collision); } else { - auto originalcol = track.template collision_as(); - tofNSigmaDeuteron = bachelorTOFPID.GetTOFNSigma(track, originalcol, collision); + return bachelorTOFPID.GetTOFNSigma(parameters, track, originalcol, collision); } } - return tofNSigmaDeuteron; - } - - //------------------------------------------------------------------ - // function to fill candidate table - template - void fillCandidateTable(TCandidate const& candidate) - { - kfvtx3bodydatalite( - // hypertriton - candidate.mass, - candidate.pos[0], candidate.pos[1], candidate.pos[2], - candidate.mom[0], candidate.mom[1], candidate.mom[2], candidate.mom[3], - candidate.charge, - candidate.dcaToPV[0], candidate.dcaToPV[1], // 3D, xy - candidate.cpaToPV[0], candidate.cpaToPV[1], // 3D, xy - candidate.decLen[0], candidate.decLen[1], // 3D, xy - candidate.ldl, - candidate.chi2geoNDF, candidate.chi2topoNDF, - candidate.ctau, - candidate.trackedClSize, - // V0 - candidate.massV0, - candidate.cpaV0ToPV, - // daughter momenta at vertex - candidate.protonMom[0], candidate.protonMom[1], candidate.protonMom[2], - candidate.pionMom[0], candidate.pionMom[1], candidate.pionMom[2], - candidate.deuteronMom[0], candidate.deuteronMom[1], candidate.deuteronMom[2], - candidate.tpcInnerParam[0], candidate.tpcInnerParam[1], candidate.tpcInnerParam[2], // proton, pion, deuteron - // daughter track quality - candidate.tpcNClDaughters[0], candidate.tpcNClDaughters[1], candidate.tpcNClDaughters[2], // proton, pion, deuteron - candidate.tpcChi2NClDeuteron, - candidate.DeltaPhiRotDeuteron, candidate.DeltaPhiRotProton, - // daughter DCAs KF - candidate.DCAdaughterToPV[0], candidate.DCAdaughterToPV[1], candidate.DCAdaughterToPV[2], // proton, pion, deuteron - candidate.DCAdaughterToPVxy[0], candidate.DCAdaughterToPVxy[1], candidate.DCAdaughterToPVxy[2], // proton, pion, deuteron - candidate.DCAdaughterToSVxy[0], candidate.DCAdaughterToSVxy[1], candidate.DCAdaughterToSVxy[2], // proton, pion, deuteron - candidate.DCAprotonToPion, candidate.DCAprotonToDeuteron, candidate.DCApionToDeuteron, - candidate.DCAvtxDaughters3D, - // daughter signs - candidate.daughterCharge[0], candidate.daughterCharge[1], candidate.daughterCharge[2], // proton, pion, deuteron - // daughter PID - candidate.tpcNsigma[0], candidate.tpcNsigma[1], candidate.tpcNsigma[2], candidate.tpcNsigma[3], // proton, pion, deuteron, bach with pion hyp - candidate.tofNsigmaDeuteron, - candidate.averageClusterSizeDeuteron, - candidate.pidForTrackingDeuteron); - - if (kfparticleConfigurations.fillCandidateFullTable) { - kfvtx3bodydata( - candidate.collisionID, candidate.trackPosID, candidate.trackNegID, candidate.trackBachID, candidate.decay3bodyID, - // hypertriton - candidate.mass, - candidate.pos[0], candidate.pos[1], candidate.pos[2], - candidate.posErr[0], candidate.posErr[1], candidate.posErr[2], - candidate.mom[0], candidate.mom[1], candidate.mom[2], candidate.mom[3], - candidate.momErr[0], candidate.momErr[1], candidate.momErr[2], candidate.momErr[3], - candidate.charge, - candidate.dcaToPV[0], candidate.dcaToPV[1], // 3D, xy - candidate.cpaToPV[0], candidate.cpaToPV[1], // 3D, xy - candidate.cpaToPVtopo[0], candidate.cpaToPVtopo[1], // 3D, xy - candidate.decLen[0], candidate.decLen[1], // 3D, xy - candidate.ldl, - candidate.chi2geoNDF, candidate.chi2topoNDF, - candidate.ctau, - candidate.trackedClSize, - // V0 - candidate.massV0, candidate.chi2massV0, - candidate.cpaV0ToPV, - // daughter momenta (at vertex and TPC) - candidate.protonMom[0], candidate.protonMom[1], candidate.protonMom[2], - candidate.pionMom[0], candidate.pionMom[1], candidate.pionMom[2], - candidate.deuteronMom[0], candidate.deuteronMom[1], candidate.deuteronMom[2], - candidate.tpcInnerParam[0], candidate.tpcInnerParam[1], candidate.tpcInnerParam[2], // proton, pion, deuteron - // daughter track quality - candidate.tpcNClDaughters[0], candidate.tpcNClDaughters[1], candidate.tpcNClDaughters[2], // proton, pion, deuteron - candidate.tpcChi2NClDeuteron, - candidate.DeltaPhiRotDeuteron, candidate.DeltaPhiRotProton, - // daughter DCAs KF - candidate.DCAdaughterToPV[0], candidate.DCAdaughterToPV[1], candidate.DCAdaughterToPV[2], // proton, pion, deuteron - candidate.DCAdaughterToPVxy[0], candidate.DCAdaughterToPVxy[1], candidate.DCAdaughterToPVxy[2], // proton, pion, deuteron - candidate.DCAdaughterToSVxy[0], candidate.DCAdaughterToSVxy[1], candidate.DCAdaughterToSVxy[2], // proton, pion, deuteron - candidate.DCAprotonToPion, candidate.DCAprotonToDeuteron, candidate.DCApionToDeuteron, - candidate.DCAvtxDaughters3D, - // daughter DCAs to PV propagated with material - candidate.trackDCAxy[0], candidate.trackDCAxy[1], candidate.trackDCAxy[2], // pos, neg, bach - candidate.trackDCA[0], candidate.trackDCA[1], candidate.trackDCA[2], // pos, neg, bach - // daughter signs - candidate.daughterCharge[0], candidate.daughterCharge[1], candidate.daughterCharge[2], // proton, pion, deuteron - // daughter PID - candidate.tpcNsigma[0], candidate.tpcNsigma[1], candidate.tpcNsigma[2], candidate.tpcNsigma[3], // proton, pion, deuteron, bach with pion hyp - candidate.tpcdEdx[0], candidate.tpcdEdx[1], candidate.tpcdEdx[2], // proton, pion, deuteron - candidate.tofNsigmaDeuteron, - candidate.averageClusterSizeDeuteron, - candidate.pidForTrackingDeuteron); - } - LOG(debug) << "Table filled."; + return -999; } - //------------------------------------------------------------------ - // function to fit KFParticle 3body vertex - template - void fit3bodyVertex(TKFParticle& kfpProton, TKFParticle& kfpPion, TKFParticle& kfpDeuteron, TKFParticle& KFHt) + // ______________________________________________________________ + // function to fill analysis tables + void fillAnalysisTables() { - // Construct 3body vertex - int nDaughters3body = 3; - const KFParticle* Daughters3body[3] = {&kfpProton, &kfpPion, &kfpDeuteron}; - KFHt.SetConstructMethod(2); - try { - KFHt.Construct(Daughters3body, nDaughters3body); - } catch (std::runtime_error& e) { - LOG(debug) << "Failed to create Hyper triton 3-body vertex." << e.what(); - return; + // generate analysis tables + if (mEnabledTables[kDecay3BodyIndices]) { + products.decay3bodyindices(helper.decay3body.decay3bodyID, + helper.decay3body.protonID, helper.decay3body.pionID, helper.decay3body.deuteronID, + helper.decay3body.collisionID); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kDecay3BodyIndices); + } + if (mEnabledTables[kVtx3BodyDatas]) { + products.vtx3bodydatas(helper.decay3body.sign, + helper.decay3body.mass, helper.decay3body.massV0, + helper.decay3body.position[0], helper.decay3body.position[1], helper.decay3body.position[2], + helper.decay3body.momentum[0], helper.decay3body.momentum[1], helper.decay3body.momentum[2], + helper.decay3body.chi2, + helper.decay3body.trackedClSize, + helper.decay3body.momProton[0], helper.decay3body.momProton[1], helper.decay3body.momProton[2], + helper.decay3body.momPion[0], helper.decay3body.momPion[1], helper.decay3body.momPion[2], + helper.decay3body.momDeuteron[0], helper.decay3body.momDeuteron[1], helper.decay3body.momDeuteron[2], + helper.decay3body.trackDCAxyToPV[0], helper.decay3body.trackDCAxyToPV[1], helper.decay3body.trackDCAxyToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.trackDCAzToPV[0], helper.decay3body.trackDCAzToPV[1], helper.decay3body.trackDCAzToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + 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.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 + helper.decay3body.pidForTrackingDeuteron); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kVtx3BodyDatas); + } + if (mEnabledTables[kVtx3BodyCovs]) { + products.vtx3bodycovs(helper.decay3body.covProton, + helper.decay3body.covPion, + helper.decay3body.covDeuteron, + helper.decay3body.covariance); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kVtx3BodyCovs); + } + if (mEnabledTables[kMcVtx3BodyDatas]) { + products.mcvtx3bodydatas(helper.decay3body.sign, + helper.decay3body.mass, helper.decay3body.massV0, + helper.decay3body.position[0], helper.decay3body.position[1], helper.decay3body.position[2], + helper.decay3body.momentum[0], helper.decay3body.momentum[1], helper.decay3body.momentum[2], + helper.decay3body.chi2, + helper.decay3body.trackedClSize, + helper.decay3body.momProton[0], helper.decay3body.momProton[1], helper.decay3body.momProton[2], + helper.decay3body.momPion[0], helper.decay3body.momPion[1], helper.decay3body.momPion[2], + helper.decay3body.momDeuteron[0], helper.decay3body.momDeuteron[1], helper.decay3body.momDeuteron[2], + helper.decay3body.trackDCAxyToPV[0], helper.decay3body.trackDCAxyToPV[1], helper.decay3body.trackDCAxyToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + helper.decay3body.trackDCAzToPV[0], helper.decay3body.trackDCAzToPV[1], helper.decay3body.trackDCAzToPV[2], // 0 - proton, 1 - pion, 2 - deuteron + 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.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 + helper.decay3body.pidForTrackingDeuteron, + // MC information + this3BodyMCInfo.genMomentum[0], this3BodyMCInfo.genMomentum[1], this3BodyMCInfo.genMomentum[2], + this3BodyMCInfo.genDecVtx[0], this3BodyMCInfo.genDecVtx[1], this3BodyMCInfo.genDecVtx[2], + this3BodyMCInfo.genCt, + this3BodyMCInfo.genPhi, this3BodyMCInfo.genEta, this3BodyMCInfo.genRapidity, + this3BodyMCInfo.genMomProton, this3BodyMCInfo.genMomPion, this3BodyMCInfo.genMomDeuteron, + this3BodyMCInfo.genPtProton, this3BodyMCInfo.genPtPion, this3BodyMCInfo.genPtDeuteron, + this3BodyMCInfo.isTrueH3L, this3BodyMCInfo.isTrueAntiH3L, + this3BodyMCInfo.isReco, + this3BodyMCInfo.motherPdgCode, + this3BodyMCInfo.daughterPrPdgCode, this3BodyMCInfo.daughterPiPdgCode, this3BodyMCInfo.daughterDePdgCode, + this3BodyMCInfo.isDeuteronPrimary, + this3BodyMCInfo.survivedEventSel); + registry.fill(HIST("Counters/hTableBuildingStatistics"), kMcVtx3BodyDatas); } - // transport all daughter tracks to hypertriton vertex - float HtVtx[3] = {0.}; - HtVtx[0] = KFHt.GetX(); - HtVtx[1] = KFHt.GetY(); - HtVtx[2] = KFHt.GetZ(); - kfpProton.TransportToPoint(HtVtx); - kfpPion.TransportToPoint(HtVtx); - kfpDeuteron.TransportToPoint(HtVtx); - LOG(debug) << "Hypertriton vertex constructed."; } - //------------------------------------------------------------------ - // 3body candidate builder with KFParticle + // ______________________________________________________________ + // function to build mixed 3body candidate from selected tracks template - void buildVtx3BodyDataTableKFParticle(TCollision const& collision, TTrack const& trackPos, TTrack const& trackNeg, TTrack const& trackBach, int64_t decay3bodyID, int bachelorcharge, double tofNSigmaDeuteron) + void doMixing(TCollision const& collision, TTrack const& trackProton, TTrack const& trackPion, TTrack const& trackDeuteron, float magField) { - gROOT->SetBatch(true); - gRandom->SetSeed(42); - - // initialise KF primary vertex - KFPVertex kfpVertex = createKFPVertexFromCollision(collision); - KFParticle kfpv(kfpVertex); - LOG(debug) << "Created KF PV."; - - // fill event QA histograms --> only for events with a decay3body! - if (kfparticleConfigurations.doVertexQA) { - registry.fill(HIST("QA/Event/hVtxXKF"), kfpv.GetX()); - registry.fill(HIST("QA/Event/hVtxYKF"), kfpv.GetY()); - registry.fill(HIST("QA/Event/hVtxZKF"), kfpv.GetZ()); - registry.fill(HIST("QA/Event/hVtxCovXXKF"), kfpv.GetCovariance(0)); - registry.fill(HIST("QA/Event/hVtxCovYYKF"), kfpv.GetCovariance(2)); - registry.fill(HIST("QA/Event/hVtxCovZZKF"), kfpv.GetCovariance(5)); - registry.fill(HIST("QA/Event/hVtxCovXYKF"), kfpv.GetCovariance(1)); - registry.fill(HIST("QA/Event/hVtxCovXZKF"), kfpv.GetCovariance(3)); - registry.fill(HIST("QA/Event/hVtxCovYZKF"), kfpv.GetCovariance(4)); - registry.fill(HIST("QA/Event/hVtxX"), collision.posX()); - registry.fill(HIST("QA/Event/hVtxY"), collision.posY()); - registry.fill(HIST("QA/Event/hVtxZ"), collision.posZ()); - registry.fill(HIST("QA/Event/hVtxCovXX"), collision.covXX()); - registry.fill(HIST("QA/Event/hVtxCovYY"), collision.covYY()); - registry.fill(HIST("QA/Event/hVtxCovZZ"), collision.covZZ()); - registry.fill(HIST("QA/Event/hVtxCovXY"), collision.covXY()); - registry.fill(HIST("QA/Event/hVtxCovXZ"), collision.covXZ()); - registry.fill(HIST("QA/Event/hVtxCovYZ"), collision.covYZ()); - } - - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxAll); - - auto trackParCovPos = getTrackParCov(trackPos); - auto trackParCovNeg = getTrackParCov(trackNeg); - auto trackParCovBach = getTrackParCov(trackBach); - LOG(debug) << "Got all daughter tracks."; - - bool isMatter = trackBach.sign() > 0 ? true : false; - - // ---------- fill track QA histograms ---------- - if (kfparticleConfigurations.doTrackQA) { - registry.fill(HIST("QA/Tracks/hTrackPosTPCNcls"), trackPos.tpcNClsFound()); - registry.fill(HIST("QA/Tracks/hTrackNegTPCNcls"), trackNeg.tpcNClsFound()); - registry.fill(HIST("QA/Tracks/hTrackBachTPCNcls"), trackBach.tpcNClsFound()); - registry.fill(HIST("QA/Tracks/hTrackPosHasTPC"), trackPos.hasTPC()); - registry.fill(HIST("QA/Tracks/hTrackNegHasTPC"), trackNeg.hasTPC()); - registry.fill(HIST("QA/Tracks/hTrackBachHasTPC"), trackBach.hasTPC()); - registry.fill(HIST("QA/Tracks/hTrackBachITSClusSizes"), trackBach.itsClusterSizes()); - if (isMatter) { - registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackPos.sign() * trackPos.tpcInnerParam(), trackPos.tpcNSigmaPr()); - registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackNeg.sign() * trackNeg.tpcInnerParam(), trackNeg.tpcNSigmaPi()); - registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackPos.pt()); - registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackNeg.pt()); - } else { - registry.fill(HIST("QA/Tracks/hTrackProtonTPCPID"), trackNeg.sign() * trackNeg.tpcInnerParam(), trackNeg.tpcNSigmaPr()); - registry.fill(HIST("QA/Tracks/hTrackPionTPCPID"), trackPos.sign() * trackPos.tpcInnerParam(), trackPos.tpcNSigmaPi()); - registry.fill(HIST("QA/Tracks/hTrackProtonPt"), trackNeg.pt()); - registry.fill(HIST("QA/Tracks/hTrackPionPt"), trackPos.pt()); - } - registry.fill(HIST("QA/Tracks/hTrackBachTPCPID"), trackBach.sign() * trackBach.tpcInnerParam(), trackBach.tpcNSigmaDe()); - registry.fill(HIST("QA/Tracks/hTrackBachPt"), trackBach.pt()); - } - - // -------- STEP 1: track selection -------- - // collision ID --> not correct? tracks can have different collisions, but belong to one 3prong vertex! - // if (trackPos.collisionId() != trackNeg.collisionId() || trackPos.collisionId() != trackBach.collisionId() || trackNeg.collisionId() != trackBach.collisionId()) { - // continue; - // } - // track IDs --> already checked in SVertexer! - - // track signs (pos, neg, bach) --> sanity check, should already be in SVertexer - if (trackPos.sign() != +1 || trackNeg.sign() != -1) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxCharge); - - // track eta - if (std::abs(trackPos.eta()) > kfparticleConfigurations.maxEta || std::abs(trackNeg.eta()) > kfparticleConfigurations.maxEta || std::abs(trackBach.eta()) > kfparticleConfigurations.maxEtaDeuteron) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxEta); - - // number of TPC clusters - if (trackBach.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsBach) { - return; - } - if (isMatter && ((kfparticleConfigurations.useTPCforPion && trackNeg.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsPion) || trackPos.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsProton)) { - return; - } else if (!isMatter && ((kfparticleConfigurations.useTPCforPion && trackPos.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsPion) || trackNeg.tpcNClsFound() <= kfparticleConfigurations.mintpcNClsProton)) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTPCNcls); - - // number of TPC crossed rows - if (trackBach.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows) { - return; - } - if (isMatter && ((kfparticleConfigurations.useTPCforPion && trackNeg.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRowsPion) || trackPos.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows)) { - return; - } else if (!isMatter && ((kfparticleConfigurations.useTPCforPion && trackPos.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRowsPion) || trackNeg.tpcNClsCrossedRows() <= kfparticleConfigurations.mintpcCrossedRows)) { + // set vertexers and propagator with correct mag field of this collision (only if run number changed compared to previous candidate build) + initFittersWithMagField(collision.runNumber(), magField); + if (helper.buildDecay3BodyCandidate(collision, trackProton, trackPion, trackDeuteron, + -1 /*decay3bodyIndex*/, + trackDeuteron.tofNSigmaDe(), + 0 /*trackedClSize*/, + decay3bodyBuilderOpts.useKFParticle, + decay3bodyBuilderOpts.kfSetTopologicalConstraint, + decay3bodyBuilderOpts.useSelections, + decay3bodyBuilderOpts.useChi2Selection, + decay3bodyBuilderOpts.useTPCforPion, + decay3bodyBuilderOpts.acceptTPCOnly, + decay3bodyBuilderOpts.askOnlyITSMatch, + decay3bodyBuilderOpts.calculateCovariance, + true /*isEventMixing*/)) { + // fill analysis tables with built candidate + fillAnalysisTables(); return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTPCRows); - - // TPC PID - float tpcNsigmaProton; - float tpcNsigmaPion; - float dEdxProton; - float dEdxPion; - float tpcNsigmaDeuteron = trackBach.tpcNSigmaDe(); - float tpcNsigmaPionBach = trackBach.tpcNSigmaPi(); - float dEdxDeuteron = trackBach.tpcSignal(); - if (isMatter) { // hypertriton (proton, pi-, deuteron) - tpcNsigmaProton = trackPos.tpcNSigmaPr(); - tpcNsigmaPion = trackNeg.tpcNSigmaPi(); - dEdxProton = trackPos.tpcSignal(); - dEdxPion = trackNeg.tpcSignal(); - if (!selectTPCPID(trackPos, trackNeg, trackBach)) { - return; - } - } else if (!isMatter) { // anti-hypertriton (anti-proton, pi+, deuteron) - tpcNsigmaProton = trackNeg.tpcNSigmaPr(); - tpcNsigmaPion = trackPos.tpcNSigmaPi(); - dEdxProton = trackNeg.tpcSignal(); - dEdxPion = trackPos.tpcSignal(); - if (!selectTPCPID(trackNeg, trackPos, trackBach)) { - return; - } - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTPCPID); - LOG(debug) << "Basic track selections done."; - - // Average ITS cluster size of deuteron track - double averageClusterSizeDeuteron(0); - int nCls(0); - for (int i = 0; i < 7; i++) { - int clusterSize = trackBach.itsClsSizeInLayer(i); - averageClusterSizeDeuteron += static_cast(clusterSize); - if (clusterSize > 0) - nCls++; - } - averageClusterSizeDeuteron = averageClusterSizeDeuteron / static_cast(nCls); - - // track DCAxy and DCAz to PV associated with decay3body - o2::dataformats::VertexBase mPV; - o2::dataformats::DCA mDcaInfoCovPos; - o2::dataformats::DCA mDcaInfoCovNeg; - o2::dataformats::DCA mDcaInfoCovBach; - auto trackParCovPVPos = trackParCovPos; - auto trackParCovPVNeg = trackParCovNeg; - auto trackParCovPVBach = trackParCovBach; - mPV.setPos({collision.posX(), collision.posY(), collision.posZ()}); - mPV.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVPos, 2.f, matCorr, &mDcaInfoCovPos); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVNeg, 2.f, matCorr, &mDcaInfoCovNeg); - o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPVBach, 2.f, matCorr, &mDcaInfoCovBach); - auto TrackPosDcaXY = mDcaInfoCovPos.getY(); - auto TrackNegDcaXY = mDcaInfoCovNeg.getY(); - auto TrackBachDcaXY = mDcaInfoCovBach.getY(); - auto TrackPosDcaZ = mDcaInfoCovPos.getZ(); - auto TrackNegDcaZ = mDcaInfoCovNeg.getZ(); - auto TrackBachDcaZ = mDcaInfoCovBach.getZ(); - // calculate 3D track DCA - auto TrackPosDca = std::sqrt(TrackPosDcaXY * TrackPosDcaXY + TrackPosDcaZ * TrackPosDcaZ); - auto TrackNegDca = std::sqrt(TrackNegDcaXY * TrackNegDcaXY + TrackNegDcaZ * TrackNegDcaZ); - auto TrackBachDca = std::sqrt(TrackBachDcaXY * TrackBachDcaXY + TrackBachDcaZ * TrackBachDcaZ); - // selection - if (kfparticleConfigurations.doDCAPreSel && isMatter && (std::fabs(TrackNegDcaXY) <= kfparticleConfigurations.mindcaXYPionPV || std::fabs(TrackPosDcaXY) <= kfparticleConfigurations.mindcaXYProtonPV)) { - return; - } else if (kfparticleConfigurations.doDCAPreSel && !isMatter && (std::fabs(TrackPosDcaXY) <= kfparticleConfigurations.mindcaXYPionPV || std::fabs(TrackNegDcaXY) <= kfparticleConfigurations.mindcaXYProtonPV)) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDCAxyPV); - if (kfparticleConfigurations.doDCAPreSel && isMatter && (std::fabs(TrackNegDcaZ) <= kfparticleConfigurations.mindcaZPionPV || std::fabs(TrackPosDcaZ) <= kfparticleConfigurations.mindcaZProtonPV)) { - return; - } else if (kfparticleConfigurations.doDCAPreSel && !isMatter && (std::fabs(TrackPosDcaZ) <= kfparticleConfigurations.mindcaZPionPV || std::fabs(TrackNegDcaZ) <= kfparticleConfigurations.mindcaZProtonPV)) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDCAzPV); - - // daughter track momentum at inner wall of TPC - float tpcInnerParamProton; - float tpcInnerParamPion; - float tpcInnerParamDeuteron = trackBach.tpcInnerParam(); - if (isMatter) { // hypertriton (proton, pi-, deuteron) - tpcInnerParamProton = trackPos.tpcInnerParam(); - tpcInnerParamPion = trackNeg.tpcInnerParam(); - } else if (!isMatter) { // anti-hypertriton (anti-proton, pi+, deuteron) - tpcInnerParamProton = trackNeg.tpcInnerParam(); - tpcInnerParamPion = trackPos.tpcInnerParam(); - } - - // -------- STEP 2: fit vertex with proton and pion -------- - // Fit vertex with DCA fitter to find minimization point --> uses material corrections implicitly - if (kfparticleConfigurations.doDCAFitterPreMinimum) { - try { - fitter3body.process(trackParCovPos, trackParCovNeg, trackParCovBach); - } catch (std::runtime_error& e) { - LOG(error) << "Exception caught in DCA fitter process call: Not able to fit decay3body vertex!"; - return; - } - // re-acquire tracks at vertex position from DCA fitter - trackParCovPos = fitter3body.getTrack(0); - trackParCovNeg = fitter3body.getTrack(1); - trackParCovBach = fitter3body.getTrack(2); - - LOG(debug) << "Minimum found with DCA fitter for decay3body."; - } - - // create KFParticle objects from tracks - KFParticle kfpProton, kfpPion; - if (isMatter) { - kfpProton = createKFParticleFromTrackParCov(trackParCovPos, trackPos.sign(), constants::physics::MassProton); - kfpPion = createKFParticleFromTrackParCov(trackParCovNeg, trackNeg.sign(), constants::physics::MassPionCharged); - } else if (!isMatter) { - kfpProton = createKFParticleFromTrackParCov(trackParCovNeg, trackNeg.sign(), constants::physics::MassProton); - kfpPion = createKFParticleFromTrackParCov(trackParCovPos, trackPos.sign(), constants::physics::MassPionCharged); - } - LOG(debug) << "KFParticle objects created from daughter tracks."; - - // Construct V0 as intermediate step - KFParticle KFV0; - int nDaughtersV0 = 2; - const KFParticle* DaughtersV0[2] = {&kfpProton, &kfpPion}; - KFV0.SetConstructMethod(2); - try { - KFV0.Construct(DaughtersV0, nDaughtersV0); - } catch (std::runtime_error& e) { - LOG(debug) << "Failed to create V0 vertex from daughter tracks." << e.what(); - return; - } - KFV0.TransportToDecayVertex(); - LOG(debug) << "V0 constructed."; - - // check V0 mass and set mass constraint - float massV0, sigmaMassV0; - KFV0.GetMass(massV0, sigmaMassV0); - KFParticle KFV0Mass = KFV0; - KFV0Mass.SetNonlinearMassConstraint(o2::constants::physics::MassLambda); - float chi2massV0 = KFV0Mass.GetChi2() / KFV0Mass.GetNDF(); - if (kfparticleConfigurations.useLambdaMassConstraint) { - LOG(debug) << "V0 mass constraint applied."; - KFV0 = KFV0Mass; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxV0MassConst); - - // apply virtual V0 cuts used in SVertexer in case of 3body mixing with proton track - if (kfparticleConfigurations.mixingType == 1 && kfparticleConfigurations.applySVertexerV0Cuts) { - // V0 radius - if (std::sqrt(KFV0.GetX() * KFV0.GetX() + KFV0.GetY() * KFV0.GetY()) <= 0.5) { - return; - } - // pT - if (KFV0.GetPt() <= 0.01) { - return; - } - // pz/pT - if (KFV0.GetPz() / KFV0.GetPt() >= 2) { - return; - } - // cos(PA) - if (cpaXYFromKF(KFV0, kfpv) <= 0.9 || cpaFromKF(KFV0, kfpv) <= 0.8) { - return; - } - } - - // -------- STEP 3: fit three body vertex -------- - // Create KFParticle object from deuteron track - KFParticle kfpDeuteron; - kfpDeuteron = createKFParticleFromTrackParCov(trackParCovBach, trackBach.sign() * bachelorcharge, constants::physics::MassDeuteron); - LOG(debug) << "KFParticle created from deuteron track."; - - // Construct vertex - KFParticle KFHt; - fit3bodyVertex(kfpProton, kfpPion, kfpDeuteron, KFHt); - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxhasSV); - - // -------- STEP 4: daughter selections after geometrical vertex fit -------- - // daughter DCAs with KF - if ((kfpProton.GetDistanceFromParticle(kfpPion) >= kfparticleConfigurations.maxDcaProPi) || (kfpProton.GetDistanceFromParticle(kfpDeuteron) >= kfparticleConfigurations.maxDcaProDeu) || (kfpPion.GetDistanceFromParticle(kfpDeuteron) >= kfparticleConfigurations.maxDcaPiDe)) { - return; - } - float DCAvtxDaughters3D = kfpProton.GetDistanceFromParticle(kfpPion) + kfpProton.GetDistanceFromParticle(kfpDeuteron) + kfpPion.GetDistanceFromParticle(kfpDeuteron); - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDcaDau); - LOG(debug) << "DCA selection after vertex fit applied."; - - // daughter DCAs to vertex - if (kfpProton.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau || kfpPion.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau || kfpDeuteron.GetDistanceFromVertexXY(KFHt) >= kfparticleConfigurations.maxDcaXYSVDau) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDcaDauVtx); - LOG(debug) << "DCA to vertex selection after vertex fit applied."; - - // daughter pT - if (kfpProton.GetPt() < kfparticleConfigurations.minPtProton || kfpProton.GetPt() > kfparticleConfigurations.maxPtProton || kfpPion.GetPt() < kfparticleConfigurations.minPtPion || kfpPion.GetPt() > kfparticleConfigurations.maxPtPion || kfpDeuteron.GetPt() < kfparticleConfigurations.minPtDeuteron || kfpDeuteron.GetPt() > kfparticleConfigurations.maxPtDeuteron) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxDauPt); - LOG(debug) << "Daughter pT selection applied."; - - // -------- STEP 5: candidate selection and constraint after geometrical vertex fit -------- - // Rapidity - float rapHt = RecoDecay::y(std::array{KFHt.GetPx(), KFHt.GetPy(), KFHt.GetPz()}, o2::constants::physics::MassHyperTriton); - if (std::abs(rapHt) > kfparticleConfigurations.maxRapidityHt) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxRap); - - // Pt selection - if (KFHt.GetPt() <= kfparticleConfigurations.minPtHt || KFHt.GetPt() >= kfparticleConfigurations.maxPtHt) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxPt); - - // Mass window - float massHt, sigmaMassHt; - KFHt.GetMass(massHt, sigmaMassHt); - if (massHt <= kfparticleConfigurations.minMassHt || massHt >= kfparticleConfigurations.maxMassHt) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxMass); - - // cos(PA) to PV - if (std::abs(cpaFromKF(KFHt, kfpv)) <= kfparticleConfigurations.minCosPA) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxCosPA); - - // cos(PA) xy to PV - if (std::abs(cpaXYFromKF(KFHt, kfpv)) <= kfparticleConfigurations.minCosPAxy) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxCosPAXY); - - // chi2 geometrical - float chi2geoNDF = KFHt.GetChi2() / KFHt.GetNDF(); - if (kfparticleConfigurations.applyTopoSel && chi2geoNDF >= kfparticleConfigurations.maxChi2geo) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxChi2geo); - LOG(debug) << "Basic selections after vertex fit done."; - - // ctau before topo constraint - if (KFHt.GetLifeTime() > kfparticleConfigurations.maxctauHt) { - return; - } - - // Set vertex constraint and topological selection - KFParticle KFHtPV = KFHt; - try { - KFHtPV.SetProductionVertex(kfpv); - } catch (std::runtime_error& e) { - LOG(error) << "Exception caught KFParticle process call: Topological constraint failed"; - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxTopoConstr); // to check if topo constraint fails - // get topological chi2 - float chi2topoNDF = KFHtPV.GetChi2() / KFHtPV.GetNDF(); - KFHtPV.TransportToDecayVertex(); - if (kfparticleConfigurations.applyTopoSel && chi2topoNDF >= kfparticleConfigurations.maxChi2topo) { - return; - } - registry.fill(HIST("Counters/hVtx3BodyCounterKFParticle"), kKfVtxChi2topo); - - // -------- STEP 6: collect and fill candidate info -------- - // get cluster size of strangeness tracked 3bodies - float trackedClSize; - if (decay3bodyID == -1) { - trackedClSize = 0; } else { - trackedClSize = !fTrackedClSizeVector.empty() ? fTrackedClSizeVector[decay3bodyID] : 0; + return; } + } - // candidate filling - kfCandidate candidate; - candidate.collisionID = collision.globalIndex(); - candidate.trackPosID = trackPos.globalIndex(); - candidate.trackNegID = trackNeg.globalIndex(); - candidate.trackBachID = trackBach.globalIndex(); - candidate.decay3bodyID = decay3bodyID; - // hypertriton - candidate.mass = massHt; - candidate.pos[0] = KFHt.GetX(); - candidate.pos[1] = KFHt.GetY(); - candidate.pos[2] = KFHt.GetZ(); - candidate.posErr[0] = KFHt.GetErrX(); - candidate.posErr[1] = KFHt.GetErrY(); - candidate.posErr[2] = KFHt.GetErrZ(); - candidate.mom[0] = KFHt.GetPx(); - candidate.mom[1] = KFHt.GetPy(); - candidate.mom[2] = KFHt.GetPz(); - candidate.mom[3] = KFHt.GetPt(); - candidate.momErr[0] = KFHt.GetErrPx(); - candidate.momErr[1] = KFHt.GetErrPy(); - candidate.momErr[2] = KFHt.GetErrPz(); - candidate.momErr[3] = KFHt.GetErrPt(); - candidate.charge = KFHt.GetQ(); - candidate.dcaToPV[0] = KFHt.GetDistanceFromVertex(kfpv); - candidate.dcaToPV[1] = KFHt.GetDistanceFromVertexXY(kfpv); - candidate.cpaToPV[0] = cpaFromKF(KFHt, kfpv); - candidate.cpaToPV[1] = cpaXYFromKF(KFHt, kfpv); - candidate.cpaToPVtopo[0] = cpaFromKF(KFHtPV, kfpv); - candidate.cpaToPVtopo[1] = cpaXYFromKF(KFHtPV, kfpv); - candidate.decLen[0] = KFHtPV.GetDecayLength(); - candidate.decLen[1] = KFHtPV.GetDecayLengthXY(); - candidate.ldl = KFHtPV.GetDecayLength() / KFHtPV.GetErrDecayLength(); - candidate.chi2geoNDF = chi2geoNDF; - candidate.chi2topoNDF = chi2topoNDF; - candidate.ctau = KFHtPV.GetLifeTime(); - candidate.trackedClSize = trackedClSize; - // V0 - candidate.massV0 = massV0; - candidate.chi2massV0 = chi2massV0; - candidate.cpaV0ToPV = cpaFromKF(KFV0, kfpv); - // daughter momenta - candidate.protonMom[0] = kfpProton.GetPx(); - candidate.protonMom[1] = kfpProton.GetPy(); - candidate.protonMom[2] = kfpProton.GetPz(); - candidate.pionMom[0] = kfpPion.GetPx(); - candidate.pionMom[1] = kfpPion.GetPy(); - candidate.pionMom[2] = kfpPion.GetPz(); - candidate.deuteronMom[0] = kfpDeuteron.GetPx(); - candidate.deuteronMom[1] = kfpDeuteron.GetPy(); - candidate.deuteronMom[2] = kfpDeuteron.GetPz(); - candidate.tpcInnerParam[0] = tpcInnerParamProton; - candidate.tpcInnerParam[1] = tpcInnerParamPion; - candidate.tpcInnerParam[2] = tpcInnerParamDeuteron; - // daughter DCAs with KF - candidate.DCAdaughterToPV[0] = kfpProton.GetDistanceFromVertex(kfpv); - candidate.DCAdaughterToPV[1] = kfpPion.GetDistanceFromVertex(kfpv); - candidate.DCAdaughterToPV[2] = kfpDeuteron.GetDistanceFromVertex(kfpv); - candidate.DCAdaughterToPVxy[0] = kfpProton.GetDistanceFromVertexXY(kfpv); - candidate.DCAdaughterToPVxy[1] = kfpPion.GetDistanceFromVertexXY(kfpv); - candidate.DCAdaughterToPVxy[2] = kfpDeuteron.GetDistanceFromVertexXY(kfpv); - candidate.DCAdaughterToSVxy[0] = kfpProton.GetDistanceFromVertexXY(KFHt); - candidate.DCAdaughterToSVxy[1] = kfpPion.GetDistanceFromVertexXY(KFHt); - candidate.DCAdaughterToSVxy[2] = kfpDeuteron.GetDistanceFromVertexXY(KFHt); - candidate.DCAprotonToPion = kfpProton.GetDistanceFromParticle(kfpPion); - candidate.DCAprotonToDeuteron = kfpProton.GetDistanceFromParticle(kfpDeuteron); - candidate.DCApionToDeuteron = kfpPion.GetDistanceFromParticle(kfpDeuteron); - candidate.DCAvtxDaughters3D = DCAvtxDaughters3D; - // daughter DCAs with material corrections - candidate.trackDCAxy[0] = TrackPosDcaXY; - candidate.trackDCAxy[1] = TrackNegDcaXY; - candidate.trackDCAxy[2] = TrackBachDcaXY; - candidate.trackDCA[0] = TrackPosDca; - candidate.trackDCA[1] = TrackNegDca; - candidate.trackDCA[2] = TrackBachDca; - // daughter signs - candidate.daughterCharge[0] = kfpProton.GetQ(); - candidate.daughterCharge[1] = kfpPion.GetQ(); - candidate.daughterCharge[2] = trackBach.sign(); - // daughter PID - candidate.tpcNsigma[0] = tpcNsigmaProton; - candidate.tpcNsigma[1] = tpcNsigmaPion; - candidate.tpcNsigma[2] = tpcNsigmaDeuteron; - candidate.tpcNsigma[3] = tpcNsigmaPionBach; - candidate.tpcdEdx[0] = dEdxProton; - candidate.tpcdEdx[1] = dEdxPion; - candidate.tpcdEdx[2] = dEdxDeuteron; - candidate.tofNsigmaDeuteron = tofNSigmaDeuteron; - candidate.averageClusterSizeDeuteron = averageClusterSizeDeuteron; - candidate.pidForTrackingDeuteron = trackBach.pidForTracking(); - - //------------------------------------------------------------------ - // table filling - fillCandidateTable(candidate); - LOG(debug) << "Table filled."; - - // fill event counter hist (has selected candidate) --> only filled once per vertex - registry.fill(HIST("Counters/hEventCounterKFParticle"), 3.5); - } // end buildVtx3BodyDataTableKFParticle - - //------------------------------------------------------------------ - void processRun3(ColwithEvTimes const& collisions, aod::Decay3Bodys const& decay3bodys, TrackExtPIDIUwithEvTimes const&, aod::BCsWithTimestamps const&) + // ______________________________________________________________ + // 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) { - VtxCandidates.clear(); - - registry.fill(HIST("hEventCounter"), 0.5, collisions.size()); - - for (const auto& d3body : decay3bodys) { - auto t0 = d3body.track0_as(); - auto t1 = d3body.track1_as(); - auto t2 = d3body.track2_as(); - auto collision = d3body.collision_as(); - auto bc = collision.bc_as(); - initCCDB(bc); - - // Recalculate the TOF PID - double tofNSigmaBach = -999; - if (t2.has_collision() && t2.hasTOF()) { - auto originalcol = t2.template collision_as(); - tofNSigmaBach = bachelorTOFPID.GetTOFNSigma(t2, originalcol, collision); + 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; + } } - - fillVtxCand(collision, t0, t1, t2, d3body.globalIndex(), bachelorcharge, tofNSigmaBach); } - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3, "Produce DCA fitter decay3body tables", true); - - //------------------------------------------------------------------ - void processRun3Reduced(aod::RedCollisions const& collisions, aod::RedDecay3Bodys const& decay3bodys, aod::RedIUTracks const&) - { - VtxCandidates.clear(); - - registry.fill(HIST("hEventCounter"), 0.5, collisions.size()); - - for (const auto& d3body : decay3bodys) { - auto t0 = d3body.track0_as(); - auto t1 = d3body.track1_as(); - auto t2 = d3body.track2_as(); - auto collision = d3body.collision_as(); - - initCCDBfromRunNumber(collision.runNumber()); - fillVtxCand(collision, t0, t1, t2, d3body.globalIndex(), bachelorcharge, t2.tofNSigmaDe()); + if (prDeMomID == -1) { + return -1; } - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3Reduced, "Produce DCA fitter decay3body tables with reduced data", false); - - //------------------------------------------------------------------ - // Event-mixing background - void processRun3ReducedEM(ReducedCollisionsMultsCents const& collisions, aod::RedDecay3Bodys const& decay3bodys, aod::RedIUTracks const&) - { - auto xAxis = registry.get(HIST("hEventPairs"))->GetXaxis(); - auto yAxis = registry.get(HIST("hEventPairs"))->GetYaxis(); - - // fill collisions counter - for (const auto& collision : collisions) { - int bin_PosZ = xAxis->FindBin(collision.posZ()); - int bin_Mult = yAxis->FindBin(collision.multNTracksPV()); - registry.fill(HIST("hEventCount"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); + if (std::abs(mcParticlePi.pdgCode()) != PDG_t::kPiPlus && std::abs(mcParticlePi.pdgCode()) != PDG_t::kMuonMinus) { + return -1; } - VtxCandidates.clear(); - - auto tuple = std::make_tuple(decay3bodys); - BinningTypeColEM binningEvent{{dcaFitterEMSel.binsVtxZ, dcaFitterEMSel.binsMultiplicity}, true}; - SameKindPair pair{binningEvent, dcaFitterEMSel.nUseMixed, -1, collisions, tuple, &cache}; - - for (const auto& [c0, decay3bodys0, c1, decay3bodys1] : pair) { - // LOG(info) << "Processing event mixing with collisions " << c0.globalIndex() << " and " << c1.globalIndex(); - initCCDBfromRunNumber(c0.runNumber()); - - int bin_PosZ = xAxis->FindBin(c0.posZ()); - int bin_Mult = yAxis->FindBin(c0.multNTracksPV()); - registry.fill(HIST("hEventPairs"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); - - for (const auto& [d3body0, d3body1] : combinations(soa::CombinationsFullIndexPolicy(decay3bodys0, decay3bodys1))) { - - registry.fill(HIST("hDecay3BodyPairsBeforeCut"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); - - auto tpos0 = d3body0.track0_as(); - auto tneg0 = d3body0.track1_as(); - auto tbach0 = d3body0.track2_as(); - auto tpos1 = d3body1.track0_as(); - auto tneg1 = d3body1.track1_as(); - auto tbach1 = d3body1.track2_as(); - - // try to fit the vertex for decay3body0 - auto Trackpos0 = getTrackParCov(tpos0); - auto Trackneg0 = getTrackParCov(tneg0); - auto Trackbach0 = getTrackParCov(tbach0); - int nVtx0 = fitter3body.process(Trackpos0, Trackneg0, Trackbach0); - if (nVtx0 == 0) { - continue; - ; - } - - if ((tbach0.sign() > 0 && !(tbach1.sign() > 0)) || (tbach0.sign() < 0 && !(tbach1.sign() < 0)) || tbach0.globalIndex() == tbach1.globalIndex()) { // only combine if tbach1 has correct sign and is not same as tbach0 - continue; - } - - const auto& vtx0XYZ = fitter3body.getPCACandidate(); - float rVtx0 = std::hypot(vtx0XYZ[0], vtx0XYZ[1]); - registry.fill(HIST("hRadius0"), rVtx0); - - std::array ppos0 = {0.}, pneg0 = {0.}, pbach0{0.}; - const auto& propagatedtpos0 = fitter3body.getTrack(0); - const auto& propagatedtneg0 = fitter3body.getTrack(1); - const auto& propagatedtbach0 = fitter3body.getTrack(2); - propagatedtpos0.getPxPyPzGlo(ppos0); - propagatedtneg0.getPxPyPzGlo(pneg0); - propagatedtbach0.getPxPyPzGlo(pbach0); - for (int i = 0; i < 3; i++) { - pbach0[i] *= bachelorcharge; - } - std::array p3B0 = {ppos0[0] + pneg0[0] + pbach0[0], ppos0[1] + pneg0[1] + pbach0[1], ppos0[2] + pneg0[2] + pbach0[2]}; - float phiVtx0 = std::atan2(p3B0[1], p3B0[0]); - - // try to fit the vertex for decay3body1 - auto Trackpos1 = getTrackParCov(tpos1); - auto Trackneg1 = getTrackParCov(tneg1); - auto Trackbach1 = getTrackParCov(tbach1); - int nVtx1 = fitter3body.process(Trackpos1, Trackneg1, Trackbach1); - if (nVtx1 == 0) { - continue; - } - - const auto& vtx1XYZ = fitter3body.getPCACandidate(); - float rVtx1 = std::hypot(vtx1XYZ[0], vtx1XYZ[1]); - registry.fill(HIST("hRadius1"), rVtx1); - - std::array ppos1 = {0.}, pneg1 = {0.}, pbach1{0.}; - const auto& propagatedtpos1 = fitter3body.getTrack(0); - const auto& propagatedtneg1 = fitter3body.getTrack(1); - const auto& propagatedtbach1 = fitter3body.getTrack(2); - propagatedtpos1.getPxPyPzGlo(ppos1); - propagatedtneg1.getPxPyPzGlo(pneg1); - propagatedtbach1.getPxPyPzGlo(pbach1); - for (int i = 0; i < 3; i++) { - pbach1[i] *= bachelorcharge; - } - std::array p3B1 = {ppos1[0] + pneg1[0] + pbach1[0], ppos1[1] + pneg1[1] + pbach1[1], ppos1[2] + pneg1[2] + pbach1[2]}; - float phiVtx1 = std::atan2(p3B1[1], p3B1[0]); - registry.fill(HIST("hPhi0"), phiVtx0 * o2::constants::math::Rad2Deg); - registry.fill(HIST("hPhi1"), phiVtx1 * o2::constants::math::Rad2Deg); - // convert deltaPhi to range [-pi, pi] - float deltaPhi = RecoDecay::constrainAngle(phiVtx1 - phiVtx0, -o2::constants::math::PI); - // check if radius and phi of the two vertices are compatible - registry.fill(HIST("hDeltaRadius"), rVtx1 - rVtx0); - registry.fill(HIST("hDeltaPhi"), deltaPhi * o2::constants::math::Rad2Deg); - if (std::abs(deltaPhi) * o2::constants::math::Rad2Deg > dcaFitterEMSel.maxDeltaPhiColMixing || std::abs(rVtx1 - rVtx0) > dcaFitterEMSel.maxDeltaRadiusColMixing) { - continue; + // 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) { + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (std::abs(motherPi.pdgCode()) == PDG_t::kPiPlus) { + mcParticlePiTmp = motherPi; + isMuonReco = true; + break; } - registry.fill(HIST("hDecay3BodyPairsAfterCut"), xAxis->GetBinCenter(bin_PosZ), yAxis->GetBinCenter(bin_Mult)); - - fillVtxCand(c0, tpos0, tneg0, tbach1, -1, bachelorcharge, tbach1.tofNSigmaDe()); - // initCCDBfromRunNumber(c1.runNumber()); - fillVtxCand(c1, tpos1, tneg1, tbach0, -1, bachelorcharge, tbach0.tofNSigmaDe()); } } - - // Aviod break of preslice in following workflow - /*std::sort(VtxCandidates.begin(), VtxCandidates.end(), [](const VtxCandidate a, const VtxCandidate b) { - return a.collisionId < b.collisionId; - });*/ - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3ReducedEM, "Produce event-mixing background", false); - - void processRun3Reduced3bodyMixing(ReducedCollisionsMults const&, aod::RedIUTracks const&, soa::Join const& decay3bodys) - { - VtxCandidates.clear(); - - auto xAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetXaxis(); - auto yAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetYaxis(); - - for (const auto& decay3body : decay3bodys) { - int bin_Radius = xAxis->FindBin(decay3body.svRadius()); - int bin_Phi = yAxis->FindBin(decay3body.momPhi()); - registry.fill(HIST("hDecay3BodyRadiusPhi"), xAxis->GetBinCenter(bin_Radius), yAxis->GetBinCenter(bin_Phi)); - registry.fill(HIST("hDecay3BodyPosZ"), decay3body.svPosZ()); + // now loop over the pion mother + for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { + if (motherPi.globalIndex() == prDeMomID) { + return motherPi.globalIndex(); + } } - - Binning3BodyDCAFitter binningOnRadiusPhi{{dcaFitterEMSel.bins3BodyRadius, dcaFitterEMSel.bins3BodyPhiDegree}, true}; - doMixed3Body(decay3bodys, binningOnRadiusPhi); + return -1; } - PROCESS_SWITCH(decay3bodyBuilder, processRun3Reduced3bodyMixing, "Produce mixing background directly from mixed decay3bodys based on DCAFitter Info", false); - void processRun3Reduced3bodyMixingKFInfo(ReducedCollisionsMults const&, aod::RedIUTracks const&, soa::Join const& decay3bodys) + // ______________________________________________________________ + // function to reset MCInfo + void resetMCInfo(mc3Bodyinfo& mcInfo) { - VtxCandidates.clear(); - - auto xAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetXaxis(); - auto yAxis = registry.get(HIST("hDecay3BodyRadiusPhi"))->GetYaxis(); - - for (const auto& decay3body : decay3bodys) { - int bin_Radius = xAxis->FindBin(decay3body.radius()); - int bin_Phi = yAxis->FindBin(decay3body.phi()); - registry.fill(HIST("hDecay3BodyRadiusPhi"), xAxis->GetBinCenter(bin_Radius), yAxis->GetBinCenter(bin_Phi)); - registry.fill(HIST("hDecay3BodyPosZ"), decay3body.posz()); - } - - Binning3BodyKFInfo binningOnRadiusPhi{{dcaFitterEMSel.bins3BodyRadius, dcaFitterEMSel.bins3BodyPhi}, true}; - doMixed3Body(decay3bodys, binningOnRadiusPhi); + mcInfo.label = -1; + mcInfo.genMomentum[0] = -1., mcInfo.genMomentum[1] = -1., mcInfo.genMomentum[2] = -1.; + mcInfo.genDecVtx[0] = -1., mcInfo.genDecVtx[1] = -1., mcInfo.genDecVtx[2] = -1.; + mcInfo.genCt = -1.; + mcInfo.genPhi = -1., mcInfo.genEta = -1., mcInfo.genRapidity = -1.; + mcInfo.genMomProton = -1., mcInfo.genMomPion = -1., mcInfo.genMomDeuteron = -1.; + mcInfo.genPtProton = -1., mcInfo.genPtPion = -1., mcInfo.genPtDeuteron = -1.; + mcInfo.isTrueH3L = false, mcInfo.isTrueAntiH3L = false; + mcInfo.isReco = false; + mcInfo.motherPdgCode = -1; + mcInfo.daughterPrPdgCode = -1, mcInfo.daughterPiPdgCode = -1, mcInfo.daughterDePdgCode = -1; + mcInfo.isDeuteronPrimary = false; + mcInfo.survivedEventSel = false; + return; } - PROCESS_SWITCH(decay3bodyBuilder, processRun3Reduced3bodyMixingKFInfo, "Produce mixing background directly from mixed decay3bodys based on KF Info", false); - //------------------------------------------------------------------ - void processRun3withKFParticle(ColwithEvTimes const& collisions, TrackExtPIDIUwithEvTimes const&, aod::Decay3Bodys const& decay3bodys, aod::BCsWithTimestamps const&) + // ______________________________________________________________ + // process functions + void processRealData(ColswithEvTimes const& collisions, + aod::Decay3Bodys const& decay3bodys, + aod::Tracked3Bodys const& tracked3bodys, + TracksExtPIDIUwithEvTimes const&, + aod::BCsWithTimestamps const& bcs) { - for (const auto& collision : collisions) { - - auto bc = collision.bc_as(); - initCCDB(bc); - LOG(debug) << "CCDB initialised."; - - // Zorro event counting - bool isZorroSelected = false; - if (kfparticleConfigurations.cfgSkimmedProcessing) { - isZorroSelected = zorro.isSelected(collision.template bc_as().globalBC()); - if (isZorroSelected) { - registry.fill(HIST("Counters/hEventCounterZorro"), 0.); - } else { - if (kfparticleConfigurations.cfgOnlyKeepInterestedTrigger) { - continue; - } - } - } - - // event selection - registry.fill(HIST("Counters/hEventCounterKFParticle"), 0.5); - if (kfparticleConfigurations.doSel8selection && !collision.sel8()) { - continue; - } - registry.fill(HIST("Counters/hEventCounterKFParticle"), 1.5); - if (kfparticleConfigurations.doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { - continue; - } - registry.fill(HIST("Counters/hEventCounterKFParticle"), 2.5); - registry.fill(HIST("QA/Event/hAllSelEventsVtxZ"), collision.posZ()); - - if (isZorroSelected) { - registry.fill(HIST("Counters/hEventCounterZorro"), 1.); - } - - // slice Decay3Body table by collision - const uint64_t collIdx = collision.globalIndex(); - auto Decay3BodyTable_thisCollision = decay3bodys.sliceBy(perCollision, collIdx); - for (auto& vtx3body : Decay3BodyTable_thisCollision) { - auto trackPos = vtx3body.template track0_as(); - auto trackNeg = vtx3body.template track1_as(); - auto trackBach = vtx3body.template track2_as(); - buildVtx3BodyDataTableKFParticle(collision, trackPos, trackNeg, trackBach, vtx3body.globalIndex(), bachelorcharge, getTOFnSigma(collision, trackBach, false /*isEventMixing*/)); - LOG(debug) << "End of processKFParticle."; - } + // initialise CCDB from BCs + if (!initCCDB(bcs, collisions)) { + LOG(info) << "CCDB initialisation failed, skipping candidate building." << std::endl; + return; } - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticle, "Produce KFParticle decay3body tables", false); - void processRun3withKFParticleStrangenessTracking(ColwithEvTimes const& collisions, TrackExtPIDIUwithEvTimes const& tracks, aod::Decay3Bodys const& decay3bodys, aod::Tracked3Bodys const& tracked3bodys, aod::BCsWithTimestamps const& bcs) - { + // get tracked cluster size info fTrackedClSizeVector.clear(); fTrackedClSizeVector.resize(decay3bodys.size(), 0); for (const auto& tvtx3body : tracked3bodys) { fTrackedClSizeVector[tvtx3body.decay3BodyId()] = tvtx3body.itsClsSize(); } - processRun3withKFParticle(collisions, tracks, decay3bodys, bcs); - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleStrangenessTracking, "Produce KFParticle strangeness tracked decay3body tables", false); - - void processRun3withKFParticleReduced(aod::RedCollisions const& collisions, aod::RedIUTracks const&, aod::RedDecay3Bodys const& decay3bodys) - { - int lastRunNumber = -1; - for (const auto& collision : collisions) { - // set magnetic field only when run number changes - if (collision.runNumber() != lastRunNumber) { - initCCDBfromRunNumber(collision.runNumber()); - lastRunNumber = collision.runNumber(); // Update the last run number - LOG(debug) << "CCDB initialized for run " << lastRunNumber; - } - - // event selection - registry.fill(HIST("Counters/hEventCounterKFParticle"), 2.5); - registry.fill(HIST("QA/Event/hAllSelEventsVtxZ"), collision.posZ()); - - // slice Decay3Body table by collision - const uint64_t collIdx = collision.globalIndex(); - auto Decay3BodyTable_thisCollision = decay3bodys.sliceBy(perReducedCollision, collIdx); - for (auto& vtx3body : Decay3BodyTable_thisCollision) { - auto trackPos = vtx3body.template track0_as(); - auto trackNeg = vtx3body.template track1_as(); - auto trackBach = vtx3body.template track2_as(); - buildVtx3BodyDataTableKFParticle(collision, trackPos, trackNeg, trackBach, vtx3body.globalIndex(), bachelorcharge, trackBach.tofNSigmaDe()); - } - LOG(debug) << "End of processKFParticleDerived."; - } + // do candidate analysis without MC processing + buildCandidates(bcs, // bc table + collisions, // collision table + decay3bodys, // decay3body table + static_cast(nullptr), // MC particle table + static_cast(nullptr)); // MC collision table } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleReduced, "Produce KFParticle decay3body tables from derived decay3body data", false); - - void processRun3withKFParticleReducedEM(ReducedCollisionsMults const& collisions, aod::RedIUTracks const&, aod::RedDecay3Bodys const& decay3bodys) - { - // ------------- Check number of events in bins -------------- - // Define a 2D array to count events and pairs per bin - std::vector> binEventCounts(10, std::vector(13, 0)); // 10 vtxZ bins, 13 multiplicity bins - std::vector> binPairCounts(10, std::vector(13, 0)); - - // Function to find bin index (returns -1 if out of range) - auto findBin = [](float value, const std::vector& binEdges) -> int { - for (size_t i = 0; i < binEdges.size() - 1; ++i) { - if (value > binEdges[i] && value <= binEdges[i + 1]) { - return i; - } - } - return -1; // Shouldn't happen if events are within range - }; - // Loop over all collisions to count them in bins - for (auto& collision : collisions) { - float vtxZ = collision.posZ(); - float mult = collision.multNTracksPV(); - - // Determine bin indices - int vtxZBin = findBin(vtxZ, {-10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}); - int multBin = findBin(mult, {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}); - - if (vtxZBin >= 0 && multBin >= 0) { - binEventCounts[vtxZBin][multBin]++; - } - } - // Print out the number of events per bin - LOG(info) << "Event count per bin (vtxZ, mult):"; - for (size_t i = 0; i < binEventCounts.size(); ++i) { - for (size_t j = 0; j < binEventCounts[i].size(); ++j) { - LOG(info) << "Bin (" << i << ", " << j << "): " << binEventCounts[i][j] << " events"; - } - } - // Fill histogram with numbers per bin - for (size_t i = 0; i < binEventCounts.size(); ++i) { - for (size_t j = 0; j < binEventCounts[i].size(); ++j) { - registry.fill(HIST("QA/EM/hEventBinCounts"), i, j, binEventCounts[i][j]); - } - } - LOG(info) << "Integral of hEventBinCounts:" << registry.get(HIST("QA/EM/hEventBinCounts"))->Integral(); - - // ------------- Check number of decay3bodys in bins ------------- - // Define a 2D array to count events and pairs per bin - std::vector> binDecay3BodyCounts(10, std::vector(13, 0)); // 10 vtxZ bins, 13 multiplicity bins - // Loop over all decay3bodys to count them in bins - for (auto& decay3body : decay3bodys) { - auto collision = decay3body.template collision_as(); - float vtx3bodyZ = collision.posZ(); - float mult3body = collision.multNTracksPV(); - - // Determine bin indices - int vtx3bodyZBin = findBin(vtx3bodyZ, {-10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}); - int mult3bodyBin = findBin(mult3body, {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}); - - if (vtx3bodyZBin >= 0 && mult3bodyBin >= 0) { - binDecay3BodyCounts[vtx3bodyZBin][mult3bodyBin]++; - } - } - // Print out the number of events per bin - LOG(debug) << "Event count per bin (vtxZ, mult):"; - for (size_t i = 0; i < binDecay3BodyCounts.size(); ++i) { - for (size_t j = 0; j < binDecay3BodyCounts[i].size(); ++j) { - LOG(debug) << "Bin (" << i << ", " << j << "): " << binDecay3BodyCounts[i][j] << " events"; - } - } - // Fill histogram with numbers per bin - for (size_t i = 0; i < binDecay3BodyCounts.size(); ++i) { - for (size_t j = 0; j < binDecay3BodyCounts[i].size(); ++j) { - registry.fill(HIST("QA/EM/h3bodyBinCounts"), i, j, binDecay3BodyCounts[i][j]); - } - } - LOG(info) << "Integral of h3bodyBinCounts:" << registry.get(HIST("QA/EM/h3bodyBinCounts"))->Integral(); - - // ------------- Do event mixing -------------- - auto tuple = std::make_tuple(decay3bodys); - BinningTypeKF binningOnPosAndMult{{kfparticleConfigurations.binsVtxZ, kfparticleConfigurations.binsMultiplicity}, true}; // ignore over-/underflow - SameKindPair pair{binningOnPosAndMult, kfparticleConfigurations.nEvtMixing, -1, collisions, tuple, &cache}; // indicates that under/overflow (-1) to be ignored - - int lastRunNumber = -1; - - for (auto& [c1, decays3body1, c2, decays3body2] : pair) { - registry.fill(HIST("QA/EM/hPairCounterMixing"), 0.5); - - // event selection already applied in reducer task - - // set magnetic field only when run number changes - if (c1.runNumber() != lastRunNumber) { - initCCDBfromRunNumber(c1.runNumber()); - lastRunNumber = c1.runNumber(); // Update the last run number - LOG(debug) << "CCDB initialized for run " << lastRunNumber; - } - // Get vtxZ and multiplicity from collision - float vtxZpair = c1.posZ(); - float multpair = c1.multNTracksPV(); - // Find the bin index - int vtxZpairBin = findBin(vtxZpair, {-10.0f, -8.f, -6.f, -4.f, -2.f, 0.f, 2.f, 4.f, 6.f, 8.f, 10.f}); - int multpairBin = findBin(multpair, {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}); - if (vtxZpairBin >= 0 && multpairBin >= 0) { - binPairCounts[vtxZpairBin][multpairBin]++; // Count the pair - } - - for (auto& [decay3body1, decay3body2] : soa::combinations(soa::CombinationsFullIndexPolicy(decays3body1, decays3body2))) { - auto trackPos1 = decay3body1.template track0_as(); - auto trackNeg1 = decay3body1.template track1_as(); - auto trackBach1 = decay3body1.template track2_as(); - auto trackPos2 = decay3body2.template track0_as(); - auto trackNeg2 = decay3body2.template track1_as(); - auto trackBach2 = decay3body2.template track2_as(); - - registry.fill(HIST("QA/EM/hCombinationCounterMixing"), 0.5); - - // ---------- selections bachelor track ---------- - if ((trackBach1.sign() > 0 && !(trackBach2.sign() > 0)) || (trackBach1.sign() < 0 && !(trackBach2.sign() < 0)) || trackBach1.globalIndex() == trackBach2.globalIndex()) { // only combine if trackBach2 has correct sign and is not same as trackBach1 - continue; - } - registry.fill(HIST("QA/EM/hCombinationCounterMixing"), 1.5); - - // ---------- check radius and phi of decay3bodys ---------- - auto trackParCovPos1 = getTrackParCov(trackPos1); - auto trackParCovNeg1 = getTrackParCov(trackNeg1); - auto trackParCovBach1 = getTrackParCov(trackBach1); - auto trackParCovPos2 = getTrackParCov(trackPos2); - auto trackParCovNeg2 = getTrackParCov(trackNeg2); - auto trackParCovBach2 = getTrackParCov(trackBach2); - // create KFParticle objects from tracks - KFParticle kfpProton1, kfpPion1, kfpDeuteron1; - if (trackBach1.sign() > 0) { - kfpProton1 = createKFParticleFromTrackParCov(trackParCovPos1, trackPos1.sign(), constants::physics::MassProton); - kfpPion1 = createKFParticleFromTrackParCov(trackParCovNeg1, trackNeg1.sign(), constants::physics::MassPionCharged); - } else if (!(trackBach1.sign() > 0)) { - kfpProton1 = createKFParticleFromTrackParCov(trackParCovNeg1, trackNeg1.sign(), constants::physics::MassProton); - kfpPion1 = createKFParticleFromTrackParCov(trackParCovPos1, trackPos1.sign(), constants::physics::MassPionCharged); - } - kfpDeuteron1 = createKFParticleFromTrackParCov(trackParCovBach1, trackBach1.sign() * bachelorcharge, constants::physics::MassDeuteron); - KFParticle kfpProton2, kfpPion2, kfpDeuteron2; - if (trackBach2.sign() > 0) { - kfpProton2 = createKFParticleFromTrackParCov(trackParCovPos2, trackPos2.sign(), constants::physics::MassProton); - kfpPion2 = createKFParticleFromTrackParCov(trackParCovNeg2, trackNeg2.sign(), constants::physics::MassPionCharged); - } else if (!(trackBach2.sign() > 0)) { - kfpProton2 = createKFParticleFromTrackParCov(trackParCovNeg2, trackNeg2.sign(), constants::physics::MassProton); - kfpPion2 = createKFParticleFromTrackParCov(trackParCovPos2, trackPos2.sign(), constants::physics::MassPionCharged); - } - kfpDeuteron2 = createKFParticleFromTrackParCov(trackParCovBach2, trackBach2.sign() * bachelorcharge, constants::physics::MassDeuteron); - // fit vertices - KFParticle KFHt1, KFHt2; - fit3bodyVertex(kfpProton1, kfpPion1, kfpDeuteron1, KFHt1); - fit3bodyVertex(kfpProton2, kfpPion2, kfpDeuteron2, KFHt2); - - // ---------- select common radius and phi region ---------- - auto radius1 = std::sqrt(KFHt1.GetX() * KFHt1.GetX() + KFHt1.GetY() * KFHt1.GetY()); - auto radius2 = std::sqrt(KFHt2.GetX() * KFHt2.GetX() + KFHt2.GetY() * KFHt2.GetY()); - registry.fill(HIST("QA/EM/hRadius1"), radius1); - registry.fill(HIST("QA/EM/hRadius2"), radius2); - registry.fill(HIST("QA/EM/hPhi1"), KFHt1.GetPhi() * (180.0 / TMath::Pi())); - registry.fill(HIST("QA/EM/hPhi2"), KFHt2.GetPhi() * (180.0 / TMath::Pi())); - registry.fill(HIST("QA/EM/hDeltaRadius"), std::abs(radius1 - radius2)); - registry.fill(HIST("QA/EM/hDeltaPhi"), std::abs(KFHt1.GetPhi() - KFHt2.GetPhi()) * (180.0 / TMath::Pi())); - if (std::abs(KFHt1.GetPhi() - KFHt2.GetPhi()) * (180.0 / TMath::Pi()) > 10 || std::abs(radius1 - radius2) > 2) { - continue; - } - registry.fill(HIST("QA/EM/hCombinationCounterMixing"), 2.5); - - // fill 2D pair counter per bin - registry.fill(HIST("QA/EM/hPairBinCounts"), vtxZpairBin, multpairBin, 1); - - // ---------- do candidate analysis ---------- - buildVtx3BodyDataTableKFParticle(c1, trackPos1, trackNeg1, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - } // end decay3body combinations loop - } // end pairing loop - } // end process - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleReducedEM, "Produce KFParticle event mixing decay3body tables from derived decay3body data", false); - - void processRun3withKFParticleReduced3bodyMixing(ReducedCollisionsMults const&, aod::RedIUTracks const&, soa::Join const& decay3bodys) + void processRealDataReduced(aod::RedCollisions const& collisions, + soa::Join const& decay3bodys, + aod::RedIUTracks const&) { - // Define a 2D array to count 3bodies per bin (radius, phi, posZ) - std::vector> bin3bodyCounts(16, std::vector(36, 0)); - - // Function to find bin index (returns -1 if out of range) - auto findBin = [](float value, const std::vector& binEdges) -> int { - for (size_t i = 0; i < binEdges.size() - 1; ++i) { - if (value > binEdges[i] && value <= binEdges[i + 1]) { - return i; - } - } - return -1; // Out of range - }; - - int counter = 0; - // Loop over all collisions to count them in bins - for (auto& decay3body : decay3bodys) { - counter++; - float radius = decay3body.radius(); - float phi = decay3body.phi(); - float posZ = decay3body.posz(); - - registry.fill(HIST("QA/EM/hRadius"), radius); - registry.fill(HIST("QA/EM/hPhi"), phi); - registry.fill(HIST("QA/EM/hPosZ"), posZ); - - // float degToRad = TMath::Pi()/180; - - // Determine bin indices - int radiusBin = findBin(radius, {0.0f, 0.5f, 1.0f, 1.5f, 2.0f, 3.0f, 4.0f, 6.0f, 8.0f, 10.0f, 12.0f, 14.0f, 16.0f, 18.0f, 20.0f, 30.0f, 1000.0}); - int phiBin = findBin(phi, {-180.0f * TMath::Pi() / 180, -160.0f * TMath::Pi() / 180, -140.0f * TMath::Pi() / 180, -120.0f * TMath::Pi() / 180, -100.0f * TMath::Pi() / 180, -80.0f * TMath::Pi() / 180, -60.0f * TMath::Pi() / 180, -40.0f * TMath::Pi() / 180, -20.0f * TMath::Pi() / 180, 0.0f, 20.0f * TMath::Pi() / 180, 40.0f * TMath::Pi() / 180, 60.0f * TMath::Pi() / 180, 80.0f * TMath::Pi() / 180, 100.0f * TMath::Pi() / 180, 120.0f * TMath::Pi() / 180, 140.0f * TMath::Pi() / 180, 160.0f * TMath::Pi() / 180, 180.0f * TMath::Pi() / 180}); - if (radiusBin >= 0 && phiBin >= 0) { // && posZBin >= 0) { - bin3bodyCounts[radiusBin][phiBin]++; //[posZBin]++; - } - } - LOG(info) << "3body counter: " << counter; - - // Print out the number of 3-body decays per bin - LOG(info) << "3body count per bin (radius, phi, posZ):"; - for (size_t i = 0; i < bin3bodyCounts.size(); ++i) { - for (size_t j = 0; j < bin3bodyCounts[i].size(); ++j) { - LOG(info) << "Bin (" << i << ", " << j << "): " << bin3bodyCounts[i][j] << " 3bodies"; - } - } - // Fill 3D histogram with numbers per bin - for (size_t i = 0; i < bin3bodyCounts.size(); ++i) { - for (size_t j = 0; j < bin3bodyCounts[i].size(); ++j) { - registry.fill(HIST("QA/EM/h3bodyBinCounts"), i, j, bin3bodyCounts[i][j]); - } - } - LOG(info) << "Integral of h3bodyBinCounts: " << registry.get(HIST("QA/EM/h3bodyBinCounts"))->Integral(); - - Binning3Body binningOnRadPhi{{kfparticleConfigurations.bins3BodyRadius, kfparticleConfigurations.bins3BodyPhi}, true}; - - // Strictly upper index policy for decay3body objects binned by radius, phi and z position - for (auto& [decay3body1, decay3body2] : selfPairCombinations(binningOnRadPhi, kfparticleConfigurations.nEvtMixing, -1, decay3bodys)) { - auto trackPos1 = decay3body1.template track0_as(); - auto trackNeg1 = decay3body1.template track1_as(); - auto trackBach1 = decay3body1.template track2_as(); - auto trackPos2 = decay3body2.template track0_as(); - auto trackNeg2 = decay3body2.template track1_as(); - auto trackBach2 = decay3body2.template track2_as(); - - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 0.5); - - // collision vertex selections - auto collision1 = decay3body1.template collision_as(); - auto collision2 = decay3body2.template collision_as(); - initCCDBfromRunNumber(collision2.runNumber()); - initCCDBfromRunNumber(collision1.runNumber()); - - if (decay3body1.collisionId() == decay3body2.collisionId()) { // only combine if from different event - continue; - } - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 1.5); - if (kfparticleConfigurations.selectVtxZ3bodyMixing && std::abs(collision1.posZ() - collision2.posZ()) > kfparticleConfigurations.VtxZBin3bodyMixing) { // only combine if collision similar in VtxZ - continue; - } - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 2.5); - - // ---------- selections ---------- - if ((trackBach1.sign() > 0 && !(trackBach2.sign() > 0)) || (trackBach1.sign() < 0 && !(trackBach2.sign() < 0)) || trackBach1.globalIndex() == trackBach2.globalIndex()) { // only combine if trackBach2 has correct sign and is not same as trackBach1 - continue; - } - registry.fill(HIST("QA/EM/h3bodyCombinationCounter"), 3.5); - - // ---------- do candidate analysis ---------- - bool isMatter1 = false; - if (trackBach1.sign() > 0) { - isMatter1 = true; - } - if (kfparticleConfigurations.mixingType == 0) { // mix deuteron - buildVtx3BodyDataTableKFParticle(collision1, trackPos1, trackNeg1, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - buildVtx3BodyDataTableKFParticle(collision2, trackPos2, trackNeg2, trackBach1, -1 /*vtx3bodyID*/, bachelorcharge, trackBach1.tofNSigmaDe()); - } else if (kfparticleConfigurations.mixingType == 1) { // mix proton - if (isMatter1 == true) { - buildVtx3BodyDataTableKFParticle(collision1, trackPos2, trackNeg1, trackBach1, -1 /*vtx3bodyID*/, bachelorcharge, trackBach1.tofNSigmaDe()); - buildVtx3BodyDataTableKFParticle(collision2, trackPos1, trackNeg2, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - } else if (isMatter1 == false) { - buildVtx3BodyDataTableKFParticle(collision1, trackPos1, trackNeg2, trackBach1, -1 /*vtx3bodyID*/, bachelorcharge, trackBach1.tofNSigmaDe()); - buildVtx3BodyDataTableKFParticle(collision2, trackPos2, trackNeg1, trackBach2, -1 /*vtx3bodyID*/, bachelorcharge, trackBach2.tofNSigmaDe()); - } - } - } // end decay3body combinations loop - } - PROCESS_SWITCH(decay3bodyBuilder, processRun3withKFParticleReduced3bodyMixing, "Produce KFParticle mixed decay3body tables from derived decay3body data", false); -}; - -// build link from decay3body -> vtx3body -struct decay3bodyDataLinkBuilder { - Produces VtxDataLink; - - void init(InitContext const&) {} - - template - void buildDecay3BodyLabel(TDecay3Bodys const& decay3bodytable, TVtx3BodyDatas const& vtxdatatable) - { - std::vector lIndices; - lIndices.reserve(decay3bodytable.size()); - for (int ii = 0; ii < decay3bodytable.size(); ii++) - lIndices[ii] = -1; - for (const auto& vtxdata : vtxdatatable) { - if (vtxdata.decay3bodyId() != -1) { - lIndices[vtxdata.decay3bodyId()] = vtxdata.globalIndex(); - } - } - for (int ii = 0; ii < decay3bodytable.size(); ii++) { - VtxDataLink(lIndices[ii]); + // get tracked cluster size info (saved in aod::Red3BodyInfo) + fTrackedClSizeVector.clear(); + fTrackedClSizeVector.resize(decay3bodys.size(), 0); + for (const auto& vtx3body : decay3bodys) { + fTrackedClSizeVector[vtx3body.globalIndex()] = vtx3body.trackedClSize(); } - } - void processStandard(aod::Decay3Bodys const& decay3bodytable, aod::Vtx3BodyDatas const& vtxdatatable) - { - buildDecay3BodyLabel(decay3bodytable, vtxdatatable); + // do candidate analysis without MC processing + buildCandidates(static_cast(nullptr), // bc table + collisions, // collision table + decay3bodys, // decay3body table + static_cast(nullptr), // MC particle table + static_cast(nullptr)); // MC collision table } - PROCESS_SWITCH(decay3bodyDataLinkBuilder, processStandard, "Produce label from decay3body to vtx3body", true); - void processReduced(aod::RedDecay3Bodys const& decay3bodytable, aod::Vtx3BodyDatas const& vtxdatatable) + void processRealDataReduced3bodyMixing(aod::RedCollisions const&, + soa::Join const& decay3bodys, + aod::RedIUTracks const&) { - buildDecay3BodyLabel(decay3bodytable, vtxdatatable); - } - PROCESS_SWITCH(decay3bodyDataLinkBuilder, processReduced, "Produce label from reducedDecay3body to vtx3body", false); -}; - -struct kfdecay3bodyDataLinkBuilder { - Produces kfvtxdataLink; + auto xAxis = registry.get(HIST("Mixing/hDecay3BodyRadiusPhi"))->GetXaxis(); + auto yAxis = registry.get(HIST("Mixing/hDecay3BodyRadiusPhi"))->GetYaxis(); - void init(InitContext const&) {} - - template - void buildDataLink(TDecay3Bodys const& decay3bodytable, TVtx3BodyDatas const& vtxdatatable) - { - std::vector lIndices; - lIndices.reserve(decay3bodytable.size()); - for (int ii = 0; ii < decay3bodytable.size(); ii++) - lIndices[ii] = -1; - for (auto& vtxdata : vtxdatatable) { - if (vtxdata.decay3bodyId() != -1) { - lIndices[vtxdata.decay3bodyId()] = vtxdata.globalIndex(); + for (const auto& decay3body : decay3bodys) { + int bin_Radius, bin_Phi; + if (decay3bodyBuilderOpts.useKFParticle) { + bin_Radius = xAxis->FindBin(decay3body.radiusKF()); + bin_Phi = yAxis->FindBin(decay3body.phiKF()); + registry.fill(HIST("Mixing/hDecay3BodyPosZ"), decay3body.poszKF()); + } else { + bin_Radius = xAxis->FindBin(decay3body.radiusDCA()); + bin_Phi = yAxis->FindBin(decay3body.phiDCA()); + registry.fill(HIST("Mixing/hDecay3BodyPosZ"), decay3body.poszDCA()); } + registry.fill(HIST("Mixing/hDecay3BodyRadiusPhi"), xAxis->GetBinCenter(bin_Radius), yAxis->GetBinCenter(bin_Phi)); } - for (int ii = 0; ii < decay3bodytable.size(); ii++) { - kfvtxdataLink(lIndices[ii]); - } - } - - void processStandard(aod::Decay3Bodys const& decay3bodytable, aod::KFVtx3BodyDatas const& vtxdatatable) - { - buildDataLink(decay3bodytable, vtxdatatable); // build Decay3Body -> KFDecay3BodyData link table - } - PROCESS_SWITCH(kfdecay3bodyDataLinkBuilder, processStandard, "Build data link table.", true); - void processReduced(aod::RedDecay3Bodys const& decay3bodytable, aod::KFVtx3BodyDatas const& vtxdatatable) - { - buildDataLink(decay3bodytable, vtxdatatable); // build ReducedDecay3Body -> KFDecay3BodyData link table - } - PROCESS_SWITCH(kfdecay3bodyDataLinkBuilder, processReduced, "Build data link table for reduced data.", false); -}; - -struct decay3bodyLabelBuilder { - - Produces vtxlabels; - Produces vtxfulllabels; - - HistogramRegistry registry{"registry", {}}; - - void init(InitContext const&) - { - if (doprocessDoNotBuildLabels == false) { - auto hLabelCounter = registry.add("hLabelCounter", "hLabelCounter", HistType::kTH1D, {{3, 0.0f, 3.0f}}); - hLabelCounter->GetXaxis()->SetBinLabel(1, "Total"); - hLabelCounter->GetXaxis()->SetBinLabel(2, "Have Same MotherTrack"); - hLabelCounter->GetXaxis()->SetBinLabel(3, "True H3L"); - - registry.add("hHypertritonMCPt", "hHypertritonMCPt", HistType::kTH1F, {{100, 0.0f, 10.0f}}); - registry.add("hAntiHypertritonMCPt", "hAntiHypertritonMCPt", HistType::kTH1F, {{100, 0.0f, 10.0f}}); - registry.add("hHypertritonMCMass", "hHypertritonMCMass", HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}); - registry.add("hAntiHypertritonMCMass", "hAntiHypertritonMCMass", HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}); - registry.add("hHypertritonMCLifetime", "hHypertritonMCLifetime", HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}); - registry.add("hAntiHypertritonMCLifetime", "hAntiHypertritonMCLifetime", HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}); + if (decay3bodyBuilderOpts.useKFParticle) { + Binning3BodyKF binningOnRadPhiKF{{mixingOpts.bins3BodyRadius, mixingOpts.bins3BodyPhi}, true}; + buildMixedCandidates(decay3bodys, binningOnRadPhiKF); + } else { + Binning3BodyDCAfitter binningOnRadPhiDCA{{mixingOpts.bins3BodyRadius, mixingOpts.bins3BodyPhi}, true}; + buildMixedCandidates(decay3bodys, binningOnRadPhiDCA); } } - Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; - - void processDoNotBuildLabels(aod::Decay3BodyDataLink const&) // is it possible to have none parameter? + void processMonteCarlo(ColswithEvTimesLabeled const& collisions, + aod::Decay3Bodys const& decay3bodys, + aod::Tracked3Bodys const& tracked3bodys, + TracksExtPIDIUwithEvTimesLabeled const&, + aod::BCsWithTimestamps const& bcs, + aod::McParticles const& mcParticles, + aod::McCollisions const& mcCollisions) { - // dummy process function - should not be required in the future - }; - PROCESS_SWITCH(decay3bodyLabelBuilder, processDoNotBuildLabels, "Do not produce MC label tables", true); - - void processBuildLabels(aod::Decay3BodysLinked const& decay3bodys, aod::Vtx3BodyDatas const& vtx3bodydatas, MCLabeledTracksIU const&, aod::McParticles const&) - { - std::vector lIndices; - lIndices.reserve(vtx3bodydatas.size()); - for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { - lIndices[ii] = -1; + // initialise CCDB from BCs + if (!initCCDB(bcs, collisions)) { + LOG(info) << "CCDB initialisation failed, skipping candidate building." << std::endl; + return; } - for (const auto& decay3body : decay3bodys) { - - int lLabel = -1; - int lPDG = -1; - float lPt = -1; - double MClifetime = -1; - bool is3bodyDecay = false; - int lGlobalIndex = -1; - - auto lTrack0 = decay3body.track0_as(); - auto lTrack1 = decay3body.track1_as(); - auto lTrack2 = decay3body.track2_as(); - registry.fill(HIST("hLabelCounter"), 0.5); - - // Association check - // There might be smarter ways of doing this in the future - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - vtxfulllabels(-1); - continue; - } - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - vtxfulllabels(-1); - continue; - } - - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lGlobalIndex = lMother1.globalIndex(); - lPt = lMother1.pt(); - lPDG = lMother1.pdgCode(); - MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); // only for hypertriton - is3bodyDecay = true; // vtxs with the same mother - } - } - } - } // end association check - if (!is3bodyDecay) { - vtxfulllabels(-1); - continue; - } - registry.fill(HIST("hLabelCounter"), 1.5); - - // Intended for hypertriton cross-checks only - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - lLabel = lGlobalIndex; - double hypertritonMCMass = RecoDecay::m(std::array{std::array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, std::array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, std::array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hHypertritonMCPt"), lPt); - registry.fill(HIST("hHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - lLabel = lGlobalIndex; - double antiHypertritonMCMass = RecoDecay::m(std::array{std::array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, std::array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, std::array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hAntiHypertritonMCPt"), lPt); - registry.fill(HIST("hAntiHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); - } - - // Construct label table, only vtx which corresponds to true mother and true daughters with a specified order is labeled - // for matter: track0->p, track1->pi, track2->bachelor - // for antimatter: track0->pi, track1->p, track2->bachelor - vtxfulllabels(lLabel); - if (decay3body.vtx3BodyDataId() != -1) { - lIndices[decay3body.vtx3BodyDataId()] = lLabel; - } - } - for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { - vtxlabels(lIndices[ii]); + // get tracked cluster size info + fTrackedClSizeVector.clear(); + fTrackedClSizeVector.resize(decay3bodys.size(), 0); + for (const auto& tvtx3body : tracked3bodys) { + fTrackedClSizeVector[tvtx3body.decay3BodyId()] = tvtx3body.itsClsSize(); } + + // do candidate analysis with MC processing + buildCandidates(bcs, // bc table + collisions, // collision table + decay3bodys, // decay3body table + mcParticles, // MC particle table + mcCollisions); // MC collision table } - PROCESS_SWITCH(decay3bodyLabelBuilder, processBuildLabels, "Produce MC label tables", false); -}; -struct decay3bodyInitializer { - Spawns vtx3bodydatas; - void init(InitContext const&) {} + PROCESS_SWITCH(decay3bodyBuilder, processRealData, "process real data", true); + PROCESS_SWITCH(decay3bodyBuilder, processRealDataReduced, "process real reduced data", false); + PROCESS_SWITCH(decay3bodyBuilder, processRealDataReduced3bodyMixing, "process real reduced data", false); + PROCESS_SWITCH(decay3bodyBuilder, processMonteCarlo, "process monte carlo", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + metadataInfo.initMetadata(cfgc); return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx index ae78ecdb735..bdb0c4a2058 100644 --- a/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx +++ b/PWGLF/TableProducer/Nuspex/ebyeMaker.cxx @@ -13,64 +13,64 @@ /// \brief table producer for e-by-e analysis in LF /// \author Mario Ciacco -#include -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/LFEbyeTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/PID/PIDTOF.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 "PWGLF/DataModel/LFStrangenessTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "Common/Core/PID/PIDTOF.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" -#include "CCDB/CcdbApi.h" -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Common/DataModel/PIDResponse.h" +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "DCAFitter/DCAFitterN.h" - -#include "PWGLF/DataModel/LFEbyeTables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" #include "TFormula.h" +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using TracksFull = soa::Join; using TracksFullPID = soa::Join; -using TracksFullIU = soa::Join; +using TracksFullIUPID = soa::Join; using BCsWithRun2Info = soa::Join; namespace { constexpr int kNpart = 2; -constexpr float trackSels[12]{/* 60, */ 80, 100, 2, 3, /* 4, */ 0.05, 0.1, /* 0.15, */ 0.5, 1, /* 1.5, */ 2, 3 /* , 4 */, 2, 3, /*, 4 */}; -constexpr float dcaSels[3]{10., 10., 10.}; -constexpr double betheBlochDefault[kNpart][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; -constexpr double betheBlochDefaultITS[6]{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}; -constexpr double estimatorsCorrelationCoef[2]{-0.669108, 1.04489}; -constexpr double estimatorsSigmaPars[4]{0.933321, 0.0416976, -0.000936344, 8.92179e-06}; -constexpr double deltaEstimatorNsigma[2]{5.5, 5.}; -constexpr double partMass[kNpart]{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}; -constexpr double partPdg[kNpart]{2212, o2::constants::physics::kDeuteron}; +constexpr float kTrackSels[12]{/* 60, */ 80, 100, 2, 3, /* 4, */ 0.05, 0.1, /* 0.15, */ 0.5, 1, /* 1.5, */ 2, 3 /* , 4 */, 2, 3, /*, 4 */}; +constexpr float kDcaSels[3]{10., 10., 10.}; +constexpr double kBetheBlochDefault[kNpart][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}, {-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; +constexpr double kBetheBlochDefaultITS[6]{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}; +constexpr double kEstimatorsCorrelationCoef[2]{-0.669108, 1.04489}; +constexpr double kEstimatorsSigmaPars[4]{0.933321, 0.0416976, -0.000936344, 8.92179e-06}; +constexpr double kDeltaEstimatorNsigma[2]{5.5, 5.}; +constexpr double kPartMass[kNpart]{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}; +constexpr double kPartPdg[kNpart]{PDG_t::kProton, o2::constants::physics::kDeuteron}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; static const std::vector particleNamesPar{"p", "d"}; static const std::vector trackSelsNames{"tpcClsMid", "tpcClsTight", "chi2TpcTight", "chi2TpcMid", "dcaxyTight", "dcaxyMid", "dcazTight", "dcazMid", "tpcNsigmaTight", "tpcNsigmaMid", "itsNsigmaTight", "itsNsigmaMid"}; @@ -83,16 +83,6 @@ void momTotXYZ(std::array& momA, std::array const& momB, std momA[i] = momB[i] + momC[i]; } } -float invMass2Body(std::array const& momA, std::array const& momB, std::array const& momC, float const& massB, float const& massC) -{ - float p2B = momB[0] * momB[0] + momB[1] * momB[1] + momB[2] * momB[2]; - float p2C = momC[0] * momC[0] + momC[1] * momC[1] + momC[2] * momC[2]; - float eB = std::sqrt(p2B + massB * massB); - float eC = std::sqrt(p2C + massC * massC); - float eA = eB + eC; - float massA = std::sqrt(eA * eA - momA[0] * momA[0] - momA[1] * momA[1] - momA[2] * momA[2]); - return massA; -} float alphaAP(std::array const& momA, std::array const& momB, std::array const& momC) { float momTot = std::sqrt(std::pow(momA[0], 2.) + std::pow(momA[1], 2.) + std::pow(momA[2], 2.)); @@ -100,26 +90,6 @@ float alphaAP(std::array const& momA, std::array const& momB float lQlNeg = (momC[0] * momA[0] + momC[1] * momA[1] + momC[2] * momA[2]) / momTot; return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); } -float etaFromMom(std::array const& momA, std::array const& momB) -{ - if (std::sqrt((1.f * momA[0] + 1.f * momB[0]) * (1.f * momA[0] + 1.f * momB[0]) + - (1.f * momA[1] + 1.f * momB[1]) * (1.f * momA[1] + 1.f * momB[1]) + - (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) - - (1.f * momA[2] + 1.f * momB[2]) < - static_cast(1e-7)) { - if ((1.f * momA[2] + 1.f * momB[2]) < 0.f) - return -100.f; - return 100.f; - } - return 0.5f * std::log((std::sqrt((1.f * momA[0] + 1.f * momB[0]) * (1.f * momA[0] + 1.f * momB[0]) + - (1.f * momA[1] + 1.f * momB[1]) * (1.f * momA[1] + 1.f * momB[1]) + - (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) + - (1.f * momA[2] + 1.f * momB[2])) / - (std::sqrt((1.f * momA[0] + 1.f * momB[0]) * (1.f * momA[0] + 1.f * momB[0]) + - (1.f * momA[1] + 1.f * momB[1]) * (1.f * momA[1] + 1.f * momB[1]) + - (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) - - (1.f * momA[2] + 1.f * momB[2]))); -} 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)); @@ -185,25 +155,9 @@ enum SelBits { enum PartTypes { kLa = BIT(20), - kSig = BIT(21), kPhysPrim = BIT(22) }; -struct TagRun2V0MCalibration { - bool mCalibrationStored = false; - TH1* mhVtxAmpCorrV0A = nullptr; - TH1* mhVtxAmpCorrV0C = nullptr; - TH1* mhMultSelCalib = nullptr; - float mMCScalePars[6] = {0.0}; - TFormula* mMCScale = nullptr; -} Run2V0MInfo; - -struct TagRun2CL0Calibration { - bool mCalibrationStored = false; - TH1* mhVtxAmpCorr = nullptr; - TH1* mhMultSelCalib = nullptr; -} Run2CL0Info; - struct EbyeMaker { Produces collisionEbyeTable; Produces miniCollTable; @@ -224,16 +178,15 @@ struct EbyeMaker { float dBz; uint8_t nTrackletsColl; uint8_t nTracksColl; - // o2::base::MatLayerCylSet* lut = nullptr; + uint8_t nChPartGen; Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; - Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 2, 6, particleNamesPar, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for deuteron"}; - Configurable> cfgBetheBlochParamsITS{"cfgBetheBlochParamsITS", {betheBlochDefaultITS, 1, 6, particleName, betheBlochParNames}, "ITS Bethe-Bloch parameterisation for deuteron"}; + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {kBetheBlochDefault[0], 2, 6, particleNamesPar, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for deuteron"}; + Configurable> cfgBetheBlochParamsITS{"cfgBetheBlochParamsITS", {kBetheBlochDefaultITS, 1, 6, particleName, betheBlochParNames}, "ITS Bethe-Bloch parameterisation for deuteron"}; ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; ConfigurableAxis multAxis{"multAxis", {100, 0, 10000}, "Binning for the multiplicity axis"}; - ConfigurableAxis multFt0Axis{"multFt0Axis", {100, 0, 100000}, "Binning for the ft0 multiplicity axis"}; // binning of (anti)lambda mass QA histograms ConfigurableAxis massLambdaAxis{"massLambdaAxis", {400, o2::constants::physics::MassLambda0 - 0.03f, o2::constants::physics::MassLambda0 + 0.03f}, "binning for the lambda invariant-mass"}; @@ -248,9 +201,7 @@ struct EbyeMaker { Configurable etaMaxV0dau{"etaMaxV0dau", 0.8f, "maximum eta V0 daughters"}; Configurable outerPIDMin{"outerPIDMin", -4.f, "minimum outer PID"}; - Configurable storeTracksNum{"storeTracksNum", false, "store the number of tracks instead of tracklets"}; - Configurable genName{"genname", "", "Genearator name: HIJING, PYTHIA8, ... Default: \"\""}; - + Configurable useAllEvSel{"useAllEvSel", false, "use additional event selections fo run 3 analyses"}; Configurable triggerCut{"triggerCut", 0x0, "trigger cut to select"}; Configurable kINT7Intervals{"kINT7Intervals", false, "toggle kINT7 trigger selection in the 10-30% and 50-90% centrality intervals (2018 Pb-Pb)"}; Configurable kUsePileUpCut{"kUsePileUpCut", false, "toggle strong correlation cuts (Run 2)"}; @@ -271,7 +222,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> cfgDcaSels{"cfgDcaSels", {dcaSels, 1, 3, particleName, dcaSelsNames}, "DCA selections"}; + Configurable> cfgDcaSels{"cfgDcaSels", {kDcaSels, 1, 3, particleName, dcaSelsNames}, "DCA selections"}; Configurable v0trackNcrossedRows{"v0trackNcrossedRows", 100, "Minimum number of crossed TPC rows for V0 daughter"}; Configurable v0trackNclusItsCut{"v0trackNclusITScut", 0, "Minimum number of ITS clusters for V0 daughter"}; @@ -302,11 +253,11 @@ struct EbyeMaker { Configurable lambdaMassCut{"lambdaMassCut", 0.02f, "maximum deviation from PDG mass (for QA histograms)"}; Configurable constDCASel{"constDCASel", true, "use DCA selections independent of pt"}; - Configurable antidItsClsSizeCut{"antidItsClsSizeCut", 1.e-10f, "cluster size cut for antideuterons"}; Configurable antidPtItsClsSizeCut{"antidPtItsClsSizeCut", 10.f, "pt for cluster size cut for antideuterons"}; - Configurable> cfgTrackSels{"cfgTrackSels", {trackSels, 1, 12, particleName, trackSelsNames}, "Track selections"}; + Configurable trklEtaMax{"trklEtaMax", 0.8f, "maximum eta for run 2 tracklets"}; + Configurable> cfgTrackSels{"cfgTrackSels", {kTrackSels, 1, 12, particleName, trackSelsNames}, "Track selections"}; std::array ptMin; std::array ptTof; @@ -320,7 +271,7 @@ struct EbyeMaker { Preslice perCollisionTracksFull = o2::aod::track::collisionId; Preslice perCollisionTracksFullPID = o2::aod::track::collisionId; - Preslice perCollisionTracksFullIU = o2::aod::track::collisionId; + Preslice perCollisionTracksFullIUPID = o2::aod::track::collisionId; Preslice perCollisionV0 = o2::aod::v0::collisionId; Preslice perCollisionMcParts = o2::aod::mcparticle::mcCollisionId; @@ -332,7 +283,7 @@ struct EbyeMaker { return -1; int pdgCode = mother.pdgCode(); switch (std::abs(pdgCode)) { - case 3122: { + case PDG_t::kLambda0: { int foundPi = 0; for (const auto& mcDaught : mother.template daughters_as()) { if (std::abs(mcDaught.pdgCode()) == PDG_t::kPiPlus) { @@ -344,10 +295,6 @@ struct EbyeMaker { return PartTypes::kLa; return -1; } - // case 3222: - // return PartTypes::kSig; - // case 3112: - // return PartTypes::kSig; default: return -1; } @@ -443,45 +390,6 @@ struct EbyeMaker { LOG(fatal) << "Got nullptr from CCDB for path " << grpPath << " of object GRPObject for timestamp " << timestamp; } o2::base::Propagator::initFieldFromGRP(grpo); - TList* callst = ccdb->getForTimeStamp("Centrality/Estimators", bc.timestamp()); - if (callst != nullptr) { - auto getccdb = [callst](const char* ccdbhname) { - TH1* h = reinterpret_cast(callst->FindObject(ccdbhname)); - return h; - }; - auto getformulaccdb = [callst](const char* ccdbhname) { - TFormula* f = reinterpret_cast(callst->FindObject(ccdbhname)); - return f; - }; - Run2V0MInfo.mhVtxAmpCorrV0A = getccdb("hVtx_fAmplitude_V0A_Normalized"); - Run2V0MInfo.mhVtxAmpCorrV0C = getccdb("hVtx_fAmplitude_V0C_Normalized"); - Run2V0MInfo.mhMultSelCalib = getccdb("hMultSelCalib_V0M"); - Run2V0MInfo.mMCScale = getformulaccdb(TString::Format("%s-V0M", genName->c_str()).Data()); - if ((Run2V0MInfo.mhVtxAmpCorrV0A != nullptr) && (Run2V0MInfo.mhVtxAmpCorrV0C != nullptr) && (Run2V0MInfo.mhMultSelCalib != nullptr)) { - if (genName->length() != 0) { - if (Run2V0MInfo.mMCScale != nullptr) { - const int nPars = 6; - for (int ixpar = 0; ixpar < nPars; ++ixpar) { - Run2V0MInfo.mMCScalePars[ixpar] = Run2V0MInfo.mMCScale->GetParameter(ixpar); - } - } else { - LOGF(fatal, "MC Scale information from V0M for run %d not available", bc.runNumber()); - } - } - Run2V0MInfo.mCalibrationStored = true; - } else { - LOGF(fatal, "Calibration information from V0M for run %d corrupted", bc.runNumber()); - } - if (doprocessRun2) { - Run2CL0Info.mhVtxAmpCorr = getccdb("hVtx_fnSPDClusters0_Normalized"); - Run2CL0Info.mhMultSelCalib = getccdb("hMultSelCalib_CL0"); - if ((Run2CL0Info.mhVtxAmpCorr != nullptr) && (Run2CL0Info.mhMultSelCalib != nullptr)) { - Run2CL0Info.mCalibrationStored = true; - } else { - LOGF(fatal, "Calibration information from CL0 multiplicity for run %d corrupted", bc.runNumber()); - } - } - } } else { auto grpmagPath{"GLO/Config/GRPMagField"}; grpmag = ccdb->getForTimeStamp("GLO/Config/GRPMagField", timestamp); @@ -494,7 +402,7 @@ struct EbyeMaker { dBz = o2::base::Propagator::Instance()->getNominalBz(); LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << dBz << " kG"; mRunNumber = bc.runNumber(); - if (doprocessMiniRun2) { + if (doprocessMiniRun2) { // get class id for HMV0M trigger classes o2::ccdb::CcdbApi ccdbApi; ccdbApi.init("http://alice-ccdb.cern.ch"); std::map metadata; @@ -509,8 +417,6 @@ struct EbyeMaker { } } fitter.setBz(dBz); - - // o2::base::Propagator::Instance()->setMatLUT(lut); } template @@ -518,7 +424,7 @@ struct EbyeMaker { { if ((doprocessMiniRun2 || doprocessMiniMcRun2) && track.hasITS()) { auto extra = trackExtraRun2.rawIteratorAt(track.globalIndex()); - double expBethe{tpc::BetheBlochAleph(static_cast(track.p() / partMass[0]), cfgBetheBlochParamsITS->get("p0"), cfgBetheBlochParamsITS->get("p1"), cfgBetheBlochParamsITS->get("p2"), cfgBetheBlochParamsITS->get("p3"), cfgBetheBlochParamsITS->get("p4"))}; + double expBethe{tpc::BetheBlochAleph(static_cast(track.p() / kPartMass[0]), cfgBetheBlochParamsITS->get("p0"), cfgBetheBlochParamsITS->get("p1"), cfgBetheBlochParamsITS->get("p2"), cfgBetheBlochParamsITS->get("p3"), cfgBetheBlochParamsITS->get("p4"))}; double expSigma{expBethe * cfgBetheBlochParamsITS->get("resolution")}; auto nSigmaITS = static_cast((extra.itsSignal() - expBethe) / expSigma); return std::make_pair(extra.itsSignal(), nSigmaITS); @@ -527,41 +433,19 @@ struct EbyeMaker { } template - float getOuterPID(T const& track) + float getCustomTPCPID(T const& track, float const mass, int const ip = 0) { - if ((doprocessMiniRun2 || doprocessMiniMcRun2) && track.hasTOF() && track.pt() > antipPtTof) - return track.tofNSigmaPr(); - return -999.f; + double expBethe{tpc::BetheBlochAleph(static_cast(track.tpcInnerParam() / mass), cfgBetheBlochParams->get(ip, "p0"), cfgBetheBlochParams->get(ip, "p1"), cfgBetheBlochParams->get(ip, "p2"), cfgBetheBlochParams->get(ip, "p3"), cfgBetheBlochParams->get(ip, "p4"))}; + double expSigma{expBethe * cfgBetheBlochParams->get(ip, "resolution")}; + return static_cast((track.tpcSignal() - expBethe) / expSigma); } - float getV0M(int64_t const id, float const zvtx, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs) + template + float getOuterPID(T const& track) { - auto fv0a = fv0as.rawIteratorAt(id); - auto fv0c = fv0cs.rawIteratorAt(id); - float multFV0A = 0; - float multFV0C = 0; - for (const float& amplitude : fv0a.amplitude()) { - multFV0A += amplitude; - } - - for (const float& amplitude : fv0c.amplitude()) { - multFV0C += amplitude; - } - - float v0m = -1; - auto scaleMC = [](float x, float pars[6]) { - return std::pow(((pars[0] + pars[1] * std::pow(x, pars[2])) - pars[3]) / pars[4], 1.0f / pars[5]); - }; - - if (Run2V0MInfo.mMCScale != nullptr) { - float multFV0M = multFV0A + multFV0C; - v0m = scaleMC(multFV0M, Run2V0MInfo.mMCScalePars); - LOGF(debug, "Unscaled v0m: %f, scaled v0m: %f", multFV0M, v0m); - } else if (Run2V0MInfo.mCalibrationStored) { - v0m = multFV0A * Run2V0MInfo.mhVtxAmpCorrV0A->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0A->FindFixBin(zvtx)) + - multFV0C * Run2V0MInfo.mhVtxAmpCorrV0C->GetBinContent(Run2V0MInfo.mhVtxAmpCorrV0C->FindFixBin(zvtx)); - } - return v0m; + if (!(doprocessRun2 || doprocessMcRun2) && track.hasTOF() && track.pt() > antipPtTof) + return track.tofNSigmaPr(); + return -999.f; } template @@ -597,7 +481,6 @@ struct EbyeMaker { void init(o2::framework::InitContext&) { - mRunNumber = 0; dBz = 0; @@ -605,7 +488,6 @@ struct EbyeMaker { ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - // lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); fitter.setPropagateToPCA(true); fitter.setMaxR(200.); @@ -623,12 +505,9 @@ struct EbyeMaker { 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/MultVsCent", ";Centrality T0C (%);Multiplicity T0C;", HistType::kTH2F, {centAxis, multFt0Axis}); } else if (doprocessRun2 || doprocessMiniRun2 || doprocessMcRun2 || doprocessMiniMcRun2) { histos.add("QA/V0MvsCL0", ";Centrality CL0 (%);Centrality V0M (%)", HistType::kTH2F, {centAxis, centAxis}); histos.add("QA/trackletsVsV0M", ";Centrality CL0 (%);Centrality V0M (%)", HistType::kTH2F, {centAxis, multAxis}); - histos.add("QA/nTrklCorrelation", ";Tracklets |#eta| < 0.6; Tracklets |#eta| > 0.7", HistType::kTH2D, {{201, -0.5, 200.5}, {201, -0.5, 200.5}}); - histos.add("QA/TrklEta", ";Tracklets #eta; Entries", HistType::kTH1D, {{100, -3., 3.}}); } // v0 QA @@ -655,7 +534,7 @@ struct EbyeMaker { auto tracksSlice(T const& tracksAll, uint64_t const& collId) { if (doprocessRun3 || doprocessMcRun3) - return tracksAll.sliceBy(perCollisionTracksFullIU, collId); + return tracksAll.sliceBy(perCollisionTracksFullIUPID, collId); else if (doprocessRun2 || doprocessMcRun2) return tracksAll.sliceBy(perCollisionTracksFull, collId); else @@ -669,20 +548,16 @@ struct EbyeMaker { candidateTracks[0].clear(); candidateTracks[1].clear(); candidateV0s.clear(); + nTrackletsColl = 0u; + nTracksColl = 0u; std::array dcaInfo; - uint8_t nTracklets[2]{0, 0}; - uint8_t nTracks{0}; - const float tklEtaCuts[]{1.2, 0.6, 0.7}; for (const auto& track : tracks) { - - if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet && std::abs(track.eta()) < tklEtaCuts[0]) { // tracklet - if (std::abs(track.eta()) < tklEtaCuts[1]) - nTracklets[0]++; - else if (std::abs(track.eta()) > tklEtaCuts[2]) - nTracklets[1]++; + if (track.trackType() == o2::aod::track::TrackTypeEnum::Run2Tracklet && std::abs(track.eta()) < trklEtaMax && !(doprocessRun3 || doprocessMcRun3)) { // tracklet + nTrackletsColl++; + } else if (std::abs(track.eta()) < trklEtaMax && track.itsNCls() > 3 && (doprocessRun3 || doprocessMcRun3)) { // ITS only + global tracks + nTrackletsColl++; } - if (!selectTrack(track)) { continue; } @@ -692,18 +567,12 @@ struct EbyeMaker { auto dca = std::hypot(dcaInfo[0], dcaInfo[1]); auto trackPt = trackParCov.getPt(); auto trackEta = trackParCov.getEta(); - if (dca > cfgDcaSels->get("dca")) { // dca - continue; - } - if (std::abs(dcaInfo[1]) > cfgDcaSels->get("dcaz")) { // dcaz - continue; - } - if (std::abs(dcaInfo[0]) > cfgDcaSels->get("dcaxy") * (constDCASel ? 1. : dcaSigma(track.pt()))) { // dcaxy + if (std::abs(dcaInfo[0]) > cfgDcaSels->get("dcaxy") * (constDCASel ? 1. : dcaSigma(track.pt())) || std::abs(dcaInfo[1]) > cfgDcaSels->get("dcaz") || dca > cfgDcaSels->get("dca")) { // dcaxy continue; } histos.fill(HIST("QA/tpcSignal"), track.tpcInnerParam(), track.tpcSignal()); - - nTracks++; + if (trackPt > ptMin[0] && trackPt < ptMax[0]) + nTracksColl++; for (int iP{0}; iP < kNpart; ++iP) { if (trackPt < ptMin[iP] || trackPt > ptMax[iP]) { @@ -717,20 +586,16 @@ struct EbyeMaker { } } - double expBethe{tpc::BetheBlochAleph(static_cast(track.tpcInnerParam() / partMass[iP]), cfgBetheBlochParams->get(iP, "p0"), cfgBetheBlochParams->get(iP, "p1"), cfgBetheBlochParams->get(iP, "p2"), cfgBetheBlochParams->get(iP, "p3"), cfgBetheBlochParams->get(iP, "p4"))}; - double expSigma{expBethe * cfgBetheBlochParams->get(iP, "resolution")}; - auto nSigmaTPC = static_cast((track.tpcSignal() - expBethe) / expSigma); + auto nSigmaTPC = getCustomTPCPID(track, kPartMass[iP], iP); float beta{track.hasTOF() ? track.length() / (track.tofSignal() - track.tofEvTime()) * o2::constants::physics::invLightSpeedCm2PS : -999.f}; beta = std::min(1.f - 1.e-6f, std::max(1.e-4f, beta)); float mass{track.tpcInnerParam() * std::sqrt(1.f / (beta * beta) - 1.f)}; - const float maxTofChi2 = 3.f; + const float maxTofChi2 = 3.f; // TODO: check if this is still needed bool hasTof = track.hasTOF() && track.tofChi2() < maxTofChi2; - if (trackPt <= ptTof[iP] || (trackPt > ptTof[iP] && hasTof && std::abs(mass - partMass[iP]) < tofMassMaxQA)) { // for QA histograms - if (nSigmaTPC > nSigmaTpcCutLow[iP] && nSigmaTPC < nSigmaTpcCutUp[iP]) { - tofMass[iP]->Fill(centrality, trackPt, mass); - } + if ((trackPt <= ptTof[iP] || (trackPt > ptTof[iP] && hasTof && std::abs(mass - kPartMass[iP]) < tofMassMaxQA)) && nSigmaTPC > nSigmaTpcCutLow[iP] && nSigmaTPC < nSigmaTpcCutUp[iP]) { // for QA histograms + tofMass[iP]->Fill(centrality, trackPt, mass); } if (nSigmaTPC < nSigmaTpcCutLow[iP] || nSigmaTPC > nSigmaTpcCutUp[iP]) { @@ -745,7 +610,7 @@ struct EbyeMaker { continue; } - if (trackPt <= ptTof[iP] || (trackPt > ptTof[iP] && hasTof && std::abs(mass - partMass[iP]) < tofMassMax[iP])) { + if (trackPt <= ptTof[iP] || (trackPt > ptTof[iP] && hasTof && std::abs(mass - kPartMass[iP]) < tofMassMax[iP])) { CandidateTrack candTrack; candTrack.pt = track.sign() > 0. ? trackPt : -trackPt; candTrack.eta = trackEta; @@ -763,11 +628,6 @@ struct EbyeMaker { } } } - if (doprocessRun2 || doprocessMcRun2 || doprocessMiniRun2 || doprocessMiniMcRun2) { - histos.fill(HIST("QA/nTrklCorrelation"), nTracklets[0], nTracklets[1]); - nTrackletsColl = nTracklets[1]; - nTracksColl = nTracks; - } if (lambdaPtMax > lambdaPtMin) { std::vector trkId; @@ -817,7 +677,7 @@ struct EbyeMaker { continue; } - auto etaV0 = etaFromMom(momPos, momNeg); + auto etaV0 = RecoDecay::eta(momV0); if (std::abs(etaV0) > etaMax) { continue; } @@ -826,16 +686,12 @@ struct EbyeMaker { bool matter = alpha > 0; auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; - auto mLambda = invMass2Body(momV0, momPos, momNeg, massPos, massNeg); - auto mK0Short = invMass2Body(momV0, momPos, momNeg, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged); + auto mLambda = RecoDecay::m(std::array, 2>{momPos, momNeg}, std::array{massPos, massNeg}); + auto mK0Short = RecoDecay::m(std::array, 2>{momPos, momNeg}, std::array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged}); // pid selections - double expBethePos{tpc::BetheBlochAleph(static_cast(posTrack.tpcInnerParam() / massPos), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; - double expSigmaPos{expBethePos * cfgBetheBlochParams->get("resolution")}; - auto nSigmaTPCPos = static_cast((posTrack.tpcSignal() - expBethePos) / expSigmaPos); - double expBetheNeg{tpc::BetheBlochAleph(static_cast(negTrack.tpcInnerParam() / massNeg), cfgBetheBlochParams->get("p0"), cfgBetheBlochParams->get("p1"), cfgBetheBlochParams->get("p2"), cfgBetheBlochParams->get("p3"), cfgBetheBlochParams->get("p4"))}; - double expSigmaNeg{expBetheNeg * cfgBetheBlochParams->get("resolution")}; - auto nSigmaTPCNeg = static_cast((negTrack.tpcSignal() - expBetheNeg) / expSigmaNeg); + float nSigmaTPCPos = getCustomTPCPID(posTrack, massPos); + float nSigmaTPCNeg = getCustomTPCPID(negTrack, massNeg); float tpcSigPr = matter ? posTrack.tpcSignal() : negTrack.tpcSignal(); if (std::abs(nSigmaTPCPos) > v0settingNSigmaTpc || std::abs(nSigmaTPCNeg) > v0settingNSigmaTpc) { @@ -884,13 +740,9 @@ struct EbyeMaker { o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, posTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); auto posDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (posDcaToPv < v0settingDcaDaughToPv && std::abs(dcaInfo[0]) < v0settingDcaDaughToPv) { - continue; - } - o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); auto negDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (negDcaToPv < v0settingDcaDaughToPv && std::abs(dcaInfo[0]) < v0settingDcaDaughToPv) { + if ((posDcaToPv < v0settingDcaDaughToPv && std::abs(dcaInfo[0]) < v0settingDcaDaughToPv) || (negDcaToPv < v0settingDcaDaughToPv && std::abs(dcaInfo[0]) < v0settingDcaDaughToPv)) { continue; } @@ -898,7 +750,6 @@ struct EbyeMaker { continue; } histos.fill(HIST("QA/massLambda"), centrality, ptV0, mLambda); - histos.fill(HIST("QA/tpcSignalPr"), matter > 0. ? posTrack.tpcInnerParam() : negTrack.tpcInnerParam(), tpcSigPr); CandidateV0 candV0; @@ -935,9 +786,9 @@ struct EbyeMaker { } if (mcLab.has_mcParticle()) { auto mcTrack = mcLab.template mcParticle_as(); - if (std::abs(mcTrack.pdgCode()) != partPdg[iP]) + if (std::abs(mcTrack.pdgCode()) != kPartPdg[iP]) continue; - if (((mcTrack.flags() & 0x8) && (doprocessMcRun2 || doprocessMiniMcRun2)) || (mcTrack.flags() & 0x2) || ((mcTrack.flags() & 0x1) && !doprocessMiniMcRun2)) + if ((((mcTrack.flags() & 0x8) || (mcTrack.flags() & 0x2)) && (doprocessMcRun2 || doprocessMiniMcRun2)) || ((mcTrack.flags() & 0x1) && !doprocessMiniMcRun2)) continue; if (!mcTrack.isPhysicalPrimary() && !doprocessMiniMcRun2) @@ -975,7 +826,7 @@ struct EbyeMaker { } if (!posMother.isPhysicalPrimary() && !posMother.has_mothers()) continue; - if (((posMother.flags() & 0x8) && (doprocessMcRun2 || doprocessMiniMcRun2)) || (posMother.flags() & 0x2) || (posMother.flags() & 0x1)) + if (((posMother.flags() & 0x8) || (posMother.flags() & 0x2) || (posMother.flags() & 0x1)) && (doprocessMcRun2 || doprocessMiniMcRun2)) continue; auto genPt = std::hypot(posMother.px(), posMother.py()); @@ -992,15 +843,19 @@ struct EbyeMaker { void fillMcGen(aod::McParticles const& mcParticles, aod::McTrackLabels const& /*mcLab*/, uint64_t const& collisionId) { + nChPartGen = 0u; auto mcParticlesThisCollision = mcParticles.sliceBy(perCollisionMcParts, collisionId); for (const auto& mcPart : mcParticlesThisCollision) { auto genEta = mcPart.eta(); if (std::abs(genEta) > etaMax) { continue; } - if (((mcPart.flags() & 0x8) && (doprocessMcRun2 || doprocessMiniMcRun2)) || (mcPart.flags() & 0x2) || ((mcPart.flags() & 0x1) && !doprocessMiniMcRun2)) + if ((((mcPart.flags() & 0x8) || (mcPart.flags() & 0x2)) && (doprocessMcRun2 || doprocessMiniMcRun2)) || ((mcPart.flags() & 0x1) && !doprocessMiniMcRun2)) continue; auto pdgCode = mcPart.pdgCode(); + auto genPt = std::hypot(mcPart.px(), mcPart.py()); + if ((std::abs(pdgCode) == PDG_t::kPiPlus || std::abs(pdgCode) == PDG_t::kElectron || std::abs(pdgCode) == PDG_t::kMuonMinus || std::abs(pdgCode) == PDG_t::kKPlus || std::abs(pdgCode) == PDG_t::kProton) && mcPart.isPhysicalPrimary() && genPt > ptMin[0] && genPt < ptMax[0]) + nChPartGen++; if (std::abs(pdgCode) == PDG_t::kLambda0) { if (!mcPart.isPhysicalPrimary() && !mcPart.has_mothers()) continue; @@ -1014,7 +869,6 @@ struct EbyeMaker { if (!foundPr) { continue; } - auto genPt = std::hypot(mcPart.px(), mcPart.py()); CandidateV0 candV0; candV0.genpt = genPt; candV0.geneta = mcPart.eta(); @@ -1026,9 +880,9 @@ struct EbyeMaker { LOGF(debug, "not found!"); candidateV0s.emplace_back(candV0); } - } else if (std::abs(pdgCode) == partPdg[0] || std::abs(pdgCode) == partPdg[1]) { + } else if (std::abs(pdgCode) == kPartPdg[0] || std::abs(pdgCode) == kPartPdg[1]) { int iP = 1; - if (std::abs(pdgCode) == partPdg[0]) { + if (std::abs(pdgCode) == kPartPdg[0]) { iP = 0; } if ((!mcPart.isPhysicalPrimary() && !doprocessMiniMcRun2)) @@ -1053,19 +907,13 @@ struct EbyeMaker { } } - void processRun3(soa::Join const& collisions, TracksFullIU const& tracks, aod::V0s const& V0s, aod::BCsWithTimestamps const&) + void processRun3(soa::Join const& collisions, TracksFullIUPID const& tracks, aod::V0s const& V0s, aod::BCsWithTimestamps const&) { for (const auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc); - if (!collision.sel8()) - continue; - - if (std::abs(collision.posZ()) > zVtxMax) - continue; - - if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) + if (std::abs(collision.posZ()) > zVtxMax || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kIsTriggerTVX) || ((!collision.selection_bit(aod::evsel::kIsGoodITSLayersAll) || !collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && useAllEvSel)) continue; histos.fill(HIST("QA/zVtx"), collision.posZ()); @@ -1074,50 +922,32 @@ struct EbyeMaker { auto v0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); v0TableThisCollision.bindExternalIndices(&tracks); - auto multiplicity = collision.multFT0C(); auto centrality = collision.centFT0C(); - fillRecoEvent(collision, tracks, v0TableThisCollision, centrality); - histos.fill(HIST("QA/PvMultVsCent"), centrality, collision.numContrib()); - histos.fill(HIST("QA/MultVsCent"), centrality, multiplicity); - - collisionEbyeTable(centrality, collision.posZ()); + fillRecoEvent(collision, tracks, v0TableThisCollision, centrality); - for (const auto& candidateV0 : candidateV0s) { - lambdaEbyeTable( - collisionEbyeTable.lastIndex(), - candidateV0.pt, - candidateV0.eta, - candidateV0.mass, - candidateV0.dcav0pv, - // candidateV0.dcanegpv, - // candidateV0.dcapospv, - candidateV0.dcav0daugh, - candidateV0.cpa, - // candidateV0.tpcnsigmaneg, - // candidateV0.tpcnsigmapos, - candidateV0.globalIndexNeg, - candidateV0.globalIndexPos); - } + miniCollTable(static_cast(collision.posZ() * 10), 0x0, nTrackletsColl, centrality, nTracksColl); - for (int iP{0}; iP < kNpart; ++iP) { - for (const auto& candidateTrack : candidateTracks[iP]) { // deuterons + protons - nucleiEbyeTable( - collisionEbyeTable.lastIndex(), - candidateTrack.pt, - candidateTrack.eta, - candidateTrack.mass, - candidateTrack.dcapv, - candidateTrack.tpcncls, - candidateTrack.tpcnsigma, - candidateTrack.tofmass); - } + for (auto& candidateTrack : candidateTracks[0]) { // o2-linter: disable=const-ref-in-for-loop (not a const ref) + auto tk = tracks.rawIteratorAt(candidateTrack.globalIndex); + float outerPID = getOuterPID(tk); + candidateTrack.itsnsigma = -999.f; + candidateTrack.outerPID = tk.pt() < antipPtTof ? candidateTrack.outerPID : outerPID; + int selMask = getTrackSelMask(candidateTrack); + if (candidateTrack.outerPID < outerPIDMin) + continue; + miniTrkTable( + miniCollTable.lastIndex(), + candidateTrack.pt, + static_cast(candidateTrack.eta * 100), + selMask, + candidateTrack.outerPID); } } } PROCESS_SWITCH(EbyeMaker, processRun3, "process (Run 3)", false); - void processRun2(soa::Join const& collisions, TracksFull const& tracks, aod::V0s const& V0s, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, BCsWithRun2Info const&) + void processRun2(soa::Join const& collisions, TracksFull const& tracks, aod::V0s const& V0s, BCsWithRun2Info const&) { for (const auto& collision : collisions) { auto bc = collision.bc_as(); @@ -1132,25 +962,17 @@ struct EbyeMaker { if (kUsePileUpCut && !(bc.eventCuts() & BIT(aod::Run2EventCuts::kTPCPileUp))) continue; - float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); - float cV0M = 105.f; - if (Run2V0MInfo.mCalibrationStored) { - cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); - const float centTriggerEdges[]{10.f, 30.f, 50.f}; - if (!(collision.sel7() && collision.alias_bit(kINT7)) && (!kINT7Intervals || (kINT7Intervals && ((cV0M >= centTriggerEdges[0] && cV0M < centTriggerEdges[1]) || cV0M > centTriggerEdges[2])))) - continue; - } + float centrality = collision.centRun2V0M(); + const float centTriggerEdges[]{10.f, 30.f, 50.f}; + if (!(collision.sel7() && collision.alias_bit(kINT7)) && (!kINT7Intervals || (kINT7Intervals && ((centrality >= centTriggerEdges[0] && centrality < centTriggerEdges[1]) || centrality > centTriggerEdges[2])))) + continue; - auto centralityCl0 = 105.0f; - if (Run2CL0Info.mCalibrationStored) { - float cl0m = bc.spdClustersL0() * Run2CL0Info.mhVtxAmpCorr->GetBinContent(Run2CL0Info.mhVtxAmpCorr->FindFixBin(collision.posZ())); - centralityCl0 = Run2CL0Info.mhMultSelCalib->GetBinContent(Run2CL0Info.mhMultSelCalib->FindFixBin(cl0m)); - } + float centralityCl0 = collision.centRun2CL0(); if (kUseEstimatorsCorrelationCut) { const auto& x = centralityCl0; - const double center = estimatorsCorrelationCoef[0] + estimatorsCorrelationCoef[1] * x; - const double sigma = estimatorsSigmaPars[0] + estimatorsSigmaPars[1] * x + estimatorsSigmaPars[2] * std::pow(x, 2) + estimatorsSigmaPars[3] * std::pow(x, 3); - if (cV0M < center - deltaEstimatorNsigma[0] * sigma || cV0M > center + deltaEstimatorNsigma[1] * sigma) { + const double center = kEstimatorsCorrelationCoef[0] + kEstimatorsCorrelationCoef[1] * x; + const double sigma = kEstimatorsSigmaPars[0] + kEstimatorsSigmaPars[1] * x + kEstimatorsSigmaPars[2] * std::pow(x, 2) + kEstimatorsSigmaPars[3] * std::pow(x, 3); + if (centrality < center - kDeltaEstimatorNsigma[0] * sigma || centrality > center + kDeltaEstimatorNsigma[1] * sigma) { continue; } } @@ -1162,12 +984,12 @@ struct EbyeMaker { v0TableThisCollision.bindExternalIndices(&tracks); auto multTracklets = collision.multTracklets(); - fillRecoEvent(collision, tracks, v0TableThisCollision, cV0M); + fillRecoEvent(collision, tracks, v0TableThisCollision, centrality); - histos.fill(HIST("QA/V0MvsCL0"), centralityCl0, cV0M); - histos.fill(HIST("QA/trackletsVsV0M"), cV0M, multTracklets); + histos.fill(HIST("QA/V0MvsCL0"), centralityCl0, centrality); + histos.fill(HIST("QA/trackletsVsV0M"), centrality, multTracklets); - collisionEbyeTable(cV0M, collision.posZ()); + collisionEbyeTable(centrality, collision.posZ()); for (const auto& candidateV0 : candidateV0s) { lambdaEbyeTable( @@ -1176,12 +998,8 @@ struct EbyeMaker { candidateV0.eta, candidateV0.mass, candidateV0.dcav0pv, - // candidateV0.dcanegpv, - // candidateV0.dcapospv, candidateV0.dcav0daugh, candidateV0.cpa, - // candidateV0.tpcnsigmaneg, - // candidateV0.tpcnsigmapos, candidateV0.globalIndexNeg, candidateV0.globalIndexPos); } @@ -1203,9 +1021,8 @@ struct EbyeMaker { } PROCESS_SWITCH(EbyeMaker, processRun2, "process (Run 2)", false); - void processMiniRun2(soa::Join const& collisions, TracksFullPID const& tracks, aod::Run2TrackExtras const& trackExtraRun2, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::V0s const& V0s, BCsWithRun2Info const&) + void processMiniRun2(soa::Join const& collisions, TracksFullPID const& tracks, aod::Run2TrackExtras const& trackExtraRun2, aod::V0s const& V0s, BCsWithRun2Info const&) { - for (const auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc); @@ -1222,26 +1039,20 @@ struct EbyeMaker { if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kPileUpMV) || bc.eventCuts() & BIT(aod::Run2EventCuts::kTPCPileUp)) && kUsePileUpCut) continue; - float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); - float maxV0M = 105.f; - float cV0M = maxV0M; - if (Run2V0MInfo.mCalibrationStored) { - cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); - } - + float centrality = collision.centRun2V0M(); histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); auto v0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); v0TableThisCollision.bindExternalIndices(&tracks); - fillRecoEvent(collision, tracks, v0TableThisCollision, cV0M); + fillRecoEvent(collision, tracks, v0TableThisCollision, centrality); uint8_t trigger = collision.alias_bit(kINT7) ? 0x1 : 0x0; for (const auto& classId : classIds) { if (bc.triggerMask() & BIT(classId)) { trigger |= 0x2; - cV0M = cV0M < (maxV0M - 1.f) ? cV0M * 100. : cV0M; + centrality = centrality * 100.; break; } } @@ -1251,7 +1062,7 @@ struct EbyeMaker { if (triggerCut != 0x0 && (trigger & triggerCut) != triggerCut) { continue; } - miniCollTable(static_cast(collision.posZ() * 10), trigger, storeTracksNum ? nTracksColl : nTrackletsColl, cV0M); + miniCollTable(static_cast(collision.posZ() * 10), trigger, 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); @@ -1274,19 +1085,13 @@ struct EbyeMaker { } PROCESS_SWITCH(EbyeMaker, processMiniRun2, "process mini tables(Run 2)", false); - void processMcRun3(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullIU const& tracks, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, aod::BCsWithTimestamps const&) + void processMcRun3(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullIUPID const& tracks, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, aod::BCsWithTimestamps const&) { for (const auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc); - if (!collision.sel8()) - continue; - - if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) - continue; - - if (std::abs(collision.posZ()) > zVtxMax) + if (std::abs(collision.posZ()) > zVtxMax || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kIsTriggerTVX) || ((!collision.selection_bit(aod::evsel::kIsGoodITSLayersAll) || !collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) && useAllEvSel)) continue; auto centrality = collision.centFT0C(); @@ -1300,51 +1105,38 @@ struct EbyeMaker { fillMcEvent(collision, tracks, v0TableThisCollision, centrality, mcParticles, mcLab); fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); - collisionEbyeTable(centrality, collision.posZ()); - - for (const auto& candidateV0 : candidateV0s) { - mcLambdaEbyeTable( - collisionEbyeTable.lastIndex(), - candidateV0.pt, - candidateV0.eta, - candidateV0.mass, - candidateV0.dcav0pv, - // candidateV0.dcanegpv, - // candidateV0.dcapospv, - candidateV0.dcav0daugh, - candidateV0.cpa, - // candidateV0.tpcnsigmaneg, - // candidateV0.tpcnsigmapos, - candidateV0.globalIndexNeg, - candidateV0.globalIndexPos, - candidateV0.genpt, - candidateV0.geneta, - candidateV0.pdgcode, - candidateV0.isreco); - } + miniCollTable(static_cast(collision.posZ() * 10), nChPartGen, nTrackletsColl, centrality, nTracksColl); - for (int iP{0}; iP < kNpart; ++iP) { - for (const auto& candidateTrack : candidateTracks[iP]) { // deuterons + protons - mcNucleiEbyeTable( - collisionEbyeTable.lastIndex(), - candidateTrack.pt, - candidateTrack.eta, - candidateTrack.mass, - candidateTrack.dcapv, - candidateTrack.tpcncls, - candidateTrack.tpcnsigma, - candidateTrack.tofmass, - candidateTrack.genpt, - candidateTrack.geneta, - candidateTrack.pdgcode, - candidateTrack.isreco); + for (auto& candidateTrack : candidateTracks[0]) { // o2-linter: disable=const-ref-in-for-loop (not a const ref) + int selMask = -1; + if (candidateTrack.isreco) { + auto tk = tracks.rawIteratorAt(candidateTrack.globalIndex); + float outerPID = getOuterPID(tk); + candidateTrack.itsnsigma = -999.f; + candidateTrack.outerPID = tk.pt() < antipPtTof ? candidateTrack.outerPID : outerPID; + selMask = getTrackSelMask(candidateTrack); + if (candidateTrack.pdgcodemoth > 0) + selMask |= candidateTrack.pdgcodemoth; + } else if (candidateTrack.pdgcodemoth > 0) { + selMask = candidateTrack.pdgcodemoth; } + if (selMask < 0) + continue; + mcMiniTrkTable( + miniCollTable.lastIndex(), + candidateTrack.pt, + static_cast(candidateTrack.eta * 100), + selMask, + candidateTrack.outerPID, + candidateTrack.pdgcode > 0 ? candidateTrack.genpt : -candidateTrack.genpt, + static_cast(candidateTrack.geneta * 100), + candidateTrack.isreco); } } } PROCESS_SWITCH(EbyeMaker, processMcRun3, "process MC (Run 3)", false); - void processMcRun2(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFull const& tracks, aod::V0s const& V0s, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) + void processMcRun2(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFull const& tracks, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) { for (const auto& collision : collisions) { auto bc = collision.bc_as(); @@ -1356,22 +1148,17 @@ struct EbyeMaker { if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) continue; - float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); - float cV0M = 105.f; - if (Run2V0MInfo.mCalibrationStored) { - cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); - } - + float centrality = collision.centRun2V0M(); histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); auto v0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); v0TableThisCollision.bindExternalIndices(&tracks); - fillMcEvent(collision, tracks, v0TableThisCollision, cV0M, mcParticles, mcLab); + fillMcEvent(collision, tracks, v0TableThisCollision, centrality, mcParticles, mcLab); fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); - collisionEbyeTable(cV0M, collision.posZ()); + collisionEbyeTable(centrality, collision.posZ()); for (const auto& candidateV0 : candidateV0s) { mcLambdaEbyeTable( @@ -1380,12 +1167,8 @@ struct EbyeMaker { candidateV0.eta, candidateV0.mass, candidateV0.dcav0pv, - // candidateV0.dcanegpv, - // candidateV0.dcapospv, candidateV0.dcav0daugh, candidateV0.cpa, - // candidateV0.tpcnsigmaneg, - // candidateV0.tpcnsigmapos, candidateV0.globalIndexNeg, candidateV0.globalIndexPos, candidateV0.genpt, @@ -1415,9 +1198,8 @@ struct EbyeMaker { } PROCESS_SWITCH(EbyeMaker, processMcRun2, "process MC (Run 2)", false); - void processMiniMcRun2(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullPID const& tracks, aod::Run2TrackExtras const& trackExtraRun2, aod::FV0As const& fv0as, aod::FV0Cs const& fv0cs, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) + void processMiniMcRun2(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullPID const& tracks, aod::Run2TrackExtras const& trackExtraRun2, aod::V0s const& V0s, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, BCsWithRun2Info const&) { - for (const auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc); @@ -1428,22 +1210,17 @@ struct EbyeMaker { if (!(bc.eventCuts() & BIT(aod::Run2EventCuts::kAliEventCutsAccepted))) continue; - float v0m = getV0M(bc.globalIndex(), collision.posZ(), fv0as, fv0cs); - float cV0M = 105.f; - if (Run2V0MInfo.mCalibrationStored) { - cV0M = Run2V0MInfo.mhMultSelCalib->GetBinContent(Run2V0MInfo.mhMultSelCalib->FindFixBin(v0m)); - } - + float centrality = collision.centRun2V0M(); histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); auto v0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); v0TableThisCollision.bindExternalIndices(&tracks); - fillMcEvent(collision, tracks, v0TableThisCollision, cV0M, mcParticles, mcLab); + fillMcEvent(collision, tracks, v0TableThisCollision, centrality, mcParticles, mcLab); fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); - miniCollTable(static_cast(collision.posZ() * 10), 0x0, storeTracksNum ? nTracksColl : nTrackletsColl, cV0M); + miniCollTable(static_cast(collision.posZ() * 10), nChPartGen, nTrackletsColl, centrality, nTracksColl); for (auto& candidateTrack : candidateTracks[0]) { // o2-linter: disable=const-ref-in-for-loop (not a const ref) int selMask = -1; @@ -1455,8 +1232,6 @@ struct EbyeMaker { candidateTrack.itsnsigma = nSigmaITS; candidateTrack.outerPID = tk.pt() < antipPtTof ? candidateTrack.outerPID : outerPID; selMask = getTrackSelMask(candidateTrack); - // if (candidateTrack.outerPID < -4) - // continue; if (candidateTrack.pdgcodemoth > 0) selMask |= candidateTrack.pdgcodemoth; } else if (candidateTrack.pdgcodemoth > 0) { diff --git a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx index a2e4413854a..f50262bd998 100644 --- a/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx +++ b/PWGLF/TableProducer/Nuspex/he3HadronFemto.cxx @@ -15,30 +15,9 @@ /// \author Your Name (your.email@cern.ch) /// \since April 2025 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include // std::prev - -#include "Framework/ASoAHelpers.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFhe3HadronTables.h" +#include "PWGLF/Utils/svPoolCreator.h" #include "Common/Core/PID/PIDTOF.h" #include "Common/Core/PID/TPCPIDResponse.h" @@ -52,21 +31,40 @@ #include "Common/DataModel/PIDResponseITS.h" #include "Common/DataModel/TrackSelectionTables.h" #include "Common/TableProducer/PID/pidTOFBase.h" - #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" #include "CCDB/BasicCCDBManager.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/LFhe3HadronTables.h" -#include "PWGLF/Utils/svPoolCreator.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include // std::prev +#include +#include using namespace o2; using namespace o2::framework; @@ -76,8 +74,8 @@ using CollBracket = o2::math_utils::Bracket; using McIter = aod::McParticles::iterator; using CollBracket = o2::math_utils::Bracket; -using CollisionsFull = soa::Join; -using CollisionsFullMC = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; using TrackCandidates = soa::Join; using TrackCandidatesMC = soa::Join; @@ -86,14 +84,12 @@ namespace constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; -// constexpr float he3Mass = o2::constants::physics::MassHelium3; -// constexpr float protonMass = o2::constants::physics::MassProton; -// constexpr float pionchargedMass = o2::constants::physics::MassPiPlus; -constexpr int Li4PDG = 1000030040; +constexpr int Li4PDG = o2::constants::physics::Pdg::kLithium4; +constexpr int H3LPDG = o2::constants::physics::Pdg::kHyperTriton; constexpr int ProtonPDG = PDG_t::kProton; +constexpr int PionPDG = PDG_t::kPiPlus; constexpr int He3PDG = o2::constants::physics::Pdg::kHelium3; constexpr float CommonInite = 0.0f; -// constexpr int pichargedPDG = 211; enum Selections { kNoCuts = 0, @@ -102,6 +98,21 @@ enum Selections { kAll }; +enum Flags { + kBothPrimaries = BIT(0), + kBothFromLi4 = BIT(1), + kBothFromHypertriton = BIT(2), + kMixedPair = BIT(3), // a primary and one from Li4/hypertriton/material/other decays (or any other combination) +}; + +enum ParticleFlags { + kPhysicalPrimary = BIT(0), // primary particle + kFromLi4 = BIT(1), // from Li4 decay + kFromHypertriton = BIT(2), // from hypertriton decay + kFromMaterial = BIT(3), // from material + kFromOtherDecays = BIT(4), // from other decays +}; + } // namespace struct He3HadCandidate { @@ -123,6 +134,7 @@ struct He3HadCandidate { float dcazHe3 = -10.f; float dcaxyHad = -10.f; float dcazHad = -10.f; + float dcaPair = -10.f; // DCA between the two tracks uint16_t tpcSignalHe3 = 0u; uint16_t tpcSignalHad = 0u; @@ -162,6 +174,10 @@ struct He3HadCandidate { float etaHadMC = -99.f; float phiHadMC = -99.f; + uint8_t flagsHe3 = 0; // flags for He3 + uint8_t flagsHad = 0; // flags for hadron + uint8_t flags = 0; // flags for the pair + // collision information int32_t collisionID = 0; }; @@ -195,6 +211,7 @@ struct he3HadronFemto { Configurable settingSaveUSandLS{"settingSaveUSandLS", true, "Save All Pairs"}; Configurable settingIsMC{"settingIsMC", false, "Run MC"}; Configurable settingFillMultiplicity{"settingFillMultiplicity", false, "Fill multiplicity table"}; + Configurable settingFillPrimariesAndMixedMc{"settingFillPrimariesAndMixedMc", false, "Fill primary MC tracks and mixed tracks (e.g. a primary track and one from Li4)"}; // Zorro Configurable settingSkimmedProcessing{"settingSkimmedProcessing", false, "Skimmed dataset processing"}; @@ -243,29 +260,32 @@ struct he3HadronFemto { HistogramRegistry mQaRegistry{ "QA", { + {"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}}}}, - {"hDCAxyHe3", ";DCA_{xy} (cm)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, - {"hDCAzHe3", ";DCA_{z} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hNClsHe3ITS", ";N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, - {"hNClsHadITS", ";N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, - {"hChi2NClHe3ITS", ";Chi2_{ITS} Ncluster", {HistType::kTH1F, {{100, 0, 100.0f}}}}, - {"hChi2NClHadITS", ";Chi2_{ITS} Ncluster", {HistType::kTH1F, {{100, 0, 100.0f}}}}, + {"hDCAxyHe3", "^{3}He;DCA_{xy} (cm)", {HistType::kTH1F, {{200, -5.0f, 5.0f}}}}, + {"hDCAzHe3", "^{3}He;DCA_{z} (cm)", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, + {"hNClsHe3ITS", "^{3}He;N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, + {"hNClsHadITS", "had;N_{ITS} Cluster", {HistType::kTH1F, {{20, -10.0f, 10.0f}}}}, + {"hChi2NClHe3ITS", "^{3}He;Chi2_{ITS} Ncluster", {HistType::kTH1F, {{100, 0, 100.0f}}}}, + {"hChi2NClHadITS", "had;Chi2_{ITS} Ncluster", {HistType::kTH1F, {{100, 0, 100.0f}}}}, {"hhe3HadtInvMass", "; M(^{3}He + p) (GeV/#it{c}^{2})", {HistType::kTH1F, {{300, 3.74f, 4.34f}}}}, - {"hHe3Pt", "#it{p}_{T} distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, - {"hHadronPt", "Pt distribution; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{120, -3.0f, 3.0f}}}}, + {"hHe3Pt", "^{3}He; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{240, -6.0f, 6.0f}}}}, + {"hHadronPt", "had; #it{p}_{T} (GeV/#it{c})", {HistType::kTH1F, {{120, -3.0f, 3.0f}}}}, {"h2dEdxHe3candidates", "dEdx distribution; #it{p} (GeV/#it{c}); dE/dx (a.u.)", {HistType::kTH2F, {{200, -5.0f, 5.0f}, {100, 0.0f, 2000.0f}}}}, {"h2NsigmaHe3TPC", "NsigmaHe3 TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(^{3}He)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, {"h2NsigmaHe3TPC_preselection", "NsigmaHe3 TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(^{3}He)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, {"h2NSigmaHe3ITS_preselection", "NsigmaHe3 ITS distribution; signed #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS} ^{3}He", {HistType::kTH2F, {{50, -5.0f, 5.0f}, {120, -3.0f, 3.0f}}}}, {"h2NSigmaHe3ITS", "NsigmaHe3 ITS distribution; signed #it{p}_{T} (GeV/#it{c}); n#sigma_{ITS} ^{3}He", {HistType::kTH2F, {{50, -5.0f, 5.0f}, {120, -3.0f, 3.0f}}}}, - {"h2NsigmaHadronTPC", "NsigmaHadron TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, - {"h2NsigmaHadronTPC_preselection", "NsigmaHe3 TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(^{3}He)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, - {"h2NsigmaHadronTOF", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, - {"h2NsigmaHadronTOF_preselection", "NsigmaHadron TOF distribution; #iit{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(p)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"h2NsigmaHadronTPC", "NsigmaHadron TPC distribution; #it{p}_{T}(GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"h2NsigmaHadronTPC_preselection", "NsigmaHe3 TPC distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TPC}(had)", {HistType::kTH2F, {{100, -5.0f, 5.0f}, {400, -10.0f, 10.0f}}}}, + {"h2NsigmaHadronTOF", "NsigmaHadron TOF distribution; #it{p}_{T} (GeV/#it{c}); n#sigma_{TOF}(had)", {HistType::kTH2F, {{20, -5.0f, 5.0f}, {200, -5.0f, 5.0f}}}}, + {"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}}}}, }, OutputObjHandlingPolicy::AnalysisObject, false, @@ -360,14 +380,16 @@ 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 { - auto bc = collision.template bc_as(); - initCCDB(bc); if (!collision.sel8() || std::abs(collision.posZ()) > settingCutVertex) { return false; @@ -383,6 +405,8 @@ struct he3HadronFemto { 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; } @@ -505,53 +529,65 @@ struct he3HadronFemto { // ================================================================================================================== - template - bool fillCandidateInfo(const Ttrack& trackHe3, const Ttrack& trackHad, const CollBracket& collBracket, const Tcollisions& collisions, He3HadCandidate& he3Hadcand, const Ttracks& /*trackTable*/, bool isMixedEvent) + template + std::array getCollisionVertex(const Tcollisions& collisions, int32_t collisionID) { - const int numCoordinates = 3; - if (!isMixedEvent) { - auto trackCovHe3 = getTrackParCov(trackHe3); - auto trackCovHad = getTrackParCov(trackHad); - int nCand = CommonInite; - try { - nCand = mFitter.process(trackCovHe3, trackCovHad); - } catch (...) { - LOG(error) << "Exception caught in DCA fitter process call!"; - return false; - } - if (nCand == 0) { - return false; - } + auto collision = collisions.rawIteratorAt(collisionID); + std::array collisionVertex = {collision.posX(), collision.posY(), collision.posZ()}; + return collisionVertex; + } - // associate collision id as the one that minimises the distance between the vertex and the PCAs of the daughters - double distanceMin = -1; - unsigned int collIdxMin = 0; - const float defaultTodistance = 0.0f; - for (int collIdx = collBracket.getMin(); collIdx <= collBracket.getMax(); collIdx++) { - auto collision = collisions.rawIteratorAt(collIdx); - std::array collVtx = {collision.posX(), collision.posY(), collision.posZ()}; - const auto& pca = mFitter.getPCACandidate(); - float distance = defaultTodistance; - for (int i = 0; i < numCoordinates; i++) { - distance += (pca[i] - collVtx[i]) * (pca[i] - collVtx[i]); - } - if (distanceMin < 0 || distance < distanceMin) { - distanceMin = distance; - collIdxMin = collIdx; - } - } + template + int32_t getCollisionID(const Ttrack& trackHe3, const Ttrack& trackHad, const CollBracket& collBracket, const Tcollisions& collisions, bool isMixedEvent) + { + if (isMixedEvent) { + return collBracket.getMin(); + } - if (!mGoodCollisions[collIdxMin]) { - return false; + auto trackCovHe3 = getTrackParCov(trackHe3); + auto trackCovHad = getTrackParCov(trackHad); + int nCand = CommonInite; + try { + nCand = mFitter.process(trackCovHe3, trackCovHad); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + return false; + } + if (nCand == 0) { + return false; + } + + // associate collision id as the one that minimises the distance between the vertex and the PCAs of the daughters + double distanceMin = -1; + unsigned int collIdxMin = 0; + const float defaultTodistance = 0.0f; + for (int collIdx = collBracket.getMin(); collIdx <= collBracket.getMax(); collIdx++) { + std::array collisionVertex = getCollisionVertex(collisions, collIdx); + const auto& pca = mFitter.getPCACandidate(); + float distance = defaultTodistance; + for (int i = 0; i < 3; i++) { + distance += (pca[i] - collisionVertex[i]) * (pca[i] - collisionVertex[i]); + } + if (distanceMin < 0 || distance < distanceMin) { + distanceMin = distance; + collIdxMin = collIdx; } - he3Hadcand.collisionID = collIdxMin; + } - } else { - he3Hadcand.collisionID = collBracket.getMin(); + if (!mGoodCollisions[collIdxMin]) { + return false; } + return collIdxMin; + } + + template + bool fillCandidateInfo(const Ttrack& trackHe3, const Ttrack& trackHad, const CollBracket& collBracket, const Tcollisions& collisions, He3HadCandidate& he3Hadcand, const Ttracks& /*trackTable*/, bool isMixedEvent) + { + he3Hadcand.collisionID = getCollisionID(trackHe3, trackHad, collBracket, collisions, isMixedEvent); + std::array collisionVertex = getCollisionVertex(collisions, he3Hadcand.collisionID); he3Hadcand.momHe3 = std::array{trackHe3.px(), trackHe3.py(), trackHe3.pz()}; - for (int i = 0; i < numCoordinates; i++) + for (int i = 0; i < 3; i++) he3Hadcand.momHe3[i] = he3Hadcand.momHe3[i] * 2; he3Hadcand.momHad = std::array{trackHad.px(), trackHad.py(), trackHad.pz()}; float invMass = CommonInite; @@ -574,10 +610,20 @@ struct he3HadronFemto { he3Hadcand.signHe3 = trackHe3.sign(); he3Hadcand.signHad = trackHad.sign(); - he3Hadcand.dcaxyHe3 = trackHe3.dcaXY(); - he3Hadcand.dcaxyHad = trackHad.dcaXY(); - he3Hadcand.dcazHe3 = trackHe3.dcaZ(); - he3Hadcand.dcazHad = trackHad.dcaZ(); + // he3Hadcand.dcaxyHe3 = trackHe3.dcaXY(); + // he3Hadcand.dcaxyHad = trackHad.dcaXY(); + // he3Hadcand.dcazHe3 = trackHe3.dcaZ(); + // he3Hadcand.dcazHad = trackHad.dcaZ(); + auto trackCovHe3 = getTrackParCov(trackHe3); + auto trackCovHad = getTrackParCov(trackHad); + std::array dcaInfo; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collisionVertex[0], collisionVertex[1], collisionVertex[2]}, trackCovHe3, 2.f, mFitter.getMatCorrType(), &dcaInfo); + he3Hadcand.dcaxyHe3 = dcaInfo[0]; + he3Hadcand.dcazHe3 = dcaInfo[1]; + o2::base::Propagator::Instance()->propagateToDCABxByBz({collisionVertex[0], collisionVertex[1], collisionVertex[2]}, trackCovHad, 2.f, mFitter.getMatCorrType(), &dcaInfo); + he3Hadcand.dcaxyHad = dcaInfo[0]; + he3Hadcand.dcazHad = dcaInfo[1]; + he3Hadcand.dcaPair = std::sqrt(std::abs(mFitter.getChi2AtPCACandidate())); he3Hadcand.tpcSignalHe3 = trackHe3.tpcSignal(); bool heliumPID = trackHe3.pidForTracking() == o2::track::PID::Helium3 || trackHe3.pidForTracking() == o2::track::PID::Alpha; @@ -632,7 +678,7 @@ struct he3HadronFemto { } template - void fillCandidateInfoMC(const Mc& mctrackHe3, const Mc& mctrackHad, const Mc& mctrackMother, He3HadCandidate& he3Hadcand) + void fillCandidateInfoMC(const Mc& mctrackHe3, const Mc& mctrackHad, He3HadCandidate& he3Hadcand) { he3Hadcand.momHe3MC = mctrackHe3.pt() * (mctrackHe3.pdgCode() > 0 ? 1 : -1); he3Hadcand.etaHe3MC = mctrackHe3.eta(); @@ -640,6 +686,11 @@ struct he3HadronFemto { he3Hadcand.momHadMC = mctrackHad.pt() * (mctrackHad.pdgCode() > 0 ? 1 : -1); he3Hadcand.etaHadMC = mctrackHad.eta(); he3Hadcand.phiHadMC = mctrackHad.phi(); + } + + template + void fillMotherInfoMC(const Mc& mctrackHe3, const Mc& mctrackHad, const Mc& mctrackMother, He3HadCandidate& he3Hadcand) + { he3Hadcand.l4PtMC = mctrackMother.pt() * (mctrackMother.pdgCode() > 0 ? 1 : -1); const double eLit = mctrackHe3.e() + mctrackHad.e(); he3Hadcand.l4MassMC = std::sqrt(eLit * eLit - mctrackMother.p() * mctrackMother.p()); @@ -729,6 +780,7 @@ struct he3HadronFemto { he3Hadcand.dcazHe3, he3Hadcand.dcaxyHad, he3Hadcand.dcazHad, + he3Hadcand.dcaPair, he3Hadcand.tpcSignalHe3, he3Hadcand.momHe3TPC, he3Hadcand.tpcSignalHad, @@ -757,7 +809,8 @@ struct he3HadronFemto { he3Hadcand.etaHadMC, he3Hadcand.phiHadMC, he3Hadcand.l4PtMC, - he3Hadcand.l4MassMC); + he3Hadcand.l4MassMC, + he3Hadcand.flags); } if (settingFillMultiplicity) { outputMultiplicityTable( @@ -803,6 +856,67 @@ struct he3HadronFemto { } } + template + void setMcParticleFlag(const TmcParticle& mcParticle, std::vector& mothers, uint8_t& flag) + { + if (mcParticle.isPhysicalPrimary()) { + + flag |= ParticleFlags::kPhysicalPrimary; + if (!mcParticle.has_mothers()) { + return; + } + + for (const auto& mother : mcParticle.template mothers_as()) { + mothers.push_back(mother.globalIndex()); + if (std::abs(mother.pdgCode()) == Li4PDG) { + flag |= ParticleFlags::kFromLi4; + } else if (std::abs(mother.pdgCode()) == H3LPDG) { + flag |= ParticleFlags::kFromHypertriton; + } else { + flag |= ParticleFlags::kFromOtherDecays; + } + } + + } else { + + if (!mcParticle.has_mothers()) { + flag |= ParticleFlags::kFromMaterial; + return; + } + + for (const auto& mother : mcParticle.template mothers_as()) { + mothers.push_back(mother.globalIndex()); + if (std::abs(mother.pdgCode()) == Li4PDG) { + flag |= ParticleFlags::kFromLi4; + } else if (std::abs(mother.pdgCode()) == H3LPDG) { + flag |= ParticleFlags::kFromHypertriton; + } else { + flag |= ParticleFlags::kFromOtherDecays; + } + } + } + } + + void searchForCommonMotherTrack(const std::vector& motherHe3Idxs, const std::vector& motherHadIdxs, const aod::McParticles& mcParticles, McIter& motherParticle, He3HadCandidate& he3Hadcand, bool& isMixedPair, const int motherPdgCode) + { + std::unordered_set motherHe3SetIdxs(motherHe3Idxs.begin(), motherHe3Idxs.end()); + for (const auto& motherHadIdx : motherHadIdxs) { + if (!motherHe3SetIdxs.contains(motherHadIdx)) { + continue; + } + + motherParticle = mcParticles.rawIteratorAt(motherHadIdx); + if (std::abs(motherParticle.pdgCode()) != motherPdgCode || std::abs(motherParticle.y()) > 1) { + continue; + } + isMixedPair = false; + break; + } + if (!isMixedPair) { + he3Hadcand.flags |= Flags::kBothFromLi4; + } + } + template void fillMcParticles(const Tcollisions& collisions, const TmcParticles& mcParticles, std::vector& filledMothers) { @@ -830,7 +944,8 @@ struct he3HadronFemto { } if (daughtHe3 && daughtHad) { He3HadCandidate he3Hadcand; - fillCandidateInfoMC(mcHe3, mcHad, mcParticle, he3Hadcand); + fillCandidateInfoMC(mcHe3, mcHad, he3Hadcand); + fillMotherInfoMC(mcHe3, mcHad, mcParticle, he3Hadcand); auto collision = collisions.rawIteratorAt(he3Hadcand.collisionID); fillTable(he3Hadcand, collision, /*isMC*/ true); } @@ -924,28 +1039,58 @@ struct he3HadronFemto { auto mctrackHe3 = heTrack.mcParticle(); auto mctrackHad = prTrack.mcParticle(); - if (std::abs(mctrackHe3.pdgCode()) != He3PDG || std::abs(mctrackHad.pdgCode()) != ProtonPDG) { + if (std::abs(mctrackHe3.pdgCode()) != He3PDG || std::abs(mctrackHad.pdgCode()) != settingHadPDGCode) { continue; } - for (const auto& mothertrack : mctrackHe3.mothers_as()) { - for (const auto& mothertrackHad : mctrackHad.mothers_as()) { - - if (mothertrack != mothertrackHad || std::abs(mothertrack.pdgCode()) != Li4PDG || std::abs(mothertrack.y()) > 1) { - continue; - } - - He3HadCandidate he3Hadcand; - if (!fillCandidateInfo(heTrack, prTrack, collBracket, collisions, he3Hadcand, tracks, /*mix*/ false)) { - continue; - } - fillCandidateInfoMC(mctrackHe3, mctrackHad, mothertrack, he3Hadcand); - fillHistograms(he3Hadcand); - auto collision = collisions.rawIteratorAt(he3Hadcand.collisionID); - fillTable(he3Hadcand, collision, /*isMC*/ true); - filledMothers.push_back(mothertrack.globalIndex()); + He3HadCandidate he3Hadcand; + McIter motherParticle; + std::vector motherHe3Idxs, motherHadIdxs; + setMcParticleFlag(mctrackHe3, motherHe3Idxs, he3Hadcand.flagsHe3); + setMcParticleFlag(mctrackHad, motherHadIdxs, he3Hadcand.flagsHad); + + bool isMixedPair = true; + + if ((he3Hadcand.flagsHe3 == ParticleFlags::kPhysicalPrimary && he3Hadcand.flagsHad == ParticleFlags::kPhysicalPrimary)) { + he3Hadcand.flags |= Flags::kBothPrimaries; + isMixedPair = false; + + } else if ((he3Hadcand.flagsHe3 & ParticleFlags::kFromLi4) && (he3Hadcand.flagsHad & ParticleFlags::kFromLi4)) { + + searchForCommonMotherTrack(motherHe3Idxs, motherHadIdxs, mcParticles, motherParticle, he3Hadcand, isMixedPair, Li4PDG); + if (!isMixedPair) { + he3Hadcand.flags |= Flags::kBothFromLi4; } + + } else if ((he3Hadcand.flagsHe3 & ParticleFlags::kFromHypertriton) && (he3Hadcand.flagsHad & ParticleFlags::kFromHypertriton)) { + + searchForCommonMotherTrack(motherHe3Idxs, motherHadIdxs, mcParticles, motherParticle, he3Hadcand, isMixedPair, H3LPDG); + if (!isMixedPair) { + he3Hadcand.flags |= Flags::kBothFromHypertriton; + } + } + + if (isMixedPair) { + he3Hadcand.flags |= Flags::kMixedPair; + } + + if (!settingFillPrimariesAndMixedMc && ((he3Hadcand.flags == Flags::kMixedPair) || he3Hadcand.flags == Flags::kBothPrimaries)) { + continue; + } + + if (!fillCandidateInfo(heTrack, prTrack, collBracket, collisions, he3Hadcand, tracks, /*mix*/ false)) { + continue; + } + fillCandidateInfoMC(mctrackHe3, mctrackHad, he3Hadcand); + + if ((he3Hadcand.flags == Flags::kBothFromLi4) || (he3Hadcand.flags == Flags::kBothFromHypertriton)) { + fillMotherInfoMC(mctrackHe3, mctrackHad, motherParticle, he3Hadcand); + filledMothers.push_back(motherParticle.globalIndex()); } + + fillHistograms(he3Hadcand); + auto collision = collisions.rawIteratorAt(he3Hadcand.collisionID); + fillTable(he3Hadcand, collision, /*isMC*/ true); } } @@ -953,6 +1098,61 @@ struct he3HadronFemto { } PROCESS_SWITCH(he3HadronFemto, processMC, "Process MC", false); + void processPiHe3MC(const CollisionsFullMC& collisions, const aod::BCsWithTimestamps& bcs, const TrackCandidatesMC& tracks, const aod::McParticles& /* mcParticles */) + { + mGoodCollisions.clear(); + mGoodCollisions.resize(collisions.size(), false); + + LOG(info) << "processPiHe3MC begin"; + + for (const auto& collision : collisions) { + + mTrackPairs.clear(); + + if (!selectCollision(collision, bcs)) { + continue; + } + + const uint64_t collIdx = collision.globalIndex(); + mGoodCollisions[collIdx] = true; + auto trackTableThisCollision = tracks.sliceBy(mPerColMC, collIdx); + trackTableThisCollision.bindExternalIndices(&tracks); + + pairTracksSameEvent(trackTableThisCollision); + + for (const auto& trackPair : mTrackPairs) { + + auto heTrack = tracks.rawIteratorAt(trackPair.tr0Idx); + auto piTrack = tracks.rawIteratorAt(trackPair.tr1Idx); + auto collBracket = trackPair.collBracket; + + if (!heTrack.has_mcParticle() || !piTrack.has_mcParticle()) { + continue; + } + + auto mctrackHe3 = heTrack.mcParticle(); + auto mctrackHad = piTrack.mcParticle(); + + if (std::abs(mctrackHe3.pdgCode()) != He3PDG || std::abs(mctrackHad.pdgCode()) != PionPDG) { + continue; + } + LOG(info) << "only pi-He3"; + + He3HadCandidate he3Hadcand; + if (!fillCandidateInfo(heTrack, piTrack, collBracket, collisions, he3Hadcand, tracks, /*mix*/ false)) { + continue; + } + + fillCandidateInfoMC(mctrackHe3, mctrackHad, he3Hadcand); + fillHistograms(he3Hadcand); + LOG(info) << "fillHistograms done"; + auto collision = collisions.rawIteratorAt(he3Hadcand.collisionID); + fillTable(he3Hadcand, collision, /*isMC*/ true); + } + } + } + PROCESS_SWITCH(he3HadronFemto, processPiHe3MC, "Process pi-He3 MC", false); + void processSameEventPools(const CollisionsFull& collisions, const TrackCandidates& tracks, const aod::AmbiguousTracks& ambiguousTracks, const aod::BCsWithTimestamps& bcs) { mGoodCollisions.clear(); @@ -1067,7 +1267,8 @@ struct he3HadronFemto { if (!fillCandidateInfo(heTrack, prTrack, collBracket, collisions, he3Hadcand, tracks, /*mix*/ false)) { continue; } - fillCandidateInfoMC(mctrackHe3, mctrackHad, mothertrackHe, he3Hadcand); + fillCandidateInfoMC(mctrackHe3, mctrackHad, he3Hadcand); + fillMotherInfoMC(mctrackHe3, mctrackHad, mothertrackHe, he3Hadcand); fillHistograms(he3Hadcand); auto collision = collisions.rawIteratorAt(he3Hadcand.collisionID); fillTable(he3Hadcand, collision, /*isMC*/ true); diff --git a/PWGLF/TableProducer/Nuspex/he3LambdaAnalysis.cxx b/PWGLF/TableProducer/Nuspex/he3LambdaAnalysis.cxx new file mode 100644 index 00000000000..9482de6d51e --- /dev/null +++ b/PWGLF/TableProducer/Nuspex/he3LambdaAnalysis.cxx @@ -0,0 +1,401 @@ +// 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/LFSlimHeLambda.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/PIDResponseTPC.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.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::constants::physics; +namespace +{ +constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; +static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; +static const std::vector particleName{"He3"}; +o2::base::MatLayerCylSet* matLUT = nullptr; + +float alphaAP(std::array const& momA, std::array const& momB, std::array const& momC) +{ + const float lQlPos = (momB[0] * momA[0] + momB[1] * momA[1] + momB[2] * momA[2]); + const float lQlNeg = (momC[0] * momA[0] + momC[1] * momA[1] + momC[2] * momA[2]); + return (lQlPos - lQlNeg) / (lQlPos + lQlNeg); +} + +float qtAP(std::array const& momA, std::array const& momB) +{ + const float dp = momA[0] * momB[0] + momA[1] * momB[1] + momA[2] * momB[2]; + const float p2A = momA[0] * momA[0] + momA[1] * momA[1] + momA[2] * momA[2]; + const float p2B = momB[0] * momB[0] + momB[1] * momB[1] + momB[2] * momB[2]; + return std::sqrt(p2B - dp * dp / p2A); +} + +std::shared_ptr hTPCsignalAll; +std::shared_ptr hTPCsignalHe3; +std::shared_ptr hTPCnSigmaAll; +std::shared_ptr hTPCnSigmaHe3; +std::shared_ptr hArmenterosPodolanskiAll; +std::shared_ptr hArmenterosPodolanskiSelected; +std::shared_ptr hInvariantMassUS; +std::shared_ptr hInvariantMassLS; + +}; // namespace + +using TracksFull = soa::Join; +using CollisionsFull = soa::Join; + +struct he3LambdaAnalysis { + + // Services + Service ccdb; + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + o2::vertexing::DCAFitterN<2> fitter; + + Produces lfHe3V0Collision; + Produces lfHe3; + Produces lfLambda; + + // Configurables for event selection + struct : ConfigurableGroup { + std::string prefix = "cfgEventSelection"; + Configurable zVertexMax{"zVertexMax", 10.0f, "Accepted z-vertex range"}; + Configurable useSel8{"useSel8", true, "Use Sel8 event selection"}; + Configurable skimmedProcessing{"skimmedProcessing", false, "Skimmed dataset processing"}; + } cfgEventSelection; + + // He3 selection criteria + struct : ConfigurableGroup { + std::string prefix = "cfgHe3"; + Configurable ptMin{"ptMin", 1.0f, "Minimum He3 pT"}; + Configurable ptMax{"ptMax", 10.0f, "Maximum He3 pT"}; + Configurable etaMax{"etaMax", 0.9f, "Maximum He3 pseudorapidity"}; + Configurable minTPCrigidity{"minTPCrigidity", 0.5f, "Minimum He3 rigidity"}; + Configurable nSigmaTPCMax{"nSigmaTPCMax", 4.0f, "Maximum He3 TPC nSigma"}; + Configurable dcaxyMax{"dcaxyMax", 0.5f, "Maximum He3 DCA xy"}; + Configurable dcazMax{"dcazMax", 0.5f, "Maximum He3 DCA z"}; + Configurable tpcClusMin{"tpcClusMin", 100, "Minimum He3 TPC clusters"}; + Configurable itsClusMin{"itsClusMin", 5, "Minimum He3 ITS clusters"}; + Configurable> betheBlochParams{"betheBlochParams", {betheBlochDefault[0], 1, 6, particleName, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for He3"}; + } cfgHe3; + + // Lambda selection criteria + struct : ConfigurableGroup { + std::string prefix = "cfgLambda"; + Configurable ptMin{"ptMin", 0.5f, "Minimum Lambda pT"}; + Configurable ptMax{"ptMax", 10.0f, "Maximum Lambda pT"}; + Configurable massWindow{"massWindow", 0.015f, "Lambda mass window"}; + Configurable cosPAMin{"cosPAMin", 0.99f, "Minimum Lambda cosPA"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, "Maximum Lambda DCA V0 daughters"}; + Configurable v0RadiusMin{"v0RadiusMin", 0.5f, "Minimum Lambda V0 radius"}; + Configurable v0RadiusMax{"v0RadiusMax", 35.0f, "Maximum Lambda V0 radius"}; + Configurable tpcNClsMin{"tpcNClsMin", 70, "Minimum TPC clusters for Lambda daughters"}; + Configurable protonNSigmaTPCMax{"protonNSigmaTPCMax", 4.0f, "Maximum proton TPC nSigma"}; + Configurable pionNSigmaTPCMax{"pionNSigmaTPCMax", 4.0f, "Maximum pion TPC nSigma"}; + } cfgLambda; + + // Pair selection criteria + struct : ConfigurableGroup { + std::string prefix = "cfgPair"; + Configurable ptMin{"PtMin", 1.0f, "Minimum pair pT"}; + Configurable ptMax{"PtMax", 20.0f, "Maximum pair pT"}; + Configurable rapidityMax{"RapidityMax", 0.5f, "Maximum pair rapidity"}; + } cfgPair; + + // CCDB options + struct : ConfigurableGroup { + std::string prefix = "ccdb"; + Configurable url{"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"}; + } ccdbOptions; + + std::array mBBparamsHe; + float mBz = 0.0f; // Magnetic field in T + HistogramRegistry mRegistry{"He3LambdaAnalysis"}; + int mRunNumber = 0; // Current run number + + void init(InitContext const&) + { + // Initialize CCDB + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(true); + + for (int i = 0; i < 5; i++) { + mBBparamsHe[i] = cfgHe3.betheBlochParams->get("He3", Form("p%i", i)); + } + mBBparamsHe[5] = cfgHe3.betheBlochParams->get("He3", "resolution"); + matLUT = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + fitter.setMatCorrType(o2::base::Propagator::MatCorrType::USEMatCorrLUT); + + zorroSummary.setObject(zorro.getZorroSummary()); + + mRegistry.add("hEventSelection", "Event Selection", {HistType::kTH1L, {{6, -.5, 5.5}}}); + std::vector labels{"Total Events", "Sel8 Events", "Z-Vertex OK", "Additional Event Selections", "He3 Candidates Found", "He3 and Lambda Candidates Found"}; + for (size_t i = 1; i <= labels.size(); ++i) { + mRegistry.get(HIST("hEventSelection"))->GetXaxis()->SetBinLabel(i, labels[i - 1].c_str()); + } + + mRegistry.add("hCentralityAll", "Centrality All", {HistType::kTH1L, {{100, 0., 100.}}}); + mRegistry.add("hCentralitySelected", "Centrality Selected", {HistType::kTH1L, {{100, 0., 100.}}}); + + hTPCsignalAll = mRegistry.add("hTPCsignalAll", "TPC Signal All", {HistType::kTH2D, {{400, -10, 10}, {1000, 0, 2000}}}); + hTPCsignalHe3 = mRegistry.add("hTPCsignalHe3", "TPC Signal He3", {HistType::kTH2D, {{400, -10, 10}, {1000, 0, 2000}}}); + + hTPCnSigmaAll = mRegistry.add("hTPCnSigmaAll", "TPC nSigma All", {HistType::kTH2D, {{400, -10, 10}, {100, -5., 5.}}}); + hTPCnSigmaHe3 = mRegistry.add("hTPCnSigmaHe3", "TPC nSigma He3", {HistType::kTH2D, {{400, -10, 10}, {100, -5., 5.}}}); + + hArmenterosPodolanskiAll = mRegistry.add("hArmenterosPodolanskiAll", "Armenteros-Podolanski All", {HistType::kTH2D, {{100, -1., 1.}, {100, 0., 0.5}}}); + hArmenterosPodolanskiSelected = mRegistry.add("hArmenterosPodolanskiSelected", "Armenteros-Podolanski Selected", {HistType::kTH2D, {{100, -1., 1.}, {100, 0., 0.5}}}); + + constexpr double ConstituentsMass = o2::constants::physics::MassProton + o2::constants::physics::MassNeutron * 2 + o2::constants::physics::MassSigmaPlus; + hInvariantMassUS = mRegistry.add("hInvariantMassUS", "Invariant Mass", {HistType::kTH2D, {{45, 1., 10}, {100, ConstituentsMass - 0.05, ConstituentsMass + 0.05}}}); + hInvariantMassLS = mRegistry.add("hInvariantMassLS", "Invariant Mass", {HistType::kTH2D, {{45, 1., 10}, {100, ConstituentsMass - 0.05, ConstituentsMass + 0.05}}}); + + LOGF(info, "He3-Lambda analysis initialized"); + } + + void initCCDB(const auto& bc) + { + int runNumber = bc.runNumber(); + if (runNumber == mRunNumber) { + return; // Already initialized for this run + } + mRunNumber = runNumber; + if (cfgEventSelection.skimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fHe"); + zorro.populateHistRegistry(mRegistry, bc.runNumber()); + } + o2::parameters::GRPMagField* grpmag = ccdb->getForRun("GLO/Config/GRPMagField", runNumber); + o2::base::Propagator::initFieldFromGRP(grpmag); + mBz = static_cast(grpmag->getNominalL3Field()); + fitter.setBz(mBz); + o2::base::Propagator::Instance()->setMatLUT(matLUT); + } + + void processData(CollisionsFull::iterator const& collision, + TracksFull const& tracks, + aod::V0s const& v0s, + aod::BCsWithTimestamps const&) + { + const auto& bc = collision.bc_as(); + initCCDB(bc); + + mRegistry.get(HIST("hEventSelection"))->Fill(0); // Total events + mRegistry.get(HIST("hCentralityAll"))->Fill(collision.centFT0C()); + if (cfgEventSelection.useSel8 && !collision.sel8()) { + return; // Skip events not passing Sel8 selection + } + mRegistry.get(HIST("hEventSelection"))->Fill(1); // Sel8 events + if (std::abs(collision.posZ()) > cfgEventSelection.zVertexMax) { + return; // Skip events with z-vertex outside range + } + mRegistry.get(HIST("hEventSelection"))->Fill(2); // Z-vertex OK + + // Additional event selections not implemented, but can be added here + if (cfgEventSelection.skimmedProcessing) { + if (!zorro.isSelected(bc.globalBC())) { + return; // Skip events not passing Zorro selection + } + } + mRegistry.get(HIST("hEventSelection"))->Fill(3); // Additional event selections + + // Process He3 candidates + std::vector he3Candidates; + o2::track::TrackParCov trackParCov; + trackParCov.setPID(o2::track::PID::Helium3); + const o2::math_utils::Point3D collVtx{collision.posX(), collision.posY(), collision.posZ()}; + + for (auto const& track : tracks) { + if (track.tpcNClsFound() < cfgHe3.tpcClusMin || track.itsNCls() < cfgHe3.itsClusMin) { + continue; // Skip tracks with insufficient clusters + } + hTPCsignalAll->Fill(track.tpcInnerParam() * track.sign(), track.tpcSignal()); + const float pt = track.pt() * 2.0f; + float expTPCSignal = o2::tpc::BetheBlochAleph(track.tpcInnerParam() * 2.0f / constants::physics::MassHelium3, mBBparamsHe[0], mBBparamsHe[1], mBBparamsHe[2], mBBparamsHe[3], mBBparamsHe[4]); + double nSigmaTPC = (track.tpcSignal() - expTPCSignal) / (expTPCSignal * mBBparamsHe[5]); + hTPCnSigmaAll->Fill(track.tpcInnerParam() * track.sign(), nSigmaTPC); + if (pt < cfgHe3.ptMin || pt > cfgHe3.ptMax || std::abs(track.eta()) > cfgHe3.etaMax || track.tpcInnerParam() < cfgHe3.minTPCrigidity || std::abs(nSigmaTPC) > cfgHe3.nSigmaTPCMax) { + continue; // Skip tracks outside He3 PID+kinematics selection criteria + } + setTrackParCov(track, trackParCov); + std::array dcaInfo; + o2::base::Propagator::Instance()->propagateToDCA(collVtx, trackParCov, mBz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dcaInfo); + if (std::abs(dcaInfo[0]) > cfgHe3.dcaxyMax || std::abs(dcaInfo[1]) > cfgHe3.dcazMax) { + continue; // Skip tracks with DCA outside range + } + hTPCsignalHe3->Fill(track.tpcInnerParam() * track.sign(), track.tpcSignal()); + hTPCnSigmaHe3->Fill(track.tpcInnerParam() * track.sign(), nSigmaTPC); + he3Candidate candidate; + candidate.momentum.SetCoordinates(track.pt() * 2.0f, track.eta(), track.phi(), o2::constants::physics::MassHelium3); + candidate.nSigmaTPC = nSigmaTPC; + candidate.dcaXY = dcaInfo[0]; + candidate.dcaZ = dcaInfo[1]; + candidate.tpcNClsFound = track.tpcNClsFound(); + candidate.tpcNClsPID = track.tpcNClsPID(); + candidate.itsNCls = track.itsNCls(); + candidate.itsClusterSizes = track.itsClusterSizes(); + candidate.sign = track.sign() > 0 ? 1 : -1; + he3Candidates.push_back(candidate); + } + if (he3Candidates.empty()) { + return; // No valid He3 candidates found + } + mRegistry.get(HIST("hEventSelection"))->Fill(4); // He3 candidates found + + // Process Lambda candidates + std::vector lambdaCandidates; + for (auto const& v0 : v0s) { + if (v0.v0Type() != 1) { + continue; + } + const auto posTrack = v0.posTrack_as(); + const auto negTrack = v0.negTrack_as(); + + if (posTrack.tpcNClsFound() < cfgLambda.tpcNClsMin || negTrack.tpcNClsFound() < cfgLambda.tpcNClsMin) { + continue; // Skip V0s with insufficient TPC clusters + } + auto trackParPos = getTrackParCov(posTrack); + auto trackParNeg = getTrackParCov(negTrack); + int nCand = 0; + try { + nCand = fitter.process(trackParPos, trackParNeg); + } catch (...) { + LOG(error) << "Exception caught in DCA fitter process call!"; + return; + } + if (nCand == 0) { + continue; + } + auto& propParPos = fitter.getTrack(0); + auto& propParNeg = fitter.getTrack(1); + std::array momPos, momNeg; + propParPos.getPxPyPzGlo(momPos); + propParNeg.getPxPyPzGlo(momNeg); + const std::array momV0{momPos[0] + momNeg[0], momPos[1] + momNeg[1], momPos[2] + momNeg[2]}; + float alpha = alphaAP(momV0, momPos, momNeg); + float qt = qtAP(momV0, momPos); + hArmenterosPodolanskiAll->Fill(alpha, qt); + + bool matter = alpha > 0; + const auto& protonTrack = matter ? posTrack : negTrack; + const auto& pionTrack = matter ? negTrack : posTrack; + const auto& protonMom = matter ? momPos : momNeg; + const auto& pionMom = matter ? momNeg : momPos; + + if (std::abs(protonTrack.tpcNSigmaPr()) > cfgLambda.protonNSigmaTPCMax || + std::abs(pionTrack.tpcNSigmaPi()) > cfgLambda.pionNSigmaTPCMax) { + continue; // Skip V0s with TPC nSigma outside range + } + ROOT::Math::LorentzVector> protonMom4D(protonMom[0], protonMom[1], protonMom[2], o2::constants::physics::MassProton); + ROOT::Math::LorentzVector> pionMom4D(pionMom[0], pionMom[1], pionMom[2], o2::constants::physics::MassPionCharged); + auto lambdaMom4D = protonMom4D + pionMom4D; + float massLambda = lambdaMom4D.M(); + + if (std::abs(massLambda - o2::constants::physics::MassLambda0) > cfgLambda.massWindow) { + continue; // Skip V0s outside mass window + } + hArmenterosPodolanskiSelected->Fill(alpha, qt); + + std::array dcaInfoProton, dcaInfoPion; + o2::base::Propagator::Instance()->propagateToDCA(collVtx, matter ? trackParPos : trackParNeg, mBz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dcaInfoProton); + o2::base::Propagator::Instance()->propagateToDCA(collVtx, matter ? trackParNeg : trackParPos, mBz, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT, &dcaInfoPion); + + const auto sv = fitter.getPCACandidate(0); + + lambdaCandidate candidate; + candidate.momentum.SetCoordinates(lambdaMom4D.Pt(), lambdaMom4D.Eta(), lambdaMom4D.Phi(), o2::constants::physics::MassLambda0); + candidate.mass = massLambda; + candidate.cosPA = (sv[0] - collVtx.x()) * lambdaMom4D.Px() + + (sv[1] - collVtx.y()) * lambdaMom4D.Py() + + (sv[2] - collVtx.z()) * lambdaMom4D.Pz(); + candidate.cosPA /= std::hypot(sv[0] - collVtx.x(), sv[1] - collVtx.y(), sv[2] - collVtx.z()) * lambdaMom4D.P(); + candidate.dcaV0Daughters = std::sqrt(fitter.getChi2AtPCACandidate(0)); + candidate.dcaProtonToPV = std::hypot(dcaInfoProton[0], dcaInfoProton[1]); + candidate.dcaPionToPV = std::hypot(dcaInfoPion[0], dcaInfoPion[1]); + candidate.v0Radius = std::hypot(sv[0], sv[1]); + candidate.protonNSigmaTPC = protonTrack.tpcNSigmaPr(); + candidate.pionNSigmaTPC = pionTrack.tpcNSigmaPi(); + candidate.sign = matter ? 1 : -1; // Positive sign for Lambda, negative for anti-Lambda + lambdaCandidates.push_back(candidate); + } + if (lambdaCandidates.empty()) { + return; // No valid Lambda candidates found + } + mRegistry.get(HIST("hEventSelection"))->Fill(5); // He3 and Lambda candidates found + mRegistry.get(HIST("hCentralitySelected"))->Fill(collision.centFT0C()); + + // Fill output tables + lfHe3V0Collision(collision.posZ(), collision.centFT0C()); + for (const auto& he3 : he3Candidates) { + lfHe3(lfHe3V0Collision.lastIndex(), he3.momentum.Pt(), he3.momentum.Eta(), he3.momentum.Phi(), + he3.dcaXY, he3.dcaZ, he3.tpcNClsFound, he3.tpcNClsPID, he3.itsClusterSizes, he3.nSigmaTPC, he3.sign); + } + for (const auto& lambda : lambdaCandidates) { + lfLambda(lfHe3V0Collision.lastIndex(), lambda.momentum.Pt(), lambda.momentum.Eta(), lambda.momentum.Phi(), + lambda.mass, lambda.cosPA, lambda.dcaV0Daughters, lambda.dcaProtonToPV, lambda.dcaPionToPV, lambda.v0Radius, lambda.protonNSigmaTPC, lambda.pionNSigmaTPC, lambda.sign); + } + + for (const auto& he3 : he3Candidates) { + for (const auto& lambda : lambdaCandidates) { + auto pairMomentum = lambda.momentum + he3.momentum; // Calculate invariant mass + (he3.sign * lambda.sign > 0 ? hInvariantMassLS : hInvariantMassUS)->Fill(pairMomentum.Pt(), pairMomentum.M()); + } + } + } + PROCESS_SWITCH(he3LambdaAnalysis, processData, "Process data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx index d06405f1a32..160310d5bd8 100644 --- a/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hypKfRecoTask.cxx @@ -63,7 +63,7 @@ using CollisionsFull = soa::Join; using TracksFull = soa::Join; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper //---------------------------------------------------------------------------------------------------------------- namespace diff --git a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx index 09ed3ec07b8..e93828980b1 100644 --- a/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx +++ b/PWGLF/TableProducer/Nuspex/hyperRecoTask.cxx @@ -11,39 +11,39 @@ // // Build hypertriton candidates from V0s and tracks -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFHypernucleiTables.h" +#include "PWGLF/Utils/svPoolCreator.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.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" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - +#include "Common/TableProducer/PID/pidTOFBase.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "DataFormatsTPC/BetheBlochAleph.h" +#include "CCDB/BasicCCDBManager.h" #include "DCAFitter/DCAFitterN.h" -#include "PWGLF/Utils/svPoolCreator.h" -#include "PWGLF/DataModel/LFHypernucleiTables.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -110,9 +110,13 @@ struct hyperCandidate { uint16_t tpcSignalHe3 = 0u; uint16_t tpcSignalPi = 0u; float tpcChi2He3 = 0.f; + float itsChi2He3 = 0.f; + float itsChi2Pi = 0.f; float massTOFHe3 = 0.f; uint8_t nTPCClustersHe3 = 0u; uint8_t nTPCClustersPi = 0u; + uint8_t nTPCpidClusHe3 = 0u; + uint8_t nTPCpidClusPi = 0u; uint32_t clusterSizeITSHe3 = 0u; uint32_t clusterSizeITSPi = 0u; @@ -168,6 +172,7 @@ struct hyperRecoTask { Configurable useCustomVertexer{"useCustomVertexer", false, "Use custom vertexer"}; Configurable skipAmbiTracks{"skipAmbiTracks", false, "Skip ambiguous tracks"}; + Configurable disableITSROFCut{"disableITSROFCut", false, "Disable ITS ROC cut for event selection"}; Configurable customVertexerTimeMargin{"customVertexerTimeMargin", 800, "Time margin for custom vertexer (ns)"}; 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"}; @@ -341,7 +346,7 @@ struct hyperRecoTask { initCCDB(bc); hEvents->Fill(0.); - if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + if (!collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && !disableITSROFCut) { continue; } @@ -404,10 +409,14 @@ struct hyperRecoTask { hypCand.nSigmaHe3 = computeNSigmaHe3(heTrack); hypCand.nTPCClustersHe3 = heTrack.tpcNClsFound(); hypCand.tpcSignalHe3 = heTrack.tpcSignal(); + hypCand.nTPCpidClusHe3 = (int16_t)heTrack.tpcNClsFindable() - heTrack.tpcNClsFindableMinusPID(); hypCand.clusterSizeITSHe3 = heTrack.itsClusterSizes(); hypCand.nTPCClustersPi = piTrack.tpcNClsFound(); + hypCand.nTPCpidClusPi = (int16_t)piTrack.tpcNClsFindable() - piTrack.tpcNClsFindableMinusPID(); hypCand.tpcSignalPi = piTrack.tpcSignal(); hypCand.tpcChi2He3 = heTrack.tpcChi2NCl(); + hypCand.itsChi2He3 = heTrack.itsChi2NCl(); + hypCand.itsChi2Pi = piTrack.itsChi2NCl(); hypCand.clusterSizeITSPi = piTrack.itsClusterSizes(); bool heliumPID = heTrack.pidForTracking() == o2::track::PID::Helium3 || heTrack.pidForTracking() == o2::track::PID::Alpha; hypCand.momHe3TPC = (heliumPID && cfgCompensatePIDinTracking) ? heTrack.tpcInnerParam() / 2 : heTrack.tpcInnerParam(); @@ -681,7 +690,8 @@ struct hyperRecoTask { hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, - hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, + hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); } @@ -715,7 +725,8 @@ struct hyperRecoTask { hypCand.decVtx[0], hypCand.decVtx[1], hypCand.decVtx[2], hypCand.dcaV0dau, hypCand.he3DCAXY, hypCand.piDCAXY, hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, - hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, + hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize); } @@ -749,8 +760,8 @@ 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.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, + hypCand.nSigmaHe3, hypCand.nTPCClustersHe3, hypCand.nTPCClustersPi, hypCand.nTPCpidClusHe3, hypCand.nTPCpidClusPi, + hypCand.momHe3TPC, hypCand.momPiTPC, hypCand.tpcSignalHe3, hypCand.tpcSignalPi, hypCand.tpcChi2He3, hypCand.itsChi2He3, hypCand.itsChi2Pi, hypCand.massTOFHe3, hypCand.clusterSizeITSHe3, hypCand.clusterSizeITSPi, hypCand.flags, trackedHypClSize, chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), hypCand.genPtHe3(), @@ -824,7 +835,7 @@ struct hyperRecoTask { -1, -1, -1, -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, false, chargeFactor * hypCand.genPt(), hypCand.genPhi(), hypCand.genEta(), hypCand.genPtHe3(), hypCand.gDecVtx[0], hypCand.gDecVtx[1], hypCand.gDecVtx[2], diff --git a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx deleted file mode 100644 index 9f700dd8405..00000000000 --- a/PWGLF/TableProducer/Nuspex/hyperhelium4sigmaRecoTask.cxx +++ /dev/null @@ -1,982 +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 hyperhelium4sigmaRecoTask.cxx -/// \brief QA and analysis task for hyper-helium4sigma (He4S) -/// \author Yuanzhe Wang - -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" -#include "PWGLF/DataModel/LFKinkDecayTables.h" -#include "PWGLF/DataModel/LFHyperhelium4sigmaTables.h" - -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using CollisionsFull = soa::Join; -using MCLabeledCollisionsFull = soa::Join; -using FullTracksExtIU = soa::Join; -using MCLabeledTracksIU = soa::Join; - -namespace -{ -constexpr float BzLowerLimit = -990.f; -constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; -constexpr int kITSLayers = 7; -constexpr int kITSInnerBarrelLayers = 3; -// constexpr int kITSOuterBarrelLayers = 4; -std::shared_ptr hMotherCounter; -std::shared_ptr hMother2BCounter; -std::shared_ptr hDauAlphaCounter; -std::shared_ptr hDauTritonCounter; -std::shared_ptr hDauProtonCounter; -std::shared_ptr hDauPionCounter; -} // namespace - -//-------------------------------------------------------------- -// Check the decay channel of hyperhelium4sigma -enum Channel { - k2body = 0, // helium4, pion0 - k3body_p, // triton, proton, pion0 - k3body_n, // triton, neutron, pion+ - kNDecayChannel -}; - -template -Channel getDecayChannelHe4S(TMCParticle const& particle, std::vector& list) -{ - if (std::abs(particle.pdgCode()) != o2::constants::physics::Pdg::kHyperHelium4Sigma) { - return kNDecayChannel; - } - - // list: charged, charged or empty, neutral - list.clear(); - list.resize(3, -1); - - bool haveAlpha = false, haveTriton = false, haveProton = false, haveNeuteron = false; - bool haveAntiAlpha = false, haveAntiTriton = false, haveAntiProton = false, haveAntiNeuteron = false; - bool havePionPlus = false, havePionMinus = false, havePion0 = false; - for (const auto& mcDaughter : particle.template daughters_as()) { - if (mcDaughter.pdgCode() == o2::constants::physics::Pdg::kAlpha) { - haveAlpha = true; - list[0] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == -o2::constants::physics::Pdg::kAlpha) { - haveAntiAlpha = true; - list[0] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == o2::constants::physics::Pdg::kTriton) { - haveTriton = true; - list[0] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == -o2::constants::physics::Pdg::kTriton) { - haveAntiTriton = true; - list[0] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == PDG_t::kProton) { - haveProton = true; - list[1] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == -PDG_t::kProton) { - haveAntiProton = true; - list[1] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == PDG_t::kNeutron) { - haveNeuteron = true; - list[2] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == -PDG_t::kNeutron) { - haveAntiNeuteron = true; - list[2] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == PDG_t::kPiPlus) { - havePionPlus = true; - list[1] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == -PDG_t::kPiPlus) { - havePionMinus = true; - list[1] = mcDaughter.globalIndex(); - } - if (mcDaughter.pdgCode() == PDG_t::kPi0) { - havePion0 = true; - list[2] = mcDaughter.globalIndex(); - } - } - - if ((haveAlpha && havePion0) || (haveAntiAlpha && havePion0)) { - return k2body; - } else if ((haveTriton && haveProton && havePion0) || (haveAntiTriton && haveAntiProton && havePion0)) { - return k3body_p; - } else if ((haveTriton && haveNeuteron && havePionPlus) || (haveAntiTriton && haveAntiNeuteron && havePionMinus)) { - return k3body_n; - } - - return kNDecayChannel; -} - -//-------------------------------------------------------------- -// Extract track parameters from a mcparticle, use global coordinates as the local one -template -o2::track::TrackParametrization getTrackParFromMC(const T& mcparticle) -{ - int sign = mcparticle.pdgCode() > 0 ? 1 : -1; // ok for hyperhelium4sigma - TrackPrecision snp = mcparticle.py() / (mcparticle.pt() + 1.e-10f); - TrackPrecision tgl = mcparticle.pz() / (mcparticle.pt() + 1.e-10f); - std::array arraypar = {mcparticle.vy(), mcparticle.vz(), snp, - tgl, 2 * sign / (mcparticle.pt() + 1.e-10f)}; - return o2::track::TrackParametrization(mcparticle.vx(), 0, std::move(arraypar)); -} - -//-------------------------------------------------------------- -// construct index array from mcParticle to track -template -void setTrackIDForMC(std::vector& mcPartIndices, aod::McParticles const& particlesMC, TTrackTable const& tracks) -{ - mcPartIndices.clear(); - mcPartIndices.resize(particlesMC.size()); - std::fill(mcPartIndices.begin(), mcPartIndices.end(), -1); - for (const auto& track : tracks) { - if (track.has_mcParticle()) { - auto mcparticle = track.template mcParticle_as(); - if (mcPartIndices[mcparticle.globalIndex()] == -1) { - mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); - } else { - auto candTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); - // Use the track which has innest information (also best quality? - if (track.x() < candTrack.x()) { - mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); - } - } - } - } -} - -//-------------------------------------------------------------- -struct Hyphe4sCandidate { - - bool isMatter = false; - - std::array primVtx = {0.0f, 0.0f, 0.0f}; - std::array decVtx = {0.0f, 0.0f, 0.0f}; - std::array momMoth = {0.0f, 0.0f, 0.0f}; - std::array momDaug = {0.0f, 0.0f, 0.0f}; - - float dcaXYMothPv = -999.f; - float dcaXYDauPv = -999.f; - float dcaKinkTopo = -999.f; - - float chi2ITSMoth = 0.0f; - uint32_t itsClusterSizeMoth = 0u; - uint32_t itsClusterSizeDau = 0u; - float nSigmaTPCDau = -999.f; - - // mc information - bool isSignal = false; - bool isSignalReco = false; - bool isCollReco = false; - bool isSurvEvSelection = false; - - std::array trueDecVtx = {0.0f, 0.0f, 0.0f}; - std::array gMomMoth = {0.0f, 0.0f, 0.0f}; - std::array gMomDau = {0.0f, 0.0f, 0.0f}; - - bool isMothReco = false; - float ptMoth = -999.f; - float pzMoth = -999.f; -}; - -//-------------------------------------------------------------- -// analysis task for hyperhelium4sigma 2-body decay -struct Hyperhelium4sigmaRecoTask { - - Produces outputDataTable; - Produces outputMCTable; - - Service ccdb; - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - - std::vector mcHe4sIndices; - - // Histograms are defined with HistogramRegistry - HistogramRegistry registry{"registry", {}}; - - // Configurable for event selection - Configurable doEventCut{"doEventCut", true, "Apply event selection"}; - Configurable maxZVertex{"maxZVertex", 10.0f, "Accepted z-vertex range (cm)"}; - Configurable cutNSigmaAl{"cutNSigmaAl", 5, "NSigmaTPCAlpha"}; - - // CCDB options - Configurable inputBz{"inputBz", -999, "bz field, -999 is automatic"}; - Configurable ccdbPath{"ccdbPath", "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"}; - - int mRunNumber; - float mBz; - o2::base::MatLayerCylSet* lut = nullptr; - - void init(InitContext const&) - { - // Axes - const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; - const AxisSpec ptAxis{50, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec nSigmaAxis{120, -6.f, 6.f, "n#sigma_{#alpha}"}; - const AxisSpec massAxis{100, 3.85, 4.25, "m (GeV/#it{c}^{2})"}; - const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta p_{T} (GeV/#it{c})"}; - const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta p_{z} (GeV/#it{c})"}; - const AxisSpec radiusAxis{40, 0.f, 40.f, "R (cm)"}; - - registry.add("hEventCounter", "hEventCounter", HistType::kTH1F, {{2, 0, 2}}); - registry.add("hVertexZCollision", "hVertexZCollision", HistType::kTH1F, {vertexZAxis}); - registry.add("hCandidateCounter", "hCandidateCounter", HistType::kTH1F, {{3, 0, 3}}); - - if (doprocessMC == true) { - registry.add("hTrueCandidateCounter", "hTrueCandidateCounter", HistType::kTH1F, {{3, 0, 3}}); - registry.add("hDiffSVx", ";#Delta x (cm);", HistType::kTH1F, {{200, -10, 10}}); - registry.add("hDiffSVy", ";#Delta y (cm);", HistType::kTH1F, {{200, -10, 10}}); - registry.add("hDiffSVz", ";#Delta z (cm);", HistType::kTH1F, {{200, -10, 10}}); - registry.add("h2TrueMotherDiffPtVsRecSVR", ";Reconstruced SV R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPtAxis}); - registry.add("h2TrueMotherDiffPzVsRecSVR", ";Reconstruced SV R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPzAxis}); - registry.add("hDiffDauPx", ";#Delta p_{x} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); - registry.add("hDiffDauPy", ";#Delta p_{y} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); - registry.add("hDiffDauPz", ";#Delta p_{z} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); - registry.add("h2TrueSignalMassPt", "h2TrueSignalMassPt", HistType::kTH2F, {{ptAxis, massAxis}}); - registry.add("h2TrueSignalNSigmaAlPt", "h2TrueSignalNSigmaAlPt", HistType::kTH2F, {{ptAxis, nSigmaAxis}}); - - registry.add("hDCAXYMothToRecSV", "hDCAXYMothToRecSV", HistType::kTH1F, {{200, -10, 10}}); - registry.add("hDCAZMothToRecSV", "hDCAZMothToRecSV", HistType::kTH1F, {{200, -10, 10}}); - } - - registry.add("h2MassHyperhelium4sigmaPt", "h2MassHyperhelium4sigmaPt", HistType::kTH2F, {{ptAxis, massAxis}}); - registry.add("h2NSigmaAlPt", "h2NSigmaAlPt", HistType::kTH2F, {{ptAxis, nSigmaAxis}}); - - ccdb->setURL(ccdbPath); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - auto timestamp = bc.timestamp(); - - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - if (inputBz < BzLowerLimit) { - // Fetch magnetic field from ccdb for current collision - mBz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << mBz << " kZG"; - } else { - mBz = inputBz; - } - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - if (inputBz < BzLowerLimit) { - // Fetch magnetic field from ccdb for current collision - mBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << mBz << " kZG"; - } else { - mBz = inputBz; - } - } - - mRunNumber = bc.runNumber(); - o2::base::Propagator::Instance()->setMatLUT(lut); - LOG(info) << "Task initialized for run " << mRunNumber << " with magnetic field " << mBz << " kZG"; - } - - template - void fillCandidate(Hyphe4sCandidate& hyphe4sCand, TCollision const& collision, TKindCandidate const& kinkCand, TTrack const& trackMoth, TTrack const& trackDau) - { - hyphe4sCand.isMatter = kinkCand.mothSign() > 0; - hyphe4sCand.primVtx[0] = collision.posX(); - hyphe4sCand.primVtx[1] = collision.posY(); - hyphe4sCand.primVtx[2] = collision.posZ(); - hyphe4sCand.decVtx[0] = kinkCand.xDecVtx(); - hyphe4sCand.decVtx[1] = kinkCand.yDecVtx(); - hyphe4sCand.decVtx[2] = kinkCand.zDecVtx(); - - hyphe4sCand.momMoth[0] = kinkCand.pxMoth(); - hyphe4sCand.momMoth[1] = kinkCand.pyMoth(); - hyphe4sCand.momMoth[2] = kinkCand.pzMoth(); - hyphe4sCand.momDaug[0] = kinkCand.pxDaug(); - hyphe4sCand.momDaug[1] = kinkCand.pyDaug(); - hyphe4sCand.momDaug[2] = kinkCand.pzDaug(); - - hyphe4sCand.dcaXYMothPv = kinkCand.dcaMothPv(); - hyphe4sCand.dcaXYDauPv = kinkCand.dcaDaugPv(); - hyphe4sCand.dcaKinkTopo = kinkCand.dcaKinkTopo(); - - fillCandidateRecoMoth(hyphe4sCand, trackMoth); - - hyphe4sCand.itsClusterSizeDau = trackDau.itsClusterSizes(); - hyphe4sCand.nSigmaTPCDau = trackDau.tpcNSigmaAl(); - } - - template - void fillCandidateRecoMoth(Hyphe4sCandidate& hyphe4sCand, TTrack const& trackMoth) - { - hyphe4sCand.isMothReco = true; - hyphe4sCand.chi2ITSMoth = trackMoth.itsChi2NCl(); - hyphe4sCand.itsClusterSizeMoth = trackMoth.itsClusterSizes(); - hyphe4sCand.ptMoth = trackMoth.pt(); - hyphe4sCand.pzMoth = trackMoth.pz(); - } - - template - void fillCandidateMCInfo(Hyphe4sCandidate& hyphe4sCand, TMCParticle const& mcMothTrack, TMCParticle const& mcDauTrack) - { - hyphe4sCand.trueDecVtx[0] = mcDauTrack.vx(); - hyphe4sCand.trueDecVtx[1] = mcDauTrack.vy(); - hyphe4sCand.trueDecVtx[2] = mcDauTrack.vz(); - hyphe4sCand.gMomMoth[0] = mcMothTrack.px(); - hyphe4sCand.gMomMoth[1] = mcMothTrack.py(); - hyphe4sCand.gMomMoth[2] = mcMothTrack.pz(); - hyphe4sCand.gMomDau[0] = mcDauTrack.px(); - hyphe4sCand.gMomDau[1] = mcDauTrack.py(); - hyphe4sCand.gMomDau[2] = mcDauTrack.pz(); - } - - void processData(CollisionsFull const& collisions, aod::KinkCands const& KinkCands, FullTracksExtIU const&) - { - for (const auto& collision : collisions) { - registry.fill(HIST("hEventCounter"), 0); - if (doEventCut && (std::abs(collision.posZ()) > maxZVertex || !collision.sel8())) { - continue; - } - registry.fill(HIST("hEventCounter"), 1); - registry.fill(HIST("hVertexZCollision"), collision.posZ()); - } - - for (const auto& kinkCand : KinkCands) { - registry.fill(HIST("hCandidateCounter"), 0); - auto collision = kinkCand.collision_as(); - if (doEventCut && (std::abs(collision.posZ()) > maxZVertex || !collision.sel8())) { - continue; - } - registry.fill(HIST("hCandidateCounter"), 1); - - auto dauTrack = kinkCand.trackDaug_as(); - if (std::abs(dauTrack.tpcNSigmaAl()) > cutNSigmaAl) { - continue; - } - float invMass = RecoDecay::m(std::array{std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}, std::array{kinkCand.pxDaugNeut(), kinkCand.pyDaugNeut(), kinkCand.pzDaugNeut()}}, std::array{o2::constants::physics::MassAlpha, o2::constants::physics::MassPi0}); - registry.fill(HIST("hCandidateCounter"), 2); - registry.fill(HIST("h2MassHyperhelium4sigmaPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); - registry.fill(HIST("h2NSigmaAlPt"), kinkCand.mothSign() * kinkCand.ptDaug(), dauTrack.tpcNSigmaAl()); - - auto motherTrack = kinkCand.trackMoth_as(); - Hyphe4sCandidate hyphe4sCand; - fillCandidate(hyphe4sCand, collision, kinkCand, motherTrack, dauTrack); - - outputDataTable( - hyphe4sCand.primVtx[0], hyphe4sCand.primVtx[1], hyphe4sCand.primVtx[2], - hyphe4sCand.decVtx[0], hyphe4sCand.decVtx[1], hyphe4sCand.decVtx[2], - hyphe4sCand.isMatter, hyphe4sCand.momMoth[0], hyphe4sCand.momMoth[1], hyphe4sCand.momMoth[2], - hyphe4sCand.momDaug[0], hyphe4sCand.momDaug[1], hyphe4sCand.momDaug[2], - hyphe4sCand.dcaXYMothPv, hyphe4sCand.dcaXYDauPv, hyphe4sCand.dcaKinkTopo, - hyphe4sCand.chi2ITSMoth, hyphe4sCand.itsClusterSizeMoth, hyphe4sCand.itsClusterSizeDau, - hyphe4sCand.nSigmaTPCDau); - } - } - PROCESS_SWITCH(Hyperhelium4sigmaRecoTask, processData, "process data", true); - - void processMC(MCLabeledCollisionsFull const& collisions, aod::KinkCands const& KinkCands, MCLabeledTracksIU const& tracks, aod::McParticles const& particlesMC, aod::McCollisions const& mcCollisions, aod::BCsWithTimestamps const&) - { - mcHe4sIndices.clear(); - std::vector mcPartIndices; - setTrackIDForMC(mcPartIndices, particlesMC, tracks); - std::vector isReconstructedMCCollisions(mcCollisions.size(), false); - std::vector isSelectedMCCollisions(mcCollisions.size(), false); - std::vector isGoodCollisions(collisions.size(), false); - std::vector dauIDList(3, -1); - - for (const auto& collision : collisions) { - isReconstructedMCCollisions[collision.mcCollisionId()] = true; - registry.fill(HIST("hEventCounter"), 0); - if (doEventCut && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > maxZVertex)) { - continue; - } - registry.fill(HIST("hEventCounter"), 1); - registry.fill(HIST("hVertexZCollision"), collision.posZ()); - isSelectedMCCollisions[collision.mcCollisionId()] = true; - isGoodCollisions[collision.globalIndex()] = true; - } - - for (const auto& kinkCand : KinkCands) { - auto motherTrack = kinkCand.trackMoth_as(); - auto dauTrack = kinkCand.trackDaug_as(); - - bool isTrueSignal = false; - if (motherTrack.has_mcParticle() && dauTrack.has_mcParticle()) { - auto mcMotherTrack = motherTrack.mcParticle_as(); - auto mcDauTrack = dauTrack.mcParticle_as(); - auto dChannel = getDecayChannelHe4S(mcMotherTrack, dauIDList); - if (dChannel == k2body && dauIDList[0] == mcDauTrack.globalIndex()) { - isTrueSignal = true; - } - } - - registry.fill(HIST("hCandidateCounter"), 0); - if (isTrueSignal) { - registry.fill(HIST("hTrueCandidateCounter"), 0); - } - auto collision = kinkCand.collision_as(); - if (!isGoodCollisions[collision.globalIndex()]) { - continue; - } - registry.fill(HIST("hCandidateCounter"), 1); - if (isTrueSignal) { - registry.fill(HIST("hTrueCandidateCounter"), 1); - } - - if (std::abs(dauTrack.tpcNSigmaAl()) > cutNSigmaAl) { - continue; - } - float invMass = RecoDecay::m(std::array{std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}, std::array{kinkCand.pxDaugNeut(), kinkCand.pyDaugNeut(), kinkCand.pzDaugNeut()}}, std::array{o2::constants::physics::MassAlpha, o2::constants::physics::MassPi0}); - registry.fill(HIST("hCandidateCounter"), 2); - if (isTrueSignal) { - registry.fill(HIST("hTrueCandidateCounter"), 2); - } - registry.fill(HIST("h2MassHyperhelium4sigmaPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); - registry.fill(HIST("h2NSigmaAlPt"), kinkCand.mothSign() * kinkCand.ptDaug(), dauTrack.tpcNSigmaAl()); - - Hyphe4sCandidate hyphe4sCand; - fillCandidate(hyphe4sCand, collision, kinkCand, motherTrack, dauTrack); - - // qa for true signal - if (isTrueSignal) { - auto mcMotherTrack = motherTrack.mcParticle_as(); - auto mcDauTrack = dauTrack.mcParticle_as(); - float recSVR = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); - registry.fill(HIST("hDiffSVx"), kinkCand.xDecVtx() - mcDauTrack.vx()); - registry.fill(HIST("hDiffSVy"), kinkCand.yDecVtx() - mcDauTrack.vy()); - registry.fill(HIST("hDiffSVz"), kinkCand.zDecVtx() - mcDauTrack.vz()); - registry.fill(HIST("h2TrueMotherDiffPtVsRecSVR"), recSVR, mcMotherTrack.pt() - kinkCand.ptMoth()); - registry.fill(HIST("h2TrueMotherDiffPzVsRecSVR"), recSVR, mcMotherTrack.pz() - kinkCand.pzMoth()); - registry.fill(HIST("hDiffDauPx"), kinkCand.pxDaug() - mcDauTrack.px()); - registry.fill(HIST("hDiffDauPy"), kinkCand.pyDaug() - mcDauTrack.py()); - registry.fill(HIST("hDiffDauPz"), kinkCand.pzDaug() - mcDauTrack.pz()); - registry.fill(HIST("h2TrueSignalMassPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); - registry.fill(HIST("h2TrueSignalNSigmaAlPt"), kinkCand.mothSign() * kinkCand.ptDaug(), dauTrack.tpcNSigmaAl()); - - hyphe4sCand.isSignal = true; - hyphe4sCand.isSignalReco = true; - hyphe4sCand.isCollReco = true; - hyphe4sCand.isSurvEvSelection = true; - fillCandidateMCInfo(hyphe4sCand, mcMotherTrack, mcDauTrack); - mcHe4sIndices.push_back(mcMotherTrack.globalIndex()); - - auto bc = collision.bc_as(); - initCCDB(bc); - std::array dcaInfo; - auto mcMotherTrackPar = getTrackParFromMC(mcMotherTrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}, mcMotherTrackPar, 2.f, matCorr, &dcaInfo); - registry.fill(HIST("hDCAXYMothToRecSV"), dcaInfo[0]); - registry.fill(HIST("hDCAZMothToRecSV"), dcaInfo[1]); - } - - outputMCTable( - hyphe4sCand.primVtx[0], hyphe4sCand.primVtx[1], hyphe4sCand.primVtx[2], - hyphe4sCand.decVtx[0], hyphe4sCand.decVtx[1], hyphe4sCand.decVtx[2], - hyphe4sCand.isMatter, hyphe4sCand.momMoth[0], hyphe4sCand.momMoth[1], hyphe4sCand.momMoth[2], - hyphe4sCand.momDaug[0], hyphe4sCand.momDaug[1], hyphe4sCand.momDaug[2], - hyphe4sCand.dcaXYMothPv, hyphe4sCand.dcaXYDauPv, hyphe4sCand.dcaKinkTopo, - hyphe4sCand.chi2ITSMoth, hyphe4sCand.itsClusterSizeMoth, hyphe4sCand.itsClusterSizeDau, - hyphe4sCand.nSigmaTPCDau, - hyphe4sCand.isSignal, hyphe4sCand.isSignalReco, hyphe4sCand.isCollReco, hyphe4sCand.isSurvEvSelection, - hyphe4sCand.trueDecVtx[0], hyphe4sCand.trueDecVtx[1], hyphe4sCand.trueDecVtx[2], - hyphe4sCand.gMomMoth[0], hyphe4sCand.gMomMoth[1], hyphe4sCand.gMomMoth[2], - hyphe4sCand.gMomDau[0], hyphe4sCand.gMomDau[1], hyphe4sCand.gMomDau[2], - hyphe4sCand.isMothReco, hyphe4sCand.ptMoth, hyphe4sCand.pzMoth); - } - - // fill hyperhelium4sigma signals which are not reconstructed - for (auto const& mcparticle : particlesMC) { - auto dChannel = getDecayChannelHe4S(mcparticle, dauIDList); - if (dChannel != k2body) { - continue; - } - if (std::find(mcHe4sIndices.begin(), mcHe4sIndices.end(), mcparticle.globalIndex()) != mcHe4sIndices.end()) { - continue; - } - - Hyphe4sCandidate hyphe4sCand; - auto mcDauTrack = particlesMC.rawIteratorAt(dauIDList[0]); - fillCandidateMCInfo(hyphe4sCand, mcparticle, mcDauTrack); - - if (mcPartIndices[mcparticle.globalIndex()] != -1) { - auto mothTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); - fillCandidateRecoMoth(hyphe4sCand, mothTrack); - } - - outputMCTable( - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, -1, -1, - -1, - true, false, isReconstructedMCCollisions[mcparticle.mcCollisionId()], isSelectedMCCollisions[mcparticle.mcCollisionId()], - hyphe4sCand.trueDecVtx[0], hyphe4sCand.trueDecVtx[1], hyphe4sCand.trueDecVtx[2], - hyphe4sCand.gMomMoth[0], hyphe4sCand.gMomMoth[1], hyphe4sCand.gMomMoth[2], - hyphe4sCand.gMomDau[0], hyphe4sCand.gMomDau[1], hyphe4sCand.gMomDau[2], - hyphe4sCand.isMothReco, hyphe4sCand.ptMoth, hyphe4sCand.pzMoth); - } - } - PROCESS_SWITCH(Hyperhelium4sigmaRecoTask, processMC, "process MC", false); -}; - -//-------------------------------------------------------------- -// check the performance of mcparticle -struct Hyperhelium4sigmaQa { - - HistogramRegistry genQAHist{"genQAHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry recoQAHist{"recoQAHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - - ConfigurableAxis ptBins{"ptBins", {200, 0.f, 10.f}, "Binning for #it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis ctBins{"ctBins", {100, 0.f, 25.f}, "Binning for c#it{t} (cm)"}; - ConfigurableAxis rigidityBins{"rigidityBins", {200, -10.f, 10.f}, "Binning for #it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis nsigmaBins{"nsigmaBins", {120, -6.f, 6.f}, "Binning for n sigma"}; - ConfigurableAxis invMassBins{"invMassBins", {100, 3.85f, 4.15f}, "Binning for invariant mass (GeV/#it{c}^{2})"}; - ConfigurableAxis radiusBins{"radiusBins", {40, 0.f, 40.f}, "Binning for radius in xy plane (cm)"}; - - void init(InitContext&) - { - if (doprocessMC == true) { - const AxisSpec ptAxis{ptBins, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec ctAxis{ctBins, "c#it{t} (cm)"}; - const AxisSpec rigidityAxis{rigidityBins, "p/z (GeV/#it{c})"}; - const AxisSpec nsigmaAxis{nsigmaBins, "TPC n#sigma"}; - const AxisSpec invMassAxis{invMassBins, "Inv Mass (GeV/#it{c}^{2})"}; - const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta p_{T} (GeV/#it{c})"}; - const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta p_{z} (GeV/#it{c})"}; - const AxisSpec itsRadiusAxis{radiusBins, "ITS R (cm)"}; - const AxisSpec svRadiuAxis{radiusBins, "Decay Vertex R (cm)"}; - - auto hCollCounter = genQAHist.add("hCollCounter", "hCollCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); - hCollCounter->GetXaxis()->SetBinLabel(1, "Reconstructed Collisions"); - hCollCounter->GetXaxis()->SetBinLabel(2, "Selected"); - auto hMcCollCounter = genQAHist.add("hMcCollCounter", "hMcCollCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); - hMcCollCounter->GetXaxis()->SetBinLabel(1, "MC Collisions"); - hMcCollCounter->GetXaxis()->SetBinLabel(2, "Reconstructed"); - - auto hGenHyperHelium4SigmaCounter = genQAHist.add("hGenHyperHelium4SigmaCounter", "", HistType::kTH1F, {{11, 0.f, 11.f}}); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(1, "He4S All"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(2, "Matter"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(3, "AntiMatter"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(4, "#alpha + #pi^{0}"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(5, "#bar{#alpha} + #pi^{0}"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(6, "t + p + #pi^{0}"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(7, "#bar{t} + #bar{p} + #pi^{0}"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(8, "t + n + #pi^{+}"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(9, "#bar{t} + #bar{n} + #pi^{+}"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(10, "Tracks found"); - hGenHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(11, "Unexpected"); - - auto hEvtSelectedHyperHelium4SigmaCounter = genQAHist.add("hEvtSelectedHyperHelium4SigmaCounter", "", HistType::kTH1F, {{2, 0.f, 2.f}}); - hEvtSelectedHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(1, "Generated"); - hEvtSelectedHyperHelium4SigmaCounter->GetXaxis()->SetBinLabel(2, "Survived"); - - genQAHist.add("hGenHyperHelium4SigmaP", "", HistType::kTH1F, {ptAxis}); - genQAHist.add("hGenHyperHelium4SigmaPt", "", HistType::kTH1F, {ptAxis}); - genQAHist.add("hGenHyperHelium4SigmaCt", "", HistType::kTH1F, {ctAxis}); - genQAHist.add("hMcRecoInvMass", "", HistType::kTH1F, {invMassAxis}); - - // efficiency/criteria studies for tracks which are true candidates - hMotherCounter = recoQAHist.add("hMotherCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); - hMother2BCounter = recoQAHist.add("hMother2BCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); - for (const auto& hist : {hMotherCounter, hMother2BCounter}) { - hist->GetXaxis()->SetBinLabel(1, "Generated"); - hist->GetXaxis()->SetBinLabel(2, "Reconstructed"); - hist->GetXaxis()->SetBinLabel(3, "eta"); - hist->GetXaxis()->SetBinLabel(4, "has collision"); - hist->GetXaxis()->SetBinLabel(5, "ITSonly"); - hist->GetXaxis()->SetBinLabel(6, "ITS hits"); - hist->GetXaxis()->SetBinLabel(7, "ITS IR"); - hist->GetXaxis()->SetBinLabel(8, "ITS chi2"); - hist->GetXaxis()->SetBinLabel(9, "pt"); - } - recoQAHist.add("h2TrueMotherSVRVsRLastITS", ";ITS R (cm); Decay Vertex R (cm);", HistType::kTH2F, {itsRadiusAxis, svRadiuAxis}); - recoQAHist.add("h2GoodMotherSVRVsRLastITS", ";ITS R (cm); Decay Vertex R (cm);", HistType::kTH2F, {itsRadiusAxis, svRadiuAxis}); - recoQAHist.add("h2TrueMotherDiffPtVsDiffR", ";#Delta R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {{80, -40.f, 40.f}, diffPtAxis}); - recoQAHist.add("h2GoodMotherDiffPtVsDiffR", ";#Delta R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {{80, -40.f, 40.f}, diffPtAxis}); - recoQAHist.add("h2TrueMotherDiffPtVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPtAxis}); - recoQAHist.add("h2TrueMotherDiffPzVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPzAxis}); - recoQAHist.add("h2GoodMotherDiffPtVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPtAxis}); - recoQAHist.add("h2GoodMotherDiffPzVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPzAxis}); - recoQAHist.add("h2TrueMotherDiffPtVsRLastITS", ";ITS R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPtAxis}); - recoQAHist.add("h2TrueMotherDiffPzVsRLastITS", ";ITS R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPzAxis}); - recoQAHist.add("h2GoodMotherDiffPtVsRLastITS", ";ITS R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPtAxis}); - recoQAHist.add("h2GoodMotherDiffPzVsRLastITS", ";ITS R (cm);#Delta p_{z} (GeV/#it{c});", HistType::kTH2F, {itsRadiusAxis, diffPzAxis}); - - hDauAlphaCounter = recoQAHist.add("hDauAlphaCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - hDauTritonCounter = recoQAHist.add("hDauTritonCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - hDauProtonCounter = recoQAHist.add("hDauProtonCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - hDauPionCounter = recoQAHist.add("hDauPionCounter", "", HistType::kTH1F, {{7, 0.f, 7.f}}); - for (const auto& hist : {hDauAlphaCounter, hDauTritonCounter, hDauProtonCounter, hDauPionCounter}) { - hist->GetXaxis()->SetBinLabel(1, "Generated"); - hist->GetXaxis()->SetBinLabel(2, "Reconstructed"); - hist->GetXaxis()->SetBinLabel(3, "eta"); - hist->GetXaxis()->SetBinLabel(4, "has ITS && TPC"); - hist->GetXaxis()->SetBinLabel(5, "ITS quality"); - hist->GetXaxis()->SetBinLabel(6, "TPC n#sigma"); - hist->GetXaxis()->SetBinLabel(7, "has TOF"); - } - - recoQAHist.add("hDauAlphaTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); - recoQAHist.add("hDauTritonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); - recoQAHist.add("hDauProtonTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); - recoQAHist.add("hDauPionTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); - } - } - - Configurable skipRejectedEvents{"skipRejectedEvents", false, "Flag to skip events that fail event selection cuts"}; - Configurable doEventCut{"doEventCut", true, "Apply event selection"}; - Configurable maxZVertex{"maxZVertex", 10.0f, "Accepted z-vertex range (cm)"}; - Configurable only2BodyDecay{"only2BodyDecay", true, "Only consider 2-body decays for hyperhelium4sigma"}; - - Configurable etaMax{"etaMax", 1., "eta cut for tracks"}; - Configurable minPtMoth{"minPtMoth", 0.5, "Minimum pT/z of the hyperhelium4sigma candidate"}; - Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; - Configurable nTPCClusMinDaug{"nTPCClusMinDaug", 80, "daug NTPC clusters cut"}; - Configurable itsMaxChi2{"itsMaxChi2", 36, "max chi2 for ITS"}; - Configurable minRatioTPCNCls{"minRatioTPCNCls", 0.8, "min ratio of TPC crossed rows to findable clusters"}; - - Preslice permcCollision = o2::aod::mcparticle::mcCollisionId; - - // qa for mother track selection - template - bool motherTrackCheck(const TTrack& track, const std::shared_ptr hist) - { - hist->Fill(1); - - if (std::abs(track.eta()) > etaMax) { - return false; - } - hist->Fill(2); - - if (!track.has_collision()) { - return false; - } - hist->Fill(3); - - if (!track.hasITS() || track.hasTPC() || track.hasTOF()) { - return false; - } - hist->Fill(4); - - if (track.itsNCls() >= kITSLayers - 1) { - return false; - } - hist->Fill(5); - - if (track.itsNClsInnerBarrel() != kITSInnerBarrelLayers) { - return false; - } - hist->Fill(6); - - if (track.itsChi2NCl() >= itsMaxChi2) { - return false; - } - hist->Fill(7); - - if (track.pt() <= minPtMoth) { - return false; - } - hist->Fill(8); - - return true; - } - - // qa for daughter track selection - template - void daughterTrackCheck(const TTrack& track, const std::shared_ptr hist, float tpcNSigma) - { - hist->Fill(1); - - if (std::abs(track.eta()) > etaMax) { - return; - } - hist->Fill(2); - - if (!track.hasITS() || !track.hasTPC()) { - return; - } - hist->Fill(3); - - if (track.itsNClsInnerBarrel() != 0 && track.itsNCls() > kITSInnerBarrelLayers && track.tpcNClsCrossedRows() <= minRatioTPCNCls * track.tpcNClsFindable() && track.tpcNClsFound() <= nTPCClusMinDaug) { - return; - } - hist->Fill(4); - - if (std::abs(tpcNSigma) > tpcPidNsigmaCut) { - return; - } - hist->Fill(5); - - if (track.hasTOF()) { - return; - } - hist->Fill(6); - } - - void processData(o2::aod::Collisions const&) - { - // dummy process function; - } - PROCESS_SWITCH(Hyperhelium4sigmaQa, processData, "process data", true); - - void processMC(aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, o2::soa::Join const& collisions, MCLabeledTracksIU const& tracks) - { - std::vector mcPartIndices; - setTrackIDForMC(mcPartIndices, particlesMC, tracks); - std::vector isSelectedMCCollisions(mcCollisions.size(), false); - std::vector dauIDList(3, -1); - for (const auto& collision : collisions) { - genQAHist.fill(HIST("hCollCounter"), 0.5); - if (doEventCut && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > maxZVertex)) { - continue; - } - genQAHist.fill(HIST("hCollCounter"), 1.5); - isSelectedMCCollisions[collision.mcCollisionId()] = true; - } - - for (const auto& mcCollision : mcCollisions) { - genQAHist.fill(HIST("hMcCollCounter"), 0.5); - if (isSelectedMCCollisions[mcCollision.globalIndex()]) { // Check that the event is reconstructed and that the reconstructed events pass the selection - genQAHist.fill(HIST("hMcCollCounter"), 1.5); - } else { - if (skipRejectedEvents) { - continue; - } - } - - const auto& dparticlesMC = particlesMC.sliceBy(permcCollision, mcCollision.globalIndex()); - - for (const auto& mcparticle : dparticlesMC) { - - bool isMatter; - if (mcparticle.pdgCode() == o2::constants::physics::Pdg::kHyperHelium4Sigma) { - isMatter = true; - } else if (mcparticle.pdgCode() == -o2::constants::physics::Pdg::kHyperHelium4Sigma) { - isMatter = false; - } else { - continue; - } - - auto dChannel = getDecayChannelHe4S(mcparticle, dauIDList); - if (dChannel == kNDecayChannel) { - genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), 10.5); - continue; - } - - // qa for mother tracks - if (dChannel == k2body) { - recoQAHist.fill(HIST("hMother2BCounter"), 0); - } else { - if (only2BodyDecay) { - continue; // skip 3-body decays - } - } - recoQAHist.fill(HIST("hMotherCounter"), 0); - - genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), 0.5); - genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), isMatter ? 1.5 : 2.5); - genQAHist.fill(HIST("hEvtSelectedHyperHelium4SigmaCounter"), 0.5); - if (isSelectedMCCollisions[mcCollision.globalIndex()]) { - genQAHist.fill(HIST("hEvtSelectedHyperHelium4SigmaCounter"), 1.5); - } - - float svPos[3] = {-999, -999, -999}; - float dauAlphaMom[3] = {-999, -999, -999}; - float dauTritonMom[3] = {-999, -999, -999}; - float dauProtonMom[3] = {-999, -999, -999}; - float dauNeuteronMom[3] = {-999, -999, -999}; - float dauChargedPionMom[3] = {-999, -999, -999}; - float dauPion0Mom[3] = {-999, -999, -999}; - for (const auto& mcparticleDaughter : mcparticle.daughters_as()) { - if (std::abs(mcparticleDaughter.pdgCode()) == o2::constants::physics::Pdg::kAlpha) { - dauAlphaMom[0] = mcparticleDaughter.px(); - dauAlphaMom[1] = mcparticleDaughter.py(); - dauAlphaMom[2] = mcparticleDaughter.pz(); - - // get SV position for 2body decay - svPos[0] = mcparticleDaughter.vx(); - svPos[1] = mcparticleDaughter.vy(); - svPos[2] = mcparticleDaughter.vz(); - - recoQAHist.fill(HIST("hDauAlphaCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - daughterTrackCheck(track, hDauAlphaCounter, track.tpcNSigmaAl()); - if (track.hasTPC()) { - recoQAHist.fill(HIST("hDauAlphaTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaAl()); - } - } - } else if (std::abs(mcparticleDaughter.pdgCode()) == o2::constants::physics::Pdg::kTriton) { - dauTritonMom[0] = mcparticleDaughter.px(); - dauTritonMom[1] = mcparticleDaughter.py(); - dauTritonMom[2] = mcparticleDaughter.pz(); - - // get SV position for 3body decay - svPos[0] = mcparticleDaughter.vx(); - svPos[1] = mcparticleDaughter.vy(); - svPos[2] = mcparticleDaughter.vz(); - - recoQAHist.fill(HIST("hDauTritonCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - daughterTrackCheck(track, hDauTritonCounter, track.tpcNSigmaTr()); - if (track.hasTPC()) { - recoQAHist.fill(HIST("hDauTritonTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaTr()); - } - } - } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kProton) { - dauProtonMom[0] = mcparticleDaughter.px(); - dauProtonMom[1] = mcparticleDaughter.py(); - dauProtonMom[2] = mcparticleDaughter.pz(); - - recoQAHist.fill(HIST("hDauProtonCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - daughterTrackCheck(track, hDauProtonCounter, track.tpcNSigmaPr()); - if (track.hasTPC()) { - recoQAHist.fill(HIST("hDauProtonTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaPr()); - } - } - } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kNeutron) { - dauNeuteronMom[0] = mcparticleDaughter.px(); - dauNeuteronMom[1] = mcparticleDaughter.py(); - dauNeuteronMom[2] = mcparticleDaughter.pz(); - } else if (std::abs(mcparticleDaughter.pdgCode()) == PDG_t::kPiPlus) { - dauChargedPionMom[0] = mcparticleDaughter.px(); - dauChargedPionMom[1] = mcparticleDaughter.py(); - dauChargedPionMom[2] = mcparticleDaughter.pz(); - - recoQAHist.fill(HIST("hDauPionCounter"), 0); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - recoQAHist.fill(HIST("hDauPionTPCNSigma"), track.p() * track.sign(), track.tpcNSigmaPi()); - daughterTrackCheck(track, hDauPionCounter, track.tpcNSigmaPi()); - } - } else if (mcparticleDaughter.pdgCode() == PDG_t::kPi0) { - dauPion0Mom[0] = mcparticleDaughter.px(); - dauPion0Mom[1] = mcparticleDaughter.py(); - dauPion0Mom[2] = mcparticleDaughter.pz(); - } - } - - genQAHist.fill(HIST("hGenHyperHelium4SigmaP"), mcparticle.p()); - genQAHist.fill(HIST("hGenHyperHelium4SigmaPt"), mcparticle.pt()); - float ct = RecoDecay::sqrtSumOfSquares(svPos[0] - mcparticle.vx(), svPos[1] - mcparticle.vy(), svPos[2] - mcparticle.vz()) * o2::constants::physics::MassHyperHelium4Sigma / mcparticle.p(); - genQAHist.fill(HIST("hGenHyperHelium4SigmaCt"), ct); - - // qa if mother track is reconstructed - if (mcPartIndices[mcparticle.globalIndex()] != -1) { - auto motherTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); - bool isGoodMother = motherTrackCheck(motherTrack, hMotherCounter); - if (dChannel == k2body) { - motherTrackCheck(motherTrack, hMother2BCounter); - } - float svR = RecoDecay::sqrtSumOfSquares(svPos[0], svPos[1]); - float diffpt = mcparticle.pt() - 2 * motherTrack.pt(); - float diffpz = mcparticle.pz() - 2 * motherTrack.pz(); - - int lastITSLayerMoth = 0; - for (int i = 6; i >= 0; i--) { - if ((motherTrack.itsClusterSizes() >> (i * 4)) & 0xf) { - lastITSLayerMoth = i; - break; - } - } - float motherR = LayerRadii[lastITSLayerMoth]; - recoQAHist.fill(HIST("h2TrueMotherSVRVsRLastITS"), motherR, svR); - recoQAHist.fill(HIST("h2TrueMotherDiffPtVsDiffR"), svR - motherR, diffpt); - recoQAHist.fill(HIST("h2TrueMotherDiffPtVsTrueSVR"), svR, diffpt); - recoQAHist.fill(HIST("h2TrueMotherDiffPzVsTrueSVR"), svR, diffpz); - recoQAHist.fill(HIST("h2TrueMotherDiffPtVsRLastITS"), motherR, diffpt); - recoQAHist.fill(HIST("h2TrueMotherDiffPzVsRLastITS"), motherR, diffpz); - if (isGoodMother) { - recoQAHist.fill(HIST("h2GoodMotherSVRVsRLastITS"), motherR, svR); - recoQAHist.fill(HIST("h2GoodMotherDiffPtVsDiffR"), svR - motherR, diffpt); - recoQAHist.fill(HIST("h2GoodMotherDiffPtVsTrueSVR"), svR, diffpt); - recoQAHist.fill(HIST("h2GoodMotherDiffPzVsTrueSVR"), svR, diffpz); - recoQAHist.fill(HIST("h2GoodMotherDiffPtVsRLastITS"), motherR, diffpt); - recoQAHist.fill(HIST("h2GoodMotherDiffPzVsRLastITS"), motherR, diffpz); - } - // fill qahist if charged daughters are also reconstructed - bool isDauReconstructed = mcPartIndices[dauIDList[0]] != -1 && (dChannel == k2body ? true : mcPartIndices[dauIDList[1]] != -1); - if (isDauReconstructed) { - genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), 9.5); - } - } - - // qa for branching ratios and invariant mass - if (dChannel == k2body) { - genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), isMatter ? 3.5 : 4.5); - float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauAlphaMom[0], dauAlphaMom[1], dauAlphaMom[2]}, std::array{dauPion0Mom[0], dauPion0Mom[1], dauPion0Mom[2]}}, std::array{o2::constants::physics::MassAlpha, o2::constants::physics::MassPi0}); - genQAHist.fill(HIST("hMcRecoInvMass"), hyperHelium4SigmaMCMass); - } else if (dChannel == k3body_p) { - genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), isMatter ? 5.5 : 6.5); - float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauTritonMom[0], dauTritonMom[1], dauTritonMom[2]}, std::array{dauProtonMom[0], dauProtonMom[1], dauProtonMom[2]}, std::array{dauPion0Mom[0], dauPion0Mom[1], dauPion0Mom[2]}}, std::array{o2::constants::physics::MassTriton, o2::constants::physics::MassProton, o2::constants::physics::MassPi0}); - genQAHist.fill(HIST("hMcRecoInvMass"), hyperHelium4SigmaMCMass); - } else if (dChannel == k3body_n) { - genQAHist.fill(HIST("hGenHyperHelium4SigmaCounter"), isMatter ? 7.5 : 8.5); - float hyperHelium4SigmaMCMass = RecoDecay::m(std::array{std::array{dauTritonMom[0], dauTritonMom[1], dauTritonMom[2]}, std::array{dauNeuteronMom[0], dauNeuteronMom[1], dauNeuteronMom[2]}, std::array{dauChargedPionMom[0], dauChargedPionMom[1], dauChargedPionMom[2]}}, std::array{o2::constants::physics::MassTriton, o2::constants::physics::MassNeutron, o2::constants::physics::MassPionCharged}); - genQAHist.fill(HIST("hMcRecoInvMass"), hyperHelium4SigmaMCMass); - } - } - } - } - PROCESS_SWITCH(Hyperhelium4sigmaQa, processMC, "do QA for MC prodcutions", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/TableProducer/Nuspex/hyperkinkRecoTask.cxx b/PWGLF/TableProducer/Nuspex/hyperkinkRecoTask.cxx new file mode 100644 index 00000000000..9614d561dc0 --- /dev/null +++ b/PWGLF/TableProducer/Nuspex/hyperkinkRecoTask.cxx @@ -0,0 +1,1365 @@ +// 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 hyperkinkRecoTask.cxx +/// \brief QA and analysis task for kink decay of hypernuclei +/// \author Yuanzhe Wang + +#include "PWGLF/DataModel/LFHyperNucleiKinkTables.h" +#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include "PWGLF/DataModel/LFPIDTOFGenericTables.h" +#include "PWGLF/Utils/pidTOFGeneric.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.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/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +o2::common::core::MetadataHelper metadataInfo; + +using CollisionsFull = soa::Join; +using MCLabeledCollisionsFull = soa::Join; +using FullTracksExtIU = soa::Join; +using MCLabeledTracksIU = soa::Join; + +enum PartType { + kHypertriton = 0, + kHyperhelium4sigma +}; + +enum DaughterType { + kDaugCharged = 0, + kDaugNeutral, + kNDaughterType +}; + +namespace +{ +constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; +constexpr int kITSLayers = 7; +constexpr int kITSInnerBarrelLayers = 3; +// constexpr int kITSOuterBarrelLayers = 4; + +const std::array covPosSV{6.4462712107237135f, 0.1309793068144521f, 6.626654155592929f, -0.4510297694023185f, 0.16996629627762413f, 4.109195981415627f}; + +std::shared_ptr hMothCounter; +std::shared_ptr hDaugCounter; +std::shared_ptr hDaugTPCNSigma; +std::shared_ptr hRecoMothCounter; +std::shared_ptr hRecoDaugCounter; +} // namespace + +//-------------------------------------------------------------- +struct H3LDecay { + enum Channel { + k2bodyNeutral = 0, // triton, pion0 + k2bodyCharged, + k3bodyCharged, + kNChannel + }; + + template + static Channel getDecayChannel(TMCParticle const& particle, std::vector& list) + { + if (std::abs(particle.pdgCode()) != o2::constants::physics::Pdg::kHyperTriton) { + return kNChannel; + } + + list.clear(); + list.resize(2, -1); + + bool haveHelium3 = false, haveAntiHelium3 = false, haveDeuteron = false, haveAntiDeuteron = false; + bool haveProton = false, haveAntiProton = false, havePionPlus = false, havePionMinus = false; + bool haveTriton = false, haveAntiTriton = false, havePion0 = false; + for (const auto& mcDaughter : particle.template daughters_as()) { + if (mcDaughter.pdgCode() == o2::constants::physics::Pdg::kTriton) { + haveTriton = true; + list[0] = mcDaughter.globalIndex(); + } + if (mcDaughter.pdgCode() == -o2::constants::physics::Pdg::kTriton) { + haveAntiTriton = true; + list[0] = mcDaughter.globalIndex(); + } + if (mcDaughter.pdgCode() == PDG_t::kPi0) { + havePion0 = true; + list[1] = mcDaughter.globalIndex(); + } + if (mcDaughter.pdgCode() == o2::constants::physics::Pdg::kHelium3) { + haveHelium3 = true; + } + if (mcDaughter.pdgCode() == -o2::constants::physics::Pdg::kHelium3) { + haveAntiHelium3 = true; + } + if (mcDaughter.pdgCode() == o2::constants::physics::Pdg::kDeuteron) { + haveDeuteron = true; + } + if (mcDaughter.pdgCode() == -o2::constants::physics::Pdg::kDeuteron) { + haveAntiDeuteron = true; + } + if (mcDaughter.pdgCode() == PDG_t::kProton) { + haveProton = true; + } + if (mcDaughter.pdgCode() == -PDG_t::kProton) { + haveAntiProton = true; + } + if (mcDaughter.pdgCode() == PDG_t::kPiPlus) { + havePionPlus = true; + } + if (mcDaughter.pdgCode() == -PDG_t::kPiPlus) { + havePionMinus = true; + } + } + + if ((haveTriton && havePion0) || (haveAntiTriton && havePion0)) { + return H3LDecay::k2bodyNeutral; + } else if ((haveHelium3 && havePion0) || (haveAntiHelium3 && havePion0)) { + return H3LDecay::k2bodyCharged; + } else if ((haveDeuteron && haveProton && havePionPlus) || (haveAntiDeuteron && haveAntiProton && havePionMinus)) { + return H3LDecay::k3bodyCharged; + } else { + return kNChannel; + } + } +}; + +//-------------------------------------------------------------- +// Check the decay channel of hyperhelium4sigma +struct He4SDecay { + enum Channel { + k2body = 0, // helium4, pion0 + k3body_p, // triton, proton, pion0 + k3body_n, // triton, neutron, pion+ + kNChannel + }; + + template + static Channel getDecayChannel(TMCParticle const& particle, std::vector& list) + { + if (std::abs(particle.pdgCode()) != o2::constants::physics::Pdg::kHyperHelium4Sigma) { + return kNChannel; + } + + list.clear(); + list.resize(2, -1); + + bool haveAlpha = false, haveTriton = false, haveProton = false, haveNeuteron = false; + bool haveAntiAlpha = false, haveAntiTriton = false, haveAntiProton = false, haveAntiNeuteron = false; + bool havePionPlus = false, havePionMinus = false, havePion0 = false; + for (const auto& mcDaughter : particle.template daughters_as()) { + if (mcDaughter.pdgCode() == o2::constants::physics::Pdg::kAlpha) { + haveAlpha = true; + list[0] = mcDaughter.globalIndex(); + } + if (mcDaughter.pdgCode() == -o2::constants::physics::Pdg::kAlpha) { + haveAntiAlpha = true; + list[0] = mcDaughter.globalIndex(); + } + if (mcDaughter.pdgCode() == o2::constants::physics::Pdg::kTriton) { + haveTriton = true; + } + if (mcDaughter.pdgCode() == -o2::constants::physics::Pdg::kTriton) { + haveAntiTriton = true; + } + if (mcDaughter.pdgCode() == PDG_t::kProton) { + haveProton = true; + } + if (mcDaughter.pdgCode() == -PDG_t::kProton) { + haveAntiProton = true; + } + if (mcDaughter.pdgCode() == PDG_t::kNeutron) { + haveNeuteron = true; + } + if (mcDaughter.pdgCode() == -PDG_t::kNeutron) { + haveAntiNeuteron = true; + } + if (mcDaughter.pdgCode() == PDG_t::kPiPlus) { + havePionPlus = true; + } + if (mcDaughter.pdgCode() == -PDG_t::kPiPlus) { + havePionMinus = true; + } + if (mcDaughter.pdgCode() == PDG_t::kPi0) { + havePion0 = true; + list[1] = mcDaughter.globalIndex(); + } + } + + if ((haveAlpha && havePion0) || (haveAntiAlpha && havePion0)) { + return He4SDecay::k2body; + } else if ((haveTriton && haveProton && havePion0) || (haveAntiTriton && haveAntiProton && havePion0)) { + return He4SDecay::k3body_p; + } else if ((haveTriton && haveNeuteron && havePionPlus) || (haveAntiTriton && haveAntiNeuteron && havePionMinus)) { + return He4SDecay::k3body_n; + } + + return kNChannel; + } +}; + +//-------------------------------------------------------------- +// Extract track parameters from a mcparticle, use global coordinates as the local one +template +o2::track::TrackParametrization getTrackParFromMC(const T& mcparticle, int charge = 1) +{ + int sign = mcparticle.pdgCode() > 0 ? 1 : -1; // ok for hypernuclei + TrackPrecision snp = mcparticle.py() / (mcparticle.pt() + 1.e-10f); + TrackPrecision tgl = mcparticle.pz() / (mcparticle.pt() + 1.e-10f); + std::array arraypar = {mcparticle.vy(), mcparticle.vz(), snp, + tgl, charge * sign / (mcparticle.pt() + 1.e-10f)}; + return o2::track::TrackParametrization(mcparticle.vx(), 0, std::move(arraypar)); +} + +//-------------------------------------------------------------- +// construct index array from mcParticle to track +template +void setTrackIDForMC(std::vector& mcPartIndices, aod::McParticles const& particlesMC, TTrackTable const& tracks) +{ + mcPartIndices.clear(); + mcPartIndices.resize(particlesMC.size()); + std::fill(mcPartIndices.begin(), mcPartIndices.end(), -1); + for (const auto& track : tracks) { + if (track.has_mcParticle()) { + auto mcparticle = track.template mcParticle_as(); + if (mcPartIndices[mcparticle.globalIndex()] == -1) { + mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); + } else { + auto candTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); + // Use the track which has innest information (also best quality? + if (track.x() < candTrack.x()) { + mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); + } + } + } + } +} + +//-------------------------------------------------------------- +// get ITSNSigma for daughter track +template +float getITSNSigma(const TTrack& track, o2::aod::ITSResponse& itsResponse, o2::track::PID partType) +{ + float nSigma = -999.f; + switch (partType) { + case o2::track::PID::Alpha: + nSigma = itsResponse.nSigmaITS(track); + break; + case o2::track::PID::Triton: + nSigma = itsResponse.nSigmaITS(track); + break; + default: + break; + } + return nSigma; +} + +//-------------------------------------------------------------- +// get default TOFNSigma for daughter track +template +float getDefaultTOFNSigma(const TTrack& track, o2::track::PID partType) +{ + float nSigma = -999.f; + switch (partType) { + case o2::track::PID::Alpha: + nSigma = track.tofNSigmaAl(); + break; + case o2::track::PID::Triton: + nSigma = track.tofNSigmaTr(); + break; + default: + break; + } + return nSigma; +} + +//-------------------------------------------------------------- +// get TPCNSigma for daughter track +template +float getTPCNSigma(const TTrack& track, o2::track::PID partType) +{ + float nSigma = -999.f; + switch (partType) { + case o2::track::PID::Alpha: + nSigma = track.tpcNSigmaAl(); + break; + case o2::track::PID::Triton: + nSigma = track.tpcNSigmaTr(); + break; + default: + break; + } + return nSigma; +} + +//-------------------------------------------------------------- +// Refit the momentum of the mother track +template +bool refitMotherTrack(const TTrack& track, o2::track::TrackParametrizationWithError& trackPar, const o2::dataformats::VertexBase& primaryVtx, const o2::dataformats::VertexBase& secondaryVtx) +{ + float trackIUPos[2] = {track.y(), track.z()}; + float trackIUCov[3] = {track.cYY(), track.cZY(), track.cZZ()}; + + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVtx, trackPar, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT); + + trackPar.resetCovariance(1e15); + if (!trackPar.update(primaryVtx)) { + return false; + } + + trackPar.rotate(track.alpha()); + o2::base::Propagator::Instance()->PropagateToXBxByBz(trackPar, track.x()); + if (!trackPar.update(trackIUPos, trackIUCov)) { + return false; + } + + o2::base::Propagator::Instance()->propagateToDCABxByBz(secondaryVtx, trackPar, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT); + if (!trackPar.update(secondaryVtx)) { + return false; + } + + return true; +} + +//-------------------------------------------------------------- +struct HypKinkCandidate { + + bool isMatter = false; + + std::array posPV = {0.0f, 0.0f, 0.0f}; + std::array posSV = {0.0f, 0.0f, 0.0f}; + std::array lastPosMoth = {0.0f, 0.0f, 0.0f}; // last position of mother track at the radii of ITS layer which has the outermost update + std::array momMothSV = {0.0f, 0.0f, 0.0f}; + std::array momDaugSV = {0.0f, 0.0f, 0.0f}; + + float dcaXYMothPv = -999.f; + float dcaXYDaugPv = -999.f; + float dcaKinkTopo = -999.f; + + float chi2ITSMoth = 0.0f; + uint32_t itsClusterSizeMoth = 0u; + uint32_t itsClusterSizeDaug = 0u; + float nSigmaTPCDaug = -999.f; + float nSigmaITSDaug = -999.f; + float nSigmaTOFDaug = -999.f; // recalculated TOF NSigma + + // mc information + bool isSignal = false; + bool isSignalReco = false; + bool isCollReco = false; + bool isSurvEvSelection = false; + + std::array truePosSV = {0.0f, 0.0f, 0.0f}; + std::array trueMomMothPV = {0.0f, 0.0f, 0.0f}; // generated mother momentum at primary vertex + std::array trueMomMothSV = {0.0f, 0.0f, 0.0f}; // true mother momentum at decay vertex + std::array trueMomDaugSV = {0.0f, 0.0f, 0.0f}; // true daughter momentum at decay vertex + + bool isMothReco = false; + std::array momMothPV = {0.0f, 0.0f, 0.0f}; + std::array updateMomMothPV = {0.0f, 0.0f, 0.0f}; // mother momentum at primary vertex after update using PV +}; + +//-------------------------------------------------------------- +// analysis task for 2-body kink decay +struct HyperkinkRecoTask { + + Produces outputDataTable; + Produces outputMCTable; + + Service ccdb; + o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; + + std::vector mcPartIndices; + + // Histograms are defined with HistogramRegistry + HistogramRegistry registry{"registry", {}}; + + Configurable hypoMoth{"hypoMoth", kHypertriton, "Mother particle hypothesis"}; + // Configurable for event selection + Configurable doEventCut{"doEventCut", true, "Apply event selection"}; + Configurable maxZVertex{"maxZVertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable cutTPCNSigmaDaug{"cutTPCNSigmaDaug", 5, "TPC NSigma cut for daughter tracks"}; + Configurable cutTOFNSigmaDaug{"cutTOFNSigmaDaug", 1000, "TOF NSigma cut for daughter tracks"}; + + // CCDB options + Configurable inputBz{"inputBz", -999, "bz field, -999 is automatic"}; + Configurable ccdbPath{"ccdbPath", "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"}; + + int mRunNumber; + float mBz; + o2::base::MatLayerCylSet* lut = nullptr; + + o2::aod::ITSResponse itsResponse; + + float massChargedDaug = 999.f; + float massNeutralDaug = 999.f; + int pdgMoth = 0; + std::array pdgDaug = {o2::constants::physics::Pdg::kTriton, PDG_t::kPi0}; // pdgcode of charged (0) and neutral (1) daughter particles + o2::track::PID pidTypeDaug = o2::track::PID::Triton; + + // secondary TOF PID + o2::aod::pidtofgeneric::TofPidNewCollision secondaryTOFPID; // to be updated in Init based on the hypothesis + o2::aod::pidtofgeneric::TofPidNewCollision secondaryTOFPIDLabeled; // to be updated in Init based on the hypothesis + // TOF response and input parameters + o2::pid::tof::TOFResoParamsV3 mRespParamsV3; + o2::aod::pidtofgeneric::TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration + + void init(InitContext& initContext) + { + if (hypoMoth == kHypertriton) { + massChargedDaug = o2::constants::physics::MassTriton; + massNeutralDaug = o2::constants::physics::MassPi0; + pdgMoth = o2::constants::physics::Pdg::kHyperTriton; + pdgDaug[kDaugCharged] = o2::constants::physics::Pdg::kTriton; + pdgDaug[kDaugNeutral] = PDG_t::kPi0; + pidTypeDaug = o2::track::PID::Triton; + } else if (hypoMoth == kHyperhelium4sigma) { + massChargedDaug = o2::constants::physics::MassAlpha; + massNeutralDaug = o2::constants::physics::MassPi0; + pdgMoth = o2::constants::physics::Pdg::kHyperHelium4Sigma; + pdgDaug[kDaugCharged] = o2::constants::physics::Pdg::kAlpha; + pdgDaug[kDaugNeutral] = PDG_t::kPi0; + pidTypeDaug = o2::track::PID::Alpha; + } else { + LOG(fatal) << "Unknown mother particle hypothesis"; + } + + // Axes + const AxisSpec vertexZAxis{100, -15., 15., "vtx_{Z} [cm]"}; + const AxisSpec ptAxis{50, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec nSigmaAxis{120, -6.f, 6.f, "n#sigma"}; + AxisSpec massAxis(100, 2.94, 3.2, "m (GeV/#it{c}^{2})"); + if (hypoMoth == kHyperhelium4sigma) { + massAxis = AxisSpec{100, 3.85, 4.25, "m (GeV/#it{c}^{2})"}; + } + const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta #it{p}_{T} (GeV/#it{c})"}; + const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta #it{p}_{z} (GeV/#it{c})"}; + const AxisSpec radiusAxis{40, 0.f, 40.f, "R (cm)"}; + + registry.add("hEventCounter", "hEventCounter", HistType::kTH1F, {{2, 0, 2}}); + registry.add("hVertexZCollision", "hVertexZCollision", HistType::kTH1F, {vertexZAxis}); + registry.add("hCandidateCounter", "hCandidateCounter", HistType::kTH1F, {{4, 0, 4}}); + + if (doprocessMC == true) { + itsResponse.setMCDefaultParameters(); + + registry.add("hTrueCandidateCounter", "hTrueCandidateCounter", HistType::kTH1F, {{4, 0, 4}}); + registry.add("hDiffSVx", ";#Delta x (cm);", HistType::kTH1F, {{200, -10, 10}}); + registry.add("hDiffSVy", ";#Delta y (cm);", HistType::kTH1F, {{200, -10, 10}}); + registry.add("hDiffSVz", ";#Delta z (cm);", HistType::kTH1F, {{200, -10, 10}}); + registry.add("h2RecSVRVsTrueSVR", ";Reconstruced SV R (cm);True SV R (cm);", HistType::kTH2F, {radiusAxis, radiusAxis}); + registry.add("h2TrueMotherDiffPtVsRecSVR", ";Reconstruced SV R (cm);#Delta #it{p}_{T} (GeV/#it{c});", HistType::kTH2F, {radiusAxis, diffPtAxis}); + registry.add("h2TrueMotherDiffEtaVsRecSVR", ";Reconstruced SV R (cm);#Delta #eta;", HistType::kTH2F, {radiusAxis, {200, -0.1, 0.1}}); + registry.add("hDiffDauPx", ";#Delta p_{x} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); + registry.add("hDiffDauPy", ";#Delta p_{y} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); + registry.add("hDiffDauPz", ";#Delta p_{z} (GeV/#it{c}); ", HistType::kTH1D, {{200, -10, 10}}); + registry.add("h2TrueSignalMassPt", "h2TrueSignalMassPt", HistType::kTH2F, {{ptAxis, massAxis}}); + registry.add("h2TrueDaugTPCNSigmaPt", "h2TrueDaugTPCNSigmaPt", HistType::kTH2F, {{ptAxis, nSigmaAxis}}); + + registry.add("hDCAXYMothToRecSV", "hDCAXYMothToRecSV", HistType::kTH1F, {{200, -10, 10}}); + registry.add("hDCAZMothToRecSV", "hDCAZMothToRecSV", HistType::kTH1F, {{200, -10, 10}}); + + registry.add("hDaugOldTOFNSigma_CorrectCol", "hDaugOldTOFNSigma_CorrectCol", HistType::kTH1F, {{600, -300, 300}}); + registry.add("hDaugOldTOFNSigma_WrongCol", "hDaugOldTOFNSigma_WrongCol", HistType::kTH1F, {{600, -300, 300}}); + registry.add("hDaugNewTOFNSigma_CorrectCol", "hDaugNewTOFNSigma_CorrectCol", HistType::kTH1F, {{600, -300, 300}}); + registry.add("hDaugNewTOFNSigma_WrongCol", "hDaugNewTOFNSigma_WrongCol", HistType::kTH1F, {{600, -300, 300}}); + } + + registry.add("h2MothMassPt", "h2MothMassPt", HistType::kTH2F, {{ptAxis, massAxis}}); + registry.add("h2DaugTPCNSigmaPt", "h2DaugTPCNSigmaPt", HistType::kTH2F, {{ptAxis, nSigmaAxis}}); + + ccdb->setURL(ccdbPath); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + mTOFCalibConfig.metadataInfo = metadataInfo; + mTOFCalibConfig.inheritFromBaseTask(initContext); + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); + secondaryTOFPID.SetPidType(pidTypeDaug); + secondaryTOFPIDLabeled.SetPidType(pidTypeDaug); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + ccdb->clearCache(grpmagPath.value.data()); + LOG(info) << "Initializing CCDB for run " << mRunNumber; + o2::parameters::GRPMagField* grpmag = ccdb->getForRun(grpmagPath, mRunNumber); + o2::base::Propagator::initFieldFromGRP(grpmag); + mBz = grpmag->getNominalL3Field(); + + if (!lut) { + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + } + o2::base::Propagator::Instance()->setMatLUT(lut); + LOG(info) << "Task initialized for run " << mRunNumber << " with magnetic field " << mBz << " kZG"; + + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, bc); + } + + // ______________________________________________________________ + // get recalulate TOFNSigma for daughter track + template + double getTOFNSigma(o2::pid::tof::TOFResoParamsV3 const& parameters, TTrack const& track, TCollision const& collision, TCollision const& originalcol) + { + // TOF PID of deuteron + if (track.has_collision() && track.hasTOF()) { + if constexpr (isMC) { + return secondaryTOFPIDLabeled.GetTOFNSigma(parameters, track, originalcol, collision); + } else { + return secondaryTOFPID.GetTOFNSigma(parameters, track, originalcol, collision); + } + } + return -999; + } + + template + void fillCandidate(HypKinkCandidate& hypkinkCand, TCollision const& collision, TKindCandidate const& kinkCand, TTrack const& trackMoth, TTrack const& trackDaug) + { + hypkinkCand.isMatter = kinkCand.mothSign() > 0; + hypkinkCand.posPV[0] = collision.posX(); + hypkinkCand.posPV[1] = collision.posY(); + hypkinkCand.posPV[2] = collision.posZ(); + hypkinkCand.posSV[0] = kinkCand.xDecVtx() + collision.posX(); + hypkinkCand.posSV[1] = kinkCand.yDecVtx() + collision.posY(); + hypkinkCand.posSV[2] = kinkCand.zDecVtx() + collision.posZ(); + + hypkinkCand.momMothSV[0] = kinkCand.pxMoth(); + hypkinkCand.momMothSV[1] = kinkCand.pyMoth(); + hypkinkCand.momMothSV[2] = kinkCand.pzMoth(); + hypkinkCand.momDaugSV[0] = kinkCand.pxDaug(); + hypkinkCand.momDaugSV[1] = kinkCand.pyDaug(); + hypkinkCand.momDaugSV[2] = kinkCand.pzDaug(); + + hypkinkCand.dcaXYMothPv = kinkCand.dcaMothPv(); + hypkinkCand.dcaXYDaugPv = kinkCand.dcaDaugPv(); + hypkinkCand.dcaKinkTopo = kinkCand.dcaKinkTopo(); + + fillCandidateRecoMoth(hypkinkCand, collision, trackMoth); + + hypkinkCand.itsClusterSizeDaug = trackDaug.itsClusterSizes(); + hypkinkCand.nSigmaTPCDaug = getTPCNSigma(trackDaug, pidTypeDaug); + hypkinkCand.nSigmaITSDaug = getITSNSigma(trackDaug, itsResponse, pidTypeDaug); + + int lastLayerMoth = 0; + for (int i = 6; i >= 0; i--) { + if (trackMoth.itsClusterMap() & (1 << i)) { + lastLayerMoth = i; + break; + } + } + auto trackparMother = getTrackParCov(trackMoth); + o2::base::Propagator::Instance()->PropagateToXBxByBz(trackparMother, LayerRadii[lastLayerMoth]); + std::array posLastHit{-999.f}; + trackparMother.getXYZGlo(posLastHit); + hypkinkCand.lastPosMoth[0] = posLastHit[0]; + hypkinkCand.lastPosMoth[1] = posLastHit[1]; + hypkinkCand.lastPosMoth[2] = posLastHit[2]; + } + + template + void fillCandidateRecoMoth(HypKinkCandidate& hypkinkCand, TCollision const& collision, TTrack const& trackMoth) + { + hypkinkCand.isMothReco = true; + hypkinkCand.chi2ITSMoth = trackMoth.itsChi2NCl(); + hypkinkCand.itsClusterSizeMoth = trackMoth.itsClusterSizes(); + + auto motherTrackPar = getTrackParCov(trackMoth); + o2::dataformats::VertexBase primaryVtx = {{collision.posX(), collision.posY(), collision.posZ()}, {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}}; + std::array pMotherPv = {-999.f}; + if (o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVtx, motherTrackPar, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT)) { + motherTrackPar.getPxPyPzGlo(pMotherPv); + } + hypkinkCand.momMothPV[0] = pMotherPv[0]; + hypkinkCand.momMothPV[1] = pMotherPv[1]; + hypkinkCand.momMothPV[2] = pMotherPv[2]; + + std::array updatePMotherPv = {-999.f}; + if (motherTrackPar.update(primaryVtx)) { + motherTrackPar.getPxPyPzGlo(updatePMotherPv); + } + hypkinkCand.updateMomMothPV[0] = updatePMotherPv[0]; + hypkinkCand.updateMomMothPV[1] = updatePMotherPv[1]; + hypkinkCand.updateMomMothPV[2] = updatePMotherPv[2]; + } + + template + void fillCandidateMCInfo(HypKinkCandidate& hypkinkCand, TMCParticle const& mcMothTrack, TMCParticle const& mcDaugTrack, TMCParticle const& mcNeutDaugTrack) + { + hypkinkCand.truePosSV[0] = mcDaugTrack.vx(); + hypkinkCand.truePosSV[1] = mcDaugTrack.vy(); + hypkinkCand.truePosSV[2] = mcDaugTrack.vz(); + hypkinkCand.trueMomMothPV[0] = mcMothTrack.px(); + hypkinkCand.trueMomMothPV[1] = mcMothTrack.py(); + hypkinkCand.trueMomMothPV[2] = mcMothTrack.pz(); + hypkinkCand.trueMomMothSV[0] = mcDaugTrack.px() + mcNeutDaugTrack.px(); + hypkinkCand.trueMomMothSV[1] = mcDaugTrack.py() + mcNeutDaugTrack.py(); + hypkinkCand.trueMomMothSV[2] = mcDaugTrack.pz() + mcNeutDaugTrack.pz(); + hypkinkCand.trueMomDaugSV[0] = mcDaugTrack.px(); + hypkinkCand.trueMomDaugSV[1] = mcDaugTrack.py(); + hypkinkCand.trueMomDaugSV[2] = mcDaugTrack.pz(); + } + + void processData(CollisionsFull const& collisions, aod::KinkCands const& KinkCands, FullTracksExtIU const&, aod::BCsWithTimestamps const&) + { + for (const auto& collision : collisions) { + registry.fill(HIST("hEventCounter"), 0); + if (doEventCut && (std::abs(collision.posZ()) > maxZVertex || !collision.sel8())) { + continue; + } + registry.fill(HIST("hEventCounter"), 1); + registry.fill(HIST("hVertexZCollision"), collision.posZ()); + } + + for (const auto& kinkCand : KinkCands) { + registry.fill(HIST("hCandidateCounter"), 0); + auto collision = kinkCand.collision_as(); + if (doEventCut && (std::abs(collision.posZ()) > maxZVertex || !collision.sel8())) { + continue; + } + registry.fill(HIST("hCandidateCounter"), 1); + + auto daugTrack = kinkCand.trackDaug_as(); + float tpcNSigmaDaug = getTPCNSigma(daugTrack, pidTypeDaug); + if (std::abs(tpcNSigmaDaug) > cutTPCNSigmaDaug) { + continue; + } + float invMass = RecoDecay::m(std::array{std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}, std::array{kinkCand.pxDaugNeut(), kinkCand.pyDaugNeut(), kinkCand.pzDaugNeut()}}, std::array{massChargedDaug, massNeutralDaug}); + registry.fill(HIST("hCandidateCounter"), 2); + registry.fill(HIST("h2MothMassPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); + registry.fill(HIST("h2DaugTPCNSigmaPt"), kinkCand.mothSign() * kinkCand.ptDaug(), tpcNSigmaDaug); + + auto bc = collision.bc_as(); + initCCDB(bc); + auto motherTrack = kinkCand.trackMoth_as(); + float nSigmaTOF = -999.f; + if (daugTrack.hasTOF() && daugTrack.has_collision()) { + auto originalDaugCol = daugTrack.collision_as(); + nSigmaTOF = getTOFNSigma(mRespParamsV3, daugTrack, collision, originalDaugCol); + } + if (std::abs(nSigmaTOF) > cutTOFNSigmaDaug) { + continue; + } + + registry.fill(HIST("hCandidateCounter"), 2); + HypKinkCandidate hypkinkCand; + fillCandidate(hypkinkCand, collision, kinkCand, motherTrack, daugTrack); + hypkinkCand.nSigmaTOFDaug = nSigmaTOF; + + o2::dataformats::VertexBase primaryVtx = {{collision.posX(), collision.posY(), collision.posZ()}, {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}}; + o2::dataformats::VertexBase secondaryVtx = {{kinkCand.xDecVtx() + collision.posX(), kinkCand.yDecVtx() + collision.posY(), kinkCand.zDecVtx() + collision.posZ()}, {covPosSV[0], covPosSV[1], covPosSV[2], covPosSV[3], covPosSV[4], covPosSV[5]}}; + std::array refitPPV = {-999.f}; + std::array refitPSV = {-999.f}; + auto motherTrackPar = getTrackParCov(motherTrack); + if (refitMotherTrack(motherTrack, motherTrackPar, primaryVtx, secondaryVtx)) { + motherTrackPar.getPxPyPzGlo(refitPSV); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVtx, motherTrackPar, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT); + motherTrackPar.getPxPyPzGlo(refitPPV); + } + + outputDataTable( + mBz > 0 ? 1 : -1, + hypkinkCand.posPV[0], hypkinkCand.posPV[1], hypkinkCand.posPV[2], + hypkinkCand.posSV[0], hypkinkCand.posSV[1], hypkinkCand.posSV[2], + hypkinkCand.isMatter, + hypkinkCand.lastPosMoth[0], hypkinkCand.lastPosMoth[1], hypkinkCand.lastPosMoth[2], + hypkinkCand.momMothSV[0], hypkinkCand.momMothSV[1], hypkinkCand.momMothSV[2], + refitPPV[0], refitPPV[1], refitPPV[2], + refitPSV[0], refitPSV[1], refitPSV[2], + hypkinkCand.momDaugSV[0], hypkinkCand.momDaugSV[1], hypkinkCand.momDaugSV[2], + hypkinkCand.dcaXYMothPv, hypkinkCand.dcaXYDaugPv, hypkinkCand.dcaKinkTopo, + hypkinkCand.chi2ITSMoth, hypkinkCand.itsClusterSizeMoth, hypkinkCand.itsClusterSizeDaug, + hypkinkCand.nSigmaTPCDaug, hypkinkCand.nSigmaITSDaug, hypkinkCand.nSigmaTOFDaug, + hypkinkCand.momMothPV[0], hypkinkCand.momMothPV[1], hypkinkCand.momMothPV[2], + hypkinkCand.updateMomMothPV[0], hypkinkCand.updateMomMothPV[1], hypkinkCand.updateMomMothPV[2]); + } + } + PROCESS_SWITCH(HyperkinkRecoTask, processData, "process data", true); + + void processMC(MCLabeledCollisionsFull const& collisions, aod::KinkCands const& KinkCands, MCLabeledTracksIU const& tracks, aod::McParticles const& particlesMC, aod::McCollisions const& mcCollisions, aod::BCsWithTimestamps const&) + { + mcPartIndices.clear(); + std::vector mcPartIndices; + setTrackIDForMC(mcPartIndices, particlesMC, tracks); + std::vector isReconstructedMCCollisions(mcCollisions.size(), false); + std::vector isSelectedMCCollisions(mcCollisions.size(), false); + std::vector isGoodCollisions(collisions.size(), false); + std::vector dauIDList(2, -1); + + for (const auto& collision : collisions) { + isReconstructedMCCollisions[collision.mcCollisionId()] = true; + registry.fill(HIST("hEventCounter"), 0); + if (doEventCut && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > maxZVertex)) { + continue; + } + registry.fill(HIST("hEventCounter"), 1); + registry.fill(HIST("hVertexZCollision"), collision.posZ()); + isSelectedMCCollisions[collision.mcCollisionId()] = true; + isGoodCollisions[collision.globalIndex()] = true; + } + + for (const auto& kinkCand : KinkCands) { + auto motherTrack = kinkCand.trackMoth_as(); + auto daugTrack = kinkCand.trackDaug_as(); + + bool isKinkSignal = false; + if (motherTrack.has_mcParticle() && daugTrack.has_mcParticle()) { + auto mcMothTrack = motherTrack.mcParticle_as(); + auto mcDaugTrack = daugTrack.mcParticle_as(); + if (hypoMoth == kHypertriton) { + auto dChannel = H3LDecay::getDecayChannel(mcMothTrack, dauIDList); + if (dChannel == H3LDecay::k2bodyNeutral && dauIDList[0] == mcDaugTrack.globalIndex()) { + isKinkSignal = true; + } + } else if (hypoMoth == kHyperhelium4sigma) { + auto dChannel = He4SDecay::getDecayChannel(mcMothTrack, dauIDList); + if (dChannel == He4SDecay::k2body && dauIDList[0] == mcDaugTrack.globalIndex()) { + isKinkSignal = true; + } + } + } + + registry.fill(HIST("hCandidateCounter"), 0); + if (isKinkSignal) { + registry.fill(HIST("hTrueCandidateCounter"), 0); + } + auto collision = kinkCand.collision_as(); + if (!isGoodCollisions[collision.globalIndex()]) { + continue; + } + registry.fill(HIST("hCandidateCounter"), 1); + if (isKinkSignal) { + registry.fill(HIST("hTrueCandidateCounter"), 1); + } + + float tpcNSigmaDaug = getTPCNSigma(daugTrack, pidTypeDaug); + if (std::abs(tpcNSigmaDaug) > cutTPCNSigmaDaug) { + continue; + } + float invMass = RecoDecay::m(std::array{std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}, std::array{kinkCand.pxDaugNeut(), kinkCand.pyDaugNeut(), kinkCand.pzDaugNeut()}}, std::array{massChargedDaug, massNeutralDaug}); + registry.fill(HIST("hCandidateCounter"), 2); + if (isKinkSignal) { + registry.fill(HIST("hTrueCandidateCounter"), 2); + } + registry.fill(HIST("h2MothMassPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); + registry.fill(HIST("h2DaugTPCNSigmaPt"), kinkCand.mothSign() * kinkCand.ptDaug(), tpcNSigmaDaug); + + auto bc = collision.bc_as(); + initCCDB(bc); + float nSigmaTOF = -999.f; + if (daugTrack.hasTOF() && daugTrack.has_collision()) { + auto originalDaugCol = daugTrack.collision_as(); + float defaultNSigmaTOF = getDefaultTOFNSigma(daugTrack, pidTypeDaug); + nSigmaTOF = getTOFNSigma(mRespParamsV3, daugTrack, collision, originalDaugCol); + if (originalDaugCol.globalIndex() == collision.globalIndex()) { + registry.fill(HIST("hDaugOldTOFNSigma_CorrectCol"), defaultNSigmaTOF); + registry.fill(HIST("hDaugNewTOFNSigma_CorrectCol"), nSigmaTOF); + } else { + registry.fill(HIST("hDaugOldTOFNSigma_WrongCol"), defaultNSigmaTOF); + registry.fill(HIST("hDaugNewTOFNSigma_WrongCol"), nSigmaTOF); + } + } + if (std::abs(nSigmaTOF) > cutTOFNSigmaDaug) { + continue; + } + registry.fill(HIST("hCandidateCounter"), 3); + if (isKinkSignal) { + registry.fill(HIST("hTrueCandidateCounter"), 3); + } + + HypKinkCandidate hypkinkCand; + fillCandidate(hypkinkCand, collision, kinkCand, motherTrack, daugTrack); + hypkinkCand.nSigmaTOFDaug = nSigmaTOF; + + std::array posDecVtx = {kinkCand.xDecVtx() + collision.posX(), kinkCand.yDecVtx() + collision.posY(), kinkCand.zDecVtx() + collision.posZ()}; + + o2::dataformats::VertexBase primaryVtx = {{collision.posX(), collision.posY(), collision.posZ()}, {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}}; + o2::dataformats::VertexBase secondaryVtx = {{posDecVtx[0], posDecVtx[1], posDecVtx[2]}, {covPosSV[0], covPosSV[1], covPosSV[2], covPosSV[3], covPosSV[4], covPosSV[5]}}; + std::array refitPPV = {-999.f}; + std::array refitPSV = {-999.f}; + auto motherTrackPar = getTrackParCov(motherTrack); + if (refitMotherTrack(motherTrack, motherTrackPar, primaryVtx, secondaryVtx)) { + motherTrackPar.getPxPyPzGlo(refitPSV); + o2::base::Propagator::Instance()->propagateToDCABxByBz(primaryVtx, motherTrackPar, 2.f, o2::base::Propagator::MatCorrType::USEMatCorrLUT); + motherTrackPar.getPxPyPzGlo(refitPPV); + } + + // QA, store mcInfo for true signals + if (isKinkSignal) { + auto mcMothTrack = motherTrack.mcParticle_as(); + auto mcDaugTrack = daugTrack.mcParticle_as(); + auto mcNeutTrack = particlesMC.rawIteratorAt(dauIDList[1]); + float recSVR = std::sqrt(posDecVtx[0] * posDecVtx[0] + posDecVtx[1] * posDecVtx[1]); + registry.fill(HIST("hDiffSVx"), posDecVtx[0] - mcDaugTrack.vx()); + registry.fill(HIST("hDiffSVy"), posDecVtx[1] - mcDaugTrack.vy()); + registry.fill(HIST("hDiffSVz"), posDecVtx[2] - mcDaugTrack.vz()); + registry.fill(HIST("h2RecSVRVsTrueSVR"), recSVR, std::hypot(mcDaugTrack.vx(), mcDaugTrack.vy())); + registry.fill(HIST("h2TrueMotherDiffPtVsRecSVR"), recSVR, mcMothTrack.pt() - kinkCand.ptMoth()); + registry.fill(HIST("h2TrueMotherDiffEtaVsRecSVR"), recSVR, mcMothTrack.eta() - motherTrack.eta()); + registry.fill(HIST("hDiffDauPx"), kinkCand.pxDaug() - mcDaugTrack.px()); + registry.fill(HIST("hDiffDauPy"), kinkCand.pyDaug() - mcDaugTrack.py()); + registry.fill(HIST("hDiffDauPz"), kinkCand.pzDaug() - mcDaugTrack.pz()); + registry.fill(HIST("h2TrueSignalMassPt"), kinkCand.mothSign() * kinkCand.ptMoth(), invMass); + registry.fill(HIST("h2TrueDaugTPCNSigmaPt"), kinkCand.mothSign() * kinkCand.ptDaug(), tpcNSigmaDaug); + + hypkinkCand.isSignal = true; + hypkinkCand.isSignalReco = true; + fillCandidateMCInfo(hypkinkCand, mcMothTrack, mcDaugTrack, mcNeutTrack); + mcPartIndices.push_back(mcMothTrack.globalIndex()); + + std::array dcaInfo; + auto mcMothTrackPar = getTrackParFromMC(mcMothTrack, 2); + o2::base::Propagator::Instance()->propagateToDCABxByBz({posDecVtx[0], posDecVtx[1], posDecVtx[2]}, mcMothTrackPar, 2.f, matCorr, &dcaInfo); + registry.fill(HIST("hDCAXYMothToRecSV"), dcaInfo[0]); + registry.fill(HIST("hDCAZMothToRecSV"), dcaInfo[1]); + } + + hypkinkCand.isCollReco = true; + hypkinkCand.isSurvEvSelection = true; + + outputMCTable( + mBz > 0 ? 1 : -1, + hypkinkCand.posPV[0], hypkinkCand.posPV[1], hypkinkCand.posPV[2], + hypkinkCand.posSV[0], hypkinkCand.posSV[1], hypkinkCand.posSV[2], + hypkinkCand.isMatter, + hypkinkCand.lastPosMoth[0], hypkinkCand.lastPosMoth[1], hypkinkCand.lastPosMoth[2], + hypkinkCand.momMothSV[0], hypkinkCand.momMothSV[1], hypkinkCand.momMothSV[2], + refitPPV[0], refitPPV[1], refitPPV[2], + refitPSV[0], refitPSV[1], refitPSV[2], + hypkinkCand.momDaugSV[0], hypkinkCand.momDaugSV[1], hypkinkCand.momDaugSV[2], + hypkinkCand.dcaXYMothPv, hypkinkCand.dcaXYDaugPv, hypkinkCand.dcaKinkTopo, + hypkinkCand.chi2ITSMoth, hypkinkCand.itsClusterSizeMoth, hypkinkCand.itsClusterSizeDaug, + hypkinkCand.nSigmaTPCDaug, hypkinkCand.nSigmaITSDaug, hypkinkCand.nSigmaTOFDaug, + hypkinkCand.isSignal, hypkinkCand.isSignalReco, hypkinkCand.isCollReco, hypkinkCand.isSurvEvSelection, + hypkinkCand.truePosSV[0], hypkinkCand.truePosSV[1], hypkinkCand.truePosSV[2], + hypkinkCand.trueMomMothPV[0], hypkinkCand.trueMomMothPV[1], hypkinkCand.trueMomMothPV[2], + hypkinkCand.trueMomMothSV[0], hypkinkCand.trueMomMothSV[1], hypkinkCand.trueMomMothSV[2], + hypkinkCand.trueMomDaugSV[0], hypkinkCand.trueMomDaugSV[1], hypkinkCand.trueMomDaugSV[2], + hypkinkCand.isMothReco, hypkinkCand.momMothPV[0], hypkinkCand.momMothPV[1], hypkinkCand.momMothPV[2], + hypkinkCand.updateMomMothPV[0], hypkinkCand.updateMomMothPV[1], hypkinkCand.updateMomMothPV[2]); + } + + // fill kink signals which are not reconstructed + for (auto const& mcparticle : particlesMC) { + bool isKinkSignal = false; + if (hypoMoth == kHypertriton) { + auto dChannel = H3LDecay::getDecayChannel(mcparticle, dauIDList); + if (dChannel == H3LDecay::k2bodyNeutral) { + isKinkSignal = true; + } + } else if (hypoMoth == kHyperhelium4sigma) { + auto dChannel = He4SDecay::getDecayChannel(mcparticle, dauIDList); + if (dChannel == He4SDecay::k2body) { + isKinkSignal = true; + } + } + if (!isKinkSignal) { + continue; + } + + if (std::find(mcPartIndices.begin(), mcPartIndices.end(), mcparticle.globalIndex()) != mcPartIndices.end()) { + continue; + } + + HypKinkCandidate hypkinkCand; + auto mcDaugTrack = particlesMC.rawIteratorAt(dauIDList[0]); + auto mcNeutTrack = particlesMC.rawIteratorAt(dauIDList[1]); + fillCandidateMCInfo(hypkinkCand, mcparticle, mcDaugTrack, mcNeutTrack); + + if (mcPartIndices[mcparticle.globalIndex()] != -1) { + auto mothTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); + if (mothTrack.has_collision()) { + auto collision = mothTrack.collision_as(); + auto bc = collision.template bc_as(); + initCCDB(bc); + fillCandidateRecoMoth(hypkinkCand, collision, mothTrack); + } + } + + outputMCTable( + mBz > 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, -1, + -1, -1, -1, + true, false, isReconstructedMCCollisions[mcparticle.mcCollisionId()], isSelectedMCCollisions[mcparticle.mcCollisionId()], + hypkinkCand.truePosSV[0], hypkinkCand.truePosSV[1], hypkinkCand.truePosSV[2], + hypkinkCand.trueMomMothPV[0], hypkinkCand.trueMomMothPV[1], hypkinkCand.trueMomMothPV[2], + hypkinkCand.trueMomMothSV[0], hypkinkCand.trueMomMothSV[1], hypkinkCand.trueMomMothSV[2], + hypkinkCand.trueMomDaugSV[0], hypkinkCand.trueMomDaugSV[1], hypkinkCand.trueMomDaugSV[2], + hypkinkCand.isMothReco, hypkinkCand.momMothPV[0], hypkinkCand.momMothPV[1], hypkinkCand.momMothPV[2], + hypkinkCand.updateMomMothPV[0], hypkinkCand.updateMomMothPV[1], hypkinkCand.updateMomMothPV[2]); + } + } + PROCESS_SWITCH(HyperkinkRecoTask, processMC, "process MC", false); +}; + +//-------------------------------------------------------------- +// check the performance of mcparticle +struct HyperkinkQa { + + Configurable hypoMoth{"hypoMoth", kHypertriton, "Mother particle hypothesis"}; + + HistogramRegistry genQAHist{"genQAHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry recoQAHist{"recoQAHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + ConfigurableAxis ptBins{"ptBins", {200, 0.f, 10.f}, "Binning for #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis ctBins{"ctBins", {100, 0.f, 25.f}, "Binning for c#it{t} (cm)"}; + ConfigurableAxis rigidityBins{"rigidityBins", {200, -10.f, 10.f}, "Binning for #it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis nsigmaBins{"nsigmaBins", {120, -6.f, 6.f}, "Binning for n sigma"}; + ConfigurableAxis invMassBins{"invMassBins", {100, 3.85f, 4.15f}, "Binning for invariant mass (GeV/#it{c}^{2})"}; + ConfigurableAxis radiusBins{"radiusBins", {40, 0.f, 40.f}, "Binning for radius in xy plane (cm)"}; + + o2::aod::ITSResponse itsResponse; + + int charge = 1; + float massMoth = 999.f; + float massChargedDaug = 999.f; + float massNeutralDaug = 999.f; + int pdgMoth = 0; + std::array pdgDaug = {o2::constants::physics::Pdg::kTriton, PDG_t::kPi0}; // pdgcode of charged (0) and neutral (1) daughter particles + o2::track::PID pidTypeDaug = o2::track::PID::Triton; + + void init(InitContext&) + { + if (doprocessMC == true) { + itsResponse.setMCDefaultParameters(); + + if (hypoMoth == kHypertriton) { + charge = 1; + massMoth = o2::constants::physics::MassHyperTriton; + massChargedDaug = o2::constants::physics::MassTriton; + massNeutralDaug = o2::constants::physics::MassPi0; + pdgMoth = o2::constants::physics::Pdg::kHyperTriton; + pdgDaug[kDaugCharged] = o2::constants::physics::Pdg::kTriton; + pdgDaug[kDaugNeutral] = PDG_t::kPi0; + pidTypeDaug = o2::track::PID::Triton; + } else if (hypoMoth == kHyperhelium4sigma) { + charge = 2; + massMoth = o2::constants::physics::MassHyperHelium4Sigma; + massChargedDaug = o2::constants::physics::MassAlpha; + massNeutralDaug = o2::constants::physics::MassPi0; + pdgMoth = o2::constants::physics::Pdg::kHyperHelium4Sigma; + pdgDaug[kDaugCharged] = o2::constants::physics::Pdg::kAlpha; + pdgDaug[kDaugNeutral] = PDG_t::kPi0; + pidTypeDaug = o2::track::PID::Alpha; + } else { + LOG(fatal) << "Unknown mother particle hypothesis"; + } + + const AxisSpec pAxis{ptBins, "#it{p} (GeV/#it{c})"}; + const AxisSpec ptAxis{ptBins, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec ctAxis{ctBins, "c#it{t} (cm)"}; + const AxisSpec rigidityAxis{rigidityBins, "p/z (GeV/#it{c})"}; + const AxisSpec nsigmaAxis{nsigmaBins, "TPC n#sigma"}; + const AxisSpec itsnsigmaAxis{nsigmaBins, "ITS n#sigma"}; + const AxisSpec invMassAxis{invMassBins, "Inv Mass (GeV/#it{c}^{2})"}; + const AxisSpec diffPtAxis{200, -10.f, 10.f, "#Delta p_{T} (GeV/#it{c})"}; + const AxisSpec diffPzAxis{200, -10.f, 10.f, "#Delta p_{z} (GeV/#it{c})"}; + const AxisSpec itsRadiusAxis{radiusBins, "ITS R (cm)"}; + const AxisSpec svRadiuAxis{radiusBins, "Decay Vertex R (cm)"}; + + auto hCollCounter = genQAHist.add("hCollCounter", "hCollCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); + hCollCounter->GetXaxis()->SetBinLabel(1, "Reconstructed Collisions"); + hCollCounter->GetXaxis()->SetBinLabel(2, "Selected"); + auto hMcCollCounter = genQAHist.add("hMcCollCounter", "hMcCollCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); + hMcCollCounter->GetXaxis()->SetBinLabel(1, "MC Collisions"); + hMcCollCounter->GetXaxis()->SetBinLabel(2, "Reconstructed"); + + if (hypoMoth == kHypertriton) { + auto hGenHyperMothCounter = genQAHist.add("hGenHyperMothCounter", "", HistType::kTH1F, {{10, 0.f, 10.f}}); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(1, "H3L All"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(2, "Matter"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(3, "AntiMatter"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(4, "t + #pi^{0}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(5, "#bar{t} + #pi^{0}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(6, "{}^{3}He + #pi^{-}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(7, "{}^{3}#bar{He} + #pi^{+}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(8, "d + p + #pi^{-}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(9, "#bar{d} + #bar{p} + #pi^{+}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(10, "Others"); + } else if (hypoMoth == kHyperhelium4sigma) { + auto hGenHyperMothCounter = genQAHist.add("hGenHyperMothCounter", "", HistType::kTH1F, {{10, 0.f, 10.f}}); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(1, "He4S All"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(2, "Matter"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(3, "AntiMatter"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(4, "#alpha + #pi^{0}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(5, "#bar{#alpha} + #pi^{0}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(6, "t + p + #pi^{0}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(7, "#bar{t} + #bar{p} + #pi^{0}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(8, "t + n + #pi^{+}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(9, "#bar{t} + #bar{n} + #pi^{+}"); + hGenHyperMothCounter->GetXaxis()->SetBinLabel(10, "Others"); + } + + auto hEvtSelectedHyperMothCounter = genQAHist.add("hEvtSelectedHyperMothCounter", "", HistType::kTH1F, {{2, 0.f, 2.f}}); + hEvtSelectedHyperMothCounter->GetXaxis()->SetBinLabel(1, "Generated"); + hEvtSelectedHyperMothCounter->GetXaxis()->SetBinLabel(2, "Survived"); + + genQAHist.add("hGenHyperMothP", "", HistType::kTH1F, {pAxis}); + genQAHist.add("hGenHyperMothPt", "", HistType::kTH1F, {ptAxis}); + genQAHist.add("hGenHyperMothCt", "", HistType::kTH1F, {ctAxis}); + genQAHist.add("hMcRecoInvMass", "", HistType::kTH1F, {invMassAxis}); + + // efficiency/criteria studies for tracks which are true candidates + hMothCounter = recoQAHist.add("hMothCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hMothCounter->GetXaxis()->SetBinLabel(1, "Generated"); + hMothCounter->GetXaxis()->SetBinLabel(2, "Reconstructed"); + hMothCounter->GetXaxis()->SetBinLabel(3, "eta"); + hMothCounter->GetXaxis()->SetBinLabel(4, "has collision"); + hMothCounter->GetXaxis()->SetBinLabel(5, "ITSonly"); + hMothCounter->GetXaxis()->SetBinLabel(6, "ITS hits"); + hMothCounter->GetXaxis()->SetBinLabel(7, "ITS IR"); + hMothCounter->GetXaxis()->SetBinLabel(8, "ITS chi2"); + hMothCounter->GetXaxis()->SetBinLabel(9, "pt"); + recoQAHist.add("h2TrueMotherDiffPtVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPtAxis}); + recoQAHist.add("h2TrueMotherDiffEtaVsTrueSVR", ";Decay Vertex R (cm);#Delta #eta;", HistType::kTH2F, {svRadiuAxis, {200, -1.f, 1.f}}); + recoQAHist.add("h2GoodMotherDiffPtVsTrueSVR", ";Decay Vertex R (cm);#Delta p_{T} (GeV/#it{c});", HistType::kTH2F, {svRadiuAxis, diffPtAxis}); + + hDaugCounter = recoQAHist.add("hDaugCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hDaugTPCNSigma = recoQAHist.add("hDaugTPCNSigma", "", HistType::kTH2F, {rigidityAxis, nsigmaAxis}); + + hRecoMothCounter = recoQAHist.add("hRecoMothCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + hRecoDaugCounter = recoQAHist.add("hRecoDaugCounter", "", HistType::kTH1F, {{9, 0.f, 9.f}}); + for (const auto& hist : {hDaugCounter, hRecoMothCounter, hRecoDaugCounter}) { + hist->GetXaxis()->SetBinLabel(1, "Generated"); + hist->GetXaxis()->SetBinLabel(2, "Reconstructed"); + hist->GetXaxis()->SetBinLabel(3, "eta"); + hist->GetXaxis()->SetBinLabel(4, "has ITS&TPC"); + hist->GetXaxis()->SetBinLabel(5, "TPC crossed rows"); + hist->GetXaxis()->SetBinLabel(6, "TPC Ncls"); + hist->GetXaxis()->SetBinLabel(7, "TPC n#sigma"); + hist->GetXaxis()->SetBinLabel(8, "ITS hits"); + hist->GetXaxis()->SetBinLabel(9, "has TOF"); + } + + recoQAHist.add("hMothIsPVContributer", "", HistType::kTH1F, {{2, 0.f, 2.f}}); + recoQAHist.add("hMothITSCls", "", HistType::kTH1F, {{8, 0.f, 8.f}}); + recoQAHist.add("hDaugIsPVContributer", "", HistType::kTH1F, {{2, 0.f, 2.f}}); + recoQAHist.add("hDaugITSCls", "", HistType::kTH1F, {{8, 0.f, 8.f}}); + recoQAHist.add("hDaugITSNSigma", "", HistType::kTH2F, {rigidityAxis, itsnsigmaAxis}); + recoQAHist.add("hRecoDaugPVsITSNSigma", "", HistType::kTH2F, {rigidityAxis, itsnsigmaAxis}); + recoQAHist.add("hRecoCandidateCount", "", HistType::kTH1F, {{4, 0.f, 4.f}}); + } + } + + Configurable skipRejectedEvents{"skipRejectedEvents", false, "Flag to skip events that fail event selection cuts"}; + Configurable doEventCut{"doEventCut", true, "Apply event selection"}; + Configurable maxZVertex{"maxZVertex", 10.0f, "Accepted z-vertex range (cm)"}; + + Configurable etaMax{"etaMax", 1., "eta cut for tracks"}; + Configurable minPtMoth{"minPtMoth", 0.5, "Minimum pT/z of the mother track"}; + Configurable tpcPidNsigmaCut{"tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; + Configurable nTPCClusMinDaug{"nTPCClusMinDaug", 80, "daug NTPC clusters cut"}; + Configurable itsMaxChi2{"itsMaxChi2", 36, "max chi2 for ITS"}; + Configurable minRatioTPCNCls{"minRatioTPCNCls", 0.8, "min ratio of TPC crossed rows to findable clusters"}; + + Preslice permcCollision = o2::aod::mcparticle::mcCollisionId; + + // QA for mother track selection + template + bool motherTrackCheck(const TTrack& track, const std::shared_ptr hist) + { + hist->Fill(1); + + if (std::abs(track.eta()) > etaMax) { + return false; + } + hist->Fill(2); + + if (!track.has_collision()) { + return false; + } + hist->Fill(3); + + if (!track.hasITS() || track.hasTPC() || track.hasTOF()) { + return false; + } + hist->Fill(4); + + if (track.itsNCls() >= kITSLayers - 1) { + return false; + } + hist->Fill(5); + + if (track.itsNClsInnerBarrel() != kITSInnerBarrelLayers) { + return false; + } + hist->Fill(6); + + if (track.itsChi2NCl() >= itsMaxChi2) { + return false; + } + hist->Fill(7); + + if (track.pt() <= minPtMoth) { + return false; + } + hist->Fill(8); + + return true; + } + + // qa for daughter track selection + template + bool daughterTrackCheck(const TTrack& track, const std::shared_ptr hist, float tpcNSigma) + { + hist->Fill(1); + + if (std::abs(track.eta()) > etaMax) { + return false; + } + hist->Fill(2); + + if (!track.hasITS() || !track.hasTPC()) { + return false; + } + hist->Fill(3); + + if (track.tpcNClsCrossedRows() <= minRatioTPCNCls * track.tpcNClsFindable()) { + return false; + } + hist->Fill(4); + + if (track.tpcNClsFound() <= nTPCClusMinDaug) { + return false; + } + hist->Fill(5); + + if (std::abs(tpcNSigma) > tpcPidNsigmaCut) { + return false; + } + hist->Fill(6); + + if (track.itsNClsInnerBarrel() != 0 || track.itsNCls() > kITSInnerBarrelLayers) { + return false; + } + hist->Fill(7); + + if (track.hasTOF()) { + return false; + } + hist->Fill(8); + + return true; + } + + void processData(o2::aod::Collisions const&) + { + // dummy process function; + } + PROCESS_SWITCH(HyperkinkQa, processData, "process data", true); + + void processMC(aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, MCLabeledCollisionsFull const& collisions, MCLabeledTracksIU const& tracks, aod::BCsWithTimestamps const&) + { + std::vector mcPartIndices; + setTrackIDForMC(mcPartIndices, particlesMC, tracks); + std::vector isSelectedMCCollisions(mcCollisions.size(), false); + std::vector dauIDList(2, -1); + for (const auto& collision : collisions) { + genQAHist.fill(HIST("hCollCounter"), 0.5); + if (doEventCut && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || std::abs(collision.posZ()) > maxZVertex)) { + continue; + } + genQAHist.fill(HIST("hCollCounter"), 1.5); + isSelectedMCCollisions[collision.mcCollisionId()] = true; + } + + for (const auto& mcCollision : mcCollisions) { + genQAHist.fill(HIST("hMcCollCounter"), 0.5); + if (isSelectedMCCollisions[mcCollision.globalIndex()]) { // Check that the event is reconstructed and that the reconstructed events pass the selection + genQAHist.fill(HIST("hMcCollCounter"), 1.5); + } else { + if (skipRejectedEvents) { + continue; + } + } + + const auto& dparticlesMC = particlesMC.sliceBy(permcCollision, mcCollision.globalIndex()); + + for (const auto& mcparticle : dparticlesMC) { + if (std::abs(mcparticle.pdgCode()) != pdgMoth) { + continue; + } + bool isMatter = mcparticle.pdgCode() > 0; + genQAHist.fill(HIST("hGenHyperMothCounter"), 0.5); + genQAHist.fill(HIST("hGenHyperMothCounter"), isMatter ? 1.5 : 2.5); + + // QA for decay channels + bool isKinkSignal = false; + if (hypoMoth == kHypertriton) { + auto dChannel = H3LDecay::getDecayChannel(mcparticle, dauIDList); + if (dChannel == H3LDecay::k2bodyNeutral) { + genQAHist.fill(HIST("hGenHyperMothCounter"), isMatter ? 3.5 : 4.5); + isKinkSignal = true; + } else if (dChannel == H3LDecay::k2bodyCharged) { + genQAHist.fill(HIST("hGenHyperMothCounter"), isMatter ? 5.5 : 6.5); + } else if (dChannel == H3LDecay::k3bodyCharged) { + genQAHist.fill(HIST("hGenHyperMothCounter"), isMatter ? 7.5 : 8.5); + } else if (dChannel == H3LDecay::kNChannel) { + genQAHist.fill(HIST("hGenHyperMothCounter"), 9.5); + continue; + } + } else if (hypoMoth == kHyperhelium4sigma) { + auto dChannel = He4SDecay::getDecayChannel(mcparticle, dauIDList); + if (dChannel == He4SDecay::k2body) { + genQAHist.fill(HIST("hGenHyperMothCounter"), isMatter ? 3.5 : 4.5); + isKinkSignal = true; + } else if (dChannel == He4SDecay::k3body_p) { + genQAHist.fill(HIST("hGenHyperMothCounter"), isMatter ? 5.5 : 6.5); + } else if (dChannel == He4SDecay::k3body_n) { + genQAHist.fill(HIST("hGenHyperMothCounter"), isMatter ? 7.5 : 8.5); + } else if (dChannel == He4SDecay::kNChannel) { + genQAHist.fill(HIST("hGenHyperMothCounter"), 9.5); + continue; + } + } + + if (!isKinkSignal) { + continue; + } + recoQAHist.fill(HIST("hMothCounter"), 0); + + genQAHist.fill(HIST("hEvtSelectedHyperMothCounter"), 0.5); + if (isSelectedMCCollisions[mcCollision.globalIndex()]) { + genQAHist.fill(HIST("hEvtSelectedHyperMothCounter"), 1.5); + } + + float svPos[3] = {-999, -999, -999}; + std::vector> dauMom(kNDaughterType, std::vector(3, -999.0f)); + for (const auto& mcparticleDaughter : mcparticle.daughters_as()) { + for (int type = 0; type < kNDaughterType; type++) { + if (std::abs(mcparticleDaughter.pdgCode()) == pdgDaug[type]) { + dauMom[type][0] = mcparticleDaughter.px(); + dauMom[type][1] = mcparticleDaughter.py(); + dauMom[type][2] = mcparticleDaughter.pz(); + + if (type == kDaugCharged) { + svPos[0] = mcparticleDaughter.vx(); + svPos[1] = mcparticleDaughter.vy(); + svPos[2] = mcparticleDaughter.vz(); + + // if daughter track is reconstructed + if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { + hDaugCounter->Fill(0.f); + auto track = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); + float tpcNSigma = getTPCNSigma(track, pidTypeDaug); + daughterTrackCheck(track, hDaugCounter, tpcNSigma); + if (track.hasTPC()) { + hDaugTPCNSigma->Fill(track.p() * track.sign(), tpcNSigma); + } + } + } + } + } + } + + genQAHist.fill(HIST("hGenHyperMothP"), mcparticle.p()); + genQAHist.fill(HIST("hGenHyperMothPt"), mcparticle.pt()); + float ct = RecoDecay::sqrtSumOfSquares(svPos[0] - mcparticle.vx(), svPos[1] - mcparticle.vy(), svPos[2] - mcparticle.vz()) * massMoth / mcparticle.p(); + genQAHist.fill(HIST("hGenHyperMothCt"), ct); + float hypermothMCMass = RecoDecay::m(std::array{std::array{dauMom[kDaugCharged][0], dauMom[kDaugCharged][1], dauMom[kDaugCharged][2]}, std::array{dauMom[kDaugNeutral][0], dauMom[kDaugNeutral][1], dauMom[kDaugNeutral][2]}}, std::array{massChargedDaug, massNeutralDaug}); + genQAHist.fill(HIST("hMcRecoInvMass"), hypermothMCMass); + + // if mother track is reconstructed + if (mcPartIndices[mcparticle.globalIndex()] != -1) { + auto motherTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); + bool isGoodMother = motherTrackCheck(motherTrack, hMothCounter); + float svR = RecoDecay::sqrtSumOfSquares(svPos[0], svPos[1]); + float diffpt = mcparticle.pt() - charge * motherTrack.pt(); + + recoQAHist.fill(HIST("h2TrueMotherDiffPtVsTrueSVR"), svR, diffpt); + recoQAHist.fill(HIST("h2TrueMotherDiffEtaVsTrueSVR"), svR, mcparticle.eta() - motherTrack.eta()); + if (isGoodMother) { + recoQAHist.fill(HIST("h2GoodMotherDiffPtVsTrueSVR"), svR, diffpt); + } + + // if mother track and charged daughters are all reconstructed + bool isDauReconstructed = mcPartIndices[dauIDList[0]] != -1; + if (isDauReconstructed) { + auto daughterTrack = tracks.rawIteratorAt(mcPartIndices[dauIDList[0]]); + bool isMoth = motherTrackCheck(motherTrack, hRecoMothCounter); + bool isDaug = daughterTrackCheck(daughterTrack, hRecoDaugCounter, getTPCNSigma(daughterTrack, pidTypeDaug)); + + recoQAHist.fill(HIST("hRecoCandidateCount"), 0.5); + recoQAHist.fill(HIST("hRecoMothCounter"), 0.5); + recoQAHist.fill(HIST("hMothITSCls"), motherTrack.itsNCls()); + recoQAHist.fill(HIST("hRecoDaugCounter"), 0.5); + recoQAHist.fill(HIST("hMothIsPVContributer"), motherTrack.isPVContributor() ? 1.5 : 0.5); + recoQAHist.fill(HIST("hDaugIsPVContributer"), daughterTrack.isPVContributor() ? 1.5 : 0.5); + + float itsNSigma = getITSNSigma(daughterTrack, itsResponse, pidTypeDaug); + if (daughterTrack.hasITS()) { + recoQAHist.fill(HIST("hDaugITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); + recoQAHist.fill(HIST("hDaugITSCls"), daughterTrack.itsNCls()); + } + + if (motherTrack.has_collision() && daughterTrack.has_collision()) { + recoQAHist.fill(HIST("hRecoCandidateCount"), 1.5); + if (motherTrack.collisionId() == daughterTrack.collisionId()) { + recoQAHist.fill(HIST("hRecoCandidateCount"), 2.5); + } + } + + if (isMoth && isDaug) { + recoQAHist.fill(HIST("hRecoCandidateCount"), 3.5); + recoQAHist.fill(HIST("hRecoDaugPVsITSNSigma"), daughterTrack.sign() * daughterTrack.p(), itsNSigma); + } + } + } + } + } + } + PROCESS_SWITCH(HyperkinkQa, processMC, "do QA for MC prodcutions", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + metadataInfo.initMetadata(cfgc); + return WorkflowSpec{ + // Parse the metadata + adaptAnalysisTask(cfgc), + adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx b/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx deleted file mode 100644 index bad62accce2..00000000000 --- a/PWGLF/TableProducer/Nuspex/hypertriton3bodyfinder.cxx +++ /dev/null @@ -1,1197 +0,0 @@ -// Copyright 2019-2020 CERN and copyright holders of ALICE O2. -// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. -// All rights not expressly granted are reserved. -// -// This software is distributed under the terms of the GNU General Public -// License v3 (GPL Version 3), copied verbatim in the file "COPYING". -// -// In applying this license CERN does not waive the privileges and immunities -// granted to it by virtue of its status as an Intergovernmental Organization -// or submit itself to any jurisdiction. - -// This 3-body method is not recommended due to high cost of computing resources -// author: yuanzhe.wang@cern.ch - -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "EventFiltering/filterTables.h" - -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using std::array; - -using FullTracksExtIU = soa::Join; -using MCLabeledTracksIU = soa::Join; - -template -bool is3bodyDecayedH3L(TMCParticle const& particle) -{ - if (particle.pdgCode() != 1010010030 && particle.pdgCode() != -1010010030) { - return false; - } - bool haveProton = false, havePionPlus = false, haveDeuteron = false; - bool haveAntiProton = false, havePionMinus = false, haveAntiDeuteron = false; - for (auto& mcparticleDaughter : particle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) - haveProton = true; - if (mcparticleDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == 211) - havePionPlus = true; - if (mcparticleDaughter.pdgCode() == -211) - havePionMinus = true; - if (mcparticleDaughter.pdgCode() == 1000010020) - haveDeuteron = true; - if (mcparticleDaughter.pdgCode() == -1000010020) - haveAntiDeuteron = true; - } - if (haveProton && havePionMinus && haveDeuteron && particle.pdgCode() == 1010010030) { - return true; - } else if (haveAntiProton && havePionPlus && haveAntiDeuteron && particle.pdgCode() == -1010010030) { - return true; - } - return false; -} - -namespace o2::aod -{ -namespace v0goodpostrack -{ -DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace v0goodpostrack -DECLARE_SOA_TABLE(V0GoodPosTracks, "AOD", "V0GOODPOSTRACKS", o2::soa::Index<>, v0goodpostrack::GoodTrackId, v0goodpostrack::CollisionId); -namespace v0goodnegtrack -{ -DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace v0goodnegtrack -DECLARE_SOA_TABLE(V0GoodNegTracks, "AOD", "V0GOODNEGTRACKS", o2::soa::Index<>, v0goodnegtrack::GoodTrackId, v0goodnegtrack::CollisionId); -namespace v0goodtrack -{ -DECLARE_SOA_INDEX_COLUMN_FULL(GoodTrack, goodTrack, int, Tracks, "_GoodTrack"); -DECLARE_SOA_INDEX_COLUMN(Collision, collision); -} // namespace v0goodtrack -DECLARE_SOA_TABLE(V0GoodTracks, "AOD", "V0GOODTRACKS", o2::soa::Index<>, v0goodtrack::GoodTrackId, v0goodtrack::CollisionId); -} // namespace o2::aod - -struct trackprefilter { - HistogramRegistry registry{ - "registry", - { - {"hCrossedRows", "hCrossedRows", {HistType::kTH1F, {{50, 0.0f, 200.0f}}}}, - {"hGoodTrackCount", "hGoodTrackCount", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - {"hGoodPosTrackCount", "hGoodPosTrackCount", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, - {"hGoodNegTrackCount", "hGoodNegTrackCount", {HistType::kTH1F, {{1, 0.0f, 1.0f}}}}, - {"h3bodyCounter", "h3bodyCounter", {HistType::kTH1F, {{6, 0.0f, 6.0f}}}}, - }, - }; - - // change the dca cut for helium3 - Configurable mintpcNCls{"mintpcNCls", 70, "min tpc Nclusters"}; - Configurable tpcrefit{"tpcrefit", 0, "demand TPC refit"}; - - Produces v0GoodPosTracks; - Produces v0GoodNegTracks; - Produces v0GoodTracks; - - // Fix: Add PID and pt cuts to tracks - void processDefault(aod::Collision const& /*collision*/, - FullTracksExtIU const& tracks) - { - for (auto& t0 : tracks) { - registry.fill(HIST("hGoodTrackCount"), 0.5); - registry.fill(HIST("hCrossedRows"), t0.tpcNClsCrossedRows()); - if (tpcrefit) { - if (!(t0.trackType() & o2::aod::track::TPCrefit)) { - continue; // TPC refit - } - } - registry.fill(HIST("hGoodTrackCount"), 1.5); - if (t0.tpcNClsFound() < mintpcNCls) { - continue; - } - registry.fill(HIST("hGoodTrackCount"), 2.5); - if (t0.signed1Pt() > 0.0f) { - v0GoodPosTracks(t0.globalIndex(), t0.collisionId()); - registry.fill(HIST("hGoodPosTrackCount"), 0.5); - registry.fill(HIST("hGoodTrackCount"), 3.5); - } - if (t0.signed1Pt() < 0.0f) { - v0GoodNegTracks(t0.globalIndex(), t0.collisionId()); - registry.fill(HIST("hGoodNegTrackCount"), 0.5); - registry.fill(HIST("hGoodTrackCount"), 3.5); - } - v0GoodTracks(t0.globalIndex(), t0.collisionId()); - } - } - PROCESS_SWITCH(trackprefilter, processDefault, "Default process function", true); - - // process function for MC d3body check - // void processCheck(aod::Collision const& collision, aod::Decay3Bodys const& decay3bodys, - void processCheck(aod::Decay3Bodys const& decay3bodys, - MCLabeledTracksIU const& /*tracks*/, aod::McParticles const& /*particlesMC*/) - { - for (auto& d3body : decay3bodys) { - registry.fill(HIST("h3bodyCounter"), 0.5); - auto lTrack0 = d3body.track0_as(); - auto lTrack1 = d3body.track1_as(); - auto lTrack2 = d3body.track2_as(); - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 1.5); - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 2.5); - - int lPDG = -1; - bool is3bodyDecay = false; - for (auto& lMother0 : lMCTrack0.mothers_as()) { - for (auto& lMother1 : lMCTrack1.mothers_as()) { - for (auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lPDG = lMother1.pdgCode(); - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - is3bodyDecay = true; // vtxs with the same mother - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - is3bodyDecay = true; // vtxs with the same mother - } - } - } - } - } // end association check - - if (!is3bodyDecay || std::abs(lPDG) != 1010010030) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 3.5); - if (lTrack0.collisionId() != lTrack1.collisionId() || lTrack0.collisionId() != lTrack2.collisionId()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 4.5); - - if (lTrack0.collisionId() != d3body.collisionId()) { - continue; - } - registry.fill(HIST("h3bodyCounter"), 5.5); - - // LOG(info) << "; Track0ID: " << lTrack0.globalIndex() << "; Track1ID:" << lTrack1.globalIndex() << "; Track2ID:" << lTrack2.globalIndex(); - v0GoodPosTracks(lTrack0.globalIndex(), lTrack0.collisionId()); - v0GoodNegTracks(lTrack1.globalIndex(), lTrack1.collisionId()); - v0GoodTracks(lTrack2.globalIndex(), lTrack2.collisionId()); - } - } - PROCESS_SWITCH(trackprefilter, processCheck, "Check specific paired tracks", false); -}; - -struct hypertriton3bodyFinder { - - Produces vtx3bodydata; - Service ccdb; - - // Configurables - Configurable UseCFFilter{"UseCFFilter", true, "Reject event without CF LD trigger"}; - Configurable RejectBkgInMC{"RejectBkgInMC", false, "Reject fake 3-body pairs in MC check"}; - - Configurable d_UseAbsDCA{"d_UseAbsDCA", true, "Use Abs DCAs"}; - Configurable d_bz_input{"d_bz", -999, "bz field, -999 is automatic"}; - - // Selection criteria - Configurable minRToMeanVertex = {"minRToMeanVertex", 0.5, ""}; ///< min radial distance of V0 from beam line (mean vertex) - // Configurable causalityRTolerance = {"causalityRTolerance", 1., ""}; ///< V0 radius cannot exceed its contributors minR by more than this value - Configurable maxV0ToProngsRDiff = {"maxV0ToProngsRDiff", 50., ""}; ///< V0 radius cannot be lower than this ammount wrt minR of contributors - Configurable minPtV0 = {"minPtV0", 0.5, ""}; ///< v0 minimum pT - Configurable maxTglV0 = {"maxTglV0", 2., ""}; ///< maximum tgLambda of V0 - Configurable maxDCAXY2ToMeanVertex3bodyV0 = {"maxDCAXY2ToMeanVertex3bodyV0", 2 * 2, ""}; - Configurable minCosPAXYMeanVertex3bodyV0 = {"minCosPAXYMeanVertex3bodyV0", 0.9, ""}; ///< min cos of PA to beam line (mean vertex) in tr. plane for 3body V0 cand. - Configurable minCosPA3bodyV0 = {"minCosPA3bodyV0", 0.8, ""}; // min cos of PA to PV for 3body V0 - - // for 3 body reconstructed Vertex - Configurable minbachPt = {"minbachPt", 0.6, ""}; ///< Minimum bachelor Pt - Configurable maxRDiff3bodyV0 = {"maxRDiff3bodyV0", 3, ""}; ///< Maximum difference between V0 and 3body radii - Configurable minPt3Body = {"minPt3Body", 0.01, ""}; // minimum pT of 3body Vertex - Configurable maxTgl3Body = {"maxTgl3Body", 2, ""}; // maximum tgLambda of 3body Vertex - Configurable minCosPA3body = {"minCosPA3body", 0.8, ""}; // min cos of PA to PV for 3body Vertex - - // for DCA - Configurable dcavtxdau{"dcavtxdau", 2.0, "DCA Vtx Daughters"}; - Configurable d_UseH3LDCACut{"d_UseH3LDCACut", true, "Use Cuts for H3L DCA to PV"}; - Configurable maxDCAXY3Body{"maxDCAXY3Body", 0.5, "DCAXY H3L to PV"}; // max DCA of 3 body decay to PV in XY - Configurable maxDCAZ3Body{"maxDCAZ3Body", 1.0, "DCAZ H3L to PV"}; // max DCA of 3 body decay to PV in Z - - Configurable useMatCorrType{"useMatCorrType", 2, "0: none, 1: TGeo, 2: LUT"}; - // CCDB options - Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; - Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; - Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; - Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; - - Preslice perCollisionGoodPosTracks = o2::aod::v0goodpostrack::collisionId; - Preslice perCollisionGoodNegTracks = o2::aod::v0goodnegtrack::collisionId; - Preslice perCollisionGoodTracks = o2::aod::v0goodtrack::collisionId; - Preslice perCollisionV0s = o2::aod::v0::collisionId; - Preslice perCollisionV0Datas = o2::aod::v0data::collisionId; - - // Helper struct to pass V0 information - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hDauTrackCounter", "hDauTrackCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hV0Counter", "hV0Counter", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}}, - {"hTrueV0Counter", "hTrueV0Counter", {HistType::kTH1F, {{8, -0.5f, 7.5f}}}}, - {"hVtx3BodyCounter", "hVtx3BodyCounter", {HistType::kTH1F, {{9, -0.5f, 8.5f}}}}, - {"hTrueVtx3BodyCounter", "hTrueVtx3BodyCounter", {HistType::kTH1F, {{9, -0.5f, 8.5f}}}}, - {"hVirtLambaCounter", "hVirtualLambaCounter", {HistType::kTH1F, {{6, -0.5f, 5.5f}}}}, - {"hCFFilteredVirtLambaCounter", "hCFFilteredVirtLambaCounter", {HistType::kTH1F, {{6, -0.5f, 5.5f}}}}, - }, - }; - - //------------------------------------------------------------------ - // Fill stats histograms - enum v0step { kV0All = 0, - kV0hasSV, - kV0Radius, - kV0Pt, - kV0TgLamda, - kV0InvMass, - kV0DcaXY, - kV0CosPA, - kNV0Steps }; - enum vtxstep { kVtxAll = 0, - kVtxbachPt, - kVtxhasSV, - kVtxRadius, - kVtxPt, - kVtxTgLamda, - kVtxCosPA, - kVtxDcaDau, - kVtxDcaH3L, - kNVtxSteps }; - - // Helper struct to do bookkeeping of building parameters - struct { - std::array v0stats; - std::array truev0stats; - std::array vtxstats; - std::array truevtxstats; - std::array virtLambdastats; - } statisticsRegistry; - - void resetHistos() - { - for (Int_t ii = 0; ii < kNV0Steps; ii++) { - statisticsRegistry.v0stats[ii] = 0; - statisticsRegistry.truev0stats[ii] = 0; - } - for (Int_t ii = 0; ii < kNVtxSteps; ii++) { - statisticsRegistry.vtxstats[ii] = 0; - statisticsRegistry.truevtxstats[ii] = 0; - } - for (Int_t ii = 0; ii < 12; ii++) { - statisticsRegistry.virtLambdastats[ii] = 0; - } - } - - void fillHistos() - { - for (Int_t ii = 0; ii < kNV0Steps; ii++) { - registry.fill(HIST("hV0Counter"), ii, statisticsRegistry.v0stats[ii]); - registry.fill(HIST("hTrueV0Counter"), ii, statisticsRegistry.truev0stats[ii]); - } - for (Int_t ii = 0; ii < kNVtxSteps; ii++) { - registry.fill(HIST("hVtx3BodyCounter"), ii, statisticsRegistry.vtxstats[ii]); - registry.fill(HIST("hTrueVtx3BodyCounter"), ii, statisticsRegistry.truevtxstats[ii]); - } - for (Int_t ii = 0; ii < 3; ii++) { - registry.fill(HIST("hVirtLambaCounter"), ii, statisticsRegistry.virtLambdastats[ii]); - registry.fill(HIST("hVirtLambaCounter"), ii + 3, statisticsRegistry.virtLambdastats[ii + 3]); - registry.fill(HIST("hCFFilteredVirtLambaCounter"), ii, statisticsRegistry.virtLambdastats[ii + 6]); - registry.fill(HIST("hCFFilteredVirtLambaCounter"), ii + 3, statisticsRegistry.virtLambdastats[ii + 9]); - } - } - - // v0, vtx, and virtual Lambda statiscs - void FillV0Counter(int kn, bool istrue = false) - { - statisticsRegistry.v0stats[kn]++; - if (istrue) { - statisticsRegistry.truev0stats[kn]++; - } - } - void FillVtxCounter(int kn, bool istrue = false) - { - statisticsRegistry.vtxstats[kn]++; - if (istrue) { - statisticsRegistry.truevtxstats[kn]++; - } - } - //------------------------------------------------------------------ - - int mRunNumber; - float d_bz; - float maxSnp; // max sine phi for propagation - float maxStep; // max step size (cm) for propagation - o2::base::MatLayerCylSet* lut = nullptr; - o2::vertexing::DCAFitterN<2> fitter; - o2::vertexing::DCAFitterN<3> fitter3body; - - void init(InitContext&) - { - resetHistos(); - mRunNumber = 0; - d_bz = 0; - maxSnp = 0.85f; // could be changed later - maxStep = 2.00f; // could be changed later - - TString DauCounterbinLabel[3] = {"Proton", "Pion", "Deuteron"}; - TString V0CounterbinLabel[8] = {"Total", "hasSV", "V0R", "V0Pt", "TgLambda", "V0Mass", "DcaXY", "CosPA"}; - TString VtxCounterbinLabel[9] = {"Total", "bachPt", "hasSV", "VtxR", "VtxPt", "TgLambda", "CosPA", "DcaDau", "DcaH3L"}; - for (int i{0}; i < 3; i++) { - registry.get(HIST("hDauTrackCounter"))->GetXaxis()->SetBinLabel(i + 1, DauCounterbinLabel[i]); - } - for (int i{0}; i < kNV0Steps; i++) { - registry.get(HIST("hV0Counter"))->GetXaxis()->SetBinLabel(i + 1, V0CounterbinLabel[i]); - registry.get(HIST("hTrueV0Counter"))->GetXaxis()->SetBinLabel(i + 1, V0CounterbinLabel[i]); - } - for (int i{0}; i < kNVtxSteps; i++) { - registry.get(HIST("hVtx3BodyCounter"))->GetXaxis()->SetBinLabel(i + 1, VtxCounterbinLabel[i]); - registry.get(HIST("hTrueVtx3BodyCounter"))->GetXaxis()->SetBinLabel(i + 1, VtxCounterbinLabel[i]); - } - - ccdb->setURL(ccdburl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - // Set 2-body fitter and 3-body fitter3body - fitter.setPropagateToPCA(true); - fitter.setMaxR(200.); //->maxRIni3body - fitter.setMinParamChange(1e-3); - fitter.setMinRelChi2Change(0.9); - fitter.setMaxDZIni(1e9); - fitter.setMaxChi2(1e9); - fitter.setUseAbsDCA(d_UseAbsDCA); - fitter3body.setPropagateToPCA(true); - fitter3body.setMaxR(200.); //->maxRIni3body - fitter3body.setMinParamChange(1e-3); - fitter3body.setMinRelChi2Change(0.9); - fitter3body.setMaxDZIni(1e9); - fitter3body.setMaxChi2(1e9); - fitter3body.setUseAbsDCA(d_UseAbsDCA); - - // Material correction in the DCA fitter - o2::base::Propagator::MatCorrType matCorr = o2::base::Propagator::MatCorrType::USEMatCorrNONE; - if (useMatCorrType == 1) { - LOGF(info, "TGeo correction requested, loading geometry"); - if (!o2::base::GeometryManager::isGeometryLoaded()) { - ccdb->get(geoPath); - } - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrTGeo; - } - if (useMatCorrType == 2) { - LOGF(info, "LUT correction requested, loading LUT"); - lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); - matCorr = o2::base::Propagator::MatCorrType::USEMatCorrLUT; - } - fitter.setMatCorrType(matCorr); - fitter3body.setMatCorrType(matCorr); - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - - // In case override, don't proceed, please - no CCDB access required - if (d_bz_input > -990) { - d_bz = d_bz_input; - fitter.setBz(d_bz); - fitter3body.setBz(d_bz); - o2::parameters::GRPMagField grpmag; - if (fabs(d_bz) > 1e-5) { - grpmag.setL3Current(30000.f / (d_bz / 5.0f)); - } - o2::base::Propagator::initFieldFromGRP(&grpmag); - mRunNumber = bc.runNumber(); - return; - } - - auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - if (grpo) { - o2::base::Propagator::initFieldFromGRP(grpo); - // Fetch magnetic field from ccdb for current collision - d_bz = grpo->getNominalL3Field(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } else { - grpmag = ccdb->getForTimeStamp(grpmagPath, run3grp_timestamp); - if (!grpmag) { - LOG(fatal) << "Got nullptr from CCDB for path " << grpmagPath << " of object GRPMagField and " << grpPath << " of object GRPObject for timestamp " << run3grp_timestamp; - } - o2::base::Propagator::initFieldFromGRP(grpmag); - // Fetch magnetic field from ccdb for current collision - d_bz = std::lround(5.f * grpmag->getL3Current() / 30000.f); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; - } - mRunNumber = bc.runNumber(); - // Set magnetic field value once known - fitter.setBz(d_bz); - fitter3body.setBz(d_bz); - - if (useMatCorrType == 2) { - // setMatLUT only after magfield has been initalized - // (setMatLUT has implicit and problematic init field call if not) - o2::base::Propagator::Instance()->setMatLUT(lut); - } - } - - //------------------------------------------------------------------ - // Check the info of good tracks - template - void CheckGoodTracks(TGoodTrackTable const& dGoodtracks, aod::McParticles const& /*particlesMC*/) - { - for (auto& goodtrackid : dGoodtracks) { - auto goodtrack = goodtrackid.template goodTrack_as(); - if (!goodtrack.has_mcParticle()) { - continue; - } - auto mcgoodtrack = goodtrack.template mcParticle_as(); - if (!mcgoodtrack.has_mothers()) { - continue; - } - bool flag_H3L = false; - for (auto& mothertrack : mcgoodtrack.template mothers_as()) { - if (is3bodyDecayedH3L(mothertrack)) { - flag_H3L = true; - } - } - if (flag_H3L && std::abs(mcgoodtrack.pdgCode()) == 2212) { - registry.fill(HIST("hDauTrackCounter"), 0.5); - } - if (flag_H3L && std::abs(mcgoodtrack.pdgCode()) == 211) { - registry.fill(HIST("hDauTrackCounter"), 1.5); - } - if (flag_H3L && std::abs(mcgoodtrack.pdgCode()) == 1000010020) { - registry.fill(HIST("hDauTrackCounter"), 2.5); - } - } - } - - o2::dataformats::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; - //------------------------------------------------------------------ - // Virtual Lambda V0 finder - template - bool DecayV0Finder(TCollisionTable const& dCollision, TTrackTable const& dPtrack, TTrackTable const& dNtrack, float& rv0, bool isTrue3bodyV0 = false) - { - if (dPtrack.collisionId() != dNtrack.collisionId()) { - return false; - } - FillV0Counter(kV0All, isTrue3bodyV0); - if (!isTrue3bodyV0 && RejectBkgInMC) { - return false; - } - - auto Track0 = getTrackParCov(dPtrack); - auto Track1 = getTrackParCov(dNtrack); - int nCand = fitter.process(Track0, Track1); - if (nCand == 0) { - return false; - } - FillV0Counter(kV0hasSV, isTrue3bodyV0); - - // validate V0 radial position - // First check closeness to the beam-line as same as SVertexer - const auto& v0XYZ = fitter.getPCACandidate(); - float dxv0 = v0XYZ[0] - mMeanVertex.getX(), dyv0 = v0XYZ[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; - // float rv0 = std::sqrt(r2v0); - rv0 = std::sqrt(r2v0); - if (rv0 < minRToMeanVertex) { - return false; - } - FillV0Counter(kV0Radius, isTrue3bodyV0); - - // Not involved: Get minR with same way in SVertexer - // float drv0P = rv0 - Track0minR, drv0N = rv0 - Track1minR; - - // check: if the process function finish the propagation - if (!fitter.isPropagateTracksToVertexDone() && !fitter.propagateTracksToVertex()) { - return false; - } - - auto& trPProp = fitter.getTrack(0); - auto& trNProp = fitter.getTrack(1); - std::array pP, pN; - trPProp.getPxPyPzGlo(pP); - trNProp.getPxPyPzGlo(pN); - // estimate DCA of neutral V0 track to beamline: straight line with parametric equation - // x = X0 + pV0[0]*t, y = Y0 + pV0[1]*t reaches DCA to beamline (Xv, Yv) at - // t = -[ (x0-Xv)*pV0[0] + (y0-Yv)*pV0[1]) ] / ( pT(pV0)^2 ) - // Similar equation for 3D distance involving pV0[2] - std::array pV0 = {pP[0] + pN[0], pP[1] + pN[1], pP[2] + pN[2]}; - float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; - float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); - if (ptV0 < minPtV0) { // pt cut - return false; - } - FillV0Counter(kV0Pt, isTrue3bodyV0); - - if (pV0[2] / ptV0 > maxTglV0) { // tgLambda cut - return false; - } - FillV0Counter(kV0TgLamda, isTrue3bodyV0); - - // apply mass selections - float massV0LambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - float massV0AntiLambdaHyp = RecoDecay::m(array{array{pP[0], pP[1], pP[2]}, array{pN[0], pN[1], pN[2]}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton}); - float massMargin = 20 * (0.001 * (1. + 0.5 * ptV0)) + 0.07; - if (massV0LambdaHyp - o2::constants::physics::MassLambda > massMargin && massV0AntiLambdaHyp - o2::constants::physics::MassLambda > massMargin) { - return false; - } - FillV0Counter(kV0InvMass, isTrue3bodyV0); - - float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; - float cosPAXY = prodXYv0 / std::sqrt(r2v0 * pt2V0); - if (dca2 > maxDCAXY2ToMeanVertex3bodyV0) { - return false; - } - FillV0Counter(kV0DcaXY, isTrue3bodyV0); - - if (cosPAXY < minCosPAXYMeanVertex3bodyV0) { - return false; - } - float dx = v0XYZ[0] - dCollision.posX(), dy = v0XYZ[1] - dCollision.posY(), dz = v0XYZ[2] - dCollision.posZ(), prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; - float cosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); - if (cosPA < minCosPA3bodyV0) { - return false; - } - FillV0Counter(kV0CosPA, isTrue3bodyV0); - return true; - } - //------------------------------------------------------------------ - // 3body decay vertex finder - template - void Decay3bodyFinder(TCollisionTable const& dCollision, TTrackTable const& dPtrack, TTrackTable const& dNtrack, TTrackTable const& dBachtrack, float const& rv0, bool isTrue3bodyVtx = false) - { - if (dPtrack.collisionId() != dBachtrack.collisionId()) { - return; - } - if (dPtrack.globalIndex() == dBachtrack.globalIndex()) { - return; // skip the track used by V0 - } - FillVtxCounter(kVtxAll, isTrue3bodyVtx); - if (!isTrue3bodyVtx && RejectBkgInMC) { - return; - } - - auto track0 = getTrackParCov(dPtrack); - auto track1 = getTrackParCov(dNtrack); - auto bach = getTrackParCov(dBachtrack); - - if (bach.getPt() < minbachPt) { - return; - } - FillVtxCounter(kVtxbachPt, isTrue3bodyVtx); - - int n3bodyVtx = fitter3body.process(track0, track1, bach); - if (n3bodyVtx == 0) { // discard this pair - return; - } - FillVtxCounter(kVtxhasSV, isTrue3bodyVtx); - - const auto& vertexXYZ = fitter3body.getPCACandidatePos(); - // make sure the cascade radius is smaller than that of the vertex - float dxc = vertexXYZ[0] - dCollision.posX(), dyc = vertexXYZ[1] - dCollision.posY(), dzc = vertexXYZ[2] - dCollision.posZ(), r2vertex = dxc * dxc + dyc * dyc; - float rvertex = std::sqrt(r2vertex); - if (std::abs(rv0 - rvertex) > maxRDiff3bodyV0 || rvertex < minRToMeanVertex) { - return; - } - FillVtxCounter(kVtxRadius, isTrue3bodyVtx); - - // Not involved: bach.minR - rveretx check - - // check: if the process function finish the propagation - if (!fitter3body.isPropagateTracksToVertexDone() && !fitter3body.propagateTracksToVertex()) { - return; - } - - auto& tr0 = fitter3body.getTrack(0); - auto& tr1 = fitter3body.getTrack(1); - auto& tr2 = fitter3body.getTrack(2); - std::array p0, p1, p2; - tr0.getPxPyPzGlo(p0); - tr1.getPxPyPzGlo(p1); - tr2.getPxPyPzGlo(p2); - std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; - - float pt2 = p3B[0] * p3B[0] + p3B[1] * p3B[1], p2candidate = pt2 + p3B[2] * p3B[2]; - float pt = std::sqrt(pt2); - if (pt < minPt3Body) { // pt cut - return; - } - FillVtxCounter(kVtxPt, isTrue3bodyVtx); - - if (p3B[2] / pt > maxTgl3Body) { // tgLambda cut - return; - } - FillVtxCounter(kVtxTgLamda, isTrue3bodyVtx); - - float cosPA = (p3B[0] * dxc + p3B[1] * dyc + p3B[2] * dzc) / std::sqrt(p2candidate * (r2vertex + dzc * dzc)); - if (cosPA < minCosPA3body) { - return; - } - FillVtxCounter(kVtxCosPA, isTrue3bodyVtx); - - if (fitter3body.getChi2AtPCACandidate() > dcavtxdau) { - return; - } - FillVtxCounter(kVtxDcaDau, isTrue3bodyVtx); - - // Calculate DCA with respect to the collision associated to the V0, not individual tracks - std::array dcaInfo; - - auto Track0Par = getTrackPar(dPtrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track0Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track0dcaXY = dcaInfo[0]; - auto Track0dca = std::sqrt(Track0dcaXY * Track0dcaXY + dcaInfo[1] * dcaInfo[1]); - - auto Track1Par = getTrackPar(dNtrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track1Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track1dcaXY = dcaInfo[0]; - auto Track1dca = std::sqrt(Track1dcaXY * Track1dcaXY + dcaInfo[1] * dcaInfo[1]); - - auto Track2Par = getTrackPar(dBachtrack); - o2::base::Propagator::Instance()->propagateToDCABxByBz({dCollision.posX(), dCollision.posY(), dCollision.posZ()}, Track2Par, 2.f, fitter3body.getMatCorrType(), &dcaInfo); - auto Track2dcaXY = dcaInfo[0]; - auto Track2dca = std::sqrt(Track2dcaXY * Track2dcaXY + dcaInfo[1] * dcaInfo[1]); - - // H3L DCA Check - // auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, fitter3body.calcPCACovMatrixFlat(), t2.sign()); - auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, dBachtrack.sign()); - o2::dataformats::DCA dca; - if (d_UseH3LDCACut && (!track3B.propagateToDCA({{dCollision.posX(), dCollision.posY(), dCollision.posZ()}, {dCollision.covXX(), dCollision.covXY(), dCollision.covYY(), dCollision.covXZ(), dCollision.covYZ(), dCollision.covZZ()}}, fitter3body.getBz(), &dca, 5.) || - std::abs(dca.getY()) > maxDCAXY3Body || std::abs(dca.getZ()) > maxDCAZ3Body)) { - return; - } - FillVtxCounter(kVtxDcaH3L, isTrue3bodyVtx); - - vtx3bodydata( - dPtrack.globalIndex(), dNtrack.globalIndex(), dBachtrack.globalIndex(), dCollision.globalIndex(), 0, - vertexXYZ[0], vertexXYZ[1], vertexXYZ[2], - p0[0], p0[1], p0[2], p1[0], p1[1], p1[2], p2[0], p2[1], p2[2], - fitter3body.getChi2AtPCACandidate(), - Track0dcaXY, Track1dcaXY, Track2dcaXY, - Track0dca, Track1dca, Track2dca, - 0); // To be fixed - } - //------------------------------------------------------------------ - // 3body decay finder for a collsion - template - void DecayFinder(TCollisionTable const& dCollision, TPosTrackTable const& dPtracks, TNegTrackTable const& dNtracks, TGoodTrackTable const& dGoodtracks) - { - for (auto& t0id : dPtracks) { // FIXME: turn into combination(...) - auto t0 = t0id.template goodTrack_as(); - - for (auto& t1id : dNtracks) { - auto t1 = t1id.template goodTrack_as(); - float rv0; - if (!DecayV0Finder(dCollision, t0, t1, rv0)) { - continue; - } - - for (auto& t2id : dGoodtracks) { - auto t2 = t2id.template goodTrack_as(); - Decay3bodyFinder(dCollision, t0, t1, t2, rv0); - } - } - } - fillHistos(); - resetHistos(); - } - //------------------------------------------------------------------ - // MC 3body decay vertex finder - template - void DecayFinderMC(TCollisionTable const& dCollision, TPosTrackTable const& dPtracks, TNegTrackTable const& dNtracks, TGoodTrackTable const& dGoodtracks) - { - for (auto& t0id : dPtracks) { // FIXME: turn into combination(...) - auto t0 = t0id.template goodTrack_as(); - for (auto& t1id : dNtracks) { - auto t1 = t1id.template goodTrack_as(); - if (t0.collisionId() != t1.collisionId()) { - continue; - } - - bool isTrue3bodyV0 = false; - if (t0.has_mcParticle() && t1.has_mcParticle()) { - auto t0mc = t0.template mcParticle_as(); - auto t1mc = t1.template mcParticle_as(); - if ((t0mc.pdgCode() == 2212 && t1mc.pdgCode() == -211) || (t0mc.pdgCode() == 211 && t1mc.pdgCode() == -2212)) { - if (t0mc.has_mothers() && t1mc.has_mothers()) { - for (auto& t0mother : t0mc.template mothers_as()) { - for (auto& t1mother : t1mc.template mothers_as()) { - if (t0mother.globalIndex() == t1mother.globalIndex() && std::abs(t0mother.pdgCode()) == 1010010030) { - isTrue3bodyV0 = true; - } - } - } - } - } - } - - float rv0; - if (!DecayV0Finder(dCollision, t0, t1, rv0, isTrue3bodyV0)) { - continue; - } - - for (auto& t2id : dGoodtracks) { - auto t2 = t2id.template goodTrack_as(); - - bool isTrue3bodyVtx = false; - if (t0.has_mcParticle() && t1.has_mcParticle() && t2.has_mcParticle()) { - auto t0mc = t0.template mcParticle_as(); - auto t1mc = t1.template mcParticle_as(); - auto t2mc = t2.template mcParticle_as(); - if ((t0mc.pdgCode() == 2212 && t1mc.pdgCode() == -211 && t2mc.pdgCode() == 1000010020) || (t0mc.pdgCode() == 211 && t1mc.pdgCode() == -2212 && t2mc.pdgCode() == -1000010020)) { - if (t0mc.has_mothers() && t1mc.has_mothers() && t2mc.has_mothers()) { - for (auto& t0mother : t0mc.template mothers_as()) { - for (auto& t1mother : t1mc.template mothers_as()) { - for (auto& t2mother : t2mc.template mothers_as()) { - if (t0mother.globalIndex() == t1mother.globalIndex() && t0mother.globalIndex() == t2mother.globalIndex() && std::abs(t0mother.pdgCode()) == 1010010030) { - isTrue3bodyVtx = true; - } - } - } - } - } - } - } - - Decay3bodyFinder(dCollision, t0, t1, t2, rv0, isTrue3bodyVtx); - } - } - } - fillHistos(); - resetHistos(); - } - //------------------------------------------------------------------ - // MC virtual lambda check - template - void VirtualLambdaCheck(TCollisionTable const& /*dCollision*/, TV0DataTable const& fullV0s, int bin) - { - for (auto& v0 : fullV0s) { - statisticsRegistry.virtLambdastats[bin]++; - auto postrack = v0.template posTrack_as(); - auto negtrack = v0.template negTrack_as(); - if (postrack.has_mcParticle() && negtrack.has_mcParticle()) { - auto postrackmc = postrack.template mcParticle_as(); - auto negtrackmc = negtrack.template mcParticle_as(); - - if ((postrackmc.pdgCode() == 2212 && negtrackmc.pdgCode() == -211) || (postrackmc.pdgCode() == 211 && negtrackmc.pdgCode() == -2212)) { - if (postrackmc.has_mothers() && negtrackmc.has_mothers()) { - for (auto& posmother : postrackmc.template mothers_as()) { - for (auto& negmother : negtrackmc.template mothers_as()) { - if (posmother.globalIndex() == negmother.globalIndex()) { - if (posmother.pdgCode() == 1010010030) - statisticsRegistry.virtLambdastats[bin + 1]++; - else if (posmother.pdgCode() == -1010010030) - statisticsRegistry.virtLambdastats[bin + 2]++; - } - } - } - } - } - } - } - fillHistos(); - resetHistos(); - } - - //------------------------------------------------------------------ - // Process Function - void processData(aod::Collision const& collision, aod::V0GoodPosTracks const& ptracks, aod::V0GoodNegTracks const& ntracks, aod::V0GoodTracks const& goodtracks, FullTracksExtIU const&, aod::BCsWithTimestamps const&) - { - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - DecayFinder(collision, ptracks, ntracks, goodtracks); - } - PROCESS_SWITCH(hypertriton3bodyFinder, processData, "Produce StoredVtx3BodyDatas with data", true); - - void processCFFilteredData(aod::Collisions const& collisions, aod::CFFilters const& cffilters, aod::V0GoodPosTracks const& Ptracks, aod::V0GoodNegTracks const& Ntracks, aod::V0GoodTracks const& Goodtracks, FullTracksExtIU const&, aod::BCsWithTimestamps const&) - { - for (int i{0}; i < collisions.size(); i++) { - auto collision = collisions.iteratorAt(i); - auto cffilter = cffilters.iteratorAt(i); - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - auto ptracks = Ptracks.sliceBy(perCollisionGoodPosTracks, collision.globalIndex()); - auto ntracks = Ntracks.sliceBy(perCollisionGoodNegTracks, collision.globalIndex()); - auto goodtracks = Goodtracks.sliceBy(perCollisionGoodTracks, collision.globalIndex()); - - if (!cffilter.hasLD_LooseKstar() && UseCFFilter) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - - DecayFinder(collision, ptracks, ntracks, goodtracks); - } - } - PROCESS_SWITCH(hypertriton3bodyFinder, processCFFilteredData, "Produce StoredVtx3BodyDatas with data using CFtriggers", false); - - void processMC(aod::Collision const& collision, aod::V0GoodPosTracks const& ptracks, aod::V0GoodNegTracks const& ntracks, aod::V0GoodTracks const& goodtracks, aod::McParticles const& particlesMC, MCLabeledTracksIU const&, aod::BCsWithTimestamps const&) - { - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - CheckGoodTracks(goodtracks, particlesMC); - DecayFinderMC(collision, ptracks, ntracks, goodtracks); - } - PROCESS_SWITCH(hypertriton3bodyFinder, processMC, "Produce StoredVtx3BodyDatas with MC", false); - - void processCFFilteredMC(aod::Collisions const& collisions, aod::CFFilters const& cffilters, aod::V0GoodPosTracks const& Ptracks, aod::V0GoodNegTracks const& Ntracks, aod::V0GoodTracks const& Goodtracks, aod::V0s const& V0s, aod::V0Datas const& fullV0s, aod::McParticles const& particlesMC, MCLabeledTracksIU const&, aod::BCsWithTimestamps const&) - { - for (int i{0}; i < collisions.size(); i++) { - auto collision = collisions.iteratorAt(i); - auto cffilter = cffilters.iteratorAt(i); - auto bc = collision.bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - auto goodtracks = Goodtracks.sliceBy(perCollisionGoodTracks, collision.globalIndex()); - CheckGoodTracks(goodtracks, particlesMC); - auto v0s = V0s.sliceBy(perCollisionV0s, collision.globalIndex()); - auto fullv0s = fullV0s.sliceBy(perCollisionV0Datas, collision.globalIndex()); - VirtualLambdaCheck(collision, v0s, 0); - VirtualLambdaCheck(collision, fullv0s, 3); - - if (!cffilter.hasLD_LooseKstar() && UseCFFilter) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - - auto ptracks = Ptracks.sliceBy(perCollisionGoodPosTracks, collision.globalIndex()); - auto ntracks = Ntracks.sliceBy(perCollisionGoodNegTracks, collision.globalIndex()); - - VirtualLambdaCheck(collision, v0s, 6); - VirtualLambdaCheck(collision, fullv0s, 9); - DecayFinderMC(collision, ptracks, ntracks, goodtracks); - } - } - PROCESS_SWITCH(hypertriton3bodyFinder, processCFFilteredMC, "Produce StoredVtx3BodyDatas with MC using CFtriggers", false); -}; - -struct hypertriton3bodyLabelBuilder { - - Produces vtxlabels; - - // for bookkeeping purposes: how many V0s come from same mother etc - HistogramRegistry registry{ - "registry", - { - {"hLabelCounter", "hLabelCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hHypertritonMCPt", "hHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hAntiHypertritonMCPt", "hAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hHypertritonMCMass", "hHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hAntiHypertritonMCMass", "hAntiHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hHypertritonMCLifetime", "hHypertritonMCLifetime", {HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}}}, - {"hAntiHypertritonMCLifetime", "hAntiHypertritonMCLifetime", {HistType::kTH1F, {{50, 0.0f, 50.0f, "ct(cm)"}}}}, - }, - }; - - void init(InitContext const&) - { - registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(1, "Total"); - registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(2, "Same MotherParticle"); - registry.get(HIST("hLabelCounter"))->GetXaxis()->SetBinLabel(3, "True H3L"); - } - - Configurable TpcPidNsigmaCut{"TpcPidNsigmaCut", 5, "TpcPidNsigmaCut"}; - - void processDoNotBuildLabels(aod::Collisions::iterator const&) - { - // dummy process function - should not be required in the future - } - PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processDoNotBuildLabels, "Do not produce MC label tables", true); - - void processBuildLabels(aod::Vtx3BodyDatas const& vtx3bodydatas, MCLabeledTracksIU const&, aod::McParticles const& /*particlesMC*/) - { - std::vector lIndices; - lIndices.reserve(vtx3bodydatas.size()); - for (int ii = 0; ii < vtx3bodydatas.size(); ii++) { - lIndices[ii] = -1; - } - - for (auto& vtx3body : vtx3bodydatas) { - - int lLabel = -1; - int lPDG = -1; - float lPt = -1; - double MClifetime = -1; - bool is3bodyDecay = false; - int lGlobalIndex = -1; - - auto lTrack0 = vtx3body.track0_as(); - auto lTrack1 = vtx3body.track1_as(); - auto lTrack2 = vtx3body.track2_as(); - registry.fill(HIST("hLabelCounter"), 0.5); - - // Association check - // There might be smarter ways of doing this in the future - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - vtxlabels(-1); - continue; - } - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - vtxlabels(-1); - continue; - } - - for (auto& lMother0 : lMCTrack0.mothers_as()) { - for (auto& lMother1 : lMCTrack1.mothers_as()) { - for (auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lGlobalIndex = lMother1.globalIndex(); - lPt = lMother1.pt(); - lPDG = lMother1.pdgCode(); - MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); - is3bodyDecay = true; // vtxs with the same mother - } - } - } - } // end association check - if (!is3bodyDecay) { - vtxlabels(-1); - continue; - } - registry.fill(HIST("hLabelCounter"), 1.5); - - // Intended for cross-checks only - // N.B. no rapidity cut! - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - lLabel = lGlobalIndex; - double hypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hHypertritonMCPt"), lPt); - registry.fill(HIST("hHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - lLabel = lGlobalIndex; - double antiHypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hAntiHypertritonMCPt"), lPt); - registry.fill(HIST("hAntiHypertritonMCLifetime"), MClifetime); - registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); - } - - // Construct label table, only true hypertriton and true daughters with a specified order is labeled - // for matter: track0->p, track1->pi, track2->d - // for antimatter: track0->pi, track1->p, track2->d - vtxlabels(lLabel); - } - } - PROCESS_SWITCH(hypertriton3bodyLabelBuilder, processBuildLabels, "Produce MC label tables", false); -}; - -struct hypertriton3bodyComparewithDecay3body { - - HistogramRegistry registry{ - "registry", - { - {"hMCInfoCounter", "hMCInfoCounter", {HistType::kTH1F, {{8, 0.0f, 8.0f}}}}, - {"hCheckCounter", "hCheckCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hHypertritonMCPtTotal", "hHypertritonMCPtTotal", {HistType::kTH1F, {{20, 0.0f, 10.0f}}}}, - {"hHypertritonMCPt", "hHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hAntiHypertritonMCPt", "hAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hHypertritonMCMass", "hHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, - {"hAntiHypertritonMCMass", "hAntiHypertritonMCMass", {HistType::kTH1F, {{40, 2.95f, 3.05f}}}}, - {"hPairedHypertritonMCPt", "hPairedHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hPairedAntiHypertritonMCPt", "hPairedAntiHypertritonMCPt", {HistType::kTH1F, {{100, 0.0f, 10.0f}}}}, - {"hSameMcIndexCounter", "hSameMcIndexCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - }, - }; - - void init(InitContext const&) - { - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(1, "Total"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(2, "Sig in Decay3body"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(3, "Sig SameCol"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(4, "Sig contained by finder"); - registry.get(HIST("hCheckCounter"))->GetXaxis()->SetBinLabel(5, "Sig SameIndex"); - } - struct Indexdaughters { // check duplicated paired daughters - int64_t index0; - int64_t index1; - int64_t index2; - bool operator==(const Indexdaughters& t) const - { - return (this->index0 == t.index0 && this->index1 == t.index1 && this->index2 == t.index2); - } - }; - - void processDoNotCompare(aod::Collisions::iterator const&) - { - // dummy process function - should not be required in the future - } - PROCESS_SWITCH(hypertriton3bodyComparewithDecay3body, processDoNotCompare, "Do not do comparison", true); - - void processDoComparison(aod::Decay3Bodys const& decay3bodytable, soa::Join const& vtx3bodydatas, MCLabeledTracksIU const&, aod::McParticles const& /*particlesMC*/) - { - std::vector set_pair; - for (auto d3body : decay3bodytable) { - registry.fill(HIST("hCheckCounter"), 0.5); - registry.fill(HIST("hMCInfoCounter"), 0.5); - auto lTrack0 = d3body.track0_as(); - auto lTrack1 = d3body.track1_as(); - auto lTrack2 = d3body.track2_as(); - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - continue; - } - registry.fill(HIST("hMCInfoCounter"), 1.5); - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (lMCTrack0.isPhysicalPrimary() || lMCTrack1.isPhysicalPrimary() || lMCTrack2.isPhysicalPrimary()) { - continue; - } - if (lMCTrack0.producedByGenerator() || lMCTrack1.producedByGenerator() || lMCTrack2.producedByGenerator()) { - continue; - } - registry.fill(HIST("hMCInfoCounter"), 2.5); - - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - continue; - } - registry.fill(HIST("hMCInfoCounter"), 3.5); - - int lPDG = -1; - float lPt = -1; - bool is3bodyDecayedH3L = false; - int lGlobalIndex = -1; - - for (auto& lMother0 : lMCTrack0.mothers_as()) { - for (auto& lMother1 : lMCTrack1.mothers_as()) { - for (auto& lMother2 : lMCTrack2.mothers_as()) { - registry.fill(HIST("hMCInfoCounter"), 4.5); - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { // vtxs with the same mother - registry.fill(HIST("hMCInfoCounter"), 7.5); - lGlobalIndex = lMother1.globalIndex(); - lPDG = lMother1.pdgCode(); - lPt = lMother1.pt(); - if (lPDG == 1010010030 && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == 1000010020) { - is3bodyDecayedH3L = true; - double hypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hHypertritonMCPt"), lPt); - registry.fill(HIST("hHypertritonMCMass"), hypertritonMCMass); - } - if (lPDG == -1010010030 && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -1000010020) { - is3bodyDecayedH3L = true; - double antiHypertritonMCMass = RecoDecay::m(array{array{lMCTrack0.px(), lMCTrack0.py(), lMCTrack0.pz()}, array{lMCTrack1.px(), lMCTrack1.py(), lMCTrack1.pz()}, array{lMCTrack2.px(), lMCTrack2.py(), lMCTrack2.pz()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hAntiHypertritonMCPt"), lPt); - registry.fill(HIST("hAntiHypertritonMCMass"), antiHypertritonMCMass); - } - } - } - } - } // end association check - - if (!is3bodyDecayedH3L) { - continue; - } - - registry.fill(HIST("hCheckCounter"), 1.5); - registry.fill(HIST("hMCInfoCounter"), 5.5); - // for check - registry.fill(HIST("hHypertritonMCPtTotal"), lPt); - - Indexdaughters temp = {lMCTrack0.globalIndex(), lMCTrack1.globalIndex(), lMCTrack2.globalIndex()}; - auto p = std::find(set_pair.begin(), set_pair.end(), temp); - if (p == set_pair.end()) { - set_pair.push_back(temp); - registry.fill(HIST("hMCInfoCounter"), 6.5); - } - - if (lTrack0.collisionId() != lTrack1.collisionId() || lTrack0.collisionId() != lTrack2.collisionId()) { - continue; - } - registry.fill(HIST("hCheckCounter"), 2.5); - - for (auto vtx : vtx3bodydatas) { - if (vtx.mcParticleId() == -1) { - continue; - } - auto mcparticle = vtx.mcParticle_as(); - if (mcparticle.globalIndex() == lGlobalIndex) { - registry.fill(HIST("hCheckCounter"), 4.5); // rare case check: if motherId matches but daughters not - if (lTrack0.globalIndex() == vtx.track0Id() && lTrack1.globalIndex() == vtx.track1Id() && lTrack2.globalIndex() == vtx.track2Id()) { - registry.fill(HIST("hCheckCounter"), 3.5); - if (lPDG > 0) { - registry.fill(HIST("hPairedHypertritonMCPt"), lPt); - } else { - registry.fill(HIST("hPairedAntiHypertritonMCPt"), lPt); - } - break; - } - } - } - } - } - PROCESS_SWITCH(hypertriton3bodyComparewithDecay3body, processDoComparison, "Compare decay3bodys and finder method with MC", false); -}; - -struct hypertriton3bodyInitializer { - Spawns vtx3bodydatas; - void init(InitContext const&) {} -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx b/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx index 68c9b7ac91d..14192166fae 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiFlowTree.cxx @@ -428,11 +428,11 @@ struct nucleiFlowTree { computeEventPlane(collision.qvecTPCallImVec()[cfgHarmonics - 2], collision.qvecTPCallReVec()[cfgHarmonics - 2]), computeEventPlane(collision.qvecTPCnegImVec()[cfgHarmonics - 2], collision.qvecTPCnegReVec()[cfgHarmonics - 2]), computeEventPlane(collision.qvecTPCposImVec()[cfgHarmonics - 2], collision.qvecTPCposReVec()[cfgHarmonics - 2]), - collision.sumAmplFT0A(), - collision.sumAmplFT0C(), - static_cast(collision.nTrkTPCall()), - static_cast(collision.nTrkTPCneg()), - static_cast(collision.nTrkTPCpos())}); + std::hypot(collision.qvecFT0AImVec()[cfgHarmonics - 2], collision.qvecFT0AReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecFT0CImVec()[cfgHarmonics - 2], collision.qvecFT0CReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecTPCallImVec()[cfgHarmonics - 2], collision.qvecTPCallReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecTPCnegImVec()[cfgHarmonics - 2], collision.qvecTPCnegReVec()[cfgHarmonics - 2]), + std::hypot(collision.qvecTPCposImVec()[cfgHarmonics - 2], collision.qvecTPCposReVec()[cfgHarmonics - 2])}); } if (flag & kTriton) { if (track.pt() < cfgCutPtMinTree || track.pt() > cfgCutPtMaxTree || track.sign() > 0) @@ -440,7 +440,7 @@ struct nucleiFlowTree { } nuclei::candidates.emplace_back(NucleusCandidate{ static_cast(track.globalIndex()), static_cast(track.collisionId()), (1 - 2 * iC) * mTrackParCov.getPt(), mTrackParCov.getEta(), mTrackParCov.getPhi(), - correctedTpcInnerParam, beta, collision.posZ(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tofChi2(), + correctedTpcInnerParam, beta, collision.posZ(), collision.numContrib(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tofChi2(), nSigmaTPC, tofMasses, fillTree, fillDCAHist, correctPV, isSecondary, fromWeakDecay, flag, track.tpcNClsFindable(), static_cast(track.tpcNClsCrossedRows()), track.itsClusterMap(), static_cast(track.tpcNClsFound()), static_cast(track.tpcNClsShared()), static_cast(track.itsNCls()), static_cast(track.itsClusterSizes())}); } @@ -456,7 +456,7 @@ struct nucleiFlowTree { } fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS); + nucleiTable(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); } for (auto& c : nuclei::candidates_flow) { nucleiTableFlow(c.centFV0A, c.centFT0M, c.centFT0A, c.centFT0C, c.psiFT0A, c.psiFT0C, c.psiTPC, c.psiTPCl, c.psiTPCr, c.qFT0A, c.qFT0C, c.qTPC, c.qTPCl, c.qTPCr); @@ -473,7 +473,7 @@ struct nucleiFlowTree { } fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS); + nucleiTable(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); } for (auto& c : nuclei::candidates_flow) { nucleiTableFlow(c.centFV0A, c.centFT0M, c.centFT0A, c.centFT0C, c.psiFT0A, c.psiFT0C, c.psiTPC, c.psiTPCl, c.psiTPCr, c.qFT0A, c.qFT0C, c.qTPC, c.qTPCl, c.qTPCr); diff --git a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx index 205c0eda0a4..5891997bc54 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx +++ b/PWGLF/TableProducer/Nuspex/nucleiSpectra.cxx @@ -19,51 +19,47 @@ // o2-analysis-pid-tof-base, o2-analysis-multiplicity-table, o2-analysis-event-selection // (to add flow: o2-analysis-qvector-table, o2-analysis-centrality-table) -#include -#include -#include -#include -#include - -#include "Math/Vector4D.h" - -#include "CCDB/BasicCCDBManager.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFSlimNucleiTables.h" +#include "Common/Core/EventPlaneHelper.h" +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/Qvectors.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/PID/PIDTOF.h" #include "Common/TableProducer/PID/pidTOFBase.h" -#include "Common/Core/EventPlaneHelper.h" -#include "Common/DataModel/Qvectors.h" -#include "Common/Core/RecoDecay.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" +#include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" - -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" - +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" - #include "ReconstructionDataFormats/Track.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "PWGLF/DataModel/LFSlimNucleiTables.h" - +#include "Math/Vector4D.h" #include "TRandom3.h" +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -79,6 +75,7 @@ struct NucleusCandidate { float tpcInnerParam; float beta; float zVertex; + int nContrib; float DCAxy; float DCAz; float TPCsignal; @@ -297,6 +294,7 @@ struct nucleiSpectra { Configurable> cfgDownscaling{"cfgDownscaling", {nuclei::DownscalingDefault[0], 5, 1, nuclei::names, nuclei::DownscalingConfigName}, "Fraction of kept candidates for light nuclei"}; Configurable> cfgTreeConfig{"cfgTreeConfig", {nuclei::TreeConfigDefault[0], 5, 2, nuclei::names, nuclei::treeConfigNames}, "Filtered trees configuration"}; Configurable cfgFillPairTree{"cfgFillPairTree", true, "Fill trees for pairs of light nuclei"}; + Configurable cfgFillGenSecondaries{"cfgFillGenSecondaries", 0, "Fill generated secondaries (0: no, 1: only weak decays, 2: all of them)"}; Configurable> cfgDCAHists{"cfgDCAHists", {nuclei::DCAHistDefault[0], 5, 2, nuclei::names, nuclei::DCAConfigNames}, "DCA hist configuration"}; Configurable> cfgFlowHist{"cfgFlowHist", {nuclei::FlowHistDefault[0], 5, 1, nuclei::names, nuclei::flowConfigNames}, "Flow hist configuration"}; @@ -793,7 +791,7 @@ struct nucleiSpectra { } nuclei::candidates.emplace_back(NucleusCandidate{ static_cast(track.globalIndex()), static_cast(track.collisionId()), (1 - 2 * iC) * mTrackParCov.getPt(), mTrackParCov.getEta(), mTrackParCov.getPhi(), - correctedTpcInnerParam, beta, collision.posZ(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tofChi2(), + correctedTpcInnerParam, beta, collision.posZ(), collision.numContrib(), dcaInfo[0], dcaInfo[1], track.tpcSignal(), track.itsChi2NCl(), track.tpcChi2NCl(), track.tofChi2(), nSigmaTPC, tofMasses, fillTree, fillDCAHist, correctPV, isSecondary, fromWeakDecay, flag, track.tpcNClsFindable(), static_cast(track.tpcNClsCrossedRows()), track.itsClusterMap(), static_cast(track.tpcNClsFound()), static_cast(track.tpcNClsShared()), static_cast(track.itsNCls()), static_cast(track.itsClusterSizes())}); } @@ -814,7 +812,7 @@ struct nucleiSpectra { for (size_t i1{0}; i1 < nuclei::candidates.size(); ++i1) { auto& c1 = nuclei::candidates[i1]; if (c1.fillTree) { - nucleiTable(c1.pt, c1.eta, c1.phi, c1.tpcInnerParam, c1.beta, c1.zVertex, c1.DCAxy, c1.DCAz, c1.TPCsignal, c1.ITSchi2, c1.TPCchi2, c1.TOFchi2, c1.flags, c1.TPCfindableCls, c1.TPCcrossedRows, c1.ITSclsMap, c1.TPCnCls, c1.TPCnClsShared, c1.clusterSizesITS); + nucleiTable(c1.pt, c1.eta, c1.phi, c1.tpcInnerParam, c1.beta, c1.zVertex, c1.nContrib, c1.DCAxy, c1.DCAz, c1.TPCsignal, c1.ITSchi2, c1.TPCchi2, c1.TOFchi2, c1.flags, c1.TPCfindableCls, c1.TPCcrossedRows, c1.ITSclsMap, c1.TPCnCls, c1.TPCnClsShared, c1.clusterSizesITS); if (cfgFillPairTree) { for (size_t i2{i1 + 1}; i2 < nuclei::candidates.size(); ++i2) { auto& c2 = nuclei::candidates[i2]; @@ -849,7 +847,7 @@ struct nucleiSpectra { fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { if (c.fillTree) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS); + nucleiTable(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); } if (c.fillDCAHist) { for (int iS{0}; iS < nuclei::species; ++iS) { @@ -878,7 +876,7 @@ struct nucleiSpectra { fillDataInfo(collision, tracks); for (auto& c : nuclei::candidates) { if (c.fillTree) { - nucleiTable(c.pt, c.eta, c.phi, c.tpcInnerParam, c.beta, c.zVertex, c.DCAxy, c.DCAz, c.TPCsignal, c.ITSchi2, c.TPCchi2, c.TOFchi2, c.flags, c.TPCfindableCls, c.TPCcrossedRows, c.ITSclsMap, c.TPCnCls, c.TPCnClsShared, c.clusterSizesITS); + nucleiTable(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); } if (c.fillDCAHist) { for (int iS{0}; iS < nuclei::species; ++iS) { @@ -971,7 +969,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.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); + 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); } int index{0}; @@ -991,6 +989,7 @@ struct nucleiSpectra { if (particle.isPhysicalPrimary()) { flags |= kIsPhysicalPrimary; nuclei::hGenNuclei[iS][particle.pdgCode() < 0]->Fill(1., particle.pt()); + // antinuclei from B hadrons are classified as physical primaries if (particle.has_mothers()) { for (auto& motherparticle : particle.mothers_as()) { if (std::find(nuclei::hfMothCodes.begin(), nuclei::hfMothCodes.end(), std::abs(motherparticle.pdgCode())) != nuclei::hfMothCodes.end()) { @@ -1001,7 +1000,10 @@ struct nucleiSpectra { } } } - } else if (particle.has_mothers()) { + } else if (particle.getProcess() == TMCProcess::kPDecay) { + if (!particle.has_mothers()) { + continue; // skip secondaries from weak decay without mothers + } flags |= kIsSecondaryFromWeakDecay; for (auto& motherparticle : particle.mothers_as()) { motherPdgCode = motherparticle.pdgCode(); @@ -1012,9 +1014,14 @@ struct nucleiSpectra { } if (!isReconstructed[index] && (cfgTreeConfig->get(iS, 0u) || cfgTreeConfig->get(iS, 1u))) { + if ((flags & kIsPhysicalPrimary) == 0 && cfgFillGenSecondaries == 0) { + continue; // skip secondaries if not requested + } + if ((flags & (kIsPhysicalPrimary | kIsSecondaryFromWeakDecay)) == 0 && cfgFillGenSecondaries == 1) { + continue; // skip secondaries from material if not requested + } float absDecL = computeAbsoDecL(particle); - - nucleiTableMC(999., 999., 999., 0., 0., 999., 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); + 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); } break; } @@ -1050,6 +1057,61 @@ struct nucleiSpectra { } PROCESS_SWITCH(nucleiSpectra, processMatching, "Matching analysis", false); + + void processMCasData(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); + for (auto& collision : collisions) { + if (!eventSelection(collision)) { + continue; + } + goodCollisions[collision.mcCollisionId()] = true; + const auto& slicedTracks = tracks.sliceBy(tracksPerCollisions, collision.globalIndex()); + fillDataInfo(collision, slicedTracks); + } + std::vector isReconstructed(particlesMC.size(), false); + for (size_t i{0}; i < nuclei::candidates.size(); ++i) { + auto& c = nuclei::candidates[i]; + if (c.fillTree) { + auto label = tracks.iteratorAt(c.globalIndex); + if (label.mcParticleId() < -1 || label.mcParticleId() >= particlesMC.size()) { + continue; + } + auto particle = particlesMC.iteratorAt(label.mcParticleId()); + int motherPdgCode = 0; + float motherDecRadius = -1; + isReconstructed[particle.globalIndex()] = true; + if (particle.isPhysicalPrimary()) { + c.flags |= kIsPhysicalPrimary; + if (particle.has_mothers()) { + for (auto& motherparticle : particle.mothers_as()) { + if (std::find(nuclei::hfMothCodes.begin(), nuclei::hfMothCodes.end(), std::abs(motherparticle.pdgCode())) != nuclei::hfMothCodes.end()) { + c.flags |= kIsSecondaryFromWeakDecay; + motherPdgCode = motherparticle.pdgCode(); + motherDecRadius = std::hypot(particle.vx() - motherparticle.vx(), particle.vy() - motherparticle.vy()); + break; + } + } + } + } else if (particle.has_mothers()) { + c.flags |= kIsSecondaryFromWeakDecay; + for (auto& motherparticle : particle.mothers_as()) { + motherPdgCode = motherparticle.pdgCode(); + motherDecRadius = std::hypot(particle.vx() - motherparticle.vx(), particle.vy() - motherparticle.vy()); + } + } else { + c.flags |= kIsSecondaryFromMaterial; + } + + 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); + } + } + } + PROCESS_SWITCH(nucleiSpectra, processMCasData, "MC as data analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/TableProducer/Nuspex/nucleiUtils.h b/PWGLF/TableProducer/Nuspex/nucleiUtils.h index 2a9a64bc4b2..29cd489768d 100644 --- a/PWGLF/TableProducer/Nuspex/nucleiUtils.h +++ b/PWGLF/TableProducer/Nuspex/nucleiUtils.h @@ -29,6 +29,7 @@ struct NucleusCandidate { float tpcInnerParam; float beta; float zVertex; + int nContrib; float DCAxy; float DCAz; float TPCsignal; diff --git a/PWGLF/TableProducer/Nuspex/pidTOFGeneric.cxx b/PWGLF/TableProducer/Nuspex/pidTOFGeneric.cxx index 9997d4d27c8..7a3afb2b71d 100644 --- a/PWGLF/TableProducer/Nuspex/pidTOFGeneric.cxx +++ b/PWGLF/TableProducer/Nuspex/pidTOFGeneric.cxx @@ -11,33 +11,37 @@ /// /// \file pidTOFGeneric.cxx -/// \origin Based on pidTOFBase.cxx +/// \origin Based on pidTOFMerged.cxx /// \brief Task to produce event Time obtained from TOF and FT0. -/// In order to redo TOF PID for tracks which are linked to wrong collisions +/// In order to redo TOF PID for secondary tracks which are linked to wrong collisions +/// \author Yuanzhe Wang /// +#include #include #include -#include // O2 includes #include "CCDB/BasicCCDBManager.h" -#include "TOFBase/EventTimeMaker.h" #include "Framework/AnalysisTask.h" #include "ReconstructionDataFormats/Track.h" +#include "TOFBase/EventTimeMaker.h" // O2Physics includes +#include "PWGLF/DataModel/LFPIDTOFGenericTables.h" +#include "PWGLF/Utils/pidTOFGeneric.h" + #include "Common/Core/TableHelper.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/FT0Corrected.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" -#include "PID/ParamBase.h" #include "PID/PIDTOF.h" -#include "PWGLF/DataModel/pidTOFGeneric.h" +#include "PID/ParamBase.h" using namespace o2; using namespace o2::framework; @@ -45,13 +49,19 @@ using namespace o2::pid; using namespace o2::framework::expressions; using namespace o2::track; +o2::common::core::MetadataHelper metadataInfo; + /// Selection criteria for tracks used for TOF event time float trackSampleMinMomentum = 0.5f; float trackSampleMaxMomentum = 2.f; template bool filterForTOFEventTime(const trackType& tr) { - return (tr.hasTOF() && tr.p() > trackSampleMinMomentum && tr.p() < trackSampleMaxMomentum && (tr.trackType() == o2::aod::track::TrackTypeEnum::Track || tr.trackType() == o2::aod::track::TrackTypeEnum::TrackIU)); + return (tr.hasTOF() && + tr.p() > trackSampleMinMomentum && tr.p() < trackSampleMaxMomentum && + tr.hasITS() && + tr.hasTPC() && + (tr.trackType() == o2::aod::track::TrackTypeEnum::Track || tr.trackType() == o2::aod::track::TrackTypeEnum::TrackIU)); } // accept all /// Specialization of TOF event time maker @@ -69,342 +79,275 @@ o2::tof::eventTimeContainer evTimeMakerForTracks(const trackTypeContainer& track } /// Task to produce the event time tables for generic TOF PID +/// Modified based on pidTOFMerge.cxx struct pidTOFGeneric { // Tables to produce Produces tableEvTime; // Table for global event time Produces tableEvTimeForTrack; // Table for event time after removing bias from the track - static constexpr float diamond = 6.0; // Collision diamond used in the estimation of the TOF event time - static constexpr float errDiamond = diamond * 33.356409f; - static constexpr float weightDiamond = 1.f / (errDiamond * errDiamond); + static constexpr bool kRemoveTOFEvTimeBias = true; // Flag to subtract the Ev. Time bias for low multiplicity events with TOF + static constexpr float kDiamond = 6.0; // Collision diamond used in the estimation of the TOF event time + static constexpr float kErrDiamond = kDiamond * 33.356409f; + static constexpr float kWeightDiamond = 1.f / (kErrDiamond * kErrDiamond); bool enableTable = false; - // Detector response and input parameters - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - Service ccdb; - Configurable inheritFromBaseTask{"inheritFromBaseTask", true, "Flag to iherit all common configurables from the TOF base task"}; + Configurable fastTOFPID{"fastTOFPID", false, "Flag to enable computeEvTimeFast for evTimeMaker"}; - // CCDB configuration (inherited from TOF signal task) - Configurable url{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; - Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; // Event time configurations Configurable minMomentum{"minMomentum", 0.5f, "Minimum momentum to select track sample for TOF event time"}; Configurable maxMomentum{"maxMomentum", 2.0f, "Maximum momentum to select track sample for TOF event time"}; Configurable maxEvTimeTOF{"maxEvTimeTOF", 100000.0f, "Maximum value of the TOF event time"}; Configurable sel8TOFEvTime{"sel8TOFEvTime", false, "Flag to compute the ev. time only for events that pass the sel8 ev. selection"}; + Configurable mComputeEvTimeWithTOF{"computeEvTimeWithTOF", -1, "Compute ev. time with TOF. -1 (autoset), 0 no, 1 yes"}; + Configurable mComputeEvTimeWithFT0{"computeEvTimeWithFT0", -1, "Compute ev. time with FT0. -1 (autoset), 0 no, 1 yes"}; Configurable maxNtracksInSet{"maxNtracksInSet", 10, "Size of the set to consider for the TOF ev. time computation"}; - // TOF Calib configuration - Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; - Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; - Configurable passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; - Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable enableTimeDependentResponse{"enableTimeDependentResponse", false, "Flag to use the collision timestamp to fetch the PID Response"}; - Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; + + // TOF response and input parameters + o2::pid::tof::TOFResoParamsV3 mRespParamsV3; + Service ccdb; + o2::aod::pidtofgeneric::TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration void init(o2::framework::InitContext& initContext) { - if (inheritFromBaseTask.value) { - if (!getTaskOptionValue(initContext, "tof-signal", "ccdb-url", url.value, true)) { - LOG(fatal) << "Could not get ccdb-url from tof-signal task"; - } - if (!getTaskOptionValue(initContext, "tof-signal", "ccdb-timestamp", timestamp.value, true)) { - LOG(fatal) << "Could not get ccdb-timestamp from tof-signal task"; - } - } - - trackSampleMinMomentum = minMomentum; - trackSampleMaxMomentum = maxMomentum; - LOG(info) << "Configuring track sample for TOF ev. time: " << trackSampleMinMomentum << " < p < " << trackSampleMaxMomentum; - // Check that both processes are not enabled - int nEnabled = 0; - if (doprocessNoFT0 == true) { - LOGF(info, "Enabling process function: processNoFT0"); - nEnabled++; - } - if (doprocessFT0 == true) { - LOGF(info, "Enabling process function: processFT0"); - nEnabled++; - } - if (doprocessOnlyFT0 == true) { - LOGF(info, "Enabling process function: processOnlyFT0"); - nEnabled++; - } - if (nEnabled > 1) { - LOGF(fatal, "Cannot enable more process functions at the same time. Please choose one."); - } + mTOFCalibConfig.metadataInfo = metadataInfo; + mTOFCalibConfig.inheritFromBaseTask(initContext); // Checking that the table is requested in the workflow and enabling it enableTable = isTableRequiredInWorkflow(initContext, "EvTimeTOFFT0") || isTableRequiredInWorkflow(initContext, "EvTimeTOFFT0ForTrack"); if (!enableTable) { LOG(info) << "Table for global Event time is not required, disabling it"; - return; + // return; //TODO: uncomment this line } + enableTable = true; // Force enabling the table for now LOG(info) << "Table EvTimeTOFFT0 enabled!"; - if (sel8TOFEvTime.value == true) { - LOG(info) << "TOF event time will be computed for collisions that pass the event selection only!"; - } - // Getting the parametrization parameters - ccdb->setURL(url.value); - ccdb->setTimestamp(timestamp.value); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - // Not later than now objects - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - // - - // TODO: implement the automatic pass name detection from metadata - if (passName.value == "") { - passName.value = "unanchored"; // temporary default - LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; - } - LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; - - const std::string fname = paramFileName.value; - if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; - if (1) { - o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, parametrizationPath.value); - LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { - mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } else { - mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); - } - } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; - - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); - paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); + if (mTOFCalibConfig.autoSetProcessFunctions()) { + LOG(info) << "Autodetecting process functions"; + if (metadataInfo.isFullyDefined()) { + if (metadataInfo.isRun3()) { + doprocessRun3.value = true; } - } else { - mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); - mRespParamsV2.printShiftParameters(); } } - mRespParamsV2.print(); - o2::tof::eventTimeContainer::setMaxNtracksInSet(maxNtracksInSet.value); - o2::tof::eventTimeContainer::printConfig(); - } - /// - /// Process function to prepare the event time on Run 3 data without the FT0 - using TrksEvTime = soa::Join; - // Define slice per collision - Preslice perCollision = aod::track::collisionId; - template - using ResponseImplementationEvTime = o2::pid::tof::ExpTimes; - using EvTimeCollisions = soa::Join; - void processNoFT0(TrksEvTime& tracks, - EvTimeCollisions const& collisions) - { - if (!enableTable) { - return; - } - tableEvTime.reserve(collisions.size()); - tableEvTimeForTrack.reserve(tracks.size()); - - // for tracks not assigned to a collision - for (auto track : tracks) { - if (!track.has_collision()) { - tableEvTimeForTrack(0.f, 999.f); + if (metadataInfo.isFullyDefined()) { + if (!metadataInfo.isRun3()) { + LOG(fatal) << "Run3 process not supported in pidTOFGeneric task"; } } - for (auto const& collision : collisions) { // Loop on collisions - const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); - if ((sel8TOFEvTime.value == true) && !collision.sel8()) { - tableEvTime(0.f, 999.f, 0.f, 999.f, 0.f, 999.f); - for (int i = 0; i < tracksInCollision.size(); i++) { - tableEvTimeForTrack(0.f, 999.f); - } - continue; - } - - // First make table for event time - const auto evTimeTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV2, diamond, fastTOFPID); - int nGoodTracksForTOF = 0; // count for ntrackIndex for removeBias() - float et = evTimeTOF.mEventTime; - float erret = evTimeTOF.mEventTimeError; + trackSampleMinMomentum = minMomentum; + trackSampleMaxMomentum = maxMomentum; + LOG(info) << "Configuring track sample for TOF ev. time: " << trackSampleMinMomentum << " < p < " << trackSampleMaxMomentum; - if (erret < errDiamond && (maxEvTimeTOF <= 0.f || abs(et) < maxEvTimeTOF)) { - } else { - et = 0.f; - erret = errDiamond; - } - tableEvTime(et, erret, et, erret, 0.f, 999.f); - for (auto const& track : tracksInCollision) { - evTimeTOF.removeBias(track, nGoodTracksForTOF, et, erret, 2); - if (erret < errDiamond && (maxEvTimeTOF <= 0.f || abs(et) < maxEvTimeTOF)) { - } else { - et = 0.f; - erret = errDiamond; - } - tableEvTimeForTrack(et, erret); - } + if (sel8TOFEvTime.value == true) { + LOG(info) << "TOF event time will be computed for collisions that pass the event selection only!"; } + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); // Getting the parametrization parameters + + o2::tof::eventTimeContainer::setMaxNtracksInSet(maxNtracksInSet.value); + o2::tof::eventTimeContainer::printConfig(); } - PROCESS_SWITCH(pidTOFGeneric, processNoFT0, "Process without FT0", false); + + void process(aod::BCs const&) {} /// - /// Process function to prepare the event for each track on Run 3 data with the FT0 + /// Process function to prepare the event for each track on Run 3 data without the FT0 + // Define slice per collision + using Run3Cols = aod::Collisions; + using EvTimeCollisions = soa::Join; using EvTimeCollisionsFT0 = soa::Join; - void processFT0(TrksEvTime& tracks, - aod::FT0s const&, - EvTimeCollisionsFT0 const& collisions) + using Run3Trks = o2::soa::Join; + using Run3TrksWtof = soa::Join; + Preslice perCollision = aod::track::collisionId; + template + using ResponseImplementationEvTime = o2::pid::tof::ExpTimes; + + void processRun3(Run3TrksWtof const& tracks, + aod::FT0s const&, + EvTimeCollisionsFT0 const& collisions, + aod::BCsWithTimestamps const& bcs) { if (!enableTable) { return; } + LOG(debug) << "Processing Run3 data for TOF event time"; + tableEvTime.reserve(collisions.size()); tableEvTimeForTrack.reserve(tracks.size()); - std::vector tEvTimeForTrack; - std::vector tEvTimeErrForTrack; - tEvTimeForTrack.resize(tracks.size()); - tEvTimeErrForTrack.resize(tracks.size()); - - // for tracks not assigned to a collision - for (auto track : tracks) { - if (!track.has_collision()) { - tEvTimeForTrack[track.globalIndex()] = 0.f; - tEvTimeErrForTrack[track.globalIndex()] = 999.f; + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, bcs.iteratorAt(0)); // Update the calibration parameters + + // Autoset the processing mode for the event time computation + if (mComputeEvTimeWithTOF == -1 || mComputeEvTimeWithFT0 == -1) { + switch (mTOFCalibConfig.collisionSystem()) { + case CollisionSystemType::kCollSyspp: // pp + mComputeEvTimeWithTOF.value = ((mComputeEvTimeWithTOF == -1) ? 0 : mComputeEvTimeWithTOF.value); + mComputeEvTimeWithFT0.value = ((mComputeEvTimeWithFT0 == -1) ? 1 : mComputeEvTimeWithFT0.value); + break; + case CollisionSystemType::kCollSysPbPb: // PbPb + mComputeEvTimeWithTOF.value = ((mComputeEvTimeWithTOF == -1) ? 1 : mComputeEvTimeWithTOF.value); + mComputeEvTimeWithFT0.value = ((mComputeEvTimeWithFT0 == -1) ? 0 : mComputeEvTimeWithFT0.value); + break; + default: + LOG(fatal) << "Collision system " << mTOFCalibConfig.collisionSystem() << " " << CollisionSystemType::getCollisionSystemName(mTOFCalibConfig.collisionSystem()) << " not supported for TOF event time computation"; + break; } } + LOG(debug) << "Running on " << CollisionSystemType::getCollisionSystemName(mTOFCalibConfig.collisionSystem()) << " mComputeEvTimeWithTOF " << mComputeEvTimeWithTOF.value << " mComputeEvTimeWithFT0 " << mComputeEvTimeWithFT0.value; - for (auto const& collision : collisions) { // Loop on collisions - const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); - if ((sel8TOFEvTime.value == true) && !collision.sel8()) { - tableEvTime(0.f, 999.f, 0.f, 999.f, 0.f, 999.f); - for (auto track : tracksInCollision) { - tEvTimeForTrack[track.globalIndex()] = 0.f; - tEvTimeErrForTrack[track.globalIndex()] = 999.f; + if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 1) { + int lastCollisionId = -1; // Last collision ID analysed + for (auto const& t : tracks) { // Loop on collisions + if (!t.has_collision() || ((sel8TOFEvTime.value == true) && !t.collision_as().sel8())) { // Track was not assigned, cannot compute event time or event did not pass the event selection + tableEvTimeForTrack(0.f, 999.f); + continue; } - continue; - } - - // Compute the TOF event time - const auto evTimeTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV2, diamond, fastTOFPID); - - float t0TOF[2] = {static_cast(evTimeTOF.mEventTime), static_cast(evTimeTOF.mEventTimeError)}; // Value and error of TOF - float t0AC[2] = {.0f, 999.f}; // Value and error of T0A or T0C or T0AC + if (t.collisionId() == lastCollisionId) { // Event time from this collision is already in the table + continue; + } + /// Create new table for the tracks in a collision + lastCollisionId = t.collisionId(); /// Cache last collision ID - float eventTime = 0.f; - float sumOfWeights = 0.f; - float weight = 0.f; + const auto& tracksInCollision = tracks.sliceBy(perCollision, lastCollisionId); + const auto& collision = t.collision_as(); - if (t0TOF[1] < errDiamond && (maxEvTimeTOF <= 0 || abs(t0TOF[0]) < maxEvTimeTOF)) { - weight = 1.f / (t0TOF[1] * t0TOF[1]); - eventTime += t0TOF[0] * weight; - sumOfWeights += weight; - } + // Compute the TOF event time + const auto evTimeMakerTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV3, kDiamond, fastTOFPID); - if (collision.has_foundFT0()) { // T0 measurement is available - // const auto& ft0 = collision.foundFT0(); - if (collision.t0ACValid()) { - t0AC[0] = collision.t0AC() * 1000.f; - t0AC[1] = collision.t0resolution() * 1000.f; - } + float t0AC[2] = {.0f, 999.f}; // Value and error of T0A or T0C or T0AC + float t0TOF[2] = {static_cast(evTimeMakerTOF.mEventTime), static_cast(evTimeMakerTOF.mEventTimeError)}; // Value and error of TOF - weight = 1.f / (t0AC[1] * t0AC[1]); - eventTime += t0AC[0] * weight; - sumOfWeights += weight; - } + int nGoodTracksForTOF = 0; + float eventTime = 0.f; + float sumOfWeights = 0.f; + float weight = 0.f; - if (sumOfWeights < weightDiamond) { // avoiding sumOfWeights = 0 or worse that diamond - eventTime = 0; - sumOfWeights = weightDiamond; - } - tableEvTime(eventTime / sumOfWeights, sqrt(1. / sumOfWeights), t0TOF[0], t0TOF[1], t0AC[0], t0AC[1]); - - int nGoodTracksForTOF = 0; // count for ntrackIndex for removeBias() - for (auto const& track : tracksInCollision) { - // Reset the event time - eventTime = 0.f; - sumOfWeights = 0.f; - weight = 0.f; - // Remove the bias on TOF ev. time - evTimeTOF.removeBias(track, nGoodTracksForTOF, t0TOF[0], t0TOF[1], 2); - if (t0TOF[1] < errDiamond && (maxEvTimeTOF <= 0 || abs(t0TOF[0]) < maxEvTimeTOF)) { + if (t0TOF[1] < kErrDiamond && (maxEvTimeTOF <= 0 || std::abs(t0TOF[0]) < maxEvTimeTOF)) { weight = 1.f / (t0TOF[1] * t0TOF[1]); eventTime += t0TOF[0] * weight; sumOfWeights += weight; } - // Add the contribution from FT0 if it is available, t0AC is already calculated - if (collision.has_foundFT0()) { + if (collision.has_foundFT0()) { // T0 measurement is available + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + t0AC[0] = collision.t0AC() * 1000.f; + t0AC[1] = collision.t0resolution() * 1000.f; + } + weight = 1.f / (t0AC[1] * t0AC[1]); eventTime += t0AC[0] * weight; sumOfWeights += weight; } - if (sumOfWeights < weightDiamond) { // avoiding sumOfWeights = 0 or worse that diamond - eventTime = 0; - sumOfWeights = weightDiamond; + tableEvTime(eventTime / sumOfWeights, std::sqrt(1. / sumOfWeights), t0TOF[0], t0TOF[1], t0AC[0], t0AC[1]); + + for (auto const& trk : tracksInCollision) { // Loop on Tracks + // Reset the event time + eventTime = 0.f; + sumOfWeights = 0.f; + weight = 0.f; + // Remove the bias on TOF ev. time + if constexpr (kRemoveTOFEvTimeBias) { + evTimeMakerTOF.removeBias(trk, nGoodTracksForTOF, t0TOF[0], t0TOF[1], 2); + } + if (t0TOF[1] < kErrDiamond && (maxEvTimeTOF <= 0 || std::abs(t0TOF[0]) < maxEvTimeTOF)) { + weight = 1.f / (t0TOF[1] * t0TOF[1]); + eventTime += t0TOF[0] * weight; + sumOfWeights += weight; + } + + if (collision.has_foundFT0()) { // T0 measurement is available + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + t0AC[0] = collision.t0AC() * 1000.f; + t0AC[1] = collision.t0resolution() * 1000.f; + } + + weight = 1.f / (t0AC[1] * t0AC[1]); + eventTime += t0AC[0] * weight; + sumOfWeights += weight; + } + + if (sumOfWeights < kWeightDiamond) { // avoiding sumOfWeights = 0 or worse that kDiamond + eventTime = 0; + sumOfWeights = kWeightDiamond; + } + tableEvTimeForTrack(eventTime / sumOfWeights, std::sqrt(1. / sumOfWeights)); } - tEvTimeForTrack[track.globalIndex()] = eventTime / sumOfWeights; - tEvTimeErrForTrack[track.globalIndex()] = sqrt(1. / sumOfWeights); } - } - for (int i = 0; i < tracks.size(); i++) { - tableEvTimeForTrack(tEvTimeForTrack[i], tEvTimeErrForTrack[i]); - } - } - PROCESS_SWITCH(pidTOFGeneric, processFT0, "Process with FT0", true); + } else if (mComputeEvTimeWithTOF == 1 && mComputeEvTimeWithFT0 == 0) { + int lastCollisionId = -1; // Last collision ID analysed + for (auto const& t : tracks) { // Loop on collisions + if (!t.has_collision() || ((sel8TOFEvTime.value == true) && !t.collision_as().sel8())) { // Track was not assigned, cannot compute event time or event did not pass the event selection + tableEvTimeForTrack(0.f, 999.f); + continue; + } + if (t.collisionId() == lastCollisionId) { // Event time from this collision is already in the table + continue; + } + /// Create new table for the tracks in a collision + lastCollisionId = t.collisionId(); /// Cache last collision ID - /// - /// Process function to prepare the event time on Run 3 data with only the FT0 - void processOnlyFT0(EvTimeCollisionsFT0 const& collisions, - TrksEvTime& tracks, - aod::FT0s const&) - { - if (!enableTable) { - return; - } - tableEvTime.reserve(collisions.size()); - tableEvTimeForTrack.reserve(tracks.size()); + const auto& tracksInCollision = tracks.sliceBy(perCollision, lastCollisionId); - // for tracks not assigned to a collision - for (auto track : tracks) { - if (!track.has_collision()) { - tableEvTimeForTrack(0.f, 999.f); - } - } + // First make table for event time + const auto evTimeMakerTOF = evTimeMakerForTracks(tracksInCollision, mRespParamsV3, kDiamond, fastTOFPID); + int nGoodTracksForTOF = 0; + float et = evTimeMakerTOF.mEventTime; + float erret = evTimeMakerTOF.mEventTimeError; - for (auto const& collision : collisions) { - const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); - if (collision.has_foundFT0()) { // T0 measurement is available - // const auto& ft0 = collision.foundFT0(); - if (collision.t0ACValid()) { - tableEvTime(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f, 0.f, 999.f, collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); - for (int i = 0; i < tracks.size(); i++) { - tableEvTimeForTrack(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); + if (erret < kErrDiamond && (maxEvTimeTOF <= 0.f || std::abs(et) < maxEvTimeTOF)) { + } else { + et = 0.f; + erret = kErrDiamond; + } + tableEvTime(et, erret, et, erret, 0.f, 999.f); + + for (auto const& trk : tracksInCollision) { // Loop on Tracks + if constexpr (kRemoveTOFEvTimeBias) { + evTimeMakerTOF.removeBias(trk, nGoodTracksForTOF, et, erret, 2); + } + if (erret < kErrDiamond && (maxEvTimeTOF <= 0.f || std::abs(et) < maxEvTimeTOF)) { + } else { + et = 0.f; + erret = kErrDiamond; } - return; + tableEvTimeForTrack(et, erret); + } + } + } else if (mComputeEvTimeWithTOF == 0 && mComputeEvTimeWithFT0 == 1) { + for (const auto& track : tracks) { + if (!track.has_collision()) { + tableEvTimeForTrack(0.f, 999.f); } } - tableEvTime(0.f, 999.f, 0.f, 999.f, 0.f, 999.f); - for (int i = 0; i < tracksInCollision.size(); i++) { - tableEvTimeForTrack(0.f, 999.f); + + for (auto const& collision : collisions) { + const auto& tracksInCollision = tracks.sliceBy(perCollision, collision.globalIndex()); + if (collision.has_foundFT0()) { // T0 measurement is available + // const auto& ft0 = collision.foundFT0(); + if (collision.t0ACValid()) { + tableEvTime(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f, 0.f, 999.f, collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); + for (int i = 0; i < tracksInCollision.size(); i++) { + tableEvTimeForTrack(collision.t0AC() * 1000.f, collision.t0resolution() * 1000.f); + } + continue; + } + } + tableEvTime(0.f, 999.f, 0.f, 999.f, 0.f, 999.f); + for (int i = 0; i < tracksInCollision.size(); i++) { + tableEvTimeForTrack(0.f, 999.f); + } } + } else { + LOG(fatal) << "Invalid configuration for TOF event time computation"; } } - PROCESS_SWITCH(pidTOFGeneric, processOnlyFT0, "Process only with FT0", false); + PROCESS_SWITCH(pidTOFGeneric, processRun3, "Process the Run3 data", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + metadataInfo.initMetadata(cfgc); return WorkflowSpec{ adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx b/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx index f8d3d04856a..e164dc2794c 100644 --- a/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx +++ b/PWGLF/TableProducer/Nuspex/reduced3bodyCreator.cxx @@ -14,47 +14,50 @@ /// \author Yuanzhe Wang /// \author Carolina Reetz -#include -#include -#include -#include -#include -#include +#include "TableHelper.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "DCAFitter/DCAFitterN.h" -#include "ReconstructionDataFormats/Track.h" +#include "PWGLF/DataModel/LFPIDTOFGenericTables.h" +#include "PWGLF/DataModel/Reduced3BodyTables.h" +#include "PWGLF/Utils/pidTOFGeneric.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Centrality.h" -#include "PWGLF/DataModel/pidTOFGeneric.h" -#include "PWGLF/DataModel/Reduced3BodyTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "Common/Core/PID/PIDTOF.h" -#include "TableHelper.h" -#include "Tools/KFparticle/KFUtilities.h" - #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" +#include "Tools/KFparticle/KFUtilities.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.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 +#include +#include +#include +#include +#include #ifndef HomogeneousField #define HomogeneousField #endif // includes KFParticle -#include "KFParticle.h" #include "KFPTrack.h" #include "KFPVertex.h" +#include "KFParticle.h" #include "KFParticleBase.h" #include "KFVertex.h" @@ -62,6 +65,8 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; +o2::common::core::MetadataHelper metadataInfo; + using FullTracksExtIU = soa::Join; using FullTracksExtPIDIU = soa::Join; @@ -78,7 +83,6 @@ struct reduced3bodyCreator { Produces reducedDecay3Bodys; Produces reduced3BodyInfo; Produces reducedFullTracksPIDIU; - Produces dcaFitterSVInfo; Service ccdb; Zorro zorro; @@ -87,9 +91,8 @@ struct reduced3bodyCreator { o2::vertexing::DCAFitterN<3> fitter3body; o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; - Configurable event_sel8_selection{"event_sel8_selection", true, "event selection count post sel8 cut"}; - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; + Configurable doSel8selection{"doSel8selection", true, "flag for sel8 event selection"}; + Configurable doPosZselection{"doPosZselection", true, "flag for posZ event selection"}; // CCDB options Configurable ccdburl{"ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; @@ -111,12 +114,17 @@ struct reduced3bodyCreator { Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction for DCAFitter"}; int mRunNumber; - float d_bz; - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; + float mBz; + // TOF response and input parameters + o2::pid::tof::TOFResoParamsV3 mRespParamsV3; + o2::aod::pidtofgeneric::TOFCalibConfig mTOFCalibConfig; // TOF Calib configuration + + // tracked cluster size + std::vector fTrackedClSizeVector; HistogramRegistry registry{"registry", {}}; - void init(InitContext&) + void init(InitContext& initContext) { mRunNumber = 0; zorroSummary.setObject(zorro.getZorroSummary()); @@ -127,6 +135,11 @@ struct reduced3bodyCreator { ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); + // TOF PID parameters initialization + mTOFCalibConfig.metadataInfo = metadataInfo; + mTOFCalibConfig.inheritFromBaseTask(initContext); + mTOFCalibConfig.initSetup(mRespParamsV3, ccdb); + fitter3body.setPropagateToPCA(true); fitter3body.setMaxR(200.); //->maxRIni3body fitter3body.setMinParamChange(1e-3); @@ -169,89 +182,22 @@ struct reduced3bodyCreator { // In case override, don't proceed, please - no CCDB access required auto run3grp_timestamp = bc.timestamp(); - o2::parameters::GRPObject* grpo = ccdb->getForTimeStamp(grpPath, run3grp_timestamp); - o2::parameters::GRPMagField* grpmag = 0x0; - 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); - d_bz = o2::base::Propagator::Instance()->getNominalBz(); - LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << d_bz << " kZG"; + o2::parameters::GRPMagField* 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 + // mBz = std::lround(5.f * grpmag->getL3Current() / 30000.f); + mBz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Retrieved GRP for timestamp " << run3grp_timestamp << " with magnetic field of " << mBz << " kZG"; // Set magnetic field for KF vertexing #ifdef HomogeneousField - KFParticle::SetField(d_bz); + KFParticle::SetField(mBz); #endif - // Initial TOF PID Paras, copied from PIDTOF.h - timestamp.value = bc.timestamp(); - ccdb->setTimestamp(timestamp.value); - // Not later than now objects - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - // TODO: implement the automatic pass name detection from metadata - if (passName.value == "") { - passName.value = "unanchored"; // temporary default - LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; - } - LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; - - const std::string fname = paramFileName.value; - if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; - if (1) { - o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, parametrizationPath.value); - LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { - mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } else { - mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); - } - } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); - paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { // Attempt at loading the parameters with the pass defined - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { // Pass is available, load non standard parameters - mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } - mRespParamsV2.print(); - if (timeShiftCCDBPath.value != "") { - if (timeShiftCCDBPath.value.find(".root") != std::string::npos) { - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); - } else { - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); - } - } - - fitter3body.setBz(d_bz); - bachelorTOFPID.SetParams(mRespParamsV2); + fitter3body.setBz(mBz); + mTOFCalibConfig.processSetup(mRespParamsV3, ccdb, bc); } //------------------------------------------------------------------ @@ -282,7 +228,7 @@ struct reduced3bodyCreator { //------------------------------------------------------------------ // function to fit KFParticle 3body vertex template - void fit3bodyVertex(TKFParticle& kfpProton, TKFParticle& kfpPion, TKFParticle& kfpDeuteron, TKFParticle& KFHt) + bool fit3bodyVertex(TKFParticle& kfpProton, TKFParticle& kfpPion, TKFParticle& kfpDeuteron, TKFParticle& KFHt) { // Construct 3body vertex int nDaughters3body = 3; @@ -292,14 +238,15 @@ struct reduced3bodyCreator { KFHt.Construct(Daughters3body, nDaughters3body); } catch (std::runtime_error& e) { LOG(debug) << "Failed to create Hyper triton 3-body vertex." << e.what(); - return; + return false; } LOG(debug) << "Hypertriton vertex constructed."; + return true; } - void process(ColwithEvTimesMultsCents const& collisions, TrackExtPIDIUwithEvTimes const&, aod::Decay3Bodys const& decay3bodys, aod::BCsWithTimestamps const&) + void process(ColwithEvTimesMultsCents const& collisions, TrackExtPIDIUwithEvTimes const&, aod::Decay3Bodys const& decay3bodys, aod::Tracked3Bodys const& tracked3bodys, aod::BCsWithTimestamps const&) { - std::vector triggeredCollisions(collisions.size(), false); + std::vector isTriggeredCollision(collisions.size(), false); int lastRunNumber = -1; // RunNumber of last collision, used for zorro counting // Event counting @@ -317,17 +264,17 @@ struct reduced3bodyCreator { isZorroSelected = zorro.isSelected(bc.globalBC()); if (isZorroSelected) { registry.fill(HIST("hEventCounterZorro"), 0.5); - triggeredCollisions[collision.globalIndex()] = true; + isTriggeredCollision[collision.globalIndex()] = true; } } // Event selection registry.fill(HIST("hEventCounter"), 0.5); - if (event_sel8_selection && !collision.sel8()) { + if (doSel8selection && !collision.sel8()) { continue; } registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm continue; } registry.fill(HIST("hEventCounter"), 2.5); @@ -340,22 +287,29 @@ struct reduced3bodyCreator { int lastCollisionID = -1; // collisionId of last analysed decay3body. Table is sorted. - // Creat reduced table + // get tracked cluster size info + fTrackedClSizeVector.clear(); + fTrackedClSizeVector.resize(decay3bodys.size(), 0); + for (const auto& tvtx3body : tracked3bodys) { + fTrackedClSizeVector[tvtx3body.decay3BodyId()] = tvtx3body.itsClsSize(); + } + + // Create reduced table for (const auto& d3body : decay3bodys) { auto collision = d3body.template collision_as(); - if (event_sel8_selection && !collision.sel8()) { + if (doSel8selection && !collision.sel8()) { continue; } - if (event_posZ_selection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm + if (doPosZselection && (collision.posZ() >= 10.0f || collision.posZ() <= -10.0f)) { // 10cm continue; } auto bc = collision.bc_as(); initCCDB(bc); if (cfgSkimmedProcessing && cfgOnlyKeepInterestedTrigger) { - if (triggeredCollisions[collision.globalIndex()] == false) { + if (isTriggeredCollision[collision.globalIndex()] == false) { continue; } } @@ -386,7 +340,7 @@ struct reduced3bodyCreator { // TOF PID of bachelor must be calcualted here // ---------------------------------------------- auto originalcol = daughter2.template collision_as(); - double tofNSigmaBach = bachelorTOFPID.GetTOFNSigma(daughter2, originalcol, collision); + double tofNSigmaBach = bachelorTOFPID.GetTOFNSigma(mRespParamsV3, daughter2, originalcol, collision); // ---------------------------------------------- // -------- save reduced track table with decay3body daughters ---------- @@ -398,7 +352,7 @@ struct reduced3bodyCreator { const auto trackStartIndex = reducedFullTracksPIDIU.lastIndex(); reducedDecay3Bodys(collisionIndex, trackStartIndex - 2, trackStartIndex - 1, trackStartIndex); - // -------- save reduced decay3body info table -------- + // -------- get decay3body info with KF -------- // get trackParCov daughters auto trackParCovPos = getTrackParCov(daughter0); auto trackParCovNeg = getTrackParCov(daughter1); @@ -413,23 +367,29 @@ struct reduced3bodyCreator { kfpPion = createKFParticleFromTrackParCov(trackParCovPos, daughter0.sign(), constants::physics::MassPionCharged); } kfpDeuteron = createKFParticleFromTrackParCov(trackParCovBach, daughter2.sign(), constants::physics::MassDeuteron); - // fit 3body vertex + // fit 3body vertex and caclulate radius, phi, z position + float radius, phi, posZ; KFParticle KFHt; - fit3bodyVertex(kfpProton, kfpPion, kfpDeuteron, KFHt); - // calculate radius and phi - auto radius = std::sqrt(KFHt.GetX() * KFHt.GetX() + KFHt.GetY() * KFHt.GetY()); - float phi, sigma; - KFHt.GetPhi(phi, sigma); - // fill 3body info table - reduced3BodyInfo(radius, phi, KFHt.GetZ()); - - // -------- save dcaFitter secondary vertex info table -------- + if (fit3bodyVertex(kfpProton, kfpPion, kfpDeuteron, KFHt)) { + radius = std::hypot(KFHt.GetX(), KFHt.GetY()); + phi = std::atan2(KFHt.GetPx(), KFHt.GetPy()); + posZ = KFHt.GetZ(); + } else { + radius = -999.; + phi = -999.; + posZ = -999.; + } + + // -------- get decay3body info with DCA fitter -------- auto Track0 = getTrackParCov(daughter0); auto Track1 = getTrackParCov(daughter1); auto Track2 = getTrackParCov(daughter2); int n3bodyVtx = fitter3body.process(Track0, Track1, Track2); + float phiVtx, rVtx, zVtx; if (n3bodyVtx == 0) { // discard this pair - dcaFitterSVInfo(-999, -999, -999); + phiVtx = -999.; + rVtx = -999.; + zVtx = -999.; } else { const auto& vtxXYZ = fitter3body.getPCACandidate(); @@ -441,10 +401,13 @@ struct reduced3bodyCreator { propagatedTrack1.getPxPyPzGlo(p1); propagatedTrack2.getPxPyPzGlo(p2); std::array p3B = {p0[0] + p1[0] + p2[0], p0[1] + p1[1] + p2[1], p0[2] + p1[2] + p2[2]}; - float phiVtx = std::atan2(p3B[1], p3B[0]); - float rVtx = std::hypot(vtxXYZ[0], vtxXYZ[1]); - dcaFitterSVInfo(rVtx, phiVtx, vtxXYZ[2]); + phiVtx = std::atan2(p3B[1], p3B[0]); + rVtx = std::hypot(vtxXYZ[0], vtxXYZ[1]); + zVtx = vtxXYZ[2]; } + + // fill 3body info table (KF and DCA fitter info) + reduced3BodyInfo(radius, phi, posZ, rVtx, phiVtx, zVtx, fTrackedClSizeVector[d3body.globalIndex()]); } // end decay3body loop registry.fill(HIST("hEventCounter"), 3.5, reducedCollisions.lastIndex() + 1); @@ -458,6 +421,7 @@ struct reduced3bodyInitializer { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { + metadataInfo.initMetadata(cfgc); return WorkflowSpec{ adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc), diff --git a/PWGLF/TableProducer/Nuspex/threebodyKFTask.cxx b/PWGLF/TableProducer/Nuspex/threebodyKFTask.cxx deleted file mode 100644 index 1fed55805c2..00000000000 --- a/PWGLF/TableProducer/Nuspex/threebodyKFTask.cxx +++ /dev/null @@ -1,488 +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 Analysis task for KFVtx3BodyDatas (3body candidates reconstructed with KF) -/// \author Carolina Reetz --> partly copied from threebodyRecoTask.cxx -// ======================== - -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using std::array; - -using MCLabeledTracksIU = soa::Join; - -struct threebodyKFTask { - - Produces outputMCTable; - std::vector filledMothers; - std::vector isGoodCollision; - - // Configurables - Configurable bachelorPdgCode{"bachelorPdgCode", 1000010020, "pdgCode of bachelor daughter"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother"}; - - ConfigurableAxis m2PrPiBins{"m2PrPiBins", {60, 1., 3.3}, "Binning for m2(p,pi) axis"}; - ConfigurableAxis m2PiDeBins{"m2PiDeBins", {120, 4.0, 8.0}, "Binning for m2(pi,d) axis"}; - - // collision filter and preslice - Filter collisionFilter = (aod::evsel::sel8 == true && nabs(aod::collision::posZ) < 10.f); - Preslice perCollisionVtx3BodyDatas = o2::aod::vtx3body::collisionId; - - HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject}; - - void init(InitContext const&) - { - const AxisSpec axisM2PrPi{m2PrPiBins, "#it{m}^{2}(p,#pi^{-}) ((GeV/#it{c}^{2})^{2})"}; - const AxisSpec axisM2PiDe{m2PiDeBins, "#it{m}^{2}(#pi^{+},#bar{d}) ((GeV/#it{c}^{2})^{2})"}; - - registry.add("hCentFT0C", "hCentFT0C", HistType::kTH1F, {{100, 0.0f, 100.0f, "FT0C Centrality"}}); - - // mass spectrum of reco candidates - registry.add("hMassHypertriton", "Mass hypertriton", HistType::kTH1F, {{80, 2.96f, 3.04f, "#it{m}(p,#pi^{-},d) (GeV/#it{c}^{2})"}}); - registry.add("hMassAntiHypertriton", "Mass anti-hypertriton", HistType::kTH1F, {{80, 2.96f, 3.04f, "#it{m}(#bar{p},#pi^{+},#bar{d}) (GeV/#it{c}^{2})"}}); - // Dalitz diagrams of reco candidates - registry.add("hDalitzHypertriton", "Dalitz diagram", HistType::kTH2F, {axisM2PrPi, axisM2PiDe})->GetYaxis()->SetTitle("#it{m}^{2}(#pi^{-},d) ((GeV/#it{c}^{2})^{2})"); - registry.add("hDalitzAntiHypertriton", "Dalitz diagram", HistType::kTH2F, {axisM2PrPi, axisM2PiDe})->GetXaxis()->SetTitle("#it{m}^{2}(#bar{p},#pi^{+}) ((GeV/#it{c}^{2})^{2})"); - - // bachelor histgrams - registry.add("hAverageITSClusterSizeBachelor", "Average ITS cluster size bachelor track", HistType::kTH1F, {{15, 0.5, 15.5, "#langle ITS cluster size #rangle"}}); - registry.add("hdEdxBachelor", "TPC dE/dx bachelor track", HistType::kTH1F, {{200, 0.0f, 200.0f, "Average ITS cluster size"}}); - registry.add("hPIDTrackingBachelor", "Tracking PID bachelor track", HistType::kTH1F, {{20, 0.5, 20.5, "Tracking PID identifier"}}); - - // for gen information of reco candidates - auto LabelHist = registry.add("hLabelCounter", "Reco MC candidate counter", HistType::kTH1F, {{3, 0.0f, 3.0f}}); - LabelHist->GetXaxis()->SetBinLabel(1, "Total"); - LabelHist->GetXaxis()->SetBinLabel(2, "Have Same MotherTrack"); - LabelHist->GetXaxis()->SetBinLabel(3, "True H3L/Anti-H3L"); - registry.add("hTrueHypertritonMCPt", "pT gen. of reco. H3L", HistType::kTH1F, {{100, -10.0f, 10.0f, "#it{p}_{T} (GeV/#it{c})"}}); - registry.add("hTrueHypertritonMCMass", "mass gen. of reco. H3L", HistType::kTH1F, {{40, 2.96f, 3.04f, "#it{m}(p,#pi^{-},d) (GeV/#it{c}^{2})"}}); - registry.add("hTrueHypMassWithMuReco", "mass gen. of reco. H3L", HistType::kTH1F, {{40, 2.96f, 3.04f, "#it{m}(p,#pi^{-},d) (GeV/#it{c}^{2})"}}); - registry.add("hTrueHypertritonMCCTau", "#it{c}#tau gen. of reco. H3L", HistType::kTH1F, {{50, 0.0f, 50.0f, "#it{c}#tau(cm)"}}); - registry.add("hTrueHypertritonMCMassPrPi", "inv. mass gen. of reco. V0 pair (H3L)", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{m}(p,#pi^{-}) (GeV/#it{c}^{2})"}}); - - // for gen information of non reco candidates - registry.add("hTrueHypertritonMCMassPrPi_nonReco", "inv. mass gen. of non-reco. V0 pair (H3L)", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{m}(p,#pi^{-}) (GeV/#it{c}^{2})"}}); - registry.add("hTrueHypertritonMCPtPion_nonReco", "Pion #it{p}_{T} gen. of non-reco. H3L", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{p}_{T}(#pi) (GeV/#it{c})"}}); - registry.add("hTrueHypertritonMCPtProton_nonReco", "Proton #it{p}_{T} gen. of non-reco. H3L", HistType::kTH1F, {{100, 0.0f, 6.0f, "#it{p}_{T}(p) (GeV/#it{c})"}}); - } - - // helper function to check if a mother track is a true H3L/Anti-H3L - template - int checkH3LTruth(MCTrack3B const& mcParticlePr, MCTrack3B const& mcParticlePi, MCTrack3B const& mcParticleDe, bool& isMuonReco) - { - if (abs(mcParticlePr.pdgCode()) != 2212 || abs(mcParticleDe.pdgCode()) != 1000010020) { - 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()) == 1010010030) { - prDeMomID = motherPr.globalIndex(); - break; - } - } - } - if (prDeMomID == -1) { - return -1; - } - if (std::abs(mcParticlePi.pdgCode()) != 211 && std::abs(mcParticlePi.pdgCode()) != 13) { - return -1; - } - // 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()) == 13) { - for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { - if (std::abs(motherPi.pdgCode()) == 211) { - mcParticlePiTmp = motherPi; - isMuonReco = true; - break; - } - } - } - // now loop over the pion mother - for (const auto& motherPi : mcParticlePiTmp.template mothers_as()) { - if (motherPi.globalIndex() == prDeMomID) { - return motherPi.globalIndex(); - } - } - return -1; - } - - template - void fillQAPlots(TCand const& vtx3body) - { - // Mass plot - if (vtx3body.track2sign() > 0) { // hypertriton - registry.fill(HIST("hMassHypertriton"), vtx3body.mass()); - } else if (vtx3body.track2sign() < 0) { // anti-hypertriton - registry.fill(HIST("hMassAntiHypertriton"), vtx3body.mass()); - } - - // Dalitz plot - auto m2prpi = RecoDecay::m2(array{array{vtx3body.pxtrack0(), vtx3body.pytrack0(), vtx3body.pztrack0()}, array{vtx3body.pxtrack1(), vtx3body.pytrack1(), vtx3body.pztrack1()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - auto m2pide = RecoDecay::m2(array{array{vtx3body.pxtrack1(), vtx3body.pytrack1(), vtx3body.pztrack1()}, array{vtx3body.pxtrack2(), vtx3body.pytrack2(), vtx3body.pztrack2()}}, array{o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - if (std::abs(vtx3body.mass() - o2::constants::physics::MassHyperTriton) <= 0.005) { - if (vtx3body.track2sign() > 0) { // hypertriton - registry.fill(HIST("hDalitzHypertriton"), m2prpi, m2pide); - } else if (vtx3body.track2sign() < 0) { // anti-hypertriton - registry.fill(HIST("hDalitzAntiHypertriton"), m2prpi, m2pide); - } - } - - // ITS cluster sizes - registry.fill(HIST("hAverageITSClusterSizeBachelor"), vtx3body.itsclussizedeuteron()); - registry.fill(HIST("hdEdxBachelor"), vtx3body.tpcdedxdeuteron()); - registry.fill(HIST("hPIDTrackingBachelor"), vtx3body.pidtrackingdeuteron()); - } - - //------------------------------------------------------------------ - // process real data analysis - void processData(soa::Filtered>::iterator const& collision, - aod::KFVtx3BodyDatas const& vtx3bodydatas) - { - registry.fill(HIST("hCentFT0C"), collision.centFT0C()); - - for (auto& vtx3bodydata : vtx3bodydatas) { - // QA histograms - fillQAPlots(vtx3bodydata); - } - } - PROCESS_SWITCH(threebodyKFTask, processData, "Data analysis", true); - - //------------------------------------------------------------------ - // process mc analysis - void processMC(soa::Join const& collisions, - aod::KFVtx3BodyDatas const& vtx3bodydatas, - aod::McParticles const& particlesMC, - MCLabeledTracksIU const&, - aod::McCollisions const& mcCollisions) - { - filledMothers.clear(); - isGoodCollision.resize(mcCollisions.size(), false); - - // loop over collisions - for (const auto& collision : collisions) { - // event selection - if (!collision.sel8() || std::abs(collision.posZ()) > 10.f) { - continue; - } - // reco collision survived event selection filter --> fill value for MC collision if collision is "true" MC collision - if (collision.mcCollisionId() >= 0) { - isGoodCollision[collision.mcCollisionId()] = true; - } - - // fill MC table with reco MC candidate information and gen information if matched to MC particle - auto Decay3BodyTable_thisCollision = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - for (auto& vtx3bodydata : Decay3BodyTable_thisCollision) { - registry.fill(HIST("hLabelCounter"), 0.5); - - // fill QA histograms for all reco candidates - fillQAPlots(vtx3bodydata); - - auto track0 = vtx3bodydata.track0_as(); - auto track1 = vtx3bodydata.track1_as(); - auto track2 = vtx3bodydata.track2_as(); - - if (!track0.has_mcParticle() || !track1.has_mcParticle() || !track2.has_mcParticle()) { - continue; - } - - auto mcTrack0 = track0.mcParticle_as(); - auto mcTrack1 = track1.mcParticle_as(); - auto mcTrack2 = track2.mcParticle_as(); - - float genPosPt = mcTrack0.pt(); - float genPosP = mcTrack0.p(); - int daughter0PDGcode = mcTrack0.pdgCode(); - float genNegPt = mcTrack1.pt(); - float genNegP = mcTrack1.p(); - int daughter1PDGcode = mcTrack1.pdgCode(); - float genBachPt = mcTrack2.pt(); - float genBachP = mcTrack2.p(); - int daughter2PDGcode = mcTrack2.pdgCode(); - bool isBachPrimary = mcTrack2.isPhysicalPrimary(); - - double MClifetime = -1.; - bool isTrueH3L = false; - bool isTrueAntiH3L = false; - float genPhi = -1.; - float genEta = -1.; - float genRap = -1.; - float genP = -1.; - float genPt = -1.; - std::array genDecVtx{-1.f}; - bool isMuonReco = false; - auto& mcTrackPr = vtx3bodydata.sign() > 0 ? mcTrack0 : mcTrack1; - auto& mcTrackPi = vtx3bodydata.sign() > 0 ? mcTrack1 : mcTrack0; - auto& mcTrackDe = mcTrack2; - int motherID = checkH3LTruth(mcTrackPr, mcTrackPi, mcTrackDe, isMuonReco); - if (motherID > 0) { - auto mcTrackHyp = particlesMC.rawIteratorAt(motherID); - genPhi = mcTrackHyp.phi(); - genEta = mcTrackHyp.eta(); - genPt = mcTrackHyp.pt(); - int chargeFactor = mcTrackHyp.pdgCode() > 0 ? 1 : -1; - isTrueH3L = chargeFactor > 0; - isTrueAntiH3L = chargeFactor < 0; - MClifetime = RecoDecay::sqrtSumOfSquares(mcTrackPr.vx() - mcTrackHyp.vx(), mcTrackPr.vy() - mcTrackHyp.vy(), mcTrackPr.vz() - mcTrackHyp.vz()) * o2::constants::physics::MassHyperTriton / mcTrackHyp.p(); - double MCMass = RecoDecay::m(array{array{mcTrackPr.px(), mcTrackPr.py(), mcTrackPr.pz()}, array{mcTrackPi.px(), mcTrackPi.py(), mcTrackPi.pz()}, array{mcTrackDe.px(), mcTrackDe.py(), mcTrackDe.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - float MCmassPrPi = RecoDecay::m(array{array{mcTrackPr.px(), mcTrackPr.py(), mcTrackPr.pz()}, array{mcTrackPi.px(), mcTrackPi.py(), mcTrackPi.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - registry.fill(HIST("hLabelCounter"), 2.5); - registry.fill(HIST("hTrueHypertritonMCPt"), mcTrackHyp.pt() * chargeFactor); - registry.fill(HIST("hTrueHypertritonMCCTau"), MClifetime); - registry.fill(HIST("hTrueHypertritonMCMass"), MCMass); - registry.fill(HIST("hTrueHypertritonMCMassPrPi"), MCmassPrPi); - if (isMuonReco) { - registry.fill(HIST("hTrueHypMassWithMuReco"), MCMass); - } - filledMothers.push_back(mcTrackHyp.globalIndex()); - } - outputMCTable( // filled for each reconstructed candidate (in KFVtx3BodyDatas) - vtx3bodydata.mass(), - vtx3bodydata.x(), vtx3bodydata.y(), vtx3bodydata.z(), - vtx3bodydata.xerr(), vtx3bodydata.yerr(), vtx3bodydata.zerr(), - vtx3bodydata.px(), vtx3bodydata.py(), vtx3bodydata.pz(), vtx3bodydata.pt(), - vtx3bodydata.pxerr(), vtx3bodydata.pyerr(), vtx3bodydata.pzerr(), vtx3bodydata.pterr(), - vtx3bodydata.sign(), - vtx3bodydata.dcavtxtopvkf(), vtx3bodydata.dcaxyvtxtopvkf(), - vtx3bodydata.vtxcospakf(), vtx3bodydata.vtxcosxypakf(), - vtx3bodydata.vtxcospakftopo(), vtx3bodydata.vtxcosxypakftopo(), - vtx3bodydata.decaylkf(), vtx3bodydata.decaylxykf(), vtx3bodydata.decayldeltal(), - vtx3bodydata.chi2geondf(), vtx3bodydata.chi2topondf(), - vtx3bodydata.ctaukftopo(), - vtx3bodydata.trackedclsize(), - vtx3bodydata.massv0(), vtx3bodydata.chi2massv0(), - vtx3bodydata.cospav0(), - vtx3bodydata.pxtrack0(), vtx3bodydata.pytrack0(), vtx3bodydata.pztrack0(), // proton - vtx3bodydata.pxtrack1(), vtx3bodydata.pytrack1(), vtx3bodydata.pztrack1(), // pion - vtx3bodydata.pxtrack2(), vtx3bodydata.pytrack2(), vtx3bodydata.pztrack2(), // deuteron - vtx3bodydata.tpcinnerparamtrack0(), vtx3bodydata.tpcinnerparamtrack1(), vtx3bodydata.tpcinnerparamtrack2(), // proton, pion, deuteron - vtx3bodydata.tpcncltrack0(), vtx3bodydata.tpcncltrack1(), vtx3bodydata.tpcncltrack1(), // proton, pion, deuteron - vtx3bodydata.tpcchi2ncldeuteron(), - vtx3bodydata.deltaphideuteron(), vtx3bodydata.deltaphiproton(), - vtx3bodydata.dcatrack0topvkf(), vtx3bodydata.dcatrack1topvkf(), vtx3bodydata.dcatrack2topvkf(), // proton, pion, deuteron - vtx3bodydata.dcaxytrack0topvkf(), vtx3bodydata.dcaxytrack1topvkf(), vtx3bodydata.dcaxytrack2topvkf(), // proton, pion, deuteron - vtx3bodydata.dcaxytrack0tosvkf(), vtx3bodydata.dcaxytrack1tosvkf(), vtx3bodydata.dcaxytrack2tosvkf(), // proton, pion, deuteron - vtx3bodydata.dcatrack0totrack1kf(), vtx3bodydata.dcatrack0totrack2kf(), vtx3bodydata.dcatrack1totrack2kf(), - vtx3bodydata.dcavtxdaughterskf(), - vtx3bodydata.dcaxytrackpostopv(), vtx3bodydata.dcaxytracknegtopv(), vtx3bodydata.dcaxytrackbachtopv(), - vtx3bodydata.dcatrackpostopv(), vtx3bodydata.dcatracknegtopv(), vtx3bodydata.dcatrackbachtopv(), - vtx3bodydata.track0sign(), vtx3bodydata.track1sign(), vtx3bodydata.track2sign(), // proton, pion, deuteron - vtx3bodydata.tpcnsigmaproton(), vtx3bodydata.tpcnsigmapion(), vtx3bodydata.tpcnsigmadeuteron(), vtx3bodydata.tpcnsigmapionbach(), - vtx3bodydata.tpcdedxproton(), vtx3bodydata.tpcdedxpion(), vtx3bodydata.tpcdedxdeuteron(), - vtx3bodydata.tofnsigmadeuteron(), - vtx3bodydata.itsclussizedeuteron(), - vtx3bodydata.pidtrackingdeuteron(), - // MC info (-1 if not matched to MC particle) - genP, - genPt, - genDecVtx[0], genDecVtx[1], genDecVtx[2], - MClifetime, - genPhi, - genEta, - genRap, - genPosP, genPosPt, genNegP, genNegPt, genBachP, genBachPt, - isTrueH3L, isTrueAntiH3L, - daughter0PDGcode, daughter1PDGcode, daughter2PDGcode, isBachPrimary, - true, // is reconstructed - true); // reco event passed event selection - } // end vtx3bodydatas loop - } // end collision loop - - // generated MC particle analysis - // fill MC table with gen information for all generated but not reconstructed particles - for (auto& mcparticle : particlesMC) { - - double genMCmassPrPi = -1.; - bool isTrueGenH3L = false; - bool isTrueGenAntiH3L = false; - float genPBach = -1.; - float genPtBach = -1.; - float genPPos = -1.; - float genPtPos = -1.; - float genPNeg = -1.; - float genPtNeg = -1.; - int posDauPdgCode = -1; - int negDauPdgCode = -1; - int bachDauPdgCode = -1; - - // check if mcparticle was reconstructed and already filled in the table - if (std::find(filledMothers.begin(), filledMothers.end(), mcparticle.globalIndex()) != std::end(filledMothers)) { - continue; - } - - // set flag if corresponding reco collision survived event selection - bool survEvSel = isGoodCollision[mcparticle.mcCollisionId()]; - - // check if MC particle is hypertriton with 3-body decay - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - bool haveProton = false, havePion = false, haveBachelor = false; - bool haveAntiProton = false, haveAntiPion = false, haveAntiBachelor = false; - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) - haveProton = true; - if (mcparticleDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == 211) - havePion = true; - if (mcparticleDaughter.pdgCode() == -211) - haveAntiPion = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) - haveBachelor = true; - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) - haveAntiBachelor = true; - } - - // check if particle or anti-particle - if (haveProton && haveAntiPion && haveBachelor && mcparticle.pdgCode() > 0) { - isTrueGenH3L = true; - // get proton and pion daughter - std::array protonMom{0.f}; - std::array piMinusMom{0.f}; - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) { - protonMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPPos = mcparticleDaughter.p(); - genPtPos = mcparticleDaughter.pt(); - posDauPdgCode = mcparticleDaughter.pdgCode(); - } else if (mcparticleDaughter.pdgCode() == -211) { - piMinusMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPNeg = mcparticleDaughter.p(); - genPtNeg = mcparticleDaughter.pt(); - negDauPdgCode = mcparticleDaughter.pdgCode(); - } - } - genMCmassPrPi = RecoDecay::m(array{protonMom, piMinusMom}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - registry.fill(HIST("hTrueHypertritonMCMassPrPi_nonReco"), genMCmassPrPi); - registry.fill(HIST("hTrueHypertritonMCPtProton_nonReco"), RecoDecay::sqrtSumOfSquares(protonMom[0], protonMom[1])); - registry.fill(HIST("hTrueHypertritonMCPtPion_nonReco"), RecoDecay::sqrtSumOfSquares(piMinusMom[0], piMinusMom[1])); - } else if (haveAntiProton && havePion && haveAntiBachelor && mcparticle.pdgCode() < 0) { - isTrueGenAntiH3L = true; - // get anti-proton and pion daughter - std::array antiProtonMom{0.f}; - std::array piPlusMom{0.f}; - for (auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == -2212) { - antiProtonMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPNeg = mcparticleDaughter.p(); - genPtNeg = mcparticleDaughter.pt(); - negDauPdgCode = mcparticleDaughter.pdgCode(); - } else if (mcparticleDaughter.pdgCode() == 211) { - piPlusMom = {mcparticleDaughter.px(), mcparticleDaughter.py(), mcparticleDaughter.pz()}; - genPPos = mcparticleDaughter.p(); - genPtPos = mcparticleDaughter.pt(); - posDauPdgCode = mcparticleDaughter.pdgCode(); - } - } - genMCmassPrPi = RecoDecay::m(array{antiProtonMom, piPlusMom}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); - registry.fill(HIST("hTrueHypertritonMCMassPrPi_nonReco"), genMCmassPrPi); - registry.fill(HIST("hTrueHypertritonMCPtProton_nonReco"), RecoDecay::sqrtSumOfSquares(antiProtonMom[0], antiProtonMom[1])); - registry.fill(HIST("hTrueHypertritonMCPtPion_nonReco"), RecoDecay::sqrtSumOfSquares(piPlusMom[0], piPlusMom[1])); - } else { - continue; // stop if particle is no true H3L or Anti-H3L - } - - // get gen decay vertex and calculate ctau - std::array genDecayVtx{0.f}; - for (auto& mcDaughter : mcparticle.daughters_as()) { - if (std::abs(mcDaughter.pdgCode()) == bachelorPdgCode) { - genDecayVtx = {mcDaughter.vx(), mcDaughter.vy(), mcDaughter.vz()}; - genPBach = mcDaughter.p(); - genPtBach = mcDaughter.pt(); - bachDauPdgCode = mcDaughter.pdgCode(); - } - } - double genMClifetime = RecoDecay::sqrtSumOfSquares(genDecayVtx[0] - mcparticle.vx(), genDecayVtx[1] - mcparticle.vy(), genDecayVtx[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - outputMCTable( // reco information (-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, - -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, - // gen information - mcparticle.p(), - mcparticle.pt(), - genDecayVtx[0], genDecayVtx[1], genDecayVtx[2], - genMClifetime, - mcparticle.phi(), - mcparticle.eta(), - mcparticle.y(), - genPPos, genPtPos, genPNeg, genPtNeg, genPBach, genPtBach, - isTrueGenH3L, isTrueGenAntiH3L, - posDauPdgCode, negDauPdgCode, bachDauPdgCode, - false, // isBachPrimary - false, // is reconstructed - survEvSel); - } // end mcparticles loop - } - PROCESS_SWITCH(threebodyKFTask, processMC, "MC analysis", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx b/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx deleted file mode 100644 index 36af287f95e..00000000000 --- a/PWGLF/TableProducer/Nuspex/threebodyRecoTask.cxx +++ /dev/null @@ -1,909 +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 threebodyRecoTask.cxx -/// \brief Analysis task for 3-body decay process (now mainly for hypertriton) -/// \author Yuanzhe Wang - -#include -#include -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "PWGLF/DataModel/Reduced3BodyTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" - -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using ReducedCols = soa::Join; -using FullTracksExtIU = soa::Join; -using MCLabeledTracksIU = soa::Join; - -std::vector triggerLabels = { - "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"}; - -struct Candidate3body { - // Index - int mcmotherId; - int track0Id; - int track1Id; - int track2Id; - // Collision - float colCentFT0C; - // sv and candidate - bool isMatter; - float invmass; - float ct; - float cosPA; - float dcadaughters; - float dcacandtopv; - float vtxradius; - // daughter tracks - TLorentzVector lcand; - TLorentzVector lproton; - TLorentzVector lpion; - TLorentzVector lbachelor; - uint8_t dautpcNclusters[3]; // 0 - proton, 1 - pion, 2 - bachelor - uint32_t dauitsclussize[3]; // 0 - proton, 1 - pion, 2 - bachelor - float daudcaxytopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float daudcatopv[3]; // 0 - proton, 1 - pion, 2 - bachelor - float dautpcNsigma[3]; // 0 - proton, 1 - pion, 2 - bachelor - float dauinnermostR[3]; // 0 - proton, 1 - pion, 2 - bachelor !!! TracksIU required !!! - float bachelortofNsigma; - bool isBachPrimary = false; - // MC infomartion - TLorentzVector lgencand = {0, 0, 0, 0}; - float genct = -1; - float genrapidity = -999; - bool isSignal = false; - bool isReco = false; - int pdgCode = -1; - bool survivedEventSelection = false; -}; - -struct ThreebodyRecoTask { - - Produces outputDataTable; - Produces outputMCTable; - std::vector candidates3body; - std::vector filledMothers; - std::vector isGoodCollision; - - Service ccdb; - Zorro zorro; - OutputObj zorroSummary{"zorroSummary"}; - - //------------------------------------------------------------------ - PresliceUnsorted perCollisionVtx3BodyDatas = o2::aod::vtx3body::collisionId; - - // Configurable for trigger selection - 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"}; - Configurable cfgOnlyKeepInterestedTrigger{"cfgOnlyKeepInterestedTrigger", false, "Flag to keep only interested trigger"}; - Configurable bcTolerance{"bcTolerance", 100, "Tolerance for BC in Zorro"}; - // Configuration to enable like-sign analysis - Configurable cfgLikeSignAnalysis{"cfgLikeSignAnalysis", false, "Enable like-sign analysis"}; - // Selection criteria - Configurable vtxcospa{"vtxcospa", 0.99, "Vtx CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; // loose cut - Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; - Configurable etacut{"etacut", 0.9, "etacut"}; - Configurable rapiditycut{"rapiditycut", 1, "rapiditycut"}; - Configurable tofPIDNSigmaMin{"tofPIDNSigmaMin", -5, "tofPIDNSigmaMin"}; - Configurable tofPIDNSigmaMax{"tofPIDNSigmaMax", 5, "tofPIDNSigmaMax"}; - Configurable tpcPIDNSigmaCut{"tpcPIDNSigmaCut", 5, "tpcPIDNSigmaCut"}; - Configurable eventSel8Cut{"eventSel8Cut", true, "flag to enable event sel8 selection"}; - Configurable mcEventCut{"mcEventCut", true, "flag to enable mc event selection: kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable eventPosZCut{"eventPosZCut", true, "flag to enable event posZ selection"}; - Configurable lifetimecut{"lifetimecut", 40., "lifetimecut"}; // ct - Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; - Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; - Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; - Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; - Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; - Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; - Configurable minDeuteronPUseTOF{"minDeuteronPUseTOF", 1, "minDeuteronPt Enable TOF PID"}; - Configurable h3LMassLowerlimit{"h3LMassLowerlimit", 2.96, "Hypertriton mass lower limit"}; - Configurable h3LMassUpperlimit{"h3LMassUpperlimit", 3.04, "Hypertriton mass upper limit"}; - Configurable mintpcNClsproton{"mintpcNClsproton", 90, "min tpc Nclusters for proton"}; - Configurable mintpcNClspion{"mintpcNClspion", 70, "min tpc Nclusters for pion"}; - Configurable mintpcNClsdeuteron{"mintpcNClsdeuteron", 100, "min tpc Nclusters for deuteron"}; - - Configurable mcsigma{"mcsigma", 0.0015, "sigma of mc invariant mass fit"}; // obtained from MC - Configurable bachelorPdgCode{"bachelorPdgCode", 1000010020, "pdgCode of bachelor daughter"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother track"}; - - // 3sigma region for Dalitz plot - float lowersignallimit = o2::constants::physics::MassHyperTriton - 3 * mcsigma; - float uppersignallimit = o2::constants::physics::MassHyperTriton + 3 * mcsigma; - - // CCDB options - 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 pidPath{"pidPath", "", "Path to the PID response object"}; - - // Zorro counting - Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; - - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hCentFT0C", "hCentFT0C", {HistType::kTH1F, {{100, 0.0f, 100.0f, "FT0C Centrality"}}}}, - {"hCandidatesCounter", "hCandidatesCounter", {HistType::kTH1F, {{12, 0.0f, 12.0f}}}}, - {"hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f}}}}, - {"hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f}}}}, - {"hMassHypertritonTotal", "hMassHypertritonTotal", {HistType::kTH1F, {{300, 2.9f, 3.2f}}}}, - {"hTOFPIDDeuteron", "hTOFPIDDeuteron", {HistType::kTH1F, {{2000, -100.0f, 100.0f}}}}, - {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hProtonTPCVsPt", "hProtonTPCVsPt", {HistType::kTH2F, {{50, 0.0f, 5.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hPionTPCVsPt", "hPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTPCVsPt", "hDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {240, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTOFVsPBeforeTOFCut", "hDeuteronTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAtferTOFCut", "hDeuteronTOFVsPAtferTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - - {"hDalitz", "hDalitz", {HistType::kTH2F, {{120, 7.85, 8.45, "M^{2}(dp) (GeV^{2}/c^{4})"}, {60, 1.1, 1.4, "M^{2}(p#pi) (GeV^{2}/c^{4})"}}}}, - }, - }; - - //------------------------------------------------------------------ - // Fill stats histograms - enum Vtxstep { kCandAll = 0, - kCandDauEta, - kCandDauPt, - kCandTPCNcls, - kCandTPCPID, - kCandTOFPID, - kCandDcaToPV, - kCandRapidity, - kCandct, - kCandCosPA, - kCandDcaDau, - kCandInvMass, - kNCandSteps }; - - struct { - std::array candstats; - std::array truecandstats; - } statisticsRegistry; - - void resetHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - statisticsRegistry.candstats[ii] = 0; - statisticsRegistry.truecandstats[ii] = 0; - } - } - void fillCandCounter(int kn, bool istrue = false) - { - statisticsRegistry.candstats[kn]++; - if (istrue) { - statisticsRegistry.truecandstats[kn]++; - } - } - void fillHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - registry.fill(HIST("hCandidatesCounter"), ii, statisticsRegistry.candstats[ii]); - if (doprocessMC == true) { - registry.fill(HIST("hTrueHypertritonCounter"), ii, statisticsRegistry.truecandstats[ii]); - } - } - } - - int mRunNumber; - - void init(InitContext const&) - { - zorroSummary.setObject(zorro.getZorroSummary()); - - mRunNumber = 0; - - ccdb->setURL(ccdbUrl); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setFatalWhenNull(false); - - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(1, "total"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(2, "sel8"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(3, "vertexZ"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(4, "Zorro H3L 3body event"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(5, "has Candidate"); - - // Check for selection criteria !!! TracksIU required !!! - registry.add("hDiffRVtxProton", "hDiffRVtxProton", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of proton - registry.add("hDiffRVtxPion", "hDiffRVtxPion", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of pion - registry.add("hDiffRVtxDeuteron", "hDiffRVtxDeuteron", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of deuteron - registry.add("hDiffDaughterR", "hDiffDaughterR", HistType::kTH1F, {{10000, -100, 100}}); // difference between minR of pion&proton and R of deuteron(bachelor) - - // Check triggers - auto hEventTriggerCount = registry.add("hEventTriggerCount", "hEventTriggerCount", HistType::kTH1F, {{static_cast(triggerLabels.size() + 1), 0, static_cast(triggerLabels.size() + 1)}}); - for (size_t i = 0; i < triggerLabels.size(); i++) { - hEventTriggerCount->GetXaxis()->SetBinLabel(i + 1, triggerLabels[i].c_str()); - } - hEventTriggerCount->GetXaxis()->SetBinLabel(triggerLabels.size() + 1, "NoTrigger"); - - if (cfgLikeSignAnalysis) { - registry.add("hInvMassCorrectSign", "hInvMassCorrectSign", HistType::kTH1F, {{80, 2.96f, 3.04f}}); // check if there are contamination of possible signals which are caused by unexpected PID - } - - if (doprocessMC == true) { - registry.add("hTrueHypertritonCounter", "hTrueHypertritonCounter", HistType::kTH1F, {{12, 0.0f, 12.0f}}); - auto hGeneratedHypertritonCounter = registry.add("hGeneratedHypertritonCounter", "hGeneratedHypertritonCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(1, "Total"); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(2, "3-body decay"); - registry.add("hPtGeneratedHypertriton", "hPtGeneratedHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedHypertriton", "hctGeneratedHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedHypertriton", "hEtaGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedHypertriton", "hRapidityGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hPtGeneratedAntiHypertriton", "hPtGeneratedAntiHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedAntiHypertriton", "hctGeneratedAntiHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedAntiHypertriton", "hEtaGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedAntiHypertriton", "hRapidityGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - } - - TString candCounterbinLabel[kNCandSteps] = {"Total", "TrackEta", "DauPt", "TPCNcls", "TPCPID", "d TOFPID", "PionDcatoPV", "MomRapidity", "Lifetime", "VtxCosPA", "VtxDcaDau", "InvMass"}; - for (int i{0}; i < kNCandSteps; i++) { - registry.get(HIST("hCandidatesCounter"))->GetXaxis()->SetBinLabel(i + 1, candCounterbinLabel[i]); - if (doprocessMC == true) { - registry.get(HIST("hTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(i + 1, candCounterbinLabel[i]); - } - } - } - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - - if (cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); - zorro.populateHistRegistry(registry, bc.runNumber()); - } - - LOGF(info, "Initializing CCDB for run %d", bc.runNumber()); - mRunNumber = bc.runNumber(); - } - - //------------------------------------------------------------------ - // Check if the mcparticle is hypertriton which decays into 3 daughters - template - bool is3bodyDecayed(TMCParticle const& particle) - { - if (std::abs(particle.pdgCode()) != motherPdgCode) { - return false; - } - bool haveProton = false, havePion = false, haveBachelor = false; - bool haveAntiProton = false, haveAntiPion = false, haveAntiBachelor = false; - for (const auto& mcparticleDaughter : particle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == PDG_t::kProton) - haveProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kProtonBar) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kPiPlus) - havePion = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kPiMinus) - haveAntiPion = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) - haveBachelor = true; - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) - haveAntiBachelor = true; - } - if (haveProton && haveAntiPion && haveBachelor && particle.pdgCode() > 0) { - return true; - } else if (haveAntiProton && havePion && haveAntiBachelor && particle.pdgCode() < 0) { - return true; - } - return false; - } - - //------------------------------------------------------------------ - // Event Selection - template - bool eventSelection(TCollision const& collision) - { - auto bc = collision.template bc_as(); - initCCDB(bc); - registry.fill(HIST("hEventCounter"), 0.5); - - if (eventSel8Cut && !collision.sel8()) { - return false; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (eventPosZCut && std::abs(collision.posZ()) > 10.f) { // 10cm - return false; - } - registry.fill(HIST("hEventCounter"), 2.5); - registry.fill(HIST("hCentFT0C"), collision.centFT0C()); - - if (cfgSkimmedProcessing) { - bool zorroSelected = zorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting - if (zorroSelected) { - registry.fill(HIST("hEventCounter"), 3.5); - } else { - if (cfgOnlyKeepInterestedTrigger) { - return false; - } - } - } - - return true; - } - - //------------------------------------------------------------------ - // Fill candidate table - template - void fillCand(TCollisionTable const& collision, TCandTable const& candData, TTrackTable const& trackProton, TTrackTable const& trackPion, TTrackTable const& trackDeuteron, bool isMatter, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, bool isBachPrimary = false) - { - double cospa = candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()); - double ct = candData.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; - - Candidate3body cand3body; - cand3body.isMatter = isMatter; - if (isMatter == true) { - cand3body.lproton.SetXYZM(candData.pxtrack0(), candData.pytrack0(), candData.pztrack0(), o2::constants::physics::MassProton); - cand3body.lpion.SetXYZM(candData.pxtrack1(), candData.pytrack1(), candData.pztrack1(), o2::constants::physics::MassPionCharged); - } else { - cand3body.lproton.SetXYZM(candData.pxtrack1(), candData.pytrack1(), candData.pztrack1(), o2::constants::physics::MassPionCharged); - cand3body.lpion.SetXYZM(candData.pxtrack0(), candData.pytrack0(), candData.pztrack0(), o2::constants::physics::MassProton); - } - - cand3body.mcmotherId = lLabel; - cand3body.track0Id = candData.track0Id(); - cand3body.track1Id = candData.track1Id(); - cand3body.track2Id = candData.track2Id(); - cand3body.colCentFT0C = collision.centFT0C(); - cand3body.invmass = cand3body.isMatter ? candData.mHypertriton() : candData.mAntiHypertriton(); - cand3body.lcand.SetXYZM(candData.px(), candData.py(), candData.pz(), o2::constants::physics::MassHyperTriton); - cand3body.ct = ct; - cand3body.cosPA = cospa; - cand3body.dcadaughters = candData.dcaVtxdaughters(); - cand3body.dcacandtopv = candData.dcavtxtopv(collision.posX(), collision.posY(), collision.posZ()); - cand3body.vtxradius = candData.vtxradius(); - cand3body.lbachelor.SetXYZM(candData.pxtrack2(), candData.pytrack2(), candData.pztrack2(), o2::constants::physics::MassDeuteron); - cand3body.dautpcNclusters[0] = trackProton.tpcNClsFound(); - cand3body.dautpcNclusters[1] = trackPion.tpcNClsFound(); - cand3body.dautpcNclusters[2] = trackDeuteron.tpcNClsFound(); - cand3body.dauitsclussize[0] = trackProton.itsClusterSizes(); - cand3body.dauitsclussize[1] = trackPion.itsClusterSizes(); - cand3body.dauitsclussize[2] = trackDeuteron.itsClusterSizes(); - cand3body.dautpcNsigma[0] = trackProton.tpcNSigmaPr(); - cand3body.dautpcNsigma[1] = trackPion.tpcNSigmaPi(); - cand3body.dautpcNsigma[2] = trackDeuteron.tpcNSigmaDe(); - cand3body.daudcaxytopv[0] = cand3body.isMatter ? candData.dcaXYtrack0topv() : candData.dcaXYtrack1topv(); - cand3body.daudcaxytopv[1] = cand3body.isMatter ? candData.dcaXYtrack1topv() : candData.dcaXYtrack0topv(); - cand3body.daudcaxytopv[2] = candData.dcaXYtrack2topv(); - cand3body.daudcatopv[0] = cand3body.isMatter ? candData.dcatrack0topv() : candData.dcatrack1topv(); - cand3body.daudcatopv[1] = cand3body.isMatter ? candData.dcatrack1topv() : candData.dcatrack0topv(); - cand3body.daudcatopv[2] = candData.dcatrack2topv(); - cand3body.dauinnermostR[0] = trackProton.x(); - cand3body.dauinnermostR[1] = trackPion.x(); - cand3body.dauinnermostR[2] = trackDeuteron.x(); - - cand3body.bachelortofNsigma = candData.tofNSigmaBachDe(); - cand3body.isBachPrimary = isBachPrimary; - if (isTrueCand) { - cand3body.mcmotherId = lLabel; - cand3body.lgencand = lmother; - cand3body.genct = mcLifetime; - cand3body.genrapidity = lmother.Rapidity(); - cand3body.isSignal = true; - cand3body.isReco = true; - cand3body.pdgCode = cand3body.isMatter ? motherPdgCode : -motherPdgCode; - cand3body.survivedEventSelection = true; - filledMothers.push_back(lLabel); - } - - candidates3body.push_back(cand3body); - - registry.fill(HIST("hProtonTPCBB"), trackProton.sign() * trackProton.p(), trackProton.tpcSignal()); - registry.fill(HIST("hPionTPCBB"), trackPion.sign() * trackPion.p(), trackPion.tpcSignal()); - registry.fill(HIST("hDeuteronTPCBB"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tpcSignal()); - registry.fill(HIST("hProtonTPCVsPt"), trackProton.pt(), trackProton.tpcNSigmaPr()); - registry.fill(HIST("hPionTPCVsPt"), trackProton.pt(), trackPion.tpcNSigmaPi()); - registry.fill(HIST("hDeuteronTPCVsPt"), trackDeuteron.pt(), trackDeuteron.tpcNSigmaDe()); - registry.fill(HIST("hTOFPIDDeuteron"), candData.tofNSigmaBachDe()); - registry.fill(HIST("hDiffRVtxProton"), trackProton.x() - candData.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), trackPion.x() - candData.vtxradius()); - registry.fill(HIST("hDiffRVtxDeuteron"), trackDeuteron.x() - candData.vtxradius()); - float diffTrackR = trackDeuteron.x() - std::min(trackProton.x(), trackPion.x()); - registry.fill(HIST("hDiffDaughterR"), diffTrackR); - } - - //------------------------------------------------------------------ - // Selections for candidates - template - bool selectCand(TCollisionTable const& collision, TCandTable const& candData, TTrackTable const& trackProton, TTrackTable const& trackPion, TTrackTable const& trackDeuteron, bool isMatter, bool isTrueCand = false) - { - fillCandCounter(kCandAll, isTrueCand); - - // Selection on daughters - if (std::abs(trackProton.eta()) > etacut || std::abs(trackPion.eta()) > etacut || std::abs(trackDeuteron.eta()) > etacut) { - return false; - } - fillCandCounter(kCandDauEta, isTrueCand); - - if (trackProton.pt() < minProtonPt || trackProton.pt() > maxProtonPt || trackPion.pt() < minPionPt || trackPion.pt() > maxPionPt || trackDeuteron.pt() < minDeuteronPt || trackDeuteron.pt() > maxDeuteronPt) { - return false; - } - fillCandCounter(kCandDauPt, isTrueCand); - - if (trackProton.tpcNClsFound() < mintpcNClsproton || trackPion.tpcNClsFound() < mintpcNClspion || trackDeuteron.tpcNClsFound() < mintpcNClsdeuteron) { - return false; - } - fillCandCounter(kCandTPCNcls, isTrueCand); - - if (std::abs(trackProton.tpcNSigmaPr()) > tpcPIDNSigmaCut || std::abs(trackPion.tpcNSigmaPi()) > tpcPIDNSigmaCut || std::abs(trackDeuteron.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - return false; - } - fillCandCounter(kCandTPCPID, isTrueCand); - - registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - if ((candData.tofNSigmaBachDe() < tofPIDNSigmaMin || candData.tofNSigmaBachDe() > tofPIDNSigmaMax) && trackDeuteron.p() > minDeuteronPUseTOF) { - return false; - } - fillCandCounter(kCandTOFPID, isTrueCand); - registry.fill(HIST("hDeuteronTOFVsPAtferTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - - double dcapion = isMatter ? candData.dcatrack1topv() : candData.dcatrack0topv(); - if (std::abs(dcapion) < dcapiontopv) { - return false; - } - fillCandCounter(kCandDcaToPV, isTrueCand); - - // Selection on candidate hypertriton - if (std::abs(candData.yHypertriton()) > rapiditycut) { - return false; - } - fillCandCounter(kCandRapidity, isTrueCand); - - double ct = candData.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; - if (ct > lifetimecut) { - return false; - } - fillCandCounter(kCandct, isTrueCand); - - double cospa = candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()); - if (cospa < vtxcospa) { - return false; - } - fillCandCounter(kCandCosPA, isTrueCand); - - if (candData.dcaVtxdaughters() > dcavtxdau) { - return false; - } - fillCandCounter(kCandDcaDau, isTrueCand); - - if ((isMatter && candData.mHypertriton() > h3LMassLowerlimit && candData.mHypertriton() < h3LMassUpperlimit)) { - // Hypertriton - registry.fill(HIST("hMassHypertriton"), candData.mHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mHypertriton()); - if (candData.mHypertriton() > lowersignallimit && candData.mHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - } else if ((!isMatter && candData.mAntiHypertriton() > h3LMassLowerlimit && candData.mAntiHypertriton() < h3LMassUpperlimit)) { - // AntiHypertriton - registry.fill(HIST("hMassAntiHypertriton"), candData.mAntiHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mAntiHypertriton()); - if (candData.mAntiHypertriton() > lowersignallimit && candData.mAntiHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - } else { - return false; - } - fillCandCounter(kCandInvMass, isTrueCand); - - return true; - } - - //------------------------------------------------------------------ - // Analysis process for a single candidate - template - void candidateAnalysis(TCollisionTable const& collision, TCandTable const& candData, bool& ifHasCandidate, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, double isBachPrimary = false) - { - auto track0 = candData.template track0_as(); - auto track1 = candData.template track1_as(); - auto track2 = candData.template track2_as(); - - bool isMatter = track2.sign() > 0; // true if the candidate is hypertriton (p pi- d) - - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - ifHasCandidate = true; - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - } - } - - //------------------------------------------------------------------ - // Analysis process for like-sign candidates : (p pi- anti-d) or (anti-p pi+ d) - template - void likeSignAnalysis(TCollisionTable const& collision, TCandTable const& candData, bool& ifHasCandidate, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, double isBachPrimary = false) - { - auto track0 = candData.template track0_as(); - auto track1 = candData.template track1_as(); - auto track2 = candData.template track2_as(); - - bool isMatter = track2.sign() < 0; // true if seach for background consists of (p pi- anti-d) - - // Assume proton has an oppisite charge with deuteron - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - ifHasCandidate = true; - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - // QA for if signals have the possibility to be reconginzed as a like-sign background - if (isMatter) { - registry.fill(HIST("hInvMassCorrectSign"), candData.mHypertriton()); - } else { - registry.fill(HIST("hInvMassCorrectSign"), candData.mAntiHypertriton()); - } - } - } - - //------------------------------------------------------------------ - // Analysis process for reduced data - template - void reducedAnalysis(TCollisionTable const& collision, TCandTable const& candData, TTracks tracks, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, double isBachPrimary = false) - { - auto track0 = tracks.rawIteratorAt(candData.track0Id()); - auto track1 = tracks.rawIteratorAt(candData.track1Id()); - auto track2 = tracks.rawIteratorAt(candData.track2Id()); - - bool isMatter = track2.sign() > 0; // true if the candidate is hypertriton (p pi- d) - - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - } - } - - //------------------------------------------------------------------ - // Analysis process for reduced data with like-sign candidates - template - void reducedLikeSignAnalysis(TCollisionTable const& collision, TCandTable const& candData, TTracks tracks, bool isTrueCand = false, int lLabel = -1, TLorentzVector lmother = {0, 0, 0, 0}, double mcLifetime = -1, bool isBachPrimary = false) - { - auto track0 = tracks.rawIteratorAt(candData.track0Id()); - auto track1 = tracks.rawIteratorAt(candData.track1Id()); - auto track2 = tracks.rawIteratorAt(candData.track2Id()); - - bool isMatter = track2.sign() < 0; // true if seach for background consists of (p pi- anti-d) - - // Assume proton has an oppisite charge with deuteron - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (selectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand)) { - fillCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - // QA for if signals have the possibility to be reconginzed as a like-sign background - if (isMatter) { - registry.fill(HIST("hInvMassCorrectSign"), candData.mHypertriton()); - } else { - registry.fill(HIST("hInvMassCorrectSign"), candData.mAntiHypertriton()); - } - } - } - - //------------------------------------------------------------------ - void fillOutputDataTable(Candidate3body const& cand3body) - { - outputDataTable(cand3body.colCentFT0C, - cand3body.isMatter, cand3body.invmass, cand3body.lcand.P(), cand3body.lcand.Pt(), cand3body.ct, - cand3body.cosPA, cand3body.dcadaughters, cand3body.dcacandtopv, cand3body.vtxradius, - cand3body.lproton.Pt(), cand3body.lproton.Eta(), cand3body.lproton.Phi(), cand3body.dauinnermostR[0], - cand3body.lpion.Pt(), cand3body.lpion.Eta(), cand3body.lpion.Phi(), cand3body.dauinnermostR[1], - cand3body.lbachelor.Pt(), cand3body.lbachelor.Eta(), cand3body.lbachelor.Phi(), cand3body.dauinnermostR[2], - cand3body.dautpcNclusters[0], cand3body.dautpcNclusters[1], cand3body.dautpcNclusters[2], - cand3body.dauitsclussize[0], cand3body.dauitsclussize[1], cand3body.dauitsclussize[2], - cand3body.dautpcNsigma[0], cand3body.dautpcNsigma[1], cand3body.dautpcNsigma[2], cand3body.bachelortofNsigma, - cand3body.daudcaxytopv[0], cand3body.daudcaxytopv[1], cand3body.daudcaxytopv[2], - cand3body.daudcatopv[0], cand3body.daudcatopv[1], cand3body.daudcatopv[2]); - } - - //------------------------------------------------------------------ - // collect information for generated hypertriton (should be called after event selection) - void getGeneratedH3LInfo(aod::McParticles const& particlesMC) - { - for (const auto& mcparticle : particlesMC) { - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - registry.fill(HIST("hGeneratedHypertritonCounter"), 0.5); - - bool haveProton = false, havePionPlus = false, haveDeuteron = false; - bool haveAntiProton = false, havePionMinus = false, haveAntiDeuteron = false; - double mcLifetime = -1; - for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == PDG_t::kProton) - haveProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kProtonBar) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == PDG_t::kPiPlus) - havePionPlus = true; - if (mcparticleDaughter.pdgCode() == -PDG_t::kPiPlus) - havePionMinus = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) { - haveDeuteron = true; - mcLifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) { - haveAntiDeuteron = true; - mcLifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - } - if (haveProton && havePionMinus && haveDeuteron && mcparticle.pdgCode() == motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedHypertriton"), mcLifetime); - registry.fill(HIST("hEtaGeneratedHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedHypertriton"), mcparticle.y()); - } else if (haveAntiProton && havePionPlus && haveAntiDeuteron && mcparticle.pdgCode() == -motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedAntiHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedAntiHypertriton"), mcLifetime); - registry.fill(HIST("hEtaGeneratedAntiHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedAntiHypertriton"), mcparticle.y()); - } - } - } - - //------------------------------------------------------------------ - // process real data analysis - void processData(soa::Join const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, FullTracksExtIU const&, aod::BCsWithTimestamps const&) - { - for (const auto& collision : collisions) { - candidates3body.clear(); - - if (!eventSelection(collision)) { - continue; - } - - bool ifHasCandidate = false; - auto d3BodyCands = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - for (const auto& vtx : d3BodyCands) { - if (cfgLikeSignAnalysis) { - likeSignAnalysis(collision, vtx, ifHasCandidate); - } else { - candidateAnalysis(collision, vtx, ifHasCandidate); - } - } - - if (ifHasCandidate) { - auto bc = collision.bc_as(); - auto triggerSelection = zorro.getTriggerOfInterestResults(bc.globalBC(), bcTolerance); - for (size_t i = 0; i < triggerSelection.size(); i++) { - if (triggerSelection[i]) { - registry.fill(HIST("hEventTriggerCount"), i + 0.5); - } - } - if (zorro.isNotSelectedByAny(bc.globalBC(), bcTolerance)) { - registry.fill(HIST("hEventTriggerCount"), triggerLabels.size() + 0.5); - } - registry.fill(HIST("hEventCounter"), 4.5); - } - fillHistos(); - resetHistos(); - - for (const auto& cand3body : candidates3body) { - fillOutputDataTable(cand3body); - } - } - } - PROCESS_SWITCH(ThreebodyRecoTask, processData, "Real data reconstruction", true); - - //------------------------------------------------------------------ - // process reduced data analysis - void processReducedData(ReducedCols const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, aod::RedIUTracks const& tracks) - { - candidates3body.clear(); - - registry.fill(HIST("hEventCounter"), 0.5, collisions.size()); - - for (const auto& vtx : vtx3bodydatas) { - const auto& collision = collisions.iteratorAt(vtx.collisionId()); - if (cfgLikeSignAnalysis) { - reducedLikeSignAnalysis(collision, vtx, tracks); - } else { - reducedAnalysis(collision, vtx, tracks); - } - for (const auto& cand3body : candidates3body) { - fillOutputDataTable(cand3body); - } - candidates3body.clear(); - } - fillHistos(); - resetHistos(); - } - PROCESS_SWITCH(ThreebodyRecoTask, processReducedData, "Reduced data reconstruction", false); - - //------------------------------------------------------------------ - // process mc analysis - void processMC(soa::Join const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, aod::McParticles const& particlesMC, MCLabeledTracksIU const& /*tracks*/, aod::McCollisions const& mcCollisions) - { - filledMothers.clear(); - getGeneratedH3LInfo(particlesMC); - isGoodCollision.resize(mcCollisions.size(), false); - - for (const auto& collision : collisions) { - candidates3body.clear(); - registry.fill(HIST("hEventCounter"), 0.5); - if (mcEventCut && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (eventPosZCut && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - registry.fill(HIST("hEventCounter"), 2.5); - registry.fill(HIST("hCentFT0C"), collision.centFT0C()); - - if (collision.mcCollisionId() >= 0) { - isGoodCollision[collision.mcCollisionId()] = true; - } - - bool ifHasCandidate = false; - auto vtxsThisCol = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - - for (const auto& vtx : vtxsThisCol) { - bool isBachPrimary = false; - int lLabel = -1; - int lPDG = -1; - double mcLifetime = -1; - TLorentzVector lmother; - bool isTrueCand = false; - auto track0 = vtx.track0_as(); - auto track1 = vtx.track1_as(); - auto track2 = vtx.track2_as(); - if (track0.has_mcParticle() && track1.has_mcParticle() && track2.has_mcParticle()) { - auto lMCTrack0 = track0.mcParticle_as(); - auto lMCTrack1 = track1.mcParticle_as(); - auto lMCTrack2 = track2.mcParticle_as(); - - if (lMCTrack2.isPhysicalPrimary()) { - isBachPrimary = true; - } - - if (lMCTrack0.has_mothers() && lMCTrack1.has_mothers() && lMCTrack2.has_mothers()) { - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - lLabel = lMother0.globalIndex(); - lPDG = lMother0.pdgCode(); - if ((lPDG == motherPdgCode && lMCTrack0.pdgCode() == PDG_t::kProton && lMCTrack1.pdgCode() == PDG_t::kPiMinus && lMCTrack2.pdgCode() == bachelorPdgCode) || - (lPDG == -motherPdgCode && lMCTrack0.pdgCode() == PDG_t::kPiPlus && lMCTrack1.pdgCode() == PDG_t::kProtonBar && lMCTrack2.pdgCode() == -bachelorPdgCode)) { - isTrueCand = true; - mcLifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); - lmother.SetXYZM(lMother0.px(), lMother0.py(), lMother0.pz(), o2::constants::physics::MassHyperTriton); - } - } - } - } - } - } - } - - candidateAnalysis(collision, vtx, ifHasCandidate, isTrueCand, lLabel, lmother, mcLifetime, isBachPrimary); - } - - if (ifHasCandidate) - registry.fill(HIST("hEventCounter"), 4.5); - fillHistos(); - resetHistos(); - - for (const auto& cand3body : candidates3body) { - outputMCTable(cand3body.colCentFT0C, - cand3body.isMatter, cand3body.invmass, cand3body.lcand.P(), cand3body.lcand.Pt(), cand3body.ct, - cand3body.cosPA, cand3body.dcadaughters, cand3body.dcacandtopv, cand3body.vtxradius, - cand3body.lproton.Pt(), cand3body.lproton.Eta(), cand3body.lproton.Phi(), cand3body.dauinnermostR[0], - cand3body.lpion.Pt(), cand3body.lpion.Eta(), cand3body.lpion.Phi(), cand3body.dauinnermostR[1], - cand3body.lbachelor.Pt(), cand3body.lbachelor.Eta(), cand3body.lbachelor.Phi(), cand3body.dauinnermostR[2], - cand3body.dautpcNclusters[0], cand3body.dautpcNclusters[1], cand3body.dautpcNclusters[2], - cand3body.dauitsclussize[0], cand3body.dauitsclussize[1], cand3body.dauitsclussize[2], - cand3body.dautpcNsigma[0], cand3body.dautpcNsigma[1], cand3body.dautpcNsigma[2], cand3body.bachelortofNsigma, - cand3body.daudcaxytopv[0], cand3body.daudcaxytopv[1], cand3body.daudcaxytopv[2], - cand3body.daudcatopv[0], cand3body.daudcatopv[1], cand3body.daudcatopv[2], - cand3body.isBachPrimary, - cand3body.lgencand.P(), cand3body.lgencand.Pt(), cand3body.genct, cand3body.lgencand.Phi(), cand3body.lgencand.Eta(), cand3body.lgencand.Rapidity(), - cand3body.isSignal, cand3body.isReco, cand3body.pdgCode, cand3body.survivedEventSelection); - } - } - - // now we fill only the signal candidates that were not reconstructed - for (const auto& mcparticle : particlesMC) { - if (!is3bodyDecayed(mcparticle)) { - continue; - } - if (std::find(filledMothers.begin(), filledMothers.end(), mcparticle.globalIndex()) != std::end(filledMothers)) { - continue; - } - bool isSurEvSelection = isGoodCollision[mcparticle.mcCollisionId()]; - std::array posSV{0.f}; - for (const auto& mcDaughter : mcparticle.daughters_as()) { - if (std::abs(mcDaughter.pdgCode()) == bachelorPdgCode) { - posSV = {mcDaughter.vx(), mcDaughter.vy(), mcDaughter.vz()}; - } - } - double mcLifetime = RecoDecay::sqrtSumOfSquares(posSV[0] - mcparticle.vx(), posSV[1] - mcparticle.vy(), posSV[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - outputMCTable(-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, - false, - mcparticle.p(), mcparticle.pt(), mcLifetime, mcparticle.phi(), mcparticle.eta(), mcparticle.y(), - true, false, mcparticle.pdgCode(), isSurEvSelection); - } - } - PROCESS_SWITCH(ThreebodyRecoTask, processMC, "MC reconstruction", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx index a33295b6021..7fe17c42d4a 100644 --- a/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx +++ b/PWGLF/TableProducer/Nuspex/trHeAnalysis.cxx @@ -16,8 +16,11 @@ /// /// \author Matthias Herzer , Goethe University Frankfurt /// -#include -#include +#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/trackUtilities.h" @@ -26,17 +29,20 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.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 "PWGLF/DataModel/LFNucleiTables.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" #include "ReconstructionDataFormats/PID.h" #include "ReconstructionDataFormats/Track.h" + #include +#include +#include + namespace o2::aod { namespace h3_data @@ -60,6 +66,8 @@ 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, @@ -68,7 +76,7 @@ DECLARE_SOA_TABLE(H3Data, "AOD", "h3_data", h3_data::TPt, h3_data::TEta, h3_data::TSigmaZ, h3_data::TnTpcCluster, h3_data::TnItsCluster, h3_data::TTpcChi2NCl, h3_data::TItsChi2NCl, h3_data::TRigidity, - h3_data::TItsClusterSize); + h3_data::TItsClusterSize, h3_data::THasTof, h3_data::TDetectorMap); namespace he_data { DECLARE_SOA_COLUMN(TPt, tPt, float); @@ -90,6 +98,8 @@ 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, @@ -98,7 +108,7 @@ DECLARE_SOA_TABLE(HeData, "AOD", "he_data", he_data::TPt, he_data::TEta, he_data::TSigmaZ, he_data::TnTpcCluster, he_data::TnItsCluster, he_data::TTpcChi2NCl, he_data::TItsChi2NCl, he_data::TRigidity, - he_data::TItsClusterSize); + he_data::TItsClusterSize, he_data::THasTof, he_data::TDetectorMap); } // namespace o2::aod namespace { @@ -113,7 +123,7 @@ static const std::vector particleCharge{1, 2}; static const std::vector particleChargeFactor{2.3, 2.55}; static const std::vector betheBlochParNames{ "p0", "p1", "p2", "p3", "p4", "resolution"}; -constexpr float betheBlochDefault[nParticles][nBetheParams]{ +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, @@ -126,7 +136,8 @@ using TracksFull = soa::Join; + aod::TOFSignal, aod::TrackSelectionExtension, + o2::aod::EvTimeTOFFT0ForTrack>; class Particle { @@ -186,7 +197,10 @@ struct TrHeAnalysis { } 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"}; @@ -212,8 +226,11 @@ struct TrHeAnalysis { 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", 2.24f, "Minimum Tof mass H3"}; - Configurable cfgCutMaxTofMassH3{"cfgCutMaxTofMassH3", 3.32f, "Maximum TOF mass H3"}; + 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)"}; @@ -226,7 +243,7 @@ struct TrHeAnalysis { 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> cfgBetheBlochParams{"cfgBetheBlochParams", {BetheBlochDefault[0], nParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; void init(o2::framework::InitContext&) { @@ -338,6 +355,9 @@ struct TrHeAnalysis { 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; @@ -385,14 +405,18 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeH3 || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeH3) { - histos.fill(HIST("histogram/cuts"), 12); - 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; + } } - if (getMass(track) < cfgCutMinTofMassH3 || getMass(track) > cfgCutMaxTofMassH3) { - histos.fill(HIST("histogram/cuts"), 13); - 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) * track.sign(), @@ -419,10 +443,12 @@ struct TrHeAnalysis { 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); + tItsClusterSize, tHasTof, tDetectorMap); } } if (enableHe && heRapCut) { @@ -436,10 +462,12 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { - histos.fill(HIST("histogram/cuts"), 12); - 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(), @@ -466,10 +494,12 @@ struct TrHeAnalysis { 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); + tItsClusterSize, tHasTof, tDetectorMap); } } } @@ -495,6 +525,9 @@ struct TrHeAnalysis { 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; @@ -540,14 +573,18 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeH3 || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeH3) { - histos.fill(HIST("histogram/cuts"), 12); - 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 (getMass(track) < cfgCutMinTofMassH3 || getMass(track) > cfgCutMaxTofMassH3) { - histos.fill(HIST("histogram/cuts"), 13); - 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()), @@ -574,10 +611,12 @@ struct TrHeAnalysis { 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); + tItsClusterSize, tHasTof, tDetectorMap); } } if (enableHe && heRapCut) { @@ -590,10 +629,12 @@ struct TrHeAnalysis { histos.fill(HIST("histogram/cuts"), 7); continue; } - if (getMeanItsClsSize(track) / std::cosh(track.eta()) <= cfgCutMinItsClusterSizeHe || - getMeanItsClsSize(track) / std::cosh(track.eta()) >= cfgCutMaxItsClusterSizeHe) { - histos.fill(HIST("histogram/cuts"), 12); - 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(), @@ -620,10 +661,12 @@ struct TrHeAnalysis { 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); + tItsClusterSize, tHasTof, tDetectorMap); } } } @@ -663,12 +706,14 @@ struct TrHeAnalysis { 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) + if (clsSize) { n++; + } } return n > 0 ? static_cast(sum) / n : 0.f; } @@ -681,13 +726,35 @@ struct TrHeAnalysis { return hePID ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); } template - float getMass(T const& track) + float getMass(const T& track) { - const float beta = track.beta(); - const float rigidity = getRigidity(track); - float gamma = 1 / std::sqrt(1 - beta * beta); - float mass = (rigidity / std::sqrt(gamma * gamma - 1)); - return mass; + if (cfgMassMethod == 0) { + float m = track.mass(); + return m * m; + } + if (cfgMassMethod == 1) { + const float beta = track.beta(); + const float rigidity = getRigidity(track); + float gamma = 1.f / std::sqrt(1.f - beta * beta); + float mass = rigidity / 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(); + constexpr float CInCmPs = 2.99792458e-2f; + float length = track.length(); + 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); + return mass * mass; + } + return -1.f; + } + return -1.f; } }; diff --git a/PWGLF/TableProducer/QC/flowQC.cxx b/PWGLF/TableProducer/QC/flowQC.cxx index f5dfa06f9d7..9a120e1afe8 100644 --- a/PWGLF/TableProducer/QC/flowQC.cxx +++ b/PWGLF/TableProducer/QC/flowQC.cxx @@ -19,34 +19,32 @@ // o2-analysis-multiplicity-table, o2-analysis-ft0-corrected-table, o2-analysis-track-propagation, // o2-analysis-trackselection, o2-analysis-qvector-table, o2-analysis-lf-flow-qc -#include - -#include "Math/Vector4D.h" - -#include "CCDB/BasicCCDBManager.h" +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "Common/Core/EventPlaneHelper.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/EventSelection.h" -#include "Common/Core/EventPlaneHelper.h" -#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/Qvectors.h" +#include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" #include "DataFormatsParameters/GRPObject.h" #include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" - +#include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" -#include "Framework/ASoAHelpers.h" #include "Framework/HistogramRegistry.h" #include "Framework/runDataProcessing.h" +#include "Math/Vector4D.h" #include "TRandom3.h" +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -111,9 +109,11 @@ struct flowQC { int mRunNumber = 0; float mBz = 0.f; + Configurable cfgHarmonic{"cfgHarmonic", 2.f, "Harmonics for flow analysis"}; + // Flow analysis using CollWithEPandQvec = soa::Join::iterator; + aod::EvSels, aod::CentFT0As, aod::CentFT0Cs, aod::CentFT0Ms, aod::CentFV0As, aod::FT0Mults, aod::FV0Mults, aod::TPCMults, aod::EPCalibrationTables, aod::QvectorFT0CVecs, aod::QvectorFT0AVecs, aod::QvectorFT0MVecs, aod::QvectorFV0AVecs, aod::QvectorTPCallVecs, aod::QvectorTPCposVecs, aod::QvectorTPCnegVecs>::iterator; HistogramRegistry general{"general", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry flow_ep{"flow_ep", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -171,15 +171,15 @@ struct flowQC { const AxisSpec centAxis{cfgCentralityBins, fmt::format("{} percentile", (std::string)centDetectorNames[cfgCentralityEstimator])}; - const AxisSpec QxAxis{cfgQvecBins, "Q_{2,x}"}; - const AxisSpec QyAxis{cfgQvecBins, "Q_{2,y}"}; + const AxisSpec QxAxis{cfgQvecBins, Form("Q_{%.0f,x}", cfgHarmonic.value)}; + const AxisSpec QyAxis{cfgQvecBins, Form("Q_{%.0f,y}", cfgHarmonic.value)}; - const AxisSpec NormQxAxis{cfgQvecBins, "#frac{Q_{2,x}}{||#vec{Q_{2}}||}"}; - const AxisSpec NormQyAxis{cfgQvecBins, "#frac{Q_{2,y}}{||#vec{Q_{2}}||}"}; + const AxisSpec NormQxAxis{cfgQvecBins, Form("#frac{Q_{%.0f,x}}{||#vec{Q_{%.0f}}||}", cfgHarmonic.value, cfgHarmonic.value)}; + const AxisSpec NormQyAxis{cfgQvecBins, Form("#frac{Q_{%.0f,y}}{||#vec{Q_{%.0f}}||}", cfgHarmonic.value, cfgHarmonic.value)}; - const AxisSpec psiAxis{cfgPhiBins, "#psi_{2}"}; - const AxisSpec psiCompAxis{cfgPhiBins, "#psi_{2}^{EP} - #psi_{2}^{Qvec}"}; - const AxisSpec cosPsiCompAxis{cfgCosPhiBins, "cos[2(#psi_{2}^{EP} - #psi_{2}^{Qvec})]"}; + const AxisSpec psiAxis{cfgPhiBins, Form("#psi_{%.0f}", cfgHarmonic.value)}; + const AxisSpec psiCompAxis{cfgPhiBins, Form("#psi_{%.0f}^{EP} - #psi_{%.0f}^{Qvec}", cfgHarmonic.value, cfgHarmonic.value)}; + const AxisSpec cosPsiCompAxis{cfgCosPhiBins, Form("cos[2(#psi_{%.0f}^{EP} - #psi_{%.0f}^{Qvec})]", cfgHarmonic.value, cfgHarmonic.value)}; // z vertex histogram general.add("hRecVtxZData", "collision z position", HistType::kTH1F, {{200, -20., +20., "z position (cm)"}}); @@ -203,12 +203,12 @@ struct flowQC { hDeltaPsi[iMethod][iQvecDet][jQvecDet] = registry->add(Form("hDeltaPsi_%s_%s_%s", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH2F, {centAxis, {cfgDeltaPhiBins, Form("#psi_{%s} - #psi_{%s}", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str())}}); // Scalar-product histograms - auto spLabel = Form("#vec{Q}_{2}^{%s} #upoint #vec{Q}_{2}^{%s}", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str()); + auto spLabel = Form("#vec{Q}_{%.0f}^{%s} #upoint #vec{Q}_{%.0f}^{%s}", cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str()); hScalarProduct[iMethod][iQvecDet][jQvecDet] = registry->add(Form("hScalarProduct_%s_%s_%s", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH2F, {centAxis, {cfgQvecBins, spLabel}}); // Normalised scalar-product histograms - auto normSpLabel = Form("#frac{#vec{Q}_{2}^{%s} #upoint #vec{Q}_{2}^{%s}}{||#vec{Q}_{2}^{%s}|| ||#vec{Q}_{2}^{%s}||}", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str()); + auto normSpLabel = Form("#frac{#vec{Q}_{%.0f}^{%s} #upoint #vec{Q}_{%.0f}^{%s}}{||#vec{Q}_{%.0f}^{%s}|| ||#vec{Q}_{%.0f}^{%s}||}", cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[iQvecDet].c_str(), cfgHarmonic.value, qVecDetectorNames[jQvecDet].c_str()); hNormalisedScalarProduct[iMethod][iQvecDet][jQvecDet] = registry->add(Form("hNormalisedScalarProduct_%s_%s_%s", qVecDetectorNames[iQvecDet].c_str(), qVecDetectorNames[jQvecDet].c_str(), suffixes[iMethod].c_str()), "", HistType::kTH2F, {centAxis, {cfgQvecBins, normSpLabel}}); } @@ -261,52 +261,52 @@ struct flowQC { // EP method float QmodFT0A_EP = collision.qFT0A(); float psiFT0A_EP = collision.psiFT0A(); - float QxFT0A_EP = QmodFT0A_EP * std::cos(2 * psiFT0A_EP); - float QyFT0A_EP = QmodFT0A_EP * std::sin(2 * psiFT0A_EP); + float QxFT0A_EP = QmodFT0A_EP * std::cos(cfgHarmonic.value * psiFT0A_EP); + float QyFT0A_EP = QmodFT0A_EP * std::sin(cfgHarmonic.value * psiFT0A_EP); float QmodFT0C_EP = collision.qFT0C(); float psiFT0C_EP = collision.psiFT0C(); - float QxFT0C_EP = QmodFT0C_EP * std::cos(2 * psiFT0C_EP); - float QyFT0C_EP = QmodFT0C_EP * std::sin(2 * psiFT0C_EP); + float QxFT0C_EP = QmodFT0C_EP * std::cos(cfgHarmonic.value * psiFT0C_EP); + float QyFT0C_EP = QmodFT0C_EP * std::sin(cfgHarmonic.value * psiFT0C_EP); float QmodTPCl_EP = collision.qTPCL(); float psiTPCl_EP = collision.psiTPCL(); - float QxTPCl_EP = QmodTPCl_EP * std::cos(2 * psiTPCl_EP); - float QyTPCl_EP = QmodTPCl_EP * std::sin(2 * psiTPCl_EP); + float QxTPCl_EP = QmodTPCl_EP * std::cos(cfgHarmonic.value * psiTPCl_EP); + float QyTPCl_EP = QmodTPCl_EP * std::sin(cfgHarmonic.value * psiTPCl_EP); float QmodTPCr_EP = collision.qTPCR(); float psiTPCr_EP = collision.psiTPCR(); - float QxTPCr_EP = QmodTPCr_EP * std::cos(2 * psiTPCr_EP); - float QyTPCr_EP = QmodTPCr_EP * std::sin(2 * psiTPCr_EP); + float QxTPCr_EP = QmodTPCr_EP * std::cos(cfgHarmonic.value * psiTPCr_EP); + float QyTPCr_EP = QmodTPCr_EP * std::sin(cfgHarmonic.value * psiTPCr_EP); float QmodTPC_EP = collision.qTPC(); float psiTPC_EP = collision.psiTPC(); - float QxTPC_EP = QmodTPC_EP * std::cos(2 * psiTPC_EP); - float QyTPC_EP = QmodTPC_EP * std::sin(2 * psiTPC_EP); + float QxTPC_EP = QmodTPC_EP * std::cos(cfgHarmonic.value * psiTPC_EP); + float QyTPC_EP = QmodTPC_EP * std::sin(cfgHarmonic.value * psiTPC_EP); // Qvec method - float QxFT0A_Qvec = collision.qvecFT0ARe(); - float QyFT0A_Qvec = collision.qvecFT0AIm(); + float QxFT0A_Qvec = collision.qvecFT0AReVec()[cfgHarmonic.value - 2]; + float QyFT0A_Qvec = collision.qvecFT0AImVec()[cfgHarmonic.value - 2]; float QmodFT0A_Qvec = std::hypot(QxFT0A_Qvec, QyFT0A_Qvec); float psiFT0A_Qvec = computeEventPlane(QyFT0A_Qvec, QxFT0A_Qvec); - float QxFT0C_Qvec = collision.qvecFT0CRe(); - float QyFT0C_Qvec = collision.qvecFT0CIm(); + float QxFT0C_Qvec = collision.qvecFT0CReVec()[cfgHarmonic.value - 2]; + float QyFT0C_Qvec = collision.qvecFT0CImVec()[cfgHarmonic.value - 2]; float QmodFT0C_Qvec = std::hypot(QxFT0C_Qvec, QyFT0C_Qvec); float psiFT0C_Qvec = computeEventPlane(QyFT0C_Qvec, QxFT0C_Qvec); - float QxTPCl_Qvec = collision.qvecBNegRe(); - float QyTPCl_Qvec = collision.qvecBNegIm(); + float QxTPCl_Qvec = collision.qvecTPCnegReVec()[cfgHarmonic.value - 2]; + float QyTPCl_Qvec = collision.qvecTPCnegImVec()[cfgHarmonic.value - 2]; float QmodTPCl_Qvec = std::hypot(QxTPCl_Qvec, QyTPCl_Qvec); float psiTPCl_Qvec = computeEventPlane(QyTPCl_Qvec, QxTPCl_Qvec); - float QxTPCr_Qvec = collision.qvecBPosRe(); - float QyTPCr_Qvec = collision.qvecBPosIm(); + float QxTPCr_Qvec = collision.qvecTPCposReVec()[cfgHarmonic.value - 2]; + float QyTPCr_Qvec = collision.qvecTPCposImVec()[cfgHarmonic.value - 2]; float QmodTPCr_Qvec = std::hypot(QxTPCr_Qvec, QyTPCr_Qvec); float psiTPCr_Qvec = computeEventPlane(QyTPCr_Qvec, QxTPCr_Qvec); - float QxTPC_Qvec = collision.qvecBTotRe(); - float QyTPC_Qvec = collision.qvecBTotIm(); + float QxTPC_Qvec = collision.qvecTPCallReVec()[cfgHarmonic.value - 2]; + float QyTPC_Qvec = collision.qvecTPCallImVec()[cfgHarmonic.value - 2]; float QmodTPC_Qvec = std::hypot(QxTPC_Qvec, QyTPC_Qvec); float psiTPC_Qvec = computeEventPlane(QyTPC_Qvec, QxTPC_Qvec); @@ -338,7 +338,7 @@ struct flowQC { } for (int iQvecDet = 0; iQvecDet < qVecDetectors::kNqVecDetectors; iQvecDet++) { hPsiComp[iQvecDet]->Fill(centrality, vec_Qpsi[methods::kEP][iQvecDet] - vec_Qpsi[methods::kQvec][iQvecDet]); - hCosPsiComp[iQvecDet]->Fill(centrality, std::cos(2 * (vec_Qpsi[methods::kEP][iQvecDet] - vec_Qpsi[methods::kQvec][iQvecDet]))); + hCosPsiComp[iQvecDet]->Fill(centrality, std::cos(cfgHarmonic.value * (vec_Qpsi[methods::kEP][iQvecDet] - vec_Qpsi[methods::kQvec][iQvecDet]))); } } }; diff --git a/PWGLF/TableProducer/Resonances/CMakeLists.txt b/PWGLF/TableProducer/Resonances/CMakeLists.txt index 79b69b5b071..a58387288a8 100644 --- a/PWGLF/TableProducer/Resonances/CMakeLists.txt +++ b/PWGLF/TableProducer/Resonances/CMakeLists.txt @@ -49,3 +49,8 @@ o2physics_add_dpl_workflow(heptaquarktable SOURCES HeptaQuarktable.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DetectorsVertexing COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(cksspinalignment + SOURCES cksspinalignment.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Resonances/cksspinalignment.cxx b/PWGLF/TableProducer/Resonances/cksspinalignment.cxx new file mode 100644 index 00000000000..56fc938f43b --- /dev/null +++ b/PWGLF/TableProducer/Resonances/cksspinalignment.cxx @@ -0,0 +1,394 @@ +// 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 cksspinalignment.cxx +/// \brief Table producer for Charged KStar spin alignment +/// +/// \author prottay.das@cern.ch + +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/LFCKSSpinalignmentTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#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/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.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/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector2D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using namespace o2::aod::rctsel; + +struct cksspinalignment { + + Produces kshortpionEvent; + Produces kshortTrack; + Produces pionTrack; + + Service ccdb; + + struct : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "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"}; + } rctCut; + + Configurable cfgCutOccupancy{"cfgCutOccupancy", 2000, "Occupancy cut"}; + + // events + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutCentralityMax{"cfgCutCentralityMax", 80.0f, "Accepted maximum Centrality"}; + Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 0.0f, "Accepted minimum Centrality"}; + + // Configs for track + Configurable cfgCutPt{"cfgCutPt", 0.2, "Pt cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + + // Configs for pion + struct : ConfigurableGroup { + Configurable itsPIDSelection{"itsPIDSelection", true, "PID ITS"}; + Configurable lowITSPIDNsigma{"lowITSPIDNsigma", -3.0, "lower cut on PID nsigma for ITS"}; + Configurable highITSPIDNsigma{"highITSPIDNsigma", 3.0, "higher cut on PID nsigma for ITS"}; + Configurable itsclusterPiMeson{"itsclusterPiMeson", 5, "Minimum number of ITS cluster for pi meson track"}; + Configurable tpcCrossedRowsPiMeson{"tpcCrossedRowsPiMeson", 80, "Minimum number of TPC Crossed Rows for pi meson track"}; + Configurable cutDCAxyPiMeson{"cutDCAxyPiMeson", 0.1, "Maximum DCAxy for pi meson track"}; + Configurable cutDCAzPiMeson{"cutDCAzPiMeson", 0.1, "Maximum DCAz for pi meson track"}; + Configurable cutEtaPiMeson{"cutEtaPiMeson", 0.8, "Maximum eta for pi meson track"}; + Configurable cutPTPiMeson{"cutPTPiMeson", 0.8, "Maximum pt for pi meson track"}; + Configurable usePID{"usePID", true, "Flag for using PID selection for pi meson track"}; + Configurable nsigmaCutTPCPiMeson{"nsigmaCutTPCPiMeson", 3.0, "Maximum nsigma cut TPC for pi meson track"}; + Configurable nsigmaCutTOFPiMeson{"nsigmaCutTOFPiMeson", 3.0, "Maximum nsigma cut TOF for pi meson track"}; + Configurable cutTOFBetaPiMeson{"cutTOFBetaPiMeson", 3.0, "Maximum beta cut for pi meson track"}; + } grpPion; + + // Configs for V0 + Configurable confV0PtMin{"confV0PtMin", 0.f, "Minimum transverse momentum of V0"}; + Configurable confV0PtMax{"confV0PtMax", 1000.f, "Maximum transverse momentum of V0"}; + Configurable confV0Rap{"confV0Rap", 0.8f, "Rapidity range of V0"}; + Configurable confV0DCADaughMax{"confV0DCADaughMax", 1.0f, "Maximum DCA between the V0 daughters"}; + Configurable confV0CPAMin{"confV0CPAMin", 0.9998f, "Minimum CPA of V0"}; + Configurable confV0TranRadV0Min{"confV0TranRadV0Min", 1.5f, "Minimum transverse radius"}; + Configurable confV0TranRadV0Max{"confV0TranRadV0Max", 100.f, "Maximum transverse radius"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 1.2, "Maximum V0 DCA to PV"}; + Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; + Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 50, "Maximum V0 life time"}; + Configurable qtArmenterosMin{"qtArmenterosMin", 0.2, "Minimum armenteros cut for K0s"}; + // config for V0 daughters + Configurable confDaughEta{"confDaughEta", 0.8f, "V0 Daugh sel: max eta"}; + Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.2, "minimum daughter pion pt"}; + Configurable confDaughTPCnclsMin{"confDaughTPCnclsMin", 50.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable confDaughTPCncrwsMin{"confDaughTPCncrwsMin", 70.f, "V0 Daugh sel: Min. nCrws TPC"}; + Configurable confDaughPIDCuts{"confDaughPIDCuts", 3, "PID selections for Kshortpion daughters"}; + + 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"}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + RCTFlagsChecker rctChecker; + void init(o2::framework::InitContext&) + { + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + AxisSpec thnAxisInvMass{iMNbins, lbinIM, hbinIM, "#it{M} (GeV/#it{c}^{2})"}; + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{5, 0, 5.0}}); + histos.add("hTrkSelInfo", "hTrkSelInfo", kTH1F, {{5, 0, 5.0}}); + histos.add("hKShortMass", "hKShortMass", kTH1F, {thnAxisInvMass}); + histos.add("hV0Info", "hV0Info", kTH1F, {{5, 0, 5.0}}); + } + + template + bool selectionTrack(const T& candidate) + { + if (candidate.isGlobalTrack() && candidate.isPVContributor() && candidate.itsNCls() >= grpPion.itsclusterPiMeson && candidate.tpcNClsCrossedRows() > grpPion.tpcCrossedRowsPiMeson && std::abs(candidate.dcaXY()) <= grpPion.cutDCAxyPiMeson && std::abs(candidate.dcaZ()) <= grpPion.cutDCAzPiMeson && std::abs(candidate.eta()) <= grpPion.cutEtaPiMeson && candidate.pt() >= grpPion.cutPTPiMeson) { + return true; + } + return false; + } + + template + bool selectionPID(const T& candidate) + { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < grpPion.nsigmaCutTPCPiMeson) { + return true; + } + if (candidate.hasTOF() && candidate.beta() > grpPion.cutTOFBetaPiMeson && std::abs(candidate.tpcNSigmaPi()) < grpPion.nsigmaCutTPCPiMeson && std::abs(candidate.tofNSigmaPi()) < grpPion.nsigmaCutTOFPiMeson) { + return true; + } + return false; + } + + template + bool selectionV0(Collision const& collision, V0 const& candidate) + { + if (std::abs(candidate.dcav0topv()) > cMaxV0DCA) { + return false; + } + const float pT = candidate.pt(); + const float tranRad = candidate.v0radius(); + const float dcaDaughv0 = std::abs(candidate.dcaV0daughters()); + const float cpav0 = candidate.v0cosPA(); + float ctauKShort = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * (o2::constants::physics::MassK0); + + if (pT < confV0PtMin) { + return false; + } + if (pT > confV0PtMax) { + return false; + } + if (dcaDaughv0 > confV0DCADaughMax) { + return false; + } + if (cpav0 < confV0CPAMin) { + return false; + } + if (tranRad < confV0TranRadV0Min) { + return false; + } + if (tranRad > confV0TranRadV0Max) { + return false; + } + if (std::abs(ctauKShort) > cMaxV0LifeTime) { + return false; + } + if ((candidate.qtarm() / std::abs(candidate.alpha())) < qtArmenterosMin) { + return false; + } + if (std::abs(candidate.yK0Short()) > confV0Rap) { // use full rapidity 0.8 for K0s + return false; + } + return true; + } + + template + bool isSelectedV0Daughter(V0 const& candidate) + { + auto postrack = candidate.template posTrack_as(); + auto negtrack = candidate.template negTrack_as(); + + const auto ncrfc = 0.8; + + if (postrack.sign() < 0 || negtrack.sign() > 0) { + return false; + } + if (postrack.tpcNClsCrossedRows() < confDaughTPCncrwsMin || negtrack.tpcNClsCrossedRows() < confDaughTPCncrwsMin) { + return false; + } + if (postrack.tpcNClsFound() < confDaughTPCnclsMin || negtrack.tpcNClsFound() < confDaughTPCnclsMin) { + return false; + } + if (postrack.tpcCrossedRowsOverFindableCls() < ncrfc || negtrack.tpcCrossedRowsOverFindableCls() < ncrfc) { + return false; + } + if (std::abs(postrack.tpcNSigmaPi()) > confDaughPIDCuts || std::abs(negtrack.tpcNSigmaPi()) > confDaughPIDCuts) { + return false; + } + if (candidate.positivept() < cfgDaughPiPt || candidate.negativept() < cfgDaughPiPt) { + return false; + } + if (std::abs(candidate.positiveeta()) > confDaughEta || std::abs(candidate.negativeeta()) > confDaughEta) { + return false; + } + if (std::abs(candidate.dcapostopv()) < cMinV0DCAPi || std::abs(candidate.dcanegtopv()) < cMinV0DCAPi) { + return false; + } + + return true; + } + + std::tuple getK0sTags(const auto& v0, const auto& collision) + { + // auto postrack = v0.template posTrack_as(); + // auto negtrack = v0.template negTrack_as(); + + int kshortTag = 0; + + if (isSelectedV0Daughter(v0) && v0.mK0Short() > lbinIM && v0.mK0Short() < hbinIM) { + kshortTag = 1; + } + + if (!kshortTag) { + return {0, false}; // No valid tags + } + + if (!selectionV0(collision, v0)) { + return {0, false}; // Fails selection + } + + return {kshortTag, true}; // Valid candidate + } + + ROOT::Math::PxPyPzMVector kshort, pion, pionbach, antiPion; + ROOT::Math::PxPyPzMVector kshortDummy, pionDummy; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter centralityFilter = (nabs(aod::cent::centFT0C) < cfgCutCentralityMax && nabs(aod::cent::centFT0C) > cfgCutCentralityMin); + Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && (aod::track::pt) > cfgCutPt); + + using EventCandidates = soa::Filtered>; + using AllTrackCandidates = soa::Filtered>; + using ResoV0s = aod::V0Datas; + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const& tracks, ResoV0s const& V0s) + { + o2::aod::ITSResponse itsResponse; + std::vector kshortMother, pionBachelor; + std::vector v0Cospa = {}; + std::vector v0Radius = {}; + std::vector dcaPositive = {}; + std::vector dcaNegative = {}; + std::vector positiveIndex = {}; + std::vector negativeIndex = {}; + std::vector dcaBetweenDaughter = {}; + std::vector v0Lifetime = {}; + // std::vector armenteros = {}; + std::vector pionBachelorIndex = {}; + // std::vector pionBachelorSign = {}; + std::vector pionBachelorTPC = {}; + std::vector pionBachelorTOF = {}; + std::vector pionBachelorTOFHit = {}; + + int numbV0 = 0; + auto centrality = collision.centFT0C(); + auto vz = collision.posZ(); + int occupancy = collision.trackOccupancyInTimeRange(); + auto psiFT0C = collision.psiFT0C(); + auto psiFT0A = collision.psiFT0A(); + auto psiTPC = collision.psiTPC(); + // 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) { + histos.fill(HIST("hEvtSelInfo"), 1.5); + if (collision.triggereventep()) { + histos.fill(HIST("hEvtSelInfo"), 2.5); + + for (const auto& track1 : tracks) { + histos.fill(HIST("hTrkSelInfo"), 0.5); + if (!selectionTrack(track1)) { + continue; + } + histos.fill(HIST("hTrkSelInfo"), 1.5); + + if (grpPion.itsPIDSelection && !(itsResponse.nSigmaITS(track1) > grpPion.lowITSPIDNsigma && itsResponse.nSigmaITS(track1) < grpPion.highITSPIDNsigma)) { + continue; + } + histos.fill(HIST("hTrkSelInfo"), 2.5); + + if (grpPion.usePID && !selectionPID(track1)) { + continue; + } + histos.fill(HIST("hTrkSelInfo"), 3.5); + + auto track1ID = track1.globalIndex(); + auto track1sign = track1.sign(); + if (track1sign == 0) + continue; + 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); + } + for (const auto& v0 : V0s) { + histos.fill(HIST("hV0Info"), 0.5); + auto [kshortTag, isValid] = getK0sTags(v0, collision); + if (kshortTag && isValid) { + histos.fill(HIST("hV0Info"), 1.5); + auto postrack1 = v0.template posTrack_as(); + auto negtrack1 = v0.template negTrack_as(); + positiveIndex.push_back(postrack1.globalIndex()); + negativeIndex.push_back(negtrack1.globalIndex()); + v0Cospa.push_back(v0.v0cosPA()); + v0Radius.push_back(v0.v0radius()); + dcaPositive.push_back(std::abs(v0.dcapostopv())); + dcaNegative.push_back(std::abs(v0.dcanegtopv())); + dcaBetweenDaughter.push_back(std::abs(v0.dcaV0daughters())); + v0Lifetime.push_back(v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * (o2::constants::physics::MassK0)); + // armenteros.push_back((v0.qtarm() / std::abs(v0.alpha()))); + + pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassPionCharged); + antiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassPionCharged); + kshort = pion + antiPion; + // chargedkstar = kshort + pionbach; + kshortMother.push_back(kshort); + // chargedkstarMother.push_back(chargedkstar); + histos.fill(HIST("hKShortMass"), kshort.M()); + } + 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)); + } + 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)); + } + } + } + } + } + PROCESS_SWITCH(cksspinalignment, processData, "Process data", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx b/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx index ce0cdcf3af5..842c0e46c82 100644 --- a/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx +++ b/PWGLF/TableProducer/Resonances/f1protonreducedtable.cxx @@ -400,7 +400,7 @@ struct f1protonreducedtable { std::vector setValuesBB(o2::ccdb::CcdbApi& ccdbApi, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) { - map metadata; + std::map metadata; auto h = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); // auto h = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); // check if possible to use this without getting fatal if (!h) { diff --git a/PWGLF/TableProducer/Resonances/filterf1proton.cxx b/PWGLF/TableProducer/Resonances/filterf1proton.cxx index 831209b0905..99d02c744cb 100644 --- a/PWGLF/TableProducer/Resonances/filterf1proton.cxx +++ b/PWGLF/TableProducer/Resonances/filterf1proton.cxx @@ -368,7 +368,7 @@ struct filterf1proton { std::vector setValuesBB(o2::ccdb::CcdbApi& ccdbApi, aod::BCsWithTimestamps::iterator const& bunchCrossing, const std::string ccdbPath) { - map metadata; + std::map metadata; auto h = ccdbApi.retrieveFromTFileAny(ccdbPath, metadata, bunchCrossing.timestamp()); // auto h = ccdb->getForTimeStamp(ccdbPath, bunchCrossing.timestamp()); // check if possible to use this without getting fatal if (!h) { diff --git a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx index da010f6ea59..c318d1d57d9 100644 --- a/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceInitializer.cxx @@ -654,7 +654,7 @@ struct ResonanceInitializer { continue; if (!filterMicroTrack(track)) continue; - o2::aod::resodmciroaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); + o2::aod::resomicrodaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); if (std::abs(track.dcaXY()) < (0.004 + (0.013 / track.pt()))) { trackSelFlag.setDCAxy0(); } @@ -673,9 +673,9 @@ struct ResonanceInitializer { track.px(), track.py(), track.pz(), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), static_cast(trackSelFlag), trackFlags); if (!cfgBypassTrackIndexFill) { diff --git a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx index 5dc53b28509..54d2533b05a 100644 --- a/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx +++ b/PWGLF/TableProducer/Resonances/resonanceModuleInitializer.cxx @@ -817,7 +817,7 @@ struct ResonanceDaughterInitializer { for (auto const& track : tracks) { if (!filterMicroTrack(track)) continue; - o2::aod::resodmciroaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); + o2::aod::resomicrodaughter::ResoMicroTrackSelFlag trackSelFlag(track.dcaXY(), track.dcaZ()); if (std::abs(track.dcaXY()) < (0.004 + (0.013 / track.pt()))) { trackSelFlag.setDCAxy0(); } @@ -836,9 +836,9 @@ struct ResonanceDaughterInitializer { track.px(), track.py(), track.pz(), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), - static_cast(o2::aod::resodmciroaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPi()), std::abs(track.tofNSigmaPi()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaKa()), std::abs(track.tofNSigmaKa()), track.hasTOF())), + static_cast(o2::aod::resomicrodaughter::PidNSigma(std::abs(track.tpcNSigmaPr()), std::abs(track.tofNSigmaPr()), track.hasTOF())), static_cast(trackSelFlag), trackFlags); if (!cfgBypassTrackIndexFill) { diff --git a/PWGLF/TableProducer/Strangeness/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/CMakeLists.txt index 6d9f2c04646..9e4a3fa04f8 100644 --- a/PWGLF/TableProducer/Strangeness/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/CMakeLists.txt @@ -91,8 +91,13 @@ o2physics_add_dpl_workflow(lambdakzerospawner PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(sigmaminus-task + SOURCES sigmaminustask.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(strange-tree-creator - SOURCES LFStrangeTreeCreator.cxx + SOURCES strangeTreeCreator.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -108,7 +113,7 @@ o2physics_add_dpl_workflow(strangederivedbuilder o2physics_add_dpl_workflow(strangenessbuilder SOURCES strangenessbuilder.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager O2Physics::MLCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(v0-selector @@ -160,4 +165,14 @@ o2physics_add_dpl_workflow(lambdajetpolarizationbuilder o2physics_add_dpl_workflow(stracents SOURCES stracents.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambdaspincorrelation + SOURCES lambdaspincorrelation.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(propagationservice + SOURCES propagationService.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::DCAFitter KFParticle::KFParticle O2Physics::TPCDriftManager + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt index 131672fd384..842137dafe1 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt +++ b/PWGLF/TableProducer/Strangeness/Converters/CMakeLists.txt @@ -41,22 +41,22 @@ o2physics_add_dpl_workflow(straevselsconverter o2physics_add_dpl_workflow(straevselsconverter2 SOURCES straevselsconverter2.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ReconstructionDataFormats COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter3 SOURCES straevselsconverter3.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ReconstructionDataFormats COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter4 SOURCES straevselsconverter4.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter5 SOURCES straevselsconverter5.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2::ITStracking O2Physics::AnalysisCCDB + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(straevselsconverter2rawcents @@ -117,4 +117,4 @@ o2physics_add_dpl_workflow(stramccollisionconverter2 o2physics_add_dpl_workflow(zdcneutronsconverter SOURCES zdcneutronsconverter.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) \ No newline at end of file + COMPONENT_NAME Analysis) diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx index 401b04bbc83..fd3ccad4ee4 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter2.cxx @@ -8,12 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ITStracking/Vertexer.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Vertex.h" + using namespace o2; using namespace o2::framework; @@ -52,7 +53,7 @@ struct straevselsconverter2 { values.totalFDDAmplitudeC(), values.energyCommonZNA(), values.energyCommonZNC(), - o2::its::Vertex::FlagsMask /*dummy flag value*/); + o2::dataformats::Vertex::FlagsMask /*dummy flag value*/); } } }; diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx index ecbd738f5fa..ac209c26fe7 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter3.cxx @@ -8,12 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "ITStracking/Vertexer.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Vertex.h" + using namespace o2; using namespace o2::framework; @@ -53,7 +54,7 @@ struct straevselsconverter3 { values.totalFDDAmplitudeC(), values.energyCommonZNA(), values.energyCommonZNC(), - o2::its::Vertex::FlagsMask /*dummy flag value*/); + o2::dataformats::Vertex::FlagsMask /*dummy flag value*/); } } }; diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx index ad988fd93aa..2dc55f365c9 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter4.cxx @@ -8,12 +8,12 @@ // In applying this license CERN does 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 "ITStracking/Vertexer.h" #include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + using namespace o2; using namespace o2::framework; diff --git a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx index f9617c42a0b..0ba066f99b3 100644 --- a/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx +++ b/PWGLF/TableProducer/Strangeness/Converters/straevselsconverter5.cxx @@ -8,13 +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. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/AggregatedRunInfo.h" -#include "ITStracking/Vertexer.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" using namespace o2; using namespace o2::framework; diff --git a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx index c66a1db16fd..0b930932754 100644 --- a/PWGLF/TableProducer/Strangeness/cascadeflow.cxx +++ b/PWGLF/TableProducer/Strangeness/cascadeflow.cxx @@ -9,8 +9,11 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// +/// \file cascadeflow.cxx +/// /// \brief Task to create derived data for cascade flow analyses -/// \authors: Chiara De Martin (chiara.de.martin@cern.ch), Maximiliano Puccio (maximiliano.puccio@cern.ch) +/// \author Chiara De Martin (chiara.de.martin@cern.ch) +/// \author Maximiliano Puccio (maximiliano.puccio@cern.ch) #include #include @@ -40,17 +43,23 @@ using std::array; using DauTracks = soa::Join; using CollEventPlane = soa::Join::iterator; +using CollEventPlaneCentralFW = soa::Join::iterator; using CollEventAndSpecPlane = soa::Join::iterator; -using CollEventPlaneCentralFW = soa::Join::iterator; +using CollEventAndSpecPlaneCentralFW = soa::Join::iterator; using MCCollisionsStra = soa::Join; +using V0Candidates = soa::Join; using CascCandidates = soa::Join; using CascMCCandidates = soa::Join; +const int nParticles = 2; // Xi, Omega +const int nCharges = 2; // Lambda, AntiLambda +const int nParameters = 4; + namespace cascadev2 { enum species { Xi = 0, Omega = 1 }; -constexpr double massSigmaParameters[4][2]{ +constexpr double massSigmaParameters[nParameters][nParticles]{ {4.9736e-3, 0.006815}, {-2.39594, -2.257}, {1.8064e-3, 0.00138}, @@ -61,15 +70,26 @@ const double AlphaXi[2] = {-0.390, 0.371}; // decay parameter of XiMinus and const double AlphaOmega[2] = {0.0154, -0.018}; // decay parameter of OmegaMinus and OmegaPlus const double AlphaLambda[2] = {0.747, -0.757}; // decay parameter of Lambda and AntiLambda -std::shared_ptr hMassBeforeSelVsPt[2]; -std::shared_ptr hMassAfterSelVsPt[2]; -std::shared_ptr hSignalScoreBeforeSel[2]; -std::shared_ptr hBkgScoreBeforeSel[2]; -std::shared_ptr hSignalScoreAfterSel[2]; -std::shared_ptr hBkgScoreAfterSel[2]; -std::shared_ptr hSparseV2C[2]; +std::shared_ptr hMassBeforeSelVsPt[nParticles]; +std::shared_ptr hMassAfterSelVsPt[nParticles]; +std::shared_ptr hSignalScoreBeforeSel[nParticles]; +std::shared_ptr hBkgScoreBeforeSel[nParticles]; +std::shared_ptr hSignalScoreAfterSel[nParticles]; +std::shared_ptr hBkgScoreAfterSel[nParticles]; +std::shared_ptr hSparseV2C[nParticles]; } // namespace cascadev2 +namespace lambdav2 +{ +enum species { Lambda = 0, + AntiLambda = 1 }; +static const std::vector speciesNames{"Lambda", "AntiLambda"}; +const double AlphaLambda[2] = {0.747, -0.757}; // decay parameter of Lambda and AntiLambda + +std::shared_ptr hMassBeforeSelVsPt[nCharges]; +std::shared_ptr hMassAfterSelVsPt[nCharges]; +} // namespace lambdav2 + namespace cascade_flow_cuts_ml { // direction of the cut @@ -136,6 +156,8 @@ struct cascadeFlow { Configurable isFillTHNXi_PzVsPsi{"isFillTHNXi_PzVsPsi", 1, ""}; Configurable isFillTHNOmega{"isFillTHNOmega", 1, ""}; Configurable isFillTHNOmega_PzVsPsi{"isFillTHNOmega_PzVsPsi", 1, ""}; + Configurable isFillTHNLambda{"isFillTHNLambda", 1, ""}; + Configurable isFillTHNLambda_PzVsPsi{"isFillTHNLambda_PzVsPsi", 1, ""}; Configurable isFillTHN_V2{"isFillTHN_V2", 1, ""}; Configurable isFillTHN_Pz{"isFillTHN_Pz", 1, ""}; Configurable isFillTHN_PzFromLambda{"isFillTHN_PzFromLambda", 1, ""}; @@ -154,7 +176,7 @@ struct cascadeFlow { ConfigurableAxis thnConfigAxisPt{"thnConfigAxisPt", {VARIABLE_WIDTH, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2, 2.25, 2.5, 2.75, 3, 3.5, 4, 5, 6, 8, 10}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis thnConfigAxisPtLambda{"thnConfigAxisPtLambda", {VARIABLE_WIDTH, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2, 2.25, 2.5, 2.75, 3, 3.5, 4, 5, 6, 8, 10, 20}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis thnConfigAxisCharge{"thnConfigAxisCharge", {2, 0, 2}, ""}; - ConfigurableAxis thnConfigAxisPsiDiff{"thnConfigAxisPsiDiff", {100, 0, 2 * TMath::Pi()}, ""}; + ConfigurableAxis thnConfigAxisPsiDiff{"thnConfigAxisPsiDiff", {100, 0, o2::constants::math::TwoPI}, ""}; ConfigurableAxis thnConfigAxisMassXi{"thnConfigAxisMassXi", {45, 1.300, 1.345}, ""}; ConfigurableAxis thnConfigAxisMassOmega{"thnConfigAxisMassOmega", {45, 1.655, 1.690}, ""}; ConfigurableAxis thnConfigAxisMassLambda{"thnConfigAxisMassLambda", {60, 1.1, 1.13}, ""}; @@ -201,6 +223,22 @@ struct cascadeFlow { Configurable MaxOmegaMass{"MaxOmegaMass", 1.690, ""}; } CandidateConfigs; + struct : ConfigurableGroup { + Configurable MinPtV0{"MinPtV0", 0.2, "Min pt of v0"}; + Configurable MaxPtV0{"MaxPtV0", 10, "Max pt of v0"}; + Configurable MinMassLambda{"MinMassLambda", 1.105, ""}; + Configurable MaxMassLambda{"MaxMassLambda", 1.125, ""}; + Configurable etaV0{"etaV0", 0.8, "etaV0"}; + 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 rapidityLambda{"rapidityLambda", 0.5, "rapidityLambda"}; + Configurable etaLambda{"etaLambda", 0.8, "etaLambda"}; + } V0Configs; + Configurable sideBandStart{"sideBandStart", 5, "Start of the sideband region in number of sigmas"}; Configurable sideBandEnd{"sideBandEnd", 7, "End of the sideband region in number of sigmas"}; Configurable downsample{"downsample", 1., "Downsample training output tree"}; @@ -223,8 +261,10 @@ struct cascadeFlow { Configurable acceptancePathsCCDBXi{"acceptancePathsCCDBXi", "Users/c/chdemart/AcceptanceXi", "Paths of Xi acceptance on CCDB"}; Configurable acceptancePathsCCDBOmega{"acceptancePathsCCDBOmega", "Users/c/chdemart/AcceptanceOmega", "Paths of Omega acceptance on CCDB"}; Configurable acceptancePathsCCDBLambda{"acceptancePathsCCDBLambda", "Users/c/chdemart/AcceptanceLambda", "Paths of Lambda acceptance on CCDB"}; + Configurable acceptancePathsCCDBPrimaryLambda{"acceptancePathsCCDBPrimaryLambda", "Users/c/chdemart/AcceptanceLambda", "Paths of PrimaryLambda acceptance on CCDB"}; Configurable acceptanceHistoNameCasc{"acceptanceHistoNameCasc", "histoCos2ThetaNoFit2D", "Histo name of acceptance on CCDB"}; Configurable acceptanceHistoNameLambda{"acceptanceHistoNameLambda", "histoCos2ThetaLambdaFromCNoFit2D", "Histo name of acceptance on CCDB"}; + Configurable acceptanceHistoNamePrimaryLambda{"acceptanceHistoNamePrimaryLambda", "histoCos2ThetaLambdaFromCNoFit2D", "Histo name of acceptance on CCDB"}; // ML inference Configurable isApplyML{"isApplyML", 1, "Flag to apply ML selections"}; @@ -261,7 +301,7 @@ struct cascadeFlow { histos.fill(HIST("hNEvents"), 1.5); // Z vertex selection - if (TMath::Abs(collision.posZ()) > cutzvertex) { + if (std::abs(collision.posZ()) > cutzvertex) { return false; } if (isFillHisto) @@ -353,13 +393,71 @@ struct cascadeFlow { return true; } + template + bool isLambdaAccepted(TDaughter negExtra, TDaughter posExtra, int& counter) // loose cuts on topological selections of v0s + { + // TPC cuts as those implemented for the training of the signal + if (doNTPCSigmaCut) { + if (std::abs(posExtra.tpcNSigmaPr()) > nsigmatpcPr || std::abs(negExtra.tpcNSigmaPi()) > nsigmatpcPi) + return false; + } + counter++; + + if (posExtra.tpcCrossedRows() < mintpccrrows || negExtra.tpcCrossedRows() < mintpccrrows) + return false; + + counter++; + return true; + } + template + bool isAntiLambdaAccepted(TDaughter negExtra, TDaughter posExtra, int& counter) // loose cuts on topological selections of v0s + { + // TPC cuts as those implemented for the training of the signal + if (doNTPCSigmaCut) { + if (std::abs(negExtra.tpcNSigmaPr()) > nsigmatpcPr || std::abs(posExtra.tpcNSigmaPi()) > nsigmatpcPi) + return false; + } + counter++; + + if (posExtra.tpcCrossedRows() < mintpccrrows || negExtra.tpcCrossedRows() < mintpccrrows) + return false; + + counter++; + return true; + } + + template + bool isV0TopoAccepted(TV0 v0) + { + // topological selections + if (v0.v0radius() < V0Configs.v0radius) + return false; + if (v0.v0radius() > V0Configs.v0radiusMax) + return false; + if (std::abs(v0.dcapostopv()) < V0Configs.dcapostopv) + return false; + if (std::abs(v0.dcanegtopv()) < V0Configs.dcanegtopv) + return false; + if (v0.v0cosPA() < V0Configs.v0cospa) + return false; + if (v0.dcaV0daughters() > V0Configs.dcav0dau) + return false; + // rapidity selection + if (std::abs(v0.yLambda()) > V0Configs.rapidityLambda) + return false; + if (std::abs(v0.eta()) > V0Configs.etaLambda) + return false; + + return true; + } + double GetPhiInRange(double phi) { while (phi < 0) { - phi += TMath::Pi(); + phi += o2::constants::math::PI; } - while (phi > TMath::Pi()) { - phi -= TMath::Pi(); + while (phi > o2::constants::math::PI) { + phi -= o2::constants::math::PI; } return phi; } @@ -368,6 +466,7 @@ struct cascadeFlow { TH2F* hAcceptanceXi; TH2F* hAcceptanceOmega; TH2F* hAcceptanceLambda; + TH2F* hAcceptancePrimaryLambda; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; HistogramRegistry histosMCGen{"histosMCGen", {}, OutputObjHandlingPolicy::AnalysisObject, false, true}; @@ -378,13 +477,13 @@ struct cascadeFlow { Produces analysisSample; Configurable> parSigmaMass{ "parSigmaMass", - {cascadev2::massSigmaParameters[0], 4, 2, + {cascadev2::massSigmaParameters[0], nParameters, nParticles, cascadev2::massSigmaParameterNames, cascadev2::speciesNames}, "Mass resolution parameters: [0]*exp([1]*x)+[2]*exp([3]*x)"}; float getNsigmaMass(const cascadev2::species s, const float pt, const float nsigma = 6) { - const auto sigma = parSigmaMass->get(0u, s) * exp(parSigmaMass->get(1, s) * pt) + parSigmaMass->get(2, s) * exp(parSigmaMass->get(3, s) * pt); + const auto sigma = parSigmaMass->get(0u, s) * std::exp(parSigmaMass->get(1, s) * pt) + parSigmaMass->get(2, s) * std::exp(parSigmaMass->get(3, s) * pt); return nsigma * sigma; } @@ -416,9 +515,9 @@ struct cascadeFlow { template void fillAnalysedTable(collision_t coll, bool hasEventPlane, bool hasSpectatorPlane, cascade_t casc, float v2CSP, float v2CEP, float v1SP_ZDCA, float v1SP_ZDCC, float PsiT0C, float BDTresponseXi, float BDTresponseOmega, int pdgCode) { - double masses[2]{o2::constants::physics::MassXiMinus, o2::constants::physics::MassOmegaMinus}; - ROOT::Math::PxPyPzMVector cascadeVector[2], lambdaVector, protonVector; - float cosThetaStarLambda[2], cosThetaStarProton; + double masses[nParticles]{o2::constants::physics::MassXiMinus, o2::constants::physics::MassOmegaMinus}; + ROOT::Math::PxPyPzMVector cascadeVector[nParticles], lambdaVector, protonVector; + float cosThetaStarLambda[nParticles], cosThetaStarProton; lambdaVector.SetCoordinates(casc.pxlambda(), casc.pylambda(), casc.pzlambda(), o2::constants::physics::MassLambda); ROOT::Math::Boost lambdaBoost{lambdaVector.BoostToCM()}; if (casc.sign() > 0) { @@ -428,7 +527,7 @@ struct cascadeFlow { } auto boostedProton{lambdaBoost(protonVector)}; cosThetaStarProton = boostedProton.Pz() / boostedProton.P(); - for (int i{0}; i < 2; ++i) { + for (int i{0}; i < nParticles; ++i) { cascadeVector[i].SetCoordinates(casc.px(), casc.py(), casc.pz(), masses[i]); ROOT::Math::Boost cascadeBoost{cascadeVector[i].BoostToCM()}; auto boostedLambda{cascadeBoost(lambdaVector)}; @@ -485,6 +584,10 @@ struct cascadeFlow { TList* listAcceptanceLambda = ccdb->get(acceptancePathsCCDBLambda); if (!listAcceptanceLambda) LOG(fatal) << "Problem getting TList object with acceptance for Lambda!"; + TList* listAcceptancePrimaryLambda = ccdb->get(acceptancePathsCCDBPrimaryLambda); + if (!listAcceptancePrimaryLambda) + LOG(fatal) << "Problem getting TList object with acceptance for Primary Lambda!"; + hAcceptanceXi = static_cast(listAcceptanceXi->FindObject(Form("%s", acceptanceHistoNameCasc->data()))); if (!hAcceptanceXi) { LOG(fatal) << "The histogram for Xi is not there!"; @@ -500,6 +603,11 @@ struct cascadeFlow { LOG(fatal) << "The histogram for Lambda is not there!"; } hAcceptanceLambda->SetName("hAcceptanceLambda"); + hAcceptancePrimaryLambda = static_cast(listAcceptancePrimaryLambda->FindObject(Form("%s", acceptanceHistoNamePrimaryLambda->data()))); + if (!hAcceptancePrimaryLambda) { + LOG(fatal) << "The histogram for Primary Lambda is not there!"; + } + hAcceptancePrimaryLambda->SetName("hAcceptancePrimaryLambda"); LOG(info) << "Acceptance now loaded"; } @@ -508,9 +616,14 @@ struct cascadeFlow { float minMass[2]{1.28, 1.6}; float maxMass[2]{1.36, 1.73}; + float minMassLambda[2]{1.09, 1.09}; + float maxMassLambda[2]{1.14, 1.14}; const AxisSpec massCascAxis[2]{{static_cast((maxMass[0] - minMass[0]) / 0.001f), minMass[0], maxMass[0], "#Xi candidate mass (GeV/c^{2})"}, {static_cast((maxMass[1] - minMass[1]) / 0.001f), minMass[1], maxMass[1], "#Omega candidate mass (GeV/c^{2})"}}; - const AxisSpec ptAxis{static_cast((CandidateConfigs.MaxPt - CandidateConfigs.MinPt) / 0.2), CandidateConfigs.MinPt, CandidateConfigs.MaxPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec massLambdaAxis[2]{{static_cast((maxMassLambda[0] - minMassLambda[0]) / 0.001f), minMassLambda[0], maxMassLambda[0], "#Lambda candidate mass (GeV/c^{2})"}, + {static_cast((maxMassLambda[1] - minMassLambda[1]) / 0.001f), minMassLambda[1], maxMassLambda[1], "#bar{#Lambda} candidate mass (GeV/c^{2})"}}; + const AxisSpec ptAxisCasc{static_cast((CandidateConfigs.MaxPt - CandidateConfigs.MinPt) / 0.2), CandidateConfigs.MinPt, CandidateConfigs.MaxPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec ptAxisLambda{static_cast((V0Configs.MaxPtV0 - V0Configs.MinPtV0) / 0.2), V0Configs.MinPtV0, V0Configs.MaxPtV0, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec v2Axis{200, -1., 1., "#it{v}_{2}"}; const AxisSpec CentAxis{18, 0., 90., "FT0C centrality percentile"}; TString hNEventsLabels[10] = {"All", "sel8", "z vrtx", "kNoSameBunchPileup", "kIsGoodZvtxFT0vsPV", "trackOccupancyInTimeRange", "kNoCollInTimeRange", "kNoCollInROF", "kTVXinTRD", "kIsGoodEventEP"}; @@ -531,9 +644,9 @@ struct cascadeFlow { } histos.add("hEventVertexZ", "hEventVertexZ", kTH1F, {{120, -12., 12.}}); histos.add("hEventCentrality", "hEventCentrality", kTH1F, {{101, 0, 101}}); - histos.add("hPsiT0C", "hPsiT0C", HistType::kTH1D, {{100, -TMath::Pi(), TMath::Pi()}}); - histos.add("hPsiT0CvsCentFT0C", "hPsiT0CvsCentFT0C", HistType::kTH2D, {CentAxis, {100, -TMath::Pi(), TMath::Pi()}}); - histos.add("hPsiZDCA_vs_ZDCC", "hPsiZDCA_vs_ZDCC", HistType::kTH2D, {{100, -TMath::Pi(), TMath::Pi()}, {100, -TMath::Pi(), TMath::Pi()}}); + histos.add("hPsiT0C", "hPsiT0C", HistType::kTH1D, {{100, -o2::constants::math::PI, o2::constants::math::PI}}); + histos.add("hPsiT0CvsCentFT0C", "hPsiT0CvsCentFT0C", HistType::kTH2D, {CentAxis, {100, -o2::constants::math::PI, o2::constants::math::PI}}); + histos.add("hPsiZDCA_vs_ZDCC", "hPsiZDCA_vs_ZDCC", HistType::kTH2D, {{100, -o2::constants::math::PI, o2::constants::math::PI}, {100, -o2::constants::math::PI, o2::constants::math::PI}}); histos.add("hEventNchCorrelation", "hEventNchCorrelation", kTH2F, {{5000, 0, 5000}, {5000, 0, 2500}}); histos.add("hEventPVcontributorsVsCentrality", "hEventPVcontributorsVsCentrality", kTH2F, {{100, 0, 100}, {5000, 0, 5000}}); histos.add("hEventGlobalTracksVsCentrality", "hEventGlobalTracksVsCentrality", kTH2F, {{100, 0, 100}, {2500, 0, 2500}}); @@ -546,16 +659,22 @@ struct cascadeFlow { histos.add("hMultNTracksITSTPCVsCentrality", "hMultNTracksITSTPCVsCentrality", kTH2F, {{100, 0, 100}, {1000, 0, 5000}}); histos.add("hCandidate", "hCandidate", HistType::kTH1F, {{22, -0.5, 21.5}}); + histos.add("hLambdaCandidate", "hLambdaCandidate", HistType::kTH1F, {{5, -0.5, 4.5}}); histos.add("hCascadeSignal", "hCascadeSignal", HistType::kTH1F, {{6, -0.5, 5.5}}); histos.add("hCascade", "hCascade", HistType::kTH1F, {{6, -0.5, 5.5}}); + histos.add("hCascadeDauSel", "hCascadeDauSel", HistType::kTH1F, {{2, -0.5, 1.5}}); + histos.add("hLambdaDauSel", "hLambdaDauSel", HistType::kTH1F, {{3, -0.5, 2.5}}); + histos.add("hALambdaDauSel", "hALambdaDauSel", HistType::kTH1F, {{3, -0.5, 2.5}}); histos.add("hXiPtvsCent", "hXiPtvsCent", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histos.add("hXiPtvsCentEta08", "hXiPtvsCentEta08", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histos.add("hXiPtvsCentY05", "hXiPtvsCentY05", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histos.add("hOmegaPtvsCent", "hOmegaPtvsCent", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histos.add("hOmegaPtvsCentEta08", "hOmegaPtvsCentEta08", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histos.add("hOmegaPtvsCentY05", "hOmegaPtvsCentY05", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); - histos.add("hCascadePhi", "hCascadePhi", HistType::kTH1F, {{100, 0, 2 * TMath::Pi()}}); - histos.add("hcascminuspsiT0C", "hcascminuspsiT0C", HistType::kTH1F, {{100, 0, TMath::Pi()}}); + histos.add("hCascadePhi", "hCascadePhi", HistType::kTH1F, {{100, 0, o2::constants::math::TwoPI}}); + histos.add("hcascminuspsiT0C", "hcascminuspsiT0C", HistType::kTH1F, {{100, 0, o2::constants::math::PI}}); + histos.add("hLambdaPhi", "hLambdaPhi", HistType::kTH1F, {{100, 0, o2::constants::math::TwoPI}}); + histos.add("hlambdaminuspsiT0C", "hlambdaminuspsiT0C", HistType::kTH1F, {{100, 0, o2::constants::math::PI}}); histos.add("hv2CEPvsFT0C", "hv2CEPvsFT0C", HistType::kTH2F, {CentAxis, {100, -1, 1}}); histos.add("hv2CEPvsv2CSP", "hv2CEPvsV2CSP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); histos.add("hv1EPvsv1SP", "hV1EPvsV1SP", HistType::kTH2F, {{100, -1, 1}, {100, -1, 1}}); @@ -636,6 +755,20 @@ struct cascadeFlow { if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) histos.add("hOmegaCos2ThetaVsPsiFromLambdaL", "THn for cos2Theta of Lambda vs Lambda mass and pt", HistType::kTHnF, {thnAxisFT0C, thnAxisCharge, thnAxisEta, thnAxisPtLambda, thnAxisMassLambda, thnAxisBDTScore, thnAxisCos2ThetaL, thnAxisPsiDiff}); } + if (fillingConfigs.isFillTHNLambda) { + if (fillingConfigs.isFillTHN_V2) + histos.add("hLambdaV2", "THn for v2 of Lambda", HistType::kTHnF, {thnAxisFT0C, thnAxisCharge, thnAxisPtLambda, thnAxisMassLambda, thnAxisV2}); + if (fillingConfigs.isFillTHN_Pz) + histos.add("hLambdaPzs2", "THn for Pzs2 of Lambda", HistType::kTHnF, {thnAxisFT0C, thnAxisCharge, thnAxisPtLambda, thnAxisMassLambda, thnAxisPzs2Lambda}); + if (fillingConfigs.isFillTHN_Acc) + histos.add("hLambdaCos2Theta", "THn for Cos2Theta of Lambda", HistType::kTHnF, {thnAxisFT0C, thnAxisCharge, thnAxisEta, thnAxisPtLambda, thnAxisMassLambda, thnAxisCos2Theta}); + } + if (fillingConfigs.isFillTHNLambda_PzVsPsi) { + if (fillingConfigs.isFillTHN_Pz) + histos.add("hLambdaPzVsPsi", "THn for cosTheta of Lambda", HistType::kTHnF, {thnAxisFT0C, thnAxisCharge, thnAxisPtLambda, thnAxisMassLambda, thnAxisCosThetaProtonAlpha, thnAxisPsiDiff}); + if (fillingConfigs.isFillTHN_Acc) + histos.add("hLambdaCos2ThetaVsPsi", "THn for cos2Theta of Lambda", HistType::kTHnF, {thnAxisFT0C, thnAxisCharge, thnAxisEta, thnAxisPtLambda, thnAxisMassLambda, thnAxisCos2Theta, thnAxisPsiDiff}); + } histosMCGen.add("h2DGenXiEta08", "h2DGenXiEta08", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); histosMCGen.add("h2DGenOmegaEta08", "h2DGenOmegaEta08", HistType::kTH2F, {{100, 0, 100}, {400, 0, 20}}); @@ -653,15 +786,20 @@ struct cascadeFlow { histosMCGen.get(HIST("hNCascGen"))->GetXaxis()->SetBinLabel(n, hNCascLabelsMC[n - 1]); } - for (int iS{0}; iS < 2; ++iS) { - cascadev2::hMassBeforeSelVsPt[iS] = histos.add(Form("hMassBeforeSelVsPt%s", cascadev2::speciesNames[iS].data()), "hMassBeforeSelVsPt", HistType::kTH2F, {massCascAxis[iS], ptAxis}); - cascadev2::hMassAfterSelVsPt[iS] = histos.add(Form("hMassAfterSelVsPt%s", cascadev2::speciesNames[iS].data()), "hMassAfterSelVsPt", HistType::kTH2F, {massCascAxis[iS], ptAxis}); + 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}); + cascadev2::hMassAfterSelVsPt[iS] = histos.add(Form("hMassAfterSelVsPt%s", cascadev2::speciesNames[iS].data()), "hMassAfterSelVsPt", HistType::kTH2F, {massCascAxis[iS], ptAxisCasc}); cascadev2::hSignalScoreBeforeSel[iS] = histos.add(Form("hSignalScoreBeforeSel%s", cascadev2::speciesNames[iS].data()), "Signal score before selection;BDT first score;entries", HistType::kTH1F, {{100, 0., 1.}}); cascadev2::hBkgScoreBeforeSel[iS] = histos.add(Form("hBkgScoreBeforeSel%s", cascadev2::speciesNames[iS].data()), "Bkg score before selection;BDT first score;entries", HistType::kTH1F, {{100, 0., 1.}}); cascadev2::hSignalScoreAfterSel[iS] = histos.add(Form("hSignalScoreAfterSel%s", cascadev2::speciesNames[iS].data()), "Signal score after selection;BDT first score;entries", HistType::kTH1F, {{100, 0., 1.}}); cascadev2::hBkgScoreAfterSel[iS] = histos.add(Form("hBkgScoreAfterSel%s", cascadev2::speciesNames[iS].data()), "Bkg score after selection;BDT first score;entries", HistType::kTH1F, {{100, 0., 1.}}); - cascadev2::hSparseV2C[iS] = histos.add(Form("hSparseV2C%s", cascadev2::speciesNames[iS].data()), "hSparseV2C", HistType::kTHnF, {massCascAxis[iS], ptAxis, v2Axis, CentAxis}); + cascadev2::hSparseV2C[iS] = histos.add(Form("hSparseV2C%s", cascadev2::speciesNames[iS].data()), "hSparseV2C", HistType::kTHnF, {massCascAxis[iS], ptAxisCasc, v2Axis, CentAxis}); + } + 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}); } + if (isApplyML) { // Configure and initialise the ML class mlResponseXi.configure(binsPtMl, cutsMl, cutDirMl, nClassesMl); @@ -699,7 +837,7 @@ struct cascadeFlow { histos.fill(HIST("hEventCentrality"), coll.centFT0C()); histos.fill(HIST("hEventVertexZ"), coll.posZ()); - for (auto& casc : Cascades) { + for (auto const& casc : Cascades) { if (gRandom->Uniform() > downsample) { continue; } @@ -749,14 +887,14 @@ struct cascadeFlow { histos.fill(HIST("hEventCentrality"), coll.centFT0C()); histos.fill(HIST("hEventVertexZ"), coll.posZ()); - for (auto& casc : Cascades) { + for (auto const& casc : Cascades) { if (!casc.has_cascMCCore()) continue; auto cascMC = casc.cascMCCore_as>(); int pdgCode{cascMC.pdgCode()}; - if (!(std::abs(pdgCode) == 3312 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 211) // Xi - && !(std::abs(pdgCode) == 3334 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 321)) // Omega + if (!(std::abs(pdgCode) == PDG_t::kXiMinus && std::abs(cascMC.pdgCodeV0()) == PDG_t::kLambda0 && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kPiPlus) // Xi + && !(std::abs(pdgCode) == PDG_t::kOmegaMinus && std::abs(cascMC.pdgCodeV0()) == PDG_t::kLambda0 && std::abs(cascMC.pdgCodeBachelor()) == kKPlus)) // Omega continue; auto negExtra = casc.negTrackExtra_as(); @@ -764,11 +902,13 @@ struct cascadeFlow { auto bachExtra = casc.bachTrackExtra_as(); int counter = 0; - IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); + bool isCascCandidate = 0; + isCascCandidate = IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); histos.fill(HIST("hCascadeSignal"), counter); // PDG cascades - fillTrainingTable(coll, casc, pdgCode); + if (isCascCandidate) + fillTrainingTable(coll, casc, pdgCode); // I only store cascades that passed PID and track quality selections } } @@ -821,8 +961,8 @@ struct cascadeFlow { resolution.fill(HIST("QVectorsNormTPCAC"), eventplaneVecTPCA.Dot(eventplaneVecTPCC) / (coll.qTPCR() * coll.qTPCL()), coll.centFT0C()); resolution.fill(HIST("QVectorsSpecPlane"), spectatorplaneVecZDCC.Dot(spectatorplaneVecZDCA), coll.centFT0C()); - std::vector bdtScore[2]; - for (auto& casc : Cascades) { + std::vector bdtScore[nParticles]; + for (auto const& casc : Cascades) { /// Add some minimal cuts for single track variables (min number of TPC clusters) auto negExtra = casc.negTrackExtra_as(); @@ -830,8 +970,12 @@ struct cascadeFlow { auto bachExtra = casc.bachTrackExtra_as(); int counter = 0; - IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); + bool isCascCandidate = 0; + isCascCandidate = IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); histos.fill(HIST("hCascade"), counter); + histos.fill(HIST("hCascadeDauSel"), (int)isCascCandidate); + if (!isCascCandidate) + continue; // ML selections bool isSelectedCasc[2]{false, false}; @@ -864,7 +1008,7 @@ struct cascadeFlow { isSelectedCasc[0] = mlResponseXi.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[0]); isSelectedCasc[1] = mlResponseOmega.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[1]); - for (int iS{0}; iS < 2; ++iS) { + for (int iS{0}; iS < nParticles; ++iS) { // Fill BDT score histograms before selection cascadev2::hSignalScoreBeforeSel[iS]->Fill(bdtScore[0][1]); cascadev2::hBkgScoreBeforeSel[iS]->Fill(bdtScore[1][0]); @@ -884,12 +1028,12 @@ struct cascadeFlow { ROOT::Math::XYZVector cascQvec{std::cos(2 * casc.phi()), std::sin(2 * casc.phi()), 0}; auto v2CSP = cascQvec.Dot(eventplaneVecT0C); // not normalised by amplitude auto cascminuspsiT0C = GetPhiInRange(casc.phi() - PsiT0C); - auto v2CEP = TMath::Cos(2.0 * cascminuspsiT0C); + auto v2CEP = std::cos(2.0 * cascminuspsiT0C); ROOT::Math::XYZVector cascUvec{std::cos(casc.phi()), std::sin(casc.phi()), 0}; auto v1SP_ZDCA = cascUvec.Dot(spectatorplaneVecZDCA); auto v1SP_ZDCC = cascUvec.Dot(spectatorplaneVecZDCC); - auto v1EP_ZDCA = TMath::Cos(casc.phi() - coll.psiZDCA()); - auto v1EP_ZDCC = TMath::Cos(casc.phi() - coll.psiZDCC()); + auto v1EP_ZDCA = std::cos(casc.phi() - coll.psiZDCA()); + auto v1EP_ZDCC = std::cos(casc.phi() - coll.psiZDCC()); float v1SP = 0.5 * (v1SP_ZDCA - v1SP_ZDCC); float v1EP = 0.5 * (v1EP_ZDCA - v1EP_ZDCC); // same as v1SP @@ -906,20 +1050,20 @@ struct cascadeFlow { } auto boostedProton{lambdaBoost(protonVector)}; cosThetaStarProton = boostedProton.Pz() / boostedProton.P(); - for (int i{0}; i < 2; ++i) { + for (int i{0}; i < nParticles; ++i) { cascadeVector[i].SetCoordinates(casc.px(), casc.py(), casc.pz(), masses[i]); ROOT::Math::Boost cascadeBoost{cascadeVector[i].BoostToCM()}; auto boostedLambda{cascadeBoost(lambdaVector)}; cosThetaStarLambda[i] = boostedLambda.Pz() / boostedLambda.P(); } - double ptLambda = sqrt(pow(casc.pxlambda(), 2) + pow(casc.pylambda(), 2)); + double ptLambda = std::sqrt(std::pow(casc.pxlambda(), 2) + std::pow(casc.pylambda(), 2)); auto etaLambda = RecoDecay::eta(std::array{casc.pxlambda(), casc.pylambda(), casc.pzlambda()}); // acceptance values if requested - double MeanCos2ThetaLambdaFromXi = 1; - double MeanCos2ThetaLambdaFromOmega = 1; - double MeanCos2ThetaProtonFromLambda = 1; + double meanCos2ThetaLambdaFromXi = 1; + double meanCos2ThetaLambdaFromOmega = 1; + double meanCos2ThetaProtonFromLambda = 1; if (applyAcceptanceCorrection) { if (ptLambda < CandidateConfigs.MinPtLambda || ptLambda > CandidateConfigs.MaxPtLambda) { continue; @@ -931,24 +1075,24 @@ struct cascadeFlow { int bin2DXi = hAcceptanceXi->FindBin(casc.pt(), casc.eta()); int bin2DOmega = hAcceptanceOmega->FindBin(casc.pt(), casc.eta()); int bin2DLambda = hAcceptanceLambda->FindBin(ptLambda, etaLambda); - MeanCos2ThetaLambdaFromXi = hAcceptanceXi->GetBinContent(bin2DXi); - MeanCos2ThetaLambdaFromOmega = hAcceptanceOmega->GetBinContent(bin2DOmega); - MeanCos2ThetaProtonFromLambda = hAcceptanceLambda->GetBinContent(bin2DLambda); + meanCos2ThetaLambdaFromXi = hAcceptanceXi->GetBinContent(bin2DXi); + meanCos2ThetaLambdaFromOmega = hAcceptanceOmega->GetBinContent(bin2DOmega); + meanCos2ThetaProtonFromLambda = hAcceptanceLambda->GetBinContent(bin2DLambda); } - int ChargeIndex = 0; + int chargeIndex = 0; if (casc.sign() > 0) - ChargeIndex = 1; - double Pzs2Xi = cosThetaStarLambda[0] * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaXi[ChargeIndex] / MeanCos2ThetaLambdaFromXi; - double Pzs2Omega = cosThetaStarLambda[1] * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaOmega[ChargeIndex] / MeanCos2ThetaLambdaFromOmega; - double Cos2ThetaXi = cosThetaStarLambda[0] * cosThetaStarLambda[0]; - double Cos2ThetaOmega = cosThetaStarLambda[1] * cosThetaStarLambda[1]; - double Pzs2LambdaFromCasc = cosThetaStarProton * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaLambda[ChargeIndex] / MeanCos2ThetaProtonFromLambda; - double Cos2ThetaLambda = cosThetaStarProton * cosThetaStarProton; - - double CosThetaXiWithAlpha = cosThetaStarLambda[0] / cascadev2::AlphaXi[ChargeIndex]; - double CosThetaOmegaWithAlpha = cosThetaStarLambda[1] / cascadev2::AlphaOmega[ChargeIndex]; - double CosThetaProtonWithAlpha = cosThetaStarProton / cascadev2::AlphaLambda[ChargeIndex]; + chargeIndex = 1; + double pzs2Xi = cosThetaStarLambda[0] * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaXi[chargeIndex] / meanCos2ThetaLambdaFromXi; + double pzs2Omega = cosThetaStarLambda[1] * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaOmega[chargeIndex] / meanCos2ThetaLambdaFromOmega; + double cos2ThetaXi = cosThetaStarLambda[0] * cosThetaStarLambda[0]; + double cos2ThetaOmega = cosThetaStarLambda[1] * cosThetaStarLambda[1]; + double pzs2LambdaFromCasc = cosThetaStarProton * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaLambda[chargeIndex] / meanCos2ThetaProtonFromLambda; + double cos2ThetaLambda = cosThetaStarProton * cosThetaStarProton; + + double cosThetaXiWithAlpha = cosThetaStarLambda[0] / cascadev2::AlphaXi[chargeIndex]; + double cosThetaOmegaWithAlpha = cosThetaStarLambda[1] / cascadev2::AlphaOmega[chargeIndex]; + double cosThetaProtonWithAlpha = cosThetaStarProton / cascadev2::AlphaLambda[chargeIndex]; histos.fill(HIST("hv2CEPvsFT0C"), coll.centFT0C(), v2CEP); histos.fill(HIST("hv2CEPvsv2CSP"), v2CSP, v2CEP); @@ -966,7 +1110,7 @@ struct cascadeFlow { cascadev2::hSparseV2C[0]->Fill(values); } - float BDTresponse[2]{0.f, 0.f}; + float BDTresponse[nParticles]{0.f, 0.f}; if (isApplyML) { BDTresponse[0] = bdtScore[0][1]; BDTresponse[1] = bdtScore[1][1]; @@ -975,73 +1119,73 @@ struct cascadeFlow { if (std::abs(casc.eta()) < CandidateConfigs.etaCasc) { if (fillingConfigs.isFillTHNXi) { if (fillingConfigs.isFillTHN_V2) - histos.get(HIST("hXiV2"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], v2CEP); + histos.get(HIST("hXiV2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], v2CEP); if (fillingConfigs.isFillTHN_Pz) - histos.get(HIST("hXiPzs2"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], Pzs2Xi); + histos.get(HIST("hXiPzs2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], pzs2Xi); if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { if (fillingConfigs.isFillTHN_PzFromLambda) - histos.get(HIST("hXiPzs2FromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], Pzs2LambdaFromCasc); + histos.get(HIST("hXiPzs2FromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], pzs2LambdaFromCasc); } if (fillingConfigs.isFillTHN_Acc) - histos.get(HIST("hXiCos2Theta"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], Cos2ThetaXi); + histos.get(HIST("hXiCos2Theta"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaXi); if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) - histos.get(HIST("hXiCos2ThetaFromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], Cos2ThetaLambda); + histos.get(HIST("hXiCos2ThetaFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaLambda); if (casc.mXi() > CandidateConfigs.MinXiMass && casc.mXi() < CandidateConfigs.MaxXiMass) { if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) - histos.get(HIST("hXiCos2ThetaFromLambdaL"))->Fill(coll.centFT0C(), ChargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[0], Cos2ThetaLambda); + histos.get(HIST("hXiCos2ThetaFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[0], cos2ThetaLambda); histos.get(HIST("massXi_ProtonAcc"))->Fill(casc.mXi()); } } if (fillingConfigs.isFillTHNXi_PzVsPsi) { if (fillingConfigs.isFillTHN_Pz) - histos.get(HIST("hXiPzVsPsi"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], CosThetaXiWithAlpha, 2 * cascminuspsiT0C); + histos.get(HIST("hXiPzVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], cosThetaXiWithAlpha, 2 * cascminuspsiT0C); if (fillingConfigs.isFillTHN_PzFromLambda) - histos.get(HIST("hXiPzVsPsiFromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], CosThetaProtonWithAlpha, 2 * cascminuspsiT0C); + histos.get(HIST("hXiPzVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], cosThetaProtonWithAlpha, 2 * cascminuspsiT0C); if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { if (fillingConfigs.isFillTHN_Acc) - histos.get(HIST("hXiCos2ThetaVsPsi"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], Cos2ThetaXi, 2 * cascminuspsiT0C); + histos.get(HIST("hXiCos2ThetaVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaXi, 2 * cascminuspsiT0C); } if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) - histos.get(HIST("hXiCos2ThetaVsPsiFromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], Cos2ThetaLambda, 2 * cascminuspsiT0C); + histos.get(HIST("hXiCos2ThetaVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaLambda, 2 * cascminuspsiT0C); if (casc.mXi() > CandidateConfigs.MinXiMass && casc.mXi() < CandidateConfigs.MaxXiMass) { if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) - histos.get(HIST("hXiCos2ThetaVsPsiFromLambdaL"))->Fill(coll.centFT0C(), ChargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[0], Cos2ThetaLambda, 2 * cascminuspsiT0C); + histos.get(HIST("hXiCos2ThetaVsPsiFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[0], cos2ThetaLambda, 2 * cascminuspsiT0C); histos.get(HIST("massXi_ProtonAcc"))->Fill(casc.mXi()); } } if (fillingConfigs.isFillTHNOmega) { if (fillingConfigs.isFillTHN_V2) - histos.get(HIST("hOmegaV2"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], v2CEP); + histos.get(HIST("hOmegaV2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], v2CEP); if (fillingConfigs.isFillTHN_Pz) - histos.get(HIST("hOmegaPzs2"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], Pzs2Omega); + histos.get(HIST("hOmegaPzs2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], pzs2Omega); if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { if (fillingConfigs.isFillTHN_PzFromLambda) - histos.get(HIST("hOmegaPzs2FromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], Pzs2LambdaFromCasc); + histos.get(HIST("hOmegaPzs2FromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], pzs2LambdaFromCasc); } if (fillingConfigs.isFillTHN_Acc) - histos.get(HIST("hOmegaCos2Theta"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], Cos2ThetaOmega); + histos.get(HIST("hOmegaCos2Theta"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaOmega); if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) - histos.get(HIST("hOmegaCos2ThetaFromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], Cos2ThetaLambda); + histos.get(HIST("hOmegaCos2ThetaFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaLambda); if (casc.mOmega() > CandidateConfigs.MinOmegaMass && casc.mOmega() < CandidateConfigs.MaxOmegaMass) { if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) - histos.get(HIST("hOmegaCos2ThetaFromLambdaL"))->Fill(coll.centFT0C(), ChargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[1], Cos2ThetaLambda); + histos.get(HIST("hOmegaCos2ThetaFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[1], cos2ThetaLambda); histos.get(HIST("massOmega_ProtonAcc"))->Fill(casc.mOmega()); } } if (fillingConfigs.isFillTHNOmega_PzVsPsi) { if (fillingConfigs.isFillTHN_Pz) - histos.get(HIST("hOmegaPzVsPsi"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], CosThetaOmegaWithAlpha, 2 * cascminuspsiT0C); + histos.get(HIST("hOmegaPzVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], cosThetaOmegaWithAlpha, 2 * cascminuspsiT0C); if (fillingConfigs.isFillTHN_PzFromLambda) - histos.get(HIST("hOmegaPzVsPsiFromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], CosThetaProtonWithAlpha, 2 * cascminuspsiT0C); + histos.get(HIST("hOmegaPzVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], cosThetaProtonWithAlpha, 2 * cascminuspsiT0C); if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { if (fillingConfigs.isFillTHN_Acc) - histos.get(HIST("hOmegaCos2ThetaVsPsi"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], Cos2ThetaOmega, 2 * cascminuspsiT0C); + histos.get(HIST("hOmegaCos2ThetaVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaOmega, 2 * cascminuspsiT0C); } if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) - histos.get(HIST("hOmegaCos2ThetaVsPsiFromLambda"))->Fill(coll.centFT0C(), ChargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], Cos2ThetaLambda, 2 * cascminuspsiT0C); + histos.get(HIST("hOmegaCos2ThetaVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaLambda, 2 * cascminuspsiT0C); if (casc.mOmega() > CandidateConfigs.MinOmegaMass && casc.mOmega() < CandidateConfigs.MaxOmegaMass) { if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) - histos.get(HIST("hOmegaCos2ThetaVsPsiFromLambdaL"))->Fill(coll.centFT0C(), ChargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[1], Cos2ThetaLambda, 2 * cascminuspsiT0C); + histos.get(HIST("hOmegaCos2ThetaVsPsiFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[1], cos2ThetaLambda, 2 * cascminuspsiT0C); histos.get(HIST("massOmega_ProtonAcc"))->Fill(casc.mOmega()); } } @@ -1054,7 +1198,7 @@ struct cascadeFlow { } } - void processAnalyseDataEPCentralFW(CollEventPlaneCentralFW const& coll, CascCandidates const& Cascades, DauTracks const&) + void processAnalyseDataEP2CentralFW(CollEventPlaneCentralFW const& coll, CascCandidates const& Cascades, DauTracks const&) { if (!AcceptEvent(coll, 1)) { @@ -1063,14 +1207,450 @@ struct cascadeFlow { // select only events used for the calibration of the event plane if (isGoodEventEP) { - if (abs(coll.qvecFT0CRe()) > 990 || abs(coll.qvecFT0CIm()) > 990 || abs(coll.qvecBNegRe()) > 990 || abs(coll.qvecBNegIm()) > 990 || abs(coll.qvecBPosRe()) > 990 || abs(coll.qvecBPosIm()) > 990) { + if (std::abs(coll.qvecFT0CRe()) > 990 || std::abs(coll.qvecFT0CIm()) > 990 || std::abs(coll.qvecBNegRe()) > 990 || std::abs(coll.qvecBNegIm()) > 990 || std::abs(coll.qvecBPosRe()) > 990 || std::abs(coll.qvecBPosIm()) > 990) { return; } } - // event has event plane + // event has FT0C event plane bool hasEventPlane = 0; - if (abs(coll.qvecFT0CRe()) > 990 || abs(coll.qvecFT0CIm()) > 990 || abs(coll.qvecBNegRe()) > 990 || abs(coll.qvecBNegIm()) > 990 || abs(coll.qvecBPosRe()) > 990 || abs(coll.qvecBPosIm()) > 990) + if (std::abs(coll.qvecFT0CRe()) < 990 && std::abs(coll.qvecFT0CIm()) < 990) + hasEventPlane = 1; + + histos.fill(HIST("hNEvents"), 9.5); + histos.fill(HIST("hEventNchCorrelationAfterEP"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); + histos.fill(HIST("hEventPVcontributorsVsCentralityAfterEP"), coll.centFT0C(), coll.multNTracksPVeta1()); + histos.fill(HIST("hEventGlobalTracksVsCentralityAfterEP"), coll.centFT0C(), coll.multNTracksGlobal()); + + histos.fill(HIST("hEventCentrality"), coll.centFT0C()); + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + + ROOT::Math::XYZVector eventplaneVecT0C{coll.qvecFT0CRe(), coll.qvecFT0CIm(), 0}; + ROOT::Math::XYZVector eventplaneVecTPCA{coll.qvecBPosRe(), coll.qvecBPosIm(), 0}; + ROOT::Math::XYZVector eventplaneVecTPCC{coll.qvecBNegRe(), coll.qvecBNegIm(), 0}; + + const float PsiT0C = std::atan2(coll.qvecFT0CIm(), coll.qvecFT0CRe()) * 0.5f; + histos.fill(HIST("hPsiT0C"), PsiT0C); + histos.fill(HIST("hPsiT0CvsCentFT0C"), coll.centFT0C(), PsiT0C); + + resolution.fill(HIST("QVectorsT0CTPCA"), eventplaneVecT0C.Dot(eventplaneVecTPCA), coll.centFT0C()); + resolution.fill(HIST("QVectorsT0CTPCC"), eventplaneVecT0C.Dot(eventplaneVecTPCC), coll.centFT0C()); + resolution.fill(HIST("QVectorsTPCAC"), eventplaneVecTPCA.Dot(eventplaneVecTPCC), coll.centFT0C()); + resolution.fill(HIST("QVectorsNormT0CTPCA"), eventplaneVecT0C.Dot(eventplaneVecTPCA) / (coll.qTPCR() * coll.sumAmplFT0C()), coll.centFT0C()); + resolution.fill(HIST("QVectorsNormT0CTPCC"), eventplaneVecT0C.Dot(eventplaneVecTPCC) / (coll.qTPCL() * coll.sumAmplFT0C()), coll.centFT0C()); + resolution.fill(HIST("QVectorsNormTPCAC"), eventplaneVecTPCA.Dot(eventplaneVecTPCC) / (coll.qTPCR() * coll.qTPCL()), coll.centFT0C()); + + std::vector bdtScore[nParticles]; + for (auto const& casc : Cascades) { + + /// Add some minimal cuts for single track variables (min number of TPC clusters) + auto negExtra = casc.negTrackExtra_as(); + auto posExtra = casc.posTrackExtra_as(); + auto bachExtra = casc.bachTrackExtra_as(); + + int counter = 0; + bool isCascCandidate = 0; + isCascCandidate = IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); + histos.fill(HIST("hCascade"), counter); + histos.fill(HIST("hCascadeDauSel"), (int)isCascCandidate); + if (!isCascCandidate) + continue; + + // ML selections + bool isSelectedCasc[nParticles]{false, false}; + + std::vector inputFeaturesCasc{casc.cascradius(), + casc.v0radius(), + casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()), + casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()), + casc.dcapostopv(), + casc.dcanegtopv(), + casc.dcabachtopv(), + casc.dcacascdaughters(), + casc.dcaV0daughters(), + casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ()), + casc.bachBaryonCosPA(), + casc.bachBaryonDCAxyToPV()}; + + float massCasc[nParticles]{casc.mXi(), casc.mOmega()}; + + // pt cut + if (casc.pt() < CandidateConfigs.MinPt || casc.pt() > CandidateConfigs.MaxPt) { + continue; + } + + cascadev2::hMassBeforeSelVsPt[0]->Fill(massCasc[0], casc.pt()); + cascadev2::hMassBeforeSelVsPt[1]->Fill(massCasc[1], casc.pt()); + + if (isApplyML) { + // Retrieve model output and selection outcome + isSelectedCasc[0] = mlResponseXi.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[0]); + isSelectedCasc[1] = mlResponseOmega.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[1]); + + for (int iS{0}; iS < nParticles; ++iS) { + // Fill BDT score histograms before selection + cascadev2::hSignalScoreBeforeSel[iS]->Fill(bdtScore[0][1]); + cascadev2::hBkgScoreBeforeSel[iS]->Fill(bdtScore[1][0]); + + // Fill histograms for selected candidates + if (isSelectedCasc[iS]) { + cascadev2::hSignalScoreAfterSel[iS]->Fill(bdtScore[0][1]); + cascadev2::hBkgScoreAfterSel[iS]->Fill(bdtScore[1][0]); + cascadev2::hMassAfterSelVsPt[iS]->Fill(massCasc[iS], casc.pt()); + } + } + } else { + isSelectedCasc[0] = true; + isSelectedCasc[1] = true; + } + + ROOT::Math::XYZVector cascQvec{std::cos(2 * casc.phi()), std::sin(2 * casc.phi()), 0}; + auto v2CSP = cascQvec.Dot(eventplaneVecT0C); // not normalised by amplitude + auto cascminuspsiT0C = GetPhiInRange(casc.phi() - PsiT0C); + auto v2CEP = std::cos(2.0 * cascminuspsiT0C); + ROOT::Math::XYZVector cascUvec{std::cos(casc.phi()), std::sin(casc.phi()), 0}; + + // polarization variables + double masses[nParticles]{o2::constants::physics::MassXiMinus, o2::constants::physics::MassOmegaMinus}; + ROOT::Math::PxPyPzMVector cascadeVector[nParticles], lambdaVector, protonVector; + float cosThetaStarLambda[nParticles], cosThetaStarProton; + lambdaVector.SetCoordinates(casc.pxlambda(), casc.pylambda(), casc.pzlambda(), o2::constants::physics::MassLambda); + ROOT::Math::Boost lambdaBoost{lambdaVector.BoostToCM()}; + if (casc.sign() > 0) { + protonVector.SetCoordinates(casc.pxneg(), casc.pyneg(), casc.pzneg(), o2::constants::physics::MassProton); + } else { + protonVector.SetCoordinates(casc.pxpos(), casc.pypos(), casc.pzpos(), o2::constants::physics::MassProton); + } + auto boostedProton{lambdaBoost(protonVector)}; + cosThetaStarProton = boostedProton.Pz() / boostedProton.P(); + for (int i{0}; i < nParticles; ++i) { + cascadeVector[i].SetCoordinates(casc.px(), casc.py(), casc.pz(), masses[i]); + ROOT::Math::Boost cascadeBoost{cascadeVector[i].BoostToCM()}; + auto boostedLambda{cascadeBoost(lambdaVector)}; + cosThetaStarLambda[i] = boostedLambda.Pz() / boostedLambda.P(); + } + + double ptLambda = std::sqrt(std::pow(casc.pxlambda(), 2) + std::pow(casc.pylambda(), 2)); + auto etaLambda = RecoDecay::eta(std::array{casc.pxlambda(), casc.pylambda(), casc.pzlambda()}); + + // acceptance values if requested + double meanCos2ThetaLambdaFromXi = 1; + double meanCos2ThetaLambdaFromOmega = 1; + double meanCos2ThetaProtonFromLambda = 1; + if (applyAcceptanceCorrection) { + if (ptLambda < CandidateConfigs.MinPtLambda || ptLambda > CandidateConfigs.MaxPtLambda) { + continue; + } + if (std::abs(casc.eta()) > CandidateConfigs.etaCasc) + continue; + if (std::abs(etaLambda) > CandidateConfigs.etaLambdaMax) + continue; + int bin2DXi = hAcceptanceXi->FindBin(casc.pt(), casc.eta()); + int bin2DOmega = hAcceptanceOmega->FindBin(casc.pt(), casc.eta()); + int bin2DLambda = hAcceptanceLambda->FindBin(ptLambda, etaLambda); + meanCos2ThetaLambdaFromXi = hAcceptanceXi->GetBinContent(bin2DXi); + meanCos2ThetaLambdaFromOmega = hAcceptanceOmega->GetBinContent(bin2DOmega); + meanCos2ThetaProtonFromLambda = hAcceptanceLambda->GetBinContent(bin2DLambda); + } + + int chargeIndex = 0; + if (casc.sign() > 0) + chargeIndex = 1; + double pzs2Xi = cosThetaStarLambda[0] * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaXi[chargeIndex] / meanCos2ThetaLambdaFromXi; + double pzs2Omega = cosThetaStarLambda[1] * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaOmega[chargeIndex] / meanCos2ThetaLambdaFromOmega; + double cos2ThetaXi = cosThetaStarLambda[0] * cosThetaStarLambda[0]; + double cos2ThetaOmega = cosThetaStarLambda[1] * cosThetaStarLambda[1]; + double pzs2LambdaFromCasc = cosThetaStarProton * std::sin(2 * (casc.phi() - PsiT0C)) / cascadev2::AlphaLambda[chargeIndex] / meanCos2ThetaProtonFromLambda; + double cos2ThetaLambda = cosThetaStarProton * cosThetaStarProton; + + double cosThetaXiWithAlpha = cosThetaStarLambda[0] / cascadev2::AlphaXi[chargeIndex]; + double cosThetaOmegaWithAlpha = cosThetaStarLambda[1] / cascadev2::AlphaOmega[chargeIndex]; + double cosThetaProtonWithAlpha = cosThetaStarProton / cascadev2::AlphaLambda[chargeIndex]; + + histos.fill(HIST("hv2CEPvsFT0C"), coll.centFT0C(), v2CEP); + histos.fill(HIST("hv2CEPvsv2CSP"), v2CSP, v2CEP); + histos.fill(HIST("hCascadePhi"), casc.phi()); + histos.fill(HIST("hcascminuspsiT0C"), cascminuspsiT0C); + + double values[4]{casc.mXi(), casc.pt(), v2CSP, coll.centFT0C()}; + if (isSelectedCasc[0]) { + cascadev2::hSparseV2C[0]->Fill(values); + } + if (isSelectedCasc[1]) { + values[0] = casc.mOmega(); + cascadev2::hSparseV2C[0]->Fill(values); + } + + float BDTresponse[nParticles]{0.f, 0.f}; + if (isApplyML) { + BDTresponse[0] = bdtScore[0][1]; + BDTresponse[1] = bdtScore[1][1]; + } + + if (std::abs(casc.eta()) < CandidateConfigs.etaCasc) { + if (fillingConfigs.isFillTHNXi) { + if (fillingConfigs.isFillTHN_V2) + histos.get(HIST("hXiV2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], v2CEP); + if (fillingConfigs.isFillTHN_Pz) + histos.get(HIST("hXiPzs2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], pzs2Xi); + if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { + if (fillingConfigs.isFillTHN_PzFromLambda) + histos.get(HIST("hXiPzs2FromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], pzs2LambdaFromCasc); + } + if (fillingConfigs.isFillTHN_Acc) + histos.get(HIST("hXiCos2Theta"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaXi); + if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) + histos.get(HIST("hXiCos2ThetaFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaLambda); + if (casc.mXi() > CandidateConfigs.MinXiMass && casc.mXi() < CandidateConfigs.MaxXiMass) { + if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) + histos.get(HIST("hXiCos2ThetaFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[0], cos2ThetaLambda); + histos.get(HIST("massXi_ProtonAcc"))->Fill(casc.mXi()); + } + } + if (fillingConfigs.isFillTHNXi_PzVsPsi) { + if (fillingConfigs.isFillTHN_Pz) + histos.get(HIST("hXiPzVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], cosThetaXiWithAlpha, 2 * cascminuspsiT0C); + if (fillingConfigs.isFillTHN_PzFromLambda) + histos.get(HIST("hXiPzVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mXi(), BDTresponse[0], cosThetaProtonWithAlpha, 2 * cascminuspsiT0C); + if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { + if (fillingConfigs.isFillTHN_Acc) + histos.get(HIST("hXiCos2ThetaVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaXi, 2 * cascminuspsiT0C); + } + if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) + histos.get(HIST("hXiCos2ThetaVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mXi(), BDTresponse[0], cos2ThetaLambda, 2 * cascminuspsiT0C); + if (casc.mXi() > CandidateConfigs.MinXiMass && casc.mXi() < CandidateConfigs.MaxXiMass) { + if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) + histos.get(HIST("hXiCos2ThetaVsPsiFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[0], cos2ThetaLambda, 2 * cascminuspsiT0C); + histos.get(HIST("massXi_ProtonAcc"))->Fill(casc.mXi()); + } + } + if (fillingConfigs.isFillTHNOmega) { + if (fillingConfigs.isFillTHN_V2) + histos.get(HIST("hOmegaV2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], v2CEP); + if (fillingConfigs.isFillTHN_Pz) + histos.get(HIST("hOmegaPzs2"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], pzs2Omega); + if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { + if (fillingConfigs.isFillTHN_PzFromLambda) + histos.get(HIST("hOmegaPzs2FromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], pzs2LambdaFromCasc); + } + if (fillingConfigs.isFillTHN_Acc) + histos.get(HIST("hOmegaCos2Theta"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaOmega); + if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) + histos.get(HIST("hOmegaCos2ThetaFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaLambda); + if (casc.mOmega() > CandidateConfigs.MinOmegaMass && casc.mOmega() < CandidateConfigs.MaxOmegaMass) { + if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) + histos.get(HIST("hOmegaCos2ThetaFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[1], cos2ThetaLambda); + histos.get(HIST("massOmega_ProtonAcc"))->Fill(casc.mOmega()); + } + } + if (fillingConfigs.isFillTHNOmega_PzVsPsi) { + if (fillingConfigs.isFillTHN_Pz) + histos.get(HIST("hOmegaPzVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], cosThetaOmegaWithAlpha, 2 * cascminuspsiT0C); + if (fillingConfigs.isFillTHN_PzFromLambda) + histos.get(HIST("hOmegaPzVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.pt(), casc.mOmega(), BDTresponse[1], cosThetaProtonWithAlpha, 2 * cascminuspsiT0C); + if (casc.mLambda() > CandidateConfigs.MinLambdaMass && casc.mLambda() < CandidateConfigs.MaxLambdaMass) { + if (fillingConfigs.isFillTHN_Acc) + histos.get(HIST("hOmegaCos2ThetaVsPsi"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaOmega, 2 * cascminuspsiT0C); + } + if (fillingConfigs.isFillTHN_AccFromLambdaVsCasc) + histos.get(HIST("hOmegaCos2ThetaVsPsiFromLambda"))->Fill(coll.centFT0C(), chargeIndex, casc.eta(), casc.pt(), casc.mOmega(), BDTresponse[1], cos2ThetaLambda, 2 * cascminuspsiT0C); + if (casc.mOmega() > CandidateConfigs.MinOmegaMass && casc.mOmega() < CandidateConfigs.MaxOmegaMass) { + if (fillingConfigs.isFillTHN_AccFromLambdaVsLambda) + histos.get(HIST("hOmegaCos2ThetaVsPsiFromLambdaL"))->Fill(coll.centFT0C(), chargeIndex, etaLambda, ptLambda, casc.mLambda(), BDTresponse[1], cos2ThetaLambda, 2 * cascminuspsiT0C); + histos.get(HIST("massOmega_ProtonAcc"))->Fill(casc.mOmega()); + } + } + } + + if (isSelectedCasc[0] || isSelectedCasc[1]) { + if (fillingConfigs.isFillTree) + fillAnalysedTable(coll, hasEventPlane, 0, casc, v2CSP, v2CEP, 0, 0, PsiT0C, BDTresponse[0], BDTresponse[1], 0); + } + } + } + + void processAnalyseLambdaEP2CentralFW(CollEventPlaneCentralFW const& coll, V0Candidates const& V0s, DauTracks const&) + { + + if (!AcceptEvent(coll, 1)) { + return; + } + + // select only events used for the calibration of the event plane + if (isGoodEventEP) { + if (std::abs(coll.qvecFT0CRe()) > 990 || std::abs(coll.qvecFT0CIm()) > 990 || std::abs(coll.qvecBNegRe()) > 990 || std::abs(coll.qvecBNegIm()) > 990 || std::abs(coll.qvecBPosRe()) > 990 || std::abs(coll.qvecBPosIm()) > 990) { + return; + } + } + + histos.fill(HIST("hNEvents"), 9.5); + histos.fill(HIST("hEventNchCorrelationAfterEP"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); + histos.fill(HIST("hEventPVcontributorsVsCentralityAfterEP"), coll.centFT0C(), coll.multNTracksPVeta1()); + histos.fill(HIST("hEventGlobalTracksVsCentralityAfterEP"), coll.centFT0C(), coll.multNTracksGlobal()); + + histos.fill(HIST("hEventCentrality"), coll.centFT0C()); + histos.fill(HIST("hEventVertexZ"), coll.posZ()); + + ROOT::Math::XYZVector eventplaneVecT0C{coll.qvecFT0CRe(), coll.qvecFT0CIm(), 0}; + ROOT::Math::XYZVector eventplaneVecTPCA{coll.qvecBPosRe(), coll.qvecBPosIm(), 0}; + ROOT::Math::XYZVector eventplaneVecTPCC{coll.qvecBNegRe(), coll.qvecBNegIm(), 0}; + + const float psiT0C = std::atan2(coll.qvecFT0CIm(), coll.qvecFT0CRe()) * 0.5f; + histos.fill(HIST("hPsiT0C"), psiT0C); + histos.fill(HIST("hPsiT0CvsCentFT0C"), coll.centFT0C(), psiT0C); + + resolution.fill(HIST("QVectorsT0CTPCA"), eventplaneVecT0C.Dot(eventplaneVecTPCA), coll.centFT0C()); + resolution.fill(HIST("QVectorsT0CTPCC"), eventplaneVecT0C.Dot(eventplaneVecTPCC), coll.centFT0C()); + resolution.fill(HIST("QVectorsTPCAC"), eventplaneVecTPCA.Dot(eventplaneVecTPCC), coll.centFT0C()); + resolution.fill(HIST("QVectorsNormT0CTPCA"), eventplaneVecT0C.Dot(eventplaneVecTPCA) / (coll.qTPCR() * coll.sumAmplFT0C()), coll.centFT0C()); + resolution.fill(HIST("QVectorsNormT0CTPCC"), eventplaneVecT0C.Dot(eventplaneVecTPCC) / (coll.qTPCL() * coll.sumAmplFT0C()), coll.centFT0C()); + resolution.fill(HIST("QVectorsNormTPCAC"), eventplaneVecTPCA.Dot(eventplaneVecTPCC) / (coll.qTPCR() * coll.qTPCL()), coll.centFT0C()); + + std::vector bdtScore[nParticles]; + 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; + if (isLambdaAccepted(negExtra, posExtra, counterLambda)) + isLambdaCandidate = 1; + if (isAntiLambdaAccepted(negExtra, posExtra, counterALambda)) + isALambdaCandidate = 1; + histos.fill(HIST("hLambdaDauSel"), counterLambda); + histos.fill(HIST("hALambdaDauSel"), counterALambda); + + // pt cut + 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; + + int chargeIndex = -1; + if (isSelectedV0[0] && !isSelectedV0[1]) { // Lambdas + histos.fill(HIST("hLambdaCandidate"), 0); + chargeIndex = 0; + } + if (isSelectedV0[1] && !isSelectedV0[0]) { // AntiLambdas + histos.fill(HIST("hLambdaCandidate"), 1); + chargeIndex = 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) + chargeIndex = 0; + else if (v0.mAntiLambda() > V0Configs.MinMassLambda && v0.mAntiLambda() < V0Configs.MaxMassLambda) + chargeIndex = 1; + else { + chargeIndex = 2; // these are bkg candidates + histos.fill(HIST("hLambdaCandidate"), 4); + } + } + if (!isSelectedV0[0] && !isSelectedV0[1]) + continue; + + 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() - psiT0C); + auto v2CEP = std::cos(2.0 * lambdaminuspsiT0C); + ROOT::Math::XYZVector lambdaUvec{std::cos(v0.phi()), std::sin(v0.phi()), 0}; + + // polarization variables + double massLambda = o2::constants::physics::MassLambda; + float cosThetaStarProton[nCharges]; + ROOT::Math::PxPyPzMVector lambdaVector, protonVector[nCharges]; + lambdaVector.SetCoordinates(v0.px(), v0.py(), v0.pz(), massLambda); + ROOT::Math::Boost lambdaBoost{lambdaVector.BoostToCM()}; + for (int i{0}; i < nCharges; ++i) { + if (i == 0) + protonVector[i].SetCoordinates(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassProton); + else + protonVector[i].SetCoordinates(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassProton); + auto boostedProton{lambdaBoost(protonVector[i])}; + cosThetaStarProton[i] = boostedProton.Pz() / boostedProton.P(); + } + + // acceptance values if requested + double meanCos2ThetaProtonFromLambda = 1; + if (applyAcceptanceCorrection) { + int bin2DLambda = hAcceptanceLambda->FindBin(v0.pt(), v0.eta()); + meanCos2ThetaProtonFromLambda = hAcceptancePrimaryLambda->GetBinContent(bin2DLambda); + } + + double pzs2Lambda = 0; + double cos2ThetaLambda = 0; + double cosThetaLambda = 0; + if (chargeIndex == 0) { + pzs2Lambda = cosThetaStarProton[0] * std::sin(2 * (v0.phi() - psiT0C)) / lambdav2::AlphaLambda[0] / meanCos2ThetaProtonFromLambda; + cos2ThetaLambda = cosThetaStarProton[0] * cosThetaStarProton[0]; + cosThetaLambda = cosThetaStarProton[0] / cascadev2::AlphaLambda[0] / meanCos2ThetaProtonFromLambda; + } else if (chargeIndex == 1) { + pzs2Lambda = cosThetaStarProton[1] * std::sin(2 * (v0.phi() - psiT0C)) / lambdav2::AlphaLambda[1] / meanCos2ThetaProtonFromLambda; + cos2ThetaLambda = cosThetaStarProton[1] * cosThetaStarProton[1]; + cosThetaLambda = cosThetaStarProton[1] / cascadev2::AlphaLambda[1] / meanCos2ThetaProtonFromLambda; + } else { // I treat these bkg candidates as Lambdas for the purpose of calculating Pz + pzs2Lambda = cosThetaStarProton[0] * std::sin(2 * (v0.phi() - psiT0C)) / lambdav2::AlphaLambda[0] / meanCos2ThetaProtonFromLambda; + cos2ThetaLambda = cosThetaStarProton[0] * cosThetaStarProton[0]; + cosThetaLambda = cosThetaStarProton[0] / cascadev2::AlphaLambda[0] / meanCos2ThetaProtonFromLambda; + } + + histos.fill(HIST("hv2CEPvsFT0C"), coll.centFT0C(), v2CEP); + histos.fill(HIST("hv2CEPvsv2CSP"), v2CSP, v2CEP); + histos.fill(HIST("hLambdaPhi"), v0.phi()); + histos.fill(HIST("hlambdaminuspsiT0C"), lambdaminuspsiT0C); + + if (fillingConfigs.isFillTHNLambda) { + if (fillingConfigs.isFillTHN_V2) + histos.get(HIST("hLambdaV2"))->Fill(coll.centFT0C(), chargeIndex, v0.pt(), v0.mLambda(), v2CEP); + if (fillingConfigs.isFillTHN_Pz) { + histos.get(HIST("hLambdaPzs2"))->Fill(coll.centFT0C(), chargeIndex, v0.pt(), v0.mLambda(), pzs2Lambda); + } + if (fillingConfigs.isFillTHN_Acc) + histos.get(HIST("hLambdaCos2Theta"))->Fill(coll.centFT0C(), chargeIndex, v0.eta(), v0.pt(), v0.mLambda(), cos2ThetaLambda); + } + if (fillingConfigs.isFillTHNLambda_PzVsPsi) { + if (fillingConfigs.isFillTHN_Pz) + histos.get(HIST("hLambdaPzVsPsi"))->Fill(coll.centFT0C(), chargeIndex, v0.pt(), v0.mLambda(), cosThetaLambda, 2 * lambdaminuspsiT0C); + if (fillingConfigs.isFillTHN_Acc) + histos.get(HIST("hLambdaCos2ThetaVsPsi"))->Fill(coll.centFT0C(), chargeIndex, v0.eta(), v0.pt(), v0.mLambda(), cos2ThetaLambda, 2 * lambdaminuspsiT0C); + } + } + } + + void processAnalyseDataEPCentralFW(CollEventAndSpecPlaneCentralFW const& coll, CascCandidates const& Cascades, DauTracks const&) + { + + if (!AcceptEvent(coll, 1)) { + return; + } + + // select only events used for the calibration of the event plane + if (isGoodEventEP) { + if (std::abs(coll.qvecFT0CRe()) > 990 || std::abs(coll.qvecFT0CIm()) > 990 || std::abs(coll.qvecBNegRe()) > 990 || std::abs(coll.qvecBNegIm()) > 990 || std::abs(coll.qvecBPosRe()) > 990 || std::abs(coll.qvecBPosIm()) > 990) { + return; + } + } + + // event has FT0C event plane + bool hasEventPlane = 0; + if (std::abs(coll.qvecFT0CRe()) < 990 && std::abs(coll.qvecFT0CIm()) < 990) hasEventPlane = 1; // event has spectator plane @@ -1092,9 +1672,9 @@ struct cascadeFlow { ROOT::Math::XYZVector spectatorplaneVecZDCA{std::cos(coll.psiZDCA()), std::sin(coll.psiZDCA()), 0}; // eta positive = projectile ROOT::Math::XYZVector spectatorplaneVecZDCC{std::cos(coll.psiZDCC()), std::sin(coll.psiZDCC()), 0}; // eta negative = target - float NormQvT0C = sqrt(eventplaneVecT0C.Dot(eventplaneVecT0C)); - float NormQvTPCA = sqrt(eventplaneVecTPCA.Dot(eventplaneVecTPCA)); - float NormQvTPCC = sqrt(eventplaneVecTPCC.Dot(eventplaneVecTPCC)); + float NormQvT0C = std::sqrt(eventplaneVecT0C.Dot(eventplaneVecT0C)); + float NormQvTPCA = std::sqrt(eventplaneVecTPCA.Dot(eventplaneVecTPCA)); + float NormQvTPCC = std::sqrt(eventplaneVecTPCC.Dot(eventplaneVecTPCC)); const float PsiT0C = std::atan2(coll.qvecFT0CIm(), coll.qvecFT0CRe()) * 0.5f; histos.fill(HIST("hPsiT0C"), PsiT0C); @@ -1108,8 +1688,8 @@ struct cascadeFlow { resolution.fill(HIST("QVectorsNormTPCAC"), eventplaneVecTPCA.Dot(eventplaneVecTPCC) / (NormQvTPCA * NormQvTPCC), coll.centFT0C()); resolution.fill(HIST("QVectorsSpecPlane"), spectatorplaneVecZDCC.Dot(spectatorplaneVecZDCA), coll.centFT0C()); - std::vector bdtScore[2]; - for (auto& casc : Cascades) { + std::vector bdtScore[nParticles]; + for (auto const& casc : Cascades) { /// Add some minimal cuts for single track variables (min number of TPC clusters) auto negExtra = casc.negTrackExtra_as(); @@ -1117,11 +1697,15 @@ struct cascadeFlow { auto bachExtra = casc.bachTrackExtra_as(); int counter = 0; - IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); + bool isCascCandidate = 0; + isCascCandidate = IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); histos.fill(HIST("hCascade"), counter); + histos.fill(HIST("hCascadeDauSel"), (int)isCascCandidate); + if (!isCascCandidate) + continue; // ML selections - bool isSelectedCasc[2]{false, false}; + bool isSelectedCasc[nParticles]{false, false}; std::vector inputFeaturesCasc{casc.cascradius(), casc.v0radius(), @@ -1136,7 +1720,7 @@ struct cascadeFlow { casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV()}; - float massCasc[2]{casc.mXi(), casc.mOmega()}; + float massCasc[nParticles]{casc.mXi(), casc.mOmega()}; // inv mass loose cut if (casc.pt() < CandidateConfigs.MinPt || casc.pt() > CandidateConfigs.MaxPt) { @@ -1151,7 +1735,7 @@ struct cascadeFlow { isSelectedCasc[0] = mlResponseXi.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[0]); isSelectedCasc[1] = mlResponseOmega.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[1]); - for (int iS{0}; iS < 2; ++iS) { + for (int iS{0}; iS < nParticles; ++iS) { // Fill BDT score histograms before selection cascadev2::hSignalScoreBeforeSel[iS]->Fill(bdtScore[0][1]); cascadev2::hBkgScoreBeforeSel[iS]->Fill(bdtScore[1][0]); @@ -1171,12 +1755,12 @@ struct cascadeFlow { ROOT::Math::XYZVector cascQvec{std::cos(2 * casc.phi()), std::sin(2 * casc.phi()), 0}; auto v2CSP = cascQvec.Dot(eventplaneVecT0C); auto cascminuspsiT0C = GetPhiInRange(casc.phi() - PsiT0C); - auto v2CEP = TMath::Cos(2.0 * cascminuspsiT0C); + auto v2CEP = std::cos(2.0 * cascminuspsiT0C); ROOT::Math::XYZVector cascUvec{std::cos(casc.phi()), std::sin(casc.phi()), 0}; auto v1SP_ZDCA = cascUvec.Dot(spectatorplaneVecZDCA); auto v1SP_ZDCC = cascUvec.Dot(spectatorplaneVecZDCC); - auto v1EP_ZDCA = TMath::Cos(casc.phi() - coll.psiZDCA()); - auto v1EP_ZDCC = TMath::Cos(casc.phi() - coll.psiZDCC()); + auto v1EP_ZDCA = std::cos(casc.phi() - coll.psiZDCA()); + auto v1EP_ZDCC = std::cos(casc.phi() - coll.psiZDCC()); float v1SP = 0.5 * (v1SP_ZDCA - v1SP_ZDCC); float v1EP = 0.5 * (v1EP_ZDCA - v1EP_ZDCC); // same as v1SP @@ -1195,7 +1779,7 @@ struct cascadeFlow { cascadev2::hSparseV2C[0]->Fill(values); } - float BDTresponse[2]{0.f, 0.f}; + float BDTresponse[nParticles]{0.f, 0.f}; if (isApplyML) { BDTresponse[0] = bdtScore[0][1]; BDTresponse[1] = bdtScore[1][1]; @@ -1214,7 +1798,7 @@ struct cascadeFlow { } bool hasEventPlane = 0; // no info at the moment - bool hasSpectatorPlane = 0; // no infor at the moment + bool hasSpectatorPlane = 0; // no info at the moment histos.fill(HIST("hNEvents"), 9.5); histos.fill(HIST("hEventNchCorrelationAfterEP"), coll.multNTracksPVeta1(), coll.multNTracksGlobal()); @@ -1224,8 +1808,8 @@ struct cascadeFlow { histos.fill(HIST("hEventVertexZ"), coll.posZ()); histos.fill(HIST("hMultNTracksITSTPCVsCentrality"), coll.centFT0C(), coll.multNTracksITSTPC()); - std::vector bdtScore[2]; - for (auto& casc : Cascades) { + std::vector bdtScore[nParticles]; + for (auto const& casc : Cascades) { if (!casc.has_cascMCCore()) continue; @@ -1233,8 +1817,8 @@ struct cascadeFlow { auto cascMC = casc.cascMCCore_as>(); int pdgCode{cascMC.pdgCode()}; - if (!(std::abs(pdgCode) == 3312 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 211) // Xi - && !(std::abs(pdgCode) == 3334 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 321)) // Omega + if (!(std::abs(pdgCode) == PDG_t::kXiMinus && std::abs(cascMC.pdgCodeV0()) == PDG_t::kLambda0 && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kPiPlus) // Xi + && !(std::abs(pdgCode) == PDG_t::kOmegaMinus && std::abs(cascMC.pdgCodeV0()) == PDG_t::kLambda0 && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kKPlus)) // Omega { pdgCode = 0; } @@ -1243,13 +1827,13 @@ struct cascadeFlow { float XiY = RecoDecay::y(std::array{casc.px(), casc.py(), casc.pz()}, constants::physics::MassXiMinus); float OmegaY = RecoDecay::y(std::array{casc.px(), casc.py(), casc.pz()}, constants::physics::MassOmegaMinus); // true reco cascades before applying any selection - if (std::abs(pdgCode) == 3312 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 211) { + if (std::abs(pdgCode) == PDG_t::kXiMinus && std::abs(cascMC.pdgCodeV0()) == PDG_t::kLambda0 && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kPiPlus) { histos.fill(HIST("hXiPtvsCent"), coll.centFT0C(), casc.pt()); if (std::abs(casc.eta()) < 0.8) histos.fill(HIST("hXiPtvsCentEta08"), coll.centFT0C(), casc.pt()); if (std::abs(XiY) < 0.5) histos.fill(HIST("hXiPtvsCentY05"), coll.centFT0C(), casc.pt()); - } else if (std::abs(pdgCode) == 3334 && std::abs(cascMC.pdgCodeV0()) == 3122 && std::abs(cascMC.pdgCodeBachelor()) == 321) { + } else if (std::abs(pdgCode) == PDG_t::kOmegaMinus && std::abs(cascMC.pdgCodeV0()) == PDG_t::kLambda0 && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kKPlus) { histos.fill(HIST("hOmegaPtvsCent"), coll.centFT0C(), casc.pt()); if (std::abs(casc.eta()) < 0.8) histos.fill(HIST("hOmegaPtvsCentEta08"), coll.centFT0C(), casc.pt()); @@ -1263,11 +1847,15 @@ struct cascadeFlow { auto bachExtra = casc.bachTrackExtra_as(); int counter = 0; - IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); + bool isCascCandidate = 0; + isCascCandidate = IsCascAccepted(casc, negExtra, posExtra, bachExtra, counter); histos.fill(HIST("hCascade"), counter); + histos.fill(HIST("hCascadeDauSel"), (int)isCascCandidate); + if (!isCascCandidate) + continue; // ML selections - bool isSelectedCasc[2]{false, false}; + bool isSelectedCasc[nParticles]{false, false}; std::vector inputFeaturesCasc{casc.cascradius(), casc.v0radius(), @@ -1282,7 +1870,7 @@ struct cascadeFlow { casc.bachBaryonCosPA(), casc.bachBaryonDCAxyToPV()}; - float massCasc[2]{casc.mXi(), casc.mOmega()}; + float massCasc[nParticles]{casc.mXi(), casc.mOmega()}; if (casc.pt() < CandidateConfigs.MinPt || casc.pt() > CandidateConfigs.MaxPt) { continue; @@ -1296,7 +1884,7 @@ struct cascadeFlow { isSelectedCasc[0] = mlResponseXi.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[0]); isSelectedCasc[1] = mlResponseOmega.isSelectedMl(inputFeaturesCasc, casc.pt(), bdtScore[1]); - for (int iS{0}; iS < 2; ++iS) { + for (int iS{0}; iS < nParticles; ++iS) { // Fill BDT score histograms before selection cascadev2::hSignalScoreBeforeSel[iS]->Fill(bdtScore[0][1]); cascadev2::hBkgScoreBeforeSel[iS]->Fill(bdtScore[1][0]); @@ -1315,7 +1903,7 @@ struct cascadeFlow { histos.fill(HIST("hCascadePhi"), casc.phi()); - float BDTresponse[2]{0.f, 0.f}; + float BDTresponse[nParticles]{0.f, 0.f}; const float PsiT0C = 0; // not defined in MC for now auto v2CSP = 0; // not defined in MC for now auto v2CEP = 0; // not defined in MC for now @@ -1341,7 +1929,7 @@ struct cascadeFlow { histosMCGen.fill(HIST("hZvertexGen"), mcCollision.posZ()); histosMCGen.fill(HIST("hNEventsMC"), 0.5); // Generated with accepted z vertex - if (TMath::Abs(mcCollision.posZ()) > cutzvertex) { + if (std::abs(mcCollision.posZ()) > cutzvertex) { return; } histosMCGen.fill(HIST("hNEventsMC"), 1.5); @@ -1374,21 +1962,21 @@ struct cascadeFlow { histosMCGen.fill(HIST("hNEventsMC"), 5.5); for (auto const& cascmc : cascMC) { - if (TMath::Abs(cascmc.pdgCode()) == 3312) + if (std::abs(cascmc.pdgCode()) == PDG_t::kXiMinus) histosMCGen.fill(HIST("hNCascGen"), 0.5); - else if (TMath::Abs(cascmc.pdgCode()) == 3334) + else if (std::abs(cascmc.pdgCode()) == PDG_t::kOmegaMinus) histosMCGen.fill(HIST("hNCascGen"), 1.5); if (!cascmc.has_straMCCollision()) continue; - if (TMath::Abs(cascmc.pdgCode()) == 3312) + if (std::abs(cascmc.pdgCode()) == PDG_t::kXiMinus) histosMCGen.fill(HIST("hNCascGen"), 2.5); - else if (TMath::Abs(cascmc.pdgCode()) == 3334) + else if (std::abs(cascmc.pdgCode()) == PDG_t::kOmegaMinus) histosMCGen.fill(HIST("hNCascGen"), 3.5); if (!cascmc.isPhysicalPrimary()) continue; - if (TMath::Abs(cascmc.pdgCode()) == 3312) + if (std::abs(cascmc.pdgCode()) == PDG_t::kXiMinus) histosMCGen.fill(HIST("hNCascGen"), 4.5); - else if (TMath::Abs(cascmc.pdgCode()) == 3334) + else if (std::abs(cascmc.pdgCode()) == PDG_t::kOmegaMinus) histosMCGen.fill(HIST("hNCascGen"), 5.5); float ptmc = RecoDecay::sqrtSumOfSquares(cascmc.pxMC(), cascmc.pyMC()); @@ -1402,27 +1990,26 @@ struct cascadeFlow { theta1 = theta; // 0 < theta1/2 < pi/4 --> 0 < tan (theta1/2) < 1 --> positive eta // if pz is negative (i.e. negative rapidity): -pi/2 < theta < 0 --> we need 0 < theta1/2 < pi/2 for the ln to be defined else - theta1 = TMath::Pi() + theta; // pi/2 < theta1 < pi --> pi/4 < theta1/2 < pi/2 --> 1 < tan (theta1/2) --> negative eta + theta1 = o2::constants::math::PI + theta; // pi/2 < theta1 < pi --> pi/4 < theta1/2 < pi/2 --> 1 < tan (theta1/2) --> negative eta - float cascMCeta = -log(std::tan(theta1 / 2)); + float cascMCeta = -std::log(std::tan(theta1 / 2)); float cascMCy = 0; - - if (TMath::Abs(cascmc.pdgCode()) == 3312) { + if (std::abs(cascmc.pdgCode()) == PDG_t::kXiMinus) { cascMCy = RecoDecay::y(std::array{cascmc.pxMC(), cascmc.pyMC(), cascmc.pzMC()}, constants::physics::MassXiMinus); - if (TMath::Abs(cascMCeta) < etaCascMCGen) { + if (std::abs(cascMCeta) < etaCascMCGen) { histosMCGen.fill(HIST("h2DGenXiEta08"), centrality, ptmc); histosMCGen.fill(HIST("hNCascGen"), 6.5); } - if (TMath::Abs(cascMCy) < yCascMCGen) + if (std::abs(cascMCy) < yCascMCGen) histosMCGen.fill(HIST("h2DGenXiY05"), centrality, ptmc); histosMCGen.fill(HIST("hGenXiY"), cascMCy); - } else if (TMath::Abs(cascmc.pdgCode() == 3334)) { + } else if (std::abs(cascmc.pdgCode()) == PDG_t::kOmegaMinus) { cascMCy = RecoDecay::y(std::array{cascmc.pxMC(), cascmc.pyMC(), cascmc.pzMC()}, constants::physics::MassOmegaMinus); - if (TMath::Abs(cascMCeta) < etaCascMCGen) { + if (std::abs(cascMCeta) < etaCascMCGen) { histosMCGen.fill(HIST("h2DGenOmegaEta08"), centrality, ptmc); histosMCGen.fill(HIST("hNCascGen"), 7.5); } - if (TMath::Abs(cascMCy) < yCascMCGen) + if (std::abs(cascMCy) < yCascMCGen) histosMCGen.fill(HIST("h2DGenOmegaY05"), centrality, ptmc); histosMCGen.fill(HIST("hGenOmegaY"), cascMCy); } @@ -1432,7 +2019,9 @@ struct cascadeFlow { 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); + PROCESS_SWITCH(cascadeFlow, processAnalyseDataEP2CentralFW, "Process to apply ML model to the data - second order event plane calibration from central framework", false); PROCESS_SWITCH(cascadeFlow, processAnalyseDataEPCentralFW, "Process to apply ML model to the data - event plane calibration from central framework", false); + 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); }; diff --git a/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx new file mode 100644 index 00000000000..3878bf4e29a --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/lambdaspincorrelation.cxx @@ -0,0 +1,448 @@ +// 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 taskLambdaSpinCorr.cxx +/// \brief Analysis task for Lambda spin spin correlation +/// +/// \author prottay.das@cern.ch +/// \author sourav.kundu@cern.ch + +#include "PWGLF/DataModel/LFSpincorrelationTables.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#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/PIDResponse.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/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Track.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector2D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +#include + +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; +using namespace o2::aod::rctsel; + +struct lambdaspincorrelation { + + Produces lambdaEvent; + Produces lambdaPair; + Produces lambdaEventmc; + Produces lambdaPairmc; + + Service ccdb; + + struct : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "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"}; + } rctCut; + // mixing + // Produce derived tables + Configurable cfgCutOccupancy{"cfgCutOccupancy", 2000, "Occupancy cut"}; + ConfigurableAxis axisVertex{"axisVertex", {5, -10, 10}, "vertex axis for bin"}; + ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {8, 0, 80}, "multiplicity percentile for bin"}; + + // events + Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; + Configurable cfgCutCentralityMax{"cfgCutCentralityMax", 80.0f, "Accepted maximum Centrality"}; + Configurable cfgCutCentralityMin{"cfgCutCentralityMin", 0.0f, "Accepted minimum Centrality"}; + + // Configs for track + Configurable cfgCutPt{"cfgCutPt", 0.2, "Pt cut on daughter track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; + + // Configs for V0 + Configurable confV0PtMin{"confV0PtMin", 0.f, "Minimum transverse momentum of V0"}; + Configurable confV0PtMax{"confV0PtMax", 1000.f, "Maximum transverse momentum of V0"}; + Configurable confV0Rap{"confV0Rap", 0.8f, "Rapidity range of V0"}; + Configurable confV0DCADaughMax{"confV0DCADaughMax", 1.0f, "Maximum DCA between the V0 daughters"}; + Configurable confV0CPAMin{"confV0CPAMin", 0.9998f, "Minimum CPA of V0"}; + Configurable confV0TranRadV0Min{"confV0TranRadV0Min", 1.5f, "Minimum transverse radius"}; + Configurable confV0TranRadV0Max{"confV0TranRadV0Max", 100.f, "Maximum transverse radius"}; + Configurable cMaxV0DCA{"cMaxV0DCA", 1.2, "Maximum V0 DCA to PV"}; + Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; + Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; + Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 50, "Maximum V0 life time"}; + + // config for V0 daughters + Configurable confDaughEta{"confDaughEta", 0.8f, "V0 Daugh sel: max eta"}; + Configurable cfgDaughPrPt{"cfgDaughPrPt", 0.2, "minimum daughter proton pt"}; + Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.2, "minimum daughter pion pt"}; + Configurable confDaughTPCnclsMin{"confDaughTPCnclsMin", 50.f, "V0 Daugh sel: Min. nCls TPC"}; + Configurable confDaughPIDCuts{"confDaughPIDCuts", 3, "PID selections for Lambda daughters"}; + + 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"}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + RCTFlagsChecker rctChecker; + void init(o2::framework::InitContext&) + { + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + AxisSpec thnAxisInvMass{iMNbins, lbinIM, hbinIM, "#it{M} (GeV/#it{c}^{2})"}; + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{5, 0, 5.0}}); + histos.add("hLambdaMass", "hLambdaMass", kTH1F, {thnAxisInvMass}); + histos.add("hV0Info", "hV0Info", kTH1F, {{5, 0, 5.0}}); + } + + template + bool selectionV0(Collision const& collision, V0 const& candidate) + { + if (std::abs(candidate.dcav0topv()) > cMaxV0DCA) { + return false; + } + const float pT = candidate.pt(); + const float tranRad = candidate.v0radius(); + const float dcaDaughv0 = std::abs(candidate.dcaV0daughters()); + const float cpav0 = candidate.v0cosPA(); + float ctauLambda = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * (o2::constants::physics::MassLambda); + + if (pT < confV0PtMin) { + return false; + } + if (pT > confV0PtMax) { + return false; + } + if (dcaDaughv0 > confV0DCADaughMax) { + return false; + } + if (cpav0 < confV0CPAMin) { + return false; + } + if (tranRad < confV0TranRadV0Min) { + return false; + } + if (tranRad > confV0TranRadV0Max) { + return false; + } + if (std::abs(ctauLambda) > cMaxV0LifeTime) { + return false; + } + if (std::abs(candidate.yLambda()) > confV0Rap) { + return false; + } + return true; + } + + template + bool isSelectedV0Daughter(V0 const& candidate, T const& track, int pid) + { + const auto tpcNClsF = track.tpcNClsFound(); + const auto ncr = 70; + const auto ncrfc = 0.8; + + if (track.tpcNClsCrossedRows() < ncr) { + return false; + } + if (tpcNClsF < confDaughTPCnclsMin) { + return false; + } + if (track.tpcCrossedRowsOverFindableCls() < ncrfc) { + return false; + } + + if (pid == 0 && std::abs(track.tpcNSigmaPr()) > confDaughPIDCuts) { + return false; + } + if (pid == 1 && std::abs(track.tpcNSigmaPi()) > confDaughPIDCuts) { + return false; + } + if (pid == 0 && (candidate.positivept() < cfgDaughPrPt || candidate.negativept() < cfgDaughPiPt)) { + return false; + } + if (pid == 1 && (candidate.positivept() < cfgDaughPiPt || candidate.negativept() < cfgDaughPrPt)) { + return false; + } + if (std::abs(candidate.positiveeta()) > confDaughEta || std::abs(candidate.negativeeta()) > confDaughEta) { + return false; + } + + if (pid == 0 && (std::abs(candidate.dcapostopv()) < cMinV0DCAPr || std::abs(candidate.dcanegtopv()) < cMinV0DCAPi)) { + return false; + } + if (pid == 1 && (std::abs(candidate.dcapostopv()) < cMinV0DCAPi || std::abs(candidate.dcanegtopv()) < cMinV0DCAPr)) { + return false; + } + + return true; + } + + std::tuple getLambdaTags(const auto& v0, const auto& collision) + { + auto postrack = v0.template posTrack_as(); + auto negtrack = v0.template negTrack_as(); + + int lambdaTag = 0; + int aLambdaTag = 0; + + const auto signpos = postrack.sign(); + const auto signneg = negtrack.sign(); + + if (signpos < 0 || signneg > 0) { + return {0, 0, false}; // Invalid candidate + } + + if (isSelectedV0Daughter(v0, postrack, 0) && isSelectedV0Daughter(v0, negtrack, 1) && v0.mLambda() > lbinIM && v0.mLambda() < hbinIM) { + lambdaTag = 1; + } + if (isSelectedV0Daughter(v0, negtrack, 0) && isSelectedV0Daughter(v0, postrack, 1) && v0.mAntiLambda() > lbinIM && v0.mAntiLambda() < hbinIM) { + aLambdaTag = 1; + } + + if (!lambdaTag && !aLambdaTag) { + return {0, 0, false}; // No valid tags + } + + if (!selectionV0(collision, v0)) { + return {0, 0, false}; // Fails selection + } + + return {lambdaTag, aLambdaTag, true}; // Valid candidate + } + + ROOT::Math::PxPyPzMVector lambda, antiLambda, proton, pion, antiProton, antiPion; + ROOT::Math::PxPyPzMVector lambdaDummy, pionDummy, protonDummy; + + Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; + Filter centralityFilter = (nabs(aod::cent::centFT0C) < cfgCutCentralityMax && nabs(aod::cent::centFT0C) > cfgCutCentralityMin); + + using EventCandidates = soa::Filtered>; + using AllTrackCandidates = soa::Join; + using ResoV0s = aod::V0Datas; + + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s) + { + std::vector lambdaMother, protonDaughter, pionDaughter; + std::vector v0Status = {}; + std::vector doubleStatus = {}; + std::vector v0Cospa = {}; + std::vector v0Radius = {}; + std::vector dcaPositive = {}; + std::vector dcaNegative = {}; + std::vector positiveIndex = {}; + std::vector negativeIndex = {}; + std::vector dcaBetweenDaughter = {}; + int numbV0 = 0; + // LOGF(info, "event collisions: (%d)", collision.index()); + auto centrality = collision.centFT0C(); + auto vz = collision.posZ(); + int occupancy = collision.trackOccupancyInTimeRange(); + 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) { + histos.fill(HIST("hEvtSelInfo"), 1.5); + for (const auto& v0 : V0s) { + // LOGF(info, "v0 index 0 : (%d)", v0.index()); + auto [lambdaTag, aLambdaTag, isValid] = getLambdaTags(v0, collision); + if (isValid) { + // LOGF(info, "v0 index 1 : (%d)", v0.index()); + if (lambdaTag) { + histos.fill(HIST("hV0Info"), 0.5); + } + if (aLambdaTag) { + histos.fill(HIST("hV0Info"), 1.5); + } + if (lambdaTag && aLambdaTag) { + doubleStatus.push_back(true); + if (std::abs(v0.mLambda() - 1.1154) < std::abs(v0.mAntiLambda() - 1.1154)) { + lambdaTag = true; + aLambdaTag = false; + } else { + lambdaTag = false; + aLambdaTag = true; + } + } else { + doubleStatus.push_back(false); + } + if (lambdaTag) { + histos.fill(HIST("hV0Info"), 2.5); + } + if (aLambdaTag) { + histos.fill(HIST("hV0Info"), 3.5); + } + // LOGF(info, "v0 index2: (%d)", v0.index()); + auto postrack1 = v0.template posTrack_as(); + auto negtrack1 = v0.template negTrack_as(); + positiveIndex.push_back(postrack1.globalIndex()); + negativeIndex.push_back(negtrack1.globalIndex()); + v0Cospa.push_back(v0.v0cosPA()); + v0Radius.push_back(v0.v0radius()); + dcaPositive.push_back(std::abs(v0.dcapostopv())); + dcaNegative.push_back(std::abs(v0.dcanegtopv())); + dcaBetweenDaughter.push_back(std::abs(v0.dcaV0daughters())); + if (lambdaTag) { + v0Status.push_back(0); + proton = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassProton); + antiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassPionCharged); + lambda = proton + antiPion; + lambdaMother.push_back(lambda); + protonDaughter.push_back(proton); + pionDaughter.push_back(antiPion); + histos.fill(HIST("hLambdaMass"), lambda.M()); + } else if (aLambdaTag) { + v0Status.push_back(1); + antiProton = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassProton); + pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda = antiProton + pion; + lambdaMother.push_back(antiLambda); + protonDaughter.push_back(antiProton); + pionDaughter.push_back(pion); + histos.fill(HIST("hLambdaMass"), lambda.M()); + } + numbV0 = numbV0 + 1; + } + } + if (numbV0 > 1 && v0Cospa.size() > 1) { + histos.fill(HIST("hEvtSelInfo"), 2.5); + lambdaEvent(centrality, vz); + auto indexEvent = lambdaEvent.lastIndex(); + //// Fill track table for V0////////////////// + for (auto if1 = lambdaMother.begin(); if1 != lambdaMother.end(); ++if1) { + auto i5 = std::distance(lambdaMother.begin(), if1); + lambdaDummy = lambdaMother.at(i5); + protonDummy = protonDaughter.at(i5); + pionDummy = pionDaughter.at(i5); + lambdaPair(indexEvent, v0Status.at(i5), doubleStatus.at(i5), v0Cospa.at(i5), v0Radius.at(i5), dcaPositive.at(i5), dcaNegative.at(i5), dcaBetweenDaughter.at(i5), lambdaDummy.Pt(), lambdaDummy.Eta(), lambdaDummy.Phi(), lambdaDummy.M(), protonDummy.Pt(), protonDummy.Eta(), protonDummy.Phi(), positiveIndex.at(i5), negativeIndex.at(i5)); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrelation, processData, "Process data", false); + + void processMc(EventCandidates::iterator const& collision, AllTrackCandidates const&, ResoV0s const& V0s) + { + std::vector lambdaMother, protonDaughter, pionDaughter; + std::vector v0Status = {}; + std::vector doubleStatus = {}; + std::vector v0Cospa = {}; + std::vector v0Radius = {}; + std::vector dcaPositive = {}; + std::vector dcaNegative = {}; + std::vector positiveIndex = {}; + std::vector negativeIndex = {}; + std::vector dcaBetweenDaughter = {}; + int numbV0 = 0; + // LOGF(info, "event collisions: (%d)", collision.index()); + auto centrality = collision.centFT0C(); + auto vz = collision.posZ(); + int occupancy = collision.trackOccupancyInTimeRange(); + 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(o2::aod::evsel::kNoCollInTimeRangeStandard) && collision.sel8() && collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll) && occupancy < cfgCutOccupancy) { + histos.fill(HIST("hEvtSelInfo"), 1.5); + for (const auto& v0 : V0s) { + // LOGF(info, "v0 index 0 : (%d)", v0.index()); + auto [lambdaTag, aLambdaTag, isValid] = getLambdaTags(v0, collision); + if (isValid) { + // LOGF(info, "v0 index 1 : (%d)", v0.index()); + if (lambdaTag) { + histos.fill(HIST("hV0Info"), 0.5); + } + if (aLambdaTag) { + histos.fill(HIST("hV0Info"), 1.5); + } + if (lambdaTag && aLambdaTag) { + doubleStatus.push_back(true); + if (std::abs(v0.mLambda() - 1.1154) < std::abs(v0.mAntiLambda() - 1.1154)) { + lambdaTag = true; + aLambdaTag = false; + } else { + lambdaTag = false; + aLambdaTag = true; + } + } else { + doubleStatus.push_back(false); + } + if (lambdaTag) { + histos.fill(HIST("hV0Info"), 2.5); + } + if (aLambdaTag) { + histos.fill(HIST("hV0Info"), 3.5); + } + // LOGF(info, "v0 index2: (%d)", v0.index()); + auto postrack1 = v0.template posTrack_as(); + auto negtrack1 = v0.template negTrack_as(); + positiveIndex.push_back(postrack1.globalIndex()); + negativeIndex.push_back(negtrack1.globalIndex()); + v0Cospa.push_back(v0.v0cosPA()); + v0Radius.push_back(v0.v0radius()); + dcaPositive.push_back(std::abs(v0.dcapostopv())); + dcaNegative.push_back(std::abs(v0.dcanegtopv())); + dcaBetweenDaughter.push_back(std::abs(v0.dcaV0daughters())); + if (lambdaTag) { + v0Status.push_back(0); + proton = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassProton); + antiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassPionCharged); + lambda = proton + antiPion; + lambdaMother.push_back(lambda); + protonDaughter.push_back(proton); + pionDaughter.push_back(antiPion); + histos.fill(HIST("hLambdaMass"), lambda.M()); + } else if (aLambdaTag) { + v0Status.push_back(1); + antiProton = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassProton); + pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda = antiProton + pion; + lambdaMother.push_back(antiLambda); + protonDaughter.push_back(antiProton); + pionDaughter.push_back(pion); + histos.fill(HIST("hLambdaMass"), lambda.M()); + } + numbV0 = numbV0 + 1; + } + } + if (numbV0 > 1 && v0Cospa.size() > 1) { + histos.fill(HIST("hEvtSelInfo"), 2.5); + lambdaEventmc(centrality, vz); + auto indexEvent = lambdaEventmc.lastIndex(); + //// Fill track table for V0////////////////// + for (auto if1 = lambdaMother.begin(); if1 != lambdaMother.end(); ++if1) { + auto i5 = std::distance(lambdaMother.begin(), if1); + lambdaDummy = lambdaMother.at(i5); + protonDummy = protonDaughter.at(i5); + pionDummy = pionDaughter.at(i5); + lambdaPairmc(indexEvent, v0Status.at(i5), doubleStatus.at(i5), v0Cospa.at(i5), v0Radius.at(i5), dcaPositive.at(i5), dcaNegative.at(i5), dcaBetweenDaughter.at(i5), lambdaDummy.Pt(), lambdaDummy.Eta(), lambdaDummy.Phi(), lambdaDummy.M(), protonDummy.Pt(), protonDummy.Eta(), protonDummy.Phi(), positiveIndex.at(i5), negativeIndex.at(i5)); + } + } + } + } + PROCESS_SWITCH(lambdaspincorrelation, processMc, "Process montecarlo", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/TableProducer/Strangeness/propagationService.cxx b/PWGLF/TableProducer/Strangeness/propagationService.cxx new file mode 100644 index 00000000000..191b920d9ef --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/propagationService.cxx @@ -0,0 +1,156 @@ +// 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 propagationService.cxx +/// \brief +/// \author ALICE + +//=============================================================== +// +// Merged track propagation + strangeness building task +// +// Provides a common task to deal with track propagation and +// strangeness building in a single DPL device that is particularly +// adequate for pipelining. +// +// Currently meant for testing and performance check +// +//=============================================================== + +#include "PWGLF/Utils/strangenessBuilderModule.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "Common/Tools/StandardCCDBLoader.h" +#include "Common/Tools/TrackPropagationModule.h" +#include "Common/Tools/TrackTuner.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" +#include "CommonConstants/GeomConstants.h" +#include "CommonUtils/NameConf.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.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 + +using namespace o2; +using namespace o2::framework; +// using namespace o2::framework::expressions; + +// 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; +using FullTracksExtLabeled = soa::Join; +using FullTracksExtLabeledIU = soa::Join; +using FullTracksExtLabeledWithPID = soa::Join; +using FullTracksExtLabeledIUWithPID = soa::Join; +using TracksWithExtra = soa::Join; + +// For dE/dx association in pre-selection +using TracksExtraWithPID = soa::Join; + +struct propagationService { + // CCDB boilerplate declarations + o2::framework::Configurable ccdburl{"ccdburl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Service ccdb; + + // propagation stuff + o2::common::StandardCCDBLoaderConfigurables standardCCDBLoaderConfigurables; + o2::common::StandardCCDBLoader ccdbLoader; + + // boilerplate: strangeness builder stuff + o2::pwglf::strangenessbuilder::products products; + o2::pwglf::strangenessbuilder::coreConfigurables baseOpts; + o2::pwglf::strangenessbuilder::v0Configurables v0BuilderOpts; + o2::pwglf::strangenessbuilder::cascadeConfigurables cascadeBuilderOpts; + o2::pwglf::strangenessbuilder::preSelectOpts preSelectOpts; + o2::pwglf::strangenessbuilder::BuilderModule strangenessBuilderModule; + + // the track tuner object -> needs to be here as it inherits from ConfigurableGroup (+ has its own copy of ccdbApi) + TrackTuner trackTunerObj; + + // track propagation + o2::common::TrackPropagationProducts trackPropagationProducts; + o2::common::TrackPropagationConfigurables trackPropagationConfigurables; + o2::common::TrackPropagationModule trackPropagation; + + // registry + HistogramRegistry histos{"histos"}; + + void init(o2::framework::InitContext& initContext) + { + // CCDB boilerplate init + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setURL(ccdburl.value); + + // task-specific + trackPropagation.init(trackPropagationConfigurables, trackTunerObj, histos, initContext); + strangenessBuilderModule.init(baseOpts, v0BuilderOpts, cascadeBuilderOpts, preSelectOpts, histos, initContext); + } + + void processRealData(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIU const& tracks, aod::BCsWithTimestamps const& bcs) + { + ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); + } + + void processMonteCarlo(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIU const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const& mcParticles) + { + ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + trackPropagation.fillTrackTables(trackPropagationConfigurables, trackTunerObj, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); + } + + // FIXME: the part below is only viable if TPC PID + // switches to using TracksIU (circular dependency) + // + // void processRealDataWithPID(soa::Join const& collisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs) + // { + // ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + // trackPropagation.fillTrackTables(trackPropagationConfigurables, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + // strangenessBuilderModule.dataProcess(ccdb, histos, collisions, static_cast(nullptr), v0s, cascades, trackedCascades, tracks, bcs, static_cast(nullptr), products); + // } + + // void processMonteCarloWithPID(soa::Join const& collisions, aod::McCollisions const& mccollisions, aod::V0s const& v0s, aod::Cascades const& cascades, aod::TrackedCascades const& trackedCascades, FullTracksExtLabeledIUWithPID const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const& mcParticles) + // { + // ccdbLoader.initCCDBfromBCs(standardCCDBLoaderConfigurables, ccdb, bcs); + // trackPropagation.fillTrackTables(trackPropagationConfigurables, ccdbLoader, collisions, tracks, trackPropagationProducts, histos); + // strangenessBuilderModule.dataProcess(ccdb, histos, collisions, mccollisions, v0s, cascades, trackedCascades, tracks, bcs, mcParticles, products); + // } + + PROCESS_SWITCH(propagationService, processRealData, "process real data", true); + PROCESS_SWITCH(propagationService, processMonteCarlo, "process monte carlo", false); + // PROCESS_SWITCH(propagationService, processRealDataWithPID, "process real data", false); + // PROCESS_SWITCH(propagationService, processMonteCarloWithPID, "process monte carlo", false); +}; + +//**************************************************************************************** +/** + * Workflow definition. + */ +//**************************************************************************************** +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + WorkflowSpec workflow{adaptAnalysisTask(cfgc)}; + return workflow; +} diff --git a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx index 89e121dbe1f..32ed292dddd 100644 --- a/PWGLF/TableProducer/Strangeness/sigma0builder.cxx +++ b/PWGLF/TableProducer/Strangeness/sigma0builder.cxx @@ -63,7 +63,7 @@ struct sigma0builder { Service ccdb; ctpRateFetcher rateFetcher; - SliceCache cache; + // SliceCache cache; Produces sigma0cores; // save sigma0 candidates for analysis Produces sigmaPhotonExtras; // save sigma0 candidates for analysis @@ -71,8 +71,8 @@ struct sigma0builder { Produces sigma0mccores; // For manual sliceBy - Preslice perCollisionMCDerived = o2::aod::v0data::straCollisionId; - Preslice perCollisionSTDDerived = o2::aod::v0data::straCollisionId; + // PresliceUnsorted perCollisionMCDerived = o2::aod::v0data::straCollisionId; + // PresliceUnsorted perCollisionSTDDerived = o2::aod::v0data::straCollisionId; PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; // pack track quality but separte also afterburner @@ -256,6 +256,7 @@ struct sigma0builder { histos.add("PhotonSel/hPhotonDCAPosToPV", "hPhotonDCAPosToPV", kTH1F, {axisDCAtoPV}); histos.add("PhotonSel/hPhotonDCADau", "hPhotonDCADau", kTH1F, {axisDCAdau}); histos.add("PhotonSel/hPhotonRadius", "hPhotonRadius", kTH1F, {axisRadius}); + histos.add("PhotonSel/h3dPhotonMass", "h3dPhotonMass", kTH3D, {axisCentrality, axisPt, axisPhotonMass}); histos.add("LambdaSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); histos.get(HIST("LambdaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); @@ -274,6 +275,8 @@ struct sigma0builder { histos.add("LambdaSel/hLambdaDCAPosToPV", "hLambdaDCAPosToPV", kTH1F, {axisDCAtoPV}); histos.add("LambdaSel/hLambdaDCADau", "hLambdaDCADau", kTH1F, {axisDCAdau}); histos.add("LambdaSel/hLambdaRadius", "hLambdaRadius", kTH1F, {axisRadius}); + histos.add("LambdaSel/h3dLambdaMass", "h3dLambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); + histos.add("LambdaSel/h3dALambdaMass", "h3dALambdaMass", kTH3D, {axisCentrality, axisPt, axisLambdaMass}); histos.add("SigmaSel/hSelectionStatistics", "hSelectionStatistics", kTH1D, {axisCandSel}); histos.get(HIST("SigmaSel/hSelectionStatistics"))->GetXaxis()->SetBinLabel(1, "No Sel"); @@ -286,7 +289,7 @@ struct sigma0builder { histos.add("SigmaSel/hSigmaMassWindow", "hSigmaMassWindow", kTH1F, {{200, -0.09f, 0.11f}}); histos.add("SigmaSel/hSigmaY", "hSigmaY", kTH1F, {axisRapidity}); histos.add("SigmaSel/hSigmaMassSelected", "hSigmaMassSelected", kTH1F, {axisSigmaMass}); - histos.add("SigmaSel/h3dMassSigma0AfterSel", "h3dMassSigma0AfterSel", kTH3F, {axisCentrality, axisPt, axisSigmaMass}); + histos.add("SigmaSel/h3dMassSigma0AfterSel", "h3dMassSigma0AfterSel", kTH3D, {axisCentrality, axisPt, axisSigmaMass}); if (fillQAhistos) { histos.add("GeneralQA/h2dMassGammaVsK0S", "h2dMassGammaVsK0S", kTH2D, {axisPhotonMass, axisK0SMass}); @@ -347,10 +350,10 @@ struct sigma0builder { // For Pi0 QA if (doPi0QA) { - histos.add("Pi0QA/h2dPtVsMassPi0BeforeSel_MCAssoc", "h2dPtVsMassPi0BeforeSel_MCAssoc", kTH2D, {axisPt, axisPi0Mass}); - histos.add("Pi0QA/h2dPtVsMassPi0AfterSel_MCAssoc", "h2dPtVsMassPi0AfterSel_MCAssoc", kTH2D, {axisPt, axisPi0Mass}); - histos.add("Pi0QA/h2dPtVsMassPi0BeforeSel_Candidates", "h2dPtVsMassPi0BeforeSel_Candidates", kTH2D, {axisPt, axisPi0Mass}); - histos.add("Pi0QA/h2dPtVsMassPi0AfterSel_Candidates", "h2dPtVsMassPi0AfterSel_Candidates", kTH2D, {axisPt, axisPi0Mass}); + histos.add("Pi0QA/h3dMassPi0BeforeSel_MCAssoc", "h3dMassPi0BeforeSel_MCAssoc", kTH3D, {axisCentrality, axisPt, axisPi0Mass}); + histos.add("Pi0QA/h3dMassPi0AfterSel_MCAssoc", "h3dMassPi0AfterSel_MCAssoc", kTH3D, {axisCentrality, axisPt, axisPi0Mass}); + histos.add("Pi0QA/h3dMassPi0BeforeSel_Candidates", "h3dMassPi0BeforeSel_Candidates", kTH3D, {axisCentrality, axisPt, axisPi0Mass}); + histos.add("Pi0QA/h3dMassPi0AfterSel_Candidates", "h3dMassPi0AfterSel_Candidates", kTH3D, {axisCentrality, axisPt, axisPi0Mass}); } if (doprocessGeneratedRun3) { @@ -382,7 +385,7 @@ struct sigma0builder { } template - bool IsEventAccepted(TCollision collision, bool fillHists) + bool IsEventAccepted(TCollision const& collision, bool fillHists) // check whether the collision passes our collision selections { if (fillHists) @@ -500,6 +503,8 @@ struct sigma0builder { if (fillHists) histos.fill(HIST("hEventSelection"), 19 /* Above max IR */); + float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + histos.fill(HIST("hEventCentrality"), centrality); return true; } @@ -731,8 +736,8 @@ struct sigma0builder { } } - template - void runPi0QA(TV0Object const& gamma1, TV0Object const& gamma2) + template + void runPi0QA(TV0Object const& gamma1, TV0Object const& gamma2, TCollision collision) { // Check if both V0s are made of the same tracks if (gamma1.posTrackExtraId() == gamma2.posTrackExtraId() || @@ -747,6 +752,7 @@ struct sigma0builder { float pi0Mass = RecoDecay::m(arrpi0, std::array{o2::constants::physics::MassPhoton, o2::constants::physics::MassPhoton}); float pi0Pt = RecoDecay::pt(std::array{gamma1.px() + gamma2.px(), gamma1.py() + gamma2.py()}); float pi0Y = RecoDecay::y(std::array{gamma1.px() + gamma2.px(), gamma1.py() + gamma2.py(), gamma1.pz() + gamma2.pz()}, o2::constants::physics::MassPi0); + float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); // MC-specific variables bool fIsPi0 = false, fIsMC = false; @@ -762,12 +768,12 @@ struct sigma0builder { gamma1MC.pdgCodeMother() == 111 && gamma2MC.pdgCodeMother() == 111 && gamma1.motherMCPartId() == gamma2.motherMCPartId()) { fIsPi0 = true; - histos.fill(HIST("Pi0QA/h2dPtVsMassPi0BeforeSel_MCAssoc"), pi0Pt, pi0Mass); + histos.fill(HIST("Pi0QA/h3dMassPi0BeforeSel_MCAssoc"), centrality, pi0Pt, pi0Mass); } } } - histos.fill(HIST("Pi0QA/h2dPtVsMassPi0BeforeSel_Candidates"), pi0Pt, pi0Mass); + histos.fill(HIST("Pi0QA/h3dMassPi0BeforeSel_Candidates"), centrality, pi0Pt, pi0Mass); // Photon-specific selections auto posTrackGamma1 = gamma1.template posTrackExtra_as(); @@ -776,8 +782,8 @@ struct sigma0builder { auto negTrackGamma2 = gamma2.template negTrackExtra_as(); // Gamma1 Selection - bool passedTPCGamma1 = (posTrackGamma1.tpcNSigmaEl() == -999.f || TMath::Abs(posTrackGamma1.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas) && - (negTrackGamma1.tpcNSigmaEl() == -999.f || TMath::Abs(negTrackGamma1.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas); + bool passedTPCGamma1 = (TMath::Abs(posTrackGamma1.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas) || + (TMath::Abs(negTrackGamma1.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas); if (TMath::Abs(gamma1.mGamma()) > Pi0PhotonMaxMass || gamma1.qtarm() >= Pi0PhotonMaxQt || @@ -797,8 +803,8 @@ struct sigma0builder { } // Gamma2 Selection - bool passedTPCGamma2 = (posTrackGamma2.tpcNSigmaEl() == -999.f || TMath::Abs(posTrackGamma2.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas) && - (negTrackGamma2.tpcNSigmaEl() == -999.f || TMath::Abs(negTrackGamma2.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas); + bool passedTPCGamma2 = (TMath::Abs(posTrackGamma2.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas) || + (TMath::Abs(negTrackGamma2.tpcNSigmaEl()) < Pi0PhotonMaxTPCNSigmas); if (TMath::Abs(gamma2.mGamma()) > Pi0PhotonMaxMass || gamma2.qtarm() >= Pi0PhotonMaxQt || @@ -823,14 +829,14 @@ struct sigma0builder { } // Fill histograms - histos.fill(HIST("Pi0QA/h2dPtVsMassPi0AfterSel_Candidates"), pi0Pt, pi0Mass); + histos.fill(HIST("Pi0QA/h3dMassPi0AfterSel_Candidates"), centrality, pi0Pt, pi0Mass); if (fIsMC && fIsPi0) - histos.fill(HIST("Pi0QA/h2dPtVsMassPi0AfterSel_MCAssoc"), pi0Pt, pi0Mass); + histos.fill(HIST("Pi0QA/h3dMassPi0AfterSel_MCAssoc"), centrality, pi0Pt, pi0Mass); } // Process photon candidate - template - bool processPhotonCandidate(TV0Object const& gamma) + template + bool processPhotonCandidate(TV0Object const& gamma, TCollision collision) { if (gamma.v0Type() == 0) return false; @@ -869,12 +875,14 @@ struct sigma0builder { return false; histos.fill(HIST("PhotonSel/hSelectionStatistics"), 6.); } + float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + histos.fill(HIST("PhotonSel/h3dPhotonMass"), centrality, gamma.pt(), gamma.mGamma()); return true; } // Process photon candidate - template - bool processLambdaCandidate(TV0Object const& lambda) + template + bool processLambdaCandidate(TV0Object const& lambda, TCollision collision) { if (lambda.v0Type() != 1) return false; @@ -912,12 +920,16 @@ struct sigma0builder { histos.fill(HIST("LambdaSel/hSelectionStatistics"), 6.); } + float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + histos.fill(HIST("LambdaSel/h3dLambdaMass"), centrality, lambda.pt(), lambda.mLambda()); + histos.fill(HIST("LambdaSel/h3dALambdaMass"), centrality, lambda.pt(), lambda.mAntiLambda()); + return true; } /////////// // Process sigma candidate and store properties in object - template - bool buildSigma0(TV0Object const& lambda, TV0Object const& gamma) + template + bool buildSigma0(TV0Object const& lambda, TV0Object const& gamma, TCollision collision) { // Checking if both V0s are made of the very same tracks if (gamma.posTrackExtraId() == lambda.posTrackExtraId() || @@ -929,31 +941,36 @@ struct sigma0builder { std::array pVecPhotons{gamma.px(), gamma.py(), gamma.pz()}; 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}); - float sigmarap = RecoDecay::y(std::array{gamma.px() + lambda.px(), gamma.py() + lambda.py(), gamma.pz() + lambda.pz()}, o2::constants::physics::MassSigma0); + float sigmaMass = RecoDecay::m(arrMom, std::array{o2::constants::physics::MassPhoton, o2::constants::physics::MassLambda0}); + float sigmaY = RecoDecay::y(std::array{gamma.px() + lambda.px(), gamma.py() + lambda.py(), gamma.pz() + lambda.pz()}, o2::constants::physics::MassSigma0); + float SigmapT = RecoDecay::pt(array{gamma.px() + lambda.px(), gamma.py() + lambda.py()}); + float centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + + // Before any selection + histos.fill(HIST("SigmaSel/h3dMassSigma0BeforeSel"), centrality, SigmapT, sigmaMass); histos.fill(HIST("SigmaSel/hSelectionStatistics"), 1.); - histos.fill(HIST("SigmaSel/hSigmaMass"), sigmamass); - histos.fill(HIST("SigmaSel/hSigmaMassWindow"), sigmamass - 1.192642); + histos.fill(HIST("SigmaSel/hSigmaMass"), sigmaMass); + histos.fill(HIST("SigmaSel/hSigmaMassWindow"), sigmaMass - 1.192642); if (fillQAhistos) { histos.fill(HIST("GeneralQA/h2dMassGammaVsK0S"), gamma.mGamma(), gamma.mK0Short()); histos.fill(HIST("GeneralQA/h2dMassLambdaVsK0S"), lambda.mLambda(), lambda.mK0Short()); histos.fill(HIST("GeneralQA/h2dMassGammaVsLambda"), gamma.mGamma(), gamma.mLambda()); histos.fill(HIST("GeneralQA/h2dMassLambdaVsGamma"), lambda.mLambda(), lambda.mGamma()); - histos.fill(HIST("GeneralQA/h3dMassSigma0VsDaupTs"), gamma.pt(), lambda.pt(), sigmamass); + histos.fill(HIST("GeneralQA/h3dMassSigma0VsDaupTs"), gamma.pt(), lambda.pt(), sigmaMass); } - if (TMath::Abs(sigmamass - 1.192642) > Sigma0Window) + if (TMath::Abs(sigmaMass - 1.192642) > Sigma0Window) return false; - histos.fill(HIST("SigmaSel/hSigmaY"), sigmarap); + histos.fill(HIST("SigmaSel/hSigmaY"), sigmaY); histos.fill(HIST("SigmaSel/hSelectionStatistics"), 2.); - if (TMath::Abs(sigmarap) > SigmaMaxRap) + if (TMath::Abs(sigmaY) > SigmaMaxRap) return false; - histos.fill(HIST("SigmaSel/hSigmaMassSelected"), sigmamass); + histos.fill(HIST("SigmaSel/hSigmaMassSelected"), sigmaMass); histos.fill(HIST("SigmaSel/hSelectionStatistics"), 3.); if (fillQAhistos) { @@ -963,6 +980,8 @@ struct sigma0builder { histos.fill(HIST("GeneralQA/h2dV0XY"), gamma.x(), gamma.y()); } + histos.fill(HIST("SigmaSel/h3dMassSigma0AfterSel"), centrality, SigmapT, sigmaMass); + return true; } @@ -1119,17 +1138,26 @@ struct sigma0builder { void processMonteCarlo(soa::Join const& collisions, V0DerivedMCDatas const& fullV0s, dauTracks const&, aod::MotherMCParts const&, soa::Join const&, soa::Join const&) { + // Initialize auxiliary vectors + std::vector bestGammasArray; + std::vector bestLambdasArray; + + // brute force grouped index construction + std::vector> v0grouped(collisions.size()); + + for (const auto& v0 : fullV0s) { + v0grouped[v0.straCollisionId()].push_back(v0.globalIndex()); + } + for (const auto& coll : collisions) { + // Clear vectors + bestGammasArray.clear(); + bestLambdasArray.clear(); if (!IsEventAccepted(coll, true)) continue; - // Do analysis with collision-grouped V0s, retain full collision information - const uint64_t collIdx = coll.globalIndex(); - auto V0s = fullV0s.sliceBy(perCollisionMCDerived, collIdx); - - float centrality = coll.centFT0C(); - histos.fill(HIST("hEventCentrality"), centrality); + float centrality = doPPAnalysis ? coll.centFT0M() : coll.centFT0C(); bool fhasMCColl = false; if (coll.has_straMCCollision()) @@ -1140,7 +1168,6 @@ struct sigma0builder { float interactionRate = -1; if (fGetIR) { interactionRate = rateFetcher.fetch(ccdb.service, coll.timestamp(), coll.runNumber(), irSource, fIRCrashOnNull) * 1.e-3; - if (interactionRate < 0) histos.get(HIST("GeneralQA/hRunNumberNegativeIR"))->Fill(Form("%d", coll.runNumber()), 1); @@ -1148,12 +1175,11 @@ struct sigma0builder { histos.fill(HIST("GeneralQA/hCentralityVsInteractionRate"), centrality, interactionRate); } - std::vector bestGammasArray; - std::vector bestLambdasArray; - //_______________________________________________ // V0s loop - for (auto& v0 : V0s) { + for (size_t i = 0; i < v0grouped[coll.globalIndex()].size(); i++) { + auto v0 = fullV0s.rawIteratorAt(v0grouped[coll.globalIndex()][i]); + if (!v0.has_v0MCCore()) continue; @@ -1175,10 +1201,10 @@ struct sigma0builder { histos.fill(HIST("MC/h2dPtVsCentralityBeforeSel_MCAssocALambda"), centrality, v0.pt()); } - if (processPhotonCandidate(v0)) // selecting photons + if (processPhotonCandidate(v0, coll)) // selecting photons bestGammasArray.push_back(v0.globalIndex()); // Save indices of best gamma candidates - if (processLambdaCandidate(v0)) // selecting lambdas + if (processLambdaCandidate(v0, coll)) // selecting lambdas bestLambdasArray.push_back(v0.globalIndex()); // Save indices of best lambda candidates } @@ -1189,7 +1215,7 @@ struct sigma0builder { auto gamma1 = fullV0s.rawIteratorAt(bestGammasArray[i]); for (size_t j = i + 1; j < bestGammasArray.size(); ++j) { auto gamma2 = fullV0s.rawIteratorAt(bestGammasArray[j]); - runPi0QA(gamma1, gamma2); + runPi0QA(gamma1, gamma2, coll); } } } @@ -1218,7 +1244,7 @@ struct sigma0builder { } for (size_t j = 0; j < bestLambdasArray.size(); ++j) { - auto lambda = fullV0s.iteratorAt(bestLambdasArray[j]); + auto lambda = fullV0s.rawIteratorAt(bestLambdasArray[j]); if (!lambda.has_v0MCCore()) continue; @@ -1269,15 +1295,10 @@ struct sigma0builder { histos.fill(HIST("MC/h2dPtVsCentralityBeforeSel_MCAssocASigma0"), centrality, SigmaMCpT); } - histos.fill(HIST("SigmaSel/h3dMassSigma0BeforeSel"), centrality, SigmapT, SigmaMass); - // Build sigma0 candidate, please - if (!buildSigma0(lambda, gamma)) + if (!buildSigma0(lambda, gamma, coll)) continue; - // Filling histos and tables - histos.fill(HIST("SigmaSel/h3dMassSigma0AfterSel"), centrality, SigmapT, SigmaMass); - if (SigmaY < 0.5) { if (fIsSigma) histos.fill(HIST("MC/h2dPtVsCentralityAfterSel_MCAssocSigma0"), centrality, SigmaMCpT); @@ -1293,7 +1314,8 @@ struct sigma0builder { PhotonCandPDGCode, PhotonCandPDGCodeMother, fIsPhotonPrimary, PhotonMCpT, fIsPhotonCorrectlyAssign, LambdaCandPDGCode, LambdaCandPDGCodeMother, fIsLambdaPrimary, LambdaMCpT, fIsLambdaCorrectlyAssign); - fillTables(lambda, gamma, coll); // filling tables with accepted candidates + // Filling tables with accepted candidates + fillTables(lambda, gamma, coll); nSigmaCandidates++; if (nSigmaCandidates % 10000 == 0) @@ -1305,24 +1327,32 @@ struct sigma0builder { void processRealData(soa::Join const& collisions, V0StandardDerivedDatas const& fullV0s, dauTracks const&) { + // Initialize auxiliary vectors + std::vector bestGammasArray; + std::vector bestLambdasArray; + + // brute force grouped index construction + std::vector> v0grouped(collisions.size()); + + for (const auto& v0 : fullV0s) { + v0grouped[v0.straCollisionId()].push_back(v0.globalIndex()); + } + for (const auto& coll : collisions) { + // Clear vectors + bestGammasArray.clear(); + bestLambdasArray.clear(); if (!IsEventAccepted(coll, true)) continue; - // Do analysis with collision-grouped V0s, retain full collision information - const uint64_t collIdx = coll.globalIndex(); - auto V0s = fullV0s.sliceBy(perCollisionSTDDerived, collIdx); - - float centrality = coll.centFT0C(); - histos.fill(HIST("hEventCentrality"), centrality); + float centrality = doPPAnalysis ? coll.centFT0M() : coll.centFT0C(); //_______________________________________________ // Retrieving IR info float interactionRate = -1; if (fGetIR) { interactionRate = rateFetcher.fetch(ccdb.service, coll.timestamp(), coll.runNumber(), irSource, fIRCrashOnNull) * 1.e-3; - if (interactionRate < 0) histos.get(HIST("GeneralQA/hRunNumberNegativeIR"))->Fill(Form("%d", coll.runNumber()), 1); @@ -1330,16 +1360,14 @@ struct sigma0builder { histos.fill(HIST("GeneralQA/hCentralityVsInteractionRate"), centrality, interactionRate); } - std::vector bestGammasArray; - std::vector bestLambdasArray; - //_______________________________________________ // V0s loop - for (auto& v0 : V0s) { - if (processPhotonCandidate(v0)) // selecting photons + for (size_t i = 0; i < v0grouped[coll.globalIndex()].size(); i++) { + auto v0 = fullV0s.rawIteratorAt(v0grouped[coll.globalIndex()][i]); + if (processPhotonCandidate(v0, coll)) // selecting photons bestGammasArray.push_back(v0.globalIndex()); // Save indices of best gamma candidates - if (processLambdaCandidate(v0)) // selecting lambdas + if (processLambdaCandidate(v0, coll)) // selecting lambdas bestLambdasArray.push_back(v0.globalIndex()); // Save indices of best lambda candidates } @@ -1350,7 +1378,7 @@ struct sigma0builder { auto gamma1 = fullV0s.rawIteratorAt(bestGammasArray[i]); for (size_t j = i + 1; j < bestGammasArray.size(); ++j) { auto gamma2 = fullV0s.rawIteratorAt(bestGammasArray[j]); - runPi0QA(gamma1, gamma2); + runPi0QA(gamma1, gamma2, coll); } } } @@ -1361,24 +1389,14 @@ struct sigma0builder { auto gamma = fullV0s.rawIteratorAt(bestGammasArray[i]); for (size_t j = 0; j < bestLambdasArray.size(); ++j) { - auto lambda = fullV0s.iteratorAt(bestLambdasArray[j]); - - // Sigma0 candidate properties - std::array pVecPhotons{gamma.px(), gamma.py(), gamma.pz()}; - 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}); - float SigmapT = RecoDecay::pt(array{gamma.px() + lambda.px(), gamma.py() + lambda.py()}); - - histos.fill(HIST("SigmaSel/h3dMassSigma0BeforeSel"), centrality, SigmapT, SigmaMass); + auto lambda = fullV0s.rawIteratorAt(bestLambdasArray[j]); // Building sigma0 candidate - if (!buildSigma0(lambda, gamma)) + if (!buildSigma0(lambda, gamma, coll)) continue; - fillTables(lambda, gamma, coll); // filling tables with accepted candidates - - histos.fill(HIST("SigmaSel/h3dMassSigma0AfterSel"), centrality, SigmapT, SigmaMass); + // Filling tables with accepted candidates + fillTables(lambda, gamma, coll); nSigmaCandidates++; if (nSigmaCandidates % 10000 == 0) diff --git a/PWGLF/TableProducer/Strangeness/sigmaminustask.cxx b/PWGLF/TableProducer/Strangeness/sigmaminustask.cxx new file mode 100644 index 00000000000..c9b2d58f08c --- /dev/null +++ b/PWGLF/TableProducer/Strangeness/sigmaminustask.cxx @@ -0,0 +1,682 @@ +// 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 sigmaminustask.cxx +/// \brief Example of a simple task for the analysis of the Sigma-minus +/// \author Francesco Mazzaschi + +#include "PWGLF/DataModel/LFKinkDecayTables.h" + +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsBase/Propagator.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using TracksFull = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; + +struct sigmaminustask { + + // Output Tables + Produces outputDataTable; + Produces outputDataTableMC; + + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rSigmaMinus{"sigmaminus", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rFindable{"findable", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable cutNSigmaPi{"cutNSigmaPi", 4, "NSigmaTPCPion"}; + Configurable cutRapMotherMC{"cutRapMotherMC", 1.0f, "Rapidity cut for mother Sigma in MC"}; + Configurable cutMinQtAP{"cutMinQtAP", 0.15f, "Minimum Qt for Armenteros-Podolanski cut"}; + Configurable cutMaxQtAP{"cutMaxQtAP", 0.20f, "Maximum Qt for Armenteros-Podolanski cut"}; + + Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Kink candidates"}; + + // Configurables for findable tracks (kinkBuilder.cxx efficiency) + Configurable minPtMothKB{"minPtMothKB", 0.5f, "Minimum pT of the mother"}; + Configurable maxPhiDiffKB{"maxPhiDiffKB", 100.0f, "Max phi difference between the kink daughter and the mother"}; + Configurable maxZDiffKB{"maxZDiffKB", 20.0f, "Max z difference between the kink daughter and the mother"}; + Configurable etaMaxKB{"etaMaxKB", 1.0f, "Max eta for both mother and daughter"}; + Configurable nTPCClusMinDaugKB{"nTPCClusMinDaugKB", 80, "Min daug NTPC clusters"}; + Configurable radiusCutKB{"radiusCutKB", 19.6213f, "Min reconstructed decay radius of the mother"}; + Configurable maxDcaMothPvKB{"maxDcaMothPvKB", 0.1f, "Max DCA of the mother to PV"}; + Configurable minDcaDaugPvKB{"minDcaDaugPvKB", 0.1f, "Min DCA of the daughter to PV"}; + + Preslice mPerCol = aod::track::collisionId; + + // Constants + float radToDeg = o2::constants::math::Rad2Deg; + + // Services CCDB + Service ccdb; + Configurable ccdbPath{"ccdbPath", "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 cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; + + // Runtime variables + int mRunNumber = 0; + float mBz = 0.0f; + o2::base::MatLayerCylSet* matLUT = nullptr; + + void init(InitContext const&) + { + // Initialize CCDB + ccdb->setURL(ccdbPath); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(true); + + matLUT = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + + // Axes + const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec ptUnsignedAxis{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec nSigmaPiAxis{60, -30, 30, "n#sigma_{#pi}"}; + const AxisSpec nSigmaPrAxis{60, -30, 30, "n#sigma_{p}"}; + const AxisSpec sigmaMassAxis{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; + const AxisSpec xiMassAxis{100, 1.2, 1.6, "m_{#Xi} (GeV/#it{c}^{2})"}; + const AxisSpec pdgAxis{10001, -5000, 5000, "PDG code"}; + const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; + const AxisSpec dcaMothAxis{100, 0, 0.03, "DCA [cm]"}; + const AxisSpec dcaDaugAxis{200, 0, 20, "DCA [cm]"}; + const AxisSpec radiusAxis{100, -1, 40, "Decay radius [cm]"}; + const AxisSpec alphaAPAxis{200, -1.0, 1.0, "#alpha_{AP}"}; + const AxisSpec qtAPAxis{200, 0.0, 0.5, "q_{T,AP}"}; + const AxisSpec cosPointingAngleAxis{100, -1.0, 1.0, "Cos#theta_{PA}"}; + + const AxisSpec ptResolutionAxis{100, -1.0, 1.0, "(#it{p}_{T}^{rec} - #it{p}_{T}^{gen}) / #it{p}_{T}^{gen}"}; + const AxisSpec massResolutionAxis{100, -0.5, 0.5, "(m_{rec} - m_{gen}) / m_{gen}"}; + const AxisSpec radiusResolutionAxis{100, -0.5, 0.5, "(r_{rec} - r_{gen}) / r_{gen}"}; + + const AxisSpec boolAxis{2, -0.5, 1.5, "Boolean value"}; + const AxisSpec filtersAxis{12, -0.5, 11.5, "Filter index"}; + const AxisSpec fakeITSAxis{8, -1.5, 6.5, "Fake ITS cluster layer"}; + + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + // Sigma-minus reconstruction + rSigmaMinus.add("h2MassSigmaMinusPt", "h2MassSigmaMinusPt", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2SigmaMassVsXiMass", "h2SigmaMassVsXiMass", {HistType::kTH2F, {xiMassAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2NSigmaTPCPiPt", "h2NSigmaTPCPiPt", {HistType::kTH2F, {ptAxis, nSigmaPiAxis}}); + rSigmaMinus.add("h2DCAMothPt", "h2DCAMothPt", {HistType::kTH2F, {ptAxis, dcaMothAxis}}); + rSigmaMinus.add("h2DCADaugPt", "h2DCADaugPt", {HistType::kTH2F, {ptAxis, dcaDaugAxis}}); + rSigmaMinus.add("h2ArmenterosPreCuts", "h2ArmenterosPreCuts", {HistType::kTH2F, {alphaAPAxis, qtAPAxis}}); + rSigmaMinus.add("h2CosPointingAnglePt", "h2CosPointingAnglePt", {HistType::kTH2F, {ptAxis, cosPointingAngleAxis}}); + + if (doprocessMC) { + // Add MC histograms if needed + rSigmaMinus.add("h2MassPtMCRec", "h2MassPtMCRec", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rSigmaMinus.add("h2MassPtMCGen", "h2MassPtMCGen", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + + rSigmaMinus.add("h2MassResolution", "h2MassResolution", {HistType::kTH2F, {ptAxis, massResolutionAxis}}); + rSigmaMinus.add("h2PtResolution", "h2PtResolution", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); + rSigmaMinus.add("h2RadiusResolution", "h2RadiusResolution", {HistType::kTH2F, {ptAxis, radiusResolutionAxis}}); + + rSigmaMinus.add("h2NSigmaTOFPiPt", "h2NSigmaTOFPiPt", {HistType::kTH2F, {ptAxis, nSigmaPiAxis}}); + rSigmaMinus.add("h2NSigmaTOFPrPt", "h2NSigmaTOFPrPt", {HistType::kTH2F, {ptAxis, nSigmaPrAxis}}); + + // BC ID comparison histograms + rSigmaMinus.add("hMcCollIdCoherence", "McCollId (coll == daug)", {HistType::kTH1F, {boolAxis}}); + rSigmaMinus.add("h2CollId_BCId", "(McCollId coherence) vs (EvSelBC == McBC)", {HistType::kTH2F, {boolAxis, boolAxis}}); + rSigmaMinus.add("h2BCId_comp", "(McBC == EvSelBC) vs (BC == EvSelBC)", {HistType::kTH2F, {boolAxis, boolAxis}}); + } + + if (doprocessFindable) { + std::vector filterLabels = {"Initial", "ITS/TPC present", "ITS/TPC quality", "Moth p_{T}", "max #eta", "max #Delta#phi", "max #Delta Z", "max DCAmoth", "min DCAdaug", "min Radius", "sel8 coll", "Daug TOF"}; + + // Add findable Sigma histograms + rFindable.add("hfakeITSfindable", "hfakeITSfindable", {HistType::kTH1F, {fakeITSAxis}}); + rFindable.add("hFilterIndex", "hFilterIndex", {HistType::kTH1F, {filtersAxis}}); + rFindable.add("h2MCRadiusFilterIndex", "h2MCRadiusFilterIndex", {HistType::kTH2F, {filtersAxis, radiusAxis}}); + rFindable.add("h2RecRadiusFilterIndex", "h2RecRadiusFilterIndex", {HistType::kTH2F, {filtersAxis, radiusAxis}}); + + auto hFilterIndex = rFindable.get(HIST("hFilterIndex")); + auto h2MCRadiusFilterIndex = rFindable.get(HIST("h2MCRadiusFilterIndex")); + auto h2RecRadiusFilterIndex = rFindable.get(HIST("h2RecRadiusFilterIndex")); + for (size_t i = 0; i < filterLabels.size(); ++i) { + hFilterIndex->GetXaxis()->SetBinLabel(i + 1, filterLabels[i].c_str()); + h2MCRadiusFilterIndex->GetXaxis()->SetBinLabel(i + 1, filterLabels[i].c_str()); + h2RecRadiusFilterIndex->GetXaxis()->SetBinLabel(i + 1, filterLabels[i].c_str()); + } + + rFindable.add("h2MCRadiusFilter_plus_protonkink", "h2MCRadiusFilter_plus_protonkink", {HistType::kTH2F, {filtersAxis, radiusAxis}}); + rFindable.add("h2MCRadiusFilter_plus_pikink", "h2MCRadiusFilter_plus_pikink", {HistType::kTH2F, {filtersAxis, radiusAxis}}); + rFindable.add("h2MCRadiusFilter_minus_pikink", "h2MCRadiusFilter_minus_pikink", {HistType::kTH2F, {filtersAxis, radiusAxis}}); + + rFindable.add("h2PtFilter_plus_protonkink", "h2PtFilter_plus_protonkink", {HistType::kTH2F, {filtersAxis, ptUnsignedAxis}}); + rFindable.add("h2PtFilter_plus_pikink", "h2PtFilter_plus_pikink", {HistType::kTH2F, {filtersAxis, ptUnsignedAxis}}); + rFindable.add("h2PtFilter_minus_pikink", "h2PtFilter_minus_pikink", {HistType::kTH2F, {filtersAxis, ptUnsignedAxis}}); + + rFindable.add("h2PtDaugFilter_plus_protonkink", "h2PtDaugFilter_plus_protonkink", {HistType::kTH2F, {filtersAxis, ptUnsignedAxis}}); + rFindable.add("h2PtDaugFilter_plus_pikink", "h2PtDaugFilter_plus_pikink", {HistType::kTH2F, {filtersAxis, ptUnsignedAxis}}); + rFindable.add("h2PtDaugFilter_minus_pikink", "h2PtDaugFilter_minus_pikink", {HistType::kTH2F, {filtersAxis, ptUnsignedAxis}}); + + rFindable.add("h2DCAMothPt_protonkink", "h2DCAMothPt_protonkink", {HistType::kTH2F, {ptAxis, dcaMothAxis}}); + rFindable.add("h2DCADaugPt_protonkink", "h2DCADaugPt_protonkink", {HistType::kTH2F, {ptAxis, dcaDaugAxis}}); + rFindable.add("h2DCAMothPt_pikink", "h2DCAMothPt_pikink", {HistType::kTH2F, {ptAxis, dcaMothAxis}}); + rFindable.add("h2DCADaugPt_pikink", "h2DCADaugPt_pikink", {HistType::kTH2F, {ptAxis, dcaDaugAxis}}); + } + } + + void initCCDB(aod::BCs::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + LOG(info) << "Initializing CCDB for run " << mRunNumber; + o2::parameters::GRPMagField* grpmag = ccdb->getForRun(grpmagPath, mRunNumber); + o2::base::Propagator::initFieldFromGRP(grpmag); + mBz = grpmag->getNominalL3Field(); + if (!matLUT) { + matLUT = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + } + o2::base::Propagator::Instance()->setMatLUT(matLUT); + LOG(info) << "Task initialized for run " << mRunNumber << " with magnetic field " << mBz << " kZG"; + } + + float alphaAP(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 qtAP(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 cosPAngle(const std::array& momMother, const std::array& posMother, const std::array& posKink) + { + std::array vMother = {posKink[0] - posMother[0], posKink[1] - posMother[1], posKink[2] - posMother[2]}; + float pMother = std::sqrt(std::inner_product(momMother.begin(), momMother.end(), momMother.begin(), 0.f)); + float vMotherNorm = std::sqrt(std::inner_product(vMother.begin(), vMother.end(), vMother.begin(), 0.f)); + return (std::inner_product(momMother.begin(), momMother.end(), vMother.begin(), 0.f)) / (pMother * vMotherNorm); + } + + void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& KinkCands, TracksFull const&) + { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + return; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + + for (const auto& kinkCand : KinkCands) { + auto dauTrack = kinkCand.trackDaug_as(); + + if (std::abs(dauTrack.tpcNSigmaPi()) > cutNSigmaPi) { + continue; + } + + float alphaAPValue = alphaAP(std::array{kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}, std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}); + float qtValue = qtAP(std::array{kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}, std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}); + rSigmaMinus.fill(HIST("h2ArmenterosPreCuts"), alphaAPValue, qtValue); + + if (qtValue < cutMinQtAP || qtValue > cutMaxQtAP) { + continue; + } + float cosPointingAngleRec = cosPAngle(std::array{kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}, + std::array{0.0f, 0.0f, 0.0f}, + std::array{kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}); + rSigmaMinus.fill(HIST("h2CosPointingAnglePt"), kinkCand.mothSign() * kinkCand.ptMoth(), cosPointingAngleRec); + + rSigmaMinus.fill(HIST("h2MassSigmaMinusPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2SigmaMassVsXiMass"), kinkCand.mXiMinus(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2NSigmaTPCPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tpcNSigmaPi()); + rSigmaMinus.fill(HIST("h2DCAMothPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.dcaMothPv()); + rSigmaMinus.fill(HIST("h2DCADaugPt"), kinkCand.mothSign() * kinkCand.ptDaug(), kinkCand.dcaDaugPv()); + + if (fillOutputTree) { + outputDataTable(kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx(), + kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth(), + kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug(), + kinkCand.dcaMothPv(), kinkCand.dcaDaugPv(), kinkCand.dcaKinkTopo(), + kinkCand.mothSign(), + dauTrack.tpcNSigmaPi(), dauTrack.tpcNSigmaPr(), dauTrack.tpcNSigmaKa(), + dauTrack.tofNSigmaPi(), dauTrack.tofNSigmaPr(), dauTrack.tofNSigmaKa()); + } + } + } + PROCESS_SWITCH(sigmaminustask, processData, "Data processing", true); + + void processMC(CollisionsFullMC const& collisions, aod::KinkCands const& KinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const&, aod::McCollisions const&) + { + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + continue; + } + + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + auto kinkCandPerColl = KinkCands.sliceBy(mPerCol, collision.globalIndex()); + + for (const auto& kinkCand : kinkCandPerColl) { + + auto dauTrack = kinkCand.trackDaug_as(); + auto mothTrack = kinkCand.trackMoth_as(); + 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 + } + if (std::abs(dauTrack.tpcNSigmaPi()) > cutNSigmaPi) { + continue; + } + + // histograms filled with all kink candidates + float alphaAPValue = alphaAP(std::array{kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}, std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}); + float qtValue = qtAP(std::array{kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}, std::array{kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug()}); + rSigmaMinus.fill(HIST("h2ArmenterosPreCuts"), alphaAPValue, qtValue); + rSigmaMinus.fill(HIST("h2MassSigmaMinusPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2SigmaMassVsXiMass"), kinkCand.mXiMinus(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2NSigmaTPCPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tpcNSigmaPi()); + + // do MC association + auto mcLabSigma = trackLabelsMC.rawIteratorAt(mothTrack.globalIndex()); + auto mcLabPiDau = trackLabelsMC.rawIteratorAt(dauTrack.globalIndex()); + if (mcLabSigma.has_mcParticle() && mcLabPiDau.has_mcParticle()) { + auto mcTrackSigma = mcLabSigma.mcParticle_as(); + auto mcTrackPiDau = mcLabPiDau.mcParticle_as(); + if (!mcTrackPiDau.has_mothers()) { + continue; + } + for (auto& piMother : mcTrackPiDau.mothers_as()) { + if (piMother.globalIndex() != mcTrackSigma.globalIndex()) { + continue; + } + if (std::abs(mcTrackSigma.pdgCode()) != 3112 && std::abs(mcTrackSigma.pdgCode()) != 3222) { + continue; + } + if (std::abs(mcTrackPiDau.pdgCode()) != 211 && std::abs(mcTrackPiDau.pdgCode()) != 2212) { + continue; + } + + float MotherMassMC = std::sqrt(piMother.e() * piMother.e() - piMother.p() * piMother.p()); + float MotherpTMC = piMother.pt(); + float deltaXMother = mcTrackPiDau.vx() - piMother.vx(); + float deltaYMother = mcTrackPiDau.vy() - piMother.vy(); + float decayRadiusMC = std::sqrt(deltaXMother * deltaXMother + deltaYMother * deltaYMother); + float decayRadiusRec = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); + float cosPointingAngleRec = cosPAngle(std::array{kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth()}, + std::array{0.0f, 0.0f, 0.0f}, + std::array{kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx()}); + + // Check coherence of MCcollision Id for daughter MCparticle and reconstructed collision + bool mcCollisionIdCheck = false; + if (collision.has_mcCollision()) { + mcCollisionIdCheck = collision.mcCollision().globalIndex() == mcTrackPiDau.mcCollisionId(); + } + // Check bunch crossing ID coherence + auto mcCollision = mcTrackPiDau.template mcCollision_as(); + // bool BCId_vs_MCBCId = collision.bcId() == mcCollision.bcId(); + bool BCId_vs_EvSel = collision.bcId() == collision.foundBCId(); + bool EvSel_vs_MCBCId = collision.foundBCId() == mcCollision.bcId(); + + rSigmaMinus.fill(HIST("hMcCollIdCoherence"), static_cast(mcCollisionIdCheck)); + rSigmaMinus.fill(HIST("h2CollId_BCId"), static_cast(mcCollisionIdCheck), static_cast(EvSel_vs_MCBCId)); + rSigmaMinus.fill(HIST("h2BCId_comp"), static_cast(EvSel_vs_MCBCId), static_cast(BCId_vs_EvSel)); + + rSigmaMinus.fill(HIST("h2MassPtMCRec"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); + rSigmaMinus.fill(HIST("h2MassResolution"), kinkCand.mothSign() * kinkCand.ptMoth(), (kinkCand.mSigmaMinus() - MotherMassMC) / MotherMassMC); + rSigmaMinus.fill(HIST("h2PtResolution"), kinkCand.mothSign() * kinkCand.ptMoth(), (kinkCand.ptMoth() - MotherpTMC) / MotherpTMC); + rSigmaMinus.fill(HIST("h2RadiusResolution"), kinkCand.mothSign() * kinkCand.ptMoth(), (decayRadiusRec - decayRadiusMC) / decayRadiusMC); + rSigmaMinus.fill(HIST("h2DCAMothPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.dcaMothPv()); + rSigmaMinus.fill(HIST("h2DCADaugPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.dcaDaugPv()); + rSigmaMinus.fill(HIST("h2CosPointingAnglePt"), kinkCand.mothSign() * kinkCand.ptMoth(), cosPointingAngleRec); + + if (std::abs(mcTrackPiDau.pdgCode()) == 211) { + rSigmaMinus.fill(HIST("h2NSigmaTOFPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tofNSigmaPi()); + } else if (std::abs(mcTrackPiDau.pdgCode()) == 2212) { + rSigmaMinus.fill(HIST("h2NSigmaTOFPrPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tofNSigmaPr()); + } + + // fill the output table with Mc information + if (fillOutputTree) { + outputDataTableMC(kinkCand.xDecVtx(), kinkCand.yDecVtx(), kinkCand.zDecVtx(), + kinkCand.pxMoth(), kinkCand.pyMoth(), kinkCand.pzMoth(), + kinkCand.pxDaug(), kinkCand.pyDaug(), kinkCand.pzDaug(), + kinkCand.dcaMothPv(), kinkCand.dcaDaugPv(), kinkCand.dcaKinkTopo(), + kinkCand.mothSign(), + dauTrack.tpcNSigmaPi(), dauTrack.tpcNSigmaPr(), dauTrack.tpcNSigmaKa(), + dauTrack.tofNSigmaPi(), dauTrack.tofNSigmaPr(), dauTrack.tofNSigmaKa(), + mcTrackSigma.pdgCode(), mcTrackPiDau.pdgCode(), + MotherpTMC, MotherMassMC, decayRadiusMC, mcCollisionIdCheck); + } + } + } // MC association and selection + } // kink cand loop + } // collision loop + + // Loop over all generated particles to fill MC histograms + for (const auto& mcPart : particlesMC) { + if ((std::abs(mcPart.pdgCode()) != 3112 && std::abs(mcPart.pdgCode()) != 3222) || std::abs(mcPart.y()) > cutRapMotherMC) { // only sigma mothers and rapidity cut + continue; + } + if (!mcPart.has_daughters()) { + continue; // Skip if no daughters + } + bool hasSigmaDaughter = false; + int daug_pdg = 0; + std::array secVtx; + std::array momDaug; + for (const auto& daughter : mcPart.daughters_as()) { + if (std::abs(daughter.pdgCode()) == 211 || std::abs(daughter.pdgCode()) == 2212) { // Pi or proton daughter + hasSigmaDaughter = true; + secVtx = {daughter.vx(), daughter.vy(), daughter.vz()}; + momDaug = {daughter.px(), daughter.py(), daughter.pz()}; + daug_pdg = daughter.pdgCode(); + break; // Found a daughter, exit loop + } + } + if (!hasSigmaDaughter) { + continue; // Skip if no pi/proton daughter found + } + float mcMass = std::sqrt(mcPart.e() * mcPart.e() - mcPart.p() * mcPart.p()); + float mcDecayRadius = std::sqrt((secVtx[0] - mcPart.vx()) * (secVtx[0] - mcPart.vx()) + (secVtx[1] - mcPart.vy()) * (secVtx[1] - mcPart.vy())); + int sigmaSign = mcPart.pdgCode() > 0 ? 1 : -1; // Determine the sign of the Sigma + rSigmaMinus.fill(HIST("h2MassPtMCGen"), sigmaSign * mcPart.pt(), mcMass); + + // Fill output table with non reconstructed MC candidates + if (fillOutputTree) { + outputDataTableMC(-999, -999, -999, + -999, -999, -999, + -999, -999, -999, + -999, -999, -999, + sigmaSign, + -999, -999, -999, + -999, -999, -999, + mcPart.pdgCode(), daug_pdg, + mcPart.pt(), mcMass, mcDecayRadius, false); + } + } + } + PROCESS_SWITCH(sigmaminustask, processMC, "MC processing", false); + + void fillFindableHistograms(int filterIndex, float mcRadius, float recRadius, float ptMoth, float ptDaug, bool isSigmaMinus, bool isPiDaughter) + { + rFindable.fill(HIST("hFilterIndex"), filterIndex); + rFindable.fill(HIST("h2MCRadiusFilterIndex"), filterIndex, mcRadius); + rFindable.fill(HIST("h2RecRadiusFilterIndex"), filterIndex, recRadius); + + if (isPiDaughter) { + if (isSigmaMinus) { + rFindable.fill(HIST("h2MCRadiusFilter_minus_pikink"), filterIndex, mcRadius); + rFindable.fill(HIST("h2PtFilter_minus_pikink"), filterIndex, ptMoth); + rFindable.fill(HIST("h2PtDaugFilter_minus_pikink"), filterIndex, ptDaug); + } else { + rFindable.fill(HIST("h2MCRadiusFilter_plus_pikink"), filterIndex, mcRadius); + rFindable.fill(HIST("h2PtFilter_plus_pikink"), filterIndex, ptMoth); + rFindable.fill(HIST("h2PtDaugFilter_plus_pikink"), filterIndex, ptDaug); + } + } else { + if (!isSigmaMinus) { + rFindable.fill(HIST("h2MCRadiusFilter_plus_protonkink"), filterIndex, mcRadius); + rFindable.fill(HIST("h2PtFilter_plus_protonkink"), filterIndex, ptMoth); + rFindable.fill(HIST("h2PtDaugFilter_plus_protonkink"), filterIndex, ptDaug); + } + } + } + + void processFindable(aod::KinkCands const& kinkCands, aod::McTrackLabels const& trackLabelsMC, + TracksFull const& tracks, aod::McParticles const&, CollisionsFullMC const&, aod::BCs const&) + { + // A - generated findable track pairs map: mcMother.globalIndex() -> (motherTrack.globalIndex(), daughterTrack.globalIndex()) + std::unordered_map> allCandsIndices; + + for (const auto& track : tracks) { + auto mcLabel = trackLabelsMC.rawIteratorAt(track.globalIndex()); + if (!mcLabel.has_mcParticle()) { + continue; + } + auto mcParticle = mcLabel.mcParticle_as(); + + if (mcParticle.has_daughters() && (std::abs(mcParticle.pdgCode()) == 3112 || std::abs(mcParticle.pdgCode()) == 3222)) { + allCandsIndices[mcParticle.globalIndex()] = {track.globalIndex(), -1}; + } + } + + for (const auto& track : tracks) { + auto mcLabel = trackLabelsMC.rawIteratorAt(track.globalIndex()); + if (!mcLabel.has_mcParticle()) { + continue; + } + auto mcParticle = mcLabel.mcParticle_as(); + + if (mcParticle.has_mothers() && (std::abs(mcParticle.pdgCode()) == 211 || std::abs(mcParticle.pdgCode()) == 2212)) { + for (const auto& mother : mcParticle.mothers_as()) { + auto it = allCandsIndices.find(mother.globalIndex()); + if (it != allCandsIndices.end()) { + it->second.second = track.globalIndex(); + break; + } + } + } + } + + // B - reconstructed kinkcands map: mcMother.globalIndex() -> kinkCand.globalIndex() + std::unordered_map findableToKinkCand; + for (const auto& kinkCand : kinkCands) { + auto motherTrack = kinkCand.trackMoth_as(); + auto daughterTrack = kinkCand.trackDaug_as(); + + auto mcLabMoth = trackLabelsMC.rawIteratorAt(motherTrack.globalIndex()); + auto mcLabDaug = trackLabelsMC.rawIteratorAt(daughterTrack.globalIndex()); + if (!mcLabMoth.has_mcParticle() || !mcLabDaug.has_mcParticle()) { + continue; + } + auto mcMother = mcLabMoth.mcParticle_as(); + auto mcDaughter = mcLabDaug.mcParticle_as(); + + if (std::abs(mcMother.pdgCode()) != 3112 && std::abs(mcMother.pdgCode()) != 3222) { + continue; + } + if (std::abs(mcDaughter.pdgCode()) != 211 && std::abs(mcDaughter.pdgCode()) != 2212) { + continue; + } + + auto findableIt = allCandsIndices.find(mcMother.globalIndex()); + if (findableIt != allCandsIndices.end() && + findableIt->second.first == motherTrack.globalIndex() && + findableIt->second.second == daughterTrack.globalIndex()) { + + findableToKinkCand[mcMother.globalIndex()] = kinkCand.globalIndex(); + } + } + + // C - loop on valid pairs for findable analysis + for (const auto& [mcMotherIndex, trackIndices] : allCandsIndices) { + if (trackIndices.second == -1 || trackIndices.first == -1) { + continue; + } + + // Retrieve mother and daughter tracks and mcParticles + auto motherTrack = tracks.rawIteratorAt(trackIndices.first); + auto daughterTrack = tracks.rawIteratorAt(trackIndices.second); + auto mcLabMoth = trackLabelsMC.rawIteratorAt(motherTrack.globalIndex()); + auto mcLabDaug = trackLabelsMC.rawIteratorAt(daughterTrack.globalIndex()); + auto mcMother = mcLabMoth.mcParticle_as(); + auto mcDaughter = mcLabDaug.mcParticle_as(); + + // Compute useful quantities for histograms + bool isSigmaMinus = (std::abs(mcMother.pdgCode()) == 3112); + bool isPiDaughter = (std::abs(mcDaughter.pdgCode()) == 211); + int sigmaSign = mcMother.pdgCode() > 0 ? 1 : -1; + float recPtDaughter = daughterTrack.pt(); + float recPtMother = motherTrack.pt(); + float mcRadius = std::sqrt((mcMother.vx() - mcDaughter.vx()) * (mcMother.vx() - mcDaughter.vx()) + (mcMother.vy() - mcDaughter.vy()) * (mcMother.vy() - mcDaughter.vy())); + float recRadius = -1.0; + if (findableToKinkCand.find(mcMother.globalIndex()) != findableToKinkCand.end()) { + auto kinkCand = kinkCands.rawIteratorAt(findableToKinkCand[mcMother.globalIndex()]); + recRadius = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); + } + + // Check for detector mismatches in ITS mother tracks + auto mask_value = mcLabMoth.mcMask(); + int mismatchITS_index = -1; + + for (int i = 0; i < 7; ++i) { // ITS has layers 0-6, bit ON means mismatch + if ((mask_value & (1 << i)) != 0) { + mismatchITS_index = i; + break; + } + } + + // Define filter index and progressively apply kinkbuilder cuts to track pairs + int filterIndex = 0; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + + // 1 - tracks with right ITS, TPC, TOF signals + if (motherTrack.has_collision() && motherTrack.hasITS() && !motherTrack.hasTPC() && !motherTrack.hasTOF() && + daughterTrack.hasITS() && daughterTrack.hasTPC()) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + rFindable.fill(HIST("hfakeITSfindable"), mismatchITS_index); + } else { + continue; + } + + // 2 - moth+daug track quality cuts + bool motherGoodITS = motherTrack.hasITS() && motherTrack.itsNCls() < 6 && motherTrack.itsNClsInnerBarrel() == 3 && motherTrack.itsChi2NCl() < 36; + bool daughterGoodITSTPC = daughterTrack.hasITS() && daughterTrack.hasTPC() && daughterTrack.itsNClsInnerBarrel() == 0 && + daughterTrack.itsNCls() < 4 && daughterTrack.tpcNClsCrossedRows() > 0.8 * daughterTrack.tpcNClsFindable() && daughterTrack.tpcNClsFound() > nTPCClusMinDaugKB; + if (motherGoodITS && daughterGoodITSTPC) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 3 - mother track min pT + if (motherTrack.pt() > minPtMothKB) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 4 - geometric cuts: eta + if (std::abs(motherTrack.eta()) < etaMaxKB && std::abs(daughterTrack.eta()) < etaMaxKB) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 5 - geometric cuts: phi difference + if (std::abs(motherTrack.phi() - daughterTrack.phi()) * radToDeg < maxPhiDiffKB) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // DCA calculation: initialization CCDB + auto collision = motherTrack.template collision_as(); + auto bc = collision.template bc_as(); + initCCDB(bc); + const o2::math_utils::Point3D collVtx{collision.posX(), collision.posY(), collision.posZ()}; + o2::track::TrackParCov trackParCovMoth = getTrackParCov(motherTrack); + o2::track::TrackParCov trackParCovDaug = getTrackParCov(daughterTrack); + + // get DCA to PV for mother and daughter tracks + std::array dcaInfoMoth; + o2::base::Propagator::Instance()->propagateToDCA(collVtx, trackParCovMoth, mBz, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoMoth); + std::array dcaInfoDaug; + o2::base::Propagator::Instance()->propagateToDCA(collVtx, trackParCovDaug, mBz, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoDaug); + float dcaXYMother = std::abs(dcaInfoMoth[0]); + float dcaXYDaughter = std::abs(dcaInfoDaug[0]); + if (isPiDaughter) { + rFindable.fill(HIST("h2DCAMothPt_pikink"), sigmaSign * recPtMother, dcaXYMother); + rFindable.fill(HIST("h2DCADaugPt_pikink"), sigmaSign * recPtDaughter, dcaXYDaughter); + } else { + rFindable.fill(HIST("h2DCAMothPt_protonkink"), sigmaSign * recPtMother, dcaXYMother); + rFindable.fill(HIST("h2DCADaugPt_protonkink"), sigmaSign * recPtDaughter, dcaXYDaughter); + } + + // 6 - max Z difference + if (std::abs(trackParCovMoth.getZ() - trackParCovDaug.getZ()) < maxZDiffKB) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 7 - DCA mother + if (dcaXYMother < maxDcaMothPvKB) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 8 - DCA daughter + if (dcaXYDaughter > minDcaDaugPvKB) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 9 - radius cut + if (recRadius > radiusCutKB) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 10 - collision selection + if (!(std::abs(collision.posZ()) > cutzvertex || !collision.sel8())) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } else { + continue; + } + + // 11 - TOF daughter presence + if (daughterTrack.hasTOF()) { + filterIndex += 1; + fillFindableHistograms(filterIndex, mcRadius, recRadius, recPtMother, recPtDaughter, isSigmaMinus, isPiDaughter); + } + } + } + + PROCESS_SWITCH(sigmaminustask, processFindable, "Findable Sigma processing", 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 e1b601fb4d8..ce5597563da 100644 --- a/PWGLF/TableProducer/Strangeness/stracents.cxx +++ b/PWGLF/TableProducer/Strangeness/stracents.cxx @@ -39,7 +39,7 @@ using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -MetadataHelper metadataInfo; // Metadata helper +o2::common::core::MetadataHelper metadataInfo; // Metadata helper struct straCents { Produces strangeCents; diff --git a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx b/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx similarity index 76% rename from PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx rename to PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx index 955b4ebc142..455da9e0719 100644 --- a/PWGLF/TableProducer/Strangeness/LFStrangeTreeCreator.cxx +++ b/PWGLF/TableProducer/Strangeness/strangeTreeCreator.cxx @@ -9,35 +9,37 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -#include -#include -#include +/// \file strangeTreeCreator.cxx +/// \brief table producer for strangeness studies +/// \author Mario Ciacco -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "Common/DataModel/EventSelection.h" +#include "PWGLF/DataModel/LFSlimStrangeTables.h" #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "DetectorsBase/Propagator.h" -#include "DetectorsBase/GeometryManager.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" #include "Common/Core/PID/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/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" -#include "DCAFitter/DCAFitterN.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFSlimStrangeTables.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 "TDatabasePDG.h" +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -49,7 +51,7 @@ namespace { void momTotXYZ(std::array& momA, std::array const& momB, std::array const& momC) { - for (int i = 0; i < 3; ++i) { + for (unsigned int i{0}; i < momA.size(); ++i) { momA[i] = momB[i] + momC[i]; } } @@ -99,10 +101,27 @@ float etaFromMom(std::array const& momA, std::array const& m (1.f * momA[2] + 1.f * momB[2]) * (1.f * momA[2] + 1.f * momB[2])) - (1.f * momA[2] + 1.f * momB[2]))); } -float CalculateDCAStraightToPV(float X, float Y, float Z, float Px, float Py, float Pz, float pvX, float pvY, float pvZ) +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)); } +float kineFactor(std::array const& momA, std::array const& momB, std::array const& momC, float const& massB, float const& massC, bool const& reso) +{ + float invMass = invMass2Body(momA, momC, momB, massC, massB); + float ptC = std::hypot(momC[0], momC[1]); + float ptB = std::hypot(momB[0], momB[1]); + float p2C = momC[0] * momC[0] + momC[1] * momC[1] + momC[2] * momC[2]; + float p2B = momB[0] * momB[0] + momB[1] * momB[1] + momB[2] * momB[2]; + float eC = RecoDecay::sqrtSumOfSquares(momC[0], momC[1], momC[2], massC); + float eB = RecoDecay::sqrtSumOfSquares(momB[0], momB[1], momB[2], massB); + float pCpB = momC[0] * momB[0] + momC[1] * momB[1] + momC[2] * momB[2]; + float kineC = (eB * p2C / eC / ptC) - pCpB / ptC; + float kineB = (eC * p2B / eB / ptB) - pCpB / ptB; + if (reso) { + return std::hypot(kineC, kineB) / invMass; + } + return (kineC + kineB) / invMass; +} } // namespace struct CandidateV0 { @@ -145,7 +164,7 @@ struct CandidateV0 { int64_t globalIndexNeg = -999; }; -struct LFStrangeTreeCreator { +struct StrangeTreeCreator { Produces lambdaTableML; Produces v0TableAP; Produces mcLambdaTableML; @@ -156,16 +175,19 @@ struct LFStrangeTreeCreator { o2::vertexing::DCAFitterN<2> fitter; int mRunNumber; - float d_bz; - // o2::base::MatLayerCylSet* lut = nullptr; - Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; + float mBz; + o2::base::MatLayerCylSet* lut = nullptr; + Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrLUT), "Type of material correction"}; ConfigurableAxis centAxis{"centAxis", {106, 0, 106}, "binning for the centrality"}; ConfigurableAxis zVtxAxis{"zVtxBins", {100, -20.f, 20.f}, "Binning for the vertex z in cm"}; + ConfigurableAxis etaAxis{"etaAxis", {8, -0.8f, 0.8f}, "binning for pseudorapidity"}; + ConfigurableAxis massKineAxis{"kineAxis", {3000, -3.f, 3.f}, "binning for the kinematic-transofrmed mass shift distributions"}; // 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"}; ConfigurableAxis massXiAxis{"massXiAxis", {400, o2::constants::physics::MassXiMinus - 0.05f, o2::constants::physics::MassXiMinus + 0.05f}, "binning for the Xi invariant-mass"}; + ConfigurableAxis massK0sAxis{"massK0sAxis", {400, o2::constants::physics::MassK0 - 0.1f, o2::constants::physics::MassK0 + 0.1f}, "binning for the K0s invariant-mass"}; Configurable zVtxMax{"zVtxMax", 10.0f, "maximum z position of the primary vertex"}; Configurable etaMax{"etaMax", 0.8f, "maximum eta"}; @@ -184,21 +206,24 @@ struct LFStrangeTreeCreator { Configurable v0trackNsharedClusTpc{"v0trackNsharedClusTpc", 5, "Maximum number of shared TPC clusters for V0 daughter"}; Configurable vetoMassK0Short{"vetoMassK0Short", 0.01f, "veto for V0 compatible with K0s mass"}; Configurable v0radiusMax{"v0radiusMax", 100.f, "maximum V0 radius eccepted"}; - - Configurable v0setting_dcav0dau{"v0setting_dcav0dau", 0.5f, "DCA V0 Daughters"}; - Configurable v0setting_dcav0pv{"v0setting_dcav0pv", 1.f, "DCA V0 to Pv"}; - Configurable v0setting_dcadaughtopv{"v0setting_dcadaughtopv", 0.1f, "DCA Pos To PV"}; - Configurable v0setting_cospa{"v0setting_cospa", 0.99f, "V0 CosPA"}; - Configurable v0setting_radius{"v0setting_radius", 5.f, "v0radius"}; - Configurable v0setting_lifetime{"v0setting_lifetime", 40.f, "v0 lifetime cut"}; - Configurable v0setting_nsigmatpc{"v0setting_nsigmatpc", 4.f, "nsigmatpc"}; - Configurable cascsetting_dcabachpv{"cascsetting_dcabachpv", 0.1f, "cascdcabachpv"}; - Configurable cascsetting_cospa{"cascsetting_cospa", 0.99f, "casc cospa cut"}; - Configurable cascsetting_dcav0bach{"cascsetting_dcav0bach", 1.0f, "dcav0bach"}; - Configurable cascsetting_vetoOm{"cascsetting_vetoOm", 0.01f, "vetoOm"}; - Configurable cascsetting_mXi{"cascsetting_mXi", 0.02f, "mXi"}; + Configurable v0alphaMax{"v0alphaMax", 10.f, "maximum Armenteros alpha (longitdinal momentum asymmetry)"}; + Configurable v0qtMin{"v0qtMin", 0.f, "minimum Armenteros qt (transverse momentum)"}; + + Configurable v0settingDcav0dau{"v0setting_dcav0dau", 0.5f, "DCA V0 Daughters"}; + Configurable v0settingDcav0pv{"v0setting_dcav0pv", 1.f, "DCA V0 to Pv"}; + Configurable v0settingDcadaughtopv{"v0setting_dcadaughtopv", 0.1f, "DCA Pos To PV"}; + Configurable v0settingCospa{"v0setting_cospa", 0.99f, "V0 CosPA"}; + Configurable v0settingRadius{"v0setting_radius", 5.f, "v0radius"}; + Configurable v0settingLifetime{"v0setting_lifetime", 40.f, "v0 lifetime cut"}; + Configurable v0settingNsigmatpc{"v0setting_nsigmatpc", 4.f, "nsigmatpc"}; + Configurable cascsettingDcabachpv{"cascsetting_dcabachpv", 0.1f, "cascdcabachpv"}; + Configurable cascsettingCospa{"cascsetting_cospa", 0.99f, "casc cospa cut"}; + Configurable cascsettingDcav0bach{"cascsetting_dcav0bach", 1.0f, "dcav0bach"}; + Configurable cascsettingVetoOm{"cascsetting_vetoOm", 0.01f, "vetoOm"}; + Configurable cascsettingMXi{"cascsetting_mXi", 0.02f, "mXi"}; Configurable lambdaMassCut{"lambdaMassCut", 0.02f, "maximum deviation from PDG mass (for QA histograms)"}; Configurable k0short{"k0short", false, "process for k0short (true) or lambda (false)"}; + Configurable tpcFindableClsOverCR{"tpcFindableClsOverCR", 0.8, "fraction of findable clusters over crossed rows in TPC"}; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -218,7 +243,7 @@ struct LFStrangeTreeCreator { if (track.itsNCls() < v0trackNclusItsCut || track.tpcNClsFound() < v0trackNclusTpcCut || track.tpcNClsCrossedRows() < v0trackNclusTpcCut || - track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable() || + track.tpcNClsCrossedRows() < tpcFindableClsOverCR * track.tpcNClsFindable() || track.tpcNClsShared() > v0trackNsharedClusTpc) { return false; } @@ -243,25 +268,28 @@ struct LFStrangeTreeCreator { o2::base::Propagator::initFieldFromGRP(grpmag); // Fetch magnetic field from ccdb for current collision - d_bz = o2::base::Propagator::Instance()->getNominalBz(); - LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << d_bz << " kG"; + mBz = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Retrieved GRP for timestamp " << timestamp << " with magnetic field of " << mBz << " kG"; mRunNumber = bc.runNumber(); - fitter.setBz(d_bz); + fitter.setBz(mBz); - // o2::base::Propagator::Instance()->setMatLUT(lut); + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); + o2::base::Propagator::Instance()->setMatLUT(lut); + + int mat{static_cast(cfgMaterialCorrection)}; + fitter.setMatCorrType(static_cast(mat)); } void init(o2::framework::InitContext&) { mRunNumber = 0; - d_bz = 0; + mBz = 0; ccdb->setURL("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - // lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get("GLO/Param/MatLUT")); fitter.setPropagateToPCA(true); fitter.setMaxR(200.); @@ -272,8 +300,6 @@ struct LFStrangeTreeCreator { fitter.setMaxChi2(1e9); fitter.setUseAbsDCA(true); fitter.setWeightedFinalPCA(false); - int mat{static_cast(cfgMaterialCorrection)}; - fitter.setMatCorrType(static_cast(mat)); // event QA histos.add("QA/zVtx", ";#it{z}_{vtx} (cm);Entries", HistType::kTH1F, {zVtxAxis}); @@ -281,6 +307,11 @@ struct LFStrangeTreeCreator { // v0 QA histos.add("QA/massLambda", ";Centrality (%);#it{p}_{T} (GeV/#it{c});#it{M}(p + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, massLambdaAxis}); histos.add("QA/massXi", ";Centrality (%);#it{p}_{T} (GeV/#it{c});#it{M}(#Lambda + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH3F, {centAxis, momAxis, massXiAxis}); + histos.add("QA/massK0s", ";#it{p}_{T} (GeV/#it{c});#it{M}(#pi^{+} + #pi^{-}) (GeV/#it{c}^{2});Entries", HistType::kTH2F, {momAxis, massK0sAxis}); + + // histograms for momentum shift/resolution extraction + histos.add("massKineBias", ";#eta;#it{p}_{T} (GeV/#it{c});#delta#it{M}/#Sigma_{i}#partial#it{M}/#partial#it{p}^{i}_{T}", HistType::kTH3F, {etaAxis, momAxis, massKineAxis}); + histos.add("massKineReso", ";#eta;#it{p}_{T} (GeV/#it{c});#delta#it{M}/#Sigma_{i}(#partial#it{M}/#partial#it{p}^{i}_{T})^{2}", HistType::kTH3F, {etaAxis, momAxis, massKineAxis}); } template @@ -334,12 +365,21 @@ struct LFStrangeTreeCreator { } auto alpha = alphaAP(momV0, momPos, momNeg); + if (std::abs(alpha) > v0alphaMax) { + continue; + } + bool matter = alpha > 0; auto massPos = matter ? o2::constants::physics::MassProton : o2::constants::physics::MassPionCharged; auto massNeg = matter ? o2::constants::physics::MassPionCharged : o2::constants::physics::MassProton; auto mLambda = invMass2Body(momV0, momPos, momNeg, massPos, massNeg); auto mK0Short = invMass2Body(momV0, momPos, momNeg, o2::constants::physics::MassPionCharged, o2::constants::physics::MassPionCharged); + auto qt = qtAP(momV0, momPos); + if (std::abs(qt) < v0qtMin) { + continue; + } + // pid selections auto nSigmaTPCPos = matter ? posTrack.tpcNSigmaPr() : posTrack.tpcNSigmaPi(); auto nSigmaTPCNeg = matter ? negTrack.tpcNSigmaPi() : negTrack.tpcNSigmaPr(); @@ -349,7 +389,7 @@ struct LFStrangeTreeCreator { nSigmaTPCNeg = negTrack.tpcNSigmaPi(); } - if (std::abs(nSigmaTPCPos) > v0setting_nsigmatpc || std::abs(nSigmaTPCNeg) > v0setting_nsigmatpc) { + if (std::abs(nSigmaTPCPos) > v0settingNsigmatpc || std::abs(nSigmaTPCNeg) > v0settingNsigmatpc) { continue; } @@ -359,7 +399,7 @@ struct LFStrangeTreeCreator { } float dcaV0dau = std::sqrt(fitter.getChi2AtPCACandidate()); - if (dcaV0dau > v0setting_dcav0dau) { + if (dcaV0dau > v0settingDcav0dau) { continue; } @@ -367,22 +407,22 @@ struct LFStrangeTreeCreator { const auto& vtx = fitter.getPCACandidate(); float radiusV0 = std::hypot(vtx[0], vtx[1]); - if (radiusV0 < v0setting_radius || radiusV0 > v0radiusMax) { + if (radiusV0 < v0settingRadius || radiusV0 > v0radiusMax) { continue; } - float dcaV0Pv = CalculateDCAStraightToPV( + float dcaV0Pv = calculateDCAStraightToPV( vtx[0], vtx[1], vtx[2], momPos[0] + momNeg[0], momPos[1] + momNeg[1], momPos[2] + momNeg[2], collision.posX(), collision.posY(), collision.posZ()); - if (std::abs(dcaV0Pv) > v0setting_dcav0pv) { + if (std::abs(dcaV0Pv) > v0settingDcav0pv) { continue; } double cosPA = RecoDecay::cpa(primVtx, vtx, momV0); - if (cosPA < v0setting_cospa) { + if (cosPA < v0settingCospa) { continue; } @@ -395,38 +435,49 @@ struct LFStrangeTreeCreator { } else { particlemass = o2::constants::physics::MassLambda; } - float ML2P = particlemass * lengthTraveled / ptotal; - if (ML2P > v0setting_lifetime) { + float mL2P = particlemass * lengthTraveled / ptotal; + if (mL2P > v0settingLifetime) { continue; } o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, posTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); auto posDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (posDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { + if (posDcaToPv < v0settingDcadaughtopv && std::abs(dcaInfo[0]) < v0settingDcadaughtopv) { continue; } o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, negTrackCov, 2.f, fitter.getMatCorrType(), &dcaInfo); auto negDcaToPv = std::hypot(dcaInfo[0], dcaInfo[1]); - if (negDcaToPv < v0setting_dcadaughtopv && std::abs(dcaInfo[0]) < v0setting_dcadaughtopv) { + if (negDcaToPv < v0settingDcadaughtopv && std::abs(dcaInfo[0]) < v0settingDcadaughtopv) { continue; } if (std::abs(mLambda - o2::constants::physics::MassLambda0) > lambdaMassCut) { // for QA histograms continue; } + + float ptPos = std::hypot(momPos[0], momPos[1]); + float pPos = std::hypot(momPos[0], momPos[1], momPos[2]); + float etaPos = 0.5 * std::log((pPos + momPos[2]) / (pPos - momPos[2])); + float deltaMass = mK0Short - o2::constants::physics::MassK0; + float massKineBias = deltaMass / kineFactor(momV0, momPos, momNeg, o2::constants::physics::MassPiMinus, o2::constants::physics::MassPiMinus, false); + float massKineReso = deltaMass / kineFactor(momV0, momPos, momNeg, o2::constants::physics::MassPiMinus, o2::constants::physics::MassPiMinus, true); + histos.fill(HIST("QA/massLambda"), centrality, ptV0, mLambda); + histos.fill(HIST("QA/massK0s"), ptV0, mK0Short); + histos.fill(HIST("massKineBias"), etaPos, ptPos, massKineBias); + histos.fill(HIST("massKineReso"), etaPos, ptPos, massKineReso); CandidateV0 candV0; candV0.pt = matter > 0. ? ptV0 : -ptV0; candV0.eta = etaV0; - candV0.ct = ML2P; + candV0.ct = mL2P; candV0.len = lengthTraveled; candV0.mass = mLambda; candV0.radius = radiusV0; candV0.cpa = cosPA; candV0.alphaAP = alpha; - candV0.qtAP = qtAP(momV0, momPos); + candV0.qtAP = qt; candV0.trackv0 = fitter.createParentTrackParCov(); candV0.mompos = std::array{momPos[0], momPos[1], momPos[2]}; candV0.momneg = std::array{momNeg[0], momNeg[1], momNeg[2]}; @@ -442,7 +493,7 @@ struct LFStrangeTreeCreator { candidateV0s.push_back(candV0); } - for (auto& casc : cascades) { + for (const auto& casc : cascades) { auto v0 = casc.template v0_as(); auto itv0 = find_if(candidateV0s.begin(), candidateV0s.end(), [&](CandidateV0 v0cand) { return v0cand.globalIndex == v0.globalIndex(); }); if (itv0 == candidateV0s.end()) { @@ -452,7 +503,7 @@ struct LFStrangeTreeCreator { auto bachTrackPar = getTrackPar(bachTrack); o2::base::Propagator::Instance()->propagateToDCABxByBz({collision.posX(), collision.posY(), collision.posZ()}, bachTrackPar, 2.f, fitter.getMatCorrType(), &dcaInfo); - if (TMath::Abs(dcaInfo[0]) < cascsetting_dcabachpv) + if (std::abs(dcaInfo[0]) < cascsettingDcabachpv) continue; auto bachelorTrack = getTrackParCov(bachTrack); @@ -476,23 +527,23 @@ struct LFStrangeTreeCreator { bachelorTrack.getPxPyPzGlo(momBach); momTotXYZ(momCasc, momV0, momBach); - auto dcacascv0bach = TMath::Sqrt(fitter.getChi2AtPCACandidate()); - if (dcacascv0bach > cascsetting_dcav0bach) + auto dcacascv0bach = std::sqrt(fitter.getChi2AtPCACandidate()); + if (dcacascv0bach > cascsettingDcav0bach) continue; std::array primVtx = {collision.posX(), collision.posY(), collision.posZ()}; const auto& vtx = fitter.getPCACandidate(); double cosPA = RecoDecay::cpa(primVtx, vtx, momCasc); - if (cosPA < cascsetting_cospa) + if (cosPA < cascsettingCospa) continue; float mXi = invMass2Body(momCasc, momV0, momBach, o2::constants::physics::MassLambda0, o2::constants::physics::MassPionCharged); float mOm = invMass2Body(momCasc, momV0, momBach, o2::constants::physics::MassLambda0, o2::constants::physics::MassKaonCharged); - if (std::abs(mOm - o2::constants::physics::MassOmegaMinus) < cascsetting_vetoOm) + if (std::abs(mOm - o2::constants::physics::MassOmegaMinus) < cascsettingVetoOm) continue; - if (std::abs(mXi - o2::constants::physics::MassXiMinus) > cascsetting_mXi) + if (std::abs(mXi - o2::constants::physics::MassXiMinus) > cascsettingMXi) continue; histos.fill(HIST("QA/massXi"), centrality, std::hypot(momCasc[0], momCasc[1]), mXi); @@ -505,7 +556,7 @@ struct LFStrangeTreeCreator { { fillRecoEvent(collision, tracks, V0s, V0s_all, cascades, centrality); - for (auto& candidateV0 : candidateV0s) { + for (auto& candidateV0 : candidateV0s) { // o2-linter disable=const-red-in-for-loops (non const) candidateV0.isreco = true; auto mcLabPos = mcLabels.rawIteratorAt(candidateV0.globalIndexPos); auto mcLabNeg = mcLabels.rawIteratorAt(candidateV0.globalIndexNeg); @@ -519,23 +570,23 @@ struct LFStrangeTreeCreator { auto pdgCodeMotherDauNeg = -999; auto pdgMatchMotherSecondMother = -999; if (mcTrackPos.has_mothers() && mcTrackNeg.has_mothers()) { - for (auto& negMother : mcTrackNeg.template mothers_as()) { - for (auto& posMother : mcTrackPos.template mothers_as()) { + for (const auto& negMother : mcTrackNeg.template mothers_as()) { + for (const auto& posMother : mcTrackPos.template mothers_as()) { if (posMother.globalIndex() != negMother.globalIndex()) { pdgCodeMotherDauPos = posMother.pdgCode(); pdgCodeMotherDauNeg = negMother.pdgCode(); - if (negMother.pdgCode() == -211) { + if (negMother.pdgCode() == PDG_t::kPiMinus) { if (negMother.has_mothers()) { - for (auto& negSecondMother : negMother.template mothers_as()) { + for (const auto& negSecondMother : negMother.template mothers_as()) { if (negSecondMother.globalIndex() == posMother.globalIndex()) { pdgMatchMotherSecondMother = negSecondMother.pdgCode(); } } } } - if (posMother.pdgCode() == 211) { + if (posMother.pdgCode() == PDG_t::kPiPlus) { if (posMother.has_mothers()) { - for (auto& posSecondMother : posMother.template mothers_as()) { + for (const auto& posSecondMother : posMother.template mothers_as()) { if (posSecondMother.globalIndex() == negMother.globalIndex()) { pdgMatchMotherSecondMother = posSecondMother.pdgCode(); } @@ -550,13 +601,13 @@ struct LFStrangeTreeCreator { bool mother; bool daughter; if (k0short) { - // mother is k0short (310) and daughters are pions (211/-211) - mother = posMother.pdgCode() == 310; - daughter = (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -211); + // mother is k0short and daughters are pions + mother = posMother.pdgCode() == PDG_t::kK0Short; + daughter = (mcTrackPos.pdgCode() == PDG_t::kPiPlus && mcTrackNeg.pdgCode() == PDG_t::kPiMinus); } else { - // mother is lambda (3122) and daughters are proton (2212) and pion(211) - mother = posMother.pdgCode() == 3122; - daughter = ((mcTrackPos.pdgCode() == 2212 && mcTrackNeg.pdgCode() == -211) || (mcTrackPos.pdgCode() == 211 && mcTrackNeg.pdgCode() == -2212)); + // mother is lambda and daughters are proton and pion + mother = posMother.pdgCode() == PDG_t::kLambda0; + daughter = ((mcTrackPos.pdgCode() == PDG_t::kProton && mcTrackNeg.pdgCode() == PDG_t::kPiMinus) || (mcTrackPos.pdgCode() == PDG_t::kPiPlus && mcTrackNeg.pdgCode() == PDG_t::kProtonBar)); } // check conditions if (!mother || !daughter) { @@ -570,9 +621,9 @@ struct LFStrangeTreeCreator { if (posMother.isPhysicalPrimary()) { pdgCodeMother = 0; } else if (posMother.has_mothers()) { - for (auto& mcMother : posMother.mothers_as()) { + for (const auto& mcMother : posMother.mothers_as()) { // feed-down: xi and omega decaying to lambda, ignore for k0 - if (!k0short && (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334)) { + if (!k0short && (std::abs(mcMother.pdgCode()) == o2::constants::physics::Pdg::kXi0 || std::abs(mcMother.pdgCode()) == PDG_t::kXiMinus || std::abs(mcMother.pdgCode()) == PDG_t::kOmegaMinus)) { pdgCodeMother = mcMother.pdgCode(); break; } @@ -595,13 +646,13 @@ struct LFStrangeTreeCreator { } if ((!mcTrackPos.has_mothers()) && mcTrackNeg.has_mothers()) { pdgCodeMotherDauPos = -999; - for (auto& negMother : mcTrackNeg.template mothers_as()) { + for (const auto& negMother : mcTrackNeg.template mothers_as()) { pdgCodeMotherDauNeg = negMother.pdgCode(); } } if ((!mcTrackNeg.has_mothers()) && mcTrackPos.has_mothers()) { pdgCodeMotherDauNeg = -999; - for (auto& posMother : mcTrackPos.template mothers_as()) { + for (const auto& posMother : mcTrackPos.template mothers_as()) { pdgCodeMotherDauPos = posMother.pdgCode(); } } @@ -629,8 +680,8 @@ struct LFStrangeTreeCreator { void fillMcGen(aod::McParticles const& mcParticles, aod::McTrackLabels const& /*mcLab*/, uint64_t const& collisionId) { - auto mcParticles_thisCollision = mcParticles.sliceBy(perCollisionMcParts, collisionId); - for (auto& mcPart : mcParticles_thisCollision) { + auto mcParticlesThisCollision = mcParticles.sliceBy(perCollisionMcParts, collisionId); + for (const auto& mcPart : mcParticlesThisCollision) { auto genEta = mcPart.eta(); if (std::abs(genEta) > etaMax) { continue; @@ -641,23 +692,23 @@ struct LFStrangeTreeCreator { std::array momPosMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; std::array momNegMC = std::array{static_cast(-999.), static_cast(-999.), static_cast(-999.)}; - // look for lambda (3122) or k0short (310) - int pdg_test = 3122; + // look for lambda or k0short + int pdg_test = PDG_t::kLambda0; if (k0short) - pdg_test = 310; + pdg_test = PDG_t::kK0Short; if (std::abs(pdgCode) == pdg_test) { if (!mcPart.isPhysicalPrimary() && !mcPart.has_mothers()) continue; - // check if its the right decay containing proton (2122) for lambda and charged pion (211) for k0short + // check if its the right decay containing proton for lambda and charged pion for k0short int pdg_particle; if (k0short) { - pdg_particle = 211; + pdg_particle = PDG_t::kPiPlus; } else { - pdg_particle = 2212; + pdg_particle = PDG_t::kProton; } bool foundParticle = false; - for (auto& mcDaught : mcPart.daughters_as()) { + for (const auto& mcDaught : mcPart.daughters_as()) { if (std::abs(mcDaught.pdgCode()) == pdg_particle) { foundParticle = true; secVtx = std::array{mcDaught.vx(), mcDaught.vy(), mcDaught.vz()}; @@ -665,7 +716,7 @@ struct LFStrangeTreeCreator { } } // momentum of daughters - for (auto& mcDaught : mcPart.daughters_as()) { + for (const auto& mcDaught : mcPart.daughters_as()) { if (mcDaught.pdgCode() < 0) { momNegMC[0] = mcDaught.px(); momNegMC[1] = mcDaught.py(); @@ -683,9 +734,9 @@ struct LFStrangeTreeCreator { if (mcPart.isPhysicalPrimary()) { pdgCodeMother = 0; } else if (mcPart.has_mothers()) { - for (auto& mcMother : mcPart.mothers_as()) { + for (const auto& mcMother : mcPart.mothers_as()) { // feed-down: xi and omega decaying to lambda, ignore for k0 - if (!k0short && (std::abs(mcMother.pdgCode()) == 3322 || std::abs(mcMother.pdgCode()) == 3312 || std::abs(mcMother.pdgCode()) == 3334)) { + if (!k0short && (std::abs(mcMother.pdgCode()) == o2::constants::physics::Pdg::kXi0 || std::abs(mcMother.pdgCode()) == PDG_t::kXiMinus || std::abs(mcMother.pdgCode()) == PDG_t::kOmegaMinus)) { pdgCodeMother = mcMother.pdgCode(); break; } @@ -740,16 +791,16 @@ struct LFStrangeTreeCreator { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); - auto CascTable_thisCollision = cascades.sliceBy(perCollisionCasc, collIdx); - V0Table_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&V0s); + auto V0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); + auto CascTableThisCollision = cascades.sliceBy(perCollisionCasc, collIdx); + V0TableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&V0s); auto centrality = collision.centFT0C(); - fillRecoEvent(collision, tracks, V0Table_thisCollision, V0s, CascTable_thisCollision, centrality); + fillRecoEvent(collision, tracks, V0TableThisCollision, V0s, CascTableThisCollision, centrality); - for (auto& candidateV0 : candidateV0s) { + for (const auto& candidateV0 : candidateV0s) { lambdaTableML( candidateV0.pt, candidateV0.eta, @@ -785,11 +836,11 @@ struct LFStrangeTreeCreator { } } } - PROCESS_SWITCH(LFStrangeTreeCreator, processRun3, "process (Run 3)", false); + PROCESS_SWITCH(StrangeTreeCreator, processRun3, "process (Run 3)", false); void processMcRun3(soa::Join const& collisions, aod::McCollisions const& /*mcCollisions*/, TracksFullIU const& tracks, aod::V0s const& V0s, aod::Cascades const& cascades, aod::McParticles const& mcParticles, aod::McTrackLabels const& mcLab, aod::BCsWithTimestamps const&) { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { auto bc = collision.bc_as(); initCCDB(bc); @@ -807,16 +858,16 @@ struct LFStrangeTreeCreator { histos.fill(HIST("QA/zVtx"), collision.posZ()); const uint64_t collIdx = collision.globalIndex(); - auto V0Table_thisCollision = V0s.sliceBy(perCollisionV0, collIdx); - auto CascTable_thisCollision = cascades.sliceBy(perCollisionCasc, collIdx); - V0Table_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&tracks); - CascTable_thisCollision.bindExternalIndices(&V0s); + auto V0TableThisCollision = V0s.sliceBy(perCollisionV0, collIdx); + auto CascTableThisCollision = cascades.sliceBy(perCollisionCasc, collIdx); + V0TableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&tracks); + CascTableThisCollision.bindExternalIndices(&V0s); - fillMcEvent(collision, tracks, V0Table_thisCollision, V0s, CascTable_thisCollision, centrality, mcParticles, mcLab); + fillMcEvent(collision, tracks, V0TableThisCollision, V0s, CascTableThisCollision, centrality, mcParticles, mcLab); fillMcGen(mcParticles, mcLab, collision.mcCollisionId()); - for (auto& candidateV0 : candidateV0s) { + for (const auto& candidateV0 : candidateV0s) { mcLambdaTableML( candidateV0.pt, candidateV0.eta, @@ -872,11 +923,11 @@ struct LFStrangeTreeCreator { } } } - PROCESS_SWITCH(LFStrangeTreeCreator, processMcRun3, "process MC (Run 3)", false); + PROCESS_SWITCH(StrangeTreeCreator, processMcRun3, "process MC (Run 3)", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx index c38c792f5e1..d7012626b4f 100644 --- a/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx +++ b/PWGLF/TableProducer/Strangeness/strangenessbuilder.cxx @@ -32,25 +32,31 @@ // -- v0builderopts ......: V0-specific building options (topological, deduplication, etc) // -- cascadebuilderopts .: cascade-specific building options (topological, etc) -#include -#include - -#include "Framework/DataSpecUtils.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.h" #include "TableHelper.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/Utils/strangenessBuilderHelper.h" + +#include "Common/Core/TPCVDriftManager.h" +#include "Common/DataModel/PIDResponse.h" +#include "Tools/ML/MlResponse.h" +#include "Tools/ML/model.h" + #include "CCDB/BasicCCDBManager.h" -#include "DataFormatsParameters/GRPObject.h" #include "DataFormatsParameters/GRPMagField.h" -#include "Common/Core/TPCVDriftManager.h" +#include "DataFormatsParameters/GRPObject.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataSpecUtils.h" +#include "Framework/runDataProcessing.h" + +#include +#include using namespace o2; using namespace o2::framework; +using namespace o2::ml; static constexpr int nParameters = 1; static const std::vector tableNames{ @@ -156,6 +162,9 @@ struct StrangenessBuilder { // helper object o2::pwglf::strangenessBuilderHelper straHelper; + // ML model + o2::ml::OnnxModel deduplication_bdt; + // table index : match order above enum tableIndex { kV0Indices = 0, kV0CoresBase, @@ -196,12 +205,12 @@ struct StrangenessBuilder { kCascFoundTags, nTables }; - enum V0PreSelection : uint8_t { selGamma = static_cast(1) << static_cast(0), + enum V0PreSelection : uint8_t { selGamma = 0, selK0Short, selLambda, selAntiLambda }; - enum CascPreSelection : uint8_t { selXiMinus = static_cast(1) << static_cast(0), + enum CascPreSelection : uint8_t { selXiMinus = 0, selXiPlus, selOmegaMinus, selOmegaPlus }; @@ -291,9 +300,33 @@ struct StrangenessBuilder { Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; } ccdbConfigurations; - // first order deduplication implementation - // more algorithms to be added as necessary - Configurable deduplicationAlgorithm{"deduplicationAlgorithm", 1, "0: disabled; 1: best pointing angle wins; 2: best DCA daughters wins; 3: best pointing and best DCA wins"}; + // ML options + std::map metadata; + + struct : ConfigurableGroup { + std::string prefix = "DeduplicationOpts"; + + Configurable deduplicationAlgorithm{"deduplicationAlgorithm", 1, + "0: disabled;" + "1: best pointing angle wins;" + "2: best DCA daughters wins;" + "3: best pointing and best DCA wins;" + "4: best BDT score wins;" + "5: selects on PA (not a winner takes it all approach!);" + "6: selects on BDT score (not a winner takes it all approach!)"}; + + // BDT settings + Configurable BDTLocalPath{"BDTLocalPath", "Deduplication_BDTModel.onnx", "(std::string) Path to the local .onnx file."}; + Configurable BDTPathCCDB{"BDTPathCCDB", "Users/g/gsetouel/MLModels2", "Path on CCDB"}; + Configurable timestampCCDB{"timestampCCDB", -1, "timestamp of the ONNX file for ML model used to query in CCDB. Exceptions: > 0 for the specific timestamp, 0 gets the run dependent timestamp"}; + Configurable loadModelsFromCCDB{"loadModelsFromCCDB", false, "Flag to enable or disable the loading of models from CCDB"}; + Configurable enableOptimizations{"enableOptimizations", false, "Enables the ONNX extended model-optimization: sessionOptions.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED)"}; + + // Selection based duplicates removal + Configurable PAthreshold{"PAthreshold", 0.02, "PA cut to remove duplicates."}; + Configurable BDTthreshold{"BDTthreshold", 0.7, "BDT score cut to remove duplicates."}; + + } DeduplicationOpts; // V0 buffer for V0s used in cascades: master switch // exchanges CPU (generate V0s again) with memory (save pre-generated V0s) @@ -516,6 +549,17 @@ struct StrangenessBuilder { }; mcCascinfo thisCascInfo; //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + // Helper structure to save v0 duplicates auxiliary info + struct V0DuplicateExtra { + bool isBestPA; + bool isBestDCADau; + bool isBestMLScore; + bool isBuildOk; + float PA; + float V0DCAToPVz; + float V0zVtx; + float MLScore; + }; HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -594,6 +638,14 @@ struct StrangenessBuilder { hFindable->GetXaxis()->SetBinLabel(6, "Cascades with collId -1"); } + if (DeduplicationOpts.deduplicationAlgorithm.value > 0) { + histos.add("DeduplicationQA/hMLScore", "hMLScore", kTH1F, {{200, 0.0f, 1.0f}}); + histos.add("DeduplicationQA/hPA", "hPA", kTH1F, {{200, 0.0f, 0.4f}}); + histos.add("DeduplicationQA/hBestPA", "hBestPA", kTH1F, {{200, 0.0f, 0.4f}}); + histos.add("DeduplicationQA/hBestDCADau", "hBestDCADau", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("DeduplicationQA/hBestMLScore", "hBestMLScore", kTH1F, {{200, 0.0f, 1.0f}}); + } + auto hPrimaryV0s = histos.add("hPrimaryV0s", "hPrimaryV0s", kTH1D, {{2, -0.5f, 1.5f}}); hPrimaryV0s->GetXaxis()->SetBinLabel(1, "All V0s"); hPrimaryV0s->GetXaxis()->SetBinLabel(2, "Primary V0s"); @@ -714,11 +766,27 @@ struct StrangenessBuilder { straHelper.cascadeselections.dcacascdau = cascadeBuilderOpts.dcacascdau; straHelper.cascadeselections.lambdaMassWindow = cascadeBuilderOpts.lambdaMassWindow; straHelper.cascadeselections.maxDaughterEta = cascadeBuilderOpts.maxDaughterEta; - } - bool verifyMask(uint8_t bitmap, uint8_t mask) - { - return (bitmap & mask) == mask; + // Loading BDT model + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 || DeduplicationOpts.deduplicationAlgorithm.value == 6) { + if (DeduplicationOpts.loadModelsFromCCDB) { + + // Retrieve the model from CCDB + ccdbApi.init(ccdbConfigurations.ccdburl); + + /// Fetching model for specific timestamp + LOG(info) << "Fetching model for timestamp: " << DeduplicationOpts.timestampCCDB.value; + + bool retrieveSuccess = ccdbApi.retrieveBlob(DeduplicationOpts.BDTPathCCDB.value, ".", metadata, DeduplicationOpts.timestampCCDB.value, false, DeduplicationOpts.BDTLocalPath.value); + if (retrieveSuccess) { + deduplication_bdt.initModel(DeduplicationOpts.BDTLocalPath.value, DeduplicationOpts.enableOptimizations.value); + } else { + LOG(fatal) << "Error encountered while fetching/loading the Gamma model from CCDB! Maybe the model doesn't exist yet for this runnumber/timestamp?"; + } + } else { + deduplication_bdt.initModel(DeduplicationOpts.BDTLocalPath.value, DeduplicationOpts.enableOptimizations.value); + } + } } // for sorting @@ -735,6 +803,211 @@ struct StrangenessBuilder { return idx; } + // Simple function to rank vectors based on values + std::vector rankSort(const std::vector& v_temp, bool descending = false) + { + std::vector> v_sort(v_temp.size()); + + // Pair each value with its original index + for (size_t i = 0U; i < v_temp.size(); ++i) { + v_sort[i] = std::make_pair(v_temp[i], i); + } + + // Sort by value - ascending: lowest gets rank 1, descending: highest gets rank 1 + + if (descending) { + std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { + return a.first > b.first; + }); + } else { + std::sort(v_sort.begin(), v_sort.end(), [](const auto& a, const auto& b) { + return a.first < b.first; + }); + } + + std::pair rank_tracker = std::make_pair(std::numeric_limits::quiet_NaN(), 0); + std::vector result(v_temp.size()); + + for (size_t i = 0U; i < v_sort.size(); ++i) { + // Only update rank if value is different from previous + if (v_sort[i].first != rank_tracker.first) { + rank_tracker = std::make_pair(v_sort[i].first, i + 1); // +1 for 1-based rank + } + result[v_sort[i].second] = rank_tracker.second; // assign rank to original index + } + + return result; + } + + //_______________________________________________________________________ + // Process duplicated photons + template + std::vector processDuplicates(TCollisions const& collisions, TTracks const& tracks, std::vector V0Grouped, size_t iV0) + { + auto pTrack = tracks.rawIteratorAt(V0Grouped[iV0].posTrackId); + auto nTrack = tracks.rawIteratorAt(V0Grouped[iV0].negTrackId); + + bool isPosTPCOnly = (pTrack.hasTPC() && !pTrack.hasITS() && !pTrack.hasTRD() && !pTrack.hasTOF()); + bool isNegTPCOnly = (nTrack.hasTPC() && !nTrack.hasITS() && !nTrack.hasTRD() && !nTrack.hasTOF()); + + // don't try to de-duplicate if no track is TPC only + if (!isPosTPCOnly && !isNegTPCOnly) { + return {}; + } + + // fitness criteria defined here + float bestPointingAngle = 10; // a nonsense angle, anything's better + size_t bestPointingAngleIndex = -1; + + float bestDCADaughters = 1e+3; // an excessively large DCA + size_t bestDCADaughtersIndex = -1; + + float bestMLScore = -1; // a nonsense ML score + size_t bestMLScoreIndex = -1; + + // Defining context variables + int NDuplicates = 0; + float AvgPA = 0.0f; + + // Containers for ranking + std::vector paVec(V0Grouped[iV0].collisionIds.size(), 999.f); + std::vector v0zVec(V0Grouped[iV0].collisionIds.size(), 999.f); + + // Auxiliary vector to store V0 duplicate info + std::vector V0DuplicateExtras; + + // Loop over duplicates + for (size_t ic = 0; ic < V0Grouped[iV0].collisionIds.size(); ic++) { + + // Helper structure to save duplicates info - initializing with dummy values + V0DuplicateExtra v0DuplicateInfo; + v0DuplicateInfo.isBestPA = false; + v0DuplicateInfo.isBestDCADau = false; + v0DuplicateInfo.isBestMLScore = false; + v0DuplicateInfo.isBuildOk = false; + v0DuplicateInfo.PA = 10; + v0DuplicateInfo.V0DCAToPVz = 999.f; + v0DuplicateInfo.V0zVtx = 999.f; + v0DuplicateInfo.MLScore = -1; + + // We include V0DuplicateExtra info in the vector at this point to avoid indexing issues later + V0DuplicateExtras.push_back(v0DuplicateInfo); + + // get track parametrizations, collisions + auto posTrackPar = getTrackParCov(pTrack); + auto negTrackPar = getTrackParCov(nTrack); + auto const& collision = collisions.rawIteratorAt(V0Grouped[iV0].collisionIds[ic]); + + // handle TPC-only tracks properly (photon conversions) + if (v0BuilderOpts.moveTPCOnlyTracks) { + if (isPosTPCOnly) { + // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + if (!mVDriftMgr.moveTPCTrack(collision, pTrack, posTrackPar)) { + continue; + } + } + if (isNegTPCOnly) { + // Nota bene: negative is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + if (!mVDriftMgr.moveTPCTrack(collision, nTrack, negTrackPar)) { + continue; + } + } + } // end TPC drift treatment + + // process candidate with helper, generate properties for consulting + // : do not apply selections: do as much as possible to preserve + // candidate at this level and do not select with topo selections + if (straHelper.buildV0Candidate(V0Grouped[iV0].collisionIds[ic], collision.posX(), collision.posY(), collision.posZ(), pTrack, nTrack, posTrackPar, negTrackPar, true, false, true)) { + + // candidate built, check pointing angle + if (straHelper.v0.pointingAngle < bestPointingAngle) { + bestPointingAngle = straHelper.v0.pointingAngle; + bestPointingAngleIndex = ic; + } + if (straHelper.v0.daughterDCA < bestDCADaughters) { + bestDCADaughters = straHelper.v0.daughterDCA; + bestDCADaughtersIndex = ic; + } + + // Calculating features for ML Analysis + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 || DeduplicationOpts.deduplicationAlgorithm.value == 6) { + AvgPA += straHelper.v0.pointingAngle; + paVec[ic] = straHelper.v0.pointingAngle; + v0zVec[ic] = std::abs(straHelper.v0.position[2]); + NDuplicates++; + } + + // Updating values in the struct + V0DuplicateExtras[ic].isBuildOk = true; + V0DuplicateExtras[ic].PA = straHelper.v0.pointingAngle; + V0DuplicateExtras[ic].V0DCAToPVz = std::abs(straHelper.v0.v0DCAToPVz); + V0DuplicateExtras[ic].V0zVtx = std::abs(straHelper.v0.position[2]); + } // end build V0 + } // end candidate loop + + // Additional loop to perform ML Analysis if requested + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 || DeduplicationOpts.deduplicationAlgorithm.value == 6) { + + // Preparing features + if (NDuplicates > 0) + AvgPA /= NDuplicates; + + // Get vector of ranks + std::vector paRanks = rankSort(paVec, false); + std::vector v0zRanks = rankSort(v0zVec, false); + + // Fill the ML score for all candidates + for (size_t ic = 0; ic < V0Grouped[iV0].collisionIds.size(); ic++) { + + // Skip if v0 was not built + if (!V0DuplicateExtras[ic].isBuildOk) + continue; + + // Input vector for BDT + std::vector inputFeatures{V0DuplicateExtras[ic].V0DCAToPVz, // 1. V0DCAToPVz + V0DuplicateExtras[ic].PA, // 2. Pointing Angle + V0DuplicateExtras[ic].V0zVtx, // 3. V0 Vtx z-position + static_cast(paRanks[ic]), // 4. Pointing Angle Rank + static_cast(NDuplicates), // 5. N. of Duplicates + AvgPA, // 6. Avg Pointing Angle + static_cast(v0zRanks[ic])}; // 7. V0 Vtx z Rank + + float* BDTProbability = deduplication_bdt.evalModel(inputFeatures); + + if (BDTProbability[1] > bestMLScore) { + bestMLScore = BDTProbability[1]; + bestMLScoreIndex = ic; + } + + // QA histo + histos.fill(HIST("DeduplicationQA/hMLScore"), BDTProbability[1]); + histos.fill(HIST("DeduplicationQA/hPA"), V0DuplicateExtras[ic].PA); + + // Updating BDT score info in the struct + V0DuplicateExtras[ic].MLScore = BDTProbability[1]; + } + } + + histos.fill(HIST("DeduplicationQA/hBestPA"), bestPointingAngle); + histos.fill(HIST("DeduplicationQA/hBestDCADau"), bestDCADaughters); + histos.fill(HIST("DeduplicationQA/hBestMLScore"), bestMLScore); + + // Final step: Defining the winners: + if (bestPointingAngleIndex != static_cast(-1)) + V0DuplicateExtras[bestPointingAngleIndex].isBestPA = true; + if (bestDCADaughtersIndex != static_cast(-1)) + V0DuplicateExtras[bestDCADaughtersIndex].isBestDCADau = true; + if (bestMLScoreIndex != static_cast(-1)) + V0DuplicateExtras[bestMLScoreIndex].isBestMLScore = true; + + // return vector with duplicates info + return V0DuplicateExtras; + } + template bool initCCDB(aod::BCsWithTimestamps const& bcs, TCollisions const& collisions) { @@ -890,7 +1163,7 @@ struct StrangenessBuilder { // keep all unless de-duplication active ao2dV0toV0List.resize(v0s.size(), -1); // -1 means keep, -2 means do not keep - if (deduplicationAlgorithm > 0 && v0BuilderOpts.generatePhotonCandidates) { + if (DeduplicationOpts.deduplicationAlgorithm.value > 0 && v0BuilderOpts.generatePhotonCandidates) { // handle duplicates explicitly: group V0s according to (p,n) indices // will provide a list of collisionIds (in V0group), allowing for // easy de-duplication when passing to the v0List @@ -900,82 +1173,44 @@ struct StrangenessBuilder { // process grouped duplicates, remove 'bad' ones for (size_t iV0 = 0; iV0 < v0tableGrouped.size(); iV0++) { - auto pTrack = tracks.rawIteratorAt(v0tableGrouped[iV0].posTrackId); - auto nTrack = tracks.rawIteratorAt(v0tableGrouped[iV0].negTrackId); - - bool isPosTPCOnly = (pTrack.hasTPC() && !pTrack.hasITS() && !pTrack.hasTRD() && !pTrack.hasTOF()); - bool isNegTPCOnly = (nTrack.hasTPC() && !nTrack.hasITS() && !nTrack.hasTRD() && !nTrack.hasTOF()); // skip single copy V0s if (v0tableGrouped[iV0].collisionIds.size() == 1) { continue; } - // don't try to de-duplicate if no track is TPC only - if (!isPosTPCOnly && !isNegTPCOnly) { + // process duplicates + std::vector deduplicationOutput = processDuplicates(collisions, tracks, v0tableGrouped, iV0); + + // skip if empty + if (deduplicationOutput.empty()) { continue; } - // fitness criteria defined here - float bestPointingAngle = 10; // a nonsense angle, anything's better - size_t bestPointingAngleIndex = -1; - - float bestDCADaughters = 1e+3; // an excessively large DCA - size_t bestDCADaughtersIndex = -1; - - for (size_t ic = 0; ic < v0tableGrouped[iV0].collisionIds.size(); ic++) { - // get track parametrizations, collisions - auto posTrackPar = getTrackParCov(pTrack); - auto negTrackPar = getTrackParCov(nTrack); - auto const& collision = collisions.rawIteratorAt(v0tableGrouped[iV0].collisionIds[ic]); - - // handle TPC-only tracks properly (photon conversions) - if (v0BuilderOpts.moveTPCOnlyTracks) { - if (isPosTPCOnly) { - // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate - posTrackPar.setPID(o2::track::PID::Electron); - negTrackPar.setPID(o2::track::PID::Electron); - if (!mVDriftMgr.moveTPCTrack(collision, pTrack, posTrackPar)) { - return; - } - } - if (isNegTPCOnly) { - // Nota bene: negative is TPC-only -> this entire V0 merits treatment as photon candidate - posTrackPar.setPID(o2::track::PID::Electron); - negTrackPar.setPID(o2::track::PID::Electron); - if (!mVDriftMgr.moveTPCTrack(collision, nTrack, negTrackPar)) { - return; - } - } - } // end TPC drift treatment - - // process candidate with helper, generate properties for consulting - // : do not apply selections: do as much as possible to preserve - // candidate at this level and do not select with topo selections - if (straHelper.buildV0Candidate(v0tableGrouped[iV0].collisionIds[ic], collision.posX(), collision.posY(), collision.posZ(), pTrack, nTrack, posTrackPar, negTrackPar, true, false, true)) { - // candidate built, check pointing angle - if (straHelper.v0.pointingAngle < bestPointingAngle) { - bestPointingAngle = straHelper.v0.pointingAngle; - bestPointingAngleIndex = ic; - } - if (straHelper.v0.daughterDCA < bestDCADaughters) { - bestDCADaughters = straHelper.v0.daughterDCA; - bestDCADaughtersIndex = ic; - } - } // end build V0 - } // end candidate loop - // mark de-duplicated candidates for (size_t ic = 0; ic < v0tableGrouped[iV0].collisionIds.size(); ic++) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -2; // algorithm 1: best pointing angle - if (bestPointingAngleIndex == ic && deduplicationAlgorithm.value == 1) { + if (DeduplicationOpts.deduplicationAlgorithm.value == 1 && deduplicationOutput[ic].isBestPA) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + // algorithm 2: best DCA between daughters + if (DeduplicationOpts.deduplicationAlgorithm.value == 2 && deduplicationOutput[ic].isBestDCADau) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + // algorithm 3: best PA AND DCA between daughters + if (DeduplicationOpts.deduplicationAlgorithm.value == 3 && deduplicationOutput[ic].isBestDCADau && deduplicationOutput[ic].isBestPA) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } - if (bestDCADaughtersIndex == ic && deduplicationAlgorithm.value == 2) { + // algorithm 4: best ML Score + if (DeduplicationOpts.deduplicationAlgorithm.value == 4 && deduplicationOutput[ic].isBestMLScore) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } - if (bestDCADaughtersIndex == ic && bestPointingAngleIndex == ic && deduplicationAlgorithm.value == 3) { + // Selection-based duplicate removal + if (DeduplicationOpts.deduplicationAlgorithm.value == 5 && deduplicationOutput[ic].PA <= DeduplicationOpts.PAthreshold) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + if (DeduplicationOpts.deduplicationAlgorithm.value == 6 && deduplicationOutput[ic].MLScore >= DeduplicationOpts.BDTthreshold) { ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only } } @@ -1413,7 +1648,8 @@ struct StrangenessBuilder { auto const& collision = collisions.rawIteratorAt(v0.collisionId); if (!mVDriftMgr.moveTPCTrack(collision, posTrack, posTrackPar)) { - return; + products.v0dataLink(-1, -1); + continue; } } @@ -1425,12 +1661,13 @@ struct StrangenessBuilder { auto const& collision = collisions.rawIteratorAt(v0.collisionId); if (!mVDriftMgr.moveTPCTrack(collision, negTrack, negTrackPar)) { - return; + products.v0dataLink(-1, -1); + continue; } } } - if (!straHelper.buildV0Candidate(v0.collisionId, pvX, pvY, pvZ, posTrack, negTrack, posTrackPar, negTrackPar, v0.isCollinearV0, mEnabledTables[kV0Covs], true)) { + if (!straHelper.buildV0Candidate(v0.collisionId, pvX, pvY, pvZ, posTrack, negTrack, posTrackPar, negTrackPar, v0.isCollinearV0, mEnabledTables[kV0Covs], v0BuilderOpts.generatePhotonCandidates)) { products.v0dataLink(-1, -1); continue; } @@ -1485,10 +1722,7 @@ struct StrangenessBuilder { histos.fill(HIST("hPreselectionV0s"), maskV0Preselection); - if (!verifyMask(maskV0Preselection, selGamma) && - !verifyMask(maskV0Preselection, selK0Short) && - !verifyMask(maskV0Preselection, selLambda) && - !verifyMask(maskV0Preselection, selAntiLambda)) { + if (maskV0Preselection == 0) { products.v0dataLink(-1, -1); continue; } @@ -1693,6 +1927,8 @@ struct StrangenessBuilder { } } // enabled tables check } // constexpr requires check + } else { + products.v0dataLink(-1, -1); } } @@ -2048,10 +2284,7 @@ struct StrangenessBuilder { histos.fill(HIST("hPreselectionCascades"), maskCascadePreselection); - if (!verifyMask(maskCascadePreselection, selXiMinus) && - !verifyMask(maskCascadePreselection, selXiPlus) && - !verifyMask(maskCascadePreselection, selOmegaMinus) && - !verifyMask(maskCascadePreselection, selOmegaPlus)) { + if (maskCascadePreselection == 0) { products.cascdataLink(-1); interlinks.cascadeToCascCores.push_back(-1); continue; diff --git a/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt b/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt index ed61c203672..258a43a91d0 100644 --- a/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt +++ b/PWGLF/Tasks/GlobalEventProperties/CMakeLists.txt @@ -23,3 +23,8 @@ o2physics_add_dpl_workflow(dndeta-mft-pp SOURCES dndeta-mft-pp.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(flattenicty-pikp + SOURCES flattenictyPikp.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx b/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx index 452a040d92f..c90a3d89474 100644 --- a/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/dndeta-mft-pp.cxx @@ -15,14 +15,14 @@ // \brief This code loops over MFT tracks and collisions and fills histograms // useful to compute dNdeta -#include -#include -#include -#include -#include -#include -#include +#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" @@ -30,19 +30,18 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/RuntimeError.h" #include "Framework/runDataProcessing.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 "PWGMM/Mult/DataModel/bestCollisionTable.h" #include "TFile.h" +#include +#include +#include +#include +#include +#include + using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -51,7 +50,7 @@ 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, 2 * M_PI, "Rad", "phi axis"}; +AxisSpec PhiAxis = {629, 0, o2::constants::math::TwoPI, "Rad", "phi axis"}; // AxisSpec EtaAxis = {18, -4.6, -1.}; AxisSpec DCAxyAxis = {100, -1, 10}; AxisSpec CentAxis = {{0, 10, 20, 30, 40, 50, 60, 70, 80, 100}}; @@ -82,17 +81,22 @@ struct PseudorapidityDensityMFT { "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", {18, -4.6, -1.}, ""}; + 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 reconstruced collisions (cm)"}; + "max allowed Z difference for reconstructed collisions (cm)"}; - Configurable usePhiCut{"usePhiCut", false, "use azimuthal angle cut"}; + Configurable usePhiCut{"usePhiCut", true, "use azimuthal angle 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, @@ -103,6 +107,8 @@ struct PseudorapidityDensityMFT { "Cut on eta1"}; Configurable cfgnEta2{"cfgnEta2", -1.0f, "Cut on eta1"}; + Configurable cfgChi2NDFMax{"cfgChi2NDFMax", 2000.0f, "Max allowed chi2/NDF for MFT tracks"}; + HistogramRegistry registry{ "registry", { @@ -145,15 +151,15 @@ struct PseudorapidityDensityMFT { auto hstat = registry.get(HIST("EventSelection")); auto* x = hstat->GetXaxis(); x->SetBinLabel(1, "All"); - x->SetBinLabel(2, "Selected"); - x->SetBinLabel(3, "Selected Vz Cut"); - x->SetBinLabel(4, "Sel8+Vz+INEL>0"); - x->SetBinLabel(5, "Sel INEL,INEL_fwd>0"); - x->SetBinLabel(6, "Rejected"); - x->SetBinLabel(7, "Good BCs"); - x->SetBinLabel(8, "BCs with collisions"); - x->SetBinLabel(9, "BCs with pile-up/splitting"); - x->SetBinLabel(10, "midtracks>0"); + 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", @@ -286,7 +292,9 @@ struct PseudorapidityDensityMFT { 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}}}); // @@ -446,13 +454,13 @@ struct PseudorapidityDensityMFT { { std::vector::iterator> cols; - for (auto& bc : bcs) { + 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"), 7); // added 5->12 + registry.fill(HIST("EventSelection"), 8); // added 5->12 cols.clear(); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { if (collision.has_foundBC()) { if (collision.foundBCId() == bc.globalIndex()) { cols.emplace_back(collision); @@ -463,9 +471,9 @@ struct PseudorapidityDensityMFT { } LOGP(debug, "BC {} has {} collisions", bc.globalBC(), cols.size()); if (!cols.empty()) { - registry.fill(HIST("EventSelection"), 8); // added 6->13 + registry.fill(HIST("EventSelection"), 9); // added 6->13 if (cols.size() > 1) { - registry.fill(HIST("EventSelection"), 9); // added 7->14 + registry.fill(HIST("EventSelection"), 10); // added 7->14 } } } @@ -522,17 +530,17 @@ struct PseudorapidityDensityMFT { } if (tracks.size() > 0) { - for (auto& track : tracks) { + for (const auto& track : tracks) { float phi = track.phi(); o2::math_utils::bringTo02Pi(phi); if (usePhiCut) { if ((phi < cfgPhiCut) || - ((phi > M_PI - cfgPhiCut) && (phi < M_PI + cfgPhiCut)) || - (phi > 2. * M_PI - cfgPhiCut) || - ((phi > ((M_PI / 2. - 0.1) * M_PI) - cfgPhiCut) && - (phi < ((M_PI / 2. - 0.1) * M_PI) + 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; } @@ -569,16 +577,28 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("EventsNtrkZvtx"), Ntrk, z); if ((z >= cfgVzCut1) && (z <= cfgVzCut2)) { registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_all"), Ntrk, z); - for (auto& retrack : retracks) { + registry.fill(HIST("EventSelection"), 2.); + for (const auto& retrack : retracks) { auto track = retrack.mfttrack(); - if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0) { + 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; + } + 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 (!useEvSel || (useEvSel && collision.sel8())) { - registry.fill(HIST("EventSelection"), 2.); + 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); - registry.fill(HIST("EventSelection"), 3.); std::unordered_set uniqueEvents; std::unordered_set uniqueEventsAmb; std::unordered_set uniqueCollisions; @@ -586,8 +606,7 @@ struct PseudorapidityDensityMFT { std::unordered_set eventsInelMFT; std::unordered_set eventsInel; if (midtracks.size() > 0) { - registry.fill(HIST("EventSelection"), 4.); - registry.fill(HIST("EventSelection"), 10.); + 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()); @@ -599,9 +618,18 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("EventSelection"), 12.); } int64_t i = 0.0, j = 0.0, k = 0.0; - for (auto& retrack : retracks) { + for (const auto& retrack : retracks) { auto track = retrack.mfttrack(); - if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster && retrack.ambDegree() > 0) { + 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; + } + 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); @@ -609,14 +637,21 @@ struct PseudorapidityDensityMFT { } } if (retracks.size() > 0) { - registry.fill(HIST("EventSelection"), 5.); + registry.fill(HIST("EventSelection"), 6.); if (midtracks.size() > 0) { registry.fill(HIST("Tracks/2Danalysis/EventsNtrkZvtx_sel8_inelfwdgt0"), Ntrk, z); } - for (auto& retrack : retracks) { + for (const auto& retrack : retracks) { auto track = retrack.mfttrack(); - - if ((cfgnEta1 < track.eta()) && (track.eta() < cfgnEta2) && track.nClusters() >= cfgnCluster) { + 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 ((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; + } registry.fill(HIST("TracksEtaZvtx"), track.eta(), z); if (midtracks.size() > 0 && retrack.ambDegree() > 0) { registry.fill(HIST("Tracks/EtaZvtx_gt0"), track.eta(), z); @@ -736,7 +771,7 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("hNumCollisions_Inel"), 1, eventsInel.size()); } } else { - registry.fill(HIST("EventSelection"), 6); + registry.fill(HIST("EventSelection"), 7); } } PROCESS_SWITCH(PseudorapidityDensityMFT, processMultReassoc, @@ -759,17 +794,17 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("Events/Centrality/NtrkZvtx"), Ntrk, z, c); - for (auto& track : tracks) { + for (const auto& track : tracks) { float phi = track.phi(); o2::math_utils::bringTo02Pi(phi); if (usePhiCut) { if ((phi < cfgPhiCut) || - ((phi > M_PI - cfgPhiCut) && (phi < M_PI + cfgPhiCut)) || - (phi > 2. * M_PI - cfgPhiCut) || - ((phi > ((M_PI / 2. - 0.1) * M_PI) - cfgPhiCut) && - (phi < ((M_PI / 2. - 0.1) * M_PI) + 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; } @@ -807,7 +842,7 @@ struct PseudorapidityDensityMFT { auto perCollisionMCSample = mcSample->sliceByCached( aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); auto nCharged = 0; - for (auto& particle : perCollisionMCSample) { + for (const auto& particle : perCollisionMCSample) { auto charge = 0.; auto p = pdg->GetParticle(particle.pdgCode()); if (p != nullptr) { @@ -824,7 +859,7 @@ struct PseudorapidityDensityMFT { auto perCollisionMCSampleCentral = mcSampleCentral->sliceByCached( aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); auto nChargedCentral = 0; - for (auto& particle : perCollisionMCSampleCentral) { + for (const auto& particle : perCollisionMCSample) { auto charge = 0.; auto p = pdg->GetParticle(particle.pdgCode()); if (p != nullptr) { @@ -849,9 +884,12 @@ struct PseudorapidityDensityMFT { LOGP(debug, "MC col {} has {} reco cols", mcCollision.globalIndex(), collisions.size()); - for (auto& collision : collisions) { + for (const auto& collision : collisions) { registry.fill(HIST("EventEfficiency"), 3.); - if (!useEvSel || (useEvSel && collision.sel8())) { + 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); @@ -888,7 +926,7 @@ struct PseudorapidityDensityMFT { registry.fill(HIST("EventsSplitMult"), nCharged); } if ((mcCollision.posZ() >= cfgVzCut1) && (mcCollision.posZ() <= cfgVzCut2)) { - for (auto& particle : particles) { + for (const auto& particle : particles) { auto p = pdg->GetParticle(particle.pdgCode()); auto charge = 0; if (p != nullptr) { @@ -897,7 +935,13 @@ struct PseudorapidityDensityMFT { if (std::abs(charge) < 3.) { continue; } - if (cfgnEta1 < particle.eta() && particle.eta() < cfgnEta2) { + 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)) { registry.fill(HIST("TracksEtaZvtxGen_t"), particle.eta(), mcCollision.posZ()); if (perCollisionMCSampleCentral.size() > 0) { @@ -943,7 +987,7 @@ struct PseudorapidityDensityMFT { float c_gen = -1; bool atLeastOne = false; - for (auto& collision : collisions) { + for (const auto& collision : collisions) { float c_rec = -1; if constexpr (ExColsGenCent::template contains()) { c_rec = collision.centFT0C(); @@ -972,7 +1016,7 @@ struct PseudorapidityDensityMFT { aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); auto nCharged = 0; - for (auto& particle : perCollisionMCSample) { + for (const auto& particle : perCollisionMCSample) { auto p = pdg->GetParticle(particle.pdgCode()); auto charge = 0; if (p != nullptr) { @@ -989,7 +1033,7 @@ struct PseudorapidityDensityMFT { mcCollision.posZ(), c_gen); } - for (auto& particle : particles) { + for (const auto& particle : particles) { auto p = pdg->GetParticle(particle.pdgCode()); auto charge = 0; if (p != nullptr) { @@ -1025,7 +1069,7 @@ struct PseudorapidityDensityMFT { MFTTracksLabeled const& tracks, aod::McParticles const&) { if (!useEvSel || (useEvSel && collision.sel8())) { - for (auto& track : tracks) { + for (const auto& track : tracks) { if (!track.has_mcParticle()) { continue; } diff --git a/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx new file mode 100644 index 00000000000..101898b826d --- /dev/null +++ b/PWGLF/Tasks/GlobalEventProperties/flattenictyPikp.cxx @@ -0,0 +1,2055 @@ +// Copyright 2020-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 flattenictyPikp.cxx +/// \author Gyula Bencedi, gyula.bencedi@cern.ch +/// \brief Task to produce pion, kaon, proton high-pT +/// distributions as a function of charged-particle flattenicity +/// \since 26 June 2025 + +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "PWGLF/Utils/inelGt.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/McCollisionExtra.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/MathConstants.h" +#include "DataFormatsFIT/Triggers.h" +#include "DetectorsCommonDataFormats/AlignParam.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/StaticFor.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" +#include +#include +#include + +#include "TEfficiency.h" +#include "THashList.h" +#include "TPDGCode.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace o2; +using namespace o2::framework; +using namespace o2::constants::math; + +auto static constexpr kMinCharge = 3.f; +// FV0 specific constants +static constexpr int kMaxRingsFV0 = 5; +static constexpr int kNCellsFV0 = 48; +static constexpr int kInnerFV0 = 32; +static constexpr float kFV0IndexPhi[5] = {0., 8., 16., 24., 32.}; +static constexpr float kEtaMaxFV0 = 5.1; +static constexpr float kEtaMinFV0 = 2.2; +static constexpr float kDEtaFV0 = (kEtaMaxFV0 - kEtaMinFV0) / kMaxRingsFV0; +// PID names +static constexpr int kProcessIdWeak = 4; +static constexpr int Ncharges = 2; +static constexpr o2::track::PID::ID Npart = 5; +static constexpr o2::track::PID::ID NpartChrg = Npart * Ncharges; +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 kSpecies[NpartChrg] = {"Elminus", "Muplus", "PiPlus", "KaPlus", "Pr", "ElPlus", "MuMinus", "PiMinus", "KaMinus", "PrBar"}; +static constexpr std::string_view kSpeciesAll[Npart] = {"El", "Mu", "Pi", "Ka", "Pr"}; +// histogram naming +static constexpr std::string_view kCharge[] = {"all/", "pos/", "neg/"}; +static constexpr std::string_view kPrefix = "Tracks/"; +static constexpr std::string_view kPrefixCleanTof = "Tracks/CleanTof/"; +static constexpr std::string_view kPrefixCleanV0 = "Tracks/CleanV0/"; +static constexpr std::string_view kStatus[] = {"preSel/", "postSel/"}; +static constexpr std::string_view kStatCalib[] = {"preCalib/", "postCalib/"}; +static constexpr std::string_view kPtGenPrimSgn = "/hPtGenPrimSgn"; +static constexpr std::string_view kPtGenPrimSgnF = "Tracks/{}/hPtGenPrimSgn"; +static constexpr std::string_view kPtGenPrimSgnINEL = "/hPtGenPrimSgnINEL"; +static constexpr std::string_view kPtGenPrimSgnINELF = "Tracks/{}/hPtGenPrimSgnINEL"; +static constexpr std::string_view kPtRecCollPrimSgn = "/hPtRecCollPrimSgn"; +static constexpr std::string_view kPtRecCollPrimSgnF = "Tracks/{}/hPtRecCollPrimSgn"; +static constexpr std::string_view kPtRecCollPrimSgnINEL = "/hPtRecCollPrimSgnINEL"; +static constexpr std::string_view kPtRecCollPrimSgnINELF = "Tracks/{}/hPtRecCollPrimSgnINEL"; +static constexpr std::string_view kPtGenRecCollPrimSgn = "/hPtGenRecCollPrimSgn"; +static constexpr std::string_view kPtGenRecCollPrimSgnF = "Tracks/{}/hPtGenRecCollPrimSgn"; +static constexpr std::string_view kPtGenRecCollPrimSgnINEL = "/hPtGenRecCollPrimSgnINEL"; +static constexpr std::string_view kPtGenRecCollPrimSgnINELF = "Tracks/{}/hPtGenRecCollPrimSgnINEL"; +static constexpr std::string_view kPtMCclosurePrim = "/hPtMCclosurePrim"; +static constexpr std::string_view kPtMCclosurePrimF = "Tracks/{}/hPtMCclosurePrim"; + +enum V0sSel { + kNaN = -1, + kGa = 0, + kKz = 1, + kLam = 2, + kaLam = 3 +}; + +enum TrkSelNoFilt { + trkSelEta, + trkSelPt, + trkSelDCA, + trkNRowsTPC, + trkSelNCls, + trkSelTPCBndr, + nTrkSel +}; + +enum EvtSel { + evtSelAll, + evtSelSel8, + evtSelNoITSROFrameBorder, + evtSelkNoTimeFrameBorder, + evtSelkNoSameBunchPileup, + evtSelkIsGoodZvtxFT0vsPV, + evtSelkIsVertexITSTPC, + evtSelkIsVertexTOFmatched, + evtSelVtxZ, + evtSelINELgt0, + nEvtSel +}; + +enum FillType { + kBefore, + kAfter +}; + +enum ChargeType { + kAll, + kPos, + kNeg +}; + +struct MultE { + static constexpr int kNoMult = 0; + static constexpr int kMultFT0M = 1; + static constexpr int kMultTPC = 2; +}; + +std::array rhoLatticeFV0{0}; +std::array fv0AmplitudeWoCalib{0}; + +std::array, NpartChrg> hPtEffRecPrim{}; +std::array, NpartChrg> hPtEffRecWeak{}; +std::array, NpartChrg> hPtEffRecMat{}; +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{}; + +struct FlattenictyPikp { + + HistogramRegistry flatchrg{"flatchrg", {}, OutputObjHandlingPolicy::AnalysisObject, true, false}; + OutputObj listEfficiency{"Efficiency"}; + Service pdg; + + std::vector fv0AmplCorr{}; + TProfile2D* zVtxMap = nullptr; + int runNumber{-1}; + + Configurable multEst{"multEst", 1, "0: without multiplicity; 1: MultFT0M; 2: MultTPC"}; + Configurable applyCalibGain{"applyCalibGain", false, "equalize detector amplitudes"}; + Configurable applyCalibVtx{"applyCalibVtx", false, "equalize Amp vs vtx"}; + Configurable applyCalibDeDx{"applyCalibDeDx", false, "calibration of dedx signal"}; + Configurable cfgFillTrackQaHist{"cfgFillTrackQaHist", false, "fill track 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 cfgFillV0Hist{"cfgFillV0Hist", false, "fill V0 histograms"}; + Configurable cfgFillChrgType{"cfgFillChrgType", false, "fill 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 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 cfgUseCcdbForRun{"cfgUseCcdbForRun", true, "Get ccdb object based on run number instead of timestamp"}; + Configurable cfgStoreThnSparse{"cfgStoreThnSparse", false, "Store histograms as THnSparse"}; + + 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 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 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"}; + } 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 axisFlatPerc{"axisFlatPerc", {102, -0.01, 1.01}, "Flattenicity percentiles binning"}; + ConfigurableAxis axisMultPerc{"axisMultPerc", {20, 0, 100}, "Multiplicity 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 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", {8, -0.8, 0.8}, "#eta binning"}; + ConfigurableAxis axisDedx{"axisDedx", {100, 0, 100}, "dE/dx binning"}; + ConfigurableAxis axisNsigmaTPC{"axisNsigmaTPC", {200, -10, 10}, "nsigmaTPC binning"}; + ConfigurableAxis axisNsigmaTOF{"axisNsigmaTOF", {200, -10, 10}, "nsigmaTOF binning"}; + ConfigurableAxis axisAmplFV0{"axsAmplFV0", {4096, 0, 4096}, "FV0 amplitude (ADC) binning"}; + ConfigurableAxis axisAmplFV0Sum{"axisAmplFV0Sum", {4096, 0, 4096 * 49}, "FV0 amplitude sum (ADC) binning"}; + ConfigurableAxis axisChannelFV0{"axisChannelFV0", {49, 0., 49.}, "FV0 channel ID binning"}; + } binOpt; + + 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", 100.0f, "Minimum of number of TPC clusters"}; + Configurable cfgPhiCutPtMin{"cfgPhiCutPtMin", 2.0f, "Minimum pT for phi cut"}; + Configurable cfgTOFBetaPion{"cfgTOFBetaPion", 1.0f, "Minimum beta for TOF pions"}; + Configurable cfgUseExtraTrkCut{"cfgUseExtraTrkCut", true, "Use extra track cut"}; + Configurable cfgGeoTrkCutMin{"cfgGeoTrkCutMin", "0.06/x+pi/18.0-0.06", "ROOT TF1 formula for minimum phi cut in TPC"}; + Configurable cfgGeoTrkCutMax{"cfgGeoTrkCutMax", "0.1/x+pi/18.0+0.06", "ROOT TF1 formula for maximum phi cut in TPC"}; + Configurable cfgMomMIPMax{"cfgMomMIPMax", 0.6f, "Maximum momentum of MIP pions"}; + Configurable cfgMomMIPMin{"cfgMomMIPMin", 0.4f, "Minimum momentum of MIP pions"}; + 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 cfgMomSelPiTOF{"cfgMomSelPiTOF", 0.7f, "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"}; + } trkSelOpt; + + struct : ConfigurableGroup { + Configurable cfgDCAv0daughter{"cfgDCAv0daughter", 0.3, "DCA of V0 daughter tracks"}; + Configurable cfgV0etamax{"cfgV0etamax", 0.9f, "max eta of V0s"}; + Configurable cfgV0DaughterTpcMomMax{"cfgV0DaughterTpcMomMax", 0.6f, "Maximum momentum of V0 daughter tracks in TPC"}; + Configurable cfgTPCnClsmin{"cfgTPCnClsmin", 50.0f, "cfgTPCnClsmin"}; + Configurable cfgDCAposToPV{"cfgDCAposToPV", 0.05f, "cfgDCAposToPV"}; + Configurable cfgv0cospa{"cfgv0cospa", 0.998, "V0 CosPA"}; + Configurable cfgv0Rmin{"cfgv0Rmin", 0.0, "cfgv0Rmin"}; + Configurable cfgv0Rmax{"cfgv0Rmax", 90.0, "cfgv0Rmax"}; + Configurable cfgdmassG{"cfgdmassG", 0.1, "max mass for photon"}; + Configurable cfgdmassK{"cfgdmassK", 0.1, "max mass for K0s"}; + Configurable cfgdmassL{"cfgdmassL", 0.1, "max mass for Lambda"}; + Configurable cfgdmassAL{"cfgdmassAL", 0.1, "max mass for anti Lambda"}; + 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"}; + Configurable cfgNsigmaElTOF{"cfgNsigmaElTOF", 3.0, "max nsigma of TOF for electorn"}; + Configurable cfgNsigmaPiTOF{"cfgNsigmaPiTOF", 3.0, "max nsigma of TOF for pion"}; + Configurable cfgNsigmaPrTOF{"cfgNsigmaPrTOF", 3.0, "max nsigma of TOF for proton"}; + } v0SelOpt; + + Service ccdb; + struct : ConfigurableGroup { + Configurable cfgMagField{"cfgMagField", 99999, "Configurable magnetic field;default CCDB will be queried"}; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpmagPath{"grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable grpPath{"grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + } ccdbConf; + + TrackSelection mTrackSelector; + Configurable isCustomTracks{"isCustomTracks", false, "Use custom track cuts"}; + Configurable requirePt{"requirePt", 0.15f, "Set minimum pT of tracks"}; + Configurable requireEta{"requireEta", 0.8f, "Set eta range of tracks"}; + Configurable setITSreq{"setITSreq", 1, "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 maxChi2PerClusterITS{"maxChi2PerClusterITS", 36.f, "Additional cut on the maximum value of the chi2 per cluster in the ITS"}; + 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"}; + + TF1* fPhiCutLow = nullptr; + TF1* fPhiCutHigh = nullptr; + + std::vector> fDeDxVsEta; + std::vector> vecParams; + + void init(InitContext&) + { + auto vecParamsMIPpos = (std::vector)paramsFuncMIPpos; + auto vecParamsMIPneg = (std::vector)paramsFuncMIPneg; + auto vecParamsMIPall = (std::vector)paramsFuncMIPall; + + auto addVec = [&](std::vector>& targetVec, const std::string& name) { + targetVec.emplace_back(vecParamsMIPpos); + targetVec.emplace_back(vecParamsMIPneg); + targetVec.emplace_back(vecParamsMIPall); + if (!vecParams.size()) { + LOG(info) << "size of " << name << "is zero."; + } + }; + addVec(vecParams, "vecParams"); + for (const auto& params : vecParams) { + fDeDxVsEta.emplace_back(setFuncPars(params)); + } + + ccdb->setURL(ccdbConf.ccdbUrl.value); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + ccdb->setFatalWhenNull(false); + + if (isCustomTracks.value) { + mTrackSelector = getGlobalTrackSelectionRun3ITSMatch(setITSreq.value); + mTrackSelector.SetPtRange(requirePt.value, 1e10f); + mTrackSelector.SetEtaRange(-requireEta.value, requireEta.value); + mTrackSelector.SetRequireITSRefit(requireITS.value); + mTrackSelector.SetRequireTPCRefit(requireTPC.value); + mTrackSelector.SetRequireGoldenChi2(requireGoldenChi2.value); + mTrackSelector.SetMaxChi2PerClusterTPC(maxChi2PerClusterTPC.value); + mTrackSelector.SetMaxChi2PerClusterITS(maxChi2PerClusterITS.value); + mTrackSelector.SetMinNClustersITS(minITSnClusters.value); + mTrackSelector.SetMinNCrossedRowsTPC(minNCrossedRowsTPC.value); + mTrackSelector.SetMinNClustersTPC(minTPCNClsFound.value); + mTrackSelector.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC.value); + // // mTrackSelector.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / pow(pt, 1.1f); }); + mTrackSelector.SetMaxDcaXYPtDep([](float /*pt*/) { return 10000.f; }); + mTrackSelector.SetMaxDcaZ(maxDcaZ.value); + mTrackSelector.print(); + } + + const AxisSpec chargeAxis{2, -2.f, 2.f, "Charge"}; + 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 etaAxis{binOpt.axisEta, "#eta"}; + const AxisSpec phiAxis{binOpt.axisPhi, "#varphi"}; + const AxisSpec phiAxisMod{binOpt.axisPhiMod, "fmod(#varphi,#pi/9)"}; + const AxisSpec pAxis{binOpt.axisPt, "#it{p} (GeV/#it{c})"}; + const AxisSpec ptAxis{binOpt.axisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec dcaXYAxis{binOpt.axisDCAxy, "DCA_{xy} (cm)"}; + const AxisSpec dcaZAxis{binOpt.axisDCAz, "DCA_{z} (cm)"}; + const AxisSpec shCluserAxis{200, 0, 1, "Fraction of shared TPC clusters"}; + const AxisSpec clTpcAxis{160, 0, 160, "Number of clusters in TPC"}; + const AxisSpec nSigmaTPCAxis{binOpt.axisNsigmaTPC, "n#sigma_{TPC}"}; + const AxisSpec nSigmaTOFAxis{binOpt.axisNsigmaTOF, "n#sigma_{TOF}"}; + const AxisSpec amplitudeFV0{binOpt.axisAmplFV0, "FV0 amplitude (ADC)"}; + const AxisSpec amplitudeFV0Sum{binOpt.axisAmplFV0Sum, "FV0 amplitude sm (ADC)"}; + const AxisSpec channelFV0Axis{binOpt.axisChannelFV0, "FV0 channel ID"}; + + AxisSpec multAxis{binOpt.axisMultPerc, "multiplicity estimator"}; + + switch (multEst) { + case MultE::kNoMult: + break; + case MultE::kMultFT0M: + multAxis.name = "multFT0M"; + break; + case MultE::kMultTPC: + multAxis.name = "multTPC"; + break; + default: + LOG(fatal) << "No valid option for mult estimator " << multEst; + } + + // Event counter + flatchrg.add("Events/hEvtSel", "Number of events; Cut; #Events Passed Cut", {HistType::kTH1F, {{nEvtSel, 0, nEvtSel}}}); + 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", {HistType::kTH1F, {{nTrkSel, 0, nTrkSel}}}); + 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(trkSelNCls + 1, "NClsTPC"); + flatchrg.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelTPCBndr + 1, "TPC Boundary"); + + if (trkSelOpt.cfgUseExtraTrkCut) { + fPhiCutLow = new TF1("fPhiCutLow", trkSelOpt.cfgGeoTrkCutMin.value.c_str(), 0, 100); + fPhiCutHigh = new TF1("fPhiCutHigh", trkSelOpt.cfgGeoTrkCutMax.value.c_str(), 0, 100); + } + + if (doprocessFlat) { + flatchrg.add("Events/hVtxZ", "Measured vertex z position", HistType::kTH1F, {vtxzAxis}); + flatchrg.add("Events/hFlatVsMultEst", "hFlatVsMultEst", HistType::kTH2F, {flatAxis, multAxis}); + flatchrg.add("Tracks/postSel/hPVsPtEta", "; #it{p} (GeV/#it{c}); #it{p}_{T} (GeV/#it{c}); #eta;", {HistType::kTH3F, {pAxis, ptAxis, etaAxis}}); + if (cfgFillTrackQaHist || cfgFilldEdxQaHist || cfgFillNsigmaQAHist) { + if (cfgFillTrackQaHist) { + flatchrg.add("Tracks/postSel/hPtPhi", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9)", {HistType::kTH2F, {ptAxis, phiAxisMod}}); + flatchrg.add("Tracks/postSel/hPtVsWOcutDCA", "hPtVsWOcutDCA", HistType::kTH2F, {ptAxis, dcaXYAxis}); + flatchrg.add("Tracks/postSel/hPt", "", HistType::kTH1F, {ptAxis}); + flatchrg.add("Tracks/postSel/hPhi", "", HistType::kTH1F, {phiAxis}); + flatchrg.add("Tracks/postSel/hEta", "", HistType::kTH1F, {etaAxis}); + flatchrg.add("Tracks/postSel/hDCAXYvsPt", "", HistType::kTH2F, {ptAxis, dcaXYAxis}); + flatchrg.add("Tracks/postSel/hDCAZvsPt", "", HistType::kTH2F, {ptAxis, dcaZAxis}); + // tpc + if (cfgStoreThnSparse) { + flatchrg.add("Tracks/postSel/hPtPhiTPCCluster", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{cluster}", {HistType::kTHnSparseF, {ptAxis, phiAxisMod, clTpcAxis}}); + } else { + flatchrg.add("Tracks/postSel/hPtPhiTPCCluster", "; #it{p}_{T} (GeV/#it{c}); fmod(#varphi,#pi/9); N_{cluster}", {HistType::kTH2F, {ptAxis, phiAxisMod}}); + } + flatchrg.add("Tracks/postSel/hShTpcClvsPt", "", {HistType::kTH2F, {ptAxis, shCluserAxis}}); + flatchrg.add("Tracks/postSel/hCrossTPCvsPt", "", {HistType::kTH2F, {ptAxis, clTpcAxis}}); + flatchrg.add("Tracks/postSel/hTPCCluster", "N_{cluster}", HistType::kTH1F, {clTpcAxis}); + flatchrg.add("Tracks/postSel/tpcNClsShared", " ; # shared TPC clusters TPC", HistType::kTH1F, {{165, -0.5, 164.5}}); + flatchrg.add("Tracks/postSel/tpcCrossedRows", " ; # crossed TPC rows", HistType::kTH1F, {{165, -0.5, 164.5}}); + flatchrg.add("Tracks/postSel/tpcCrossedRowsOverFindableCls", " ; crossed rows / findable TPC clusters", HistType::kTH1F, {{60, 0.7, 1.3}}); + // its + flatchrg.add("Tracks/postSel/itsNCls", " ; # ITS clusters", HistType::kTH1F, {{8, -0.5, 7.5}}); + flatchrg.add("Tracks/postSel/hChi2ITSTrkSegment", "chi2ITS", HistType::kTH1F, {{100, -0.5, 99.5}}); + // tof + flatchrg.add("Tracks/postSel/hTOFPvsBeta", "Beta from TOF; #it{p} (GeV/#it{c}); #beta", {HistType::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", {HistType::kTHnSparseF, {etaAxis, pAxis, dEdxAxis}}); + } else { + flatchrg.add("Tracks/postSel/hTOFpi", "Primary Pions from TOF; #eta; #it{p} (GeV/#it{c}); dEdx", {HistType::kTH3F, {etaAxis, pAxis, dEdxAxis}}); + } + } + if (cfgFilldEdxQaHist) { + if (cfgStoreThnSparse) { + flatchrg.add("Tracks/postCalib/all/hMIP", "; mult; flat; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTHnSparseF, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateau", "; mult; flat; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTHnSparseF, {multAxis, flatAxis, etaAxis, dEdxAxis}}); + } else { + flatchrg.add("Tracks/postCalib/all/hMIP", "; #eta; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2F, {etaAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateau", "; #eta; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2F, {etaAxis, dEdxAxis}}); + } + flatchrg.add("Tracks/postCalib/all/hMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTH2F, {phiAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pMIPVsPhi", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks};", {HistType::kTProfile, {phiAxis}}); + flatchrg.add("Tracks/postCalib/all/hMIPVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{MIP, primary tracks}; #eta;", {HistType::kTH3F, {phiAxis, dEdxAxis, etaAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTH2F, {phiAxis, dEdxAxis}}); + flatchrg.add("Tracks/postCalib/all/pPlateauVsPhi", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks};", {HistType::kTProfile, {phiAxis}}); + flatchrg.add("Tracks/postCalib/all/hPlateauVsPhiVsEta", "; #varphi; #LT dE/dx #GT_{Plateau, primary tracks}; #eta;", {HistType::kTH3F, {phiAxis, dEdxAxis, etaAxis}}); + flatchrg.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/"); + } + } + 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)", HistType::kTHnSparseF, {ptAxis, nSigmaTPCAxis, multAxis, flatAxis}); + } else { + hPtNsigmaTPC[i] = flatchrg.add("Tracks/hPtNsigmaTPC" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, nSigmaTPCAxis}); + } + hPtNsigmaTOF[i] = flatchrg.add("Tracks/hPtNsigmaTOF" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, nSigmaTOFAxis}); + hPtNsigmaTPCTOF[i] = flatchrg.add("Tracks/hPtNsigmaTPCTOF" + strID, PidChrg[i], HistType::kTH2F, {nSigmaTPCAxis, nSigmaTOFAxis}); + } + } + } + flatchrg.addClone("Tracks/postSel/", "Tracks/preSel/"); + // FV0 QA + flatchrg.add("FV0/hFV0AmplWCalib", "", {HistType::kTH2F, {channelFV0Axis, amplitudeFV0}}); + flatchrg.add("FV0/hFV0AmplvsVtxzWoCalib", "", {HistType::kTH2F, {vtxzAxis, amplitudeFV0Sum}}); + flatchrg.add("FV0/hFV0AmplvsVtxzCalib", "", {HistType::kTH2F, {vtxzAxis, amplitudeFV0Sum}}); + flatchrg.add("FV0/hFV0amp", "", {HistType::kTH2F, {channelFV0Axis, amplitudeFV0}}); + flatchrg.add("FV0/pFV0amp", "", HistType::kTProfile, {channelFV0Axis}); + flatchrg.add("FV0/hFV0ampCorr", "", {HistType::kTH2F, {channelFV0Axis, amplitudeFV0}}); + // V0's QA + flatchrg.add("Tracks/V0qa/hV0Pt", "pT", HistType::kTH1F, {{100, 0.0f, 10}}); + flatchrg.add("Tracks/V0qa/hV0ArmPod", ";#alpha; #it{q}_T", HistType::kTH2F, {{200, -1.0f, +1.0f}, {250, 0.0f, 0.25f}}); + // dEdx PID + flatchrg.add({"Tracks/all/hdEdx", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::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", {HistType::kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hEV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hPiV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hPV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTHnSparseF, {etaAxis, multAxis, flatAxis, pAxis, dEdxAxis}}}); + } else { + flatchrg.add({"Tracks/CleanTof/all/hPiTof", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hEV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hPiV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + flatchrg.add({"Tracks/CleanV0/pos/hPV0", "; #eta; mult; flat; #it{p} (GeV/#it{c}); dEdx", {HistType::kTH3F, {etaAxis, pAxis, dEdxAxis}}}); + } + flatchrg.addClone("Tracks/CleanV0/pos/", "Tracks/CleanV0/neg/"); + if (cfgFillChrgType) { + flatchrg.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/pos/"); + flatchrg.addClone("Tracks/CleanTof/all/", "Tracks/CleanTof/neg/"); + } + } + if (cfgFillChrgType) { + flatchrg.addClone("Tracks/all/", "Tracks/pos/"); + flatchrg.addClone("Tracks/all/", "Tracks/neg/"); + } + } + + if (doprocessMC) { + auto h = flatchrg.add("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", {HistType::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."); + + 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)", HistType::kTH1F, {ptAxis}); + hPtGenPrimRecEvt[i] = flatchrg.add("Tracks/hPtGenPrimRecEvt" + strID, " ; p_{T} (GeV/c)", HistType::kTH1F, {ptAxis}); + hPtEffGenPrim[i] = flatchrg.add("Tracks/hPtEffGenPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH3F, {multAxis, flatAxis, ptAxis}); + hPtEffGenWeak[i] = flatchrg.add("Tracks/hPtEffGenWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH3F, {multAxis, flatAxis, ptAxis}); + hPtEffGenMat[i] = flatchrg.add("Tracks/hPtEffGenMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH3F, {multAxis, flatAxis, ptAxis}); + hPtEffRecPrim[i] = flatchrg.add("Tracks/hPtEffRecPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH3F, {multAxis, flatAxis, ptAxis}); + hPtEffRecWeak[i] = flatchrg.add("Tracks/hPtEffRecWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH3F, {multAxis, flatAxis, ptAxis}); + hPtEffRecMat[i] = flatchrg.add("Tracks/hPtEffRecMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH3F, {multAxis, flatAxis, ptAxis}); + hDCAxyBadCollPrim[i] = flatchrg.add("Tracks/hDCAxyBadCollPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, dcaXYAxis}); + hDCAxyBadCollWeak[i] = flatchrg.add("Tracks/hDCAxyBadCollWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, dcaXYAxis}); + hDCAxyBadCollMat[i] = flatchrg.add("Tracks/hDCAxyBadCollMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, dcaXYAxis}); + hPtVsDCAxyPrim[i] = flatchrg.add("Tracks/hPtVsDCAxyPrim" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, dcaXYAxis}); + hPtVsDCAxyWeak[i] = flatchrg.add("Tracks/hPtVsDCAxyWeak" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, dcaXYAxis}); + hPtVsDCAxyMat[i] = flatchrg.add("Tracks/hPtVsDCAxyMat" + strID, " ; p_{T} (GeV/c)", HistType::kTH2F, {ptAxis, dcaXYAxis}); + } + + flatchrg.add({"hPtOut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {ptAxis}}}); + flatchrg.add({"hPtOutPrim", " ; p_{T} (GeV/c)", {HistType::kTH1F, {ptAxis}}}); + flatchrg.add({"hPtOutNoEtaCut", " ; p_{T} (GeV/c)", {HistType::kTH1F, {ptAxis}}}); + flatchrg.add({"PtOutFakes", " ; p_{T} (GeV/c)", {HistType::kTH1F, {ptAxis}}}); + flatchrg.add("hPtVsDCAxyPrimAll", "hPtVsDCAxyPrimAll", HistType::kTH2F, {ptAxis, dcaXYAxis}); + flatchrg.add("hPtVsDCAxyWeakAll", "hPtVsDCAxyWeakAll", HistType::kTH2F, {ptAxis, dcaXYAxis}); + flatchrg.add("hPtVsDCAxyMatAll", "hPtVsDCAxyMatAll", HistType::kTH2F, {ptAxis, dcaXYAxis}); + flatchrg.add("hPtVsDCAxyAll", "hPtVsDCAxyAll", HistType::kTH2F, {ptAxis, dcaXYAxis}); + flatchrg.add({"ResponseGen", " ; N_{part}; F_{FV0};", {HistType::kTHnSparseF, {multAxis, flatAxis}}}); + flatchrg.add("h1flatencityFV0MCGen", "", HistType::kTH1F, {{102, -0.01, 1.01, "1-flatencityFV0"}}); + + // Hash list for efficiency + listEfficiency.setObject(new THashList); + static_for<0, 1>([&](auto pidSgn) { + bookMcHist(); + bookMcHist(); + bookMcHist(); + initEfficiency(); + initEfficiency(); + initEfficiency(); + }); + } + + if (doprocessMCclosure) { + for (int i = 0; i < Npart; i++) { + flatchrg.add({fmt::format(kPtMCclosurePrimF.data(), kSpeciesAll[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3F, {multAxis, flatAxis, ptAxis}}}); + } + } + + if (doprocessSgnLoss) { + flatchrg.add("hFlatMCGenRecColl", "hFlatMCGenRecColl", {HistType::kTH1F, {flatAxis}}); + flatchrg.add("hFlatMCGen", "hFlatMCGen", {HistType::kTH1F, {flatAxis}}); + // Event counter + flatchrg.add("hEvtMcGen", "hEvtMcGen", {HistType::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", {HistType::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", {HistType::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", {HistType::kTH1F, {flatAxis}}); + + for (int i = 0; i < NpartChrg; ++i) { + flatchrg.add({fmt::format(kPtGenPrimSgnF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3F, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtGenPrimSgnINELF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3F, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtRecCollPrimSgnF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3F, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtRecCollPrimSgnINELF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3F, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtGenRecCollPrimSgnF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3F, {multAxis, flatAxis, ptAxis}}}); + flatchrg.add({fmt::format(kPtGenRecCollPrimSgnINELF.data(), kSpecies[i]).c_str(), " ; p_{T} (GeV/c)", {HistType::kTH3F, {multAxis, flatAxis, ptAxis}}}); + } + } + + LOG(info) << "Size of the histograms:"; + flatchrg.print(); + } + + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + fv0AmplCorr.clear(); + fv0AmplCorr = {}; + std::string fullPathCalibGain; + std::string fullPathCalibVtx; + auto timestamp = bc.timestamp(); + auto runnumber = bc.runNumber(); + + if (applyCalibGain) { + fullPathCalibGain = cfgGainEqCcdbPath; + fullPathCalibGain += "/FV0"; + auto objfv0Gain = getForTsOrRun>(fullPathCalibGain, timestamp, runnumber); + if (!objfv0Gain) { + for (auto i{0u}; i < kNCellsFV0; i++) { + fv0AmplCorr.push_back(1.); + LOGF(warning, "Setting FV0 calibration object values to 1"); + } + } else { + fv0AmplCorr = *(objfv0Gain); + } + } + + if (applyCalibVtx) { + fullPathCalibVtx = cfgVtxEqCcdbPath; + fullPathCalibVtx += "/FV0"; + zVtxMap = getForTsOrRun(fullPathCalibVtx, timestamp, runnumber); + } + } + + 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.)); + if (vecPars.size() >= 1) { + for (typename T::size_type i = 0; i < vecPars.size(); i++) { + fCalibFunc->SetParameter(i, vecPars[i]); + } + } + return fCalibFunc; + } + + template + bool isPID(const P& mcParticle) + { + static_assert(pidSgn == 0 || pidSgn == 1); + static_assert(id > 0 || id < Npart); + constexpr int kIdx = id + pidSgn * Npart; + return mcParticle.pdgCode() == PidSgn[kIdx]; + } + + 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) + { + if (track.p() < trkSelOpt.cfgMomSelPiTOF) { + if (track.hasTOF()) { + if (std::abs(track.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC && std::abs(track.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF) { + return true; + } + } + } + return false; + } + + template + void fillNsigma(T const& tracks, const C& collision) + { + const float mult = getMult(collision); + const float flat = fillFlat(collision); + for (const auto& track : tracks) { + checkNsigma(track, mult, flat); + } + } + + template + void filldEdx(T const& tracks, V const& v0s, const C& collision, aod::BCsWithTimestamps const& /*bcs*/) + { + auto bc = collision.template bc_as(); + auto magField = (ccdbConf.cfgMagField == 0) ? getMagneticField(bc.timestamp()) : ccdbConf.cfgMagField; + + if (applyCalibGain || applyCalibVtx) { + int currentRun = bc.runNumber(); + if (runNumber != currentRun) { + initCCDB(bc); + runNumber = currentRun; + } + } + + const float mult = getMult(collision); + const float flat = fillFlat(collision); + flatchrg.fill(HIST("Events/hFlatVsMultEst"), flat, mult); + + for (const auto& track : tracks) { + float dEdx = track.tpcSignal(); + if (cfgFillTrackQaHist) { + fillTrackQA(track); + } + if (!isGoodTrack(track, magField)) { + continue; + } + if (cfgFillTrackQaHist) { + fillTrackQA(track); + } + if (cfgFilldEdxCalibHist && cfgFilldEdxQaHist) { + if (cfgFillChrgType) { + if (track.sign() * track.tpcInnerParam() > 0) { + filldEdxQA(track, collision, dEdx); + } else { + filldEdxQA(track, collision, dEdx); + } + } else { + filldEdxQA(track, collision, dEdx); + } + } + if (applyCalibDeDx) { + if (cfgFillChrgType) { + dEdx *= (50.0 / getCalibration(fDeDxVsEta, track)); + if (cfgFilldEdxQaHist) { + if (track.sign() * track.tpcInnerParam() > 0) { + filldEdxQA(track, collision, dEdx); + } else { + filldEdxQA(track, collision, dEdx); + } + } + } else { + dEdx *= (50.0 / getCalibration(fDeDxVsEta, track)); + if (cfgFilldEdxQaHist) { + filldEdxQA(track, collision, dEdx); + } + } + } + + // PID TPC dEdx + if (cfgFillChrgType) { + if (track.sign() * track.tpcInnerParam() > 0) { + flatchrg.fill(HIST(kPrefix) + HIST(kCharge[kPos]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } else { + flatchrg.fill(HIST(kPrefix) + HIST(kCharge[kNeg]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } + } else { + flatchrg.fill(HIST(kPrefix) + HIST(kCharge[kAll]) + HIST("hdEdx"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } + + // TOF pions + if (cfgFillV0Hist) { + if (track.hasTOF() && track.beta() > 1.) { + if (selTOFPi(track)) { + if (cfgFillChrgType) { + if (track.sign() * track.tpcInnerParam() > 0) { + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kPos]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } else { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kPos]) + HIST("hPiTof"), track.eta(), track.tpcInnerParam(), dEdx); + } + } else { + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kNeg]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } else { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kNeg]) + HIST("hPiTof"), track.eta(), track.tpcInnerParam(), dEdx); + } + } + } else { + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kAll]) + HIST("hPiTof"), track.eta(), mult, flat, track.tpcInnerParam(), dEdx); + } else { + flatchrg.fill(HIST(kPrefixCleanTof) + HIST(kCharge[kAll]) + HIST("hPiTof"), track.eta(), track.tpcInnerParam(), dEdx); + } + } + } + } + } + } + + // V0s + if (cfgFillV0Hist) { + for (const auto& v0 : v0s) { + if (!isGoodV0Track(v0, tracks)) { + continue; + } + + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + float dEdxPos = posTrack.tpcSignal(); + float dEdxNeg = negTrack.tpcSignal(); + + if (applyCalibDeDx) { + dEdxPos *= (50.0 / getCalibration(fDeDxVsEta, posTrack)); + dEdxNeg *= (50.0 / getCalibration(fDeDxVsEta, negTrack)); + } + + if (selectTypeV0s(v0, posTrack, negTrack) == kGa) { // Gamma selection + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hEV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hEV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } else { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hEV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hEV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + } + if (selectTypeV0s(v0, posTrack, negTrack) == kKz) { // K0S -> pi + pi + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } else { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPiV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + } + if (selectTypeV0s(v0, posTrack, negTrack) == kLam) { // L -> p + pi- + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } else { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + } + if (selectTypeV0s(v0, posTrack, negTrack) == kaLam) { // L -> p + pi- + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPiV0"), posTrack.eta(), mult, flat, posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), mult, flat, negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } else { + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kPos]) + HIST("hPiV0"), posTrack.eta(), posTrack.sign() * posTrack.tpcInnerParam(), dEdxPos); + flatchrg.fill(HIST(kPrefixCleanV0) + HIST(kCharge[kNeg]) + HIST("hPiV0"), negTrack.eta(), negTrack.sign() * negTrack.tpcInnerParam(), dEdxNeg); + } + } + } + } + } + + template + float getCalibration(std::vector> const& fCalib, V const& track) + { + float valCalib = -1.; + if constexpr (isChrg) { + if (track.sign() * track.tpcInnerParam() > 0) { + valCalib = fCalib.at(0)->Eval(track.eta()); + } else { + valCalib = fCalib.at(1)->Eval(track.eta()); + } + } else { + valCalib = fCalib.at(2)->Eval(track.eta()); + } + return valCalib; + } + + bool isChrgParticle(int code) + { + auto p = pdg->GetParticle(code); + auto charge = 0.; + if (p != nullptr) { + charge = p->Charge(); + } + return std::abs(charge) >= kMinCharge; + } + + template + bool phiCut(T const& track, float mag, TF1* fphiCutLow, TF1* fphiCutHigh) + { + if (track.pt() < trkSelOpt.cfgPhiCutPtMin) + return true; + // cut to remove tracks at TPC boundaries + double phimodn = track.phi(); + if (mag < 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 = std::fmod(phimodn, o2::constants::math::PI / 9.0); + + if (cfgFillTrackQaHist) { + flatchrg.fill(HIST("Tracks/preSel/hPtPhi"), track.pt(), phimodn); + if (track.hasTPC() && track.hasITS()) { + if (cfgStoreThnSparse) { + flatchrg.fill(HIST("Tracks/preSel/hPtPhiTPCCluster"), track.pt(), phimodn, track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()); + } else { + flatchrg.fill(HIST("Tracks/preSel/hPtPhiTPCCluster"), track.pt(), phimodn); + } + } + } + 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/hPtPhiTPCCluster"), track.pt(), phimodn, track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()); + } else { + flatchrg.fill(HIST("Tracks/postSel/hPtPhiTPCCluster"), track.pt(), phimodn); + } + } + } + return true; + } + + template + bool isGoodTrack(T const& track, int const magfield) + { + if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelEta); + if (track.pt() < trkSelOpt.cfgTrkPtMin) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelPt); + if (!isDCAxyCut(track)) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelDCA); + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkNRowsTPC); + auto nClusterTPC = track.tpcNClsFindable() - track.tpcNClsFindableMinusFound(); + if (nClusterTPC < trkSelOpt.cfgNclTPCMin) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelNCls); + if (trkSelOpt.cfgUseExtraTrkCut && !phiCut(track, magfield, fPhiCutLow, fPhiCutHigh)) { + return false; + } + flatchrg.fill(HIST("Tracks/hTrkSel"), trkSelTPCBndr); + return true; + } + + template + int selectTypeV0s(T1 const& v0, T2 const& postrk, T2 const& negtrk) + { + // Gamma selection + if (v0.mGamma() < v0SelOpt.cfgdmassG) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaEl()) < v0SelOpt.cfgNsigmaElTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaEl()) < v0SelOpt.cfgNsigmaElTOF) { + return kGa; + } + } + if (negtrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaEl()) < v0SelOpt.cfgNsigmaElTPC) { + if (negtrk.hasTOF() && std::abs(negtrk.tofNSigmaEl()) < v0SelOpt.cfgNsigmaElTOF) { + return kGa; + } + } + } + // K0S selection, K0S -> pi + pi + if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0SelOpt.cfgdmassK) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaElTOF) { + return kKz; + } + } + if (negtrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC) { + if (negtrk.hasTOF() && std::abs(negtrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF) { + return kKz; + } + } + } + // Lambda selection, L -> p + pi- + if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0SelOpt.cfgdmassL) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaPr()) < v0SelOpt.cfgNsigmaPrTPC && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaPr()) < v0SelOpt.cfgNsigmaPrTOF && negtrk.hasTOF() && std::abs(negtrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF) { + return kLam; + } + } + } + // antiLambda -> pbar + pi+ + if (std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < v0SelOpt.cfgdmassL) { + if (postrk.tpcInnerParam() < v0SelOpt.cfgV0DaughterTpcMomMax && postrk.hasTPC() && std::abs(postrk.tpcNSigmaPi()) < v0SelOpt.cfgNsigmaPiTPC && negtrk.hasTPC() && std::abs(negtrk.tpcNSigmaPr()) < v0SelOpt.cfgNsigmaPrTPC) { + if (postrk.hasTOF() && std::abs(postrk.tofNSigmaPi()) < v0SelOpt.cfgNsigmaPiTOF && negtrk.hasTOF() && std::abs(negtrk.tofNSigmaPr()) < v0SelOpt.cfgNsigmaPrTOF) { + return kaLam; + } + } + } + return kNaN; + } + + template + bool isGoodV0Track(T1 const& v0, T2 const& /*track*/) + { + const auto& posTrack = v0.template posTrack_as(); + const auto& negTrack = v0.template negTrack_as(); + + if (std::abs(posTrack.eta()) > v0SelOpt.cfgV0etamax || std::abs(negTrack.eta()) > v0SelOpt.cfgV0etamax) { + return false; + } + if (posTrack.tpcNClsFound() < v0SelOpt.cfgTPCnClsmin || negTrack.tpcNClsFound() < v0SelOpt.cfgTPCnClsmin) { + return false; + } + if (posTrack.sign() * negTrack.sign() > 0) { // reject same sign pair + return false; + } + if (v0.dcaV0daughters() > v0SelOpt.cfgDCAv0daughter) { + return false; + } + if (v0.v0cosPA() < v0SelOpt.cfgv0cospa) { + return false; + } + if (v0.v0radius() < v0SelOpt.cfgv0Rmin || v0.v0radius() > v0SelOpt.cfgv0Rmax) { + return false; + } + if (std::abs(v0.dcapostopv()) < v0SelOpt.cfgDCAposToPV || std::abs(v0.dcanegtopv()) < v0SelOpt.cfgDCAposToPV) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Tracks/V0qa/hV0Pt"), v0.pt()); + flatchrg.fill(HIST("Tracks/V0qa/hV0ArmPod"), v0.alpha(), v0.qtarm()); + } + return true; + } + + template + void checkNsigma(const T& track, const float mult, const float flat) + { + if (std::abs(track.rapidity(o2::track::PID::getMass(pid))) > trkSelOpt.cfgRapMax) { + return; + } + + 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.sign() > 0) { + if (cfgStoreThnSparse) { + hThPtNsigmaTPC[pid]->Fill(track.pt(), valTPCnsigma, mult, flat); + } else { + hPtNsigmaTPC[pid]->Fill(track.pt(), valTPCnsigma); + } + } else { + if (cfgStoreThnSparse) { + hThPtNsigmaTPC[pid + Npart]->Fill(track.pt(), valTPCnsigma, mult, flat); + } else { + hPtNsigmaTPC[pid + Npart]->Fill(track.pt(), valTPCnsigma); + } + } + if (!track.hasTOF()) { + return; + } + if (track.sign() > 0) { + 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); + } + } + + template + inline void fillTrackQA(T const& track) + { + if constexpr (fillHist) { + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hPt"), track.pt()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hPhi"), track.phi()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hEta"), track.eta()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hDCAXYvsPt"), track.pt(), track.dcaXY()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hDCAZvsPt"), track.pt(), track.dcaZ()); + + if (track.hasTPC() && track.hasITS()) { + int nFindable = track.tpcNClsFindable(); + int nMinusFound = track.tpcNClsFindableMinusFound(); + int nCluster = nFindable - nMinusFound; + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hTPCCluster"), nCluster); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hShTpcClvsPt"), track.pt(), track.tpcFractionSharedCls()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hCrossTPCvsPt"), track.pt(), track.tpcNClsFound()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("tpcNClsShared"), track.tpcNClsShared()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("tpcCrossedRows"), track.tpcNClsCrossedRows()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("tpcCrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hChi2ITSTrkSegment"), track.itsChi2NCl()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("itsNCls"), track.itsNCls()); + } + + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hTOFPvsBeta"), track.tpcInnerParam(), track.beta()); + if (track.beta() > trkSelOpt.cfgTOFBetaPion && track.beta() < trkSelOpt.cfgTOFBetaPion + 0.05) { // TOF pions + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hTOFpi"), track.eta(), track.tpcInnerParam(), track.tpcSignal()); + } + + if (std::abs(track.eta()) < trkSelOpt.cfgTrkEtaMax) { + if (isDCAxyWoCut(track)) { + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hPtVsWOcutDCA"), track.pt(), track.dcaXY()); + } + } + } + flatchrg.fill(HIST(kPrefix) + HIST(kStatus[ft]) + HIST("hPVsPtEta"), track.tpcInnerParam(), track.pt(), track.eta()); + } + + template + inline void filldEdxQA(T const& track, C const& collision, const float dEdx) + { + const float mult = getMult(collision); + const float flat = fillFlat(collision); + // float dEdx = track.tpcSignal(); + if constexpr (fillHist) { + if (track.tpcInnerParam() >= trkSelOpt.cfgMomMIPMin && track.tpcInnerParam() <= trkSelOpt.cfgMomMIPMax) { + if (dEdx > trkSelOpt.cfgDeDxMIPMin && dEdx < trkSelOpt.cfgDeDxMIPMax) { // MIP pions + if (cfgStoreThnSparse) { + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIP"), mult, flat, track.eta(), dEdx); + } else { + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIP"), track.eta(), dEdx); + } + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIPVsPhi"), track.phi(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hMIPVsPhiVsEta"), track.phi(), dEdx, track.eta()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[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(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateau"), mult, flat, track.eta(), dEdx); + } else { + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateau"), track.eta(), dEdx); + } + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateauVsPhi"), track.phi(), dEdx); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("hPlateauVsPhiVsEta"), track.phi(), dEdx, track.eta()); + flatchrg.fill(HIST(kPrefix) + HIST(kStatCalib[ft]) + HIST(kCharge[chrg]) + HIST("pPlateauVsPhi"), track.phi(), dEdx); + } + } + } + } + } + + template + bool isGoodEvent(C const& collision) + { + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelAll); + } + if (evtSelOpt.cfgCustomTVX) { + if (!collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + } else { + if (!collision.sel8()) { + return false; + } + } + if constexpr (fillHist) { + flatchrg.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); + } + if (evtSelOpt.cfgRemoveNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if constexpr (fillHist) { + flatchrg.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); + } + if (evtSelOpt.cfgRequireIsGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if constexpr (fillHist) { + flatchrg.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); + } + if (evtSelOpt.cfgRequirekIsVertexTOFmatched && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if constexpr (fillHist) { + flatchrg.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()); + } + if (evtSelOpt.cfgINELCut && !collision.isInelGt0()) { + return false; + } + if constexpr (fillHist) { + flatchrg.fill(HIST("Events/hEvtSel"), evtSelINELgt0); + } + return true; + } + + int getFV0IndexPhi(int i_ch) + { + int iRing = -1; + + if (i_ch >= kFV0IndexPhi[0] && i_ch < kFV0IndexPhi[1]) { + if (i_ch < kFV0IndexPhi[0] + 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[1] - 1) { + iRing = i_ch - 3; // 4; + } else if (i_ch == kFV0IndexPhi[1] - 2) { + iRing = i_ch - 1; // 5; + } else if (i_ch == kFV0IndexPhi[1] - 3) { + iRing = i_ch + 1; // 6; + } else if (i_ch == kFV0IndexPhi[1] - 4) { + iRing = i_ch + 3; // 7; + } + } + } else if (i_ch >= kFV0IndexPhi[1] && i_ch < kFV0IndexPhi[2]) { + if (i_ch < kFV0IndexPhi[2] - 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[2] - 1) { + iRing = i_ch - 3; // 12; + } else if (i_ch == kFV0IndexPhi[2] - 2) { + iRing = i_ch - 1; // 13; + } else if (i_ch == kFV0IndexPhi[2] - 3) { + iRing = i_ch + 1; // 14; + } else if (i_ch == kFV0IndexPhi[2] - 4) { + iRing = i_ch + 3; // 15; + } + } + } else if (i_ch >= kFV0IndexPhi[2] && i_ch < kFV0IndexPhi[3]) { + if (i_ch < kFV0IndexPhi[3] - 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[3] - 1) { + iRing = i_ch - 3; // 20; + } else if (i_ch == kFV0IndexPhi[3] - 2) { + iRing = i_ch - 1; // 21; + } else if (i_ch == kFV0IndexPhi[3] - 3) { + iRing = i_ch + 1; // 22; + } else if (i_ch == kFV0IndexPhi[3] - 4) { + iRing = i_ch + 3; // 23; + } + } + } else if (i_ch >= kFV0IndexPhi[3] && i_ch < kFV0IndexPhi[4]) { + if (i_ch < kFV0IndexPhi[3] + 4) { + iRing = i_ch; + } else { + if (i_ch == kFV0IndexPhi[4] - 5) { + iRing = i_ch - 3; // 28; + } else if (i_ch == kFV0IndexPhi[4] - 6) { + iRing = i_ch - 1; // 29; + } else if (i_ch == kFV0IndexPhi[4] - 7) { + iRing = i_ch + 1; // 30; + } else if (i_ch == kFV0IndexPhi[4] - 8) { + iRing = i_ch + 3; // 31; + } + } + } else if (i_ch == kFV0IndexPhi[4]) { + iRing = kFV0IndexPhi[4]; + } else if (i_ch == kFV0IndexPhi[4] + 8) { + iRing = i_ch - 7; // 33; + } else if (i_ch == kFV0IndexPhi[4] - 3) { + iRing = i_ch + 1; // 34; + } else if (i_ch == kFV0IndexPhi[4] + 5) { + iRing = i_ch - 6; // 35; + } else if (i_ch == kFV0IndexPhi[4] - 2) { + iRing = i_ch + 2; // 36; + } else if (i_ch == kFV0IndexPhi[4] + 6) { + iRing = i_ch - 5; // 37; + } else if (i_ch == kFV0IndexPhi[4] - 1) { + iRing = i_ch + 3; // 38; + } else if (i_ch == kFV0IndexPhi[4] + 7) { + iRing = i_ch - 4; // 39; + } else if (i_ch == kFV0IndexPhi[4] + 11) { + iRing = i_ch + 7; // 40; + } else if (i_ch == kFV0IndexPhi[4] + 3) { + iRing = i_ch + 2; // 41; + } else if (i_ch == kFV0IndexPhi[4] + 10) { + iRing = i_ch - 4; // 42; + } else if (i_ch == kFV0IndexPhi[4] + 1) { + iRing = i_ch + 5; // 43; + } else if (i_ch == kFV0IndexPhi[4] + 9) { + iRing = i_ch - 1; // 44; + } else if (i_ch == kFV0IndexPhi[4] + 1) { + iRing = i_ch + 8; // 45; + } else if (i_ch == kFV0IndexPhi[4] + 8) { + iRing = i_ch + 2; // 46; + } else if (i_ch == kFV0IndexPhi[4]) { + iRing = i_ch + 11; // 47; + } + return iRing; + } + + int getMagneticField(uint64_t timestamp) + { + o2::parameters::GRPMagField* grpmag = nullptr; + grpmag = ccdb->getForTimeStamp(ccdbConf.grpmagPath, timestamp); + if (!grpmag) { + return 0; + } + return grpmag->getNominalL3Field(); + } + + template + float getMult(C const& collision) + { + float val = -999.0; + switch (multEst) { + case MultE::kNoMult: + return val; + break; + case MultE::kMultFT0M: + return collision.centFT0M(); + break; + case MultE::kMultTPC: + if constexpr (!isMC) { + return collision.multTPC(); + } else { + LOG(fatal) << "No valid multiplicity estimator: " << multEst; + return val; + } + break; + default: + return collision.centFT0M(); + break; + } + } + + float getMultMC(MCColls::iterator const& collision) + { + return getMult(collision); + } + + template + float calcFlatenicity(std::array const& signals) + { + static_assert(S != 0); + + int entries = signals.size(); + float flat{-1}; + float mRho{0}; + for (int iCell = 0; iCell < entries; ++iCell) { + if (signals[iCell] > 0.) { + mRho += 1.0 * signals[iCell]; + } + } + // average activity per cell + mRho /= (1.0 * entries); + if (mRho <= 0) { + return -1; + } + // get sigma + float sRhoTmp{0}; + float sRho{0}; + for (int iCell = 0; iCell < entries; ++iCell) { + if (signals[iCell] > 0.) { + sRhoTmp += std::pow(1.0 * signals[iCell] - mRho, 2); + } + } + sRhoTmp /= (1.0 * entries * entries); + sRho = std::sqrt(sRhoTmp); + if (mRho > 0.) { + flat = sRho / mRho; + } else { + flat = -1; + } + return flat; + } + + template + float fillFlat(C const& collision) + { + rhoLatticeFV0.fill(0); + fv0AmplitudeWoCalib.fill(0); + bool isOkFV0OrA = false; + if (collision.has_foundFV0()) { + auto fv0 = collision.foundFV0(); + std::bitset<8> fV0Triggers = fv0.triggerMask(); + isOkFV0OrA = fV0Triggers[o2::fit::Triggers::bitA]; + if (isOkFV0OrA) { + for (std::size_t ich = 0; ich < fv0.channel().size(); ich++) { + float amplCh = fv0.amplitude()[ich]; + 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); + if (applyCalibGain) { + flatchrg.fill(HIST("FV0/hFV0ampCorr"), chv0, amplCh / fv0AmplCorr[chv0]); + } + } + if (amplCh > 0.) { + if (applyCalibGain) { // equalize gain channel-by-channel + amplCh /= fv0AmplCorr[chv0]; + } + if (chv0phi > 0) { + fv0AmplitudeWoCalib[chv0phi] = amplCh; + if constexpr (fillHist) { + flatchrg.fill(HIST("FV0/hFV0AmplWCalib"), ich, fv0AmplitudeWoCalib[ich]); + } + if (chv0 < kInnerFV0) { + rhoLatticeFV0[chv0phi] += amplCh; + } else { // two channels per bin + rhoLatticeFV0[chv0phi] += amplCh / 2.; + } + if constexpr (fillHist) { + flatchrg.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]); + } + } + } + } + } + float flattenicityFV0 = calcFlatenicity(rhoLatticeFV0); + return 1. - flattenicityFV0; + } else { + return 9999; + } + } else { + return 9999; + } + } + + template + bool isDCAxyCut(T const& track) const + { + if (isCustomTracks.value) { + for (int i = 0; i < static_cast(TrackSelection::TrackCuts::kNCuts); i++) { + if (i == static_cast(TrackSelection::TrackCuts::kDCAxy)) { + continue; + } + if (!mTrackSelector.IsSelected(track, static_cast(i))) { + return false; + } + } + return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); + } + return track.isGlobalTrack(); + } + + template + bool isDCAxyWoCut(T const& track) const + { + 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 (!mTrackSelector.IsSelected(track, static_cast(i))) { + return false; + } + } + return true; + } + return track.isGlobalTrackWoDCA(); + } + + Preslice perCol = aod::track::collisionId; + Preslice perColV0s = aod::v0::collisionId; + + template + void processData(C const& collisions, + MyPIDTracks const& tracks, + aod::V0Datas const& v0s, + aod::BCsWithTimestamps const& bcs) + { + for (const auto& collision : collisions) { + if (!isGoodEvent(collision)) { + continue; + } + auto tracksPerCollision = tracks.sliceBy(perCol, collision.globalIndex()); + 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); + } + } + } + + void processFlat( + Colls const& collisions, + MyPIDTracks const& tracks, + aod::V0Datas const& v0s, + aod::BCsWithTimestamps const& bcs, + aod::FT0s const&, aod::FV0As const&) + { + processData(collisions, tracks, v0s, bcs); + } + PROCESS_SWITCH(FlattenictyPikp, processFlat, "process Flat data inclusive", true); + + template + float fillFlatMC(McPart const& mcparts) + { + int nFV0sectors = 0; + float minPhi = 0; + float maxPhi = 0; + float dPhi = 0; + + double etaMinFV0bins[kMaxRingsFV0] = {0.0}; + double etaMaxFV0bins[kMaxRingsFV0] = {0.0}; + for (int i = 0; i < kMaxRingsFV0; ++i) { + etaMaxFV0bins[i] = kEtaMaxFV0 - i * kDEtaFV0; + if (i < kMaxRingsFV0 - 1) { + etaMinFV0bins[i] = kEtaMaxFV0 - (i + 1) * kDEtaFV0; + } else { + etaMinFV0bins[i] = kEtaMinFV0; + } + } + + rhoLatticeFV0.fill(0); + std::vector vNch; + float nCharged{0}; + for (const auto& mcPart : mcparts) { + if (!isChrgParticle(mcPart.pdgCode())) { + continue; + } + auto etaMc = mcPart.eta(); + auto phiMc = mcPart.phi(); + + int isegment = 0; + for (int ieta = 0; ieta < kMaxRingsFV0; ieta++) { + + nFV0sectors = kNCellsFV0 / 6.; + if (ieta == kMaxRingsFV0 - 1) { + nFV0sectors = kNCellsFV0 / 3.; + } + + for (int iphi = 0; iphi < nFV0sectors; iphi++) { + + minPhi = iphi * TwoPI / nFV0sectors; + maxPhi = (iphi + 1) * TwoPI / nFV0sectors; + dPhi = std::abs(maxPhi - minPhi); + + if (etaMc >= etaMinFV0bins[ieta] && etaMc < etaMaxFV0bins[ieta] && phiMc >= minPhi && phiMc < maxPhi) { + rhoLatticeFV0[isegment] += 1. / std::abs(kDEtaFV0 * dPhi); + } + isegment++; + } + } + nCharged++; + } + + vNch.push_back(nCharged); + auto flatFV0 = calcFlatenicity(rhoLatticeFV0); + + if constexpr (fillHist) { + flatchrg.fill(HIST("ResponseGen"), vNch[0], 1. - flatFV0); + flatchrg.fill(HIST("h1flatencityFV0MCGen"), 1. - flatFV0); + } + vNch.clear(); + return 1. - flatFV0; + } + + template + void bookMcHist() + { + AxisSpec ptAxis{binOpt.axisPt, "#it{p}_{T} (GeV/#it{c})"}; + constexpr int kHistIdx = id + pidSgn * Npart; + auto kIdx = static_cast(id); + const std::string strID = Form("/%s/%s", (pidSgn == 0 && id < Npart) ? "pos" : "neg", Pid[kIdx]); + hPtEffRec[kHistIdx] = flatchrg.add("Tracks/hPtEffRec" + strID, " ; p_{T} (GeV/c)", HistType::kTH1F, {ptAxis}); + hPtEffGen[kHistIdx] = flatchrg.add("Tracks/hPtEffGen" + strID, " ; p_{T} (GeV/c)", HistType::kTH1F, {ptAxis}); + } + + template + void initEfficiency() + { + static_assert(pidSgn == 0 || pidSgn == 1); + static_assert(id > 0 || id < Npart); + constexpr int kIdx = id + pidSgn * Npart; + const TString partName = PidChrg[kIdx]; + THashList* lhash = new THashList(); + lhash->SetName(partName); + listEfficiency->Add(lhash); + + auto bookEff = [&](const TString eName, auto h) { + const TAxis* axis = h->GetXaxis(); + TString eTitle = h->GetTitle(); + eTitle.ReplaceAll("Numerator", "").Strip(TString::kBoth); + eTitle = Form("%s;%s;Efficiency", eTitle.Data(), axis->GetTitle()); + lhash->Add(new TEfficiency(eName, eTitle, axis->GetNbins(), axis->GetXbins()->GetArray())); + }; + + const int kHistIdx = id + pidSgn * Npart; + bookEff("hEffvsPt", hPtEffRec[kHistIdx]); + } + + template + void fillEfficiency() + { + static_assert(pidSgn == 0 || pidSgn == 1); + constexpr int kHistIdx = id + pidSgn * Npart; + const char* partName = PidChrg[kHistIdx]; + THashList* lhash = static_cast(listEfficiency->FindObject(partName)); + if (!lhash) { + LOG(warning) << "No efficiency object found for particle " << partName; + return; + } + + auto fillEff = [&](const TString eName, auto num, auto den) { + TEfficiency* eff = static_cast(lhash->FindObject(eName)); + if (!eff) { + LOG(warning) << "Cannot find TEfficiency " << eName; + return; + } + eff->SetTotalHistogram(*den, "f"); + eff->SetPassedHistogram(*num, "f"); + }; + fillEff("hEffvsPt", hPtEffRec[kHistIdx], hPtEffGen[kHistIdx]); + } + + template + void fillMCRecTrack(MyLabeledPIDTracks::iterator const& track, const float mult, const float flat) + { + static_assert(pidSgn == 0 || pidSgn == 1); + constexpr int kHistIdx = id + pidSgn * Npart; + const aod::McParticles::iterator& mcParticle = track.mcParticle(); + const CollsGen::iterator& collision = track.collision_as(); + + if (!isPID(mcParticle)) { + return; + } + flatchrg.fill(HIST("hPtOutNoEtaCut"), track.pt()); + if (std::abs(track.eta()) > trkSelOpt.cfgTrkEtaMax) { + return; + } + if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + return; + } + + if ((collision.has_mcCollision() && (mcParticle.mcCollisionId() != collision.mcCollisionId())) || !collision.has_mcCollision()) { + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == kProcessIdWeak) { + hDCAxyBadCollWeak[kHistIdx]->Fill(track.pt(), track.dcaXY()); + } else { + hDCAxyBadCollMat[kHistIdx]->Fill(track.pt(), track.dcaXY()); + } + } else { + hDCAxyBadCollPrim[kHistIdx]->Fill(track.pt(), track.dcaXY()); + } + } + + if (!isDCAxyCut(track)) { + return; + } + flatchrg.fill(HIST("hPtVsDCAxyAll"), track.pt(), track.dcaXY()); + + if (selTPCtrack(track)) { + hPtEffRec[kHistIdx]->Fill(mcParticle.pt()); + } + + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == kProcessIdWeak) { + hPtEffRecWeak[kHistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyWeak[kHistIdx]->Fill(track.pt(), track.dcaXY()); + flatchrg.fill(HIST("hPtVsDCAxyWeakAll"), track.pt(), track.dcaXY()); + } else { + hPtEffRecMat[kHistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyMat[kHistIdx]->Fill(track.pt(), track.dcaXY()); + flatchrg.fill(HIST("hPtVsDCAxyMatAll"), track.pt(), track.dcaXY()); + } + } else { + hPtEffRecPrim[kHistIdx]->Fill(mult, flat, track.pt()); + hPtVsDCAxyPrim[kHistIdx]->Fill(track.pt(), track.dcaXY()); + flatchrg.fill(HIST("hPtVsDCAxyPrimAll"), track.pt(), track.dcaXY()); + } + } + + template + void fillMCGen(aod::McParticles::iterator const& mcParticle, const float mult, const float flat) + { + static_assert(pidSgn == 0 || pidSgn == 1); + constexpr int kHistIdx = id + pidSgn * Npart; + + if (!isPID(mcParticle)) { + return; + } + + if constexpr (recoEvt) { + hPtGenRecEvt[kHistIdx]->Fill(mcParticle.pt()); + if (mcParticle.isPhysicalPrimary()) { + hPtGenPrimRecEvt[kHistIdx]->Fill(mcParticle.pt()); + } + return; + } + + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == kProcessIdWeak) { + hPtEffGenWeak[kHistIdx]->Fill(mult, flat, mcParticle.pt()); + } else { + hPtEffGenMat[kHistIdx]->Fill(mult, flat, mcParticle.pt()); + } + } else { + hPtEffGenPrim[kHistIdx]->Fill(mult, flat, mcParticle.pt()); + hPtEffGen[kHistIdx]->Fill(mcParticle.pt()); + } + } + + 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 kIdx = i.value; + if (particle.pdgCode() == PidSgn[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenPrimSgn), mult, flat, particle.pt()); + if (isINELgt0mc) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenPrimSgnINEL), 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 kIdx = i.value; + if (particle.pdgCode() == PidSgn[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtRecCollPrimSgn), mult, flat, particle.pt()); + if (nRecCollINELgt0) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtRecCollPrimSgnINEL), mult, flat, particle.pt()); + } + } + }); + } + } + + if (nRecCollINEL < 1) { + return; + } + // Evt loss num + flatchrg.fill(HIST("hEvtMcGenRecColl"), 0.5); + if (nRecCollINELgt0 > 0) { + 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 kIdx = i.value; + if (particle.pdgCode() == PidSgn[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenRecCollPrimSgn), mult, flat, particle.pt()); + if (nRecCollINELgt0) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpecies[kIdx]) + HIST(kPtGenRecCollPrimSgnINEL), 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(); + auto bc = coll.template bc_as(); + auto magField = (ccdbConf.cfgMagField == 0) ? getMagneticField(bc.timestamp()) : ccdbConf.cfgMagField; + + 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 kIdx = i.value; + if ((std::abs(o2::aod::pidutils::tpcNSigma(track)) < trkSelOpt.cfgNsigmaMax) && std::abs(track.rapidity(o2::track::PID::getMass(kIdx))) <= trkSelOpt.cfgRapMax) { + if (std::fabs(mcParticle.pdgCode()) == PDGs[kIdx]) { + flatchrg.fill(HIST(kPrefix) + HIST(kSpeciesAll[kIdx]) + HIST(kPtMCclosurePrim), 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, + MyLabeledPIDTracks const& tracks, + aod::McParticles const& mcparticles) + { + flatchrg.fill(HIST("hEvtGenRec"), 1.f, mcCollisions.size()); + flatchrg.fill(HIST("hEvtGenRec"), 2.f, collisions.size()); + + for (const auto& mcCollision : mcCollisions) { + if (mcCollision.isInelGt0()) { + flatchrg.fill(HIST("hEvtGenRec"), 3.f); + } + flatchrg.fill(HIST("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 + continue; + } + flatchrg.fill(HIST("hEvtMcGenColls"), 2); + for (const auto& collision : groupedColls) { + flatchrg.fill(HIST("hEvtMcGenColls"), 3); + if (!isGoodEvent(collision)) { + continue; + } + flatchrg.fill(HIST("hEvtMcGenColls"), 4); + const auto groupedTrks = tracks.sliceBy(perCollTrk, collision.globalIndex()); + for (const auto& track : groupedTrks) { + if (!isDCAxyWoCut(track)) { + continue; + } + if (!track.has_mcParticle()) { + flatchrg.fill(HIST("PtOutFakes"), track.pt()); + continue; + } + const auto& mcParticle = track.mcParticle(); + if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + if (!track.has_collision()) { + continue; + } + static_for<0, 1>([&](auto pidSgn) { + fillMCRecTrack(track, multMC, flatMC); + fillMCRecTrack(track, multMC, flatMC); + fillMCRecTrack(track, multMC, flatMC); + }); + } + + if (std::abs(mcCollision.posZ()) > evtSelOpt.cfgCutVtxZ) { + continue; + } + + if (evtSelOpt.cfgINELCut.value) { + if (!o2::pwglf::isINELgt0mc(groupedParts, pdg)) { + continue; + } + } + + for (const auto& particle : groupedParts) { + if (std::abs(particle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + static_for<0, 1>([&](auto pidSgn) { + fillMCGen(particle, multMC, flatMC); + fillMCGen(particle, multMC, flatMC); + fillMCGen(particle, multMC, flatMC); + }); + } + } // reco collisions + + if (evtSelOpt.cfgINELCut.value) { + if (!o2::pwglf::isINELgt0mc(groupedParts, pdg)) { + continue; + } + } + + for (const auto& mcParticle : groupedParts) { + if (std::abs(mcParticle.y()) > trkSelOpt.cfgRapMax) { + continue; + } + static_for<0, 1>([&](auto pidSgn) { + fillMCGen(mcParticle, multMC, flatMC); + fillMCGen(mcParticle, multMC, flatMC); + fillMCGen(mcParticle, multMC, flatMC); + }); + } + + static_for<0, 1>([&](auto pidSgn) { + fillEfficiency(); + fillEfficiency(); + fillEfficiency(); + }); + + } // gen collisions + } + PROCESS_SWITCH(FlattenictyPikp, processMC, "process MC", false); + + template + ObjType* getForTsOrRun(std::string const& fullPath, int64_t timestamp, int runNumber) + { + if (cfgUseCcdbForRun) { + return ccdb->getForRun(fullPath, runNumber); + } else { + return ccdb->getForTimeStamp(fullPath, timestamp); + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx index 7da02f51416..f0e6012d4a4 100644 --- a/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx +++ b/PWGLF/Tasks/GlobalEventProperties/uccZdc.cxx @@ -15,18 +15,6 @@ /// \author Omar Vazquez (omar.vazquez.rueda@cern.ch) /// \since January 29, 2025 -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include "Common/CCDB/EventSelectionParams.h" #include "Common/CCDB/TriggerAliases.h" #include "Common/Core/TrackSelection.h" @@ -34,6 +22,7 @@ #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/TrackSelectionTables.h" + #include "CommonConstants/MathConstants.h" #include "CommonConstants/ZDCConstants.h" #include "Framework/ASoAHelpers.h" // required for Filter op. @@ -44,7 +33,22 @@ #include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/GlobalTrackID.h" #include "ReconstructionDataFormats/Track.h" +#include + #include "TPDGCode.h" +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include using namespace std; using namespace o2; @@ -63,10 +67,43 @@ using SimCollisions = soa::Join; } // namespace o2::aod +static constexpr int kSizeBootStrapEnsemble{8}; + +std::array, kSizeBootStrapEnsemble> hPoisson{}; +std::array, kSizeBootStrapEnsemble> hNchVsT0M{}; +std::array, kSizeBootStrapEnsemble> hNchVsV0A{}; +std::array, kSizeBootStrapEnsemble> hNchVsZN{}; + +std::array, kSizeBootStrapEnsemble> pNchVsOneParCorrVsZN{}; +std::array, kSizeBootStrapEnsemble> pNchVsTwoParCorrVsZN{}; +std::array, kSizeBootStrapEnsemble> pNchVsThreeParCorrVsZN{}; + +std::array, kSizeBootStrapEnsemble> pNchVsOneParCorrVsT0M{}; +std::array, kSizeBootStrapEnsemble> pNchVsTwoParCorrVsT0M{}; +std::array, kSizeBootStrapEnsemble> pNchVsThreeParCorrVsT0M{}; + +std::array, kSizeBootStrapEnsemble> pNchVsOneParCorrVsV0A{}; +std::array, kSizeBootStrapEnsemble> pNchVsTwoParCorrVsV0A{}; +std::array, kSizeBootStrapEnsemble> pNchVsThreeParCorrVsV0A{}; + +std::array, kSizeBootStrapEnsemble> pOneParCorrVsNch{}; +std::array, kSizeBootStrapEnsemble> pTwoParCorrVsNch{}; +std::array, kSizeBootStrapEnsemble> pThreeParCorrVsNch{}; + +std::array, kSizeBootStrapEnsemble> hPoissonMC{}; +std::array, kSizeBootStrapEnsemble> hNchGen{}; +std::array, kSizeBootStrapEnsemble> hNch{}; + +std::array, kSizeBootStrapEnsemble> pOneParCorrVsNchGen{}; +std::array, kSizeBootStrapEnsemble> pTwoParCorrVsNchGen{}; +std::array, kSizeBootStrapEnsemble> pThreeParCorrVsNchGen{}; + struct UccZdc { static constexpr float kCollEnergy{2.68}; static constexpr float kZero{0.}; + static constexpr float kOne{1.}; + static constexpr float kMinCharge{3.f}; // Configurables Event Selection Configurable isNoCollInTimeRangeStrict{"isNoCollInTimeRangeStrict", true, "use isNoCollInTimeRangeStrict?"}; @@ -81,6 +118,11 @@ struct UccZdc { Configurable isZEMcut{"isZEMcut", true, "Use ZEM cut"}; Configurable useMidRapNchSel{"useMidRapNchSel", true, "Use mid-rapidit Nch selection"}; Configurable applyEff{"applyEff", true, "Apply track-by-track efficiency correction"}; + Configurable applyFD{"applyFD", false, "Apply track-by-track feed down correction"}; + Configurable correctNch{"correctNch", true, "Correct also Nch"}; + Configurable skipRecoColGTOne{"skipRecoColGTOne", true, "Remove collisions if reconstructed more than once"}; + Configurable detector4Calibration{"detector4Calibration", "T0M", "Detector for nSigma-Nch rejection"}; + Configurable detectorZDC{"detectorZDC", "ZN", "Detector for Cent. Selec. based on spectator neutrons"}; // Event selection Configurable posZcut{"posZcut", +10.0, "z-vertex position cut"}; @@ -102,31 +144,37 @@ struct UccZdc { Configurable maxEta{"maxEta", +0.8, "maximum eta"}; // Configurables, binning - Configurable nBinsITSTrack{"nBinsITSTrack", 2000, "N bins ITS tracks"}; - Configurable minITSTrack{"minITSTrack", 0., "Min ITS tracks"}; - Configurable maxITSTrack{"maxITSTrack", 6000., "Min ITS tracks"}; - Configurable maxAmpFV0{"maxAmpFV0", 2000, "Max FV0 amp"}; - Configurable nBinsAmpFT0{"nBinsAmpFT0", 100, "N bins FT0 amp"}; - Configurable nBinsAmpFT0Fine{"nBinsAmpFT0Fine", 1000, "N bins FT0 amp"}; - Configurable maxAmpFT0{"maxAmpFT0", 2500, "Max FT0 amp"}; - Configurable nBinsNch{"nBinsNch", 2501, "N bins Nch (|eta|<0.8)"}; - Configurable nBinsNchFine{"nBinsNchFine", 3000, "N bins Nch (|eta|<0.8)"}; Configurable minNch{"minNch", 0, "Min Nch (|eta|<0.8)"}; + Configurable minZN{"minZN", -0.5, "Min ZN signal"}; + Configurable minTdc{"minTdc", -15.0, "minimum TDC"}; + Configurable maxNch{"maxNch", 3000, "Max Nch (|eta|<0.8)"}; - Configurable nBinsZN{"nBinsZN", 400, "N bins ZN"}; - Configurable nBinsZP{"nBinsZP", 160, "N bins ZP"}; - Configurable minZN{"minZN", 0, "Min ZN signal"}; + Configurable maxITSTrack{"maxITSTrack", 6000., "Min ITS tracks"}; + Configurable maxAmpV0A{"maxAmpV0A", 2000, "Max FV0 amp"}; + Configurable maxAmpFT0{"maxAmpFT0", 2500, "Max FT0 amp"}; + Configurable maxAmpFT0A{"maxAmpFT0A", 200, "Max FT0 amp"}; + Configurable maxAmpFT0C{"maxAmpFT0C", 60, "Max FT0 amp"}; Configurable maxZN{"maxZN", 150, "Max ZN signal"}; Configurable maxZP{"maxZP", 60, "Max ZP signal"}; Configurable maxZEM{"maxZEM", 2200, "Max ZEM signal"}; - Configurable nBinsTDC{"nBinsTDC", 150, "nbinsTDC"}; - Configurable minTdc{"minTdc", -15.0, "minimum TDC"}; Configurable maxTdc{"maxTdc", 15.0, "maximum TDC"}; + + Configurable nBinsNch{"nBinsNch", 2501, "N bins Nch (|eta|<0.8)"}; + Configurable nBinsITSTrack{"nBinsITSTrack", 2000, "N bins ITS tracks"}; + Configurable nBinsAmpV0A{"nBinsAmpV0A", 100, "N bins V0A amp"}; + Configurable nBinsAmpFT0{"nBinsAmpFT0", 100, "N bins FT0 amp"}; + Configurable nBinsAmpFT0A{"nBinsAmpFT0A", 100, "N bins FT0A amp"}; + Configurable nBinsAmpFT0C{"nBinsAmpFT0C", 100, "N bins FT0C amp"}; + Configurable nBinsZN{"nBinsZN", 400, "N bins ZN"}; + Configurable nBinsZP{"nBinsZP", 160, "N bins ZP"}; + Configurable nBinsTDC{"nBinsTDC", 150, "nbinsTDC"}; + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12}, "pT binning"}; ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 10., 20., 30., 40., 50., 60., 70., 80., 90., 100.}, "T0C binning"}; // CCDB paths - Configurable paTH{"paTH", "Users/o/omvazque/TrackingEfficiency", "base path to the ccdb object"}; + Configurable paTHEff{"paTHEff", "Users/o/omvazque/MCcorrection/perTimeStamp/TrackingEff", "base path to the ccdb object"}; + Configurable paTHFD{"paTHFD", "Users/o/omvazque/MCcorrection/perTimeStamp/FeedDown", "base path to the ccdb object"}; Configurable paTHmeanNch{"paTHmeanNch", "Users/o/omvazque/FitMeanNch_9May2025", "base path to the ccdb object"}; Configurable paTHsigmaNch{"paTHsigmaNch", "Users/o/omvazque/FitSigmaNch_9May2025", "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"}; @@ -161,31 +209,49 @@ struct UccZdc { HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; Service ccdb; + struct Config { + TH2F* hEfficiency = nullptr; + TH2F* hFeedDown = nullptr; + bool correctionsLoaded = false; + } cfg; + + struct NchConfig { + TH1F* hMeanNch = nullptr; + TH1F* hSigmaNch = nullptr; + bool calibrationsLoaded = false; + } cfgNch; + void init(InitContext const&) { + const char* tiT0A{"T0A (#times 1/100, 3.5 < #eta < 4.9)"}; + const char* tiT0C{"T0C (#times 1/100, -3.3 < #eta < -2.1)"}; + const char* tiT0M{"T0A+T0C (#times 1/100, -3.3 < #eta < -2.1 and 3.5 < #eta < 4.9)"}; + const char* tiNch{"#it{N}_{ch} (|#eta| < 0.8)"}; + const char* tiV0A{"V0A (#times 1/100, 2.2 < #eta < 5)"}; + const char* tiZNs{"ZNA + ZNC"}; + const char* tiZPs{"ZPA + ZPC"}; + const char* tiPt{"#it{p}_{T} (GeV/#it{c})"}; + const char* tiOneParCorr{"#LT[#it{p}_{T}^{(1)}]#GT (GeV/#it{c})"}; + const char* tiTwoParCorr{"Two-Particle #it{p}_{T} correlation"}; + const char* tiThreeParCorr{"Three-Particle #it{p}_{T} correlation"}; + // define axes you want to use const AxisSpec axisZpos{48, -12., 12., "Vtx_{z} (cm)"}; const AxisSpec axisEvent{18, 0.5, 18.5, ""}; - const AxisSpec axisEta{30, -1.05, +1.05, "#eta"}; + const AxisSpec axisEta{40, -1., +1., "#eta"}; const AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec axisDeltaPt{100, -1.0, +1.0, "#Delta(p_{T})"}; const AxisSpec axisCent{binsCent, "T0C centrality"}; const AxisSpec axisAmpCh{250, 0., 2500., "Amplitude of non-zero channels"}; const AxisSpec axisEneCh{300, 0., 300., "Energy of non-zero channels"}; - registry.add("zPos", ";;Entries;", kTH1F, {axisZpos}); - registry.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); - registry.add("NchUncorrected", ";#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{300, 0., 3000.}}); + registry.add("NchUncorrected", Form(";%s;Entries;", tiNch), kTH1F, {{nBinsNch, minNch, maxNch}}); registry.add("hEventCounter", ";;Events", kTH1F, {axisEvent}); - registry.add("ZNamp", ";ZNA+ZNC;Entries;", kTH1F, {{nBinsZN, -0.5, maxZN}}); - registry.add("ExcludedEvtVsFT0M", ";T0A+T0C (#times 1/100, -3.3 < #eta < -2.1 and 3.5 < #eta < 4.9);Entries;", kTH1F, {{nBinsAmpFT0, 0., maxAmpFT0}}); - registry.add("ExcludedEvtVsNch", ";#it{N}_{ch} (|#eta|<0.8);Entries;", kTH1F, {{300, 0, 3000}}); - registry.add("Nch", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);", kTH1F, {{nBinsNch, minNch, maxNch}}); - registry.add("NchVsOneParCorr", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(1)}]#GT (GeV/#it{c})", kTProfile, {{nBinsNch, minNch, maxNch}}); - registry.add("EtaVsPhi", ";#eta;#varphi", kTH2F, {{{axisEta}, {100, -0.1 * PI, +2.1 * PI}}}); - registry.add("ZposVsEta", "", kTProfile, {axisZpos}); - registry.add("sigma1Pt", ";;#sigma(p_{T})/p_{T};", kTProfile, {axisPt}); - registry.add("dcaXYvspT", ";DCA_{xy} (cm);;", kTH2F, {{{50, -1., 1.}, {axisPt}}}); + registry.add("ExcludedEvtVsFT0M", Form(";%s;Entries;", tiT0M), kTH1F, {{nBinsAmpFT0, 0., maxAmpFT0}}); + registry.add("ExcludedEvtVsFV0A", Form(";%s;Entries;", tiT0M), kTH1F, {{nBinsAmpV0A, 0., maxAmpV0A}}); + registry.add("ExcludedEvtVsNch", Form(";%s;Entries;", tiNch), kTH1F, {{nBinsNch, minNch, maxNch}}); + registry.add("Nch", Form(";%s;Entries;", tiNch), kTH1F, {{nBinsNch, minNch, maxNch}}); + registry.add("NchVsOneParCorr", Form(";%s;%s;", tiNch, tiOneParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); auto hstat = registry.get(HIST("hEventCounter")); auto* x = hstat->GetXaxis(); @@ -208,20 +274,51 @@ struct UccZdc { x->SetBinLabel(17, "Within ZEM cut?"); if (doprocessZdcCollAss) { - registry.add("NchVsZN", ";#it{N}_{ch} (|#eta| < 0.8); ZNA+ZNC;", kTH2F, {{{nBinsNchFine, minNch, maxNch}, {nBinsZN, -0.5, maxZN}}}); - registry.add("NchVsZP", ";#it{N}_{ch} (|#eta| < 0.8); ZPA+ZPC;", kTH2F, {{{nBinsNchFine, minNch, maxNch}, {nBinsZP, -0.5, maxZP}}}); - registry.add("NITSTacksVsZN", ";ITS tracks; ZNA+ZNC;", kTH2F, {{{nBinsITSTrack, minITSTrack, maxITSTrack}, {nBinsZN, -0.5, maxZN}}}); - registry.add("NITSTacksVsZP", ";ITS tracks; ZPA+ZPC;", kTH2F, {{{nBinsITSTrack, minITSTrack, maxITSTrack}, {nBinsZP, -0.5, maxZP}}}); - registry.add("T0MVsZN", ";T0A+T0C amp (#times 1/100); ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0Fine, 0., maxAmpFT0}, {nBinsZN, -0.5, maxZN}}}); - registry.add("T0MVsZP", ";T0A+T0C amp (#times 1/100); ZPA+ZPC;", kTH2F, {{{nBinsAmpFT0Fine, 0., maxAmpFT0}, {nBinsZP, -0.5, maxZP}}}); - registry.add("NchVsZNVsPt", ";#it{N}_{ch} (|#eta| < 0.8); ZNA+ZNC;#it{p}_{T} (GeV/#it{c})", kTH3F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, -0.5, maxZN}, {axisPt}}}); - registry.add("NchVsOneParCorrVsZN", ";#it{N}_{ch} (|#eta| < 0.8, Corrected); ZNA+ZNC; #LT[#it{p}_{T}^{(1)}]#G (GeV/#it{c})T", kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, -0.5, maxZN}}}); - registry.add("NchVsTwoParCorrVsZN", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);ZNA+ZNC;#LT[#it{p}_{T}^{(2)}]#GT", kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, -0.5, maxZN}}}); - registry.add("NchVsThreeParCorrVsZN", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);ZNA+ZNC;#LT[#it{p}_{T}^{(3)}]#GT", kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, -0.5, maxZN}}}); - registry.add("NchVsFourParCorrVsZN", ";#it{N}_{ch} (|#eta| < 0.8, Corrected);ZNA+ZNC;#LT[#it{p}_{T}^{(4)}]#GT", kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, -0.5, maxZN}}}); + registry.add("NchVsT0M", Form(";%s;%s;", tiNch, tiT0M), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + registry.add("NchVsV0A", Form(";%s;%s;", tiNch, tiV0A), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + registry.add("NchVsZN", Form(";%s;%s;", tiNch, tiZNs), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + registry.add("NchVsZP", Form(";%s;%s;", tiNch, tiZPs), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZP, minZN, maxZP}}}); + registry.add("NchVsZNVsPt", Form(";%s;%s;%s", tiNch, tiZNs, tiPt), kTH3F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}, {axisPt}}}); + + registry.add("NchVsOneParCorrVsZN", Form(";%s;%s;%s", tiNch, tiZNs, tiOneParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + registry.add("NchVsTwoParCorrVsZN", Form(";%s;%s;%s", tiNch, tiZNs, tiTwoParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + registry.add("NchVsThreeParCorrVsZN", Form(";%s;%s;%s", tiNch, tiZNs, tiThreeParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + + registry.add("NchVsOneParCorrVsT0M", Form(";%s;%s;%s", tiNch, tiT0M, tiOneParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + registry.add("NchVsTwoParCorrVsT0M", Form(";%s;%s;%s", tiNch, tiT0M, tiTwoParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + registry.add("NchVsThreeParCorrVsT0M", Form(";%s;%s;%s", tiNch, tiT0M, tiThreeParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + + registry.add("NchVsOneParCorrVsV0A", Form(";%s;%s;%s", tiNch, tiV0A, tiOneParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + registry.add("NchVsTwoParCorrVsV0A", Form(";%s;%s;%s", tiNch, tiV0A, tiTwoParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + registry.add("NchVsThreeParCorrVsV0A", Form(";%s;%s;%s", tiNch, tiV0A, tiThreeParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + + for (int i = 0; i < kSizeBootStrapEnsemble; i++) { + hNchVsZN[i] = registry.add(Form("NchVsZN_Rep%d", i), Form(";%s;%s", tiNch, tiZNs), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + hNchVsV0A[i] = registry.add(Form("NchVsV0A_Rep%d", i), Form(";%s;%s", tiNch, tiV0A), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + hNchVsT0M[i] = registry.add(Form("NchVsT0M_Rep%d", i), Form(";%s;%s", tiNch, tiT0M), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + hPoisson[i] = registry.add(Form("Poisson_Rep%d", i), ";#it{k};Entries", kTH1F, {{11, -0.5, 10.5}}); + + pNchVsOneParCorrVsZN[i] = registry.add(Form("NchVsOneParCorrVsZN_Rep%d", i), Form(";%s;%s;%s", tiNch, tiZNs, tiOneParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + pNchVsTwoParCorrVsZN[i] = registry.add(Form("NchVsTwoParCorrVsZN_Rep%d", i), Form(";%s;%s;%s", tiNch, tiZNs, tiTwoParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + pNchVsThreeParCorrVsZN[i] = registry.add(Form("NchVsThreeParCorrVsZN_Rep%d", i), Form(";%s;%s;%s", tiNch, tiZNs, tiThreeParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + + pNchVsOneParCorrVsT0M[i] = registry.add(Form("NchVsOneParCorrVsT0M_Rep%d", i), Form(";%s;%s;%s", tiNch, tiT0M, tiOneParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + pNchVsTwoParCorrVsT0M[i] = registry.add(Form("NchVsTwoParCorrVsT0M_Rep%d", i), Form(";%s;%s;%s", tiNch, tiT0M, tiTwoParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + pNchVsThreeParCorrVsT0M[i] = registry.add(Form("NchVsThreeParCorrVsT0M_Rep%d", i), Form(";%s;%s;%s", tiNch, tiT0M, tiThreeParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpFT0, 0., maxAmpFT0}}}); + + pNchVsOneParCorrVsV0A[i] = registry.add(Form("NchVsOneParCorrVsV0A_Rep%d", i), Form(";%s;%s;%s", tiNch, tiV0A, tiOneParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + pNchVsTwoParCorrVsV0A[i] = registry.add(Form("NchVsTwoParCorrVsV0A_Rep%d", i), Form(";%s;%s;%s", tiNch, tiV0A, tiTwoParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + pNchVsThreeParCorrVsV0A[i] = registry.add(Form("NchVsThreeParCorrVsV0A_Rep%d", i), Form(";%s;%s;%s", tiNch, tiV0A, tiThreeParCorr), kTProfile2D, {{{nBinsNch, minNch, maxNch}, {nBinsAmpV0A, 0., maxAmpV0A}}}); + } } if (doprocessMCclosure) { + registry.add("zPos", ";;Entries;", kTH1F, {axisZpos}); + registry.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); + registry.add("EtaVsPhi", ";#eta;#varphi", kTH2F, {{{axisEta}, {100, -0.1 * PI, +2.1 * PI}}}); + registry.add("ZposVsEta", "", kTProfile, {axisZpos}); + registry.add("sigma1Pt", ";;#sigma(p_{T})/p_{T};", kTProfile, {axisPt}); + registry.add("dcaXYvspT", ";DCA_{xy} (cm);;", kTH2F, {{{50, -1., 1.}, {axisPt}}}); registry.add("RandomNumber", "", kTH1F, {{50, 0., 1.}}); registry.add("EvtsDivided", ";Event type;Entries;", kTH1F, {{2, -0.5, 1.5}}); auto hEvtsDiv = registry.get(HIST("EvtsDivided")); @@ -229,71 +326,96 @@ struct UccZdc { xEvtsDiv->SetBinLabel(1, "MC closure"); xEvtsDiv->SetBinLabel(2, "Corrections"); // MC closure - registry.add("NchGen", "MC closure;#it{N}_{ch} (|#eta| < 0.8);Entries;", kTH1F, {{nBinsNch, minNch, maxNch}}); - registry.add("NchvsOneParCorrGen", "MC closure;#it{N}_{ch} (|#eta| < 0.8);#LT[#it{p}_{T}^{(1)}]#GT (GeV/#it{c})", kTProfile, {{nBinsNch, minNch, maxNch}}); - registry.add("NchvsTwoParCorrGen", "MC closure;#it{N}_{ch} (|#eta| < 0.8);#LT[#it{p}_{T}^{(2)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); - registry.add("NchvsThreeParCorrGen", "MC closure;#it{N}_{ch} (|#eta| < 0.8);#LT[#it{p}_{T}^{(3)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); - registry.add("NchvsFourParCorrGen", "MC closure;#it{N}_{ch} (|#eta| < 0.8);#LT[#it{p}_{T}^{(4)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); - registry.add("NchVsTwoParCorr", "MC closure;#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(2)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); - registry.add("NchVsThreeParCorr", "MC closure;#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(3)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); - registry.add("NchVsFourParCorr", "MC closure;#it{N}_{ch} (|#eta| < 0.8, Corrected);#LT[#it{p}_{T}^{(4)}]#GT", kTProfile, {{nBinsNch, minNch, maxNch}}); + registry.add("NchGen", Form("MC Closure;%s;Entries", tiNch), kTH1F, {{nBinsNch, minNch, maxNch}}); + registry.add("NchvsOneParCorrGen", Form("MC Closure;%s;%s", tiNch, tiOneParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + registry.add("NchvsTwoParCorrGen", Form("MC Closure;%s;%s", tiNch, tiTwoParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + registry.add("NchvsThreeParCorrGen", Form("MC Closure;%s;%s", tiNch, tiThreeParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + registry.add("NchVsTwoParCorr", Form("MC Closure;%s;%s", tiNch, tiTwoParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + registry.add("NchVsThreeParCorr", Form("MC Closure;%s;%s", tiNch, tiThreeParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); // Corrections registry.add("zPosMC", "Filled at MC closure + Corrections;;Entries;", kTH1F, {axisZpos}); registry.add("hEventCounterMC", "Event counter", kTH1F, {axisEvent}); registry.add("nRecColvsCent", "", kTH2F, {{6, -0.5, 5.5}, {{axisCent}}}); - registry.add("Pt_all_ch", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_ch", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_pi", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_ka", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_pr", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_sigpos", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_signeg", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("Pt_re", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_ch", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_pi", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_ka", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_pr", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_sigpos", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_signeg", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); - registry.add("PtMC_re", "Corrections;;;", kTH2F, {{axisCent}, {axisPt}}); + registry.add("Pt_all_ch", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_ch", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_pi", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_ka", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_pr", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_sigpos", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_signeg", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("Pt_re", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_ch", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_pi", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_ka", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_pr", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_sigpos", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_signeg", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("PtMC_re", Form("Corrections;%s;%s", tiNch, tiPt), kTH2F, {{nBinsNch, minNch, maxNch}, {axisPt}}); + registry.add("McNchVsFT0M", Form("Corrections;%s;%s", tiT0M, tiNch), kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsNch, minNch, maxNch}}}); auto hECMC = registry.get(HIST("hEventCounterMC")); auto* x = hECMC->GetXaxis(); x->SetBinLabel(1, "All"); x->SetBinLabel(13, "VtxZ cut"); - } + for (int i = 0; i < kSizeBootStrapEnsemble; i++) { + + hPoissonMC[i] = registry.add(Form("PoissonMC_Rep%d", i), ";#it{k};Entries", kTH1F, {{11, -0.5, 10.5}}); + hNchGen[i] = registry.add(Form("NchGen_Rep%d", i), Form(";%s;Entries", tiNch), kTH1F, {{nBinsNch, minNch, maxNch}}); + pOneParCorrVsNchGen[i] = registry.add(Form("OneParCorrVsNchGen_Rep%d", i), Form(";%s;%s;", tiNch, tiOneParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + pTwoParCorrVsNchGen[i] = registry.add(Form("TwoParCorrVsNchGen_Rep%d", i), Form(";%s;%s;", tiNch, tiTwoParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + pThreeParCorrVsNchGen[i] = registry.add(Form("ThreeParCorrVsNchGen_Rep%d", i), Form(";%s;%s;", tiNch, tiThreeParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + + hNch[i] = registry.add(Form("Nch_Rep%d", i), Form(";%s;Entries", tiNch), kTH1F, {{nBinsNch, minNch, maxNch}}); + hPoisson[i] = registry.add(Form("Poisson_Rep%d", i), ";#it{k};Entries", kTH1F, {{11, -0.5, 10.5}}); + + pOneParCorrVsNch[i] = registry.add(Form("OneParCorrVsNch_Rep%d", i), Form(";%s;%s;", tiNch, tiOneParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + pTwoParCorrVsNch[i] = registry.add(Form("TwoParCorrVsNch_Rep%d", i), Form(";%s;%s;", tiNch, tiTwoParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + pThreeParCorrVsNch[i] = registry.add(Form("ThreeParCorrVsNch_Rep%d", i), Form(";%s;%s;", tiNch, tiTwoParCorr), kTProfile, {{nBinsNch, minNch, maxNch}}); + } + } if (doprocessQA) { + registry.add("zPos", ";;Entries;", kTH1F, {axisZpos}); + registry.add("T0Ccent", ";;Entries", kTH1F, {axisCent}); + registry.add("EtaVsPhi", ";#eta;#varphi", kTH2F, {{{axisEta}, {100, -0.1 * PI, +2.1 * PI}}}); + registry.add("ZposVsEta", "", kTProfile, {axisZpos}); + registry.add("sigma1Pt", ";;#sigma(p_{T})/p_{T};", kTProfile, {axisPt}); + registry.add("dcaXYvspT", ";DCA_{xy} (cm);;", kTH2F, {{{50, -1., 1.}, {axisPt}}}); registry.add("Debunch", ";t_{ZDC}-t_{ZDA};t_{ZDC}+t_{ZDA}", kTH2F, {{{nBinsTDC, minTdc, maxTdc}, {nBinsTDC, minTdc, maxTdc}}}); - registry.add("NchVsFT0M", ";T0A+T0C (#times 1/100, -3.3 < #eta < -2.1 and 3.5 < #eta < 4.9);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsNch, minNch, maxNch}}}); - registry.add("NchVsFT0A", ";T0A (#times 1/100, 3.5 < #eta < 4.9);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{80, 0., 1800.}, {nBinsNch, minNch, maxNch}}}); - registry.add("NchVsFT0C", ";T0C (#times 1/100, -3.3 < #eta < -2.1);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{80, 0., 600.}, {nBinsNch, minNch, maxNch}}}); - registry.add("NchVsFV0A", ";V0A (#times 1/100, 2.2 < #eta < 5);#it{N}_{ch} (|#eta|<0.8);", kTH2F, {{{80, 0., maxAmpFV0}, {nBinsNch, minNch, maxNch}}}); - registry.add("NchVsEt", ";#it{E}_{T} (|#eta|<0.8);#LTITS+TPC tracks#GT (|#eta|<0.8);", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsNch, minNch, maxNch}}}); - registry.add("NchVsNPV", ";#it{N}_{PV} (|#eta|<1);ITS+TPC tracks (|#eta|<0.8);", kTH2F, {{{300, -0.5, 5999.5}, {nBinsNch, minNch, maxNch}}}); - registry.add("NchVsITStracks", ";ITS tracks nCls >= 5;TITS+TPC tracks (|#eta|<0.8);", kTH2F, {{{300, -0.5, 5999.5}, {nBinsNch, minNch, maxNch}}}); - registry.add("ZNVsFT0A", ";T0A (#times 1/100);ZNA+ZNC;", kTH2F, {{{80, 0., 1800.}, {nBinsZN, -0.5, maxZN}}}); - registry.add("ZNVsFT0C", ";T0C (#times 1/100);ZNA+ZNC;", kTH2F, {{{80, 0., 600.}, {nBinsZN, -0.5, maxZN}}}); - registry.add("ZNVsFT0M", ";T0A+T0C (#times 1/100);ZNA+ZNC;", kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZN, -0.5, maxZN}}}); - registry.add("ZNAamp", ";ZNA;Entries;", kTH1F, {{nBinsZN, -0.5, maxZN}}); - registry.add("ZPAamp", ";ZPA;Entries;", kTH1F, {{nBinsZP, -0.5, maxZP}}); - registry.add("ZNCamp", ";ZNC;Entries;", kTH1F, {{nBinsZN, -0.5, maxZN}}); - registry.add("ZPCamp", ";ZPC;Entries;", kTH1F, {{nBinsZP, -0.5, maxZP}}); - registry.add("ZNAVsZNC", ";ZNC;ZNA", kTH2F, {{{30, -0.5, maxZN}, {30, -0.5, maxZN}}}); - registry.add("ZPAVsZPC", ";ZPC;ZPA;", kTH2F, {{{100, -0.5, maxZP}, {100, -0.5, maxZP}}}); - registry.add("ZNAVsZPA", ";ZPA;ZNA;", kTH2F, {{{20, -0.5, maxZP}, {30, -0.5, maxZN}}}); - registry.add("ZNCVsZPC", ";ZPC;ZNC;", kTH2F, {{{20, -0.5, maxZP}, {30, -0.5, maxZN}}}); - registry.add("ZNVsZEM", ";ZEM;ZNA+ZNC;", kTH2F, {{{60, -0.5, maxZEM}, {60, -0.5, maxZN}}}); - registry.add("ZNCVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); - registry.add("ZNAVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); - registry.add("ZNVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA+ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); - registry.add("ZNDifVsNch", ";#it{N}_{ch} (|#eta|<0.8);ZNA-ZNC;", kTH2F, {{{nBinsNch, minNch, maxNch}, {100, -50., 50.}}}); + registry.add("NchVsFT0M", Form(";%s;%s;", tiT0M, tiNch), kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsNch, minNch, maxNch}}}); + registry.add("NchVsFT0A", Form(";%s;%s;", tiT0A, tiNch), kTH2F, {{{nBinsAmpFT0A, 0., maxAmpFT0A}, {nBinsNch, minNch, maxNch}}}); + registry.add("NchVsFT0C", Form(";%s;%s;", tiT0C, tiNch), kTH2F, {{{nBinsAmpFT0C, 0., maxAmpFT0C}, {nBinsNch, minNch, maxNch}}}); + registry.add("NchVsFV0A", Form(";%s;%s;", tiV0A, tiNch), kTH2F, {{{nBinsAmpV0A, 0., maxAmpV0A}, {nBinsNch, minNch, maxNch}}}); + registry.add("NchVsNPV", ";#it{N}_{PV} (|#eta|<1);ITS+TPC tracks (|#eta|<0.8);", kTH2F, {{{nBinsITSTrack, 0, maxITSTrack}, {nBinsNch, minNch, maxNch}}}); + registry.add("NchVsITStracks", ";ITS trks (|#eta|<0.8);TITS+TPC tracks (|#eta|<0.8);", kTH2F, {{{nBinsITSTrack, 0, maxITSTrack}, {nBinsNch, minNch, maxNch}}}); + registry.add("ZNVsFT0A", Form(";%s;%s;", tiT0A, tiZNs), kTH2F, {{{nBinsAmpFT0A, 0., maxAmpFT0A}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNVsFT0C", Form(";%s;%s;", tiT0C, tiZNs), kTH2F, {{{nBinsAmpFT0C, 0., maxAmpFT0C}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNVsFT0M", Form(";%s;%s;", tiT0M, tiZNs), kTH2F, {{{nBinsAmpFT0, 0., maxAmpFT0}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNAamp", ";ZNA;Entries;", kTH1F, {{nBinsZN, minZN, maxZN}}); + registry.add("ZPAamp", ";ZPA;Entries;", kTH1F, {{nBinsZP, minZN, maxZP}}); + registry.add("ZNCamp", ";ZNC;Entries;", kTH1F, {{nBinsZN, minZN, maxZN}}); + registry.add("ZPCamp", ";ZPC;Entries;", kTH1F, {{nBinsZP, minZN, maxZP}}); + registry.add("ZNAVsZNC", ";ZNC;ZNA", kTH2F, {{{nBinsZN, minZN, maxZN}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZPAVsZPC", ";ZPC;ZPA;", kTH2F, {{{nBinsZP, minZN, maxZP}, {nBinsZP, minZN, maxZP}}}); + registry.add("ZNAVsZPA", ";ZPA;ZNA;", kTH2F, {{{nBinsZP, minZN, maxZP}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNCVsZPC", ";ZPC;ZNC;", kTH2F, {{{nBinsZP, minZN, maxZP}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNVsZEM", ";ZEM;ZNA+ZNC;", kTH2F, {{{nBinsZN, minZN, maxZEM}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNCVsNch", Form(";%s;ZNC;", tiNch), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNAVsNch", Form(";%s;ZNA;", tiNch), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNVsNch", Form(";%s;%s;", tiNch, tiZNs), kTH2F, {{{nBinsNch, minNch, maxNch}, {nBinsZN, minZN, maxZN}}}); + registry.add("ZNDifVsNch", Form(";%s;ZNA-ZNC;", tiNch), kTH2F, {{{nBinsNch, minNch, maxNch}, {100, -50., 50.}}}); } LOG(info) << "\tccdbNoLaterThan=" << ccdbNoLaterThan.value; LOG(info) << "\tapplyEff=" << applyEff.value; - LOG(info) << "\tpaTH=" << paTH.value; + LOG(info) << "\tapplyFD=" << applyFD.value; + LOG(info) << "\tcorrectNch=" << correctNch.value; + LOG(info) << "\tpaTHEff=" << paTHEff.value; + LOG(info) << "\tpaTHFD=" << paTHFD.value; + LOG(info) << "\tdetectorZDC=" << detectorZDC.value; LOG(info) << "\tuseMidRapNchSel=" << useMidRapNchSel.value; + LOG(info) << "\tdetector4Calibration=" << detector4Calibration.value; + LOG(info) << "\tnSigmaNchCut=" << nSigmaNchCut.value; LOG(info) << "\tpaTHmeanNch=" << paTHmeanNch.value; LOG(info) << "\tpaTHsigmaNch=" << paTHsigmaNch.value; LOG(info) << "\tminPt=" << minPt.value; @@ -301,12 +423,9 @@ struct UccZdc { LOG(info) << "\tmaxPtSpectra=" << maxPtSpectra.value; ccdb->setURL("http://alice-ccdb.cern.ch"); - // Enabling object caching, otherwise each call goes to the CCDB server ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - // 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); } @@ -393,7 +512,6 @@ struct UccZdc { return true; } - void processQA(o2::aod::ColEvSels::iterator const& collision, o2::aod::BCsRun3 const& /**/, aod::Zdcs const& /**/, aod::FV0As const& /**/, aod::FT0s const& /**/, TheFilteredTracks const& tracks) { // LOG(info) << " Collisions size: " << collisions.size() << " Table's size: " << collisions.tableSize() << "\n"; @@ -410,7 +528,8 @@ struct UccZdc { registry.fill(HIST("hEventCounter"), EvCutLabel::Zdc); auto zdc = foundBC.zdc(); - float aT0A = 0., aT0C = 0., aV0A = 0.; + double aT0A{-999.}; + double aT0C{-999.}; if (foundBC.has_ft0()) { for (const auto& amplitude : foundBC.ft0().amplitudeA()) { aT0A += amplitude; @@ -423,15 +542,17 @@ struct UccZdc { } registry.fill(HIST("hEventCounter"), EvCutLabel::TZero); + double aV0A{-999.}; if (foundBC.has_fv0a()) { for (const auto& amplitude : foundBC.fv0a().amplitude()) { aV0A += amplitude; } - } else { - aV0A = -999.; } const double normT0M{(aT0A + aT0C) / 100.}; + const double normV0A{aV0A / 100.}; + const double normT0A{aT0A / 100.}; + const double normT0C{aT0C / 100.}; float znA{zdc.amplitudeZNA()}; float znC{zdc.amplitudeZNC()}; float zpA{zdc.amplitudeZPA()}; @@ -450,7 +571,6 @@ struct UccZdc { zpC /= kCollEnergy; float sumZNs{znA + znC}; float sumZEMs{aZEM1 + aZEM2}; - // TDC cut if (isTDCcut) { if (std::sqrt(std::pow(tZDCdif, 2.) + std::pow(tZDCsum, 2.)) > tdcCut) { @@ -469,7 +589,7 @@ struct UccZdc { int itsTracks = 0, glbTracks = 0; for (const auto& track : tracks) { - if (track.hasITS()) { + if (track.hasITS() && ((track.eta() > minEta) && (track.eta() < maxEta))) { itsTracks++; } // Track Selection @@ -479,41 +599,46 @@ struct UccZdc { if ((track.pt() < minPt) || (track.pt() > maxPt)) { continue; } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } 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!"); + loadNchCalibrations(foundBC.timestamp()); + if (!(cfgNch.hMeanNch && cfgNch.hSigmaNch)) return; + + TString s1 = TString(detector4Calibration.value); + double xEval{1.}; + if (s1 == "T0M") { + xEval = normT0M; } - if (!hSigmaNch) { - LOGF(info, "hSigmaNch NOT LOADED!"); - return; + if (s1 == "V0A") { + xEval = normV0A; } - const int binT0M{hMeanNch->FindBin(normT0M)}; - const double meanNch{hMeanNch->GetBinContent(binT0M)}; - const double sigmaNch{hSigmaNch->GetBinContent(binT0M)}; + const int bin4Calibration{cfgNch.hMeanNch->FindBin(xEval)}; + const double meanNch{cfgNch.hMeanNch->GetBinContent(bin4Calibration)}; + const double sigmaNch{cfgNch.hSigmaNch->GetBinContent(bin4Calibration)}; const double nSigmaSelection{nSigmaNchCut * sigmaNch}; const double diffMeanNch{meanNch - glbTracks}; - if (!(std::abs(diffMeanNch) < nSigmaSelection)) { + if (std::abs(diffMeanNch) > nSigmaSelection) { registry.fill(HIST("ExcludedEvtVsFT0M"), normT0M); + registry.fill(HIST("ExcludedEvtVsFV0A"), normV0A); registry.fill(HIST("ExcludedEvtVsNch"), glbTracks); - } else { skipEvent = true; } } - if (!skipEvent) { + if (useMidRapNchSel && skipEvent) { return; } - float et = 0., meanpt = 0.; + double meanpt{0.}; for (const auto& track : tracks) { // Track Selection if (!track.isGlobalTrack()) { @@ -522,12 +647,14 @@ struct UccZdc { if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { continue; } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } registry.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); registry.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); registry.fill(HIST("sigma1Pt"), track.pt(), track.sigma1Pt()); registry.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); - et += std::sqrt(std::pow(track.pt(), 2.) + std::pow(o2::constants::physics::MassPionCharged, 2.)); meanpt += track.pt(); } @@ -537,35 +664,31 @@ struct UccZdc { registry.fill(HIST("ZNCamp"), znC); registry.fill(HIST("ZPAamp"), zpA); registry.fill(HIST("ZPCamp"), zpC); - registry.fill(HIST("ZNamp"), sumZNs); registry.fill(HIST("ZNAVsZNC"), znC, znA); registry.fill(HIST("ZNAVsZPA"), zpA, znA); registry.fill(HIST("ZNCVsZPC"), zpC, znC); registry.fill(HIST("ZPAVsZPC"), zpC, zpA); registry.fill(HIST("ZNVsZEM"), sumZEMs, sumZNs); registry.fill(HIST("Debunch"), tZDCdif, tZDCsum); - registry.fill(HIST("ZNVsFT0A"), aT0A / 100., sumZNs); - registry.fill(HIST("ZNVsFT0C"), aT0C / 100., sumZNs); + registry.fill(HIST("ZNVsFT0A"), normT0A, sumZNs); + registry.fill(HIST("ZNVsFT0C"), normT0C, sumZNs); registry.fill(HIST("ZNVsFT0M"), normT0M, sumZNs); - registry.fill(HIST("NchVsFV0A"), aV0A / 100., glbTracks); - registry.fill(HIST("NchVsFT0A"), aT0A / 100., glbTracks); - registry.fill(HIST("NchVsFT0C"), aT0C / 100., glbTracks); + registry.fill(HIST("NchVsFV0A"), normV0A, glbTracks); + registry.fill(HIST("NchVsFT0A"), normT0A, glbTracks); + registry.fill(HIST("NchVsFT0C"), normT0C, glbTracks); registry.fill(HIST("NchVsFT0M"), normT0M, glbTracks); registry.fill(HIST("NchUncorrected"), glbTracks); registry.fill(HIST("Nch"), glbTracks); - registry.fill(HIST("NchVsEt"), et, glbTracks); registry.fill(HIST("NchVsNPV"), collision.multNTracksPVeta1(), glbTracks); registry.fill(HIST("NchVsITStracks"), itsTracks, glbTracks); registry.fill(HIST("ZNAVsNch"), glbTracks, znA); registry.fill(HIST("ZNCVsNch"), glbTracks, znC); registry.fill(HIST("ZNVsNch"), glbTracks, sumZNs); registry.fill(HIST("ZNDifVsNch"), glbTracks, znA - znC); - if (glbTracks >= minNchSel) { + if (glbTracks >= minNchSel) registry.fill(HIST("NchVsOneParCorr"), glbTracks, meanpt / glbTracks); - } } PROCESS_SWITCH(UccZdc, processQA, "Process QA", true); - void processZdcCollAss(o2::aod::ColEvSels::iterator const& collision, o2::aod::BCsRun3 const& /*bcs*/, aod::Zdcs const& /*zdcs*/, aod::FV0As const& /*fv0as*/, aod::FT0s const& /*ft0s*/, TheFilteredTracks const& tracks) { if (!isEventSelected(collision)) { @@ -581,7 +704,8 @@ struct UccZdc { } registry.fill(HIST("hEventCounter"), EvCutLabel::Zdc); - float aT0A = 0., aT0C = 0.; + double aT0A{-999.}; + double aT0C{-999.}; if (foundBC.has_ft0()) { for (const auto& amplitude : foundBC.ft0().amplitudeA()) { aT0A += amplitude; @@ -594,7 +718,15 @@ struct UccZdc { } registry.fill(HIST("hEventCounter"), EvCutLabel::TZero); + double aV0A{-999.}; + if (foundBC.has_fv0a()) { + for (const auto& amplitude : foundBC.fv0a().amplitude()) { + aV0A += amplitude; + } + } + const double normT0M{(aT0A + aT0C) / 100.}; + const double normV0A{aV0A / 100.}; float znA{foundBC.zdc().amplitudeZNA()}; float znC{foundBC.zdc().amplitudeZNC()}; float zpA{foundBC.zdc().amplitudeZPA()}; @@ -611,9 +743,18 @@ struct UccZdc { znC /= kCollEnergy; zpA /= kCollEnergy; zpC /= kCollEnergy; - float sumZNs{znA + znC}; - float sumZPs{zpA + zpC}; - float sumZEMs{aZEM1 + aZEM2}; + double sumZNs{-999.}; + const double sumZPs{zpA + zpC}; + const double sumZEMs{aZEM1 + aZEM2}; + + TString sZDC = TString(detectorZDC.value); + if (sZDC == "ZNA") { + sumZNs = znA; + } else if (sZDC == "ZNC") { + sumZNs = znC; + } else { + sumZNs = (znA + znC); + } // TDC cut if (isTDCcut) { @@ -631,109 +772,165 @@ struct UccZdc { registry.fill(HIST("hEventCounter"), EvCutLabel::Zem); } - registry.fill(HIST("zPos"), collision.posZ()); - registry.fill(HIST("T0Ccent"), collision.centFT0C()); - // Nch-based selection - int itsTracks = 0, glbTracks = 0; + double glbTracks{0.0}; for (const auto& track : tracks) { // Track Selection - if (track.hasITS()) { - itsTracks++; - } if (!track.isGlobalTrack()) { continue; } if ((track.pt() < minPt) || (track.pt() > maxPt)) { continue; } - registry.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); - registry.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); - registry.fill(HIST("sigma1Pt"), track.pt(), track.sigma1Pt()); - registry.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); - glbTracks++; + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + glbTracks += 1.0; } 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!"); + loadNchCalibrations(foundBC.timestamp()); + if (!(cfgNch.hMeanNch && cfgNch.hSigmaNch)) return; + + TString s1 = TString(detector4Calibration.value); + double xEval{1.}; + if (s1 == "T0M") { + xEval = normT0M; } - if (!hSigmaNch) { - LOGF(info, "hSigmaNch NOT LOADED!"); - return; + if (s1 == "V0A") { + xEval = normV0A; } - const int binT0M{hMeanNch->FindBin(normT0M)}; - const double meanNch{hMeanNch->GetBinContent(binT0M)}; - const double sigmaNch{hSigmaNch->GetBinContent(binT0M)}; + const int bin4Calibration{cfgNch.hMeanNch->FindBin(xEval)}; + const double meanNch{cfgNch.hMeanNch->GetBinContent(bin4Calibration)}; + const double sigmaNch{cfgNch.hSigmaNch->GetBinContent(bin4Calibration)}; const double nSigmaSelection{nSigmaNchCut * sigmaNch}; const double diffMeanNch{meanNch - glbTracks}; - if (!(std::abs(diffMeanNch) < nSigmaSelection)) { + if (std::abs(diffMeanNch) > nSigmaSelection) { registry.fill(HIST("ExcludedEvtVsFT0M"), normT0M); + registry.fill(HIST("ExcludedEvtVsFV0A"), normV0A); registry.fill(HIST("ExcludedEvtVsNch"), glbTracks); - } else { skipEvent = true; } } - if (!skipEvent) { + // Skip event based on number of Nch sigmas + if (useMidRapNchSel && skipEvent) { return; } - auto efficiency = ccdb->getForTimeStamp(paTH.value, foundBC.timestamp()); - // auto efficiency = ccdb->getForRun(paTH.value, foundBC.runNumber()); - if (!efficiency) { + // Reject low-multiplcicity events + if (glbTracks < minNchSel) { return; } - std::vector pTs; - std::vector wIs; - // Calculates the event weight, W_k - for (const auto& track : tracks) { - // Track Selection - if (!track.isGlobalTrack()) { - continue; - } - if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { - continue; + double nchMult{glbTracks}; + std::vector pTs; + std::vector vecFD; + std::vector vecEff; + + // apply corrections + if (applyEff || applyFD) { + nchMult = 0.; + loadCorrections(foundBC.timestamp()); + if (!(cfg.hEfficiency && cfg.hFeedDown)) + return; + + const int foundNchBin{cfg.hEfficiency->GetXaxis()->FindBin(glbTracks)}; + + // Calculates the Corrected Nch + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + + const float pt{track.pt()}; + const int foundPtBin{cfg.hEfficiency->GetYaxis()->FindBin(pt)}; + const double effValue{cfg.hEfficiency->GetBinContent(foundNchBin, foundPtBin)}; + double fdValue{1.}; + + if (applyFD) + fdValue = cfg.hFeedDown->GetBinContent(foundNchBin, foundPtBin); + + if ((effValue > 0.) && (fdValue > 0.)) { + nchMult += (std::pow(effValue, -1.) * fdValue); + } } - float pt{track.pt()}; - double weight{1.}; - if (applyEff) { - weight = efficiency->GetBinContent(efficiency->FindBin(pt)); + if (applyEff && !correctNch) { + nchMult = glbTracks; } - if (weight > 0.) { - pTs.emplace_back(pt); - wIs.emplace_back(weight); + + // Reject low-multiplcicity events + if (nchMult < minNchSel) { + return; } - } - double p1, p2, p3, p4, w1, w2, w3, w4; - p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; - getPTpowers(pTs, wIs, p1, w1, p2, w2, p3, w3, p4, w4); - const double nch{static_cast(pTs.size())}; - if (nch < minNchSel) { - return; - } + // Fill vectors for [pT] measurement + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } - // To calculate event-averaged - for (const auto& track : tracks) { - // Track Selection - if (!track.isGlobalTrack()) { - continue; + const float pt{track.pt()}; + const int foundPtBin{cfg.hEfficiency->GetYaxis()->FindBin(pt)}; + const double effValue{cfg.hEfficiency->GetBinContent(foundNchBin, foundPtBin)}; + double fdValue{1.}; + + if (applyFD) + fdValue = cfg.hFeedDown->GetBinContent(foundNchBin, foundPtBin); + + if ((effValue > 0.) && (fdValue > 0.)) { + pTs.emplace_back(pt); + vecEff.emplace_back(effValue); + vecFD.emplace_back(fdValue); + // To calculate event-averaged + registry.fill(HIST("NchVsZNVsPt"), nchMult, sumZNs, pt * (fdValue / effValue)); + } } - if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { - continue; + } else { + // Fill vectors for [pT] measurement + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + + pTs.emplace_back(track.pt()); + vecEff.emplace_back(1.); + vecFD.emplace_back(1.); + // To calculate event-averaged + registry.fill(HIST("NchVsZNVsPt"), nchMult, sumZNs, track.pt()); } - registry.fill(HIST("NchVsZNVsPt"), w1, sumZNs, track.pt()); } + double p1, p2, p3, p4, w1, w2, w3, w4; + p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; + getPTpowers(pTs, vecEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); + // EbE one-particle pT correlation double oneParCorr{p1 / w1}; @@ -748,38 +945,43 @@ struct UccZdc { double threeParCorr{numThreeParCorr / denThreeParCorr}; // EbE four-particle pT correlation - double denFourParCorr{std::pow(w1, 4.) - 6. * w2 * std::pow(w1, 2.) + 3. * std::pow(w2, 2.) + 8 * w3 * w1 - 6. * w4}; - double numFourParCorr{std::pow(p1, 4.) - 6. * p2 * std::pow(p1, 2.) + 3. * std::pow(p2, 2.) + 8 * p3 * p1 - 6. * p4}; - double fourParCorr{numFourParCorr / denFourParCorr}; - - registry.fill(HIST("Nch"), w1); - registry.fill(HIST("ZNamp"), sumZNs); - registry.fill(HIST("NchVsZN"), w1, sumZNs); - registry.fill(HIST("NchVsZP"), w1, sumZPs); - registry.fill(HIST("NITSTacksVsZN"), itsTracks, sumZNs); - registry.fill(HIST("NITSTacksVsZP"), itsTracks, sumZPs); - registry.fill(HIST("T0MVsZN"), normT0M, sumZNs); - registry.fill(HIST("T0MVsZP"), normT0M, sumZPs); + // double denFourParCorr{std::pow(w1, 4.) - 6. * w2 * std::pow(w1, 2.) + 3. * std::pow(w2, 2.) + 8 * w3 * w1 - 6. * w4}; + // double numFourParCorr{std::pow(p1, 4.) - 6. * p2 * std::pow(p1, 2.) + 3. * std::pow(p2, 2.) + 8 * p3 * p1 - 6. * p4}; + // double fourParCorr{numFourParCorr / denFourParCorr}; + + // One-dimensional distributions + registry.fill(HIST("Nch"), nchMult); registry.fill(HIST("NchUncorrected"), glbTracks); - registry.fill(HIST("NchVsOneParCorr"), w1, oneParCorr, w1); - registry.fill(HIST("NchVsOneParCorrVsZN"), w1, sumZNs, oneParCorr, w1); - registry.fill(HIST("NchVsTwoParCorrVsZN"), w1, sumZNs, twoParCorr, denTwoParCorr); - registry.fill(HIST("NchVsThreeParCorrVsZN"), w1, sumZNs, threeParCorr, denThreeParCorr); - registry.fill(HIST("NchVsFourParCorrVsZN"), w1, sumZNs, fourParCorr, denFourParCorr); + + registry.fill(HIST("NchVsV0A"), nchMult, normV0A); + registry.fill(HIST("NchVsT0M"), nchMult, normT0M); + registry.fill(HIST("NchVsZN"), nchMult, sumZNs); + registry.fill(HIST("NchVsZP"), nchMult, sumZPs); + + registry.fill(HIST("NchVsOneParCorr"), nchMult, oneParCorr, w1); + + registry.fill(HIST("NchVsOneParCorrVsZN"), nchMult, sumZNs, oneParCorr, w1); + registry.fill(HIST("NchVsTwoParCorrVsZN"), nchMult, sumZNs, twoParCorr, denTwoParCorr); + registry.fill(HIST("NchVsThreeParCorrVsZN"), nchMult, sumZNs, threeParCorr, denThreeParCorr); + + registry.fill(HIST("NchVsOneParCorrVsT0M"), nchMult, normT0M, oneParCorr, w1); + registry.fill(HIST("NchVsTwoParCorrVsT0M"), nchMult, normT0M, twoParCorr, denTwoParCorr); + registry.fill(HIST("NchVsThreeParCorrVsT0M"), nchMult, normT0M, threeParCorr, denThreeParCorr); + + registry.fill(HIST("NchVsOneParCorrVsV0A"), nchMult, normV0A, oneParCorr, w1); + registry.fill(HIST("NchVsTwoParCorrVsV0A"), nchMult, normV0A, twoParCorr, denTwoParCorr); + registry.fill(HIST("NchVsThreeParCorrVsV0A"), nchMult, normV0A, threeParCorr, denThreeParCorr); + + const uint64_t timeStamp{foundBC.timestamp()}; + eventSampling(tracks, normV0A, normT0M, sumZNs, timeStamp); } PROCESS_SWITCH(UccZdc, processZdcCollAss, "Process ZDC W/Coll Ass.", true); - // Preslice perMCCollision = aod::mcparticle::mcCollisionId; Preslice perCollision = aod::track::collisionId; - TRandom* randPointer = new TRandom(); - void processMCclosure(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, o2::aod::BCsRun3 const& /*bcs*/, aod::McParticles const& mcParticles, TheFilteredSimTracks const& simTracks) + Service pdg; + void processMCclosure(aod::McCollisions::iterator const& mccollision, soa::SmallGroups const& collisions, o2::aod::BCsRun3 const& /*bcs*/, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, aod::McParticles const& mcParticles, TheFilteredSimTracks const& simTracks) { - - float rndNum = randPointer->Uniform(0.0, 1.0); - registry.fill(HIST("RandomNumber"), rndNum); - for (const auto& collision : collisions) { - // Event selection if (!isEventSelected(collision)) { continue; @@ -795,76 +997,163 @@ struct UccZdc { continue; } + const auto& foundBC = collision.foundBC_as(); + + uint64_t timeStamp{foundBC.timestamp()}; + TRandom3 rndGen(timeStamp); + const double rndNum{rndGen.Uniform(0.0, 1.0)}; + registry.fill(HIST("RandomNumber"), rndNum); + + double aT0A = 0., aT0C = 0.; + if (foundBC.has_ft0()) { + for (const auto& amplitude : foundBC.ft0().amplitudeA()) { + aT0A += amplitude; + } + for (const auto& amplitude : foundBC.ft0().amplitudeC()) { + aT0C += amplitude; + } + } else { + return; + } + + // double aV0A{-999.}; + // if (foundBC.has_fv0a()) { + // for (const auto& amplitude : foundBC.fv0a().amplitude()) { aV0A += amplitude; } + // } + + const double normT0M{(aT0A + aT0C) / 100.}; + // const double normV0A{aV0A/100.}; + + double nchRaw{0.}; + double nchMult{0.}; + double nchMC{0.}; + registry.fill(HIST("zPos"), collision.posZ()); registry.fill(HIST("zPosMC"), mccollision.posZ()); registry.fill(HIST("hEventCounterMC"), EvCutLabel::VtxZ); + + if (skipRecoColGTOne && (collisions.size() > kOne)) { + continue; + } + registry.fill(HIST("nRecColvsCent"), collisions.size(), collision.centFT0C()); const auto& cent{collision.centFT0C()}; registry.fill(HIST("T0Ccent"), cent); + const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; + // Half of the statistics for MC closure if (rndNum >= kZero && rndNum < evtFracMCcl) { + registry.fill(HIST("EvtsDivided"), 0); - // To use run-by-run efficiency - const auto& foundBC = collision.foundBC_as(); - // auto efficiency = ccdb->getForTimeStamp(paTH.value, foundBC.timestamp()); - auto efficiency = ccdb->getForRun(paTH.value, foundBC.runNumber()); - if (!efficiency) { + // Run-by-run efficiency + loadCorrections(foundBC.timestamp()); + if (!(cfg.hEfficiency && cfg.hFeedDown)) { continue; } - std::vector pTs; - std::vector wIs; - const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; + std::vector pTs; + std::vector vecFD; + std::vector vecEff; + + // Calculates the event's Nch to evaluate the efficiency + for (const auto& track : groupedTracks) { + // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } + if (!track.isGlobalTrack()) { + continue; + } + nchRaw++; + } + + // Reject event if nchRaw less than a lower cutoff + if (nchRaw < minNchSel) { + return; + } + // Calculates the event weight, W_k + const int foundNchBin{cfg.hEfficiency->GetXaxis()->FindBin(nchRaw)}; + for (const auto& track : groupedTracks) { // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } if (!track.isGlobalTrack()) { continue; } + if (!track.has_mcParticle()) { + continue; + } + const auto& particle{track.mcParticle()}; - float pt{track.pt()}; - double weight{efficiency->GetBinContent(efficiency->FindBin(pt))}; - if (!(weight > 0.)) { + auto charge{0.}; + // Get the MC particle + auto* pdgParticle = pdg->GetParticle(particle.pdgCode()); + if (pdgParticle != nullptr) { + charge = pdgParticle->Charge(); + } else { continue; } - pTs.emplace_back(pt); - wIs.emplace_back(weight); - } - const double nch{static_cast(pTs.size())}; - if (nch < minNchSel) { - continue; + // Is it a charged particle? + if (std::abs(charge) < kMinCharge) { + continue; + } + // Is it a primary particle? + // if (!particle.isPhysicalPrimary()) { continue; } + + const double pt{static_cast(track.pt())}; + const int foundPtBin{cfg.hEfficiency->GetYaxis()->FindBin(pt)}; + const double effValue{cfg.hEfficiency->GetBinContent(foundNchBin, foundPtBin)}; + double fdValue{1.}; + + if (applyFD) + fdValue = cfg.hFeedDown->GetBinContent(foundNchBin, foundPtBin); + if ((effValue > 0.) && (fdValue > 0.)) { + pTs.emplace_back(pt); + vecEff.emplace_back(effValue); + vecFD.emplace_back(fdValue); + nchMult += (std::pow(effValue, -1.0) * fdValue); + } } double p1, p2, p3, p4, w1, w2, w3, w4; p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; - getPTpowers(pTs, wIs, p1, w1, p2, w2, p3, w3, p4, w4); + getPTpowers(pTs, vecEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); const double denTwoParCorr{std::pow(w1, 2.) - w2}; const double numTwoParCorr{std::pow(p1, 2.) - p2}; const double denThreeParCorr{std::pow(w1, 3.) - 3. * w2 * w1 + 2. * w3}; const double numThreeParCorr{std::pow(p1, 3.) - 3. * p2 * p1 + 2. * p3}; - const double denFourParCorr{std::pow(w1, 4.) - 6. * w2 * std::pow(w1, 2.) + 3. * std::pow(w2, 2.) + 8 * w3 * w1 - 6. * w4}; - const double numFourParCorr{std::pow(p1, 4.) - 6. * p2 * std::pow(p1, 2.) + 3. * std::pow(p2, 2.) + 8 * p3 * p1 - 6. * p4}; + // const double denFourParCorr{std::pow(w1, 4.) - 6. * w2 * std::pow(w1, 2.) + 3. * std::pow(w2, 2.) + 8 * w3 * w1 - 6. * w4}; + // const double numFourParCorr{std::pow(p1, 4.) - 6. * p2 * std::pow(p1, 2.) + 3. * std::pow(p2, 2.) + 8 * p3 * p1 - 6. * p4}; const double oneParCorr{p1 / w1}; const double twoParCorr{numTwoParCorr / denTwoParCorr}; const double threeParCorr{numThreeParCorr / denThreeParCorr}; - const double fourParCorr{numFourParCorr / denFourParCorr}; - registry.fill(HIST("Nch"), w1); - registry.fill(HIST("NchUncorrected"), nch); - registry.fill(HIST("NchVsOneParCorr"), w1, oneParCorr, w1); - registry.fill(HIST("NchVsTwoParCorr"), w1, twoParCorr, denTwoParCorr); - registry.fill(HIST("NchVsThreeParCorr"), w1, threeParCorr, denThreeParCorr); - registry.fill(HIST("NchVsFourParCorr"), w1, fourParCorr, denFourParCorr); + registry.fill(HIST("Nch"), nchMult); + registry.fill(HIST("NchUncorrected"), nchRaw); + registry.fill(HIST("NchVsOneParCorr"), nchMult, oneParCorr, w1); + registry.fill(HIST("NchVsTwoParCorr"), nchMult, twoParCorr, denTwoParCorr); + registry.fill(HIST("NchVsThreeParCorr"), nchMult, threeParCorr, denThreeParCorr); //--------------------------- Generated MC --------------------------- std::vector pTsMC; - std::vector wIsMC; + std::vector vecFullEff; + std::vector vecFDEqualOne; + // Calculates the event weight, W_k for (const auto& particle : mcParticles) { if (particle.eta() < minEta || particle.eta() > maxEta) { @@ -873,47 +1162,90 @@ struct UccZdc { if (particle.pt() < minPt || particle.pt() > 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? if (!particle.isPhysicalPrimary()) { continue; } float pt{particle.pt()}; pTsMC.emplace_back(pt); - wIsMC.emplace_back(1.); + vecFullEff.emplace_back(1.); + vecFDEqualOne.emplace_back(1.); + nchMC++; } - const double nchMC{static_cast(pTsMC.size())}; if (nchMC < minNchSel) { continue; } + // printf("nchMult = %f | nchMC = %f | nchMult/nchMc = %f\n",nchMult,nchMC,nchMult/nchMC); double p1MC, p2MC, p3MC, p4MC, w1MC, w2MC, w3MC, w4MC; p1MC = p2MC = p3MC = p4MC = w1MC = w2MC = w3MC = w4MC = 0.0; - getPTpowers(pTsMC, wIsMC, p1MC, w1MC, p2MC, w2MC, p3MC, w3MC, p4MC, w4MC); + getPTpowers(pTsMC, vecFullEff, vecFDEqualOne, p1MC, w1MC, p2MC, w2MC, p3MC, w3MC, p4MC, w4MC); const double denTwoParCorrMC{std::pow(w1MC, 2.) - w2MC}; const double numTwoParCorrMC{std::pow(p1MC, 2.) - p2MC}; const double denThreeParCorrMC{std::pow(w1MC, 3.) - 3. * w2MC * w1MC + 2. * w3MC}; const double numThreeParCorrMC{std::pow(p1MC, 3.) - 3. * p2MC * p1MC + 2. * p3MC}; - const double denFourParCorrMC{std::pow(w1MC, 4.) - 6. * w2MC * std::pow(w1MC, 2.) + 3. * std::pow(w2MC, 2.) + 8 * w3MC * w1MC - 6. * w4MC}; - const double numFourParCorrMC{std::pow(p1MC, 4.) - 6. * p2MC * std::pow(p1MC, 2.) + 3. * std::pow(p2MC, 2.) + 8 * p3MC * p1MC - 6. * p4MC}; + // const double denFourParCorrMC{std::pow(w1MC, 4.) - 6. * w2MC * std::pow(w1MC, 2.) + 3. * std::pow(w2MC, 2.) + 8 * w3MC * w1MC - 6. * w4MC}; + // const double numFourParCorrMC{std::pow(p1MC, 4.) - 6. * p2MC * std::pow(p1MC, 2.) + 3. * std::pow(p2MC, 2.) + 8 * p3MC * p1MC - 6. * p4MC}; const double oneParCorrMC{p1MC / w1MC}; const double twoParCorrMC{numTwoParCorrMC / denTwoParCorrMC}; const double threeParCorrMC{numThreeParCorrMC / denThreeParCorrMC}; - const double fourParCorrMC{numFourParCorrMC / denFourParCorrMC}; + // const double fourParCorrMC{numFourParCorrMC / denFourParCorrMC}; registry.fill(HIST("NchGen"), nchMC); registry.fill(HIST("NchvsOneParCorrGen"), nchMC, oneParCorrMC, w1MC); registry.fill(HIST("NchvsTwoParCorrGen"), nchMC, twoParCorrMC, denTwoParCorrMC); registry.fill(HIST("NchvsThreeParCorrGen"), nchMC, threeParCorrMC, denThreeParCorrMC); - registry.fill(HIST("NchvsFourParCorrGen"), nchMC, fourParCorrMC, denFourParCorrMC); + + //------------------ Poisson sampling + eventSamplingMC(mcParticles, timeStamp); + eventSamplingMCRec(groupedTracks, timeStamp); } else { // Correction with the remaining half of the sample registry.fill(HIST("EvtsDivided"), 1); //----- MC reconstructed -----// - const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; + // const auto& groupedTracks{simTracks.sliceBy(perCollision, collision.globalIndex())}; for (const auto& track : groupedTracks) { // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } + if (!track.isGlobalTrack()) { + continue; + } + registry.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); + registry.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); + registry.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); + nchRaw++; + } + + for (const auto& track : groupedTracks) { + // Track Selection + if (track.eta() < minEta || track.eta() > maxEta) { + continue; + } + if (track.pt() < minPt || track.pt() > maxPt) { + continue; + } if (!track.isGlobalTrack()) { continue; } @@ -921,30 +1253,40 @@ struct UccZdc { if (!track.has_mcParticle()) { continue; } - + // Get the MC particle const auto& particle{track.mcParticle()}; - registry.fill(HIST("Pt_all_ch"), cent, track.pt()); - registry.fill(HIST("ZposVsEta"), collision.posZ(), track.eta()); - registry.fill(HIST("EtaVsPhi"), track.eta(), track.phi()); - registry.fill(HIST("dcaXYvspT"), track.dcaXY(), track.pt()); + 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; + } + // All charged particles + registry.fill(HIST("Pt_all_ch"), nchRaw, track.pt()); + // Is it a primary particle? if (!particle.isPhysicalPrimary()) { continue; } - registry.fill(HIST("Pt_ch"), cent, track.pt()); + registry.fill(HIST("Pt_ch"), nchRaw, track.pt()); if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { - registry.fill(HIST("Pt_pi"), cent, track.pt()); + registry.fill(HIST("Pt_pi"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { - registry.fill(HIST("Pt_ka"), cent, track.pt()); + registry.fill(HIST("Pt_ka"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { - registry.fill(HIST("Pt_pr"), cent, track.pt()); + registry.fill(HIST("Pt_pr"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaPlus || particle.pdgCode() == PDG_t::kSigmaBarMinus) { - registry.fill(HIST("Pt_sigpos"), cent, track.pt()); + registry.fill(HIST("Pt_sigpos"), nchRaw, track.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaMinus || particle.pdgCode() == PDG_t::kSigmaBarPlus) { - registry.fill(HIST("Pt_signeg"), cent, track.pt()); + registry.fill(HIST("Pt_signeg"), nchRaw, track.pt()); } else { - registry.fill(HIST("Pt_re"), cent, track.pt()); + registry.fill(HIST("Pt_re"), nchRaw, track.pt()); } } @@ -956,37 +1298,55 @@ struct UccZdc { if (particle.pt() < minPt || particle.pt() > 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? if (!particle.isPhysicalPrimary()) { continue; } - registry.fill(HIST("PtMC_ch"), cent, particle.pt()); + registry.fill(HIST("PtMC_ch"), nchRaw, particle.pt()); if (particle.pdgCode() == PDG_t::kPiPlus || particle.pdgCode() == PDG_t::kPiMinus) { // pion - registry.fill(HIST("PtMC_pi"), cent, particle.pt()); + registry.fill(HIST("PtMC_pi"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kKPlus || particle.pdgCode() == PDG_t::kKMinus) { // kaon - registry.fill(HIST("PtMC_ka"), cent, particle.pt()); + registry.fill(HIST("PtMC_ka"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kProton || particle.pdgCode() == PDG_t::kProtonBar) { // proton - registry.fill(HIST("PtMC_pr"), cent, particle.pt()); + registry.fill(HIST("PtMC_pr"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaPlus || particle.pdgCode() == PDG_t::kSigmaBarMinus) { // positive sigma - registry.fill(HIST("PtMC_sigpos"), cent, particle.pt()); + registry.fill(HIST("PtMC_sigpos"), nchRaw, particle.pt()); } else if (particle.pdgCode() == PDG_t::kSigmaMinus || particle.pdgCode() == PDG_t::kSigmaBarPlus) { // negative sigma - registry.fill(HIST("PtMC_signeg"), cent, particle.pt()); + registry.fill(HIST("PtMC_signeg"), nchRaw, particle.pt()); } else { // rest - registry.fill(HIST("PtMC_re"), cent, particle.pt()); + registry.fill(HIST("PtMC_re"), nchRaw, particle.pt()); } } } // Half of statistics for corrections + registry.fill(HIST("McNchVsFT0M"), normT0M, nchRaw); } // Collisions } PROCESS_SWITCH(UccZdc, processMCclosure, "Process MC closure", false); template - void getPTpowers(const T& pTs, const T& wIs, U& pOne, U& wOne, U& pTwo, U& wTwo, U& pThree, U& wThree, U& pFour, U& wFour) + void getPTpowers(const T& pTs, const T& vecEff, const T& vecFD, U& pOne, U& wOne, U& pTwo, U& wTwo, U& pThree, U& wThree, U& pFour, U& wFour) { pOne = wOne = pTwo = wTwo = pThree = wThree = pFour = wFour = 0.; for (std::size_t i = 0; i < pTs.size(); ++i) { - const float pTi{pTs.at(i)}; - const float wEighti{wIs.at(i)}; + const double pTi{pTs.at(i)}; + const double eFFi{vecEff.at(i)}; + const double fDi{vecFD.at(i)}; + const double wEighti{std::pow(eFFi, -1.) * fDi}; pOne += wEighti * pTi; wOne += wEighti; pTwo += std::pow(wEighti * pTi, 2.); @@ -997,6 +1357,429 @@ struct UccZdc { wFour += std::pow(wEighti, 4.); } } + + template + void eventSamplingMC(const T& mcParticles, const V& timeStamp) + { + TRandom3 rndGen(timeStamp); + std::vector vPoisson; + for (int replica = 0; replica < kSizeBootStrapEnsemble; ++replica) + vPoisson.emplace_back(rndGen.Poisson(1.)); + + for (int replica = 0; replica < kSizeBootStrapEnsemble; ++replica) { + + hPoissonMC[replica]->Fill(vPoisson.at(replica)); + + for (uint64_t evtRep = 0; evtRep < vPoisson.at(replica); ++evtRep) { + + double nchMult{0.}; + std::vector pTs; + std::vector vecFD; + std::vector vecEff; + + // Calculates the event weight, W_k + for (const auto& particle : mcParticles) { + if (particle.eta() < minEta || particle.eta() > maxEta) { + continue; + } + if (particle.pt() < minPt || particle.pt() > 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? + if (!particle.isPhysicalPrimary()) { + continue; + } + + float pt{particle.pt()}; + pTs.emplace_back(pt); + vecEff.emplace_back(1.); + vecFD.emplace_back(1.); + nchMult++; + } + + if (nchMult < minNchSel) { + continue; + } + // printf("nchMult = %f | nchMC = %f | nchMult/nchMc = %f\n",nchMult,nchMC,nchMult/nchMC); + + double p1, p2, p3, p4, w1, w2, w3, w4; + p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; + getPTpowers(pTs, vecEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); + + // EbE one-particle pT correlation + const double oneParCorr{p1 / w1}; + + // EbE two-particle pT correlation + const double denTwoParCorr{std::pow(w1, 2.) - w2}; + const double numTwoParCorr{std::pow(p1, 2.) - p2}; + const double twoParCorr{numTwoParCorr / denTwoParCorr}; + + // EbE three-particle pT correlation + const double denThreeParCorr{std::pow(w1, 3.) - 3. * w2 * w1 + 2. * w3}; + const double numThreeParCorr{std::pow(p1, 3.) - 3. * p2 * p1 + 2. * p3}; + const double threeParCorr{numThreeParCorr / denThreeParCorr}; + + hNchGen[replica]->Fill(nchMult); + pOneParCorrVsNchGen[replica]->Fill(nchMult, oneParCorr, w1); + pTwoParCorrVsNchGen[replica]->Fill(nchMult, twoParCorr, denTwoParCorr); + pThreeParCorrVsNchGen[replica]->Fill(nchMult, threeParCorr, denThreeParCorr); + } // event per replica + } // replica's loop + } + + template + void eventSamplingMCRec(const T& tracks, const V& timeStamp) + { + TRandom3 rndGen(timeStamp); + std::vector vPoisson; + for (int replica = 0; replica < kSizeBootStrapEnsemble; ++replica) + vPoisson.emplace_back(rndGen.Poisson(1.)); + + for (int replica = 0; replica < kSizeBootStrapEnsemble; ++replica) { + + hPoisson[replica]->Fill(vPoisson.at(replica)); + + for (uint64_t evtRep = 0; evtRep < vPoisson.at(replica); ++evtRep) { + + double nchMult{0.}; + int glbTracks{0}; + std::vector pTs; + std::vector vecFD; + std::vector vecEff; + + // Calculates the uncorrected Nch multiplicity + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + glbTracks++; + } + + if (glbTracks < minNchSel) { + continue; + } + + // Calculates the Nch multiplicity if corrections are loaded + if (cfg.correctionsLoaded) { + const int foundNchBin{cfg.hEfficiency->GetXaxis()->FindBin(glbTracks)}; + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + + float pt{track.pt()}; + double fdValue{1.}; + int foundPtBin{cfg.hEfficiency->GetYaxis()->FindBin(pt)}; + double effValue{cfg.hEfficiency->GetBinContent(foundNchBin, foundPtBin)}; + + if (applyFD) + fdValue = cfg.hFeedDown->GetBinContent(foundNchBin, foundPtBin); + if ((effValue > 0.) && (fdValue > 0.)) { + nchMult += (std::pow(effValue, -1.) * fdValue); + } + } + } + + if (!applyEff) + nchMult = static_cast(glbTracks); + if (applyEff && !correctNch) + nchMult = static_cast(glbTracks); + + // Fill vectors for [pT] measurement + if (cfg.correctionsLoaded) { + const int foundNchBin{cfg.hEfficiency->GetXaxis()->FindBin(glbTracks)}; + // Fill vectors for [pT] measurement + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + + float pt{track.pt()}; + double fdValue{1.}; + int foundPtBin{cfg.hEfficiency->GetYaxis()->FindBin(pt)}; + double effValue{cfg.hEfficiency->GetBinContent(foundNchBin, foundPtBin)}; + + if (applyFD) + fdValue = cfg.hFeedDown->GetBinContent(foundNchBin, foundPtBin); + + if ((effValue > 0.) && (fdValue > 0.)) { + pTs.emplace_back(pt); + vecEff.emplace_back(effValue); + vecFD.emplace_back(fdValue); + } + } + } else { + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + + pTs.emplace_back(track.pt()); + vecEff.emplace_back(1.); + vecFD.emplace_back(1.); + } + } + + double p1, p2, p3, p4, w1, w2, w3, w4; + p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; + getPTpowers(pTs, vecEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); + + // EbE one-particle pT correlation + const double oneParCorr{p1 / w1}; + + // EbE two-particle pT correlation + const double denTwoParCorr{std::pow(w1, 2.) - w2}; + const double numTwoParCorr{std::pow(p1, 2.) - p2}; + const double twoParCorr{numTwoParCorr / denTwoParCorr}; + + // EbE three-particle pT correlation + const double denThreeParCorr{std::pow(w1, 3.) - 3. * w2 * w1 + 2. * w3}; + const double numThreeParCorr{std::pow(p1, 3.) - 3. * p2 * p1 + 2. * p3}; + const double threeParCorr{numThreeParCorr / denThreeParCorr}; + + hNch[replica]->Fill(nchMult); + pOneParCorrVsNch[replica]->Fill(nchMult, oneParCorr, w1); + pTwoParCorrVsNch[replica]->Fill(nchMult, twoParCorr, denTwoParCorr); + pThreeParCorrVsNch[replica]->Fill(nchMult, threeParCorr, denThreeParCorr); + } // event per replica + } // replica's loop + } + + template + void eventSampling(const T& tracks, const U& normV0A, const U& normT0M, const U& sumZNs, const V& timeStamp) + { + TRandom3 rndGen(timeStamp); + std::vector vPoisson; + for (int replica = 0; replica < kSizeBootStrapEnsemble; ++replica) + vPoisson.emplace_back(rndGen.Poisson(1.)); + + for (int replica = 0; replica < kSizeBootStrapEnsemble; ++replica) { + + hPoisson[replica]->Fill(vPoisson.at(replica)); + + for (uint64_t evtRep = 0; evtRep < vPoisson.at(replica); ++evtRep) { + + double nchMult{0.}; + int glbTracks{0}; + std::vector pTs; + std::vector vecFD; + std::vector vecEff; + + // Calculates the uncorrected Nch multiplicity + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + glbTracks++; + } + + if (glbTracks < minNchSel) { + continue; + } + + // Calculates the Nch multiplicity if corrections are loaded + if (cfg.correctionsLoaded) { + const int foundNchBin{cfg.hEfficiency->GetXaxis()->FindBin(glbTracks)}; + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPt)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + + float pt{track.pt()}; + double fdValue{1.}; + int foundPtBin{cfg.hEfficiency->GetYaxis()->FindBin(pt)}; + double effValue{cfg.hEfficiency->GetBinContent(foundNchBin, foundPtBin)}; + + if (applyFD) + fdValue = cfg.hFeedDown->GetBinContent(foundNchBin, foundPtBin); + if ((effValue > 0.) && (fdValue > 0.)) { + nchMult += (std::pow(effValue, -1.) * fdValue); + } + } + } + + if (!applyEff) + nchMult = static_cast(glbTracks); + if (applyEff && !correctNch) + nchMult = static_cast(glbTracks); + + // Fill vectors for [pT] measurement + if (cfg.correctionsLoaded) { + const int foundNchBin{cfg.hEfficiency->GetXaxis()->FindBin(glbTracks)}; + // Fill vectors for [pT] measurement + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + if ((track.eta() < minEta) || (track.eta() > maxEta)) { + continue; + } + + float pt{track.pt()}; + double fdValue{1.}; + int foundPtBin{cfg.hEfficiency->GetYaxis()->FindBin(pt)}; + double effValue{cfg.hEfficiency->GetBinContent(foundNchBin, foundPtBin)}; + + if (applyFD) + fdValue = cfg.hFeedDown->GetBinContent(foundNchBin, foundPtBin); + + if ((effValue > 0.) && (fdValue > 0.)) { + pTs.emplace_back(pt); + vecEff.emplace_back(effValue); + vecFD.emplace_back(fdValue); + // To calculate event-averaged + registry.fill(HIST("NchVsZNVsPt"), nchMult, sumZNs, pt * (fdValue / effValue)); + } + } + } else { + for (const auto& track : tracks) { + // Track Selection + if (!track.isGlobalTrack()) { + continue; + } + if ((track.pt() < minPt) || (track.pt() > maxPtSpectra)) { + continue; + } + + pTs.emplace_back(track.pt()); + vecEff.emplace_back(1.); + vecFD.emplace_back(1.); + + // To calculate event-averaged + registry.fill(HIST("NchVsZNVsPt"), nchMult, sumZNs, track.pt()); + } + } + + double p1, p2, p3, p4, w1, w2, w3, w4; + p1 = p2 = p3 = p4 = w1 = w2 = w3 = w4 = 0.0; + getPTpowers(pTs, vecEff, vecFD, p1, w1, p2, w2, p3, w3, p4, w4); + + // EbE one-particle pT correlation + const double oneParCorr{p1 / w1}; + + // EbE two-particle pT correlation + const double denTwoParCorr{std::pow(w1, 2.) - w2}; + const double numTwoParCorr{std::pow(p1, 2.) - p2}; + const double twoParCorr{numTwoParCorr / denTwoParCorr}; + + // EbE three-particle pT correlation + const double denThreeParCorr{std::pow(w1, 3.) - 3. * w2 * w1 + 2. * w3}; + const double numThreeParCorr{std::pow(p1, 3.) - 3. * p2 * p1 + 2. * p3}; + const double threeParCorr{numThreeParCorr / denThreeParCorr}; + + hNchVsZN[replica]->Fill(nchMult, sumZNs); + hNchVsV0A[replica]->Fill(nchMult, normV0A); + hNchVsT0M[replica]->Fill(nchMult, normT0M); + + pNchVsOneParCorrVsZN[replica]->Fill(nchMult, sumZNs, oneParCorr, w1); + pNchVsTwoParCorrVsZN[replica]->Fill(nchMult, sumZNs, twoParCorr, denTwoParCorr); + pNchVsThreeParCorrVsZN[replica]->Fill(nchMult, sumZNs, threeParCorr, denThreeParCorr); + + pNchVsOneParCorrVsT0M[replica]->Fill(nchMult, normT0M, oneParCorr, w1); + pNchVsTwoParCorrVsT0M[replica]->Fill(nchMult, normT0M, twoParCorr, denTwoParCorr); + pNchVsThreeParCorrVsT0M[replica]->Fill(nchMult, normT0M, threeParCorr, denThreeParCorr); + + pNchVsOneParCorrVsV0A[replica]->Fill(nchMult, normV0A, oneParCorr, w1); + pNchVsTwoParCorrVsV0A[replica]->Fill(nchMult, normV0A, twoParCorr, denTwoParCorr); + pNchVsThreeParCorrVsV0A[replica]->Fill(nchMult, normV0A, threeParCorr, denThreeParCorr); + } // event per replica + } // replica's loop + } + + void loadCorrections(uint64_t timeStamp) + { + // if (cfg.correctionsLoaded) return; + + if (paTHEff.value.empty() == false) { + cfg.hEfficiency = ccdb->getForTimeStamp(paTHEff, timeStamp); + if (cfg.hEfficiency == nullptr) { + LOGF(fatal, "Could not load efficiency histogram from %s", paTHEff.value.c_str()); + } + } + + if (paTHFD.value.empty() == false) { + cfg.hFeedDown = ccdb->getForTimeStamp(paTHFD, timeStamp); + if (cfg.hFeedDown == nullptr) { + LOGF(fatal, "Could not load feed down histogram from %s", paTHFD.value.c_str()); + } + } + cfg.correctionsLoaded = true; + } + + void loadNchCalibrations(uint64_t timeStamp) + { + if (paTHmeanNch.value.empty() == false) { + cfgNch.hMeanNch = ccdb->getForTimeStamp(paTHmeanNch, timeStamp); + if (cfgNch.hMeanNch == nullptr) { + LOGF(fatal, "Could not load hMeanNch histogram from %s", paTHmeanNch.value.c_str()); + } + } + + if (paTHsigmaNch.value.empty() == false) { + cfgNch.hSigmaNch = ccdb->getForTimeStamp(paTHsigmaNch, timeStamp); + if (cfgNch.hSigmaNch == nullptr) { + LOGF(fatal, "Could not load hSigmaNch histogram from %s", paTHsigmaNch.value.c_str()); + } + } + cfgNch.calibrationsLoaded = true; + } }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Nuspex/CMakeLists.txt b/PWGLF/Tasks/Nuspex/CMakeLists.txt index b2af549c871..cc23b8d0544 100644 --- a/PWGLF/Tasks/Nuspex/CMakeLists.txt +++ b/PWGLF/Tasks/Nuspex/CMakeLists.txt @@ -24,16 +24,6 @@ o2physics_add_dpl_workflow(nuclei-hist PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(hypertriton3bodyanalysis - SOURCES hypertriton3bodyanalysis.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - -o2physics_add_dpl_workflow(hypertriton3bodymcqa - SOURCES hypertriton3bodyMcqa.cxx - PUBLIC_LINK_LIBRARIES O2::DCAFitter O2Physics::AnalysisCore O2::TOFBase - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(helium-flow SOURCES helium_flow.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -89,8 +79,8 @@ o2physics_add_dpl_workflow(spectra-tpc-tiny-pikapr PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(spectra-charged - SOURCES spectraCharged.cxx +o2physics_add_dpl_workflow(charged-particles + SOURCES chargedParticles.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -147,6 +137,22 @@ o2physics_add_dpl_workflow(angular-correlations-in-jets o2physics_add_dpl_workflow(antinuclei-in-jets SOURCES antinucleiInJets.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(kink-pika + SOURCES spectraKinkPiKa.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(he3-lambda-derived-analysis + SOURCES he3LambdaDerivedAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(dedx-pid-analysis + SOURCES dedxPidAnalysis.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + endif() diff --git a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx index f3f57325bac..8e5f159d331 100644 --- a/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx +++ b/PWGLF/Tasks/Nuspex/LFNucleiBATask.cxx @@ -18,30 +18,33 @@ /// #include "PWGLF/DataModel/LFNucleiTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/DataModel/mcCentrality.h" +#include "Common/CCDB/EventSelectionParams.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/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" + #include "CCDB/BasicCCDBManager.h" -#include -#include -#include -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" - -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "Common/CCDB/EventSelectionParams.h" -#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" + +#include +// #include + +#include using namespace o2; using namespace o2::framework; @@ -78,18 +81,18 @@ struct LFNucleiBATask { // 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 useTVXtrigger{"useTVXtrigger", 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; // 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"}; + Configurable cfgMultCutLow{"cfgMultCutLow", 0.0f, "Accepted multiplicity percentage lower limit"}; + Configurable cfgMultCutHigh{"cfgMultCutHigh", 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"}; + Configurable cfgVzCutLow{"cfgVzCutLow", -10.0f, "Accepted z-vertex lower limit"}; + Configurable cfgVzCutHigh{"cfgVzCutHigh", 10.0f, "Accepted z-vertex upper limit"}; // Set the quality cuts for tracks struct : ConfigurableGroup { @@ -105,13 +108,14 @@ struct LFNucleiBATask { // Set the kinematic and PID cuts for tracks struct : ConfigurableGroup { - Configurable pCut{"pCut", 0.3f, "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)"}; + Configurable cfgMomentumCut{"cfgMomentumCut", 0.3f, "Value of the p selection for spectra (default 0.3)"}; + Configurable cfgEtaCut{"cfgEtaCut", 0.8f, "Value of the eta selection for spectra (default 0.8)"}; + Configurable cfgRapidityCutLow{"cfgRapidityCutLow", -1.0f, "Value of the low rapidity selection for spectra (default -1.0)"}; + Configurable cfgRapidityCutHigh{"cfgRapidityCutHigh", 1.0f, "Value of the high rapidity selection for spectra (default 1.0)"}; } kinemOptions; Configurable isPVContributorCut{"isPVContributorCut", false, "Flag to enable isPVContributor cut."}; + Configurable initITSPID{"initITSPID", false, "Flag to init the ITS PID response"}; struct : ConfigurableGroup { Configurable nsigmaTPCPr{"nsigmaTPCPr", 3.f, "Value of the Nsigma TPC cut for protons"}; @@ -122,13 +126,15 @@ struct LFNucleiBATask { } nsigmaTPCvar; struct : ConfigurableGroup { + Configurable useITSDeCut{"useITSDeCut", false, "Select Deuteron if compatible with deuteron hypothesis (via SigmaITS)"}; Configurable useITSHeCut{"useITSHeCut", false, "Select Helium if compatible with helium hypothesis (via SigmaITS)"}; + Configurable nsigmaITSDe{"nsigmaITSDe", -1.f, "Value of the Nsigma ITS cut for deuteron ( > nSigmaITSHe)"}; Configurable nsigmaITSHe{"nsigmaITSHe", -1.f, "Value of the Nsigma ITS cut for helium-3 ( > nSigmaITSHe)"}; Configurable showAverageClusterSize{"showAverageClusterSize", false, "Show average cluster size"}; } nsigmaITSvar; // Set additional cuts (used for debug) - Configurable betaCut{"betaCut", 0.4f, "Value of the beta selection for TOF cut (default 0.4)"}; + Configurable cfgBetaCut{"cfgBetaCut", 0.4f, "Value of the beta selection for TOF cut (default 0.4)"}; // Set the axis used in this task ConfigurableAxis binsPercentile{"binsPercentile", {100, 0, 100}, "Centrality FT0M"}; @@ -155,11 +161,11 @@ struct LFNucleiBATask { Configurable enableEvTimeSplitting{"enableEvTimeSplitting", false, "Flag to enable histograms splitting depending on the Event Time used"}; } filterOptions; - Configurable enableDCACustomCut{"enableDCACustomCut", false, "Flag to enable DCA custom cuts - unflag to use standard isGlobalCut DCA cut"}; + Configurable enableCustomDCACut{"enableCustomDCACut", false, "Flag to enable DCA custom cuts - unflag to use standard isGlobalCut DCA cut"}; struct : ConfigurableGroup { - Configurable DCACustomConfig{"DCACustomConfig", 0, "Select to use: pT independent DCAxy and DCAz CustomCut (0), pT dependent DCAxy and DCAz cut (1), pt dependent DCAxy, DCAz CustomCut (2) DCAxy CustomCut, pT dependent DCAz (3) or a circular DCAxy,z cut (4) for tracks. Need 'enableDCACustomCut' to be enabled."}; - Configurable DCAxyCustomCut{"DCAxyCustomCut", 0.05f, "Value of the DCAxy selection for spectra (default 0.05 cm)"}; - Configurable DCAzCustomCut{"DCAzCustomCut", 0.5f, "Value of the DCAz selection for spectra (default 0.5 cm)"}; + Configurable cfgCustomDCA{"cfgCustomDCA", 0, "Select to use: pT independent DCAxy and DCAz CustomCut (0), pT dependent DCAxy and DCAz cut (1), pt dependent DCAxy, DCAz CustomCut (2) DCAxy CustomCut, pT dependent DCAz (3) or a circular DCAxy,z cut (4) for tracks. Need 'enableCustomDCACut' to be enabled."}; + Configurable cfgCustomDCAxy{"cfgCustomDCAxy", 0.05f, "Value of the DCAxy selection for spectra (default 0.05 cm)"}; + Configurable cfgCustomDCAz{"cfgCustomDCAz", 0.5f, "Value of the DCAz selection for spectra (default 0.5 cm)"}; } dcaConfOptions; Configurable> parDCAxycuts{"parDCAxycuts", {0.004f, 0.013f, 1, 1}, "Parameters for Pt dependent DCAxy cut (if enabled): |DCAxy| < [3] * ([O] + [1]/Pt^[2])."}; @@ -175,18 +181,20 @@ struct LFNucleiBATask { Configurable enableExpSignalTPC{"enableExpSignalTPC", true, "Flag to export dEdX - dEdX(exp) plots."}; Configurable enableExpSignalTOF{"enableExpSignalTOF", false, "Flag to export T - T(exp) plots."}; Configurable enableBetaCut{"enableBetaCut", false, "Flag to enable TOF histograms with beta cut for debug"}; + Configurable enablePIDplot{"enablePIDplot", false, "Flag to enable PID histograms for debug"}; + Configurable enableEffPlots{"enableEffPlots", false, "Flag to enable histograms for efficiency debug."}; + Configurable enableNoTOFPlots{"enableNoTOFPlots", false, "Flag to enable histograms for TOF debug."}; + } outFlagOptions; - Configurable enablePIDplot{"enablePIDplot", false, "Flag to enable PID histograms for debug"}; Configurable enableDebug{"enableDebug", false, "Flag to enable histograms for debug"}; - Configurable enablePtSpectra{"enablePtSpectra", false, "Flag to enable histograms for efficiency debug."}; Configurable usenITSLayer{"usenITSLayer", false, "Flag to enable ITS layer hit"}; Configurable useHasTRDConfig{"useHasTRDConfig", 0, "No selections on TRD (0); With TRD (1); Without TRD (2)"}; Configurable massTOFConfig{"massTOFConfig", 0, "Estimate massTOF using beta with (0) TPC momentum (1) TOF expected momentum (2) p momentum."}; Configurable helium3Pt{"helium3Pt", 0, "Select use default pT (0) or use instead 2*pT (1) for helium-3"}; - Configurable DeuteronPt{"DeuteronPt", 0, "Select (0) to apply deuteron pT shift or (1) to use default pT."}; - Configurable antiDeuteronPt{"antiDeuteronPt", 0, "Select (0) to apply antideuteron pT shift or (1) to use default pT."}; + Configurable unableDPtShift{"unableDPtShift", 0, "Select (0) to apply deuteron pT shift or (1) to use default pT."}; + Configurable unableAntiDPtShift{"unableAntiDPtShift", 0, "Select (0) to apply antideuteron pT shift or (1) to use default pT."}; // Additional function used for pT-shift calibration TF1* fShiftPtHe = 0; @@ -194,30 +202,30 @@ struct LFNucleiBATask { TF1* fShiftAntiD = 0; TF1* fShiftD = 0; - Configurable enablePtShiftAntiD{"enablePtShiftAntiD", true, "Flag to enable Pt shift (for antiDeuteron only)"}; Configurable enablePtShiftD{"enablePtShiftD", true, "Flag to enable Pt shift (for Deuteron only)"}; - Configurable> parShiftPtAntiD{"parShiftPtAntiD", {-0.0955412, 0.798164, -0.536111, 0.0887876, -1.11022e-13}, "Parameters for Pt shift (if enabled)."}; + Configurable enablePtShiftAntiD{"enablePtShiftAntiD", true, "Flag to enable Pt shift (for antiDeuteron only)"}; Configurable> parShiftPtD{"parShiftPtD", {-0.0955412, 0.798164, -0.536111, 0.0887876, -1.11022e-13}, "Parameters for Pt shift (if enabled)."}; + Configurable> parShiftPtAntiD{"parShiftPtAntiD", {-0.0955412, 0.798164, -0.536111, 0.0887876, -1.11022e-13}, "Parameters for Pt shift (if enabled)."}; - Configurable enablePtShift{"enablePtShift", false, "Flag to enable Pt shift (for He only)"}; + Configurable enablePtShiftHe{"enablePtShiftHe", false, "Flag to enable Pt shift (for He only)"}; 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> parShiftPtAntiHe{"parShiftPtAntiHe", {0.0f, 0.1f, 0.1f, 0.1f, 0.1f}, "Parameters for anti-helium3-Pt shift (if enabled)."}; Configurable enableCentrality{"enableCentrality", true, "Flag to enable centrality 3D histos)"}; // PDG codes and masses used in this analysis - static constexpr int PDGPion = 211; - static constexpr int PDGKaon = 321; - static constexpr int PDGProton = 2212; - static constexpr int PDGDeuteron = 1000010020; - static constexpr int PDGTriton = 1000010030; - static constexpr int PDGHelium = 1000020030; - static constexpr int PDGAlpha = 1000020040; - static constexpr float MassProtonVal = 0.938272088f; - static constexpr float MassDeuteronVal = 1.87561f; - static constexpr float MassTritonVal = 2.80892f; - static constexpr float MassHeliumVal = 2.80839f; - static constexpr float MassAlphaVal = 3.72738f; + static constexpr int PDGPion = PDG_t::kPiPlus; + static constexpr int PDGKaon = PDG_t::kKPlus; + static constexpr int PDGProton = PDG_t::kProton; + static constexpr int PDGDeuteron = o2::constants::physics::Pdg::kDeuteron; + static constexpr int PDGTriton = o2::constants::physics::Pdg::kTriton; + static constexpr int PDGHelium = o2::constants::physics::Pdg::kHelium3; + static constexpr int PDGAlpha = o2::constants::physics::Pdg::kAlpha; + static constexpr float MassProtonVal = o2::constants::physics::MassProton; + static constexpr float MassDeuteronVal = o2::constants::physics::MassDeuteron; + static constexpr float MassTritonVal = o2::constants::physics::MassTriton; + static constexpr float MassHeliumVal = o2::constants::physics::MassHelium3; + static constexpr float MassAlphaVal = o2::constants::physics::MassAlpha; template float averageClusterSizeTrk(const TrackType& track) @@ -241,8 +249,11 @@ struct LFNucleiBATask { } } - void init(o2::framework::InitContext&) + void init(o2::framework::InitContext& context) { + if (initITSPID) { + o2::aod::ITSResponse::setParameters(context); + } if (skimmingOptions.applySkimming) { zorroSummary.setObject(zorro.getZorroSummary()); } @@ -324,7 +335,7 @@ struct LFNucleiBATask { hSkim->GetXaxis()->SetBinLabel(1, "Total"); hSkim->GetXaxis()->SetBinLabel(2, "Skimmed events"); - histos.add("event/eventSelection", "eventSelection", HistType::kTH1D, {{7, -0.5, 6.5}}); + histos.add("event/eventSelection", "eventSelection", HistType::kTH1D, {{8, -0.5, 7.5}}); auto h = histos.get(HIST("event/eventSelection")); if (skimmingOptions.applySkimming) h->GetXaxis()->SetBinLabel(1, "Skimmed events"); @@ -336,9 +347,10 @@ struct LFNucleiBATask { h->GetXaxis()->SetBinLabel(5, "TVX + TF + ITS ROF"); h->GetXaxis()->SetBinLabel(6, "Sel8 cut"); h->GetXaxis()->SetBinLabel(7, "Z-vert Cut"); + h->GetXaxis()->SetBinLabel(8, "Multiplicity cut"); histos.add("event/h1VtxZ", "V_{z};V_{z} (in cm); counts", HistType::kTH1F, {{1500, -15, 15}}); - if (enablePIDplot) { + if (outFlagOptions.enablePIDplot) { histos.add("tracks/h1pT", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{500, 0., 10.}}); histos.add("tracks/h1p", "Track momentum; p (GeV/#it{c}); counts", HistType::kTH1F, {{500, 0., 10.}}); } @@ -350,7 +362,7 @@ struct LFNucleiBATask { histos.add("qa/h1chi2ITS", "#chi^{2}_{ITS}/n_{ITS}; #chi^{2}_{ITS}/n_{ITS};counts", HistType::kTH1F, {{51, -0.5, 50.5}}); histos.add("qa/h1chi2TPC", "#chi^{2}_{TPC}/n_{TPC}; #chi^{2}_{TPC}/n_{TPC}; counts", HistType::kTH1F, {{11, -0.5, 10.5}}); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.add("tracks/eff/h2pVsTPCmomentum", "#it{p}_{TPC} vs #it{p}; #it{p}_{TPC}; #it{p}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); if (outFlagOptions.doTOFplots) histos.add("tracks/eff/h2TPCmomentumVsTOFExpMomentum", "#it{p}_{TOF} vs #it{p}_{TPC}; #it{p}_{TOF}; #it{p}_{TPC}", HistType::kTH2F, {{200, 0.f, 8.f}, {200, 0.f, 8.f}}); @@ -406,7 +418,7 @@ struct LFNucleiBATask { debugHistos.add("debug/tracks/h2PionYvsPt", "#it{y} vs #it{p}_{T} (#pi)", HistType::kTH2F, {{200, -2.0, 2.0}, {ptAxis}}); } - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { if (enableDebug) { debugHistos.add("tracks/eff/hPtP", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); debugHistos.add("tracks/eff/hPtantiP", "Track #it{p}_{T}; #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); @@ -461,16 +473,12 @@ struct LFNucleiBATask { histos.add("tracks/dca/before/hDCAzVsPt", "DCAz vs Pt", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); if (enablePr) { - // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtProton", "DCAxy vs DCAz vs Pt/z (p)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/proton/dca/before/hDCAxyVsDCAzVsPtantiProton", "DCAxy vs DCAz vs Pt/z (#bar{p})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtProton", "DCAxy vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAxyVsPtantiProton", "DCAxy vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtProton", "DCAz vs Pt (p)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/proton/dca/before/hDCAzVsPtantiProton", "DCAz vs Pt (#bar{p})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); } if (enableDe) { - // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtDeuteron", "DCAxy vs DCAz vs Pt/z (d)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/deuteron/dca/before/hDCAxyVsDCAzVsPtantiDeuteron", "DCAxy vs DCAz vs Pt/z (#bar{d})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); if (enableCentrality) { histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronVsMult", "DCAxy vs Pt (d)", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronVsMult", "DCAxy vs Pt (#bar{d})", HistType::kTH3F, {{ptAxis}, {dcaxyAxis}, {binsPercentile}}); @@ -481,14 +489,14 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteron", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); - histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + if (outFlagOptions.enableNoTOFPlots) { + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF", "DCAxy vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF", "DCAxy vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF", "DCAz vs Pt (d)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + histos.add("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF", "DCAz vs Pt (#bar{d})", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); + } } if (enableTr) { - // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtTriton", "DCAxy vs DCAz vs Pt/z (t)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); - // histos.add("tracks/triton/dca/before/hDCAxyVsDCAzVsPtantiTriton", "DCAxy vs DCAz vs Pt/z (#bar{t})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtHe}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtTriton", "DCAxy vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAxyVsPtantiTriton", "DCAxy vs Pt (#bar{t})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/triton/dca/before/hDCAzVsPtTriton", "DCAz vs Pt (t)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -502,10 +510,12 @@ struct LFNucleiBATask { histos.add("tracks/helium/dca/before/hDCAzVsPtHelium", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); histos.add("tracks/helium/dca/before/hDCAzVsPtantiHelium", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); - histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + if (outFlagOptions.enableNoTOFPlots) { + histos.add("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF", "DCAxy vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF", "DCAxy vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF", "DCAz vs Pt (He)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + histos.add("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF", "DCAz vs Pt (#bar{He})", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); + } if (outFlagOptions.doTOFplots) { histos.add("tracks/helium/dca/before/TOF/hDCAxyVsDCAzVsPtHelium", "DCAxy vs DCAz vs Pt/z (He) (w/TOF); DCAxy; DCAz", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); @@ -517,8 +527,6 @@ struct LFNucleiBATask { } } if (enableAl) { - // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtAlpha", "DCAxy vs DCAz vs Pt/z (#alpha)", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); - // histos.add("tracks/alpha/dca/before/hDCAxyVsDCAzVsPtantiAlpha", "DCAxy vs DCAz vs Pt/z (#bar{#alpha})", HistType::kTH3F, {{140, -0.7f, 0.7f}, {160, -0.8f, 0.8f}, {binsPtZHe}}); histos.add("tracks/alpha/dca/before/hDCAxyVsPtAlpha", "DCAxy vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/before/hDCAxyVsPtantiAlpha", "DCAxy vs Pt (#bar{#alpha})", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/alpha/dca/before/hDCAzVsPtAlpha", "DCAz vs Pt (#alpha)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -598,20 +606,20 @@ struct LFNucleiBATask { histos.add("tracks/triton/h1antiTritonSpectra", "#it{p}_{T} (#bar{t})", HistType::kTH1F, {ptAxis}); } if (enableHe) { - histos.add("tracks/helium/h1HeliumSpectra", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectra", "#it{p}_{T}/z (#bar{He})", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectra", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectra", "#it{p}_{T}/z (#bar{He})", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h2HeliumYvsPt", "#it{y} vs #it{p}_{T}/z (He)", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); + // histos.add("tracks/helium/h2HeliumYvsPt", "#it{y} vs #it{p}_{T}/z (He)", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); histos.add("tracks/helium/h2HeliumYvsPt_Z2", "#it{y} vs #it{p}_{T} (He)", HistType::kTH2F, {{96, -1.2, 1.2}, {ptHeAxis}}); - histos.add("tracks/helium/h2HeliumEtavsPt", "#it{#eta} vs #it{p}_{T}/z (He)", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); + // histos.add("tracks/helium/h2HeliumEtavsPt", "#it{#eta} vs #it{p}_{T}/z (He)", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); histos.add("tracks/helium/h2HeliumEtavsPt_Z2", "#it{#eta} vs #it{p}_{T} (He)", HistType::kTH2F, {{96, -1.2, 1.2}, {ptHeAxis}}); 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}); - histos.add("tracks/helium/h2antiHeliumYvsPt", "#it{y} vs #it{p}_{T}/z (#bar{He})", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); + // histos.add("tracks/helium/h2antiHeliumYvsPt", "#it{y} vs #it{p}_{T}/z (#bar{He})", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); histos.add("tracks/helium/h2antiHeliumYvsPt_Z2", "#it{y} vs #it{p}_{T} (#bar{He})", HistType::kTH2F, {{96, -1.2, 1.2}, {ptHeAxis}}); - histos.add("tracks/helium/h2antiHeliumEtavsPt", "#it{#eta} vs #it{p}_{T}/z (#bar{He})", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); + // histos.add("tracks/helium/h2antiHeliumEtavsPt", "#it{#eta} vs #it{p}_{T}/z (#bar{He})", HistType::kTH2F, {{96, -1.2, 1.2}, {ptZHeAxis}}); histos.add("tracks/helium/h2antiHeliumEtavsPt_Z2", "#it{#eta} vs #it{p}_{T} (#bar{He})", HistType::kTH2F, {{96, -1.2, 1.2}, {ptHeAxis}}); } if (enableAl) { @@ -811,11 +819,11 @@ struct LFNucleiBATask { histos.add("tracks/triton/h1antiTritonSpectraTrueTransport", "#it{p}_{T} (#bar{t})", HistType::kTH1F, {ptAxis}); } if (enableHe) { - histos.add("tracks/helium/h1HeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1HeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1HeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); histos.add("tracks/helium/h1HeliumSpectraTrue_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1HeliumSpectraTrueWPID_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); @@ -823,11 +831,11 @@ struct LFNucleiBATask { histos.add("tracks/helium/h1HeliumSpectraTrueSec_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1HeliumSpectraTrueTransport_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); - histos.add("tracks/helium/h1antiHeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrue", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrueWPID", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTruePrim", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrueSec", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); + // histos.add("tracks/helium/h1antiHeliumSpectraTrueTransport", "#it{p}_{T}/z (He)", HistType::kTH1F, {ptZHeAxis}); histos.add("tracks/helium/h1antiHeliumSpectraTrue_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/h1antiHeliumSpectraTrueWPID_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); @@ -839,12 +847,12 @@ struct LFNucleiBATask { histos.add("tracks/helium/TOF/h1HeliumSpectraTruePrim_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); histos.add("tracks/helium/TOF/h1antiHeliumSpectraTruePrim_Z2", "#it{p}_{T} (He)", HistType::kTH1F, {ptHeAxis}); } - if (enablePtSpectra) { - histos.add("tracks/eff/helium/hPtHeTrue", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); - histos.add("tracks/eff/helium/hPtantiHeTrue", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + if (outFlagOptions.enableEffPlots) { + histos.add("tracks/eff/helium/hPtHeTrue_Z2", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/helium/hPtantiHeTrue_Z2", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); if (outFlagOptions.doTOFplots) { - histos.add("tracks/eff/helium/hPtHeTOFTrue", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); - histos.add("tracks/eff/helium/hPtantiHeTOFTrue", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/helium/hPtHeTOFTrue_Z2", "Track #it{p}_{T} (He); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); + histos.add("tracks/eff/helium/hPtantiHeTOFTrue_Z2", "Track #it{p}_{T} (#bar{He}); #it{p}_{T} (GeV/#it{c}); counts", HistType::kTH1F, {{400, 0., 8.}}); } } } @@ -944,12 +952,14 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtDeuteronTrueMaterial", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/hDCAxyVsPtantiDeuteronTrueMaterial", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); } if (outFlagOptions.doTOFplots) { @@ -987,12 +997,14 @@ struct LFNucleiBATask { histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTruePrim", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueSec", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueTransport", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtDeuteronTrueMaterial", "DCAxy vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrue", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTruePrim", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueSec", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueTransport", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); + histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAxyVsPtantiDeuteronTrueMaterial", "DCAxy vs Pt (#bar{d}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptAxis}, {dcaxyAxis}}); histos.add("tracks/deuteron/dca/before/fake/TOF/hDCAzVsPtDeuteronTrue", "DCAz vs Pt (d); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptAxis}, {dcazAxis}}); @@ -1179,12 +1191,14 @@ struct LFNucleiBATask { histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTruePrim", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueSec", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueMaterial", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtHeliumTrueTransport", "DCAxy vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrue", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTruePrim", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueSec", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); + histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueMaterial", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAxyVsPtantiHeliumTrueTransport", "DCAxy vs Pt (#bar{He}); #it{p}_{T} (GeV/#it{c}); DCAxy (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcaxyAxis}}); histos.add("tracks/helium/dca/before/fake/hDCAzVsPtHeliumTrue", "DCAz vs Pt (He); #it{p}_{T} (GeV/#it{c}); DCAz (cm)", HistType::kTH2F, {{ptZHeAxis}, {dcazAxis}}); @@ -1509,7 +1523,8 @@ struct LFNucleiBATask { } // Bethe-Bloch TPC distribution and Beta vs pT TOF distribution - if (nsigmaITSvar.showAverageClusterSize && enablePIDplot) { + if (nsigmaITSvar.showAverageClusterSize && outFlagOptions.enablePIDplot) { + histos.add("tracks/avgClusterSizePerCoslInvVsITSlayers", "", HistType::kTH3F, {{pZAxis}, {avClsEffAxis}, {8, -0.5, 7.5}}); histos.add("tracks/averageClusterSize", "", HistType::kTH2F, {{pZAxis}, {avClsAxis}}); histos.add("tracks/averageClusterSizePerCoslInv", "", HistType::kTH2F, {{pZAxis}, {avClsEffAxis}}); } @@ -1517,27 +1532,27 @@ struct LFNucleiBATask { debugHistos.add("debug/h2TPCsignVsTPCmomentum_AllTracks", "TPC <-dE/dX> vs #it{p}/Z (w/o rejection); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); debugHistos.add("debug/h2TPCsignVsTPCmomentum_FakeHits", "TPC <-dE/dX> vs #it{p}/Z (Fake hits); Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); } - if (enablePIDplot) { + if (outFlagOptions.enablePIDplot) { histos.add("tracks/h2TPCsignVsTPCmomentum", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, -8.f, 8.f}, {dedxAxis}}); if (enablePr) { - histos.add("tracks/proton/h2TPCsignVsTPCmomentumProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/proton/h2TPCsignVsTPCmomentumantiProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/proton/h2TPCsignVsTPCmomentumProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/proton/h2TPCsignVsTPCmomentumantiProton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableDe) { - histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableTr) { - histos.add("tracks/triton/h2TPCsignVsTPCmomentumTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/triton/h2TPCsignVsTPCmomentumantiTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/triton/h2TPCsignVsTPCmomentumTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/triton/h2TPCsignVsTPCmomentumantiTriton", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableHe) { - histos.add("tracks/helium/h2TPCsignVsTPCmomentumHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/helium/h2TPCsignVsTPCmomentumantiHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/helium/h2TPCsignVsTPCmomentumHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/helium/h2TPCsignVsTPCmomentumantiHelium", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } if (enableAl) { - histos.add("tracks/alpha/h2TPCsignVsTPCmomentumAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); - histos.add("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{400, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/alpha/h2TPCsignVsTPCmomentumAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); + histos.add("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha", "TPC <-dE/dX> vs #it{p}/Z; Signed #it{p} (GeV/#it{c}); TPC <-dE/dx> (a.u.)", HistType::kTH2F, {{200, 0.f, 8.f}, {dedxAxis}}); } } @@ -1548,7 +1563,7 @@ struct LFNucleiBATask { } } - if (outFlagOptions.doTOFplots && enablePIDplot) { + 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/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) @@ -1582,6 +1597,11 @@ struct LFNucleiBATask { histos.add("tracks/proton/h2antiProtonVspTNSigmaTPC", "NSigmaTPC(#bar{p}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {sigmaTPCAxis}}); } if (enableDe) { + histos.add("tracks/deuteron/h2DeuteronVspNSigmaITSDe", "NSigmaITS(d) vs p/z; #it{p}/z (GeV/#it{c}); NSigmaITS(d)", HistType::kTH2F, {{pZAxis}, {sigmaITSAxis}}); + histos.add("tracks/deuteron/h2antiDeuteronVspNSigmaITSDe", "NSigmaITS(#bar{d}) vs p/z; #it{p}/z (GeV/#it{c}); NSigmaITS(#bar{d})", HistType::kTH2F, {{pZAxis}, {sigmaITSAxis}}); + histos.add("tracks/deuteron/h2DeuteronVspNSigmaITSDe_wTPCpid", "NSigmaITS(d) vs p/z; #it{p}/z (GeV/#it{c}); NSigmaITS(d)", HistType::kTH2F, {{pZAxis}, {sigmaITSAxis}}); + histos.add("tracks/deuteron/h2antiDeuteronVspNSigmaITSDe_wTPCpid", "NSigmaITS(#bar{d}) vs p/z; #it{p}/z (GeV/#it{c}); NSigmaITS(#bar{d})", HistType::kTH2F, {{pZAxis}, {sigmaITSAxis}}); + if (enableCentrality) { histos.add("tracks/deuteron/h3DeuteronVspTNSigmaTPCVsMult", "NSigmaTPC(d) vs pT; #it{p}_{T} (GeV/#it{c}) vs mult; NSigmaTPC", HistType::kTH3F, {{ptAxis}, {sigmaTPCAxis}, {binsPercentile}}); histos.add("tracks/deuteron/h3antiDeuteronVspTNSigmaTPCVsMult", "NSigmaTPC(#bar{d}) vs pT; #it{p}_{T} (GeV/#it{c}) vs mult; NSigmaTPC", HistType::kTH3F, {{ptAxis}, {sigmaTPCAxis}, {binsPercentile}}); @@ -1593,9 +1613,6 @@ struct LFNucleiBATask { } } if (enableTr) { - // histos.add("tracks/triton/h2TritonVspTNSigmaITS", "NSigmaITS(t) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaITS", HistType::kTH2F, {{ptAxis}, {sigmaITSAxis}}); - // histos.add("tracks/triton/h2antiTritonVspTNSigmaITS", "NSigmaITS(#bar{t}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaITS", HistType::kTH2F, {{ptAxis}, {sigmaITSAxis}}); - histos.add("tracks/triton/h2TritonVspTNSigmaTPC", "NSigmaTPC(t) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {sigmaTPCAxis}}); histos.add("tracks/triton/h2antiTritonVspTNSigmaTPC", "NSigmaTPC(#bar{t}) vs pT; #it{p}_{T} (GeV/#it{c}); NSigmaTPC", HistType::kTH2F, {{ptAxis}, {sigmaTPCAxis}}); } @@ -1679,7 +1696,7 @@ struct LFNucleiBATask { histos.add("tracks/helium/h2antiHeliumVspTNSigmaTOF", "NSigmaTOF(#bar{He}) vs #it{p}_{T}/z; #it{p}_{T}/z (GeV/#it{c}); NSigmaTOF", HistType::kTH2F, {{ptZHeAxis}, {sigmaTOFAxis}}); } // TOF mass histograms - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.add("tracks/h2TOFmassVsPt", "h2TOFmassVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); if (enablePr) { histos.add("tracks/proton/h2TOFmassProtonVsPt", "h2TOFmassProtonVsPt; TOFmass; #it{p}_{T} (GeV)", HistType::kTH2F, {{180, 0.4, 4.}, {250, 0., 5.}}); @@ -2098,7 +2115,7 @@ struct LFNucleiBATask { if constexpr (!IsFilteredData) { if (!event.selection_bit(aod::evsel::kIsTriggerTVX)) { - if (evselOptions.TVXtrigger) + if (evselOptions.useTVXtrigger) return; } else { histos.fill(HIST("event/eventSelection"), 1); @@ -2136,24 +2153,24 @@ struct LFNucleiBATask { if (enableDebug) debugHistos.fill(HIST("qa/h1VtxZ_sel8"), event.posZ()); - if (enableCentrality) { - if (event.centFT0M() < cfgLowMultCut || event.centFT0M() > cfgHighMultCut) { - return; - } - if (enableDebug) - debugHistos.fill(HIST("event/h1VtxZ_Centrality"), event.posZ()); - } - - if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) + if (event.posZ() < cfgVzCutLow || event.posZ() > cfgVzCutHigh) return; histos.fill(HIST("event/eventSelection"), 6); } else { - if (event.posZ() < cfgLowCutVertex || event.posZ() > cfgHighCutVertex) + if (event.posZ() < cfgVzCutLow || event.posZ() > cfgVzCutHigh) return; if (evselOptions.removeTFBorder && !event.selection_bit(aod::evsel::kNoTimeFrameBorder)) return; } + if (event.centFT0M() <= cfgMultCutLow || event.centFT0M() > cfgMultCutHigh) { + return; + } + 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; @@ -2174,6 +2191,7 @@ struct LFNucleiBATask { } auto tracksWithITS = soa::Attach(tracks); if (tracksWithITS.size() != tracks.size()) { @@ -2189,6 +2207,12 @@ struct LFNucleiBATask { } } std::bitset<8> itsClusterMap = track.itsClusterMap(); + + if constexpr (!IsFilteredData) { + if (nsigmaITSvar.showAverageClusterSize && outFlagOptions.enablePIDplot) + histos.fill(HIST("tracks/avgClusterSizePerCoslInvVsITSlayers"), track.p(), averageClusterSizePerCoslInv(track), track.itsNCls()); + } + if (track.itsNCls() < trkqcOptions.cfgCutITSClusters) continue; if (track.tpcNClsCrossedRows() < trkqcOptions.cfgCutTPCXRows) @@ -2204,7 +2228,14 @@ struct LFNucleiBATask { if ((track.itsChi2NCl() < itsChi2NclRange[0]) || (track.itsChi2NCl() > itsChi2NclRange[1])) continue; - if (enablePIDplot) { + // p cut + if (std::abs(track.tpcInnerParam()) < kinemOptions.cfgMomentumCut) + continue; + // eta cut + if (std::abs(track.eta()) > kinemOptions.cfgEtaCut) + continue; + + if (outFlagOptions.enablePIDplot) { histos.fill(HIST("tracks/h1pT"), track.pt()); histos.fill(HIST("tracks/h1p"), track.p()); } @@ -2214,15 +2245,15 @@ struct LFNucleiBATask { float shiftPtPos = 0.f; float shiftPtNeg = 0.f; - if (enablePtShift && !fShiftPtHe) { + if (enablePtShiftHe && !fShiftPtHe) { fShiftPtHe = new TF1("fShiftPtHe", "[0] * TMath::Exp([1] + [2] * x) + [3] + [4] * x", 0.f, 8.f); auto par = (std::vector)parShiftPtHe; fShiftPtHe->SetParameters(par[0], par[1], par[2], par[3], par[4]); } - if (enablePtShift && !fShiftPtantiHe) { + if (enablePtShiftHe && !fShiftPtantiHe) { fShiftPtantiHe = new TF1("fShiftPtantiHe", "[0] * TMath::Exp([1] + [2] * x) + [3] + [4] * x", 0.f, 8.f); - auto par = (std::vector)parShiftPtantiHe; + auto par = (std::vector)parShiftPtAntiHe; fShiftPtantiHe->SetParameters(par[0], par[1], par[2], par[3], par[4]); } @@ -2232,7 +2263,7 @@ struct LFNucleiBATask { fShiftAntiD->SetParameters(par[0], par[1], par[2], par[3], par[4]); } - switch (antiDeuteronPt) { + switch (unableAntiDPtShift) { case 0: if (enablePtShiftAntiD && fShiftAntiD) { auto shiftAntiD = fShiftAntiD->Eval(track.pt()); @@ -2250,7 +2281,7 @@ struct LFNucleiBATask { fShiftD->SetParameters(par[0], par[1], par[2], par[3], par[4]); } - switch (DeuteronPt) { + switch (unableDPtShift) { case 0: if (enablePtShiftD && fShiftD) { auto shiftD = fShiftD->Eval(track.pt()); @@ -2265,12 +2296,12 @@ struct LFNucleiBATask { switch (helium3Pt) { case 0: hePt = track.pt(); - if (enablePtShift && fShiftPtHe) { + if (enablePtShiftHe && fShiftPtHe) { shiftPtPos = fShiftPtHe->Eval(2 * track.pt()); hePt = track.pt() - shiftPtPos / 2.f; } antihePt = track.pt(); - if (enablePtShift && fShiftPtantiHe) { + if (enablePtShiftHe && fShiftPtantiHe) { shiftPtNeg = fShiftPtantiHe->Eval(2 * track.pt()); antihePt = track.pt() - shiftPtNeg / 2.f; } @@ -2281,9 +2312,14 @@ struct LFNucleiBATask { break; } + // float nITSDe_Table = 99.f; + float nITSDe = 99.f; float nITSTr = 99.f; float nITSHe = 99.f; + // o2::aod::ITSResponse itsResponse; + if (!IsFilteredData) { + nITSDe = track.itsNSigmaDe(); nITSTr = track.itsNSigmaTr(); nITSHe = track.itsNSigmaHe(); } @@ -2345,20 +2381,20 @@ struct LFNucleiBATask { bool passDCAxyzCut = false; - switch (dcaConfOptions.DCACustomConfig) { + switch (dcaConfOptions.cfgCustomDCA) { case 0: - passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - - passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - - passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); - passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); - passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + + passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + + passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); + passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); + passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); break; case 1: passDCAxyCut = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(track.pt(), parDCAxy[2]))); @@ -2376,45 +2412,45 @@ struct LFNucleiBATask { break; case 2: passDCAxyCut = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(track.pt(), parDCAxy[2]))); - passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCut = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutDe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(DPt, parDCAxy[2]))); - passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(antiDPt, parDCAxy[2]))); - passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutHe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(hePt, parDCAxy[2]))); - passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(antihePt, parDCAxy[2]))); - passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.DCAzCustomCut); + passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= dcaConfOptions.cfgCustomDCAz); break; case 3: - passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCut = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCut = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(track.pt(), parDCAz[2]))); - passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutDe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(DPt, parDCAz[2]))); - passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutAntiDe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutAntiDe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(antiDPt, parDCAz[2]))); - passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutHe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(hePt, parDCAz[2]))); - passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.DCAxyCustomCut); + passDCAxyCutAntiHe = (std::abs(track.dcaXY()) <= dcaConfOptions.cfgCustomDCAxy); passDCAzCutAntiHe = (std::abs(track.dcaZ()) <= parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(antihePt, parDCAz[2]))); break; case 4: - passDCAxyCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - - passDCAxyCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAxyCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - - passDCAxyCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAxyCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; - passDCAzCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.DCAxyCustomCut, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.DCAzCustomCut, 2) <= 1; + passDCAxyCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCut = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + + passDCAxyCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAxyCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutAntiDe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + + passDCAxyCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAxyCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; + passDCAzCutAntiHe = std::pow(track.dcaXY(), 2) / std::pow(dcaConfOptions.cfgCustomDCAxy, 2) + std::pow(track.dcaZ(), 2) / std::pow(dcaConfOptions.cfgCustomDCAz, 2) <= 1; break; case 5: passDCAxyCut = std::pow(track.dcaXY(), 2) / std::pow(parDCAxy[3] * (parDCAxy[0] + parDCAxy[1] / std::pow(track.pt(), parDCAxy[2])), 2) + std::pow(track.dcaZ(), 2) / std::pow(parDCAz[3] * (parDCAz[0] + parDCAz[1] / std::pow(track.pt(), parDCAz[2])), 2) <= 1; @@ -2432,19 +2468,12 @@ struct LFNucleiBATask { break; } - // p cut - if (std::abs(track.tpcInnerParam()) < kinemOptions.pCut) - continue; - // eta cut - if (std::abs(track.eta()) > kinemOptions.etaCut) - continue; - // Rapidity cuts - prRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) < kinemOptions.yHighCut; - deRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) < kinemOptions.yHighCut; - 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; - alRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) > kinemOptions.yLowCut && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) < kinemOptions.yHighCut; + prRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)) < kinemOptions.cfgRapidityCutHigh; + deRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)) < kinemOptions.cfgRapidityCutHigh; + trRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Triton)) < kinemOptions.cfgRapidityCutHigh; + heRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)) < kinemOptions.cfgRapidityCutHigh; + alRapCut = track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) > kinemOptions.cfgRapidityCutLow && track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Alpha)) < kinemOptions.cfgRapidityCutHigh; isDeuteron = enableDe && deRapCut; isHelium = enableHe && heRapCut; @@ -2452,6 +2481,10 @@ struct LFNucleiBATask { isAntiDe = isDeuteron && track.sign() < 0; // nSigmaITSHe cut + if (nsigmaITSvar.useITSDeCut && (nITSDe <= nsigmaITSvar.nsigmaITSDe)) { + continue; + } + if (nsigmaITSvar.useITSHeCut && (nITSHe <= nsigmaITSvar.nsigmaITSHe)) { continue; } @@ -2544,19 +2577,19 @@ struct LFNucleiBATask { if (isDeWoDCAzWTPCpid) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteron"), DPt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtDeuteronNoTOF"), DPt, track.dcaZ()); } if (isAntiDeWoDCAzWTPCpid) { histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteron"), antiDPt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAzVsPtantiDeuteronNoTOF"), antiDPt, track.dcaZ()); } if (isHeWoDCAzWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHelium"), hePt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtHeliumNoTOF"), hePt, track.dcaZ()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtHelium"), hePt, track.dcaZ()); @@ -2565,7 +2598,7 @@ struct LFNucleiBATask { if (isAntiHeWoDCAzWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAzVsPtantiHeliumNoTOF"), hePt, track.dcaZ()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAzVsPtantiHelium"), antihePt, track.dcaZ()); @@ -3040,7 +3073,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronVsMult"), DPt, track.dcaXY(), event.centFT0M()); else histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteron"), DPt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtDeuteronNoTOF"), DPt, track.dcaXY()); } if (isAntiDeWoDCAxyWTPCpid) { @@ -3050,13 +3083,13 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronVsMult"), antiDPt, track.dcaXY(), event.centFT0M()); else histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteron"), antiDPt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/deuteron/dca/before/hDCAxyVsPtantiDeuteronNoTOF"), antiDPt, track.dcaXY()); } if (isHeWoDCAxyWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHelium"), hePt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtHeliumNoTOF"), hePt, track.dcaXY()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtHelium"), hePt, track.dcaXY()); @@ -3064,7 +3097,7 @@ struct LFNucleiBATask { } if (isAntiHeWoDCAxyWTPCpid) { histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); - if (!track.hasTOF()) + if (!track.hasTOF() && (outFlagOptions.enableNoTOFPlots)) histos.fill(HIST("tracks/helium/dca/before/hDCAxyVsPtantiHeliumNoTOF"), antihePt, track.dcaXY()); if (track.hasTOF() && outFlagOptions.doTOFplots) { histos.fill(HIST("tracks/helium/dca/before/TOF/hDCAxyVsPtantiHelium"), antihePt, track.dcaXY()); @@ -3646,7 +3679,7 @@ struct LFNucleiBATask { // DCA Cut if constexpr (!IsFilteredData) { if (filterOptions.enableIsGlobalTrack) { - if (!enableDCACustomCut) { + if (!enableCustomDCACut) { if (!track.isGlobalTrack()) continue; } else { @@ -3798,7 +3831,7 @@ struct LFNucleiBATask { debugHistos.fill(HIST("debug/tracks/kaon/h2KaonVspTNSigmaTPC"), track.pt(), track.tpcNSigmaKa()); } - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/h2pVsTPCmomentum"), track.tpcInnerParam(), track.p()); if (filterOptions.enableFiltering) { @@ -3806,11 +3839,11 @@ struct LFNucleiBATask { continue; } - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TPCsignVsTPCmomentum"), track.tpcInnerParam() / (1.f * track.sign()), track.tpcSignal()); if constexpr (!IsFilteredData) { - if (nsigmaITSvar.showAverageClusterSize && enablePIDplot) { + if (nsigmaITSvar.showAverageClusterSize && outFlagOptions.enablePIDplot) { histos.fill(HIST("tracks/averageClusterSize"), track.p(), averageClusterSizeTrk(track)); histos.fill(HIST("tracks/averageClusterSizePerCoslInv"), track.p(), averageClusterSizePerCoslInv(track)); } @@ -3915,7 +3948,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0tof/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -3947,7 +3980,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -3979,7 +4012,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/tof/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/tof/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/tof/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -4013,7 +4046,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/fill/proton/h3ProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/fill/deuteron/h3DeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), DPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/fill/proton/h2ProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -4069,7 +4102,7 @@ struct LFNucleiBATask { evtimeHistos.fill(HIST("tracks/evtime/ft0tof/proton/h3antiProtonNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaPr(), track.tofNSigmaPr(), track.pt()); if (enableDe) evtimeHistos.fill(HIST("tracks/evtime/ft0tof/deuteron/h3antiDeuteronNSigmaTPCvsNSigmaTOFvsPt"), track.tpcNSigmaDe(), track.tofNSigmaDe(), antiDPt); - if (enableDebug && (track.beta() > betaCut)) { + if (enableDebug && (track.beta() > cfgBetaCut)) { if (enablePr) debugHistos.fill(HIST("debug/evtime/ft0tof/proton/h2antiProtonVspTNSigmaTPC_BetaCut"), track.pt(), track.tpcNSigmaPr()); if (enableDe) @@ -4185,6 +4218,8 @@ struct LFNucleiBATask { if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/deuteron/h2DeuteronTPCExpSignalDiffVsPt"), DPt, track.tpcExpSignalDiffDe()); + histos.fill(HIST("tracks/deuteron/h2DeuteronVspNSigmaITSDe"), track.p(), nITSDe); + switch (useHasTRDConfig) { case 0: if (enableCentrality) @@ -4208,6 +4243,8 @@ struct LFNucleiBATask { if (outFlagOptions.enableExpSignalTPC) histos.fill(HIST("tracks/deuteron/h2antiDeuteronTPCExpSignalDiffVsPt"), antiDPt, track.tpcExpSignalDiffDe()); + histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspNSigmaITSDe"), track.p(), nITSDe); + switch (useHasTRDConfig) { case 0: if (enableCentrality) @@ -4317,7 +4354,7 @@ struct LFNucleiBATask { if (passDCAxyzCut) { // PID - if (enablePtSpectra && enableDebug) { + if (outFlagOptions.enableEffPlots && enableDebug) { if (track.sign() > 0) { debugHistos.fill(HIST("tracks/eff/hPtP"), track.pt()); debugHistos.fill(HIST("tracks/eff/hPtPrebinned"), track.pt()); @@ -4330,7 +4367,7 @@ struct LFNucleiBATask { if (enablePr) { if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr && prRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtPr"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtPrrebinned"), track.pt()); histos.fill(HIST("tracks/eff/proton/h2pVsTPCmomentumPr"), track.tpcInnerParam(), track.p()); @@ -4339,10 +4376,10 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/proton/h2ProtonYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)), track.pt()); histos.fill(HIST("tracks/proton/h2ProtonEtavsPt"), track.eta(), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/proton/h2TPCsignVsTPCmomentumProton"), track.tpcInnerParam(), track.tpcSignal()); } else { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtantiPr"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtantiPrrebinned"), track.pt()); histos.fill(HIST("tracks/eff/proton/h2pVsTPCmomentumantiPr"), track.tpcInnerParam(), track.p()); @@ -4351,7 +4388,7 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/proton/h2antiProtonYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Proton)), track.pt()); histos.fill(HIST("tracks/proton/h2antiProtonEtavsPt"), track.eta(), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/proton/h2TPCsignVsTPCmomentumantiProton"), track.tpcInnerParam(), track.tpcSignal()); } } @@ -4359,20 +4396,20 @@ struct LFNucleiBATask { if (enableTr) { if ((isTritonTPCpid) && trRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/hPtTr"), track.pt()); histos.fill(HIST("tracks/eff/triton/h2pVsTPCmomentumTr"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/triton/h1TritonSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/triton/h2TPCsignVsTPCmomentumTriton"), track.tpcInnerParam(), track.tpcSignal()); } else { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/hPtantiTr"), track.pt()); histos.fill(HIST("tracks/eff/triton/h2pVsTPCmomentumantiTr"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/triton/h1antiTritonSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/triton/h2TPCsignVsTPCmomentumantiTriton"), track.tpcInnerParam(), track.tpcSignal()); } } @@ -4381,18 +4418,18 @@ struct LFNucleiBATask { if ((std::abs(track.tpcNSigmaAl()) < nsigmaTPCvar.nsigmaTPCAl) && alRapCut) { if (track.sign() > 0) { histos.fill(HIST("tracks/alpha/h1AlphaSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/alpha/h2TPCsignVsTPCmomentumAlpha"), track.tpcInnerParam(), track.tpcSignal()); } else { histos.fill(HIST("tracks/alpha/h1antiAlphaSpectra"), track.pt()); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/alpha/h2TPCsignVsTPCmomentumantiAlpha"), track.tpcInnerParam(), track.tpcSignal()); } } } if (outFlagOptions.doTOFplots && track.hasTOF()) { - if (enablePtSpectra && enableDebug) { + if (outFlagOptions.enableEffPlots && enableDebug) { if (track.sign() > 0) { debugHistos.fill(HIST("tracks/eff/hPtPTOF"), track.pt()); debugHistos.fill(HIST("tracks/eff/hPtPTOFrebinned"), track.pt()); @@ -4402,9 +4439,9 @@ struct LFNucleiBATask { } } - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut) && enablePIDplot) + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut) && outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TOFbetaVsP_BetaCut"), track.p() / (1.f * track.sign()), track.beta()); - if (enablePIDplot) { + if (outFlagOptions.enablePIDplot) { switch (useHasTRDConfig) { case 0: histos.fill(HIST("tracks/h2TOFbetaVsP"), track.p() / (1.f * track.sign()), track.beta()); @@ -4422,20 +4459,20 @@ struct LFNucleiBATask { } } - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/h2TPCmomentumVsTOFExpMomentum"), track.tofExpMom(), track.tpcInnerParam()); if (enablePr && prRapCut) { if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr && track.sign() > 0) { histos.fill(HIST("tracks/proton/h2ProtonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/h2pVsTOFExpMomentumPr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumPr"), track.tofExpMom(), track.tpcInnerParam()); } } if (std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr && track.sign() < 0) { histos.fill(HIST("tracks/proton/h2antiProtonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/h2pVsTOFExpMomentumantiPr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/proton/h2TPCmomentumVsTOFExpMomentumantiPr"), track.tofExpMom(), track.tpcInnerParam()); } @@ -4444,14 +4481,14 @@ struct LFNucleiBATask { if (enableTr && trRapCut) { if (isTritonTPCpid && track.sign() > 0) { histos.fill(HIST("tracks/triton/h2TritonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/h2pVsTOFExpMomentumTr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumTr"), track.tofExpMom(), track.tpcInnerParam()); } } if (isTritonTPCpid && track.sign() < 0) { histos.fill(HIST("tracks/triton/h2antiTritonTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/triton/h2pVsTOFExpMomentumantiTr"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/triton/h2TPCmomentumVsTOFExpMomentumantiTr"), track.tofExpMom(), track.tpcInnerParam()); } @@ -4476,65 +4513,71 @@ struct LFNucleiBATask { } if (isDeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/hPtDe"), DPt); histos.fill(HIST("tracks/eff/deuteron/h2pVsTPCmomentumDe"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/deuteron/h1DeuteronSpectra"), DPt); histos.fill(HIST("tracks/deuteron/h2DeuteronYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)), DPt); - if (enablePIDplot) + histos.fill(HIST("tracks/deuteron/h2DeuteronEtavsPt"), track.eta(), DPt); + histos.fill(HIST("tracks/deuteron/h2DeuteronVspNSigmaITSDe_wTPCpid"), track.p(), nITSDe); + + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/deuteron/h2TPCsignVsTPCmomentumDeuteron"), track.tpcInnerParam(), track.tpcSignal()); } if (isAntiDeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/hPtantiDe"), antiDPt); histos.fill(HIST("tracks/eff/deuteron/h2pVsTPCmomentumantiDe"), track.tpcInnerParam(), track.p()); } histos.fill(HIST("tracks/deuteron/h1antiDeuteronSpectra"), antiDPt); histos.fill(HIST("tracks/deuteron/h2antiDeuteronYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Deuteron)), antiDPt); - if (enablePIDplot) + histos.fill(HIST("tracks/deuteron/h2antiDeuteronEtavsPt"), track.eta(), antiDPt); + histos.fill(HIST("tracks/deuteron/h2antiDeuteronVspNSigmaITSDe_wTPCpid"), track.p(), nITSDe); + + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/deuteron/h2TPCsignVsTPCmomentumantiDeuteron"), track.tpcInnerParam(), track.tpcSignal()); } if (isHeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/hPtHe"), 2 * hePt); histos.fill(HIST("tracks/eff/helium/h2pVsTPCmomentumHe"), heTPCmomentum, heP); } - histos.fill(HIST("tracks/helium/h1HeliumSpectra"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectra"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectra_Z2"), 2 * hePt); - histos.fill(HIST("tracks/helium/h2HeliumYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), hePt); + // histos.fill(HIST("tracks/helium/h2HeliumYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), hePt); histos.fill(HIST("tracks/helium/h2HeliumYvsPt_Z2"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), 2 * hePt); - histos.fill(HIST("tracks/helium/h2HeliumEtavsPt"), track.eta(), hePt); + // histos.fill(HIST("tracks/helium/h2HeliumEtavsPt"), track.eta(), hePt); histos.fill(HIST("tracks/helium/h2HeliumEtavsPt_Z2"), track.eta(), 2 * hePt); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/helium/h2TPCsignVsTPCmomentumHelium"), heTPCmomentum, track.tpcSignal()); } if (isAntiHeWTPCpid) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/hPtantiHe"), 2 * antihePt); histos.fill(HIST("tracks/eff/helium/h2pVsTPCmomentumantiHe"), antiheTPCmomentum, antiheP); } - histos.fill(HIST("tracks/helium/h1antiHeliumSpectra"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectra"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectra_Z2"), 2 * antihePt); - histos.fill(HIST("tracks/helium/h2antiHeliumYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), antihePt); + // histos.fill(HIST("tracks/helium/h2antiHeliumYvsPt"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), antihePt); histos.fill(HIST("tracks/helium/h2antiHeliumYvsPt_Z2"), track.rapidity(o2::track::PID::getMass2Z(o2::track::PID::Helium3)), 2 * antihePt); - histos.fill(HIST("tracks/helium/h2antiHeliumEtavsPt"), track.eta(), antihePt); + // histos.fill(HIST("tracks/helium/h2antiHeliumEtavsPt"), track.eta(), antihePt); histos.fill(HIST("tracks/helium/h2antiHeliumEtavsPt_Z2"), track.eta(), 2 * antihePt); - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/helium/h2TPCsignVsTPCmomentumantiHelium"), antiheTPCmomentum, track.tpcSignal()); } if (outFlagOptions.doTOFplots && track.hasTOF()) { if (isDeWTPCpid) { histos.fill(HIST("tracks/deuteron/h2DeuteronTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/h2pVsTOFExpMomentumDe"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumDe"), track.tofExpMom(), track.tpcInnerParam()); } } if (isAntiDeWTPCpid) { histos.fill(HIST("tracks/deuteron/h2antiDeuteronTOFbetaVsP"), track.p(), track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/deuteron/h2pVsTOFExpMomentumantiDe"), track.tofExpMom(), track.p()); histos.fill(HIST("tracks/eff/deuteron/h2TPCmomentumVsTOFExpMomentumantiDe"), track.tofExpMom(), track.tpcInnerParam()); } @@ -4542,7 +4585,7 @@ struct LFNucleiBATask { if (isHeWTPCpid) { histos.fill(HIST("tracks/helium/h2HeliumTOFbetaVsP"), heP, track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/h2pVsTOFExpMomentumHe"), track.tofExpMom(), heP); histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumHe"), track.tofExpMom(), heTPCmomentum); } @@ -4550,7 +4593,7 @@ struct LFNucleiBATask { if (isAntiHeWTPCpid) { histos.fill(HIST("tracks/helium/h2antiHeliumTOFbetaVsP"), antiheP, track.beta()); - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/helium/h2pVsTOFExpMomentumantiHe"), track.tofExpMom(), antiheP); histos.fill(HIST("tracks/eff/helium/h2TPCmomentumVsTOFExpMomentumantiHe"), track.tofExpMom(), antiheTPCmomentum); } @@ -4574,7 +4617,7 @@ struct LFNucleiBATask { massTOFantihe = antiheP * std::sqrt(1.f / (track.beta() * track.beta()) - 1.f); break; } - if (passDCAxyzCut && outFlagOptions.doTOFplots && enablePIDplot) + if (passDCAxyzCut && outFlagOptions.doTOFplots && outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TPCsignVsBetaGamma"), (track.beta() * gamma) / (1.f * track.sign()), track.tpcSignal()); } else { massTOF = -99.f; @@ -4583,7 +4626,7 @@ struct LFNucleiBATask { } if (passDCAxyzCut) { - if (enablePIDplot) + if (outFlagOptions.enablePIDplot) histos.fill(HIST("tracks/h2TOFmassVsPt"), massTOF, track.pt()); if (filterOptions.enableEvTimeSplitting) { if (track.isEvTimeTOF() && track.isEvTimeT0AC()) { @@ -4600,13 +4643,13 @@ struct LFNucleiBATask { if (enablePr) { if ((std::abs(track.tpcNSigmaPr()) < nsigmaTPCvar.nsigmaTPCPr) && prRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtPrTOF"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtPrTOFrebinned"), track.pt()); } histos.fill(HIST("tracks/proton/h2TOFmassProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/proton/h2TOFmassProtonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2ProtonVsPt_BetaCut"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); } @@ -4624,13 +4667,13 @@ struct LFNucleiBATask { } } } else { - if (enablePtSpectra) { + if (outFlagOptions.enableEffPlots) { histos.fill(HIST("tracks/eff/proton/hPtantiPrTOF"), track.pt()); histos.fill(HIST("tracks/eff/proton/hPtantiPrTOFrebinned"), track.pt()); } histos.fill(HIST("tracks/proton/h2TOFmassantiProtonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/proton/h2TOFmassantiProtonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/proton/h2TOFmass2antiProtonVsPt_BetaCut"), massTOF * massTOF - MassProtonVal * MassProtonVal, track.pt()); } @@ -4654,20 +4697,20 @@ struct LFNucleiBATask { if (enableTr) { if ((isTritonTPCpid) && trRapCut) { if (track.sign() > 0) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/triton/hPtTrTOF"), track.pt()); histos.fill(HIST("tracks/triton/h2TOFmassTritonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/triton/h2TOFmassTritonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2TritonVsPt_BetaCut"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); } } else { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/triton/hPtantiTrTOF"), track.pt()); histos.fill(HIST("tracks/triton/h2TOFmassantiTritonVsPt"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2antiTritonVsPt"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/triton/h2TOFmassantiTritonVsPt_BetaCut"), massTOF, track.pt()); histos.fill(HIST("tracks/triton/h2TOFmass2antiTritonVsPt_BetaCut"), massTOF * massTOF - MassTritonVal * MassTritonVal, track.pt()); } @@ -4677,14 +4720,14 @@ struct LFNucleiBATask { } if (isDeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/deuteron/hPtDeTOF"), DPt); histos.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt"), massTOF, DPt); if (enableCentrality) histos.fill(HIST("tracks/deuteron/h3TOFmass2DeuteronVsPtVsMult"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, DPt, event.centFT0M()); else histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, DPt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassDeuteronVsPt_BetaCut"), massTOF, DPt); histos.fill(HIST("tracks/deuteron/h2TOFmass2DeuteronVsPt_BetaCut"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, DPt); } @@ -4703,14 +4746,14 @@ struct LFNucleiBATask { } } if (isAntiDeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/deuteron/hPtantiDeTOF"), antiDPt); histos.fill(HIST("tracks/deuteron/h2TOFmassantiDeuteronVsPt"), massTOF, antiDPt); if (enableCentrality) histos.fill(HIST("tracks/deuteron/h3TOFmass2antiDeuteronVsPtVsMult"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, antiDPt, event.centFT0M()); else histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, antiDPt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/deuteron/h2TOFmassantiDeuteronVsPt_BetaCut"), massTOF, antiDPt); histos.fill(HIST("tracks/deuteron/h2TOFmass2antiDeuteronVsPt_BetaCut"), massTOF * massTOF - MassDeuteronVal * MassDeuteronVal, antiDPt); } @@ -4730,12 +4773,12 @@ struct LFNucleiBATask { } if (isHeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/helium/hPtHeTOF"), 2 * hePt); histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt"), 2.f * massTOFhe, hePt); histos.fill(HIST("tracks/helium/h2TOFmassDeltaHeliumVsPt"), 2.f * massTOFhe - MassHeliumVal, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt"), 2.f * massTOFhe * 2.f * massTOFhe - MassHeliumVal * MassHeliumVal, hePt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassHeliumVsPt_BetaCut"), 2.f * massTOFhe, hePt); histos.fill(HIST("tracks/helium/h2TOFmass2HeliumVsPt_BetaCut"), 2.f * massTOFhe * 2.f * massTOFhe - MassHeliumVal * MassHeliumVal, hePt); } @@ -4743,12 +4786,12 @@ struct LFNucleiBATask { histos.fill(HIST("tracks/helium/h2HeliumTOFExpSignalDiffVsPtCut"), hePt, track.tofExpSignalDiffHe()); } if (isAntiHeWTPCpid) { - if (enablePtSpectra) + if (outFlagOptions.enableEffPlots) histos.fill(HIST("tracks/eff/helium/hPtantiHeTOF"), 2 * antihePt); histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt"), 2.f * massTOFantihe, antihePt); histos.fill(HIST("tracks/helium/h2TOFmassDeltaantiHeliumVsPt"), 2.f * massTOFantihe - MassHeliumVal, antihePt); histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt"), 2.f * massTOFantihe * 2.f * massTOFantihe - MassHeliumVal * MassHeliumVal, antihePt); - if (outFlagOptions.enableBetaCut && (track.beta() > betaCut)) { + if (outFlagOptions.enableBetaCut && (track.beta() > cfgBetaCut)) { histos.fill(HIST("tracks/helium/h2TOFmassantiHeliumVsPt_BetaCut"), 2.f * massTOFantihe, antihePt); histos.fill(HIST("tracks/helium/h2TOFmass2antiHeliumVsPt_BetaCut"), 2.f * massTOFantihe * 2.f * massTOFantihe - MassHeliumVal * MassHeliumVal, antihePt); } @@ -5475,7 +5518,7 @@ struct LFNucleiBATask { break; case PDGHelium: if (isHelium && passDCAzCutHe && passDCAxyCutHe) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrue_Z2"), 2 * hePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5488,17 +5531,17 @@ struct LFNucleiBATask { } } if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueWPID_Z2"), 2 * hePt); - if (enablePtSpectra) { - histos.fill(HIST("tracks/eff/helium/hPtHeTrue"), 2 * hePt); + if (outFlagOptions.enableEffPlots) { + histos.fill(HIST("tracks/eff/helium/hPtHeTrue_Z2"), 2 * hePt); if (track.hasTOF() && outFlagOptions.doTOFplots) { - histos.fill(HIST("tracks/eff/helium/hPtHeTOFTrue"), 2 * hePt); + histos.fill(HIST("tracks/eff/helium/hPtHeTOFTrue_Z2"), 2 * hePt); } } } if (isPhysPrim) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTruePrim_Z2"), 2 * hePt); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { @@ -5518,7 +5561,7 @@ struct LFNucleiBATask { } if (!isPhysPrim && !isProdByGen) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueTransport_Z2"), 2 * hePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5530,7 +5573,7 @@ struct LFNucleiBATask { } } if (isWeakDecay) { - histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec"), hePt); + // histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec"), hePt); histos.fill(HIST("tracks/helium/h1HeliumSpectraTrueSec_Z2"), 2 * hePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5547,7 +5590,7 @@ struct LFNucleiBATask { break; case -PDGHelium: if (isHelium && passDCAzCutAntiHe && passDCAxyCutAntiHe) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrue_Z2"), 2 * antihePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5559,17 +5602,17 @@ struct LFNucleiBATask { } } if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueWPID_Z2"), 2 * antihePt); - if (enablePtSpectra) { - histos.fill(HIST("tracks/eff/helium/hPtantiHeTrue"), 2 * antihePt); + if (outFlagOptions.enableEffPlots) { + histos.fill(HIST("tracks/eff/helium/hPtantiHeTrue_Z2"), 2 * antihePt); if (track.hasTOF() && outFlagOptions.doTOFplots) { - histos.fill(HIST("tracks/eff/helium/hPtantiHeTOFTrue"), 2 * antihePt); + histos.fill(HIST("tracks/eff/helium/hPtantiHeTOFTrue_Z2"), 2 * antihePt); } } } if (isPhysPrim) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTruePrim_Z2"), 2 * antihePt); if (std::abs(track.tpcNSigmaHe()) < nsigmaTPCvar.nsigmaTPCHe) { @@ -5588,7 +5631,7 @@ struct LFNucleiBATask { } } if (!isPhysPrim && !isProdByGen) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueTransport_Z2"), 2 * antihePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5601,7 +5644,7 @@ struct LFNucleiBATask { } if (isWeakDecay) { - histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec"), antihePt); + // histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec"), antihePt); histos.fill(HIST("tracks/helium/h1antiHeliumSpectraTrueSec_Z2"), 2 * antihePt); if (outFlagOptions.makeDCAAfterCutPlots) { @@ -5687,7 +5730,7 @@ struct LFNucleiBATask { using EventCandidates = soa::Join; using EventCandidatesMC = soa::Join; - using TrackCandidates0 = soa::Join const&, soa::Join const& tracks, aod::McParticles const& mcParticles, o2::aod::BCsWithTimestamps const&) @@ -5769,6 +5813,7 @@ struct LFNucleiBATask { // Process function that runs on the original AO2D (for the MC) with the LfPIDcalibration void processMCRecoLfPid(EventCandidatesMC::iterator const& event, + soa::Join const&, soa::Join const& tracks, aod::McParticles const& mcParticles, o2::aod::BCsWithTimestamps const&) @@ -5792,7 +5837,7 @@ struct LFNucleiBATask { const auto& particlesInCollision = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, collision.mcCollision().globalIndex(), cache); for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } spectraGen.fill(HIST("LfEv/pT_nocut"), mcParticle.pt()); @@ -5805,7 +5850,7 @@ struct LFNucleiBATask { } if (collision.selection_bit(aod::evsel::kIsTriggerTVX)) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5820,7 +5865,7 @@ struct LFNucleiBATask { } if (collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5835,7 +5880,7 @@ struct LFNucleiBATask { } if (collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5850,7 +5895,7 @@ struct LFNucleiBATask { } if ((collision.selection_bit(aod::evsel::kIsTriggerTVX)) && (collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5871,7 +5916,7 @@ struct LFNucleiBATask { } if (collision.sel8()) { for (const auto& mcParticle : particlesInCollision) { - if (mcParticle.y() > kinemOptions.yHighCut || mcParticle.y() < kinemOptions.yLowCut) { + if (mcParticle.y() > kinemOptions.cfgRapidityCutHigh || mcParticle.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -5912,12 +5957,14 @@ struct LFNucleiBATask { //////////// // LOOP OVER GENERATED MC PARTICLES - void processMCGen(aod::McCollision const& mcCollision, - aod::McParticles& mcParticles) + void processMCGen(soa::Join::iterator const& mcCollision, + aod::McParticles const& mcParticles) { spectraGen.fill(HIST("histGenVetxZ"), mcCollision.posZ()); + if (mcCollision.centFT0M() < cfgMultCutLow || mcCollision.centFT0M() > cfgMultCutHigh) + return; for (auto& mcParticleGen : mcParticles) { - if (mcParticleGen.y() > kinemOptions.yHighCut || mcParticleGen.y() < kinemOptions.yLowCut) { + if (mcParticleGen.y() > kinemOptions.cfgRapidityCutHigh || mcParticleGen.y() < kinemOptions.cfgRapidityCutLow) { continue; } @@ -6147,11 +6194,11 @@ struct LFNucleiBATask { } } // Close processMCGen PROCESS_SWITCH(LFNucleiBATask, processMCGen, "process MC Generated", true); - void processEvSgLossMC(aod::McCollision const& mcCollision, + void processEvSgLossMC(soa::Join::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recoColls) { - if (std::abs(mcCollision.posZ()) < cfgHighCutVertex) { + if (std::abs(mcCollision.posZ()) < cfgVzCutHigh) { evLossHistos.fill(HIST("evLoss/hEvent"), 0.5); } @@ -6160,7 +6207,7 @@ struct LFNucleiBATask { // Check if there is an event reconstructed for a generated event for (const auto& recoColl : recoColls) { - if (std::abs(recoColl.posZ()) > cfgHighCutVertex) + if (std::abs(recoColl.posZ()) > cfgVzCutHigh) continue; if (recoColl.selection_bit(o2::aod::evsel::kIsTriggerTVX)) { isTvxEvent = true; diff --git a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx index 5ddaa882de8..a84c39ed953 100644 --- a/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx +++ b/PWGLF/Tasks/Nuspex/antinucleiInJets.cxx @@ -15,52 +15,57 @@ /// \author Alberto Caliva (alberto.caliva@cern.ch), Chiara Pinto (chiara.pinto@cern.ch) /// \since February 13, 2025 -#include -#include -#include -#include -#include -#include -#include -#include -#include "TGrid.h" -#include -#include +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.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 "Framework/RunningWorkflowInfo.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/DataTypes.h" +#include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" -#include "ReconstructionDataFormats/Track.h" -#include "ReconstructionDataFormats/PID.h" +#include "Framework/RunningWorkflowInfo.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/DCA.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/PIDResponseITS.h" +#include "ReconstructionDataFormats/PID.h" +#include "ReconstructionDataFormats/Track.h" + +#include "TGrid.h" +#include +#include +#include +#include +#include +#include #include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/Jet.h" + +#include +#include +#include +#include +#include using namespace std; using namespace o2; @@ -72,34 +77,51 @@ using namespace o2::constants::physics; using namespace o2::constants::math; using std::array; -using SelectedCollisions = soa::Join; -using SimCollisions = soa::Join; - -using FullNucleiTracks = soa::Join; - -using MCTracks = soa::Join; +// Define convenient aliases for commonly used table joins +using SelectedCollisions = soa::Join; +using RecCollisionsMc = soa::Join; +using GenCollisionsMc = aod::McCollisions; +using AntiNucleiTracks = soa::Join; +using AntiNucleiTracksMc = soa::Join; struct AntinucleiInJets { - // histogram registries + // Histogram registries for data, MC, quality control, multiplicity and correlations HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - - // global parameters - Configurable minJetPt{"minJetPt", 10.0, "Minimum pt of the jet"}; + HistogramRegistry registryMult{"registryMult", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryCorr{"registryCorr", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Event selection criteria + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "Reject events near the ITS ROF border"}; + Configurable rejectTFBorder{"rejectTFBorder", true, "Reject events near the TF border"}; + Configurable requireVtxITSTPC{"requireVtxITSTPC", true, "Require at least one ITS-TPC matched track"}; + Configurable rejectSameBunchPileup{"rejectSameBunchPileup", true, "Reject events with same-bunch pileup collisions"}; + Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", true, "Require consistent FT0 vs PV z-vertex"}; + Configurable requireIsVertexTOFmatched{"requireIsVertexTOFmatched", false, "Require at least one vertex track matched to TOF"}; + + // Skimmed data flag and list of active triggers for processing + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + Configurable triggerList{"triggerList", "fHe", "Trigger list"}; + + // Jet selection and event filtering parameters + Configurable minJetPt{"minJetPt", 10.0, "Minimum 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 zVtx{"zVtx", 10.0, "Maximum zVertex"}; + Configurable applyAreaCut{"applyAreaCut", false, "apply area cut"}; + Configurable maxNormalizedJetArea{"maxNormalizedJetArea", 0.6, "area cut"}; Configurable deltaEtaEdge{"deltaEtaEdge", 0.05, "eta gap from the edge"}; + Configurable applyRandomEventRejection{"applyRandomEventRejection", false, "reject some events for syst"}; + Configurable rejectionPercentage{"rejectionPercentage", 3.0, "percentage of events to reject"}; + Configurable nSyst{"nSyst", 50, "number of systematic variations"}; - // track parameters + // Track quality, kinematic, and PID selection parameters Configurable requirePvContributor{"requirePvContributor", false, "require that the track is a PV contributor"}; Configurable applyItsPid{"applyItsPid", true, "apply ITS PID"}; - Configurable rejectEvents{"rejectEvents", false, "reject some events"}; - Configurable rejectionPercentage{"rejectionPercentage", 3, "percentage of events to reject"}; Configurable minItsNclusters{"minItsNclusters", 5, "minimum number of ITS clusters"}; - Configurable minTpcNcrossedRows{"minTpcNcrossedRows", 80, "minimum number of TPC crossed pad rows"}; - Configurable minTpcNcrossedRowsOverFindable{"minTpcNcrossedRowsOverFindable", 0.8, "crossed rows/findable"}; + Configurable minTpcNcrossedRows{"minTpcNcrossedRows", 100, "minimum number of TPC crossed pad rows"}; Configurable maxChiSquareTpc{"maxChiSquareTpc", 4.0, "maximum TPC chi^2/Ncls"}; Configurable maxChiSquareIts{"maxChiSquareIts", 36.0, "maximum ITS chi^2/Ncls"}; Configurable minPt{"minPt", 0.3, "minimum pt of the tracks"}; @@ -114,57 +136,53 @@ struct AntinucleiInJets { Configurable ptMaxItsPidProt{"ptMaxItsPidProt", 1.0, "maximum pt for ITS PID for protons"}; Configurable ptMaxItsPidDeut{"ptMaxItsPidDeut", 1.0, "maximum pt for ITS PID for deuterons"}; Configurable ptMaxItsPidHel{"ptMaxItsPidHel", 1.0, "maximum pt for ITS PID for helium"}; - Configurable nSigmaItsMin{"nSigmaItsMin", -2.0, "nSigmaITS min"}; - Configurable nSigmaItsMax{"nSigmaItsMax", +2.0, "nSigmaITS max"}; - - // reweighting - Configurable applyReweighting{"applyReweighting", true, "apply reweighting"}; - Configurable urlToCcdb{"urlToCcdb", "http://alice-ccdb.cern.ch", "url of the personal ccdb"}; - Configurable pathToFile{"pathToFile", "", "path to file with reweighting"}; - Configurable histoNameWeightAntipJet{"histoNameWeightAntipJet", "", "reweighting histogram: antip in jet"}; - Configurable histoNameWeightAntipUe{"histoNameWeightAntipUe", "", "reweighting histogram: antip in ue"}; - TH2F* twoDweightsAntipJet; - TH2F* twoDweightsAntipUe; - - // jet pt unfolding - Configurable applyPtUnfolding{"applyPtUnfolding", true, "apply jet pt unfolding"}; - Configurable urlToCcdbPtUnfolding{"urlToCcdbPtUnfolding", "http://alice-ccdb.cern.ch", "url of the personal ccdb"}; - Configurable pathToFilePtUnfolding{"pathToFilePtUnfolding", "Users/c/chpinto/My/Object/ResponseMatrix", "path to file with pt unfolding"}; - Configurable histoNamePtUnfolding{"histoNamePtUnfolding", "detectorResponseMatrix", "pt unfolding histogram"}; - TH2F* responseMatrix; + Configurable nSigmaItsMin{"nSigmaItsMin", -3.0, "nSigmaITS min"}; + Configurable nSigmaItsMax{"nSigmaItsMax", +3.0, "nSigmaITS max"}; + Configurable setMCDefaultItsParams{"setMCDefaultItsParams", false, "set MC default parameters"}; + // CCDB manager service for accessing condition data Service ccdb; + + // Direct interface to the CCDB API for manual data access o2::ccdb::CcdbApi ccdbApi; + // 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; + // Initialize ITS PID Response object + o2::aod::ITSResponse itsResponse; + + // Initialize CCDB access and histogram registry for Zorro processing + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (cfgSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); + zorro.populateHistRegistry(registryData, bc.runNumber()); + } + } + void init(InitContext const&) { - ccdb->setURL(urlToCcdb.value); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdb->setFatalWhenNull(false); - - if (applyReweighting) { - getReweightingHistograms(ccdb, TString(pathToFile), TString(histoNameWeightAntipJet), TString(histoNameWeightAntipUe)); - } else { - twoDweightsAntipJet = nullptr; - twoDweightsAntipUe = nullptr; + // Set summary object if processing skimmed data + if (cfgSkimmedProcessing) { + zorroSummary.setObject(zorro.getZorroSummary()); } - if (applyPtUnfolding) { - getPtUnfoldingHistogram(ccdb, TString(pathToFilePtUnfolding), TString(histoNamePtUnfolding)); - } else { - responseMatrix = nullptr; + // Set default MC parametrization for ITS response + if (setMCDefaultItsParams) { + itsResponse.setMCDefaultParameters(); } - // binning + // Binning double min = 0.0; double max = 6.0; int nbins = 120; - // QC histograms + // Quality control histograms for jet/UE topology and multiplicity if (doprocessQC) { registryQC.add("deltaEta_deltaPhi_jet", "deltaEta_deltaPhi_jet", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, PIHalf, "#Delta#phi"}}); registryQC.add("deltaEta_deltaPhi_ue", "deltaEta_deltaPhi_ue", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, PIHalf, "#Delta#phi"}}); @@ -179,121 +197,217 @@ struct AntinucleiInJets { registryQC.add("nJetsFound", "nJetsFound", HistType::kTH1F, {{50, 0, 50, "#it{n}_{Jet}"}}); registryQC.add("nJetsInAcceptance", "nJetsInAcceptance", HistType::kTH1F, {{50, 0, 50, "#it{n}_{Jet}"}}); registryQC.add("nJetsSelectedHighPt", "nJetsSelectedHighPt", HistType::kTH1F, {{50, 0, 50, "#it{n}_{Jet}"}}); - registryQC.add("jetEffectiveArea", "jetEffectiveArea", HistType::kTH1F, {{2000, 0, 2, "Area/#piR^{2}"}}); registryQC.add("jetPtDifference", "jetPtDifference", HistType::kTH1F, {{200, -1, 1, "#Deltap_{T}^{jet}"}}); + registryQC.add("ptDistributionJetCone", "ptDistributionJetCone", HistType::kTH1F, {{2000, 0, 200, "#it{p}_{T} (GeV/#it{c})"}}); + registryQC.add("ptDistributionJet", "ptDistributionJet", HistType::kTH1F, {{2000, 0, 200, "#it{p}_{T} (GeV/#it{c})"}}); + } + + // Multiplicity histograms: check charged-particle multiplicity in events with selected jets (Run 3) or ptTrigger > threshold (Run 2-like) + if (doprocessMultEvents) { + registryMult.add("multiplicityEvtsPtLeading", "multiplicityEvtsPtLeading", HistType::kTH1F, {{1000, 0, 1000, "#it{N}_{ch}"}}); + registryMult.add("multiplicityEvtsWithJet", "multiplicityEvtsWithJet", HistType::kTH1F, {{1000, 0, 1000, "#it{N}_{ch}"}}); } - // data histograms + // Histograms for real data if (doprocessData) { - // event counter data - registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{10, 0, 10, "counter"}}); + // Event counters + registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{20, 0, 20, "counter"}}); registryData.add("number_of_rejected_events", "check on number of events rejected", HistType::kTH1F, {{10, 0, 10, "counter"}}); - // antiprotons + // Jet effective area over piR^2 + registryData.add("jetEffectiveAreaOverPiR2", "jet effective area / piR^2", HistType::kTH1F, {{2000, 0, 2, "Area/#piR^{2}"}}); + + // Antiprotons registryData.add("antiproton_jet_tpc", "antiproton_jet_tpc", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); registryData.add("antiproton_jet_tof", "antiproton_jet_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); registryData.add("antiproton_ue_tpc", "antiproton_ue_tpc", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); registryData.add("antiproton_ue_tof", "antiproton_ue_tof", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); - registryData.add("antiproton_dca_jet", "antiproton_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); - registryData.add("antiproton_dca_ue", "antiproton_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -0.5, 0.5, "DCA_{xy} (cm)"}}); - - // antideuterons - registryData.add("antideuteron_jet_tpc", "antideuteron_jet_tpc", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); - registryData.add("antideuteron_jet_tof", "antideuteron_jet_tof", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); - registryData.add("antideuteron_ue_tpc", "antideuteron_ue_tpc", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); - registryData.add("antideuteron_ue_tof", "antideuteron_ue_tof", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); - - // deuterons - registryData.add("deuteron_jet_tof", "deuteron_jet_tof", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); - registryData.add("deuteron_ue_tof", "deuteron_ue_tof", HistType::kTH2F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); - - // antihelium-3 - registryData.add("antihelium3_jet_tpc", "antihelium3_jet_tpc", HistType::kTH2F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); - registryData.add("antihelium3_ue_tpc", "antihelium3_ue_tpc", HistType::kTH2F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); - - // helium-3 - registryData.add("helium3_jet_tpc", "helium3_jet_tpc", HistType::kTH2F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); - registryData.add("helium3_ue_tpc", "helium3_ue_tpc", HistType::kTH2F, {{nbins, min * 3, max * 3, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); - } - - // monte carlo histograms - if (doprocessEfficiency) { - - // event counter MC - registryMC.add("number_of_events_mc", "number of events in mc", HistType::kTH1F, {{10, 0, 10, "counter"}}); - - // generated spectra - registryMC.add("antiproton_incl_gen", "antiproton_incl_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("deuteron_incl_gen", "deuteron_incl_gen", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_incl_gen", "antideuteron_incl_gen", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("helium3_incl_gen", "helium3_incl_gen", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antihelium3_incl_gen", "antihelium3_incl_gen", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); - - // reconstructed TPC - registryMC.add("antiproton_incl_rec_tpc", "antiproton_incl_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_incl_rec_tpc", "antideuteron_incl_rec_tpc", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("deuteron_incl_rec_tpc", "deuteron_incl_rec_tpc", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antihelium3_incl_rec_tpc", "antihelium3_incl_rec_tpc", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("helium3_incl_rec_tpc", "helium3_incl_rec_tpc", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); - - // reconstructed TOF - registryMC.add("antiproton_incl_rec_tof", "antiproton_incl_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_incl_rec_tof", "antideuteron_incl_rec_tof", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("deuteron_incl_rec_tof", "deuteron_incl_rec_tof", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); - - // fraction of primary antiprotons from MC - registryMC.add("antiproton_incl_prim", "antiproton_incl_prim", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_incl_all", "antiproton_incl_all", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - - // antiproton reweighting - registryMC.add("antiproton_eta_pt_pythia", "antiproton_eta_pt_pythia", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); + 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)"}}); + + // 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}"}}); + + // 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}"}}); + registryData.add("deuteron_jet_tof", "deuteron_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("deuteron_ue_tpc", "deuteron_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("deuteron_ue_tof", "deuteron_ue_tof", HistType::kTH2F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + + // Antihelium-3 + registryData.add("antihelium3_jet_tpc", "antihelium3_jet_tpc", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antihelium3_ue_tpc", "antihelium3_ue_tpc", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + + // Helium-3 + registryData.add("helium3_jet_tpc", "helium3_jet_tpc", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("helium3_ue_tpc", "helium3_ue_tpc", HistType::kTH2F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); } + // Generated antiproton spectra in jets and UE from MC truth if (doprocessJetsMCgen) { - registryMC.add("antiproton_jet_gen", "antiproton_jet_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_gen", "antiproton_ue_gen", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_eta_pt_jet", "antiproton_eta_pt_jet", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); - registryMC.add("antiproton_eta_pt_ue", "antiproton_eta_pt_ue", HistType::kTH2F, {{200, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}, {20, -1.0, 1.0, "#it{#eta}"}}); + + // Event counter + registryMC.add("genEvents", "number of generated events in mc", HistType::kTH1F, {{10, 0, 10, "counter"}}); + + // Generated spectra of antiprotons + registryMC.add("antiproton_gen_jet", "antiproton_gen_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_gen_ue", "antiproton_gen_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); } + // Reconstructed antiproton spectra in jets and UE (MC-matched) with TPC/TOF PID if (doprocessJetsMCrec) { - registryMC.add("antiproton_jet_prim", "antiproton_jet_prim", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_all", "antiproton_jet_all", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_prim", "antiproton_ue_prim", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_all", "antiproton_all_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_rec_tpc", "antiproton_jet_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_rec_tpc", "antiproton_ue_rec_tpc", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_rec_tof", "antiproton_jet_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_ue_rec_tof", "antiproton_ue_rec_tof", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_tpc_rec_vs_generatedptjet", "antiproton_jet_tpc_rec_vs_generatedptjet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T, antiproton}^{rec} (GeV/#it{c})"}, {1000, 0., 100., "#it{p}_{T, jet}^{gen} (GeV/#it{c})"}}); - registryMC.add("antiproton_jet_tof_rec_vs_generatedptjet", "antiproton_jet_tof_rec_vs_generatedptjet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T, antiproton}^{rec} (GeV/#it{c})"}, {1000, 0., 100., "#it{p}_{T, jet}^{gen} (GeV/#it{c})"}}); - - // detector response matrix - registryMC.add("detectorResponseMatrix", "detectorResponseMatrix", HistType::kTH2F, {{1000, 0.0, 100.0, "#it{p}_{T}^{rec} (GeV/#it{c})"}, {2000, -20.0, 20.0, "#it{p}_{T}^{gen} - #it{p}_{T}^{rec} (GeV/#it{c})"}}); - registryMC.add("generatedVsReconstructedPt", "generatedVsReconstructedPt", HistType::kTH2F, {{1000, 0.0, 100.0, "#it{p}_{T}^{rec} (GeV/#it{c})"}, {1000, 0.0, 100.0, "#it{p}_{T}^{gen} (GeV/#it{c})"}}); + + // Event counter + registryMC.add("recEvents", "number of reconstructed events in mc", HistType::kTH1F, {{20, 0, 20, "counter"}}); + + // Reconstructed spectra of antiprotons + registryMC.add("antiproton_rec_tpc_jet", "antiproton_rec_tpc_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_jet", "antiproton_rec_tof_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tpc_ue", "antiproton_rec_tpc_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_ue", "antiproton_rec_tof_ue", 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})"}}); + registryMC.add("antiproton_prim_ue", "antiproton_prim_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_incl_ue", "antiproton_incl_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // DCA templates + registryMC.add("antiproton_prim_dca_jet", "antiproton_prim_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_prim_dca_ue", "antiproton_prim_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_all_dca_jet", "antiproton_all_dca_jet", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + registryMC.add("antiproton_all_dca_ue", "antiproton_all_dca_ue", HistType::kTH2F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {200, -1, 1, "DCA_{xy} (cm)"}}); + } + + // Efficiency of antinuclei + if (doprocessAntinucleiEfficiency) { + + // Event counter MC + registryMC.add("number_of_events_mc_nuclei_efficiency", "number of events in mc", HistType::kTH1F, {{20, 0, 20, "counter"}}); + + // Generated spectra of (anti)protons + registryMC.add("antip_gen_jet", "antip_gen_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antip_gen_ue", "antip_gen_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Generated spectra of (anti)deuterons + registryMC.add("deuteron_gen_jet", "deuteron_gen_jet", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("deuteron_gen_ue", "deuteron_gen_ue", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_gen_jet", "antideuteron_gen_jet", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_gen_ue", "antideuteron_gen_ue", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Generated spectra of (anti)helium3 + registryMC.add("helium3_gen_jet", "helium3_gen_jet", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("helium3_gen_ue", "helium3_gen_ue", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_gen_jet", "antihelium3_gen_jet", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_gen_ue", "antihelium3_gen_ue", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Reconstructed spectra of antiprotons + registryMC.add("antip_rec_tpc_jet", "antip_rec_tpc_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antip_rec_tof_jet", "antip_rec_tof_jet", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antip_rec_tpc_ue", "antip_rec_tpc_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antip_rec_tof_ue", "antip_rec_tof_ue", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Reconstructed spectra of (anti)deuterons + registryMC.add("deuteron_rec_tpc_jet", "deuteron_rec_tpc_jet", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("deuteron_rec_tof_jet", "deuteron_rec_tof_jet", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("deuteron_rec_tpc_ue", "deuteron_rec_tpc_ue", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("deuteron_rec_tof_ue", "deuteron_rec_tof_ue", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_rec_tpc_jet", "antideuteron_rec_tpc_jet", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_rec_tof_jet", "antideuteron_rec_tof_jet", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_rec_tpc_ue", "antideuteron_rec_tpc_ue", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_rec_tof_ue", "antideuteron_rec_tof_ue", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Reconstructed spectra of (anti)helium3 + registryMC.add("helium3_rec_tpc_jet", "helium3_rec_tpc_jet", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("helium3_rec_tpc_ue", "helium3_rec_tpc_ue", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_rec_tpc_jet", "antihelium3_rec_tpc_jet", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_rec_tpc_ue", "antihelium3_rec_tpc_ue", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + } + + // Systematic uncertainties (Data) + if (doprocessSystData) { + registryData.add("number_of_events_data_syst", "event counter", HistType::kTH1F, {{20, 0, 20, "counter"}}); + + registryData.add("antiproton_tpc_syst", "antiproton_tpc_syst", HistType::kTH3F, {{50, 0, 50, "systematic uncertainty"}, {nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antiproton_tof_syst", "antiproton_tof_syst", HistType::kTH3F, {{50, 0, 50, "systematic uncertainty"}, {nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antideuteron_tpc_syst", "antideuteron_tpc_syst", HistType::kTH3F, {{50, 0, 50, "systematic uncertainty"}, {nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); + registryData.add("antideuteron_tof_syst", "antideuteron_tof_syst", HistType::kTH3F, {{50, 0, 50, "systematic uncertainty"}, {nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}}); + registryData.add("antihelium3_tpc_syst", "antihelium3_tpc_syst", HistType::kTH3F, {{50, 0, 50, "systematic uncertainty"}, {nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}}); } - // systematic uncertainties - if (doprocessSystematicsData) { - registryData.add("number_of_rejected_events_syst", "check on number of events rejected", HistType::kTH1F, {{10, 0, 10, "counter"}}); - registryData.add("antiproton_tpc_syst", "antiproton_tpc_syst", HistType::kTHnSparseF, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}, {10, 0, 10, "systematic uncertainty"}}); - registryData.add("antiproton_tof_syst", "antiproton_tof_syst", HistType::kTHnSparseF, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}, {10, 0, 10, "systematic uncertainty"}}); - registryData.add("antideuteron_tpc_syst", "antideuteron_tpc_syst", HistType::kTHnSparseF, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TPC}"}, {10, 0, 10, "systematic uncertainty"}}); - registryData.add("antideuteron_tof_syst", "antideuteron_tof_syst", HistType::kTHnSparseF, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}, {400, -20.0, 20.0, "n#sigma_{TOF}"}, {10, 0, 10, "systematic uncertainty"}}); + // Systematic uncertainties (MC) + if (doprocessSystEff) { + + // Histograms for generated antiparticles + registryMC.add("antiproton_gen_syst", "antiproton_gen_syst", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_gen_syst", "antideuteron_gen_syst", HistType::kTH1F, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_gen_syst", "antihelium3_gen_syst", HistType::kTH1F, {{nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Histograms for reconstructed antiparticles + registryMC.add("antiproton_rec_tpc_syst", "antiproton_rec_tpc_syst", HistType::kTH2F, {{50, 0, 50, "systematic uncertainty"}, {nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_rec_tof_syst", "antiproton_rec_tof_syst", HistType::kTH2F, {{50, 0, 50, "systematic uncertainty"}, {nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_rec_tpc_syst", "antideuteron_rec_tpc_syst", HistType::kTH2F, {{50, 0, 50, "systematic uncertainty"}, {nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antideuteron_rec_tof_syst", "antideuteron_rec_tof_syst", HistType::kTH2F, {{50, 0, 50, "systematic uncertainty"}, {nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antihelium3_rec_tpc_syst", "antihelium3_rec_tpc_syst", HistType::kTH2F, {{50, 0, 50, "systematic uncertainty"}, {nbins, 3 * min, 3 * max, "#it{p}_{T} (GeV/#it{c})"}}); + + // Histograms for primary antiprotons + registryMC.add("antiproton_incl_syst", "antiproton_incl_syst", HistType::kTH2F, {{50, 0, 50, "systematic uncertainty"}, {nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); + registryMC.add("antiproton_prim_syst", "antiproton_prim_syst", HistType::kTH2F, {{50, 0, 50, "systematic uncertainty"}, {nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); } - if (doprocessSystematicsEfficiency) { - registryMC.add("antiproton_incl_gen_syst", "antiproton_incl_gen_syst", HistType::kTH1F, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antideuteron_incl_gen_syst", "antideuteron_incl_gen_syst", HistType::kTH1F, {{nbins, min * 2, max * 2, "#it{p}_{T} (GeV/#it{c})"}}); - registryMC.add("antiproton_incl_prim_syst", "antiproton_incl_prim_syst", HistType::kTHnSparseF, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {10, 0, 10, "systematic uncertainty"}}); - registryMC.add("antiproton_incl_rec_tpc_syst", "antiproton_incl_rec_tpc_syst", HistType::kTHnSparseF, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {10, 0, 10, "systematic uncertainty"}}); - registryMC.add("antiproton_incl_rec_tof_syst", "antiproton_incl_rec_tof_syst", HistType::kTHnSparseF, {{nbins, min, max, "#it{p}_{T} (GeV/#it{c})"}, {10, 0, 10, "systematic uncertainty"}}); - registryMC.add("antideuteron_incl_rec_tpc_syst", "antideuteron_incl_rec_tpc_syst", HistType::kTHnSparseF, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {10, 0, 10, "systematic uncertainty"}}); - registryMC.add("antideuteron_incl_rec_tof_syst", "antideuteron_incl_rec_tof_syst", HistType::kTHnSparseF, {{nbins, 2 * min, 2 * max, "#it{p}_{T} (GeV/#it{c})"}, {10, 0, 10, "systematic uncertainty"}}); + // Correlation analysis + if (doprocessCorr) { + + // 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}"}; + + // Event counter + registryCorr.add("eventCounter", "number of events", HistType::kTH1F, {{20, 0, 20, "counter"}}); + + // Correlation histograms: antiproton vs. antideuteron number vs. event multiplicity + registryCorr.add("rho_jet", "rho_jet", HistType::kTH3F, {nAntideuteronsAxis, nAntiprotonsAxis, multiplicityAxis}); + registryCorr.add("rho_ue", "rho_ue", HistType::kTH3F, {nAntideuteronsAxis, nAntiprotonsAxis, multiplicityAxis}); + registryCorr.add("rho_fullEvent", "rho_fullEvent", HistType::kTH3F, {nAntideuteronsAxis, nAntiprotonsAxis, multiplicityAxis}); + + // Correlation histograms: net antiproton vs. net antideuteron numbers + registryCorr.add("rho_netP_netD_jet", "rho_netP_netD_jet", HistType::kTH2F, {nAntideuteronsAxis, nAntiprotonsAxis}); + registryCorr.add("rho_netP_netD_ue", "rho_netP_netD_ue", HistType::kTH2F, {nAntideuteronsAxis, nAntiprotonsAxis}); + registryCorr.add("rho_netP_netD_fullEvent", "rho_netP_netD_fullEvent", HistType::kTH2F, {nAntideuteronsAxis, nAntiprotonsAxis}); + + // Efficiency histograms jet + registryCorr.add("q1d_jet", "q1d_jet", HistType::kTH2F, {nAntideuteronsAxis, ptPerNucleonAxis}); + registryCorr.add("q1p_jet", "q1p_jet", HistType::kTH2F, {nAntiprotonsAxis, ptPerNucleonAxis}); + registryCorr.add("q1d_square_jet", "q1d_square_jet", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarD2Axis}); + registryCorr.add("q1p_square_jet", "q1p_square_jet", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarP2Axis}); + registryCorr.add("q1d_q1p_jet", "q1d_q1p_jet", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarDnBarPAxis}); + + // Efficiency histograms UE + registryCorr.add("q1d_ue", "q1d_ue", HistType::kTH2F, {nAntideuteronsAxis, ptPerNucleonAxis}); + registryCorr.add("q1p_ue", "q1p_ue", HistType::kTH2F, {nAntiprotonsAxis, ptPerNucleonAxis}); + registryCorr.add("q1d_square_ue", "q1d_square_ue", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarD2Axis}); + registryCorr.add("q1p_square_ue", "q1p_square_ue", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarP2Axis}); + registryCorr.add("q1d_q1p_ue", "q1d_q1p_ue", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarDnBarPAxis}); + + // Efficiency histograms full event + registryCorr.add("q1d_fullEvent", "q1d_fullEvent", HistType::kTH2F, {nAntideuteronsAxis, ptPerNucleonAxis}); + registryCorr.add("q1p_fullEvent", "q1p_fullEvent", HistType::kTH2F, {nAntiprotonsAxis, ptPerNucleonAxis}); + registryCorr.add("q1d_square_fullEvent", "q1d_square_fullEvent", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarD2Axis}); + registryCorr.add("q1p_square_fullEvent", "q1p_square_fullEvent", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarP2Axis}); + registryCorr.add("q1d_q1p_fullEvent", "q1d_q1p_fullEvent", HistType::kTH3F, {ptPerNucleonAxis, ptPerNucleonAxis, nBarDnBarPAxis}); } } + // Compute two unit vectors perpendicular to p void getPerpendicularAxis(const TVector3& p, TVector3& u, double sign) { double px = p.X(); @@ -345,6 +459,7 @@ struct AntinucleiInJets { u.SetXYZ(ux, uy, pz); } + // Compute delta phi double getDeltaPhi(double a1, double a2) { double deltaPhi(0); @@ -360,6 +475,17 @@ struct AntinucleiInJets { return deltaPhi; } + // Find bin + int findBin(const std::vector& edges, double value) + { + auto it = std::upper_bound(edges.begin(), edges.end(), value); + int index = static_cast(it - edges.begin()) - 1; + if (index < 0 || index >= static_cast(edges.size()) - 1) { + return -1; // value is out of bounds + } + return index; + } + // ITS hit template bool hasITSHit(const TrackIts& track, int layer) @@ -368,21 +494,18 @@ struct AntinucleiInJets { return (track.itsClusterMap() & (1 << ibit)); } - // single-track selection for particles inside jets + // Single-track selection for particles inside jets template bool passedTrackSelectionForJetReconstruction(const JetTrack& track) { - - const int minTpcCr = 70; - const double minCrFindable = 0.8; - const double maxChi2Tpc = 4.0; - const double maxChi2Its = 36.0; - const double maxPseudorapidity = 0.8; - const double minPtTrack = 0.1; - const double dcaxyMaxTrackPar0 = 0.0105; - const double dcaxyMaxTrackPar1 = 0.035; - const double dcaxyMaxTrackPar2 = 1.1; - const double dcazMaxTrack = 2.0; + 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; if (!track.hasITS()) return false; @@ -390,26 +513,24 @@ struct AntinucleiInJets { return false; if (!track.hasTPC()) return false; - if (track.tpcNClsCrossedRows() < minTpcCr) + if (track.tpcNClsCrossedRows() < MinTpcCr) return false; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minCrFindable) + if (track.tpcChi2NCl() > MaxChi2Tpc) return false; - if (track.tpcChi2NCl() > maxChi2Tpc) + if (track.itsChi2NCl() > MaxChi2Its) return false; - if (track.itsChi2NCl() > maxChi2Its) + if (std::fabs(track.eta()) > maxEta) return false; - if (track.eta() < -maxPseudorapidity || track.eta() > maxPseudorapidity) + if (track.pt() < MinPtTrack) return false; - if (track.pt() < minPtTrack) + if (std::fabs(track.dcaXY()) > (DcaxyMaxTrackPar0 + DcaxyMaxTrackPar1 / std::pow(track.pt(), DcaxyMaxTrackPar2))) return false; - if (std::fabs(track.dcaXY()) > (dcaxyMaxTrackPar0 + dcaxyMaxTrackPar1 / std::pow(track.pt(), dcaxyMaxTrackPar2))) - return false; - if (std::fabs(track.dcaZ()) > dcazMaxTrack) + if (std::fabs(track.dcaZ()) > DcazMaxTrack) return false; return true; } - // single-track selection + // Single-track selection for antinuclei template bool passedTrackSelection(const AntinucleusTrack& track) { @@ -423,8 +544,6 @@ struct AntinucleiInJets { return false; if (track.tpcNClsCrossedRows() < minTpcNcrossedRows) return false; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - return false; if (track.tpcChi2NCl() > maxChiSquareTpc) return false; if (track.itsChi2NCl() > maxChiSquareIts) @@ -437,6 +556,72 @@ struct AntinucleiInJets { return true; } + // Single-track selection for antinuclei candidates with systematic variations + template + bool passedTrackSelectionSyst(const AntinucleusTrack& track, int isyst) + { + // Define cut settings + static std::vector minItsNclustersSyst = { + 3, 7, 6, 6, 6, 4, 5, 6, 7, 4, + 4, 3, 6, 3, 7, 5, 4, 6, 5, 7, + 6, 5, 3, 5, 4, 3, 6, 6, 4, 7, + 3, 4, 3, 5, 7, 6, 6, 4, 3, 5, + 4, 7, 3, 6, 4, 5, 6, 3, 7, 5}; + static std::vector minTpcNcrossedRowsSyst = { + 90, 108, 112, 119, 92, 111, 98, 105, 86, 117, + 118, 101, 87, 116, 82, 109, 80, 115, 89, 97, + 107, 120, 104, 94, 100, 93, 103, 84, 102, 85, + 108, 96, 113, 117, 91, 88, 99, 110, 106, 83, + 118, 95, 112, 114, 109, 89, 116, 92, 98, 120}; + static std::vector maxChiSquareTpcSyst = { + 4.28, 4.81, 4.43, 4.02, 3.38, 3.58, 3.11, 4.17, 3.51, 4.53, + 4.90, 3.07, 3.20, 4.86, 4.62, 3.91, 3.98, 4.38, 3.66, 3.84, + 3.03, 3.14, 4.96, 4.07, 4.75, 4.32, 3.31, 3.78, 4.11, 3.23, + 3.87, 3.70, 4.99, 4.48, 4.69, 4.25, 3.93, 3.45, 4.58, 3.35, + 3.18, 3.60, 4.21, 3.75, 4.64, 4.35, 3.26, 3.42, 4.15, 3.09}; + static std::vector maxChiSquareItsSyst = { + 42.84, 48.66, 39.27, 34.09, 43.73, 36.98, 30.23, 49.11, 37.67, 35.10, + 44.55, 46.79, 38.92, 40.66, 47.14, 33.46, 30.88, 41.32, 45.90, 39.68, + 31.42, 32.71, 43.17, 36.04, 49.80, 33.95, 31.89, 38.37, 48.08, 35.87, + 47.61, 44.02, 32.15, 46.21, 34.75, 40.17, 37.14, 30.55, 45.42, 42.30, + 41.79, 33.21, 39.12, 47.98, 36.52, 31.58, 49.44, 38.02, 35.56, 43.49}; + static std::vector minEtaSyst = { + -0.804, -0.844, -0.751, -0.784, -0.819, -0.823, -0.768, -0.781, -0.845, -0.787, + -0.758, -0.828, -0.776, -0.842, -0.808, -0.763, -0.849, -0.770, -0.799, -0.754, + -0.825, -0.847, -0.806, -0.783, -0.796, -0.835, -0.777, -0.752, -0.838, -0.813, + -0.785, -0.802, -0.795, -0.846, -0.780, -0.829, -0.817, -0.773, -0.765, -0.789, + -0.800, -0.839, -0.758, -0.820, -0.833, -0.762, -0.792, -0.809, -0.827, -0.751}; + static std::vector maxEtaSyst = { + 0.804, 0.844, 0.751, 0.784, 0.819, 0.823, 0.768, 0.781, 0.845, 0.787, + 0.758, 0.828, 0.776, 0.842, 0.808, 0.763, 0.849, 0.770, 0.799, 0.754, + 0.825, 0.847, 0.806, 0.783, 0.796, 0.835, 0.777, 0.752, 0.838, 0.813, + 0.785, 0.802, 0.795, 0.846, 0.780, 0.829, 0.817, 0.773, 0.765, 0.789, + 0.800, 0.839, 0.758, 0.820, 0.833, 0.762, 0.792, 0.809, 0.827, 0.751}; + + // Track Selection + if (requirePvContributor && !(track.isPVContributor())) + return false; + if (!track.hasITS()) + return false; + if (track.itsNCls() < minItsNclustersSyst[isyst]) + return false; + if (!track.hasTPC()) + return false; + if (track.tpcNClsCrossedRows() < minTpcNcrossedRowsSyst[isyst]) + return false; + if (track.tpcChi2NCl() > maxChiSquareTpcSyst[isyst]) + return false; + if (track.itsChi2NCl() > maxChiSquareItsSyst[isyst]) + return false; + if (track.eta() < minEtaSyst[isyst] || track.eta() > maxEtaSyst[isyst]) + return false; + if (track.pt() < minPt) + return false; + + return true; + } + + // Selection of high-purity antiproton sample template bool isHighPurityAntiproton(const AntiprotonTrack& track) { @@ -444,115 +629,130 @@ struct AntinucleiInJets { double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); double pt = track.pt(); - double ptThreshold = 0.5; - double nsigmaMaxPr = 2.0; + static constexpr double PtThreshold = 0.5; + static constexpr double NsigmaMaxPr = 2.0; - if (pt < ptThreshold && std::fabs(nsigmaTPCPr) < nsigmaMaxPr) + if (pt < PtThreshold && std::fabs(nsigmaTPCPr) < NsigmaMaxPr) return true; - if (pt >= ptThreshold && std::fabs(nsigmaTPCPr) < nsigmaMaxPr && track.hasTOF() && std::fabs(nsigmaTOFPr) < nsigmaMaxPr) + if (pt >= PtThreshold && std::fabs(nsigmaTPCPr) < NsigmaMaxPr && track.hasTOF() && std::fabs(nsigmaTOFPr) < NsigmaMaxPr) return true; return false; } - double getCorrectedPt(double ptRec, TH2* responseMatrix) + // Selection of (anti)protons + template + bool isProton(const ProtonTrack& track) { - if (!responseMatrix) { - LOGP(error, "Response matrix is null. Returning uncorrected pt."); - return ptRec; - } + // Constants + static constexpr double kPtThreshold = 0.6; + static constexpr double kNsigmaMax = 3.0; - int binX = responseMatrix->GetXaxis()->FindBin(ptRec); - if (binX < 1 || binX > responseMatrix->GetNbinsX()) { - LOGP(error, "Bin index out of range: binX = {}", binX); - return ptRec; // Return uncorrected pt if bin index is invalid - } - std::unique_ptr proj(responseMatrix->ProjectionY("proj", binX, binX)); + // PID variables and transverse momentum of the track + const double nsigmaTPC = track.tpcNSigmaPr(); + const double nsigmaTOF = track.tofNSigmaPr(); + const double pt = track.pt(); - // add a protection in case the projection is empty - if (proj->GetEntries() == 0) { - return ptRec; - } + // Apply TPC PID cut + if (std::abs(nsigmaTPC) > kNsigmaMax) + return false; - double deltaPt = proj->GetRandom(); - double ptGen = ptRec + deltaPt; + // Low-pt: TPC PID is sufficient + if (pt < kPtThreshold) + return true; - return ptGen; + // High-pt: require valid TOF match and pass TOF PID + return (track.hasTOF() && std::abs(nsigmaTOF) < kNsigmaMax); } - void getPtUnfoldingHistogram(o2::framework::Service const& ccdbObj, TString filepath, TString histoNamePtUnfolding) + // Selection of (anti)deuterons + template + bool isDeuteron(const DeuteronTrack& track) { - TList* l = ccdbObj->get(filepath.Data()); - if (!l) { - LOGP(error, "Could not open the file {}", Form("%s", filepath.Data())); - return; - } - TObject* obj = l->FindObject(Form("%s", histoNamePtUnfolding.Data())); - if (!obj || !obj->InheritsFrom(TH2F::Class())) { - LOGP(error, "Could not find a valid TH2F histogram {}", Form("%s", histoNamePtUnfolding.Data())); - return; - } - responseMatrix = static_cast(obj); - LOGP(info, "Opened histogram {}", Form("%s", histoNamePtUnfolding.Data())); - } + // Constants + static constexpr double kPtThreshold = 1.0; + static constexpr double kNsigmaMax = 3.0; - void getReweightingHistograms(o2::framework::Service const& ccdbObj, TString filepath, TString histname_antip_jet, TString histname_antip_ue) - { - TList* l = ccdbObj->get(filepath.Data()); - if (!l) { - LOGP(error, "Could not open the file {}", Form("%s", filepath.Data())); - return; - } - twoDweightsAntipJet = static_cast(l->FindObject(Form("%s_antiproton", histname_antip_jet.Data()))); - if (!twoDweightsAntipJet) { - LOGP(error, "Could not open histogram {}", Form("%s_antiproton", histname_antip_jet.Data())); - return; - } - twoDweightsAntipUe = static_cast(l->FindObject(Form("%s_antiproton", histname_antip_ue.Data()))); - if (!twoDweightsAntipUe) { - LOGP(error, "Could not open histogram {}", Form("%s_antiproton", histname_antip_ue.Data())); - return; - } - LOGP(info, "Opened histogram {}", Form("%s_antiproton", histname_antip_jet.Data())); - LOGP(info, "Opened histogram {}", Form("%s_antiproton", histname_antip_ue.Data())); + // PID variables and transverse momentum of the track + const double nsigmaTPC = track.tpcNSigmaDe(); + const double nsigmaTOF = track.tofNSigmaDe(); + const double pt = track.pt(); + + // Apply TPC PID cut + if (std::abs(nsigmaTPC) > kNsigmaMax) + return false; + + // Low-pt: TPC PID is sufficient + if (pt < kPtThreshold) + return true; + + // High-pt: require valid TOF match and pass TOF PID + return (track.hasTOF() && std::abs(nsigmaTOF) < kNsigmaMax); } - bool shouldRejectEvent() + // Event rejection + bool rejectEvent() { static std::random_device rd; static std::mt19937 gen(rd()); - static std::uniform_int_distribution<> dis(0, 99); - int randomNumber = dis(gen); - if (randomNumber > rejectionPercentage) { - return false; // accept event - } - return true; // reject event + static std::uniform_real_distribution dis(0.0, 100.0); + + return dis(gen) < rejectionPercentage; } // Process Data - void processData(SelectedCollisions::iterator const& collision, FullNucleiTracks const& tracks) + void processData(SelectedCollisions::iterator const& collision, AntiNucleiTracks const& tracks, aod::BCsWithTimestamps const&) { - if (rejectEvents) { - // event counter: before event rejection - registryData.fill(HIST("number_of_rejected_events"), 0.5); + // Event counter: before event selection + registryData.fill(HIST("number_of_events_data"), 0.5); - if (shouldRejectEvent()) - return; + // Retrieve the bunch crossing information with timestamps from the collision + auto bc = collision.template bc_as(); + initCCDB(bc); - // event counter: after event rejection - registryData.fill(HIST("number_of_rejected_events"), 1.5); + // If skimmed processing is enabled, apply Zorro trigger selection + if (cfgSkimmedProcessing && !zorro.isSelected(collision.template bc_as().globalBC())) { + return; } + registryData.fill(HIST("number_of_events_data"), 1.5); - // event counter: before event selection - registryData.fill(HIST("number_of_events_data"), 0.5); - - // event selection + // Apply standard event selection if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) return; - // event counter: after event selection - registryData.fill(HIST("number_of_events_data"), 1.5); + // Event counter: after event selection + registryData.fill(HIST("number_of_events_data"), 2.5); + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + return; + registryData.fill(HIST("number_of_events_data"), 3.5); + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + return; + registryData.fill(HIST("number_of_events_data"), 4.5); + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return; + registryData.fill(HIST("number_of_events_data"), 5.5); + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + registryData.fill(HIST("number_of_events_data"), 6.5); + + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + registryData.fill(HIST("number_of_events_data"), 7.5); - // loop over reconstructed tracks + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + return; + registryData.fill(HIST("number_of_events_data"), 8.5); + + // Loop over reconstructed tracks int id(-1); std::vector fjParticles; for (auto const& track : tracks) { @@ -566,54 +766,61 @@ struct AntinucleiInJets { fjParticles.emplace_back(fourMomentum); } - // reject empty events - if (fjParticles.size() < 1) + // Reject empty events + if (fjParticles.empty()) return; - registryData.fill(HIST("number_of_events_data"), 2.5); + registryData.fill(HIST("number_of_events_data"), 9.5); - // cluster particles using the anti-kt algorithm + // Cluster particles using the anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); - fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // active_area_explicit_ghosts + 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()); auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // loop over reconstructed jets + // Loop over reconstructed jets bool isAtLeastOneJetSelected = false; for (const auto& jet : jets) { - // jet must be fully contained in the acceptance + // Jet must be fully contained in the acceptance if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) continue; - // jet pt must be larger than threshold + // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + if (jetMinusBkg.pt() < minJetPt) + continue; + + // Apply area cut if required + double normalizedJetArea = jet.area() / (PI * rJet * rJet); + if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) continue; isAtLeastOneJetSelected = true; - // perpendicular cone + // Perpendicular cones double coneRadius = std::sqrt(jet.area() / PI); - TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); // before or after subtraction of perpendicular cone? + TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0); TVector3 ueAxis2(0, 0, 0); getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); - // get jet constituents + // Fill histogram with jet effective area / piR^2 + registryData.fill(HIST("jetEffectiveAreaOverPiR2"), jet.area() / (PI * rJet * rJet)); + + // Get jet constituents std::vector jetConstituents = jet.constituents(); - o2::aod::ITSResponse itsResponse; - // loop over jet constituents + // Loop over jet constituents for (const auto& particle : jetConstituents) { - // get corresponding track and apply track selection criteria + // Get corresponding track and apply track selection criteria auto const& track = tracks.iteratorAt(particle.user_index()); if (!passedTrackSelection(track)) continue; - // variables + // Define variables double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); double nsigmaTPCDe = track.tpcNSigmaDe(); @@ -623,39 +830,32 @@ struct AntinucleiInJets { double dcaxy = track.dcaXY(); double dcaz = track.dcaZ(); - // fill DCA distribution for antiprotons + // Fill DCA distribution for antiprotons if (track.sign() < 0 && isHighPurityAntiproton(track) && std::fabs(dcaz) < maxDcaz) { registryData.fill(HIST("antiproton_dca_jet"), pt, dcaxy); } - // DCA selections + // Apply DCA selections if (std::fabs(dcaxy) > maxDcaxy || std::fabs(dcaz) > maxDcaz) continue; - // particle identification using the ITS cluster size - bool passedItsPidProt(false), passedItsPidDeut(false), passedItsPidHel(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + // Particle identification using the ITS cluster size + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidHel = true; + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; - passedItsPidHel = true; + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMin || nSigmaITShel3 > nSigmaItsMax)) { + passedItsPidHel = false; } - if (pt > ptMaxItsPidProt) - passedItsPidProt = true; - if (pt > ptMaxItsPidDeut) - passedItsPidDeut = true; - if ((2.0 * pt) > ptMaxItsPidHel) - passedItsPidHel = true; - - // antimatter + + // Fill histograms for antimatter if (track.sign() < 0) { if (passedItsPidProt) { registryData.fill(HIST("antiproton_jet_tpc"), pt, nsigmaTPCPr); @@ -672,33 +872,45 @@ struct AntinucleiInJets { } } - // matter + // Fill histograms for matter if (track.sign() > 0) { - if (passedItsPidDeut && nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc && track.hasTOF()) - registryData.fill(HIST("deuteron_jet_tof"), pt, nsigmaTOFDe); + if (passedItsPidDeut) { + registryData.fill(HIST("deuteron_jet_tpc"), pt, nsigmaTPCDe); + if (nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("deuteron_jet_tof"), pt, nsigmaTOFDe); + } if (passedItsPidHel) { registryData.fill(HIST("helium3_jet_tpc"), 2.0 * pt, nsigmaTPCHe); } } } - // underlying event + // Loop over tracks in the underlying event for (auto const& track : tracks) { - // get corresponding track and apply track selection criteria + // Get corresponding track and apply track selection criteria if (!passedTrackSelection(track)) continue; + // Calculate the angular distance between the track and underlying event axes in eta-phi space double deltaEtaUe1 = track.eta() - ueAxis1.Eta(); double deltaPhiUe1 = getDeltaPhi(track.phi(), ueAxis1.Phi()); double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); double deltaEtaUe2 = track.eta() - ueAxis2.Eta(); double deltaPhiUe2 = getDeltaPhi(track.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - if (deltaRUe1 > coneRadius && deltaRUe2 > coneRadius) + + // Determine the maximum allowed distance from UE axes for particle selection + double maxConeRadius = coneRadius; + if (applyAreaCut) { + maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; + } + + // Reject tracks that lie outside the maxConeRadius from both UE axes + if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) continue; - // variables + // Define variables double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); double nsigmaTPCDe = track.tpcNSigmaDe(); @@ -708,39 +920,32 @@ struct AntinucleiInJets { double dcaxy = track.dcaXY(); double dcaz = track.dcaZ(); - // fill DCA distribution for antiprotons + // Fill DCA distribution for antiprotons if (track.sign() < 0 && isHighPurityAntiproton(track) && std::fabs(dcaz) < maxDcaz) { registryData.fill(HIST("antiproton_dca_ue"), pt, dcaxy); } - // DCA selections + // Apply DCA selections if (std::fabs(dcaxy) > maxDcaxy || std::fabs(dcaz) > maxDcaz) continue; - // particle identification using the ITS cluster size - bool passedItsPidProt(false), passedItsPidDeut(false), passedItsPidHel(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + // Particle identification using the ITS cluster size + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidHel = true; + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; - passedItsPidHel = true; + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMin || nSigmaITShel3 > nSigmaItsMax)) { + passedItsPidHel = false; } - if (pt > ptMaxItsPidProt) - passedItsPidProt = true; - if (pt > ptMaxItsPidDeut) - passedItsPidDeut = true; - if ((2.0 * pt) > ptMaxItsPidHel) - passedItsPidHel = true; - - // antimatter + + // Fill histograms for antimatter if (track.sign() < 0) { if (passedItsPidProt) { registryData.fill(HIST("antiproton_ue_tpc"), pt, nsigmaTPCPr); @@ -757,31 +962,130 @@ struct AntinucleiInJets { } } - // matter + // Fill histograms for matter if (track.sign() > 0) { - if (passedItsPidDeut && nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc && track.hasTOF()) - registryData.fill(HIST("deuteron_ue_tof"), pt, nsigmaTOFDe); - // helium3 + if (passedItsPidDeut) { + registryData.fill(HIST("deuteron_ue_tpc"), pt, nsigmaTPCDe); + if (nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc && track.hasTOF()) + registryData.fill(HIST("deuteron_ue_tof"), pt, nsigmaTOFDe); + } if (passedItsPidHel) { registryData.fill(HIST("helium3_ue_tpc"), 2.0 * pt, nsigmaTPCHe); } } } } + // Event counter: events with at least one jet selected if (isAtLeastOneJetSelected) { - registryData.fill(HIST("number_of_events_data"), 3.5); + registryData.fill(HIST("number_of_events_data"), 10.5); } } PROCESS_SWITCH(AntinucleiInJets, processData, "Process Data", true); + // Charged-particle multiplicity in events with selected jets (Run 3) or ptTrigger > threshold (Run 2-like) + void processMultEvents(SelectedCollisions::iterator const& collision, AntiNucleiTracks const& tracks) + { + // Apply event selection + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + return; + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + return; + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + return; + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return; + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + return; + + // Initialize variable to store the maximum pt in the event + double ptMax(0.0); + + // Loop over reconstructed tracks + int id(-1); + std::vector fjParticles; + for (auto const& track : tracks) { + id++; + if (!passedTrackSelectionForJetReconstruction(track)) + continue; + if (track.pt() > ptMax) { + ptMax = track.pt(); + } + + // 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); + } + + // Reject empty events + if (fjParticles.empty()) { + return; + } + + // Fill charged-particle multiplicity for events with leading track having pt>threshold + if (ptMax > ptLeadingMin) { + registryMult.fill(HIST("multiplicityEvtsPtLeading"), fjParticles.size()); + } + + // Cluster particles using the anti-kt algorithm + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + 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()); + auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); + + // Loop over reconstructed jets + bool isAtLeastOneJetSelected = false; + for (const auto& jet : jets) { + + // Jet must be fully contained in the acceptance + if ((std::fabs(jet.eta()) + rJet) > (maxEta - 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; + + // Apply area cut if required + double normalizedJetArea = jet.area() / (PI * rJet * rJet); + if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + continue; + isAtLeastOneJetSelected = true; + } + + // Fill histogram of charged-particle multiplicity for events containing at least one selected jet + if (isAtLeastOneJetSelected) { + registryMult.fill(HIST("multiplicityEvtsWithJet"), fjParticles.size()); + } + } + PROCESS_SWITCH(AntinucleiInJets, processMultEvents, "Process Mult Events", false); + // Process QC - void processQC(SelectedCollisions::iterator const& collision, FullNucleiTracks const& tracks) + void processQC(SelectedCollisions::iterator const& collision, AntiNucleiTracks const& tracks) { - // event selection + // Apply event selection if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) return; + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + return; + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + return; + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return; + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + return; - // loop over reconstructed tracks + // Loop over reconstructed tracks std::vector fjParticles; for (auto const& track : tracks) { if (!passedTrackSelectionForJetReconstruction(track)) @@ -792,41 +1096,43 @@ struct AntinucleiInJets { fjParticles.emplace_back(fourMomentum); } - // reject empty events - if (fjParticles.size() < 1) + // Reject empty events + if (fjParticles.empty()) return; - // cluster particles using the anti-kt algorithm + // Cluster particles using the anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); - fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // active_area_explicit_ghosts + 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()); auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // loop over reconstructed jets + // Loop over reconstructed jets int njetsInAcc(0); int njetsHighPt(0); for (const auto& jet : jets) { - // jet must be fully contained in the acceptance + // Jet must be fully contained in the acceptance if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) continue; njetsInAcc++; registryQC.fill(HIST("sumPtJetCone"), jet.pt()); double ptJetBeforeSub = jet.pt(); - // jet pt must be larger than threshold + // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); double ptJetAfterSub = jetForSub.pt(); registryQC.fill(HIST("jetPtDifference"), ptJetAfterSub - ptJetBeforeSub); + registryQC.fill(HIST("ptDistributionJetCone"), ptJetBeforeSub); + registryQC.fill(HIST("ptDistributionJet"), ptJetAfterSub); - if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + if (jetMinusBkg.pt() < minJetPt) continue; njetsHighPt++; registryQC.fill(HIST("sumPtJet"), jet.pt()); - // jet properties and perpendicular cone + // Jet properties and perpendicular cone std::vector jetConstituents = jet.constituents(); TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); double coneRadius = std::sqrt(jet.area() / PI); @@ -835,10 +1141,9 @@ struct AntinucleiInJets { getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); - registryQC.fill(HIST("jetEffectiveArea"), jet.area() / (PI * rJet * rJet)); registryQC.fill(HIST("NchJetCone"), static_cast(jetConstituents.size())); - // loop over jet constituents + // Loop over jet constituents for (const auto& particle : jetConstituents) { double deltaEta = particle.eta() - jetAxis.Eta(); @@ -847,7 +1152,7 @@ struct AntinucleiInJets { registryQC.fill(HIST("eta_phi_jet"), particle.eta(), particle.phi()); } - // loop over particles in perpendicular cones + // Loop over particles in perpendicular cones double nParticlesPerp(0); double ptPerp(0); for (auto const& track : tracks) { @@ -880,452 +1185,1062 @@ struct AntinucleiInJets { } PROCESS_SWITCH(AntinucleiInJets, processQC, "Process QC", false); - void processEfficiency(SimCollisions const& collisions, MCTracks const& mcTracks, aod::McParticles const& mcParticles) + // Antinuclei reconstruction efficiency + void processAntinucleiEfficiency(RecCollisionsMc const& collisions, AntiNucleiTracksMc const& mcTracks, aod::McParticles const& mcParticles) { + // Loop over all simulated collision events for (const auto& collision : collisions) { - // event counter before event selection - registryMC.fill(HIST("number_of_events_mc"), 0.5); + // Count all generated events before applying any event selection criteria + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 0.5); - // event selection + // Apply event selection: require sel8 and vertex position within the allowed z range if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) continue; - // event counter after event selection - registryMC.fill(HIST("number_of_events_mc"), 1.5); + // Count events that pass the selection criteria + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 1.5); + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 2.5); + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 3.5); + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + continue; + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 4.5); + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 5.5); + + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 6.5); + + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + continue; + registryMC.fill(HIST("number_of_events_mc_nuclei_efficiency"), 7.5); - // generated + // Loop over all generated Monte Carlo particles for the selected event for (const auto& particle : mcParticles) { + // Select primary particles if (!particle.isPhysicalPrimary()) continue; - if (particle.pdgCode() == kProtonBar) { - registryMC.fill(HIST("antiproton_eta_pt_pythia"), particle.pt(), particle.eta()); - } - + // Select particles within the specified pseudorapidity interval if (particle.eta() < minEta || particle.eta() > maxEta) continue; + // Process different particle species based on PDG code switch (particle.pdgCode()) { - case kProtonBar: - registryMC.fill(HIST("antiproton_incl_gen"), particle.pt()); + case PDG_t::kProtonBar: + registryMC.fill(HIST("antip_gen_jet"), particle.pt()); + registryMC.fill(HIST("antip_gen_ue"), particle.pt()); break; case o2::constants::physics::Pdg::kDeuteron: - registryMC.fill(HIST("deuteron_incl_gen"), particle.pt()); + registryMC.fill(HIST("deuteron_gen_jet"), particle.pt()); + registryMC.fill(HIST("deuteron_gen_ue"), particle.pt()); break; case -o2::constants::physics::Pdg::kDeuteron: - registryMC.fill(HIST("antideuteron_incl_gen"), particle.pt()); + registryMC.fill(HIST("antideuteron_gen_jet"), particle.pt()); + registryMC.fill(HIST("antideuteron_gen_ue"), particle.pt()); break; case o2::constants::physics::Pdg::kHelium3: - registryMC.fill(HIST("helium3_incl_gen"), particle.pt()); + registryMC.fill(HIST("helium3_gen_jet"), particle.pt()); + registryMC.fill(HIST("helium3_gen_ue"), particle.pt()); break; case -o2::constants::physics::Pdg::kHelium3: - registryMC.fill(HIST("antihelium3_incl_gen"), particle.pt()); + registryMC.fill(HIST("antihelium3_gen_jet"), particle.pt()); + registryMC.fill(HIST("antihelium3_gen_ue"), particle.pt()); break; } } - // ITS pid using cluster size - o2::aod::ITSResponse itsResponse; - - // Reconstructed Tracks + // Loop over all reconstructed MC tracks for (auto const& track : mcTracks) { - // Track Selection + // Apply standard track selection criteria if (!passedTrackSelection(track)) continue; - if (std::fabs(track.dcaXY()) > maxDcaxy) - continue; - if (std::fabs(track.dcaZ()) > maxDcaz) + + // Cut on transverse and longitudinal distance of closest approach + if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) continue; - // Get MC Particle + // Skip tracks that are not associated with a true MC particle if (!track.has_mcParticle()) continue; const auto particle = track.mcParticle(); - // Variables + // Select only physical primary particles + if (!particle.isPhysicalPrimary()) + continue; + + // Retrieve PID responses from TPC and TOF detectors for proton, deuteron, helium-3 double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); double nsigmaTPCDe = track.tpcNSigmaDe(); double nsigmaTOFDe = track.tofNSigmaDe(); double nsigmaTPCHe = track.tpcNSigmaHe(); + double pt = track.pt(); // particle identification using the ITS cluster size - bool passedItsPidProt(false), passedItsPidDeut(false), passedItsPidHel(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidHel = true; + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; - passedItsPidHel = true; + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMin || nSigmaITShel3 > nSigmaItsMax)) { + passedItsPidHel = false; } - if (track.pt() > ptMaxItsPidProt) - passedItsPidProt = true; - if (track.pt() > ptMaxItsPidDeut) - passedItsPidDeut = true; - if ((2.0 * track.pt()) > ptMaxItsPidHel) - passedItsPidHel = true; - - if (particle.pdgCode() == kProtonBar) - registryMC.fill(HIST("antiproton_incl_all"), track.pt()); - - if (!particle.isPhysicalPrimary()) - continue; - if (particle.pdgCode() == kProtonBar) - registryMC.fill(HIST("antiproton_incl_prim"), track.pt()); - - // antiprotons - if (particle.pdgCode() == kProtonBar && passedItsPidProt) { + // Fill histograms of antiprotons + if (track.sign() < 0 && particle.pdgCode() == PDG_t::kProtonBar && passedItsPidProt) { if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { - registryMC.fill(HIST("antiproton_incl_rec_tpc"), track.pt()); - if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) - registryMC.fill(HIST("antiproton_incl_rec_tof"), track.pt()); + registryMC.fill(HIST("antip_rec_tpc_jet"), track.pt()); + registryMC.fill(HIST("antip_rec_tpc_ue"), track.pt()); + + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { + registryMC.fill(HIST("antip_rec_tof_jet"), track.pt()); + registryMC.fill(HIST("antip_rec_tof_ue"), track.pt()); + } } } - // antideuterons - if (particle.pdgCode() == -o2::constants::physics::Pdg::kDeuteron && passedItsPidDeut) { + // Fill histograms of antideuterons + if (track.sign() < 0 && particle.pdgCode() == -o2::constants::physics::Pdg::kDeuteron && passedItsPidDeut) { if (nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc) { - registryMC.fill(HIST("antideuteron_incl_rec_tpc"), track.pt()); - if (track.hasTOF() && nsigmaTOFDe > minNsigmaTof && nsigmaTOFDe < maxNsigmaTof) - registryMC.fill(HIST("antideuteron_incl_rec_tof"), track.pt()); + registryMC.fill(HIST("antideuteron_rec_tpc_jet"), track.pt()); + registryMC.fill(HIST("antideuteron_rec_tpc_ue"), track.pt()); + + if (track.hasTOF() && nsigmaTOFDe > minNsigmaTof && nsigmaTOFDe < maxNsigmaTof) { + registryMC.fill(HIST("antideuteron_rec_tof_jet"), track.pt()); + registryMC.fill(HIST("antideuteron_rec_tof_ue"), track.pt()); + } } } - // deuterons - if (particle.pdgCode() == o2::constants::physics::Pdg::kDeuteron && passedItsPidDeut) { + // Fill histograms of deuterons + if (track.sign() > 0 && particle.pdgCode() == o2::constants::physics::Pdg::kDeuteron && passedItsPidDeut) { if (nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc) { - registryMC.fill(HIST("deuteron_incl_rec_tpc"), track.pt()); - if (track.hasTOF() && nsigmaTOFDe > minNsigmaTof && nsigmaTOFDe < maxNsigmaTof) - registryMC.fill(HIST("deuteron_incl_rec_tof"), track.pt()); + registryMC.fill(HIST("deuteron_rec_tpc_jet"), track.pt()); + registryMC.fill(HIST("deuteron_rec_tpc_ue"), track.pt()); + if (track.hasTOF() && nsigmaTOFDe > minNsigmaTof && nsigmaTOFDe < maxNsigmaTof) { + registryMC.fill(HIST("deuteron_rec_tof_jet"), track.pt()); + registryMC.fill(HIST("deuteron_rec_tof_ue"), track.pt()); + } } } - // antihelium3 - if (particle.pdgCode() == -o2::constants::physics::Pdg::kHelium3 && passedItsPidHel) { + // Fill histograms of antihelium3 + if (track.sign() < 0 && particle.pdgCode() == -o2::constants::physics::Pdg::kHelium3 && passedItsPidHel) { if (nsigmaTPCHe > minNsigmaTpc && nsigmaTPCHe < maxNsigmaTpc) { - registryMC.fill(HIST("antihelium3_incl_rec_tpc"), 2.0 * track.pt()); + registryMC.fill(HIST("antihelium3_rec_tpc_jet"), 2.0 * track.pt()); + registryMC.fill(HIST("antihelium3_rec_tpc_ue"), 2.0 * track.pt()); } } - // helium3 - if (particle.pdgCode() == o2::constants::physics::Pdg::kHelium3 && passedItsPidHel) { + // Fill histograms of helium3 + if (track.sign() > 0 && particle.pdgCode() == o2::constants::physics::Pdg::kHelium3 && passedItsPidHel) { if (nsigmaTPCHe > minNsigmaTpc && nsigmaTPCHe < maxNsigmaTpc) { - registryMC.fill(HIST("helium3_incl_rec_tpc"), 2.0 * track.pt()); + registryMC.fill(HIST("helium3_rec_tpc_jet"), 2.0 * track.pt()); + registryMC.fill(HIST("helium3_rec_tpc_ue"), 2.0 * track.pt()); } } } } } - PROCESS_SWITCH(AntinucleiInJets, processEfficiency, "process efficiency", false); + PROCESS_SWITCH(AntinucleiInJets, processAntinucleiEfficiency, "process antinuclei efficiency", false); - void processJetsMCgen(SimCollisions const& collisions, aod::McParticles const& mcParticles) + // Generated events + void processJetsMCgen(GenCollisionsMc const& collisions, aod::McParticles const& mcParticles) { + // Loop over all simulated collisions for (const auto& collision : collisions) { - // event selection - if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + // Event counter: before event selection + registryMC.fill(HIST("genEvents"), 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 + registryMC.fill(HIST("genEvents"), 1.5); + + // Loop over all MC particles std::vector fjParticles; + std::vector protonMomentum; for (const auto& particle : mcParticles) { + // Select physical primaries within acceptance if (!particle.isPhysicalPrimary()) continue; - double minPtParticle = 0.1; - if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < minPtParticle) + static constexpr double MinPtParticle = 0.1; + if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < MinPtParticle) continue; + // Store 3-momentum vectors of antiprotons for further analysis + if (particle.pdgCode() == PDG_t::kProtonBar) { + TVector3 pVec(particle.px(), particle.py(), particle.pz()); + protonMomentum.push_back(pVec); + } + + // 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); fourMomentum.set_user_index(particle.pdgCode()); fjParticles.emplace_back(fourMomentum); } - // reject empty events - if (fjParticles.size() < 1) + + // Reject empty events + if (fjParticles.empty()) continue; + registryMC.fill(HIST("genEvents"), 2.5); - // cluster particles using the anti-kt algorithm + // Cluster MC particles into jets using anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); - fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // active_area_explicit_ghosts + 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()); auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // loop over jets + // Loop over clustered jets + bool isAtLeastOneJetSelected = false; for (const auto& jet : jets) { - // jet must be fully contained in the acceptance + // Jet must be fully contained in the acceptance if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) continue; - // jet pt must be larger than threshold + // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); if (jetMinusBkg.pt() < minJetPt) continue; - // jet properties and perpendicular cone - std::vector jetConstituents = jet.constituents(); - TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - double coneRadius = std::sqrt(jet.area() / PI); - TVector3 ueAxis1(0, 0, 0); - TVector3 ueAxis2(0, 0, 0); - getPerpendicularAxis(jetAxis, ueAxis1, +1); - getPerpendicularAxis(jetAxis, ueAxis2, -1); + // Apply area cut if required + double normalizedJetArea = jet.area() / (PI * rJet * rJet); + if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + continue; + isAtLeastOneJetSelected = true; - // loop over jet constituents + // Analyze jet constituents + std::vector jetConstituents = jet.constituents(); for (const auto& particle : jetConstituents) { + if (particle.user_index() != PDG_t::kProtonBar) + continue; - if (particle.user_index() != kProtonBar) + if (particle.eta() < minEta || particle.eta() > maxEta) continue; - registryMC.fill(HIST("antiproton_jet_gen"), particle.pt()); - registryMC.fill(HIST("antiproton_eta_pt_jet"), particle.pt(), particle.eta()); + + // Fill histogram for generated antiprotons + registryMC.fill(HIST("antiproton_gen_jet"), particle.pt()); } - // loop over underlying-event - for (const auto& particle : mcParticles) { + // 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); + TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); + getPerpendicularAxis(jetAxis, ueAxis1, +1); + getPerpendicularAxis(jetAxis, ueAxis2, -1); - if (!particle.isPhysicalPrimary()) - continue; - double minPtParticle = 0.1; - if (particle.eta() < minEta || particle.eta() > maxEta || particle.pt() < minPtParticle) - continue; + // Loop over MC particles to analyze underlying event region + for (const auto& protonVec : protonMomentum) { - double deltaEtaUe1 = particle.eta() - ueAxis1.Eta(); - double deltaPhiUe1 = getDeltaPhi(particle.phi(), ueAxis1.Phi()); + // Compute distance of particle from both perpendicular cone axes + double deltaEtaUe1 = protonVec.Eta() - ueAxis1.Eta(); + double deltaPhiUe1 = getDeltaPhi(protonVec.Phi(), ueAxis1.Phi()); double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - double deltaEtaUe2 = particle.eta() - ueAxis2.Eta(); - double deltaPhiUe2 = getDeltaPhi(particle.phi(), ueAxis2.Phi()); + double deltaEtaUe2 = protonVec.Eta() - ueAxis2.Eta(); + double deltaPhiUe2 = getDeltaPhi(protonVec.Phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - if (deltaRUe1 > coneRadius && deltaRUe2 > coneRadius) - continue; - if (particle.pdgCode() != kProtonBar) + // Determine the maximum allowed distance from UE axes for particle selection + double maxConeRadius = coneRadius; + if (applyAreaCut) { + maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; + } + + // Reject tracks that lie outside the maxConeRadius from both UE axes + if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) continue; - registryMC.fill(HIST("antiproton_ue_gen"), particle.pt()); - registryMC.fill(HIST("antiproton_eta_pt_ue"), particle.pt(), particle.eta()); + // Fill histogram for antiprotons in the UE + registryMC.fill(HIST("antiproton_gen_ue"), protonVec.Pt()); } } + if (isAtLeastOneJetSelected) { + registryMC.fill(HIST("genEvents"), 3.5); + } } } PROCESS_SWITCH(AntinucleiInJets, processJetsMCgen, "process jets mc gen", false); - void processJetsMCrec(SimCollisions const& collisions, MCTracks const& mcTracks, McParticles const&) + // Reconstructed events + void processJetsMCrec(RecCollisionsMc const& collisions, AntiNucleiTracksMc const& mcTracks, McParticles const&) { + // Loop over all reconstructed collisions for (const auto& collision : collisions) { - // event selection + // Event counter: before event selection + registryMC.fill(HIST("recEvents"), 0.5); + + // Apply event selection: require sel8 and vertex position to be within the allowed z range if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) - return; + continue; + + // Event counter: after event selection + registryMC.fill(HIST("recEvents"), 1.5); + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + continue; + registryMC.fill(HIST("recEvents"), 2.5); + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + continue; + registryMC.fill(HIST("recEvents"), 3.5); + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + continue; + registryMC.fill(HIST("recEvents"), 4.5); + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + continue; + registryMC.fill(HIST("recEvents"), 5.5); - // loop over reconstructed tracks + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + continue; + registryMC.fill(HIST("recEvents"), 6.5); + + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + continue; + registryMC.fill(HIST("recEvents"), 7.5); + + // Loop over reconstructed tracks int id(-1); std::vector fjParticles; + std::vector trackIndex; for (auto const& track : mcTracks) { id++; + + // Get corresponding MC particle + if (!track.has_mcParticle()) + continue; + const auto mcparticle = track.mcParticle(); + + // Store track index for antiproton tracks + if (passedTrackSelection(track) && track.sign() < 0 && mcparticle.pdgCode() == PDG_t::kProtonBar) { + trackIndex.emplace_back(id); + } + + // Apply track selection for jet reconstruction if (!passedTrackSelectionForJetReconstruction(track)) continue; - // 4-momentum representations of a particle + // 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); } - // reject empty events - if (fjParticles.size() < 1) + + // Reject empty events + if (fjParticles.empty()) continue; + registryMC.fill(HIST("recEvents"), 8.5); - // cluster particles using the anti-kt algorithm + // Cluster particles using the anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); 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()); auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // loop over reconstructed jets + // Loop over reconstructed jets + bool isAtLeastOneJetSelected = false; for (const auto& jet : jets) { - // get jet constituents - std::vector jetConstituents = jet.constituents(); - - // calculate generated jet pt - double jetPtGen(0); - for (const auto& particle : jetConstituents) { - - // get corresponding track - auto const& track = mcTracks.iteratorAt(particle.user_index()); - if (!track.has_mcParticle()) - continue; - const auto mcparticle = track.mcParticle(); - jetPtGen = jetPtGen + mcparticle.pt(); - } - - // jet must be fully contained in the acceptance + // Jet must be fully contained in the acceptance if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) continue; - // fill detector response matrix - registryMC.fill(HIST("detectorResponseMatrix"), jet.pt(), jetPtGen - jet.pt()); // maybe it should be filled after bkg sub - registryMC.fill(HIST("generatedVsReconstructedPt"), jet.pt(), jetPtGen); - - // jet pt must be larger than threshold + // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + if (jetMinusBkg.pt() < minJetPt) continue; - // perpendicular cone + // Apply area cut if required + double normalizedJetArea = jet.area() / (PI * rJet * rJet); + if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) + continue; + isAtLeastOneJetSelected = true; + + // Set up two perpendicular cone axes for underlying event estimation double coneRadius = std::sqrt(jet.area() / PI); TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - TVector3 ueAxis1(0, 0, 0); - TVector3 ueAxis2(0, 0, 0); + TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); - o2::aod::ITSResponse itsResponse; // to be implemented + // Get jet constituents + std::vector jetConstituents = jet.constituents(); - // loop over jet constituents + // Loop over jet constituents for (const auto& particle : jetConstituents) { - // get corresponding track and apply track selection criteria + // Get corresponding track and apply track selection criteria auto const& track = mcTracks.iteratorAt(particle.user_index()); if (!passedTrackSelection(track)) continue; - if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) - continue; + + // Antimatter selection if (track.sign() > 0) continue; + + // Get corresponding MC particle if (!track.has_mcParticle()) continue; const auto mcparticle = track.mcParticle(); - if (mcparticle.pdgCode() != kProtonBar) + + // Antiproton selection based on the PDG + if (mcparticle.pdgCode() != PDG_t::kProtonBar) continue; - // variables + // Define variables double nsigmaTPCPr = track.tpcNSigmaPr(); double nsigmaTOFPr = track.tofNSigmaPr(); + double pt = track.pt(); + double dcaxy = track.dcaXY(); + double dcaz = track.dcaZ(); - registryMC.fill(HIST("antiproton_jet_all"), track.pt()); + // Fill DCA templates + if (std::fabs(dcaz) < maxDcaz) { + if (mcparticle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_dca_jet"), pt, dcaxy); + } else { + registryMC.fill(HIST("antiproton_all_dca_jet"), pt, dcaxy); + } + } - if (!mcparticle.isPhysicalPrimary()) + // Apply DCA selections + if (std::fabs(dcaxy) > maxDcaxy || std::fabs(dcaz) > maxDcaz) continue; - registryMC.fill(HIST("antiproton_jet_prim"), track.pt()); - - // particle identification using the ITS cluster size - bool passedItsPidProt(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; + // Particle identification using the ITS cluster size + bool passedItsPidProt(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; } - if (!applyItsPid) - passedItsPidProt = true; - if (track.pt() > ptMaxItsPidProt) - passedItsPidProt = true; - if (passedItsPidProt) { - registryMC.fill(HIST("antiproton_jet_rec_tpc"), track.pt(), nsigmaTPCPr); - registryMC.fill(HIST("antiproton_jet_tpc_rec_vs_generatedptjet"), track.pt(), jetPtGen); - if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc && track.hasTOF()) - registryMC.fill(HIST("antiproton_jet_rec_tof"), track.pt(), nsigmaTOFPr); - registryMC.fill(HIST("antiproton_jet_tof_rec_vs_generatedptjet"), track.pt(), jetPtGen); + // Fill inclusive antiproton spectrum + registryMC.fill(HIST("antiproton_incl_jet"), pt); + + // Select physical primary antiprotons + if (!mcparticle.isPhysicalPrimary()) + continue; + + // Fill antiproton spectrum for physical primaries + registryMC.fill(HIST("antiproton_prim_jet"), pt); + + // Fill histograms (TPC and TOF) only for selected candidates + if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { + registryMC.fill(HIST("antiproton_rec_tpc_jet"), pt); + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { + registryMC.fill(HIST("antiproton_rec_tof_jet"), pt); + } } } - // underlying event - for (auto const& track : mcTracks) { + // Loop over tracks in the underlying event + for (auto const& index : trackIndex) { - // get corresponding track and apply track selection criteria - if (!passedTrackSelection(track)) - continue; - if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) - continue; - if (track.sign() > 0) - continue; + // retrieve track associated to index + auto const& track = mcTracks.iteratorAt(index); + // Get corresponding MC particle if (!track.has_mcParticle()) continue; const auto mcparticle = track.mcParticle(); - if (mcparticle.pdgCode() != kProtonBar) + + // Define variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double pt = track.pt(); + double dcaxy = track.dcaXY(); + double dcaz = track.dcaZ(); + + // Fill DCA templates + if (std::fabs(dcaz) < maxDcaz) { + if (mcparticle.isPhysicalPrimary()) { + registryMC.fill(HIST("antiproton_prim_dca_ue"), pt, dcaxy); + } else { + registryMC.fill(HIST("antiproton_all_dca_ue"), pt, dcaxy); + } + } + + // Apply DCA selection + if (std::fabs(dcaxy) > maxDcaxy || std::fabs(dcaz) > maxDcaz) continue; + // Calculate the angular distance between the track and underlying event axes in eta-phi space double deltaEtaUe1 = track.eta() - ueAxis1.Eta(); double deltaPhiUe1 = getDeltaPhi(track.phi(), ueAxis1.Phi()); double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); double deltaEtaUe2 = track.eta() - ueAxis2.Eta(); double deltaPhiUe2 = getDeltaPhi(track.phi(), ueAxis2.Phi()); double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - if (deltaRUe1 > coneRadius && deltaRUe2 > coneRadius) + + // Determine the maximum allowed distance from UE axes for particle selection + double maxConeRadius = coneRadius; + if (applyAreaCut) { + maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; + } + + // Reject tracks that lie outside the maxConeRadius from both UE axes + if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) continue; - // variables - double nsigmaTPCPr = track.tpcNSigmaPr(); - double nsigmaTOFPr = track.tofNSigmaPr(); + // Particle identification using the ITS cluster size + bool passedItsPidProt(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; + } + + // Fill inclusive antiproton spectrum + registryMC.fill(HIST("antiproton_incl_ue"), pt); - registryMC.fill(HIST("antiproton_ue_all"), track.pt()); + // Select physical primary antiprotons if (!mcparticle.isPhysicalPrimary()) continue; - registryMC.fill(HIST("antiproton_ue_prim"), track.pt()); - // particle identification using the ITS cluster size - bool passedItsPidProt(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (!applyItsPid) - passedItsPidProt = true; - if (track.pt() > ptMaxItsPidProt) - passedItsPidProt = true; + // Fill antiproton spectrum for physical primaries + registryMC.fill(HIST("antiproton_prim_ue"), pt); - if (passedItsPidProt) { - if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { - registryMC.fill(HIST("antiproton_ue_rec_tpc"), track.pt()); - if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) - registryMC.fill(HIST("antiproton_ue_rec_tof"), track.pt()); + // Fill histograms (TPC and TOF) only for selected candidates + if (passedItsPidProt && nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { + registryMC.fill(HIST("antiproton_rec_tpc_ue"), pt); + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) { + registryMC.fill(HIST("antiproton_rec_tof_ue"), pt); } } } } + if (isAtLeastOneJetSelected) { + registryMC.fill(HIST("recEvents"), 9.5); + } } } PROCESS_SWITCH(AntinucleiInJets, processJetsMCrec, "process jets MC rec", false); - // Process Systematics - void processSystematicsData(SelectedCollisions::iterator const& collision, FullNucleiTracks const& tracks) + // Process real data with systematic variations of analysis parameters + void processSystData(SelectedCollisions::iterator const& collision, AntiNucleiTracks const& tracks) { - if (rejectEvents) { - // event counter: before event rejection - registryData.fill(HIST("number_of_rejected_events_syst"), 0.5); + // Event counter: before event selection + registryData.fill(HIST("number_of_events_data_syst"), 0.5); - if (shouldRejectEvent()) - return; + // Apply standard event selection + if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) + return; + + // Event counter: after event selection + registryData.fill(HIST("number_of_events_data_syst"), 1.5); + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + return; + registryData.fill(HIST("number_of_events_data_syst"), 2.5); + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + return; + registryData.fill(HIST("number_of_events_data_syst"), 3.5); + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return; + registryData.fill(HIST("number_of_events_data_syst"), 4.5); + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + registryData.fill(HIST("number_of_events_data_syst"), 5.5); + + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + registryData.fill(HIST("number_of_events_data_syst"), 6.5); - // event counter: after event rejection - registryData.fill(HIST("number_of_rejected_events_syst"), 1.5); + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + return; + registryData.fill(HIST("number_of_events_data_syst"), 7.5); + + // Cut settings + static std::vector maxDcaxySyst = { + 0.071, 0.060, 0.066, 0.031, 0.052, 0.078, 0.045, 0.064, 0.036, 0.074, + 0.079, 0.043, 0.067, 0.059, 0.032, 0.070, 0.048, 0.077, 0.062, 0.034, + 0.057, 0.055, 0.073, 0.038, 0.050, 0.075, 0.041, 0.061, 0.033, 0.069, + 0.035, 0.044, 0.076, 0.049, 0.037, 0.054, 0.072, 0.046, 0.058, 0.040, + 0.068, 0.042, 0.056, 0.039, 0.047, 0.065, 0.051, 0.053, 0.063, 0.030}; + static std::vector maxDcazSyst = { + 0.064, 0.047, 0.032, 0.076, 0.039, 0.058, 0.043, 0.069, 0.050, 0.035, + 0.074, 0.061, 0.045, 0.033, 0.068, 0.055, 0.037, 0.071, 0.042, 0.053, + 0.077, 0.038, 0.065, 0.049, 0.036, 0.059, 0.044, 0.067, 0.041, 0.034, + 0.073, 0.052, 0.040, 0.063, 0.046, 0.031, 0.070, 0.054, 0.037, 0.062, + 0.048, 0.035, 0.075, 0.051, 0.039, 0.066, 0.043, 0.060, 0.032, 0.056}; + static std::vector nSigmaItsMinSyst = { + -2.91, -2.77, -3.03, -3.40, -2.69, -3.28, -2.96, -3.11, -3.36, -3.14, + -2.99, -2.75, -3.17, -2.64, -2.72, -3.44, -2.87, -2.95, -3.00, -2.66, + -2.93, -3.31, -3.05, -3.12, -3.21, -3.01, -2.89, -2.73, -3.26, -2.97, + -2.81, -3.33, -2.68, -3.30, -2.78, -3.39, -2.84, -3.45, -2.92, -3.15, + -3.22, -2.58, -3.07, -2.86, -3.10, -2.76, -2.94, -3.25, -3.04, -2.82}; + static std::vector nSigmaItsMaxSyst = { + 2.91, 2.77, 3.03, 3.40, 2.69, 3.28, 2.96, 3.11, 3.36, 3.14, + 2.99, 2.75, 3.17, 2.64, 2.72, 3.44, 2.87, 2.95, 3.00, 2.66, + 2.93, 3.31, 3.05, 3.12, 3.21, 3.01, 2.89, 2.73, 3.26, 2.97, + 2.81, 3.33, 2.68, 3.30, 2.78, 3.39, 2.84, 3.45, 2.92, 3.15, + 3.22, 2.58, 3.07, 2.86, 3.10, 2.76, 2.94, 3.25, 3.04, 2.82}; + static std::vector minNsigmaTpcSyst = { + -3.18, -2.86, -3.12, -2.91, -3.49, -2.57, -3.33, -2.98, -3.46, -2.70, + -3.01, -2.65, -3.27, -3.40, -2.81, -3.10, -2.55, -3.22, -3.07, -2.77, + -3.35, -2.68, -3.43, -2.88, -3.04, -2.53, -3.30, -2.79, -3.15, -2.66, + -3.41, -2.75, -3.26, -2.61, -3.09, -2.54, -3.36, -2.95, -3.20, -2.58, + -3.44, -2.83, -3.11, -2.62, -3.28, -2.69, -3.23, -2.73, -3.39, -2.90}; + static std::vector maxNsigmaTpcSyst = { + 3.18, 2.86, 3.12, 2.91, 3.49, 2.57, 3.33, 2.98, 3.46, 2.70, + 3.01, 2.65, 3.27, 3.40, 2.81, 3.10, 2.55, 3.22, 3.07, 2.77, + 3.35, 2.68, 3.43, 2.88, 3.04, 2.53, 3.30, 2.79, 3.15, 2.66, + 3.41, 2.75, 3.26, 2.61, 3.09, 2.54, 3.36, 2.95, 3.20, 2.58, + 3.44, 2.83, 3.11, 2.62, 3.28, 2.69, 3.23, 2.73, 3.39, 2.90}; + + // Loop over reconstructed tracks + for (auto const& track : tracks) { + + // Select only antimatter + if (track.sign() > 0) + continue; + + // Loop over different cut settings + for (int isyst = 0; isyst < nSyst; isyst++) { + + // Apply track selection + if (!passedTrackSelectionSyst(track, isyst)) + continue; + + // Define variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double nsigmaTPCDe = track.tpcNSigmaDe(); + double nsigmaTOFDe = track.tofNSigmaDe(); + double nsigmaTPCHe = track.tpcNSigmaHe(); + double pt = track.pt(); + double dcaxy = track.dcaXY(); + double dcaz = track.dcaZ(); + + // Apply DCA selections + if (std::fabs(dcaxy) > maxDcaxySyst[isyst] || std::fabs(dcaz) > maxDcazSyst[isyst]) + continue; + + // Particle identification using the ITS cluster size (vary also PID ITS) + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMinSyst[isyst] || nSigmaITSprot > nSigmaItsMaxSyst[isyst])) { + passedItsPidProt = false; + } + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMinSyst[isyst] || nSigmaITSdeut > nSigmaItsMaxSyst[isyst])) { + passedItsPidDeut = false; + } + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMinSyst[isyst] || nSigmaITShel3 > nSigmaItsMaxSyst[isyst])) { + passedItsPidHel = false; + } + + // Fill histograms + if (passedItsPidProt) { + registryData.fill(HIST("antiproton_tpc_syst"), isyst, pt, nsigmaTPCPr); + if (nsigmaTPCPr > minNsigmaTpcSyst[isyst] && nsigmaTPCPr < maxNsigmaTpcSyst[isyst] && track.hasTOF()) + registryData.fill(HIST("antiproton_tof_syst"), isyst, pt, nsigmaTOFPr); + } + if (passedItsPidDeut) { + registryData.fill(HIST("antideuteron_tpc_syst"), isyst, pt, nsigmaTPCDe); + if (nsigmaTPCDe > minNsigmaTpcSyst[isyst] && nsigmaTPCDe < maxNsigmaTpcSyst[isyst] && track.hasTOF()) + registryData.fill(HIST("antideuteron_tof_syst"), isyst, pt, nsigmaTOFDe); + } + if (passedItsPidHel) { + registryData.fill(HIST("antihelium3_tpc_syst"), isyst, 2.0 * pt, nsigmaTPCHe); + } + } + } + } + PROCESS_SWITCH(AntinucleiInJets, processSystData, "Process syst data", false); + + // Process MC with systematic variations of analysis parameters + void processSystEff(GenCollisionsMc const& genCollisions, RecCollisionsMc const& recCollisions, AntiNucleiTracksMc const& mcTracks, aod::McParticles const& mcParticles) + { + // Cut settings + static std::vector maxDcaxySyst = { + 0.071, 0.060, 0.066, 0.031, 0.052, 0.078, 0.045, 0.064, 0.036, 0.074, + 0.079, 0.043, 0.067, 0.059, 0.032, 0.070, 0.048, 0.077, 0.062, 0.034, + 0.057, 0.055, 0.073, 0.038, 0.050, 0.075, 0.041, 0.061, 0.033, 0.069, + 0.035, 0.044, 0.076, 0.049, 0.037, 0.054, 0.072, 0.046, 0.058, 0.040, + 0.068, 0.042, 0.056, 0.039, 0.047, 0.065, 0.051, 0.053, 0.063, 0.030}; + static std::vector maxDcazSyst = { + 0.064, 0.047, 0.032, 0.076, 0.039, 0.058, 0.043, 0.069, 0.050, 0.035, + 0.074, 0.061, 0.045, 0.033, 0.068, 0.055, 0.037, 0.071, 0.042, 0.053, + 0.077, 0.038, 0.065, 0.049, 0.036, 0.059, 0.044, 0.067, 0.041, 0.034, + 0.073, 0.052, 0.040, 0.063, 0.046, 0.031, 0.070, 0.054, 0.037, 0.062, + 0.048, 0.035, 0.075, 0.051, 0.039, 0.066, 0.043, 0.060, 0.032, 0.056}; + static std::vector nSigmaItsMinSyst = { + -2.91, -2.77, -3.03, -3.40, -2.69, -3.28, -2.96, -3.11, -3.36, -3.14, + -2.99, -2.75, -3.17, -2.64, -2.72, -3.44, -2.87, -2.95, -3.00, -2.66, + -2.93, -3.31, -3.05, -3.12, -3.21, -3.01, -2.89, -2.73, -3.26, -2.97, + -2.81, -3.33, -2.68, -3.30, -2.78, -3.39, -2.84, -3.45, -2.92, -3.15, + -3.22, -2.58, -3.07, -2.86, -3.10, -2.76, -2.94, -3.25, -3.04, -2.82}; + static std::vector nSigmaItsMaxSyst = { + 2.91, 2.77, 3.03, 3.40, 2.69, 3.28, 2.96, 3.11, 3.36, 3.14, + 2.99, 2.75, 3.17, 2.64, 2.72, 3.44, 2.87, 2.95, 3.00, 2.66, + 2.93, 3.31, 3.05, 3.12, 3.21, 3.01, 2.89, 2.73, 3.26, 2.97, + 2.81, 3.33, 2.68, 3.30, 2.78, 3.39, 2.84, 3.45, 2.92, 3.15, + 3.22, 2.58, 3.07, 2.86, 3.10, 2.76, 2.94, 3.25, 3.04, 2.82}; + static std::vector minNsigmaTpcSyst = { + -3.18, -2.86, -3.12, -2.91, -3.49, -2.57, -3.33, -2.98, -3.46, -2.70, + -3.01, -2.65, -3.27, -3.40, -2.81, -3.10, -2.55, -3.22, -3.07, -2.77, + -3.35, -2.68, -3.43, -2.88, -3.04, -2.53, -3.30, -2.79, -3.15, -2.66, + -3.41, -2.75, -3.26, -2.61, -3.09, -2.54, -3.36, -2.95, -3.20, -2.58, + -3.44, -2.83, -3.11, -2.62, -3.28, -2.69, -3.23, -2.73, -3.39, -2.90}; + static std::vector maxNsigmaTpcSyst = { + 3.18, 2.86, 3.12, 2.91, 3.49, 2.57, 3.33, 2.98, 3.46, 2.70, + 3.01, 2.65, 3.27, 3.40, 2.81, 3.10, 2.55, 3.22, 3.07, 2.77, + 3.35, 2.68, 3.43, 2.88, 3.04, 2.53, 3.30, 2.79, 3.15, 2.66, + 3.41, 2.75, 3.26, 2.61, 3.09, 2.54, 3.36, 2.95, 3.20, 2.58, + 3.44, 2.83, 3.11, 2.62, 3.28, 2.69, 3.23, 2.73, 3.39, 2.90}; + static std::vector minNsigmaTofSyst = { + -3.18, -2.86, -3.12, -2.91, -3.49, -2.57, -3.33, -2.98, -3.46, -2.70, + -3.01, -2.65, -3.27, -3.40, -2.81, -3.10, -2.55, -3.22, -3.07, -2.77, + -3.35, -2.68, -3.43, -2.88, -3.04, -2.53, -3.30, -2.79, -3.15, -2.66, + -3.41, -2.75, -3.26, -2.61, -3.09, -2.54, -3.36, -2.95, -3.20, -2.58, + -3.44, -2.83, -3.11, -2.62, -3.28, -2.69, -3.23, -2.73, -3.39, -2.90}; + static std::vector maxNsigmaTofSyst = { + 3.94, 3.62, 3.83, 3.15, 3.23, 3.49, 3.10, 3.78, 3.54, 3.36, + 3.91, 3.84, 3.72, 3.00, 3.63, 3.13, 3.68, 3.40, 3.97, 3.01, + 3.74, 3.25, 3.89, 3.08, 3.30, 3.48, 3.59, 3.16, 3.47, 3.31, + 3.92, 3.03, 3.43, 3.24, 3.11, 3.86, 3.60, 3.07, 3.21, 3.98, + 3.14, 3.69, 3.56, 3.12, 3.28, 3.46, 3.34, 3.39, 3.05, 3.76}; + + // Loop over generated collisions + for (const auto& collision : genCollisions) { + + // Apply event selection: require vertex position to be within the allowed z range + if (std::fabs(collision.posZ()) > zVtx) + continue; + + // Loop over all generated Monte Carlo particles for the selected event + for (const auto& particle : mcParticles) { + + // Select primary particles + if (!particle.isPhysicalPrimary()) + continue; + + // Select particles within the specified pseudorapidity interval + if (particle.eta() < minEta || particle.eta() > maxEta) + continue; + + // Process different particle species based on PDG code + switch (particle.pdgCode()) { + case PDG_t::kProtonBar: + registryMC.fill(HIST("antiproton_gen_syst"), particle.pt()); + break; + case -o2::constants::physics::Pdg::kDeuteron: + registryMC.fill(HIST("antideuteron_gen_syst"), particle.pt()); + break; + case -o2::constants::physics::Pdg::kHelium3: + registryMC.fill(HIST("antihelium3_gen_syst"), particle.pt()); + break; + } + } } - const int nSystematics = 10; - int itsNclustersSyst[nSystematics] = {5, 6, 5, 4, 5, 3, 5, 6, 3, 4}; - float tpcNcrossedRowsSyst[nSystematics] = {100, 85, 80, 110, 95, 90, 105, 95, 100, 105}; - float dcaxySyst[nSystematics] = {0.05, 0.07, 0.10, 0.03, 0.06, 0.15, 0.08, 0.04, 0.09, 0.10}; - float dcazSyst[nSystematics] = {0.1, 0.15, 0.3, 0.075, 0.12, 0.18, 0.2, 0.1, 0.15, 0.2}; + // Loop over reconstructed collisions + for (const auto& collision : recCollisions) { - // event selection + // Apply standard event selection + 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; + + // Loop over reconstructed tracks + for (auto const& track : mcTracks) { + + // Select only antimatter + if (track.sign() > 0) + continue; + + // Get corresponding MC particle + if (!track.has_mcParticle()) + continue; + const auto mcparticle = track.mcParticle(); + + // Loop over different cut settings + for (int isyst = 0; isyst < nSyst; isyst++) { + + // Apply track selection + if (!passedTrackSelectionSyst(track, isyst)) + continue; + + // Define variables + double nsigmaTPCPr = track.tpcNSigmaPr(); + double nsigmaTOFPr = track.tofNSigmaPr(); + double nsigmaTPCDe = track.tpcNSigmaDe(); + double nsigmaTOFDe = track.tofNSigmaDe(); + double nsigmaTPCHe = track.tpcNSigmaHe(); + double pt = track.pt(); + double dcaxy = track.dcaXY(); + double dcaz = track.dcaZ(); + + // Apply DCA selections + if (std::fabs(dcaxy) > maxDcaxySyst[isyst] || std::fabs(dcaz) > maxDcazSyst[isyst]) + continue; + + // Fill inclusive antiproton spectrum + registryMC.fill(HIST("antiproton_incl_syst"), isyst, pt); + + // Select physical primary antiprotons + if (!mcparticle.isPhysicalPrimary()) + continue; + + // Fill antiproton spectrum for physical primaries + registryMC.fill(HIST("antiproton_prim_syst"), isyst, pt); + + // Particle identification using the ITS cluster size (vary also PID ITS) + bool passedItsPidProt(true), passedItsPidDeut(true), passedItsPidHel(true); + double nSigmaITSprot = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITSdeut = static_cast(itsResponse.nSigmaITS(track)); + double nSigmaITShel3 = static_cast(itsResponse.nSigmaITS(track)); + + if (applyItsPid && pt < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMinSyst[isyst] || nSigmaITSprot > nSigmaItsMaxSyst[isyst])) { + passedItsPidProt = false; + } + if (applyItsPid && pt < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMinSyst[isyst] || nSigmaITSdeut > nSigmaItsMaxSyst[isyst])) { + passedItsPidDeut = false; + } + if (applyItsPid && (2.0 * pt) < ptMaxItsPidHel && (nSigmaITShel3 < nSigmaItsMinSyst[isyst] || nSigmaITShel3 > nSigmaItsMaxSyst[isyst])) { + passedItsPidHel = false; + } + + // Fill histograms for antiprotons + if (passedItsPidProt && mcparticle.pdgCode() == PDG_t::kProtonBar && nsigmaTPCPr > minNsigmaTpcSyst[isyst] && nsigmaTPCPr < maxNsigmaTpcSyst[isyst]) { + registryMC.fill(HIST("antiproton_rec_tpc_syst"), isyst, pt); + if (track.hasTOF() && nsigmaTOFPr > minNsigmaTofSyst[isyst] && nsigmaTOFPr < maxNsigmaTofSyst[isyst]) + registryMC.fill(HIST("antiproton_rec_tof_syst"), isyst, pt); + } + // Fill histograms for antideuterons + if (passedItsPidDeut && mcparticle.pdgCode() == -o2::constants::physics::Pdg::kDeuteron && nsigmaTPCDe > minNsigmaTpcSyst[isyst] && nsigmaTPCDe < maxNsigmaTpcSyst[isyst]) { + registryMC.fill(HIST("antideuteron_rec_tpc_syst"), isyst, pt); + if (track.hasTOF() && nsigmaTOFDe > minNsigmaTofSyst[isyst] && nsigmaTOFDe < maxNsigmaTofSyst[isyst]) + registryMC.fill(HIST("antideuteron_rec_tof_syst"), isyst, pt); + } + // Fill histograms for antihelium3 + if (passedItsPidHel && mcparticle.pdgCode() == -o2::constants::physics::Pdg::kHelium3 && nsigmaTPCHe > minNsigmaTpcSyst[isyst] && nsigmaTPCHe < maxNsigmaTpcSyst[isyst]) { + registryMC.fill(HIST("antihelium3_rec_tpc_syst"), isyst, 2.0 * pt); + } + } + } + } + } + PROCESS_SWITCH(AntinucleiInJets, processSystEff, "process syst mc", false); + + // Process correlation + void processCorr(SelectedCollisions::iterator const& collision, AntiNucleiTracks const& tracks) + { + // Event counter: before event selection + registryCorr.fill(HIST("eventCounter"), 0.5); + + // Apply standard event selection if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) return; - // loop over reconstructed tracks + // Event counter: after event selection + registryCorr.fill(HIST("eventCounter"), 1.5); + + // Reject events near the ITS Read-Out Frame border + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) + return; + registryCorr.fill(HIST("eventCounter"), 2.5); + + // Reject events at the Time Frame border + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) + return; + registryCorr.fill(HIST("eventCounter"), 3.5); + + // Require at least one ITS-TPC matched track + if (requireVtxITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) + return; + registryCorr.fill(HIST("eventCounter"), 4.5); + + // Reject events with same-bunch pileup + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + registryCorr.fill(HIST("eventCounter"), 5.5); + + // Require consistent FT0 vs PV z-vertex + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + registryCorr.fill(HIST("eventCounter"), 6.5); + + // Require TOF match for at least one vertex track + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) + return; + registryCorr.fill(HIST("eventCounter"), 7.5); + + // Multiplicity percentile + const float multiplicity = collision.centFT0M(); + + // 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; + + // Particle counters + std::vector nAntiprotonFullEvent(nBins, 0); + std::vector nAntideuteronFullEvent(nBins, 0); + int nTotProtonFullEvent(0); + int nTotDeuteronFullEvent(0); + int nTotAntiprotonFullEvent(0); + int nTotAntideuteronFullEvent(0); + + // Loop over reconstructed tracks + for (auto const& track : tracks) { + + // Apply track selection + if (!passedTrackSelection(track)) + continue; + + // Apply DCA selections + if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > 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 (applyItsPid && track.pt() < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; + } + if (applyItsPid && track.pt() < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; + } + + // Kinematic range selection + if (isProton(track) && passedItsPidProt) { + if (track.pt() < ptOverAbins[0] || track.pt() >= ptOverAbins[nBins]) { + continue; + } + } else if (isDeuteron(track) && passedItsPidDeut) { + double ptPerNucleon = 0.5 * track.pt(); + if (ptPerNucleon < ptOverAbins[0] || ptPerNucleon >= ptOverAbins[nBins]) { + continue; + } + } else { + continue; + } + + // (Anti)protons + if (isProton(track) && passedItsPidProt) { + if (track.sign() > 0) { + nTotProtonFullEvent++; + } else if (track.sign() < 0) { + nTotAntiprotonFullEvent++; + int ibin = findBin(ptOverAbins, track.pt()); + nAntiprotonFullEvent[ibin]++; + } + } + + // (Anti)deuterons + if (isDeuteron(track) && passedItsPidDeut) { + const double ptPerNucleon = 0.5 * track.pt(); + + if (track.sign() > 0) { + nTotDeuteronFullEvent++; + } else if (track.sign() < 0) { + nTotAntideuteronFullEvent++; + int ibin = findBin(ptOverAbins, ptPerNucleon); + nAntideuteronFullEvent[ibin]++; + } + } + } + + // Fill correlation histograms + int netProtonFullEvent = nTotProtonFullEvent - nTotAntiprotonFullEvent; + int netDeuteronFullEvent = nTotDeuteronFullEvent - nTotAntideuteronFullEvent; + registryCorr.fill(HIST("rho_fullEvent"), nTotAntideuteronFullEvent, nTotAntiprotonFullEvent, multiplicity); + registryCorr.fill(HIST("rho_netP_netD_fullEvent"), 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"), nAntideuteronFullEvent[i], ptAcenteri); + registryCorr.fill(HIST("q1p_fullEvent"), nAntiprotonFullEvent[i], ptAcenteri); + for (int j = 0; j < nBins; j++) { + double ptAcenterj = 0.5 * (ptOverAbins[j] + ptOverAbins[j + 1]); + registryCorr.fill(HIST("q1d_square_fullEvent"), ptAcenteri, ptAcenterj, nAntideuteronFullEvent[i] * nAntideuteronFullEvent[j]); + registryCorr.fill(HIST("q1p_square_fullEvent"), ptAcenteri, ptAcenterj, nAntiprotonFullEvent[i] * nAntiprotonFullEvent[j]); + registryCorr.fill(HIST("q1d_q1p_fullEvent"), ptAcenteri, ptAcenterj, nAntideuteronFullEvent[i] * nAntiprotonFullEvent[j]); + } + } + + // Loop over reconstructed tracks (refactoring: this part can be incorporated above) int id(-1); std::vector fjParticles; for (auto const& track : tracks) { @@ -1339,232 +2254,254 @@ struct AntinucleiInJets { fjParticles.emplace_back(fourMomentum); } - // reject empty events - if (fjParticles.size() < 1) + // Reject empty events + if (fjParticles.empty()) return; + registryCorr.fill(HIST("eventCounter"), 8.5); - // cluster particles using the anti-kt algorithm + // Cluster particles using the anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); - fastjet::AreaDefinition areaDef(fastjet::active_area, fastjet::GhostedAreaSpec(1.0)); // active_area_explicit_ghosts + 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()); auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // loop over reconstructed jets + // Loop over reconstructed jets + bool isAtLeastOneJetSelected = false; for (const auto& jet : jets) { - // jet must be fully contained in the acceptance + // Jet must be fully contained in the acceptance if ((std::fabs(jet.eta()) + rJet) > (maxEta - deltaEtaEdge)) continue; - // jet pt must be larger than threshold + // Jet pt must be larger than threshold auto jetForSub = jet; fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - if (getCorrectedPt(jetMinusBkg.pt(), responseMatrix) < minJetPt) + if (jetMinusBkg.pt() < minJetPt) + continue; + + // Apply area cut if required + double normalizedJetArea = jet.area() / (PI * rJet * rJet); + if (applyAreaCut && normalizedJetArea > maxNormalizedJetArea) continue; + isAtLeastOneJetSelected = true; + + // Perpendicular cones + double coneRadius = std::sqrt(jet.area() / PI); + TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); + TVector3 ueAxis1(0, 0, 0); + TVector3 ueAxis2(0, 0, 0); + getPerpendicularAxis(jetAxis, ueAxis1, +1); + getPerpendicularAxis(jetAxis, ueAxis2, -1); - // get jet constituents + // Get jet constituents std::vector jetConstituents = jet.constituents(); - o2::aod::ITSResponse itsResponse; - // loop over jet constituents + // Particle counters + std::vector nAntiprotonJet(nBins, 0); + std::vector nAntideuteronJet(nBins, 0); + int nTotProtonJet(0); + int nTotDeuteronJet(0); + int nTotAntiprotonJet(0); + int nTotAntideuteronJet(0); + + // Loop over jet constituents for (const auto& particle : jetConstituents) { - for (int i = 0; i < nSystematics; i++) { - // get corresponding track and apply track selection criteria - auto const& track = tracks.iteratorAt(particle.user_index()); - // 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(); + // Get corresponding track and apply track selection criteria + auto const& track = tracks.iteratorAt(particle.user_index()); + if (!passedTrackSelection(track)) + continue; - if (requirePvContributor && !(track.isPVContributor())) - continue; - if (!track.hasITS()) - continue; - if (track.itsNCls() < itsNclustersSyst[i]) - continue; - if (!track.hasTPC()) - continue; - if (track.tpcNClsCrossedRows() < tpcNcrossedRowsSyst[i]) - continue; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - continue; - if (track.tpcChi2NCl() > maxChiSquareTpc) - continue; - if (track.itsChi2NCl() > maxChiSquareIts) - continue; - if (track.eta() < minEta || track.eta() > maxEta) - continue; - if (track.pt() < minPt) - continue; - if (std::fabs(dcaxy) > dcaxySyst[i]) - continue; - if (std::fabs(dcaz) > dcazSyst[i]) - continue; + // Apply DCA selections + if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) + continue; - bool passedItsPidProt(false), passedItsPidDeut(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; - } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + // 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 (applyItsPid && track.pt() < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; + } + if (applyItsPid && track.pt() < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; + } + + // Kinematic range selection + if (isProton(track) && passedItsPidProt) { + if (track.pt() < ptOverAbins[0] || track.pt() >= ptOverAbins[nBins]) { + continue; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; + } else if (isDeuteron(track) && passedItsPidDeut) { + double ptPerNucleon = 0.5 * track.pt(); + if (ptPerNucleon < ptOverAbins[0] || ptPerNucleon >= ptOverAbins[nBins]) { + continue; } - if (pt > ptMaxItsPidProt) - passedItsPidProt = true; - if (pt > ptMaxItsPidDeut) - passedItsPidDeut = true; - - // antimatter - if (track.sign() < 0) { - if (passedItsPidProt) { - registryData.fill(HIST("antiproton_tpc_syst"), pt, nsigmaTPCPr, i); - if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc && track.hasTOF()) - registryData.fill(HIST("antiproton_tof_syst"), pt, nsigmaTOFPr, i); - } - if (passedItsPidDeut) { - registryData.fill(HIST("antideuteron_tpc_syst"), pt, nsigmaTPCDe, i); - if (nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc && track.hasTOF()) - registryData.fill(HIST("antideuteron_tof_syst"), pt, nsigmaTOFDe, i); - } + } else { + continue; + } + + // (Anti)protons + if (isProton(track) && passedItsPidProt) { + if (track.sign() > 0) { + nTotProtonJet++; + } else if (track.sign() < 0) { + nTotAntiprotonJet++; + int ibin = findBin(ptOverAbins, track.pt()); + nAntiprotonJet[ibin]++; } } - } - } - } - PROCESS_SWITCH(AntinucleiInJets, processSystematicsData, "Process Systematics", false); - void processSystematicsEfficiency(SimCollisions const& collisions, MCTracks const& mcTracks, aod::McParticles const& mcParticles) - { - const int nSystematics = 10; - int itsNclustersSyst[nSystematics] = {5, 6, 5, 4, 5, 3, 5, 6, 3, 4}; - float tpcNcrossedRowsSyst[nSystematics] = {100, 85, 80, 110, 95, 90, 105, 95, 100, 105}; - float dcaxySyst[nSystematics] = {0.05, 0.07, 0.10, 0.03, 0.06, 0.15, 0.08, 0.04, 0.09, 0.10}; - float dcazSyst[nSystematics] = {0.1, 0.15, 0.3, 0.075, 0.12, 0.18, 0.2, 0.1, 0.15, 0.2}; + // (Anti)deuterons + if (isDeuteron(track) && passedItsPidDeut) { + const double ptPerNucleon = 0.5 * track.pt(); - for (const auto& collision : collisions) { + if (track.sign() > 0) { + nTotDeuteronJet++; + } else if (track.sign() < 0) { + nTotAntideuteronJet++; + int ibin = findBin(ptOverAbins, ptPerNucleon); + nAntideuteronJet[ibin]++; + } + } + } // end of loop over constituents + + // Fill correlation histograms + int netProtonJet = nTotProtonJet - nTotAntiprotonJet; + int netDeuteronJet = nTotDeuteronJet - nTotAntideuteronJet; + registryCorr.fill(HIST("rho_jet"), nTotAntideuteronJet, nTotAntiprotonJet, multiplicity); + registryCorr.fill(HIST("rho_netP_netD_jet"), netDeuteronJet, netProtonJet); + + // Fill efficiency histograms + for (int i = 0; i < nBins; i++) { + double ptAcenteri = 0.5 * (ptOverAbins[i] + ptOverAbins[i + 1]); + + registryCorr.fill(HIST("q1d_jet"), nAntideuteronJet[i], ptAcenteri); + registryCorr.fill(HIST("q1p_jet"), nAntiprotonJet[i], ptAcenteri); + for (int j = 0; j < nBins; j++) { + double ptAcenterj = 0.5 * (ptOverAbins[j] + ptOverAbins[j + 1]); + registryCorr.fill(HIST("q1d_square_jet"), ptAcenteri, ptAcenterj, nAntideuteronJet[i] * nAntideuteronJet[j]); + registryCorr.fill(HIST("q1p_square_jet"), ptAcenteri, ptAcenterj, nAntiprotonJet[i] * nAntiprotonJet[j]); + registryCorr.fill(HIST("q1d_q1p_jet"), ptAcenteri, ptAcenterj, nAntideuteronJet[i] * nAntiprotonJet[j]); + } + } - if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) - continue; + // Particle counters + std::vector nAntiprotonUE(nBins, 0); + std::vector nAntideuteronUE(nBins, 0); + int nTotProtonUE(0); + int nTotDeuteronUE(0); + int nTotAntiprotonUE(0); + int nTotAntideuteronUE(0); - // generated - for (const auto& particle : mcParticles) { + // Loop over tracks in the underlying event + for (auto const& track : tracks) { - if (!particle.isPhysicalPrimary()) + // Get corresponding track and apply track selection criteria + if (!passedTrackSelection(track)) continue; - if (particle.eta() < minEta || particle.eta() > maxEta) + // Apply DCA selections + if (std::fabs(track.dcaXY()) > maxDcaxy || std::fabs(track.dcaZ()) > maxDcaz) continue; - switch (particle.pdgCode()) { - case kProtonBar: - registryMC.fill(HIST("antiproton_incl_gen_syst"), particle.pt()); - break; - case -o2::constants::physics::Pdg::kDeuteron: - registryMC.fill(HIST("antideuteron_incl_gen_syst"), particle.pt()); - break; - } - } - - // ITS pid using cluster size - o2::aod::ITSResponse itsResponse; + // Calculate the angular distance between the track and underlying event axes in eta-phi space + double deltaEtaUe1 = track.eta() - ueAxis1.Eta(); + double deltaPhiUe1 = getDeltaPhi(track.phi(), ueAxis1.Phi()); + double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + double deltaEtaUe2 = track.eta() - ueAxis2.Eta(); + double deltaPhiUe2 = getDeltaPhi(track.phi(), ueAxis2.Phi()); + double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - // Reconstructed Tracks - for (auto const& track : mcTracks) { + // Determine the maximum allowed distance from UE axes for particle selection + double maxConeRadius = coneRadius; + if (applyAreaCut) { + maxConeRadius = std::sqrt(maxNormalizedJetArea) * rJet; + } - // Get MC Particle - if (!track.has_mcParticle()) + // Reject tracks that lie outside the maxConeRadius from both UE axes + if (deltaRUe1 > maxConeRadius && deltaRUe2 > maxConeRadius) continue; - const auto particle = track.mcParticle(); - // Variables - double nsigmaTPCPr = track.tpcNSigmaPr(); - double nsigmaTOFPr = track.tofNSigmaPr(); - double nsigmaTPCDe = track.tpcNSigmaDe(); - double nsigmaTOFDe = track.tofNSigmaDe(); - double dcaxy = track.dcaXY(); - double dcaz = track.dcaZ(); + // 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)); - for (int i = 0; i < nSystematics; i++) { + if (applyItsPid && track.pt() < ptMaxItsPidProt && (nSigmaITSprot < nSigmaItsMin || nSigmaITSprot > nSigmaItsMax)) { + passedItsPidProt = false; + } + if (applyItsPid && track.pt() < ptMaxItsPidDeut && (nSigmaITSdeut < nSigmaItsMin || nSigmaITSdeut > nSigmaItsMax)) { + passedItsPidDeut = false; + } - // Track Selection - if (requirePvContributor && !(track.isPVContributor())) + // Kinematic range selection + if (isProton(track) && passedItsPidProt) { + if (track.pt() < ptOverAbins[0] || track.pt() >= ptOverAbins[nBins]) { continue; - if (!track.hasITS()) - continue; - if (track.itsNCls() < itsNclustersSyst[i]) - continue; - if (!track.hasTPC()) - continue; - if (track.tpcNClsCrossedRows() < tpcNcrossedRowsSyst[i]) - continue; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - continue; - if (track.tpcChi2NCl() > maxChiSquareTpc) - continue; - if (track.itsChi2NCl() > maxChiSquareIts) - continue; - if (track.eta() < minEta || track.eta() > maxEta) - continue; - if (track.pt() < minPt) - continue; - if (std::fabs(dcaxy) > dcaxySyst[i]) - continue; - if (std::fabs(dcaz) > dcazSyst[i]) - continue; - - // particle identification using the ITS cluster size - bool passedItsPidProt(false), passedItsPidDeut(false); - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidProt = true; } - if (itsResponse.nSigmaITS(track) > nSigmaItsMin && itsResponse.nSigmaITS(track) < nSigmaItsMax) { - passedItsPidDeut = true; + } else if (isDeuteron(track) && passedItsPidDeut) { + double ptPerNucleon = 0.5 * track.pt(); + if (ptPerNucleon < ptOverAbins[0] || ptPerNucleon >= ptOverAbins[nBins]) { + continue; } - if (!applyItsPid) { - passedItsPidProt = true; - passedItsPidDeut = true; + } else { + continue; + } + + // (Anti)protons + if (isProton(track) && passedItsPidProt) { + if (track.sign() > 0) { + nTotProtonUE++; + } else if (track.sign() < 0) { + nTotAntiprotonUE++; + int ibin = findBin(ptOverAbins, track.pt()); + nAntiprotonUE[ibin]++; } - if (track.pt() > ptMaxItsPidProt) - passedItsPidProt = true; - if (track.pt() > ptMaxItsPidDeut) - passedItsPidDeut = true; - if (!particle.isPhysicalPrimary()) - continue; + } - if (particle.pdgCode() == kProtonBar) - registryMC.fill(HIST("antiproton_incl_prim_syst"), track.pt(), i); + // (Anti)deuterons + if (isDeuteron(track) && passedItsPidDeut) { + const double ptPerNucleon = 0.5 * track.pt(); - // antiprotons - if (particle.pdgCode() == kProtonBar && passedItsPidProt) { - if (nsigmaTPCPr > minNsigmaTpc && nsigmaTPCPr < maxNsigmaTpc) { - registryMC.fill(HIST("antiproton_incl_rec_tpc_syst"), track.pt(), i); - if (track.hasTOF() && nsigmaTOFPr > minNsigmaTof && nsigmaTOFPr < maxNsigmaTof) - registryMC.fill(HIST("antiproton_incl_rec_tof_syst"), track.pt(), i); - } + if (track.sign() > 0) { + nTotDeuteronUE++; + } else if (track.sign() < 0) { + nTotAntideuteronUE++; + int ibin = findBin(ptOverAbins, ptPerNucleon); + nAntideuteronUE[ibin]++; } + } + } - // antideuterons - if (particle.pdgCode() == -o2::constants::physics::Pdg::kDeuteron && passedItsPidDeut) { - if (nsigmaTPCDe > minNsigmaTpc && nsigmaTPCDe < maxNsigmaTpc) { - registryMC.fill(HIST("antideuteron_incl_rec_tpc_syst"), track.pt(), i); - if (track.hasTOF() && nsigmaTOFDe > minNsigmaTof && nsigmaTOFDe < maxNsigmaTof) - registryMC.fill(HIST("antideuteron_incl_rec_tof_syst"), track.pt(), i); - } - } + // Fill correlation histograms + int netProtonUE = nTotProtonUE - nTotAntiprotonUE; + int netDeuteronUE = nTotDeuteronUE - nTotAntideuteronUE; + registryCorr.fill(HIST("rho_ue"), nTotAntideuteronUE, nTotAntiprotonUE, multiplicity); + registryCorr.fill(HIST("rho_netP_netD_ue"), netDeuteronUE, netProtonUE); + + // Fill efficiency histograms + for (int i = 0; i < nBins; i++) { + double ptAcenteri = 0.5 * (ptOverAbins[i] + ptOverAbins[i + 1]); + + registryCorr.fill(HIST("q1d_ue"), nAntideuteronUE[i], ptAcenteri); + registryCorr.fill(HIST("q1p_ue"), nAntiprotonUE[i], ptAcenteri); + for (int j = 0; j < nBins; j++) { + double ptAcenterj = 0.5 * (ptOverAbins[j] + ptOverAbins[j + 1]); + registryCorr.fill(HIST("q1d_square_ue"), ptAcenteri, ptAcenterj, nAntideuteronUE[i] * nAntideuteronUE[j]); + registryCorr.fill(HIST("q1p_square_ue"), ptAcenteri, ptAcenterj, nAntiprotonUE[i] * nAntiprotonUE[j]); + registryCorr.fill(HIST("q1d_q1p_ue"), ptAcenteri, ptAcenterj, nAntideuteronUE[i] * nAntiprotonUE[j]); } } } + // Event counter: events with at least one jet selected + if (isAtLeastOneJetSelected) { + registryCorr.fill(HIST("eventCounter"), 9.5); + } } - PROCESS_SWITCH(AntinucleiInJets, processSystematicsEfficiency, "process efficiency for systematics", false); + PROCESS_SWITCH(AntinucleiInJets, processCorr, "Process Correlation analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Nuspex/spectraCharged.cxx b/PWGLF/Tasks/Nuspex/chargedParticles.cxx similarity index 70% rename from PWGLF/Tasks/Nuspex/spectraCharged.cxx rename to PWGLF/Tasks/Nuspex/chargedParticles.cxx index 94e3b30dc4a..42bbb437a89 100644 --- a/PWGLF/Tasks/Nuspex/spectraCharged.cxx +++ b/PWGLF/Tasks/Nuspex/chargedParticles.cxx @@ -9,44 +9,71 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. -// task for charged particle pt spectra vs multiplicity analysis with 2d unfolding for run3+ -// mimics https://github.com/alisw/AliPhysics/blob/master/PWGLF/SPECTRA/ChargedHadrons/MultDepSpec/AliMultDepSpecAnalysisTask.cxx - -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/Track.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/EventSelection.h" +/// \file chargedParticles.cxx +/// \brief Task for analysis of charged particle pt spectra vs multiplicity with 2d unfolding. +/// \author Mario Krüger + +#include "Common/Core/TrackSelection.h" +#include "Common/Core/TrackSelectionDefaults.h" #include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "TDatabasePDG.h" + +#include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; +using aod::track::TrackSelectionFlags; //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- // Task declaration //-------------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------------- -struct chargedSpectra { +struct ChargedParticles { HistogramRegistry histos; Service pdg; - // task settings that can be steered via hyperloop Configurable isRun3{"isRun3", true, "is Run3 dataset"}; Configurable maxMultMeas{"maxMultMeas", 100, "max measured multiplicity"}; Configurable maxMultTrue{"maxMultTrue", 100, "max true multiplicity"}; Configurable etaCut{"etaCut", 0.8f, "eta cut"}; Configurable ptMinCut{"ptMinCut", 0.15f, "pt min cut"}; Configurable ptMaxCut{"ptMaxCut", 10.f, "pt max cut"}; - Configurable normINELGT0{"normINELGT0", false, "normalize INEL>0 according to MC"}; + enum : uint32_t { + kSystNominal = 100, + kSystDownChi2PerClusterITS, + kSystUpChi2PerClusterITS, + kSystDownChi2PerClusterTPC, + kSystUpChi2PerClusterTPC, + kSystDownTPCCrossedRowsOverNCls, + kSystUpTPCCrossedRowsOverNCls, + kSystDownDCAxy = 111, + kSystUpDCAxy, + kSystDownDCAz, + kSystUpDCAz, + kSystITSHits, + kSystDownTPCCrossedRows, + kSystUpTPCCrossedRows + }; + Configurable systMode{"systMode", kSystNominal, "variation for systematic uncertainties"}; + uint16_t trackSelMask{TrackSelectionFlags::kGlobalTrackWoPtEta}; // track selection bitmask (without cut that is being varied) + uint16_t cutVarFlag{0}; + TrackSelection trackSel; + TrackSelection::TrackCuts trackSelFlag; + // helper struct to store transient properties - struct varContainer { + struct VarContainer { uint32_t multMeas{0u}; uint32_t multTrue{0u}; bool isAcceptedEvent{false}; @@ -54,7 +81,8 @@ struct chargedSpectra { bool isINELGT0EventMC{false}; bool isChargedPrimary{false}; }; - varContainer vars; + VarContainer vars; + static constexpr float kMaxVtxZ = 10.f; void init(InitContext const&); @@ -70,43 +98,29 @@ struct chargedSpectra { template void initEventMC(const C& collision, const P& particles); - template - void processMeas(const C& collision, const T& tracks); + template + void processMeas(const T& tracks); - template - void processTrue(const C& collision, const P& particles); + template + void processTrue(const P& particles); using CollisionTableData = soa::Join; - using TrackTableData = soa::Join; + using TrackTableData = soa::Join; void processData(CollisionTableData::iterator const& collision, TrackTableData const& tracks); - PROCESS_SWITCH(chargedSpectra, processData, "process data", false); + PROCESS_SWITCH(ChargedParticles, processData, "process data", false); using CollisionTableMCTrue = aod::McCollisions; using CollisionTableMC = soa::SmallGroups>; - using TrackTableMC = soa::Join; + using TrackTableMC = soa::Join; using ParticleTableMC = aod::McParticles; Preslice perCollision = aod::track::collisionId; void processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles); - PROCESS_SWITCH(chargedSpectra, processMC, "process mc", true); - - // TODO: - Milestone - express most of the selections on events and tracks in a declarative way to improve performance - /* - add - Filter xy; - soa::Filtered - - For the collision and track tables (data and MC): - - collision z pos < 10cm - - trigger condition + event selection - - track selection + is in kine range - - For the MC tables we need to keep everything that EITHER fulfils the conditions in data OR in MC to get correct efficiencies and contamination! - */ + PROCESS_SWITCH(ChargedParticles, processMC, "process mc", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc)}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } //-------------------------------------------------------------------------------------------------- @@ -120,7 +134,7 @@ WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) * Initialise the task and add histograms. */ //************************************************************************************************** -void chargedSpectra::init(InitContext const&) +void ChargedParticles::init(InitContext const&) { std::vector ptBinEdges = {0.15, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, @@ -162,6 +176,62 @@ void chargedSpectra::init(InitContext const&) histos.add("multPtSpec_trk_meas_evtcont", "", kTH2D, {multMeasAxis, ptMeasAxis}); // tracks from events that are measured, but do not belong to the desired class of events histos.add("multPtSpec_trk_inter", "", kTH2D, {multTrueAxis, ptMeasAxis}); } + + trackSel = getGlobalTrackSelection(); + if (systMode == kSystDownChi2PerClusterITS) { + trackSel.SetMaxChi2PerClusterITS(25.); + cutVarFlag = TrackSelectionFlags::kITSChi2NDF; + trackSelFlag = TrackSelection::TrackCuts::kITSChi2NDF; + } else if (systMode == kSystUpChi2PerClusterITS) { + trackSel.SetMaxChi2PerClusterITS(49.); + cutVarFlag = TrackSelectionFlags::kITSChi2NDF; + trackSelFlag = TrackSelection::TrackCuts::kITSChi2NDF; + } else if (systMode == kSystDownChi2PerClusterTPC) { + trackSel.SetMaxChi2PerClusterTPC(3.0); + cutVarFlag = TrackSelectionFlags::kTPCChi2NDF; + trackSelFlag = TrackSelection::TrackCuts::kTPCChi2NDF; + } else if (systMode == kSystUpChi2PerClusterTPC) { + trackSel.SetMaxChi2PerClusterTPC(5.0); + cutVarFlag = TrackSelectionFlags::kTPCChi2NDF; + trackSelFlag = TrackSelection::TrackCuts::kTPCChi2NDF; + } else if (systMode == kSystDownTPCCrossedRowsOverNCls) { + trackSel.SetMinNCrossedRowsOverFindableClustersTPC(0.7); + cutVarFlag = TrackSelectionFlags::kTPCCrossedRowsOverNCls; + trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRowsOverNCls; + } else if (systMode == kSystUpTPCCrossedRowsOverNCls) { + trackSel.SetMinNCrossedRowsOverFindableClustersTPC(0.9); + cutVarFlag = TrackSelectionFlags::kTPCCrossedRowsOverNCls; + trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRowsOverNCls; + } else if (systMode == kSystDownDCAxy) { + trackSel.SetMaxDcaXYPtDep([](float pt) { return 4. / 7. * (0.0105f + 0.0350f / std::pow(pt, 1.1f)); }); + cutVarFlag = TrackSelectionFlags::kDCAxy; + trackSelFlag = TrackSelection::TrackCuts::kDCAxy; + } else if (systMode == kSystUpDCAxy) { + trackSel.SetMaxDcaXYPtDep([](float pt) { return 10. / 7. * (0.0105f + 0.0350f / std::pow(pt, 1.1f)); }); + cutVarFlag = TrackSelectionFlags::kDCAxy; + trackSelFlag = TrackSelection::TrackCuts::kDCAxy; + } else if (systMode == kSystDownDCAz) { + trackSel.SetMaxDcaZ(1.0); + cutVarFlag = TrackSelectionFlags::kDCAz; + trackSelFlag = TrackSelection::TrackCuts::kDCAz; + } else if (systMode == kSystUpDCAz) { + trackSel.SetMaxDcaZ(5.0); + cutVarFlag = TrackSelectionFlags::kDCAz; + trackSelFlag = TrackSelection::TrackCuts::kDCAz; + } else if (systMode == kSystITSHits) { + trackSel.ResetITSRequirements(); + cutVarFlag = TrackSelectionFlags::kITSHits; + trackSelFlag = TrackSelection::TrackCuts::kITSHits; + } else if (systMode == kSystDownTPCCrossedRows) { + trackSel.SetMinNCrossedRowsTPC(60); + cutVarFlag = TrackSelectionFlags::kTPCCrossedRows; + trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRows; + } else if (systMode == kSystUpTPCCrossedRows) { + trackSel.SetMinNCrossedRowsTPC(80); + cutVarFlag = TrackSelectionFlags::kTPCCrossedRows; + trackSelFlag = TrackSelection::TrackCuts::kTPCCrossedRows; + } + trackSelMask &= (~cutVarFlag); } //************************************************************************************************** @@ -169,10 +239,10 @@ void chargedSpectra::init(InitContext const&) * Entrypoint to processes data. */ //************************************************************************************************** -void chargedSpectra::processData(CollisionTableData::iterator const& collision, TrackTableData const& tracks) +void ChargedParticles::processData(CollisionTableData::iterator const& collision, TrackTableData const& tracks) { initEvent(collision, tracks); - processMeas(collision, tracks); + processMeas(tracks); } //************************************************************************************************** @@ -180,7 +250,7 @@ void chargedSpectra::processData(CollisionTableData::iterator const& collision, * Entrypoint to processes mc. */ //************************************************************************************************** -void chargedSpectra::processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles) +void ChargedParticles::processMC(CollisionTableMCTrue::iterator const& mcCollision, CollisionTableMC const& collisions, TrackTableMC const& tracks, ParticleTableMC const& particles) { histos.fill(HIST("collision_ambiguity"), collisions.size()); @@ -198,14 +268,14 @@ void chargedSpectra::processMC(CollisionTableMCTrue::iterator const& mcCollision if (collisions.size() == 0) { vars.isAcceptedEvent = false; } else { - for (auto& collision : collisions) { + for (const auto& collision : collisions) { auto curTracks = tracks.sliceBy(perCollision, collision.globalIndex()); initEvent(collision, curTracks); - processMeas(collision, curTracks); + processMeas(curTracks); break; // for now look only at first collision... } } - processTrue(mcCollision, particles); + processTrue(particles); } //************************************************************************************************** @@ -214,7 +284,7 @@ void chargedSpectra::processMC(CollisionTableMCTrue::iterator const& mcCollision */ //************************************************************************************************** template -bool chargedSpectra::initParticle(const P& particle) +bool ChargedParticles::initParticle(const P& particle) { vars.isChargedPrimary = false; auto pdgParticle = pdg->GetParticle(particle.pdgCode()); @@ -241,7 +311,7 @@ bool chargedSpectra::initParticle(const P& particle) */ //************************************************************************************************** template -bool chargedSpectra::initTrack(const T& track) +bool ChargedParticles::initTrack(const T& track) { if (std::abs(track.eta()) >= etaCut) { return false; @@ -249,7 +319,11 @@ bool chargedSpectra::initTrack(const T& track) if (track.pt() <= ptMinCut || track.pt() >= ptMaxCut) { return false; } - if (!track.isGlobalTrackWoPtEta()) { + if (!TrackSelectionFlags::checkFlag(track.trackCutFlag(), trackSelMask)) { + return false; + } + // for systematic variation of standard selections, check if the varied cut is passed + if (cutVarFlag && !trackSel.IsSelected(track, trackSelFlag)) { return false; } return true; @@ -261,17 +335,17 @@ bool chargedSpectra::initTrack(const T& track) */ //************************************************************************************************** template -void chargedSpectra::initEvent(const C& collision, const T& tracks) +void ChargedParticles::initEvent(const C& collision, const T& tracks) { vars.multMeas = 0; - for (auto& track : tracks) { + for (const auto& track : tracks) { if (initTrack(track)) { ++vars.multMeas; } } vars.isAcceptedEvent = false; - if (std::abs(collision.posZ()) < 10.f) { + if (std::abs(collision.posZ()) < kMaxVtxZ) { if (isRun3 ? collision.sel8() : collision.sel7()) { if ((isRun3 || doprocessMC) ? true : collision.alias_bit(kINT7)) { vars.isAcceptedEvent = true; @@ -286,18 +360,18 @@ void chargedSpectra::initEvent(const C& collision, const T& tracks) */ //************************************************************************************************** template -void chargedSpectra::initEventMC(const C& collision, const P& particles) +void ChargedParticles::initEventMC(const C& collision, const P& particles) { vars.isINELGT0EventMC = false; // will be set to true in case a charged particle within eta +-1 is found vars.multTrue = 0; - for (auto& particle : particles) { + for (const auto& particle : particles) { if (!initParticle(particle) || !vars.isChargedPrimary) { continue; } ++vars.multTrue; } bool isGoodEventClass = (normINELGT0) ? vars.isINELGT0EventMC : (vars.multTrue > 0); - vars.isAcceptedEventMC = isGoodEventClass && (std::abs(collision.posZ()) < 10.f); + vars.isAcceptedEventMC = isGoodEventClass && (std::abs(collision.posZ()) < kMaxVtxZ); } //************************************************************************************************** @@ -305,8 +379,8 @@ void chargedSpectra::initEventMC(const C& collision, const P& particles) * Function to processes MC truth info. Assumes initEvent and initEventMC have been called previously. */ //************************************************************************************************** -template -void chargedSpectra::processTrue(const C& /*collision*/, const P& particles) +template +void ChargedParticles::processTrue(const P& particles) { if (!vars.isAcceptedEventMC) { return; @@ -314,7 +388,7 @@ void chargedSpectra::processTrue(const C& /*collision*/, const P& particles) histos.fill(HIST("multDist_evt_gen"), vars.multTrue); - for (auto& particle : particles) { + for (const auto& particle : particles) { if (initParticle(particle) && vars.isChargedPrimary) { histos.fill(HIST("multPtSpec_prim_gen"), vars.multTrue, particle.pt()); if (!vars.isAcceptedEvent) { @@ -329,8 +403,8 @@ void chargedSpectra::processTrue(const C& /*collision*/, const P& particles) * Function to process reconstructed data and MC. Assumes initEvent (and initEventMC in case of MC) have been called previously. */ //************************************************************************************************** -template -void chargedSpectra::processMeas(const C& /*collision*/, const T& tracks) +template +void ChargedParticles::processMeas(const T& tracks) { if (!vars.isAcceptedEvent) { return; @@ -345,8 +419,7 @@ void chargedSpectra::processMeas(const C& /*collision*/, const T& tracks) } std::vector foundParticles; - for (auto& track : tracks) { - + for (const auto& track : tracks) { if (!initTrack(track)) { continue; } @@ -390,7 +463,7 @@ void chargedSpectra::processMeas(const C& /*collision*/, const T& tracks) } std::unordered_set uniqueIndices(foundParticles.begin(), foundParticles.end()); - for (auto mcParticleID : uniqueIndices) { + for (const auto& mcParticleID : uniqueIndices) { histos.fill(HIST("track_ambiguity"), std::count(foundParticles.begin(), foundParticles.end(), mcParticleID)); } } diff --git a/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx new file mode 100644 index 00000000000..d688f0c8e72 --- /dev/null +++ b/PWGLF/Tasks/Nuspex/dedxPidAnalysis.cxx @@ -0,0 +1,852 @@ +// 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 Torres (paola.vargas.torres@cern.ch) +/// \since January 8, 2025 +/// \file dedxPidAnalysis.cxx +/// \brief Analysis to do PID + +#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/PIDResponse.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 "TF1.h" + +using namespace o2; +using namespace o2::framework; +using namespace constants::physics; + +using PIDTracks = soa::Join< + aod::Tracks, aod::TracksExtra, aod::TrackSelectionExtension, aod::TracksDCA, aod::TrackSelection, + aod::pidTOFFullPi, aod::pidTOFFullPr, aod::pidTOFFullEl, aod::pidTOFbeta>; + +using SelectedCollisions = soa::Join; + +struct DedxPidAnalysis { + + // dE/dx for all charged particles + HistogramRegistry registryDeDx{ + "registryDeDx", + {}, + OutputObjHandlingPolicy::AnalysisObject, + true, + true}; + // Constant values + static constexpr int kEtaIntervals = 8; + static constexpr int kParticlesType = 4; + float tpcCut = 0.6; + float pionMin = 0.35; + float pionMax = 0.45; + float elTofCut = 0.1; + float pionTofCut = 1.0; + float invMassCut = 0.01; + float invMassCutGamma = 0.0015; + float magField = 1; + float pTcut = 2.0; + + // Configurable Parameters + // Tracks cuts + Configurable minTPCnClsFound{"minTPCnClsFound", 70.0f, + "min number of found TPC clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 70.0f, "min number of found TPC crossed rows"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, + "max chi2 per cluster TPC"}; + Configurable maxChi2ITS{"maxChi2ITS", 36.0f, + "max chi2 per cluster ITS"}; + Configurable maxZDistanceToIP{"maxZDistanceToIP", 10.0f, + "max z distance to IP"}; + Configurable etaMin{"etaMin", -0.8f, "etaMin"}; + Configurable etaMax{"etaMax", +0.8f, "etaMax"}; + 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", 2.f, "maxDCAz"}; + // v0 cuts + 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 nclCut{"nclCut", 135.0f, + "ncl Cut"}; + Configurable calibrationMode{"calibrationMode", false, "calibration mode"}; + Configurable additionalCuts{"additionalCuts", true, "additional cuts"}; + // 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 kNclDedxMomentumNegBefore[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_8_Before"}; + static constexpr std::string_view kNclDedxMomentumPosBefore[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_8_Before"}; + static constexpr std::string_view kNclDedxMomentumNegAfter[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Neg_1_After", "Ncl_vs_dEdx_vs_Momentum_Neg_2_After", "Ncl_vs_dEdx_vs_Momentum_Neg_3_After", "Ncl_vs_dEdx_vs_Momentum_Neg_4_After", "Ncl_vs_dEdx_vs_Momentum_Neg_5_After", "Ncl_vs_dEdx_vs_Momentum_Neg_6_After", "Ncl_vs_dEdx_vs_Momentum_Neg_7_After", "Ncl_vs_dEdx_vs_Momentum_Neg_8_After"}; + static constexpr std::string_view kNclDedxMomentumPosAfter[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Pos_1_After", "Ncl_vs_dEdx_vs_Momentum_Pos_2_After", "Ncl_vs_dEdx_vs_Momentum_Pos_3_After", "Ncl_vs_dEdx_vs_Momentum_Pos_4_After", "Ncl_vs_dEdx_vs_Momentum_Pos_5_After", "Ncl_vs_dEdx_vs_Momentum_Pos_6_After", "Ncl_vs_dEdx_vs_Momentum_Pos_7_After", "Ncl_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}; + 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}, ""}; + + // phi cut fits + TF1* fphiCutHigh = nullptr; + TF1* fphiCutLow = nullptr; + + TrackSelection myTrackSelection() + { + TrackSelection selectedTracks; + selectedTracks.SetPtRange(0.1f, 1e10f); + selectedTracks.SetEtaRange(etaMin, etaMax); + selectedTracks.SetRequireITSRefit(true); + selectedTracks.SetRequireTPCRefit(true); + selectedTracks.SetMinNCrossedRowsTPC(minNCrossedRowsTPC); + selectedTracks.SetMinNCrossedRowsOverFindableClustersTPC(minNCrossedRowsOverFindableClustersTPC); + selectedTracks.SetMaxChi2PerClusterTPC(maxChi2TPC); + selectedTracks.SetRequireHitsInITSLayers(1, {0, 1}); + selectedTracks.SetMaxChi2PerClusterITS(maxChi2ITS); + selectedTracks.SetMaxDcaXYPtDep([](float pt) { return 0.0105f + 0.0350f / std::pow(pt, 1.1f); }); + selectedTracks.SetMaxDcaZ(maxDCAz); + selectedTracks.SetRequireGoldenChi2(true); + + return selectedTracks; + } + + TrackSelection mySelectionPrim; + + void init(InitContext const&) + { + AxisSpec dedxAxis{100, 0.0, 100.0, "dE/dx (a. u.)"}; + AxisSpec ptAxis = {binP, "pT (GeV/c)"}; + AxisSpec etaAxis{8, -0.8, 0.8, "#eta"}; + AxisSpec pAxis = {binP, "#it{p}/Z (GeV/c)"}; + fphiCutLow = new TF1("StandardPhiCutLow", "0.119297/x/x+pi/18.0-0.000379693", 0, 50); + fphiCutHigh = new TF1("StandardPhiCutHigh", "0.16685/x+pi/18.0+0.00981942", 0, 50); + if (calibrationMode) { + // MIP for pions + registryDeDx.add( + "hdEdx_vs_eta_Neg_Pi", "dE/dx", HistType::kTH2F, + {{etaAxis}, {dedxAxis}}); + registryDeDx.add( + "hdEdx_vs_eta_Pos_Pi", "dE/dx", HistType::kTH2F, + {{etaAxis}, {dedxAxis}}); + // MIP for electrons + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Neg_El", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Pos_El", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + // Pions from TOF + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Neg_TOF", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Pos_TOF", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + + } else { + // MIP for pions + registryDeDx.add( + "hdEdx_vs_eta_Neg_calibrated_Pi", "dE/dx", HistType::kTH2F, + {{etaAxis}, {dedxAxis}}); + + registryDeDx.add( + "hdEdx_vs_eta_Pos_calibrated_Pi", "dE/dx", HistType::kTH2F, + {{etaAxis}, {dedxAxis}}); + + // MIP for electrons + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Neg_calibrated_El", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Pos_calibrated_El", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + + // Pions from TOF + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Neg_calibrated_TOF", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + + registryDeDx.add( + "hdEdx_vs_eta_vs_p_Pos_calibrated_TOF", "dE/dx", HistType::kTH3F, + {{etaAxis}, {dedxAxis}, {pAxis}}); + + // pt vs p + registryDeDx.add( + "hp_vs_pt_all_Neg", "p_vs_pT", HistType::kTH2F, + {{ptAxis}, {pAxis}}); + registryDeDx.add( + "hp_vs_pt_all_Pos", "p_vs_pT", HistType::kTH2F, + {{ptAxis}, {pAxis}}); + + // De/Dx for ch and v0 particles + for (int i = 0; i < kParticlesType; ++i) { + registryDeDx.add(kDedxvsMomentumPos[i].data(), "dE/dx", HistType::kTH3F, + {{pAxis}, {dedxAxis}, {etaAxis}}); + registryDeDx.add(kDedxvsMomentumNeg[i].data(), "dE/dx", HistType::kTH3F, + {{pAxis}, {dedxAxis}, {etaAxis}}); + } + } + + registryDeDx.add( + "hdEdx_vs_phi", "dE/dx", HistType::kTH2F, + {{100, 0.0, 6.4, "#phi"}, {dedxAxis}}); + + // phi cut + registryDeDx.add( + "hpt_vs_phi_Ncl_After", "phi cut", HistType::kTH3F, + {{ptAxis}, {100, 0.0, 0.4, "#varphi^{'}"}, {100, 0, 160, "N_{cl}"}}); + + registryDeDx.add( + "hpt_vs_phi_Ncl_Before", "phi cut", HistType::kTH3F, + {{ptAxis}, {100, 0.0, 0.4, "#varphi^{'}"}, {100, 0, 160, "N_{cl}"}}); + + // Ncl vs de/dx + + for (int i = 0; i < kEtaIntervals; ++i) { + registryDeDx.add(kNclDedxMomentumPosBefore[i].data(), "Ncl vs dE/dx vs Momentum Positive before", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + registryDeDx.add(kNclDedxMomentumNegBefore[i].data(), "Ncl vs dE/dx vs Momentum Negative before", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + + registryDeDx.add(kNclDedxMomentumPosAfter[i].data(), "Ncl vs dE/dx vs Momentum Positive after", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + registryDeDx.add(kNclDedxMomentumNegAfter[i].data(), "Ncl vs dE/dx vs Momentum Negative after", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + } + + // beta plot + registryDeDx.add( + "hbeta_vs_p_Neg", "beta", HistType::kTH2F, + {{pAxis}, {100, 0.0, 1.1, "#beta"}}); + + registryDeDx.add( + "hbeta_vs_p_Pos", "beta", HistType::kTH2F, + {{pAxis}, {100, 0.0, 1.1, "#beta"}}); + + // Event Counter + registryDeDx.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{100, -20.0, +20.0, "z_{vtx} (cm)"}}); + + mySelectionPrim = myTrackSelection(); + } + + // 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() > tpcCut) { + if (!ptrack.hasTOF()) + return false; + if (std::abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > tpcCut) { + if (!ntrack.hasTOF()) + return false; + if (std::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() > tpcCut) { + if (!ptrack.hasTOF()) + return false; + if (std::abs(ptrack.tofNSigmaPr()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > tpcCut) { + if (!ntrack.hasTOF()) + return false; + if (std::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() > tpcCut) { + if (!ptrack.hasTOF()) + return false; + if (std::abs(ptrack.tofNSigmaPi()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > tpcCut) { + if (!ntrack.hasTOF()) + return false; + if (std::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() > tpcCut) { + if (!ptrack.hasTOF()) + return false; + if (std::abs(ptrack.tofNSigmaEl()) > nsigmaTOFmax) + return false; + } + + if (ntrack.tpcInnerParam() > tpcCut) { + if (!ntrack.hasTOF()) + return false; + if (std::abs(ntrack.tofNSigmaEl()) > nsigmaTOFmax) + return false; + } + + // Invariant-Mass Selection + if (v0.mGamma() < minMassGamma || v0.mGamma() > maxMassGamma) + return false; + + return true; + } + + // Phi cut + template + bool passedPhiCut(const T& trk, float magField, const TF1& fphiCutLow, const TF1& fphiCutHigh) + { + float pt = trk.pt(); + float phi = trk.phi(); + int charge = trk.sign(); + float eta = trk.eta(); + auto nTPCCl = trk.tpcNClsFindable() - trk.tpcNClsFindableMinusFound(); + float sigP = trk.sign() * trk.tpcInnerParam(); + + if (pt < pTcut) + return true; + + if (magField < 0) // for negatve polarity field + phi = o2::constants::math::TwoPI - phi; + if (charge < 0) // for negatve charge + phi = o2::constants::math::TwoPI - phi; + + // to center gap in the middle + phi += o2::constants::math::PI / 18.0f; + phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + + registryDeDx.fill(HIST("hpt_vs_phi_Ncl_Before"), pt, phi, nTPCCl); + + // cut phi + if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) + return false; // reject track + + if (eta > EtaCut[0] && eta < EtaCut[1]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[0]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[1] && eta < EtaCut[2]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[1]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[2] && eta < EtaCut[3]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[2]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[3] && eta < EtaCut[4]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[3]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[4] && eta < EtaCut[5]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[4]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[5] && eta < EtaCut[6]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[5]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[6] && eta < EtaCut[7]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[6]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[7] && eta < EtaCut[8]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[7]), nTPCCl, trk.tpcSignal(), sigP); + } + } + + // cut Ncl + if (nTPCCl < nclCut) + return false; + + registryDeDx.fill(HIST("hpt_vs_phi_Ncl_After"), pt, phi, nTPCCl); + + if (eta > EtaCut[0] && eta < EtaCut[1]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[0]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[1] && eta < EtaCut[2]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[1]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[2] && eta < EtaCut[3]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[2]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[3] && eta < EtaCut[4]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[3]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[4] && eta < EtaCut[5]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[4]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[5] && eta < EtaCut[6]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[5]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[6] && eta < EtaCut[7]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[6]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[7] && eta < EtaCut[8]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[7]), nTPCCl, trk.tpcSignal(), sigP); + } + } + + return true; + } + + // Phi cut Secondaries + template + bool passedPhiCutSecondaries(const T& trk, float magField, const TF1& fphiCutLow, const TF1& fphiCutHigh) + { + float pt = trk.pt(); + float phi = trk.phi(); + int charge = trk.sign(); + auto nTPCCl = trk.tpcNClsFindable() - trk.tpcNClsFindableMinusFound(); + + if (pt < pTcut) + return true; + + if (magField < 0) // for negatve polarity field + phi = o2::constants::math::TwoPI - phi; + if (charge < 0) // for negatve charge + phi = o2::constants::math::TwoPI - phi; + + // to center gap in the middle + phi += o2::constants::math::PI / 18.0f; + phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + + // cut phi + if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) + return false; // reject track + + // cut Ncl + if (nTPCCl < nclCut) + 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; + + if (additionalCuts) { + if (!collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) + return; + + if (!collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) + return; + + if (std::abs(collision.posZ()) >= maxZDistanceToIP) + return; + + if (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) + return; + } + + // Event Counter + registryDeDx.fill(HIST("histRecVtxZData"), collision.posZ()); + + // Kaons + for (const auto& trk : tracks) { + + // track Selection + if (!passedSingleTrackSelection(trk, collision)) + continue; + + if (!mySelectionPrim.IsSelected(trk)) + continue; + + // phi and Ncl cut + if (!passedPhiCut(trk, magField, *fphiCutLow, *fphiCutHigh)) + continue; + + float signedP = trk.sign() * trk.tpcInnerParam(); + + // MIP calibration for pions + if (trk.tpcInnerParam() >= pionMin && trk.tpcInnerParam() <= pionMax) { + if (calibrationMode) { + if (signedP < 0) { + registryDeDx.fill(HIST("hdEdx_vs_eta_Neg_Pi"), trk.eta(), trk.tpcSignal()); + } else { + registryDeDx.fill(HIST("hdEdx_vs_eta_Pos_Pi"), trk.eta(), trk.tpcSignal()); + } + + } else { + for (int i = 0; i < kEtaIntervals; ++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)); + } else { + registryDeDx.fill(HIST("hdEdx_vs_eta_Pos_calibrated_Pi"), trk.eta(), trk.tpcSignal() * 50 / calibrationFactorPos->at(i)); + } + } + } + } + } + // Beta from TOF + if (signedP < 0) { + registryDeDx.fill(HIST("hbeta_vs_p_Neg"), std::abs(signedP), trk.beta()); + } else { + registryDeDx.fill(HIST("hbeta_vs_p_Pos"), signedP, trk.beta()); + } + // Electrons from TOF + if (std::abs(trk.beta() - 1) < elTofCut) { // beta cut + if (calibrationMode) { + if (signedP < 0) { + registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Neg_El"), trk.eta(), trk.tpcSignal(), std::abs(signedP)); + } else { + registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Pos_El"), trk.eta(), trk.tpcSignal(), signedP); + } + } else { + for (int i = 0; i < kEtaIntervals; ++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)); + } else { + registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Pos_calibrated_El"), trk.eta(), trk.tpcSignal() * 50 / calibrationFactorPos->at(i), signedP); + } + } + } + } + } + // pions from TOF + if (trk.beta() > pionTofCut && trk.beta() < pionTofCut + 0.05) { // beta cut + if (calibrationMode) { + if (signedP < 0) { + registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Neg_TOF"), trk.eta(), trk.tpcSignal(), std::abs(signedP)); + } else { + registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Pos_TOF"), trk.eta(), trk.tpcSignal(), signedP); + } + } else { + for (int i = 0; i < kEtaIntervals; ++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)); + } else { + registryDeDx.fill(HIST("hdEdx_vs_eta_vs_p_Pos_calibrated_TOF"), trk.eta(), trk.tpcSignal() * 50 / calibrationFactorPos->at(i), signedP); + } + } + } + } + } + + registryDeDx.fill(HIST("hdEdx_vs_phi"), trk.phi(), trk.tpcSignal()); + + if (!calibrationMode) { + for (int i = 0; i < kEtaIntervals; ++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("hp_vs_pt_all_Pos"), trk.pt(), signedP); + } else { + registryDeDx.fill(HIST(kDedxvsMomentumNeg[0]), std::abs(signedP), trk.tpcSignal() * 50 / calibrationFactorNeg->at(i), trk.eta()); + registryDeDx.fill(HIST("hp_vs_pt_all_Neg"), trk.pt(), std::abs(signedP)); + } + } + } + } + } + + // Loop over Reconstructed V0s + if (!calibrationMode) { + for (const 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; + // phi and Ncl cut + if (!passedPhiCutSecondaries(posTrack, magField, *fphiCutLow, *fphiCutHigh)) + continue; + + if (!passedPhiCutSecondaries(negTrack, magField, *fphiCutLow, *fphiCutHigh)) + continue; + + float signedPpos = posTrack.sign() * posTrack.tpcInnerParam(); + float signedPneg = negTrack.sign() * negTrack.tpcInnerParam(); + + float pxPos = posTrack.px(); + float pyPos = posTrack.py(); + float pzPos = posTrack.pz(); + + float pxNeg = negTrack.px(); + float pyNeg = negTrack.py(); + float pzNeg = negTrack.pz(); + + const float gammaMass = 2 * MassElectron; // GeV/c^2 + + // K0s Selection + if (passedK0Selection(v0, negTrack, posTrack, collision)) { + float ePosPi = posTrack.energy(MassPionCharged); + float eNegPi = negTrack.energy(MassPionCharged); + + float invMass = std::sqrt((eNegPi + ePosPi) * (eNegPi + ePosPi) - ((pxNeg + pxPos) * (pxNeg + pxPos) + (pyNeg + pyPos) * (pyNeg + pyPos) + (pzNeg + pzPos) * (pzNeg + pzPos))); + + if (std::abs(invMass - MassK0Short) > invMassCut) { + continue; + } + + for (int i = 0; i < kEtaIntervals; ++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()); + } + if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { + registryDeDx.fill(HIST(kDedxvsMomentumPos[1]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + } + } + } + + // Lambda Selection + if (passedLambdaSelection(v0, negTrack, posTrack, collision)) { + + float ePosPr = posTrack.energy(MassProton); + float eNegPi = negTrack.energy(MassPionCharged); + + float invMass = std::sqrt((eNegPi + ePosPr) * (eNegPi + ePosPr) - ((pxNeg + pxPos) * (pxNeg + pxPos) + (pyNeg + pyPos) * (pyNeg + pyPos) + (pzNeg + pzPos) * (pzNeg + pzPos))); + + if (std::abs(invMass - MassLambda) > invMassCut) { + continue; + } + + for (int i = 0; i < kEtaIntervals; ++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()); + } + if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { + registryDeDx.fill(HIST(kDedxvsMomentumPos[2]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + } + } + } + + // AntiLambda Selection + if (passedAntiLambdaSelection(v0, negTrack, posTrack, collision)) { + + float ePosPi = posTrack.energy(MassPionCharged); + float eNegPr = negTrack.energy(MassProton); + + float invMass = std::sqrt((eNegPr + ePosPi) * (eNegPr + ePosPi) - ((pxNeg + pxPos) * (pxNeg + pxPos) + (pyNeg + pyPos) * (pyNeg + pyPos) + (pzNeg + pzPos) * (pzNeg + pzPos))); + + if (std::abs(invMass - MassLambda) > invMassCut) { + continue; + } + + for (int i = 0; i < kEtaIntervals; ++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()); + } + if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { + registryDeDx.fill(HIST(kDedxvsMomentumPos[1]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + } + } + } + + // Gamma Selection + if (passedGammaSelection(v0, negTrack, posTrack, collision)) { + + float ePosEl = posTrack.energy(MassElectron); + float eNegEl = negTrack.energy(MassElectron); + + float invMass = std::sqrt((eNegEl + ePosEl) * (eNegEl + ePosEl) - ((pxNeg + pxPos) * (pxNeg + pxPos) + (pyNeg + pyPos) * (pyNeg + pyPos) + (pzNeg + pzPos) * (pzNeg + pzPos))); + + if (std::abs(invMass - gammaMass) > invMassCutGamma) { + continue; + } + + for (int i = 0; i < kEtaIntervals; ++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()); + } + if (posTrack.eta() > EtaCut[i] && posTrack.eta() < EtaCut[i + 1]) { + registryDeDx.fill(HIST(kDedxvsMomentumPos[3]), signedPpos, posTrack.tpcSignal() * 50 / calibrationFactorPos->at(i), posTrack.eta()); + } + } + } + } + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx index 6407e12a3c9..fec8025339a 100644 --- a/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx +++ b/PWGLF/Tasks/Nuspex/hadronnucleicorrelation.cxx @@ -13,36 +13,38 @@ /// \author Francesca Ercolessi /// \since 21 April 2024 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "TGrid.h" +#include "PWGCF/Femto3D/Core/femto3dPairTask.h" +#include "PWGCF/Femto3D/DataModel/singletrackselector.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/DataModel/Multiplicity.h" #include "CCDB/BasicCCDBManager.h" #include "CCDB/CcdbApi.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" - #include "Framework/ASoA.h" -#include "MathUtils/Utils.h" -#include "Framework/DataTypes.h" -#include "Common/DataModel/Multiplicity.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/DataTypes.h" #include "Framework/Expressions.h" - +#include "Framework/HistogramRegistry.h" #include "Framework/StaticFor.h" -#include "PWGCF/Femto3D/DataModel/singletrackselector.h" -#include "PWGCF/Femto3D/Core/femto3dPairTask.h" +#include "Framework/runDataProcessing.h" +#include "MathUtils/Utils.h" + +#include "TGrid.h" +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include using namespace o2; using namespace o2::soa; @@ -56,6 +58,8 @@ struct hadronnucleicorrelation { static constexpr int pdgProton = 2212; static constexpr int pdgDeuteron = 1000010020; + Configurable mode{"mode", 0, "0: antid-antip, 1: d-p, 2: antid-p, 3: d-antip, 4: antip-p, 5: antip-antip, 6: p-p"}; + Configurable doQA{"doQA", true, "save QA histograms"}; Configurable doMCQA{"doMCQA", false, "save MC QA histograms"}; Configurable isMC{"isMC", false, "is MC"}; @@ -94,6 +98,9 @@ struct hadronnucleicorrelation { Configurable max_tpcSharedCls{"max_tpcSharedCls", 0.4, "maximum fraction of TPC shared clasters"}; Configurable min_itsNCls{"min_itsNCls", 0, "minimum allowed number of ITS clasters"}; Configurable maxmixcollsGen{"maxmixcollsGen", 100, "maxmixcollsGen"}; + Configurable radiusTPC{"radiusTPC", 1.2, "TPC radius to calculate phi_star for"}; + Configurable deta{"deta", 0.01, "minimum allowed defference in eta between two tracks in a pair"}; + Configurable dphi{"dphi", 0.01, "minimum allowed defference in phi_star between two tracks in a pair"}; // Mixing parameters Configurable _vertexNbinsToMix{"vertexNbinsToMix", 10, "Number of vertexZ bins for the mixing"}; @@ -103,6 +110,7 @@ struct hadronnucleicorrelation { Configurable> pTBins{"pTBins", {0.6f, 1.0f, 1.2f, 2.f}, "p_{T} bins"}; ConfigurableAxis AxisNSigma{"AxisNSigma", {35, -7.f, 7.f}, "n#sigma"}; + ConfigurableAxis DeltaPhiAxis = {"DeltaPhiAxis", {46, -1 * o2::constants::math::PIHalf, 3 * o2::constants::math::PIHalf}, "#Delta#phi (rad)"}; using FilteredCollisions = soa::Filtered; using SimCollisions = aod::McCollisions; @@ -143,16 +151,24 @@ struct hadronnucleicorrelation { // key: pair of an integer and a float - value: vector of colType objects // for each key I have a vector of collisions - std::map, std::vector> mixbins_antidantip; + std::map, std::vector> mixbins_antid; + std::map, std::vector> mixbins_d; + std::map, std::vector> mixbins_antip; + std::map, std::vector> mixbins_p; std::map, std::vector> mixbinsPID_antidantip; std::map> mixbinsMC_antidantip; std::map> mixbinsMC_dp; - std::vector> hEtaPhi_AntiDeAntiPr_SE; - std::vector> hEtaPhi_AntiDeAntiPr_ME; - std::vector> hCorrEtaPhi_AntiDeAntiPr_SE; - std::vector> hCorrEtaPhi_AntiDeAntiPr_ME; + std::unique_ptr> Pair = std::make_unique>(); + std::unique_ptr> PairMC = std::make_unique>(); + // Data histograms + std::vector> hEtaPhi_SE; + std::vector> hEtaPhi_ME; + std::vector> hCorrEtaPhi_SE; + std::vector> hCorrEtaPhi_ME; + + // MC histograms std::vector> hEtaPhiRec_AntiDeAntiPr_SE; std::vector> hEtaPhiGen_AntiDeAntiPr_SE; std::vector> hEtaPhiRec_AntiDeAntiPr_ME; @@ -161,7 +177,6 @@ struct hadronnucleicorrelation { std::vector> hPIDEtaPhiGen_AntiDeAntiPr_SE; std::vector> hPIDEtaPhiRec_AntiDeAntiPr_ME; std::vector> hPIDEtaPhiGen_AntiDeAntiPr_ME; - std::vector> hEtaPhiGen_AntiPrAntiPr_SE; std::vector> hEtaPhiGen_AntiPrAntiPr_ME; @@ -193,19 +208,20 @@ struct hadronnucleicorrelation { AxisSpec ptBinnedAxis = {pTBins, "#it{p}_{T} of #bar{p} (GeV/c)"}; AxisSpec etaAxis = {100, -1., 1., "#eta"}; - AxisSpec phiAxis = {157, 0., 2 * o2::constants::math::PI, "#phi (rad)"}; + AxisSpec phiAxis = {157, 0., o2::constants::math::TwoPI, "#phi (rad)"}; AxisSpec pTAxis = {200, -10.f, 10.f, "p_{T} GeV/c"}; AxisSpec pTAxis_small = {100, -5.f, 5.f, "p_{T} GeV/c"}; AxisSpec DeltaEtaAxis = {100, -1.5, 1.5, "#Delta#eta"}; - AxisSpec DeltaPhiAxis = {60, -o2::constants::math::PI / 2, 1.5 * o2::constants::math::PI, "#Delta#phi (rad)"}; - registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{5, 0.f, 5.f}}}); + registry.add("hNEvents", "hNEvents", {HistType::kTH1D, {{7, 0.f, 7.f}}}); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "Selected"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "events with #bar{d}-#bar{p}"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "events with d-p"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "events with #bar{d}"); registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "events with d"); + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "events with #bar{p}"); + registry.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(7, "events with p"); nBinspT = pTBins.value.size() - 1; @@ -251,24 +267,53 @@ struct hadronnucleicorrelation { } } + TString name = "AntiDeAntiPr"; + switch (mode) { + case 1: + name = "DePr"; + break; + case 2: + name = "AntiDePr"; + break; + case 3: + name = "DeAntiPr"; + break; + case 4: + name = "AntiPrPr"; + break; + case 5: + name = "AntiPrAntiPr"; + break; + case 6: + name = "PrPr"; + break; + } + if (!isMC) { for (int i = 0; i < nBinspT; i++) { - auto htempSE_AntiDeAntiPr = registry.add(Form("hEtaPhi_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hEtaPhi_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_AntiDeAntiPr_SE_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_AntiDeAntiPr_ME_pt%02.0f%02.0f", pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f(Form("hEtaPhi_%s_SE_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hEtaPhi_%s_ME_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("Raw #Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_%s_SE_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f(Form("hCorrEtaPhi_%s_ME_pt%02.0f%02.0f", name.Data(), pTBins.value.at(i) * 10, pTBins.value.at(i + 1) * 10), Form("#Delta#eta#Delta#phi (%.1f - void mixTracks(Type const& tracks1, Type const& tracks2, bool isMCPID) + template + void mixTracks(Type const& tracks1, Type const& tracks2, bool isIdentical) { // last value: 0 -- SE; 1 -- ME - for (auto it1 : tracks1) { - for (auto it2 : tracks2) { + for (auto const& it1 : tracks1) { + for (auto const& it2 : tracks2) { + + Pair->SetPair(it1, it2); + Pair->SetIdentical(isIdentical); + + // if Identical (pp and antip-antip) + if (isIdentical && Pair->IsClosePair(deta, dphi, radiusTPC)) { + QA.fill(HIST("QA/hdetadphistar"), Pair->GetPhiStarDiff(radiusTPC), Pair->GetEtaDiff()); + continue; + } // Calculate Delta-eta Delta-phi (reco) float deltaEta = it2->eta() - it1->eta(); float deltaPhi = it2->phi() - it1->phi(); - deltaPhi = getDeltaPhi(deltaPhi); + deltaPhi = RecoDecay::constrainAngle(deltaPhi, -1 * o2::constants::math::PIHalf); + + for (int k = 0; k < nBinspT; k++) { + + if (it1->pt() >= pTBins.value.at(k) && it1->pt() < pTBins.value.at(k + 1)) { + + float corr1 = 1, corr2 = 1; + + if (docorrection) { // Apply corrections + switch (mode) { + case 0: + corr1 = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); + break; + case 1: + corr1 = hEffpTEta_deuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + case 2: + corr1 = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + case 3: + corr1 = hEffpTEta_deuteron->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); + break; + case 4: + corr1 = hEffpTEta_antiproton->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + case 5: + corr1 = hEffpTEta_antiproton->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); + break; + case 6: + corr1 = hEffpTEta_proton->Interpolate(it1->pt(), it1->eta()); + corr2 = hEffpTEta_proton->Interpolate(it2->pt(), it2->eta()); + break; + } + } + + if (ME) { + hEtaPhi_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hCorrEtaPhi_ME[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (corr1 * corr2)); + } else { + hEtaPhi_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hCorrEtaPhi_SE[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (corr1 * corr2)); + } // SE + } // pT condition + } // nBinspT loop + + Pair->ResetPair(); + + } // tracks 2 + } // tracks 1 + } + + template + void mixTracksMC(Type const& tracks1, Type const& tracks2, bool isIdentical, bool isMCPID) + { // last value: 0 -- SE; 1 -- ME + for (auto const& it1 : tracks1) { + for (auto const& it2 : tracks2) { + + PairMC->SetPair(it1, it2); + PairMC->SetIdentical(isIdentical); + + // if Identical (pp and antip-antip) + if (isIdentical && PairMC->IsClosePair(deta, dphi, radiusTPC)) { + QA.fill(HIST("QA/hdetadphistar"), PairMC->GetPhiStarDiff(radiusTPC), PairMC->GetEtaDiff()); + continue; + } + + // Calculate Delta-eta Delta-phi (reco) + float deltaEta = it2->eta() - it1->eta(); + float deltaPhi = it2->phi() - it1->phi(); + deltaPhi = RecoDecay::constrainAngle(deltaPhi, -1 * o2::constants::math::PIHalf); // Calculate Delta-eta Delta-phi (gen) float deltaEtaGen = -999.; float deltaPhiGen = -999.; - if constexpr (doMC) { - deltaEtaGen = it2->eta_MC() - it1->eta_MC(); - deltaPhiGen = it2->phi_MC() - it1->phi_MC(); - deltaPhiGen = getDeltaPhi(deltaPhiGen); - } - - float antipcorr = 1, antidcorr = 1; + deltaEtaGen = it2->eta_MC() - it1->eta_MC(); + deltaPhiGen = it2->phi_MC() - it1->phi_MC(); + deltaPhiGen = RecoDecay::constrainAngle(deltaPhiGen, -1 * o2::constants::math::PIHalf); for (int k = 0; k < nBinspT; k++) { if (it1->pt() >= pTBins.value.at(k) && it1->pt() < pTBins.value.at(k + 1)) { - if (docorrection) { // Apply corrections - antipcorr = hEffpTEta_antiproton->Interpolate(it2->pt(), it2->eta()); - antidcorr = hEffpTEta_antideuteron->Interpolate(it1->pt(), it1->eta()); - } - if (ME) { - if constexpr (!doMC) { // Data - hEtaPhi_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (antipcorr * antidcorr)); - } else { // MC - if (isMCPID) { - hPIDEtaPhiRec_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hPIDEtaPhiGen_AntiDeAntiPr_ME[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } else { - hEtaPhiRec_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hEtaPhiGen_AntiDeAntiPr_ME[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } + if (isMCPID) { + hPIDEtaPhiRec_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hPIDEtaPhiGen_AntiDeAntiPr_ME[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); + } else { + hEtaPhiRec_AntiDeAntiPr_ME[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hEtaPhiGen_AntiDeAntiPr_ME[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); } } else { - if constexpr (!doMC) { // Data - hEtaPhi_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hCorrEtaPhi_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt(), 1. / (antipcorr * antidcorr)); - } else { // MC - if (isMCPID) { - hPIDEtaPhiRec_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hPIDEtaPhiGen_AntiDeAntiPr_SE[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } else { - hEtaPhiRec_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); - hEtaPhiGen_AntiDeAntiPr_SE[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); - } + if (isMCPID) { + hPIDEtaPhiRec_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hPIDEtaPhiGen_AntiDeAntiPr_SE[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); + } else { + hEtaPhiRec_AntiDeAntiPr_SE[k]->Fill(deltaEta, deltaPhi, it2->pt()); + hEtaPhiGen_AntiDeAntiPr_SE[k]->Fill(deltaEtaGen, deltaPhiGen, it2->pt()); } } // SE } // pT condition } // nBinspT loop + + Pair->ResetPair(); + } // tracks 2 } // tracks 1 } @@ -587,11 +715,11 @@ struct hadronnucleicorrelation { template void mixMCParticles(Type const& particles1, Type const& particles2) { - for (auto it1 : particles1) { - for (auto it2 : particles2) { + for (auto const& it1 : particles1) { + for (auto const& it2 : particles2) { // Calculate Delta-eta Delta-phi (gen) float deltaEtaGen = it2->eta() - it1->eta(); - float deltaPhiGen = getDeltaPhi(it2->phi() - it1->phi()); + float deltaPhiGen = RecoDecay::constrainAngle(it2->phi() - it1->phi(), -1 * o2::constants::math::PIHalf); // Loop over pT bins for (int k = 0; k < nBinspT; k++) { @@ -611,11 +739,11 @@ struct hadronnucleicorrelation { template void mixMCParticlesIdentical(Type const& particles1, Type const& particles2) { - for (auto it1 : particles1) { - for (auto it2 : particles2) { + for (auto const& it1 : particles1) { + for (auto const& it2 : particles2) { // Calculate Delta-eta Delta-phi (gen) float deltaEtaGen = it2->eta() - it1->eta(); - float deltaPhiGen = getDeltaPhi(it2->phi() - it1->phi()); + float deltaPhiGen = RecoDecay::constrainAngle(it2->phi() - it1->phi(), -1 * o2::constants::math::PIHalf); if (!ME && std::abs(deltaPhiGen) < 0.001 && std::abs(deltaEtaGen) < 0.001) { continue; @@ -636,16 +764,6 @@ struct hadronnucleicorrelation { } } - float getDeltaPhi(float deltaPhi) - { - if (deltaPhi < -o2::constants::math::PI / 2) { - return deltaPhi += 2 * o2::constants::math::PI; - } else if (deltaPhi >= 3 * o2::constants::math::PI / 2) { - return deltaPhi -= 2 * o2::constants::math::PI; - } - return deltaPhi; - } - void GetCorrection(o2::framework::Service const& ccdbObj, TString filepath, TString histname) { TList* l = ccdbObj->get(filepath.Data()); @@ -689,11 +807,22 @@ struct hadronnucleicorrelation { continue; if (track.itsNCls() < min_itsNCls) continue; + + if (IsProton(track, +1)) + registry.fill(HIST("hPrDCAxy"), track.dcaXY(), track.pt()); + if (IsProton(track, -1)) + registry.fill(HIST("hAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (IsDeuteron(track, +1)) + registry.fill(HIST("hDeDCAxy"), track.dcaXY(), track.pt()); + if (IsDeuteron(track, -1)) + registry.fill(HIST("hAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (!applyDCAcut(track)) continue; if (doQA) { QA.fill(HIST("QA/hTPCnClusters"), track.tpcNClsFound()); + QA.fill(HIST("QA/hTPCSharedClusters"), track.tpcFractionSharedCls()); QA.fill(HIST("QA/hTPCchi2"), track.tpcChi2NCl()); QA.fill(HIST("QA/hTPCcrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); QA.fill(HIST("QA/hITSchi2"), track.itsChi2NCl()); @@ -793,14 +922,121 @@ struct hadronnucleicorrelation { if (selectedtracks_antid.find(collision.globalIndex()) != selectedtracks_antid.end()) { registry.fill(HIST("hNEvents"), 3.5); + mixbins_antid[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + if (selectedtracks_d.find(collision.globalIndex()) != selectedtracks_d.end()) { + registry.fill(HIST("hNEvents"), 4.5); + mixbins_d[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + if (selectedtracks_antip.find(collision.globalIndex()) != selectedtracks_antip.end()) { + registry.fill(HIST("hNEvents"), 5.5); + mixbins_antip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + if (selectedtracks_p.find(collision.globalIndex()) != selectedtracks_p.end()) { + registry.fill(HIST("hNEvents"), 6.5); + mixbins_p[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + } + + Pair->SetMagField1(collision.magField()); + Pair->SetMagField2(collision.magField()); + } + + if (mode == 0 && !mixbins_antid.empty()) { + + for (auto i = mixbins_antid.begin(); i != mixbins_antid.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { + mixTracks<0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col1->index()], 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { + mixTracks<1>(selectedtracks_antid[col1->index()], selectedtracks_antip[col2->index()], 0); // mixing ME + } + } + } + } + } + + if (mode == 1 && !mixbins_d.empty()) { + + for (auto i = mixbins_d.begin(); i != mixbins_d.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0>(selectedtracks_d[col1->index()], selectedtracks_p[col1->index()], 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } - mixbins_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1>(selectedtracks_d[col1->index()], selectedtracks_p[col2->index()], 0); // mixing ME + } + } + } } } - if (!mixbins_antidantip.empty()) { + if (mode == 2 && !mixbins_antid.empty()) { - for (auto i = mixbins_antidantip.begin(); i != mixbins_antidantip.end(); i++) { // iterating over all vertex&mult bins + for (auto i = mixbins_antid.begin(); i != mixbins_antid.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0>(selectedtracks_antid[col1->index()], selectedtracks_p[col1->index()], 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1>(selectedtracks_antid[col1->index()], selectedtracks_p[col2->index()], 0); // mixing ME + } + } + } + } + } + + if (mode == 3 && !mixbins_d.empty()) { + + for (auto i = mixbins_d.begin(); i != mixbins_d.end(); i++) { // iterating over all vertex&mult bins std::vector value = i->second; int EvPerBin = value.size(); // number of collisions in each vertex&mult bin @@ -810,7 +1046,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { - mixTracks<0, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col1->index()], 0); // mixing SE + mixTracks<0>(selectedtracks_d[col1->index()], selectedtracks_antip[col1->index()], 0); // mixing SE } for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin @@ -822,7 +1058,100 @@ struct hadronnucleicorrelation { } if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { - mixTracks<1, 0>(selectedtracks_antid[col1->index()], selectedtracks_antip[col2->index()], 0); // mixing ME + mixTracks<1>(selectedtracks_d[col1->index()], selectedtracks_antip[col2->index()], 0); // mixing ME + } + } + } + } + } + + if (mode == 4 && !mixbins_antip.empty()) { + + for (auto i = mixbins_antip.begin(); i != mixbins_antip.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0>(selectedtracks_antip[col1->index()], selectedtracks_p[col1->index()], 0); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1>(selectedtracks_antip[col1->index()], selectedtracks_p[col2->index()], 0); // mixing ME + } + } + } + } + } + + if (mode == 5 && !mixbins_antip.empty()) { + + for (auto i = mixbins_antip.begin(); i != mixbins_antip.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_antip.find(col1->index()) != selectedtracks_antip.end()) { + mixTracks<0>(selectedtracks_antip[col1->index()], selectedtracks_antip[col1->index()], 1); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_antip.find(col2->index()) != selectedtracks_antip.end()) { + mixTracks<1>(selectedtracks_antip[col1->index()], selectedtracks_antip[col2->index()], 1); // mixing ME + } + } + } + } + } + + if (mode == 6 && !mixbins_p.empty()) { + + for (auto i = mixbins_p.begin(); i != mixbins_p.end(); i++) { // iterating over all vertex&mult bins + + std::vector value = i->second; + int EvPerBin = value.size(); // number of collisions in each vertex&mult bin + + for (int indx1 = 0; indx1 < EvPerBin; indx1++) { // loop over all the events in each vertex&mult bin + + auto col1 = value[indx1]; + + if (selectedtracks_p.find(col1->index()) != selectedtracks_p.end()) { + mixTracks<0>(selectedtracks_p[col1->index()], selectedtracks_p[col1->index()], 1); // mixing SE + } + + for (int indx2 = 0; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin + + auto col2 = value[indx2]; + + if (col1 == col2) { + continue; + } + + if (selectedtracks_p.find(col2->index()) != selectedtracks_p.end()) { + mixTracks<1>(selectedtracks_p[col1->index()], selectedtracks_p[col2->index()], 1); // mixing ME } } } @@ -846,10 +1175,25 @@ struct hadronnucleicorrelation { (i->second).clear(); selectedtracks_d.clear(); - for (auto& pair : mixbins_antidantip) { + for (auto& pair : mixbins_antid) { pair.second.clear(); // Clear the vector associated with the key } - mixbins_antidantip.clear(); // Then clear the map itself + mixbins_antid.clear(); // Then clear the map itself + + for (auto& pair : mixbins_d) { + pair.second.clear(); // Clear the vector associated with the key + } + mixbins_d.clear(); // Then clear the map itself + + for (auto& pair : mixbins_antip) { + pair.second.clear(); // Clear the vector associated with the key + } + mixbins_antip.clear(); // Then clear the map itself + + for (auto& pair : mixbins_p) { + pair.second.clear(); // Clear the vector associated with the key + } + mixbins_p.clear(); // Then clear the map itself } PROCESS_SWITCH(hadronnucleicorrelation, processData, "processData", true); @@ -863,6 +1207,44 @@ struct hadronnucleicorrelation { continue; if (track.itsNCls() < min_itsNCls) continue; + + if (IsProton(track, +1) && track.pdgCode() == pdgProton) { + registry.fill(HIST("hPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatPrDCAxy"), track.dcaXY(), track.pt()); + } + if (IsProton(track, -1) && track.pdgCode() == -pdgProton) { + registry.fill(HIST("hAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakAntiPrDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatAntiPrDCAxy"), track.dcaXY(), track.pt()); + } + if (IsDeuteron(track, +1) && track.pdgCode() == pdgDeuteron) { + registry.fill(HIST("hDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatDeDCAxy"), track.dcaXY(), track.pt()); + } + if (IsDeuteron(track, -1) && track.pdgCode() == -pdgDeuteron) { + registry.fill(HIST("hAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 0) + registry.fill(HIST("hPrimAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 1) + registry.fill(HIST("hSecWeakAntiDeDCAxy"), track.dcaXY(), track.pt()); + if (track.origin() == 2) + registry.fill(HIST("hSecMatAntiDeDCAxy"), track.dcaXY(), track.pt()); + } + if (!applyDCAcut(track)) continue; @@ -872,6 +1254,7 @@ struct hadronnucleicorrelation { if (doQA) { QA.fill(HIST("QA/hTPCnClusters"), track.tpcNClsFound()); + QA.fill(HIST("QA/hTPCSharedClusters"), track.tpcFractionSharedCls()); QA.fill(HIST("QA/hTPCchi2"), track.tpcChi2NCl()); QA.fill(HIST("QA/hTPCcrossedRowsOverFindableCls"), track.tpcCrossedRowsOverFindableCls()); QA.fill(HIST("QA/hITSchi2"), track.itsChi2NCl()); @@ -1222,17 +1605,20 @@ struct hadronnucleicorrelation { int centBinToMix = std::floor(collision.multPerc() / (100.0 / _multNsubBins)); if (selectedtracksMC_antid.find(collision.globalIndex()) != selectedtracksMC_antid.end()) { - mixbins_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); + mixbins_antid[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); } if (selectedtracksPIDMC_antid.find(collision.globalIndex()) != selectedtracksPIDMC_antid.end()) { mixbinsPID_antidantip[std::pair{vertexBinToMix, centBinToMix}].push_back(std::make_shared(collision)); } + + PairMC->SetMagField1(collision.magField()); + PairMC->SetMagField2(collision.magField()); } // coll - if (!mixbins_antidantip.empty()) { + if (!mixbins_antid.empty()) { - for (auto i = mixbins_antidantip.begin(); i != mixbins_antidantip.end(); i++) { // iterating over all vertex&mult bins + for (auto i = mixbins_antid.begin(); i != mixbins_antid.end(); i++) { // iterating over all vertex&mult bins std::vector value = i->second; int EvPerBin = value.size(); // number of collisions in each vertex&mult bin @@ -1242,7 +1628,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracksMC_antip.find(col1->index()) != selectedtracksMC_antip.end()) { - mixTracks<0, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col1->index()], 0); // mixing SE + mixTracksMC<0>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col1->index()], 0, 0); // mixing SE } for (int indx2 = indx1 + 1; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin @@ -1254,7 +1640,7 @@ struct hadronnucleicorrelation { } if (selectedtracksMC_antip.find(col2->index()) != selectedtracksMC_antip.end()) { - mixTracks<1, 1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col2->index()], 0); // mixing ME + mixTracksMC<1>(selectedtracksMC_antid[col1->index()], selectedtracksMC_antip[col2->index()], 0, 0); // mixing ME } } } @@ -1273,7 +1659,7 @@ struct hadronnucleicorrelation { auto col1 = value[indx1]; if (selectedtracksPIDMC_antip.find(col1->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<0, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col1->index()], 1); // mixing SE + mixTracksMC<0>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col1->index()], 0, 1); // mixing SE } for (int indx2 = indx1 + 1; indx2 < EvPerBin; indx2++) { // nested loop for all the combinations of collisions in a chosen mult/vertex bin @@ -1285,7 +1671,7 @@ struct hadronnucleicorrelation { } if (selectedtracksPIDMC_antip.find(col2->index()) != selectedtracksPIDMC_antip.end()) { - mixTracks<1, 1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col2->index()], 1); // mixing ME + mixTracksMC<1>(selectedtracksPIDMC_antid[col1->index()], selectedtracksPIDMC_antip[col2->index()], 0, 1); // mixing ME } } } @@ -1330,10 +1716,10 @@ struct hadronnucleicorrelation { } mixbinsPID_antidantip.clear(); // clear the map - for (auto& pair : mixbins_antidantip) { + for (auto& pair : mixbins_antid) { pair.second.clear(); // clear the vector associated with the key } - mixbins_antidantip.clear(); // clear the map + mixbins_antid.clear(); // clear the map } PROCESS_SWITCH(hadronnucleicorrelation, processMC, "processMC", false); diff --git a/PWGLF/Tasks/Nuspex/he3LambdaDerivedAnalysis.cxx b/PWGLF/Tasks/Nuspex/he3LambdaDerivedAnalysis.cxx new file mode 100644 index 00000000000..7929f4eaa9c --- /dev/null +++ b/PWGLF/Tasks/Nuspex/he3LambdaDerivedAnalysis.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. + +#include "PWGLF/DataModel/LFSlimHeLambda.h" + +#include +#include +#include +#include + +#include + +#include + +namespace +{ +std::shared_ptr hInvariantMassUS[2]; +std::shared_ptr hInvariantMassLS[2]; +std::shared_ptr hRotationInvariantMassUS[2]; +std::shared_ptr hRotationInvariantMassLS[2]; +std::shared_ptr hRotationInvariantMassAntiLSeta[2]; +std::shared_ptr hInvariantMassLambda[2]; +std::shared_ptr hCosPALambda; +std::shared_ptr hNsigmaHe3; +std::shared_ptr hNsigmaProton; +}; // namespace + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct he3LambdaDerivedAnalysis { + HistogramRegistry mRegistry{"He3LambdaDerivedAnalysis"}; + + Configurable cfgNrotations{"cfgNrotations", 7, "Number of rotations for He3 candidates"}; + Configurable cfgMirrorEta{"cfgMirrorEta", true, "Mirror eta for He3 candidates"}; + Configurable cfgMinCosPA{"cfgMinCosPA", 0.99, "Minimum cosPA for Lambda candidates"}; + Configurable cfgMaxNSigmaTPCHe3{"cfgMaxNSigmaTPCHe3", 2.0, "Maximum nSigmaTPC for He3 candidates"}; + Configurable cfgMinLambdaPt{"cfgMinLambdaPt", 0.4, "Minimum pT for Lambda candidates"}; + Configurable cfgMaxLambdaDeltaM{"cfgMaxLambdaDeltaM", 10.0e-3, "Maximum deltaM for Lambda candidates"}; + + void init(InitContext const&) + { + constexpr double ConstituentsMass = o2::constants::physics::MassProton + o2::constants::physics::MassNeutron * 2 + o2::constants::physics::MassSigmaPlus; + for (int i = 0; i < 2; ++i) { + hInvariantMassUS[i] = mRegistry.add(Form("hInvariantMassUS%i", i), "Invariant Mass", {HistType::kTH2D, {{45, 1., 10}, {100, ConstituentsMass - 0.05, ConstituentsMass + 0.05}}}); + hInvariantMassLS[i] = mRegistry.add(Form("hInvariantMassLS%i", i), "Invariant Mass", {HistType::kTH2D, {{45, 1., 10}, {100, ConstituentsMass - 0.05, ConstituentsMass + 0.05}}}); + hRotationInvariantMassUS[i] = mRegistry.add(Form("hRotationInvariantMassUS%i", i), "Rotation Invariant Mass", {HistType::kTH2D, {{45, 1., 10}, {100, ConstituentsMass - 0.05, ConstituentsMass + 0.05}}}); + hRotationInvariantMassLS[i] = mRegistry.add(Form("hRotationInvariantMassLS%i", i), "Rotation Invariant Mass", {HistType::kTH2D, {{45, 1., 10}, {100, ConstituentsMass - 0.05, ConstituentsMass + 0.05}}}); + hInvariantMassLambda[i] = mRegistry.add(Form("hInvariantMassLambda%i", i), "Invariant Mass Lambda", {HistType::kTH2D, {{50, 0., 10.}, {30, o2::constants::physics::MassLambda0 - 0.015, o2::constants::physics::MassLambda0 + 0.015}}}); + hRotationInvariantMassAntiLSeta[i] = mRegistry.add(Form("hRotationInvariantMassAntiLSeta%i", i), "Rotation Invariant Mass Anti-Lambda", {HistType::kTH2D, {{45, 1., 10}, {100, ConstituentsMass - 0.05, ConstituentsMass + 0.05}}}); + } + hCosPALambda = mRegistry.add("hCosPALambda", "Cosine of Pointing Angle for Lambda", {HistType::kTH2D, {{50, 0., 10.}, {500, 0.9, 1.}}}); + hNsigmaHe3 = mRegistry.add("hNsigmaHe3", "nSigma TPC for He3", {HistType::kTH2D, {{100, -10., 10.}, {200, -5, 5.}}}); + hNsigmaProton = mRegistry.add("hNsigmaProton", "nSigma TPC for Proton", {HistType::kTH2D, {{100, -10., 10.}, {200, -5, 5.}}}); + } + + void processSameEvent(o2::aod::LFEvents::iterator const& collision, o2::aod::LFHe3_000 const& he3s, o2::aod::LFLambda_000 const& lambdas) + { + std::vector he3Candidates; + he3Candidates.reserve(he3s.size()); + std::vector lambdaCandidates; + lambdaCandidates.reserve(lambdas.size()); + for (const auto& he3 : he3s) { + if (he3.lfEventId() != collision.globalIndex()) { + std::cout << "He3 candidate does not match event index, skipping." << std::endl; + return; + } + he3Candidate candidate; + candidate.momentum = ROOT::Math::LorentzVector>(he3.pt(), he3.eta(), he3.phi(), o2::constants::physics::MassHelium3); + candidate.nSigmaTPC = he3.nSigmaTPC(); + candidate.dcaXY = he3.dcaXY(); + candidate.dcaZ = he3.dcaZ(); + candidate.tpcNClsFound = he3.tpcNCls(); + candidate.itsNCls = he3.itsClusterSizes(); + candidate.itsClusterSizes = he3.itsClusterSizes(); + candidate.sign = he3.sign(); + hNsigmaHe3->Fill(he3.pt() * he3.sign(), he3.nSigmaTPC()); + if (std::abs(he3.nSigmaTPC()) > cfgMaxNSigmaTPCHe3) { + continue; // Skip candidates with nSigmaTPC outside range + } + he3Candidates.push_back(candidate); + } + for (const auto& lambda : lambdas) { + if (lambda.lfEventId() != collision.globalIndex()) { + std::cout << "Lambda candidate does not match event index, skipping." << std::endl; + return; + } + lambdaCandidate candidate; + candidate.momentum.SetCoordinates(lambda.pt(), lambda.eta(), lambda.phi(), o2::constants::physics::MassLambda0); + candidate.mass = lambda.mass(); + candidate.cosPA = lambda.cosPA(); + candidate.dcaV0Daughters = lambda.dcaDaughters(); + hCosPALambda->Fill(lambda.pt(), candidate.cosPA); + // hNsigmaProton->Fill(lambda.pt() * lambda.sign(), lambda.protonNSigmaTPC()); + hInvariantMassLambda[0]->Fill(lambda.pt(), lambda.mass()); + if (candidate.cosPA < cfgMinCosPA || lambda.pt() < cfgMinLambdaPt || + std::abs(lambda.mass() - o2::constants::physics::MassLambda0) > cfgMaxLambdaDeltaM) { + continue; // Skip candidates with low cosPA + } + hInvariantMassLambda[1]->Fill(lambda.pt(), lambda.mass()); + lambdaCandidates.push_back(candidate); + } + + for (const auto& he3 : he3Candidates) { + for (const auto& lambda : lambdaCandidates) { + auto pairMomentum = lambda.momentum + he3.momentum; // Calculate invariant mass + (he3.sign * lambda.sign > 0 ? hInvariantMassLS : hInvariantMassUS)[he3.sign > 0]->Fill(pairMomentum.Pt(), pairMomentum.M()); + } + for (int iEta{0}; iEta <= cfgMirrorEta; ++iEta) { + for (int iR{0}; iR <= cfgNrotations; ++iR) { + auto he3Momentum = ROOT::Math::LorentzVector>(he3.momentum.Pt(), (1. - iEta * 2.) * he3.momentum.Eta(), he3.momentum.Phi() + TMath::Pi() * (0.75 + 0.5 * iR / cfgNrotations), he3.momentum.M()); + for (const auto& lambda : lambdaCandidates) { + auto pairMomentum = lambda.momentum + he3Momentum; // Calculate invariant mass + (he3.sign * lambda.sign > 0 ? hRotationInvariantMassLS : hRotationInvariantMassUS)[he3.sign > 0]->Fill(pairMomentum.Pt(), pairMomentum.M()); + if (he3.sign < 0 && lambda.sign < 0) { + hRotationInvariantMassAntiLSeta[iEta]->Fill(pairMomentum.Pt(), pairMomentum.M()); + } + } + } + } + } + } + PROCESS_SWITCH(he3LambdaDerivedAnalysis, processSameEvent, "Process same event", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx b/PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx deleted file mode 100644 index ef8dfb4b958..00000000000 --- a/PWGLF/Tasks/Nuspex/hypertriton3bodyMcqa.cxx +++ /dev/null @@ -1,908 +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 hypertriton3bodyMcqa.cxx -/// \brief QA for MC productions which contain hypertriton 3body decay process, including special checks for TOF PID -/// \author Yuanzhe Wang - -#include -#include -#include -#include -#include -#include -#include - -#include "CommonDataFormat/InteractionRecord.h" -#include "CommonDataFormat/IRFrame.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/pidTOFGeneric.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/TableProducer/PID/pidTOFBase.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" -#include "CCDB/BasicCCDBManager.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; -using std::array; -using ColwithEvTimes = o2::soa::Join; -using FullTracksExtIU = soa::Join; -using MCLabeledTracksIU = soa::Join; - -template -bool is3bodyDecayedH3L(TMCParticle const& particle) -{ - if (std::abs(particle.pdgCode()) != 1010010030) { - return false; - } - bool haveProton = false, havePion = false, haveDeuteron = false; - bool haveAntiProton = false, haveAntiPion = false, haveAntiDeuteron = false; - for (const auto& mcDaughter : particle.template daughters_as()) { - if (mcDaughter.pdgCode() == 2212) - haveProton = true; - if (mcDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcDaughter.pdgCode() == 211) - havePion = true; - if (mcDaughter.pdgCode() == -211) - haveAntiPion = true; - if (mcDaughter.pdgCode() == 1000010020) - haveDeuteron = true; - if (mcDaughter.pdgCode() == -1000010020) - haveAntiDeuteron = true; - } - if (haveProton && haveAntiPion && haveDeuteron && particle.pdgCode() > 0) { - return true; - } else if (haveAntiProton && havePion && haveAntiDeuteron && particle.pdgCode() < 0) { - return true; - } - return false; -} - -template -bool isPairedH3LDaughters(TMCParticle const& mctrack0, TMCParticle const& mctrack1, TMCParticle const& mctrack2) -{ - for (const auto& particleMother : mctrack0.template mothers_as()) { - if (!(particleMother.pdgCode() == 1010010030 && mctrack0.pdgCode() == 2212 && mctrack1.pdgCode() == -211 && mctrack2.pdgCode() == 1000010020) && - !(particleMother.pdgCode() == -1010010030 && mctrack0.pdgCode() == -2212 && mctrack1.pdgCode() == 211 && mctrack2.pdgCode() == -1000010020)) { - continue; - } - bool flag1 = false, flag2 = false; - for (const auto& mcDaughter : particleMother.template daughters_as()) { - if (mcDaughter.globalIndex() == mctrack1.globalIndex()) - flag1 = true; - if (mcDaughter.globalIndex() == mctrack2.globalIndex()) - flag2 = true; - } - if (!flag1 || !flag2) - continue; - // move the requirement in mass region into the loop to draw a histogram - // double hypertritonMCMass = RecoDecay::m(array{array{mctrack0.px(), mctrack0.py(), mctrack0.pz()}, array{mctrack1.px(), mctrack1.py(), mctrack1.pz()}, array{mctrack2.px(), mctrack2.py(), mctrack2.pz()}}, array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - // if (hypertritonMCMass > 2.990 && hypertritonMCMass < 2.993) - return true; - } - return false; -} - -// check the properties of daughters candidates and true daughters -struct Hypertriton3bodyMcqa { - - Service ccdb; - Preslice perCollisionTracks = aod::track::collisionId; - - int mRunNumber; - - // Basic checks - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hParticleCounter", "hParticleCounter", {HistType::kTH1F, {{7, 0.0f, 7.0f}}}}, - - {"hTPCNCls", "hTPCNCls", {HistType::kTH1F, {{160, 0.0f, 160.0f}}}}, - {"hTPCNClsCrossedRows", "hTPCNClsCrossedRows", {HistType::kTH1F, {{160, 0.0f, 160.0f}}}}, - {"hTrackEta", "hTrackEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hTrackITSNcls", "hTrackITSNcls", {HistType::kTH1F, {{10, 0.0f, 10.0f}}}}, - {"hTrackMcRapidity", "hTrackMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hTrackNsigmaProton", "hTrackNsigmaProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTrackNsigmaPion", "hTrackNsigmaPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTrackNsigmaDeuteron", "hTrackNsigmaDeuteron", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - - {"hHypertritonEta", "hHypertritomEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hHypertritonMcRapidity", "hHypertritonMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hHypertritonMcPt", "hHypertritonMcPt", {HistType::kTH1F, {{300, 0.0f, 15.0f}}}}, - - {"hProtonCounter", "hProtonCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hProtonPt", "hProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonP", "hProtonP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonMcPt", "hProtonMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonMcP", "hProtonMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hProtonEta", "hProtonEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hProtonMcRapidity", "hProtonMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hProtonNsigmaProton", "hProtonNsigmaProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hProtonTPCNCls", "hProtonTPCNCls", {HistType::kTH1F, {{120, 0.0f, 120.0f}}}}, - {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hProtonTPCBBAfterTPCNclsCut", "hProtonTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDauProtonPt", "hDauProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauProtonMcPt", "hDauProtonMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauProtonNsigmaProton", "hDauProtonNsigmaProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hDauProtonTPCVsPt", "hDauProtonTPCVsPt", {HistType::kTH2F, {{50, 0.0f, 5.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - - {"hPionCounter", "hPionCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hPionPt", "hPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionP", "hPionP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionMcPt", "hPionMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionMcP", "hPionMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPionEta", "hPionEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hPionMcRapidity", "hPionMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hPionNsigmaPion", "hPionNsigmaPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hPionTPCNCls", "hPionTPCNCls", {HistType::kTH1F, {{160, 0.0f, 160.0f}}}}, - {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hPionTPCBBAfterTPCNclsCut", "hPionTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDauPionPt", "hDauPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauPionMcPt", "hDauPionMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauPionNsigmaPion", "hDauPionNsigmaPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hDauPionTPCVsPt", "hDauPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDauPionDcaXY", "hDauPionDcaXY", {HistType::kTH1F, {{100, -10.0f, 10.0f}}}}, - - {"hDeuteronCounter", "hDeuteronCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - {"hDeuteronPt", "hDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronP", "hDeuteronP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronMcPt", "hDeuteronMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronMcP", "hDeuteronMcP", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDeuteronEta", "hDeuteronEta", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hDeuteronMcRapidity", "hDeuteronMcRapidity", {HistType::kTH1F, {{200, -10.0f, 10.0f}}}}, - {"hDeuteronNsigmaDeuteron", "hDeuteronNsigmaDeuteron", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hDeuteronTPCNCls", "hDeuteronTPCNCls", {HistType::kTH1F, {{120, 0.0f, 120.0f}}}}, - {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDeuteronTPCBBAfterTPCNclsCut", "hDeuteronTPCBBAfterTPCNclsCut", {HistType::kTH2F, {{320, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDauDeuteronPt", "hDauDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauDeuteronMcPt", "hDauDeuteronMcPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDauDeuteronTPCVsPt", "hDauDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsP", "hDauDeuteronTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsPHasTOF", "hDauDeuteronTOFNSigmaVsPHasTOF", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronMatchCounter", "hDauDeuteronMatchCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - - {"hTPCBB", "hTPCBB", {HistType::kTH2F, {{120, -8.0f, 8.0f, "p/z(GeV/c)"}, {100, 0.0f, 1000.0f, "TPCSignal"}}}}, - - {"hPairedH3LDaughers", "hPairedH3LDaughers", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - {"hPairedH3LDaughersInvMass", "hPairedH3LDaughersInvMass", {HistType::kTH1F, {{300, 2.9f, 3.2f}}}}, - {"hDuplicatedH3LDaughers", "hDuplicatedH3LDaughers", {HistType::kTH1F, {{3, 0.0f, 3.0f}}}}, - - // Diff checks always requir hasTOF - {"hDiffTrackTOFSignal", "hDiffTrackTOFSignal", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hDiffEvTimeForTrack", "hDiffEvTimeForTrack", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hDiffTrackTOFNSigmaDe", "hDiffTrackTOFNSigmaDe", {HistType::kTH1F, {{200, -1.0f, 1.0f}}}}, - {"hDauDeuteronNewTOFNSigmaVsP", "hDauDeuteronNewTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hWrongDeuteronTOFNSigmaVsP", "hWrongDeuteronTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hWrongDeuteronNewTOFNSigmaVsP", "hWrongDeuteronNewTOFNSigmaVsP", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDiffColTime", "hDiffColTime", {HistType::kTH1F, {{200, -100.0f, 100.0f}}}}, - {"hDauDeuteronDiffTOFNsigmaDeHasTOF", "hDauDeuteronDiffTOFNsigmaDeHasTOF", {HistType::kTH1F, {{200, -100.0f, 100.0f}}}}, - - // _v2 for using relinked collision - {"hDauDeuteronTOFNSigmaVsP_CorrectCol", "hDauDeuteronTOFNSigmaVsP_CorrectCol", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronNewTOFNSigmaVsP_CorrectCol", "hDauDeuteronNewTOFNSigmaVsP_CorrectCol", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsP_v2", "hDauDeuteronTOFNSigmaVsP_v2", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronNewTOFNSigmaVsP_v2_AO2D", "hDauDeuteronNewTOFNSigmaVsP_v2 AO2D", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronNewTOFNSigmaVsP_v2_EvSel", "hDauDeuteronNewTOFNSigmaVsP_v2 EvSel", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsColTimeRes_v2", "hDauDeuteronTOFNSigmaVsColTimeRes_v2", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsColTimeRes_v2_AO2D", "hDauDeuteronTOFNSigmaVsColTimeRes_v2 AO2D", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFNSigmaVsColTimeRes_v2_EvSel", "hDauDeuteronTOFNSigmaVsColTimeRes_v2 EvSel", {HistType::kTH2F, {{100, 0.0f, 400.0f, "CollisionTimeRes(ns)"}, {600, -300.0f, 300.0f, "TOF n#sigma"}}}}, - {"hDauDeuteronTOFPIDCounter", "hDauDeuteronTOFPIDCounter", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - {"hDauDeuteronTOFPIDCounter_CloseBC", "hDauDeuteronTOFPIDCounter CloseBC", {HistType::kTH1F, {{5, 0.0f, 5.0f}}}}, - }, - }; - - void init(InitContext&) - { - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(1, "Readin"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(2, "Has_mcparticle"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(3, "Rapidity Cut"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(4, "McisHypertriton"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(5, "McisProton"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(6, "McisPion"); - registry.get(HIST("hParticleCounter"))->GetXaxis()->SetBinLabel(7, "McisDeuteron"); - - TString trackCounterbinLabel[2] = {"hasMom", "FromHypertriton"}; - for (int i{0}; i < 2; i++) { - registry.get(HIST("hProtonCounter"))->GetXaxis()->SetBinLabel(i + 1, trackCounterbinLabel[i]); - registry.get(HIST("hPionCounter"))->GetXaxis()->SetBinLabel(i + 1, trackCounterbinLabel[i]); - registry.get(HIST("hDeuteronCounter"))->GetXaxis()->SetBinLabel(i + 1, trackCounterbinLabel[i]); - } - registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(1, "proton"); - registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(2, "pion"); - registry.get(HIST("hDuplicatedH3LDaughers"))->GetXaxis()->SetBinLabel(3, "deuteron"); - - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(1, "Total"); - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(2, "correct collision"); - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(3, "hasTOF"); - registry.get(HIST("hDauDeuteronMatchCounter"))->GetXaxis()->SetBinLabel(4, "hasTOF & correct collsion"); - - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(1, "Origin |n#sigma| >= 5"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(2, "BothBC work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(3, "Only BCAO2D work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(4, "Only BCEvSel work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter"))->GetXaxis()->SetBinLabel(5, "BothBC not work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(1, "Origin |n#sigma| < 6"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(2, "BothBC work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(3, "Only BCAO2D work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(4, "Only BCEvSel work"); - registry.get(HIST("hDauDeuteronTOFPIDCounter_CloseBC"))->GetXaxis()->SetBinLabel(5, "BothBC not work"); - } - - Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; - Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; - Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; - Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; - Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; - Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; - Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; - - // CCDB TOF PID paras - Configurable timestamp{"ccdb-timestamp", -1, "timestamp of the object"}; - Configurable paramFileName{"paramFileName", "", "Path to the parametrization object. If empty the parametrization is not taken from file"}; - Configurable parametrizationPath{"parametrizationPath", "TOF/Calib/Params", "Path of the TOF parametrization on the CCDB or in the file, if the paramFileName is not empty"}; - Configurable passName{"passName", "", "Name of the pass inside of the CCDB parameter collection. If empty, the automatically deceted from metadata (to be implemented!!!)"}; - Configurable timeShiftCCDBPath{"timeShiftCCDBPath", "", "Path of the TOF time shift vs eta. If empty none is taken"}; - Configurable loadResponseFromCCDB{"loadResponseFromCCDB", false, "Flag to load the response from the CCDB"}; - Configurable fatalOnPassNotAvailable{"fatalOnPassNotAvailable", true, "Flag to throw a fatal if the pass is not available in the retrieved CCDB object"}; - - o2::aod::pidtofgeneric::TofPidNewCollision bachelorTOFPID; - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) - { - if (mRunNumber == bc.runNumber()) { - return; - } - mRunNumber = bc.runNumber(); - - // Initial TOF PID Paras, copied from PIDTOF.h - timestamp.value = bc.timestamp(); - ccdb->setTimestamp(timestamp.value); - // Not later than now objects - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - // TODO: implement the automatic pass name detection from metadata - if (passName.value == "") { - passName.value = "unanchored"; // temporary default - LOG(warning) << "Passed autodetect mode for pass, not implemented yet, waiting for metadata. Taking '" << passName.value << "'"; - } - LOG(info) << "Using parameter collection, starting from pass '" << passName.value << "'"; - - const std::string fname = paramFileName.value; - if (!fname.empty()) { // Loading the parametrization from file - LOG(info) << "Loading exp. sigma parametrization from file " << fname << ", using param: " << parametrizationPath.value; - if (1) { - o2::tof::ParameterCollection paramCollection; - paramCollection.loadParamFromFile(fname, parametrizationPath.value); - LOG(info) << "+++ Loaded parameter collection from file +++"; - if (!paramCollection.retrieveParameters(mRespParamsV2, passName.value)) { - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { - mRespParamsV2.setShiftParameters(paramCollection.getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } else { - mRespParamsV2.loadParamFromFile(fname.data(), parametrizationPath.value); - } - } else if (loadResponseFromCCDB) { // Loading it from CCDB - LOG(info) << "Loading exp. sigma parametrization from CCDB, using path: " << parametrizationPath.value << " for timestamp " << timestamp.value; - o2::tof::ParameterCollection* paramCollection = ccdb->getForTimeStamp(parametrizationPath.value, timestamp.value); - paramCollection->print(); - if (!paramCollection->retrieveParameters(mRespParamsV2, passName.value)) { // Attempt at loading the parameters with the pass defined - if (fatalOnPassNotAvailable) { - LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } else { - LOGF(warning, "Pass '%s' not available in the retrieved CCDB object", passName.value.data()); - } - } else { // Pass is available, load non standard parameters - mRespParamsV2.setShiftParameters(paramCollection->getPars(passName.value)); - mRespParamsV2.printShiftParameters(); - } - } - mRespParamsV2.print(); - if (timeShiftCCDBPath.value != "") { - if (timeShiftCCDBPath.value.find(".root") != std::string::npos) { - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Pos", true); - mRespParamsV2.setTimeShiftParameters(timeShiftCCDBPath.value, "gmean_Neg", false); - } else { - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/pos", timeShiftCCDBPath.value.c_str()), timestamp.value), true); - mRespParamsV2.setTimeShiftParameters(ccdb->getForTimeStamp(Form("%s/neg", timeShiftCCDBPath.value.c_str()), timestamp.value), false); - } - } - - bachelorTOFPID.SetParams(mRespParamsV2); - } - - struct Indexdaughters { // check duplicated paired daughters - int64_t index0; - int64_t index1; - int64_t index2; - bool operator==(const Indexdaughters& t) const - { - return (this->index0 == t.index0 && this->index1 == t.index1 && this->index2 == t.index2); - } - }; - - void process(ColwithEvTimes const& collisions, MCLabeledTracksIU const& tracks, aod::McParticles const& /*particlesMC*/, aod::McCollisions const& /*mcCollisions*/, aod::BCsWithTimestamps const&) - { - for (const auto& collision : collisions) { - auto bc = collision.bc_as(); - initCCDB(bc); - - registry.fill(HIST("hEventCounter"), 0.5); - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - registry.fill(HIST("hEventCounter"), 2.5); - - std::vector protons, pions, deuterons; // index for daughter tracks - std::unordered_set set_proton, set_pion, set_deuteron; // check duplicated daughters - int itrack = -1; - - auto coltracks = tracks.sliceBy(perCollisionTracks, collision.globalIndex()); - - for (const auto& track : coltracks) { - - ++itrack; - registry.fill(HIST("hParticleCounter"), 0.5); - registry.fill(HIST("hTrackITSNcls"), track.itsNCls()); - registry.fill(HIST("hTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hTPCNClsCrossedRows"), track.tpcNClsCrossedRows()); - registry.fill(HIST("hTrackNsigmaDeuteron"), track.tpcNSigmaDe()); - registry.fill(HIST("hTrackNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hTrackNsigmaPion"), track.tpcNSigmaPi()); - - if (!track.has_mcParticle()) { - continue; - } - auto mcparticle = track.mcParticle_as(); - registry.fill(HIST("hTPCBB"), track.p() * track.sign(), track.tpcSignal()); - - registry.fill(HIST("hParticleCounter"), 1.5); - - // if (TMath::Abs(mcparticle.y()) > 0.9) {continue;} - registry.fill(HIST("hParticleCounter"), 2.5); - registry.fill(HIST("hTrackEta"), track.eta()); - registry.fill(HIST("hTrackMcRapidity"), mcparticle.y()); - - // Hypertriton detected directly - if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hParticleCounter"), 3.5); - registry.fill(HIST("hHypertritonMcPt"), mcparticle.pt()); - registry.fill(HIST("hHypertritonEta"), track.eta()); - registry.fill(HIST("hHypertritonMcRapidity"), mcparticle.y()); - } - - // Proton - if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { - registry.fill(HIST("hParticleCounter"), 4.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hProtonTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); - } - - if (mcparticle.has_mothers()) { - registry.fill(HIST("hProtonCounter"), 0.5); - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - protons.push_back(itrack); - auto p = set_proton.insert(mcparticle.globalIndex()); - if (p.second == false) - registry.fill(HIST("hDuplicatedH3LDaughers"), 0); - registry.fill(HIST("hProtonCounter"), 1.5); - registry.fill(HIST("hDauProtonPt"), track.pt()); - registry.fill(HIST("hDauProtonMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauProtonNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hDauProtonTPCVsPt"), track.pt(), track.tpcNSigmaPr()); - } - } - - registry.fill(HIST("hProtonMcPt"), mcparticle.pt()); - registry.fill(HIST("hProtonMcP"), mcparticle.p()); - registry.fill(HIST("hProtonPt"), track.pt()); - registry.fill(HIST("hProtonP"), track.p()); - - registry.fill(HIST("hProtonNsigmaProton"), track.tpcNSigmaPr()); - registry.fill(HIST("hProtonTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hProtonEta"), track.eta()); - registry.fill(HIST("hProtonMcRapidity"), mcparticle.y()); - registry.fill(HIST("hProtonTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } - - // Pion - if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { - registry.fill(HIST("hParticleCounter"), 5.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hPionTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); - } - - if (mcparticle.has_mothers()) { - registry.fill(HIST("hPionCounter"), 0.5); - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - pions.push_back(itrack); - auto p = set_pion.insert(mcparticle.globalIndex()); - if (p.second == false) { - registry.fill(HIST("hDuplicatedH3LDaughers"), 1); - } - registry.fill(HIST("hPionCounter"), 1.5); - registry.fill(HIST("hDauPionPt"), track.pt()); - registry.fill(HIST("hDauPionMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauPionTPCVsPt"), track.pt(), track.tpcNSigmaPi()); - registry.fill(HIST("hDauPionDcaXY"), track.dcaXY()); - } - } - - registry.fill(HIST("hPionMcPt"), mcparticle.pt()); - registry.fill(HIST("hPionMcP"), mcparticle.p()); - registry.fill(HIST("hPionPt"), track.pt()); - registry.fill(HIST("hPionP"), track.p()); - - registry.fill(HIST("hPionNsigmaPion"), track.tpcNSigmaPi()); - registry.fill(HIST("hPionTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hPionEta"), track.eta()); - registry.fill(HIST("hPionMcRapidity"), mcparticle.y()); - registry.fill(HIST("hPionTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } - - float tofNsigmaDe = -999; - static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps - - if (track.hasTOF() && track.has_collision()) { - auto responseDe = o2::pid::tof::ExpTimes(); - // float bachExpTime = track.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - - float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; - float bachExpTime = track.length() * std::sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - float tofsignal = track.trackTime() * 1000 + bachExpTime; // in ps - - float expSigma = responseDe.GetExpectedSigma(mRespParamsV2, track, tofsignal, track.tofEvTimeErr()); - // tofNsigmaDe = (track.tofSignal() - track.tofEvTime() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - tofNsigmaDe = (tofsignal - track.tofEvTime() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - // tofNsigmaDe = (tofsignal - track.evTimeForTrack() - responseDe.GetCorrectedExpectedSignal(mRespParamsV2, track)) / expSigma; - - if (collision.bcId() == collision.foundBCId()) { - registry.fill(HIST("hDiffColTime"), track.tofEvTime() - collision.collisionTime()); - } - - // Assume deuterons linked to the correct collision, result of new TOF PID should be same as the default one - registry.fill(HIST("hDiffTrackTOFSignal"), track.tofSignal() - tofsignal); - registry.fill(HIST("hDiffEvTimeForTrack"), track.tofEvTime() - track.evTimeForTrack()); - registry.fill(HIST("hDiffTrackTOFNSigmaDe"), track.tofNSigmaDe() - bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, collision, collision)); - // registry.fill(HIST("hDiffTrackTOFNSigmaDe"), track.tofExpSigmaDe() - bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, collision, collision)); - } - - // Deuteron - if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { - registry.fill(HIST("hParticleCounter"), 6.5); - if (track.tpcNClsFound() > 70) { - registry.fill(HIST("hDeuteronTPCBBAfterTPCNclsCut"), track.p() * track.sign(), track.tpcSignal()); - } - - if (mcparticle.has_mothers()) { - registry.fill(HIST("hDeuteronCounter"), 0.5); - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - deuterons.push_back(itrack); - auto p = set_deuteron.insert(mcparticle.globalIndex()); - if (p.second == false) - registry.fill(HIST("hDuplicatedH3LDaughers"), 2); - registry.fill(HIST("hDeuteronCounter"), 1.5); - registry.fill(HIST("hDauDeuteronPt"), track.pt()); - registry.fill(HIST("hDauDeuteronMcPt"), mcparticle.pt()); - registry.fill(HIST("hDauDeuteronTPCVsPt"), track.pt(), track.tpcNSigmaDe()); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsP"), track.sign() * track.p(), track.tofNSigmaDe()); - - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP"), track.sign() * track.p(), tofNsigmaDe); - if (track.hasTOF()) { - registry.fill(HIST("hDauDeuteronTOFNSigmaVsPHasTOF"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronDiffTOFNsigmaDeHasTOF"), track.tofNSigmaDe() - tofNsigmaDe); - } - registry.fill(HIST("hDauDeuteronMatchCounter"), 0.5); - if (mcparticle.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 1.5); - } - if (track.hasTOF()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 2.5); - if (mcparticle.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDauDeuteronMatchCounter"), 3.5); - } - } - } - } - - registry.fill(HIST("hDeuteronMcPt"), mcparticle.pt()); - registry.fill(HIST("hDeuteronMcP"), mcparticle.p()); - registry.fill(HIST("hDeuteronPt"), track.pt()); - registry.fill(HIST("hDeuteronP"), track.p()); - - registry.fill(HIST("hDeuteronNsigmaDeuteron"), track.tpcNSigmaDe()); - registry.fill(HIST("hDeuteronTPCNCls"), track.tpcNClsFound()); - registry.fill(HIST("hDeuteronEta"), track.eta()); - registry.fill(HIST("hDeuteronMcRapidity"), mcparticle.y()); - registry.fill(HIST("hDeuteronTPCBB"), track.p() * track.sign(), track.tpcSignal()); - } else { - if (track.hasTOF()) { - registry.fill(HIST("hWrongDeuteronTOFNSigmaVsP"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hWrongDeuteronNewTOFNSigmaVsP"), track.sign() * track.p(), tofNsigmaDe); - } - } - } - - std::vector set_pair; - for (size_t iproton = 0; iproton < protons.size(); iproton++) { - auto track0 = tracks.iteratorAt(protons[iproton]); - auto mctrack0 = track0.mcParticle_as(); - for (size_t ipion = 0; ipion < pions.size(); ipion++) { - auto track1 = tracks.iteratorAt(pions[ipion]); - auto mctrack1 = track1.mcParticle_as(); - for (size_t ideuteron = 0; ideuteron < deuterons.size(); ideuteron++) { - auto track2 = tracks.iteratorAt(deuterons[ideuteron]); - auto mctrack2 = track2.mcParticle_as(); - if (isPairedH3LDaughters(mctrack0, mctrack1, mctrack2)) { - registry.fill(HIST("hPairedH3LDaughers"), 0); - // MC mass cut, to check if the daughters are from materials - double hypertritonMCMass = RecoDecay::m(std::array{std::array{mctrack0.px(), mctrack0.py(), mctrack0.pz()}, std::array{mctrack1.px(), mctrack1.py(), mctrack1.pz()}, std::array{mctrack2.px(), mctrack2.py(), mctrack2.pz()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hPairedH3LDaughersInvMass"), hypertritonMCMass); - if (hypertritonMCMass < 2.990 || hypertritonMCMass > 2.993) - continue; - registry.fill(HIST("hPairedH3LDaughers"), 1); - // duplicated daughters check - Indexdaughters temp = {mctrack0.globalIndex(), mctrack1.globalIndex(), mctrack2.globalIndex()}; - auto p = std::find(set_pair.begin(), set_pair.end(), temp); - if (p == set_pair.end()) { - set_pair.push_back(temp); - registry.fill(HIST("hPairedH3LDaughers"), 2); - } - } - } - } - } - } - - // Check for recalculated TOF PID for secondary deuterons - - std::vector SelectedEvents(collisions.size()); - int nevts = 0; - for (const auto& collision : collisions) { - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); - } - - for (const auto& track : tracks) { - if (!track.has_mcParticle()) { - continue; - } - auto mcparticle = track.mcParticle_as(); - if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { - if (!mcparticle.has_mothers()) { - continue; - } - const auto evtReconstructed = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcparticle.mcCollision_as().globalIndex()); - if (evtReconstructed == SelectedEvents.end() || !track.has_collision()) { - continue; - } - if (!track.has_collision()) { - continue; - } - auto collision = collisions.iteratorAt(evtReconstructed - SelectedEvents.begin()); - auto originalcollision = track.collision_as(); - - for (const auto& particleMother : mcparticle.mothers_as()) { - bool flag_H3L = is3bodyDecayedH3L(particleMother); - if (!flag_H3L) { - continue; - } - - auto bc = collision.bc_as(); - initCCDB(bc); - float tofNsigmaDeAO2D = -999; - float tofNsigmaDeEvSel = -999; - - if (track.hasTOF()) { - /*auto responseDe = o2::pid::tof::ExpTimes(); - //float bachExpTime = track.length() * sqrt((o2::constants::physics::MassDeuteron * o2::constants::physics::MassDeuteron) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; - float bachExpTime = track.length() * std::sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v - */ - - tofNsigmaDeAO2D = bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, originalcollision, collision); - tofNsigmaDeEvSel = bachelorTOFPID.GetTOFNSigma(o2::track::PID::Deuteron, track, originalcollision, collision, false); - - if (collision.globalIndex() == originalcollision.globalIndex()) { - registry.fill(HIST("hDauDeuteronTOFNSigmaVsP_CorrectCol"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_CorrectCol"), track.sign() * track.p(), tofNsigmaDeAO2D); - continue; - } - - /*if (originalcollision.collisionTimeRes() > 40){ - continue; - }*/ - registry.fill(HIST("hDauDeuteronTOFNSigmaVsP_v2"), track.sign() * track.p(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_v2_AO2D"), track.sign() * track.p(), tofNsigmaDeAO2D); - registry.fill(HIST("hDauDeuteronNewTOFNSigmaVsP_v2_EvSel"), track.sign() * track.p(), tofNsigmaDeEvSel); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2"), collision.collisionTimeRes(), track.tofNSigmaDe()); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2_AO2D"), originalcollision.collisionTimeRes(), tofNsigmaDeAO2D); - registry.fill(HIST("hDauDeuteronTOFNSigmaVsColTimeRes_v2_EvSel"), originalcollision.collisionTimeRes(), tofNsigmaDeEvSel); - - if (std::abs(track.tofNSigmaDe()) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 0.5); - if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 1.5); - } else if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 2.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 3.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter"), 4.5); - } - } else if (std::abs(track.tofNSigmaDe()) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 0.5); - if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 1.5); - } else if (std::abs(tofNsigmaDeAO2D) < 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 2.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) < 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 3.5); - } else if (std::abs(tofNsigmaDeAO2D) >= 5 && std::abs(tofNsigmaDeEvSel) >= 5) { - registry.fill(HIST("hDauDeuteronTOFPIDCounter_CloseBC"), 4.5); - } - } - } - } - } - } - } -}; - -// check the performance of mcparticle -struct Hypertriton3bodyMcParticleCheck { - // Basic checks - HistogramRegistry registry{ - "registry", - { - {"hMcCollCounter", "hMcCollCounter", {HistType::kTH1F, {{2, 0.0f, 2.0f}}}}, - - {"h3dMCDecayedHypertriton", "h3dMCDecayedHypertriton", {HistType::kTH3F, {{20, -1.0f, 1.0f, "Rapidity"}, {200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {50, 0.0f, 50.0f, "ct(cm)"}}}}, - - {"hMcHypertritonCounter", "hMcHypertritonCounter", {HistType::kTH1F, {{9, 0.0f, 9.0f}}}}, - {"hMcHypertritonPt", "hMcHypertritonPt", {HistType::kTH1F, {{300, 0.0f, 15.0f}}}}, - {"hMcProtonPt", "hMcProtonPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hMcPionPt", "hMcPionPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hMcDeuteronPt", "hMcDeuteronPt", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - - {"hMcRecoInvMass", "hMcRecoInvMass", {HistType::kTH1F, {{100, 2.95, 3.05f}}}}, - - {"hDiffDaughterR", "hDiffDaughterR", {HistType::kTH1F, {{10000, -100, 100}}}}, // difference between minR of pion&proton and R of deuteron(bachelor) - {"hTrackX", "hTrackX", {HistType::kTH1F, {{10000, -100, 100}}}}, - {"hTrackY", "hTrackY", {HistType::kTH1F, {{10000, -100, 100}}}}, - {"hTrackZ", "hTrackZ", {HistType::kTH1F, {{10000, -100, 100}}}}, - }, - }; - - o2::pid::tof::TOFResoParamsV2 mRespParamsV2; - - void init(InitContext&) - { - registry.get(HIST("hMcCollCounter"))->GetXaxis()->SetBinLabel(1, "Total Counter"); - registry.get(HIST("hMcCollCounter"))->GetXaxis()->SetBinLabel(2, "Reconstructed"); - - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(1, "Hypertriton All"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(2, "Matter All"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(3, "AntiMatter All"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(4, "confirm to 3-body decay"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(5, "Matter"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(6, "AntiMatter"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(7, "Rapidity"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(8, "Lifetime"); - registry.get(HIST("hMcHypertritonCounter"))->GetXaxis()->SetBinLabel(9, "PtCut"); - } - - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; - - Preslice permcCollision = o2::aod::mcparticle::mcCollisionId; - - std::vector mcPartIndices; - template - void SetTrackIDForMC(aod::McParticles const& particlesMC, TTrackTable const& tracks) - { - mcPartIndices.clear(); - mcPartIndices.resize(particlesMC.size()); - std::fill(mcPartIndices.begin(), mcPartIndices.end(), -1); - for (const auto& track : tracks) { - if (track.has_mcParticle()) { - auto mcparticle = track.template mcParticle_as(); - if (mcPartIndices[mcparticle.globalIndex()] == -1) { - mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); - } else { - auto candTrack = tracks.rawIteratorAt(mcPartIndices[mcparticle.globalIndex()]); - // Use the track which has innest information (also best quality? - if (track.x() < candTrack.x()) { - mcPartIndices[mcparticle.globalIndex()] = track.globalIndex(); - } - } - - // Checks for TrackR - registry.fill(HIST("hTrackX"), track.x()); - registry.fill(HIST("hTrackY"), track.y()); - registry.fill(HIST("hTrackZ"), track.z()); - } - } - } - - void process(aod::McCollisions const& mcCollisions, aod::McParticles const& particlesMC, const o2::soa::Join& collisions, MCLabeledTracksIU const& tracks) - { - SetTrackIDForMC(particlesMC, tracks); - std::vector SelectedEvents(collisions.size()); - int nevts = 0; - for (const auto& collision : collisions) { - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); - } - SelectedEvents.resize(nevts); - - for (const auto& mcCollision : mcCollisions) { - registry.fill(HIST("hMcCollCounter"), 0.5); - const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); - if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection - continue; - } - registry.fill(HIST("hMcCollCounter"), 1.5); - - const auto& dparticlesMC = particlesMC.sliceBy(permcCollision, mcCollision.globalIndex()); - - for (const auto& mcparticle : dparticlesMC) { - - if (mcparticle.pdgCode() == 2212 || mcparticle.pdgCode() == -2212) { - registry.fill(HIST("hMcProtonPt"), mcparticle.pt()); - } - if (mcparticle.pdgCode() == 211 || mcparticle.pdgCode() == -211) { - registry.fill(HIST("hMcPionPt"), mcparticle.pt()); - } - if (mcparticle.pdgCode() == 1000010020 || mcparticle.pdgCode() == -1000010020) { - registry.fill(HIST("hMcDeuteronPt"), mcparticle.pt()); - } - if (mcparticle.pdgCode() == 1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 1.5); - } else if (mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 2.5); - } - if (mcparticle.pdgCode() == 1010010030 || mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 0.5); - registry.fill(HIST("hMcHypertritonPt"), mcparticle.pt()); - - double dauDeuteronPos[3] = {-999, -999, -999}; - double dauProtonMom[3] = {-999, -999, -999}; - double dauPionMom[3] = {-999, -999, -999}; - double dauDeuteronMom[3] = {-999, -999, -999}; - double MClifetime = 999; - double dauProtonTrackR = 9999, dauPionTrackR = 99999, dauDeuteronTrackR = 999999; - bool flag_H3L = is3bodyDecayedH3L(mcparticle); - if (!flag_H3L) { - continue; - } - for (const auto& mcparticleDaughter : mcparticle.daughters_as()) { - if (std::abs(mcparticleDaughter.pdgCode()) == 2212) { - dauProtonMom[0] = mcparticleDaughter.px(); - dauProtonMom[1] = mcparticleDaughter.py(); - dauProtonMom[2] = mcparticleDaughter.pz(); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto trackProton = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - dauProtonTrackR = trackProton.x(); - } - } - if (std::abs(mcparticleDaughter.pdgCode()) == 211) { - dauPionMom[0] = mcparticleDaughter.px(); - dauPionMom[1] = mcparticleDaughter.py(); - dauPionMom[2] = mcparticleDaughter.pz(); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto trackPion = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - dauPionTrackR = trackPion.x(); - } - } - if (std::abs(mcparticleDaughter.pdgCode()) == 1000010020) { - dauDeuteronPos[0] = mcparticleDaughter.vx(); - dauDeuteronPos[1] = mcparticleDaughter.vy(); - dauDeuteronPos[2] = mcparticleDaughter.vz(); - dauDeuteronMom[0] = mcparticleDaughter.px(); - dauDeuteronMom[1] = mcparticleDaughter.py(); - dauDeuteronMom[2] = mcparticleDaughter.pz(); - if (mcPartIndices[mcparticleDaughter.globalIndex()] != -1) { - auto trackDeuteron = tracks.rawIteratorAt(mcPartIndices[mcparticleDaughter.globalIndex()]); - dauDeuteronTrackR = trackDeuteron.x(); - } - } - } - if (mcparticle.pdgCode() == 1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 3.5); - registry.fill(HIST("hMcHypertritonCounter"), 4.5); - } - if (mcparticle.pdgCode() == -1010010030) { - registry.fill(HIST("hMcHypertritonCounter"), 3.5); - registry.fill(HIST("hMcHypertritonCounter"), 5.5); - } - double hypertritonMCMass = RecoDecay::m(std::array{std::array{dauProtonMom[0], dauProtonMom[1], dauProtonMom[2]}, std::array{dauPionMom[0], dauPionMom[1], dauPionMom[2]}, std::array{dauDeuteronMom[0], dauDeuteronMom[1], dauDeuteronMom[2]}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); - registry.fill(HIST("hMcRecoInvMass"), hypertritonMCMass); - - if (hypertritonMCMass > 2.990 && hypertritonMCMass < 2.993) { - MClifetime = RecoDecay::sqrtSumOfSquares(dauDeuteronPos[0] - mcparticle.vx(), dauDeuteronPos[1] - mcparticle.vy(), dauDeuteronPos[2] - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - registry.fill(HIST("h3dMCDecayedHypertriton"), mcparticle.y(), mcparticle.pt(), MClifetime); - - double diffTrackR = dauDeuteronTrackR - std::min(dauPionTrackR, dauProtonTrackR); - registry.fill(HIST("hDiffDaughterR"), diffTrackR); - - // int daughterPionCount = 0; - // for (auto& mcparticleDaughter : mcparticle.daughters_as()) { - // if (std::abs(mcparticleDaughter.pdgCode()) == 211) { - // daughterPionCount++; - // } - // } - - // Counter for hypertriton N_gen - if (std::abs(mcparticle.y()) < 1) { - registry.fill(HIST("hMcHypertritonCounter"), 6.5); - if (MClifetime < 40) { - registry.fill(HIST("hMcHypertritonCounter"), 7.5); - if (mcparticle.pt() > 1 && mcparticle.pt() < 10) { - registry.fill(HIST("hMcHypertritonCounter"), 8.5); - } - } - } - } - } - } - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx b/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx deleted file mode 100644 index b8aeb1d34c3..00000000000 --- a/PWGLF/Tasks/Nuspex/hypertriton3bodyanalysis.cxx +++ /dev/null @@ -1,797 +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 hypertriton3bodyanalysis.cxx -/// \brief Standard analysis workflow for hypertriton 3-body decay -/// \author Yuanzhe Wang - -#include -#include -#include -#include -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -// #include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/Vtx3BodyTables.h" -#include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" -#include "CommonConstants/PhysicsConstants.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using FullTracksExtIU = soa::Join; -// using FullTracksExtIU = soa::Join; // For TOF PID check -using MCLabeledTracksIU = soa::Join; - -struct hypertriton3bodyQa { - // Basic checks - HistogramRegistry registry{ - "registry", - { - {"hVtxRadius", "hVtxRadius", {HistType::kTH1F, {{1000, 0.0f, 100.0f, "cm"}}}}, - {"hVtxCosPA", "hVtxCosPA", {HistType::kTH1F, {{1000, 0.9f, 1.0f}}}}, - {"hPtProton", "hPtProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtPionMinus", "hPtPionMinus", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtDeuteron", "hPtDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtPionPlus", "hPtPionPlus", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f}}}}, - {"hDCAXYProtonToPV", "hDCAXYProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYPionToPV", "hDCAXYPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYDeuteronToPV", "hDCAXYDeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAProtonToPV", "hDCAProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAPionToPV", "hDCAPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCADeuteronToPV", "hDCADeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hProtonTPCNcls", "hProtonTPCNcls", {HistType::kTH1F, {{300, 0, 300, "TPC cluster"}}}}, - {"hPionTPCNcls", "hPionTPCNcls", {HistType::kTH1F, {{300, 0, 300, "TPC cluster"}}}}, - {"hDeuteronTPCNcls", "hDeuteronTPCNcls", {HistType::kTH1F, {{300, 0, 300, "TPC cluster"}}}}, - {"hDCAVtxDau", "hDCAVtxDau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, - {"hVtxPt", "hVtxPt", {HistType::kTH1F, {{200, 0.0f, 10.0f, "p_{T}"}}}}, - {"hTOFPIDDeuteron", "hTOFPIDDeuteron", {HistType::kTH1F, {{2000, -100.0f, 100.0f}}}}, - {"hDeuTOFNsigma", "Deuteron TOF Nsigma distribution", {HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {2000, -100, 100, "TOF n#sigma"}}}}, - {"hDeuTOFNsigmaWithTPC", "Deuteron TOF Nsigma distribution", {HistType::kTH2F, {{1200, -6, 6, "#it{p} (GeV/#it{c})"}, {1000, -100, 100, "TOF n#sigma"}}}}, - }, - }; - - void init(InitContext const&) - { - AxisSpec massAxis = {120, 2.9f, 3.2f, "Inv. Mass (GeV/c^{2})"}; - registry.add("hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {massAxis}}); - registry.add("hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {massAxis}}); - // Check for selection criteria - registry.add("hDiffRVtxProton", "hDiffRVtxProton", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of proton - registry.add("hDiffRVtxPion", "hDiffRVtxPion", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of pion - registry.add("hDiffRVtxDeuteron", "hDiffRVtxDeuteron", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of deuteron - registry.add("hDiffDaughterR", "hDiffDaughterR", HistType::kTH1F, {{10000, -100, 100}}); // difference between minR of pion&proton and R of deuteron(bachelor) - } - - void process(aod::Collision const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, FullTracksExtIU const& /*tracks*/) - { - for (const auto& vtx : vtx3bodydatas) { - auto track0 = vtx.track0_as(); - auto track1 = vtx.track1_as(); - auto track2 = vtx.track2_as(); - - registry.fill(HIST("hVtxRadius"), vtx.vtxradius()); - registry.fill(HIST("hVtxCosPA"), vtx.vtxcosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("hDCAVtxDau"), vtx.dcaVtxdaughters()); - registry.fill(HIST("hVtxPt"), vtx.pt()); - registry.fill(HIST("hMassHypertriton"), vtx.mHypertriton()); - registry.fill(HIST("hMassAntiHypertriton"), vtx.mAntiHypertriton()); - if (std::abs(track2.tpcNSigmaDe()) < 5) { - registry.fill(HIST("hDeuTOFNsigmaWithTPC"), track2.tpcInnerParam() * track2.sign(), vtx.tofNSigmaBachDe()); - } - if (track2.sign() > 0) { - registry.fill(HIST("hPtProton"), track0.pt()); - registry.fill(HIST("hPtPionMinus"), track1.pt()); - registry.fill(HIST("hPtDeuteron"), track2.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), vtx.dcaXYtrack0topv()); - registry.fill(HIST("hDCAXYPionToPV"), vtx.dcaXYtrack1topv()); - registry.fill(HIST("hDCAProtonToPV"), vtx.dcatrack0topv()); - registry.fill(HIST("hDCAPionToPV"), vtx.dcatrack1topv()); - registry.fill(HIST("hProtonTPCNcls"), track0.tpcNClsCrossedRows()); - registry.fill(HIST("hPionTPCNcls"), track1.tpcNClsCrossedRows()); - registry.fill(HIST("hDiffRVtxProton"), track0.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), track1.x() - vtx.vtxradius()); - } else { - registry.fill(HIST("hPtPionPlus"), track0.pt()); - registry.fill(HIST("hPtAntiProton"), track1.pt()); - registry.fill(HIST("hPtAntiDeuteron"), track2.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), vtx.dcaXYtrack1topv()); - registry.fill(HIST("hDCAXYPionToPV"), vtx.dcaXYtrack0topv()); - registry.fill(HIST("hDCAProtonToPV"), vtx.dcatrack1topv()); - registry.fill(HIST("hDCAPionToPV"), vtx.dcatrack0topv()); - registry.fill(HIST("hProtonTPCNcls"), track1.tpcNClsCrossedRows()); - registry.fill(HIST("hPionTPCNcls"), track0.tpcNClsCrossedRows()); - registry.fill(HIST("hDiffRVtxProton"), track1.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), track0.x() - vtx.vtxradius()); - } - registry.fill(HIST("hDCAXYDeuteronToPV"), vtx.dcaXYtrack2topv()); - registry.fill(HIST("hDCADeuteronToPV"), vtx.dcatrack2topv()); - registry.fill(HIST("hDeuteronTPCNcls"), track2.tpcNClsCrossedRows()); - registry.fill(HIST("hTOFPIDDeuteron"), vtx.tofNSigmaBachDe()); - registry.fill(HIST("hDeuTOFNsigma"), track2.tpcInnerParam() * track2.sign(), vtx.tofNSigmaBachDe()); - registry.fill(HIST("hDiffRVtxDeuteron"), track2.x() - vtx.vtxradius()); - float diffTrackR = track2.x() - std::min(track0.x(), track1.x()); - registry.fill(HIST("hDiffDaughterR"), diffTrackR); - } - } -}; - -struct hypertriton3bodyAnalysis { - - Preslice perCollisionVtx3BodyDatas = o2::aod::vtx3body::collisionId; - - // Selection criteria - Configurable vtxcospa{"vtxcospa", 0.99, "Vtx CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) - Configurable dcavtxdau{"dcavtxdau", 1.0, "DCA Vtx Daughters"}; // loose cut - Configurable dcapiontopv{"dcapiontopv", .05, "DCA Pion To PV"}; - Configurable etacut{"etacut", 0.9, "etacut"}; - Configurable rapiditycut{"rapiditycut", 1, "rapiditycut"}; - Configurable tofPIDNSigmaMin{"tofPIDNSigmaMin", -5, "tofPIDNSigmaMin"}; - Configurable tofPIDNSigmaMax{"tofPIDNSigmaMax", 5, "tofPIDNSigmaMax"}; - Configurable tpcPIDNSigmaCut{"tpcPIDNSigmaCut", 5, "tpcPIDNSigmaCut"}; - Configurable event_sel8_selection{"event_sel8_selection", true, "event selection count post sel8 cut"}; - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", true, "event selection count post poZ cut"}; - Configurable lifetimecut{"lifetimecut", 40., "lifetimecut"}; // ct - Configurable minProtonPt{"minProtonPt", 0.3, "minProtonPt"}; - Configurable maxProtonPt{"maxProtonPt", 5, "maxProtonPt"}; - Configurable minPionPt{"minPionPt", 0.1, "minPionPt"}; - Configurable maxPionPt{"maxPionPt", 1.2, "maxPionPt"}; - Configurable minDeuteronPt{"minDeuteronPt", 0.6, "minDeuteronPt"}; - Configurable maxDeuteronPt{"maxDeuteronPt", 10, "maxDeuteronPt"}; - Configurable minDeuteronPUseTOF{"minDeuteronPUseTOF", 1, "minDeuteronPt Enable TOF PID"}; - Configurable h3LMassLowerlimit{"h3LMassLowerlimit", 2.96, "Hypertriton mass lower limit"}; - Configurable h3LMassUpperlimit{"h3LMassUpperlimit", 3.04, "Hypertriton mass upper limit"}; - Configurable mintpcNClsproton{"mintpcNClsproton", 90, "min tpc Nclusters for proton"}; - Configurable mintpcNClspion{"mintpcNClspion", 70, "min tpc Nclusters for pion"}; - Configurable mintpcNClsdeuteron{"mintpcNClsdeuteron", 100, "min tpc Nclusters for deuteron"}; - - Configurable mcsigma{"mcsigma", 0.0015, "sigma of mc invariant mass fit"}; // obtained from MC - Configurable bachelorPdgCode{"bachelorPdgCode", 1000010020, "pdgCode of bachelor daughter"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother track"}; - - // 3sigma region for Dalitz plot - float lowersignallimit = o2::constants::physics::MassHyperTriton - 3 * mcsigma; - float uppersignallimit = o2::constants::physics::MassHyperTriton + 3 * mcsigma; - - HistogramRegistry registry{ - "registry", - { - {"hEventCounter", "hEventCounter", {HistType::kTH1F, {{4, 0.0f, 4.0f}}}}, - {"hCandidatesCounter", "hCandidatesCounter", {HistType::kTH1F, {{12, 0.0f, 12.0f}}}}, - {"hMassHypertriton", "hMassHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hMassAntiHypertriton", "hMassAntiHypertriton", {HistType::kTH1F, {{80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hMassHypertritonTotal", "hMassHypertritonTotal", {HistType::kTH1F, {{300, 2.9f, 3.2f, "Inv. Mass (GeV/c^{2})"}}}}, - {"hPtProton", "hPtProton", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtPionMinus", "hPtPionMinus", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtDeuteron", "hPtDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtAntiProton", "hPtAntiProton", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtPionPlus", "hPtPionPlus", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hPtAntiDeuteron", "hPtAntiDeuteron", {HistType::kTH1F, {{200, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}}}}, - {"hDCAXYProtonToPV", "hDCAXYProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYPionToPV", "hDCAXYPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAXYDeuteronToPV", "hDCAXYDeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAProtonToPV", "hDCAProtonToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCAPionToPV", "hDCAPionToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hDCADeuteronToPV", "hDCADeuteronToPV", {HistType::kTH1F, {{1000, -10.0f, 10.0f, "cm"}}}}, - {"hProtonTPCNcls", "hProtonTPCNcls", {HistType::kTH1F, {{180, 0, 180, "TPC cluster"}}}}, - {"hPionTPCNcls", "hPionTPCNcls", {HistType::kTH1F, {{180, 0, 180, "TPC cluster"}}}}, - {"hDeuteronTPCNcls", "hDeuteronTPCNcls", {HistType::kTH1F, {{180, 0, 180, "TPC cluster"}}}}, - {"hVtxCosPA", "hVtxCosPA", {HistType::kTH1F, {{1000, 0.9f, 1.0f}}}}, - {"hDCAVtxDau", "hDCAVtxDau", {HistType::kTH1F, {{1000, 0.0f, 10.0f, "cm^{2}"}}}}, - {"hTOFPIDDeuteron", "hTOFPIDDeuteron", {HistType::kTH1F, {{2000, -100.0f, 100.0f}}}}, - {"hTPCPIDProton", "hTPCPIDProton", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTPCPIDPion", "hTPCPIDPion", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hTPCPIDDeuteron", "hTPCPIDDeuteron", {HistType::kTH1F, {{120, -6.0f, 6.0f}}}}, - {"hProtonTPCBB", "hProtonTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hPionTPCBB", "hPionTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hDeuteronTPCBB", "hDeuteronTPCBB", {HistType::kTH2F, {{160, -8.0f, 8.0f, "p/z(GeV/c)"}, {200, 0.0f, 1000.0f, "TPCSignal"}}}}, - {"hProtonTPCVsPt", "hProtonTPCVsPt", {HistType::kTH2F, {{50, 0.0f, 5.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hPionTPCVsPt", "hPionTPCVsPt", {HistType::kTH2F, {{20, 0.0f, 2.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTPCVsPt", "hDeuteronTPCVsPt", {HistType::kTH2F, {{80, 0.0f, 8.0f, "#it{p}_{T} (GeV/c)"}, {120, -6.0f, 6.0f, "TPC n#sigma"}}}}, - {"hDeuteronTOFVsPBeforeTOFCut", "hDeuteronTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAfterTOFCut", "hDeuteronTOFVsPAfterTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - - {"hDalitz", "hDalitz", {HistType::kTH2F, {{120, 7.85, 8.45, "M^{2}(dp) (GeV^{2}/c^{4})"}, {60, 1.1, 1.4, "M^{2}(p#pi) (GeV^{2}/c^{4})"}}}}, - {"h3dMassHypertriton", "h3dMassHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"h3dMassAntiHypertriton", "h3dMassAntiHypertriton", {HistType::kTH3F, {{20, 0.0f, 100.0f, "Cent (%)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - {"h3dTotalHypertriton", "h3dTotalHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - - {"hDeuteronTOFVsPBeforeTOFCutSig", "hDeuteronTOFVsPBeforeTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronTOFVsPAfterTOFCutSig", "hDeuteronTOFVsPAfterTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"h3dTotalTrueHypertriton", "h3dTotalTrueHypertriton", {HistType::kTH3F, {{50, 0, 50, "ct(cm)"}, {100, 0.0f, 10.0f, "#it{p}_{T} (GeV/c)"}, {80, 2.96f, 3.04f, "Inv. Mass (GeV/c^{2})"}}}}, - // For TOF PID check - /*{"hDeuteronDefaultTOFVsPBeforeTOFCut", "hDeuteronDefaultTOFVsPBeforeTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronDefaultTOFVsPAtferTOFCut", "hDeuteronDefaultTOFVsPAtferTOFCut", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronDefaultTOFVsPBeforeTOFCutSig", "hDeuteronDefaultTOFVsPBeforeTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}}, - {"hDeuteronDefaultTOFVsPAfterTOFCutSig", "hDeuteronDefaultTOFVsPAfterTOFCutSig", {HistType::kTH2F, {{40, -10.0f, 10.0f, "p/z (GeV/c)"}, {40, -10.0f, 10.0f, "TOF n#sigma"}}}},*/ - }, - }; - - //------------------------------------------------------------------ - // Fill stats histograms - enum vtxstep { kCandAll = 0, - kCandDauEta, - kCandDauPt, - kCandTPCNcls, - kCandTPCPID, - kCandTOFPID, - kCandDcaToPV, - kCandRapidity, - kCandct, - kCandCosPA, - kCandDcaDau, - kCandInvMass, - kNCandSteps }; - - struct { - std::array candstats; - std::array truecandstats; - } statisticsRegistry; - - void resetHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - statisticsRegistry.candstats[ii] = 0; - statisticsRegistry.truecandstats[ii] = 0; - } - } - void FillCandCounter(int kn, bool istrue = false) - { - statisticsRegistry.candstats[kn]++; - if (istrue) { - statisticsRegistry.truecandstats[kn]++; - } - } - void fillHistos() - { - for (int ii = 0; ii < kNCandSteps; ii++) { - registry.fill(HIST("hCandidatesCounter"), ii, statisticsRegistry.candstats[ii]); - if (doprocessMC == true) { - registry.fill(HIST("hTrueHypertritonCounter"), ii, statisticsRegistry.truecandstats[ii]); - } - } - } - - ConfigurableAxis dcaBinning{"dca-binning", {200, 0.0f, 1.0f}, ""}; - ConfigurableAxis ptBinning{"pt-binning", {200, 0.0f, 10.0f}, ""}; - - void init(InitContext const&) - { - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(1, "total"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(2, "sel8"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(3, "vertexZ"); - registry.get(HIST("hEventCounter"))->GetXaxis()->SetBinLabel(4, "has Candidate"); - - if (doprocessMC == true) { - registry.add("hTrueHypertritonCounter", "hTrueHypertritonCounter", HistType::kTH1F, {{12, 0.0f, 12.0f}}); - auto hGeneratedHypertritonCounter = registry.add("hGeneratedHypertritonCounter", "hGeneratedHypertritonCounter", HistType::kTH1F, {{2, 0.0f, 2.0f}}); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(1, "Total"); - hGeneratedHypertritonCounter->GetXaxis()->SetBinLabel(2, "3-body decay"); - registry.add("hPtGeneratedHypertriton", "hPtGeneratedHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedHypertriton", "hctGeneratedHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedHypertriton", "hEtaGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedHypertriton", "hRapidityGeneratedHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hPtGeneratedAntiHypertriton", "hPtGeneratedAntiHypertriton", HistType::kTH1F, {{200, 0.0f, 10.0f}}); - registry.add("hctGeneratedAntiHypertriton", "hctGeneratedAntiHypertriton", HistType::kTH1F, {{50, 0, 50, "ct(cm)"}}); - registry.add("hEtaGeneratedAntiHypertriton", "hEtaGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - registry.add("hRapidityGeneratedAntiHypertriton", "hRapidityGeneratedAntiHypertriton", HistType::kTH1F, {{40, -2.0f, 2.0f}}); - } - - TString CandCounterbinLabel[kNCandSteps] = {"Total", "TrackEta", "DauPt", "TPCNcls", "TPCPID", "d TOFPID", "PionDcatoPV", "MomRapidity", "Lifetime", "VtxCosPA", "VtxDcaDau", "InvMass"}; - for (int i{0}; i < kNCandSteps; i++) { - registry.get(HIST("hCandidatesCounter"))->GetXaxis()->SetBinLabel(i + 1, CandCounterbinLabel[i]); - if (doprocessMC == true) { - registry.get(HIST("hTrueHypertritonCounter"))->GetXaxis()->SetBinLabel(i + 1, CandCounterbinLabel[i]); - } - } - } - - //------------------------------------------------------------------ - // Selections for candidates - template - bool SelectCand(TCollisionTable const& collision, TCandTable const& candData, TTrackTable const& trackProton, TTrackTable const& trackPion, TTrackTable const& trackDeuteron, bool isMatter, bool isTrueCand = false, double MClifetime = -1, double lPt = -1) - { - FillCandCounter(kCandAll, isTrueCand); - - // Selection on daughters - if (std::abs(trackProton.eta()) > etacut || std::abs(trackPion.eta()) > etacut || std::abs(trackDeuteron.eta()) > etacut) { - return false; - } - FillCandCounter(kCandDauEta, isTrueCand); - - if (trackProton.pt() < minProtonPt || trackProton.pt() > maxProtonPt || trackPion.pt() < minPionPt || trackPion.pt() > maxPionPt || trackDeuteron.pt() < minDeuteronPt || trackDeuteron.pt() > maxDeuteronPt) { - return false; - } - FillCandCounter(kCandDauPt, isTrueCand); - - if (trackProton.tpcNClsFound() < mintpcNClsproton || trackPion.tpcNClsFound() < mintpcNClspion || trackDeuteron.tpcNClsFound() < mintpcNClsdeuteron) { - return false; - } - FillCandCounter(kCandTPCNcls, isTrueCand); - - if (std::abs(trackProton.tpcNSigmaPr()) > tpcPIDNSigmaCut || std::abs(trackPion.tpcNSigmaPi()) > tpcPIDNSigmaCut || std::abs(trackDeuteron.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - return false; - } - FillCandCounter(kCandTPCPID, isTrueCand); - - // registry.fill(HIST("hDeuteronDefaultTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - if (isTrueCand) { - // registry.fill(HIST("hDeuteronDefaultTOFVsPBeforeTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPBeforeTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - } - if ((candData.tofNSigmaBachDe() < tofPIDNSigmaMin || candData.tofNSigmaBachDe() > tofPIDNSigmaMax) && trackDeuteron.p() > minDeuteronPUseTOF) { - return false; - } - FillCandCounter(kCandTOFPID, isTrueCand); - // registry.fill(HIST("hDeuteronDefaultTOFVsPAtferTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPAfterTOFCut"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - if (isTrueCand) { - // registry.fill(HIST("hDeuteronDefaultTOFVsPAfterTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tofNSigmaDe()); - registry.fill(HIST("hDeuteronTOFVsPAfterTOFCutSig"), trackDeuteron.sign() * trackDeuteron.p(), candData.tofNSigmaBachDe()); - } - - double dcapion = isMatter ? candData.dcatrack1topv() : candData.dcatrack0topv(); - if (std::abs(dcapion) < dcapiontopv) { - return false; - } - FillCandCounter(kCandDcaToPV, isTrueCand); - - // Selection on candidate hypertriton - if (std::abs(candData.yHypertriton()) > rapiditycut) { - return false; - } - FillCandCounter(kCandRapidity, isTrueCand); - - double ct = candData.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassHyperTriton; - if (ct > lifetimecut) { - return false; - } - FillCandCounter(kCandct, isTrueCand); - - double cospa = candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ()); - if (cospa < vtxcospa) { - return false; - } - FillCandCounter(kCandCosPA, isTrueCand); - - if (candData.dcaVtxdaughters() > dcavtxdau) { - return false; - } - FillCandCounter(kCandDcaDau, isTrueCand); - - if ((isMatter && candData.mHypertriton() > h3LMassLowerlimit && candData.mHypertriton() < h3LMassUpperlimit)) { - // Hypertriton - registry.fill(HIST("hPtProton"), trackProton.pt()); - registry.fill(HIST("hPtPionMinus"), trackPion.pt()); - registry.fill(HIST("hPtDeuteron"), trackDeuteron.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack0topv()); - registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack1topv()); - registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack0topv()); - registry.fill(HIST("hDCAPionToPV"), candData.dcatrack1topv()); - - registry.fill(HIST("hMassHypertriton"), candData.mHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mHypertriton()); - registry.fill(HIST("h3dMassHypertriton"), 0., candData.pt(), candData.mHypertriton()); // collision.centV0M() instead of 0. once available - registry.fill(HIST("h3dTotalHypertriton"), ct, candData.pt(), candData.mHypertriton()); - if (candData.mHypertriton() > lowersignallimit && candData.mHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}, std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - if (isTrueCand) { - registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, candData.mHypertriton()); - } - } else if ((!isMatter && candData.mAntiHypertriton() > h3LMassLowerlimit && candData.mAntiHypertriton() < h3LMassUpperlimit)) { - // AntiHypertriton - registry.fill(HIST("hPtAntiProton"), trackProton.pt()); - registry.fill(HIST("hPtPionPlus"), trackPion.pt()); - registry.fill(HIST("hPtAntiDeuteron"), trackDeuteron.pt()); - registry.fill(HIST("hDCAXYProtonToPV"), candData.dcaXYtrack1topv()); - registry.fill(HIST("hDCAXYPionToPV"), candData.dcaXYtrack0topv()); - registry.fill(HIST("hDCAProtonToPV"), candData.dcatrack1topv()); - registry.fill(HIST("hDCAPionToPV"), candData.dcatrack0topv()); - - registry.fill(HIST("hMassAntiHypertriton"), candData.mAntiHypertriton()); - registry.fill(HIST("hMassHypertritonTotal"), candData.mAntiHypertriton()); - registry.fill(HIST("h3dMassAntiHypertriton"), 0., candData.pt(), candData.mAntiHypertriton()); // collision.centV0M() instead of 0. once available - registry.fill(HIST("h3dTotalHypertriton"), ct, candData.pt(), candData.mAntiHypertriton()); - if (candData.mAntiHypertriton() > lowersignallimit && candData.mAntiHypertriton() < uppersignallimit) { - registry.fill(HIST("hDalitz"), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack2(), candData.pytrack2(), candData.pztrack2()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassDeuteron}), RecoDecay::m2(std::array{std::array{candData.pxtrack1(), candData.pytrack1(), candData.pztrack1()}, std::array{candData.pxtrack0(), candData.pytrack0(), candData.pztrack0()}}, std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged})); - } - if (isTrueCand) { - registry.fill(HIST("h3dTotalTrueHypertriton"), MClifetime, lPt, candData.mHypertriton()); - } - } else { - return false; - } - - FillCandCounter(kCandInvMass, isTrueCand); - - registry.fill(HIST("hDCAXYDeuteronToPV"), candData.dcaXYtrack2topv()); - registry.fill(HIST("hDCADeuteronToPV"), candData.dcatrack2topv()); - registry.fill(HIST("hVtxCosPA"), candData.vtxcosPA(collision.posX(), collision.posY(), collision.posZ())); - registry.fill(HIST("hDCAVtxDau"), candData.dcaVtxdaughters()); - registry.fill(HIST("hProtonTPCNcls"), trackProton.tpcNClsCrossedRows()); - registry.fill(HIST("hPionTPCNcls"), trackPion.tpcNClsCrossedRows()); - registry.fill(HIST("hDeuteronTPCNcls"), trackDeuteron.tpcNClsCrossedRows()); - registry.fill(HIST("hTPCPIDProton"), trackProton.tpcNSigmaPr()); - registry.fill(HIST("hTPCPIDPion"), trackPion.tpcNSigmaPi()); - registry.fill(HIST("hTPCPIDDeuteron"), trackDeuteron.tpcNSigmaDe()); - registry.fill(HIST("hProtonTPCBB"), trackProton.sign() * trackProton.p(), trackProton.tpcSignal()); - registry.fill(HIST("hPionTPCBB"), trackPion.sign() * trackPion.p(), trackPion.tpcSignal()); - registry.fill(HIST("hDeuteronTPCBB"), trackDeuteron.sign() * trackDeuteron.p(), trackDeuteron.tpcSignal()); - registry.fill(HIST("hProtonTPCVsPt"), trackProton.pt(), trackProton.tpcNSigmaPr()); - registry.fill(HIST("hPionTPCVsPt"), trackProton.pt(), trackPion.tpcNSigmaPi()); - registry.fill(HIST("hDeuteronTPCVsPt"), trackDeuteron.pt(), trackDeuteron.tpcNSigmaDe()); - registry.fill(HIST("hTOFPIDDeuteron"), candData.tofNSigmaBachDe()); - - return true; - } - - //------------------------------------------------------------------ - // Analysis process for a single candidate - template - void CandidateAnalysis(TCollisionTable const& collision, TCandTable const& candData, bool& if_hasvtx, bool isTrueCand = false, double MClifetime = -1, double lPt = -1) - { - - auto track0 = candData.template track0_as(); - auto track1 = candData.template track1_as(); - auto track2 = candData.template track2_as(); - - bool isMatter = track2.sign() > 0; - - auto& trackProton = isMatter ? track0 : track1; - auto& trackPion = isMatter ? track1 : track0; - auto& trackDeuteron = track2; - - if (SelectCand(collision, candData, trackProton, trackPion, trackDeuteron, isMatter, isTrueCand, MClifetime, lPt)) { - if_hasvtx = true; - } - } - - //------------------------------------------------------------------ - // collect information for generated hypertriton (should be called after event selection) - void GetGeneratedH3LInfo(aod::McParticles const& particlesMC) - { - for (const auto& mcparticle : particlesMC) { - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - registry.fill(HIST("hGeneratedHypertritonCounter"), 0.5); - - bool haveProton = false, havePionPlus = false, haveDeuteron = false; - bool haveAntiProton = false, havePionMinus = false, haveAntiDeuteron = false; - double MClifetime = -1; - for (const auto& mcparticleDaughter : mcparticle.template daughters_as()) { - if (mcparticleDaughter.pdgCode() == 2212) - haveProton = true; - if (mcparticleDaughter.pdgCode() == -2212) - haveAntiProton = true; - if (mcparticleDaughter.pdgCode() == 211) - havePionPlus = true; - if (mcparticleDaughter.pdgCode() == -211) - havePionMinus = true; - if (mcparticleDaughter.pdgCode() == bachelorPdgCode) { - haveDeuteron = true; - MClifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - if (mcparticleDaughter.pdgCode() == -bachelorPdgCode) { - haveAntiDeuteron = true; - MClifetime = RecoDecay::sqrtSumOfSquares(mcparticleDaughter.vx() - mcparticle.vx(), mcparticleDaughter.vy() - mcparticle.vy(), mcparticleDaughter.vz() - mcparticle.vz()) * o2::constants::physics::MassHyperTriton / mcparticle.p(); - } - } - if (haveProton && havePionMinus && haveDeuteron && mcparticle.pdgCode() == motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedHypertriton"), MClifetime); - registry.fill(HIST("hEtaGeneratedHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedHypertriton"), mcparticle.y()); - } else if (haveAntiProton && havePionPlus && haveAntiDeuteron && mcparticle.pdgCode() == -motherPdgCode) { - registry.fill(HIST("hGeneratedHypertritonCounter"), 1.5); - registry.fill(HIST("hPtGeneratedAntiHypertriton"), mcparticle.pt()); - registry.fill(HIST("hctGeneratedAntiHypertriton"), MClifetime); - registry.fill(HIST("hEtaGeneratedAntiHypertriton"), mcparticle.eta()); - registry.fill(HIST("hRapidityGeneratedAntiHypertriton"), mcparticle.y()); - } - } - } - - //------------------------------------------------------------------ - // process real data analysis - void processData(soa::Join::iterator const& collision, aod::Vtx3BodyDatas const& vtx3bodydatas, FullTracksExtIU const& /*tracks*/) - { - registry.fill(HIST("hEventCounter"), 0.5); - if (event_sel8_selection && !collision.sel8()) { - return; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - return; - } - registry.fill(HIST("hEventCounter"), 2.5); - - bool if_hasvtx = false; - - for (const auto& vtx : vtx3bodydatas) { - CandidateAnalysis(collision, vtx, if_hasvtx); - } - - if (if_hasvtx) - registry.fill(HIST("hEventCounter"), 3.5); - fillHistos(); - resetHistos(); - } - PROCESS_SWITCH(hypertriton3bodyAnalysis, processData, "Real data analysis", true); - - //------------------------------------------------------------------ - // process mc analysis - void processMC(soa::Join const& collisions, aod::Vtx3BodyDatas const& vtx3bodydatas, aod::McParticles const& particlesMC, MCLabeledTracksIU const& /*tracks*/) - { - GetGeneratedH3LInfo(particlesMC); - - for (const auto& collision : collisions) { - registry.fill(HIST("hEventCounter"), 0.5); - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - continue; - } - registry.fill(HIST("hEventCounter"), 1.5); - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - continue; - } - registry.fill(HIST("hEventCounter"), 2.5); - - bool if_hasvtx = false; - auto vtxsthiscol = vtx3bodydatas.sliceBy(perCollisionVtx3BodyDatas, collision.globalIndex()); - - for (const auto& vtx : vtxsthiscol) { - // int lLabel = -1; - int lPDG = -1; - float lPt = -1; - double MClifetime = -1; - bool isTrueCand = false; - auto track0 = vtx.track0_as(); - auto track1 = vtx.track1_as(); - auto track2 = vtx.track2_as(); - if (track0.has_mcParticle() && track1.has_mcParticle() && track2.has_mcParticle()) { - auto lMCTrack0 = track0.mcParticle_as(); - auto lMCTrack1 = track1.mcParticle_as(); - auto lMCTrack2 = track2.mcParticle_as(); - if (lMCTrack0.has_mothers() && lMCTrack1.has_mothers() && lMCTrack2.has_mothers()) { - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - // lLabel = lMother1.globalIndex(); - lPt = lMother1.pt(); - lPDG = lMother1.pdgCode(); - if ((lPDG == motherPdgCode && lMCTrack0.pdgCode() == 2212 && lMCTrack1.pdgCode() == -211 && lMCTrack2.pdgCode() == bachelorPdgCode) || - (lPDG == -motherPdgCode && lMCTrack0.pdgCode() == 211 && lMCTrack1.pdgCode() == -2212 && lMCTrack2.pdgCode() == -bachelorPdgCode)) { - isTrueCand = true; - MClifetime = RecoDecay::sqrtSumOfSquares(lMCTrack2.vx() - lMother2.vx(), lMCTrack2.vy() - lMother2.vy(), lMCTrack2.vz() - lMother2.vz()) * o2::constants::physics::MassHyperTriton / lMother2.p(); - } - } - } - } - } - } - } - - CandidateAnalysis(collision, vtx, if_hasvtx, isTrueCand, MClifetime, lPt); - } - - if (if_hasvtx) - registry.fill(HIST("hEventCounter"), 3.5); - fillHistos(); - resetHistos(); - } - } - PROCESS_SWITCH(hypertriton3bodyAnalysis, processMC, "MC analysis", false); -}; - -// check vtx3body with mclabels -struct hypertriton3bodyLabelCheck { - - Configurable mc_event_selection{"mc_event_selection", true, "mc event selection count post kIsTriggerTVX and kNoTimeFrameBorder"}; - Configurable event_posZ_selection{"event_posZ_selection", false, "event selection count post poZ cut"}; - Configurable tpcPIDNSigmaCut{"tpcPIDNSigmaCut", 5, "tpcPIDNSigmaCut"}; - Configurable motherPdgCode{"motherPdgCode", 1010010030, "pdgCode of mother track"}; - - HistogramRegistry registry{"registry", {}}; - - void init(InitContext const&) - { - if (doprocessData == false) { - auto hLabeledVtxCounter = registry.add("hLabeledVtxCounter", "hLabeledVtxCounter", HistType::kTH1F, {{3, 0.0f, 3.0f}}); - hLabeledVtxCounter->GetXaxis()->SetBinLabel(1, "Readin"); - hLabeledVtxCounter->GetXaxis()->SetBinLabel(2, "TrueMCH3L"); - hLabeledVtxCounter->GetXaxis()->SetBinLabel(3, "Nonrepetitive"); - registry.add("hMassTrueH3L", "hMassTrueH3L", HistType::kTH1F, {{80, 2.96f, 3.04f}}); - registry.add("hMassTrueH3LMatter", "hMassTrueH3LMatter", HistType::kTH1F, {{80, 2.96f, 3.04f}}); - registry.add("hMassTrueH3LAntiMatter", "hMassTrueH3LAntiMatter", HistType::kTH1F, {{80, 2.96f, 3.04f}}); - auto hPIDCounter = registry.add("hPIDCounter", "hPIDCounter", HistType::kTH1F, {{6, 0.0f, 6.0f}}); - hPIDCounter->GetXaxis()->SetBinLabel(1, "H3L Proton PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(2, "H3L Pion PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(3, "H3L Deuteron PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(4, "#bar{H3L} Proton PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(5, "#bar{H3L} Pion PID > 5"); - hPIDCounter->GetXaxis()->SetBinLabel(6, "#bar{H3L} Deuteron PID > 5"); - auto hHypertritonCounter = registry.add("hHypertritonCounter", "hHypertritonCounter", HistType::kTH1F, {{4, 0.0f, 4.0f}}); - hHypertritonCounter->GetXaxis()->SetBinLabel(1, "H3L"); - hHypertritonCounter->GetXaxis()->SetBinLabel(2, "H3L daughters pass PID"); - hHypertritonCounter->GetXaxis()->SetBinLabel(3, "#bar{H3L}"); - hHypertritonCounter->GetXaxis()->SetBinLabel(4, "#bar{H3L} daughters pass PID"); - auto hDecay3BodyCounter = registry.add("hDecay3BodyCounter", "hDecay3BodyCounter", HistType::kTH1F, {{5, 0.0f, 5.0f}}); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(1, "Total"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(2, "True H3L"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(3, "Unduplicated H3L"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(4, "Correct collision"); - hDecay3BodyCounter->GetXaxis()->SetBinLabel(5, "Same ColID for daughters"); - registry.add("hDiffRVtxProton", "hDiffRVtxProton", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of proton - registry.add("hDiffRVtxPion", "hDiffRVtxPion", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of pion - registry.add("hDiffRVtxDeuteron", "hDiffRVtxDeuteron", HistType::kTH1F, {{100, -10, 10}}); // difference between the radius of decay vertex and minR of deuteron - } - } - - struct Indexdaughters { // check duplicated paired daughters - int64_t index0; - int64_t index1; - int64_t index2; - bool operator==(const Indexdaughters& t) const - { - return (this->index0 == t.index0 && this->index1 == t.index1 && this->index2 == t.index2); - } - }; - - void processData(soa::Join::iterator const&) - { - // dummy function - } - PROCESS_SWITCH(hypertriton3bodyLabelCheck, processData, "Donot check MC label tables", true); - - void processCheckLabel(soa::Join::iterator const& collision, aod::Decay3Bodys const& decay3bodys, soa::Join const& vtx3bodydatas, MCLabeledTracksIU const& /*tracks*/, aod::McParticles const& /*particlesMC*/, aod::McCollisions const& /*mcCollisions*/) - { - // check the decay3body table - std::vector set_pair; - for (const auto& d3body : decay3bodys) { - registry.fill(HIST("hDecay3BodyCounter"), 0.5); - auto lTrack0 = d3body.track0_as(); - auto lTrack1 = d3body.track1_as(); - auto lTrack2 = d3body.track2_as(); - if (!lTrack0.has_mcParticle() || !lTrack1.has_mcParticle() || !lTrack2.has_mcParticle()) { - continue; - } - auto lMCTrack0 = lTrack0.mcParticle_as(); - auto lMCTrack1 = lTrack1.mcParticle_as(); - auto lMCTrack2 = lTrack2.mcParticle_as(); - if (!lMCTrack0.has_mothers() || !lMCTrack1.has_mothers() || !lMCTrack2.has_mothers()) { - continue; - } - - for (const auto& lMother0 : lMCTrack0.mothers_as()) { - for (const auto& lMother1 : lMCTrack1.mothers_as()) { - for (const auto& lMother2 : lMCTrack2.mothers_as()) { - if (lMother0.globalIndex() == lMother1.globalIndex() && lMother0.globalIndex() == lMother2.globalIndex()) { - registry.fill(HIST("hDecay3BodyCounter"), 1.5); - // duplicated daughters check - Indexdaughters temp = {lMCTrack0.globalIndex(), lMCTrack1.globalIndex(), lMCTrack2.globalIndex()}; - auto p = std::find(set_pair.begin(), set_pair.end(), temp); - if (p == set_pair.end()) { - set_pair.push_back(temp); - registry.fill(HIST("hDecay3BodyCounter"), 2.5); - if (lMother0.mcCollisionId() == collision.mcCollisionId()) { - registry.fill(HIST("hDecay3BodyCounter"), 3.5); - if (lTrack0.collisionId() == lTrack1.collisionId() && lTrack0.collisionId() == lTrack2.collisionId()) { - registry.fill(HIST("hDecay3BodyCounter"), 4.5); - } - } - } - } - } - } - } - } - - if (mc_event_selection && (!collision.selection_bit(aod::evsel::kIsTriggerTVX) || !collision.selection_bit(aod::evsel::kNoTimeFrameBorder))) { - return; - } - - if (event_posZ_selection && std::abs(collision.posZ()) > 10.f) { // 10cm - return; - } - - std::vector set_mothertrack; - for (const auto& vtx : vtx3bodydatas) { - registry.fill(HIST("hLabeledVtxCounter"), 0.5); - if (vtx.mcParticleId() != -1) { - auto mcparticle = vtx.mcParticle_as(); - auto lTrack0 = vtx.track0_as(); - auto lTrack1 = vtx.track1_as(); - auto lTrack2 = vtx.track2_as(); - if (std::abs(mcparticle.pdgCode()) != motherPdgCode) { - continue; - } - registry.fill(HIST("hLabeledVtxCounter"), 1.5); - registry.fill(HIST("hDiffRVtxDeuteron"), lTrack2.x() - vtx.vtxradius()); - if (mcparticle.pdgCode() > 0) { - registry.fill(HIST("hHypertritonCounter"), 0.5); - registry.fill(HIST("hMassTrueH3L"), vtx.mHypertriton()); - registry.fill(HIST("hMassTrueH3LMatter"), vtx.mHypertriton()); - registry.fill(HIST("hDiffRVtxProton"), lTrack0.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), lTrack1.x() - vtx.vtxradius()); - auto p = std::find(set_mothertrack.begin(), set_mothertrack.end(), mcparticle.globalIndex()); - if (p == set_mothertrack.end()) { - set_mothertrack.push_back(mcparticle.globalIndex()); - registry.fill(HIST("hLabeledVtxCounter"), 2.5); - } - if (std::abs(lTrack0.tpcNSigmaPr()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 0.5); - } - if (std::abs(lTrack1.tpcNSigmaPi()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 1.5); - } - if (std::abs(lTrack2.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 2.5); - } - if (std::abs(lTrack0.tpcNSigmaPr()) < tpcPIDNSigmaCut && std::abs(lTrack1.tpcNSigmaPi()) < tpcPIDNSigmaCut && std::abs(lTrack2.tpcNSigmaDe()) < tpcPIDNSigmaCut) { - registry.fill(HIST("hHypertritonCounter"), 1.5); - } - } else { - registry.fill(HIST("hHypertritonCounter"), 2.5); - registry.fill(HIST("hMassTrueH3L"), vtx.mAntiHypertriton()); - registry.fill(HIST("hMassTrueH3LAntiMatter"), vtx.mAntiHypertriton()); - registry.fill(HIST("hDiffRVtxProton"), lTrack1.x() - vtx.vtxradius()); - registry.fill(HIST("hDiffRVtxPion"), lTrack0.x() - vtx.vtxradius()); - auto p = std::find(set_mothertrack.begin(), set_mothertrack.end(), mcparticle.globalIndex()); - if (p == set_mothertrack.end()) { - set_mothertrack.push_back(mcparticle.globalIndex()); - registry.fill(HIST("hLabeledVtxCounter"), 2.5); - } - if (std::abs(lTrack0.tpcNSigmaPi()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 4.5); - } - if (std::abs(lTrack1.tpcNSigmaPr()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 3.5); - } - if (std::abs(lTrack2.tpcNSigmaDe()) > tpcPIDNSigmaCut) { - registry.fill(HIST("hPIDCounter"), 5.5); - } - if (std::abs(lTrack0.tpcNSigmaPi()) < tpcPIDNSigmaCut && std::abs(lTrack1.tpcNSigmaPr()) < tpcPIDNSigmaCut && std::abs(lTrack2.tpcNSigmaDe()) < tpcPIDNSigmaCut) { - registry.fill(HIST("hHypertritonCounter"), 3.5); - } - } - } - } - } - PROCESS_SWITCH(hypertriton3bodyLabelCheck, processCheckLabel, "Check MC label tables", false); -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - adaptAnalysisTask(cfgc), - }; -} diff --git a/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx b/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx index dc4e70c2ee3..2d959f9488d 100644 --- a/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx +++ b/PWGLF/Tasks/Nuspex/nucleiFromHypertritonMap.cxx @@ -79,17 +79,17 @@ struct nucleiFromHypertritonMap { void init(InitContext const&) { - registryMC.add("hypertritonPtgen", "hypertritonPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); + registryMC.add("hypertritonPtGen", "hypertritonPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); if (saveHelium) { registryMC.add("he3SecPtRec_from_hypertriton", "he3SecPtRec_from_hypertriton", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); - registryMC.add("hyperHe4Ptgen", "hyperHe4PtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); + registryMC.add("hyperHe4PtGen", "hyperHe4PtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("he3SecPtRec_from_hyperHe4", "he3SecPtRec_from_hyperHe4", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("he3PtRec", "he3PtRec", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("he3PtGen", "he3PtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); } else { registryMC.add("deutSecPtRec_from_hypertriton", "deutSecPtRec_from_hypertriton", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); registryMC.add("deutPtRec", "deutPtRec", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); - registryMC.add("deutPtgen", "deutPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); + registryMC.add("deutPtGen", "deutPtGen", HistType::kTH1F, {{nbin_pt, min_pt, max_pt, "p_{T} (GeV/c)"}}); } } @@ -107,21 +107,21 @@ struct nucleiFromHypertritonMap { if (mcparticle.pdgCode() == AntiHypertritonPDG) { for (auto& daughter : mcparticle.daughters_as()) { if (daughter.pdgCode() == selectedPDG) { - registryMC.fill(HIST("hypertritonPtgen"), mcparticle.pt()); + registryMC.fill(HIST("hypertritonPtGen"), mcparticle.pt()); } } } if (mcparticle.pdgCode() == AntiHyperHelium4PDG) { for (auto& daughter : mcparticle.daughters_as()) { if (daughter.pdgCode() == selectedPDG) { - registryMC.fill(HIST("hyperHe4Ptgen"), mcparticle.pt()); + registryMC.fill(HIST("hyperHe4PtGen"), mcparticle.pt()); } } } - if (mcparticle.pdgCode() == AntihePDG) { + if (mcparticle.pdgCode() == AntihePDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("he3PtGen"), mcparticle.pt()); } - if (mcparticle.pdgCode() == AntideuteronPDG) { + if (mcparticle.pdgCode() == AntideuteronPDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("deutPtGen"), mcparticle.pt()); } } @@ -148,10 +148,10 @@ struct nucleiFromHypertritonMap { track.itsChi2NCl() > 36.f) { continue; } - if (mcparticle.pdgCode() == AntideuteronPDG) { + if (mcparticle.pdgCode() == AntideuteronPDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("deutPtRec"), track.pt()); } - if (mcparticle.pdgCode() == AntihePDG) { + if (mcparticle.pdgCode() == AntihePDG && mcparticle.isPhysicalPrimary()) { registryMC.fill(HIST("he3PtRec"), 2 * track.pt()); } diff --git a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx index 090f57589bc..d69d0b97b93 100644 --- a/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx +++ b/PWGLF/Tasks/Nuspex/nucleitpcpbpb.cxx @@ -8,46 +8,48 @@ // In applying this license CERN does 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 nucleitpcpbpb.cxx +/// \brief nuclei analysis +/// \note under work /// -/// \brief This task use global tracks and used for primary selection analysis using TPC detector. -/// It currently contemplates 6 particle types: -/// pion, Proton, Deuteron, Triton, Helium3, Alpha -/// -/// \author Jaideep Tanwar -/// \since Jan. 20, 2025 -/// -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" +/// \author Jaideep Tanwar , Panjab University + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/Core/PID/TPCPIDResponse.h" #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" -#include "Common/Core/PID/TPCPIDResponse.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/CollisionAssociationTables.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsTPC/BetheBlochAleph.h" -#include "DataFormatsParameters/GRPObject.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "DataFormatsParameters/GRPMagField.h" +#include "DataFormatsParameters/GRPObject.h" +#include "DataFormatsTPC/BetheBlochAleph.h" #include "DetectorsBase/GeometryManager.h" #include "DetectorsBase/Propagator.h" -#include "CCDB/BasicCCDBManager.h" -#include "DCAFitter/DCAFitterN.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 using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using CollisionsFull = soa::Join; -using TracksFull = soa::Join; +using TracksFull = soa::Join; +using CollisionsFullMC = soa::Join; //--------------------------------------------------------------------------------------------------------------------------------- namespace { @@ -58,22 +60,22 @@ static const std::vector particleMasses{o2::constants::physics::MassPion 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[nParticles][nBetheParams]{ +constexpr double kBetheBlochDefault[nParticles][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 = 16; -static const std::vector trackPIDsettingsNames{"useBBparams", "minITSnCls", "minTPCnCls", "maxTPCchi2", "maxITSchi2", "minRigidity", "maxRigidity", "maxTPCnSigma", "TOFrequiredabove", "minTOFmass", "maxTOFmass", "maxDcaXY", "maxDcaZ", "minITSclsSize", "maxITSclsSize", "minTPCnClsCrossedRows"}; -constexpr double trackPIDsettings[nParticles][nTrkSettings]{ - {0, 0, 60, 3.0, 100, 0.15, 1.2, 2.5, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 2.5, 100, 0.20, 4.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 5.0, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 5.0, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 75, 1.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}, - {1, 0, 70, 1.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70}}; +const int nTrkSettings = 19; +static const std::vector trackPIDsettingsNames{"useBBparams", "minITSnCls", "minITSnClscos", "minTPCnCls", "maxTPCchi2", "minTPCchi2", "maxITSchi2", "minRigidity", "maxRigidity", "maxTPCnSigma", "TOFrequiredabove", "minTOFmass", "maxTOFmass", "maxDcaXY", "maxDcaZ", "minITSclsSize", "maxITSclsSize", "minTPCnClsCrossedRows", "minReqClusterITSib"}; +constexpr double kTrackPIDSettings[nParticles][nTrkSettings]{ + {0, 0, 4, 60, 4.0, 0.5, 100, 0.15, 1.2, 2.5, -1, 0, 100, 2., 2., 0., 1000, 70, 1}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.20, 4.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70, 1}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70, 1}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.50, 5.0, 3.0, -1, 0, 100, 2., 2., 0., 1000, 70, 1}, + {1, 0, 4, 75, 4.0, 0.5, 100, 0.50, 5.0, 5.0, -1, 0, 100, 2., 2., 0., 1000, 70, 1}, + {1, 0, 4, 70, 4.0, 0.5, 100, 0.50, 5.0, 5.0, -1, 0, 100, 2., 2., 0., 1000, 70, 1}}; struct PrimParticles { TString name; int pdgCode, charge; @@ -98,6 +100,7 @@ std::vector> hmass; struct NucleitpcPbPb { Preslice perCollision = aod::track_association::collisionId; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry histomc{"histomc", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; Configurable cfgDebug{"cfgDebug", 1, "debug level"}; // event Selections cuts Configurable removeITSROFrameBorder{"removeITSROFrameBorder", false, "Remove TF border"}; @@ -108,6 +111,9 @@ struct NucleitpcPbPb { Configurable cfgRigidityCorrection{"cfgRigidityCorrection", false, "apply rigidity correction"}; // Track Selection Cuts Configurable cfgCutEta{"cfgCutEta", 0.9f, "Eta range for tracks"}; + Configurable cfgetaRequire{"cfgetaRequire", true, "eta cut require"}; + Configurable cfgetaRequireMC{"cfgetaRequireMC", true, "eta cut require for generated particles"}; + Configurable cfgrapidityRequireMC{"cfgrapidityRequireMC", true, "rapidity cut require for generated particles"}; Configurable cfgUsePVcontributors{"cfgUsePVcontributors", true, "use tracks that are PV contibutors"}; Configurable cfgITSrequire{"cfgITSrequire", true, "Additional cut on ITS require"}; Configurable cfgTPCrequire{"cfgTPCrequire", true, "Additional cut on TPC require"}; @@ -117,9 +123,14 @@ struct NucleitpcPbPb { Configurable cfgTPCNClsfoundRequire{"cfgTPCNClsfoundRequire", true, "Require TPCNClsfound Cut"}; Configurable cfgTPCNClsCrossedRowsRequire{"cfgTPCNClsCrossedRowsRequire", true, "Require TPCNClsCrossedRows Cut"}; Configurable cfgmaxTPCchi2Require{"cfgmaxTPCchi2Require", true, "Require maxTPCchi2 Cut"}; - Configurable cfgminITSnClsRequire{"cfgminITSnClsRequire", true, "Require minITSnCls Cut"}; + Configurable cfgminTPCchi2Require{"cfgminTPCchi2Require", true, "Require minTPCchi2 Cut"}; + Configurable cfgminITSnClsRequire{"cfgminITSnClsRequire", false, "Require minITSnCls Cut"}; + Configurable cfgmccorrectionhe4Require{"cfgmccorrectionhe4Require", true, "MC correction for pp he4 particle"}; + Configurable cfgminITSnClscosRequire{"cfgminITSnClscosRequire", true, "Require minITSnCls / cosh(eta) Cut"}; + Configurable cfgminReqClusterITSibRequire{"cfgminReqClusterITSibRequire", true, " Require min number of clusters required in ITS inner barrel"}; Configurable cfgmaxITSchi2Require{"cfgmaxITSchi2Require", true, "Require maxITSchi2 Cut"}; Configurable cfgmaxTPCnSigmaRequire{"cfgmaxTPCnSigmaRequire", true, "Require maxTPCnSigma Cut"}; + Configurable cfgmaxITSnSigmaRequire{"cfgmaxITSnSigmaRequire", true, "Require maxITSnSigma Cut for helium"}; Configurable cfgminGetMeanItsClsSizeRequire{"cfgminGetMeanItsClsSizeRequire", true, "Require minGetMeanItsClsSize Cut"}; Configurable cfgmaxGetMeanItsClsSizeRequire{"cfgmaxGetMeanItsClsSizeRequire", true, "Require maxGetMeanItsClsSize Cut"}; Configurable cfgRigidityCutRequire{"cfgRigidityCutRequire", true, "Require Rigidity Cut"}; @@ -127,18 +138,37 @@ struct NucleitpcPbPb { Configurable cfgDCAwithptRequire{"cfgDCAwithptRequire", true, "Require DCA cuts with pt dependance"}; Configurable cfgDCAnopt{"cfgDCAnopt", true, "Require DCA cuts without pt dependance"}; Configurable cfgTwicemass{"cfgTwicemass", true, "multiply mass by its charge"}; - 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 selection and PID criteria"}; - Configurable cfgFillDeDxWithoutCut{"cfgFillDeDxWithoutCut", false, "Fill without cut beth bloch"}; - Configurable cfgFillDeDxWithCut{"cfgFillDeDxWithCut", false, "Fill with cut beth bloch"}; - Configurable cfgFillnsigma{"cfgFillnsigma", true, "Fill n-sigma histograms"}; + Configurable cfgRequirebetaplot{"cfgRequirebetaplot", true, "Require beta plot"}; + Configurable cfgRequireMCposZ{"cfgRequireMCposZ", true, "Require beta plot"}; + + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {kBetheBlochDefault[0], nParticles, nBetheParams, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for light nuclei"}; + Configurable> cfgTrackPIDsettings{"cfgTrackPIDsettings", {kTrackPIDSettings[0], nParticles, nTrkSettings, particleNames, trackPIDsettingsNames}, "track selection and PID criteria"}; + Configurable cfgFillDeDxWithCut{"cfgFillDeDxWithCut", true, "Fill with cut beth bloch"}; + Configurable cfgFillnsigma{"cfgFillnsigma", false, "Fill n-sigma histograms"}; Configurable cfgFillmass{"cfgFillmass", false, "Fill mass histograms"}; Configurable centcut{"centcut", 80.0f, "centrality cut"}; Configurable cfgCutRapidity{"cfgCutRapidity", 0.5f, "Rapidity range"}; Configurable cfgZvertex{"cfgZvertex", 10, "Min Z Vertex"}; + Configurable cfgZvertexRequire{"cfgZvertexRequire", true, "Pos Z cut require"}; + Configurable cfgZvertexRequireMC{"cfgZvertexRequireMC", true, "Pos Z cut require for generated particles"}; + Configurable cfgsel8Require{"cfgsel8Require", true, "sel8 cut require"}; + Configurable cfgITSnsigma{"cfgITSnsigma", 5, "Max ITS nsigma value"}; Configurable cfgtpcNClsFound{"cfgtpcNClsFound", 100.0f, "min. no. of tpcNClsFound"}; Configurable cfgitsNCls{"cfgitsNCls", 2.0f, "min. no. of itsNCls"}; - + o2::track::TrackParametrizationWithError mTrackParCov; + // Binning configuration + ConfigurableAxis axisMagField{"axisMagField", {10, -10., 10.}, "magnetic field"}; + ConfigurableAxis axisNev{"axisNev", {3, 0., 3.}, "Number of events"}; + ConfigurableAxis axisRigidity{"axisRigidity", {4000, -10., 10.}, "#it{p}^{TPC}/#it{z}"}; + ConfigurableAxis axisdEdx{"axisdEdx", {4000, 0, 4000}, "d#it{E}/d#it{x}"}; + ConfigurableAxis axisCent{"axisCent", {100, 0, 100}, "centrality"}; + ConfigurableAxis axisVtxZ{"axisVtxZ", {120, -20, 20}, "z"}; + ConfigurableAxis axisImpt{"axisImpt", {100, 0, 20}, "impact parameter"}; + ConfigurableAxis ptAxis{"ptAxis", {200, 0, 10}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axiseta{"axiseta", {100, -1, 1}, "eta"}; + ConfigurableAxis axisrapidity{"axisrapidity", {100, -2, 2}, "rapidity"}; + ConfigurableAxis axismass{"axismass", {100, -10, 10}, "mass^{2}"}; + ConfigurableAxis nsigmaAxis{"nsigmaAxis", {160, -20, 20}, "n#sigma_{#pi^{+}}"}; // CCDB Service ccdb; Configurable bField{"bField", -999, "bz field, -999 is automatic"}; @@ -148,12 +178,15 @@ struct NucleitpcPbPb { Configurable lutPath{"lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; Configurable geoPath{"geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; Configurable pidPath{"pidPath", "", "Path to the PID response object"}; + std::vector primaryParticles; std::vector primVtx, cents; - bool collHasCandidate, collPassedEvSel; + bool collHasCandidate, collPassedEvSel, collPassedEvSelMc; int mRunNumber, occupancy; float dBz, momn; TRandom3 rand; + float he3 = 4; + float he4 = 5; //---------------------------------------------------------------------------------------------------------------- void init(InitContext const&) { @@ -167,41 +200,28 @@ struct NucleitpcPbPb { for (int i = 0; i < nParticles; i++) { // create primaryParticles primaryParticles.push_back(PrimParticles(particleNames.at(i), particlePdgCodes.at(i), particleMasses.at(i), particleCharge.at(i), cfgBetheBlochParams)); } - // define histogram axes - const AxisSpec axisMagField{10, -10., 10., "magnetic field"}; - const AxisSpec axisNev{3, 0., 3., "Number of events"}; - const AxisSpec axisRigidity{4000, -10., 10., "#it{p}^{TPC}/#it{z}"}; - const AxisSpec axisdEdx{2000, 0, 2000, "d#it{E}/d#it{x}"}; - const AxisSpec axisCent{100, 0, 100, "centrality"}; - const AxisSpec axisVtxZ{100, -20, 20, "z"}; - const AxisSpec ptAxis{200, 0, 20, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec axiseta{100, -1, 1, "eta"}; - const AxisSpec axisrapidity{100, -2, 2, "rapidity"}; - const AxisSpec axismass{100, 0, 20, "mass^{2}"}; - AxisSpec nsigmaAxis = {160, -20, 20, "n#sigma_{#pi^{+}}"}; // create histograms + if (doprocessData) { + histos.add("histMagField", "histMagField", kTH1F, {axisMagField}); + histos.add("histNev", "histNev", kTH1F, {axisNev}); + histos.add("histVtxZ", "histVtxZ", kTH1F, {axisVtxZ}); + histos.add("histCentFT0C", "histCentFT0C", kTH1F, {axisCent}); + histos.add("histCentFT0M", "histCentFT0M", kTH1F, {axisCent}); + histos.add("histCentFTOC_cut", "histCentFTOC_cut", kTH1F, {axisCent}); + } histos.add("histeta", "histeta", kTH1F, {axiseta}); - histos.add("histCentFTOC_cut", "histCentFTOC_cut", kTH1F, {axisCent}); - histos.add("Tof_signal", "Tof_signal", kTH2F, {axisRigidity, {4000, 0.2, 1.2, "#beta"}}); + histos.add("Tofsignal", "Tofsignal", kTH2F, {axisRigidity, {4000, 0.2, 1.2, "#beta"}}); histos.add("histDcaZVsPtData_particle", "dcaZ vs Pt (particle)", HistType::kTH2F, {{1000, 0, 20}, {1000, -2.5, 2.5, "dca"}}); histos.add("histDcaXYVsPtData_particle", "dcaXY vs Pt (particle)", HistType::kTH2F, {{1000, 0, 20}, {1000, -2.0, 2.0, "dca"}}); histos.add("histDcaZVsPtData_antiparticle", "dcaZ vs Pt (antiparticle)", HistType::kTH2F, {{1000, 0, 20}, {1000, -2.5, 2.5, "dca"}}); histos.add("histDcaXYVsPtData_antiparticle", "dcaXY vs Pt (antiparticle)", HistType::kTH2F, {{1000, 0, 20}, {1000, -2.0, 2.0, "dca"}}); - histos.add("histMagField", "histMagField", kTH1F, {axisMagField}); - histos.add("histNev", "histNev", kTH1F, {axisNev}); - histos.add("histVtxZ", "histVtxZ", kTH1F, {axisVtxZ}); - histos.add("histCentFT0C", "histCentFT0C", kTH1F, {axisCent}); - histos.add("histCentFT0M", "histCentFT0M", kTH1F, {axisCent}); hDeDx.resize(2 * nParticles + 2); hNsigmaPt.resize(2 * nParticles + 2); hmass.resize(2 * nParticles + 2); for (int i = 0; i < nParticles + 1; i++) { TString histName = i < nParticles ? primaryParticles[i].name : "all"; - if (cfgFillDeDxWithoutCut) { - hDeDx[2 * i] = histos.add(Form("dedx/histdEdx_%s", histName.Data()), ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", HistType::kTH2F, {axisRigidity, axisdEdx}); - } if (cfgFillDeDxWithCut) { - hDeDx[2 * i + 1] = histos.add(Form("dedx/histdEdx_%s_Cuts", histName.Data()), ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", HistType::kTH2F, {axisRigidity, axisdEdx}); + hDeDx[2 * i] = histos.add(Form("dedx/histdEdx_%s_Cuts", histName.Data()), ";p_{TPC}/z (GeV/#it{c}); d#it{E}/d#it{x}", HistType::kTH2F, {axisRigidity, axisdEdx}); } } for (int i = 0; i < nParticles; i++) { @@ -215,14 +235,34 @@ struct NucleitpcPbPb { hmass[2 * i + 1] = histos.add(Form("histmass_ptanti/histmass_%s", histName.Data()), ";p_T{TPC} (GeV/#it{c}); mass^{2}", HistType::kTH2F, {ptAxis, axismass}); } } + + if (doprocessMC) { + histomc.add("histVtxZgen", "histVtxZgen", kTH1F, {axisVtxZ}); + histomc.add("ImptParameter", "ImptParameter", kTH1F, {axisImpt}); + histomc.add("histEtagen", "histEtagen", kTH1F, {axiseta}); + histomc.add("histPtgenHe3", "histPtgenHe3", kTH1F, {ptAxis}); + histomc.add("histPtgenAntiHe3", "histPtgenAntiHe3", kTH1F, {ptAxis}); + histomc.add("histPtgenHe4", "histPtgenHe4", kTH1F, {ptAxis}); + histomc.add("histPtgenAntiHe4", "histPtgenAntiHe4", kTH1F, {ptAxis}); + // Reconstrcuted eta + 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("histPtRecoHe3", "histPtgenHe3", kTH1F, {ptAxis}); + histomc.add("histPtRecoAntiHe3", "histPtgenAntiHe3", kTH1F, {ptAxis}); + histomc.add("histPtRecoHe4", "histPtgenHe4", kTH1F, {ptAxis}); + histomc.add("histPtRecoAntiHe4", "histPtgenAntiHe4", kTH1F, {ptAxis}); + 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("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)"}}); + } } //---------------------------------------------------------------------------------------------------------------- void findprimaryParticles(aod::TrackAssoc const& tracksByColl, TracksFull const& tracks) { - // track loop, store daughter candidates in std::vector for (const auto& trackId : tracksByColl) { const auto& track = tracks.rawIteratorAt(trackId.trackId()); - filldedx(track, nParticles); if (!track.isPVContributor() && cfgUsePVcontributors) continue; if (!track.hasITS() && cfgITSrequire) @@ -233,20 +273,26 @@ struct NucleitpcPbPb { continue; if (!track.passedTPCRefit() && cfgPassedTPCRefit) continue; - if (std::abs(track.eta()) > cfgCutEta) + if (std::abs(track.eta()) > cfgCutEta && cfgetaRequire) continue; for (size_t i = 0; i < primaryParticles.size(); i++) { if (std::abs(getRapidity(track, i)) > cfgCutRapidity && cfgRapidityRequire) continue; if (track.tpcNClsFound() < cfgTrackPIDsettings->get(i, "minTPCnCls") && cfgTPCNClsfoundRequire) continue; - double min_value = 0.8; - if (((track.tpcNClsCrossedRows() < cfgTrackPIDsettings->get(i, "minTPCnClsCrossedRows")) || track.tpcNClsCrossedRows() < min_value * track.tpcNClsFindable()) && cfgTPCNClsCrossedRowsRequire) + if (((track.tpcNClsCrossedRows() < cfgTrackPIDsettings->get(i, "minTPCnClsCrossedRows")) || track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable()) && cfgTPCNClsCrossedRowsRequire) // o2-linter: disable=magic-number (To be checked) continue; if (track.tpcChi2NCl() > cfgTrackPIDsettings->get(i, "maxTPCchi2") && cfgmaxTPCchi2Require) continue; + if (track.tpcChi2NCl() < cfgTrackPIDsettings->get(i, "minTPCchi2") && cfgminTPCchi2Require) + 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; + if ((track.itsNClsInnerBarrel() < cfgTrackPIDsettings->get(i, "minReqClusterITSib")) && cfgminReqClusterITSibRequire) + continue; if (track.itsChi2NCl() > cfgTrackPIDsettings->get(i, "maxITSchi2") && cfgmaxITSchi2Require) continue; if (getMeanItsClsSize(track) < cfgTrackPIDsettings->get(i, "minITSclsSize") && cfgminGetMeanItsClsSizeRequire) @@ -255,32 +301,47 @@ struct NucleitpcPbPb { continue; if ((getRigidity(track) < cfgTrackPIDsettings->get(i, "minRigidity") || getRigidity(track) > cfgTrackPIDsettings->get(i, "maxRigidity")) && cfgRigidityCutRequire) 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"))) && cfgmassRequire) - continue; - bool insideDCAxy = (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); - if ((!(insideDCAxy) || std::abs(track.dcaZ()) > cfgTrackPIDsettings->get(i, "maxDcaZ")) && cfgDCAwithptRequire) - continue; - if ((std::abs(track.dcaXY()) > cfgTrackPIDsettings->get(i, "maxDcaXY") || std::abs(track.dcaZ()) > cfgTrackPIDsettings->get(i, "maxDcaZ")) && cfgDCAnopt) + float ptMomn; + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + ptMomn = (i == he3 || i == he4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + bool insideDCAxy = (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(ptMomn, 1.1f)))); // o2-linter: disable=magic-number (To be checked) + if ((!(insideDCAxy) || std::abs(track.dcaZ()) > dcazSigma(ptMomn, cfgTrackPIDsettings->get(i, "maxDcaZ"))) && cfgDCAwithptRequire) continue; if (track.sign() > 0) { - histos.fill(HIST("histDcaZVsPtData_particle"), track.pt(), track.dcaZ()); - histos.fill(HIST("histDcaXYVsPtData_particle"), track.pt(), track.dcaXY()); + histos.fill(HIST("histDcaZVsPtData_particle"), ptMomn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_particle"), ptMomn, track.dcaXY()); } if (track.sign() < 0) { - histos.fill(HIST("histDcaZVsPtData_antiparticle"), track.pt(), track.dcaZ()); - histos.fill(HIST("histDcaXYVsPtData_antiparticle"), track.pt(), track.dcaXY()); + histos.fill(HIST("histDcaZVsPtData_antiparticle"), ptMomn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_antiparticle"), ptMomn, track.dcaXY()); } - fillnsigma(track, i); - if (std::abs(getTPCnSigma(track, primaryParticles.at(i))) > cfgTrackPIDsettings->get(i, "maxTPCnSigma") && cfgmaxTPCnSigmaRequire) + float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); + if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) + continue; + float itsSigma = getITSnSigma(track, primaryParticles.at(i)); + if ((std::abs(itsSigma) > cfgITSnsigma) && cfgmaxITSnSigmaRequire) continue; + fillnsigma(track, i); filldedx(track, i); + // TOF selection + if (!track.hasTOF() && cfgTrackPIDsettings->get(i, "TOFrequiredabove") < 1) + continue; + float beta{o2::pid::tof::Beta::GetBeta(track)}; + float charge{1.f + static_cast(i == he3 || i == he4)}; + float tofMasses = getRigidity(track) * charge * std::sqrt(1.f / (beta * beta) - 1.f); + if ((getRigidity(track) > cfgTrackPIDsettings->get(i, "TOFrequiredabove") && (tofMasses < cfgTrackPIDsettings->get(i, "minTOFmass") || tofMasses > cfgTrackPIDsettings->get(i, "maxTOFmass"))) && cfgmassRequire) + continue; fillhmass(track, i); + if (cfgRequirebetaplot) { + histos.fill(HIST("Tofsignal"), getRigidity(track) * track.sign(), o2::pid::tof::Beta::GetBeta(track)); + } + filldedx(track, nParticles); } histos.fill(HIST("histeta"), track.eta()); } // track loop } //---------------------------------------------------------------------------------------------------------------- - //---------------------------------------------------------------------------------------------------------------- void processData(CollisionsFull const& collisions, TracksFull const& tracks, aod::BCsWithTimestamps const&, aod::TrackAssoc const& tracksColl) { for (const auto& collision : collisions) { @@ -309,8 +370,212 @@ struct NucleitpcPbPb { continue; } } - PROCESS_SWITCH(NucleitpcPbPb, processData, "data analysis", true); + PROCESS_SWITCH(NucleitpcPbPb, processData, "data analysis", false); //---------------------------------------------------------------------------------------------------------------- + // MC particles + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + struct McCollInfo { + bool passedEvSel = false; + }; + std::vector mcCollInfos; + void processMC(CollisionsFullMC const& collisions, aod::McCollisions const& mcCollisions, TracksFull const& tracks, aod::BCsWithTimestamps const& bcs, aod::McParticles const& particlesMC, aod::McTrackLabels const& trackLabelsMC, aod::McCollisionLabels const& collLabels, aod::TrackAssoc const& tracksColl, CollisionsFull const& colls) + { + (void)colls; + (void)collLabels; + (void)bcs; + mcCollInfos.clear(); + mcCollInfos.resize(mcCollisions.size()); + // ----------------------------- Generated particles loop ----------------------------- + for (auto const& mcColl : mcCollisions) { + if (std::abs(mcColl.posZ()) > cfgZvertex && cfgZvertexRequireMC) + continue; + histomc.fill(HIST("histVtxZgen"), mcColl.posZ()); + histomc.fill(HIST("ImptParameter"), mcColl.impactParameter()); + for (auto const& mcParticle : particlesMC) { + if (mcParticle.mcCollisionId() != mcColl.globalIndex()) + continue; + if (!mcParticle.isPhysicalPrimary()) + continue; + int pdgCode = mcParticle.pdgCode(); + if (std::abs(mcParticle.y()) > cfgCutRapidity && cfgrapidityRequireMC) + continue; + if (std::abs(mcParticle.eta()) > cfgCutEta && cfgetaRequireMC) + continue; + histomc.fill(HIST("histEtagen"), mcParticle.eta()); + float ptScaled = mcParticle.pt(); + if (pdgCode == particlePdgCodes.at(4)) { + histomc.fill(HIST("histPtgenHe3"), ptScaled); + } else if (pdgCode == -particlePdgCodes.at(4)) { + histomc.fill(HIST("histPtgenAntiHe3"), ptScaled); + } else if (pdgCode == particlePdgCodes.at(5)) { + histomc.fill(HIST("histPtgenHe4"), ptScaled); + } else if (pdgCode == -particlePdgCodes.at(5)) { + histomc.fill(HIST("histPtgenAntiHe4"), ptScaled); + } + } // mc track loop generated + } // mc collision loop generated + // ----------------------------- Reconstructed track loop ----------------------------- + for (auto const& collision : collisions) { + auto mcCollIdx = collision.mcCollisionId(); + if (mcCollIdx < 0 || mcCollIdx >= mcCollisions.size()) + continue; + auto bc = collision.bc_as(); + initCCDB(bc); + collHasCandidate = false; + histomc.fill(HIST("histNevReco"), 0.5); + if (std::abs(collision.posZ()) > cfgZvertex && cfgZvertexRequire) + continue; + collPassedEvSel = collision.sel8(); + occupancy = collision.trackOccupancyInTimeRange(); + if (!collPassedEvSel && cfgsel8Require) + continue; + histomc.fill(HIST("histNevReco"), 1.5); + histomc.fill(HIST("histVtxZReco"), collision.posZ()); + histomc.fill(HIST("histCentFT0CReco"), collision.centFT0C()); + histomc.fill(HIST("histCentFT0MReco"), collision.centFT0M()); + if (collision.centFT0C() > centcut) + continue; + 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)) + continue; + if (requireIsVertexITSTPC && !collision.selection_bit(aod::evsel::kIsVertexITSTPC)) + continue; + if (removeNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) + continue; + // Loop through TrackAssoc and check if this track belongs to the current collision + for (const auto& assoc : tracksColl) { + if (assoc.collisionId() != collision.globalIndex()) + continue; + const auto& track = tracks.rawIteratorAt(assoc.trackId()); + auto labelRow = trackLabelsMC.iteratorAt(track.globalIndex()); + int label = labelRow.mcParticleId(); + if (label < 0 || label >= particlesMC.size()) + continue; + auto const& matchedMCParticle = particlesMC.iteratorAt(label); + int pdg = matchedMCParticle.pdgCode(); + if (!track.isPVContributor() && cfgUsePVcontributors) + continue; + if (!track.hasITS() && cfgITSrequire) + continue; + if (!track.hasTPC() && cfgTPCrequire) + continue; + if (!track.passedITSRefit() && cfgPassedITSRefit) + continue; + if (!track.passedTPCRefit() && cfgPassedTPCRefit) + 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; + if (std::abs(getRapidity(track, i)) > cfgCutRapidity && cfgRapidityRequire) + continue; + if (track.tpcNClsFound() < cfgTrackPIDsettings->get(i, "minTPCnCls") && cfgTPCNClsfoundRequire) + continue; + if (((track.tpcNClsCrossedRows() < cfgTrackPIDsettings->get(i, "minTPCnClsCrossedRows")) || track.tpcNClsCrossedRows() < 0.8 * track.tpcNClsFindable()) && cfgTPCNClsCrossedRowsRequire) // o2-linter: disable=magic-number (To be checked) + continue; + if (track.tpcChi2NCl() > cfgTrackPIDsettings->get(i, "maxTPCchi2") && cfgmaxTPCchi2Require) + continue; + if (track.tpcChi2NCl() < cfgTrackPIDsettings->get(i, "minTPCchi2") && cfgminTPCchi2Require) + 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; + if ((track.itsNClsInnerBarrel() < cfgTrackPIDsettings->get(i, "minReqClusterITSib")) && cfgminReqClusterITSibRequire) + continue; + if (track.itsChi2NCl() > cfgTrackPIDsettings->get(i, "maxITSchi2") && cfgmaxITSchi2Require) + continue; + if (getMeanItsClsSize(track) < cfgTrackPIDsettings->get(i, "minITSclsSize") && cfgminGetMeanItsClsSizeRequire) + continue; + if (getMeanItsClsSize(track) > cfgTrackPIDsettings->get(i, "maxITSclsSize") && cfgmaxGetMeanItsClsSizeRequire) + continue; + if ((getRigidity(track) < cfgTrackPIDsettings->get(i, "minRigidity") || getRigidity(track) > cfgTrackPIDsettings->get(i, "maxRigidity")) && cfgRigidityCutRequire) + continue; + float ptMomn; + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + ptMomn = (i == he3 || i == he4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + bool insideDCAxy = (std::abs(track.dcaXY()) <= (cfgTrackPIDsettings->get(i, "maxDcaXY") * (0.0105f + 0.0350f / std::pow(ptMomn, 1.1f)))); // o2-linter: disable=magic-number (To be checked) + if ((!(insideDCAxy) || std::abs(track.dcaZ()) > dcazSigma(ptMomn, cfgTrackPIDsettings->get(i, "maxDcaZ"))) && cfgDCAwithptRequire) + continue; + if (track.sign() > 0) { + histos.fill(HIST("histDcaZVsPtData_particle"), ptMomn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_particle"), ptMomn, track.dcaXY()); + } + if (track.sign() < 0) { + histos.fill(HIST("histDcaZVsPtData_antiparticle"), ptMomn, track.dcaZ()); + histos.fill(HIST("histDcaXYVsPtData_antiparticle"), ptMomn, track.dcaXY()); + } + float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); + if ((std::abs(tpcNsigma) > cfgTrackPIDsettings->get(i, "maxTPCnSigma")) && cfgmaxTPCnSigmaRequire) + continue; + float itsSigma = getITSnSigma(track, primaryParticles.at(i)); + if ((std::abs(itsSigma) > cfgITSnsigma) && cfgmaxITSnSigmaRequire) + continue; + fillnsigma(track, i); + filldedx(track, i); + if (!track.hasTOF() && cfgTrackPIDsettings->get(i, "TOFrequiredabove") < 1) + continue; + float beta{o2::pid::tof::Beta::GetBeta(track)}; + float charge{1.f + static_cast(i == he3 || i == he4)}; + float tofMasses = getRigidity(track) * charge * std::sqrt(1.f / (beta * beta) - 1.f); + if ((getRigidity(track) > cfgTrackPIDsettings->get(i, "TOFrequiredabove") && (tofMasses < cfgTrackPIDsettings->get(i, "minTOFmass") || tofMasses > cfgTrackPIDsettings->get(i, "maxTOFmass"))) && cfgmassRequire) + continue; + fillhmass(track, i); + if (cfgRequirebetaplot) { + histos.fill(HIST("Tofsignal"), getRigidity(track) * track.sign(), o2::pid::tof::Beta::GetBeta(track)); + } + filldedx(track, nParticles); + /*----------------------------------------------------------------------------------------------------------------*/ + float ptReco; + mTrackParCov.setPID(track.pidForTracking()); + ptReco = (std::abs(pdg) == particlePdgCodes.at(4) || std::abs(pdg) == particlePdgCodes.at(5)) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + if (pdg == -particlePdgCodes.at(5) && cfgmccorrectionhe4Require) { + ptReco = ptReco + 0.00765 + 0.503791 * std::exp(-1.10517 * ptReco); + } + + if (pdg == -particlePdgCodes.at(4) && cfgmccorrectionhe4Require) { + int pidGuess = track.pidForTracking(); + int antitriton = 6; + if (pidGuess == antitriton) { + ptReco = ptReco - 0.464215 + 0.195771 * ptReco - 0.0183111 * ptReco * ptReco; + // LOG(info) << "we have he3" << pidGuess; + } + } + float ptGen = matchedMCParticle.pt(); + float deltaPt = ptReco - ptGen; + + if (pdg == -particlePdgCodes.at(4)) { + histomc.fill(HIST("histDeltaPtVsPtGen"), ptReco, deltaPt); + histomc.fill(HIST("histPIDtrack"), ptReco, track.pidForTracking()); + } + if (pdg == -particlePdgCodes.at(5)) { + histomc.fill(HIST("histDeltaPtVsPtGenHe4"), ptReco, deltaPt); + } + if (pdg == particlePdgCodes.at(4)) { + histomc.fill(HIST("histPtRecoHe3"), ptReco); + } else if (pdg == -particlePdgCodes.at(4)) { + histomc.fill(HIST("histPtRecoAntiHe3"), ptReco); + } else if (pdg == particlePdgCodes.at(5)) { + histomc.fill(HIST("histPtRecoHe4"), ptReco); + } else if (pdg == -particlePdgCodes.at(5)) { + histomc.fill(HIST("histPtRecoAntiHe4"), ptReco); + } + } + histos.fill(HIST("histeta"), track.eta()); + /*----------------------------------------------------------------------------------------------------------------*/ + } // Track loop + } // Collision loop + } + PROCESS_SWITCH(NucleitpcPbPb, processMC, "MC reco+gen analysis", false); + //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= void initCCDB(aod::BCsWithTimestamps::iterator const& bc) { if (mRunNumber == bc.runNumber()) { @@ -358,7 +623,6 @@ struct NucleitpcPbPb { if (collPassedEvSel) { histos.fill(HIST("histNev"), 1.5); histos.fill(HIST("histVtxZ"), collision.posZ()); - // histos.fill(HIST("histCentFT0A"), collision.centFT0A()); histos.fill(HIST("histCentFT0C"), collision.centFT0C()); histos.fill(HIST("histCentFT0M"), collision.centFT0M()); } @@ -370,13 +634,10 @@ struct NucleitpcPbPb { void filldedx(T const& track, int species) { const float rigidity = getRigidity(track); - if (cfgFillDeDxWithoutCut) { - hDeDx[2 * species]->Fill(track.sign() * rigidity, track.tpcSignal()); - } if (track.tpcNClsFound() < cfgtpcNClsFound || track.itsNCls() < cfgitsNCls) return; if (cfgFillDeDxWithCut) { - hDeDx[2 * species + 1]->Fill(track.sign() * rigidity, track.tpcSignal()); + hDeDx[2 * species]->Fill(track.sign() * rigidity, track.tpcSignal()); } } //---------------------------------------------------------------------------------------------------------------- @@ -388,19 +649,15 @@ struct NucleitpcPbPb { if (cfgFillnsigma) { int i = species; const float tpcNsigma = getTPCnSigma(track, primaryParticles.at(i)); - double momn; - int speciesHe3 = 4; - int speciesHe4 = 5; - if (species == speciesHe3 || species == speciesHe4) { - momn = 2 * track.pt(); - } else { - momn = track.pt(); - } + float ptMomn; + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + ptMomn = (i == he3 || i == he4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); if (track.sign() > 0) { - hNsigmaPt[2 * species]->Fill(momn, tpcNsigma); + hNsigmaPt[2 * species]->Fill(ptMomn, tpcNsigma); } if (track.sign() < 0) { - hNsigmaPt[2 * species + 1]->Fill(momn, tpcNsigma); + hNsigmaPt[2 * species + 1]->Fill(ptMomn, tpcNsigma); } } } @@ -410,32 +667,30 @@ struct NucleitpcPbPb { { if (track.tpcNClsFound() < cfgtpcNClsFound || track.itsNCls() < cfgitsNCls) return; - if (cfgFillmass) { - double mass; - int speciesHe3 = 4; - int speciesHe4 = 5; - if ((species == speciesHe3 || species == speciesHe4) && cfgTwicemass) { - mass = 2 * track.mass(); - } else { - mass = track.mass(); - } - double momn; - if (species == speciesHe3 || species == speciesHe4) { - momn = 2 * track.pt(); - } else { - momn = track.pt(); - } - if (track.sign() > 0) { - hmass[2 * species]->Fill(momn, mass * mass); - } - if (track.sign() < 0) { - hmass[2 * species + 1]->Fill(momn, mass * mass); - } + if (!track.hasTOF() || !cfgFillmass) + return; + float beta{o2::pid::tof::Beta::GetBeta(track)}; + if (beta <= 0.f || beta >= 1.f) + return; + float charge = (species == he3 || species == he4) ? 2.f : 1.f; + float p = getRigidity(track); // assuming this is the momentum from inner TPC + float massTOF = p * charge * std::sqrt(1.f / (beta * beta) - 1.f); + // get PDG mass + float pdgMass = particleMasses[species]; + float massDiff = massTOF - pdgMass; + float ptMomn; + setTrackParCov(track, mTrackParCov); + mTrackParCov.setPID(track.pidForTracking()); + ptMomn = (species == he3 || species == he4) ? 2 * mTrackParCov.getPt() : mTrackParCov.getPt(); + if (track.sign() > 0) { + hmass[2 * species]->Fill(ptMomn, massDiff); + } else if (track.sign() < 0) { + hmass[2 * species + 1]->Fill(ptMomn, massDiff); } } //---------------------------------------------------------------------------------------------------------------- template - float getTPCnSigma(T const& track, PrimParticles const& particle) + float getTPCnSigma(T const& track, PrimParticles& particle) { const float rigidity = getRigidity(track); if (!track.hasTPC()) @@ -460,6 +715,27 @@ struct NucleitpcPbPb { } //---------------------------------------------------------------------------------------------------------------- template + float getITSnSigma(T const& track, PrimParticles& particle) + { + if (!track.hasITS()) + return -999; + o2::aod::ITSResponse itsResponse; + if (particle.name == "pion") + return itsResponse.nSigmaITS(track); + if (particle.name == "proton") + return itsResponse.nSigmaITS(track); + if (particle.name == "deuteron") + return itsResponse.nSigmaITS(track); + if (particle.name == "triton") + return itsResponse.nSigmaITS(track); + if (particle.name == "helion") + return itsResponse.nSigmaITS(track); + if (particle.name == "alpha") + return itsResponse.nSigmaITS(track); + return -999; // fallback if no match + } + //---------------------------------------------------------------------------------------------------------------- + template float getMeanItsClsSize(T const& track) { int sum = 0, n = 0; @@ -481,6 +757,12 @@ struct NucleitpcPbPb { return hePID ? track.tpcInnerParam() / 2 : track.tpcInnerParam(); } //---------------------------------------------------------------------------------------------------------------- + float dcazSigma(double pt, float dcasigma) + { + float invPt = 1.f / pt; + return (5.00000e-04 + 8.73690e-03 * invPt + 9.62329e-04 * invPt * invPt) * dcasigma; // o2-linter: disable=magic-number (To be checked) + } + //---------------------------------------------------------------------------------------------------------------- template float getRapidity(T const& track, int species) { diff --git a/PWGLF/Tasks/Nuspex/spectraKinkPiKa.cxx b/PWGLF/Tasks/Nuspex/spectraKinkPiKa.cxx new file mode 100644 index 00000000000..1b3c900fc35 --- /dev/null +++ b/PWGLF/Tasks/Nuspex/spectraKinkPiKa.cxx @@ -0,0 +1,693 @@ +// 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 spectraKinkPiKa.cxx +/// \brief Example of a simple task for the analysis of the muon from Kaon pion using kink topology +/// \author sandeep dudi sandeep.dudi@cern.ch + +#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include "PWGLF/DataModel/LFParticleIdentification.h" +#include "PWGLF/Utils/svPoolCreator.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.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 "Common/DataModel/PIDResponse.h" + +#include "Framework/O2DatabasePDGPlugin.h" +#include "ReconstructionDataFormats/PID.h" + +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TPDGCode.h" +#include "TVector3.h" +#include +#include + +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace o2; +using namespace o2::aod; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; +using VBracket = o2::math_utils::Bracket; + +using TracksFull = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; +namespace +{ +constexpr std::array LayerRadii{2.33959f, 3.14076f, 3.91924f, 19.6213f, 24.5597f, 34.388f, 39.3329f}; +constexpr double betheBlochDefault[1][6]{{-1.e32, -1.e32, -1.e32, -1.e32, -1.e32, -1.e32}}; +static const std::vector betheBlochParNames{"p0", "p1", "p2", "p3", "p4", "resolution"}; +static const std::vector particleNames{"Daughter"}; + +} // namespace + +struct kinkCandidate { + int mothTrackID; + int daugTrackID; + int collisionID; + + int mothSign; + std::array momMoth = {-999, -999, -999}; + std::array momDaug = {-999, -999, -999}; + std::array primVtx = {-999, -999, -999}; + std::array decVtx = {-999, -999, -999}; + + float dcaKinkTopo = -999; + float dcaXYdaug = -999; + float dcaXYmoth = -999; + float kinkAngle = -999; +}; +struct kinkBuilder { + // kink analysis + Produces outputDataTable; + Service ccdb; + // Selection criteria + Configurable maxDCAMothToPV{"maxDCAMothToPV", 0.1, "Max DCA of the mother to the PV"}; + Configurable minDCADaugToPV{"minDCADaugToPV", 0., "Min DCA of the daughter to the PV"}; + Configurable minPtMoth{"minPtMoth", 0.5, "Minimum pT of the hypercandidate"}; + 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 etaMax{"etaMax", 1., "eta daughter"}; + Configurable nTPCClusMinDaug{"nTPCClusMinDaug", 30, "mother NTPC clusters cut"}; + Configurable itsChi2cut{"itsChi2cut", 30, "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 "}; + + o2::vertexing::DCAFitterN<2> fitter; + o2::base::MatLayerCylSet* lut = nullptr; + + // constants + float radToDeg = o2::constants::math::Rad2Deg; + svPoolCreator svCreator; + + // bethe bloch parameters + Configurable> cfgBetheBlochParams{"cfgBetheBlochParams", {betheBlochDefault[0], 1, 6, particleNames, betheBlochParNames}, "TPC Bethe-Bloch parameterisation for charged daughter"}; + Configurable cfgMaterialCorrection{"cfgMaterialCorrection", static_cast(o2::base::Propagator::MatCorrType::USEMatCorrNONE), "Type of material correction"}; + Configurable customVertexerTimeMargin{"customVertexerTimeMargin", 800, "Time margin for custom vertexer (ns)"}; + Configurable skipAmbiTracks{"skipAmbiTracks", false, "Skip ambiguous tracks"}; + Configurable unlikeSignBkg{"unlikeSignBkg", false, "Use unlike sign background"}; + + // CCDB options + Configurable ccdbPath{"ccdbPath", "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"}; + + // std vector of candidates + std::vector kinkCandidates; + int mRunNumber; + float mBz; + std::array mBBparamsDaug; + + // mother and daughter tracks' properties (absolute charge and mass) + int charge = 1; + void init(InitContext const&) + { + // dummy values, 1 for mother, 0 for daughter + svCreator.setPDGs(1, 0); + + mRunNumber = 0; + mBz = 0; + + ccdb->setURL(ccdbPath); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + fitter.setPropagateToPCA(true); + fitter.setMaxR(200.); + fitter.setMinParamChange(1e-3); + fitter.setMinRelChi2Change(0.9); + fitter.setMaxDZIni(1e9); + fitter.setMaxChi2(1e9); + fitter.setUseAbsDCA(true); + + svCreator.setTimeMargin(customVertexerTimeMargin); + if (skipAmbiTracks) { + svCreator.setSkipAmbiTracks(); + } + for (int i = 0; i < 5; i++) { + mBBparamsDaug[i] = cfgBetheBlochParams->get("Daughter", Form("p%i", i)); + } + mBBparamsDaug[5] = cfgBetheBlochParams->get("Daughter", "resolution"); + } + + template + bool selectMothTrack(const T& candidate) + { + // ITS-standalone (no TPC, no TOF) + if (!kaontopologhy) { + if (candidate.has_collision() && candidate.hasITS() && !candidate.hasTPC() && !candidate.hasTOF() && + candidate.itsNCls() < 6 && + candidate.itsNClsInnerBarrel() == 3 && + candidate.itsChi2NCl() < 36 && + candidate.pt() > minPtMoth) { + return true; + } + return false; + } + // Kaon topology: ITS+TPC, no TOF + if (kaontopologhy) { + if (candidate.has_collision() && candidate.hasITS() && candidate.hasTPC() && !candidate.hasTOF() && + candidate.pt() > minPtMoth && + candidate.tpcNClsCrossedRows() >= nTPCClusMinDaug && + candidate.itsChi2NCl() <= itsChi2cut) { + return true; + } + return false; + } + + return false; // fallback + } + + template + bool selectDaugTrack(const T& candidate) + { + if (!kaontopologhy && (!candidate.hasTPC() || !candidate.hasITS())) { + return false; + } + + if (kaontopologhy && (!candidate.hasTPC() || candidate.hasITS())) { + return false; + } + + if (askTOFforDaug && !candidate.hasTOF()) { + return false; + } + return true; + } + + template + void fillCandidateData(const Tcolls& collisions, const Ttracks& tracks, aod::AmbiguousTracks const& ambiguousTracks, aod::BCs const& bcs) + { + svCreator.clearPools(); + svCreator.fillBC2Coll(collisions, bcs); + + for (const auto& track : tracks) { + if (std::abs(track.eta()) > etaMax) + continue; + + bool isDaug = selectDaugTrack(track); + bool isMoth = selectMothTrack(track); + + if (!isDaug && !isMoth) + continue; + + int pdgHypo = isMoth ? 1 : 0; + svCreator.appendTrackCand(track, collisions, pdgHypo, ambiguousTracks, bcs); + } + auto& kinkPool = svCreator.getSVCandPool(collisions, !unlikeSignBkg); + + for (const auto& svCand : kinkPool) { + kinkCandidate kinkCand; + + auto trackMoth = tracks.rawIteratorAt(svCand.tr0Idx); + auto trackDaug = tracks.rawIteratorAt(svCand.tr1Idx); + + auto const& collision = trackMoth.template collision_as(); + 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()); + kinkCand.primVtx = {primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}; + + o2::track::TrackParCov trackParCovMoth = getTrackParCov(trackMoth); + o2::track::TrackParCov trackParCovMothPV{trackParCovMoth}; + o2::base::Propagator::Instance()->PropagateToXBxByBz(trackParCovMoth, LayerRadii[trackMoth.itsNCls() - 1]); + std::array dcaInfoMoth; + o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovMothPV, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoMoth); + + o2::track::TrackParCov trackParCovDaug = getTrackParCov(trackDaug); + + // check if the kink daughter is close to the mother + if (std::abs(trackParCovMoth.getZ() - trackParCovDaug.getZ()) > maxZDiff) { + continue; + } + if ((std::abs(trackParCovMoth.getPhi() - trackParCovDaug.getPhi()) * radToDeg) > maxPhiDiff) { + continue; + } + + // propagate to PV + std::array dcaInfoDaug; + o2::base::Propagator::Instance()->propagateToDCABxByBz({primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ()}, trackParCovDaug, 2.f, static_cast(cfgMaterialCorrection.value), &dcaInfoDaug); + if (std::abs(dcaInfoDaug[0]) < 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) { + continue; + } + + if (!fitter.propagateTracksToVertex()) { + continue; + } + + auto propMothTrack = fitter.getTrack(0); + auto propDaugTrack = fitter.getTrack(1); + kinkCand.decVtx = fitter.getPCACandidatePos(); + + for (int i = 0; i < 3; i++) { + kinkCand.decVtx[i] -= kinkCand.primVtx[i]; + } + propMothTrack.getPxPyPzGlo(kinkCand.momMoth); + propDaugTrack.getPxPyPzGlo(kinkCand.momDaug); + for (int i = 0; i < 3; i++) { + kinkCand.momMoth[i] *= charge; + kinkCand.momDaug[i] *= charge; + } + float pMoth = propMothTrack.getP() * charge; + float pDaug = propDaugTrack.getP() * charge; + float spKink = kinkCand.momMoth[0] * kinkCand.momDaug[0] + kinkCand.momMoth[1] * kinkCand.momDaug[1] + kinkCand.momMoth[2] * kinkCand.momDaug[2]; + kinkCand.kinkAngle = std::acos(spKink / (pMoth * pDaug)); + + kinkCand.collisionID = collision.globalIndex(); + kinkCand.mothTrackID = trackMoth.globalIndex(); + kinkCand.daugTrackID = trackDaug.globalIndex(); + + kinkCand.dcaXYmoth = dcaInfoMoth[0]; + kinkCand.mothSign = trackMoth.sign(); + kinkCand.dcaXYdaug = dcaInfoDaug[0]; + kinkCand.dcaKinkTopo = std::sqrt(fitter.getChi2AtPCACandidate()); + kinkCandidates.push_back(kinkCand); + } + } + + void initCCDB(aod::BCs::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + LOG(info) << "Initializing CCDB for run " << mRunNumber; + o2::parameters::GRPMagField* grpmag = ccdb->getForRun(grpmagPath, mRunNumber); + o2::base::Propagator::initFieldFromGRP(grpmag); + mBz = grpmag->getNominalL3Field(); + fitter.setBz(mBz); + + if (!lut) { + lut = o2::base::MatLayerCylSet::rectifyPtrFromFile(ccdb->get(lutPath)); + int mat{static_cast(cfgMaterialCorrection)}; + fitter.setMatCorrType(static_cast(mat)); + } + o2::base::Propagator::Instance()->setMatLUT(lut); + LOG(info) << "Task initialized for run " << mRunNumber << " with magnetic field " << mBz << " kZG"; + } + + void process(aod::Collisions const& collisions, TracksFull const& tracks, aod::AmbiguousTracks const& ambiTracks, aod::BCs const& bcs) + { + kinkCandidates.clear(); + fillCandidateData(collisions, tracks, ambiTracks, bcs); + // sort kinkCandidates by collisionID to allow joining with collision table + std::sort(kinkCandidates.begin(), kinkCandidates.end(), [](const kinkCandidate& a, const kinkCandidate& b) { return a.collisionID < b.collisionID; }); + + for (const auto& kinkCand : kinkCandidates) { + outputDataTable(kinkCand.collisionID, kinkCand.mothTrackID, kinkCand.daugTrackID, + kinkCand.decVtx[0], kinkCand.decVtx[1], kinkCand.decVtx[2], + kinkCand.mothSign, kinkCand.momMoth[0], kinkCand.momMoth[1], kinkCand.momMoth[2], + kinkCand.momDaug[0], kinkCand.momDaug[1], kinkCand.momDaug[2], + kinkCand.dcaXYmoth, kinkCand.dcaXYdaug, kinkCand.dcaKinkTopo); + } + } + PROCESS_SWITCH(kinkBuilder, process, "Produce kink tables", false); +}; + +struct spectraKinkPiKa { + Service pdg; + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rpiKkink{"rpiKkink", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Configurable for event selection + Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable cutNSigmaPi{"cutNSigmaPi", 4, "NSigmaTPCPion"}; + Configurable cutNSigmaKa{"cutNSigmaKa", 4, "NSigmaTPCKaon"}; + Configurable cutNSigmaMu{"cutNSigmaMu", 4, "cutNSigmaMu"}; + Configurable rapCut{"rapCut", 0.8, "rapCut"}; + Configurable kinkanglecut{"kinkanglecut", 2.0, "kinkanglecut"}; + Configurable minradius{"minradius", 130.0, "minradiuscut"}; + Configurable maxradius{"maxradius", 200.0, "maxradiuscut"}; + Configurable dcaXYcut{"dcaXYcut", 0.2, "dcaXYcut"}; + Configurable dcaZcut{"dcaZcut", 0.2, "dcaZcut"}; + Configurable tpcChi2Cut{"tpcChi2Cut", 4.0, "tpcChi2Cut"}; + + Configurable pid{"pidMother", 321, ""}; + Configurable dpid{"pidDaughter", 13, ""}; + Configurable d0pid{"dopid", 0, ""}; + + Preslice mPerCol = aod::track::collisionId; + Preslice mtPerCol = aod::track::collisionId; + + void init(InitContext const&) + { + // Axes + const AxisSpec ptAxis{100, 0, 10, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec qtAxis{2000, 0, 2, "#it{q}_{T} (GeV/#it{c})"}; + const AxisSpec kinkAxis{200, 0, 4, "#theta"}; + const AxisSpec etaAxis{200, -5.0, 5.0, "#eta"}; + const AxisSpec vertexAxis{1200, -300., 300., "vrtx [cm]"}; + const AxisSpec radiusAxis{600, 0., 300., "vrtx [cm]"}; + const AxisSpec massAxis{600, 0.1, 0.7, "Inv mass (GeV/#it{c}^{2})"}; + + // Event selection + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexAxis}}); + + rpiKkink.add("h2_dau_pt_vs_eta_rec", "pt_vs_eta_dau", {HistType::kTH2F, {ptAxis, etaAxis}}); + rpiKkink.add("h2_moth_pt_vs_eta_rec", "pt_vs_eta_moth", {HistType::kTH2F, {ptAxis, etaAxis}}); + rpiKkink.add("h2_pt_moth_vs_dau_rec", "pt_moth_vs_dau", {HistType::kTH2F, {ptAxis, ptAxis}}); + + rpiKkink.add("h2_qt", "qt", {HistType::kTH1F, {qtAxis}}); + rpiKkink.add("h2_qt_vs_pt", "qt_pt", {HistType::kTH2F, {qtAxis, ptAxis}}); + + rpiKkink.add("h2_kink_angle", "kink angle", {HistType::kTH1F, {kinkAxis}}); + + // pion + rpiKkink.add("h2_dau_pt_vs_eta_rec_pion", "pt_vs_eta_dau", {HistType::kTH2F, {ptAxis, etaAxis}}); + rpiKkink.add("h2_moth_pt_vs_eta_rec_pion", "pt_vs_eta_moth", {HistType::kTH2F, {ptAxis, etaAxis}}); + rpiKkink.add("h2_pt_moth_vs_dau_rec_pion", "pt_moth_vs_dau", {HistType::kTH2F, {ptAxis, ptAxis}}); + + // inv mass + rpiKkink.add("h2_invmass_kaon", "Inv mass vs Pt", {HistType::kTH3F, {massAxis, ptAxis, ptAxis}}); + rpiKkink.add("h2_invmass_pion", "Inv mass vs Pt", {HistType::kTH3F, {massAxis, ptAxis, ptAxis}}); + + rpiKkink.add("h2_qt_pion", "qt", {HistType::kTH1F, {qtAxis}}); + rpiKkink.add("h2_qt_vs_ptpion", "qt_pt", {HistType::kTH2F, {qtAxis, ptAxis}}); + rpiKkink.add("h2_kink_angle_pion", "kink angle", {HistType::kTH1F, {kinkAxis}}); + + // track qa + + rpiKkink.add("h2_kinkradius_vs_vz", "kink radius_vz", {HistType::kTH2F, {vertexAxis, radiusAxis}}); + rpiKkink.add("h2_kink_vx_vs_vy", "kink vx vs vz ", {HistType::kTH2F, {vertexAxis, vertexAxis}}); + + if (doprocessMC) { + rpiKkink.add("h2_dau_pt_vs_eta_gen", "pt_vs_eta_dau", {HistType::kTH2F, {ptAxis, etaAxis}}); + rpiKkink.add("h2_moth_pt_vs_eta_gen", "pt_vs_eta_moth", {HistType::kTH2F, {ptAxis, etaAxis}}); + rpiKkink.add("h2_pt_moth_vs_dau_gen", "pt_moth_vs_dau", {HistType::kTH2F, {ptAxis, ptAxis}}); + + rpiKkink.add("h2_qt_gen", "qt", {HistType::kTH1F, {qtAxis}}); + rpiKkink.add("h2_qt_rec", "qt", {HistType::kTH1F, {qtAxis}}); + rpiKkink.add("h2_kink_angle_gen", "kink angle", {HistType::kTH1F, {kinkAxis}}); + } + } + + double computeMotherMass(ROOT::Math::PxPyPzMVector p_moth, ROOT::Math::PxPyPzMVector p_daug) + { + // Infer neutrino momentum from conservation + ROOT::Math::XYZVector p_nu_vec = p_moth.Vect() - p_daug.Vect(); + + // Neutrino energy (massless): E_nu = |p_nu| + double E_nu = p_nu_vec.R(); + + // Total energy of the system + double E_total = p_daug.E() + E_nu; + + // Total momentum = p_nu + p_daug + ROOT::Math::XYZVector p_total_vec = p_nu_vec + p_daug.Vect(); + double p_total_sq = p_total_vec.Mag2(); + + // Invariant mass from E² - |p|² + double m2 = E_total * E_total - p_total_sq; + return (m2 > 0) ? std::sqrt(m2) : -1.0; + } + + void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& KinkCands, TracksFull const&) + { + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8() || !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + for (const auto& kinkCand : KinkCands) { + 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 + } + bool kaon = false; + bool pion = false; + /* + if (mothTrack.dcaXY() > dcaXYcut) + continue; + if (mothTrack.dcaZ() > dcaZcut) + continue; + */ + if (mothTrack.tpcChi2NCl() > tpcChi2Cut) + continue; + if (std::abs(mothTrack.tpcNSigmaKa()) < cutNSigmaKa) { + kaon = true; + } + if (std::abs(mothTrack.tpcNSigmaPi()) < cutNSigmaPi) { + pion = true; + } + if (!kaon && !pion) { + continue; + } + if (cutNSigmaMu != -1 && std::abs(dauTrack.tpcNSigmaMu()) > cutNSigmaMu) { + continue; + } + double radiusxy = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); + if (radiusxy < minradius || radiusxy > maxradius) + continue; + rpiKkink.fill(HIST("h2_kinkradius_vs_vz"), kinkCand.zDecVtx(), radiusxy); + rpiKkink.fill(HIST("h2_kink_vx_vs_vy"), kinkCand.xDecVtx(), kinkCand.yDecVtx()); + + v0.SetCoordinates(mothTrack.px(), mothTrack.py(), mothTrack.pz(), o2::constants::physics::MassPionCharged); + v1.SetCoordinates(dauTrack.px(), dauTrack.py(), dauTrack.pz(), o2::constants::physics::MassMuon); + + float pMoth = v0.P(); + float pDaug = v1.P(); + float spKink = mothTrack.px() * dauTrack.px() + mothTrack.py() * dauTrack.py() + mothTrack.pz() * dauTrack.pz(); + float kinkangle = std::acos(spKink / (pMoth * pDaug)); + float radToDeg = o2::constants::math::Rad2Deg; + if (kinkangle * radToDeg < kinkanglecut) + continue; + + if (kaon) { + rpiKkink.fill(HIST("h2_moth_pt_vs_eta_rec"), v0.Pt(), v0.Eta()); + rpiKkink.fill(HIST("h2_dau_pt_vs_eta_rec"), v1.Pt(), v1.Eta()); + rpiKkink.fill(HIST("h2_pt_moth_vs_dau_rec"), v0.Pt(), v1.Pt()); + rpiKkink.fill(HIST("h2_kink_angle"), kinkangle); + } + if (pion) { + rpiKkink.fill(HIST("h2_moth_pt_vs_eta_rec_pion"), v0.Pt(), v0.Eta()); + rpiKkink.fill(HIST("h2_dau_pt_vs_eta_rec_pion"), v1.Pt(), v1.Eta()); + rpiKkink.fill(HIST("h2_pt_moth_vs_dau_rec_pion"), v0.Pt(), v1.Pt()); + rpiKkink.fill(HIST("h2_kink_angle_pion"), kinkangle); + } + TVector3 pdlab(v1.Px(), v1.Py(), v1.Pz()); + // Compute transverse component + TVector3 motherDir(v0.Px(), v0.Py(), v0.Pz()); + double ptd = pdlab.Perp(motherDir); // or p_d_lab.Mag() * sin(theta) + + if (kaon) { + v0.SetCoordinates(mothTrack.px(), mothTrack.py(), mothTrack.pz(), o2::constants::physics::MassKaonCharged); + double mass = computeMotherMass(v0, v1); + rpiKkink.fill(HIST("h2_qt"), ptd); + rpiKkink.fill(HIST("h2_qt_vs_pt"), ptd, v1.Pt()); + rpiKkink.fill(HIST("h2_invmass_kaon"), mass, v0.Pt(), ptd); + } + if (pion) { + v0.SetCoordinates(mothTrack.px(), mothTrack.py(), mothTrack.pz(), o2::constants::physics::MassPionCharged); + double mass = computeMotherMass(v0, v1); + rpiKkink.fill(HIST("h2_qt_pion"), ptd); + rpiKkink.fill(HIST("h2_qt_vs_ptpion"), ptd, v1.Pt()); + rpiKkink.fill(HIST("h2_invmass_pion"), mass, v0.Pt(), ptd); + } + } + } + PROCESS_SWITCH(spectraKinkPiKa, processData, "Data processing", true); + + void processMC(CollisionsFullMC const& collisions, aod::KinkCands const& KinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const&) + { + for (const auto& collision : collisions) { + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8() || !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + if (!collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + auto kinkCandPerColl = KinkCands.sliceBy(mPerCol, collision.globalIndex()); + for (const auto& kinkCand : kinkCandPerColl) { + auto dauTrack = kinkCand.trackDaug_as(); + auto mothTrack = kinkCand.trackMoth_as(); + 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 + } + bool kaon = false; + bool pion = false; + if (std::abs(mothTrack.tpcNSigmaKa()) < cutNSigmaKa) { + kaon = true; + } + if (std::abs(mothTrack.tpcNSigmaPi()) < cutNSigmaPi) { + pion = true; + } + if (!kaon && !pion) + continue; + double radiusxy = std::sqrt(kinkCand.xDecVtx() * kinkCand.xDecVtx() + kinkCand.yDecVtx() * kinkCand.yDecVtx()); + if (radiusxy < minradius || radiusxy > maxradius) + continue; + rpiKkink.fill(HIST("h2_kinkradius_vs_vz"), kinkCand.zDecVtx(), radiusxy); + rpiKkink.fill(HIST("h2_kink_vx_vs_vy"), kinkCand.xDecVtx(), kinkCand.yDecVtx()); + v0.SetCoordinates(mothTrack.px(), mothTrack.py(), mothTrack.pz(), o2::constants::physics::MassPionCharged); + v1.SetCoordinates(dauTrack.px(), dauTrack.py(), dauTrack.pz(), o2::constants::physics::MassMuon); + + float pMoth = v0.P(); + float pDaug = v1.P(); + float spKink = mothTrack.px() * dauTrack.px() + mothTrack.py() * dauTrack.py() + mothTrack.pz() * dauTrack.pz(); + float kinkangle = std::acos(spKink / (pMoth * pDaug)); + float radToDeg = o2::constants::math::Rad2Deg; + if (kinkangle * radToDeg < kinkanglecut) + continue; + + rpiKkink.fill(HIST("h2_moth_pt_vs_eta_rec"), v0.Pt(), v0.Eta()); + rpiKkink.fill(HIST("h2_dau_pt_vs_eta_rec"), v1.Pt(), v1.Eta()); + rpiKkink.fill(HIST("h2_pt_moth_vs_dau_rec"), v0.Pt(), v1.Pt()); + rpiKkink.fill(HIST("h2_kink_angle"), kinkangle); + + TVector3 pdlab(v1.Px(), v1.Py(), v1.Pz()); + // Compute transverse component + TVector3 motherDir(v0.Px(), v0.Py(), v0.Pz()); + double ptd = pdlab.Perp(motherDir); // or p_d_lab.Mag() * sin(theta) + + rpiKkink.fill(HIST("h2_qt"), ptd); + + // do MC association + auto mcLabMoth = trackLabelsMC.rawIteratorAt(mothTrack.globalIndex()); + auto mcLabDau = trackLabelsMC.rawIteratorAt(dauTrack.globalIndex()); + + if (mcLabMoth.has_mcParticle() && mcLabDau.has_mcParticle()) { + + auto mcTrackMoth = mcLabMoth.mcParticle_as(); + auto mcTrackDau = mcLabDau.mcParticle_as(); + if (!mcTrackDau.has_mothers()) { + continue; + } + for (const auto& piMother : mcTrackDau.mothers_as()) { + if (piMother.globalIndex() != mcTrackMoth.globalIndex()) { + continue; + } + if (std::abs(mcTrackMoth.pdgCode()) != pid || std::abs(mcTrackDau.pdgCode()) != dpid) { + continue; + } + rpiKkink.fill(HIST("h2_qt_rec"), ptd); + } + } + } + } + for (const auto& mcPart : particlesMC) { + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + if (!d0pid && (std::abs(mcPart.pdgCode()) != pid || std::abs(mcPart.eta()) > rapCut)) { + continue; + } + bool isDmeson = std::abs(mcPart.pdgCode()) == kD0 || std::abs(mcPart.pdgCode()) == kDPlus || std::abs(mcPart.pdgCode()) == kDStar; + if (d0pid && (!isDmeson || std::abs(mcPart.eta()) > rapCut)) { + continue; + } + if (!mcPart.has_daughters()) { + continue; // Skip if no daughters + } + bool hasKaonpionDaughter = false; + for (const auto& daughter : mcPart.daughters_as()) { + if (std::abs(daughter.pdgCode()) == dpid) { // muon PDG code + hasKaonpionDaughter = true; + v1.SetCoordinates(daughter.px(), daughter.py(), daughter.pz(), o2::constants::physics::MassMuon); + break; // Found a muon daughter, exit loop + } + } + if (!hasKaonpionDaughter) { + continue; // Skip if no muon daughter found + } + if (!d0pid && pid == kKPlus) { + v0.SetCoordinates(mcPart.px(), mcPart.py(), mcPart.pz(), o2::constants::physics::MassKaonCharged); + } + + if (!d0pid && pid == kPiPlus) { + v0.SetCoordinates(mcPart.px(), mcPart.py(), mcPart.pz(), o2::constants::physics::MassPionCharged); + } + if (d0pid) { + v0.SetCoordinates(mcPart.px(), mcPart.py(), mcPart.pz(), o2::constants::physics::MassD0); + } + float pMoth = v0.P(); + float pDaug = v1.P(); + float spKink = v0.Px() * v1.Px() + v0.Py() * v1.Py() + v0.Pz() * v1.Pz(); + float kinkangle = std::acos(spKink / (pMoth * pDaug)); + float radToDeg = o2::constants::math::Rad2Deg; + if (kinkangle * radToDeg < kinkanglecut) + continue; + rpiKkink.fill(HIST("h2_moth_pt_vs_eta_gen"), v0.Pt(), v0.Eta()); + rpiKkink.fill(HIST("h2_dau_pt_vs_eta_gen"), v1.Pt(), v1.Eta()); + rpiKkink.fill(HIST("h2_pt_moth_vs_dau_gen"), v0.Pt(), v1.Pt()); + rpiKkink.fill(HIST("h2_kink_angle_gen"), kinkangle); + TVector3 pdlab(v1.Px(), v1.Py(), v1.Pz()); + // Compute transverse component + TVector3 motherDir(v0.Px(), v0.Py(), v0.Pz()); + double ptd = pdlab.Perp(motherDir); // or p_d_lab.Mag() * sin(theta) + rpiKkink.fill(HIST("h2_qt_gen"), ptd); + } + } + PROCESS_SWITCH(spectraKinkPiKa, processMC, "MC processing", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + auto builderTask = adaptAnalysisTask(cfgc); + auto spectraTask = adaptAnalysisTask(cfgc); + + return {builderTask, spectraTask}; // Just return both tasks +} diff --git a/PWGLF/Tasks/Nuspex/spectraTOF.cxx b/PWGLF/Tasks/Nuspex/spectraTOF.cxx index e1607610ac6..f80b2870959 100644 --- a/PWGLF/Tasks/Nuspex/spectraTOF.cxx +++ b/PWGLF/Tasks/Nuspex/spectraTOF.cxx @@ -18,6 +18,7 @@ /// // O2 includes + #include #include #include "ReconstructionDataFormats/Track.h" @@ -97,6 +98,7 @@ struct tofSpectra { } trkselOptions; Configurable enableDcaGoodEvents{"enableDcaGoodEvents", true, "Enables the MC plots with the correct match between data and MC"}; + Configurable enablePureDCAHistogram{"enablePureDCAHistogram", false, "Enables the pure DCA histograms"}; Configurable enableTrackCutHistograms{"enableTrackCutHistograms", true, "Enables track cut histograms, before and after the cut"}; Configurable enableDeltaHistograms{"enableDeltaHistograms", true, "Enables the delta TPC and TOF histograms"}; Configurable enableTPCTOFHistograms{"enableTPCTOFHistograms", true, "Enables TPC TOF histograms"}; @@ -1017,7 +1019,6 @@ struct tofSpectra { } } } - if constexpr (fillFullInfo) { if (enableDeltaHistograms) { const auto& deltaTOF = o2::aod::pidutils::tofExpSignalDiff(track); @@ -1036,7 +1037,6 @@ 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) { @@ -1206,7 +1206,7 @@ struct tofSpectra { return false; } } - return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / pow(track.pt(), 1.1f)))); + return (std::abs(track.dcaXY()) <= (maxDcaXYFactor.value * (0.0105f + 0.0350f / std::pow(track.pt(), 1.1f)))); } return track.isGlobalTrack(); } @@ -1887,7 +1887,9 @@ struct tofSpectra { if (!isParticleEnabled()) { // Check if the particle is enabled return; } - + if (!collision.has_mcCollision()) { + return; // Skips processing if no corresponding MC collision is found (rare case!) + } const auto& mcCollision = collision.mcCollision_as(); const float multiplicity = getMultiplicity(collision); const int occupancy = collision.trackOccupancyInTimeRange(); @@ -1906,130 +1908,138 @@ struct tofSpectra { if (std::abs(mcParticle.y()) > trkselOptions.cfgCutY) { return; } + if (enablePureDCAHistogram) { + const auto& nsigmaTPCKa = o2::aod::pidutils::tpcNSigma<3>(track); + const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); - const auto& nsigmaTPCKa = o2::aod::pidutils::tpcNSigma<3>(track); - const bool isKaonTPC = std::abs(nsigmaTPCKa) < trkselOptions.cfgCutNsigma; - - const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); - const bool isKaonTOF = std::abs(nsigmaTOFKa) < trkselOptions.cfgCutNsigma; - - // 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); - } - - if (isDCAPureSample) { - if (enableDCAvsmotherHistograms) { - hDcaXYMC[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMC[i]->Fill(track.pt(), track.dcaZ()); + // 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); } - if (!mcParticle.isPhysicalPrimary()) { // Secondaries (weak decays and material) - if (mcParticle.getProcess() == 4) { // Particles from decay - if (enableDCAxyzHistograms) { - hDcaXYZStr[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); - } else { - histos.fill(HIST(hdcaxystr[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazstr[i]), track.pt(), track.dcaZ()); - } + if (isDCAPureSample) { + if (enableDCAvsmotherHistograms) { + hDcaXYMC[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMC[i]->Fill(track.pt(), track.dcaZ()); + } + + if (!mcParticle.isPhysicalPrimary()) { // Secondaries (weak decays and material) + if (mcParticle.getProcess() == 4) { // Particles from decay + if (enableDCAxyzHistograms) { + hDcaXYZStr[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + } else { + histos.fill(HIST(hdcaxystr[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazstr[i]), track.pt(), track.dcaZ()); + } - if (mcParticle.has_mothers()) { - for (const auto& mother : mcParticle.template mothers_as()) { - auto daughter0 = mother.template daughters_as().begin(); - double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; - double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; - auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); - hDecayLengthStr[i]->Fill(track.pt(), decayLength); + if (mcParticle.has_mothers()) { + for (const auto& mother : mcParticle.template mothers_as()) { + auto daughter0 = mother.template daughters_as().begin(); + double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; + double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; + auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); + hDecayLengthStr[i]->Fill(track.pt(), decayLength); + } + } + } else { // Particles from the material + if (enableDCAxyzHistograms) { + hDcaXYZMat[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + } else { + histos.fill(HIST(hdcaxymat[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazmat[i]), track.pt(), track.dcaZ()); } } - } else { // Particles from the material + } else { // Primaries if (enableDCAxyzHistograms) { - hDcaXYZMat[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + hDcaXYZPrm[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); + if (enableDcaGoodEvents.value && collision.has_mcCollision()) { + histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY(), track.dcaZ()); + } } else { - histos.fill(HIST(hdcaxymat[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazmat[i]), track.pt(), track.dcaZ()); + // DCAxy for all primaries + histos.fill(HIST(hdcaxyprm[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazprm[i]), track.pt(), track.dcaZ()); } - } - } else { // Primaries - if (enableDCAxyzHistograms) { - hDcaXYZPrm[i]->Fill(track.pt(), track.dcaXY(), track.dcaZ()); if (enableDcaGoodEvents.value && collision.has_mcCollision()) { - histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY(), track.dcaZ()); + histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY()); + histos.fill(HIST(hdcazprmgoodevs[i]), track.pt(), track.dcaZ()); } - } else { - // DCAxy for all primaries - histos.fill(HIST(hdcaxyprm[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazprm[i]), track.pt(), track.dcaZ()); - } - if (enableDcaGoodEvents.value && collision.has_mcCollision()) { - histos.fill(HIST(hdcaxyprmgoodevs[i]), track.pt(), track.dcaXY()); - histos.fill(HIST(hdcazprmgoodevs[i]), track.pt(), track.dcaZ()); - } - if (enableDCAvsmotherHistograms) { - bool IsD0Mother = false; - bool IsCharmMother = false; - bool IsBeautyMother = false; - bool IsNotHFMother = false; - if (mcParticle.has_mothers()) { - 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) { - IsD0Mother = true; - } - if (charmOrigin == RecoDecay::OriginType::NonPrompt) { - IsBeautyMother = true; - } - if (charmOrigin == RecoDecay::OriginType::Prompt) { - IsCharmMother = true; - } - if (charmOrigin == RecoDecay::OriginType::None) { - IsNotHFMother = true; + if (enableDCAvsmotherHistograms) { + bool IsD0Mother = false; + bool IsCharmMother = false; + bool IsBeautyMother = false; + bool IsNotHFMother = false; + if (mcParticle.has_mothers()) { + 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) { + IsD0Mother = true; + } + if (charmOrigin == RecoDecay::OriginType::NonPrompt) { + IsBeautyMother = true; + } + if (charmOrigin == RecoDecay::OriginType::Prompt) { + IsCharmMother = true; + } + if (charmOrigin == RecoDecay::OriginType::None) { + IsNotHFMother = true; + } } } - } - if (IsD0Mother) { - hDcaXYMCD0[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMCD0[i]->Fill(track.pt(), track.dcaZ()); - } - if (IsCharmMother) { - hDcaXYMCCharm[i]->Fill(track.pt(), track.dcaXY()); - hdcaZMCCharm[i]->Fill(track.pt(), track.dcaZ()); - } - if (IsBeautyMother) { - hDcaXYMCBeauty[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMCBeauty[i]->Fill(track.pt(), track.dcaZ()); - } - if (IsNotHFMother) { - hDcaXYMCNotHF[i]->Fill(track.pt(), track.dcaXY()); - hDcaZMCNotHF[i]->Fill(track.pt(), track.dcaZ()); - } - - if (mcParticle.has_mothers()) { - for (const auto& mother : mcParticle.template mothers_as()) { - auto daughter0 = mother.template daughters_as().begin(); - double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; - double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; - auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); + if (IsD0Mother) { + hDcaXYMCD0[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMCD0[i]->Fill(track.pt(), track.dcaZ()); + } + if (IsCharmMother) { + hDcaXYMCCharm[i]->Fill(track.pt(), track.dcaXY()); + hdcaZMCCharm[i]->Fill(track.pt(), track.dcaZ()); + } + if (IsBeautyMother) { + hDcaXYMCBeauty[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMCBeauty[i]->Fill(track.pt(), track.dcaZ()); + } + if (IsNotHFMother) { + hDcaXYMCNotHF[i]->Fill(track.pt(), track.dcaXY()); + hDcaZMCNotHF[i]->Fill(track.pt(), track.dcaZ()); + } - if (IsD0Mother) { - hDecayLengthMCD0[i]->Fill(track.pt(), decayLength); - } - if (IsCharmMother) { - hDecayLengthMCCharm[i]->Fill(track.pt(), decayLength); - } - if (IsBeautyMother) { - hDecayLengthMCBeauty[i]->Fill(track.pt(), decayLength); - } - if (IsNotHFMother) { - hDecayLengthMCNotHF[i]->Fill(track.pt(), decayLength); + if (mcParticle.has_mothers()) { + for (const auto& mother : mcParticle.template mothers_as()) { + auto daughter0 = mother.template daughters_as().begin(); + double vertexDau[3] = {daughter0.vx(), daughter0.vy(), daughter0.vz()}; + double vertexMoth[3] = {mother.vx(), mother.vy(), mother.vz()}; + auto decayLength = RecoDecay::distance(vertexMoth, vertexDau); + + if (IsD0Mother) { + hDecayLengthMCD0[i]->Fill(track.pt(), decayLength); + } + if (IsCharmMother) { + hDecayLengthMCCharm[i]->Fill(track.pt(), decayLength); + } + if (IsBeautyMother) { + hDecayLengthMCBeauty[i]->Fill(track.pt(), decayLength); + } + if (IsNotHFMother) { + hDecayLengthMCNotHF[i]->Fill(track.pt(), decayLength); + } } } } } } + } else { + if (!mcParticle.isPhysicalPrimary()) { + if (mcParticle.getProcess() == 4) { + histos.fill(HIST(hdcaxystr[i]), track.pt(), track.dcaXY()); + } else { + histos.fill(HIST(hdcaxymat[i]), track.pt(), track.dcaXY()); + } + } else { + histos.fill(HIST(hdcaxyprm[i]), track.pt(), track.dcaXY()); + } } if ((collision.has_mcCollision() && (mcParticle.mcCollisionId() != collision.mcCollisionId())) || !collision.has_mcCollision()) { @@ -2049,15 +2059,19 @@ struct tofSpectra { } const int pdgCode = mcParticle.pdgCode(); const auto& nsigmaTPCPi = o2::aod::pidutils::tpcNSigma<2>(track); + const auto& nsigmaTPCKa = o2::aod::pidutils::tpcNSigma<3>(track); const auto& nsigmaTPCPr = o2::aod::pidutils::tpcNSigma<4>(track); const bool isPionTPC = std::abs(nsigmaTPCPi) < trkselOptions.cfgCutNsigma; + const bool isKaonTPC = std::abs(nsigmaTPCKa) < trkselOptions.cfgCutNsigma; const bool isProtonTPC = std::abs(nsigmaTPCPr) < trkselOptions.cfgCutNsigma; const auto& nsigmaTOFPi = o2::aod::pidutils::tofNSigma<2>(track); + const auto& nsigmaTOFKa = o2::aod::pidutils::tofNSigma<3>(track); const auto& nsigmaTOFPr = o2::aod::pidutils::tofNSigma<4>(track); const bool isPionTOF = std::abs(nsigmaTOFPi) < trkselOptions.cfgCutNsigma; + const bool isKaonTOF = std::abs(nsigmaTOFKa) < trkselOptions.cfgCutNsigma; const bool isProtonTOF = std::abs(nsigmaTOFPr) < trkselOptions.cfgCutNsigma; if (!mcParticle.isPhysicalPrimary()) { // Is not physical primary diff --git a/PWGLF/Tasks/QC/CMakeLists.txt b/PWGLF/Tasks/QC/CMakeLists.txt index f8c8e35cafa..126ec29b3e5 100644 --- a/PWGLF/Tasks/QC/CMakeLists.txt +++ b/PWGLF/Tasks/QC/CMakeLists.txt @@ -112,7 +112,7 @@ o2physics_add_dpl_workflow(mcinelgt0 o2physics_add_dpl_workflow(tracked-cascade-properties SOURCES trackedCascadeProperties.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(mc-particle-predictions diff --git a/PWGLF/Tasks/QC/trackedCascadeProperties.cxx b/PWGLF/Tasks/QC/trackedCascadeProperties.cxx index 04c7250208c..489e37e2608 100644 --- a/PWGLF/Tasks/QC/trackedCascadeProperties.cxx +++ b/PWGLF/Tasks/QC/trackedCascadeProperties.cxx @@ -16,99 +16,129 @@ /// \author Alberto Caliva (alberto.caliva@cern.ch), Francesca Ercolessi (francesca.ercolessi@cern.ch) /// \since May 31, 2024 -#include -#include -#include -#include -#include -#include -#include -#include +#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/PIDResponse.h" #include "Common/DataModel/Multiplicity.h" -#include "Common/Core/TrackSelection.h" +#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "Framework/ASoA.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "ReconstructionDataFormats/Track.h" #include "ReconstructionDataFormats/DCA.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include using namespace std; using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; +using namespace o2::constants::math; using std::array; +// Define type aliases for joined tables using SelectedCollisions = soa::Join; - using FullTracks = soa::Join; struct TrackedCascadeProperties { - // QC Histograms - HistogramRegistry registryQC{ - "registryQC", - {}, - OutputObjHandlingPolicy::AnalysisObject, - true, - true}; - - // Analysis Histograms: Data - HistogramRegistry registryData{ - "registryData", - {}, - OutputObjHandlingPolicy::AnalysisObject, - true, - true}; + // Instantiate the CCDB manager service and API interface + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + + // Instantiate the main Zorro processing object and define an output to store summary information + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + // Histogram registry for quality control + HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Histogram registry for data + HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Global Parameters Configurable zVtx{"zVtx", 10.0f, "z vertex cut"}; + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; + Configurable triggerList{"triggerList", "fTrackedOmega, fTrackedXi, fOmegaLargeRadius, fDoubleOmega, fOmegaHighMult, fSingleXiYN, fQuadrupleXi, fDoubleXi, fhadronOmega, fOmegaXi, fTripleXi, fOmega", "Trigger list"}; - // Mass Cuts + // Analysis Selections + Configurable minItsClustersCasc{"minItsClustersCasc", 4, "min ITS Clusters"}; Configurable massMinXi{"massMinXi", 1.315f, "mMin Xi"}; Configurable massMaxXi{"massMaxXi", 1.328f, "mMax Xi"}; Configurable massMinOmega{"massMinOmega", 1.665f, "mMin Omega"}; Configurable massMaxOmega{"massMaxOmega", 1.680f, "mMax Omega"}; + // Initialize CCDB access and histogram registry for Zorro processing + void initCCDB(aod::BCsWithTimestamps::iterator const& bc) + { + if (cfgSkimmedProcessing) { + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); + zorro.populateHistRegistry(registryData, bc.runNumber()); + } + } + void init(InitContext const&) { + if (cfgSkimmedProcessing) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + + // Quality Control Histograms registryQC.add("matchingChi2", "matching Chi2", HistType::kTH1F, {{200, 0, 1000, "#chi^{2}_{matching}"}}); registryQC.add("topologyChi2", "topology Chi2", HistType::kTH1F, {{500, 0, 0.5, "#chi^{2}_{topology}"}}); registryQC.add("nITScls_vs_p_xi", "nITS Xi", HistType::kTH2F, {{100, 0, 10, "#it{p} (GeV/#it{c})"}, {8, 0, 8, "n_{ITS}^{cls}"}}); registryQC.add("nITScls_vs_p_omega", "nITS Omega", HistType::kTH2F, {{100, 0, 10, "#it{p} (GeV/#it{c})"}, {8, 0, 8, "n_{ITS}^{cls}"}}); registryQC.add("decayXY", "decayXY", HistType::kTH2F, {{500, -50, 50, "x"}, {500, -50, 50, "y"}}); - registryQC.add("deltaClsSize", "deltaClsSize", HistType::kTH1F, {{40, -20, 20, "#DeltaClsSize"}}); - registryQC.add("deltaP", "deltaP", HistType::kTH1F, {{1000, -1, 1, "#Deltap"}}); - registryQC.add("deltaEta", "deltaEta", HistType::kTH1F, {{200, -0.5, 0.5, "#Delta#eta"}}); - registryQC.add("deltaNclsITS", "deltaNclsITS", HistType::kTH1F, {{20, -10, 10, "#DeltaN"}}); - registryQC.add("deltaNclsITS_track", "deltaNclsITS_track", HistType::kTH1F, {{20, -10, 10, "#DeltaN"}}); - registryQC.add("deltaNclsITS_itstrack", "deltaNclsITS_itstrack", HistType::kTH1F, {{20, -10, 10, "#DeltaN"}}); + // Event Counter registryData.add("number_of_events_data", "number of events in data", HistType::kTH1F, {{5, 0, 5, "Event Cuts"}}); - registryData.add("xi_pos_avgclustersize", "xi_pos_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("xi_neg_avgclustersize", "xi_neg_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("omega_pos_avgclustersize", "omega_pos_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("omega_neg_avgclustersize", "omega_neg_avgclustersize", HistType::kTH3F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT"}, {16, -0.8, 0.8, "#eta"}}); - registryData.add("xi_pos_avgclustersize_cosL", "xi_pos_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); - registryData.add("xi_neg_avgclustersize_cosL", "xi_neg_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); - registryData.add("omega_pos_avgclustersize_cosL", "omega_pos_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); - registryData.add("omega_neg_avgclustersize_cosL", "omega_neg_avgclustersize_cosL", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + // Average cluster size vs momentum + registryData.add("xi_pos_avgclustersize_cosL_vs_p", "xi_pos_avgclustersize_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("xi_neg_avgclustersize_cosL_vs_p", "xi_neg_avgclustersize_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_pos_avgclustersize_cosL_vs_p", "omega_pos_avgclustersize_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_neg_avgclustersize_cosL_vs_p", "omega_neg_avgclustersize_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + // Average cluster size vs betagamma registryData.add("xi_pos_avgclustersize_cosL_vs_betagamma", "xi_pos_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); registryData.add("xi_neg_avgclustersize_cosL_vs_betagamma", "xi_neg_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); registryData.add("omega_pos_avgclustersize_cosL_vs_betagamma", "omega_pos_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); registryData.add("omega_neg_avgclustersize_cosL_vs_betagamma", "omega_neg_avgclustersize_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + // Cluster size using truncated mean vs momentum + registryData.add("xi_pos_avgclustersize_trunc_cosL_vs_p", "xi_pos_avgclustersize_trunc_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("xi_neg_avgclustersize_trunc_cosL_vs_p", "xi_neg_avgclustersize_trunc_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_pos_avgclustersize_trunc_cosL_vs_p", "omega_pos_avgclustersize_trunc_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_neg_avgclustersize_trunc_cosL_vs_p", "omega_neg_avgclustersize_trunc_cosL_vs_p", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + + // Cluster size using truncated mean vs betagamma + registryData.add("xi_pos_avgclustersize_trunc_cosL_vs_betagamma", "xi_pos_avgclustersize_trunc_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("xi_neg_avgclustersize_trunc_cosL_vs_betagamma", "xi_neg_avgclustersize_trunc_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_pos_avgclustersize_trunc_cosL_vs_betagamma", "omega_pos_avgclustersize_trunc_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + registryData.add("omega_neg_avgclustersize_trunc_cosL_vs_betagamma", "omega_neg_avgclustersize_trunc_cosL_vs_betagamma", HistType::kTH2F, {{200, 0.0, 10.0, "#beta#gamma"}, {100, 0.0, 20.0, "#LT ITS cluster size #GT cos(#lambda)"}}); + + // mass histograms registryData.add("xi_mass_pos", "xi_mass_pos", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {200, 1.28, 1.36, "m_{p#pi#pi} (GeV/#it{c}^{2})"}}); registryData.add("xi_mass_neg", "xi_mass_neg", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {200, 1.28, 1.36, "m_{p#pi#pi} (GeV/#it{c}^{2})"}}); registryData.add("omega_mass_pos", "omega_mass_pos", HistType::kTH2F, {{100, 0.0, 10.0, "#it{p} (GeV/#it{c})"}, {200, 1.63, 1.71, "m_{p#piK} (GeV/#it{c}^{2})"}}); @@ -119,10 +149,10 @@ struct TrackedCascadeProperties { { double lambda(0); double theta = 2.0 * std::atan(std::exp(-eta)); - if (theta <= o2::constants::math::PIHalf) - lambda = o2::constants::math::PIHalf - theta; - if (theta > o2::constants::math::PIHalf) - lambda = theta - o2::constants::math::PIHalf; + if (theta <= PIHalf) + lambda = PIHalf - theta; + if (theta > PIHalf) + lambda = theta - PIHalf; return lambda; } @@ -137,59 +167,83 @@ struct TrackedCascadeProperties { } void processData(SelectedCollisions::iterator const& collision, aod::AssignedTrackedCascades const& trackedCascades, - aod::Cascades const&, FullTracks const&) + aod::Cascades const&, FullTracks const&, aod::BCsWithTimestamps const&) { + // Number of events before any selection registryData.fill(HIST("number_of_events_data"), 0.5); - if (!collision.sel8()) + + // Retrieve the bunch crossing information with timestamps from the collision + auto bc = collision.template bc_as(); + initCCDB(bc); + + // If skimmed processing is enabled, apply Zorro trigger selection + if (cfgSkimmedProcessing && !zorro.isSelected(collision.template bc_as().globalBC())) { return; + } + // Number of events after skimming selection registryData.fill(HIST("number_of_events_data"), 1.5); - if (std::abs(collision.posZ()) > zVtx) + if (!collision.sel8()) return; + // Number of events after sel8 registryData.fill(HIST("number_of_events_data"), 2.5); + if (std::abs(collision.posZ()) > zVtx) + return; + + // Number of events after zVtx cut + registryData.fill(HIST("number_of_events_data"), 3.5); + // radii of ITS layers std::vector edgesItsLayers = {0.0, 2.2, 2.8, 3.6, 20.0, 22.0, 37.0, 39.0, 100.0}; + // Loop over tracked cascades for (const auto& trackedCascade : trackedCascades) { + // Get tracked cascade const auto track = trackedCascade.track_as(); const auto trackITS = trackedCascade.itsTrack_as(); - - // Comparison between track and ITStrack - registryQC.fill(HIST("deltaP"), track.p() - trackITS.p()); - registryQC.fill(HIST("deltaEta"), track.eta() - trackITS.eta()); - registryQC.fill(HIST("deltaNclsITS"), track.itsNCls() - trackITS.itsNCls()); - - const int nItsLayers = 7; - for (int i = 0; i < nItsLayers; i++) { - registryQC.fill(HIST("deltaClsSize"), track.itsClsSizeInLayer(i) - trackITS.itsClsSizeInLayer(i)); - } - const auto& casc = trackedCascade.cascade(); const auto& btrack = casc.bachelor_as(); double dx = trackedCascade.decayX(); double dy = trackedCascade.decayY(); double r = std::sqrt(dx * dx + dy * dy); - int nClsCascade = findBin(edgesItsLayers, r); + int nItsLayersCrossed = findBin(edgesItsLayers, r); + // Fill QC histograms registryQC.fill(HIST("matchingChi2"), trackedCascade.matchingChi2()); registryQC.fill(HIST("topologyChi2"), trackedCascade.topologyChi2()); registryQC.fill(HIST("decayXY"), dx, dy); - // Calculate (Average) Cluster Size - double averageClusterSize(0); - int nCls(0); - for (int i = 0; i < nClsCascade; i++) { - int clusterSize = trackITS.itsClsSizeInLayer(i); - averageClusterSize += static_cast(clusterSize); - if (clusterSize > 0) + // Compute average cluster size and truncated mean + double sumClusterSize = 0.0; + double sumClusterSizeTrunc = 0.0; + double maxClusterSize = 0.0; + double averageClusterSize = 0.0; + double averageClusterSizeTrunc = 0.0; + int nCls = 0; + + for (int i = 0; i < nItsLayersCrossed; i++) { + double clusterSize = static_cast(trackITS.itsClsSizeInLayer(i)); + if (clusterSize > 0) { + sumClusterSize += clusterSize; + sumClusterSizeTrunc += clusterSize; nCls++; + if (clusterSize > maxClusterSize) { + maxClusterSize = clusterSize; + } + } + } + if (nCls > 0) { + averageClusterSize = sumClusterSize / static_cast(nCls); + } + if (nCls > 1) { + averageClusterSizeTrunc = (sumClusterSizeTrunc - maxClusterSize) / static_cast(nCls - 1); } - averageClusterSize = averageClusterSize / static_cast(nCls); - registryQC.fill(HIST("deltaNclsITS_track"), nCls - track.itsNCls()); - registryQC.fill(HIST("deltaNclsITS_itstrack"), nCls - trackITS.itsNCls()); + // Apply selection on number of ITS clusters + if (nCls < minItsClustersCasc) + continue; // Xi Mass if (btrack.sign() > 0) { @@ -199,21 +253,27 @@ struct TrackedCascadeProperties { registryData.fill(HIST("xi_mass_neg"), track.p(), trackedCascade.xiMass()); } - // Track Inclination + // Variables double lambda = trackInclination(track.eta()); + double clsSizeCosL = averageClusterSize * std::cos(lambda); + double clsSizeCosLtrunc = averageClusterSizeTrunc * std::cos(lambda); + double bgXi = track.p() / MassXiPlusBar; + double bgOmega = track.p() / MassOmegaPlusBar; // Xi if (trackedCascade.xiMass() > massMinXi && trackedCascade.xiMass() < massMaxXi) { registryQC.fill(HIST("nITScls_vs_p_xi"), track.p(), trackITS.itsNCls()); if (btrack.sign() > 0) { - registryData.fill(HIST("xi_pos_avgclustersize"), track.p(), averageClusterSize, track.eta()); - registryData.fill(HIST("xi_pos_avgclustersize_cosL"), track.p(), averageClusterSize * std::cos(lambda)); - registryData.fill(HIST("xi_pos_avgclustersize_cosL_vs_betagamma"), track.p() / o2::constants::physics::MassXiPlusBar, averageClusterSize * std::cos(lambda)); + registryData.fill(HIST("xi_pos_avgclustersize_cosL_vs_p"), track.p(), clsSizeCosL); + registryData.fill(HIST("xi_pos_avgclustersize_cosL_vs_betagamma"), bgXi, clsSizeCosL); + registryData.fill(HIST("xi_pos_avgclustersize_trunc_cosL_vs_p"), track.p(), clsSizeCosLtrunc); + registryData.fill(HIST("xi_pos_avgclustersize_trunc_cosL_vs_betagamma"), bgXi, clsSizeCosLtrunc); } if (btrack.sign() < 0) { - registryData.fill(HIST("xi_neg_avgclustersize"), track.p(), averageClusterSize, track.eta()); - registryData.fill(HIST("xi_neg_avgclustersize_cosL"), track.p(), averageClusterSize * std::cos(lambda)); - registryData.fill(HIST("xi_neg_avgclustersize_cosL_vs_betagamma"), track.p() / o2::constants::physics::MassXiMinus, averageClusterSize * std::cos(lambda)); + registryData.fill(HIST("xi_neg_avgclustersize_cosL_vs_p"), track.p(), clsSizeCosL); + registryData.fill(HIST("xi_neg_avgclustersize_cosL_vs_betagamma"), bgXi, clsSizeCosL); + registryData.fill(HIST("xi_neg_avgclustersize_trunc_cosL_vs_p"), track.p(), clsSizeCosLtrunc); + registryData.fill(HIST("xi_neg_avgclustersize_trunc_cosL_vs_betagamma"), bgXi, clsSizeCosLtrunc); } continue; } @@ -230,14 +290,16 @@ struct TrackedCascadeProperties { if (trackedCascade.omegaMass() > massMinOmega && trackedCascade.omegaMass() < massMaxOmega) { registryQC.fill(HIST("nITScls_vs_p_omega"), track.p(), trackITS.itsNCls()); if (btrack.sign() > 0) { - registryData.fill(HIST("omega_pos_avgclustersize"), track.p(), averageClusterSize, track.eta()); - registryData.fill(HIST("omega_pos_avgclustersize_cosL"), track.p(), averageClusterSize * std::cos(lambda)); - registryData.fill(HIST("omega_pos_avgclustersize_cosL_vs_betagamma"), track.p() / o2::constants::physics::MassOmegaPlusBar, averageClusterSize * std::cos(lambda)); + registryData.fill(HIST("omega_pos_avgclustersize_cosL_vs_p"), track.p(), clsSizeCosL); + registryData.fill(HIST("omega_pos_avgclustersize_cosL_vs_betagamma"), bgOmega, clsSizeCosL); + registryData.fill(HIST("omega_pos_avgclustersize_trunc_cosL_vs_p"), track.p(), clsSizeCosLtrunc); + registryData.fill(HIST("omega_pos_avgclustersize_trunc_cosL_vs_betagamma"), bgOmega, clsSizeCosLtrunc); } if (btrack.sign() < 0) { - registryData.fill(HIST("omega_neg_avgclustersize"), track.p(), averageClusterSize, track.eta()); - registryData.fill(HIST("omega_neg_avgclustersize_cosL"), track.p(), averageClusterSize * std::cos(lambda)); - registryData.fill(HIST("omega_neg_avgclustersize_cosL_vs_betagamma"), track.p() / o2::constants::physics::MassOmegaMinus, averageClusterSize * std::cos(lambda)); + registryData.fill(HIST("omega_neg_avgclustersize_cosL_vs_p"), track.p(), clsSizeCosL); + registryData.fill(HIST("omega_neg_avgclustersize_cosL_vs_betagamma"), bgOmega, clsSizeCosL); + registryData.fill(HIST("omega_neg_avgclustersize_trunc_cosL_vs_p"), track.p(), clsSizeCosLtrunc); + registryData.fill(HIST("omega_neg_avgclustersize_trunc_cosL_vs_betagamma"), bgOmega, clsSizeCosLtrunc); } } } diff --git a/PWGLF/Tasks/Resonances/CMakeLists.txt b/PWGLF/Tasks/Resonances/CMakeLists.txt index 4ba33fce401..709643f75f4 100644 --- a/PWGLF/Tasks/Resonances/CMakeLists.txt +++ b/PWGLF/Tasks/Resonances/CMakeLists.txt @@ -19,6 +19,11 @@ o2physics_add_dpl_workflow(phianalysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(cksspinalignder + SOURCES cksspinalignder.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(k892analysis SOURCES k892analysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -39,13 +44,23 @@ o2physics_add_dpl_workflow(k892pmanalysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(lambda1405analysis + SOURCES lambda1405analysis.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(lambda1520analysis SOURCES lambda1520analysis.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(lstaranalysis - SOURCES lstaranalysis.cxx +o2physics_add_dpl_workflow(lambda1520analysisinpp + SOURCES lambda1520analysisinpp.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambda1520analysisinoo + SOURCES lambda1520analysisinOO.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) @@ -54,6 +69,11 @@ o2physics_add_dpl_workflow(k1analysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(k1analysismicro + SOURCES k1AnalysisMicro.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(phianalysisrun3 SOURCES phianalysisrun3.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -213,3 +233,13 @@ o2physics_add_dpl_workflow(double-resonance-scan SOURCES doubleResonanceScan.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(kstarinoo + SOURCES kstarInOO.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + + o2physics_add_dpl_workflow(phioo + SOURCES phiOO.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx index 8286f876bc8..536d7a2d030 100644 --- a/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/chargedkstaranalysis.cxx @@ -14,26 +14,12 @@ /// /// /// \author Protay +/// \author Navneet -#include "TF1.h" -// #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/collisionCuts.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" +#include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelection.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" @@ -41,110 +27,177 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.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 "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" -// For charged kstarpp analysis -#include "PWGLF/DataModel/LFResonanceTables.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 // FIXME + +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; -using std::array; +using namespace o2::constants::physics; struct chargedkstaranalysis { - - // Connect to ccdb SliceCache cache; - Preslice perRCol = aod::resodaughter::resoCollisionId; Preslice perCollision = aod::track::collisionId; - // For charged Kstarpp analysis use Resonance Initalizer and THnSparse - ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 1., 5., 10., 30., 50., 70., 100., 110.}, "Binning of the centrality axis"}; - 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 etabins{"etabins", - {VARIABLE_WIDTH, -1.0, -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, 1.0}, - "Eta Binning"}; - Configurable cDCABinsQA{"cDCABinsQA", 150, "DCA binning"}; - 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"}; - - AxisSpec k892pmCountAxis = {2, 0., 2., "K*^{+}(892) = 1, K*^{-}(892) = 2"}; - - HistogramRegistry histos1{ - "histos1", - {}, - OutputObjHandlingPolicy::AnalysisObject, - true, - true}; - - // Pre-selection cuts - Configurable cMinPtcut{"cMinPtcut", 0.15, "Track minimum pt cut"}; - Configurable confevtcollintimerangestandard{"confevtcollintimerangestandard", true, "Evt sel: apply NoCollInTimeRangeStandard"}; - /// PID Selections - Configurable nsigmaCutCombinedPion{"nsigmaCutCombinedPion", -999, - "Combined nSigma cut for Pion"}; // Combined - // DCAr to PV - Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.5, - "Track DCAr cut to PV Maximum"}; - // DCAz to PV - Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, - "Track DCAz cut to PV Maximum"}; - // 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 cfgPVContributor{"cfgPVContributor", true, - "PV contributor track selection"}; // PV Contributor - // V0 selections - Configurable cV0MinCosPA{"cV0MinCosPA", 0.97, - "V0 minimum pointing angle cosine"}; - Configurable cV0MaxDaughDCA{"cV0MaxDaughDCA", 1.0, - "V0 daughter DCA Maximum"}; - // Competing V0 rejection - Configurable cV0MassWindow{"cV0MassWindow", 0.0043, "Mass window for competing Lambda0 rejection"}; - Configurable cInvMassStart{"cInvMassStart", 0.6, "Invariant mass start"}; - Configurable cInvMassEnd{"cInvMassEnd", 1.5, "Invariant mass end"}; - Configurable cInvMassBins{"cInvMassBins", 900, "Invariant mass binning"}; - - // Rapidity Cut - Configurable confRapidity{"confRapidity", 0.5, "Rapidity cut"}; - - // Event mixing + using EventCandidates = soa::Join; + // using EventCandidates = soa::Join; + // using TrackCandidates = soa::Join; + // using TrackCandidates = 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}; + 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., 1., 5., 10., 30., 50., 70., 100., 110.}, "Mixing bins - multiplicity"}; - Configurable cTpcNsigmaPionBinsQA{"cTpcNsigmaPionBinsQA", 140, "tpcNSigmaPi binning"}; - // Configurable for histograms - Configurable nBins{"nBins", 100, "N bins in all histos"}; + 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"}; + + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 2.0, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable cMinDCAzToPVcut{"cMinDCAzToPVcut", 0.0, "Track DCAz cut to PV Minimum"}; + + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + + Configurable trackSelection{"trackSelection", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQ ualityTracks, 5 -> kInAcceptanceTracks"}; + // + // Filter trackFilter = (trackSelection.node() == 0) || // from tpcSkimsTableCreator + // ((trackSelection.node() == 1) && requireGlobalTrackInFilter()) || + // ((trackSelection.node() == 2) && requireGlobalTrackWoPtEtaInFilter()) || + // ((trackSelection.node() == 3) && requireGlobalTrackWoDCAInFilter()) || + // ((trackSelection.node() == 4) && requireQualityTracksInFilter()) || + // ((trackSelection.node() == 5) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); + // Filter trackEtaFilter = nabs(aod::track::eta) < cfgCutEta; // Eta cut + // + // 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"}; + + 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"}; - // Configurable parameters for V0 selection - Configurable confdaugheta{"confdaugheta", 0.8f, "V0 Daugh sel: max eta"}; - Configurable nSigmaCutTPC{"nSigmaCutTPC", 3.0, "Value of the TPC Nsigma cut"}; - Configurable nSigmaCutTOF{"nSigmaCutTOF", 3.0, - "Value of the TOF Nsigma cut"}; - Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "Value of the Combined Nsigma cut"}; - Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; + /// 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{"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"}; + 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 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"}; // For rotational background Configurable fillRotation{"fillRotation", true, "fill rotation"}; @@ -152,382 +205,735 @@ struct chargedkstaranalysis { 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"}; - void init(InitContext const&) + float centrality; + + // PDG code + int kPDGK0s = 310; + int kKstarPlus = static_cast(o2::constants::physics::Pdg::kKPlusStar892); + int kPiPlus = 211; + int kPDGK0 = 311; + + void init(o2::framework::InitContext&) { - AxisSpec dcaxyAxisQA = {cDCABinsQA, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; - AxisSpec dcazAxisQA = {cDCABinsQA, 0.0, 3.0, "DCA_{#it{xy}} (cm)"}; - AxisSpec ptAxisQA = {binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec tpcNSigmaPiAxisQA = {cTpcNsigmaPionBinsQA, -7.0, 7.0, - "N#sigma_{TPC}"}; + 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 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 centAxis = {binsCent, "V0M (%)"}; - AxisSpec ptAxis = {binsPt, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec invMassAxis = {cInvMassBins, cInvMassStart, cInvMassEnd, - "Invariant Mass (GeV/#it{c}^2)"}; - AxisSpec etaAxis = {etabins, "#eta"}; - AxisSpec goodTrackCountAxis = { - 3, 0., 3., "Passed track = 1, Passed V0 = 2, Passed track and V0 = 3"}; - // register histograms - histos1.add("hVertexZ", "hVertexZ", HistType::kTH1F, {{nBins, -15., 15.}}); - // Multiplicity and accepted events QA - histos1.add("QAbefore/collMult", "Collision multiplicity", HistType::kTH1F, - {centAxis}); - // QA before - histos1.add("QAbefore/pi_Eta", "Primary pion track eta", kTH1F, {etaAxis}); - histos1.add("QAbefore/k0s_Eta", "K0short track eta", kTH1F, {etaAxis}); - histos1.add("QAbefore/chargedkstarpmRapidity", - "Reconstructed K*^{#pm} rapidity", kTH1F, {etaAxis}); - histos1.add("QAbefore/trkpionTOFPID", "TOF PID of bachelor pion candidates", HistType::kTH2D, {ptAxisQA, pidQAAxis}); - histos1.add("QAbefore/trkpionTPCTOFPID", "TPC-TOF PID map of bachelor pion candidates", HistType::kTH2D, {pidQAAxis, pidQAAxis}); - - histos1.add("QAbefore/DCAxy_pi", - "DCAxy distribution of pion track candidates", HistType::kTH1F, - {dcaxyAxisQA}); - histos1.add("QAbefore/DCAz_pi", - "DCAz distribution of pion track candidates", HistType::kTH1F, - {dcazAxisQA}); - histos1.add("QAbefore/pT_pi", "pT distribution of pion track candidates", - kTH1F, {ptAxisQA}); - histos1.add("QAbefore/tpcNsigmaPionQA", - "NsigmaTPC distribution of primary pion candidates", kTH2F, - {ptAxisQA, tpcNSigmaPiAxisQA}); - - // QA after - histos1.add("QAAfter/DCAxy_pi", - "DCAxy distribution of pion track candidates", HistType::kTH1F, - {dcaxyAxisQA}); - histos1.add("QAAfter/DCAz_pi", "DCAz distribution of pion track candidates", - HistType::kTH1F, {dcazAxisQA}); - histos1.add("QAAfter/pT_pi", "pT distribution of pion track candidates", - kTH1F, {ptAxisQA}); - histos1.add("QAAfter/tpcNsigmaPionQA", - "NsigmaTPC distribution of primary pion candidates", kTH2F, - {ptAxisQA, tpcNSigmaPiAxisQA}); - histos1.add("QAAfter/pi_Eta", "Primary pion track eta", kTH1F, {etaAxis}); - - // Good tracks and V0 counts QA - histos1.add("QAafter/hGoodTracksV0s", "Number of good track and V0 passed", - kTH1F, {goodTrackCountAxis}); - histos1.add("chargedkstarinvmassUlikeSign", - "Invariant mass of charged K*(892)", kTH1F, {invMassAxis}); - histos1.add("chargedkstarinvmassMixedEvent", - "Invariant mass of charged K*(892)", kTH1F, {invMassAxis}); - - // Mass vs Pt vs Multiplicity 3-dimensional histogram - // histos1.add("chargekstarMassPtMult", "Charged K*(892) mass vs pT vs V0 - // multiplicity distribution", kTH3F, {invMassAxis, ptAxis, centAxis}); - - histos1.add("chargekstarMassPtMultPtUnlikeSign", - "Invariant mass of CKS meson Unlike Sign", kTHnSparseF, - {invMassAxis, ptAxis, centAxis}, true); - histos1.add("hSparseChargeKstarSameEventRotational", "hSparseChargeKstarSameEventRotational", HistType::kTHnSparseF, {invMassAxis, ptAxis, centAxis}, true); - - histos1.add("chargekstarMassPtMultPtMixedEvent", - "Invariant mass of CKS meson MixedEvent Sign", kTHnSparseF, - {invMassAxis, ptAxis, centAxis}, true); + AxisSpec dataTypeAxis = {9, 0, 9, "Histogram types"}; + AxisSpec mcTypeAxis = {4, 0, 4, "Histogram types"}; + + // 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 (fillRotation) { - histos1.add("hRotation", "hRotation", kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); + histos.add("hRotation", "hRotation", kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); + } + // 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/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()); } - // for MC production - if (doprocessMCTrue) { - // DEBUG HISTOGRAMS - histos1.add("hK892pmCounter", "Generated MC resonances", kTH1F, {k892pmCountAxis}); - histos1.add("k892pmPtGen", "pT distribution of True MC charged K*(892)", kTH1F, {ptAxis}); - histos1.add("k892pPtGen", "pT distribution of True MC K*(892) Plus", kTH1F, {ptAxis}); - histos1.add("k892mPtGen", "pT distribution of True MC K*(892) Minus", kTH1F, {ptAxis}); + // Print output histograms statistics + LOG(info) << "Size of the histograms in chK(892) Analysis Task"; + histos.print(); + } + + // 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; + } + + template + bool isTrackSelected(TrackType const& track) + { + // Track selection + // These are the track selection for the resotracks this cut is to compare the no. of tracks after reso-initializer + // MC case can be handled here + // DCAxy cut + if (std::fabs(track.dcaXY()) > cMaxDCArToPVcut) + return false; + // DCAz cut + if (std::fabs(track.dcaZ()) > cMaxDCAzToPVcut || std::fabs(track.dcaZ()) < cMinDCAzToPVcut) + 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; + } + } - // histos.add("hDaughterCounter", "Generated MC resonance daughters", kTH1F, {daughterCountAxis}); + if (tpcPIDPassed && tofPIDPassed) { + return true; } - if (doprocessMCLight) { - // MC QA - histos1.add("k892pmPtRec", "pT distribution of Reconstructed MC charged K*(892)", kTH1F, {ptAxis}); + 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 v0Radius = candidate.v0radius(); + auto DCAtoPV = candidate.dcav0topv(); + auto cosPA = candidate.v0cosPA(); + auto PropTauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0s; + 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 (v0Radius < cSecondaryRadiusMin) { + histos.fill(HIST("QA/K0sCutCheck"), 6); + returnFlag = false; + } + if (DCAtoPV > cSecondaryDCAtoPVMax) { + histos.fill(HIST("QA/K0sCutCheck"), 7); + returnFlag = false; + } + if (cosPA < cSecondaryCosPAMin) { + histos.fill(HIST("QA/K0sCutCheck"), 8); + returnFlag = false; + } + if (PropTauK0s > cSecondaryProperLifetimeMax) { + histos.fill(HIST("QA/K0sCutCheck"), 9); + returnFlag = false; + } + if (std::fabs(mK0s - massK0s) > cSecondaryMassWindow) { + histos.fill(HIST("QA/K0sCutCheck"), 10); + returnFlag = false; + } + + return returnFlag; + + } else { + if (std::fabs(mK0s - massK0s) > 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 (v0Radius < cSecondaryRadiusMin) { + histos.fill(HIST("QA/K0sCutCheck"), 6); + return false; + } + if (DCAtoPV > cSecondaryDCAtoPVMax) { + histos.fill(HIST("QA/K0sCutCheck"), 7); + return false; + } + if (cosPA < cSecondaryCosPAMin) { + histos.fill(HIST("QA/K0sCutCheck"), 8); + return false; + } + if (PropTauK0s > cSecondaryProperLifetimeMax) { + histos.fill(HIST("QA/K0sCutCheck"), 9); + return false; + } + if (std::fabs(mK0s - massK0s) > cSecondaryMassWindow) { + histos.fill(HIST("QA/K0sCutCheck"), 10); + return false; + } + return true; + + } else { + if (std::fabs(mK0s - massK0s) > cSecondaryMassWindow) { + histos.fill(HIST("QA/K0sCutCheck"), 10); + return false; + } + return true; + } } + } // selectionK0s + + template + bool isTrueKstar(const TrackTemplate& bTrack, const V0Template& K0scand) + { + if (std::abs(bTrack.PDGCode()) != kPiPlus) // Are you pion? + return false; + if (std::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 (std::abs(motherbTrack.pdgCode()) != kKstarPlus) // Are you charged Kstar's daughter? + return false; // Apply first since it's more restrictive + + if (std::abs(motherkV0.pdgCode()) != kPDGK0) // Is it K0s? + return false; + // Check if K0s's mother is K0 (311) + auto motherK0 = motherkV0.template mothers_as(); + if (std::abs(motherK0.pdgCode()) != kPDGK0) + return false; + + // Check if K0's mother is Kstar (323) + auto motherKstar = motherK0.template mothers_as(); + if (std::abs(motherKstar.pdgCode()) != kKstarPlus) + 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; double massPi = o2::constants::physics::MassPionCharged; double massK0s = o2::constants::physics::MassK0Short; - double massKa = o2::constants::physics::MassKPlus; - ROOT::Math::PtEtaPhiMVector cksvector; - - double massK0 = o2::constants::physics::MassK0Short; - double massPicharged = o2::constants::physics::MassPionCharged; - double massLambda0 = o2::constants::physics::MassLambda; - double massAntiLambda0 = o2::constants::physics::MassLambda0Bar; - // Fill histograms (main function) - template - void fillHistograms(const CollisionType& collision, const TracksType& dTracks, - const V0sType& dV0s) + + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksTypeK0s& dTracks2) { - // auto multiplicity = collision.cent(); - auto multiplicity = collision.cent(); - histos1.fill(HIST("QAbefore/collMult"), multiplicity); - TLorentzVector lDecayDaughter, lDecayV0, lResonance, pionrot, chargekstarrot; - - for (const auto& track : dTracks) { // loop over all dTracks1 to find the bachelor pion - auto trackId = track.index(); - auto trackptPi = track.pt(); - auto tracketaPi = track.eta(); - auto istrkhasTOF = track.hasTOF(); - auto trkNSigmaPiTPC = track.tpcNSigmaPi(); - auto trkNSigmaPiTOF = (istrkhasTOF) ? track.tofNSigmaPi() : -999.; - - histos1.fill(HIST("QAbefore/pi_Eta"), tracketaPi); - - if (!IsMix) { - // TPC PID (before cuts) - histos1.fill(HIST("QAbefore/tpcNsigmaPionQA"), trackptPi, trkNSigmaPiTPC); - if (istrkhasTOF) { - histos1.fill(HIST("QAbefore/trkpionTOFPID"), trackptPi, trkNSigmaPiTOF); - histos1.fill(HIST("QAbefore/trkpionTPCTOFPID"), trkNSigmaPiTPC, trkNSigmaPiTOF); - } - // DCA QA (before cuts) - histos1.fill(HIST("QAbefore/DCAxy_pi"), track.dcaXY()); - histos1.fill(HIST("QAbefore/DCAz_pi"), track.dcaZ()); - // Pseudo-rapidity QA (before cuts) - histos1.fill(HIST("QAbefore/pi_Eta"), tracketaPi); - // pT QA (before cuts) - histos1.fill(HIST("QAbefore/pT_pi"), trackptPi); + 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 = {}; + + for (const auto& bTrack : dTracks1) { + auto trkbpt = bTrack.pt(); + auto istrkbhasTOF = bTrack.hasTOF(); + auto trkbNSigmaPiTPC = bTrack.tpcNSigmaPi(); + auto trkbNSigmaPiTOF = (istrkbhasTOF) ? bTrack.tofNSigmaPi() : -999.; + + if (!isTrackSelected(bTrack)) + continue; + 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()); + } else { + + histos.fill(HIST("QA/trkbpionTPCPIDME"), trkbpt, trkbNSigmaPiTPC); } - // apply the track cut - if (!trackCutpp(track) || !selectionPIDpp(track)) + if (!trackCut(bTrack)) + continue; + if (!selectionPIDPion(bTrack)) continue; - histos1.fill(HIST("QAafter/hGoodTracksV0s"), 0.5); - - if (!IsMix) { - // DCA QA (before cuts) - histos1.fill(HIST("QAAfter/DCAxy_pi"), track.dcaXY()); - histos1.fill(HIST("QAAfter/DCAz_pi"), track.dcaZ()); - // Pseudo-rapidity QA (before cuts) - histos1.fill(HIST("QAAfter/pi_Eta"), tracketaPi); - // pT QA (before cuts) - histos1.fill(HIST("QAAfter/pT_pi"), trackptPi); - // TPC PID (before cuts) - histos1.fill(HIST("QAAfter/tpcNsigmaPionQA"), trackptPi, - track.tpcNSigmaPi()); + 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 (const auto& v0 : dV0s) { + 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 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 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/hInvmassSecondary"), trkkMass); + } - // Full index policy is needed to consider all possible combinations - if (v0.indices()[0] == trackId || v0.indices()[1] == trackId) - continue; // To avoid combining secondary and primary pions - //// Initialize variables - // trk: Pion, v0: K0s - // apply the track cut - if (!v0cut(v0)) - continue; - histos1.fill(HIST("QAafter/hGoodTracksV0s"), 1.5); + // 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 - lDecayDaughter.SetXYZM(track.px(), track.py(), track.pz(), massPi); - lDecayV0.SetXYZM(v0.px(), v0.py(), v0.pz(), massK0); - lResonance = lDecayDaughter + lDecayV0; - // Counting how many resonances passed - histos1.fill(HIST("QAafter/hGoodTracksV0s"), 2.5); + 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/hInvmassSecondary"), trkkMass); + } + k0sIndicies.push_back(K0scand.index()); + } - // Checking whether the mid-rapidity condition is met - if (std::abs(lResonance.Rapidity()) > confRapidity) + 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); + 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) { - histos1.fill(HIST("chargedkstarinvmassUlikeSign"), lResonance.M()); - // Reconstructed K*(892)pm 3d mass, pt, multiplicity histogram - histos1.fill(HIST("chargekstarMassPtMultPtUnlikeSign"), - lResonance.M(), lResonance.Pt(), multiplicity); - if constexpr (IsMC) { - bool pass1 = false; - bool pass2 = false; - // LOG(info) << "track PDG:\t" << trk.pdgCode() << "\tV0 PDG:\t" << v0.pdgCode(); - if ((track.pdgCode() != PDG_t::kPiPlus) && (v0.pdgCode() != PDG_t::kK0Short)) { // One decay to K0s and the other to pi+ (K*(892)+ mother) - Particle pass - pass1 = true; - } - if ((track.pdgCode() != PDG_t::kPiMinus) && (v0.pdgCode() != -310)) { // One decay to K0s and the other to pi+ (K*(892)+ mother) - Particle pass - pass2 = true; - } - if (!pass1 && !pass2) // Go on only if we have both decay products, else skip to next iteration - continue; - if (track.motherPDG() != v0.motherPDG()) - continue; - // LOG(info) << "track PDG:\t" << trk.pdgCode() << "\tV0 PDG:\t" << v0.pdgCode(); - if (track.motherPDG() != o2::constants::physics::Pdg::kKPlusStar892) - continue; - histos1.fill(HIST("k892pmPtRec"), lResonance.Pt()); - } + + 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()); + } else { - histos1.fill(HIST("chargedkstarinvmassMixedEvent"), lResonance.M()); - // Reconstructed K*(892)pm 3d mass, pt, multiplicity histogram - histos1.fill(HIST("chargekstarMassPtMultPtMixedEvent"), - lResonance.M(), lResonance.Pt(), multiplicity); + + histos.fill(HIST("hInvmass_KstarME"), collision.centFT0M(), lResoKstar.Pt(), lResoKstar.M()); } if constexpr (!IsMix) { if (fillRotation) { for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { - auto rotangle = o2::constants::math::PI; + auto rotangle = o2::constants::math::PI; // If there is only one rotation then it should be pi ): if (nBkgRotations > 1) { auto anglestart = confMinRot; auto angleend = confMaxRot; auto anglestep = (angleend - anglestart) / (1.0 * (nBkgRotations - 1)); rotangle = anglestart + nrotbkg * anglestep; } - histos1.fill(HIST("hRotation"), rotangle); - auto rotpionPx = lDecayDaughter.Px() * std::cos(rotangle) - lDecayDaughter.Py() * std::sin(rotangle); - auto rotpionPy = lDecayDaughter.Px() * std::sin(rotangle) + lDecayDaughter.Py() * std::cos(rotangle); - pionrot.SetXYZM(rotpionPx, rotpionPy, lDecayDaughter.Pz(), massPi); - chargekstarrot = pionrot + lDecayV0; - if (std::abs(chargekstarrot.Rapidity()) > confRapidity) { + 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() > cKstarMaxRap || chargekstarrot.Rapidity() < cKstarMinRap) continue; - } - histos1.fill(HIST("hSparseChargeKstarSameEventRotational"), chargekstarrot.M(), chargekstarrot.Pt(), multiplicity); + histos.fill(HIST("hInvmass_KstarRotated"), collision.centFT0M(), chargekstarrot.Pt(), chargekstarrot.M()); } } } - } - } - } + } // K0scand + } // bTrack - template - bool selectionPIDpp(const T& candidate) - { - bool tpcPIDPassed{false}, tofPIDPassed{false}; - if (std::abs(candidate.tpcNSigmaPi()) < nSigmaCutTPC) { - tpcPIDPassed = true; - } - if (candidate.hasTOF()) { - if (std::abs(candidate.tofNSigmaPi()) < nSigmaCutTOF) { - tofPIDPassed = true; - } - if ((nsigmaCutCombinedPion > 0) && - (candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + - candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < - nsigmaCutCombinedPion * nsigmaCutCombinedPion)) { - tofPIDPassed = true; - } - } else { - tofPIDPassed = true; - } - if (tpcPIDPassed && tofPIDPassed) { - return true; - } - return false; - } + count++; - template - bool trackCutpp(const TrackType track) - { - // basic track cuts - if (std::abs(track.pt()) < cMinPtcut) - return false; - if (std::abs(track.eta()) > confdaugheta) - return false; - if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) - return false; - if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) - return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) - return false; - if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) - return false; - if (cfgPVContributor && !track.isPVContributor()) - return false; + } // fillHistograms - return true; - } - template - bool v0cut(const V0Type v0) + // process data + void processDataSE(EventCandidates::iterator const& collision, + TrackCandidates const& tracks, + V0Candidates const& v0s, + aod::BCsWithTimestamps const&) { - // V0 track cuts - if (std::abs(v0.eta()) > confdaugheta) - return false; - if (v0.v0CosPA() < cV0MinCosPA) - return false; - if (v0.daughDCA() > cV0MaxDaughDCA) - return false; - - // apply the competing V0 rejection cut (excluding Lambda0 candidates, - // massLambdaPDG = 1115.683 MeV/c2) - - if (std::abs(v0.mLambda() - massLambda0) < cV0MassWindow) - return false; - if (std::abs(v0.mAntiLambda() - massAntiLambda0) < cV0MassWindow) - return false; - - return true; + if (!colCuts.isSelected(collision)) // Default event selection + return; + colCuts.fillQA(collision); + fillHistograms(collision, tracks, v0s); } + PROCESS_SWITCH(chargedkstaranalysis, processDataSE, "Process Event for data without Partitioning", true); - /* - SameKindPair - pair{binningOnPositions, cfgNoMixedEvents, -1, &cache}; - */ + using BinningTypeVtxZT0M = ColumnBinningPolicy; - void processSEnew(aod::ResoCollision const& collision, - aod::ResoTracks const& resotracks, - aod::ResoV0s const& resov0s) - { - // Fill the event counter - histos1.fill(HIST("hVertexZ"), collision.posZ()); - fillHistograms(collision, resotracks, - resov0s); // Fill histograms, no MC, no mixing - } - PROCESS_SWITCH(chargedkstaranalysis, processSEnew, "Process Same event new", - true); - - using BinningTypeVtxZT0M = - ColumnBinningPolicy; - void processMEnew(aod::ResoCollisions const& collisions, - aod::ResoTracks const& resotracks, - aod::ResoV0s const& resov0s) + // using BinningTypeVtxZT0M = ColumnBinningPolicy>; + BinningTypeVtxZT0M colBinning{{cfgvtxbins, cfgmultbins}, true}; + void processDataME(EventCandidates const& collisions, TrackCandidates const& tracks, V0Candidates const& v0s) { - auto tracksV0sTuple = std::make_tuple(resotracks, resov0s); - auto v0stuple = std::make_tuple(resov0s); - BinningTypeVtxZT0M colBinning{{cfgvtxbins, cfgmultbins}, true}; - Pair - pairs{colBinning, nEvtMixing, -1, collisions, - tracksV0sTuple, &cache}; // -1 is the number of the bin to skip - for (const auto& [c1, restrk1, c2, resov0s2] : pairs) { + auto tracksV0sTuple = std::make_tuple(tracks, v0s); + + Pair pair{colBinning, nEvtMixing, -1, collisions, tracksV0sTuple, &cache}; + // restrk1 is a TrackCandidates table of tracks belonging to collision c1 (aod::Collision::iterator) + // resov0s2 is a V0Candidates table of V0s belonging to collision c2 (aod::Collision::iterator) + for (const auto& [c1, restrk1, c2, resov0s2] : pair) { + if (!colCuts.isSelected(c1) || !colCuts.isSelected(c2)) { + // Default event selection + continue; + } + colCuts.fillQA(c1); fillHistograms(c1, restrk1, resov0s2); } + // fillHistograms(collision, tracks, v0s); // second order } - PROCESS_SWITCH(chargedkstaranalysis, processMEnew, "Process Mixed events new", - true); + PROCESS_SWITCH(chargedkstaranalysis, processDataME, "Process Event for data without Partitioning", true); - void processMCTrue(aod::ResoMCParents const& resoParents) + // process MC reconstructed level + void processMC(MCEventCandidates::iterator const& collision, + MCTrackCandidates const& tracks, + MCV0Candidates const& v0s) { - for (const auto& part : resoParents) { // loop over all pre-filtered MC particles - if (std::abs(part.pdgCode()) != o2::constants::physics::Pdg::kKPlusStar892) // K*892(pm) - continue; - if (std::abs(part.y()) > 0.5) // rapidity cut - continue; - bool pass1 = false; - bool pass2 = false; - if (part.daughterPDG1() == PDG_t::kPiPlus && part.daughterPDG2() == PDG_t::kK0Short) { // One decay to K0s and the other to pi+ (K*(892)+ mother) - Particle pass - pass1 = true; - histos1.fill(HIST("hK892pmCounter"), 0.5); - histos1.fill(HIST("k892pPtGen"), part.pt()); - } - if (part.daughterPDG1() == PDG_t::kPiMinus && part.daughterPDG2() == -310) { // One decay to AntiK0s and the other to pi- (K*(892)- mother) - Antiparticle pass - pass2 = true; - histos1.fill(HIST("hK892pmCounter"), 1.5); - histos1.fill(HIST("k892mPtGen"), part.pt()); - } - if (!pass1 && !pass2) // Go on only if we have both decay products, else skip to next iteration - continue; - histos1.fill(HIST("k892pmPtGen"), part.pt()); - } - } - PROCESS_SWITCH(chargedkstaranalysis, processMCTrue, "Process Event for MC", false); + // histos.fill(HIST("QAMC/hEvent"), 1.0); - void processMCLight(aod::ResoCollision const& collision, - soa::Join const& resotracks, - soa::Join const& resov0s) - { - fillHistograms(collision, resotracks, resov0s); + fillHistograms(collision, tracks, v0s); } - PROCESS_SWITCH(chargedkstaranalysis, processMCLight, "Process Event for MC", false); + PROCESS_SWITCH(chargedkstaranalysis, processMC, "Process Event for MC", false); }; - WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{adaptAnalysisTask(cfgc)}; diff --git a/PWGLF/Tasks/Resonances/chk892Flow.cxx b/PWGLF/Tasks/Resonances/chk892Flow.cxx index 18e21f5dd11..2c616d81406 100644 --- a/PWGLF/Tasks/Resonances/chk892Flow.cxx +++ b/PWGLF/Tasks/Resonances/chk892Flow.cxx @@ -118,6 +118,7 @@ struct Chk892Flow { 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"}; + ConfigurableAxis cfgBinsOccu{"cfgBinsOccu", {VARIABLE_WIDTH, 0, 500, 1000, 2500, 9999}, "Binning of the occupancy 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"}; ConfigurableAxis cfgAxisV2{"cfgAxisV2", {200, -1, 1}, "Binning of the v2 axis (+-1 for EP method)"}; @@ -136,8 +137,8 @@ struct Chk892Flow { 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 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)"}; @@ -257,7 +258,7 @@ struct Chk892Flow { { lCentrality = -999; - colCuts.setCuts(EventCuts.cfgEvtZvtx, EventCuts.cfgEvtTriggerCheck, EventCuts.cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, EventCuts.cfgEvtOccupancyInTimeRangeMax, EventCuts.cfgEvtOccupancyInTimeRangeMin); + colCuts.setCuts(EventCuts.cfgEvtZvtx, EventCuts.cfgEvtTriggerCheck, EventCuts.cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, /*EventCuts.cfgEvtOccupancyInTimeRangeMax*/ false, /*EventCuts.cfgEvtOccupancyInTimeRangeMin*/ false); colCuts.init(&histos); colCuts.setTriggerTVX(EventCuts.cfgEvtTriggerTVXSel); colCuts.setApplyTFBorderCut(EventCuts.cfgEvtTFBorderCut); @@ -277,6 +278,7 @@ struct Chk892Flow { AxisSpec ptAxisQA = {AxisConfig.cfgBinsPtQA, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec v2Axis = {AxisConfig.cfgAxisV2, "#v_{2}"}; AxisSpec phiAxis = {AxisConfig.cfgAxisPhi, "2(#phi-#Psi_{2})"}; + AxisSpec occuAxis = {AxisConfig.cfgBinsOccu, "Occupancy"}; AxisSpec radiusAxis = {50, 0, 5, "Radius (cm)"}; AxisSpec cpaAxis = {30, 0.97, 1.0, "CPA"}; AxisSpec tauAxis = {250, 0, 25, "Lifetime (cm)"}; @@ -284,7 +286,7 @@ struct Chk892Flow { AxisSpec dcaxyAxis = {100, 0, 1, "DCA_{#it{xy}} (cm)"}; AxisSpec dcazAxis = {200, 0, 2, "DCA_{#it{z}} (cm)"}; AxisSpec yAxis = {50, -1, 1, "Rapidity"}; - AxisSpec invMassAxisK0s = {400 / AxisConfig.cNbinsDiv, 0.3, 0.7, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 + AxisSpec invMassAxisK0s = {800 / AxisConfig.cNbinsDiv, 0.46, 0.54, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 AxisSpec invMassAxisReso = {900 / AxisConfig.cNbinsDiv, 0.5f, 1.4f, "Invariant Mass (GeV/#it{c}^2)"}; // chK(892) ~892 AxisSpec pidQAAxis = {130 / AxisConfig.cNbinsDivQA, -6.5, 6.5}; @@ -296,7 +298,8 @@ struct Chk892Flow { histos.add("QA/K0sCutCheck", "Check K0s cut", HistType::kTH1D, {AxisSpec{13, -0.5, 12.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/VtxZ", "z-vertex distribution", {HistType::kTH1D, {vtxzAxis}}); + histos.add("QA/before/Occupancy", "Occupancy distribution", {HistType::kTH1D, {occuAxis}}); // EventPlane histos.add("QA/EP/hEPDet", "Event plane distribution of FT0C (Det = A)", {HistType::kTH2D, {centAxis, epAxis}}); @@ -443,16 +446,16 @@ struct Chk892Flow { // Invariant mass nSparse if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis}); - histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis, phiAxis}); + histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis, occuAxis}); + histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis, phiAxis, occuAxis}); if (doprocessMC) { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis, occuAxis}); } } else { - histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis}); - histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis}); + histos.add("hInvmass_Kstar", "Invariant mass of unlike-sign chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, occuAxis}); + histos.add("hInvmass_K0s", "Invariant mass of unlike-sign K0s", HistType::kTHnSparseD, {centAxis, ptAxis, invMassAxisK0s, v2Axis, occuAxis}); if (doprocessMC) { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, occuAxis}); } } @@ -520,9 +523,9 @@ struct Chk892Flow { histos.add("QAMC/kstarv2vsinvmass_noKstar", "Invariant mass vs v2 of unlike-sign no chK(892)", HistType::kTH2D, {invMassAxisReso, v2Axis}); if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, phiAxis, occuAxis}); } else { - histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis}); + histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso, v2Axis, occuAxis}); } } @@ -891,9 +894,15 @@ struct Chk892Flow { auto trkkPropTau = k0sCand.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * MassK0Short; auto trkkMass = k0sCand.mK0Short(); - lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + // lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); auto lPhiMinusPsiK0s = RecoDecay::constrainAngle(lResoSecondary.Phi() - lEPDet, 0.0, 2); // constrain angle to range 0, Pi - auto v2K0s = std::cos(static_cast(nmode) * lPhiMinusPsiK0s); + // auto v2K0s = std::cos(static_cast(nmode) * lPhiMinusPsiK0s); + + float cosNPhi_K0s = std::cos(static_cast(nmode) * lResoSecondary.Phi()); + float sinNPhi_K0s = std::sin(static_cast(nmode) * lResoSecondary.Phi()); + + auto v2K0s = cosNPhi_K0s * collision.qvecRe()[lQvecDetInd] + sinNPhi_K0s * collision.qvecIm()[lQvecDetInd]; if constexpr (!IsMix) { if (AnalysisConfig.cfgFillQAPlots) { // Seconddary QA plots @@ -962,15 +971,15 @@ struct Chk892Flow { histos.fill(HIST("QA/after/k0sv2vsinvmass"), lResoSecondary.M(), v2K0s); if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, collision.trackOccupancyInTimeRange()); } } if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, static_cast(nmode) * lPhiMinusPsiK0s, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M(), v2K0s, collision.trackOccupancyInTimeRange()); } k0sIndicies.push_back(k0sCand.index()); } @@ -980,9 +989,11 @@ struct Chk892Flow { for (const auto& k0sIndex : k0sIndicies) { auto bTrack = dTracks1.rawIteratorAt(trackIndex); auto k0sCand = dTracks2.rawIteratorAt(k0sIndex); + auto trkkMass = k0sCand.mK0Short(); lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); - lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + // lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), MassK0Short); + lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); lResoKstar = lResoSecondary + lDecayDaughter_bach; auto resoPhi = lResoKstar.Phi(); // EP method @@ -1016,9 +1027,9 @@ struct Chk892Flow { histos.fill(HIST("QA/after/kstarv2vsinvmass"), lResoKstar.M(), resoFlowValue); } if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M(), resoFlowValue, collision.trackOccupancyInTimeRange()); } if (BkgEstimationConfig.cfgFillRotBkg) { @@ -1046,9 +1057,9 @@ struct Chk892Flow { } typeKstar = bTrack.sign() > 0 ? BinType::kKstarP_Rot : BinType::kKstarN_Rot; if (AnalysisConfig.cfgFillAdditionalAxis) { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue, static_cast(nmode) * lPhiMinusPsiKstar, collision.trackOccupancyInTimeRange()); } else { - histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue); + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M(), resoFlowValue, collision.trackOccupancyInTimeRange()); } } } diff --git a/PWGLF/Tasks/Resonances/chk892pp.cxx b/PWGLF/Tasks/Resonances/chk892pp.cxx index 269e8d0845d..72ecdce733e 100644 --- a/PWGLF/Tasks/Resonances/chk892pp.cxx +++ b/PWGLF/Tasks/Resonances/chk892pp.cxx @@ -24,7 +24,7 @@ #include #include #include -#include // FIXME +// #include // FIXME #include // FIXME #include @@ -63,6 +63,7 @@ #include "Common/Core/RecoDecay.h" #include "CommonConstants/PhysicsConstants.h" +#include "CommonConstants/MathConstants.h" #include "ReconstructionDataFormats/Track.h" @@ -80,23 +81,16 @@ using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; using namespace o2::constants::physics; +using namespace o2::aod::rctsel; -struct chk892pp { - enum binType : unsigned int { +struct Chk892pp { + 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, + kKstarP_Rot, + kKstarN_Rot, kTYEnd }; @@ -118,35 +112,45 @@ struct chk892pp { 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"}; + 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 - 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"}; + 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.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"}; + Configurable cNbinsDivQA{"cNbinsDivQA", 1, "Integer to divide the number of bins for QA"}; + } AxisConfig; /// 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"}; + 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", 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", true, "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 cfgincludeCentralityMC{"cfgincludeCentralityMC", false, "Include centrality in MC"}; + 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"}; + 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; /* // Cuts from polarization analysis @@ -157,86 +161,111 @@ struct chk892pp { */ 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 + struct : ConfigurableGroup { + Configurable cfgTPConly{"cfgTPConly", true, "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 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 + } 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 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"}; + 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", false, "pT-dependent DCAxy 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 - 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"}; + 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.0, "Minimum DCA Secondary positive daughters to PV"}; + Configurable cfgSecondaryDauNegDCAtoPVMin{"cfgSecondaryDauNegDCAtoPVMin", 0.0, "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", 1.2, "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.3, "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 - Configurable cKstarMaxRap{"cKstarMaxRap", 0.5, "Kstar maximum rapidity"}; - Configurable cKstarMinRap{"cKstarMinRap", -0.5, "Kstar minimum rapidity"}; - - float centrality; + struct : ConfigurableGroup { + Configurable cfgKstarMaxRap{"cfgKstarMaxRap", 0.5, "Kstar maximum rapidity"}; + Configurable cfgKstarMinRap{"cfgKstarMinRap", -0.5, "Kstar minimum rapidity"}; + } KstarCuts; + + // 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; + + float lCentrality; // PDG code - int kPDGK0s = 310; - int kPDGK0 = 311; - int kKstarPlus = 323; - int kPiPlus = 211; + int kPDGK0s = kK0Short; + int kPDGK0 = kK0; + int kKstarPlus = o2::constants::physics::Pdg::kKPlusStar892; + // int kPiPlus = 211; void init(o2::framework::InitContext&) { - centrality = -999; + lCentrality = -999; - colCuts.setCuts(ConfEvtZvtx, ConfEvtTriggerCheck, ConfEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, ConfEvtOccupancyInTimeRangeMax, ConfEvtOccupancyInTimeRangeMin); + colCuts.setCuts(EventCuts.cfgEvtZvtx, EventCuts.cfgEvtTriggerCheck, EventCuts.cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, EventCuts.cfgEvtOccupancyInTimeRangeMax, EventCuts.cfgEvtOccupancyInTimeRangeMin); 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)"}; + colCuts.setTriggerTVX(EventCuts.cfgEvtTriggerTVXSel); + colCuts.setApplyTFBorderCut(EventCuts.cfgEvtTFBorderCut); + colCuts.setApplyITSTPCvertex(EventCuts.cfgEvtUseITSTPCvertex); + colCuts.setApplyZvertexTimedifference(EventCuts.cfgEvtZvertexTimedifference); + colCuts.setApplyPileupRejection(EventCuts.cfgEvtPileupRejection); + colCuts.setApplyNoITSROBorderCut(EventCuts.cfgEvtNoITSROBorderCut); + 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 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 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)"}; @@ -244,15 +273,14 @@ struct chk892pp { 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 invMassAxisK0s = {800 / AxisConfig.cNbinsDiv, 0.46, 0.54, "Invariant Mass (GeV/#it{c}^2)"}; // K0s ~497.611 + AxisSpec invMassAxisReso = {900 / AxisConfig.cNbinsDiv, 0.5f, 1.4f, "Invariant Mass (GeV/#it{c}^2)"}; // chK(892) ~892 + AxisSpec pidQAAxis = {130 / AxisConfig.cNbinsDivQA, -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 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"}}); @@ -261,6 +289,10 @@ struct chk892pp { 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}); @@ -397,7 +429,7 @@ struct chk892pp { histos.add("hInvmass_Kstar_MC", "Invariant mass of unlike chK(892)", HistType::kTHnSparseD, {axisType, centAxis, ptAxis, invMassAxisReso}); - ccdb->setURL(cfgURL); + ccdb->setURL(CCDBConfig.cfgURL); ccdbApi.init("http://alice-ccdb.cern.ch"); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); @@ -410,7 +442,7 @@ struct chk892pp { } template - float GetCentrality(CollisionType const& collision) + float getCentrality(CollisionType const& collision) { if (cfgCentEst == 1) { return collision.multFT0C(); @@ -422,7 +454,7 @@ struct chk892pp { } template - int GetDetId(DetNameType const& name) + int getlDetId(DetNameType const& name) { LOGF(info, "GetDetID running"); if (name.value == "FT0C") { @@ -447,41 +479,47 @@ struct chk892pp { bool trackCut(TrackType const& track) { // basic track cuts - if (std::abs(track.pt()) < cMinPtcut) - return false; - if (std::abs(track.eta()) > cMaxEtacut) + if (std::abs(track.pt()) < TrackCuts.cfgMinPtcut) return false; - if (track.itsNCls() < cfgITScluster) + if (std::abs(track.eta()) > TrackCuts.cfgMaxEtacut) return false; - if (track.tpcNClsFound() < cfgTPCcluster) + if (track.itsNCls() < TrackCuts.cfgITScluster) return false; - if (track.tpcCrossedRowsOverFindableCls() < cfgRatioTPCRowsOverFindableCls) + if (track.tpcNClsFound() < TrackCuts.cfgTPCcluster) return false; - if (track.itsChi2NCl() >= cfgITSChi2NCl) + if (track.tpcCrossedRowsOverFindableCls() < TrackCuts.cfgRatioTPCRowsOverFindableCls) return false; - if (track.tpcChi2NCl() >= cfgTPCChi2NCl) + if (track.itsChi2NCl() >= TrackCuts.cfgITSChi2NCl) return false; - if (cfgHasITS && !track.hasITS()) + if (track.tpcChi2NCl() >= TrackCuts.cfgTPCChi2NCl) return false; - if (cfgHasTPC && !track.hasTPC()) + if (TrackCuts.cfgHasITS && !track.hasITS()) return false; - if (cfgHasTOF && !track.hasTOF()) + if (TrackCuts.cfgHasTPC && !track.hasTPC()) return false; - if (cfgUseITSRefit && !track.passedITSRefit()) + if (TrackCuts.cfgHasTOF && !track.hasTOF()) return false; - if (cfgUseTPCRefit && !track.passedTPCRefit()) + if (TrackCuts.cfgUseITSRefit && !track.passedITSRefit()) return false; - if (cfgPVContributor && !track.isPVContributor()) + if (TrackCuts.cfgUseTPCRefit && !track.passedTPCRefit()) return false; - if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + if (TrackCuts.cfgPVContributor && !track.isPVContributor()) return false; - if (cfgGlobalTrack && !track.isGlobalTrack()) + if (TrackCuts.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) + if (TrackCuts.cfgGlobalTrack && !track.isGlobalTrack()) return false; - if (std::abs(track.dcaXY()) > cMaxbDCArToPVcut) + if (TrackCuts.cfgPrimaryTrack && !track.isPrimaryTrack()) return false; - if (std::abs(track.dcaZ()) > cMaxbDCAzToPVcut) + 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 (std::abs(track.dcaXY()) > TrackCuts.cfgMaxbDCArToPVcut) + return false; + } + if (std::abs(track.dcaZ()) > TrackCuts.cfgMaxbDCAzToPVcut) return false; return true; } @@ -490,217 +528,158 @@ struct chk892pp { template bool selectionPIDPion(TrackType const& candidate) { - bool tpcPIDPassed{false}, tofPIDPassed{false}; + bool tpcPIDPassed = std::abs(candidate.tpcNSigmaPi()) < PIDCuts.cfgMaxTPCnSigmaPion; + bool tofPIDPassed = false; - if (cTPConly) { - - if (std::abs(candidate.tpcNSigmaPi()) < cMaxTPCnSigmaPion) { - tpcPIDPassed = true; - } else { - return false; - } - tofPIDPassed = true; + if (PIDCuts.cfgTPConly) { + return tpcPIDPassed; + } + if (candidate.hasTOF()) { + tofPIDPassed = std::abs(candidate.tofNSigmaPi()) < PIDCuts.cfgMaxTOFnSigmaPion || + (PIDCuts.cfgNsigmaCutCombinedPion > 0 && + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi() + + candidate.tofNSigmaPi() * candidate.tofNSigmaPi() < + PIDCuts.cfgNsigmaCutCombinedPion * PIDCuts.cfgNsigmaCutCombinedPion); } 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; - } + tofPIDPassed = PIDCuts.cfgTOFVeto; } - if (tpcPIDPassed && tofPIDPassed) { - return true; - } - return false; + return tpcPIDPassed && tofPIDPassed; } 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; - } + auto lDauDCA = candidate.dcaV0daughters(); + auto lDauPosDCAtoPV = candidate.dcapostopv(); + auto lDauNegDCAtoPV = candidate.dcanegtopv(); + auto lPt = candidate.pt(); + auto lRapidity = candidate.yK0Short(); + auto lRadius = candidate.v0radius(); + auto lDCAtoPV = 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 (lDauDCA > SecondaryCuts.cfgSecondaryDauDCAMax) + return false; + if (lDauPosDCAtoPV < SecondaryCuts.cfgSecondaryDauPosDCAtoPVMin) + return false; + if (lDauNegDCAtoPV < SecondaryCuts.cfgSecondaryDauNegDCAtoPVMin) + return false; + if (lPt < SecondaryCuts.cfgSecondaryPtMin) + return false; + if (std::fabs(lRapidity) > SecondaryCuts.cfgSecondaryRapidityMax) + return false; + if (lRadius < SecondaryCuts.cfgSecondaryRadiusMin || lRadius > SecondaryCuts.cfgSecondaryRadiusMax) + return false; + if (lDCAtoPV > SecondaryCuts.cfgSecondaryDCAtoPVMax) + return false; + if (lCPA < SecondaryCuts.cfgSecondaryCosPAMin) + return false; + if (lPropTauK0s > SecondaryCuts.cfgSecondaryProperLifetimeMax) + return false; + if (candidate.qtarm() < SecondaryCuts.cfgSecondaryparamArmenterosCut * std::abs(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; + }; - return returnFlag; + 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; } - - } 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; - + 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::abs(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 { - if (fabs(mK0s - MassK0Short) > cSecondaryMassWindow) { - histos.fill(HIST("QA/K0sCutCheck"), 10); - return false; - } - return true; + return std::fabs(lMk0s - MassK0Short) <= SecondaryCuts.cfgSecondaryMassWindow; // always apply mass window cut } } } // 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? + if (std::abs(bTrack.PDGCode()) != kPiPlus) // Are you pion? return false; - if (abs(K0scand.PDGCode()) != kPDGK0s) // Are you K0s? + if (std::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? + if (std::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? + if (std::abs(motherkV0.pdgCode()) != kPDGK0s) // Is it K0s? return false; // Check if K0s's mother is K0 (311) auto motherK0 = motherkV0.template mothers_as(); - if (abs(motherK0.pdgCode()) != 311) + if (std::abs(motherK0.pdgCode()) != kPDGK0) return false; // Check if K0's mother is Kstar (323) auto motherKstar = motherK0.template mothers_as(); - if (abs(motherKstar.pdgCode()) != 323) + if (std::abs(motherKstar.pdgCode()) != kKstarPlus) return false; // Check if bTrack and K0 have the same mother (global index) @@ -715,13 +694,13 @@ struct chk892pp { template void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksTypeK0s& dTracks2) { - histos.fill(HIST("QA/before/CentDist"), centrality); + histos.fill(HIST("QA/before/CentDist"), lCentrality); - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResoSecondary, lDecayDaughter_bach, lResoKstar; + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResoSecondary, lDecayDaughter_bach, lResoKstar, lDaughterRot, lResonanceRot; std::vector trackIndicies = {}; std::vector k0sIndicies = {}; - for (auto& bTrack : dTracks1) { + for (const auto& bTrack : dTracks1) { auto trkbpt = bTrack.pt(); auto istrkbhasTOF = bTrack.hasTOF(); auto trkbNSigmaPiTPC = bTrack.tpcNSigmaPi(); @@ -758,9 +737,9 @@ struct chk892pp { trackIndicies.push_back(bTrack.index()); } - for (auto& K0scand : dTracks2) { - auto posDauTrack = K0scand.template posTrack_as(); - auto negDauTrack = K0scand.template negTrack_as(); + for (const auto& k0sCand : dTracks2) { + auto posDauTrack = k0sCand.template posTrack_as(); + auto negDauTrack = k0sCand.template negTrack_as(); /// Daughters // Positve pion @@ -775,16 +754,16 @@ struct chk892pp { 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(); + 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(); if constexpr (!IsMix) { // Seconddary QA plots @@ -819,13 +798,11 @@ struct chk892pp { 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) + if (!SecondaryCuts.cfgByPassDauPIDSelection && !selectionPIDPion(posDauTrack)) continue; - if (!cfgByPassDauPIDSelection && !selectionPIDPion(negDauTrack)) + if (!SecondaryCuts.cfgByPassDauPIDSelection && !selectionPIDPion(negDauTrack)) continue; - if (!selectionK0s(collision, K0scand)) + if (!selectionK0s(collision, k0sCand)) continue; if constexpr (!IsMix) { @@ -860,17 +837,19 @@ struct chk892pp { histos.fill(HIST("QA/after/hCPASecondary"), trkkCPA); histos.fill(HIST("QA/after/hPropTauSecondary"), trkkPropTau); histos.fill(HIST("QA/after/hInvmassSecondary"), trkkMass); + histos.fill(HIST("hInvmass_K0s"), lCentrality, lResoSecondary.Pt(), lResoSecondary.M()); } - k0sIndicies.push_back(K0scand.index()); + k0sIndicies.push_back(k0sCand.index()); } - for (auto& trackIndex : trackIndicies) { - for (auto& k0sIndex : k0sIndicies) { + for (const auto& trackIndex : trackIndicies) { + for (const auto& k0sIndex : k0sIndicies) { auto bTrack = dTracks1.rawIteratorAt(trackIndex); - auto K0scand = dTracks2.rawIteratorAt(k0sIndex); + auto k0sCand = dTracks2.rawIteratorAt(k0sIndex); + auto trkkMass = k0sCand.mK0Short(); lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassPionCharged); - lResoSecondary.SetXYZM(K0scand.px(), K0scand.py(), K0scand.pz(), MassK0Short); + lResoSecondary.SetXYZM(k0sCand.px(), k0sCand.py(), k0sCand.pz(), trkkMass); lResoKstar = lResoSecondary + lDecayDaughter_bach; // QA plots @@ -879,16 +858,33 @@ struct chk892pp { histos.fill(HIST("QA/before/kstarinvmass"), lResoKstar.M()); } - if (lResoKstar.Rapidity() > cKstarMaxRap || lResoKstar.Rapidity() < cKstarMinRap) + if (lResoKstar.Rapidity() > KstarCuts.cfgKstarMaxRap || lResoKstar.Rapidity() < KstarCuts.cfgKstarMinRap) continue; if constexpr (!IsMix) { - unsigned int typeKstar = bTrack.sign() > 0 ? binType::kKstarP : binType::kKstarN; + 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()); - + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResoKstar.Pt(), lResoKstar.M()); + + if (BkgEstimationConfig.cfgFillRotBkg) { + for (int i = 0; i < BkgEstimationConfig.cfgNrotBkg; i++) { + auto lRotAngle = BkgEstimationConfig.cfgMinRot + i * ((BkgEstimationConfig.cfgMaxRot - BkgEstimationConfig.cfgMinRot) / (BkgEstimationConfig.cfgNrotBkg - 1)); + histos.fill(HIST("QA/RotBkg/hRotBkg"), lRotAngle); + if (BkgEstimationConfig.cfgRotPion) { + lDaughterRot = lDecayDaughter_bach; + lDaughterRot.RotateZ(lRotAngle); + lResonanceRot = lDaughterRot + lResoSecondary; + } else { + lDaughterRot = lResoSecondary; + lDaughterRot.RotateZ(lRotAngle); + lResonanceRot = lDecayDaughter_bach + lDaughterRot; + } + typeKstar = bTrack.sign() > 0 ? BinType::kKstarP_Rot : BinType::kKstarN_Rot; + histos.fill(HIST("hInvmass_Kstar"), typeKstar, lCentrality, lResonanceRot.Pt(), lResonanceRot.M()); + } + } } // IsMix } // K0scand } // bTrack @@ -905,12 +901,17 @@ struct chk892pp { { 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; colCuts.fillQA(collision); - centrality = GetCentrality(collision); fillHistograms(collision, tracks, v0s); // second order } - PROCESS_SWITCH(chk892pp, processData, "Process Event for data without Partitioning", true); + PROCESS_SWITCH(Chk892pp, processData, "Process Event for data without Partitioning", true); // process MC reconstructed level void processMC(EventCandidates::iterator const& collision, @@ -922,9 +923,9 @@ struct chk892pp { fillHistograms(collision, tracks, v0s); } - PROCESS_SWITCH(chk892pp, processMC, "Process Event for MC", false); + PROCESS_SWITCH(Chk892pp, processMC, "Process Event for MC", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { - return WorkflowSpec{adaptAnalysisTask(cfgc, TaskName{"lf-chk892pp"})}; + return WorkflowSpec{adaptAnalysisTask(cfgc)}; } diff --git a/PWGLF/Tasks/Resonances/cksspinalignder.cxx b/PWGLF/Tasks/Resonances/cksspinalignder.cxx new file mode 100644 index 00000000000..ae29ab6a6fc --- /dev/null +++ b/PWGLF/Tasks/Resonances/cksspinalignder.cxx @@ -0,0 +1,279 @@ +// 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 cksspinalignder.cxx +/// \brief Analysis task for ChargedKStar spin alignment +/// +/// \author prottay.das@cern.ch + +#include "PWGLF/DataModel/LFCKSSpinalignmentTables.h" + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/BinningPolicy.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include + +#include +#include +#include +#include + +#include + +#include // for std::fabs +#include +// #include +#include +#include // <<< CHANGED: for dedup sets +#include +#include +#include +#include // <<< CHANGED: for seenMap +#include +#include + +// o2 includes. +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct cksspinalignder { + + struct : ConfigurableGroup { + 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"}; + } cfgCcdbParam; + + // event sel///////// + Configurable centMin{"centMin", 0, "Minimum Centrality"}; + Configurable centMax{"centMax", 80, "Maximum Centrality"}; + // V0 selection //////////// + Configurable cosPA{"cosPA", 0.995, "Cosine Pointing Angle"}; + Configurable radiusMin{"radiusMin", 1.2, "Minimum V0 radius"}; + Configurable radiusMax{"radiusMax", 100, "Maximum V0 radius"}; + Configurable dcaPion{"dcaPion", 0.1, "DCA Pion"}; + Configurable dcaDaughters{"dcaDaughters", 1.0, "DCA between daughters"}; + Configurable lifetimeMax{"lifetimeMax", 20, "Maximum V0 lifetime"}; + Configurable ptMin{"ptMin", 0.5, "V0 Pt minimum"}; + 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"}; + + // 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"}; + + // THnsparse bining + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {50, 1.09, 1.14}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.0}, "#it{p}_{T}"}; + ConfigurableAxis configThnAxisSA{"configThnAxisSA", {20, -1.0, 1.0}, "cos#it{#theta *}"}; + ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0.0, 80.0}, "Centrality"}; + + // Enable access to the CCDB for the offset and correction constants and save them in dedicated variables. + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + + histos.add("hCentrality", "Centrality distribution", kTH1F, {{80, 0, 80}}); + histos.add("hKShortMass", "hKShortMass", kTH1F, {{100, 0.45, 0.55}}); + + histos.add("hSparsesame", "hSparsesame", kTHnSparseF, {configThnAxisInvMass, configThnAxisPt, configThnAxisSA, configThnAxisCentrality}); + histos.add("hSparsemix", "hSparsemix", kTHnSparseF, {configThnAxisInvMass, configThnAxisPt, configThnAxisSA, configThnAxisCentrality}); + + 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()); + } + + template + bool selectionV0(T const& candidate) + { + auto kshortPt = std::sqrt(candidate.kShortPx() * candidate.kShortPx() + candidate.kShortPy() * candidate.kShortPy()); + auto px = candidate.kShortPx(); + auto py = candidate.kShortPy(); + auto pz = candidate.kShortPz(); + auto p = std::sqrt(px * px + py * py + pz * pz); + auto kshortEta = 0.5 * std::log((p + pz) / (p - pz)); + + if (std::abs(kshortEta) > v0eta) { + return false; + } + if (candidate.v0Cospa() < cosPA) { + return false; + } + if (candidate.v0Radius() > radiusMax) { + return false; + } + if (candidate.v0Radius() < radiusMin) { + return false; + } + if (candidate.dcaBetweenDaughter() > dcaDaughters) { + return false; + } + if (std::abs(candidate.dcaPositive()) < dcaPion && std::abs(candidate.dcaNegative()) < dcaPion) { + return false; + } + if (candidate.v0Lifetime() > lifetimeMax) { + return false; + } + if (kshortPt < ptMin) { + return false; + } + if (kshortPt > ptMax) { + return false; + } + return true; + } + + template + bool selectionPID(const T& candidate) + { + 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) { + return true; + } + return false; + } + + std::tuple computePtEtaPhi(float px, float py, float pz) + { + float pt = std::sqrt(px * px + py * py); + float p = std::sqrt(px * px + py * py + pz * pz); + float eta = (p != std::abs(pz)) ? 0.5 * std::log((p + pz) / (p - pz)) : 0.0f; // avoid division by zero + float phi = RecoDecay::constrainAngle(std::atan2(py, px)); + return {pt, eta, phi}; + } + + ROOT::Math::PtEtaPhiMVector kshort, pion, chkstar; + ROOT::Math::PtEtaPhiMVector kshortmix, pionmix, chkstarmix; + ROOT::Math::PxPyPzMVector fourVecDauCM, fourVecDauCMmix; + ROOT::Math::XYZVector threeVecDauCM, eventplaneVecNorm, threeVecDauCMmix, eventplaneVecNormmix; + + Filter centralityFilter = (nabs(aod::kshortpionevent::cent) < centMax && nabs(aod::kshortpionevent::cent) > centMin); + + using EventCandidates = soa::Filtered; + + void processSameData(EventCandidates::iterator const& collision, aod::KShortTracks const& V0s, aod::PionTracks const& piontracks) + { + auto centrality = collision.cent(); + histos.fill(HIST("hCentrality"), centrality); + + auto psiFT0C = collision.psiFT0C(); + + for (const auto& v0 : V0s) { + if (!selectionV0(v0)) { + continue; + } + auto [kshortPt, kshortEta, kshortPhi] = computePtEtaPhi(v0.kShortPx(), v0.kShortPy(), v0.kShortPz()); + kshort = ROOT::Math::PtEtaPhiMVector(kshortPt, kshortEta, kshortPhi, v0.kShortMass()); + histos.fill(HIST("hKShortMass"), kshort.M()); + + for (const auto& piontrack : piontracks) { + 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()}; + fourVecDauCM = boost(kshort); + threeVecDauCM = fourVecDauCM.Vect(); + eventplaneVecNorm = ROOT::Math::XYZVector(std::sin(2.0 * psiFT0C), -std::cos(2.0 * psiFT0C), 0); + auto cosThetaStar = eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); + + histos.fill(HIST("hSparsesame"), chkstar.M(), chkstar.Pt(), cosThetaStar, centrality); + } + } + } + PROCESS_SWITCH(cksspinalignder, processSameData, "Process same data", true); + + // Processing Event Mixing + SliceCache cache; + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{cfgVtxBins, cfgMultBins}, true}; + Preslice tracksPerCollisionV0 = aod::kshortpionpair::kshortpioneventId; + Preslice tracksPerCollisionBach = aod::kshortpionpair::kshortpioneventId; + + void processMixedData(EventCandidates const& collisions, aod::KShortTracks const& V0s, aod::PionTracks const& piontracks) + { + for (const auto& [collision1, collision2] : selfCombinations(colBinning, nEvtMixing, -1, collisions, collisions)) { + if (collision1.index() == collision2.index()) { + continue; + } + auto centrality = collision1.cent(); + auto psiFT0Cmix = collision1.psiFT0C(); + + auto groupV0 = V0s.sliceBy(tracksPerCollisionV0, collision1.index()); + auto groupPion = piontracks.sliceBy(tracksPerCollisionBach, collision2.index()); + for (const auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV0, groupPion))) { + if (!selectionV0(t1)) + continue; + auto [kshortPtmix, kshortEtamix, kshortPhimix] = computePtEtaPhi(t1.kShortPx(), t1.kShortPy(), t1.kShortPz()); + kshortmix = ROOT::Math::PtEtaPhiMVector(kshortPtmix, kshortEtamix, kshortPhimix, t1.kShortMass()); + + 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; + + ROOT::Math::Boost boost{chkstarmix.BoostToCM()}; + fourVecDauCMmix = boost(kshortmix); + threeVecDauCMmix = fourVecDauCMmix.Vect(); + eventplaneVecNormmix = ROOT::Math::XYZVector(std::sin(2.0 * psiFT0Cmix), -std::cos(2.0 * psiFT0Cmix), 0); + auto cosThetaStarmix = eventplaneVecNormmix.Dot(threeVecDauCMmix) / std::sqrt(threeVecDauCMmix.Mag2()) / std::sqrt(eventplaneVecNormmix.Mag2()); + + histos.fill(HIST("hSparsemix"), chkstarmix.M(), chkstarmix.Pt(), cosThetaStarmix, centrality); + } + } + } + PROCESS_SWITCH(cksspinalignder, processMixedData, "Process mixed data", true); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx b/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx index 5d8772ef7e9..4b67171c448 100644 --- a/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx +++ b/PWGLF/Tasks/Resonances/doubleResonanceScan.cxx @@ -232,13 +232,13 @@ struct DoubleResonanceScan { if (std::abs(track.pt()) < cMinPtcut) return false; if (cUsePtDependentDCArCut) { - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > -Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > -Epsilon) return false; } else { - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) return false; } - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) return false; if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; @@ -268,11 +268,11 @@ struct DoubleResonanceScan { } else { switch (particleType) { case 0: // pion - return o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); + return o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); case 1: // kaon - return o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaKaFlag()); + return o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaKaFlag()); case 2: // proton - return o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag()); + return o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag()); default: return -999; } @@ -297,11 +297,11 @@ struct DoubleResonanceScan { } else { switch (particleType) { case 0: // pion - return candidate.hasTOF() ? o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()) : -999; + return candidate.hasTOF() ? o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()) : -999; case 1: // kaon - return candidate.hasTOF() ? o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaKaFlag()) : -999; + return candidate.hasTOF() ? o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaKaFlag()) : -999; case 2: // proton - return candidate.hasTOF() ? o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag()) : -999; + return candidate.hasTOF() ? o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag()) : -999; default: return -999; } @@ -338,8 +338,8 @@ struct DoubleResonanceScan { dcaXY = track.dcaXY(); dcaZ = track.dcaZ(); } else { - dcaXY = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()); - dcaZ = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()); + dcaXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()); + dcaZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()); } // FIXME: Apply better method switch (daughterIndex) { diff --git a/PWGLF/Tasks/Resonances/f0980analysis.cxx b/PWGLF/Tasks/Resonances/f0980analysis.cxx index 01b059a7f29..0d489209e93 100644 --- a/PWGLF/Tasks/Resonances/f0980analysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980analysis.cxx @@ -8,131 +8,122 @@ // In applying this license CERN does 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 f0980analysis.cxx +/// \brief f0(980) analysis in pp 13.6 TeV +/// \author Yunseul Bae (ybae@cern.ch), Junlee Kim (jikim1290@gmail.com) +/// \since 01/07/2024 -/// \author Junlee Kim (jikim1290@gmail.com) - -#include -#include -#include "TVector2.h" -#include +#include "PWGLF/DataModel/LFResonanceTables.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/PIDResponse.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 "PWGLF/DataModel/LFResonanceTables.h" -#include "CommonConstants/PhysicsConstants.h" +#include + +#include "Math/LorentzVector.h" +#include "Math/Vector4D.h" +#include "TVector2.h" +#include + +#include using namespace o2; +using namespace o2::constants::physics; using namespace o2::framework; using namespace o2::framework::expressions; +using namespace o2::aod; using namespace o2::soa; -using namespace o2::constants::physics; struct f0980analysis { SliceCache cache; - HistogramRegistry histos{ - "histos", - {}, - OutputObjHandlingPolicy::AnalysisObject}; - - 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 cfgMaxTPC{"cfgMaxTPC", 5.0, "Maximum TPC PID with TOF"}; - Configurable cfgMaxTOF{"cfgMaxTOF", 3.0, "Maximum TOF PID with TPC"}; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // 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 cfgMinRap{"cfgMinRap", -0.5, "Minimum rapidity for pair"}; Configurable cfgMaxRap{"cfgMaxRap", 0.5, "Maximum rapidity for pair"}; Configurable cfgFindRT{"cfgFindRT", false, "boolean for RT analysis"}; - // Track selection - 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 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"}; + // Track selections + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", true, "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 cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; Configurable cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 0, "Number of TPC cluster"}; - // PID - Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; // TOF - Configurable cMaxTPCnSigmaPion{"cMaxTPCnSigmaPion", 3.0, "TPC nSigma cut for Pion"}; // TPC + // PID + Configurable cMaxTOFnSigmaPion{"cMaxTOFnSigmaPion", 3.0, "TOF nSigma cut for Pion"}; + 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", 0, "PID selection type"}; - // Axis + // Axis ConfigurableAxis massAxis{"massAxis", {400, 0.2, 2.2}, "Invariant mass axis"}; - ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}, "Transverse momentum Binning"}; - ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 95.0, 100.0, 105.0, 110.0}, "Centrality Binning"}; + ConfigurableAxis pTAxis{"pTAxis", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}, "Transverse momentum Binning"}; + ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0.0, 1.0, 5.0, 10.0, 15.0, 20.0, 25.0, 30.0, 35.0, 40.0, 45.0, 50.0, 55.0, 60.0, 65.0, 70.0, 75.0, 80.0, 95.0, 100.0, 105.0, 110.0}, "Centrality Binning"}; + void init(o2::framework::InitContext&) { std::vector lptBinning = {0, 5.0, 13.0, 20.0, 50.0, 1000.0}; - AxisSpec RTAxis = {3, 0, 3}; - AxisSpec LptAxis = {lptBinning}; // Minimum leading hadron pT selection + AxisSpec rtAxis = {3, 0, 3}; + AxisSpec lptAxis = {lptBinning}; // Minimum leading hadron pT selection - AxisSpec PIDqaAxis = {120, -6, 6}; + AxisSpec pidqaAxis = {60, -6, 6}; AxisSpec pTqaAxis = {200, 0, 20}; - AxisSpec phiqaAxis = {72, 0., 2.0 * constants::math::PI}; - AxisSpec EPAxis = {10, 0, constants::math::PI}; - AxisSpec EPqaAxis = {200, -constants::math::PI, constants::math::PI}; - AxisSpec EPresAxis = {200, -2, 2}; + AxisSpec phiqaAxis = {72, 0, o2::constants::math::TwoPI}; // Azimuthal angle axis + + AxisSpec epAxis = {10, 0, o2::constants::math::PI}; // Event Plane + AxisSpec epqaAxis = {200, -o2::constants::math::PI, o2::constants::math::PI}; + AxisSpec epResAxis = {200, -2, 2}; if (cfgFindRT) { - histos.add("hInvMass_f0980_US", "unlike invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); - histos.add("hInvMass_f0980_LSpp", "++ invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); - histos.add("hInvMass_f0980_LSmm", "-- invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, RTAxis, LptAxis}}); + histos.add("hInvMass_f0980_US", "unlike invariant mass", {HistType::kTHnSparseF, {massAxis, pTAxis, centAxis, rtAxis, lptAxis}}); + histos.add("hInvMass_f0980_LSpp", "++ invariant mass", {HistType::kTHnSparseF, {massAxis, pTAxis, centAxis, rtAxis, lptAxis}}); + histos.add("hInvMass_f0980_LSmm", "-- invariant mass", {HistType::kTHnSparseF, {massAxis, pTAxis, centAxis, rtAxis, lptAxis}}); + } else { + histos.add("hInvMass_f0980_US_EPA", "unlike invariant mass", {HistType::kTHnSparseF, {massAxis, pTAxis, centAxis, epAxis}}); + histos.add("hInvMass_f0980_LSpp_EPA", "++ invariant mass", {HistType::kTHnSparseF, {massAxis, pTAxis, centAxis, epAxis}}); + histos.add("hInvMass_f0980_LSmm_EPA", "-- invariant mass", {HistType::kTHnSparseF, {massAxis, pTAxis, centAxis, epAxis}}); } - histos.add("hInvMass_f0980_US_EPA", "unlike invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, EPAxis}}); - histos.add("hInvMass_f0980_LSpp_EPA", "++ invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, EPAxis}}); - histos.add("hInvMass_f0980_LSmm_EPA", "-- invariant mass", - {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, EPAxis}}); - - histos.add("QA/hEPResAB", "", {HistType::kTH2F, {centAxis, EPresAxis}}); - histos.add("QA/hEPResAC", "", {HistType::kTH2F, {centAxis, EPresAxis}}); - histos.add("QA/hEPResBC", "", {HistType::kTH2F, {centAxis, EPresAxis}}); - histos.add("QA/Nsigma_TPC", "", {HistType::kTH2F, {pTqaAxis, PIDqaAxis}}); - histos.add("QA/Nsigma_TOF", "", {HistType::kTH2F, {pTqaAxis, PIDqaAxis}}); - histos.add("QA/TPC_TOF", "", {HistType::kTH2F, {PIDqaAxis, PIDqaAxis}}); + histos.add("QA/EPhist", "", {HistType::kTH2F, {centAxis, epqaAxis}}); + histos.add("QA/hEPResAB", "", {HistType::kTH2F, {centAxis, epResAxis}}); + histos.add("QA/hEPResBC", "", {HistType::kTH2F, {centAxis, epResAxis}}); + histos.add("QA/hEPResAC", "", {HistType::kTH2F, {centAxis, epResAxis}}); histos.add("QA/LTpt", "", {HistType::kTH3F, {pTqaAxis, centAxis, phiqaAxis}}); - histos.add("QA/EPhist", "", {HistType::kTH2F, {centAxis, EPqaAxis}}); + + histos.add("QA/Nsigma_TPC", "", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); + histos.add("QA/Nsigma_TOF", "", {HistType::kTH2F, {pTqaAxis, pidqaAxis}}); + histos.add("QA/Nsigma_TPC_TOF", "", {HistType::kTH2F, {pidqaAxis, pidqaAxis}}); if (doprocessMCLight) { - histos.add("MCL/hpT_f0980_GEN", "generated f0 signals", HistType::kTH1F, - {pTqaAxis}); - histos.add("MCL/hpT_f0980_REC", "reconstructed f0 signals", - HistType::kTH3F, {massAxis, pTqaAxis, centAxis}); + histos.add("MCL/hpT_f0980_GEN", "generated f0 signals", HistType::kTH1F, {pTqaAxis}); + histos.add("MCL/hpT_f0980_REC", "reconstructed f0 signals", HistType::kTH3F, {massAxis, pTqaAxis, centAxis}); } histos.print(); @@ -140,23 +131,28 @@ struct f0980analysis { double massPi = MassPionCharged; - int RTIndex(double pairphi, double lhphi) + static constexpr float OneThird = 1.0f / 3.0f; + static constexpr float PIthird = o2::constants::math::PI * OneThird; + static constexpr float TWOPIthird = o2::constants::math::TwoPI * OneThird; + + int rtIndex(double pairphi, double lhphi) { double dphi = std::fabs(TVector2::Phi_mpi_pi(lhphi - pairphi)); - if (dphi < constants::math::PI / 3.0) + + if (dphi < PIthird) return 0; - if (dphi < 2.0 * constants::math::PI / 3.0 && dphi > constants::math::PI / 3.0) + if (dphi < TWOPIthird && dphi > PIthird) return 1; - if (dphi > 2.0 * constants::math::PI / 3.0) + if (dphi > TWOPIthird) return 2; return -1; } template - bool SelTrack(const TrackType track) + bool selTrack(const TrackType track) { - if (std::abs(track.pt()) < cfgMinPt) + if (std::abs(track.pt()) < cfgMinpT) return false; if (std::fabs(track.eta()) > cfgMaxEta) return false; @@ -166,148 +162,143 @@ struct f0980analysis { return false; if (track.tpcNClsFound() < cfgTPCcluster) return false; - if (cfgHasTOF && !track.hasTOF()) + if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; - if (cfgUseITSRefit && !track.passedITSRefit()) + if (cfgGlobalTrack && !track.isGlobalTrack()) return false; - if (cfgUseTPCRefit && !track.passedTPCRefit()) + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; if (cfgPVContributor && !track.isPVContributor()) return false; - if (cfgPrimaryTrack && !track.isPrimaryTrack()) + if (cfgUseITSRefit && !track.passedITSRefit()) return false; - if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + if (cfgUseTPCRefit && !track.passedTPCRefit()) return false; - if (cfgGlobalTrack && !track.isGlobalTrack()) + if (cfgHasTOF && !track.hasTOF()) return false; return true; } template - bool SelPion(const TrackType track) + bool selPion(const TrackType track) { - if (SelectType == 0) { - if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) - return false; - } - if (SelectType == 1) { - if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion) - return false; - } - if (SelectType == 2) { - if (track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi() >= nsigmaCutCombinedPion * nsigmaCutCombinedPion) - return false; + switch (selectType) { + case 0: + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) + return false; + break; + case 1: + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion) + return false; + break; + case 2: + if (track.tpcNSigmaPi() * track.tpcNSigmaPi() + track.tofNSigmaPi() * track.tofNSigmaPi() >= nsigmaCutCombinedPion * nsigmaCutCombinedPion) + return false; + break; + case 3: + if (track.hasTOF()) { + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPion || std::fabs(track.tofNSigmaPi()) >= cMaxTOFnSigmaPion) + return false; + } else { + if (std::fabs(track.tpcNSigmaPi()) >= cMaxTPCnSigmaPionWoTOF) + return false; + } + break; } return true; } template - void fillHistograms(const CollisionType& collision, - const TracksType& dTracks) + void fillHistograms(const CollisionType& collision, const TracksType& dTracks) { - double LHpt = 0.; - double LHphi = 0.; - double relPhi = 0.; + double lhpT = 0.; + double lhphi = 0.; + double relphi = 0.; if (cfgFindRT) { - for (auto& trk : dTracks) { - if (trk.pt() > LHpt) { - LHpt = trk.pt(); - LHphi = trk.phi(); + for (const auto& trk : dTracks) { + if (trk.pt() > lhpT) { + lhpT = trk.pt(); + lhphi = trk.phi(); } } } - histos.fill(HIST("QA/EPhist"), collision.cent(), collision.evtPl()); histos.fill(HIST("QA/hEPResAB"), collision.cent(), collision.evtPlResAB()); - histos.fill(HIST("QA/hEPResAC"), collision.cent(), collision.evtPlResBC()); - histos.fill(HIST("QA/hEPResBC"), collision.cent(), collision.evtPlResAC()); - histos.fill(HIST("QA/LTpt"), LHpt, collision.cent(), LHphi); - - TLorentzVector Pion1, Pion2, Reco; - for (auto& [trk1, trk2] : - combinations(CombinationsStrictlyUpperIndexPolicy(dTracks, dTracks))) { - if (trk1.index() == trk2.index()) { - if (!SelTrack(trk1)) - continue; - histos.fill(HIST("QA/Nsigma_TPC"), trk1.pt(), trk1.tpcNSigmaPi()); - histos.fill(HIST("QA/Nsigma_TOF"), trk1.pt(), trk1.tofNSigmaPi()); - histos.fill(HIST("QA/TPC_TOF"), trk1.tpcNSigmaPi(), trk1.tofNSigmaPi()); - continue; - } + histos.fill(HIST("QA/hEPResBC"), collision.cent(), collision.evtPlResBC()); + histos.fill(HIST("QA/hEPResAC"), collision.cent(), collision.evtPlResAC()); + histos.fill(HIST("QA/LTpt"), lhpT, collision.cent(), lhphi); - if (!SelTrack(trk1) || !SelTrack(trk2)) - continue; - if (!SelPion(trk1) || !SelPion(trk2)) + ROOT::Math::LorentzVector> pion1, pion2, reco; + for (const auto& [trk1, trk2] : combinations(CombinationsStrictlyUpperIndexPolicy(dTracks, dTracks))) { + + if (!selTrack(trk1) || !selTrack(trk2)) continue; + histos.fill(HIST("QA/Nsigma_TPC"), trk1.pt(), trk1.tpcNSigmaPi()); + histos.fill(HIST("QA/Nsigma_TOF"), trk1.pt(), trk1.tofNSigmaPi()); + histos.fill(HIST("QA/Nsigma_TPC_TOF"), trk1.tpcNSigmaPi(), trk1.tofNSigmaPi()); - Pion1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massPi); - Pion2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); - Reco = Pion1 + Pion2; + if (!selPion(trk1) || !selPion(trk2)) + continue; - if (Reco.Rapidity() > cfgMaxRap || Reco.Rapidity() < cfgMinRap) + 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 (reco.Rapidity() > cfgMaxRap || reco.Rapidity() < cfgMinRap) continue; - relPhi = TVector2::Phi_0_2pi(Reco.Phi() - collision.evtPl()); - if (relPhi > constants::math::PI) { - relPhi -= constants::math::PI; + relphi = TVector2::Phi_0_2pi(reco.Phi() - collision.evtPl()); + if (relphi > o2::constants::math::PI) { + relphi -= o2::constants::math::PI; } if (trk1.sign() * trk2.sign() < 0) { if (cfgFindRT) { - histos.fill(HIST("hInvMass_f0980_US"), Reco.M(), Reco.Pt(), - collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + histos.fill(HIST("hInvMass_f0980_US"), reco.M(), reco.Pt(), collision.cent(), rtIndex(reco.Phi(), lhphi), lhpT); } - histos.fill(HIST("hInvMass_f0980_US_EPA"), Reco.M(), Reco.Pt(), - collision.cent(), relPhi); + histos.fill(HIST("hInvMass_f0980_US_EPA"), reco.M(), reco.Pt(), collision.cent(), relphi); if constexpr (IsMC) { - if (abs(trk1.pdgCode()) != 211 || abs(trk2.pdgCode()) != 211) + if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kPiPlus) continue; if (trk1.motherId() != trk2.motherId()) continue; - if (abs(trk1.motherPDG()) != 9010221) + if (std::abs(trk1.motherPDG()) != 9010221) continue; - histos.fill(HIST("MCL/hpT_f0980_REC"), Reco.M(), Reco.Pt(), - collision.cent()); + histos.fill(HIST("MCL/hpT_f0980_REC"), reco.M(), reco.Pt(), collision.cent()); } } else if (trk1.sign() > 0 && trk2.sign() > 0) { if (cfgFindRT) { - histos.fill(HIST("hInvMass_f0980_LSpp"), Reco.M(), Reco.Pt(), - collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + histos.fill(HIST("hInvMass_f0980_LSpp"), reco.M(), reco.Pt(), collision.cent(), rtIndex(reco.Phi(), lhphi), lhpT); } - histos.fill(HIST("hInvMass_f0980_LSpp_EPA"), Reco.M(), Reco.Pt(), - collision.cent(), relPhi); + histos.fill(HIST("hInvMass_f0980_LSpp_EPA"), reco.M(), reco.Pt(), collision.cent(), relphi); } else if (trk1.sign() < 0 && trk2.sign() < 0) { if (cfgFindRT) { - histos.fill(HIST("hInvMass_f0980_LSmm"), Reco.M(), Reco.Pt(), - collision.cent(), RTIndex(Reco.Phi(), LHphi), LHpt); + histos.fill(HIST("hInvMass_f0980_LSmm"), reco.M(), reco.Pt(), collision.cent(), rtIndex(reco.Phi(), lhphi), lhpT); } - histos.fill(HIST("hInvMass_f0980_LSmm_EPA"), Reco.M(), Reco.Pt(), - collision.cent(), relPhi); + histos.fill(HIST("hInvMass_f0980_LSmm_EPA"), reco.M(), reco.Pt(), collision.cent(), relphi); } } } - void processData(soa::Join::iterator const& collision, - aod::ResoTracks const& resotracks) + void processData(o2::soa::Join::iterator const& collision, + o2::aod::ResoTracks const& resotracks) { fillHistograms(collision, resotracks); } PROCESS_SWITCH(f0980analysis, processData, "Process Event for data", true); void processMCLight( - soa::Join::iterator const& collision, - soa::Join const& resotracks) + o2::soa::Join::iterator const& collision, + o2::soa::Join const& resotracks) { fillHistograms(collision, resotracks); } PROCESS_SWITCH(f0980analysis, processMCLight, "Process Event for MC", false); - void processMCTrue(aod::ResoMCParents& resoParents) + void processMCTrue(const o2::aod::ResoMCParents& resoParents) { - - for (auto& part : resoParents) { // loop over all pre-filtered MC particles - if (abs(part.pdgCode()) != 9010221) + for (const auto& part : resoParents) { // loop over all pre-filtered MC particles + if (std::abs(part.pdgCode()) != 9010221) continue; if (!part.producedByGenerator()) continue; @@ -315,8 +306,8 @@ struct f0980analysis { continue; } bool pass = false; - if ((abs(part.daughterPDG1()) == 211 && - abs(part.daughterPDG2()) == 211)) { + if ((std::abs(part.daughterPDG1()) == kPiPlus && + std::abs(part.daughterPDG2()) == kPiPlus)) { pass = true; } if (!pass) // If we have both decay products diff --git a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx index 51046fcaa16..4279f99bbc0 100644 --- a/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx +++ b/PWGLF/Tasks/Resonances/f0980pbpbanalysis.cxx @@ -15,50 +15,47 @@ #include #include -#include + #include -#include #include +#include +#include // #include #include // #include "TLorentzVector.h" -#include "TRandom3.h" -#include "TF1.h" -#include "TVector2.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/StaticFor.h" - -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/Qvectors.h" +#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" - +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "CommonConstants/PhysicsConstants.h" - -#include "ReconstructionDataFormats/Track.h" - -#include "DataFormatsParameters/GRPObject.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 -#include "CCDB/CcdbApi.h" -#include "CCDB/BasicCCDBManager.h" +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TF1.h" +#include "TRandom3.h" +#include "TVector2.h" +#include // from phi #include "Common/DataModel/PIDResponseITS.h" @@ -132,11 +129,20 @@ struct F0980pbpbanalysis { Configurable cfgTOFBetaCut{"cfgTOFBetaCut", 0.0, "cut TOF beta"}; Configurable cfgDeepAngleSel{"cfgDeepAngleSel", true, "Deep Angle cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; - Configurable cfgTrackIndexSel{"cfgTrackIndexSel", false, "Index selection flag"}; + Configurable cfgTrackIndexSelType{"cfgTrackIndexSelType", 1, "Index selection type"}; + Configurable cMaxTiednSigmaPion{"cMaxTiednSigmaPion", 3.0, "Combined nSigma cut for Pion"}; ConfigurableAxis massAxis{"massAxis", {400, 0.2, 2.2}, "Invariant mass axis"}; ConfigurableAxis ptAxis{"ptAxis", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 13.0, 20.0}, "Transverse momentum Binning"}; ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 100}, "Centrality interval"}; + ConfigurableAxis epAxis{"epAxis", {6, 0.0, o2::constants::math::TwoPI}, "EP axis"}; + + // for event mixing + SliceCache cache; + Configurable cfgNMixedEvents{"cfgNMixedEvents", 10, "Number of mixed events per event"}; + ConfigurableAxis mixingAxisVertex{"mixingAxisVertex", {10, -10, 10}, "Vertex axis for mixing bin"}; + ConfigurableAxis mixingAxisMultiplicity{"mixingAxisMultiplicity", {VARIABLE_WIDTH, 0, 10, 20, 50, 100}, "multiplicity percentile for mixing bin"}; + // ConfigurableAxis mixingAxisMultiplicity{"mixingAxisMultiplicity", {2000, 0, 10000}, "TPC multiplicity for bin"}; TF1* fMultPVCutLow = nullptr; TF1* fMultPVCutHigh = nullptr; @@ -154,6 +160,7 @@ struct F0980pbpbanalysis { double angle; double relPhi; double relPhiRot; + double relPhiMix; // double massPi = o2::constants::physics::MassPionCharged; double massPtl; @@ -174,6 +181,12 @@ struct F0980pbpbanalysis { PtlKaon = 1, }; + enum IndexSelList { + None = 0, + woSame = 1, + leq = 2 + }; + TRandom* rn = new TRandom(); // float theta2; @@ -189,6 +202,8 @@ struct F0980pbpbanalysis { using TrackCandidates = soa::Filtered>; // aod::pidTOFbeta 추가됨 + using BinningTypeVertexContributor = ColumnBinningPolicy; + template int getDetId(const T& name) { @@ -212,6 +227,7 @@ struct F0980pbpbanalysis { template bool eventSelected(TCollision collision) { + constexpr double QvecAmpMin = 1e-4; if (!collision.sel8()) { return 0; } @@ -234,7 +250,7 @@ struct F0980pbpbanalysis { if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return 0; } - if (cfgQvecSel && (collision.qvecAmp()[detId] < 1e-4 || collision.qvecAmp()[refAId] < 1e-4 || collision.qvecAmp()[refBId] < 1e-4)) { + if (cfgQvecSel && (collision.qvecAmp()[detId] < QvecAmpMin || collision.qvecAmp()[refAId] < QvecAmpMin || collision.qvecAmp()[refBId] < QvecAmpMin)) { return 0; } if (cfgOccupancySel && (collision.trackOccupancyInTimeRange() > cfgOccupancyMax || collision.trackOccupancyInTimeRange() < cfgOccupancyMin)) { @@ -320,12 +336,15 @@ struct F0980pbpbanalysis { } } } else if (cfgSelectPID == PIDList::PIDTest) { - if (track.hasTOF()) { - if (std::fabs(getTofNSigma(track)) > cMaxTOFnSigmaPion) { - return 0; - } - if (std::fabs(getTpcNSigma(track)) > cMaxTPCnSigmaPion) { - return 0; + if (cfgUSETOF) { + if (track.hasTOF()) { + if ((getTpcNSigma(track) * getTpcNSigma(track) + getTofNSigma(track) * getTofNSigma(track)) > (cMaxTiednSigmaPion * cMaxTiednSigmaPion)) { + return 0; + } + } else { + if (std::fabs(getTpcNSigma(track)) > cMaxTPCnSigmaPionS) { + return 0; + } } } else { if (std::fabs(getTpcNSigma(track)) > cMaxTPCnSigmaPionS) { @@ -336,6 +355,21 @@ struct F0980pbpbanalysis { return 1; } + template + bool indexSelection(const TrackType1 track1, const TrackType2 track2) + { + if (cfgTrackIndexSelType == IndexSelList::woSame) { + if (track2.globalIndex() == track1.globalIndex()) { + return 0; + } + } else if (cfgTrackIndexSelType == IndexSelList::leq) { + if (track2.globalIndex() <= track1.globalIndex()) { + return 0; + } + } + return 1; + } + template bool selectionPair(const TrackType1 track1, const TrackType2 track2) { @@ -420,11 +454,11 @@ struct F0980pbpbanalysis { histos.fill(HIST("QA/TPC_TOF_selected"), getTpcNSigma(trk2), getTofNSigma(trk2)); } - if (cfgTrackIndexSel && cfgSelectPID == PIDList::PIDTest && trk2.globalIndex() <= trk1.globalIndex()) { + if (!indexSelection(trk1, trk2)) { continue; } - if (cfgSelectPID == PIDList::PIDTest && !selectionPair(trk1, trk2)) { + if (!selectionPair(trk1, trk2)) { continue; } @@ -460,9 +494,104 @@ struct F0980pbpbanalysis { } } + void processEventMixing(EventCandidates const& collisions, TrackCandidates const& tracks) + { + int nmode = 2; // second order + qVecDetInd = detId * 4 + 3 + (nmode - 2) * cfgNQvec * 4; + + auto trackTuple = std::make_tuple(tracks); + BinningTypeVertexContributor binningOnPositions{{mixingAxisVertex, mixingAxisMultiplicity}, true}; + SameKindPair pair{binningOnPositions, cfgNMixedEvents, -1, collisions, trackTuple, &cache}; + ROOT::Math::PxPyPzMVector ptl1, ptl2, recoPtl; + for (const auto& [c1, t1, c2, t2] : pair) { + if (cfgCentEst == CentEstList::FT0C) { + centrality = c1.centFT0C(); + } else if (cfgCentEst == CentEstList::FT0M) { + centrality = c1.centFT0M(); + } + if (!eventSelected(c1) || !eventSelected(c2)) { + continue; + } + if (c1.bcId() == c2.bcId()) { + continue; + } + double eventPlaneDet = std::atan2(c1.qvecIm()[qVecDetInd], c1.qvecRe()[qVecDetInd]) / static_cast(nmode); + + for (const auto& trk1 : t1) { + if (!trackSelected(trk1)) { + continue; + } + if (!selectionPID(trk1)) { + continue; + } + + for (const auto& trk2 : t2) { + if (!trackSelected(trk2)) { + continue; + } + if (!selectionPID(trk2)) { + continue; + } + if (!indexSelection(trk1, trk2)) { + continue; + } + if (!selectionPair(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() > cfgRapMax || recoPtl.Rapidity() < cfgRapMin) { + continue; + } + + relPhiMix = TVector2::Phi_0_2pi((recoPtl.Phi() - eventPlaneDet) * static_cast(nmode)); + + if (trk1.sign() * trk2.sign() < 0) { + histos.fill(HIST("hInvMass_f0980_MixedUS_EPA"), recoPtl.M(), recoPtl.Pt(), centrality, relPhiMix); + } // else if (trk1.sign() > 0 && trk2.sign() > 0) { + // histos.fill(HIST("hInvMass_f0980_MixedLSpp_EPA"), recoPtl.M(), recoPtl.Pt(), centrality, relPhiMix); + // } else if (trk1.sign() < 0 && trk2.sign() < 0) { + // histos.fill(HIST("hInvMass_f0980_MixedLSmm_EPA"), recoPtl.M(), recoPtl.Pt(), centrality, relPhiMix); + // } + } + } + // for (auto& [trk1, trk2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(t1, t2))) { + // if (!trackSelected(trk1) || !trackSelected(trk2)) { + // continue; + // } + // if (!selectionPID(trk1) || !selectionPID(trk2)) { + // continue; + // } + // if (!indexSelection(trk1, trk2)) { + // continue; + // } + // if (!selectionPair(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() > cfgRapMax || recoPtl.Rapidity() < cfgRapMin) { + // continue; + // } + + // relPhiMix = TVector2::Phi_0_2pi((recoPtl.Phi() - eventPlaneDet) * static_cast(nmode)); + + // if (trk1.sign() * trk2.sign() < 0) { + // histos.fill(HIST("hInvMass_f0980_MixedUS_EPA"), recoPtl.M(), recoPtl.Pt(), centrality, relPhiMix); + // } else if (trk1.sign() > 0 && trk2.sign() > 0) { + // histos.fill(HIST("hInvMass_f0980_MixedLSpp_EPA"), recoPtl.M(), recoPtl.Pt(), centrality, relPhiMix); + // } else if (trk1.sign() < 0 && trk2.sign() < 0) { + // histos.fill(HIST("hInvMass_f0980_MixedLSmm_EPA"), recoPtl.M(), recoPtl.Pt(), centrality, relPhiMix); + // } + // } + } + } + PROCESS_SWITCH(F0980pbpbanalysis, processEventMixing, "Process Event mixing", true); + void init(o2::framework::InitContext&) { - AxisSpec epAxis = {6, 0.0, o2::constants::math::TwoPI}; AxisSpec qaCentAxis = {110, 0, 110}; AxisSpec qaVzAxis = {100, -20, 20}; AxisSpec qaPIDAxis = {100, -10, 10}; @@ -494,6 +623,8 @@ struct F0980pbpbanalysis { {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, epAxis}}); histos.add("hInvMass_f0980_USRot_EPA", "unlike invariant mass Rotation", {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, epAxis}}); + histos.add("hInvMass_f0980_MixedUS_EPA", "unlike invariant mass EventMixing", + {HistType::kTHnSparseF, {massAxis, ptAxis, centAxis, epAxis}}); // if (doprocessMCLight) { // histos.add("MCL/hpT_f0980_GEN", "generated f0 signals", HistType::kTH1F, {qaPtAxis}); // histos.add("MCL/hpT_f0980_REC", "reconstructed f0 signals", HistType::kTH3F, {massAxis, qaPtAxis, centAxis}); diff --git a/PWGLF/Tasks/Resonances/higherMassResonances.cxx b/PWGLF/Tasks/Resonances/higherMassResonances.cxx index 252fdd6d658..3a34c13fad2 100644 --- a/PWGLF/Tasks/Resonances/higherMassResonances.cxx +++ b/PWGLF/Tasks/Resonances/higherMassResonances.cxx @@ -14,47 +14,51 @@ /// \author Sawan // #include +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.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/TrackSelectionTables.h" + +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" // +#include "Framework/O2DatabasePDGPlugin.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 #include #include #include #include -#include #include #include #include + +#include #include #include #include +#include #include -#include -#include "TF1.h" -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" - -#include "Common/Core/TrackSelection.h" -#include "Common/Core/trackUtilities.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/Track.h" -#include "Framework/O2DatabasePDGPlugin.h" - -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/EventSelection.h" // -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/PIDResponse.h" // -#include "Common/DataModel/TrackSelectionTables.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/AnalysisTask.h" // -#include "Framework/runDataProcessing.h" // -#include "PWGLF/DataModel/LFStrangenessTables.h" // using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::soa; +using namespace o2::aod::rctsel; // using namespace o2::constants::physics; using std::array; @@ -65,6 +69,16 @@ struct HigherMassResonances { HistogramRegistry hglue{"hglueball", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry hMChists{"hMChists", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + struct RCTCut : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "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; + struct : ConfigurableGroup { // PID and QA Configurable qAv0{"qAv0", false, "qAv0"}; @@ -74,19 +88,21 @@ struct HigherMassResonances { // Configurable invMass1D{"invMass1D", false, "1D invariant mass histograms"}; Configurable correlation2Dhist{"correlation2Dhist", true, "Lamda K0 mass correlation"}; Configurable cDCAv0topv{"cDCAv0topv", false, "DCA V0 to PV"}; - Configurable armcut{"armcut", false, "arm cut"}; + // Configurable armcut{"armcut", false, "arm cut"}; Configurable globalTracks{"globalTracks", false, "Global tracks"}; Configurable hasTPC{"hasTPC", false, "TPC"}; Configurable selectTWOKsOnly{"selectTWOKsOnly", true, "Select only events with two K0s"}; + Configurable applyPairRapidityRec{"applyPairRapidityRec", false, "Apply pair rapidity cut on reconstructed mother (after already applying rapidity cut on generated mother)"}; + Configurable applyPairRapidityGen{"applyPairRapidityGen", false, "Apply pair rapidity cut on generated mother (before applying rapidity cut on reconstructed mother)"}; // Configurables for event selection Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; Configurable cfgETAcut{"cfgETAcut", 0.8f, "Track ETA cut"}; - Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; - Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; - Configurable goodzvertex{"goodzvertex", false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference."}; - Configurable itstpctracks{"itstpctracks", false, "selects collisions with at least one ITS-TPC track,"}; - Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; + Configurable timFrameEvsel{"timFrameEvsel", true, "TPC Time frame boundary cut"}; + // Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; + // Configurable goodzvertex{"goodzvertex", false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference."}; + // Configurable itstpctracks{"itstpctracks", false, "selects collisions with at least one ITS-TPC track,"}; + // Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; // Configurable applyOccupancyCut{"applyOccupancyCut", false, "Apply occupancy cut"}; // Configurable occupancyCut{"occupancyCut", 1000, "Mimimum Occupancy cut"}; @@ -107,7 +123,7 @@ struct HigherMassResonances { Configurable confDaughEta{"confDaughEta", 0.8f, "V0 Daugh sel: max eta"}; Configurable confDaughTPCnclsMin{"confDaughTPCnclsMin", 70.f, "V0 Daugh sel: Min. nCls TPC"}; Configurable confDaughPIDCuts{"confDaughPIDCuts", 5, "PID selections for KS0 daughters"}; - Configurable confarmcut{"confarmcut", 0.2f, "Armenteros cut"}; + // Configurable confarmcut{"confarmcut", 0.2f, "Armenteros cut"}; Configurable confKsrapidity{"confKsrapidity", 0.5f, "Rapidity cut on K0s"}; // Configurable lowmasscutks0{"lowmasscutks0", 0.497 - 4 * 0.005, "Low mass cut on K0s"}; // Configurable highmasscutks0{"highmasscutks0", 0.497 + 4 * 0.005, "High mass cut on K0s"}; @@ -121,10 +137,12 @@ struct HigherMassResonances { ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0., 5., 10., 30., 50., 70., 100., 110., 150.}, "Binning of the centrality axis"}; // Configurable for MC + Configurable isMC{"isMC", false, "Is MC"}; Configurable allGenCollisions{"allGenCollisions", true, "To fill all generated collisions for the signal loss calculations"}; Configurable cTVXEvsel{"cTVXEvsel", true, "Triggger selection"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", false, "avoid split track in MC"}; Configurable selectMCparticles{"selectMCparticles", 1, "0: f0(1710), 1: f2(1525), 2: a2(1320), 3: f0(1370), 4: f0(1500)"}; + Configurable applyRapidityMC{"applyRapidityMC", true, "Apply rapidity cut on generated and reconstructed particles"}; std::vector pdgCodes = {10331, 335, 115, 10221, 9030221}; // output THnSparses @@ -138,51 +156,62 @@ struct HigherMassResonances { // Configurable rapidityks{"rapidityks", true, "rapidity cut on K0s"}; Configurable applyCompetingcut{"applyCompetingcut", false, "Competing cascade rejection cut"}; Configurable competingcascrejlambda{"competingcascrejlambda", 0.005, "rejecting competing cascade lambda"}; - Configurable competingcascrejlambdaanti{"competingcascrejlambdaanti", 0.005, "rejecting competing cascade anti-lambda"}; // If one of the pions is misidentified as a proton, then instead of Ks we reconstruct lambda, therefore the competing cascade rejection cut is applied in which if the reconstrcted mass of a pion and proton (which we are assuming to be misidentified as proton) is close to lambda or anti-lambda, then the track is rejected + // Configurable competingcascrejlambdaanti{"competingcascrejlambdaanti", 0.005, "rejecting competing cascade anti-lambda"}; // If one of the pions is misidentified as a proton, then instead of Ks we reconstruct lambda, therefore the competing cascade rejection cut is applied in which if the reconstrcted mass of a pion and proton (which we are assuming to be misidentified as proton) is close to lambda or anti-lambda, then the track is rejected Configurable tpcCrossedrows{"tpcCrossedrows", 70, "TPC crossed rows"}; Configurable tpcCrossedrowsOverfcls{"tpcCrossedrowsOverfcls", 0.8, "TPC crossed rows over findable clusters"}; - // Mass and pT axis as configurables - Configurable cPtMin{"cPtMin", 0.0f, "Minimum pT"}; - Configurable cPtMax{"cPtMax", 30.0f, "Maximum pT"}; - Configurable cPtBins{"cPtBins", 300, "Number of pT bins"}; - Configurable cMassMin{"cMassMin", 0.9f, "Minimum mass of glueball"}; - Configurable cMassMax{"cMassMax", 3.0f, "Maximum mass of glueball"}; - Configurable cMassBins{"cMassBins", 210, "Number of mass bins for glueball"}; - Configurable ksMassMin{"ksMassMin", 0.45f, "Minimum mass of K0s"}; - Configurable ksMassMax{"ksMassMax", 0.55f, "Maximum mass of K0s"}; - Configurable ksMassBins{"ksMassBins", 200, "Number of mass bins for K0s"}; + // // Mass and pT axis as configurables Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + ConfigurableAxis configThnAxisPhi{"configThnAxisPhi", {70, 0.0f, 7.0f}, "Phi axis"}; // 0 to 2pi + ConfigurableAxis ksMassBins{"ksMassBins", {200, 0.45f, 0.55f}, "K0s invariant mass axis"}; + ConfigurableAxis cGlueMassBins{"cGlueMassBins", {200, 0.9f, 3.0f}, "Glueball invariant mass axis"}; + ConfigurableAxis cPtBins{"cPtBins", {200, 0.0f, 20.0f}, "Glueball pT axis"}; // ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; // ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; // ConfigurableAxis axisMultdist{"axisMultdist", {3500, 0, 70000}, "Multiplicity distribution"}; - // ConfigurableAxis occupancyBins{"occupancyBins", {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: occupancy axis"}; + + // fixed variables + float rapidityMotherData = 0.5; + float beamEnergy = 13600.0; + double beamMomentum = std::sqrt(beamEnergy * beamEnergy / 4 - o2::constants::physics::MassProton * o2::constants::physics::MassProton); // GeV + int noOfDaughters = 2; } config; // Service PDGdatabase; TRandom* rn = new TRandom(); // variables declaration - TLorentzVector lv1, lv2, lv3, lv4, lv5; float multiplicity = 0.0f; float theta2; - ROOT::Math::PxPyPzMVector daughter1, daughter2, fourVecDau1, fourVecMother, fourVecDauCM; - ROOT::Math::XYZVector threeVecDauCM, helicityVec, randomVec, beamVec, normalVec; + ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterRot, daughterRotCM, mother, motherRot, fourVecDauCM, fourVecDauCM1; + ROOT::Math::PxPyPzEVector mother1; + ROOT::Math::XYZVector randomVec, beamVec, normalVec; + ROOT::Math::XYZVectorF v1CM, zaxisHE, yaxisHE, xaxisHE; + // ROOT::Math::XYZVector threeVecDauCM, helicityVec, randomVec, beamVec, normalVec; + ROOT::Math::XYZVector zBeam; // ẑ: beam direction in lab frame + ROOT::Math::PxPyPzEVector beam1{0., 0., -config.beamMomentum, 13600. / 2.}; + ROOT::Math::PxPyPzEVector beam2{0., 0., config.beamMomentum, 13600. / 2.}; + ROOT::Math::XYZVectorF beam1CM, beam2CM; + // const double massK0s = o2::constants::physics::MassK0Short; bool isMix = false; void init(InitContext const&) { + rctCut.rctChecker.init( + rctCut.cfgEvtRCTFlagCheckerLabel, + rctCut.cfgEvtRCTFlagCheckerZDCCheck, + rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + // Axes - AxisSpec k0ShortMassAxis = {config.ksMassBins, config.ksMassMin, config.ksMassMax, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - AxisSpec glueballMassAxis = {config.cMassBins, config.cMassMin, config.cMassMax, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec k0ShortMassAxis = {config.ksMassBins, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec glueballMassAxis = {config.cGlueMassBins, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec vertexZAxis = {60, -15.f, 15.f, "vrtx_{Z} [cm]"}; // for histogram - AxisSpec ptAxis = {config.cPtBins, config.cPtMin, config.cPtMax, "#it{p}_{T} (GeV/#it{c})"}; - // AxisSpec multiplicityAxis = {110, 0.0f, 150.0f, "Multiplicity Axis"}; + AxisSpec ptAxis = {config.cPtBins, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec multiplicityAxis = {config.binsCent, "Multiplicity Axis"}; AxisSpec thnAxisPOL{config.configThnAxisPOL, "Configurabel theta axis"}; - // AxisSpec occupancyAxis = {occupancyBins, "Occupancy [-40,100]"}; + AxisSpec thnAxisPhi = {config.configThnAxisPhi, "Configurabel phi axis"}; // 0 to 2pi // THnSparses std::array sparses = {config.activateTHnSparseCosThStarHelicity, config.activateTHnSparseCosThStarProduction, config.activateTHnSparseCosThStarBeam, config.activateTHnSparseCosThStarRandom}; @@ -216,9 +245,9 @@ struct HigherMassResonances { // rEventSelection.add("hNcontributor", "Number of primary vertex contributor", kTH1F, {{2000, 0.0f, 10000.0f}}); } - hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); - hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); - hglue.add("h3glueInvMassRot", "h3glueInvMassRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}, true); + hglue.add("h3glueInvMassDS", "h3glueInvMassDS", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL, thnAxisPhi}, true); + hglue.add("h3glueInvMassME", "h3glueInvMassME", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL, thnAxisPhi}, true); + hglue.add("h3glueInvMassRot", "h3glueInvMassRot", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL, thnAxisPhi}, true); hglue.add("heventscheck", "heventscheck", kTH1I, {{10, 0, 10}}); hglue.add("htrackscheck_v0", "htrackscheck_v0", kTH1I, {{15, 0, 15}}); hglue.add("htrackscheck_v0_daughters", "htrackscheck_v0_daughters", kTH1I, {{15, 0, 15}}); @@ -286,27 +315,37 @@ struct HigherMassResonances { // } // For MC - hMChists.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); - hMChists.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); - hMChists.add("Genf1710", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis}); - hMChists.add("Recf1710_pt1", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}); - hMChists.add("Recf1710_pt2", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis}); - hMChists.add("Recf1710_p", "Rec f_{0}(1710) p", kTH1F, {ptAxis}); - hMChists.add("h1Recsplit", "Rec p_{T}2", kTH1F, {ptAxis}); - - hMChists.add("Recf1710_mass", "Rec f_{0}(1710) mass", kTH1F, {glueballMassAxis}); - hMChists.add("Genf1710_mass", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); - hMChists.add("GenEta", "Gen Eta", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); - hMChists.add("GenPhi", "Gen Phi", kTH1F, {{70, -3.5f, 3.5f}}); - hMChists.add("GenRapidity", "Gen Rapidity", kTHnSparseF, {ptAxis, {100, -1.0f, 1.0f}}); - hMChists.add("RecEta", "Rec Eta", kTH1F, {{100, -1.0f, 1.0f}}); - hMChists.add("RecPhi", "Rec Phi", kTH1F, {{70, 0.0f, 7.0f}}); - hMChists.add("RecRapidity", "Rec Rapidity", kTH1F, {{100, -1.0f, 1.0f}}); - hMChists.add("MC_mult", "Multiplicity in MC", kTH1F, {multiplicityAxis}); - hMChists.add("MC_mult_after_event_sel", "Multiplicity in MC", kTH1F, {multiplicityAxis}); - // hMChists.add("GenPx", "Gen Px", kTH1F, {{100, -10.0f, 10.0f}}); - // hMChists.add("GenPy", "Gen Py", kTH1F, {{100, -10.0f, 10.0f}}); - // hMChists.add("GenPz", "Gen Pz", kTH1F, {{100, -10.0f, 10.0f}}); + if (config.isMC) { + hMChists.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); + hMChists.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{25, 0, 25}}); + hMChists.add("Genf1710", "Gen f_{0}(1710)", kTHnSparseF, {multiplicityAxis, ptAxis, thnAxisPOL}); + hMChists.add("Genf17102", "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("Recf1710_pt2", "Rec f_{0}(1710) p_{T}", kTHnSparseF, {multiplicityAxis, ptAxis, glueballMassAxis, thnAxisPOL}); + // hMChists.add("Recf1710_p", "Rec f_{0}(1710) p", kTH1F, {ptAxis}); + hMChists.add("h1Recsplit", "Rec p_{T}2", kTH1F, {ptAxis}); + // hMChists.add("Recf1710_mass", "Rec f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + hMChists.add("Genf1710_mass", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + hMChists.add("Genf1710_mass2", "Gen f_{0}(1710) mass", kTH1F, {glueballMassAxis}); + // hMChists.add("Genf1710_pt2", "Gen f_{0}(1710) p_{T}", kTH1F, {ptAxis}); + hMChists.add("GenPhi", "Gen Phi", kTH1F, {{70, 0.0, 7.0f}}); + hMChists.add("GenPhi2", "Gen Phi", kTH1F, {{70, 0.0, 7.0f}}); + hMChists.add("GenEta", "Gen Eta", kTHnSparseF, {{150, -1.5f, 1.5f}}); + hMChists.add("GenEta2", "Gen Eta", kTHnSparseF, {{150, -1.5f, 1.5f}}); + hMChists.add("GenRapidity", "Gen Rapidity", kTHnSparseF, {{100, -1.0f, 1.0f}}); + hMChists.add("GenRapidity2", "Gen Rapidity", kTHnSparseF, {{100, -1.0f, 1.0f}}); + hMChists.add("RecEta", "Rec Eta", kTH1F, {{150, -1.5f, 1.5f}}); + hMChists.add("RecEta2", "Rec Eta", kTH1F, {{150, -1.5f, 1.5f}}); + hMChists.add("RecPhi", "Rec Phi", kTH1F, {{70, 0.0f, 7.0f}}); + hMChists.add("RecPhi2", "Rec Phi", kTH1F, {{70, 0.0f, 7.0f}}); + hMChists.add("RecRapidity", "Rec Rapidity", kTH1F, {{100, -1.0f, 1.0f}}); + hMChists.add("RecRapidity2", "Rec Rapidity", kTH1F, {{100, -1.0f, 1.0f}}); + hMChists.add("Rec_Multiplicity", "Multiplicity in MC", kTH1F, {multiplicityAxis}); + hMChists.add("MC_mult_after_event_sel", "Multiplicity in MC", kTH1F, {multiplicityAxis}); + // hMChists.add("GenPx", "Gen Px", kTH1F, {{100, -10.0f, 10.0f}}); + // hMChists.add("GenPy", "Gen Py", kTH1F, {{100, -10.0f, 10.0f}}); + // hMChists.add("GenPz", "Gen Pz", kTH1F, {{100, -10.0f, 10.0f}}); + } } template @@ -324,20 +363,20 @@ struct HigherMassResonances { } hglue.fill(HIST("heventscheck"), 3.5); - if (config.piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - return false; - } - hglue.fill(HIST("heventscheck"), 4.5); + // if (config.piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // return false; + // } + // hglue.fill(HIST("heventscheck"), 4.5); - if (config.goodzvertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - return false; - } - hglue.fill(HIST("heventscheck"), 5.5); + // if (config.goodzvertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // return false; + // } + // hglue.fill(HIST("heventscheck"), 5.5); - if (config.itstpctracks && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - return false; - } - hglue.fill(HIST("heventscheck"), 6.5); + // if (config.itstpctracks && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + // return false; + // } + // hglue.fill(HIST("heventscheck"), 6.5); return true; } @@ -345,17 +384,17 @@ struct HigherMassResonances { template bool selectionV0(Collision const& collision, V0 const& candidate, float /*multiplicity*/) { - const float qtarm = candidate.qtarm(); - const float alph = candidate.alpha(); - float arm = qtarm / alph; + // const float qtarm = candidate.qtarm(); + // const float alph = candidate.alpha(); + // float arm = qtarm / alph; const float pT = candidate.pt(); const float tranRad = candidate.v0radius(); const float dcaDaughv0 = candidate.dcaV0daughters(); const float cpav0 = candidate.v0cosPA(); float ctauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short; - float lowmasscutks0 = 0.497 - config.cWidthKs0 * config.cSigmaMassKs0; - float highmasscutks0 = 0.497 + config.cWidthKs0 * config.cSigmaMassKs0; + float lowmasscutks0 = o2::constants::physics::MassKPlus - config.cWidthKs0 * config.cSigmaMassKs0; + float highmasscutks0 = o2::constants::physics::MassKPlus + config.cWidthKs0 * config.cSigmaMassKs0; // float decayLength = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * RecoDecay::sqrtSumOfSquares(candidate.px(), candidate.py(), candidate.pz()); if (config.qAv0) { @@ -441,15 +480,15 @@ struct HigherMassResonances { // if (config.correlation2Dhist) // rKzeroShort.fill(HIST("mass_lambda_kshort_after8"), candidate.mK0Short(), candidate.mLambda()); - if (config.armcut && arm < config.confarmcut) { - return false; - } + // if (config.armcut && arm < config.confarmcut) { + // return false; + // } hglue.fill(HIST("htrackscheck_v0"), 9.5); // if (config.correlation2Dhist) // rKzeroShort.fill(HIST("mass_lambda_kshort_after9"), candidate.mK0Short(), candidate.mLambda()); // if (config.applyCompetingcut && (std::abs(candidate.mLambda() - PDGdatabase->Mass(3122)) <= config.competingcascrejlambda || std::abs(candidate.mAntiLambda() - PDGdatabase->Mass(-3122)) <= config.competingcascrejlambdaanti)) - if (config.applyCompetingcut && (std::abs(candidate.mLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambda || std::abs(candidate.mAntiLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambdaanti)) { + if (config.applyCompetingcut && (std::abs(candidate.mLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambda || std::abs(candidate.mAntiLambda() - o2::constants::physics::MassLambda0) <= config.competingcascrejlambda)) { return false; } hglue.fill(HIST("htrackscheck_v0"), 10.5); @@ -542,7 +581,9 @@ struct HigherMassResonances { phi2 = candidate2.phi(); double angle = std::sqrt(std::pow(eta1 - eta2, 2) + std::pow(phi1 - phi2, 2)); - rKzeroShort.fill(HIST("angularSeparation"), angle); + if (config.qAv0) { + rKzeroShort.fill(HIST("angularSeparation"), angle); + } if (config.applyAngSepCut && angle > config.angSepCut) { return false; } @@ -564,79 +605,149 @@ struct HigherMassResonances { // For Monte Carlo using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; - using V0TrackCandidatesMC = soa::Join; + using V0TrackCandidatesMC = soa::Filtered>; + // zBeam direction in lab frame - template - void fillInvMass(const T2& lv3, const T3& lv5, float multiplicity, const T4& daughter1, bool isMix) + template + void fillInvMass(const T& mother, float multiplicity, const T& daughter1, const T& daughter2, bool isMix) { - // polarization calculations + // //polarization calculations + // zBeam = ROOT::Math::XYZVector(0.f, 0.f, 1.f); // ẑ: beam direction in lab frame - fourVecDau1 = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), o2::constants::physics::MassK0Short); // Kaon or Pion + ROOT::Math::Boost boost{mother.BoostToCM()}; // define the boost to the center of mass frame + fourVecDauCM = boost(daughter1); // boost the frame of daughter to the center of mass frame + // threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter same as mother - threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother + beam1CM = ROOT::Math::XYZVectorF((boost(beam1).Vect()).Unit()); + beam2CM = ROOT::Math::XYZVectorF((boost(beam2).Vect()).Unit()); - if (std::abs(lv3.Rapidity()) < 0.5) { - if (config.activateTHnSparseCosThStarHelicity) { - helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); - if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); - - for (int i = 0; i < config.cRotations; i++) { - theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity); - } - } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + // define y = zBeam x z: Normal to the production plane + // ẑ: mother direction in lab, boosted into mother's rest frame + + // auto motherLabDirection = ROOT::Math::XYZVector(0, 0, mother.Vect().Z()); // ẑ axis in lab frame + + // // ŷ = zBeam × ẑ + // auto y_axis = zBeam.Cross(motherLabDirection).Unit(); + + // // x̂ = ŷ × ẑ + // auto x_axis = y_axis.Cross(motherLabDirection).Unit(); + + // // Project daughter momentum onto x–y plane + // auto p_proj_x = threeVecDauCM.Dot(x_axis); + // auto p_proj_y = threeVecDauCM.Dot(y_axis); + + // // Calculate φ in [-π, π] + // auto anglePhi = std::atan2(p_proj_y, p_proj_x); // φ in radians + + v1CM = ROOT::Math::XYZVectorF(boost(daughter1).Vect()).Unit(); + // ROOT::Math::XYZVectorF v2_CM{(boost(daughter1).Vect()).Unit()}; + // using positive sign convention for the first track + // ROOT::Math::XYZVectorF v_CM = (t1.sign() > 0 ? v1CM : v2_CM); // here selected decay daughter momentum is intested. here you can choose one decay daughter no need to check both case as it is neutral particle for our case + // Helicity frame + zaxisHE = ROOT::Math::XYZVectorF(mother.Vect()).Unit(); + yaxisHE = ROOT::Math::XYZVectorF(beam1CM.Cross(beam2CM)).Unit(); + xaxisHE = ROOT::Math::XYZVectorF(yaxisHE.Cross(zaxisHE)).Unit(); + + // CosThetaHE = zaxisHE.Dot(v_CM); + + auto anglePhi = std::atan2(yaxisHE.Dot(v1CM), xaxisHE.Dot(v1CM)); + anglePhi = RecoDecay::constrainAngle(anglePhi, 0.0); + // if (anglePhi < 0) { + // anglePhi += o2::constants::math::TwoPI; // ensure phi is in [0, 2pi] + // } + + // if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + if (config.activateTHnSparseCosThStarHelicity) { + // helicityVec = mother.Vect(); // 3 vector of mother in COM frame + // auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + auto cosThetaStarHelicity = mother.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(mother.Vect().Mag2())); + if (!isMix) { + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity, anglePhi); } - } else if (config.activateTHnSparseCosThStarProduction) { - normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); - auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); - if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); - for (int i = 0; i < config.cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction); + for (int i = 0; i < config.cRotations; i++) { + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.rotationalCut); + + 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; + + ROOT::Math::Boost boost2{motherRot.BoostToCM()}; + daughterRotCM = boost2(daughterRot); + + auto cosThetaStarHelicityRot = motherRot.Vect().Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(motherRot.Vect().Mag2())); + if (motherRot.Rapidity() < config.rapidityMotherData) + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarHelicityRot, anglePhi); + } + } else { + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity, anglePhi); + } + } + } else if (config.activateTHnSparseCosThStarProduction) { + normalVec = ROOT::Math::XYZVector(mother.Py(), -mother.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(normalVec.Mag2())); + if (!isMix) { + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction, anglePhi); + } + for (int i = 0; i < config.cRotations; i++) { + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.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()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarProduction, anglePhi); } - } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); } - - } else if (config.activateTHnSparseCosThStarBeam) { - beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); - for (int i = 0; i < config.cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam); + } else { + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction, anglePhi); + } + } + } else if (config.activateTHnSparseCosThStarBeam) { + 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()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam, anglePhi); + } + for (int i = 0; i < config.cRotations; i++) { + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.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()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarBeam, anglePhi); } - } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); } - - } else if (config.activateTHnSparseCosThStarRandom) { - auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); - auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); - - randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - if (!isMix) { - hglue.fill(HIST("h3glueInvMassDS"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); - for (int i = 0; i < config.cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - hglue.fill(HIST("h3glueInvMassRot"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom); + } else { + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam, anglePhi); + } + } + } else if (config.activateTHnSparseCosThStarRandom) { + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + + randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); + if (!isMix) { + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassDS"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom, anglePhi); + } + for (int i = 0; i < config.cRotations; i++) { + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / config.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / config.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()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassRot"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarRandom, anglePhi); } - } else { - hglue.fill(HIST("h3glueInvMassME"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + } + } else { + if (std::abs(mother.Rapidity()) < config.rapidityMotherData) { + hglue.fill(HIST("h3glueInvMassME"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom, anglePhi); } } } + // } } void processSE(EventCandidates::iterator const& collision, TrackCandidates const& /*tracks*/, aod::V0Datas const& V0s) @@ -652,6 +763,10 @@ struct HigherMassResonances { return; } + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(collision)) { + return; + } + // auto occupancyNumber = collision.trackOccupancyInTimeRange(); // if (applyOccupancyCut && occupancyNumber < occupancyCut) { // return; @@ -735,37 +850,304 @@ struct HigherMassResonances { } allConditionsMet = 1; daughter1 = ROOT::Math::PxPyPzMVector(v1.px(), v1.py(), v1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(v2.px(), v2.py(), v2.pz(), o2::constants::physics::MassK0Short); // Kshort - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv5.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi(), o2::constants::physics::MassK0Short); - lv2.SetPtEtaPhiM(v2.pt(), v2.eta(), v2.phi(), o2::constants::physics::MassK0Short); - lv4.SetPtEtaPhiM(v1.pt(), v1.eta(), v1.phi() + theta2, o2::constants::physics::MassK0Short); // for rotated background - lv3 = lv1 + lv2; - lv5 = lv2 + lv4; + mother = daughter1 + daughter2; // invariant mass of Kshort pair isMix = false; if (!config.selectTWOKsOnly) - fillInvMass(lv3, lv5, multiplicity, daughter1, isMix); + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); } int sizeofv0indexes = v0indexes.size(); rKzeroShort.fill(HIST("NksProduced"), sizeofv0indexes); - if (config.selectTWOKsOnly && sizeofv0indexes == 2 && allConditionsMet) { - fillInvMass(lv3, lv5, multiplicity, daughter1, false); + if (config.selectTWOKsOnly && sizeofv0indexes == config.noOfDaughters && allConditionsMet) { + fillInvMass(mother, multiplicity, daughter1, daughter2, false); } v0indexes.clear(); } - PROCESS_SWITCH(HigherMassResonances, processSE, "same event process", true); + using EventCandidatesDerivedData = soa::Join; + using V0CandidatesDerivedData = soa::Join; + using DauTracks = soa::Join; + + void processSEderived(EventCandidatesDerivedData::iterator const& collision, TrackCandidates const& /*tracks*/, aod::V0Datas const& V0s) + { + hglue.fill(HIST("heventscheck"), 0.5); + multiplicity = 0.0; + if (config.cfgMultFOTM) { + multiplicity = collision.centFT0M(); + } else { + multiplicity = collision.centFT0C(); + } + if (!eventselection(collision)) { + return; + } + + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(collision)) { + return; + } + + // auto occupancyNumber = collision.trackOccupancyInTimeRange(); + // if (applyOccupancyCut && occupancyNumber < occupancyCut) { + // return; + // } + + if (config.qAevents) { + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + rEventSelection.fill(HIST("hmultiplicity"), multiplicity); + // rEventSelection.fill(HIST("multdist_FT0M"), collision.multFT0M()); + // rEventSelection.fill(HIST("multdist_FT0A"), collision.multFT0A()); + // rEventSelection.fill(HIST("multdist_FT0C"), collision.multFT0C()); + // rEventSelection.fill(HIST("hNcontributor"), collision.numContrib()); + } + + std::vector v0indexes; + bool allConditionsMet = 0; + + for (const auto& [v1, v2] : combinations(CombinationsFullIndexPolicy(V0s, V0s))) { + + if (v1.size() == 0 || v2.size() == 0) { + continue; + } + + if (!selectionV0(collision, v1, multiplicity)) { + continue; + } + if (!selectionV0(collision, v2, multiplicity)) { + continue; + } + + auto postrack1 = v1.template posTrack_as(); + auto negtrack1 = v1.template negTrack_as(); + auto postrack2 = v2.template posTrack_as(); + auto negtrack2 = v2.template negTrack_as(); + + double nTPCSigmaPos1{postrack1.tpcNSigmaPi()}; + double nTPCSigmaNeg1{negtrack1.tpcNSigmaPi()}; + double nTPCSigmaPos2{postrack2.tpcNSigmaPi()}; + double nTPCSigmaNeg2{negtrack2.tpcNSigmaPi()}; + + if (!(isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, v1) && isSelectedV0Daughter(postrack1, 1, nTPCSigmaPos1, v1))) { + continue; + } + if (!(isSelectedV0Daughter(postrack2, 1, nTPCSigmaPos2, v2) && isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, v2))) { + continue; + } + + if (std::find(v0indexes.begin(), v0indexes.end(), v1.globalIndex()) == v0indexes.end()) { + v0indexes.push_back(v1.globalIndex()); + } + // if (!(std::find(v0indexes.begin(), v0indexes.end(), v2.globalIndex()) != v0indexes.end())) { + // v0indexes.push_back(v2.globalIndex()); + // } + + if (v2.globalIndex() <= v1.globalIndex()) { + continue; + } + + // if (config.qAv0Daughters) { + // rKzeroShort.fill(HIST("negative_pt"), negtrack1.pt()); + // rKzeroShort.fill(HIST("positive_pt"), postrack1.pt()); + // rKzeroShort.fill(HIST("negative_eta"), negtrack1.eta()); + // rKzeroShort.fill(HIST("positive_eta"), postrack1.eta()); + // rKzeroShort.fill(HIST("negative_phi"), negtrack1.phi()); + // rKzeroShort.fill(HIST("positive_phi"), postrack1.phi()); + // } + + if (postrack1.globalIndex() == postrack2.globalIndex()) { + continue; + } + if (negtrack1.globalIndex() == negtrack2.globalIndex()) { + continue; + } + + if (!applyAngSep(v1, v2)) { + continue; + } + + if (config.qAv0) { + rKzeroShort.fill(HIST("hMasscorrelationbefore"), v1.mK0Short(), v2.mK0Short()); + } + allConditionsMet = 1; + daughter1 = ROOT::Math::PxPyPzMVector(v1.px(), v1.py(), v1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(v2.px(), v2.py(), v2.pz(), o2::constants::physics::MassK0Short); // Kshort + + mother = daughter1 + daughter2; // invariant mass of Kshort pair + isMix = false; + + if (!config.selectTWOKsOnly) + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); + } + int sizeofv0indexes = v0indexes.size(); + rKzeroShort.fill(HIST("NksProduced"), sizeofv0indexes); + if (config.selectTWOKsOnly && sizeofv0indexes == config.noOfDaughters && allConditionsMet) { + fillInvMass(mother, multiplicity, daughter1, daughter2, false); + } + v0indexes.clear(); + } + PROCESS_SWITCH(HigherMassResonances, processSEderived, "same event process in strangeness derived data", true); + + ConfigurableAxis mevz = {"mevz", {10, -10., 10.}, "mixed event vertex z binning"}; + ConfigurableAxis memult = {"memult", {20, 0, 100}, "mixed event multiplicity binning"}; + + // Processing Event Mixing + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{mevz, memult}, true}; + Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only + + void processMEderived(EventCandidatesDerivedData const& collisions, TrackCandidates const& /*tracks*/, V0CandidatesDerivedData const& v0s) + { + // auto tracksTuple = std::make_tuple(v0s); + // BinningTypeVertexContributor binningOnPositions1{{mevz, memult}, true}; + // BinningTypeCentralityM binningOnPositions2{{mevz, memult}, true}; + + // SameKindPair pair1{binningOnPositions1, config.cfgNmixedEvents, -1, collisions, tracksTuple, &cache}; // for PbPb + // SameKindPair pair2{binningOnPositions2, config.cfgNmixedEvents, -1, collisions, tracksTuple, &cache}; // for pp + + // if (config.cfgMultFOTM) { + for (const auto& [c1, c2] : selfCombinations(colBinning, config.cfgNmixedEvents, -1, collisions, collisions)) // two different centrality c1 and c2 and tracks corresponding to them + { + + multiplicity = 0.0; + multiplicity = c1.centFT0M(); + + if (!eventselection(c1) || !eventselection(c2)) { + continue; + } + // auto occupancyNumber = c1.trackOccupancyInTimeRange(); + // auto occupancyNumber2 = c2.trackOccupancyInTimeRange(); + // if (applyOccupancyCut && (occupancyNumber < occupancyCut || occupancyNumber2 < occupancyCut)) { + // return; + // } + + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(c1)) { + return; + } + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(c2)) { + return; + } + auto groupV01 = v0s.sliceBy(tracksPerCollisionV0Mixed, c1.index()); + auto groupV02 = v0s.sliceBy(tracksPerCollisionV0Mixed, c2.index()); + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV02))) { + + if (t1.size() == 0 || t2.size() == 0) { + continue; + } + + if (!selectionV0(c1, t1, multiplicity)) + continue; + if (!selectionV0(c2, t2, multiplicity)) + continue; + + auto postrack1 = t1.template posTrackExtra_as(); + auto negtrack1 = t1.template negTrackExtra_as(); + auto postrack2 = t2.template posTrackExtra_as(); + auto negtrack2 = t2.template negTrackExtra_as(); + + if (postrack1.globalIndex() == postrack2.globalIndex()) { + continue; + } + if (negtrack1.globalIndex() == negtrack2.globalIndex()) { + continue; + } + double nTPCSigmaPos1{postrack1.tpcNSigmaPi()}; + double nTPCSigmaNeg1{negtrack1.tpcNSigmaPi()}; + double nTPCSigmaPos2{postrack2.tpcNSigmaPi()}; + double nTPCSigmaNeg2{negtrack2.tpcNSigmaPi()}; + + if (!isSelectedV0Daughter(postrack1, 1, nTPCSigmaPos1, t1)) { + continue; + } + if (!isSelectedV0Daughter(postrack2, 1, nTPCSigmaPos2, t2)) { + continue; + } + if (!isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, t1)) { + continue; + } + if (!isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { + continue; + } + + daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), o2::constants::physics::MassK0Short); // Kshort + + mother = daughter1 + daughter2; // invariant mass of Kshort pair + isMix = true; + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); + } + } + // } + // else { + // for (const auto& [c1, tracks1, c2, tracks2] : pair1) // two different centrality c1 and c2 and tracks corresponding to them + // { + // multiplicity = 0.0f; + // multiplicity = c1.centFT0C(); + + // if (!eventselection(c1) || !eventselection(c2)) { + // continue; + // } + // // auto occupancyNumber = c1.trackOccupancyInTimeRange(); + // // auto occupancyNumber2 = c2.trackOccupancyInTimeRange(); + // // if (applyOccupancyCut && (occupancyNumber < occupancyCut || occupancyNumber2 < occupancyCut)) { + // // return; + // // } + + // for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + // if (t1.size() == 0 || t2.size() == 0) { + // continue; + // } + + // if (!selectionV0(c1, t1, multiplicity)) + // continue; + // if (!selectionV0(c2, t2, multiplicity)) + // continue; + + // auto postrack1 = t1.template posTrack_as(); + // auto negtrack1 = t1.template negTrack_as(); + // auto postrack2 = t2.template posTrack_as(); + // auto negtrack2 = t2.template negTrack_as(); + // if (postrack1.globalIndex() == postrack2.globalIndex()) { + // continue; + // } + // if (negtrack1.globalIndex() == negtrack2.globalIndex()) { + // continue; + // } + // double nTPCSigmaPos1{postrack1.tpcNSigmaPi()}; + // double nTPCSigmaNeg1{negtrack1.tpcNSigmaPi()}; + // double nTPCSigmaPos2{postrack2.tpcNSigmaPi()}; + // double nTPCSigmaNeg2{negtrack2.tpcNSigmaPi()}; + + // if (!isSelectedV0Daughter(postrack1, 1, nTPCSigmaPos1, t1)) { + // continue; + // } + // if (!isSelectedV0Daughter(postrack2, 1, nTPCSigmaPos2, t2)) { + // continue; + // } + // if (!isSelectedV0Daughter(negtrack1, -1, nTPCSigmaNeg1, t1)) { + // continue; + // } + // if (!isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { + // continue; + // } + // daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassK0Short); // Kshort + // daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), o2::constants::physics::MassK0Short); // Kshort + + // mother = daughter1 + daughter2; // invariant mass of Kshort pair + // isMix = true; + // fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); + // } + // } + // } + } + PROCESS_SWITCH(HigherMassResonances, processMEderived, "mixed event process in derived data", true); + array pvec0; array pvec1; // use any one of 3 alias depending on the dataset. If pp then FT0M and if pbpb then FTOC using BinningTypeTPCMultiplicity = ColumnBinningPolicy; using BinningTypeCentralityM = ColumnBinningPolicy; using BinningTypeVertexContributor = ColumnBinningPolicy; - ConfigurableAxis mevz = {"mevz", {10, -10., 10.}, "mixed event vertex z binning"}; - ConfigurableAxis memult = {"memult", {2000, 0, 10000}, "mixed event multiplicity binning"}; void processME(EventCandidates const& collisions, TrackCandidates const& /*tracks*/, V0TrackCandidate const& v0s) { @@ -792,6 +1174,13 @@ struct HigherMassResonances { // return; // } + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(c1)) { + return; + } + if (rctCut.requireRCTFlagChecker && !rctCut.rctChecker(c2)) { + return; + } + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (t1.size() == 0 || t2.size() == 0) { @@ -832,15 +1221,11 @@ struct HigherMassResonances { } daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), o2::constants::physics::MassK0Short); // Kshort - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassK0Short); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassK0Short); - lv4.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi() + theta2, o2::constants::physics::MassK0Short); // for rotated background - lv3 = lv1 + lv2; - lv5 = lv2 + lv4; + mother = daughter1 + daughter2; // invariant mass of Kshort pair isMix = true; - fillInvMass(lv3, lv5, multiplicity, daughter1, isMix); + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); } } } else { @@ -895,17 +1280,12 @@ struct HigherMassResonances { if (!isSelectedV0Daughter(negtrack2, -1, nTPCSigmaNeg2, t2)) { continue; } - daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassK0Short); // Kshort + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), o2::constants::physics::MassK0Short); // Kshort - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), o2::constants::physics::MassK0Short); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), o2::constants::physics::MassK0Short); - lv4.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi() + theta2, o2::constants::physics::MassK0Short); // for rotated background - lv3 = lv1 + lv2; - lv5 = lv2 + lv4; + mother = daughter1 + daughter2; // invariant mass of Kshort pair isMix = true; - fillInvMass(lv3, lv5, multiplicity, daughter1, isMix); + fillInvMass(mother, multiplicity, daughter1, daughter2, isMix); } } } @@ -914,9 +1294,15 @@ struct HigherMassResonances { int counter = 0; float multiplicityGen = 0.0; + std::vector passKs; + ROOT::Math::PxPyPzMVector lResonanceGen1; + ROOT::Math::PxPyPzEVector lResonanceGen; + void processGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { - TLorentzVector genvec; + if (config.isMC == false) { + return; + } hMChists.fill(HIST("events_check"), 0.5); if (std::abs(mcCollision.posZ()) < config.cutzvertex) { hMChists.fill(HIST("events_check"), 1.5); @@ -968,29 +1354,21 @@ struct HigherMassResonances { } hMChists.fill(HIST("events_check"), 5.5); - // if (counter < 1e3) - // std::cout << "px " << mcParticle.px() << " py " << mcParticle.py() << " pz " << mcParticle.pz() << " y " << mcParticle.y() << std::endl; - // counter++; - - hMChists.fill(HIST("GenRapidity"), mcParticle.pt(), mcParticle.y()); - hMChists.fill(HIST("GenPhi"), mcParticle.phi()); - hMChists.fill(HIST("GenEta"), mcParticle.pt(), mcParticle.eta()); - // hMChists.fill(HIST("GenPx"), mcParticle.px()); - // hMChists.fill(HIST("GenPy"), mcParticle.py()); - // hMChists.fill(HIST("GenPz"), mcParticle.pz()); - - if (std::abs(mcParticle.y()) >= 0.5) { + if (config.applyRapidityMC && std::abs(mcParticle.y()) >= config.rapidityMotherData) { continue; } hMChists.fill(HIST("events_check"), 6.5); + // if (counter < 1e3) + // std::cout << "px " << mcParticle.px() << " py " << mcParticle.py() << " pz " << mcParticle.pz() << " y " << mcParticle.y() << std::endl; + // counter++; + auto kDaughters = mcParticle.daughters_as(); - if (kDaughters.size() != 2) { + if (kDaughters.size() != config.noOfDaughters) { continue; } hMChists.fill(HIST("events_check"), 7.5); - auto passKs = false; for (const auto& kCurrentDaughter : kDaughters) { // int daupdg = std::abs(kCurrentDaughter.pdgCode()); @@ -998,33 +1376,60 @@ struct HigherMassResonances { continue; } hMChists.fill(HIST("events_check"), 8.5); - - if (std::abs(kCurrentDaughter.pdgCode()) == 310) { - passKs = true; + if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kK0Short) { + passKs.push_back(true); hMChists.fill(HIST("events_check"), 9.5); + 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 (passKs) { - genvec.SetPtEtaPhiE(mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), mcParticle.e()); - hMChists.fill(HIST("Genf1710_mass"), genvec.M()); - hMChists.fill(HIST("Genf1710"), multiplicityGen, mcParticle.pt()); + if (static_cast(passKs.size()) == config.noOfDaughters) { + lResonanceGen = ROOT::Math::PxPyPzEVector(mcParticle.pt(), mcParticle.eta(), mcParticle.phi(), mcParticle.e()); + lResonanceGen1 = daughter1 + daughter2; + + ROOT::Math::Boost boost{lResonanceGen.BoostToCM()}; + ROOT::Math::Boost boost1{lResonanceGen1.BoostToCM()}; + + fourVecDauCM = boost(daughter1); + fourVecDauCM1 = boost1(daughter1); + + auto helicityGen = lResonanceGen.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(lResonanceGen.Vect().Mag2())); + 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("Genf1710_mass"), lResonanceGen.M()); + hMChists.fill(HIST("GenRapidity"), mcParticle.y()); + hMChists.fill(HIST("GenEta"), mcParticle.eta()); + hMChists.fill(HIST("GenPhi"), mcParticle.phi()); + + if (config.applyPairRapidityGen && std::abs(lResonanceGen1.Rapidity()) >= config.rapidityMotherData) { + continue; + } + + hMChists.fill(HIST("Genf17102"), multiplicityGen, lResonanceGen1.pt(), helicityGen1); + hMChists.fill(HIST("Genf1710_mass2"), lResonanceGen1.M()); + hMChists.fill(HIST("GenRapidity2"), lResonanceGen1.Rapidity()); + hMChists.fill(HIST("GenEta2"), lResonanceGen1.Eta()); + hMChists.fill(HIST("GenPhi2"), lResonanceGen1.Phi()); } + passKs.clear(); // clear the vector for the next iteration } } PROCESS_SWITCH(HigherMassResonances, processGen, "Process Generated", false); - int counter2 = 0; 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*/) { + if (config.isMC == false) { + return; + } - TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - // lDecayDaughter1.SetXYZM(0.0,0.0,0.0,0.0); - // lDecayDaughter2.SetXYZM(0.0,0.0,0.0,0.0); - // lDecayDaughter1.SetXYZM(0.0,0.0,0.0,0.0); - auto multiplicity = collision.centFT0C(); - hMChists.fill(HIST("MC_mult"), multiplicity); + auto multiplicity = collision.centFT0M(); + hMChists.fill(HIST("Rec_Multiplicity"), multiplicity); hMChists.fill(HIST("events_checkrec"), 0.5); if (!collision.has_mcCollision()) { @@ -1037,17 +1442,21 @@ struct HigherMassResonances { } hMChists.fill(HIST("events_checkrec"), 2.5); - if (config.timFrameEvsel && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - return; - } - hMChists.fill(HIST("events_checkrec"), 3.5); - if (config.cTVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { + // if (config.timFrameEvsel && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + // return; + // } + // hMChists.fill(HIST("events_checkrec"), 3.5); + // if (config.cTVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { + // return; + // } + + if (!collision.sel8()) { return; } hMChists.fill(HIST("events_checkrec"), 4.5); hMChists.fill(HIST("MC_mult_after_event_sel"), multiplicity); eventCounter++; - auto oldindex = -999; + // auto oldindex = -999; for (const auto& v01 : V0s) { @@ -1080,7 +1489,6 @@ struct HigherMassResonances { double nTPCSigmaPos1[1]{postrack1.tpcNSigmaPi()}; double nTPCSigmaNeg1[1]{negtrack1.tpcNSigmaPi()}; - double nTPCSigmaPos2[1]{postrack2.tpcNSigmaPi()}; double nTPCSigmaNeg2[1]{negtrack2.tpcNSigmaPi()}; @@ -1105,7 +1513,7 @@ struct HigherMassResonances { int trackv0PDG1 = std::abs(mctrackv01.pdgCode()); int trackv0PDG2 = std::abs(mctrackv02.pdgCode()); - if (std::abs(trackv0PDG1) != 310 || std::abs(trackv0PDG2) != 310) { + if (std::abs(trackv0PDG1) != PDG_t::kK0Short || std::abs(trackv0PDG2) != PDG_t::kK0Short) { continue; } hMChists.fill(HIST("events_checkrec"), 12.5); @@ -1119,85 +1527,79 @@ struct HigherMassResonances { continue; } } - // if (counter2 < 1e4) - // std::cout << "Mother1 pdg code: " << motpdgs << " p_{T} " << mothertrack1.pt() << "Global index " << mothertrack1.globalIndex() << " event " << eventCounter << std::endl; - // counter2++; - - // int counter_check = 0; for (const auto& mothertrack2 : mctrackv02.mothers_as()) { hMChists.fill(HIST("events_checkrec"), 13.5); - if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { + if (mothertrack1.pdgCode() != config.pdgCodes[config.selectMCparticles]) { continue; } hMChists.fill(HIST("events_checkrec"), 14.5); - // int motpdgs2 = std::abs(mothertrack2.pdgCode()); + if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { + continue; + } + hMChists.fill(HIST("events_checkrec"), 15.5); + gindex2.push_back(mothertrack2.globalIndex()); if (gindex2.size() > 1) { if (std::find(gindex2.begin(), gindex2.end(), mothertrack2.globalIndex()) != gindex2.end()) { continue; } } - // if (counter2 < 1e4) - // std::cout << "Mother2 pdg code: " << motpdgs2 << " p_{T} " << mothertrack2.pt() << "Global index " << mothertrack1.globalIndex() << " event " << eventCounter << std::endl; - - if (mothertrack1.pdgCode() != config.pdgCodes[config.selectMCparticles]) { - continue; - } - hMChists.fill(HIST("events_checkrec"), 15.5); - - if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) { - continue; - } hMChists.fill(HIST("events_checkrec"), 16.5); - if (!mothertrack1.producedByGenerator()) { + if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) { continue; } hMChists.fill(HIST("events_checkrec"), 17.5); - if (std::abs(mothertrack1.y()) >= 0.5) { + if (!mothertrack1.producedByGenerator()) { continue; } hMChists.fill(HIST("events_checkrec"), 18.5); - if (config.avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { - hMChists.fill(HIST("h1Recsplit"), mothertrack1.pt()); + if (config.applyRapidityMC && std::abs(mothertrack1.y()) >= config.rapidityMotherData) { continue; } - oldindex = mothertrack1.globalIndex(); + hMChists.fill(HIST("events_checkrec"), 19.5); - // counter_check++; - // if (counter_check > 1) { - // std::cout << "Total mothers is " << counter_check << std::endl; + // if (config.avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { + // hMChists.fill(HIST("h1Recsplit"), mothertrack1.pt()); + // continue; // } - // std::cout << "After selection " << " p_{T} " << mothertrack2.pt() << " event " << eventCounter << std::endl; - - pvec0 = std::array{v01.px(), v01.py(), v01.pz()}; - pvec1 = std::array{v02.px(), v02.py(), v02.pz()}; - auto arrMomrec = std::array{pvec0, pvec1}; - auto motherP = mothertrack1.p(); - // auto motherE = mothertrack1.e(); - // auto genMass = std::sqrt(motherE * motherE - motherP * motherP); - auto recMass = RecoDecay::m(arrMomrec, std::array{o2::constants::physics::MassK0Short, o2::constants::physics::MassK0Short}); - // auto recpt = TMath::Sqrt((track1.px() + track2.px()) * (track1.px() + track2.px()) + (track1.py() + track2.py()) * (track1.py() + track2.py())); - //// Resonance reconstruction - lDecayDaughter1.SetXYZM(v01.px(), v01.py(), v01.pz(), o2::constants::physics::MassK0Short); - lDecayDaughter2.SetXYZM(v02.px(), v02.py(), v02.pz(), o2::constants::physics::MassK0Short); - lResonance = lDecayDaughter1 + lDecayDaughter2; - - hMChists.fill(HIST("Recf1710_p"), motherP); - hMChists.fill(HIST("Recf1710_mass"), recMass); - hMChists.fill(HIST("Recf1710_pt1"), multiplicity, mothertrack1.pt(), recMass); - // hMChists.fill(HIST("Genf1710_mass"), genMass); - hMChists.fill(HIST("Recf1710_pt2"), multiplicity, lResonance.Pt(), recMass); + // hMChists.fill(HIST("events_checkrec"), 20.5); + // oldindex = mothertrack1.globalIndex(); // split tracks is already handled using gindex1 and gindex2 + + daughter1 = ROOT::Math::PxPyPzMVector(v01.px(), v01.py(), v01.pz(), o2::constants::physics::MassK0Short); + daughter2 = ROOT::Math::PxPyPzMVector(v02.px(), v02.py(), v02.pz(), o2::constants::physics::MassK0Short); + mother = daughter1 + daughter2; + mother1 = ROOT::Math::PxPyPzEVector(mothertrack1.px(), mothertrack1.py(), mothertrack1.pz(), mothertrack1.e()); + + ROOT::Math::Boost boost{mother.BoostToCM()}; + ROOT::Math::Boost boost1{mother1.BoostToCM()}; + + fourVecDauCM = boost(daughter1); + fourVecDauCM1 = boost1(daughter1); + + auto helicityRec = mother.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(mother.Vect().Mag2())); + auto helicityRec2 = mother1.Vect().Dot(fourVecDauCM1.Vect()) / (std::sqrt(fourVecDauCM1.Vect().Mag2()) * std::sqrt(mother1.Vect().Mag2())); + + hMChists.fill(HIST("Recf1710_pt1"), multiplicity, mothertrack1.pt(), mother1.M(), helicityRec2); hMChists.fill(HIST("RecRapidity"), mothertrack1.y()); hMChists.fill(HIST("RecPhi"), mothertrack1.phi()); hMChists.fill(HIST("RecEta"), mothertrack1.eta()); + + if (config.applyPairRapidityRec && std::abs(mother.Rapidity()) >= config.rapidityMotherData) { + continue; + } + + hMChists.fill(HIST("Recf1710_pt2"), multiplicity, mother.Pt(), mother.M(), helicityRec); + hMChists.fill(HIST("RecRapidity2"), mother.Rapidity()); + hMChists.fill(HIST("RecPhi2"), mother.Phi()); + hMChists.fill(HIST("RecEta2"), mother.Eta()); } gindex2.clear(); } diff --git a/PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx b/PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx new file mode 100644 index 00000000000..35d6224da36 --- /dev/null +++ b/PWGLF/Tasks/Resonances/k1AnalysisMicro.cxx @@ -0,0 +1,741 @@ +// 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 k1AnalysisMicro.cxx +/// \brief Reconstruction of track-track decay resonance candidates +/// \author Su-Jeong Ji , Bong-Hwi Lim +/// + +#include +#include +#include // FIXME +#include // FIXME + +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Framework/AnalysisTask.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/runDataProcessing.h" +#include "PWGLF/DataModel/LFResonanceTables.h" +#include "DataFormatsParameters/GRPObject.h" +#include "CommonConstants/PhysicsConstants.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; +using namespace o2::constants::physics; +using namespace o2::constants::math; +; + +struct K1AnalysisMicro { + enum BinAnti : unsigned int { + kNormal = 0, + kAnti, + kNAEnd + }; + 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, + kTYEnd + }; + SliceCache cache; + Preslice perRCol = aod::resodaughter::resoCollisionId; + Preslice perCollision = aod::track::collisionId; + 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 + // 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 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 cMinSecondaryPtCut{"cMinSecondaryPtCut", 0.5, "Min pT cut for secondary selection"}; + /* + Configurable cfgModeK892orRho{"cfgModeK892orRho", false, "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"}; +*/ + + // K1 selection + Configurable cK1MaxRap{"cK1MaxRap", 0.5, "K1 maximum rapidity"}; + Configurable cK1MinRap{"cK1MinRap", -0.5, "K1 minimum rapidity"}; + + 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{z}} (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"}; + + // 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 mcLabelAxis = {5, -0.5, 4.5, "MC Label"}; + + // DCA QA + // Primary pion + histos.add("QA/trkppionDCAxy", "DCAxy disstribution of primary pion candidates", HistType::kTH1F, {dcaxyAxis}); + histos.add("QA/trkppionDCAz", "DCAz disstribution of primary pion candidates", HistType::kTH1F, {dcazAxis}); + 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, {dcazAxis}); + 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}); + + // 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, {dcazAxis}); + 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, {dcazAxis}); + 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, {dcazAxis}); + 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, {dcazAxis}); + 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}); + + // K1 + histos.add("QA/K1OA", "Opening angle of K1(1270)", HistType::kTH1F, {AxisSpec{100, 0, 3.14, "Opening angle"}}); + histos.add("QA/K1PairAsym", "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, {invMassAxisRho, 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/K1PairAsym", "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, {invMassAxisRho, 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}); + + // Invariant mass + histos.add("hInvmass_K1", "Invariant mass of K1(1270) (US)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); + histos.add("hInvmass_K1_LS", "Invariant mass of K1(1270) (LS)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); + histos.add("hInvmass_K1_Mix", "Invariant mass of K1(1270) (ME)", HistType::kTHnSparseD, {axisAnti, axisType, centAxis, ptAxis, invMassAxisReso}); + // Mass QA (quick check) + histos.add("k1invmass", "Invariant mass of K1(1270) (US)", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_LS", "Invariant mass of K1(1270) (LS)", HistType::kTH1F, {invMassAxisReso}); + histos.add("k1invmass_Mix", "Invariant mass of K1(1270) (ME)", 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, {dcazAxis}); + 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, {dcazAxis}); + 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, {dcazAxis}); + 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/K1PairAsym", "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, {invMassAxisRho, 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}); + } // doprocessMC + // Print output histograms statistics + LOG(info) << "Size of the histograms in K1 Analysis Task"; + histos.print(); + } // init + + // PDG code + int kPDGRho770 = 113; + int kK1Plus = 10323; + + template + bool trackCut(const TrackType track) + { + if constexpr (!IsResoMicrotrack) { + // basic track cuts + if (std::abs(track.pt()) < cMinPtcut) + return false; + if (std::abs(track.dcaXY()) > cMaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cMaxDCAzToPVcut) + return false; + if (track.tpcNClsFound() < cfgTPCcluster) + 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 (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgGlobalTrack && !track.isGlobalTrack()) + return false; + } else { + if (std::abs(track.pt()) < cMinPtcut) + return false; + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) + return false; + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) + return false; + if (cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (cfgPVContributor && !track.isPVContributor()) + return false; + } + return true; + } + + // Pion PID selection tools + template + bool selectionPIDpion(const T& candidate) + { + if constexpr (!IsResoMicrotrack) { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + 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; + } + } else { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + tpcPIDPassed = std::abs(o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag())) < cMaxTPCnSigmaPion + Epsilon; + tofPIDPassed = candidate.hasTOF() ? std::abs(o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag())) < cMaxTOFnSigmaPion + Epsilon : true; + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } + return false; + } + + // Kaon PID selection tools + template + bool selectionPIDkaon(const T& candidate) + { + if constexpr (!IsResoMicrotrack) { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + if (std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaon) { + tpcPIDPassed = true; + } else { + return false; + } + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cMaxTOFnSigmaKaon) { + tofPIDPassed = true; + } + if ((nsigmaCutCombinedKaon > 0) && (candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa() < nsigmaCutCombinedKaon * nsigmaCutCombinedKaon)) { + tofPIDPassed = true; + } + } else { + if (!cTOFVeto) { + return false; + } + tofPIDPassed = true; + } + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } else { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + tpcPIDPassed = std::abs(o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaKaFlag())) < cMaxTPCnSigmaKaon + Epsilon; + tofPIDPassed = candidate.hasTOF() ? std::abs(o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaKaFlag())) < cMaxTOFnSigmaKaon + Epsilon : true; + if (tpcPIDPassed && tofPIDPassed) { + return true; + } + } + return false; + } + + template + bool isTrueK1(const T& trk1, const T& trk2, const T2& bTrack) + { + if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kPiPlus) + return false; + if (std::abs(bTrack.pdgCode()) != kKPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (((std::abs(trk1.motherPDG()) && std::abs(trk2.motherPDG()) != kPDGRho770) && (std::abs(bTrack.motherPDG()) != kK1Plus)) || (std::abs(trk1.motherPDG()) && std::abs(bTrack.motherPDG()) != kK0Star892 && (std::abs(trk2.motherPDG()) != kK1Plus)) || (std::abs(trk2.motherPDG()) && std::abs(bTrack.motherPDG()) != kK0Star892 && (std::abs(trk1.motherPDG()) != kK1Plus))) + return false; + auto siblings = bTrack.siblingIds(); + if (siblings[0] != mother1 && siblings[1] != mother2) + return false; + return true; + } // isTrueK1 + + template + bool isTrueK892(const T& trk1, const T& trk2) + { + if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kKPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (std::abs(trk1.motherPDG()) != kK0Star892) + return false; + return true; + } + + template + bool isTrueRho(const T& trk1, const T& trk2) + { + if (std::abs(trk1.pdgCode()) != kPiPlus || std::abs(trk2.pdgCode()) != kPiPlus) + return false; + auto mother1 = trk1.motherId(); + auto mother2 = trk2.motherId(); + if (mother1 != mother2) + return false; + if (std::abs(trk1.motherPDG()) != kPDGRho770) + return false; + return true; + } + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + { + auto multiplicity = collision.cent(); + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonanceSecondary, lDecayDaughter_bach, lResonanceK1; + for (const 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 too. But the same id pairs are not needed. + // trk1: pion, trk2: pion, bTrack: kaon + if (!trackCut(trk1) || !trackCut(trk2)) + continue; + + auto trk1pt = trk1.pt(); + auto trk2pt = trk2.pt(); + auto isTrk1hasTOF = trk1.hasTOF(); + auto isTrk2hasTOF = trk2.hasTOF(); + + if constexpr (!IsResoMicrotrack) { + auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; + auto trk2NSigmaPiTPC = trk2.tpcNSigmaPi(); + auto trk2NSigmaPiTOF = (isTrk2hasTOF) ? trk2.tofNSigmaPi() : -999.; + + if (cUseOnlyTOFTrackPi && !isTrk1hasTOF) + continue; + if (!selectionPIDpion(trk1) || !selectionPIDpion(trk2)) + continue; + + if constexpr (!IsMix) { + + histos.fill(HIST("QA/trkppionTPCPID"), trk1pt, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/trkppionTOFPID"), trk1pt, trk1NSigmaPiTOF); + histos.fill(HIST("QA/trkppionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); + } + histos.fill(HIST("QA/trkppionpT"), trk1pt); + histos.fill(HIST("QA/trkppionDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QA/trkppionDCAz"), trk1.dcaZ()); + + histos.fill(HIST("QA/trkspionTPCPID"), trk2pt, trk2NSigmaPiTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/trkspionTOFPID"), trk2pt, trk2NSigmaPiTOF); + histos.fill(HIST("QA/trkspionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } + histos.fill(HIST("QA/trkspionpT"), trk2pt); + histos.fill(HIST("QA/trkspionDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QA/trkspionDCAz"), trk2.dcaZ()); + } + } else { + histos.fill(HIST("QA/trkppionTPCPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag())); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/trkppionTOFPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag())); + histos.fill(HIST("QA/trkppionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag())); + } + histos.fill(HIST("QA/trkppionpT"), trk1pt); + histos.fill(HIST("QA/trkppionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags())); + histos.fill(HIST("QA/trkppionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags())); + + histos.fill(HIST("QA/trkspionTPCPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaPiFlag())); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/trkspionTOFPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaPiFlag())); + histos.fill(HIST("QA/trkspionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaPiFlag()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaPiFlag())); + } + histos.fill(HIST("QA/trkspionpT"), trk2pt); + histos.fill(HIST("QA/trkspionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk2.trackSelectionFlags())); + histos.fill(HIST("QA/trkspionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk2.trackSelectionFlags())); + } + + // Resonance reconstruction + lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), MassPionCharged); + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), MassPionCharged); + lResonanceSecondary = lDecayDaughter1 + lDecayDaughter2; + + if (lResonanceSecondary.Pt() < cMinSecondaryPtCut) + continue; + + if constexpr (!IsMix) { + histos.fill(HIST("QA/hInvmassSecon"), lResonanceSecondary.M()); + } + if constexpr (IsMC) { + /* + 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()); + } + */ + histos.fill(HIST("QAMC/hpT_Secondary"), lResonanceSecondary.Pt()); + } + // Mass Window cut is removed + + for (const auto& bTrack : dTracks1) { + if (bTrack.index() == trk1.index() || bTrack.index() == trk2.index()) + continue; + if (!trackCut(bTrack)) + continue; + if (!selectionPIDkaon(bTrack)) + continue; + + // K1 reconstruction + lDecayDaughter_bach.SetXYZM(bTrack.px(), bTrack.py(), bTrack.pz(), MassKaonCharged); + lResonanceK1 = lResonanceSecondary + lDecayDaughter_bach; + + // Cuts + if (lResonanceK1.Rapidity() > cK1MaxRap || lResonanceK1.Rapidity() < cK1MinRap) + continue; + + auto lK1Angle = lResonanceSecondary.Angle(lDecayDaughter_bach.Vect()); + auto lPairAsym = (lResonanceSecondary.E() - lDecayDaughter_bach.E()) / (lResonanceSecondary.E() + lDecayDaughter_bach.E()); + + TLorentzVector temp13 = lDecayDaughter1 + lDecayDaughter_bach; + TLorentzVector temp23 = lDecayDaughter2 + lDecayDaughter_bach; + + // QA histogram + if constexpr (!IsMix) { + histos.fill(HIST("QA/K1OA"), lK1Angle); + histos.fill(HIST("QA/K1PairAsym"), lPairAsym); + histos.fill(HIST("QA/hInvmassK892_Rho"), temp13.M(), lResonanceSecondary.M()); + histos.fill(HIST("QA/hInvmassSecon_PiKa"), lResonanceSecondary.M(), temp23.M()); + histos.fill(HIST("QA/hpT_Secondary"), lResonanceSecondary.Pt()); + } + // Selection cuts are removed + // QA histograms after the cuts are removed as no cuts are applied + + if constexpr (!IsMix) { + unsigned int typeK1 = bTrack.sign() > 0 ? BinType::kK1P : BinType::kK1N; + unsigned int typeNormal = BinAnti::kNormal; + if (trk1.sign() * trk2.sign() < 0) { + histos.fill(HIST("k1invmass"), lResonanceK1.M()); + histos.fill(HIST("hInvmass_K1"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + } else { + histos.fill(HIST("k1invmass_LS"), lResonanceK1.M()); + histos.fill(HIST("hInvmass_K1_LS"), 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/K1PairAsym"), lPairAsym); + 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_Seocondary"), lResonanceSecondary.Pt()); + + if constexpr (!IsResoMicrotrack) { + + auto trk1NSigmaPiTPC = trk1.tpcNSigmaPi(); + auto trk1NSigmaPiTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPi() : -999.; + auto trk2NSigmaPiTPC = trk2.tpcNSigmaPi(); + auto trk2NSigmaPiTOF = (isTrk2hasTOF) ? trk2.tofNSigmaPi() : -999.; + + // PID QA primary pion + histos.fill(HIST("QAMC/trkppionTPCPID"), trk1pt, trk1NSigmaPiTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMC/trkppionTOFPID"), trk1pt, trk1NSigmaPiTOF); + histos.fill(HIST("QAMC/trkppionTPCTOFPID"), trk1NSigmaPiTPC, trk1NSigmaPiTOF); + } + histos.fill(HIST("QAMC/trkppionpT"), trk1pt); + histos.fill(HIST("QAMC/trkppionDCAxy"), trk1.dcaXY()); + histos.fill(HIST("QAMC/trkppionDCAz"), trk1.dcaZ()); + + // PID QA secondary pion + histos.fill(HIST("QAMC/trkspionTPCPID"), trk2pt, trk2NSigmaPiTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QAMC/trkspionTOFPID"), trk2pt, trk2NSigmaPiTOF); + histos.fill(HIST("QAMC/trkspionTPCTOFPID"), trk2NSigmaPiTPC, trk2NSigmaPiTOF); + } + histos.fill(HIST("QAMC/trkspionpT"), trk2pt); + histos.fill(HIST("QAMC/trkspionDCAxy"), trk2.dcaXY()); + histos.fill(HIST("QAMC/trkspionDCAz"), trk2.dcaZ()); + + } else { + + histos.fill(HIST("QAMC/trkppionTPCPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaSelectionFlags())); + if (isTrk1hasTOF) { + histos.fill(HIST("QAMC/trkppionTOFPID"), trk1pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaSelectionFlags())); + histos.fill(HIST("QAMC/trkppionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaSelectionFlags()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaSelectionFlags())); + } + histos.fill(HIST("QAMC/trkppionpT"), trk1pt); + histos.fill(HIST("QAMC/trkppionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags())); + histos.fill(HIST("QAMC/trkppionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags())); + + // PID QA secondary pion + histos.fill(HIST("QAMC/trkspionTPCPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaSelectionFlags())); + if (isTrk2hasTOF) { + histos.fill(HIST("QAMC/trkspionTOFPID"), trk2pt, o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaSelectionFlags())); + histos.fill(HIST("QAMC/trkspionTPCTOFPID"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk2.pidNSigmaSelectionFlags()), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk2.pidNSigmaSelectionFlags())); + } + histos.fill(HIST("QAMC/trkspionpT"), trk2pt); + histos.fill(HIST("QAMC/trkspionDCAxy"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk2.trackSelectionFlags())); + histos.fill(HIST("QAMC/trkspionDCAz"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk2.trackSelectionFlags())); + } + } else { + histos.fill(HIST("k1invmass_MC_noK1"), lResonanceK1.M()); + } + } // IsMC + } else { + unsigned int typeK1 = bTrack.sign() > 0 ? BinType::kK1P_Mix : BinType::kK1N_Mix; + unsigned int typeNormal = BinAnti::kNormal; + histos.fill(HIST("hInvmass_K1_Mix"), typeNormal, typeK1, multiplicity, lResonanceK1.Pt(), lResonanceK1.M()); + histos.fill(HIST("k1invmass_Mix"), lResonanceK1.M()); + } + } // bTrack + } + } // fillHistograms + + void processResoTracks(aod::ResoCollision const& collision, + aod::ResoTracks const& resotracks) + { + fillHistograms(collision, resotracks, resotracks); + } + PROCESS_SWITCH(K1AnalysisMicro, processResoTracks, "Process ResoTracks", false); + + void processResoMicroTracks(aod::ResoCollision const& collision, + aod::ResoMicroTracks const& resomicrotracks) + { + fillHistograms(collision, resomicrotracks, resomicrotracks); + } + PROCESS_SWITCH(K1AnalysisMicro, processResoMicroTracks, "Process ResoMicroTracks", true); + + void processMC(aod::ResoCollision const& collision, + soa::Join const& resotracks) + { + fillHistograms(collision, resotracks, resotracks); + } + PROCESS_SWITCH(K1AnalysisMicro, processMC, "Process Event for MC", false); + + void processMCTrue(ResoMCCols::iterator const& collision, aod::ResoMCParents const& resoParents) + { + auto multiplicity = collision.cent(); + for (const auto& part : resoParents) { + if (std::abs(part.pdgCode()) != kK1Plus) + continue; + if (std::abs(part.y()) > 0.5) { + continue; + } + bool pass1 = false; + bool pass2 = false; + bool pass3 = false; + bool pass4 = false; + if (std::abs(part.daughterPDG1()) == 313 || std::abs(part.daughterPDG2()) == 313) { // At least one decay into K892 + pass2 = true; + } + if (std::abs(part.daughterPDG1()) == kPiPlus || std::abs(part.daughterPDG2()) == kPiPlus) { // At lest one decay into pion + pass1 = true; + } + if (std::abs(part.daughterPDG1()) == kPDGRho770 || std::abs(part.daughterPDG2()) == kPDGRho770) { + pass4 = true; + } + if (std::abs(part.daughterPDG1()) == kKPlus || std::abs(part.daughterPDG2()) == kKPlus) { + pass3 = true; + } + if (!pass1 || !pass2 || !pass3 || !pass4) // If we have both decay products + continue; + auto typeNormal = part.pdgCode() > 0 ? BinAnti::kNormal : BinAnti::kAnti; + if (collision.isVtxIn10()) // INEL>10 + { + 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); + } + } + } + PROCESS_SWITCH(K1AnalysisMicro, processMCTrue, "Process Event for MC", false); + + // Processing Event Mixing + using BinningTypeVtxZT0M = ColumnBinningPolicy; + void processME(o2::aod::ResoCollisions const& 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 + + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + fillHistograms(collision1, tracks1, tracks2); + } + }; + PROCESS_SWITCH(K1AnalysisMicro, processME, "Process EventMixing light without partition", false); + + // Processing Event Mixing -- Micro + // using BinningTypeVtxZT0M = ColumnBinningPolicy; + void processMEMicro(o2::aod::ResoCollisions const& collisions, aod::ResoMicroTracks const& resomicrotracks) + { + auto tracksTuple = std::make_tuple(resomicrotracks); + BinningTypeVtxZT0M colBinning{{cfgVtxBins, cfgMultBins}, true}; + SameKindPair pairs{colBinning, nEvtMixing, -1, collisions, tracksTuple, &cache}; // -1 is the number of the bin to skip + + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + fillHistograms(collision1, tracks1, tracks2); + } + }; + PROCESS_SWITCH(K1AnalysisMicro, processMEMicro, "Process EventMixing light without partition", true); +}; // struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx b/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx index 81af59575ab..7db6d327c15 100644 --- a/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx +++ b/PWGLF/Tasks/Resonances/kaonkaonanalysis.cxx @@ -12,77 +12,86 @@ // (1) For Run3 // (2) Event and track selection need to be optimized // (3) particle = 0 --> phi -// (4) particle = 1 --> kstar +// (4) particle = 1 --> Phi // (5) particle = 2 --> lambdastar // (6) 4 process function (a) Data same event (b) Data mixed event (c) MC generated (d) MC reconstructed /// \brief kaon kaon analysis for higher mass resonances (code taken from phianalysisrun3) /// \author Sawan (sawan.sawan@cern.ch) -#include +#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/TrackSelectionTables.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.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 #include +#include +#include +#include #include -#include #include #include -#include -#include -#include #include -#include -#include + #include +#include #include -#include "TF1.h" -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using std::array; +using namespace o2::aod::rctsel; + struct kaonkaonAnalysisRun3 { + struct : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "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"}; + } rctCut; + RCTFlagsChecker rctChecker; + SliceCache cache; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + HistogramRegistry hInvMass{"hInvMass", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // For histograms + Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; + Configurable calcRotational{"calcRotational", false, "Calculate Rotational"}; // events Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; - Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; - Configurable goodzvertex{"goodzvertex", false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference."}; - Configurable itstpctracks{"itstpctracks", false, "selects collisions with at least one ITS-TPC track,"}; + // Configurable piluprejection{"piluprejection", false, "Pileup rejection"}; + // Configurable goodzvertex{"goodzvertex", false, "removes collisions with large differences between z of PV by tracks and z of PV from FT0 A-C time difference."}; + // Configurable itstpctracks{"itstpctracks", false, "selects collisions with at least one ITS-TPC track,"}; Configurable timFrameEvsel{"timFrameEvsel", true, "TPC Time frame boundary cut"}; - Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; Configurable otherQAplots{"otherQAplots", true, "Other QA plots"}; Configurable QAPID{"QAPID", true, "QA PID plots"}; Configurable QAevents{"QAevents", true, "QA events"}; Configurable cfgMultFT0M{"cfgMultFT0M", true, "true for pp (FT0M estimator) and false for PbPb (FT0C estimator)"}; - // Event selection cuts - Alex (Temporary, need to fix!) - TF1* fMultPVCutLow = nullptr; - TF1* fMultPVCutHigh = nullptr; - TF1* fMultCutLow = nullptr; - TF1* fMultCutHigh = nullptr; - TF1* fMultMultPVCut = nullptr; - // track - Configurable rotational_cut{"rotational_cut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; Configurable cfgCutPT{"cfgCutPT", 0.2, "PT cut on daughter track"}; Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; @@ -94,24 +103,16 @@ struct kaonkaonAnalysisRun3 { Configurable iscustomDCAcut{"iscustomDCAcut", false, "iscustomDCAcut"}; Configurable isNoTOF{"isNoTOF", false, "isNoTOF"}; Configurable ismanualDCAcut{"ismanualDCAcut", true, "ismanualDCAcut"}; - Configurable isITSOnlycut{"isITSOnlycut", true, "isITSOnlycut"}; + Configurable isITSOnlycut{"isITSOnlycut", false, "isITSOnlycut"}; Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; Configurable isDeepAngle{"isDeepAngle", false, "Deep Angle cut"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; - Configurable cmultLow{"cmultLow", 0.0f, "Low centrality percentile"}; - Configurable cmultHigh{"cmultHigh", 150.0f, "High centrality percentile"}; - Configurable cmultBins{"cmultBins", 150, "Number of centrality bins"}; - Configurable cpTlow{"cpTlow", 0.0f, "Low pT"}; - Configurable cpThigh{"cpThigh", 10.0f, "High pT"}; - Configurable cpTbins{"cpTbins", 100, "Number of pT bins"}; - Configurable cMasslow{"cMasslow", 0.9f, "Low mass"}; - Configurable cMasshigh{"cMasshigh", 2.5f, "High mass"}; - Configurable cMassbins{"cMassbins", 320, "Number of mass bins"}; - Configurable c_nof_rotations{"c_nof_rotations", 3, "Number of random rotations in the rotational background"}; - ConfigurableAxis axisdEdx{"axisdEdx", {20000, 0.0f, 200.0f}, "dE/dx (a.u.)"}; - ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {2000, 0, 20}, "pT (GeV/c)"}; - ConfigurableAxis axisMultdist{"axisMultdist", {3500, 0, 70000}, "Multiplicity distribution"}; + + Configurable cRotations{"cRotations", 3, "Number of random rotations in the rotational background"}; + ConfigurableAxis axisdEdx{"axisdEdx", {1, 0.0f, 200.0f}, "dE/dx (a.u.)"}; + ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {1, 0, 20}, "pT (GeV/c)"}; + ConfigurableAxis axisMultdist{"axisMultdist", {1, 0, 70000}, "Multiplicity distribution"}; // different frames Configurable activateTHnSparseCosThStarHelicity{"activateTHnSparseCosThStarHelicity", true, "Activate the THnSparse with cosThStar w.r.t. helicity axis"}; @@ -119,6 +120,9 @@ struct kaonkaonAnalysisRun3 { Configurable activateTHnSparseCosThStarBeam{"activateTHnSparseCosThStarBeam", false, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; Configurable activateTHnSparseCosThStarRandom{"activateTHnSparseCosThStarRandom", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + ConfigurableAxis invMassKKAxis{"invMassKKAxis", {200, 1.0f, 3.0f}, "KK pair invariant mass axis"}; + ConfigurableAxis ptAxisKK{"ptAxisKK", {200, 0.0f, 20.0f}, "KK pair pT axis"}; + ConfigurableAxis multAxis{"multAxis", {110, 0.0f, 110.0f}, "THnSparse multiplicity axis"}; // MC Configurable isMC{"isMC", false, "Run MC"}; @@ -127,9 +131,10 @@ struct kaonkaonAnalysisRun3 { void init(o2::framework::InitContext&) { - AxisSpec axisMult{cmultBins, cmultLow, cmultHigh, "Multiplicity"}; - AxisSpec axisPt{cpTbins, cpTlow, cpThigh, "pT (GeV/c)"}; - AxisSpec axisMass{cMassbins, cMasslow, cMasshigh, "Invariant mass (GeV/c^2)"}; + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); + AxisSpec axisMult{multAxis, "Multiplicity"}; + AxisSpec axisPt{ptAxisKK, "pT (GeV/c)"}; + AxisSpec axisMass{invMassKKAxis, "Invariant mass (GeV/c^2)"}; const AxisSpec thnAxisPOL{configThnAxisPOL, "Frame axis"}; // THnSparses @@ -189,46 +194,30 @@ struct kaonkaonAnalysisRun3 { histos.add("Chi2perclusterTOF", "Chi2 / cluster for the TOF track segment", kTH1F, {{50, 0.0f, 50.0f}}); } if (!isMC) { - histos.add("h3PhiInvMassUnlikeSign", "KK Unlike Sign", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); - histos.add("h3PhiInvMassLikeSignPP", "KK Like Sign +", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); - histos.add("h3PhiInvMassLikeSignMM", "KK Like Sign -", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); - histos.add("h3PhiInvMassMixed", "KK Mixed", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); - histos.add("h3PhiInvMassRotation", "KK Rotation", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + hInvMass.add("h3PhiInvMassUnlikeSign", "KK Unlike Sign", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + hInvMass.add("h3PhiInvMassLikeSignPP", "KK Like Sign +", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + hInvMass.add("h3PhiInvMassLikeSignMM", "KK Like Sign -", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + hInvMass.add("h3PhiInvMassMixed", "KK Mixed", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); + hInvMass.add("h3PhiInvMassRotated", "KK Rotation", kTHnSparseF, {axisMult, axisPt, axisMass, thnAxisPOL}, true); } else if (isMC) { + hInvMass.add("h1PhiGen", "Phi meson Gen", kTH1F, {axisMult, axisPt}); + hInvMass.add("h3PhiRec", "Phi meson Rec", kTHnSparseF, {axisMult, axisPt, axisMass}); histos.add("hMC", "MC Event statistics", kTH1F, {{6, 0.0f, 6.0f}}); - histos.add("h1PhiGen", "Phi meson Gen", kTH1F, {axisPt}); histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {axisPt}); - histos.add("h3PhiRec", "Phi meson Rec", kTHnSparseF, {axisPt, axisPt, {200, -0.1, 0.1}}, true); - } - if (additionalEvsel) { - fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); - fMultPVCutLow->SetParameters(2834.66, -87.0127, 0.915126, -0.00330136, 332.513, -12.3476, 0.251663, -0.00272819, 1.12242e-05); - fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); - fMultPVCutHigh->SetParameters(2834.66, -87.0127, 0.915126, -0.00330136, 332.513, -12.3476, 0.251663, -0.00272819, 1.12242e-05); - fMultCutLow = new TF1("fMultCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.5*([4]+[5]*x)", 0, 100); - fMultCutLow->SetParameters(1893.94, -53.86, 0.502913, -0.0015122, 109.625, -1.19253); - fMultCutHigh = new TF1("fMultCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 3.*([4]+[5]*x)", 0, 100); - fMultCutHigh->SetParameters(1893.94, -53.86, 0.502913, -0.0015122, 109.625, -1.19253); - fMultMultPVCut = new TF1("fMultMultPVCut", "[0]+[1]*x+[2]*x*x", 0, 5000); - fMultMultPVCut->SetParameters(-0.1, 0.785, -4.7e-05); + histos.add("Recmutiplicity", "Reconstructed multiplicity distribution", kTH1F, {axisMult}); + histos.add("Genmutiplicity", "Generated multiplicity distribution", kTH1F, {axisMult}); } } double massKa = o2::constants::physics::MassKPlus; - double rapidity; - double genMass, recMass, resolution; - double mass{0.}; - double massrotation1{0.}; - double massrotation2{0.}; - double pT{0.}; - array pvec0; - array pvec1; - array pvec1rotation; - array pvec2rotation; - ROOT::Math::PxPyPzMVector daughter1, daughter2; + double rapidity{0.0}, mass{0.}, massrotation1{0.}, massrotation2{0.}, pT{0.}; + float theta2; + ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterRot, mother, motherRot, daughterSelected, fourVecDauCM, daughterRotCM; + ROOT::Math::XYZVector randomVec, beamVec, normalVec; + bool isMix = false; template - bool eventselection(Collision const& collision, const float& multiplicity) + bool eventselection(Collision const& collision) { if (!collision.sel8()) { return false; @@ -236,32 +225,15 @@ struct kaonkaonAnalysisRun3 { if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { return false; } - if (piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { - return false; - } - if (goodzvertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { - return false; - } - if (itstpctracks && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { - return false; - } - // if (collision.alias_bit(kTVXinTRD)) { - // // TRD triggered - // // return 0; + // if (piluprejection && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + // return false; + // } + // if (goodzvertex && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + // return false; + // } + // if (itstpctracks && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + // return false; // } - auto multNTracksPV = collision.multNTracksPV(); - if (additionalEvsel && multNTracksPV < fMultPVCutLow->Eval(multiplicity)) { - return false; - } - if (additionalEvsel && multNTracksPV > fMultPVCutHigh->Eval(multiplicity)) { - return false; - } - // if (multTrk < fMultCutLow->Eval(multiplicity)) - // return 0; - // if (multTrk > fMultCutHigh->Eval(multiplicity)) - // return 0; - // if (multTrk > fMultMultPVCut->Eval(multNTracksPV)) - // return 0; return true; } @@ -310,73 +282,141 @@ struct kaonkaonAnalysisRun3 { } return true; } - template - void FillinvMass(const T1& candidate1, const T2& candidate2, const T3& framecalculation, float multiplicity, bool unlike, bool mix, bool likesign, bool rotation, float massd1, float massd2) + + template + void fillInvMass(const T1& daughter1, const T1& daughter2, const T1& mother, float multiplicity, bool isMix, const T2& track1, const T2& track2) { - int track1Sign = candidate1.sign(); - int track2Sign = candidate2.sign(); - TLorentzVector vec1, vec2, vec3, vec4, vec5; - vec1.SetPtEtaPhiM(candidate1.pt(), candidate1.eta(), candidate1.phi(), massd1); - vec2.SetPtEtaPhiM(candidate2.pt(), candidate2.eta(), candidate2.phi(), massd2); - vec3 = vec1 + vec2; - // daughter1 = ROOT::Math::PxPyPzMVector(candidate1.px(), candidate1.py(), candidate1.pz(), massd1); // Kplus - // daughter2 = ROOT::Math::PxPyPzMVector(candidate2.px(), candidate2.py(), candidate2.pz(), massd2); // Kminus - double rapidity = vec3.Rapidity(); + ROOT::Math::Boost boost{mother.BoostToCM()}; + fourVecDauCM = boost(daughter1); - if (otherQAplots) { - histos.fill(HIST("Chi2perclusterITS"), candidate1.itsChi2NCl()); - histos.fill(HIST("Chi2perclusterITS"), candidate2.itsChi2NCl()); - histos.fill(HIST("Chi2perclusterTPC"), candidate1.tpcChi2NCl()); - histos.fill(HIST("Chi2perclusterTPC"), candidate2.tpcChi2NCl()); - histos.fill(HIST("Chi2perclusterTRD"), candidate1.trdChi2()); - histos.fill(HIST("Chi2perclusterTRD"), candidate2.trdChi2()); - histos.fill(HIST("Chi2perclusterTOF"), candidate1.tofChi2()); - histos.fill(HIST("Chi2perclusterTOF"), candidate2.tofChi2()); - } - if (QAPID) { - histos.fill(HIST("dE_by_dx_TPC"), candidate1.p(), candidate1.tpcSignal()); - histos.fill(HIST("dE_by_dx_TPC"), candidate2.p(), candidate2.tpcSignal()); - } + if (std::abs(mother.Rapidity()) < 0.5) { + if (activateTHnSparseCosThStarHelicity) { + auto cosThetaStarHelicity = mother.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(mother.Vect().Mag2())); - // polarization calculations - // auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); - // auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); - // ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massd1); // Kaon - - // ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(vec3.Px(), vec3.Py(), vec3.Pz(), vec3.M()); // mass of KaonKaon pair - // ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - // ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother - // ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - - // default filling - // if (activateTHnSparseCosThStarHelicity) { - // ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - // auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); - if (std::abs(rapidity) < 0.5 && track1Sign * track2Sign < 0) { - if (unlike) { - histos.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); - } - if (mix) { - histos.fill(HIST("h3PhiInvMassMixed"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); - } + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + hInvMass.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); + + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / rotationalCut, o2::constants::math::PI + o2::constants::math::PI / rotationalCut); - if (rotation) { - for (int i = 0; i < c_nof_rotations; i++) { - float theta2 = rn->Uniform(TMath::Pi() - TMath::Pi() / rotational_cut, TMath::Pi() + TMath::Pi() / rotational_cut); - vec4.SetPtEtaPhiM(candidate1.pt(), candidate1.eta(), candidate1.phi() + theta2, massd1); // for rotated background - vec5 = vec4 + vec2; - histos.fill(HIST("h3PhiInvMassRotation"), multiplicity, vec5.Pt(), vec5.M(), framecalculation); + 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; + + ROOT::Math::Boost boost2{motherRot.BoostToCM()}; + daughterRotCM = boost2(daughterRot); + + auto cosThetaStarHelicityRot = motherRot.Vect().Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(motherRot.Vect().Mag2())); + + if (calcRotational) + hInvMass.fill(HIST("h3PhiInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarHelicityRot); + } + } else { + hInvMass.fill(HIST("h3PhiInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); + } + } else { + if (!isMix) { + if (calcLikeSign) { + if (track1.sign() * track2.sign() > 0) { + hInvMass.fill(HIST("h3PhiInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); + } else { + hInvMass.fill(HIST("h3PhiInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); + } + } + } + } + + } else if (activateTHnSparseCosThStarProduction) { + normalVec = ROOT::Math::XYZVector(mother.Py(), -mother.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(normalVec.Mag2())); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + hInvMass.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(0, o2::constants::math::PI); + 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; + if (calcRotational) + hInvMass.fill(HIST("h3PhiInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarProduction); + } + } else { + hInvMass.fill(HIST("h3PhiInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); + } + } else { + if (!isMix) { + if (calcLikeSign) { + if (track1.sign() * track2.sign() > 0) { + hInvMass.fill(HIST("h3PhiInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); + } else { + hInvMass.fill(HIST("h3PhiInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); + } + } + } + } + } else if (activateTHnSparseCosThStarBeam) { + beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + hInvMass.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(0, o2::constants::math::PI); + 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; + if (calcRotational) + hInvMass.fill(HIST("h3PhiInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarBeam); + } + } else { + hInvMass.fill(HIST("h3PhiInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); + } + } else { + if (calcLikeSign) { + if (track1.sign() * track2.sign() > 0) { + hInvMass.fill(HIST("h3PhiInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); + } else { + hInvMass.fill(HIST("h3PhiInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); + } + } + } + } else if (activateTHnSparseCosThStarRandom) { + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + + randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + hInvMass.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(0, o2::constants::math::PI); + 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; + if (calcRotational) + hInvMass.fill(HIST("h3PhiInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarRandom); + } + } else { + hInvMass.fill(HIST("h3PhiInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + } + } else { + if (!isMix) { + if (calcLikeSign) { + if (track1.sign() * track2.sign() > 0) { + hInvMass.fill(HIST("h3PhiInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + } else { + hInvMass.fill(HIST("h3PhiInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + } + } + } } } } - if (std::abs(rapidity) < 0.5 && track1Sign * track2Sign > 0 && likesign) { - if (track1Sign > 0 && track2Sign > 0) { - histos.fill(HIST("h3PhiInvMassLikeSignPP"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); - } else { - histos.fill(HIST("h3PhiInvMassLikeSignMM"), multiplicity, vec3.Pt(), vec3.M(), framecalculation); - } - } - // } } Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; @@ -387,12 +427,15 @@ struct kaonkaonAnalysisRun3 { using TrackCandidates = soa::Filtered>; // using EventCandidatesMC = soa::Join; - using EventCandidatesMC = soa::Join; + using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { - if (!eventselection(collision, collision.centFT0M())) { + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { + return; + } + if (!eventselection(collision)) { return; } float multiplicity; @@ -433,74 +476,16 @@ struct kaonkaonAnalysisRun3 { continue; } - // calculation of event planes - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); // Kplus - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); // Kminus - - ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massKa); // Kaon - TLorentzVector lv1, lv2, lv3; - lv1.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi(), massKa); - lv2.SetPtEtaPhiM(track2.pt(), track2.eta(), track2.phi(), massKa); - lv3 = lv1 + lv2; - - ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KaonKaon pair - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother - ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - - bool unlike = true; - bool mix = false; - bool likesign = true; - bool rotation = true; - if (activateTHnSparseCosThStarHelicity) { - ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); - - if (isITSOnlycut) { - FillinvMass(track1, track2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { - FillinvMass(track1, track2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarProduction) { - ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); - auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); - - if (isITSOnlycut) { - FillinvMass(track1, track2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { - FillinvMass(track1, track2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarBeam) { - ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - - if (isITSOnlycut) { - FillinvMass(track1, track2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { - FillinvMass(track1, track2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarRandom) { - auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); - auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); - ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - - if (isITSOnlycut) { - FillinvMass(track1, track2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { - FillinvMass(track1, track2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } + if (!selectionPID(track1)) // Track 1 is checked with Kaon + continue; + if (!selectionPID(track2)) // Track 2 is checked with Pion + continue; - // if (!isITSOnlycut && selectionPID(track1) && selectionPID(track2)) { - // // histos.fill(HIST("hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); - // // histos.fill(HIST("hNsigmaKaonTOF_after"), track1.pt(), track1.tofNSigmaKa()); - // // histos.fill(HIST("hNsigmaKaonTOF_TPC_after"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); - // } + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + mother = daughter1 + daughter2; // Kstar meson + isMix = false; + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, track1, track2); } } } @@ -516,204 +501,53 @@ struct kaonkaonAnalysisRun3 { { auto tracksTuple = std::make_tuple(tracks); //////// currently mixing the event with similar TPC multiplicity //////// - BinningTypeVertexContributor1 binningOnPositions1{{axisVertex, axisMultiplicity}, true}; - BinningTypeVertexContributor2 binningOnPositions2{{axisVertex, axisMultiplicity}, true}; + BinningTypeVertexContributor1 binningOnPositions1{{axisVertex, axisMultiplicity}, true}; // for pp + BinningTypeVertexContributor2 binningOnPositions2{{axisVertex, axisMultiplicity}, true}; // for PbPb SameKindPair pair1{binningOnPositions1, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; SameKindPair pair2{binningOnPositions2, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; - if (cfgMultFT0M == true) { - for (auto& [c1, tracks1, c2, tracks2] : pair1) { - float multiplicity = c1.centFT0M(); - if (!eventselection(c1, multiplicity)) { - continue; - } - if (!eventselection(c2, multiplicity)) { - continue; - } - - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - bool unlike = false; - bool mix = true; - bool likesign = false; - bool rotation = false; - if (!selectionTrack(t1)) { - continue; - } - if (!selectionTrack(t2)) { - continue; - } - if (!selectionPair(t1, t2)) { - continue; - } + for (auto& [c1, tracks1, c2, tracks2] : pair1) { + float multiplicity = c1.centFT0M(); - // calculation of event planes - daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); // Kplus - daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); // Kminus - - ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massKa); // Kaon - TLorentzVector lv1, lv2, lv3; - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massKa); - lv3 = lv1 + lv2; - - ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KaonKaon pair - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother - ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - - if (activateTHnSparseCosThStarHelicity) { - ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); - - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarProduction) { - ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); - auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + if (rctCut.requireRCTFlagChecker && !rctChecker(c1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(c2)) { + continue; + } - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarBeam) { - ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + if (!eventselection(c1)) { + continue; + } + if (!eventselection(c2)) { + continue; + } - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarRandom) { - auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); - auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); - ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } + for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - // histos.fill(HIST("hNsigmaKaonTPC_after"), t1.pt(), t1.tpcNSigmaKa()); - // histos.fill(HIST("hNsigmaKaonTOF_after"), t1.pt(), t1.tofNSigmaKa()); - // histos.fill(HIST("hNsigmaKaonTOF_TPC_after"), t1.tofNSigmaKa(), t1.tpcNSigmaKa()); - // } - // if (isITSOnlycut) { - // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - // } - // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - // } + if (!selectionTrack(t1)) { + continue; } - } - } else { - for (auto& [c1, tracks1, c2, tracks2] : pair2) { - float multiplicity = c1.centFT0C(); - - if (!eventselection(c1, multiplicity)) { + if (!selectionTrack(t2)) { continue; } - if (!eventselection(c2, multiplicity)) { + if (!selectionPair(t1, t2)) { continue; } - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { - bool unlike = false; - bool mix = true; - bool likesign = false; - bool rotation = false; - if (!selectionTrack(t1)) { - continue; - } - if (!selectionTrack(t2)) { - continue; - } - if (!selectionPair(t1, t2)) { - continue; - } - // calculation of event planes - daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); // Kplus - daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); // Kminus - - ROOT::Math::PxPyPzMVector fourVecDau = ROOT::Math::PxPyPzMVector(daughter1.Px(), daughter1.Py(), daughter1.Pz(), massKa); // Kaon - TLorentzVector lv1, lv2, lv3; - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massKa); - lv3 = lv1 + lv2; - - ROOT::Math::PxPyPzMVector fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KaonKaon pair - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - ROOT::Math::PxPyPzMVector fourVecDauCM = boost(fourVecDau); // boost the frame of daughter same as mother - ROOT::Math::XYZVector threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - - if (activateTHnSparseCosThStarHelicity) { - ROOT::Math::XYZVector helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); + if (!selectionPID(t1)) + continue; + if (!selectionPID(t2)) + continue; - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarHelicity, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarProduction) { - ROOT::Math::XYZVector normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); - auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); + mother = daughter1 + daughter2; // Kstar meson - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarProduction, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarBeam) { - ROOT::Math::XYZVector beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); + isMix = true; - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarBeam, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } else if (activateTHnSparseCosThStarRandom) { - auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); - auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); - ROOT::Math::XYZVector randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - - if (isITSOnlycut) { - FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, cosThetaStarRandom, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - } - } - - // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - // histos.fill(HIST("hNsigmaKaonTPC_after"), t1.pt(), t1.tpcNSigmaKa()); - // histos.fill(HIST("hNsigmaKaonTOF_after"), t1.pt(), t1.tofNSigmaKa()); - // histos.fill(HIST("hNsigmaKaonTOF_TPC_after"), t1.tofNSigmaKa(), t1.tpcNSigmaKa()); - // } - - // if (isITSOnlycut) { - // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - // } - // if (!isITSOnlycut && selectionPID(t1) && selectionPID(t2)) { - // FillinvMass(t1, t2, multiplicity, unlike, mix, likesign, rotation, massKa, massKa); - // } + if (std::abs(mother.Rapidity()) < 0.5) { + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, t1, t2); } } } @@ -726,6 +560,7 @@ struct kaonkaonAnalysisRun3 { if (std::abs(mcCollision.posZ()) < cfgCutVertex) { histos.fill(HIST("hMC"), 1.5); } + auto multiplicity = -1; int Nchinel = 0; for (auto& mcParticle : mcParticles) { auto pdgcode = std::abs(mcParticle.pdgCode()); @@ -744,6 +579,7 @@ struct kaonkaonAnalysisRun3 { continue; } SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + multiplicity = collision.centFT0M(); } SelectedEvents.resize(nevts); const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); @@ -751,6 +587,7 @@ struct kaonkaonAnalysisRun3 { if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; } + histos.fill(HIST("Genmutiplicity"), multiplicity); histos.fill(HIST("hMC"), 4.5); for (auto& mcParticle : mcParticles) { if (std::abs(mcParticle.y()) > 0.5) { @@ -776,7 +613,7 @@ struct kaonkaonAnalysisRun3 { } } if (daughtp && daughtm) { - histos.fill(HIST("h1PhiGen"), mcParticle.pt()); + hInvMass.fill(HIST("h1PhiGen"), multiplicity, mcParticle.pt()); } } } @@ -790,6 +627,8 @@ struct kaonkaonAnalysisRun3 { if (std::abs(collision.mcCollision().posZ()) > cfgCutVertex || !collision.sel8()) { return; } + auto multiplicity = collision.centFT0M(); + histos.fill(HIST("Recmutiplicity"), multiplicity); histos.fill(HIST("hMC"), 5.5); auto oldindex = -999; for (auto track1 : tracks) { @@ -847,23 +686,27 @@ struct kaonkaonAnalysisRun3 { if (std::abs(mothertrack1.pdgCode()) != 333) { continue; } - if (!isITSOnlycut && !(selectionPID(track1) && selectionPID(track2))) { + if (!(selectionPID(track1))) { + continue; + } + if (!(selectionPID(track2))) { continue; } if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { histos.fill(HIST("h1PhiRecsplit"), mothertrack1.pt()); continue; } - oldindex = mothertrack1.globalIndex(); - pvec0 = array{track1.px(), track1.py(), track1.pz()}; - pvec1 = array{track2.px(), track2.py(), track2.pz()}; - auto arrMomrec = array{pvec0, pvec1}; - auto motherP = mothertrack1.p(); - auto motherE = mothertrack1.e(); - genMass = std::sqrt(motherE * motherE - motherP * motherP); - recMass = RecoDecay::m(arrMomrec, array{massKa, massKa}); - auto recpt = TMath::Sqrt((track1.px() + track2.px()) * (track1.px() + track2.px()) + (track1.py() + track2.py()) * (track1.py() + track2.py())); - histos.fill(HIST("h3PhiRec"), mothertrack1.pt(), recpt, recMass - genMass); + + if (track1.sign() * track2.sign() < 0) { + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } + mother = daughter1 + daughter2; + + if (TMath::Abs(mother.Rapidity()) >= 0.5) { + continue; + } + hInvMass.fill(HIST("h3PhiRec"), multiplicity, mother.Pt(), mother.M()); } } } diff --git a/PWGLF/Tasks/Resonances/kstarInOO.cxx b/PWGLF/Tasks/Resonances/kstarInOO.cxx new file mode 100644 index 00000000000..47259ec84ed --- /dev/null +++ b/PWGLF/Tasks/Resonances/kstarInOO.cxx @@ -0,0 +1,470 @@ +// 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 kstarInOO.cxx +/// \brief the pT spectra of k*0(892) resonance analysis in OO collisions +/// \author Jimun Lee + +#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 + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct kstarInOO { + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + //================================== + //|| + //|| Selection + //|| + //================================== + + // 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, 110.0}, "Binning of the centrality axis"}; + + // Track Selection + // General + Configurable cfgTrackMinPt{"cfgTrackMinPt", 0.15, "set track min pT"}; + Configurable cfgTrackMaxEta{"cfgTrackMaxEta", 0.9, "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 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 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"}; + + // IT + Configurable cfgTracknITSChi2{"cfgTrackITSChi2", 36.0, "nITS Chi2 per Cluster"}; + + // PID + Configurable cfgTrackTPCPID{"cfgTrackTPCPID", true, "Enables TPC PID"}; + Configurable cfgTrackTOFPID{"cfgTrackTOFPID", true, "Enables TOF PID"}; + 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"}; + + // 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 + Configurable cfgEventCutQA{"cfgEventCutsQA", false, "Enable Event QA Hists"}; + Configurable cfgTrackCutQA{"cfgTrackCutQA", false, "Enable Track QA Hists"}; + + // std::vector eventSelectionBits; + + 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}; + + if (cfgEventCutQA) { + histos.add("hPosZ_BC", "hPosZ_Bc", kTH1F, {{100, 0.0, 15.0}}); + histos.add("hPosZ_AC", "hPosZ_AC", kTH1F, {{100, 0.0, 15.0}}); + } + + if (cfgTrackCutQA) { + // histos.add("h_rawpT", "h_rawpT", kTH1F, {{1000, 0.0, 10.0}}); + // histos.add("h_rawpT_Kaon", "h_rawpT_Kaon", kTH1F, {{1000, 0.0, 10.0}}); + // histos.add("h_rawpT_Pion", "h_rawpT_Pion", kTH1F, {{1000, 0.0, 10.0}}); + // histos.add("h_eta", "h_eta", kTH1F, {axisEta}); + // histos.add("h_phi", "h_phi", kTH1F, {axisPhi}); + + 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_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_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_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}}); + } + + // MC histos + histos.add("hMC_USS", "hMC_USS", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hMC_LSS", "hMC_LSS", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hMC_USS_Mix", "hMC_USS_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + histos.add("hMC_LSS_Mix", "hMC_LSS_Mix", kTHnSparseF, {cfgCentAxis, ptAxis, minvAxis}); + + // histos.add("hMC_pt_Pion", "hMC_pt_Pion", kTH1F, {ptAxis}); + // histos.add("hMC_pt_Kaon", "hMC_pt_Kaon", kTH1F, {ptAxis}); + // histos.add("hMC_pt_Proton", "hMC_pt_Proton", kTH1F, {ptAxis}); + + // Event Histograms + histos.add("nEvents_MC", "nEvents_MC", kTH1F, {{4, 0.0, 4.0}}); + histos.add("nEvents_MC_Mix", "nEvents_MC_Mix", kTH1F, {{4, 0.0, 4.0}}); + + } // end of init + + using EventCandidates = soa::Join; //, aod::CentFT0Ms, aod::CentFT0As + using TrackCandidates = soa::Join; + using TrackCandidatesMC = soa::Join; + + // For Mixed Event + using BinningType = ColumnBinningPolicy; + + 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 + bool eventSelection(const EventType event) + { + if (cfgEventCutQA) + histos.fill(HIST("hPosZ_BC"), event.posZ()); + + if (!event.sel8()) + return false; + if (std::abs(event.posZ()) > cfgEventVtxCut) + return false; + if (!event.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + if (!event.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + if (!event.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return false; + if (!event.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return false; + if (!event.selection_bit(aod::evsel::kNoCollInTimeRangeStandard)) + return false; + + if (cfgEventCutQA) + histos.fill(HIST("hPosZ_AC"), event.posZ()); + + return true; + }; + + template + bool trackSelection(const TracksType track) + { + 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 (track.tpcNClsFindable() < cfgTracknFindableTPCClusters) + return false; + + if (track.tpcNClsCrossedRows() < cfgTracknTPCCrossedRows) + return false; + + if (track.tpcCrossedRowsOverFindableCls() > cfgTracknRowsOverFindable) + return false; + + if (track.tpcChi2NCl() > cfgTracknTPCChi2) + return false; + + if (track.itsChi2NCl() > cfgTracknITSChi2) + return false; + + if (cfgTrackConnectedToPV && !track.isPVContributor()) + return false; + + return true; + }; + + template + bool trackPIDKaon(const TrackPID& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + // TPC + if (cfgTrackCutQA) { + 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()); + } + if (std::abs(candidate.tpcNSigmaKa()) < cfgTrackTPCPIDnSig) + tpcPIDPassed = true; + + // TOF + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cfgTrackTOFPIDnSig) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + + // TPC & TOF + if (tpcPIDPassed && tofPIDPassed) { + if (cfgTrackCutQA) { + 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()); + } + return true; + } + return false; + } + + template + bool trackPIDPion(const TrackPID& candidate) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + // TPC + if (cfgTrackCutQA) { + 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()); + } + if (std::abs(candidate.tpcNSigmaPi()) < cfgTrackTPCPIDnSig) + tpcPIDPassed = true; + + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaPi()) < cfgTrackTOFPIDnSig) { + tofPIDPassed = true; + } + } else { + tofPIDPassed = true; + } + + // TPC & TOF + if (tpcPIDPassed && tofPIDPassed) { + if (cfgTrackCutQA) { + 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()); + } + return true; + } + return false; + } + + template + void TrackSlicingMC(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool IsMix) + { + 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 (!trackSelection(trk1) || !trackSelection(trk2)) + continue; + if (!trackPIDKaon(trk1) || !trackPIDPion(trk2)) + continue; + + auto [KstarPt, Minv] = minvReconstruction(trk1, trk2); + if (Minv < 0) + continue; + + double conjugate = trk1.sign() * trk2.sign(); + if (!IsMix) { + if (conjugate < 0) { + histos.fill(HIST("hMC_USS"), centrality, KstarPt, Minv); + } else if (conjugate > 0) { + histos.fill(HIST("hMC_LSS"), centrality, KstarPt, Minv); + } + } else { + if (conjugate < 0) { + histos.fill(HIST("hMC_USS_Mix"), centrality, KstarPt, Minv); + } else if (conjugate > 0) { + histos.fill(HIST("hMC_LSS_Mix"), centrality, KstarPt, Minv); + } + } + } + } + + template + std::pair minvReconstruction(const TracksType& trk1, const TracksType& trk2) + { + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; + + if (!trackSelection(trk1) || !trackSelection(trk2)) + return {-1.0, -1.0}; + + if (!trackPIDKaon(trk1) || !trackPIDPion(trk2)) + return {-1.0, -1.0}; + + if (trk1.globalIndex() == trk2.globalIndex()) { + return {-1.0, -1.0}; // For Kstar, we need to run (0,1), (1,0) pairs as well. but same id pairs are not need. + } + + lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massPi); + lResonance = lDecayDaughter1 + lDecayDaughter2; + + if (std::abs(lResonance.Eta()) > cfgTrackMaxEta) + return {-1.0, -1.0}; + + return {lResonance.Pt(), lResonance.M()}; + } + + //======================================================= + //| + //| 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 = eventSelection(collision); + histos.fill(HIST("nEvents_MC"), 0.5); + if (!goodEv) + return; + + bool INELgt0 = false; + for (const auto& track : tracks) { + if (std::fabs(track.eta()) < cfgTrackMaxEta) { + INELgt0 = true; + break; + } + } + if (!INELgt0) + return; + + histos.fill(HIST("nEvents_MC"), 1.5); + TrackSlicingMC(collision, tracks, collision, tracks, false); + + } // processSameEvents_MC + PROCESS_SWITCH(kstarInOO, processSameEventMC, "process Same Event MC", true); + + //======================================================= + //| + //| 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 = eventSelection(collision1); + auto goodEv2 = eventSelection(collision2); + histos.fill(HIST("nEvents_MC_Mix"), 0.5); + + if (!goodEv1 || !goodEv2) + continue; + + histos.fill(HIST("nEvents_MC_Mix"), 1.5); + + TrackSlicingMC(collision1, tracks1, collision2, tracks2, true); + } // mixing + } // processMixedEvent_MC + PROCESS_SWITCH(kstarInOO, processMixedEventMC, "process Mixed Event MC", false); + + void processEventsDummy(EventCandidates::iterator const&, TrackCandidates const&) + { + return; + } + PROCESS_SWITCH(kstarInOO, processEventsDummy, "dummy", false); + +}; // kstarInOO + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGLF/Tasks/Resonances/kstarpbpb.cxx b/PWGLF/Tasks/Resonances/kstarpbpb.cxx index 0093b921c80..e650e1f8d91 100644 --- a/PWGLF/Tasks/Resonances/kstarpbpb.cxx +++ b/PWGLF/Tasks/Resonances/kstarpbpb.cxx @@ -10,50 +10,51 @@ // or submit itself to any jurisdiction. // sourav.kundu@cern.ch , sarjeeta.gami@cern.ch -#include +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#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/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.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/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 +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include + #include +#include #include -#include #include - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "TF1.h" - -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table +#include using namespace o2; using namespace o2::framework; @@ -101,6 +102,7 @@ struct kstarpbpb { Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; Configurable useGlobalTrack{"useGlobalTrack", true, "use Global track"}; + Configurable usepolar{"usepolar", true, "flag to fill type of SA"}; Configurable nsigmaCutTOF{"nsigmacutTOF", 3.0, "Value of the TOF Nsigma cut"}; Configurable nsigmaCutTPC{"nsigmacutTPC", 3.0, "Value of the TPC Nsigma cut"}; Configurable isTOFOnly{"isTOFOnly", false, "use TOF only PID"}; @@ -159,8 +161,8 @@ struct kstarpbpb { Preslice perCollision = aod::track::collisionId; SliceCache cache; - Partition posTracks = aod::track::signed1Pt > cfgCutCharge; - Partition negTracks = aod::track::signed1Pt < cfgCutCharge; + // Partition posTracks = aod::track::signed1Pt > cfgCutCharge; + // Partition negTracks = aod::track::signed1Pt < cfgCutCharge; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -183,10 +185,10 @@ struct kstarpbpb { AxisSpec resAxis = {6000, -30, 30, "Res"}; AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; + histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); if (!fillSA) { if (same) { histos.add("hSparseV2SASameEvent_V2", "hSparseV2SASameEvent_V2", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisPt, configThnAxisV2, configThnAxisCentrality}); - histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); } if (like) { histos.add("hSparseV2SAlikeEventNN_V2", "hSparseV2SAlikeEventNN_V2", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisPt, configThnAxisV2, configThnAxisCentrality}); @@ -663,15 +665,25 @@ struct kstarpbpb { threeVecDauCM = fourVecDauCM.Vect(); threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); eventplaneVec = ROOT::Math::XYZVector(std::cos(2.0 * psiFT0C), std::sin(2.0 * psiFT0C), 0); + eventplaneVecNorm = ROOT::Math::XYZVector(std::sin(2.0 * psiFT0C), -std::cos(2.0 * psiFT0C), 0); auto cosPhistarminuspsi = GetPhiInRange(fourVecDauCM.Phi() - psiFT0C); auto SA = TMath::Cos(2.0 * cosPhistarminuspsi); + auto cosThetaStar = eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); - if (track1Sign * track2Sign < 0) - histos.fill(HIST("hSparseSAvsrapsameunlike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); - else if (track1Sign * track2Sign > 0) - histos.fill(HIST("hSparseSAvsrapsamelike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + if (track1Sign * track2Sign < 0) { + if (usepolar) { + histos.fill(HIST("hSparseSAvsrapsameunlike"), KstarMother.M(), KstarMother.Pt(), cosThetaStar, KstarMother.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsrapsameunlike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + } + } else if (track1Sign * track2Sign > 0) { + if (usepolar) { + histos.fill(HIST("hSparseSAvsrapsamelike"), KstarMother.M(), KstarMother.Pt(), cosThetaStar, KstarMother.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsrapsamelike"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + } + } } - if (fillRotation) { for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { auto anglestart = confMinRot; @@ -707,8 +719,12 @@ struct kstarpbpb { threeVecDauCMXYrot = ROOT::Math::XYZVector(threeVecDauCMrot.X(), threeVecDauCMrot.Y(), 0.); auto cosPhistarminuspsirot = GetPhiInRange(fourVecDauCMrot.Phi() - psiFT0C); auto SArot = TMath::Cos(2.0 * cosPhistarminuspsirot); - - histos.fill(HIST("hSparseSAvsraprot"), kstarrot.M(), kstarrot.Pt(), SArot, kstarrot.Rapidity(), centrality); + auto cosThetaStarrot = eventplaneVecNorm.Dot(threeVecDauCMrot) / std::sqrt(threeVecDauCMrot.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); + if (usepolar) { + histos.fill(HIST("hSparseSAvsraprot"), kstarrot.M(), kstarrot.Pt(), cosThetaStarrot, kstarrot.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsraprot"), kstarrot.M(), kstarrot.Pt(), SArot, kstarrot.Rapidity(), centrality); + } } } } @@ -1203,10 +1219,15 @@ struct kstarpbpb { threeVecDauCM = fourVecDauCM.Vect(); threeVecDauCMXY = ROOT::Math::XYZVector(threeVecDauCM.X(), threeVecDauCM.Y(), 0.); eventplaneVec = ROOT::Math::XYZVector(std::cos(2.0 * psiFT0C), std::sin(2.0 * psiFT0C), 0); + eventplaneVecNorm = ROOT::Math::XYZVector(std::sin(2.0 * psiFT0C), -std::cos(2.0 * psiFT0C), 0); auto cosPhistarminuspsi = GetPhiInRange(fourVecDauCM.Phi() - psiFT0C); auto SA = TMath::Cos(2.0 * cosPhistarminuspsi); - - histos.fill(HIST("hSparseSAvsrapmix"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + auto cosThetaStar = eventplaneVecNorm.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()) / std::sqrt(eventplaneVecNorm.Mag2()); + if (usepolar) { + histos.fill(HIST("hSparseSAvsrapmix"), KstarMother.M(), KstarMother.Pt(), cosThetaStar, KstarMother.Rapidity(), centrality); + } else { + histos.fill(HIST("hSparseSAvsrapmix"), KstarMother.M(), KstarMother.Pt(), SA, KstarMother.Rapidity(), centrality); + } } } } diff --git a/PWGLF/Tasks/Resonances/kstarqa.cxx b/PWGLF/Tasks/Resonances/kstarqa.cxx index 804e8538824..5071fa7c203 100644 --- a/PWGLF/Tasks/Resonances/kstarqa.cxx +++ b/PWGLF/Tasks/Resonances/kstarqa.cxx @@ -15,22 +15,10 @@ /// \since 13/03/2024 // #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.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" #include "Common/DataModel/Centrality.h" @@ -38,6 +26,9 @@ #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "CommonConstants/PhysicsConstants.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" @@ -45,19 +36,125 @@ #include "Framework/HistogramRegistry.h" #include "Framework/StepTHn.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" +#include "Math/GenVector/Boost.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "TRandom3.h" +#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 std::array; +using namespace o2::aod::rctsel; struct Kstarqa { SliceCache cache; + struct : ConfigurableGroup { + Configurable requireRCTFlagChecker{"requireRCTFlagChecker", true, "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"}; + } rctCut; + RCTFlagsChecker rctChecker; + + struct : ConfigurableGroup { + // Configurables for event selections + Configurable isINELgt0{"isINELgt0", true, "INEL>0 selection"}; + Configurable isTriggerTVX{"isTriggerTVX", false, "TriggerTVX"}; + Configurable isGoodZvtxFT0vsPV{"isGoodZvtxFT0vsPV", false, "IsGoodZvtxFT0vsPV"}; + Configurable isApplyOccCut{"isApplyOccCut", true, "Apply occupancy cut"}; + Configurable isNoSameBunchPileup{"isNoSameBunchPileup", true, "kNoSameBunchPileup"}; + Configurable isAllLayersGoodITS{"isAllLayersGoodITS", 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 cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; + Configurable configOccCut{"configOccCut", 1000., "Occupancy cut"}; + + // Configurables for track selections + Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor + Configurable cfgPrimaryTrack{"cfgPrimaryTrack", false, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable isGlobalTracks{"isGlobalTracks", true, "isGlobalTracks"}; + + Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + Configurable cfgCutPT{"cfgCutPT", 0.2f, "PT cut on daughter track"}; + Configurable cfgCutEtaMax{"cfgCutEtaMax", 0.8f, "Eta cut on daughter track"}; + Configurable cfgCutEtaMin{"cfgCutEtaMin", 0.0f, "Eta cut on daughter track"}; + Configurable cfgCutDCAxyMax{"cfgCutDCAxyMax", 2.0f, "DCAxy range for tracks"}; + Configurable cfgCutDCAxyMin{"cfgCutDCAxyMin", 0.0f, "DCAxy range for tracks"}; + Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; + Configurable ctrackRapidity{"ctrackRapidity", 0.3f, "Cut on track rapidity"}; + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; + Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; + Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; + Configurable cfgRCRFC{"cfgRCRFC", 0.8f, "Crossed Rows to Findable Clusters"}; + Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 36.0, "ITS Chi2/NCl"}; + Configurable cfgTPCChi2NClMax{"cfgTPCChi2NClMax", 4.0, "TPC Chi2/NCl"}; + Configurable cfgTPCChi2NClMin{"cfgTPCChi2NClMin", 0.0, "TPC Chi2/NCl"}; + Configurable cfgUseITSTPCRefit{"cfgUseITSTPCRefit", false, "Require ITS Refit"}; + // Configurable isVertexITSTPC{"isVertexITSTPC", false, "Vertex ITS TPC"}; + Configurable isVertexTOFMatched{"isVertexTOFMatched", false, "Vertex TOF Matched"}; + Configurable isNoCollInTimeRangeStandard{"isNoCollInTimeRangeStandard", false, "No collision in time range standard"}; + Configurable isApplyPtDepDCAxyCut{"isApplyPtDepDCAxyCut", false, "Apply pT dependent DCAxy cut"}; + Configurable isGoldenChi2{"isGoldenChi2", false, "Apply golden chi2 cut"}; + + // cuts on mother + Configurable isApplyCutsOnMother{"isApplyCutsOnMother", false, "Enable additional cuts on Kstar mother"}; + Configurable cMaxPtMotherCut{"cMaxPtMotherCut", 15.0, "Maximum pt of mother cut"}; + Configurable cMaxMinvMotherCut{"cMaxMinvMotherCut", 1.5, "Maximum mass of mother cut"}; + Configurable isPDGCheckMC{"isPDGCheckMC", true, "Check PDG code in MC (false for MC closure test)"}; + + // PID selections + Configurable nsigmaCutTPCPi{"nsigmaCutTPCPi", 3.0, "TPC Nsigma cut for pions"}; + Configurable nsigmaCutTPCKa{"nsigmaCutTPCKa", 3.0, "TPC Nsigma cut for kaons"}; + Configurable nsigmaCutTOFPi{"nsigmaCutTOFPi", 3.0, "TOF Nsigma cut for pions"}; + Configurable nsigmaCutTOFKa{"nsigmaCutTOFKa", 3.0, "TOF Nsigma cut for kaons"}; + Configurable nsigmaCutTPCPr{"nsigmaCutTPCPr", 3.0, "TPC Nsigma cut for protons (for MID)"}; + Configurable nsigmaCutTOFPr{"nsigmaCutTOFPr", 3.0, "TOF Nsigma cut for protons (for MID)"}; + Configurable nsigmaCutCombinedKa{"nsigmaCutCombinedKa", 3.0, "Combined Nsigma cut for kaon"}; + Configurable nsigmaCutCombinedPi{"nsigmaCutCombinedPi", 3.0, "Combined Nsigma cut for pion"}; + + // Other fixed variables + float lowPtCutPID = 0.5; + int noOfDaughters = 2; + float rapidityMotherData = 0.5; + + } selectionConfig; + + enum MultEstimator { + kFT0M, + kFT0A, + kFT0C, + kFV0A, + kFV0C, + kFV0M, + kNEstimators // useful if you want to iterate or size things + }; + + enum PIDParticle { + kPion, + kKaon, + kProton + }; + // Histograms are defined with HistogramRegistry HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry hInvMass{"hInvMass", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -66,62 +163,34 @@ struct Kstarqa { // Confugrable for QA histograms Configurable calcLikeSign{"calcLikeSign", true, "Calculate Like Sign"}; - Configurable calcRotational{"calcRotational", true, "Calculate Rotational"}; + Configurable calcRotational{"calcRotational", false, "Calculate Rotational"}; Configurable cQAplots{"cQAplots", true, "cQAplots"}; Configurable cQAevents{"cQAevents", true, "Multiplicity dist, DCAxy, DCAz"}; Configurable onlyTOF{"onlyTOF", false, "only TOF tracks"}; Configurable onlyTOFHIT{"onlyTOFHIT", false, "accept only TOF hit tracks at high pt"}; Configurable onlyTPC{"onlyTPC", true, "only TPC tracks"}; + Configurable cRotations{"cRotations", 3, "Number of random rotations in the rotational background"}; + Configurable cSelectMultEstimator{"cSelectMultEstimator", 0, "Select multiplicity estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C"}; + Configurable applyRecMotherRapidity{"applyRecMotherRapidity", true, "Apply rapidity cut on reconstructed mother track"}; + Configurable applypTdepPID{"applypTdepPID", false, "Apply pT dependent PID"}; - // Configurables for track selections - Configurable rotationalCut{"rotationalCut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; - Configurable cfgCutPT{"cfgCutPT", 0.2f, "PT cut on daughter track"}; - Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta cut on daughter track"}; - Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; - Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; - Configurable ismanualDCAcut{"ismanualDCAcut", true, "ismanualDCAcut"}; - Configurable cfgITScluster{"cfgITScluster", 0, "Number of ITS cluster"}; - Configurable cfgTPCcluster{"cfgTPCcluster", 70, "Number of TPC cluster"}; - Configurable cfgRCRFC{"cfgRCRFC", 0.8f, "Crossed Rows to Findable Clusters"}; - Configurable cfgITSChi2NCl{"cfgITSChi2NCl", 36.0, "ITS Chi2/NCl"}; - Configurable cfgTPCChi2NCl{"cfgTPCChi2NCl", 4.0, "TPC Chi2/NCl"}; - Configurable cfgPVContributor{"cfgPVContributor", false, "PV contributor track selection"}; // PV Contriuibutor - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", false, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz - Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", false, "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 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"}; + Configurable cFakeTrack{"cFakeTrack", true, "Fake track selection"}; Configurable cFakeTrackCutKa{"cFakeTrackCutKa", 0.5, "Cut based on momentum difference in global and TPC tracks for Kaons"}; Configurable cFakeTrackCutPi{"cFakeTrackCutPi", 0.5, "Cut based on momentum difference in global and TPC tracks for Pions"}; - Configurable cFakeTrack{"cFakeTrack", true, "Fake track selection"}; - - // PID selections - Configurable nsigmaCutTPCPi{"nsigmaCutTPCPi", 3.0, "TPC Nsigma cut for pions"}; - Configurable nsigmaCutTPCKa{"nsigmaCutTPCKa", 3.0, "TPC Nsigma cut for kaons"}; - Configurable nsigmaCutTOFPi{"nsigmaCutTOFPi", 3.0, "TOF Nsigma cut for pions"}; - Configurable nsigmaCutTOFKa{"nsigmaCutTOFKa", 3.0, "TOF Nsigma cut for kaons"}; - Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "Combined Nsigma cut"}; - - // Event selection configurables - Configurable timFrameEvsel{"timFrameEvsel", false, "TPC Time frame boundary cut"}; - Configurable cTVXEvsel{"cTVXEvsel", false, "Triggger selection"}; - Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; - // Configurable cMID{"cMID", false, "Misidentification of tracks"}; // Configurable for histograms - Configurable nBins{"nBins", 100, "No. of bins in Vz distribution"}; - Configurable nBinsinvMass{"nBinsinvMass", 180, "N bins in invMass hInvMass"}; - Configurable invMassbinlow{"invMassbinlow", 0.6, "invMass bin low"}; - Configurable invMassbinhigh{"invMassbinhigh", 1.5, "invMass bin high"}; - Configurable nBinspT{"nBinspT", 200, "N bins in pT hInvMass"}; - Configurable pTbinlow{"pTbinlow", 0.0, "pT bin low"}; - Configurable pTbinhigh{"pTbinhigh", 20.0, "pT bin high"}; Configurable avoidsplitrackMC{"avoidsplitrackMC", true, "avoid split track in MC"}; Configurable cAllGenCollisions{"cAllGenCollisions", false, "To fill all generated collisions for the signal loss calculations"}; - ConfigurableAxis binsMultPlot{"binsMultPlot", {201, -0.5f, 200.5f}, "centrality axis bins"}; + ConfigurableAxis binsMultPlot{"binsMultPlot", {110, 0.0, 110}, "THnSpare multiplicity axis"}; ConfigurableAxis axisdEdx{"axisdEdx", {1, 0.0f, 200.0f}, "dE/dx (a.u.)"}; ConfigurableAxis axisPtfordEbydx{"axisPtfordEbydx", {1, 0, 20}, "pT (GeV/c)"}; ConfigurableAxis axisMultdist{"axisMultdist", {1, 0, 70000}, "Multiplicity distribution"}; + ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + ConfigurableAxis invMassKstarAxis{"invMassKstarAxis", {300, 0.7f, 1.3f}, "Kstar invariant mass axis"}; + ConfigurableAxis ptAxisKstar{"ptAxisKstar", {200, 0.0f, 20.0f}, "Kstar pT axis"}; + ConfigurableAxis binsImpactPar{"binsImpactPar", {100, 0, 25}, "Binning of the impact parameter axis"}; // Event plane configurables Configurable boostDaugter1{"boostDaugter1", false, "Boost daughter Kaon in the COM frame"}; @@ -130,24 +199,43 @@ struct Kstarqa { Configurable activateTHnSparseCosThStarProduction{"activateTHnSparseCosThStarProduction", false, "Activate the THnSparse with cosThStar w.r.t. production axis"}; Configurable activateTHnSparseCosThStarBeam{"activateTHnSparseCosThStarBeam", false, "Activate the THnSparse with cosThStar w.r.t. beam axis (Gottified jackson frame)"}; Configurable activateTHnSparseCosThStarRandom{"activateTHnSparseCosThStarRandom", false, "Activate the THnSparse with cosThStar w.r.t. random axis"}; - Configurable cRotations{"cRotations", 3, "Number of random rotations in the rotational background"}; - ConfigurableAxis configThnAxisPOL{"configThnAxisPOL", {20, -1.0, 1.0}, "Costheta axis"}; + TRandom* rn = new TRandom(); void init(InitContext const&) { + rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); // Axes - AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm] for plots"}; - AxisSpec ptAxis = {nBinspT, pTbinlow, pTbinhigh, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec invmassAxis = {nBinsinvMass, invMassbinlow, invMassbinhigh, "Invariant mass (GeV/#it{c}^{2})"}; + AxisSpec vertexZAxis = {60, -15., 15., "vrtx_{Z} [cm] for plots"}; + AxisSpec ptAxis = {ptAxisKstar, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec invmassAxis = {invMassKstarAxis, "Invariant mass (GeV/#it{c}^{2})"}; AxisSpec thnAxisPOL{configThnAxisPOL, "cos(#theta)"}; + AxisSpec multiplicityAxis = {binsMultPlot, "Multiplicity Axis"}; + AxisSpec impactParAxis = {binsImpactPar, "Impact Parameter (cm)"}; // Histograms // Event selection rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - rEventSelection.add("hmult", "Multiplicity percentile", kTH1F, {{binsMultPlot}}); - - // for primary tracks + rEventSelection.add("hMultiplicity", "Multiplicity percentile", kTH1F, {{110, 0, 110}}); + + rEventSelection.add("hEventCut", "No. of event after cuts", kTH1I, {{20, 0, 20}}); + std::shared_ptr hCutFlow = rEventSelection.get(HIST("hEventCut")); + hCutFlow->GetXaxis()->SetBinLabel(1, "All Events"); + hCutFlow->GetXaxis()->SetBinLabel(2, "|Vz| < cut"); + hCutFlow->GetXaxis()->SetBinLabel(3, "sel8"); + hCutFlow->GetXaxis()->SetBinLabel(4, "kNoTimeFrameBorder"); + hCutFlow->GetXaxis()->SetBinLabel(5, "kNoITSROFrameBorder"); + hCutFlow->GetXaxis()->SetBinLabel(6, "kNoSameBunchPileup"); + hCutFlow->GetXaxis()->SetBinLabel(7, "kIsGoodITSLayersAll"); + 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(13, "isVertexITSTPC"); + hCutFlow->GetXaxis()->SetBinLabel(14, "isVertexTOFMatched"); + + // for primary tracksbinsMultPlot if (cQAplots) { hOthers.add("dE_by_dx_TPC", "dE/dx signal in the TPC as a function of pT", kTH2F, {axisPtfordEbydx, axisdEdx}); hOthers.add("hphi", "Phi distribution", kTH1F, {{65, 0, 6.5}}); @@ -155,49 +243,113 @@ struct Kstarqa { hOthers.add("hCRFC_after", "CRFC after distribution", kTH1F, {{100, 0.0f, 10.0f}}); hOthers.add("hCRFC_before", "CRFC before distribution", kTH1F, {{100, 0.0f, 10.0f}}); - hPID.add("Before/hNsigmaTPC_Ka_before", "N #sigma Kaon TPC before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigmaTOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigmaTPC_Pi_before", "N #sigma Pion TPC before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigmaTOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("Before/hNsigma_TPC_TOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); - hPID.add("Before/hNsigma_TPC_TOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); - hPID.add("h1PID_TPC_kaon_data", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TPC_pion_data", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TPC_kaon_MC", "Kaon PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TPC_pion_MC", "Pion PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_kaon_data", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_pion_data", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_kaon_MC", "Kaon PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - hPID.add("h1PID_TOF_pion_MC", "Pion PID distribution in MC", kTH1F, {{100, -10.0f, 10.0f}}); - - hPID.add("After/hNsigmaPionTPC_after", "N #Pi TPC after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigmaPionTOF_after", "N #Pi TOF after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigmaKaonTPC_after", "N #sigma Kaon TPC after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigmaKaonTOF_after", "N #sigma Kaon TOF after", kTH2F, {{100, 0.0f, 10.0f}, {200, -10.0f, 10.0f}}); - hPID.add("After/hNsigma_TPC_TOF_Ka_after", "N #sigma Kaon TOF after", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); - hPID.add("After/hNsigma_TPC_TOF_Pi_after", "N #sigma Pion TOF after", kTH2F, {{100, -5.0f, 5.0f}, {100, -5.0f, 5.0f}}); + hOthers.add("hKstar_Rap", "Pair rapidity distribution; y; Counts", kTH1F, {{1000, -5.0f, 5.0f}}); + hOthers.add("hKstar_Eta", "Pair eta distribution; #eta; Counts", kTH1F, {{1000, -5.0f, 5.0f}}); + + hPID.add("Before/hNsigmaTPC_Ka_before", "N #sigma Kaon TPC before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigmaTOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigmaTPC_Pi_before", "N #sigma Pion TPC before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigmaTOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("Before/hNsigma_TPC_TOF_Ka_before", "N #sigma Kaon TOF before", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); + hPID.add("Before/hNsigma_TPC_TOF_Pi_before", "N #sigma Pion TOF before", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); + + hPID.add("Before/h1PID_TPC_pos_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TPC_pos_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_pos_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_pos_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TPC_neg_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TPC_neg_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_neg_kaon", "Kaon PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + hPID.add("Before/h1PID_TOF_neg_pion", "Pion PID distribution in data", kTH1F, {{100, -10.0f, 10.0f}}); + + hPID.add("Before/hTPCnsigKa_mult_pt", "TPC nsigma of Kaon brfore PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); + hPID.add("Before/hTPCnsigPi_mult_pt", "TPC nsigma of Pion brfore PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); + hPID.add("Before/hTOFnsigKa_mult_pt", "TPC nsigma of Kaon brfore PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); + hPID.add("Before/hTOFnsigPi_mult_pt", "TPC nsigma of Pion brfore PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); + + hPID.add("After/hNsigmaPionTPC_after", "N #Pi TPC after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigmaPionTOF_after", "N #Pi TOF after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigmaKaonTPC_after", "N #sigma Kaon TPC after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigmaKaonTOF_after", "N #sigma Kaon TOF after", kTH2F, {{50, 0.0f, 10.0f}, {100, -10.0f, 10.0f}}); + hPID.add("After/hNsigma_TPC_TOF_Ka_after", "N #sigma Kaon TOF after", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); + hPID.add("After/hNsigma_TPC_TOF_Pi_after", "N #sigma Pion TOF after", kTH2F, {{50, -5.0f, 5.0f}, {50, -5.0f, 5.0f}}); + + hPID.add("After/hDcaxyPi", "Dcaxy distribution of selected Pions", kTH1F, {{200, -1.0f, 1.0f}}); + hPID.add("After/hDcaxyKa", "Dcaxy distribution of selected Kaons", kTH1F, {{200, -1.0f, 1.0f}}); + hPID.add("After/hDcazPi", "Dcaz distribution of selected Pions", kTH1F, {{200, -1.0f, 1.0f}}); + hPID.add("After/hDcazKa", "Dcaz distribution of selected Kaons", kTH1F, {{200, -1.0f, 1.0f}}); + + hPID.add("After/hTPCnsigKa_mult_pt", "TPC nsigma of Kaon after PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); + hPID.add("After/hTPCnsigPi_mult_pt", "TPC nsigma of Pion after PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); + hPID.add("After/hTOFnsigKa_mult_pt", "TPC nsigma of Kaon after PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); + hPID.add("After/hTOFnsigPi_mult_pt", "TPC nsigma of Pion after PID with pt and multiplicity", kTH3F, {{100, -10.0f, 10.0f}, multiplicityAxis, ptAxis}); } // KStar histograms - hInvMass.add("h3KstarInvMassUnlikeSign", "kstar Unlike Sign", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); - hInvMass.add("h3KstarInvMassMixed", "kstar Mixed", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); - if (calcLikeSign) - hInvMass.add("h3KstarInvMasslikeSign", "kstar like Sign", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMassUnlikeSign", "kstar Unlike Sign", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMassMixed", "kstar Mixed", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); + if (calcLikeSign) { + hInvMass.add("h3KstarInvMasslikeSignPP", "kstar like Sign", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMasslikeSignMM", "kstar like Sign", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); + } if (calcRotational) - hInvMass.add("h3KstarInvMassRotated", "kstar rotated", kTHnSparseF, {binsMultPlot, ptAxis, invmassAxis, thnAxisPOL}); + hInvMass.add("h3KstarInvMassRotated", "kstar rotated", kTHnSparseF, {multiplicityAxis, ptAxis, invmassAxis, thnAxisPOL}); - // MC generated histograms - hInvMass.add("hk892GenpT", "pT distribution of True MC K(892)0", kTH2F, {ptAxis, binsMultPlot}); - // hInvMass.add("hk892GenpTAnti", "pT distribution of True MC Anti-K(892)0", kTH2F, {ptAxis}, {binsMultPlot}); - // Reconstructed MC histogram + // MC histograms + hInvMass.add("hk892GenpT", "pT distribution of True MC K(892)0", kTHnSparseF, {ptAxis, multiplicityAxis}); + hInvMass.add("hk892GenpT2", "pT distribution of True MC K(892)0", kTHnSparseF, {ptAxis, multiplicityAxis}); hInvMass.add("h1KstarRecMass", "Invariant mass of kstar meson", kTH1F, {invmassAxis}); - hInvMass.add("h2KstarRecpt1", "pT of kstar meson", kTH2F, {ptAxis, binsMultPlot}); - hInvMass.add("h2KstarRecpt2", "pT of generated kstar meson", kTH2F, {ptAxis, binsMultPlot}); + hInvMass.add("h2KstarRecpt1", "pT of kstar meson", kTHnSparseF, {ptAxis, multiplicityAxis, invmassAxis}); + hInvMass.add("h2KstarRecpt2", "pT of generated kstar meson", kTHnSparseF, {ptAxis, multiplicityAxis, invmassAxis}); hInvMass.add("h1genmass", "Invariant mass of generated kstar meson", kTH1F, {invmassAxis}); - rEventSelection.add("events_check_data", "No. of events in the data", kTH1I, {{20, 0, 20}}); - rEventSelection.add("events_check", "No. of events in the generated MC", kTH1I, {{20, 0, 20}}); - rEventSelection.add("events_checkrec", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); + hInvMass.add("h1GenMult", "Multiplicity generated", kTH1F, {multiplicityAxis}); + hInvMass.add("h1RecMult", "Multiplicity reconstructed", kTH1F, {multiplicityAxis}); hInvMass.add("h1KSRecsplit", "KS meson Rec split", kTH1F, {{100, 0.0f, 10.0f}}); + hInvMass.add("MCcorrections/hSignalLossDenominator", "Kstar generated before event selection", kTH2F, {{ptAxis}, {impactParAxis}}); + hInvMass.add("MCcorrections/hSignalLossNumerator", "Kstar generated after event selection", kTH2F, {{ptAxis}, {impactParAxis}}); + // hInvMass.add("hAllGenCollisionsImpact", "All generated collisions vs impact parameter", kTH1F, {multiplicityAxis}); + hInvMass.add("hAllGenCollisions", "All generated events", kTH1F, {multiplicityAxis}); + hInvMass.add("hAllGenCollisions1Rec", "All gen events with at least one rec event", kTH1F, {multiplicityAxis}); + hInvMass.add("hAllKstarGenCollisisons", "All generated Kstar in events with rapidity in 0.5", kTH2F, {{multiplicityAxis}, {ptAxis}}); + hInvMass.add("hAllKstarGenCollisisons1Rec", "All generated Kstar in events with at least one rec event in rapidity in 0.5", kTH2F, {{multiplicityAxis}, {ptAxis}}); + hInvMass.add("hAllRecCollisions", "All reconstructed events", kTH1F, {multiplicityAxis}); + hInvMass.add("MCcorrections/hImpactParameterRec", "Impact parameter in reconstructed MC", kTH1F, {impactParAxis}); + hInvMass.add("MCcorrections/hImpactParameterGen", "Impact parameter in generated MC", kTH1F, {impactParAxis}); + hInvMass.add("MCcorrections/hImpactParametervsMultiplicity", "Impact parameter vs multiplicity in reconstructed MC", kTH2F, {{impactParAxis}, {multiplicityAxis}}); + rEventSelection.add("tracksCheckData", "No. of events in the data", kTH1I, {{10, 0, 10}}); + rEventSelection.add("eventsCheckGen", "No. of events in the generated MC", kTH1I, {{10, 0, 10}}); + rEventSelection.add("recMCparticles", "No. of events in the reconstructed MC", kTH1I, {{20, 0, 20}}); + rEventSelection.add("hOccupancy", "Occupancy distribution", kTH1F, {{1000, 0, 15000}}); + + std::shared_ptr hrecLabel = rEventSelection.get(HIST("recMCparticles")); + hrecLabel->GetXaxis()->SetBinLabel(1, "All tracks"); + hrecLabel->GetXaxis()->SetBinLabel(2, "Track selection"); + hrecLabel->GetXaxis()->SetBinLabel(3, "has_MC"); + hrecLabel->GetXaxis()->SetBinLabel(4, "StrictlyUpperIndex"); + hrecLabel->GetXaxis()->SetBinLabel(5, "Unlike Sign"); + hrecLabel->GetXaxis()->SetBinLabel(6, "Physical Primary"); + hrecLabel->GetXaxis()->SetBinLabel(7, "PID Cut"); + hrecLabel->GetXaxis()->SetBinLabel(8, "Rapidity Cut"); + hrecLabel->GetXaxis()->SetBinLabel(9, "Same mother"); + hrecLabel->GetXaxis()->SetBinLabel(10, "Generator"); + hrecLabel->GetXaxis()->SetBinLabel(11, "Rapidity"); + hrecLabel->GetXaxis()->SetBinLabel(12, "MotherPID313"); + hrecLabel->GetXaxis()->SetBinLabel(13, "Split track"); + + std::shared_ptr hDataTracks = rEventSelection.get(HIST("tracksCheckData")); + hDataTracks->GetXaxis()->SetBinLabel(1, "All tracks"); + hDataTracks->GetXaxis()->SetBinLabel(2, "Track selection"); + hDataTracks->GetXaxis()->SetBinLabel(3, "PID Cut"); + hDataTracks->GetXaxis()->SetBinLabel(4, "Remove Fake Tracks"); + hDataTracks->GetXaxis()->SetBinLabel(5, "Rapidity Cut"); + hDataTracks->GetXaxis()->SetBinLabel(6, "MID"); + hDataTracks->GetXaxis()->SetBinLabel(7, "Global Index"); + + std::shared_ptr hGenTracks = rEventSelection.get(HIST("eventsCheckGen")); + hGenTracks->GetXaxis()->SetBinLabel(1, "All events"); + hGenTracks->GetXaxis()->SetBinLabel(2, "INELgt0+vtz"); + hGenTracks->GetXaxis()->SetBinLabel(3, "INELgt0"); + hGenTracks->GetXaxis()->SetBinLabel(4, "Event Reconstructed"); // Multplicity distribution if (cQAevents) { @@ -214,35 +366,143 @@ struct Kstarqa { double massPi = o2::constants::physics::MassPiPlus; double massKa = o2::constants::physics::MassKPlus; + template + bool selectionEvent(const Coll& collision, bool fillHist = true) + { + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 0); + + if (std::abs(collision.posZ()) > selectionConfig.cutzvertex) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 1); + + if (!collision.sel8()) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 2); + + if (selectionConfig.isNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 3); + + if (selectionConfig.isNoITSROFrameBorder && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 4); + + if (selectionConfig.isNoSameBunchPileup && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup))) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 5); + + if (selectionConfig.isAllLayersGoodITS && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 6); + + if (selectionConfig.isNoCollInTimeRangeStandard && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) + return false; + + if (selectionConfig.isApplyOccCut && (std::abs(collision.trackOccupancyInTimeRange()) > selectionConfig.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 (selectionConfig.isTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 9); + + if (selectionConfig.isGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) + return false; + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 10); + + if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { + return false; + } + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 11); + + // if (selectionConfig.isVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + // return false; + // } + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 12); + + if (selectionConfig.isVertexTOFMatched && !collision.selection_bit(aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if (fillHist) + rEventSelection.fill(HIST("hEventCut"), 13); + + return true; + } + template bool selectionTrack(const T& candidate) { - if (ismanualDCAcut && !(candidate.isGlobalTrackWoDCA() && candidate.isPVContributor() && std::abs(candidate.dcaXY()) < cfgCutDCAxy && std::abs(candidate.dcaZ()) < cfgCutDCAz && candidate.itsNCls() > cfgITScluster)) { - return false; - } else if (!ismanualDCAcut) { - if (std::abs(candidate.pt()) < cfgCutPT) + if (selectionConfig.isGlobalTracks) { + if (!candidate.isGlobalTrackWoDCA()) + return false; + if (std::abs(candidate.pt()) < selectionConfig.cfgCutPT) + return false; + if (std::abs(candidate.eta()) > selectionConfig.cfgCutEtaMax || std::abs(candidate.eta()) < selectionConfig.cfgCutEtaMin) return false; - if (std::abs(candidate.dcaXY()) > cfgCutDCAxy) + if (!selectionConfig.isApplyPtDepDCAxyCut) { + if (std::abs(candidate.dcaXY()) > selectionConfig.cfgCutDCAxyMax || std::abs(candidate.dcaXY()) < selectionConfig.cfgCutDCAxyMin) + return false; + } else { + if (std::abs(candidate.dcaXY()) > (0.0105 + 0.035 / std::pow(candidate.pt(), 1.1))) + return false; + } + if (selectionConfig.isGoldenChi2 && candidate.passedGoldenChi2()) + return false; + if (std::abs(candidate.dcaZ()) > selectionConfig.cfgCutDCAz) + return false; + if (candidate.tpcCrossedRowsOverFindableCls() < selectionConfig.cfgRCRFC) + return false; + if (candidate.itsNCls() < selectionConfig.cfgITScluster) + return false; + if (candidate.tpcNClsFound() < selectionConfig.cfgTPCcluster) + return false; + if (candidate.itsChi2NCl() >= selectionConfig.cfgITSChi2NCl) return false; - if (std::abs(candidate.dcaZ()) > cfgCutDCAz) + if (candidate.tpcChi2NCl() >= selectionConfig.cfgTPCChi2NClMax || candidate.tpcChi2NCl() < selectionConfig.cfgTPCChi2NClMin) return false; - if (candidate.tpcCrossedRowsOverFindableCls() < cfgRCRFC) + if (selectionConfig.cfgPVContributor && !candidate.isPVContributor()) return false; - if (candidate.itsNCls() < cfgITScluster) + if (selectionConfig.cfgUseITSTPCRefit && (!(o2::aod::track::ITSrefit) || !(o2::aod::track::TPCrefit))) return false; - if (candidate.tpcNClsFound() < cfgTPCcluster) + } else if (!selectionConfig.isGlobalTracks) { + if (std::abs(candidate.pt()) < selectionConfig.cfgCutPT) return false; - if (candidate.itsChi2NCl() >= cfgITSChi2NCl) + if (std::abs(candidate.eta()) > selectionConfig.cfgCutEtaMax || std::abs(candidate.eta()) < selectionConfig.cfgCutEtaMin) return false; - if (candidate.tpcChi2NCl() >= cfgTPCChi2NCl) + if (std::abs(candidate.dcaXY()) > selectionConfig.cfgCutDCAxyMax || std::abs(candidate.dcaXY()) < selectionConfig.cfgCutDCAxyMin) return false; - if (cfgPVContributor && !candidate.isPVContributor()) + if (std::abs(candidate.dcaZ()) > selectionConfig.cfgCutDCAz) return false; - if (cfgPrimaryTrack && !candidate.isPrimaryTrack()) + if (candidate.tpcCrossedRowsOverFindableCls() < selectionConfig.cfgRCRFC) return false; - if (cfgGlobalWoDCATrack && !candidate.isGlobalTrackWoDCA()) + if (candidate.itsNCls() < selectionConfig.cfgITScluster) return false; - if (cfgGlobalTrack && !candidate.isGlobalTrack()) + if (candidate.tpcNClsFound() < selectionConfig.cfgTPCcluster) + return false; + if (candidate.itsChi2NCl() >= selectionConfig.cfgITSChi2NCl) + return false; + if (candidate.tpcChi2NCl() >= selectionConfig.cfgTPCChi2NClMax || candidate.tpcChi2NCl() < selectionConfig.cfgTPCChi2NClMin) + return false; + if (selectionConfig.cfgPVContributor && !candidate.isPVContributor()) + return false; + if (selectionConfig.cfgPrimaryTrack && !candidate.isPrimaryTrack()) return false; } @@ -266,51 +526,75 @@ struct Kstarqa { template bool selectionPID(const T& candidate, int PID) { - if (PID == 0) { + if (PID == PIDParticle::kPion) { + if (onlyTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && candidate.beta() > cBetaCutTOF) { + return true; + } + } else if (onlyTOFHIT) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < selectionConfig.nsigmaCutTOFPi && candidate.beta() > cBetaCutTOF) { + return true; + } + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { + return true; + } + } else if (onlyTPC) { + if (std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { + return true; + } + } else { + if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (selectionConfig.nsigmaCutCombinedPi * selectionConfig.nsigmaCutCombinedPi) && candidate.beta() > cBetaCutTOF) { + return true; + } + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < selectionConfig.nsigmaCutTPCPi) { + return true; + } + } + } else if (PID == PIDParticle::kKaon) { if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < nsigmaCutTOFPi && candidate.beta() > cBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && candidate.beta() > cBetaCutTOF) { return true; } } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < nsigmaCutTOFPi && candidate.beta() > cBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < selectionConfig.nsigmaCutTOFKa && candidate.beta() > cBetaCutTOF) { return true; } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < nsigmaCutTPCPi) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { return true; } } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaPi()) < nsigmaCutTPCPi) { + if (std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { return true; } } else { - if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (nsigmaCutCombined * nsigmaCutCombined) && candidate.beta() > cBetaCutTOF) { + if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (selectionConfig.nsigmaCutCombinedKa * selectionConfig.nsigmaCutCombinedKa) && candidate.beta() > cBetaCutTOF) { return true; } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < nsigmaCutTPCPi) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < selectionConfig.nsigmaCutTPCKa) { return true; } } - } else if (PID == 1) { + } else if (PID == PIDParticle::kProton) { // for proton if (onlyTOF) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < nsigmaCutTOFKa && candidate.beta() > cBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < selectionConfig.nsigmaCutTOFPr && candidate.beta() > cBetaCutTOF) { return true; } } else if (onlyTOFHIT) { - if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < nsigmaCutTOFKa && candidate.beta() > cBetaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < selectionConfig.nsigmaCutTOFPr && candidate.beta() > cBetaCutTOF) { return true; } - if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPCKa) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { return true; } } else if (onlyTPC) { - if (std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPCKa) { + if (std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { return true; } } else { - if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (nsigmaCutCombined * nsigmaCutCombined) && candidate.beta() > cBetaCutTOF) { + 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.tpcNSigmaKa()) < nsigmaCutTPCKa) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { return true; } } @@ -318,85 +602,43 @@ struct Kstarqa { return false; } - // template - // bool cMIDselectionPID(const T& candidate, int PID) - // { - // if (PID == 0) { - // if (onlyTOF) { - // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < 3.0) { - // return true; - // } - // } else if (onlyTOFHIT) { - // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPi()) < 3.0) { - // return true; - // } - // if (!candidate.hasTOF() && - // std::abs(candidate.tpcNSigmaPi()) < 3.0) { - // return true; - // } - // } else if (onlyTPC) { - // if (std::abs(candidate.tpcNSigmaPi()) < 3.0) { - // return true; - // } - // } else { - // if (candidate.hasTOF() && (candidate.tofNSigmaPi() * candidate.tofNSigmaPi() + candidate.tpcNSigmaPi() * candidate.tpcNSigmaPi()) < (3.0 * 3.0)) { - // return true; - // } - // if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPi()) < 3.0) { - // return true; - // } - // } - // } else if (PID == 1) { - // if (onlyTOF) { - // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < 3.0) { - // return true; - // } - // } else if (onlyTOFHIT) { - // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaKa()) < 3.0) { - // return true; - // } - // if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < 3.0) { - // return true; - // } - // } else if (onlyTPC) { - // if (std::abs(candidate.tpcNSigmaKa()) < 3.0) { - // return true; - // } - // } else { - // if (candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (3.0 * 3.0)) { - // return true; - // } - // if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < 3.0) { - // return true; - // } - // } - // } else if (PID == 2) { - // if (onlyTOF) { - // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < 3.0) { - // return true; - // } - // } else if (onlyTOFHIT) { - // if (candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < 3.0) { - // return true; - // } - // if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < 3.0) { - // return true; - // } - // } else if (onlyTPC) { - // if (std::abs(candidate.tpcNSigmaPr()) < 3.0) { - // return true; - // } - // } else { - // if (candidate.hasTOF() && (candidate.tofNSigmaPr() * candidate.tofNSigmaPr() + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr()) < (3.0 * 3.0)) { - // return true; - // } - // if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaPr()) < 3.0) { - // return true; - // } - // } - // } - // return false; - // } + template + bool selectionPIDNew(const T& candidate, int PID) + { + if (PID == PIDParticle::kPion) { + 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 (PID == PIDParticle::kKaon) { + 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 (PID == PIDParticle::kProton) { // for proton + if (candidate.pt() < selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr && candidate.hasTOF() && std::abs(candidate.tofNSigmaPr()) < selectionConfig.nsigmaCutTOFPr) { + return true; + } + if (candidate.pt() >= selectionConfig.lowPtCutPID && std::abs(candidate.tpcNSigmaPr()) < selectionConfig.nsigmaCutTPCPr && !candidate.hasTOF()) { + return true; + } + } + + return false; + } std::array pvec0; std::array pvec1; @@ -405,170 +647,222 @@ struct Kstarqa { // Processed events will be already fulfilling the event selection // requirements // Filter eventFilter = (o2::aod::evsel::sel8 == true); - Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutzvertex); + Filter posZFilter = (nabs(o2::aod::collision::posZ) < selectionConfig.cutzvertex); - Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); - Filter fDCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter acceptanceFilter = (nabs(aod::track::eta) < selectionConfig.cfgCutEtaMax && nabs(aod::track::pt) > selectionConfig.cfgCutPT) && (nabs(aod::track::eta) > selectionConfig.cfgCutEtaMin); + Filter fDCAcutFilter = (nabs(aod::track::dcaXY) < selectionConfig.cfgCutDCAxyMax) && (nabs(aod::track::dcaZ) < selectionConfig.cfgCutDCAz) && (nabs(aod::track::dcaXY) > selectionConfig.cfgCutDCAxyMin); - using EventCandidates = soa::Filtered>; - using TrackCandidates = soa::Filtered>; - using EventCandidatesMC = soa::Join; + using EventCandidates = soa::Filtered>; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs + using EventCandidatesMix = soa::Filtered>; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs + using TrackCandidates = soa::Filtered>; + using EventCandidatesMC = soa::Join; + // using EventCandidatesMC = soa::Filtered>; - using TrackCandidatesMC = soa::Filtered>; + using TrackCandidatesMC = soa::Filtered>; + using EventMCGenerated = soa::Join; // aod::CentNGlobals, aod::CentNTPVs, aod::CentMFTs //*********Varibles declaration*************** - TLorentzVector lv1, lv2, lv3, lv4, lv5; - float multiplicity = 0.0f; - float theta2; - ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterSelected, fourVecDau1, fourVecMother, fourVecDauCM; - ROOT::Math::XYZVector threeVecDauCM, helicityVec, randomVec, beamVec, normalVec; + float multiplicity{-1.0}, theta2; + ROOT::Math::PxPyPzMVector daughter1, daughter2, daughterRot, mother, motherRot, daughterSelected, fourVecDauCM, daughterRotCM; + ROOT::Math::XYZVector randomVec, beamVec, normalVec; bool isMix = false; - template - void fillInvMass(const T1& track1, const T2& track2, const T3& lv2, const T4& lv3, float multiplicity, bool isMix) + template + void fillInvMass(const T1& daughter1, const T1& daughter2, const T1& mother, float multiplicity, bool isMix, const T2& track1, const T2& track2) { - daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); // Kaon - daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); // Pion - daughterSelected = (boostDaugter1) ? daughter1 : daughter2; - auto selectedDauMass = (boostDaugter1) ? massKa : massPi; - - // polarization calculations - - fourVecDau1 = ROOT::Math::PxPyPzMVector(daughterSelected.Px(), daughterSelected.Py(), daughterSelected.Pz(), selectedDauMass); // Kaon or Pion - - fourVecMother = ROOT::Math::PxPyPzMVector(lv3.Px(), lv3.Py(), lv3.Pz(), lv3.M()); // mass of KshortKshort pair - ROOT::Math::Boost boost{fourVecMother.BoostToCM()}; // boost mother to center of mass frame - fourVecDauCM = boost(fourVecDau1); // boost the frame of daughter same as mother - threeVecDauCM = fourVecDauCM.Vect(); // get the 3 vector of daughter in the frame of mother - - if (std::abs(lv3.Rapidity()) < 0.5) { - if (activateTHnSparseCosThStarHelicity) { - helicityVec = fourVecMother.Vect(); // 3 vector of mother in COM frame - auto cosThetaStarHelicity = helicityVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(helicityVec.Mag2())); - - if (track1.sign() * track2.sign() < 0) { - if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); - - for (int i = 0; i < cRotations; i++) { - theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / rotationalCut, o2::constants::math::PI + o2::constants::math::PI / rotationalCut); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; - if (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarHelicity); - } - } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + daughterSelected = (boostDaugter1) ? daughter1 : daughter2; // polarization calculations + ROOT::Math::Boost boost{mother.BoostToCM()}; // boost mother to center of mass frame + fourVecDauCM = boost(daughterSelected); // boost the frame of daughter same as mother + + // if (std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + if (activateTHnSparseCosThStarHelicity) { + auto cosThetaStarHelicity = mother.Vect().Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(mother.Vect().Mag2())); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + if (std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); } - } else { - if (!isMix) { - if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarHelicity); + + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / selectionConfig.rotationalCut, o2::constants::math::PI + o2::constants::math::PI / selectionConfig.rotationalCut); + + 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; + + ROOT::Math::Boost boost2{motherRot.BoostToCM()}; + daughterRotCM = boost2(daughterRot); + + auto cosThetaStarHelicityRot = motherRot.Vect().Dot(daughterRotCM.Vect()) / (std::sqrt(daughterRotCM.Vect().Mag2()) * std::sqrt(motherRot.Vect().Mag2())); + + if (calcRotational && motherRot.Rapidity() < selectionConfig.rapidityMotherData) + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarHelicityRot); } + } else if (isMix && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); } + } else { + if (!isMix) { + if (calcLikeSign && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + if (track1.sign() > 0 && track2.sign() > 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); + } else if (track1.sign() < 0 && track2.sign() < 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarHelicity); + } + } + } + } - } else if (activateTHnSparseCosThStarProduction) { - normalVec = ROOT::Math::XYZVector(lv3.Py(), -lv3.Px(), 0.f); - auto cosThetaStarProduction = normalVec.Dot(threeVecDauCM) / (std::sqrt(threeVecDauCM.Mag2()) * std::sqrt(normalVec.Mag2())); + } else if (activateTHnSparseCosThStarProduction) { + normalVec = ROOT::Math::XYZVector(mother.Py(), -mother.Px(), 0.f); + auto cosThetaStarProduction = normalVec.Dot(fourVecDauCM.Vect()) / (std::sqrt(fourVecDauCM.Vect().Mag2()) * std::sqrt(normalVec.Mag2())); - if (track1.sign() * track2.sign() < 0) { - if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); - for (int i = 0; i < cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; - if (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarProduction); - } - } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + if (std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); } - } else { - if (!isMix) { - if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarProduction); + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(0, o2::constants::math::PI); + 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; + if (calcRotational && std::abs(motherRot.Rapidity()) < selectionConfig.rapidityMotherData) + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarProduction); } + } else if (isMix && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); } - } else if (activateTHnSparseCosThStarBeam) { - beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); - auto cosThetaStarBeam = beamVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - - if (track1.sign() * track2.sign() < 0) { - if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); - for (int i = 0; i < cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; - if (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarBeam); + } else { + if (!isMix) { + if (calcLikeSign && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + if (track1.sign() > 0 && track2.sign() > 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); + } else if (track1.sign() < 0 && track2.sign() < 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarProduction); } - } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); } - } else { - if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarBeam); - } - } else if (activateTHnSparseCosThStarRandom) { - auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); - auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); - - randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); - auto cosThetaStarRandom = randomVec.Dot(threeVecDauCM) / std::sqrt(threeVecDauCM.Mag2()); - - if (track1.sign() * track2.sign() < 0) { - if (!isMix) { - hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); - for (int i = 0; i < cRotations; i++) { - theta2 = rn->Uniform(0, o2::constants::math::PI); - lv4.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi() + theta2, massKa); // for rotated background - lv5 = lv2 + lv4; - if (calcRotational) - hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, lv5.Pt(), lv5.M(), cosThetaStarRandom); - } - } else { - hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + } + } + } else if (activateTHnSparseCosThStarBeam) { + beamVec = ROOT::Math::XYZVector(0.f, 0.f, 1.f); + auto cosThetaStarBeam = beamVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + if (std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); } - } else { - if (!isMix) { - if (calcLikeSign) - hInvMass.fill(HIST("h3KstarInvMasslikeSign"), multiplicity, lv3.Pt(), lv3.M(), cosThetaStarRandom); + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(0, o2::constants::math::PI); + 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; + if (calcRotational && std::abs(motherRot.Rapidity()) < selectionConfig.rapidityMotherData) + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarBeam); + } + } else if (isMix && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); + } + } else { + if (calcLikeSign && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + if (track1.sign() > 0 && track2.sign() > 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); + } else if (track1.sign() < 0 && track2.sign() < 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarBeam); + } + } + } + } else if (activateTHnSparseCosThStarRandom) { + auto phiRandom = gRandom->Uniform(0.f, constants::math::TwoPI); + auto thetaRandom = gRandom->Uniform(0.f, constants::math::PI); + + randomVec = ROOT::Math::XYZVector(std::sin(thetaRandom) * std::cos(phiRandom), std::sin(thetaRandom) * std::sin(phiRandom), std::cos(thetaRandom)); + auto cosThetaStarRandom = randomVec.Dot(fourVecDauCM.Vect()) / std::sqrt(fourVecDauCM.Vect().Mag2()); + + if (track1.sign() * track2.sign() < 0) { + if (!isMix) { + if (std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassUnlikeSign"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + } + for (int i = 0; i < cRotations; i++) { + theta2 = rn->Uniform(0, o2::constants::math::PI); + 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; + if (calcRotational && std::abs(motherRot.Rapidity()) < selectionConfig.rapidityMotherData) + hInvMass.fill(HIST("h3KstarInvMassRotated"), multiplicity, motherRot.Pt(), motherRot.M(), cosThetaStarRandom); + } + } else if (isMix && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + hInvMass.fill(HIST("h3KstarInvMassMixed"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + } + } else { + if (!isMix) { + if (calcLikeSign && std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + if (track1.sign() > 0 && track2.sign() > 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignPP"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + } else if (track1.sign() < 0 && track2.sign() < 0) { + hInvMass.fill(HIST("h3KstarInvMasslikeSignMM"), multiplicity, mother.Pt(), mother.M(), cosThetaStarRandom); + } } } } } + // } } // int counter = 0; - void processSE(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { - rEventSelection.fill(HIST("events_check_data"), 0.5); - if (cTVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { - return; - } - rEventSelection.fill(HIST("events_check_data"), 1.5); + // if (cTVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { + // return; + // } + + // if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + // return; + // } + + // if (!collision.sel8()) { + // return; + // } + int occupancy = collision.trackOccupancyInTimeRange(); + rEventSelection.fill(HIST("hOccupancy"), occupancy); - if (timFrameEvsel && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + if (!selectionEvent(collision, true)) { return; } - rEventSelection.fill(HIST("events_check_data"), 2.5); - if (!collision.sel8()) { - return; + multiplicity = -1; + + 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 } - rEventSelection.fill(HIST("events_check_data"), 3.5); - multiplicity = collision.centFT0M(); + /* else if (cSelectMultEstimator == 4) { + multiplicity = collision.centMFT(); + } */ + /* else if (cSelectMultEstimator == 5) { + multiplicity = collision.centNGlobal(); + } */ + /* else if (cSelectMultEstimator == 6) { + multiplicity = collision.centNTPV(); + } */ // Fill the event counter if (cQAevents) { rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - rEventSelection.fill(HIST("hmult"), multiplicity); + rEventSelection.fill(HIST("hMultiplicity"), multiplicity); rEventSelection.fill(HIST("multdist_FT0M"), collision.multFT0M()); // rEventSelection.fill(HIST("multdist_FT0A"), collision.multFT0A()); // rEventSelection.fill(HIST("multdist_FT0C"), collision.multFT0C()); @@ -576,6 +870,18 @@ struct Kstarqa { } for (const auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + rEventSelection.fill(HIST("tracksCheckData"), 0.5); + if (!selectionTrack(track1)) { + continue; + } + if (!selectionTrack(track2)) { + continue; + } + rEventSelection.fill(HIST("tracksCheckData"), 1.5); + + if (track1.globalIndex() == track2.globalIndex()) + continue; + if (cQAplots) { hPID.fill(HIST("Before/hNsigmaTPC_Ka_before"), track1.pt(), track1.tpcNSigmaKa()); hPID.fill(HIST("Before/hNsigmaTOF_Ka_before"), track1.pt(), track1.tofNSigmaKa()); @@ -583,27 +889,28 @@ struct Kstarqa { hPID.fill(HIST("Before/hNsigmaTOF_Pi_before"), track2.pt(), track2.tofNSigmaPi()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); hPID.fill(HIST("Before/hNsigma_TPC_TOF_Pi_before"), track2.tpcNSigmaPi(), track2.tofNSigmaPi()); - hPID.fill(HIST("h1PID_TPC_kaon_data"), track1.tpcNSigmaKa()); - hPID.fill(HIST("h1PID_TPC_pion_data"), track2.tpcNSigmaPi()); - hPID.fill(HIST("h1PID_TOF_kaon_data"), track1.tofNSigmaKa()); - hPID.fill(HIST("h1PID_TOF_pion_data"), track2.tofNSigmaPi()); + + hPID.fill(HIST("Before/hTPCnsigKa_mult_pt"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("Before/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); + hPID.fill(HIST("Before/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("Before/hTOFnsigPi_mult_pt"), track2.tofNSigmaKa(), multiplicity, track2.pt()); hOthers.fill(HIST("hCRFC_before"), track1.tpcCrossedRowsOverFindableCls()); hOthers.fill(HIST("dE_by_dx_TPC"), track1.p(), track1.tpcSignal()); hOthers.fill(HIST("hphi"), track1.phi()); - } - rEventSelection.fill(HIST("events_check_data"), 4.5); - if (!selectionTrack(track1)) { - continue; - } - if (!selectionTrack(track2)) { - continue; + if (track1.sign() < 0) { + hPID.fill(HIST("Before/h1PID_TPC_neg_kaon"), track1.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TPC_neg_pion"), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_neg_kaon"), track1.tofNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_neg_pion"), track2.tofNSigmaPi()); + } else { + hPID.fill(HIST("Before/h1PID_TPC_pos_kaon"), track1.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TPC_pos_pion"), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_pos_kaon"), track1.tofNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_pos_pion"), track2.tofNSigmaPi()); + } } - rEventSelection.fill(HIST("events_check_data"), 5.5); - // if (counter < 1e4) - // std::cout << "TOF beta value is " << track1.beta() << std::endl; - // counter++; if (cQAevents) { rEventSelection.fill(HIST("hDcaxy"), track1.dcaXY()); @@ -611,30 +918,54 @@ 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 (!selectionPID(track1, 1)) // Track 1 is checked with Kaon + if (!applypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon continue; - if (!selectionPID(track2, 0)) // Track 2 is checked with Pion + if (!applypTdepPID && !selectionPID(track2, 0)) // Track 2 is checked with Pion continue; - rEventSelection.fill(HIST("events_check_data"), 6.5); + if (applypTdepPID && !selectionPIDNew(track1, 1)) // Track 1 is checked with Kaon + continue; + if (applypTdepPID && !selectionPIDNew(track2, 0)) // Track 2 is checked with Pion + continue; + + rEventSelection.fill(HIST("tracksCheckData"), 2.5); if (cFakeTrack && isFakeTrack(track1, 1)) // Kaon continue; if (cFakeTrack && isFakeTrack(track2, 0)) // Pion continue; + rEventSelection.fill(HIST("tracksCheckData"), 3.5); - // if (cMID) { - // if (cMIDselectionPID(track1, 0)) // Kaon misidentified as pion - // continue; - // if (cMIDselectionPID(track1, 2)) // Kaon misidentified as proton - // continue; - // if (cMIDselectionPID(track2, 1)) // Pion misidentified as kaon - // continue; - // } + if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) + continue; - rEventSelection.fill(HIST("events_check_data"), 7.5); + if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > selectionConfig.ctrackRapidity) + continue; + rEventSelection.fill(HIST("tracksCheckData"), 4.5); + + if (selectionConfig.isApplyParticleMID) { + if (selectionPID(track1, 0)) // Kaon misidentified as pion + continue; + if (selectionPID(track1, 2)) // Kaon misidentified as proton + continue; + if (selectionPID(track2, 1)) // Pion misidentified as kaon + continue; + if (selectionPID(track2, 2)) // Pion misidentified as proton + continue; + } + + rEventSelection.fill(HIST("tracksCheckData"), 5.5); if (cQAplots) { + hPID.fill(HIST("After/hDcaxyPi"), track2.dcaXY()); + hPID.fill(HIST("After/hDcaxyKa"), track1.dcaXY()); + hPID.fill(HIST("After/hDcazPi"), track2.dcaZ()); + hPID.fill(HIST("After/hDcazKa"), track1.dcaZ()); + + hPID.fill(HIST("After/hTPCnsigKa_mult_pt"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("After/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); + hPID.fill(HIST("After/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("After/hTOFnsigPi_mult_pt"), track2.tofNSigmaKa(), multiplicity, track2.pt()); hOthers.fill(HIST("hEta_after"), track1.eta()); hOthers.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); hPID.fill(HIST("After/hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); @@ -645,17 +976,24 @@ struct Kstarqa { hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_after"), track2.tpcNSigmaPi(), track2.tofNSigmaPi()); } - if (track1.globalIndex() == track2.globalIndex()) - continue; + rEventSelection.fill(HIST("tracksCheckData"), 6.5); + + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); + mother = daughter1 + daughter2; // Kstar meson + + if (selectionConfig.isApplyCutsOnMother) { + if (mother.Pt() >= selectionConfig.cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (mother.M() >= selectionConfig.cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } - rEventSelection.fill(HIST("events_check_data"), 8.5); + hOthers.fill(HIST("hKstar_Rap"), mother.Rapidity()); + hOthers.fill(HIST("hKstar_Eta"), mother.Eta()); - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(track1.pt(), track1.eta(), track1.phi(), massKa); - lv2.SetPtEtaPhiM(track2.pt(), track2.eta(), track2.phi(), massPi); - lv3 = lv1 + lv2; isMix = false; - fillInvMass(track1, track2, lv2, lv3, multiplicity, isMix); + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, track1, track2); } } @@ -666,144 +1004,478 @@ struct Kstarqa { ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "TPC multiplicity axis for ME mixing"}; // using BinningTypeTPCMultiplicity = ColumnBinningPolicy; - // using BinningTypeCentralityM = ColumnBinningPolicy; + using BinningTypeCentralityM = ColumnBinningPolicy; using BinningTypeVertexContributor = ColumnBinningPolicy; + using BinningTypeFT0A = ColumnBinningPolicy; + using BinningTypeFV0A = ColumnBinningPolicy; + + using BinningTypeMCFT0M = ColumnBinningPolicy; + using BinningTypeMCFT0A = ColumnBinningPolicy; + using BinningTypeMCFT0C = ColumnBinningPolicy; + using BinningTypeMCFV0A = ColumnBinningPolicy; BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicity}, true}; - // BinningTypeCentralityM binningOnCentrality{{axisVertex, axisMultiplicity}, true}; + BinningTypeCentralityM binningOnCentrality{{axisVertex, axisMultiplicity}, true}; + BinningTypeFT0A binningOnFT0A{{axisVertex, axisMultiplicity}, true}; + BinningTypeFV0A binningOnFV0A{{axisVertex, axisMultiplicity}, true}; + + BinningTypeMCFT0M binningOnMCFT0M{{axisVertex, axisMultiplicity}, true}; + BinningTypeMCFT0A binningOnMCFT0A{{axisVertex, axisMultiplicity}, true}; + BinningTypeMCFT0C binningOnMCFT0C{{axisVertex, axisMultiplicity}, true}; + BinningTypeMCFV0A binningOnMCFV0A{{axisVertex, axisMultiplicity}, true}; + + SameKindPair pair1{binningOnPositions, selectionConfig.cfgNoMixedEvents, -1, &cache}; + SameKindPair pair2{binningOnCentrality, selectionConfig.cfgNoMixedEvents, -1, &cache}; + SameKindPair pair3{binningOnFT0A, selectionConfig.cfgNoMixedEvents, -1, &cache}; + SameKindPair pair4{binningOnFV0A, selectionConfig.cfgNoMixedEvents, -1, &cache}; + + SameKindPair pairmc1{binningOnMCFT0M, selectionConfig.cfgNoMixedEvents, -1, &cache}; + SameKindPair pairmc2{binningOnMCFT0C, selectionConfig.cfgNoMixedEvents, -1, &cache}; + SameKindPair pairmc3{binningOnMCFT0A, selectionConfig.cfgNoMixedEvents, -1, &cache}; + SameKindPair pairmc4{binningOnMCFV0A, selectionConfig.cfgNoMixedEvents, -1, &cache}; + + void processME(EventCandidatesMix const&, TrackCandidates const&) + { + // Map estimator to pair and multiplicity accessor + auto runMixing = [&](auto& pair, auto multiplicityGetter) { + for (const auto& [c1, tracks1, c2, tracks2] : pair) { + // if (!c1.sel8() || !c2.sel8()) + // continue; + + if (!selectionEvent(c1, false) || !selectionEvent(c2, false)) { + continue; + } + + multiplicity = multiplicityGetter(c1); + + 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)) + continue; + + if (std::abs(t1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) + continue; + + if (std::abs(t2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > selectionConfig.ctrackRapidity) + continue; - SameKindPair pair1{binningOnPositions, cfgNoMixedEvents, -1, &cache}; - // SameKindPair pair2{binningOnCentrality, cfgNoMixedEvents, -1, &cache}; + if (cFakeTrack && isFakeTrack(t1, 1)) // Kaon + continue; + if (cFakeTrack && isFakeTrack(t2, 0)) // Pion + continue; - void processME(EventCandidates const&, TrackCandidates const&) + if (selectionConfig.isApplyParticleMID) { + if (selectionPID(t1, 0)) // Kaon misidentified as pion + continue; + if (selectionPID(t1, 2)) // Kaon misidentified as proton + continue; + if (selectionPID(t2, 1)) // Pion misidentified as kaon + continue; + if (selectionPID(t2, 2)) // Pion misidentified as proton + continue; + } + + daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massPi); + mother = daughter1 + daughter2; + + isMix = true; + + if (std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, t1, t2); + } + } + } + }; + + // Call mixing based on selected estimator + if (cSelectMultEstimator == kFT0M) { + runMixing(pair1, [](const auto& c) { return c.centFT0M(); }); + } else if (cSelectMultEstimator == kFT0A) { + runMixing(pair2, [](const auto& c) { return c.centFT0A(); }); + } else if (cSelectMultEstimator == kFT0C) { + runMixing(pair3, [](const auto& c) { return c.centFT0C(); }); + } else if (cSelectMultEstimator == kFV0A) { + runMixing(pair4, [](const auto& c) { return c.centFV0A(); }); + } + } + PROCESS_SWITCH(Kstarqa, processME, "Process Mixed event", true); + + void processMEMC(EventCandidatesMC const&, TrackCandidatesMC const&, aod::McParticles const&, aod::McCollisions const&) { - for (const auto& [c1, tracks1, c2, tracks2] : pair1) { + auto runMixing = [&](auto& pair, auto multiplicityGetter) { + for (const auto& [c1, tracks1, c2, tracks2] : pair) { + + if (!selectionEvent(c1, false) || !selectionEvent(c2, false)) { + continue; + } + + if (!c1.has_mcCollision() || !c2.has_mcCollision()) { + continue; // skip if no MC collision associated + } + + multiplicity = multiplicityGetter(c1); + // multiplicity = c1.centFT0M(); // default, can be changed later + + 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)) + continue; + + if (!t1.has_mcParticle() || !t2.has_mcParticle()) { + continue; // skip if no MC particle associated + } + + if (std::abs(t1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) + continue; + + if (std::abs(t2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > selectionConfig.ctrackRapidity) + continue; + + const auto mctrack1 = t1.mcParticle(); + const auto mctrack2 = t2.mcParticle(); + + if (!mctrack1.isPhysicalPrimary()) { + continue; + } + + if (!mctrack2.isPhysicalPrimary()) { + continue; + } + + daughter1 = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massPi); + mother = daughter1 + daughter2; + + isMix = true; + + if (std::abs(mother.Rapidity()) < selectionConfig.rapidityMotherData) { + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, t1, t2); + } + } + } + }; + // Call mixing based on selected estimator + if (cSelectMultEstimator == kFT0M) { + runMixing(pairmc1, [](const auto& c) { return c.centFT0M(); }); + } else if (cSelectMultEstimator == kFT0A) { + runMixing(pairmc2, [](const auto& c) { return c.centFT0A(); }); + } else if (cSelectMultEstimator == kFT0C) { + runMixing(pairmc3, [](const auto& c) { return c.centFT0C(); }); + } else if (cSelectMultEstimator == kFV0A) { + runMixing(pairmc4, [](const auto& c) { return c.centFV0A(); }); + } + } + PROCESS_SWITCH(Kstarqa, processMEMC, "Process mixed-event in MC", true); + + void processSEMC(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&, aod::McCollisions const& /*mcCollisions*/) + { + auto oldindex = -999; + if (!collision.has_mcCollision()) { + return; + } + int occupancy = collision.trackOccupancyInTimeRange(); + rEventSelection.fill(HIST("hOccupancy"), occupancy); + + if (!selectionEvent(collision, false)) { + return; + } - if (!c1.sel8()) { + multiplicity = -1; + + 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 + } + + // Fill the event counter + if (cQAevents) { + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + rEventSelection.fill(HIST("hMultiplicity"), multiplicity); + rEventSelection.fill(HIST("multdist_FT0M"), collision.multFT0M()); + // rEventSelection.fill(HIST("multdist_FT0A"), collision.multFT0A()); + // rEventSelection.fill(HIST("multdist_FT0C"), collision.multFT0C()); + // rEventSelection.fill(HIST("hNcontributor"), collision.numContrib()); + } + + for (const auto& [track1, track2] : combinations(CombinationsFullIndexPolicy(tracks, tracks))) { + rEventSelection.fill(HIST("tracksCheckData"), 0.5); + if (!selectionTrack(track1)) { continue; } - if (!c2.sel8()) { + if (!selectionTrack(track2)) { continue; } - if (timFrameEvsel && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + const auto mctrack1 = track1.mcParticle(); + const auto mctrack2 = track2.mcParticle(); + + if (!track1.has_mcParticle() || !track2.has_mcParticle()) { + continue; // skip if no MC particle associated + } + + if (!mctrack1.isPhysicalPrimary()) { continue; } - if (cTVXEvsel && (!c1.selection_bit(aod::evsel::kIsTriggerTVX) || !c2.selection_bit(aod::evsel::kIsTriggerTVX))) { - return; + if (!mctrack2.isPhysicalPrimary()) { + continue; } + rEventSelection.fill(HIST("tracksCheckData"), 1.5); - multiplicity = c1.centFT0M(); + if (cQAplots) { + hPID.fill(HIST("Before/hNsigmaTPC_Ka_before"), track1.pt(), track1.tpcNSigmaKa()); + hPID.fill(HIST("Before/hNsigmaTOF_Ka_before"), track1.pt(), track1.tofNSigmaKa()); + hPID.fill(HIST("Before/hNsigmaTPC_Pi_before"), track2.pt(), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/hNsigmaTOF_Pi_before"), track2.pt(), track2.tofNSigmaPi()); + hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); + hPID.fill(HIST("Before/hNsigma_TPC_TOF_Pi_before"), track2.tpcNSigmaPi(), track2.tofNSigmaPi()); - for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + hPID.fill(HIST("Before/hTPCnsigKa_mult_pt"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("Before/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); + hPID.fill(HIST("Before/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("Before/hTOFnsigPi_mult_pt"), track2.tofNSigmaKa(), multiplicity, track2.pt()); - if (!selectionTrack(t1)) // Kaon - continue; - if (!selectionTrack(t2)) // Pion - continue; - if (!selectionPID(t1, 1)) // Kaon - continue; - if (!selectionPID(t2, 0)) // Pion - continue; + hOthers.fill(HIST("hCRFC_before"), track1.tpcCrossedRowsOverFindableCls()); + hOthers.fill(HIST("dE_by_dx_TPC"), track1.p(), track1.tpcSignal()); + hOthers.fill(HIST("hphi"), track1.phi()); - // if (cMID) { - // if (cMIDselectionPID(t1, 0)) // misidentified as pion - // continue; - // if (cMIDselectionPID(t1, 2)) // misidentified as proton - // continue; - // if (cMIDselectionPID(t2, 1)) // misidentified as kaon - // continue; - // } + if (track1.sign() < 0) { + hPID.fill(HIST("Before/h1PID_TPC_neg_kaon"), track1.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TPC_neg_pion"), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_neg_kaon"), track1.tofNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_neg_pion"), track2.tofNSigmaPi()); + } else { + hPID.fill(HIST("Before/h1PID_TPC_pos_kaon"), track1.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TPC_pos_pion"), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_pos_kaon"), track1.tofNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_pos_pion"), track2.tofNSigmaPi()); + } + } + + if (cQAevents) { + rEventSelection.fill(HIST("hDcaxy"), track1.dcaXY()); + rEventSelection.fill(HIST("hDcaz"), track1.dcaZ()); + } + + // since we are using combinations full index policy, so repeated pairs are allowed, so we can check one with Kaon and other with pion + if (!applypTdepPID && !selectionPID(track1, 1)) // Track 1 is checked with Kaon + continue; + if (!applypTdepPID && !selectionPID(track2, 0)) // Track 2 is checked with Pion + continue; + rEventSelection.fill(HIST("tracksCheckData"), 2.5); + + if (applypTdepPID && !selectionPIDNew(track1, 1)) // Track 1 is checked with Kaon + continue; + if (applypTdepPID && !selectionPIDNew(track2, 0)) // Track 2 is checked with Pion + continue; + rEventSelection.fill(HIST("tracksCheckData"), 3.5); + + if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) + continue; + + if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > selectionConfig.ctrackRapidity) + continue; + rEventSelection.fill(HIST("tracksCheckData"), 4.5); + + // if (cFakeTrack && isFakeTrack(track1, 1)) // Kaon + // continue; + // if (cFakeTrack && isFakeTrack(track2, 0)) // Pion + // continue; + rEventSelection.fill(HIST("tracksCheckData"), 5.5); + + if (cQAplots) { + hPID.fill(HIST("After/hDcaxyPi"), track2.dcaXY()); + hPID.fill(HIST("After/hDcaxyKa"), track1.dcaXY()); + hPID.fill(HIST("After/hDcazPi"), track2.dcaZ()); + hPID.fill(HIST("After/hDcazKa"), track1.dcaZ()); + + hPID.fill(HIST("After/hTPCnsigKa_mult_pt"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("After/hTPCnsigPi_mult_pt"), track2.tpcNSigmaPi(), multiplicity, track2.pt()); + hPID.fill(HIST("After/hTOFnsigKa_mult_pt"), track1.tofNSigmaKa(), multiplicity, track1.pt()); + hPID.fill(HIST("After/hTOFnsigPi_mult_pt"), track2.tofNSigmaKa(), multiplicity, track2.pt()); + hOthers.fill(HIST("hEta_after"), track1.eta()); + hOthers.fill(HIST("hCRFC_after"), track1.tpcCrossedRowsOverFindableCls()); + hPID.fill(HIST("After/hNsigmaKaonTPC_after"), track1.pt(), track1.tpcNSigmaKa()); + hPID.fill(HIST("After/hNsigmaKaonTOF_after"), track1.pt(), track1.tofNSigmaKa()); + hPID.fill(HIST("After/hNsigmaPionTPC_after"), track2.pt(), track2.tpcNSigmaPi()); + hPID.fill(HIST("After/hNsigmaPionTOF_after"), track2.pt(), track2.tofNSigmaPi()); + hPID.fill(HIST("After/hNsigma_TPC_TOF_Ka_after"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); + hPID.fill(HIST("After/hNsigma_TPC_TOF_Pi_after"), track2.tpcNSigmaPi(), track2.tofNSigmaPi()); + } - // TLorentzVector vKAON; - // vKAON.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); - // TLorentzVector vPION; - // vPION.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massPi); - lv3.SetPtEtaPhiM(0.0, 0.0, 0.0, 0.0); - lv1.SetPtEtaPhiM(t1.pt(), t1.eta(), t1.phi(), massKa); - lv2.SetPtEtaPhiM(t2.pt(), t2.eta(), t2.phi(), massPi); + if (track1.globalIndex() == track2.globalIndex()) + continue; - // TLorentzVector kstar = vKAON + vPION; - lv3 = lv1 + lv2; - isMix = true; + rEventSelection.fill(HIST("tracksCheckData"), 6.5); - // if (std::abs(kstar.Rapidity()) < 0.5) { - // fillInvMass(t1, t2, vPION, kstar, multiplicity, isMix); + for (const auto& mothertrack1 : mctrack1.mothers_as()) { + for (const auto& mothertrack2 : mctrack2.mothers_as()) { + + if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) { + continue; + } - if (std::abs(lv3.Rapidity()) < 0.5) { - fillInvMass(t1, t2, lv2, lv3, multiplicity, isMix); + if (!mothertrack1.producedByGenerator()) { + continue; + } + + if (selectionConfig.isApplyCutsOnMother) { + if (mothertrack1.pt() >= selectionConfig.cMaxPtMotherCut) // excluding candidates in overflow + continue; + if ((std::sqrt(mothertrack1.e() * mothertrack1.e() - mothertrack1.p() * mothertrack1.p())) >= selectionConfig.cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + + if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { + continue; + } + rEventSelection.fill(HIST("recMCparticles"), 11.5); + + oldindex = mothertrack1.globalIndex(); + + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); + mother = daughter1 + daughter2; // Kstar meson + + if (selectionConfig.isApplyCutsOnMother) { + if (mother.Pt() >= selectionConfig.cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (mother.M() >= selectionConfig.cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + + hOthers.fill(HIST("hKstar_Rap"), mother.Rapidity()); + hOthers.fill(HIST("hKstar_Eta"), mother.Eta()); + + isMix = false; + fillInvMass(daughter1, daughter2, mother, multiplicity, isMix, track1, track2); } } } } + PROCESS_SWITCH(Kstarqa, processSEMC, "Process same event in MC", true); - PROCESS_SWITCH(Kstarqa, processME, "Process Mixed event", true); + Service pdgDB; + // void processGen(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) void processGen(aod::McCollision const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& collisions) { - rEventSelection.fill(HIST("events_check"), 0.5); - if (std::abs(mcCollision.posZ()) < cutzvertex) { - rEventSelection.fill(HIST("events_check"), 1.5); - } + rEventSelection.fill(HIST("eventsCheckGen"), 0.5); int nChInel = 0; for (const auto& mcParticle : mcParticles) { auto pdgcode = std::abs(mcParticle.pdgCode()); - if (mcParticle.isPhysicalPrimary() && (pdgcode == 211 || pdgcode == 321 || pdgcode == 2212 || pdgcode == 11 || pdgcode == 13)) { + if (mcParticle.isPhysicalPrimary() && (pdgcode == PDG_t::kPiPlus || pdgcode == PDG_t::kKPlus || pdgcode == PDG_t::kProton || pdgcode == std::abs(PDG_t::kElectron) || pdgcode == std::abs(PDG_t::kMuonMinus))) { if (std::abs(mcParticle.eta()) < 1.0) { nChInel = nChInel + 1; } } } - if (nChInel > 0 && std::abs(mcCollision.posZ()) < cutzvertex) - rEventSelection.fill(HIST("events_check"), 2.5); + if (nChInel > 0 && std::abs(mcCollision.posZ()) < selectionConfig.cutzvertex) + rEventSelection.fill(HIST("eventsCheckGen"), 1.5); std::vector selectedEvents(collisions.size()); int nevts = 0; + multiplicity = -1.0; + // float impactParameter = mcCollision.impactParameter(); - multiplicity = 0; - for (const auto& collision : collisions) { - // if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > cutzvertex) { - if (std::abs(collision.mcCollision().posZ()) > cutzvertex) { - continue; - } + bool isINELgt0true = false; - if (timFrameEvsel && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { - continue; - } - if (cTVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { + if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + isINELgt0true = true; + } + if (selectionConfig.isINELgt0 && !isINELgt0true) { + return; + } + + // if (selectionConfig.isINELgt0 && !mcCollision.isInelGt0()) { + // return; + // } + rEventSelection.fill(HIST("eventsCheckGen"), 2.5); + + for (const auto& collision : collisions) { + // if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > selectionConfig.cutzvertex) { + // if (std::abs(collision.mcCollision().posZ()) > selectionConfig.cutzvertex) { + // continue; + // } + // if (!collision.sel8()) { + // continue; + // } + // if (selectionConfig.isNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + // continue; + // } + // if (selectionConfig.isTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + // continue; + // } + // if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { + // continue; + // } + // if (selectionConfig.isNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + // continue; + // } + // if (selectionConfig.isGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + // continue; + // } + if (!selectionEvent(collision, true)) { continue; } multiplicity = collision.centFT0M(); + hInvMass.fill(HIST("h1GenMult"), multiplicity); + + int occupancy = collision.trackOccupancyInTimeRange(); + rEventSelection.fill(HIST("hOccupancy"), occupancy); + selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); } selectedEvents.resize(nevts); - rEventSelection.fill(HIST("events_check"), 3.5); - const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); + for (const auto& mcParticle : mcParticles) { + if (std::abs(mcParticle.y()) < selectionConfig.rapidityMotherData && std::abs(mcParticle.pdgCode()) == o2::constants::physics::kK0Star892) { + hInvMass.fill(HIST("hAllKstarGenCollisisons"), multiplicity, mcParticle.pt()); + } + } + const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); + hInvMass.fill(HIST("hAllGenCollisions"), multiplicity); if (!cAllGenCollisions && !evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; } - rEventSelection.fill(HIST("events_check"), 4.5); + hInvMass.fill(HIST("hAllGenCollisions1Rec"), multiplicity); + rEventSelection.fill(HIST("eventsCheckGen"), 3.5); for (const auto& mcParticle : mcParticles) { - if (std::abs(mcParticle.y()) >= 0.5) { + + if (std::abs(mcParticle.y()) >= selectionConfig.rapidityMotherData) { continue; } - rEventSelection.fill(HIST("events_check"), 5.5); - if (std::abs(mcParticle.pdgCode()) != 313) { + if (selectionConfig.isApplyCutsOnMother) { + if (mcParticle.pt() >= selectionConfig.cMaxPtMotherCut) // excluding candidates in overflow + continue; + if ((std::sqrt(mcParticle.e() * mcParticle.e() - mcParticle.p() * mcParticle.p())) >= selectionConfig.cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + + if (std::abs(mcParticle.pdgCode()) != o2::constants::physics::kK0Star892) { continue; } - rEventSelection.fill(HIST("events_check"), 6.5); + hInvMass.fill(HIST("hAllKstarGenCollisisons1Rec"), multiplicity, mcParticle.pt()); auto kDaughters = mcParticle.daughters_as(); - if (kDaughters.size() != 2) { + if (kDaughters.size() != selectionConfig.noOfDaughters) { continue; } - rEventSelection.fill(HIST("events_check"), 7.5); auto passkaon = false; auto passpion = false; @@ -811,187 +1483,282 @@ struct Kstarqa { if (!kCurrentDaughter.isPhysicalPrimary()) { continue; } - rEventSelection.fill(HIST("events_check"), 8.5); - if (std::abs(kCurrentDaughter.pdgCode()) == 321) { - // if (kCurrentDaughter.pdgCode() == +321) { + if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { passkaon = true; - rEventSelection.fill(HIST("events_check"), 9.5); + daughter1 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); - } else if (std::abs(kCurrentDaughter.pdgCode()) == 211) { - //} else if (kCurrentDaughter.pdgCode() == -321) { + } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kPiPlus) { passpion = true; - // rEventSelection.fill(HIST("events_check"), 10.5); + daughter2 = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massPi); } } if (passkaon && passpion) { - // if (mcParticle.pdgCode() > 0) + mother = daughter1 + daughter2; // Kstar meson hInvMass.fill(HIST("hk892GenpT"), mcParticle.pt(), multiplicity); - // else - // hInvMass.fill(HIST("hk892GenpTAnti"), mcParticle.pt()); + hInvMass.fill(HIST("hk892GenpT2"), mother.Pt(), multiplicity); + hInvMass.fill(HIST("h1genmass"), mother.M()); } } } PROCESS_SWITCH(Kstarqa, processGen, "Process Generated", false); - void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&, aod::McCollisions const& /*mcCollisions*/) + // void processEvtLossSigLossMC(EventMCGenerated::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) + void processEvtLossSigLossMC(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) { + // if (selectionConfig.isINELgt0 && !mcCollision.isInelGt0()) { + // return; + // } - // TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; - multiplicity = collision.centFT0M(); - - rEventSelection.fill(HIST("events_checkrec"), 0.5); + bool isINELgt0true = false; - if (!collision.has_mcCollision()) { + if (pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) { + isINELgt0true = true; + } + if (selectionConfig.isINELgt0 && !isINELgt0true) { return; } - rEventSelection.fill(HIST("events_checkrec"), 1.5); - // if (std::abs(collision.mcCollision().posZ()) > cutzvertex || !collision.sel8()) { - if (std::abs(collision.mcCollision().posZ()) > cutzvertex) { + auto impactPar = mcCollision.impactParameter(); + hInvMass.fill(HIST("MCcorrections/hImpactParameterGen"), impactPar); + + bool isSelectedEvent = false; + auto multiplicity1 = -999.; + for (const auto& RecCollision : recCollisions) { + if (!selectionEvent(RecCollision, false)) + continue; + multiplicity1 = RecCollision.centFT0M(); + isSelectedEvent = true; + } + + // Event loss + if (isSelectedEvent) { + hInvMass.fill(HIST("MCcorrections/hImpactParameterRec"), impactPar); + hInvMass.fill(HIST("MCcorrections/hImpactParametervsMultiplicity"), impactPar, multiplicity1); + } + + // Generated MC + for (const auto& mcPart : mcParticles) { + if (std::abs(mcPart.y()) >= selectionConfig.rapidityMotherData || std::abs(mcPart.pdgCode()) != o2::constants::physics::kK0Star892) + continue; + + // signal loss estimation + hInvMass.fill(HIST("MCcorrections/hSignalLossDenominator"), mcPart.pt(), impactPar); + if (isSelectedEvent) { + hInvMass.fill(HIST("MCcorrections/hSignalLossNumerator"), mcPart.pt(), impactPar); + } + } // end loop on gen particles + } + PROCESS_SWITCH(Kstarqa, processEvtLossSigLossMC, "Process Signal Loss, Event Loss", false); + + void processRec(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const&, aod::McCollisions const& /*mcCollisions*/) + { + + if (!collision.has_mcCollision()) { return; } - rEventSelection.fill(HIST("events_checkrec"), 2.5); - if (timFrameEvsel && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + if (selectionConfig.isINELgt0 && !collision.isInelGt0()) { return; } - rEventSelection.fill(HIST("events_checkrec"), 3.5); + multiplicity = collision.centFT0M(); + hInvMass.fill(HIST("hAllRecCollisions"), multiplicity); - if (cTVXEvsel && (!collision.selection_bit(aod::evsel::kIsTriggerTVX))) { + if (!selectionEvent(collision, false)) { return; } - rEventSelection.fill(HIST("events_checkrec"), 4.5); + + // // if (std::abs(collision.mcCollision().posZ()) > selectionConfig.cutzvertex || !collision.sel8()) { + // if (std::abs(collision.mcCollision().posZ()) > selectionConfig.cutzvertex) { + // return; + // } + + // if (selectionConfig.isNoTimeFrameBorder && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + // return; + // } + + // if (selectionConfig.isTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + // return; + // } + + // if (!collision.sel8()) { + // return; + // } + + // if (selectionConfig.isNoSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + // return; + // } + // if (selectionConfig.isGoodZvtxFT0vsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + // return; + // } + + multiplicity = collision.centFT0M(); + hInvMass.fill(HIST("h1RecMult"), multiplicity); auto oldindex = -999; for (const auto& track1 : tracks) { if (!selectionTrack(track1)) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 5.5); if (!track1.has_mcParticle()) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 6.5); auto track1ID = track1.index(); for (const auto& track2 : tracks) { + rEventSelection.fill(HIST("recMCparticles"), 0.5); if (!track2.has_mcParticle()) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 7.5); + rEventSelection.fill(HIST("recMCparticles"), 1.5); if (!selectionTrack(track2)) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 8.5); + rEventSelection.fill(HIST("recMCparticles"), 2.5); auto track2ID = track2.index(); if (track2ID <= track1ID) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 9.5); + rEventSelection.fill(HIST("recMCparticles"), 3.5); if (track1.sign() * track2.sign() >= 0) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 10.5); + rEventSelection.fill(HIST("recMCparticles"), 4.5); const auto mctrack1 = track1.mcParticle(); const auto mctrack2 = track2.mcParticle(); int track1PDG = std::abs(mctrack1.pdgCode()); int track2PDG = std::abs(mctrack2.pdgCode()); - if (cQAplots && track1PDG == 211) { - hPID.fill(HIST("h1PID_TPC_kaon_MC"), track1.tpcNSigmaKa()); - hPID.fill(HIST("h1PID_TOF_kaon_MC"), track1.tofNSigmaKa()); + if (cQAplots && (mctrack2.pdgCode() == PDG_t::kPiPlus)) { // pion + hPID.fill(HIST("Before/h1PID_TPC_pos_pion"), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_pos_pion"), track2.tofNSigmaPi()); + hPID.fill(HIST("Before/hNsigmaTPC_Pi_before"), track2.pt(), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/hNsigmaTOF_Pi_before"), track2.pt(), track2.tofNSigmaPi()); } - if (cQAplots && track1PDG == 321) { - hPID.fill(HIST("h1PID_TPC_pion_MC"), track1.tpcNSigmaPi()); - hPID.fill(HIST("h1PID_TOF_pion_MC"), track1.tofNSigmaPi()); + if (cQAplots && (mctrack2.pdgCode() == PDG_t::kKPlus)) { // kaon + hPID.fill(HIST("Before/h1PID_TPC_pos_kaon"), track2.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_pos_kaon"), track2.tofNSigmaKa()); + hPID.fill(HIST("Before/hNsigmaTPC_Ka_before"), track2.pt(), track2.tpcNSigmaKa()); + hPID.fill(HIST("Before/hNsigmaTOF_Ka_before"), track2.pt(), track2.tofNSigmaKa()); + } + if (cQAplots && (mctrack2.pdgCode() == -PDG_t::kPiMinus)) { // negative track pion + hPID.fill(HIST("Before/h1PID_TPC_neg_pion"), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/h1PID_TOF_neg_pion"), track2.tofNSigmaPi()); + hPID.fill(HIST("Before/hNsigmaTPC_Pi_before"), track2.pt(), track2.tpcNSigmaPi()); + hPID.fill(HIST("Before/hNsigmaTOF_Pi_before"), track2.pt(), track2.tofNSigmaPi()); + } + if (cQAplots && (mctrack2.pdgCode() == -PDG_t::kKMinus)) { // negative track kaon + hPID.fill(HIST("Before/h1PID_TPC_neg_kaon"), track2.tpcNSigmaKa()); + hPID.fill(HIST("Before/h1PID_TOF_neg_kaon"), track2.tofNSigmaKa()); + hPID.fill(HIST("Before/hNsigmaTPC_Ka_before"), track2.pt(), track2.tpcNSigmaKa()); + hPID.fill(HIST("Before/hNsigmaTOF_Ka_before"), track2.pt(), track2.tofNSigmaKa()); + } + if (cQAplots && (std::abs(mctrack1.pdgCode()) == PDG_t::kKPlus && std::abs(mctrack2.pdgCode()) == PDG_t::kPiPlus)) { + hPID.fill(HIST("Before/hNsigma_TPC_TOF_Ka_before"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); + hPID.fill(HIST("Before/hNsigma_TPC_TOF_Pi_before"), track2.tpcNSigmaPi(), track2.tofNSigmaPi()); } if (!mctrack1.isPhysicalPrimary()) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 11.5); if (!mctrack2.isPhysicalPrimary()) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 12.5); + rEventSelection.fill(HIST("recMCparticles"), 5.5); - // if (!(track1PDG == 321 && track2PDG == 211)) { + // if (!(track1PDG == PDG_t::kKPlus && track2PDG == PDG_t::kPiPlus)) { // continue; // } - if (!(track1PDG == 211) && !(track1PDG == 321)) { + if (selectionConfig.isPDGCheckMC && (track1PDG != PDG_t::kPiPlus) && (track1PDG != PDG_t::kKPlus)) { continue; } - if (!(track2PDG == 211) && !(track2PDG == 321)) { + if (selectionConfig.isPDGCheckMC && (track2PDG != PDG_t::kPiPlus) && (track2PDG != PDG_t::kKPlus)) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 13.5); + rEventSelection.fill(HIST("recMCparticles"), 6.5); - if (track1PDG == 211) { - if (!(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon - continue; - } - } else { - if (!(selectionPID(track1, 1) && selectionPID(track2, 0))) { // kaon and pion - continue; - } - } - rEventSelection.fill(HIST("events_checkrec"), 14.5); + if (std::abs(track1.rapidity(o2::track::PID::getMass(o2::track::PID::Kaon))) > selectionConfig.ctrackRapidity) + continue; + + if (std::abs(track2.rapidity(o2::track::PID::getMass(o2::track::PID::Pion))) > selectionConfig.ctrackRapidity) + continue; + + rEventSelection.fill(HIST("recMCparticles"), 7.5); for (const auto& mothertrack1 : mctrack1.mothers_as()) { for (const auto& mothertrack2 : mctrack2.mothers_as()) { - if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { + if (selectionConfig.isPDGCheckMC && (mothertrack1.pdgCode() != mothertrack2.pdgCode())) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 15.5); if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 16.5); + rEventSelection.fill(HIST("recMCparticles"), 8.5); if (!mothertrack1.producedByGenerator()) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 17.5); + rEventSelection.fill(HIST("recMCparticles"), 9.5); - if (std::abs(mothertrack1.y()) >= 0.5) { + if (std::abs(mothertrack1.y()) >= selectionConfig.rapidityMotherData) { continue; } - rEventSelection.fill(HIST("events_checkrec"), 18.5); + rEventSelection.fill(HIST("recMCparticles"), 10.5); - if (std::abs(mothertrack1.pdgCode()) != 313) { + if (selectionConfig.isPDGCheckMC && (std::abs(mothertrack1.pdgCode()) != o2::constants::physics::kK0Star892)) { continue; } + rEventSelection.fill(HIST("recMCparticles"), 11.5); + + if (selectionConfig.isPDGCheckMC && (track1PDG == PDG_t::kPiPlus)) { + if (!applypTdepPID && !(selectionPID(track1, 0) && selectionPID(track2, 1))) { // pion and kaon + continue; + } else if (applypTdepPID && !(selectionPIDNew(track1, 0) && selectionPIDNew(track2, 1))) { // pion and kaon + continue; + } + } else if (selectionConfig.isPDGCheckMC) { + if (!applypTdepPID && !(selectionPID(track1, 1) && selectionPID(track2, 0))) { // kaon and pion + continue; + } else if (applypTdepPID && !(selectionPIDNew(track1, 1) && selectionPIDNew(track2, 0))) { // kaon and pion + continue; + } + } + + if (selectionConfig.isApplyCutsOnMother) { + if (mothertrack1.pt() >= selectionConfig.cMaxPtMotherCut) // excluding candidates in overflow + continue; + if ((std::sqrt(mothertrack1.e() * mothertrack1.e() - mothertrack1.p() * mothertrack1.p())) >= selectionConfig.cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { hInvMass.fill(HIST("h1KSRecsplit"), mothertrack1.pt()); continue; } + rEventSelection.fill(HIST("recMCparticles"), 12.5); + oldindex = mothertrack1.globalIndex(); - pvec0 = std::array{track1.px(), track1.py(), track1.pz()}; - pvec1 = std::array{track2.px(), track2.py(), track2.pz()}; - auto arrMomrec = std::array{pvec0, pvec1}; - auto motherP = mothertrack1.p(); - auto motherE = mothertrack1.e(); - auto genMass = std::sqrt(motherE * motherE - motherP * motherP); - auto recMass = RecoDecay::m(arrMomrec, std::array{massKa, massPi}); - auto recpt = std::sqrt((track1.px() + track2.px()) * (track1.px() + track2.px()) + (track1.py() + track2.py()) * (track1.py() + track2.py())); - //// Resonance reconstruction - // lDecayDaughter1.SetXYZM(track1.px(), track1.py(), track1.pz(), massKa); - // lDecayDaughter2.SetXYZM(track2.px(), track2.py(), track2.pz(), massPi); - // lResonance = lDecayDaughter1 + lDecayDaughter2; - - hInvMass.fill(HIST("h1KstarRecMass"), recMass); - hInvMass.fill(HIST("h1genmass"), genMass); - hInvMass.fill(HIST("h2KstarRecpt1"), mothertrack1.pt(), multiplicity); - hInvMass.fill(HIST("h2KstarRecpt2"), recpt, multiplicity); + if (track1.sign() * track2.sign() < 0) { + daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + daughter2 = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massPi); + mother = daughter1 + daughter2; // Kstar meson + + hInvMass.fill(HIST("h2KstarRecpt2"), mothertrack1.pt(), multiplicity, std::sqrt(mothertrack1.e() * mothertrack1.e() - mothertrack1.p() * mothertrack1.p())); + + if (applyRecMotherRapidity && mother.Rapidity() >= selectionConfig.rapidityMotherData) { + continue; + } + + hInvMass.fill(HIST("h1KstarRecMass"), mother.M()); + hInvMass.fill(HIST("h2KstarRecpt1"), mother.Pt(), multiplicity, mother.M()); + } } } } diff --git a/PWGLF/Tasks/Resonances/lambda1405analysis.cxx b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx new file mode 100644 index 00000000000..dc134339d63 --- /dev/null +++ b/PWGLF/Tasks/Resonances/lambda1405analysis.cxx @@ -0,0 +1,465 @@ +// 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 lambda1405analysis.cxx +/// \brief Analysis task for lambda1405 via sigma kink decay +/// \author Francesco Mazzaschi + +#include "PWGLF/DataModel/LFKinkDecayTables.h" +#include "PWGLF/DataModel/LFLambda1405Table.h" + +#include "Common/Core/PID/PIDTOF.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/PIDResponse.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/PID.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +using TracksFull = soa::Join; +using CollisionsFull = soa::Join; +using CollisionsFullMC = soa::Join; + +struct lambda1405candidate { + // Columns for Lambda(1405) candidate + float mass = -1; // Invariant mass of the Lambda(1405) candidate + float massXi1530 = -1; // Invariant mass of the Xi(1530) candidate + float px = -1; // Px of the Lambda(1405) candidate + float py = -1; // Py of the Lambda(1405) candidate + float pz = -1; // Pz of the Lambda(1405) candidate + float pt() const { return std::sqrt(px * px + py * py); } // pT of the Lambda(1405 candidate + + bool isSigmaPlus = false; // True if compatible with Sigma+ + bool isSigmaMinus = false; // True if compatible with Sigma- + float sigmaMinusMass = -1; // Invariant mass of the Sigma- candidate + float sigmaPlusMass = -1; // Invariant mass of the Sigma+ candidate + float xiMinusMass = -1; // Invariant mass of the Xi- candidate + int sigmaSign = 0; // Sign of the Sigma candidate: 1 for matter, -1 for antimatter + float sigmaPt = -1; // pT of the Sigma daughter + float sigmaAlphaAP = -1; // Alpha of the Sigma + float sigmaQtAP = -1; // qT of the Sigma + float kinkPt = -1; // pT of the kink daughter + float kinkTPCNSigmaPi = -1; // Number of sigmas for the pion candidate from Sigma kink in TPC + float kinkTOFNSigmaPi = -1; // Number of sigmas for the pion candidate from Sigma kink in TOF + float kinkTPCNSigmaPr = -1; // Number of sigmas for the proton candidate from Sigma kink in TPC + float kinkTOFNSigmaPr = -1; // Number of sigmas for the proton candidate from Sigma kink in TOF + float dcaKinkDauToPV = -1; // DCA of the kink daughter to the primary vertex + float sigmaRadius = -1; // Radius of the Sigma decay vertex + + float piPt = -1; // pT of the pion daughter + float nSigmaTPCPi = -1; // Number of sigmas for the pion candidate + float nSigmaTOFPi = -1; // Number of sigmas for the pion candidate using TOF + int kinkDauID = 0; // ID of the pion from Sigma decay in MC + int sigmaID = 0; // ID of the Sigma candidate in MC + int piID = 0; // ID of the pion candidate in MC +}; + +struct lambda1405analysis { + int lambda1405PdgCode = 102132; // PDG code for Lambda(1405) + lambda1405candidate lambda1405Cand; // Lambda(1405) candidate structure + Produces outputDataTable; // Output table for Lambda(1405) candidates + Produces outputDataTableMC; // Output table for Lambda(1405) candidates in MC + // Histograms are defined with HistogramRegistry + HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rLambda1405{"lambda1405", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + // Configurable for event selection + Configurable cutzvertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; + 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 cutDCAtoPVPiFromSigma{"cutDCAtoPVPiFromSigma", 2., "Min DCA to primary vertex for pion from Sigma candidates (cm)"}; + + Configurable cutUpperMass{"cutUpperMass", 1.6f, "Upper mass cut for Lambda(1405) candidates (GeV/c^2)"}; + Configurable cutSigmaRadius{"cutSigmaRadius", 20.f, "Minimum radius for Sigma candidates (cm)"}; + Configurable cutSigmaMass{"cutSigmaMass", 0.1, "Sigma mass window (MeV/c^2)"}; + Configurable cutNITSClusPi{"cutNITSClusPi", 5, "Minimum number of ITS clusters for pion candidate"}; + Configurable cutNTPCClusPi{"cutNTPCClusPi", 90, "Minimum number of TPC clusters for pion candidate"}; + Configurable cutNSigmaTPC{"cutNSigmaTPC", 3, "NSigmaTPCPion"}; + Configurable cutNSigmaTOF{"cutNSigmaTOF", 3, "NSigmaTOFPion"}; + + Configurable fillOutputTree{"fillOutputTree", true, "If true, fill the output tree with Lambda(1405) candidates"}; + Configurable doLSBkg{"doLikeSignBkg", false, "Use like-sign background"}; + Configurable useTOF{"useTOF", false, "Use TOF for PID for pion candidates"}; + + Preslice mKinkPerCol = aod::track::collisionId; + Preslice mPerColTracks = aod::track::collisionId; + + void init(InitContext const&) + { + // Axes + const AxisSpec ptAxis{100, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec ptPiAxis{100, -5, 5, "#it{p}_{T}^{#pi} (GeV/#it{c})"}; + const AxisSpec ptResolutionAxis{100, -0.5, 0.5, "#it{p}_{T}^{rec} - #it{p}_{T}^{gen} (GeV/#it{c})"}; + const AxisSpec massAxis{100, 1.3, 1.6, "m (GeV/#it{c}^{2})"}; + const AxisSpec massResolutionAxis{100, -0.1, 0.1, "m_{rec} - m_{gen} (GeV/#it{c}^{2})"}; + const AxisSpec nSigmaPiAxis{100, -5, 5, "n#sigma_{#pi}"}; + const AxisSpec sigmaMassAxis{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; + const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; + rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); + + // lambda1405 to sigmaminus + rLambda1405.add("h2PtMass_0", "h2PtMass_0", {HistType::kTH2F, {ptAxis, massAxis}}); + rLambda1405.add("h2PtMassSigmaBeforeCuts_0", "h2PtMassSigmaBeforeCuts_0", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rLambda1405.add("h2PtMassSigma_0", "h2PtMassSigma_0", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rLambda1405.add("h2SigmaMassVsMass_0", "h2SigmaMassVsMass_0", {HistType::kTH2F, {massAxis, sigmaMassAxis}}); + rLambda1405.add("h2PtPiNSigma_0", "h2PtPiNSigma_0", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); + rLambda1405.add("h2PtPiNSigmaTOF_0", "h2PtPiNSigmaTOF_0", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); + // lambda1405 to sigmaplus + rLambda1405.add("h2PtMass_1", "h2PtMass_1", {HistType::kTH2F, {ptAxis, massAxis}}); + rLambda1405.add("h2PtMassSigmaBeforeCuts_1", "h2PtMassSigmaBeforeCuts_1", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rLambda1405.add("h2PtMassSigma_1", "h2PtMassSigma_1", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); + rLambda1405.add("h2SigmaMassVsMass_1", "h2SigmaMassVsMass_1", {HistType::kTH2F, {massAxis, sigmaMassAxis}}); + rLambda1405.add("h2PtPiNSigma_1", "h2PtPiNSigma_1", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); + rLambda1405.add("h2PtPiNSigmaTOF_1", "h2PtPiNSigmaTOF_1", {HistType::kTH2F, {ptPiAxis, nSigmaPiAxis}}); + + if (doprocessMC) { + // Add MC histograms if needed, to sigmaminus + rLambda1405.add("h2MassResolution_0", "h2MassResolution_0", {HistType::kTH2F, {massAxis, massResolutionAxis}}); + rLambda1405.add("h2PtResolution_0", "h2PtResolution_0", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); + rLambda1405.add("h2PtMassMC_0", "h2PtMassMC_0", {HistType::kTH2F, {ptAxis, massAxis}}); + // Add MC histograms if needed, to sigmaplus + rLambda1405.add("h2MassResolution_1", "h2MassResolution_1", {HistType::kTH2F, {massAxis, massResolutionAxis}}); + rLambda1405.add("h2PtResolution_1", "h2PtResolution_1", {HistType::kTH2F, {ptAxis, ptResolutionAxis}}); + rLambda1405.add("h2PtMassMC_1", "h2PtMassMC_1", {HistType::kTH2F, {ptAxis, massAxis}}); + } + } + + float alphaAP(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 qtAP(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); + } + + template + bool selectPiTrack(const Ttrack& candidate, bool piFromSigma) + { + if (std::abs(candidate.tpcNSigmaPi()) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusPi || std::abs(candidate.eta()) > cutEtaDaught) { + return false; + } + if (piFromSigma) { + return true; + } + + if (candidate.itsNCls() < cutNITSClusPi) { + return false; + } + + if (useTOF && !candidate.hasTOF()) { + return false; + } + + if (useTOF && std::abs(candidate.tofNSigmaPi()) > cutNSigmaTOF) { + return false; + } + + return true; // Track is selected + } + + template + bool selectProTrack(const Ttrack& candidate, bool prFromSigma) + { + if (std::abs(candidate.tpcNSigmaPr()) > cutNSigmaTPC || candidate.tpcNClsFound() < cutNTPCClusPi || std::abs(candidate.eta()) > cutEtaDaught) { + return false; + } + if (prFromSigma) { + return true; + } + if (candidate.itsNCls() < cutNITSClusPi) { + return false; + } + if (useTOF && !candidate.hasTOF()) { + return false; + } + if (useTOF && std::abs(candidate.tofNSigmaPr()) > cutNSigmaTOF) { + return false; + } + return true; // Track is selected + } + + bool selectCandidate(aod::KinkCands::iterator const& sigmaCand, TracksFull const& tracks) + { + auto kinkDauTrack = sigmaCand.trackDaug_as(); + bool isPiKink = selectPiTrack(kinkDauTrack, true); + bool isProKink = selectProTrack(kinkDauTrack, true); + if (!isPiKink && !isProKink) { + return false; + } + + if (isPiKink) { + rLambda1405.fill(HIST("h2PtMassSigmaBeforeCuts_0"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaMinus()); + rLambda1405.fill(HIST("h2PtPiNSigma_0"), sigmaCand.mothSign() * kinkDauTrack.pt(), kinkDauTrack.tpcNSigmaPi()); + } + if (isProKink) { + rLambda1405.fill(HIST("h2PtMassSigmaBeforeCuts_1"), sigmaCand.mothSign() * sigmaCand.ptMoth(), sigmaCand.mSigmaPlus()); + rLambda1405.fill(HIST("h2PtPiNSigma_1"), sigmaCand.mothSign() * kinkDauTrack.pt(), kinkDauTrack.tpcNSigmaPr()); + } + + lambda1405Cand.isSigmaPlus = isProKink && (sigmaCand.mSigmaPlus() > o2::constants::physics::MassSigmaPlus - cutSigmaMass && sigmaCand.mSigmaPlus() < o2::constants::physics::MassSigmaPlus + cutSigmaMass); + lambda1405Cand.isSigmaMinus = isPiKink && (sigmaCand.mSigmaMinus() > o2::constants::physics::MassSigmaMinus - cutSigmaMass && sigmaCand.mSigmaMinus() < o2::constants::physics::MassSigmaMinus + cutSigmaMass); + if (!lambda1405Cand.isSigmaPlus && !lambda1405Cand.isSigmaMinus) { + return false; + } + float sigmaRad = std::hypot(sigmaCand.xDecVtx(), sigmaCand.yDecVtx()); + if (std::abs(sigmaCand.dcaMothPv()) > cutDCAtoPVSigma || std::abs(sigmaCand.dcaDaugPv()) < cutDCAtoPVPiFromSigma || sigmaRad < cutSigmaRadius) { + return false; + } + + for (const auto& piTrack : tracks) { + if (!doLSBkg) { + if (piTrack.sign() == sigmaCand.mothSign()) { + continue; + } + } else { + if (piTrack.sign() != sigmaCand.mothSign()) { + continue; + } + } + + if (!selectPiTrack(piTrack, false)) { + continue; + } + + auto kinkDauMom = std::array{sigmaCand.pxDaug(), sigmaCand.pyDaug(), sigmaCand.pzDaug()}; + auto sigmaMom = std::array{sigmaCand.pxMoth(), sigmaCand.pyMoth(), sigmaCand.pzMoth()}; + auto piMom = std::array{piTrack.px(), piTrack.py(), piTrack.pz()}; + float invMass = RecoDecay::m(std::array{sigmaMom, piMom}, std::array{o2::constants::physics::MassSigmaMinus, o2::constants::physics::MassPiPlus}); + float invMassXiPi = RecoDecay::m(std::array{sigmaMom, kinkDauMom}, std::array{o2::constants::physics::MassXiMinus, o2::constants::physics::MassPiPlus}); + if (invMass > cutUpperMass) { + continue; + } + + lambda1405Cand.kinkDauID = kinkDauTrack.globalIndex(); + lambda1405Cand.sigmaID = sigmaCand.globalIndex(); + lambda1405Cand.piID = piTrack.globalIndex(); + + lambda1405Cand.px = sigmaMom[0] + piMom[0]; + lambda1405Cand.py = sigmaMom[1] + piMom[1]; + lambda1405Cand.pz = sigmaMom[2] + piMom[2]; + lambda1405Cand.mass = invMass; + lambda1405Cand.massXi1530 = invMassXiPi; + + lambda1405Cand.sigmaMinusMass = sigmaCand.mSigmaMinus(); + lambda1405Cand.sigmaPlusMass = sigmaCand.mSigmaPlus(); + lambda1405Cand.xiMinusMass = sigmaCand.mXiMinus(); + lambda1405Cand.sigmaSign = sigmaCand.mothSign(); + lambda1405Cand.sigmaAlphaAP = alphaAP(sigmaMom, kinkDauMom); + lambda1405Cand.sigmaQtAP = qtAP(sigmaMom, kinkDauMom); + lambda1405Cand.sigmaPt = sigmaCand.ptMoth(); + lambda1405Cand.sigmaRadius = sigmaRad; + lambda1405Cand.kinkPt = kinkDauTrack.pt(); + lambda1405Cand.kinkTPCNSigmaPi = kinkDauTrack.tpcNSigmaPi(); + lambda1405Cand.kinkTOFNSigmaPi = kinkDauTrack.tofNSigmaPi(); + lambda1405Cand.kinkTPCNSigmaPr = kinkDauTrack.tpcNSigmaPr(); + lambda1405Cand.kinkTOFNSigmaPr = kinkDauTrack.tofNSigmaPr(); + lambda1405Cand.dcaKinkDauToPV = sigmaCand.dcaDaugPv(); + + lambda1405Cand.piPt = piTrack.pt(); + lambda1405Cand.nSigmaTPCPi = piTrack.tpcNSigmaPi(); + if (useTOF) { + lambda1405Cand.nSigmaTOFPi = piTrack.tofNSigmaPi(); + } else { + lambda1405Cand.nSigmaTOFPi = -999; // Not used if TOF is not enabled + } + return true; // Candidate is selected + } + return false; // No valid pion track found + } + + template + bool checkSigmaKinkMC(const mcTrack& mcTrackSigma, const mcTrack& mcTrackKinkDau, float sigmaAbsPDG, float kinkAbsPDG, aod::McParticles const&) + { + if (std::abs(mcTrackSigma.pdgCode()) != sigmaAbsPDG || std::abs(mcTrackKinkDau.pdgCode()) != kinkAbsPDG) { + return false; // Not a valid Sigma kink decay + } + if (!mcTrackKinkDau.has_mothers()) { + return false; // No mothers found + } + // Check if the kink comes from the Sigma + bool isKinkFromSigma = false; + for (const auto& mcMother : mcTrackKinkDau.template mothers_as()) { + if (mcMother.globalIndex() == mcTrackSigma.globalIndex()) { + isKinkFromSigma = true; + break; + } + } + return isKinkFromSigma; // Return true if the kink comes from the Sigma + } + + void processData(CollisionsFull::iterator const& collision, aod::KinkCands const& kinkCands, TracksFull const& tracks) + { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + return; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + for (const auto& sigmaCand : kinkCands) { + if (selectCandidate(sigmaCand, tracks)) { + if (lambda1405Cand.isSigmaMinus) { + rLambda1405.fill(HIST("h2PtMass_0"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtMassSigma_0"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMinusMass); + rLambda1405.fill(HIST("h2SigmaMassVsMass_0"), lambda1405Cand.mass, lambda1405Cand.sigmaMinusMass); + rLambda1405.fill(HIST("h2PtPiNSigmaTOF_0"), lambda1405Cand.sigmaSign * lambda1405Cand.piPt, lambda1405Cand.nSigmaTOFPi); + } + if (lambda1405Cand.isSigmaPlus) { + rLambda1405.fill(HIST("h2PtMass_1"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtMassSigma_1"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaPlusMass); + rLambda1405.fill(HIST("h2SigmaMassVsMass_1"), lambda1405Cand.mass, lambda1405Cand.sigmaPlusMass); + rLambda1405.fill(HIST("h2PtPiNSigmaTOF_1"), lambda1405Cand.sigmaSign * lambda1405Cand.piPt, lambda1405Cand.nSigmaTOFPi); + } + if (fillOutputTree) { + outputDataTable(lambda1405Cand.px, lambda1405Cand.py, lambda1405Cand.pz, + lambda1405Cand.mass, lambda1405Cand.massXi1530, + lambda1405Cand.sigmaMinusMass, lambda1405Cand.sigmaPlusMass, lambda1405Cand.xiMinusMass, + lambda1405Cand.sigmaPt, lambda1405Cand.sigmaAlphaAP, lambda1405Cand.sigmaQtAP, lambda1405Cand.sigmaRadius, + lambda1405Cand.kinkPt, + lambda1405Cand.kinkTPCNSigmaPi, lambda1405Cand.kinkTOFNSigmaPi, + lambda1405Cand.kinkTPCNSigmaPr, lambda1405Cand.kinkTOFNSigmaPr, + lambda1405Cand.dcaKinkDauToPV, + lambda1405Cand.nSigmaTPCPi, lambda1405Cand.nSigmaTOFPi); + } + } + } + } + PROCESS_SWITCH(lambda1405analysis, processData, "Data processing", true); + + void processMC(CollisionsFullMC const& collisions, aod::KinkCands const& kinkCands, aod::McTrackLabels const& trackLabelsMC, aod::McParticles const& particlesMC, TracksFull const& tracks) + { + for (const auto& collision : collisions) { + if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { + continue; + } + rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); + auto sigmaCandsPerCol = kinkCands.sliceBy(mKinkPerCol, collision.globalIndex()); + auto tracksPerCol = tracks.sliceBy(mPerColTracks, collision.globalIndex()); + for (const auto& sigmaCand : sigmaCandsPerCol) { + if (selectCandidate(sigmaCand, tracksPerCol)) { + // Do MC association + auto mcLabPiKink = trackLabelsMC.rawIteratorAt(lambda1405Cand.kinkDauID); + auto mcLabSigma = trackLabelsMC.rawIteratorAt(lambda1405Cand.sigmaID); + auto mcLabPi = trackLabelsMC.rawIteratorAt(lambda1405Cand.piID); + if (!mcLabSigma.has_mcParticle() || mcLabPiKink.has_mcParticle() || mcLabPi.has_mcParticle()) { + continue; // Skip if no valid MC association + } + auto mcTrackKink = mcLabPiKink.mcParticle_as(); + auto mcTrackSigma = mcLabSigma.mcParticle_as(); + auto mcTrackPi = mcLabPi.mcParticle_as(); + + bool isSigmaMinusKink = checkSigmaKinkMC(mcTrackSigma, mcTrackKink, 3122, 211, particlesMC); + bool isSigmaPlusToPiKink = checkSigmaKinkMC(mcTrackSigma, mcTrackKink, 3222, 211, particlesMC); + bool isSigmaPlusToPrKink = checkSigmaKinkMC(mcTrackSigma, mcTrackKink, 3222, 2212, particlesMC); + + if (!isSigmaMinusKink && !isSigmaPlusToPiKink && !isSigmaPlusToPrKink) { + continue; // Skip if not a valid Sigma kink decay + } + + if (std::abs(mcTrackPi.pdgCode()) != 211) { + continue; // Skip if not a valid pion candidate + } + + if (!mcTrackSigma.has_mothers() || !mcTrackPi.has_mothers()) { + continue; // Skip if no mothers found + } + + // check that labpi and labsigma have the same mother (a lambda1405 candidate) + int lambda1405Id = -1; + for (const auto& piMother : mcTrackPi.mothers_as()) { + for (const auto& sigmaMother : mcTrackSigma.mothers_as()) { + if (piMother.globalIndex() == sigmaMother.globalIndex() && std::abs(piMother.pdgCode()) == lambda1405PdgCode) { + lambda1405Id = piMother.globalIndex(); + break; // Found the mother, exit loop + } + } + } + if (lambda1405Id == -1) { + continue; // Skip if the Sigma and pion do not share the same lambda1405 candidate + } + auto lambda1405Mother = particlesMC.rawIteratorAt(lambda1405Id); + float lambda1405Mass = std::sqrt(lambda1405Mother.e() * lambda1405Mother.e() - lambda1405Mother.p() * lambda1405Mother.p()); + if (lambda1405Cand.isSigmaMinus) { + rLambda1405.fill(HIST("h2PtMass_0"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtMassSigma_0"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaMinusMass); + rLambda1405.fill(HIST("h2SigmaMassVsMass_0"), lambda1405Cand.mass, lambda1405Cand.sigmaMinusMass); + rLambda1405.fill(HIST("h2PtPiNSigma_0"), lambda1405Cand.piPt, lambda1405Cand.nSigmaTPCPi); + rLambda1405.fill(HIST("h2MassResolution_0"), lambda1405Mass, lambda1405Mass - lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtResolution_0"), lambda1405Cand.pt(), lambda1405Cand.pt() - lambda1405Mother.pt()); + } + if (lambda1405Cand.isSigmaPlus) { + rLambda1405.fill(HIST("h2PtMass_1"), lambda1405Cand.sigmaSign * lambda1405Cand.pt(), lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtMassSigma_1"), lambda1405Cand.sigmaSign * lambda1405Cand.sigmaPt, lambda1405Cand.sigmaPlusMass); + rLambda1405.fill(HIST("h2SigmaMassVsMass_1"), lambda1405Cand.mass, lambda1405Cand.sigmaPlusMass); + rLambda1405.fill(HIST("h2PtPiNSigma_1"), lambda1405Cand.piPt, lambda1405Cand.nSigmaTPCPi); + rLambda1405.fill(HIST("h2MassResolution_1"), lambda1405Mass, lambda1405Mass - lambda1405Cand.mass); + rLambda1405.fill(HIST("h2PtResolution_1"), lambda1405Cand.pt(), lambda1405Cand.pt() - lambda1405Mother.pt()); + } + + if (fillOutputTree) { + outputDataTableMC(lambda1405Cand.px, lambda1405Cand.py, lambda1405Cand.pz, + lambda1405Cand.mass, lambda1405Cand.massXi1530, + lambda1405Cand.sigmaMinusMass, lambda1405Cand.sigmaPlusMass, lambda1405Cand.xiMinusMass, + lambda1405Cand.sigmaPt, lambda1405Cand.sigmaAlphaAP, lambda1405Cand.sigmaQtAP, lambda1405Cand.sigmaRadius, + lambda1405Cand.kinkPt, + lambda1405Cand.kinkTPCNSigmaPi, lambda1405Cand.kinkTOFNSigmaPi, + lambda1405Cand.kinkTPCNSigmaPr, lambda1405Cand.kinkTOFNSigmaPr, + lambda1405Cand.dcaKinkDauToPV, + lambda1405Cand.nSigmaTPCPi, lambda1405Cand.nSigmaTOFPi, + lambda1405Mother.pt(), lambda1405Mass, mcTrackSigma.pdgCode(), mcTrackKink.pdgCode()); + } + } + } + } + + // Loop over generated particles to fill MC histograms + for (const auto& mcPart : particlesMC) { + if (std::abs(mcPart.pdgCode()) != lambda1405PdgCode) { + continue; // Only consider Lambda(1405) candidates + } + + if (!mcPart.has_daughters()) { + continue; // Skip if no daughters + } + + // Check if the Lambda(1405) has a Sigma daughter + bool hasSigmaDaughter = false; + int dauPdgCode = 0; + for (const auto& daughter : mcPart.daughters_as()) { + if (std::abs(daughter.pdgCode()) == 3122 || std::abs(daughter.pdgCode()) == 3222) { // Sigma PDG code + hasSigmaDaughter = true; + dauPdgCode = daughter.pdgCode(); + break; // Found a Sigma daughter, exit loop + } + } + if (!hasSigmaDaughter) { + continue; // Skip if no Sigma daughter found + } + + float mcMass = std::sqrt(mcPart.e() * mcPart.e() - mcPart.p() * mcPart.p()); + dauPdgCode ? rLambda1405.fill(HIST("h2PtMassMC_0"), mcPart.pt(), mcMass) : rLambda1405.fill(HIST("h2PtMassMC_1"), mcPart.pt(), mcMass); + } + } + PROCESS_SWITCH(lambda1405analysis, processMC, "MC processing", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx index d032d0c90aa..830722b4bbf 100644 --- a/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520_PbPb.cxx @@ -555,7 +555,7 @@ struct lambdaAnalysis_pb { { auto mult = collision.cent(); - histos.fill(HIST("Event/h1d_ft0_mult_percentile"), mult); + histos.fill(HIST("Event/h1d_ft0_mult_percentile"), mult, 100); fillDataHistos(tracks, tracks, mult); // get MC pT-spectra diff --git a/PWGLF/Tasks/Resonances/lstaranalysis.cxx b/PWGLF/Tasks/Resonances/lambda1520analysisinOO.cxx similarity index 71% rename from PWGLF/Tasks/Resonances/lstaranalysis.cxx rename to PWGLF/Tasks/Resonances/lambda1520analysisinOO.cxx index 816761609b6..d280d3c1da3 100644 --- a/PWGLF/Tasks/Resonances/lstaranalysis.cxx +++ b/PWGLF/Tasks/Resonances/lambda1520analysisinOO.cxx @@ -21,56 +21,64 @@ #include // 4. Other includes: O2 framework, ROOT, etc. -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" - -#include - -#include "Framework/O2DatabasePDGPlugin.h" -#include "Framework/HistogramRegistry.h" - #include "PWGLF/Utils/collisionCuts.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/Centrality.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" -#include "TRandom.h" -#include "TVector3.h" #include "Math/Vector4D.h" #include "TPDGCode.h" +#include "TRandom.h" +#include "TVector3.h" 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 LorentzVectorPtEtaPhiMass = ROOT::Math::PtEtaPhiMVector; +enum { + kINEL = 1, + kINEL10, + kINELg0, + kINELg010, + kTrig, + kTrig10, + kTrigINELg0, + kTrigINELg010, + kSel8, + kSel810, + kSel8INELg0, + kSel8INELg010, + kAllCuts, + kAllCuts10, + kAllCutsINELg0, + kAllCutsINELg010, +}; + struct Lstaranalysis { // Define slice per Resocollision SliceCache cache; Preslice perCollision = o2::aod::track::collisionId; - - using EventCandidates = soa::Join; - using TrackCandidates = soa::Join; - - using MCEventCandidates = soa::Join; - using MCTrackCandidates = soa::Join; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; - Service ccdb; Service pdg; - ccdb::CcdbApi ccdbApi; - - Configurable cfgURL{"cfgURL", "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"}; /// Event cuts o2::analysis::CollisonCuts colCuts; + 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"}; @@ -89,8 +97,11 @@ struct Lstaranalysis { // Configurables // Pre-selection Track cuts + Configurable trackSelection{"trackSelection", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; Configurable cMinPtcut{"cMinPtcut", 0.15f, "Minimal pT for tracks"}; Configurable cMinTPCNClsFound{"cMinTPCNClsFound", 120, "minimum TPCNClsFound value for good track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min crossed rows for good track"}; // DCA Selections // DCAr to PV @@ -120,7 +131,6 @@ struct Lstaranalysis { Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; Configurable> kaonTPCTOFCombinedpTintv{"kaonTPCTOFCombinedpTintv", {999.}, "pT intervals for Kaon TPC-TOF PID cuts"}; Configurable> kaonTPCTOFCombinedPIDcuts{"kaonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Kaon TPC-TOF PID cuts"}; - Configurable cMaxTPCnSigmaKaonVETO{"cMaxTPCnSigmaKaonVETO", 3.0, "TPC nSigma VETO cut for Kaon"}; // TPC // Proton Configurable> protonTPCPIDpTintv{"protonTPCPIDpTintv", {0.9}, "pT intervals for Kaon TPC PID cuts"}; @@ -129,7 +139,6 @@ struct Lstaranalysis { Configurable> protonTOFPIDcuts{"protonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; Configurable> protonTPCTOFCombinedpTintv{"protonTPCTOFCombinedpTintv", {999.}, "pT intervals for Proton TPC-TOF PID cuts"}; Configurable> protonTPCTOFCombinedPIDcuts{"protonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Proton TPC-TOF PID cuts"}; - Configurable cMaxTPCnSigmaProtonVETO{"cMaxTPCnSigmaProtonVETO", 3.0, "TPC nSigma VETO cut for Proton"}; // TPC // Additional purity check Configurable crejectPion{"crejectPion", false, "Switch to turn on/off pion contamination"}; @@ -150,6 +159,8 @@ struct Lstaranalysis { // MC selection cut Configurable cZvertCutMC{"cZvertCutMC", 10.0, "MC Z-vertex cut"}; Configurable cEtacutMC{"cEtacutMC", 0.5, "MC eta cut"}; + Configurable cUseRapcutMC{"cUseRapcutMC", true, "MC eta cut"}; + Configurable cUseEtacutMC{"cUseEtacutMC", true, "MC eta cut"}; // cuts on mother Configurable cfgCutsOnMother{"cfgCutsOnMother", false, "Enable additional cuts on mother"}; @@ -164,17 +175,35 @@ struct Lstaranalysis { Configurable cFilladditionalMEPlots{"cFilladditionalMEPlots", false, "Additional Mixed event plots"}; Configurable cFilldeltaEtaPhiPlots{"cFilldeltaEtaPhiPlots", false, "Enamble additional cuts on daughters"}; Configurable cFillinvmass1DPlots{"cFillinvmass1DPlots", false, "Invariant mass 1D"}; + Configurable multEstimator{"multEstimator", 0, "Select multiplicity estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C"}; Configurable cfgCentEst{"cfgCentEst", 2, "Centrality estimator, 1: FT0C, 2: FT0M"}; TRandom* rn = new TRandom(); + // Pre-filters for efficient process + // Filter tofPIDFilter = aod::track::tofExpMom < 0.f || ((aod::track::tofExpMom > 0.f) && ((nabs(aod::pidtof::tofNSigmaPi) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaKa) < pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaPr) < pidnSigmaPreSelectionCut))); // TOF + // Filter tpcPIDFilter = nabs(aod::pidtpc::tpcNSigmaPi) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaKa) < pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaPr) < pidnSigmaPreSelectionCut; // TPC + /* Filter trackFilter = (trackSelection == 0) || + ((trackSelection == 1) && requireGlobalTrackInFilter()) || + ((trackSelection == 2) && requireGlobalTrackWoPtEtaInFilter()) || + ((trackSelection == 3) && requireGlobalTrackWoDCAInFilter()) || + ((trackSelection == 4) && requireQualityTracksInFilter()) || + ((trackSelection == 5) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); */ + Filter trackEtaFilter = nabs(aod::track::eta) < cfgCutEta; // Eta cut + + using EventCandidates = soa::Join; + using TrackCandidates = soa::Filtered>; + + using MCEventCandidates = soa::Join; + using MCTrackCandidates = soa::Filtered>; + /// Figures ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.25, 1.3, 1.4, 1.5, 1.6, 1.7, 1.75, 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.6, 3.7, 3.8, 3.9, 4.0, 4.1, 4.2, 4.5, 4.6, 4.8, 4.9, 5.0, 5.5, 5.6, 6.0, 6.4, 6.5, 7.0, 7.2, 8.0, 9.0, 9.5, 9.6, 10.0, 11.0, 11.5, 12.0, 13.0, 14.0, 14.4, 15.0, 16.0, 18.0, 19.2, 20.}, "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, 10.2, 10.4, 10.6, 10.8, 11, 11.2, 11.4, 11.6, 11.8, 12, 12.2, 12.4, 12.6, 12.8, 13, 13.2, 13.4, 13.6, 13.8, 14, 14.2, 14.4, 14.6, 14.8, 15, 15.2, 15.4, 15.6, 15.8, 16, 16.2, 16.4, 16.6, 16.8, 17, 17.2, 17.4, 17.6, 17.8, 18, 18.2, 18.4, 18.6, 18.8, 19, 19.2, 19.4, 19.6, 19.8, 20}, "Binning of the pT axis"}; ConfigurableAxis binsEta{"binsEta", {150, -1.5, 1.5}, ""}; ConfigurableAxis binsMass{"binsMass", {70, 1.3, 2.0}, "Invariant Mass (GeV/#it{c}^2)"}; - ConfigurableAxis binsMult{"binsMult", {110, 0.0, 110.0}, "mult_{FT0M}"}; + ConfigurableAxis binsMult{"binsMult", {105, 0.0, 105.0}, "mult_{FT0M}"}; ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2, 0.2}, ""}; ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2, 0.2}, ""}; ConfigurableAxis binsTPCXrows{"binsTPCXrows", {100, 60, 160}, ""}; @@ -189,6 +218,7 @@ struct Lstaranalysis { centrality = -999; colCuts.setCuts(cfgEvtZvtx, cfgEvtTriggerCheck, cfgEvtOfflineCheck, /*checkRun3*/ true, /*triggerTVXsel*/ false, cfgEvtOccupancyInTimeRangeMax, cfgEvtOccupancyInTimeRangeMin); + colCuts.init(&histos); colCuts.setTriggerTVX(cfgEvtTriggerTVXSel); colCuts.setApplyTFBorderCut(cfgEvtTFBorderCut); @@ -197,11 +227,13 @@ struct Lstaranalysis { colCuts.setApplyPileupRejection(cfgEvtPileupRejection); colCuts.setApplyNoITSROBorderCut(cfgEvtNoITSROBorderCut); colCuts.setApplyCollInTimeRangeStandard(cfgEvtCollInTimeRangeStandard); + colCuts.printCuts(); // axes AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec axisPtQA{binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec axisEta{binsEta, "#eta"}; + AxisSpec axisRap{binsEta, "#it{y}"}; AxisSpec axisMassLambda1520{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; AxisSpec axisMult{binsMult, "mult_{V0M}"}; AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; @@ -209,11 +241,12 @@ struct Lstaranalysis { AxisSpec axisTPCXrow{binsTPCXrows, "#Xrows_{TPC}"}; AxisSpec axisPIDQA{binsnSigma, "#sigma"}; AxisSpec axisTPCSignal{binsnTPCSignal, ""}; - AxisSpec axisMClabel{5, -0.5, 5.5, "MC Label"}; + AxisSpec axisMClabel{6, -1.5, 5.5, "MC Label"}; AxisSpec axisEtaPhi{binsEtaPhi, ""}; - AxisSpec axisPhi{350, -3.5, 3.5, "#Phi"}; + AxisSpec axisPhi{350, 0, 7, "#Phi"}; AxisSpec axisMultMix{cfgMultBins, "Multiplicity"}; AxisSpec axisVtxMix{cfgVtxBins, "Vertex Z (cm)"}; + AxisSpec idxMCAxis = {26, -0.5, 25.5, "Index"}; if (cFilladditionalQAeventPlots) { // event histograms @@ -245,17 +278,17 @@ struct Lstaranalysis { if (doprocessData) { // Track QA before cuts // --- Track - histos.add("QA/QAbefore/Track/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TPConly_Nsigma_ka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;#sigma_{TOF}^{Proton};#sigma_{TPC}^{Proton}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/TPConly_Nsigma_pr", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAbefore/Track/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTHnSparseF, {axisPt, axisDCAz}); - histos.add("QA/QAbefore/Track/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAxy}); - histos.add("QA/QAbefore/Track/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTHnSparseF, {axisPt, axisTPCXrow}); + histos.add("QA/QAbefore/Track/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_ka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;{#sigma_{TOF}^{Proton}};{#sigma_{TPC}^{Proton}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_pr", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAbefore/Track/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAbefore/Track/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); histos.add("QA/QAbefore/Track/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); histos.add("QA/QAbefore/Track/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); @@ -267,29 +300,29 @@ struct Lstaranalysis { // PID QA after cuts // --- Kaon - histos.add("QA/QAafter/Kaon/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;#sigma_{TOF}^{Kaon};#sigma_{TPC}^{Kaon}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAafter/Kaon/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Kaon/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTHnSparseF, {axisPt, axisDCAz}); - histos.add("QA/QAafter/Kaon/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAxy}); - histos.add("QA/QAafter/Kaon/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTHnSparseF, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Kaon/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Kaon/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Kaon/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); histos.add("QA/QAafter/Kaon/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); histos.add("QA/QAafter/Kaon/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); - histos.add("QA/QAafter/Kaon/TPC_Signal_ka_all", "TPC Signal for Kaon;#it{p}_{T} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTHnSparseF, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Kaon/TPC_Signal_ka_all", "TPC Signal for Kaon;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); histos.add("QA/QAafter/Kaon/TPCnclusterPhika", "TPC ncluster vs phi", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0, 6.28, "#phi"}}); // --- Proton - histos.add("QA/QAafter/Proton/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;#sigma_{TOF}^{Proton};#sigma_{TPC}^{Proton}", {HistType::kTHnSparseF, {axisPIDQA, axisPIDQA}}); - histos.add("QA/QAafter/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisPt, axisPIDQA}}); - histos.add("QA/QAafter/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAz}); - histos.add("QA/QAafter/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTHnSparseF, {axisPt, axisDCAxy}); - histos.add("QA/QAafter/Proton/TPC_CR", "# TPC Xrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTHnSparseF, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Proton/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;{#sigma_{TOF}^{Proton}};{#sigma_{TPC}^{Proton}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Proton/TPC_CR", "# TPC Xrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); histos.add("QA/QAafter/Proton/pT", "pT distribution of Protons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); histos.add("QA/QAafter/Proton/eta", "#eta distribution of Protons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); - histos.add("QA/QAafter/Proton/TPC_Signal_pr_all", "TPC Signal for Proton;#it{p}_{T} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTHnSparseF, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Proton/TPC_Signal_pr_all", "TPC Signal for Proton;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); histos.add("QA/QAafter/Proton/TPCnclusterPhipr", "TPC ncluster vs phi", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0, 6.28, "#phi"}}); // Mass QA 1D for quick check @@ -338,42 +371,37 @@ struct Lstaranalysis { } // MC QA + histos.add("Event/hMCEventIndices", "hMCEventIndices", kTH2D, {axisMult, idxMCAxis}); if (doprocessMCTrue) { 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, axisEta}); - histos.add("QA/MC/h2GenEtaPt_beforeEtacut", " #eta-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); - histos.add("QA/MC/h2GenPhiRapidity_beforeEtacut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisEta}); - histos.add("QA/MC/h2GenEtaPt_afterEtacut", " #phi-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); - histos.add("QA/MC/h2GenPhiRapidity_afterEtacut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisEta}); + 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}); + histos.add("QA/MC/h2GenPhiRapidity_afterEtaRapCut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + histos.add("QA/MC/h2GenEtaPt_afterRapcut", " #phi-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); + histos.add("QA/MC/h2GenPhiRapidity_afterRapcut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); histos.add("Result/MC/Genlambda1520pt", "pT distribution of True MC #Lambda(1520)0", kTHnSparseF, {axisMClabel, axisPt, axisMult}); histos.add("Result/MC/Genantilambda1520pt", "pT distribution of True MC Anti-#Lambda(1520)0", kTHnSparseF, {axisMClabel, axisPt, axisMult}); } if (doprocessMC) { 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, axisEta}); + histos.add("QA/MC/h2RecoPhiRapidity_after", " #phi-y distribution of Reconstructed #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); histos.add("QA/MC/trkDCAxy_pr", "DCAxy distribution of proton track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); histos.add("QA/MC/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); histos.add("QA/MC/trkDCAz_pr", "DCAz distribution of proton track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); histos.add("QA/MC/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); - histos.add("QA/MC/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/MC/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Proton};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/MC/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); - histos.add("QA/MC/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); 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}); - - 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 spectraTOF"; + LOG(info) << "Size of the histograms in LstarAnalysis:"; histos.print(); } @@ -394,25 +422,44 @@ struct Lstaranalysis { } } - template - int getDetId(DetNameType const& name) + // Centralicity estimator selection + template + float centEst(ResoColl ResoEvents) { - 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; + float returnValue = -999.0; + switch (multEstimator) { + case 0: + returnValue = ResoEvents.centFT0M(); + break; + case 1: + returnValue = ResoEvents.centFT0A(); + break; + case 2: + returnValue = ResoEvents.centFT0C(); + break; + default: + returnValue = ResoEvents.centFT0M(); + break; } + return returnValue; + } + + // 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()) >= 3) { + if (std::abs(mcparticle.eta()) < 1) + return true; + } + } + } + return false; } template @@ -432,6 +479,8 @@ struct Lstaranalysis { return false; if (cTPCNClsFound && (track.tpcNClsFound() < cMinTPCNClsFound)) return false; + if (track.tpcNClsCrossedRows() < cfgMinCrossedRows) + return false; if (cfgHasTOF && !track.hasTOF()) return false; if (cfgPrimaryTrack && !track.isPrimaryTrack()) @@ -450,7 +499,9 @@ struct Lstaranalysis { return true; } - // PID selection old PID method + // LOGF(info, "AFTER: pt: %f, hasTOF: %d, TPCSigma: %f, TOFSigma: %f, boolTPC: %d, boolTOF: %d, bool: %d", pt, candidate.hasTOF(), + // candidate.tpcNSigmaPr(), candidate.tofNSigmaPr(), tpcPIDPassed, tofPIDPassed, tpcPIDPassed || tofPIDPassed); + template bool pTdependentPIDProton(const T& candidate) { @@ -461,69 +512,58 @@ struct Lstaranalysis { auto vProtonTPCTOFCombinedpTintv = static_cast>(protonTPCTOFCombinedpTintv); auto vProtonTPCTOFCombinedPIDcuts = static_cast>(protonTPCTOFCombinedPIDcuts); auto vProtonTOFPIDcuts = static_cast>(protonTOFPIDcuts); - auto lengthOfprotonTPCPIDpTintv = static_cast(vProtonTPCPIDpTintv.size()); - auto lengthOfprotonTOFPIDpTintv = static_cast(vProtonTOFPIDpTintv.size()); - auto lengthOfprotonTPCTOFCombinedPIDpTintv = static_cast(vProtonTPCTOFCombinedpTintv.size()); - bool tpcPIDPassed{false}, tofPIDPassed{false}; + float pt = candidate.pt(); + float ptSwitchToTOF = vProtonTPCPIDpTintv.back(); - // For Proton candidate: - // TPC PID - if (lengthOfprotonTPCPIDpTintv > 0) { - if (candidate.pt() > vProtonTPCPIDpTintv[lengthOfprotonTPCPIDpTintv - 1]) { - tpcPIDPassed = false; - } else { - for (int i = 0; i < lengthOfprotonTPCPIDpTintv; i++) { - if (candidate.pt() > vProtonTPCPIDpTintv[i] && candidate.pt() < vProtonTPCPIDpTintv[i + 1]) { - if (std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts[i]) - tpcPIDPassed = true; - } - } + bool tpcPIDPassed = false; + + // TPC PID (interval check) + for (size_t i = 0; i < vProtonTPCPIDpTintv.size() - 1; ++i) { + if (pt > vProtonTPCPIDpTintv[i] && pt < vProtonTPCPIDpTintv[i + 1]) { + if (std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts[i]) + tpcPIDPassed = true; } } - // bypass TOF - if (cByPassTOF && tpcPIDPassed) { - return true; + // TOF bypass option (for QA or MC) + if (cByPassTOF) { + return std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts.back(); } - // TOF PID + // Case 1: No TOF and pt ≤ threshold → accept only via TPC PID + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } + + // Case 2: No TOF but pt > threshold → reject + if (!candidate.hasTOF() && pt > ptSwitchToTOF) { + return false; + } + + // Case 3: Has TOF → use TPC + TOF (square or circular) if (candidate.hasTOF()) { if (cPIDcutType == 1) { - if (lengthOfprotonTOFPIDpTintv > 0) { - if (candidate.pt() > vProtonTOFPIDpTintv[lengthOfprotonTOFPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfprotonTOFPIDpTintv; i++) { - if (candidate.pt() < vProtonTOFPIDpTintv[i]) { - - if (std::abs(candidate.tofNSigmaPr()) < vProtonTOFPIDcuts[i] && std::abs(candidate.tpcNSigmaPr()) < cMaxTPCnSigmaProtonVETO) - tofPIDPassed = true; - } - } + // Rectangular cut + for (size_t i = 0; i < vProtonTOFPIDpTintv.size(); ++i) { + if (pt < vProtonTOFPIDpTintv[i]) { + if (std::abs(candidate.tofNSigmaPr()) < vProtonTOFPIDcuts[i] && + std::abs(candidate.tpcNSigmaPr()) < vProtonTPCPIDcuts.back()) + return true; } } - } else if (cPIDcutType == static_cast(2)) { - if (lengthOfprotonTPCTOFCombinedPIDpTintv > 0) { - if (candidate.pt() > vProtonTPCTOFCombinedpTintv[lengthOfprotonTPCTOFCombinedPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfprotonTPCTOFCombinedPIDpTintv; i++) { - if (candidate.pt() < vProtonTPCTOFCombinedpTintv[i]) { - if ((candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + candidate.tofNSigmaPr() * candidate.tofNSigmaPr()) < (vProtonTPCTOFCombinedPIDcuts[i] * vProtonTPCTOFCombinedPIDcuts[i])) - tofPIDPassed = true; - } - } + } else if (cPIDcutType == 2) { + // Circular cut + for (size_t i = 0; i < vProtonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vProtonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = + candidate.tpcNSigmaPr() * candidate.tpcNSigmaPr() + + candidate.tofNSigmaPr() * candidate.tofNSigmaPr(); + if (combinedSigma2 < vProtonTPCTOFCombinedPIDcuts[i] * vProtonTPCTOFCombinedPIDcuts[i]) + return true; } } } - } else { - tofPIDPassed = true; - } - - // TPC-TOF Combined PID - if (tpcPIDPassed && tofPIDPassed) { - return true; } return false; @@ -539,69 +579,61 @@ struct Lstaranalysis { auto vKaonTPCTOFCombinedpTintv = static_cast>(kaonTPCTOFCombinedpTintv); auto vKaonTPCTOFCombinedPIDcuts = static_cast>(kaonTPCTOFCombinedPIDcuts); auto vKaonTOFPIDcuts = static_cast>(kaonTOFPIDcuts); - auto lengthOfkaonTPCPIDpTintv = static_cast(vKaonTPCPIDpTintv.size()); - auto lengthOfkaonTOFPIDpTintv = static_cast(vKaonTOFPIDpTintv.size()); - auto lengthOfkaonTPCTOFCombinedPIDpTintv = static_cast(vKaonTPCTOFCombinedpTintv.size()); - bool tpcPIDPassed{false}, tofPIDPassed{false}; + float pt = candidate.pt(); + float ptSwitchToTOF = vKaonTPCPIDpTintv.back(); - // For Kaon candidate: - // TPC PID - if (lengthOfkaonTPCPIDpTintv > 0) { - if (candidate.pt() > vKaonTPCPIDpTintv[lengthOfkaonTPCPIDpTintv - 1]) { - tpcPIDPassed = false; - } else { - for (int i = 0; i < lengthOfkaonTPCPIDpTintv; i++) { - if (candidate.pt() > vKaonTPCPIDpTintv[i] && candidate.pt() < vKaonTPCPIDpTintv[i + 1]) { - if (std::abs(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts[i]) - tpcPIDPassed = true; - } + bool tpcPIDPassed = false; + + // TPC PID interval-based check + for (size_t i = 0; i < vKaonTPCPIDpTintv.size() - 1; ++i) { + if (pt > vKaonTPCPIDpTintv[i] && pt < vKaonTPCPIDpTintv[i + 1]) { + if (std::abs(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts[i]) { + tpcPIDPassed = true; + break; } } } - // bypass TOF - if (cByPassTOF && tpcPIDPassed) { - return true; + // TOF bypass option + if (cByPassTOF) { + return std::abs(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts.back(); } - // TOF PID + // Case 1: No TOF and pt ≤ ptSwitch → use TPC-only + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } + + // Case 2: No TOF but pt > ptSwitch → reject + if (!candidate.hasTOF() && pt > ptSwitchToTOF) { + return false; + } + + // Case 3: TOF is available → apply TPC+TOF PID logic if (candidate.hasTOF()) { if (cPIDcutType == 1) { - if (lengthOfkaonTOFPIDpTintv > 0) { - if (candidate.pt() > vKaonTOFPIDpTintv[lengthOfkaonTOFPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfkaonTOFPIDpTintv; i++) { - if (candidate.pt() < vKaonTOFPIDpTintv[i]) { - - if (std::abs(candidate.tofNSigmaKa()) < vKaonTOFPIDcuts[i] && std::abs(candidate.tpcNSigmaKa()) < cMaxTPCnSigmaKaonVETO) - tofPIDPassed = true; - } + // Rectangular cut + for (size_t i = 0; i < vKaonTOFPIDpTintv.size(); ++i) { + if (pt < vKaonTOFPIDpTintv[i]) { + if (std::abs(candidate.tofNSigmaKa()) < vKaonTOFPIDcuts[i] && + std::abs(candidate.tpcNSigmaKa()) < vKaonTPCPIDcuts.back()) { + return true; } } } - } else if (cPIDcutType == static_cast(2)) { - if (lengthOfkaonTPCTOFCombinedPIDpTintv > 0) { - if (candidate.pt() > vKaonTPCTOFCombinedpTintv[lengthOfkaonTPCTOFCombinedPIDpTintv - 1]) { - tofPIDPassed = false; - } else { - for (int i = 0; i < lengthOfkaonTPCTOFCombinedPIDpTintv; i++) { - if (candidate.pt() < vKaonTPCTOFCombinedpTintv[i]) { - if ((candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + candidate.tofNSigmaKa() * candidate.tofNSigmaKa()) < (vKaonTPCTOFCombinedPIDcuts[i] * vKaonTPCTOFCombinedPIDcuts[i])) - tofPIDPassed = true; - } + } else if (cPIDcutType == 2) { + // Circular cut + for (size_t i = 0; i < vKaonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vKaonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa() + + candidate.tofNSigmaKa() * candidate.tofNSigmaKa(); + if (combinedSigma2 < vKaonTPCTOFCombinedPIDcuts[i] * vKaonTPCTOFCombinedPIDcuts[i]) { + return true; } } } } - } else { - tofPIDPassed = true; - } - - // TPC-TOF Combined PID - if (tpcPIDPassed && tofPIDPassed) { - return true; } return false; @@ -720,7 +752,7 @@ struct Lstaranalysis { //// QA plots after the selection if constexpr (IsData) { // --- PID QA Proton histos.fill(HIST("QA/QAafter/Proton/TPC_Nsigma_pr_all"), multiplicity, trk1ptPr, trk1NSigmaPrTPC); - histos.fill(HIST("QA/QAafter/Proton/TPC_Signal_pr_all"), trk1ptPr, trk1.tpcSignal()); + histos.fill(HIST("QA/QAafter/Proton/TPC_Signal_pr_all"), trk1.tpcInnerParam(), trk1.tpcSignal()); if (isTrk1hasTOF) { histos.fill(HIST("QA/QAafter/Proton/TOF_Nsigma_pr_all"), multiplicity, trk1ptPr, trk1NSigmaPrTOF); histos.fill(HIST("QA/QAafter/Proton/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); @@ -737,7 +769,7 @@ struct Lstaranalysis { // --- PID QA Kaon histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTPC); - histos.fill(HIST("QA/QAafter/Kaon/TPC_Signal_ka_all"), trk2ptKa, trk2.tpcSignal()); + histos.fill(HIST("QA/QAafter/Kaon/TPC_Signal_ka_all"), trk2.tpcInnerParam(), trk2.tpcSignal()); if (isTrk2hasTOF) { histos.fill(HIST("QA/QAafter/Kaon/TOF_Nsigma_ka_all"), multiplicity, trk2ptKa, trk2NSigmaKaTOF); histos.fill(HIST("QA/QAafter/Kaon/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); @@ -771,9 +803,12 @@ struct Lstaranalysis { lDecayDaughter1 = LorentzVectorPtEtaPhiMass(trk1.pt(), trk1.eta(), trk1.phi(), massPr); lDecayDaughter2 = LorentzVectorPtEtaPhiMass(trk2.pt(), trk2.eta(), trk2.phi(), massKa); lResonance = lDecayDaughter1 + lDecayDaughter2; - // Rapidity cut - if (std::abs(lResonance.Rapidity()) > static_cast(0.5)) - continue; + + if constexpr (IsData || IsMix) { + // Rapidity cut + if (std::abs(lResonance.Rapidity()) > static_cast(0.5)) + continue; + } if (cfgCutsOnMother) { if (lResonance.Pt() >= cMaxPtMotherCut) // excluding candidates in overflow @@ -837,44 +872,68 @@ struct Lstaranalysis { // MC if constexpr (IsMC) { - // LOG(info) << "trk1 pdgcode: " << trk1.pdgCode() << "trk2 pdgcode: " << trk2.pdgCode() << endl; - const auto mctrack1 = trk1.mcParticle(); - const auto mctrack2 = trk2.mcParticle(); + // ------ Temporal lambda function to prevent error in build + auto getMothersIndeces = [&](auto const& theMcParticle) { + std::vector lMothersIndeces{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother index lMother: %d", lMother.globalIndex()); + lMothersIndeces.push_back(lMother.globalIndex()); + } + return lMothersIndeces; + }; + auto getMothersPDGCodes = [&](auto const& theMcParticle) { + std::vector lMothersPDGs{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother pdgcode lMother: %d", lMother.pdgCode()); + lMothersPDGs.push_back(lMother.pdgCode()); + } + return lMothersPDGs; + }; + // ------ + std::vector motherstrk1 = {-1, -1}; + std::vector mothersPDGtrk1 = {-1, -1}; + + std::vector motherstrk2 = {-1, -1}; + std::vector mothersPDGtrk2 = {-1, -1}; + + // + // Get the MC particle + const auto& mctrk1 = trk1.mcParticle(); + if (mctrk1.has_mothers()) { + motherstrk1 = getMothersIndeces(mctrk1); + mothersPDGtrk1 = getMothersPDGCodes(mctrk1); + } + while (motherstrk1.size() > 2) { + motherstrk1.pop_back(); + mothersPDGtrk1.pop_back(); + } + + const auto& mctrk2 = trk2.mcParticle(); + if (mctrk2.has_mothers()) { + motherstrk2 = getMothersIndeces(mctrk2); + mothersPDGtrk2 = getMothersPDGCodes(mctrk2); + } + while (motherstrk2.size() > 2) { + motherstrk2.pop_back(); + mothersPDGtrk2.pop_back(); + } - if (std::abs(mctrack1.pdgCode()) != PDG_t::kProton || std::abs(mctrack2.pdgCode()) != PDG_t::kKPlus) + if (std::abs(mctrk1.pdgCode()) != 2212 || std::abs(mctrk2.pdgCode()) != 321) continue; - bool isMotherOk = false; - int pdgCodeMother = -999; - if (!trk1.has_mcParticle() || !trk2.has_mcParticle()) + if (motherstrk1[0] != motherstrk2[0]) // Same mother continue; - for (const auto& mothertrack1 : mctrack1.template mothers_as()) { - for (const auto& mothertrack2 : mctrack2.template mothers_as()) { - if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) - continue; - if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) - continue; - - if (std::abs(mothertrack1.pdgCode()) == kLambda1520PDG) // Pb PDG code - continue; - - pdgCodeMother = mothertrack1.pdgCode(); - - isMotherOk = true; - } - } + if (std::abs(mothersPDGtrk1[0]) != 102134) + continue; - // if (motherdTracks1.id() != motherdTracks2.id()) // Same mother - // continue; - // if (std::abs(motherdTracks1.pdgCode()) != kLambda1520PDG) - // continue; + // LOGF(info, "mother trk1 id: %d, mother trk1: %d, trk1 id: %d, trk1 pdgcode: %d, mother trk2 id: %d, mother trk2: %d, trk2 id: %d, trk2 pdgcode: %d", motherstrk1[0], mothersPDGtrk1[0], trk1.globalIndex(), mctrk1.pdgCode(), motherstrk2[0], mothersPDGtrk2[0], trk2.globalIndex(), mctrk2.pdgCode()); - if (std::abs(lResonance.Eta()) > cEtacutMC) // eta cut + if (cUseEtacutMC && std::abs(lResonance.Eta()) > cEtacutMC) // eta cut continue; - if (!isMotherOk) + if (cUseRapcutMC && std::abs(lResonance.Rapidity()) > static_cast(0.5)) // rapidity cut continue; histos.fill(HIST("QA/MC/h2RecoEtaPt_after"), lResonance.Eta(), lResonance.Pt()); @@ -896,7 +955,7 @@ struct Lstaranalysis { } // MC histograms - if (pdgCodeMother > 0) { + if (mothersPDGtrk1[0] > 0) { histos.fill(HIST("Result/MC/h3lambda1520Recoinvmass"), multiplicity, lResonance.Pt(), lResonance.M()); } else { histos.fill(HIST("Result/MC/h3antilambda1520Recoinvmass"), multiplicity, lResonance.Pt(), lResonance.M()); @@ -922,16 +981,11 @@ struct Lstaranalysis { } void processData(EventCandidates::iterator const& collision, - TrackCandidates const& tracks, - BCsWithTimestamps const&) + TrackCandidates const& tracks) { if (!colCuts.isSelected(collision)) // Default event selection return; - centrality = getCentrality(collision); - // if (centrality < cfgEventCentralityMin || centrality > cfgEventCentralityMax) - // return; - colCuts.fillQA(collision); if (cFilladditionalQAeventPlots) @@ -941,69 +995,71 @@ struct Lstaranalysis { PROCESS_SWITCH(Lstaranalysis, processData, "Process Event for data without partition", false); void processMC(MCEventCandidates::iterator const& collision, - MCTrackCandidates const& tracks, - BCsWithTimestamps const&) + aod::McCollisions const&, + MCTrackCandidates const& tracks, aod::McParticles const&) { - if (!colCuts.isSelected(collision) || (std::abs(collision.posZ()) > cZvertCutMC)) // MC event selection, all cuts missing vtx cut + colCuts.fillQA(collision); + + if (std::abs(collision.posZ()) > cZvertCutMC) // Z-vertex cut return; + fillHistograms(collision, tracks, tracks); } PROCESS_SWITCH(Lstaranalysis, processMC, "Process Event for MC Light without partition", false); - void processMCTrue(EventCandidates::iterator const& collision, McParticles const& mcParticles) + Partition selectedMCParticles = (nabs(aod::mcparticle::pdgCode) == 102134); // Lambda(1520) + + void processMCTrue(MCEventCandidates::iterator const& collision, aod::McCollisions const&, aod::McParticles const& mcParticles) { + bool isInAfterAllCuts = colCuts.isSelected(collision); + bool inVtx10 = (std::abs(collision.mcCollision().posZ()) > 10.) ? false : true; + bool isTriggerTVX = collision.selection_bit(aod::evsel::kIsTriggerTVX); + bool isSel8 = collision.sel8(); + bool isTrueINELgt0 = isTrueINEL0(collision, mcParticles); + centrality = centEst(collision); + auto multiplicity = collision.centFT0M(); - LorentzVectorPtEtaPhiMass lDecayDaughter1, lDecayDaughter2, vresoParent; + auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); // Not related to the real collisions - for (const auto& part : mcParticles) { // loop over all MC particles + for (const auto& part : mcParts) { // loop over all MC particles + if (std::abs(part.pdgCode()) != kLambda1520PDG) // Lambda1520(0) continue; - auto kDaughters = part.daughters_as(); - if (kDaughters.size() != static_cast(2)) { - continue; + std::vector daughterPDGs; + if (part.has_daughters()) { + auto daughter01 = mcParticles.rawIteratorAt(part.daughtersIds()[0] - mcParticles.offset()); + auto daughter02 = mcParticles.rawIteratorAt(part.daughtersIds()[1] - mcParticles.offset()); + daughterPDGs = {daughter01.pdgCode(), daughter02.pdgCode()}; + } else { + daughterPDGs = {-1, -1}; } - // bool pass1 = std::abs(part.daughterPDG1()) == 321 || std::abs(part.daughterPDG2()) == 321; // At least one decay to Kaon - // bool pass2 = std::abs(part.daughterPDG1()) == 2212 || std::abs(part.daughterPDG2()) == 2212; // At least one decay to Proton - - auto daughtp = false; - auto daughtk = false; - for (const auto& kCurrentDaughter : kDaughters) { - if (!kCurrentDaughter.isPhysicalPrimary()) - break; - - if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kProton) { // Proton - daughtp = true; - lDecayDaughter1 = LorentzVectorPtEtaPhiMass(kCurrentDaughter.pt(), kCurrentDaughter.eta(), kCurrentDaughter.phi(), massPr); - } else if (std::abs(kCurrentDaughter.pdgCode()) == PDG_t::kKPlus) { - daughtk = true; - lDecayDaughter2 = LorentzVectorPtEtaPhiMass(kCurrentDaughter.pt(), kCurrentDaughter.eta(), kCurrentDaughter.phi(), massKa); - } - } + bool pass1 = std::abs(daughterPDGs[0]) == kKPlus || std::abs(daughterPDGs[1]) == kKPlus; // At least one decay to Kaon + bool pass2 = std::abs(daughterPDGs[0]) == kProton || std::abs(daughterPDGs[1]) == kProton; // At least one decay to Proton // Checking if we have both decay products - if (!daughtp || !daughtk) + if (!pass1 || !pass2) continue; - vresoParent = lDecayDaughter1 + lDecayDaughter2; + // LOGF(info, "Part PDG: %d", part.pdgCode(), "DAU_ID1: %d", pass1, "DAU_ID2: %d", pass2); - histos.fill(HIST("QA/MC/h2GenEtaPt_beforeanycut"), vresoParent.Eta(), part.pt()); - histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeanycut"), vresoParent.Phi(), part.y()); + histos.fill(HIST("QA/MC/h2GenEtaPt_beforeanycut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeanycut"), part.phi(), part.y()); - if (std::abs(part.y()) > static_cast(0.5)) // rapidity cut + if (cUseRapcutMC && std::abs(part.y()) > static_cast(0.5)) // rapidity cut continue; - histos.fill(HIST("QA/MC/h2GenEtaPt_beforeEtacut"), vresoParent.Eta(), part.pt()); - histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeEtacut"), vresoParent.Phi(), part.y()); + histos.fill(HIST("QA/MC/h2GenEtaPt_afterRapcut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterRapcut"), part.phi(), part.y()); - if (std::abs(vresoParent.Eta()) > cEtacutMC) // eta cut + if (cUseEtacutMC && std::abs(part.eta()) > cEtacutMC) // eta cut continue; - histos.fill(HIST("QA/MC/h2GenEtaPt_afterEtacut"), vresoParent.Eta(), part.pt()); - histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterEtacut"), vresoParent.Phi(), part.y()); + 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) @@ -1011,28 +1067,28 @@ struct Lstaranalysis { else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 0, part.pt(), multiplicity); - if (collision.posZ() > static_cast(10.)) // INEL10 + if (inVtx10) // INEL10 { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 1, part.pt(), multiplicity); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 1, part.pt(), multiplicity); } - if (collision.posZ() > static_cast(10.) && collision.sel8()) // INEL>10, vtx10 + if (inVtx10 && isSel8) // INEL>10, vtx10 { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 2, part.pt(), multiplicity); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 2, part.pt(), multiplicity); } - if (collision.posZ() > static_cast(10.) && collision.selection_bit(aod::evsel::kIsTriggerTVX)) // vtx10, TriggerTVX + if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 3, part.pt(), multiplicity); else histos.fill(HIST("Result/MC/Genantilambda1520pt"), 3, part.pt(), multiplicity); } - if (colCuts.isSelected(collision)) // after all event selection + if (isInAfterAllCuts) // after all event selection { if (part.pdgCode() > 0) histos.fill(HIST("Result/MC/Genlambda1520pt"), 4, part.pt(), multiplicity); @@ -1040,6 +1096,45 @@ struct Lstaranalysis { histos.fill(HIST("Result/MC/Genantilambda1520pt"), 4, part.pt(), multiplicity); } } + + // QA for Trigger efficiency + histos.fill(HIST("Event/hMCEventIndices"), centrality, kINEL); + if (inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kINEL10); + if (isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kINELg0); + if (inVtx10 && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kINELg010); + + // TVX MB trigger + if (isTriggerTVX) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kTrig); + if (isTriggerTVX && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kTrig10); + if (isTriggerTVX && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kTrigINELg0); + if (isTriggerTVX && isTrueINELgt0 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kTrigINELg010); + + // Sel8 event selection + if (isSel8) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kSel8); + if (isSel8 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kSel810); + if (isSel8 && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kSel8INELg0); + if (isSel8 && isTrueINELgt0 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kSel8INELg010); + + // CollisionCuts selection + if (isInAfterAllCuts) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kAllCuts); + if (isInAfterAllCuts && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kAllCuts10); + if (isInAfterAllCuts && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kAllCutsINELg0); + if (isInAfterAllCuts && isTrueINELgt0 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, kAllCutsINELg010); } PROCESS_SWITCH(Lstaranalysis, processMCTrue, "Process Event for MC only", false); @@ -1048,8 +1143,7 @@ struct Lstaranalysis { BinningTypeVtxZT0M colBinning{{cfgVtxBins, cfgMultBins}, true}; void processME(EventCandidates const& collision, - TrackCandidates const& tracks, - BCsWithTimestamps const&) + TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); SameKindPair pairs{colBinning, nEvtMixing, -1, collision, tracksTuple, &cache}; // -1 is the number of the bin to skip diff --git a/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx new file mode 100644 index 00000000000..0348751dae9 --- /dev/null +++ b/PWGLF/Tasks/Resonances/lambda1520analysisinpp.cxx @@ -0,0 +1,1252 @@ +// 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 lambda1520analysisinpp.cxx +/// \brief This standalone task reconstructs track-track decay of lambda(1520) resonance candidate +/// \author Hirak Kumar Koley + +#include "PWGLF/Utils/collisionCuts.h" + +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + +#include "Math/Vector4D.h" +#include "TPDGCode.h" +#include "TRandom.h" + +#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 LorentzVectorPtEtaPhiMass = ROOT::Math::PtEtaPhiMVector; + +enum { + Inel = 1, + Inel10, + Inelg0, + Inelg010, + Trig, + Trig10, + TrigINELg0, + TrigINELg010, + Sel8, + Sel810, + Sel8INELg0, + Sel8INELg010, + AllCuts, + AllCuts10, + AllCutsINELg0, + AllCutsINELg010, +}; + +enum TrackSelectionType { + AllTracks = 0, + GlobalTracks, + GlobalTracksWoPtEta, + GlobalTracksWoDCA, + QualityTracks, + InAcceptanceTracks, +}; + +enum PIDCutType { + SquareType = 1, + CircularType, +}; + +struct Lambda1520analysisinpp { + // Define slice per Resocollision + SliceCache cache; + Preslice perCollision = o2::aod::track::collisionId; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + Service pdg; + + /// Event cuts + o2::analysis::CollisonCuts colCuts; + + struct : ConfigurableGroup { + 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"}; + } configEvents; + + struct : ConfigurableGroup { + // Pre-selection Track cuts + Configurable trackSelection{"trackSelection", 0, "Track selection: 0 -> No Cut, 1 -> kGlobalTrack, 2 -> kGlobalTrackWoPtEta, 3 -> kGlobalTrackWoDCA, 4 -> kQualityTracks, 5 -> kInAcceptanceTracks"}; + Configurable cMinPtcut{"cMinPtcut", 0.15f, "Minimal pT for tracks"}; + Configurable cMinTPCNClsFound{"cMinTPCNClsFound", 120, "minimum TPCNClsFound value for good track"}; + Configurable cfgCutEta{"cfgCutEta", 0.8f, "Eta range for tracks"}; + Configurable cfgCutRapidity{"cfgCutRapidity", 0.5f, "rapidity range for particles"}; + Configurable cfgMinCrossedRows{"cfgMinCrossedRows", 70, "min crossed rows for good track"}; + + // DCA Selections + // DCAr to PV + Configurable cMaxDCArToPVcut{"cMaxDCArToPVcut", 0.1f, "Track DCAr cut to PV Maximum"}; + // DCAz to PV + Configurable cMaxDCAzToPVcut{"cMaxDCAzToPVcut", 0.1f, "Track DCAz cut to PV Maximum"}; + + // 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 cfgHasTOF{"cfgHasTOF", false, "Require TOF"}; + Configurable cfgUseTPCRefit{"cfgUseTPCRefit", false, "Require TPC Refit"}; + Configurable cfgUseITSRefit{"cfgUseITSRefit", false, "Require ITS Refit"}; + Configurable cTPCNClsFound{"cTPCNClsFound", false, "Switch to turn on/off TPCNClsFound cut"}; + Configurable cDCAr7SigCut{"cDCAr7SigCut", false, "Track DCAr 7 Sigma cut to PV Maximum"}; + } configTracks; + + struct : ConfigurableGroup { + /// PID Selections + Configurable pidnSigmaPreSelectionCut{"pidnSigmaPreSelectionCut", 4.0f, "pidnSigma Cut for pre-selection of tracks"}; + Configurable cByPassTOF{"cByPassTOF", false, "By pass TOF PID selection"}; // By pass TOF PID selection + Configurable cPIDcutType{"cPIDcutType", 2, "cPIDcutType = 1 for square cut, 2 for circular cut"}; // By pass TOF PID selection + + // Kaon + Configurable> kaonTPCPIDpTintv{"kaonTPCPIDpTintv", {0.5f}, "pT intervals for Kaon TPC PID cuts"}; + Configurable> kaonTPCPIDcuts{"kaonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; + Configurable> kaonTOFPIDpTintv{"kaonTOFPIDpTintv", {999.0f}, "pT intervals for Kaon TOF PID cuts"}; + Configurable> kaonTOFPIDcuts{"kaonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable> kaonTPCTOFCombinedpTintv{"kaonTPCTOFCombinedpTintv", {999.0f}, "pT intervals for Kaon TPC-TOF PID cuts"}; + Configurable> kaonTPCTOFCombinedPIDcuts{"kaonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Kaon TPC-TOF PID cuts"}; + + // Proton + Configurable> protonTPCPIDpTintv{"protonTPCPIDpTintv", {0.9f}, "pT intervals for Kaon TPC PID cuts"}; + Configurable> protonTPCPIDcuts{"protonTPCPIDcuts", {2}, "nSigma list for Kaon TPC PID cuts"}; + Configurable> protonTOFPIDpTintv{"protonTOFPIDpTintv", {999.0f}, "pT intervals for Kaon TOF PID cuts"}; + Configurable> protonTOFPIDcuts{"protonTOFPIDcuts", {2}, "nSigma list for Kaon TOF PID cuts"}; + Configurable> protonTPCTOFCombinedpTintv{"protonTPCTOFCombinedpTintv", {999.0f}, "pT intervals for Proton TPC-TOF PID cuts"}; + Configurable> protonTPCTOFCombinedPIDcuts{"protonTPCTOFCombinedPIDcuts", {2}, "nSigma list for Proton TPC-TOF PID cuts"}; + } configPID; + + struct : ConfigurableGroup { + /// 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"}; + + // Rotational background + Configurable rotationalcut{"rotationalcut", 10, "Cut value (Rotation angle pi - pi/cut and pi + pi/cut)"}; + Configurable cNofRotations{"cNofRotations", 3, "Number of random rotations in the rotational background"}; + Configurable cfgRotPr{"cfgRotPr", true, "rotate Proton"}; + } configBkg; + + // Additional purity check + Configurable crejectPion{"crejectPion", false, "Switch to turn on/off pion contamination"}; + Configurable cUseOpeningAngleCut{"cUseOpeningAngleCut", false, "Kinematic Cuts for p-K pair opening angle"}; + Configurable cMinOpeningAngle{"cMinOpeningAngle", 1.4f, "Minimum opening angle between daughters"}; + Configurable cMaxOpeningAngle{"cMaxOpeningAngle", 2.4f, "Maximum opening angle between daughters"}; + Configurable cfgUseDeltaEtaPhiCuts{"cfgUseDeltaEtaPhiCuts", false, "Switch to turn on/off delta eta and delta phi cuts"}; + 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"}; + + // cuts on mother + Configurable cfgUseCutsOnMother{"cfgUseCutsOnMother", false, "Enable additional cuts on mother"}; + Configurable cMaxPtMotherCut{"cMaxPtMotherCut", 10.0f, "Maximum pt of mother cut"}; + Configurable cMaxMinvMotherCut{"cMaxMinvMotherCut", 3.0f, "Maximum Minv of mother cut"}; + Configurable cMaxDeltaEtaCut{"cMaxDeltaEtaCut", 0.7f, "Maximum deltaEta between daughters"}; + Configurable cMaxDeltaPhiCut{"cMaxDeltaPhiCut", 1.5f, "Maximum deltaPhi between daughters"}; + + // switches + Configurable cFillMultQA{"cFillMultQA", false, "Turn on/off additional QA plots"}; + Configurable cFilladditionalQAeventPlots{"cFilladditionalQAeventPlots", false, "Additional QA event plots"}; + Configurable cFilladditionalMEPlots{"cFilladditionalMEPlots", false, "Additional Mixed event plots"}; + Configurable cFilldeltaEtaPhiPlots{"cFilldeltaEtaPhiPlots", false, "Enamble additional cuts on daughters"}; + Configurable cFill1DQAs{"cFill1DQAs", false, "Invariant mass 1D"}; + Configurable centEstimator{"centEstimator", 0, "Select centrality estimator: 0 - FT0M, 1 - FT0A, 2 - FT0C"}; + + TRandom* rn = new TRandom(); + + // Pre-filters for efficient process + Filter zVtxFilter = (nabs(o2::aod::collision::posZ) <= configEvents.cfgEvtZvtx); + Filter collisionFilterMC = nabs(aod::mccollision::posZ) <= configEvents.cfgEvtZvtx; + // Filter centralityFilter = nabs(aod::cent::centFT0C) <= cfg_Event_CentralityMax; + // Filter triggerFilter = (o2::aod::evsel::sel8 == true); + + Filter tofPIDFilter = aod::track::tofExpMom < 0.0f || ((aod::track::tofExpMom > 0.0f) && (/* (nabs(aod::pidtof::tofNSigmaPi) < configPID.pidnSigmaPreSelectionCut) || */ (nabs(aod::pidtof::tofNSigmaKa) < configPID.pidnSigmaPreSelectionCut) || (nabs(aod::pidtof::tofNSigmaPr) < configPID.pidnSigmaPreSelectionCut))); // TOF + Filter tpcPIDFilter = /* nabs(aod::pidtpc::tpcNSigmaPi) < configPID.pidnSigmaPreSelectionCut || */ nabs(aod::pidtpc::tpcNSigmaKa) < configPID.pidnSigmaPreSelectionCut || nabs(aod::pidtpc::tpcNSigmaPr) < configPID.pidnSigmaPreSelectionCut; // TPC + Filter trackFilter = (configTracks.trackSelection == AllTracks) || + ((configTracks.trackSelection == GlobalTracks) && requireGlobalTrackInFilter()) || + ((configTracks.trackSelection == GlobalTracksWoPtEta) && requireGlobalTrackWoPtEtaInFilter()) || + ((configTracks.trackSelection == GlobalTracksWoDCA) && requireGlobalTrackWoDCAInFilter()) || + ((configTracks.trackSelection == QualityTracks) && requireQualityTracksInFilter()) || + ((configTracks.trackSelection == InAcceptanceTracks) && requireTrackCutInFilter(TrackSelectionFlags::kInAcceptanceTracks)); + + Filter acceptanceFilter = (nabs(aod::track::eta) < configTracks.cfgCutEta && nabs(aod::track::pt) > configTracks.cMinPtcut); + // Filter DCAcutFilter = (nabs(aod::track::dcaXY) < configTracks.cfgCutDCAxy) && (nabs(aod::track::dcaZ) < configTracks.cfgCutDCAz); + // Filter primarytrackFilter = requirePVContributor() && requirePrimaryTrack() && requireGlobalTrackWoDCA(); + + using EventCandidates = soa::Join; + using TrackCandidates = soa::Filtered>; + + using MCEventCandidates = soa::Join; + using MCTrackCandidates = soa::Filtered>; + + /// Figures + ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0f, 0.1f, 0.12f, 0.14f, 0.16f, 0.18f, 0.2f, 0.25f, 0.3f, 0.35f, 0.4f, 0.45f, 0.5f, 0.55f, 0.6f, 0.65f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 0.95f, 1.0f, 1.1f, 1.2f, 1.25f, 1.3f, 1.4f, 1.5f, 1.6f, 1.7f, 1.75f, 1.8f, 1.9f, 2.0f, 2.1f, 2.2f, 2.3f, 2.4f, 2.5f, 2.6f, 2.7f, 2.8f, 2.9f, 3.0f, 3.1f, 3.2f, 3.3f, 3.4f, 3.6f, 3.7f, 3.8f, 3.9f, 4.0f, 4.1f, 4.2f, 4.5f, 4.6f, 4.8f, 4.9f, 5.0f, 5.5f, 5.6f, 6.0f, 6.4f, 6.5f, 7.0f, 7.2f, 8.0f, 9.0f, 9.5f, 9.6f, 10.0f, 11.0f, 11.5f, 12.0f, 13.0f, 14.0f, 14.4f, 15.0f, 16.0f, 18.0f, 19.2f, 20.0f}, "Binning of the pT axis"}; + ConfigurableAxis binsPtQA{"binsPtQA", {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.2f, 2.4f, 2.6f, 2.8f, 3.0f, 3.2f, 3.4f, 3.6f, 3.8f, 4.0f, 4.2f, 4.4f, 4.6f, 4.8f, 5.0f, 5.2f, 5.4f, 5.6f, 5.8f, 6.0f, 6.2f, 6.4f, 6.6f, 6.8f, 7.0f, 7.2f, 7.4f, 7.6f, 7.8f, 8.0f, 8.2f, 8.4f, 8.6f, 8.8f, 9.0f, 9.2f, 9.4f, 9.6f, 9.8f, 10.0f, 10.2f, 10.4f, 10.6f, 10.8f, 11.0f, 11.2f, 11.4f, 11.6f, 11.8f, 12.0f, 12.2f, 12.4f, 12.6f, 12.8f, 13.0f, 13.2f, 13.4f, 13.6f, 13.8f, 14.0f, 14.2f, 14.4f, 14.6f, 14.8f, 15.0f, 15.2f, 15.4f, 15.6f, 15.8f, 16.0f, 16.2f, 16.4f, 16.6f, 16.8f, 17.0f, 17.2f, 17.4f, 17.6f, 17.8f, 18.0f, 18.2f, 18.4f, 18.6f, 18.8f, 19.0f, 19.2f, 19.4f, 19.6f, 19.8f, 20.0f}, "Binning of the pT axis"}; + ConfigurableAxis binsEta{"binsEta", {150, -1.5f, 1.5f}, ""}; + ConfigurableAxis binsMass{"binsMass", {70, 1.3f, 2.0f}, "Invariant Mass (GeV/#it{c}^2)"}; + ConfigurableAxis binsMult{"binsMult", {105, 0.0f, 105.0f}, "mult_{FT0M}"}; + ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2f, 0.2f}, ""}; + ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2f, 0.2f}, ""}; + ConfigurableAxis binsTPCXrows{"binsTPCXrows", {100, 60, 160}, ""}; + ConfigurableAxis binsnSigma{"binsnSigma", {130, -6.5f, 6.5f}, ""}; + ConfigurableAxis binsnTPCSignal{"binsnTPCSignal", {1000, 0, 1000}, ""}; + ConfigurableAxis binsEtaPhi{"binsEtaPhi", {350, -3.5f, 3.5f}, ""}; + + void init(framework::InitContext&) + { + colCuts.setCuts(configEvents.cfgEvtZvtx, configEvents.cfgEvtTriggerCheck, configEvents.cfgEvtOfflineCheck, /*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.printCuts(); + + // axes + AxisSpec axisPt{binsPt, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisPtQA{binsPtQA, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec axisEta{binsEta, "#eta"}; + AxisSpec axisRap{binsEta, "#it{y}"}; + AxisSpec axisMassLambda1520{binsMass, "Invariant Mass (GeV/#it{c}^2)"}; + AxisSpec axisMult{binsMult, "mult_{V0M}"}; + 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 axisEtaPhi{binsEtaPhi, ""}; + AxisSpec axisPhi{350, 0, 7, "#Phi"}; + AxisSpec axisMultMix{configBkg.cfgMultBins, "Multiplicity"}; + AxisSpec axisVtxMix{configBkg.cfgVtxBins, "Vertex Z (cm)"}; + AxisSpec idxMCAxis = {26, -0.5f, 25.5f, "Index"}; + + if (cFilladditionalQAeventPlots) { + // event histograms + if (doprocessData) { + 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 + if (doprocessME) { + + // Histograms for Mixed Event Pool characteristics + histos.add("QAevent/hMixPool_VtxZ", "Mixed Event Pool: Vertex Z;Vtx Z (cm);Counts", HistType::kTH1F, {axisVtxMix}); + histos.add("QAevent/hMixPool_Multiplicity", "Mixed Event Pool: Multiplicity;Multiplicity;Counts", HistType::kTH1F, {axisMultMix}); + histos.add("QAevent/hMixPool_VtxZ_vs_Multiplicity", "Mixed Event Pool: Vertex Z vs Multiplicity;Counts", HistType::kTH2F, {axisVtxMix, axisMultMix}); + + histos.add("QAevent/hPairsCounterMixedE", "total valid no. of pairs mixedE", HistType::kTH1F, {{1, 0.5f, 1.5f}}); + histos.add("QAevent/hVertexZMixedE", "Collision Vertex Z position", HistType::kTH1F, {{100, -15.0f, 15.0f}}); + 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 (doprocessData) { + // Track QA before cuts + // --- Track + histos.add("QA/QAbefore/Track/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_ka", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;{#sigma_{TOF}^{Proton}};{#sigma_{TPC}^{Proton}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/TPConly_Nsigma_pr", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAbefore/Track/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAbefore/Track/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAbefore/Track/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAbefore/Track/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAbefore/Track/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + + if (cFillMultQA) { + // Multiplicity correlation calibrations + histos.add("MultCalib/centGloPVpr", "Centrality vs Global-Tracks", kTHnSparseF, {{110, 0, 110, "Centrality"}, {500, 0, 5000, "Global Tracks"}, {500, 0, 5000, "PV tracks"}}); + histos.add("MultCalib/centGloPVka", "Centrality vs Global-Tracks", kTHnSparseF, {{110, 0, 110, "Centrality"}, {500, 0, 5000, "Global Tracks"}, {500, 0, 5000, "PV tracks"}}); + } + + // PID QA after cuts + // --- Kaon + histos.add("QA/QAafter/Kaon/TOF_TPC_Map_ka_all", "TOF + TPC Combined PID for Kaon;{#sigma_{TOF}^{Kaon}};{#sigma_{TPC}^{Kaon}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Kaon/dcaZ", "DCA_{Z} distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm); ", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Kaon/dcaXY", "DCA_{XY} momentum distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Kaon/TPC_CR", "# TPC Xrows distribution of selected Kaons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Kaon/pT", "pT distribution of Kaons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Kaon/eta", "#eta distribution of Kaons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Kaon/TPC_Signal_ka_all", "TPC Signal for Kaon;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Kaon/TPCnclusterPhika", "TPC ncluster vs phi", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0.0f, 6.28f, "#phi"}}); + + // --- Proton + histos.add("QA/QAafter/Proton/TOF_TPC_Map_pr_all", "TOF + TPC Combined PID for Proton;{#sigma_{TOF}^{Proton}};{#sigma_{TPC}^{Proton}}", {HistType::kTH2F, {axisPIDQA, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTH2F, {axisPt, axisPIDQA}}); + histos.add("QA/QAafter/Proton/dcaZ", "DCA_{Z} distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{Z} (cm);", HistType::kTH2F, {axisPt, axisDCAz}); + histos.add("QA/QAafter/Proton/dcaXY", "DCA_{XY} momentum distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); DCA_{XY} (cm);", HistType::kTH2F, {axisPt, axisDCAxy}); + histos.add("QA/QAafter/Proton/TPC_CR", "# TPC Xrows distribution of selected Protons; #it{p}_{T} (GeV/#it{c}); TPC X rows", HistType::kTH2F, {axisPt, axisTPCXrow}); + histos.add("QA/QAafter/Proton/pT", "pT distribution of Protons; #it{p}_{T} (GeV/#it{c}); Counts;", {HistType::kTH1F, {axisPt}}); + histos.add("QA/QAafter/Proton/eta", "#eta distribution of Protons; #eta; Counts;", {HistType::kTH1F, {axisEta}}); + histos.add("QA/QAafter/Proton/TPC_Signal_pr_all", "TPC Signal for Proton;#it{p} (GeV/#it{c});TPC Signal (A.U.)", {HistType::kTH2F, {axisPt, axisTPCSignal}}); + histos.add("QA/QAafter/Proton/TPCnclusterPhipr", "TPC ncluster vs phi", kTHnSparseF, {{160, 0, 160, "TPC nCluster"}, {63, 0.0f, 6.28f, "#phi"}}); + + // Mass QA 1D for quick check + if (cFill1DQAs) { + histos.add("Result/Data/lambda1520invmass", "Invariant mass of #Lambda(1520) K^{#pm}p^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/antilambda1520invmass", "Invariant mass of #Lambda(1520) K^{#mp}p^{#pm}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/lambda1520invmassLSPP", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K+ + Pr + histos.add("Result/Data/lambda1520invmassLSMM", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K- + anti-Pr + } + // eta phi QA + if (cFilldeltaEtaPhiPlots) { + histos.add("QAbefore/deltaEta", "deltaEta of kaon and proton candidates", HistType::kTH1F, {axisEtaPhi}); + histos.add("QAbefore/deltaPhi", "deltaPhi of kaon and proton candidates", HistType::kTH1F, {axisEtaPhi}); + + histos.add("QAafter/deltaEta", "deltaEta of kaon and proton candidates", HistType::kTH1F, {axisEtaPhi}); + histos.add("QAafter/deltaPhi", "deltaPhi of kaon and proton candidates", HistType::kTH1F, {axisEtaPhi}); + + histos.add("QAafter/PhiPrafter", "Phi of proton candidates", HistType::kTH1F, {axisPhi}); + histos.add("QAafter/PhiKaafter", "Phi of kaon candidates", HistType::kTH1F, {axisPhi}); + } + + // 3d histogram + histos.add("Result/Data/h3lambda1520invmass", "Invariant mass of #Lambda(1520) K^{#pm}p^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3antilambda1520invmass", "Invariant mass of #Lambda(1520) K^{#mp}p^{#pm}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3lambda1520invmassLSPP", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); // K+ + Pr + histos.add("Result/Data/h3lambda1520invmassLSMM", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); // K- + anti-Pr + } + + if (doprocessRotational) { + if (cFill1DQAs) { + histos.add("Result/Data/lambda1520InvMassRotation", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K+ + Pr + histos.add("Result/Data/antilambda1520InvMassRotation", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K- + anti-Pr + } + histos.add("Result/Data/h3lambda1520InvMassRotation", "Invariant mass of #Lambda(1520) rotation", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3antilambda1520InvMassRotation", "Invariant mass of #Lambda(1520) rotation", kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); + } + // Mixed event histograms + if (doprocessME) { + if (cFill1DQAs) { + histos.add("Result/Data/lambda1520invmassME_UnlikeSign", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); + histos.add("Result/Data/antilambda1520invmassME_UnlikeSign", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); + } + histos.add("Result/Data/h3lambda1520invmassME_UnlikeSign", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); + histos.add("Result/Data/h3antilambda1520invmassME_UnlikeSign", "Invariant mass of #Lambda(1520) mixed event K^{#pm}p^{#mp}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); + + if (cFilladditionalMEPlots) { + if (cFill1DQAs) { + histos.add("Result/Data/lambda1520invmassME_LSPP", "Invariant mass of #Lambda(1520) Like Sign Method K^{#plus}p^{#plus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K+ + Pr + histos.add("Result/Data/lambda1520invmassME_LSMM", "Invariant mass of #Lambda(1520) Like Sign Method K^{#minus}p^{#minus}; Invariant Mass (GeV/#it{c}^2); Counts;", {HistType::kTH1F, {axisMassLambda1520}}); // K- + anti-Pr + } + histos.add("Result/Data/h3lambda1520invmassME_LSPP", "Invariant mass of #Lambda(1520) mixed event Like Sign Method K^{#plus}p^{#plus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); // K+ + Pr + histos.add("Result/Data/h3lambda1520invmassME_LSMM", "Invariant mass of #Lambda(1520) mixed event Like Sign Method K^{#minus}p^{#minus}", HistType::kTHnSparseF, {axisMult, axisPt, axisMassLambda1520}); // K- + anti-Pr + } + } + + // MC QA + histos.add("Event/hMCEventIndices", "hMCEventIndices", kTH2D, {axisMult, idxMCAxis}); + if (doprocessMCTrue) { + 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}); + histos.add("QA/MC/h2GenPhiRapidity_afterEtaRapCut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + histos.add("QA/MC/h2GenEtaPt_afterRapcut", " #phi-#it{p}_{T} distribution of Generated #Lambda(1520); #eta; #it{p}_{T}; Counts;", HistType::kTHnSparseF, {axisEta, axisPtQA}); + histos.add("QA/MC/h2GenPhiRapidity_afterRapcut", " #phi-y distribution of Generated #Lambda(1520); #phi; y; Counts;", HistType::kTHnSparseF, {axisPhi, axisRap}); + + histos.add("Result/MC/Genlambda1520pt", "pT distribution of True MC #Lambda(1520)0", kTHnSparseF, {axisMClabel, axisPt, axisMult}); + histos.add("Result/MC/Genantilambda1520pt", "pT distribution of True MC Anti-#Lambda(1520)0", kTHnSparseF, {axisMClabel, axisPt, axisMult}); + } + if (doprocessMC) { + 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}); + + histos.add("QA/MC/trkDCAxy_pr", "DCAxy distribution of proton track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); + histos.add("QA/MC/trkDCAxy_ka", "DCAxy distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAxy}); + histos.add("QA/MC/trkDCAz_pr", "DCAz distribution of proton track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); + histos.add("QA/MC/trkDCAz_ka", "DCAz distribution of kaon track candidates", HistType::kTHnSparseF, {axisPt, axisDCAz}); + histos.add("QA/MC/TOF_Nsigma_pr_all", "TOF NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_pr_all", "TPC NSigma for Proton;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Proton}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TOF_Nsigma_ka_all", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TOF}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + histos.add("QA/MC/TPC_Nsigma_ka_all", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});{#sigma_{TPC}^{Kaon}};", {HistType::kTHnSparseF, {axisMult, axisPt, axisPIDQA}}); + + 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}); + } + + // Print output histograms statistics + LOG(info) << "Size of the histograms in Lambda1520analysisinpp:"; + histos.print(); + } + + float massKa = MassKaonCharged; + float massPr = MassProton; + + // 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; + } + + 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) + { + // basic track cuts + if (std::abs(track.pt()) < configTracks.cMinPtcut) + return false; + if (configTracks.cDCAr7SigCut) { + if (std::abs(track.dcaXY()) > (0.004f + 0.013f / (track.pt()))) // 7 - Sigma cut + return false; + } else { + if (std::abs(track.dcaXY()) > configTracks.cMaxDCArToPVcut) + return false; + } + if (std::abs(track.dcaZ()) > configTracks.cMaxDCAzToPVcut) + return false; + if (configTracks.cTPCNClsFound && (track.tpcNClsFound() < configTracks.cMinTPCNClsFound)) + return false; + if (track.tpcNClsCrossedRows() < configTracks.cfgMinCrossedRows) + return false; + if (configTracks.cfgHasTOF && !track.hasTOF()) + return false; + if (configTracks.cfgPrimaryTrack && !track.isPrimaryTrack()) + return false; + if (configTracks.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) + return false; + if (configTracks.cfgPVContributor && !track.isPVContributor()) + return false; + if (configTracks.cfgGlobalTrack && !track.isGlobalTrack()) + return false; + if (configTracks.cfgUseITSRefit && !track.passedITSRefit()) + return false; + if (configTracks.cfgUseTPCRefit && !track.passedTPCRefit()) + return false; + + return true; + } + + // LOGF(info, "AFTER: pt: %f, hasTOF: %d, TPCSigma: %f, TOFSigma: %f, boolTPC: %d, boolTOF: %d, bool: %d", pt, candidate.hasTOF(), + // candidate.tpcNSigmaPr(), candidate.tofNSigmaPr(), tpcPIDPassed, tofPIDPassed, tpcPIDPassed || tofPIDPassed); + + template + bool ptDependentPidProton(const T& candidate) + { + auto vProtonTPCPIDpTintv = configPID.protonTPCPIDpTintv.value; + vProtonTPCPIDpTintv.insert(vProtonTPCPIDpTintv.begin(), configTracks.cMinPtcut); + auto vProtonTPCPIDcuts = configPID.protonTPCPIDcuts.value; + auto vProtonTOFPIDpTintv = configPID.protonTOFPIDpTintv.value; + auto vProtonTPCTOFCombinedpTintv = configPID.protonTPCTOFCombinedpTintv.value; + auto vProtonTPCTOFCombinedPIDcuts = configPID.protonTPCTOFCombinedPIDcuts.value; + auto vProtonTOFPIDcuts = configPID.protonTOFPIDcuts.value; + + float pt = candidate.pt(); + float ptSwitchToTOF = vProtonTPCPIDpTintv.back(); + float tpcNsigmaPr = candidate.tpcNSigmaPr(); + float tofNsigmaPr = candidate.tofNSigmaPr(); + + bool tpcPIDPassed = false; + + // TPC PID (interval check) + for (size_t i = 0; i < vProtonTPCPIDpTintv.size() - 1; ++i) { + if (pt > vProtonTPCPIDpTintv[i] && pt < vProtonTPCPIDpTintv[i + 1]) { + if (std::abs(tpcNsigmaPr) < vProtonTPCPIDcuts[i]) + tpcPIDPassed = true; + } + } + + // TOF bypass option (for QA or MC) + if (configPID.cByPassTOF) { + return std::abs(tpcNsigmaPr) < vProtonTPCPIDcuts.back(); + } + + // Case 1: No TOF and pt ≤ threshold → accept only via TPC PID + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } + + // Case 2: No TOF but pt > threshold → reject + if (!candidate.hasTOF() && pt > ptSwitchToTOF) { + return false; + } + + // Case 3: Has TOF → use TPC + TOF (square or circular) + if (candidate.hasTOF()) { + if (configPID.cPIDcutType == SquareType) { + // Rectangular cut + for (size_t i = 0; i < vProtonTOFPIDpTintv.size(); ++i) { + if (pt < vProtonTOFPIDpTintv[i]) { + if (std::abs(tofNsigmaPr) < vProtonTOFPIDcuts[i] && + std::abs(tpcNsigmaPr) < vProtonTPCPIDcuts.back()) + return true; + } + } + } else if (configPID.cPIDcutType == CircularType) { + // Circular cut + for (size_t i = 0; i < vProtonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vProtonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = + tpcNsigmaPr * tpcNsigmaPr + + tofNsigmaPr * tofNsigmaPr; + if (combinedSigma2 < vProtonTPCTOFCombinedPIDcuts[i] * vProtonTPCTOFCombinedPIDcuts[i]) + return true; + } + } + } + } + + return false; + } + + template + bool ptDependentPidKaon(const T& candidate) + { + auto vKaonTPCPIDpTintv = configPID.kaonTPCPIDpTintv.value; + vKaonTPCPIDpTintv.insert(vKaonTPCPIDpTintv.begin(), configTracks.cMinPtcut); + auto vKaonTPCPIDcuts = configPID.kaonTPCPIDcuts.value; + auto vKaonTOFPIDpTintv = configPID.kaonTOFPIDpTintv.value; + auto vKaonTPCTOFCombinedpTintv = configPID.kaonTPCTOFCombinedpTintv.value; + auto vKaonTPCTOFCombinedPIDcuts = configPID.kaonTPCTOFCombinedPIDcuts.value; + auto vKaonTOFPIDcuts = configPID.kaonTOFPIDcuts.value; + + float pt = candidate.pt(); + float ptSwitchToTOF = vKaonTPCPIDpTintv.back(); + float tpcNsigmaKa = candidate.tpcNSigmaKa(); + float tofNsigmaKa = candidate.tofNSigmaKa(); + + bool tpcPIDPassed = false; + + // TPC PID interval-based check + for (size_t i = 0; i < vKaonTPCPIDpTintv.size() - 1; ++i) { + if (pt > vKaonTPCPIDpTintv[i] && pt < vKaonTPCPIDpTintv[i + 1]) { + if (std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts[i]) { + tpcPIDPassed = true; + break; + } + } + } + + // TOF bypass option + if (configPID.cByPassTOF) { + return std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts.back(); + } + + // Case 1: No TOF and pt ≤ ptSwitch → use TPC-only + if (!candidate.hasTOF() && pt <= ptSwitchToTOF) { + return tpcPIDPassed; + } + + // Case 2: No TOF but pt > ptSwitch → reject + if (!candidate.hasTOF() && pt > ptSwitchToTOF) { + return false; + } + + // Case 3: TOF is available → apply TPC+TOF PID logic + if (candidate.hasTOF()) { + if (configPID.cPIDcutType == SquareType) { + // Rectangular cut + for (size_t i = 0; i < vKaonTOFPIDpTintv.size(); ++i) { + if (pt < vKaonTOFPIDpTintv[i]) { + if (std::abs(tofNsigmaKa) < vKaonTOFPIDcuts[i] && + std::abs(tpcNsigmaKa) < vKaonTPCPIDcuts.back()) { + return true; + } + } + } + } else if (configPID.cPIDcutType == CircularType) { + // Circular cut + for (size_t i = 0; i < vKaonTPCTOFCombinedpTintv.size(); ++i) { + if (pt < vKaonTPCTOFCombinedpTintv[i]) { + float combinedSigma2 = tpcNsigmaKa * tpcNsigmaKa + + tofNsigmaKa * tofNsigmaKa; + if (combinedSigma2 < vKaonTPCTOFCombinedPIDcuts[i] * vKaonTPCTOFCombinedPIDcuts[i]) { + return true; + } + } + } + } + } + + return false; + } + + auto static constexpr MinPtforPionRejection = 1.0f; + auto static constexpr MaxPtforPionRejection = 2.0f; + auto static constexpr MaxnSigmaforPionRejection = 2.0f; + + template + bool rejectPion(const T& candidate) + { + if (candidate.pt() > MinPtforPionRejection && candidate.pt() < MaxPtforPionRejection && !candidate.hasTOF() && candidate.tpcNSigmaPi() < MaxnSigmaforPionRejection) { + return false; + } + return true; + } + + auto static constexpr MaxNoLambda1520Daughters = 2; + + template + void fillHistograms(const CollisionType& collision, const TracksType& dTracks1, const TracksType& dTracks2) + { + auto centrality = centEst(collision); + + // Multiplicity correlation calibration plots + if (cFillMultQA) { + if constexpr (IsData) { + histos.fill(HIST("MultCalib/centGloPVpr"), centrality, dTracks1.size(), collision.multNTracksPV()); + histos.fill(HIST("MultCalib/centGloPVka"), centrality, dTracks2.size(), collision.multNTracksPV()); + } + } + + if (cFilladditionalQAeventPlots) { + if constexpr (IsData) { + histos.fill(HIST("QAevent/hnTrksSameE"), dTracks1.size()); + } else if constexpr (IsMix) { + histos.fill(HIST("QAevent/hVertexZMixedE"), collision.posZ()); + histos.fill(HIST("QAevent/hMultiplicityPercentMixedE"), centrality); + histos.fill(HIST("QAevent/hnTrksMixedE"), dTracks1.size()); + } + } + // LOG(info) << "After pass, Collision index:" << collision.index() << "multiplicity: " << collision.centFT0M() << endl; + + LorentzVectorPtEtaPhiMass lDecayDaughter1, lDecayDaughter2, lResonance, ldaughterRot, lResonanceRot; + + for (const auto& [trk1, trk2] : combinations(CombinationsFullIndexPolicy(dTracks1, dTracks2))) { + // Full index policy is needed to consider all possible combinations + if (trk1.index() == trk2.index()) + continue; // We need to run (0,1), (1,0) pairs as well. but same id pairs are not needed. + + // apply the track cut + if (!trackCut(trk1) || !trackCut(trk2)) + continue; + + //// Initialize variables + // Trk1: Proton + auto isTrk1hasTOF = trk1.hasTOF(); + auto trk1ptPr = trk1.pt(); + auto trk1etaPr = trk1.eta(); + auto trk1phiPr = trk1.phi(); + auto trk1NSigmaPrTPC = trk1.tpcNSigmaPr(); + auto trk1NSigmaPrTOF = (isTrk1hasTOF) ? trk1.tofNSigmaPr() : -999.0f; + + // Trk2: Kaon + auto isTrk2hasTOF = trk2.hasTOF(); + auto trk2ptKa = trk2.pt(); + auto trk2etaKa = trk2.eta(); + auto trk2phiKa = trk2.phi(); + auto trk2NSigmaKaTPC = trk2.tpcNSigmaKa(); + auto trk2NSigmaKaTOF = (isTrk2hasTOF) ? trk2.tofNSigmaKa() : -999.0f; + + auto deltaEta = 0.0f; + auto deltaPhi = 0.0f; + + if (cfgUseDeltaEtaPhiCuts) { + deltaEta = std::abs(trk1etaPr - trk2etaKa); + deltaPhi = std::abs(trk1phiPr - trk2phiKa); + deltaPhi = (deltaPhi > o2::constants::math::PI) ? (o2::constants::math::TwoPI - deltaPhi) : deltaPhi; + if (deltaEta >= cMaxDeltaEtaCut) + continue; + if (deltaPhi >= cMaxDeltaPhiCut) + continue; + } + + //// QA plots before the selection + // --- Track QA all + if constexpr (IsData) { + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_pr_all"), centrality, trk1ptPr, trk1NSigmaPrTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TOF_Nsigma_pr_all"), centrality, trk1ptPr, trk1NSigmaPrTOF); + histos.fill(HIST("QA/QAbefore/Track/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); + } + if (!isTrk1hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TPConly_Nsigma_pr"), trk1ptPr, trk1NSigmaPrTPC); + } + histos.fill(HIST("QA/QAbefore/Track/TPC_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TOF_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/QAbefore/Track/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAbefore/Track/TPConly_Nsigma_ka"), trk2ptKa, trk2NSigmaKaTPC); + } + + histos.fill(HIST("QA/QAbefore/Track/dcaZ"), trk1ptPr, trk1.dcaZ()); + histos.fill(HIST("QA/QAbefore/Track/dcaXY"), trk1ptPr, trk1.dcaXY()); + histos.fill(HIST("QA/QAbefore/Track/TPC_CR"), trk1ptPr, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAbefore/Track/pT"), trk1ptPr); + histos.fill(HIST("QA/QAbefore/Track/eta"), trk1etaPr); + if (cFilldeltaEtaPhiPlots) { + histos.fill(HIST("QAbefore/deltaEta"), deltaEta); + histos.fill(HIST("QAbefore/deltaPhi"), deltaPhi); + } + } + + //// Apply the pid selection + if (crejectPion && rejectPion(trk2)) // to remove pion contamination from the kaon track + continue; + + if (!ptDependentPidProton(trk1) || !ptDependentPidKaon(trk2)) + continue; + + //// QA plots after the selection + if constexpr (IsData) { // --- PID QA Proton + histos.fill(HIST("QA/QAafter/Proton/TPC_Nsigma_pr_all"), centrality, trk1ptPr, trk1NSigmaPrTPC); + histos.fill(HIST("QA/QAafter/Proton/TPC_Signal_pr_all"), trk1.tpcInnerParam(), trk1.tpcSignal()); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Proton/TOF_Nsigma_pr_all"), centrality, trk1ptPr, trk1NSigmaPrTOF); + histos.fill(HIST("QA/QAafter/Proton/TOF_TPC_Map_pr_all"), trk1NSigmaPrTOF, trk1NSigmaPrTPC); + } + if (!isTrk1hasTOF) { + histos.fill(HIST("QA/QAafter/Proton/TPC_Nsigma_pr_TPConly"), trk1ptPr, trk1NSigmaPrTPC); + } + histos.fill(HIST("QA/QAafter/Proton/dcaZ"), trk1ptPr, trk1.dcaZ()); + histos.fill(HIST("QA/QAafter/Proton/dcaXY"), trk1ptPr, trk1.dcaXY()); + histos.fill(HIST("QA/QAafter/Proton/TPC_CR"), trk1ptPr, trk1.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Proton/pT"), trk1ptPr); + histos.fill(HIST("QA/QAafter/Proton/eta"), trk1etaPr); + histos.fill(HIST("QA/QAafter/Proton/TPCnclusterPhipr"), trk1.tpcNClsFound(), trk1phiPr); + + // --- PID QA Kaon + histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTPC); + histos.fill(HIST("QA/QAafter/Kaon/TPC_Signal_ka_all"), trk2.tpcInnerParam(), trk2.tpcSignal()); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Kaon/TOF_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTOF); + histos.fill(HIST("QA/QAafter/Kaon/TOF_TPC_Map_ka_all"), trk2NSigmaKaTOF, trk2NSigmaKaTPC); + } + if (!isTrk2hasTOF) { + histos.fill(HIST("QA/QAafter/Kaon/TPC_Nsigma_ka_TPConly"), trk2ptKa, trk2NSigmaKaTPC); + } + histos.fill(HIST("QA/QAafter/Kaon/dcaZ"), trk2ptKa, trk2.dcaZ()); + histos.fill(HIST("QA/QAafter/Kaon/dcaXY"), trk2ptKa, trk2.dcaXY()); + histos.fill(HIST("QA/QAafter/Kaon/TPC_CR"), trk2ptKa, trk2.tpcNClsCrossedRows()); + histos.fill(HIST("QA/QAafter/Kaon/pT"), trk2ptKa); + histos.fill(HIST("QA/QAafter/Kaon/eta"), trk2etaKa); + histos.fill(HIST("QA/QAafter/Kaon/TPCnclusterPhika"), trk2.tpcNClsFound(), trk2phiKa); + + if (cFilldeltaEtaPhiPlots) { + histos.fill(HIST("QAafter/PhiPrafter"), trk1phiPr); + histos.fill(HIST("QAafter/PhiKaafter"), trk2phiKa); + histos.fill(HIST("QAafter/deltaEta"), deltaEta); + histos.fill(HIST("QAafter/deltaPhi"), deltaPhi); + } + } + + //// Resonance reconstruction + lDecayDaughter1 = LorentzVectorPtEtaPhiMass(trk1ptPr, trk1etaPr, trk1phiPr, massPr); + lDecayDaughter2 = LorentzVectorPtEtaPhiMass(trk2ptKa, trk2etaKa, trk2phiKa, massKa); + + // Apply kinematic opening angle cut + if (cUseOpeningAngleCut) { + auto v1 = lDecayDaughter1.Vect(); + auto v2 = lDecayDaughter2.Vect(); + float alpha = std::acos(v1.Dot(v2) / (v1.R() * v2.R())); + if (alpha > cMinOpeningAngle && alpha < cMaxOpeningAngle) + continue; + } + + lResonance = lDecayDaughter1 + lDecayDaughter2; + + auto resonanceMass = lResonance.M(); + auto resonancePt = lResonance.Pt(); + auto resonanceRapidity = lResonance.Rapidity(); + + if constexpr (IsData || IsMix) { + // Rapidity cut + if (std::abs(resonanceRapidity) > configTracks.cfgCutRapidity) + continue; + } + + if (cfgUseCutsOnMother) { + if (resonancePt >= cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (resonanceMass >= cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + + if (cFilladditionalQAeventPlots) { + if constexpr (IsData) { + histos.fill(HIST("QAevent/hPairsCounterSameE"), 1.0f); + } else if (IsMix) { + histos.fill(HIST("QAevent/hPairsCounterMixedE"), 1.0f); + } + } + + //// Un-like sign pair only + if (trk1.sign() * trk2.sign() < 0) { + if constexpr (IsRot) { + for (int i = 0; i < configBkg.cNofRotations; i++) { + float theta = rn->Uniform(o2::constants::math::PI - o2::constants::math::PI / configBkg.rotationalcut, o2::constants::math::PI + o2::constants::math::PI / configBkg.rotationalcut); + if (configBkg.cfgRotPr) { + ldaughterRot = LorentzVectorPtEtaPhiMass(trk1ptPr, trk1etaPr, trk1phiPr + theta, massPr); + lResonanceRot = ldaughterRot + lDecayDaughter2; + } else { + ldaughterRot = LorentzVectorPtEtaPhiMass(trk2ptKa, trk2etaKa, trk2phiKa + theta, massKa); + lResonanceRot = lDecayDaughter1 + ldaughterRot; + } + auto resonanceRotMass = lResonanceRot.M(); + auto resonanceRotPt = lResonanceRot.Pt(); + + // Rapidity cut + if (std::abs(lResonanceRot.Rapidity()) >= configTracks.cfgCutRapidity) + continue; + + if (cfgUseCutsOnMother) { + if (resonanceRotPt >= cMaxPtMotherCut) // excluding candidates in overflow + continue; + if (resonanceRotMass >= cMaxMinvMotherCut) // excluding candidates in overflow + continue; + } + if (trk1.sign() < 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/lambda1520InvMassRotation"), resonanceRotMass); + } + histos.fill(HIST("Result/Data/h3lambda1520InvMassRotation"), centrality, resonanceRotPt, resonanceRotMass); + } else if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/antilambda1520InvMassRotation"), resonanceRotMass); + } + histos.fill(HIST("Result/Data/h3antilambda1520InvMassRotation"), centrality, resonanceRotPt, resonanceRotMass); + } + } + } + if constexpr (IsData) { + if (trk1.sign() < 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/lambda1520invmass"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3lambda1520invmass"), centrality, resonancePt, resonanceMass); + } else if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/antilambda1520invmass"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3antilambda1520invmass"), centrality, resonancePt, resonanceMass); + } + } else if (IsMix) { + if (trk1.sign() < 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/lambda1520invmassME_UnlikeSign"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3lambda1520invmassME_UnlikeSign"), centrality, resonancePt, resonanceMass); + } else if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/antilambda1520invmassME_UnlikeSign"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3antilambda1520invmassME_UnlikeSign"), centrality, resonancePt, resonanceMass); + } + } + + // MC + if constexpr (IsMC) { + // now we do mc true + // ------ Temporal lambda function to prevent error in build + auto getMothersIndeces = [&](auto const& theMcParticle) { + std::vector lMothersIndeces{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother index lMother: %d", lMother.globalIndex()); + lMothersIndeces.push_back(lMother.globalIndex()); + } + return lMothersIndeces; + }; + auto getMothersPDGCodes = [&](auto const& theMcParticle) { + std::vector lMothersPDGs{}; + for (auto const& lMother : theMcParticle.template mothers_as()) { + LOGF(debug, " mother pdgcode lMother: %d", lMother.pdgCode()); + lMothersPDGs.push_back(lMother.pdgCode()); + } + return lMothersPDGs; + }; + // ------ + std::vector motherstrk1 = {-1, -1}; + std::vector mothersPDGtrk1 = {-1, -1}; + + std::vector motherstrk2 = {-1, -1}; + std::vector mothersPDGtrk2 = {-1, -1}; + + // + // Get the MC particle + const auto& mctrk1 = trk1.mcParticle(); + if (mctrk1.has_mothers()) { + motherstrk1 = getMothersIndeces(mctrk1); + mothersPDGtrk1 = getMothersPDGCodes(mctrk1); + } + while (motherstrk1.size() > MaxNoLambda1520Daughters) { + motherstrk1.pop_back(); + mothersPDGtrk1.pop_back(); + } + + const auto& mctrk2 = trk2.mcParticle(); + if (mctrk2.has_mothers()) { + motherstrk2 = getMothersIndeces(mctrk2); + mothersPDGtrk2 = getMothersPDGCodes(mctrk2); + } + while (motherstrk2.size() > MaxNoLambda1520Daughters) { + motherstrk2.pop_back(); + mothersPDGtrk2.pop_back(); + } + + if (std::abs(mctrk1.pdgCode()) != kProton || std::abs(mctrk2.pdgCode()) != kKPlus) + continue; + + if (motherstrk1[0] != motherstrk2[0]) // Same mother + continue; + + if (std::abs(mothersPDGtrk1[0]) != Pdg::kLambda1520_Py) + continue; + + // LOGF(info, "mother trk1 id: %d, mother trk1: %d, trk1 id: %d, trk1 pdgcode: %d, mother trk2 id: %d, mother trk2: %d, trk2 id: %d, trk2 pdgcode: %d", motherstrk1[0], mothersPDGtrk1[0], trk1.globalIndex(), mctrk1.pdgCode(), motherstrk2[0], mothersPDGtrk2[0], trk2.globalIndex(), mctrk2.pdgCode()); + + if (cUseEtacutMC && std::abs(lResonance.Eta()) > cEtacutMC) // eta cut + continue; + + if (cUseRapcutMC && std::abs(resonanceRapidity) > configTracks.cfgCutRapidity) // rapidity cut + continue; + + histos.fill(HIST("QA/MC/h2RecoEtaPt_after"), lResonance.Eta(), resonancePt); + histos.fill(HIST("QA/MC/h2RecoPhiRapidity_after"), lResonance.Phi(), resonanceRapidity); + + // Track selection check. + histos.fill(HIST("QA/MC/trkDCAxy_pr"), trk1ptPr, trk1.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAxy_ka"), trk2ptKa, trk2.dcaXY()); + histos.fill(HIST("QA/MC/trkDCAz_pr"), trk1ptPr, trk1.dcaZ()); + histos.fill(HIST("QA/MC/trkDCAz_ka"), trk2ptKa, trk2.dcaZ()); + + histos.fill(HIST("QA/MC/TPC_Nsigma_pr_all"), centrality, trk1ptPr, trk1NSigmaPrTPC); + if (isTrk1hasTOF) { + histos.fill(HIST("QA/MC/TOF_Nsigma_pr_all"), centrality, trk1ptPr, trk1NSigmaPrTOF); + } + histos.fill(HIST("QA/MC/TPC_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTPC); + if (isTrk2hasTOF) { + histos.fill(HIST("QA/MC/TOF_Nsigma_ka_all"), centrality, trk2ptKa, trk2NSigmaKaTOF); + } + + // MC histograms + if (mothersPDGtrk1[0] > 0) { + histos.fill(HIST("Result/MC/h3lambda1520Recoinvmass"), centrality, resonancePt, resonanceMass); + } else { + histos.fill(HIST("Result/MC/h3antilambda1520Recoinvmass"), centrality, resonancePt, resonanceMass); + } + } + } else { + if constexpr (IsData) { + // Like sign pair ++ + if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/lambda1520invmassLSPP"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3lambda1520invmassLSPP"), centrality, resonancePt, resonanceMass); + } else { // Like sign pair -- + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/lambda1520invmassLSMM"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3lambda1520invmassLSMM"), centrality, resonancePt, resonanceMass); + } + } else if (IsMix) { + if (cFilladditionalMEPlots) { + // Like sign pair ++ + if (trk1.sign() > 0) { + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/lambda1520invmassME_LSPP"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3lambda1520invmassME_LSPP"), centrality, resonancePt, resonanceMass); + } else { // Like sign pair -- + if (cFill1DQAs) { + histos.fill(HIST("Result/Data/lambda1520invmassME_LSMM"), resonanceMass); + } + histos.fill(HIST("Result/Data/h3lambda1520invmassME_LSMM"), centrality, resonancePt, resonanceMass); + } + } + } + } + } + } + + void processData(EventCandidates::iterator const& collision, + TrackCandidates const& tracks) + { + if (!colCuts.isSelected(collision)) // Default event selection + return; + + colCuts.fillQA(collision); + + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Lambda1520analysisinpp, processData, "Process Event for data without partition", false); + + void processRotational(EventCandidates::iterator const& collision, TrackCandidates const& tracks) + { + if (!colCuts.isSelected(collision, false)) // Default event selection + 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&) + { + colCuts.fillQA(collision); + + if (std::abs(collision.posZ()) > cZvertCutMC) // Z-vertex cut + return; + + fillHistograms(collision, tracks, tracks); + } + PROCESS_SWITCH(Lambda1520analysisinpp, processMC, "Process Event for MC Light 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) + { + bool isInAfterAllCuts = colCuts.isSelected(collision); + 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 centrality = centEst(collision); + + auto mcParts = selectedMCParticles->sliceBy(perMcCollision, collision.mcCollision().globalIndex()); + + // Not related to the real collisions + for (const auto& part : mcParts) { // loop over all MC particles + + std::vector daughterPDGs; + if (part.has_daughters()) { + auto daughter01 = mcParticles.rawIteratorAt(part.daughtersIds()[0] - mcParticles.offset()); + auto daughter02 = mcParticles.rawIteratorAt(part.daughtersIds()[1] - mcParticles.offset()); + daughterPDGs = {daughter01.pdgCode(), daughter02.pdgCode()}; + } else { + daughterPDGs = {-1, -1}; + } + + bool pass1 = std::abs(daughterPDGs[0]) == kKPlus || std::abs(daughterPDGs[1]) == kKPlus; // At least one decay to Kaon + bool pass2 = std::abs(daughterPDGs[0]) == kProton || std::abs(daughterPDGs[1]) == kProton; // At least one decay to Proton + + // Checking if we have both decay products + if (!pass1 || !pass2) + continue; + + // LOGF(info, "Part PDG: %d", part.pdgCode(), "DAU_ID1: %d", pass1, "DAU_ID2: %d", pass2); + + histos.fill(HIST("QA/MC/h2GenEtaPt_beforeanycut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_beforeanycut"), part.phi(), part.y()); + + if (cUseRapcutMC && std::abs(part.y()) > configTracks.cfgCutRapidity) // rapidity cut + continue; + + if (cfgUseDaughterEtaCutMC) { + for (auto const& daughters : part.daughters_as()) { + if (std::fabs(daughters.eta()) > configTracks.cfgCutEta) + continue; // eta cut for daughters + } // loop over daughters + } + + histos.fill(HIST("QA/MC/h2GenEtaPt_afterRapcut"), part.eta(), part.pt()); + histos.fill(HIST("QA/MC/h2GenPhiRapidity_afterRapcut"), part.phi(), part.y()); + + if (cUseEtacutMC && std::abs(part.eta()) > cEtacutMC) // eta cut + continue; + + 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("Result/MC/Genlambda1520pt"), 0, part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), 0, part.pt(), centrality); + + if (inVtx10) // INEL10 + { + 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 (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genlambda1520pt"), 2, part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), 2, part.pt(), centrality); + } + if (inVtx10 && isTriggerTVX) // vtx10, TriggerTVX + { + 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 (part.pdgCode() > 0) + histos.fill(HIST("Result/MC/Genlambda1520pt"), 4, part.pt(), centrality); + else + histos.fill(HIST("Result/MC/Genantilambda1520pt"), 4, part.pt(), centrality); + } + } + + // QA for Trigger efficiency + histos.fill(HIST("Event/hMCEventIndices"), centrality, Inel); + if (inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Inel10); + if (isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Inelg0); + if (inVtx10 && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Inelg010); + + // TVX MB trigger + if (isTriggerTVX) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Trig); + if (isTriggerTVX && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Trig10); + if (isTriggerTVX && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, TrigINELg0); + if (isTriggerTVX && isTrueINELgt0 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, TrigINELg010); + + // Sel8 event selection + if (isSel8) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Sel8); + if (isSel8 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Sel810); + if (isSel8 && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Sel8INELg0); + if (isSel8 && isTrueINELgt0 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, Sel8INELg010); + + // CollisionCuts selection + if (isInAfterAllCuts) + histos.fill(HIST("Event/hMCEventIndices"), centrality, AllCuts); + if (isInAfterAllCuts && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, AllCuts10); + if (isInAfterAllCuts && isTrueINELgt0) + histos.fill(HIST("Event/hMCEventIndices"), centrality, AllCutsINELg0); + if (isInAfterAllCuts && isTrueINELgt0 && inVtx10) + histos.fill(HIST("Event/hMCEventIndices"), centrality, AllCutsINELg010); + } + PROCESS_SWITCH(Lambda1520analysisinpp, processMCTrue, "Process Event for MC only", false); + + // Processing Event Mixing + using BinningTypeVtxZT0M = ColumnBinningPolicy; + + void processME(EventCandidates const& collision, + TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + + BinningTypeVtxZT0M colBinning{{configBkg.cfgVtxBins, configBkg.cfgMultBins}, 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) { + // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.globalIndex(), collision2.globalIndex()); + + // for (auto& [t1, t2] : combinations(CombinationsFullIndexPolicy(tracks1, tracks2))) { + // LOGF(info, "Mixed event tracks pair: (%d, %d) from events (%d, %d)", t1.index(), t2.index(), collision1.index(), collision2.index()); + // } + + 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. + if (cFill1DQAs) { + histos.fill(HIST("QAevent/hMixPool_VtxZ"), collision1.posZ()); + histos.fill(HIST("QAevent/hMixPool_Multiplicity"), collision1.centFT0M()); + } + histos.fill(HIST("QAevent/hMixPool_VtxZ_vs_Multiplicity"), collision1.posZ(), collision1.centFT0M()); + + // You might also want to fill for collision2 if you want to see both partners' distributions + // histos.fill(HIST("QAevent/hMixPool_VtxZ"), collision2.posZ()); + // histos.fill(HIST("QAevent/hMixPool_Multiplicity"), collision2.centFT0M()); + // histos.fill(HIST("QAevent/hMixPool_VtxZ_vs_Multiplicity"), collision2.posZ(), collision2.centFT0M()); + } + fillHistograms(collision1, tracks1, tracks2); + } + } + PROCESS_SWITCH(Lambda1520analysisinpp, processME, "Process EventMixing light without partition", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Resonances/phiOO.cxx b/PWGLF/Tasks/Resonances/phiOO.cxx new file mode 100644 index 00000000000..9c7e6005264 --- /dev/null +++ b/PWGLF/Tasks/Resonances/phiOO.cxx @@ -0,0 +1,675 @@ +// 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 phiInJets.cxx +/// \brief Reconstruction of Phi yield through track-track Minv correlations for resonance OO analysis +/// +/// +/// \author Adrian Fereydon Nassirpour +#include +#include +#include +#include +#include + +#include "TRandom.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; + +struct phiOO { + + SliceCache cache; + Preslice perCollision = aod::track::collisionId; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // Event configurables + Configurable cfg_Event_Sel{"cfg_Event_Sel", "sel8", "choose event selection"}; + Configurable cfg_Event_VtxCut{"cfg_Event_VtxCut", 10.0, "V_z cut selection"}; + Configurable cfg_Event_Timeframe{"cfg_Event_Timeframe", true, "Timeframe border cut"}; + Configurable cfg_Event_Timerange{"cfg_Event_Timerange", true, "Timerange border cut"}; + Configurable cfg_Event_Centrality{"cfg_Event_Centrality", true, "Centrality cut"}; + Configurable cfg_Event_CentralityMax{"cfg_Event_CentralityMax", 100, "CentralityMax cut"}; + 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"}; + + // Track configurables + Configurable cfg_Track_Sel{"cfg_Track_Sel", "globalTracks", "set track selections"}; + Configurable cfg_Track_MinPt{"cfg_Track_MinPt", 0.15, "set track min pT"}; + Configurable cfg_Track_MaxEta{"cfg_Track_MaxEta", 0.9, "set track max Eta"}; + Configurable cfg_Track_MaxDCArToPVcut{"cfg_Track_MaxDCArToPVcut", 0.5, "Track DCAr cut to PV Maximum"}; + Configurable cfg_Track_MaxDCAzToPVcut{"cfg_Track_MaxDCAzToPVcut", 2.0, "Track DCAz cut to PV Maximum"}; + Configurable cfg_Track_PrimaryTrack{"cfg_Track_PrimaryTrack", true, "Primary track selection"}; // kGoldenChi2 | kDCAxy | kDCAz + Configurable cfg_Track_ConnectedToPV{"cfg_Track_ConnectedToPV", true, "PV contributor track selection"}; // PV Contributor + Configurable cfg_Track_GlobalWoDCATrack{"cfg_Track_GlobalWoDCATrack", true, "Global track selection without DCA"}; // kQualityTracks (kTrackType | kTPCNCls | kTPCCrossedRows | kTPCCrossedRowsOverNCls | kTPCChi2NDF | kTPCRefit | kITSNCls | kITSChi2NDF | kITSRefit | kITSHits) | kInAcceptanceTracks (kPtRange | kEtaRange) + Configurable cfg_Track_nFindableTPCClusters{"cfg_Track_FindableTPCClusters", 50, "nFindable TPC Clusters"}; + Configurable cfg_Track_nTPCCrossedRows{"cfg_Track_TPCCrossedRows", 70, "nCrossed TPC Rows"}; + Configurable cfg_Track_nRowsOverFindable{"cfg_Track_RowsOverFindable", 1.2, "nRowsOverFindable TPC CLusters"}; + Configurable cfg_Track_nTPCChi2{"cfg_Track_TPCChi2", 4.0, "nTPC Chi2 per Cluster"}; + Configurable cfg_Track_nITSChi2{"cfg_Track_ITSChi2", 36.0, "nITS Chi2 per Cluster"}; + Configurable cfg_Track_TPCPID{"cfg_Track_TPCPID", true, "Enables TPC PID"}; + Configurable cfg_Track_TOFPID{"cfg_Track_TOFPID", true, "Enables TOF PID"}; + Configurable cfg_Track_Hard_TOFPID{"cfg_Track_Hard_TOFPID", true, "Enables STRICT TOF Reqruirement"}; + Configurable cfg_Track_TPCPID_nSig{"cfg_Track_TPCPID_nSig", 4, "nTPC PID sigma"}; + Configurable cfg_Track_TOFPID_nSig{"cfg_Track_TOFPID_nSig", 4, "nTOF PID sigma"}; + Configurable cfg_Track_Explicit_PID{"cfg_Track_Explicit_PID", true, "Enables explicit pid cehck"}; + Configurable cDebugLevel{"cDebugLevel", 0, "Resolution of Debug"}; + + // Pair configurables + Configurable cfg_Pair_MinvBins{"cfg_Pair_MinvBins", 300, "Number of bins for Minv axis"}; + Configurable cfg_Pair_MinvMin{"cfg_Pair_MinvMin", 0.90, "Minimum Minv value"}; + Configurable cfg_Pair_MinvMax{"cfg_Pair_MinvMax", 1.50, "Maximum Minv value"}; + + Configurable cfg_Mix_NMixedEvents{"cfg_Mix_NMixedEvents", 5, "Number of mixed events per event"}; + + // MCGen configurables + Configurable cfg_Force_GenReco{"cfg_Force_GenReco", false, "Only consider events which are reconstructed (neglect event-loss)"}; + Configurable cfg_Force_BR{"cfg_Force_BR", false, "Only consider phi->K+K-"}; + Configurable cfg_Force_Kaon_Acceptence{"cfg_Force_Kaon_Acceptence", false, "Only consider phi's whose daughters decay inside acceptence (no signal loss)"}; + + // Histogram Configurables + Configurable cfg_Event_CutQA{"cfg_Event_CutsQA", true, "Enables Track QA plots"}; + Configurable cfg_Track_CutQA{"cfg_Track_CutsQA", true, "Enables Track QA plots"}; + + // Configurables for axis + ConfigurableAxis binsDCAz{"binsDCAz", {40, -0.2, 0.2}, ""}; + ConfigurableAxis binsDCAxy{"binsDCAxy", {40, -0.2, 0.2}, ""}; + ConfigurableAxis cfg_bins_Cent{"cfg_bins_Cent", {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 cfg_bins_MixVtx{"cfg_bins_MixVtx", {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 cfg_bins_MixMult{"cfg_bins_MixMult", {VARIABLE_WIDTH, 0.0f, 1.0f, 5.0f, 10.0f, 20.0f, 30.0f, 40.0f, 50.0f, 60.0f, 70.0f, 80.0f}, "Mixing bins - z-vertex"}; + + void init(o2::framework::InitContext&) + { + const AxisSpec MinvAxis = {cfg_Pair_MinvBins, cfg_Pair_MinvMin, cfg_Pair_MinvMax}; + const AxisSpec PtAxis = {200, 0, 20.0}; + const AxisSpec MultAxis = {100, 0, 100}; + const AxisSpec dRAxis = {100, 0, 100}; + const AxisSpec pidAxis = {100, -5, 5}; + const AxisSpec axisDCAz{binsDCAz, "DCA_{z}"}; + const AxisSpec axisDCAxy{binsDCAxy, "DCA_{XY}"}; + + // 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("hOccupancy_BC", "Occupancy_BC", kTH1F, {{100, 0.0, 20000}}); + // + histos.add("hcentFT0C_AC", "centFT0C_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}}); + } + // Track QA + if (cfg_Track_CutQA) { + 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("hTPC_nSigma_BC", "hTPC_nSigma_BC", kTH1F, {pidAxis}); + histos.add("hTOF_nSigma_BC", "hTOF_nSigma_BC", kTH1F, {pidAxis}); + histos.add("hTPC_nSigma_v_pt_BC", "hTPC_nSigma_v_pt_BC", HistType::kTHnSparseD, {pidAxis, PtAxis}); + histos.add("hTOF_nSigma_v_pt_BC", "hTOF_nSigma_v_pt_BC", HistType::kTHnSparseD, {pidAxis, PtAxis}); + // + 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("hTPC_nSigma_AC", "hTPC_nSigma_AC", kTH1F, {pidAxis}); + histos.add("hTOF_nSigma_AC", "hTOF_nSigma_AC", kTH1F, {pidAxis}); + histos.add("hTPC_nSigma_v_pt_AC", "hTPC_nSigma_v_pt_AC", HistType::kTHnSparseD, {pidAxis, PtAxis}); + histos.add("hTOF_nSigma_v_pt_AC", "hTOF_nSigma_v_pt_AC", HistType::kTHnSparseD, {pidAxis, PtAxis}); + } + // Data histos + histos.add("hUSS", "hUSS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hLSS", "hLSS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hUSS_Mix", "hUSS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hLSS_Mix", "hLSS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + + // MC histos + histos.add("hMC_USS", "hMC_USS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hMC_LSS", "hMC_LSS", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hMC_USS_Mix", "hMC_USS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hMC_LSS_Mix", "hMC_LSS_Mix", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hMC_USS_True", "hMC_USS_True", HistType::kTHnSparseD, {cfg_bins_Cent, MinvAxis, PtAxis}); + histos.add("hMC_Phi_True", "hMC_Phi_True", HistType::kTHnSparseD, {cfg_bins_Cent, PtAxis}); + + // Event Histograms + histos.add("hnEvents", "Event selection decision", kTH1I, {{10, -0.5, 9.5}}); + histos.add("hnEvents_MC", "Event selection decision", kTH1I, {{10, -0.5, 9.5}}); + histos.add("hnEvents_MC_True", "Event selection decision", kTH1I, {{10, -0.5, 9.5}}); + + } // end of init + + 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 acceptanceFilter = (nabs(aod::track::eta) < cfg_Track_MaxEta && nabs(aod::track::pt) >= cfg_Track_MinPt); + using EventCandidates = soa::Filtered>; + using EventCandidates_True = soa::Filtered; + + using TrackCandidates = soa::Filtered>; + using TrackCandidates_MC = soa::Filtered>; + + using BinningTypeVtxCent = ColumnBinningPolicy; + + Partition PosKaon_MC = + (aod::track::signed1Pt > static_cast(0)) && + (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); + Partition NegKaon_MC = + (aod::track::signed1Pt < static_cast(0)) && + (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); + Partition PosKaon = + (aod::track::signed1Pt > static_cast(0)) && + (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); + Partition NegKaon = + (aod::track::signed1Pt < static_cast(0)) && + (!cfg_Track_TPCPID || (nabs(aod::pidtpc::tpcNSigmaKa) <= cfg_Track_TPCPID_nSig)); + + double massKa = o2::constants::physics::MassKPlus; + //***********************************// + // First, we declare some helper functions + 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()); + } + } + } + if constexpr (requires { obj.tpcCrossedRowsOverFindableCls(); }) { + if (objecttype == 2) { + 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()); + } 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()); + } + } + if (objecttype == 3) { + if (!pass) { + histos.fill(HIST("hTPC_nSigma_BC"), obj.tpcNSigmaKa()); + histos.fill(HIST("hTOF_nSigma_BC"), obj.tofNSigmaKa()); + histos.fill(HIST("hTPC_nSigma_v_pt_BC"), obj.tpcNSigmaKa(), obj.pt()); + histos.fill(HIST("hTOF_nSigma_v_pt_BC"), obj.tofNSigmaKa(), obj.pt()); + } else { + histos.fill(HIST("hTPC_nSigma_AC"), obj.tpcNSigmaKa()); + histos.fill(HIST("hTOF_nSigma_AC"), obj.tofNSigmaKa()); + histos.fill(HIST("hTPC_nSigma_v_pt_AC"), obj.tpcNSigmaKa(), obj.pt()); + histos.fill(HIST("hTOF_nSigma_v_pt_AC"), obj.tofNSigmaKa(), obj.pt()); + } + } + } + }; + //***********************************// + + // evsel + template + std::pair eventSelection(const EventType event, const bool QA) + { + + if (cfg_Track_CutQA && QA) + fillQA(false, event, 1); + + if (!event.sel8()) + return {false, 1}; + if (std::abs(event.posZ()) > cfg_Event_VtxCut) + return {false, 2}; + if (cfg_Event_Timeframe && (!event.selection_bit(aod::evsel::kNoTimeFrameBorder) || !event.selection_bit(aod::evsel::kNoITSROFrameBorder))) + return {false, 3}; + if (cfg_Event_Timerange && (!event.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) + 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)) + return {false, 6}; + if (cfg_Event_OccupancyCut && (event.trackOccupancyInTimeRange() > cfg_Event_MaxOccupancy)) + return {false, 7}; + + if (cfg_Track_CutQA && QA) + fillQA(true, event, 1); + + return {true, 8}; + }; + + // tracksel + template + bool trackSelection(const TrackType track, const bool QA) + { + if (cfg_Track_CutQA && QA) + fillQA(false, track, 2); + + // basic track cuts + if (track.pt() < cfg_Track_MinPt) + return false; + if (std::abs(track.eta()) > cfg_Track_MaxEta) + return false; + if (std::abs(track.dcaXY()) > cfg_Track_MaxDCArToPVcut) + return false; + if (std::abs(track.dcaZ()) > cfg_Track_MaxDCAzToPVcut) + return false; + if (cfg_Track_PrimaryTrack && !track.isPrimaryTrack()) + return false; + if (track.tpcNClsFindable() < cfg_Track_nFindableTPCClusters) + return false; + if (track.tpcNClsCrossedRows() < cfg_Track_nTPCCrossedRows) + return false; + if (track.tpcCrossedRowsOverFindableCls() > cfg_Track_nRowsOverFindable) + return false; + if (track.tpcChi2NCl() > cfg_Track_nTPCChi2) + return false; + if (track.itsChi2NCl() > cfg_Track_nITSChi2) + return false; + if (cfg_Track_ConnectedToPV && !track.isPVContributor()) + return false; + + if (cfg_Track_CutQA && QA) + fillQA(true, track, 2); + return true; + }; + + // trackpid + + template + bool trackPIDKaon(const TrackPID& candidate, const bool QA) + { + bool tpcPIDPassed{false}, tofPIDPassed{false}; + + if (cfg_Track_CutQA && QA) + fillQA(false, candidate, 3); + + if (!cfg_Track_TPCPID) { + tpcPIDPassed = true; + } else { + if (std::abs(candidate.tpcNSigmaKa()) < cfg_Track_TPCPID_nSig) + tpcPIDPassed = true; + } + + if (!cfg_Track_TOFPID) { + tofPIDPassed = true; + } else { + if (candidate.hasTOF()) { + if (std::abs(candidate.tofNSigmaKa()) < cfg_Track_TOFPID_nSig) { + tofPIDPassed = true; + } + } else if (!cfg_Track_Hard_TOFPID) { + tofPIDPassed = true; + } + if (!candidate.hasTOF()) { + std::cout << candidate.tofNSigmaKa() << std::endl; + } + } + if (tpcPIDPassed && tofPIDPassed) { + if (cfg_Track_CutQA && QA) { + fillQA(true, candidate, 3); + } + return true; + } + return false; + } + + template + void TrackSlicing(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool QA, const bool IsMix) + { + auto slicedtracks1 = PosKaon->sliceByCached(aod::track::collisionId, collision1.globalIndex(), cache); + auto slicedtracks2 = NegKaon->sliceByCached(aod::track::collisionId, collision2.globalIndex(), cache); + auto centrality = collision1.centFT0C(); + for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { + auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); + if (Minv < 0) + continue; + double conjugate = track1.sign() * track2.sign(); + if (!IsMix) { + if (conjugate < 0) { + histos.fill(HIST("hUSS"), centrality, Minv, PhiPt); + } else if (conjugate > 0) { + histos.fill(HIST("hLSS"), centrality, Minv, PhiPt); + } + } else { + if (conjugate < 0) { + histos.fill(HIST("hUSS_Mix"), centrality, Minv, PhiPt); + } else if (conjugate > 0) { + histos.fill(HIST("hLSS_Mix"), centrality, Minv, PhiPt); + } + } + } + } // TrackSlicing + + template + void TrackSlicing_MC(const CollisionType& collision1, const TracksType&, const CollisionType& collision2, const TracksType&, const bool QA, const bool IsMix) + { + 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(); + for (auto& [track1, track2] : combinations(o2::soa::CombinationsFullIndexPolicy(slicedtracks1, slicedtracks2))) { + auto [Minv, PhiPt] = minvReconstruction(track1, track2, QA); + if (Minv < 0) + continue; + double conjugate = track1.sign() * track2.sign(); + if (!IsMix) { + if (conjugate < 0) { + histos.fill(HIST("hMC_USS"), centrality, Minv, PhiPt); + } else if (conjugate > 0) { + histos.fill(HIST("hMC_LSS"), centrality, Minv, PhiPt); + } + } else { + if (conjugate < 0) { + histos.fill(HIST("hMC_USS_Mix"), centrality, Minv, PhiPt); + } else if (conjugate > 0) { + histos.fill(HIST("hMC_LSS_Mix"), centrality, Minv, PhiPt); + } + } + // now we do mc true + if (!track1.has_mcParticle() || !track2.has_mcParticle()) + continue; + auto part1 = track1.mcParticle(); + auto part2 = track2.mcParticle(); + if (std::fabs(part1.pdgCode()) != 321) + continue; // Not Kaon + if (std::fabs(part2.pdgCode()) != 321) + continue; // Not Kaon + + if (!part1.has_mothers()) + continue; // Not decaying Kaon + if (!part2.has_mothers()) + continue; // Not decaying Kaon + + std::vector mothers1{}; + std::vector mothers1PDG{}; + for (auto& part1_mom : part1.template mothers_as()) { + mothers1.push_back(part1_mom.globalIndex()); + mothers1PDG.push_back(part1_mom.pdgCode()); + } + + std::vector mothers2{}; + std::vector mothers2PDG{}; + for (auto& part2_mom : part2.template mothers_as()) { + mothers2.push_back(part2_mom.globalIndex()); + mothers2PDG.push_back(part2_mom.pdgCode()); + } + + if (mothers1PDG[0] != 333) + continue; // mother not phi + if (mothers2PDG[0] != 333) + continue; // mother not phi + + if (mothers1[0] != mothers2[0]) + continue; // Kaons not from the same phi + + histos.fill(HIST("hMC_USS_True"), centrality, Minv, PhiPt); + } + } // TrackSlicing + + // Invariant mass + template + std::pair minvReconstruction(const TracksType& trk1, const TracksType& trk2, const bool QA) + { + TLorentzVector lDecayDaughter1, lDecayDaughter2, lResonance; + //==================================================== + + if (!trackSelection(trk1, QA) || !trackSelection(trk2, false)) + return {-1.0, -1.0}; + + if (cfg_Track_Explicit_PID) { + if (!trackPIDKaon(trk1, QA) || !trackPIDKaon(trk2, false)) + return {-1.0, -1.0}; + } + + if (trk1.globalIndex() >= trk2.globalIndex()) + return {-1.0, -1.0}; + + lDecayDaughter1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), massKa); + lDecayDaughter2.SetXYZM(trk2.px(), trk2.py(), trk2.pz(), massKa); + lResonance = lDecayDaughter1 + lDecayDaughter2; + + return {lResonance.M(), lResonance.Pt()}; + } // MinvReconstruction + + //***************// + // DATA + //***************// + + int nEvents = 0; + void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks) + { + if (cDebugLevel > 0) { + ++nEvents; + if (nEvents % 10000 == 0) { + std::cout << "Processed Data Events: " << nEvents << std::endl; + } + } + + auto [goodEv, code] = eventSelection(collision, true); + histos.fill(HIST("hnEvents"), code); + if (!goodEv) + return; + TrackSlicing(collision, tracks, collision, tracks, true, false); + + } // end of process + + PROCESS_SWITCH(phiOO, processSameEvent, "Process Same events", true); + + //***************// + // DATA (MIX) + //***************// + + int nEvents_Mix = 0; + void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + BinningTypeVtxCent colBinning{{cfg_bins_MixVtx, cfg_bins_MixMult}, true}; + SameKindPair pairs{colBinning, cfg_Mix_NMixedEvents, -1, collisions, tracksTuple, &cache}; + + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (cDebugLevel > 0) { + ++nEvents_Mix; + if (nEvents_Mix % 10000 == 0) { + std::cout << "Processed Mixed Events: " << nEvents_Mix << std::endl; + } + } + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); + if (!goodEv1 || !goodEv2) + continue; + TrackSlicing(collision1, tracks1, collision2, tracks2, false, true); + } // mixing + } // end of process + PROCESS_SWITCH(phiOO, processMixedEvent, "Process Mixed events", false); + + //***************// + // RECONSTRUCTED MC + //***************// + + int nEvents_MC = 0; + void processSameEvent_MC(EventCandidates::iterator const& collision, TrackCandidates_MC const& tracks, aod::McParticles const&) + { + if (cDebugLevel > 0) { + ++nEvents_MC; + if (nEvents_MC % 10000 == 0) { + std::cout << "Processed MC (REC) Events: " << nEvents_MC << std::endl; + } + } + + auto [goodEv, code] = eventSelection(collision, true); + histos.fill(HIST("hnEvents_MC"), code); + if (!goodEv) + return; + TrackSlicing_MC(collision, tracks, collision, tracks, true, false); + + } // end of process + PROCESS_SWITCH(phiOO, processSameEvent_MC, "Process Same events (MC)", true); + + //***************// + // RECONSTRUCTED MC (MIX) + //***************// + + int nEvents_MC_Mix = 0; + void processMixedEvent_MC(EventCandidates const& collisions, TrackCandidates_MC const& tracks, aod::McParticles const&) + { + auto tracksTuple = std::make_tuple(tracks); + BinningTypeVtxCent colBinning{{cfg_bins_MixVtx, cfg_bins_MixMult}, true}; + SameKindPair pairs{colBinning, cfg_Mix_NMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { + if (cDebugLevel > 0) { + ++nEvents_MC_Mix; + if (nEvents_MC_Mix % 10000 == 0) { + std::cout << "Processed Mixed Events: " << nEvents_MC_Mix << std::endl; + } + } + auto [goodEv1, code1] = eventSelection(collision1, false); + auto [goodEv2, code2] = eventSelection(collision2, false); + if (!goodEv1 || !goodEv2) + continue; + TrackSlicing_MC(collision1, tracks1, collision2, tracks2, false, true); + } // mixing + } // end of process + PROCESS_SWITCH(phiOO, processMixedEvent_MC, "Process Mixed events (MC)", false); + + //***************// + // GENERATED MC + //***************// + + int nEvents_True = 0; + void processParticles(EventCandidates_True::iterator const& collision, soa::SmallGroups> const& recocolls, aod::McParticles const& particles) + { + if (cDebugLevel > 0) { + ++nEvents_True; + if (nEvents_True % 10000 == 0) { + std::cout << "Processed MC (GEN) Events: " << nEvents_True << std::endl; + } + } + + if (fabs(collision.posZ()) > cfg_Event_VtxCut) + return; + + if (recocolls.size() <= 0) { // not reconstructed + if (cfg_Force_GenReco) { + return; + } + } + + double centrality = -1; + for (auto& recocoll : recocolls) { // poorly reconstructed + centrality = recocoll.centFT0C(); + auto [goodEv, code] = eventSelection(recocoll, false); + histos.fill(HIST("hnEvents_MC_True"), code); + if (!goodEv) + return; + } + + for (auto& particle : particles) { + if (particle.pdgCode() != 333) + continue; + if (std::fabs(particle.eta()) > cfg_Track_MaxEta) + continue; + + 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 + + histos.fill(HIST("hMC_Phi_True"), centrality, particle.pt()); + } // loop over particles + + } // end of process + PROCESS_SWITCH(phiOO, processParticles, "Process Particles", false); + +}; // end of main struct + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +}; diff --git a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx index e2224d11e3f..520fd541b26 100644 --- a/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx +++ b/PWGLF/Tasks/Resonances/phianalysisrun3_PbPb.cxx @@ -16,49 +16,50 @@ // (5) particle = 2 --> lambdastar // (6) 4 process function (a) Data same event (b) Data mixed event (c) MC generated (d) MC reconstructed -#include +#include "PWGLF/DataModel/EPCalibrationTables.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/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.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/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 #include +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include -#include + #include +#include #include -#include #include - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "TF1.h" - -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" +#include using namespace o2; using namespace o2::framework; @@ -82,14 +83,18 @@ struct phianalysisrun3_PbPb { Configurable cfgCutEta{"cfgCutEta", 0.8, "Eta cut on daughter track"}; Configurable cfgCutDCAxy{"cfgCutDCAxy", 2.0f, "DCAxy range for tracks"}; Configurable cfgCutDCAz{"cfgCutDCAz", 2.0f, "DCAz range for tracks"}; - Configurable nsigmaCutTPC{"nsigmacutTPC", 2.0, "Value of the TPC Nsigma cut"}; - Configurable nsigmaCutTOF{"nsigmacutTOF", 2.0, "Value of the TOF Nsigma cut"}; + Configurable nsigmacutTPC{"nsigmacutTPC", 2.0f, "Value of the TPC Nsigma cut"}; + Configurable nsigmacutTOF{"nsigmacutTOF", 2.0f, "Value of the TOF Nsigma cut"}; Configurable nsigmaCutCombined{"nsigmaCutCombined", 3.0, "Value of the TOF Nsigma cut"}; Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; Configurable fillOccupancy{"fillOccupancy", true, "fill Occupancy"}; Configurable isNoTOF{"isNoTOF", false, "isNoTOF"}; + Configurable additionalEvSel1{"additionalEvSel1", true, "Additional evsel1"}; Configurable additionalEvSel2{"additionalEvSel2", true, "Additional evsel2"}; Configurable additionalEvSel3{"additionalEvSel3", true, "Additional evsel3"}; + Configurable additionalEvSel4{"additionalEvSel4", true, "Additional evsel4"}; + Configurable additionalEvSel5{"additionalEvSel5", true, "Additional evsel5"}; + Configurable additionalEvSel6{"additionalEvSel6", true, "Additional evsel6"}; Configurable cfgMultFT0{"cfgMultFT0", true, "cfgMultFT0"}; Configurable iscustomDCAcut{"iscustomDCAcut", false, "iscustomDCAcut"}; Configurable ismanualDCAcut{"ismanualDCAcut", true, "ismanualDCAcut"}; @@ -101,17 +106,15 @@ struct phianalysisrun3_PbPb { Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; Configurable nBkgRotations{"nBkgRotations", 3, "Number of rotated copies (background) per each original candidate"}; Configurable fillRotation{"fillRotation", true, "fill rotation"}; - Configurable confMinRot{"confMinRot", 5.0 * TMath::Pi() / 6.0, "Minimum of rotation"}; - Configurable confMaxRot{"confMaxRot", 7.0 * TMath::Pi() / 6.0, "Maximum of rotation"}; - Configurable PDGcheck{"PDGcheck", true, "PDGcheck"}; - Configurable Reco{"Reco", true, "Reco"}; + Configurable confMinRot{"confMinRot", 5.0f * TMath::Pi() / 6.0f, "Minimum of rotation"}; + Configurable confMaxRot{"confMaxRot", 7.0f * TMath::Pi() / 6.0f, "Maximum of rotation"}; + Configurable pdgcheck{"pdgcheck", true, "pdgcheck"}; + Configurable reco{"reco", true, "reco"}; ConfigurableAxis binsImpactPar{"binsImpactPar", {VARIABLE_WIDTH, 0, 3.5, 5.67, 7.45, 8.85, 10.0, 11.21, 12.26, 13.28, 14.23, 15.27}, "Binning of the impact parameter axis"}; ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.2, 0.3, 0.4, 0.6, 0.8, 1, 1.2, 1.4, 1.6, 1.8, 2.0, 2.2, 2.4, 2.6, 2.8, 3.0, 3.5, 4.0, 4.5, 5.0, 6.0, 7.0, 8.0, 10.0, 12.0}, "Binning of the pT axis"}; ConfigurableAxis binsCent{"binsCent", {VARIABLE_WIDTH, 0.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"}; - Configurable cfgCutCentrality{"cfgCutCentrality", 80.0f, "Accepted maximum Centrality"}; - Configurable cfgCutMaxOccupancy{"cfgCutMaxOccupancy", 2000.0f, "Accepted maximum Occupancy"}; - Configurable cfgApplyOccupancyCut{"cfgApplyOccupancyCut", false, "Apply maximum Occupancy"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 3000, "Occupancy cut"}; + Configurable centestimator{"centestimator", 0, "Select multiplicity estimator: 0 - FT0C, 1 - FT0A, 2 - FT0M, 3 - FV0A, 4 - PVTracks"}; Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; // MC @@ -132,6 +135,7 @@ struct phianalysisrun3_PbPb { histos.add("h3PhiInvMassMixed", "Invariant mass of Phi meson Mixed", kTH3F, {{200, 0.0, 200.0}, {200, 0.0f, 20.0f}, {200, 0.9, 1.1}}); histos.add("h3PhiInvMassRot", "Invariant mass of Phi meson Rotation", kTH3F, {{200, 0.0, 200.0}, {200, 0.0f, 20.0f}, {200, 0.9, 1.1}}); histos.add("h3PhiInvMassSame", "Invariant mass of Phi meson same", kTH3F, {{200, 0.0, 200.0}, {200, 0.0f, 20.0f}, {200, 0.9, 1.1}}); + histos.add("h2PhiRapidity", "phi meson Rapidity", kTH2F, {{200, 0.0f, 20.0f}, {200, -4, 4}}); } else if (isMC) { histos.add("hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); histos.add("EL1", "MC Event statistics", kTH1F, {impactParAxis}); @@ -145,6 +149,8 @@ struct phianalysisrun3_PbPb { histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {{200, 0.0f, 20.0f}}); histos.add("Centrec", "MC Centrality", kTH1F, {{200, 0.0, 200.0}}); histos.add("Centgen", "MC Centrality", kTH1F, {{200, 0.0, 200.0}}); + histos.add("hVtxZgen", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); + histos.add("hVtxZrec", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); histos.add("h2PhiRec2", "Phi meson Rec", kTH2F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}}); histos.add("h3PhiRec3", "Phi meson Rec", kTH3F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}, {200, 0.9, 1.1}}); histos.add("h3Phi1Rec3", "Phi meson Rec", kTH3F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}, {200, 0.9, 1.1}}); @@ -163,12 +169,25 @@ struct phianalysisrun3_PbPb { histos.add("h1Phi1massrec", "Phi meson Rec", kTH1F, {{200, 0.9, 1.1}}); histos.add("h1Phipt", "Phi meson Rec", kTH1F, {{200, 0.0f, 20.0f}}); histos.add("hOccupancy1", "Occupancy distribution", kTH1F, {{500, 0, 50000}}); + histos.add("h1PhifinalRec", "Phi meson Rec", kTH1F, {{200, 0.0f, 20.0f}}); + histos.add("h1Phifinalgenmass", "Phi meson gen mass", kTH1F, {{200, 0.9, 1.1}}); + histos.add("h3PhifinalRec", "Phi meson Rec", kTH3F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}, {200, 0.9, 1.1}}); + histos.add("h1PhifinalGen", "Phi meson Gen", kTH1F, {{200, 0.0f, 20.0f}}); + histos.add("h2PhifinalGen", "Phi meson Gen", kTH2F, {{200, 0.0f, 20.0f}, {200, 0.0, 200.0}}); + histos.add("hMC1", "MC Event statistics", kTH1F, {{15, 0.0f, 15.0f}}); + histos.add("Centrec1", "MC Centrality", kTH1F, {{200, 0.0, 200.0}}); + histos.add("Centgen1", "MC Centrality", kTH1F, {{200, 0.0, 200.0}}); + histos.add("h1PhiRecsplit1", "Phi meson Rec split", kTH1F, {{200, 0.0f, 20.0f}}); histos.add("hImpactParameterGen", "Impact parameter of generated MC events", kTH1F, {impactParAxis}); histos.add("hImpactParameterRec", "Impact parameter of generated MC events", kTH1F, {impactParAxis}); histos.add("hImpactParameterGenCen", "Impact parameter of generated MC events", kTH2F, {impactParAxis, centAxis}); histos.add("hImpactParameterRecCen", "Impact parameter of generated MC events", kTH2F, {impactParAxis, centAxis}); histos.add("TOF_Nsigma_MC", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3D, {{200, -12, 12}, {200, 0.0, 200.0}, {200, 0.0f, 20.0f}}}); histos.add("TPC_Nsigma_MC", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3D, {{200, -12, 12}, {200, 0.0, 200.0}, {200, 0.0f, 20.0f}}}); + histos.add("TOF_Nsigma1_MC", "TOF NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TOF}^{Kaon};", {HistType::kTH3D, {{200, -12, 12}, {200, 0.0, 200.0}, {200, 0.0f, 20.0f}}}); + histos.add("TPC_Nsigma1_MC", "TPC NSigma for Kaon;#it{p}_{T} (GeV/#it{c});#sigma_{TPC}^{Kaon};", {HistType::kTH3D, {{200, -12, 12}, {200, 0.0, 200.0}, {200, 0.0f, 20.0f}}}); + histos.add("trkDCAxy", "DCAxy distribution of positive kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); + histos.add("trkDCAz", "DCAxy distribution of negative kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); 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}); @@ -178,6 +197,9 @@ struct phianalysisrun3_PbPb { } } + histos.add("hEta", "eta of kaon track candidates", HistType::kTH2F, {{200, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("hPhi", "phi of kaon track candidates", HistType::kTH2F, {{65, 0, 6.5}, {200, 0.0f, 20.0f}}); + // DCA QA // DCA histograms: separate for positive and negative kaons, range [-1.0, 1.0] histos.add("QAbefore/trkDCAxy_pos", "DCAxy distribution of positive kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); @@ -185,10 +207,20 @@ struct phianalysisrun3_PbPb { histos.add("QAbefore/trkDCAz_pos", "DCAz distribution of positive kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); histos.add("QAbefore/trkDCAz_neg", "DCAz distribution of negative kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); + histos.add("QAbefore/trkDCAxypt_pos", "DCAxy distribution of positive kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("QAbefore/trkDCAxypt_neg", "DCAxy distribution of negative kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("QAbefore/trkDCAzpt_pos", "DCAz distribution of positive kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("QAbefore/trkDCAzpt_neg", "DCAz distribution of negative kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("QAafter/trkDCAxy_pos", "DCAxy distribution of positive kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); histos.add("QAafter/trkDCAxy_neg", "DCAxy distribution of negative kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); histos.add("QAafter/trkDCAz_pos", "DCAz distribution of positive kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); histos.add("QAafter/trkDCAz_neg", "DCAz distribution of negative kaon track candidates", HistType::kTH1F, {{150, -1.0f, 1.0f}}); + + histos.add("QAafter/trkDCAxypt_pos", "DCAxy distribution of positive kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("QAafter/trkDCAxypt_neg", "DCAxy distribution of negative kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("QAafter/trkDCAzpt_pos", "DCAz distribution of positive kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); + histos.add("QAafter/trkDCAzpt_neg", "DCAz distribution of negative kaon track candidates", HistType::kTH2F, {{150, -1.0f, 1.0f}, {200, 0.0f, 20.0f}}); // PID QA before cuts histos.add("QAbefore/TOF_TPC_Mapka_all_pos", "TOF + TPC Combined PID for positive Kaon;#sigma_{TOF}^{K^{+}};#sigma_{TPC}^{K^{+}}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); histos.add("QAbefore/TOF_TPC_Mapka_all_neg", "TOF + TPC Combined PID for negative Kaon;#sigma_{TOF}^{K^{-}};#sigma_{TPC}^{K^{-}}", {HistType::kTH2D, {{100, -6, 6}, {100, -6, 6}}}); @@ -238,10 +270,10 @@ struct phianalysisrun3_PbPb { if (!isNoTOF && candidate.hasTOF() && (candidate.tofNSigmaKa() * candidate.tofNSigmaKa() + candidate.tpcNSigmaKa() * candidate.tpcNSigmaKa()) < (nsigmaCutCombined * nsigmaCutCombined)) { return true; } - if (!isNoTOF && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { + if (!isNoTOF && !candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < nsigmacutTPC) { return true; } - if (isNoTOF && std::abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { + if (isNoTOF && std::abs(candidate.tpcNSigmaKa()) < nsigmacutTPC) { return true; } return false; @@ -249,10 +281,10 @@ struct phianalysisrun3_PbPb { template bool selectionPIDpTdependent(const T& candidate) { - if (!candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC) { + if (!candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < nsigmacutTPC) { return true; } - if (candidate.hasTOF() && TMath::Abs(candidate.tpcNSigmaKa()) < nsigmaCutTPC && TMath::Abs(candidate.tofNSigmaKa()) < nsigmaCutTOF) { + if (candidate.hasTOF() && std::abs(candidate.tpcNSigmaKa()) < nsigmacutTPC && std::abs(candidate.tofNSigmaKa()) < nsigmacutTOF) { return true; } return false; @@ -262,17 +294,32 @@ struct phianalysisrun3_PbPb { { if (std::abs(collision.posZ()) > cfgCutVertex) return false; + if (!collision.sel8()) return false; - if (additionalEvSel2 && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) + + if (additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) return false; - if (additionalEvSel3 && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) + + if (additionalEvSel2 && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) + return false; + + if (additionalEvSel3 && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) + return false; + + if (additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) + return false; + if (additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) + return false; + if (additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) return false; int occupancy = collision.trackOccupancyInTimeRange(); if (fillOccupancy && (occupancy > cfgCutOccupancy)) return false; + return true; } + // deep angle cut on pair to remove photon conversion template bool selectionPair(const T1& candidate1, const T2& candidate2) @@ -284,28 +331,42 @@ struct phianalysisrun3_PbPb { pz2 = candidate2.pz(); p1 = candidate1.p(); p2 = candidate2.p(); - angle = TMath::ACos((pt1 * pt2 + pz1 * pz2) / (p1 * p2)); + angle = std::acos((pt1 * pt2 + pz1 * pz2) / (p1 * p2)); if (isDeepAngle && angle < cfgDeepAngle) { return false; } return true; } template - void FillinvMass(const T1& candidate1, const T2& candidate2, float multiplicity, bool unlike, bool mix, float massd1, float massd2) + void fillinvMass(const T1& candidate1, const T2& candidate2, float multiplicity, bool unlike, bool mix, float massd1, float massd2) { - pvec0 = array{candidate1.px(), candidate1.py(), candidate1.pz()}; - pvec1 = array{candidate2.px(), candidate2.py(), candidate2.pz()}; - auto arrMom = array{pvec0, pvec1}; + pvec0 = std::array{candidate1.px(), candidate1.py(), candidate1.pz()}; + pvec1 = std::array{candidate2.px(), candidate2.py(), candidate2.pz()}; + auto arrMom = std::array, 2>{pvec0, pvec1}; + int track1Sign = candidate1.sign(); int track2Sign = candidate2.sign(); - mass = RecoDecay::m(arrMom, array{massd1, massd2}); - pT = RecoDecay::pt(array{candidate1.px() + candidate2.px(), candidate1.py() + candidate2.py()}); - rapidity = RecoDecay::y(array{candidate1.px() + candidate2.px(), candidate1.py() + candidate2.py(), candidate1.pz() + candidate2.pz()}, mass); + mass = RecoDecay::m(arrMom, std::array{massd1, massd2}); + + pT = RecoDecay::pt(std::array{ + candidate1.px() + candidate2.px(), + candidate1.py() + candidate2.py()}); + + rapidity = RecoDecay::y(std::array{ + candidate1.px() + candidate2.px(), + candidate1.py() + candidate2.py(), + candidate1.pz() + candidate2.pz()}, + mass); + + constexpr float kRapidityCut = 0.5; + constexpr int kOppositeCharge = 0; // default filling - if (std::abs(rapidity) < 0.5 && track1Sign * track2Sign < 0) { + if (std::abs(rapidity) < kRapidityCut && track1Sign * track2Sign < kOppositeCharge) { + if (unlike) { histos.fill(HIST("h3PhiInvMassUnlikeSign"), multiplicity, pT, mass); + histos.fill(HIST("h2PhiRapidity"), pT, rapidity); } if (mix) { histos.fill(HIST("h3PhiInvMassMixed"), multiplicity, pT, mass); @@ -314,13 +375,13 @@ struct phianalysisrun3_PbPb { } Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter acceptanceFilter = (nabs(aod::track::eta) < cfgCutEta && nabs(aod::track::pt) > cfgCutPT); - Filter DCAcutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); + Filter dcacutFilter = (nabs(aod::track::dcaXY) < cfgCutDCAxy) && (nabs(aod::track::dcaZ) < cfgCutDCAz); - using EventCandidates = soa::Filtered>; + using EventCandidates = soa::Filtered>; using TrackCandidates = soa::Filtered>; // using EventCandidatesMC = soa::Join; - using EventCandidatesMC = soa::Join; + using EventCandidatesMC = soa::Join; using TrackCandidatesMC = soa::Filtered>; @@ -331,15 +392,17 @@ struct phianalysisrun3_PbPb { using FilTrackMCRecTable = soa::Filtered; ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; - ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; - ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "TPC multiplicity for bin"}; + ConfigurableAxis axisMultiplicity{"axisMultiplicity", {2000, 0, 10000}, "multiplicity for bin"}; Preslice perCollision = aod::track::collisionId; SliceCache cache; - using BinningTypeVertexContributor = ColumnBinningPolicy; - ROOT::Math::PxPyPzMVector PhiMesonMother, KaonPlus, KaonMinus; + using BinningTypeVertexContributor1 = ColumnBinningPolicy; + using BinningTypeVertexContributor2 = ColumnBinningPolicy; + using BinningTypeVertexContributor3 = ColumnBinningPolicy; + using BinningTypeVertexContributor4 = ColumnBinningPolicy; + ROOT::Math::PxPyPzMVector phiMesonMother, kaonPlus, kaonMinus; void processSameEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { histos.fill(HIST("hEvtSelInfo"), 0.5); @@ -351,47 +414,82 @@ struct phianalysisrun3_PbPb { return; } histos.fill(HIST("hEvtSelInfo"), 2.5); - if (additionalEvSel2 && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + if (additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { return; } histos.fill(HIST("hEvtSelInfo"), 3.5); - if (additionalEvSel3 && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + if (additionalEvSel2 && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { return; } histos.fill(HIST("hEvtSelInfo"), 4.5); + if (additionalEvSel3 && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 5.5); + if (additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 6.5); + if (additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 7.5); + if (additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 8.5); int occupancy = collision.trackOccupancyInTimeRange(); if (fillOccupancy && (occupancy > cfgCutOccupancy)) { return; } - histos.fill(HIST("hEvtSelInfo"), 5.5); + histos.fill(HIST("hEvtSelInfo"), 9.5); float multiplicity{-1}; - if (cfgMultFT0) + const int kCentFT0C = 0; + const int kCentFT0A = 1; + const int kCentFT0M = 2; + const int kCentFV0A = 3; + + if (centestimator == kCentFT0C) { multiplicity = collision.centFT0C(); + } else if (centestimator == kCentFT0A) { + multiplicity = collision.centFT0A(); + } else if (centestimator == kCentFT0M) { + multiplicity = collision.centFT0M(); + } else if (centestimator == kCentFV0A) { + multiplicity = collision.centFV0A(); + } + histos.fill(HIST("hCentrality"), multiplicity); histos.fill(HIST("hVtxZ"), collision.posZ()); histos.fill(HIST("hOccupancy"), occupancy); - for (auto track1 : tracks) { + for (const auto& track1 : tracks) { if (!selectionTrack(track1)) { continue; } int track1Sign = track1.sign(); // or track1.charge(), assuming it returns ±1 + histos.fill(HIST("hEta"), track1.eta(), track1.pt()); + histos.fill(HIST("hPhi"), track1.phi(), track1.pt()); if (track1Sign > 0) { // Positive kaon histos.fill(HIST("QAbefore/TPC_Nsigma_all_pos"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAbefore/TOF_Nsigma_all_pos"), track1.tofNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAbefore/trkDCAxy_pos"), track1.dcaXY()); histos.fill(HIST("QAbefore/trkDCAz_pos"), track1.dcaZ()); + histos.fill(HIST("QAbefore/trkDCAxypt_pos"), track1.dcaXY(), track1.pt()); + histos.fill(HIST("QAbefore/trkDCAzpt_pos"), track1.dcaZ(), track1.pt()); histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all_pos"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); } else if (track1Sign < 0) { // Negative kaon histos.fill(HIST("QAbefore/TPC_Nsigma_all_neg"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAbefore/TOF_Nsigma_all_neg"), track1.tofNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAbefore/trkDCAxy_neg"), track1.dcaXY()); histos.fill(HIST("QAbefore/trkDCAz_neg"), track1.dcaZ()); + histos.fill(HIST("QAbefore/trkDCAxypt_neg"), track1.dcaXY(), track1.pt()); + histos.fill(HIST("QAbefore/trkDCAzpt_neg"), track1.dcaZ(), track1.pt()); histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all_neg"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); } auto track1ID = track1.globalIndex(); - for (auto track2 : tracks) { + for (const auto& track2 : tracks) { if (!selectionTrack(track2)) { continue; } @@ -412,16 +510,20 @@ struct phianalysisrun3_PbPb { histos.fill(HIST("QAafter/TOF_Nsigma_all_pos"), track1.tofNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAafter/trkDCAxy_pos"), track1.dcaXY()); histos.fill(HIST("QAafter/trkDCAz_pos"), track1.dcaZ()); + histos.fill(HIST("QAafter/trkDCAxypt_pos"), track1.dcaXY(), track1.pt()); + histos.fill(HIST("QAafter/trkDCAzpt_pos"), track1.dcaZ(), track1.pt()); histos.fill(HIST("QAafter/TOF_TPC_Mapka_all_pos"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); } else if (track1Sign < 0) { // Negative kaon histos.fill(HIST("QAafter/TPC_Nsigma_all_neg"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAafter/TOF_Nsigma_all_neg"), track1.tofNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAafter/trkDCAxy_neg"), track1.dcaXY()); histos.fill(HIST("QAafter/trkDCAz_neg"), track1.dcaZ()); + histos.fill(HIST("QAafter/trkDCAxypt_neg"), track1.dcaXY(), track1.pt()); + histos.fill(HIST("QAafter/trkDCAzpt_neg"), track1.dcaZ(), track1.pt()); histos.fill(HIST("QAafter/TOF_TPC_Mapka_all_neg"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); } - FillinvMass(track1, track2, multiplicity, unlike, mix, massKa, massKa); + fillinvMass(track1, track2, multiplicity, unlike, mix, massKa, massKa); } if (ispTdepPID && selectionPIDpTdependent(track1) && selectionPIDpTdependent(track2)) { @@ -432,29 +534,33 @@ struct phianalysisrun3_PbPb { histos.fill(HIST("QAafter/TOF_Nsigma_all_pos"), track1.tofNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAafter/trkDCAxy_pos"), track1.dcaXY()); histos.fill(HIST("QAafter/trkDCAz_pos"), track1.dcaZ()); + histos.fill(HIST("QAafter/trkDCAxypt_pos"), track1.dcaXY(), track1.pt()); + histos.fill(HIST("QAafter/trkDCAzpt_pos"), track1.dcaZ(), track1.pt()); histos.fill(HIST("QAafter/TOF_TPC_Mapka_all_pos"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); } else if (track1Sign < 0) { // Negative kaon histos.fill(HIST("QAafter/TPC_Nsigma_all_neg"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAafter/TOF_Nsigma_all_neg"), track1.tofNSigmaKa(), multiplicity, track1.pt()); histos.fill(HIST("QAafter/trkDCAxy_neg"), track1.dcaXY()); histos.fill(HIST("QAafter/trkDCAz_neg"), track1.dcaZ()); + histos.fill(HIST("QAafter/trkDCAxypt_neg"), track1.dcaXY(), track1.pt()); + histos.fill(HIST("QAafter/trkDCAzpt_neg"), track1.dcaZ(), track1.pt()); histos.fill(HIST("QAafter/TOF_TPC_Mapka_all_neg"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); } - FillinvMass(track1, track2, multiplicity, unlike, mix, massKa, massKa); + fillinvMass(track1, track2, multiplicity, unlike, mix, massKa, massKa); } } } } PROCESS_SWITCH(phianalysisrun3_PbPb, processSameEvent, "Process Same event", false); - void processMixedEvent(EventCandidates const& collisions, TrackCandidates const& tracks) + void processMixedEvent1(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); //////// currently mixing the event with similar TPC multiplicity //////// - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicity}, true}; - SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; - for (auto& [c1, tracks1, c2, tracks2] : pair) { + BinningTypeVertexContributor1 binningOnPositions{{axisVertex, axisMultiplicity}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [c1, tracks1, c2, tracks2] : pair) { if (rctCut.requireRCTFlagChecker && !rctChecker(c1)) { continue; } @@ -467,33 +573,168 @@ struct phianalysisrun3_PbPb { if (!c2.sel8()) { continue; } - if (additionalEvSel2 && (!c1.selection_bit(aod::evsel::kNoSameBunchPileup) || !c1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + if (additionalEvSel1 && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder))) { + continue; + } + if (additionalEvSel2 && (!c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { continue; } - if (additionalEvSel2 && (!c2.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + if (additionalEvSel3 && (!c1.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kNoSameBunchPileup))) { continue; } - if (additionalEvSel3 && (!c1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + if (additionalEvSel4 && (!c1.selection_bit(aod::evsel::kIsGoodITSLayersAll) || !c2.selection_bit(aod::evsel::kIsGoodITSLayersAll))) { continue; } - if (additionalEvSel3 && (!c2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + if (additionalEvSel5 && (!c1.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) || !c2.selection_bit(aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + if (additionalEvSel6 && (!c1.selection_bit(aod::evsel::kNoCollInRofStandard) || !c2.selection_bit(aod::evsel::kNoCollInRofStandard))) { continue; } int occupancy1 = c1.trackOccupancyInTimeRange(); int occupancy2 = c2.trackOccupancyInTimeRange(); - if (fillOccupancy && (occupancy1 > cfgCutOccupancy)) { + + if (fillOccupancy && (occupancy1 > cfgCutOccupancy || occupancy2 > cfgCutOccupancy)) { continue; } - if (fillOccupancy && (occupancy2 > cfgCutOccupancy)) { + float multiplicity; + multiplicity = c1.centFT0C(); + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + bool unlike = false; + bool mix = true; + if (!selectionTrack(t1)) { + continue; + } + if (!selectionTrack(t2)) { + continue; + } + if (!selectionPair(t1, t2)) { + continue; + } + if (!ispTdepPID && selectionPID(t1) && selectionPID(t2)) { + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + } + if (ispTdepPID && selectionPIDpTdependent(t1) && selectionPIDpTdependent(t2)) { + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + } + } + } + } + PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent1, "Process Mixed event", false); + void processMixedEvent2(EventCandidates const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + //////// currently mixing the event with similar TPC multiplicity //////// + BinningTypeVertexContributor2 binningOnPositions{{axisVertex, axisMultiplicity}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [c1, tracks1, c2, tracks2] : pair) { + if (rctCut.requireRCTFlagChecker && !rctChecker(c1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(c2)) { + continue; + } + if (!c1.sel8()) { + continue; + } + if (!c2.sel8()) { + continue; + } + if (additionalEvSel1 && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder))) { + continue; + } + if (additionalEvSel2 && (!c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel3 && (!c1.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (additionalEvSel4 && (!c1.selection_bit(aod::evsel::kIsGoodITSLayersAll) || !c2.selection_bit(aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + if (additionalEvSel5 && (!c1.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) || !c2.selection_bit(aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + if (additionalEvSel6 && (!c1.selection_bit(aod::evsel::kNoCollInRofStandard) || !c2.selection_bit(aod::evsel::kNoCollInRofStandard))) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); + int occupancy2 = c2.trackOccupancyInTimeRange(); + + if (fillOccupancy && (occupancy1 > cfgCutOccupancy || occupancy2 > cfgCutOccupancy)) { continue; } float multiplicity; - if (cfgMultFT0) - multiplicity = c1.centFT0C(); - if (!cfgMultFT0) - multiplicity = c1.numContrib(); + multiplicity = c1.centFT0A(); + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + bool unlike = false; + bool mix = true; + if (!selectionTrack(t1)) { + continue; + } + if (!selectionTrack(t2)) { + continue; + } + if (!selectionPair(t1, t2)) { + continue; + } + if (!ispTdepPID && selectionPID(t1) && selectionPID(t2)) { + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + } + if (ispTdepPID && selectionPIDpTdependent(t1) && selectionPIDpTdependent(t2)) { + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + } + } + } + } + + PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent2, "Process Mixed event", false); + void processMixedEvent3(EventCandidates const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + //////// currently mixing the event with similar TPC multiplicity //////// + BinningTypeVertexContributor3 binningOnPositions{{axisVertex, axisMultiplicity}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [c1, tracks1, c2, tracks2] : pair) { + if (rctCut.requireRCTFlagChecker && !rctChecker(c1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(c2)) { + continue; + } + if (!c1.sel8()) { + continue; + } + if (!c2.sel8()) { + continue; + } + if (additionalEvSel1 && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder))) { + continue; + } + if (additionalEvSel2 && (!c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel3 && (!c1.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (additionalEvSel4 && (!c1.selection_bit(aod::evsel::kIsGoodITSLayersAll) || !c2.selection_bit(aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + if (additionalEvSel5 && (!c1.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) || !c2.selection_bit(aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + if (additionalEvSel6 && (!c1.selection_bit(aod::evsel::kNoCollInRofStandard) || !c2.selection_bit(aod::evsel::kNoCollInRofStandard))) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); + int occupancy2 = c2.trackOccupancyInTimeRange(); - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (fillOccupancy && (occupancy1 > cfgCutOccupancy || occupancy2 > cfgCutOccupancy)) { + continue; + } + float multiplicity; + multiplicity = c1.centFT0M(); + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { bool unlike = false; bool mix = true; if (!selectionTrack(t1)) { @@ -506,16 +747,84 @@ struct phianalysisrun3_PbPb { continue; } if (!ispTdepPID && selectionPID(t1) && selectionPID(t2)) { - FillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); } if (ispTdepPID && selectionPIDpTdependent(t1) && selectionPIDpTdependent(t2)) { - FillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); } } } } - PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent, "Process Mixed event", false); + PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent3, "Process Mixed event", false); + void processMixedEvent4(EventCandidates const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + //////// currently mixing the event with similar TPC multiplicity //////// + BinningTypeVertexContributor4 binningOnPositions{{axisVertex, axisMultiplicity}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + for (const auto& [c1, tracks1, c2, tracks2] : pair) { + if (rctCut.requireRCTFlagChecker && !rctChecker(c1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(c2)) { + continue; + } + if (!c1.sel8()) { + continue; + } + if (!c2.sel8()) { + continue; + } + if (additionalEvSel1 && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder))) { + continue; + } + if (additionalEvSel2 && (!c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel3 && (!c1.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kNoSameBunchPileup))) { + continue; + } + if (additionalEvSel4 && (!c1.selection_bit(aod::evsel::kIsGoodITSLayersAll) || !c2.selection_bit(aod::evsel::kIsGoodITSLayersAll))) { + continue; + } + if (additionalEvSel5 && (!c1.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) || !c2.selection_bit(aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + if (additionalEvSel6 && (!c1.selection_bit(aod::evsel::kNoCollInRofStandard) || !c2.selection_bit(aod::evsel::kNoCollInRofStandard))) { + continue; + } + int occupancy1 = c1.trackOccupancyInTimeRange(); + int occupancy2 = c2.trackOccupancyInTimeRange(); + + if (fillOccupancy && (occupancy1 > cfgCutOccupancy || occupancy2 > cfgCutOccupancy)) { + continue; + } + float multiplicity; + multiplicity = c1.centFV0A(); + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + bool unlike = false; + bool mix = true; + if (!selectionTrack(t1)) { + continue; + } + if (!selectionTrack(t2)) { + continue; + } + if (!selectionPair(t1, t2)) { + continue; + } + if (!ispTdepPID && selectionPID(t1) && selectionPID(t2)) { + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + } + if (ispTdepPID && selectionPIDpTdependent(t1) && selectionPIDpTdependent(t2)) { + fillinvMass(t1, t2, multiplicity, unlike, mix, massKa, massKa); + } + } + } + } + + PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEvent4, "Process Mixed event", false); void processRotEvent(EventCandidates::iterator const& collision, TrackCandidates const& tracks, aod::BCs const&) { if (!collision.sel8()) { @@ -537,7 +846,8 @@ struct phianalysisrun3_PbPb { histos.fill(HIST("hCentrality"), multiplicity); histos.fill(HIST("hVtxZ"), collision.posZ()); histos.fill(HIST("hOccupancy"), occupancy); - for (auto track1 : tracks) { + for (const auto& track1 : tracks) { + if (!selectionTrack(track1)) { continue; } @@ -548,7 +858,7 @@ struct phianalysisrun3_PbPb { histos.fill(HIST("QAbefore/TOF_TPC_Mapka_all"), track1.tofNSigmaKa(), track1.tpcNSigmaKa()); auto track1ID = track1.globalIndex(); - for (auto track2 : tracks) { + for (const auto& track2 : tracks) { if (!selectionTrack(track2)) { continue; } @@ -566,14 +876,14 @@ struct phianalysisrun3_PbPb { continue; } if (track1.sign() * track2.sign() < 0) { - KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); - KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + kaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); } - PhiMesonMother = KaonPlus + KaonMinus; - if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + phiMesonMother = kaonPlus + kaonMinus; + if (std::abs(phiMesonMother.Rapidity()) > confRapidity) { continue; } - histos.fill(HIST("h3PhiInvMassSame"), multiplicity, PhiMesonMother.pt(), PhiMesonMother.M()); + histos.fill(HIST("h3PhiInvMassSame"), multiplicity, phiMesonMother.pt(), phiMesonMother.M()); if (fillRotation) { for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { auto anglestart = confMinRot; @@ -583,14 +893,14 @@ struct phianalysisrun3_PbPb { if (track1.sign() * track2.sign() < 0) { auto rotkaonPx = track1.px() * std::cos(rotangle) - track1.py() * std::sin(rotangle); auto rotkaonPy = track1.px() * std::sin(rotangle) + track1.py() * std::cos(rotangle); - KaonPlus = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track1.pz(), massKa); - KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + kaonPlus = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track1.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); } - PhiMesonMother = KaonPlus + KaonMinus; - if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + phiMesonMother = kaonPlus + kaonMinus; + if (std::abs(phiMesonMother.Rapidity()) > confRapidity) { continue; } - histos.fill(HIST("h3PhiInvMassRot"), multiplicity, PhiMesonMother.pt(), PhiMesonMother.M()); + histos.fill(HIST("h3PhiInvMassRot"), multiplicity, phiMesonMother.pt(), phiMesonMother.M()); } } } @@ -609,7 +919,7 @@ struct phianalysisrun3_PbPb { histos.fill(HIST("hMC"), 2); return; } - for (auto& RecCollision : RecCollisions) { + for (const auto& RecCollision : RecCollisions) { histos.fill(HIST("hMC"), 3); if (!RecCollision.sel8()) { histos.fill(HIST("hMC"), 4); @@ -626,16 +936,16 @@ struct phianalysisrun3_PbPb { if (fillOccupancy && (occupancy > cfgCutOccupancy)) { continue; } - if (TMath::Abs(RecCollision.posZ()) > cfgCutVertex) { + if (std::abs(RecCollision.posZ()) > cfgCutVertex) { histos.fill(HIST("hMC"), 6); continue; } histos.fill(HIST("hMC"), 7); auto centrality = RecCollision.centFT0C(); auto oldindex = -999; - auto Rectrackspart = RecTracks.sliceBy(perCollision, RecCollision.globalIndex()); + auto rectrackspart = RecTracks.sliceBy(perCollision, RecCollision.globalIndex()); // loop over reconstructed particle - for (auto track1 : Rectrackspart) { + for (const auto& track1 : rectrackspart) { if (!selectionTrack(track1)) { continue; } @@ -649,7 +959,7 @@ struct phianalysisrun3_PbPb { continue; } auto track1ID = track1.index(); - for (auto track2 : Rectrackspart) { + for (const auto& track2 : rectrackspart) { auto track2ID = track2.index(); if (track2ID <= track1ID) { continue; @@ -674,29 +984,29 @@ struct phianalysisrun3_PbPb { } const auto mctrack1 = track1.mcParticle(); const auto mctrack2 = track2.mcParticle(); - int track1PDG = TMath::Abs(mctrack1.pdgCode()); - int track2PDG = TMath::Abs(mctrack2.pdgCode()); + int track1PDG = std::abs(mctrack1.pdgCode()); + int track2PDG = std::abs(mctrack2.pdgCode()); if (!mctrack1.isPhysicalPrimary()) { continue; } if (!mctrack2.isPhysicalPrimary()) { continue; } - if (!(track1PDG == 321 && track2PDG == 321)) { + if (!(track1PDG == PDG_t::kKPlus && track2PDG == PDG_t::kKPlus)) { continue; } - for (auto& mothertrack1 : mctrack1.mothers_as()) { - for (auto& mothertrack2 : mctrack2.mothers_as()) { + for (const auto& mothertrack1 : mctrack1.mothers_as()) { + for (const auto& mothertrack2 : mctrack2.mothers_as()) { if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { continue; } if (mothertrack1 != mothertrack2) { continue; } - if (TMath::Abs(mothertrack1.y()) > confRapidity) { + if (std::abs(mothertrack1.y()) > confRapidity) { continue; } - if (PDGcheck && TMath::Abs(mothertrack1.pdgCode()) != 333) { + if (pdgcheck && std::abs(mothertrack1.pdgCode()) != o2::constants::physics::kPhi) { continue; } if (!ispTdepPID && (!selectionPID(track1) || !selectionPID(track2))) { @@ -711,65 +1021,68 @@ struct phianalysisrun3_PbPb { } oldindex = mothertrack1.globalIndex(); if (track1.sign() * track2.sign() < 0) { - KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); - KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + kaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); } - PhiMesonMother = KaonPlus + KaonMinus; + phiMesonMother = kaonPlus + kaonMinus; - if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + if (std::abs(phiMesonMother.Rapidity()) > confRapidity) { continue; } - histos.fill(HIST("h1PhiRec1"), PhiMesonMother.pt()); - histos.fill(HIST("h2PhiRec2"), PhiMesonMother.pt(), centrality); - histos.fill(HIST("h1Phimassrec"), PhiMesonMother.M()); - histos.fill(HIST("h3PhiRec3"), PhiMesonMother.pt(), centrality, PhiMesonMother.M()); + histos.fill(HIST("h1PhiRec1"), phiMesonMother.pt()); + histos.fill(HIST("h2PhiRec2"), phiMesonMother.pt(), centrality); + histos.fill(HIST("h1Phimassrec"), phiMesonMother.M()); + histos.fill(HIST("h3PhiRec3"), phiMesonMother.pt(), centrality, phiMesonMother.M()); histos.fill(HIST("Centrec"), centrality); } } } } // loop over generated particle - for (auto& mcParticle : GenParticles) { - if (TMath::Abs(mcParticle.y()) > confRapidity) { + for (const auto& mcParticle : GenParticles) { + if (std::abs(mcParticle.y()) > confRapidity) { continue; } - if (PDGcheck && mcParticle.pdgCode() != 333) { + if (pdgcheck && mcParticle.pdgCode() != o2::constants::physics::kPhi) { continue; } auto kDaughters = mcParticle.daughters_as(); - if (kDaughters.size() != 2) { + const size_t kExpectedDaughterCount = 2; + + if (kDaughters.size() != kExpectedDaughterCount) { + continue; } auto daughtp = false; auto daughtm = false; - for (auto kCurrentDaughter : kDaughters) { + for (const auto& kCurrentDaughter : kDaughters) { if (!kCurrentDaughter.isPhysicalPrimary()) { continue; } - if (kCurrentDaughter.pdgCode() == +321) { - if (genacceptancecut && kCurrentDaughter.pt() > cfgCutPT && TMath::Abs(kCurrentDaughter.eta()) < cfgCutEta) { + if (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { + if (genacceptancecut && kCurrentDaughter.pt() > cfgCutPT && std::abs(kCurrentDaughter.eta()) < cfgCutEta) { daughtp = true; } if (!genacceptancecut) { daughtp = true; } - KaonPlus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); - } else if (kCurrentDaughter.pdgCode() == -321) { - if (genacceptancecut && kCurrentDaughter.pt() > cfgCutPT && TMath::Abs(kCurrentDaughter.eta()) < cfgCutEta) { + kaonPlus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { + if (genacceptancecut && kCurrentDaughter.pt() > cfgCutPT && std::abs(kCurrentDaughter.eta()) < cfgCutEta) { daughtm = true; } if (!genacceptancecut) { daughtm = true; } - KaonMinus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); } } if (daughtp && daughtm) { - PhiMesonMother = KaonPlus + KaonMinus; - histos.fill(HIST("h1PhiGen"), PhiMesonMother.pt()); - histos.fill(HIST("h2PhiGen2"), PhiMesonMother.pt(), centrality); + phiMesonMother = kaonPlus + kaonMinus; + histos.fill(HIST("h1PhiGen"), phiMesonMother.pt()); + histos.fill(HIST("h2PhiGen2"), phiMesonMother.pt(), centrality); histos.fill(HIST("Centgen"), centrality); - histos.fill(HIST("h1Phimassgen"), PhiMesonMother.M()); + histos.fill(HIST("h1Phimassgen"), phiMesonMother.M()); } } } // rec collision loop @@ -785,7 +1098,7 @@ struct phianalysisrun3_PbPb { } float imp = mcCollision.impactParameter(); histos.fill(HIST("hImpactParameterGen"), imp); - std::vector SelectedEvents(collisions.size()); + std::vector selectedEvents(collisions.size()); int nevts = 0; auto multiplicity = 0; for (const auto& collision : collisions) { @@ -802,53 +1115,60 @@ struct phianalysisrun3_PbPb { histos.fill(HIST("hOccupancy1"), occupancy); multiplicity = collision.centFT0C(); histos.fill(HIST("Centgen"), multiplicity); + histos.fill(HIST("hVtxZgen"), collision.mcCollision().posZ()); histos.fill(HIST("hImpactParameterGenCen"), imp, multiplicity); - SelectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); histos.fill(HIST("hMC"), 2.5); } - SelectedEvents.resize(nevts); + selectedEvents.resize(nevts); - const auto evtReconstructedAndSelected = std::find(SelectedEvents.begin(), SelectedEvents.end(), mcCollision.globalIndex()) != SelectedEvents.end(); + const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); histos.fill(HIST("EL1"), imp); histos.fill(HIST("EL2"), multiplicity); - if (Reco && !evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + if (reco && !evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection return; } histos.fill(HIST("ES1"), imp); histos.fill(HIST("ES2"), multiplicity); - for (auto& mcParticle : mcParticles) { - if (std::abs(mcParticle.y()) >= 0.5) { + for (const auto& mcParticle : mcParticles) { + const double kMaxAcceptedRapidity = 0.5; + + if (std::abs(mcParticle.y()) >= kMaxAcceptedRapidity) { + continue; } - if (PDGcheck && mcParticle.pdgCode() != 333) { + if (pdgcheck && mcParticle.pdgCode() != o2::constants::physics::kPhi) { continue; } auto kDaughters = mcParticle.daughters_as(); - if (kDaughters.size() != 2) { + const size_t kExpectedNumberOfDaughters = 2; + + if (kDaughters.size() != kExpectedNumberOfDaughters) { + continue; } auto daughtp = false; auto daughtm = false; - for (auto kCurrentDaughter : kDaughters) { + for (const auto& kCurrentDaughter : kDaughters) { if (!kCurrentDaughter.isPhysicalPrimary()) { continue; } - if (kCurrentDaughter.pdgCode() == +321) { + if (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { daughtp = true; - KaonPlus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); - } else if (kCurrentDaughter.pdgCode() == -321) { + kaonPlus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { daughtm = true; - KaonMinus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(kCurrentDaughter.px(), kCurrentDaughter.py(), kCurrentDaughter.pz(), massKa); } } if (daughtp && daughtm) { - PhiMesonMother = KaonPlus + KaonMinus; - histos.fill(HIST("h1PhiGen"), PhiMesonMother.pt()); - histos.fill(HIST("h2PhiGen2"), PhiMesonMother.pt(), multiplicity); - histos.fill(HIST("h2PhiGen1"), PhiMesonMother.pt(), imp); - histos.fill(HIST("h1Phimassgen"), PhiMesonMother.M()); - histos.fill(HIST("h3PhiGen3"), PhiMesonMother.pt(), multiplicity, PhiMesonMother.M()); + phiMesonMother = kaonPlus + kaonMinus; + histos.fill(HIST("h1PhiGen"), phiMesonMother.pt()); + histos.fill(HIST("h2PhiGen2"), phiMesonMother.pt(), multiplicity); + histos.fill(HIST("h2PhiGen1"), phiMesonMother.pt(), imp); + histos.fill(HIST("h1Phimassgen"), phiMesonMother.M()); + histos.fill(HIST("h3PhiGen3"), phiMesonMother.pt(), multiplicity, phiMesonMother.M()); } } } @@ -870,13 +1190,14 @@ struct phianalysisrun3_PbPb { } auto multiplicity = collision.centFT0C(); histos.fill(HIST("Centrec"), multiplicity); + histos.fill(HIST("hVtxZrec"), collision.posZ()); float imp = collision.mcCollision().impactParameter(); histos.fill(HIST("hImpactParameterRec"), imp); histos.fill(HIST("hImpactParameterRecCen"), imp, multiplicity); histos.fill(HIST("ES3"), imp); histos.fill(HIST("ES4"), multiplicity); auto oldindex = -999; - for (auto track1 : tracks) { + for (const auto& track1 : tracks) { if (!selectionTrack(track1)) { continue; } @@ -884,7 +1205,7 @@ struct phianalysisrun3_PbPb { continue; } auto track1ID = track1.index(); - for (auto track2 : tracks) { + for (const auto& track2 : tracks) { if (!track2.has_mcParticle()) { continue; } @@ -911,7 +1232,7 @@ struct phianalysisrun3_PbPb { if (!mctrack2.isPhysicalPrimary()) { continue; } - if (!(track1PDG == 321 && track2PDG == 321)) { + if (!(track1PDG == PDG_t::kKPlus && track2PDG == PDG_t::kKPlus)) { continue; } daughter1 = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); @@ -920,8 +1241,8 @@ struct phianalysisrun3_PbPb { phiMother = daughter1 + daughter2; histos.fill(HIST("h1Phi1massrec"), phiMother.M()); histos.fill(HIST("h3Phi1Rec3"), phiMother.pt(), multiplicity, phiMother.M()); - for (auto& mothertrack1 : mctrack1.mothers_as()) { - for (auto& mothertrack2 : mctrack2.mothers_as()) { + for (const auto& mothertrack1 : mctrack1.mothers_as()) { + for (const auto& mothertrack2 : mctrack2.mothers_as()) { if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { continue; } @@ -931,10 +1252,13 @@ struct phianalysisrun3_PbPb { if (!mothertrack1.producedByGenerator()) { continue; } - if (std::abs(mothertrack1.y()) >= 0.5) { + const double kMaxRapidityCut = 0.5; + + if (std::abs(mothertrack1.y()) >= kMaxRapidityCut) { continue; } - if (PDGcheck && std::abs(mothertrack1.pdgCode()) != 333) { + + if (pdgcheck && std::abs(mothertrack1.pdgCode()) != o2::constants::physics::kPhi) { continue; } if (!ispTdepPID && (!selectionPID(track1) || !selectionPID(track2))) { @@ -952,18 +1276,18 @@ struct phianalysisrun3_PbPb { } oldindex = mothertrack1.globalIndex(); if (track1.sign() * track2.sign() < 0) { - KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); - KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + kaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); } - PhiMesonMother = KaonPlus + KaonMinus; + phiMesonMother = kaonPlus + kaonMinus; - if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + if (std::abs(phiMesonMother.Rapidity()) > confRapidity) { continue; } - histos.fill(HIST("h1PhiRec1"), PhiMesonMother.pt()); - histos.fill(HIST("h2PhiRec2"), PhiMesonMother.pt(), multiplicity); - histos.fill(HIST("h1Phimassrec"), PhiMesonMother.M()); - histos.fill(HIST("h3PhiRec3"), PhiMesonMother.pt(), multiplicity, PhiMesonMother.M()); + histos.fill(HIST("h1PhiRec1"), phiMesonMother.pt()); + histos.fill(HIST("h2PhiRec2"), phiMesonMother.pt(), multiplicity); + histos.fill(HIST("h1Phimassrec"), phiMesonMother.M()); + histos.fill(HIST("h3PhiRec3"), phiMesonMother.pt(), multiplicity, phiMesonMother.M()); } } } @@ -976,10 +1300,22 @@ struct phianalysisrun3_PbPb { if (!collision.sel8()) { return; } - if (additionalEvSel2 && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + if (additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { return; } - if (additionalEvSel3 && (!collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + if (additionalEvSel2 && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + if (additionalEvSel3 && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + if (additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + if (additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return; + } + if (additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return; } int occupancy = collision.trackOccupancyInTimeRange(); @@ -988,12 +1324,12 @@ struct phianalysisrun3_PbPb { } float multiplicity{-1}; multiplicity = collision.centFT0C(); - for (auto track1 : tracks) { + for (const auto& track1 : tracks) { if (!selectionTrack(track1)) { continue; } auto track1ID = track1.globalIndex(); - for (auto track2 : tracks) { + for (const auto& track2 : tracks) { if (!selectionTrack(track2)) { continue; } @@ -1011,15 +1347,15 @@ struct phianalysisrun3_PbPb { continue; } if (track1.sign() * track2.sign() < 0) { - KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); - KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + kaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); } - PhiMesonMother = KaonPlus + KaonMinus; - if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + phiMesonMother = kaonPlus + kaonMinus; + if (std::abs(phiMesonMother.Rapidity()) > confRapidity) { continue; } - histos.fill(HIST("h3PhiInvMassSameMC"), multiplicity, PhiMesonMother.pt(), PhiMesonMother.M()); - histos.fill(HIST("h1Phimasssame"), PhiMesonMother.M()); + histos.fill(HIST("h3PhiInvMassSameMC"), multiplicity, phiMesonMother.pt(), phiMesonMother.M()); + histos.fill(HIST("h1Phimasssame"), phiMesonMother.M()); if (fillRotation) { for (int nrotbkg = 0; nrotbkg < nBkgRotations; nrotbkg++) { auto anglestart = confMinRot; @@ -1029,15 +1365,15 @@ struct phianalysisrun3_PbPb { if (track1.sign() * track2.sign() < 0) { auto rotkaonPx = track1.px() * std::cos(rotangle) - track1.py() * std::sin(rotangle); auto rotkaonPy = track1.px() * std::sin(rotangle) + track1.py() * std::cos(rotangle); - KaonPlus = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track1.pz(), massKa); - KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + kaonPlus = ROOT::Math::PxPyPzMVector(rotkaonPx, rotkaonPy, track1.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); } - PhiMesonMother = KaonPlus + KaonMinus; - if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + phiMesonMother = kaonPlus + kaonMinus; + if (std::abs(phiMesonMother.Rapidity()) > confRapidity) { continue; } - histos.fill(HIST("h3PhiInvMassRotMC"), multiplicity, PhiMesonMother.pt(), PhiMesonMother.M()); - histos.fill(HIST("h1Phimassrot"), PhiMesonMother.M()); + histos.fill(HIST("h3PhiInvMassRotMC"), multiplicity, phiMesonMother.pt(), phiMesonMother.M()); + histos.fill(HIST("h1Phimassrot"), phiMesonMother.M()); } } } @@ -1049,26 +1385,32 @@ struct phianalysisrun3_PbPb { { auto tracksTuple = std::make_tuple(RecTracks); - BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicity}, true}; - SameKindPair pairs{binningOnPositions, cfgNoMixedEvents, -1, recCollisions, tracksTuple, &cache}; + BinningTypeVertexContributor1 binningOnPositions{{axisVertex, axisMultiplicity}, true}; + SameKindPair pairs{binningOnPositions, cfgNoMixedEvents, -1, recCollisions, tracksTuple, &cache}; - for (auto& [c1, tracks1, c2, tracks2] : pairs) { + for (const auto& [c1, tracks1, c2, tracks2] : pairs) { if (!c1.sel8()) { continue; } if (!c2.sel8()) { continue; } - if (additionalEvSel2 && (!c1.selection_bit(aod::evsel::kNoSameBunchPileup) || !c1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + if (additionalEvSel1 && (!c1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !c2.selection_bit(aod::evsel::kNoTimeFrameBorder))) { + continue; + } + if (additionalEvSel2 && (!c1.selection_bit(aod::evsel::kNoITSROFrameBorder) || !c2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { continue; } - if (additionalEvSel2 && (!c2.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + if (additionalEvSel3 && (!c1.selection_bit(aod::evsel::kNoSameBunchPileup) || !c2.selection_bit(aod::evsel::kNoSameBunchPileup))) { continue; } - if (additionalEvSel3 && (!c1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + if (additionalEvSel4 && (!c1.selection_bit(aod::evsel::kIsGoodITSLayersAll) || !c2.selection_bit(aod::evsel::kIsGoodITSLayersAll))) { continue; } - if (additionalEvSel3 && (!c2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard))) { + if (additionalEvSel5 && (!c1.selection_bit(aod::evsel::kNoCollInTimeRangeStandard) || !c2.selection_bit(aod::evsel::kNoCollInTimeRangeStandard))) { + continue; + } + if (additionalEvSel6 && (!c1.selection_bit(aod::evsel::kNoCollInRofStandard) || !c2.selection_bit(aod::evsel::kNoCollInRofStandard))) { continue; } int occupancy1 = c1.trackOccupancyInTimeRange(); @@ -1080,7 +1422,7 @@ struct phianalysisrun3_PbPb { continue; } auto multiplicity = c1.centFT0C(); - for (auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + for (const auto& [t1, t2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { histos.fill(HIST("hMC"), 6.5); if (!selectionTrack(t1)) { continue; @@ -1098,19 +1440,263 @@ struct phianalysisrun3_PbPb { continue; } if (t1.sign() * t2.sign() < 0) { - KaonPlus = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); - KaonMinus = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); + kaonPlus = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); + kaonMinus = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); } - PhiMesonMother = KaonPlus + KaonMinus; - if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { + phiMesonMother = kaonPlus + kaonMinus; + if (std::abs(phiMesonMother.Rapidity()) > confRapidity) { continue; } - histos.fill(HIST("h3PhiInvMassMixedMC"), multiplicity, PhiMesonMother.pt(), PhiMesonMother.M()); - histos.fill(HIST("h1Phimassmix"), PhiMesonMother.M()); + histos.fill(HIST("h3PhiInvMassMixedMC"), multiplicity, phiMesonMother.pt(), phiMesonMother.M()); + histos.fill(HIST("h1Phimassmix"), phiMesonMother.M()); } } } PROCESS_SWITCH(phianalysisrun3_PbPb, processMixedEventMC, "Process Mixed event MC", true); + void processGen1(aod::McCollision const& mcCollision, aod::McParticles& mcParticles, const soa::SmallGroups& collisions) + { + histos.fill(HIST("hMC1"), 0.5); + if (std::abs(mcCollision.posZ()) < cfgCutVertex) { + histos.fill(HIST("hMC1"), 1.5); + } + std::vector selectedEvents(collisions.size()); + int nevts = 0; + auto multiplicity = -1.0; + histos.fill(HIST("hMC1"), 2.5); + for (const auto& collision : collisions) { + if (!collision.sel8() || std::abs(collision.mcCollision().posZ()) > cfgCutVertex) { + continue; + } + histos.fill(HIST("hMC1"), 3.5); + if (additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + continue; + } + histos.fill(HIST("hMC1"), 4.5); + if (additionalEvSel2 && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + continue; + } + histos.fill(HIST("hMC1"), 5.5); + if (additionalEvSel3 && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + histos.fill(HIST("hMC1"), 6.5); + if (additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + histos.fill(HIST("hMC1"), 7.5); + if (additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + histos.fill(HIST("hMC1"), 8.5); + if (additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + histos.fill(HIST("hMC1"), 9.5); + int occupancy = collision.trackOccupancyInTimeRange(); + if (fillOccupancy && (occupancy > cfgCutOccupancy)) { + continue; + } + histos.fill(HIST("hMC1"), 10.5); + const int kCentFT0C = 0; + const int kCentFT0A = 1; + const int kCentFT0M = 2; + const int kCentFV0A = 3; + + if (centestimator == kCentFT0C) { + multiplicity = collision.centFT0C(); + } else if (centestimator == kCentFT0A) { + multiplicity = collision.centFT0A(); + } else if (centestimator == kCentFT0M) { + multiplicity = collision.centFT0M(); + } else if (centestimator == kCentFV0A) { + multiplicity = collision.centFV0A(); + } + histos.fill(HIST("Centgen1"), multiplicity); + selectedEvents[nevts++] = collision.mcCollision_as().globalIndex(); + } + selectedEvents.resize(nevts); + const auto evtReconstructedAndSelected = std::find(selectedEvents.begin(), selectedEvents.end(), mcCollision.globalIndex()) != selectedEvents.end(); + histos.fill(HIST("hMC1"), 11.5); + if (!evtReconstructedAndSelected) { // Check that the event is reconstructed and that the reconstructed events pass the selection + return; + } + histos.fill(HIST("hMC1"), 12.5); + for (const auto& mcParticle : mcParticles) { + const double kMaxRapidityCut = 0.5; + + if (std::abs(mcParticle.y()) >= kMaxRapidityCut) { + continue; + } + + if (mcParticle.pdgCode() != o2::constants::physics::kPhi) { + continue; + } + auto kDaughters = mcParticle.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 (kCurrentDaughter.pdgCode() == PDG_t::kKPlus) { + daughtp = true; + } else if (kCurrentDaughter.pdgCode() == PDG_t::kKMinus) { + daughtm = true; + } + } + if (daughtp && daughtm) { + histos.fill(HIST("h1PhifinalGen"), mcParticle.pt()); + histos.fill(HIST("h2PhifinalGen"), mcParticle.pt(), multiplicity); + } + } + } + + PROCESS_SWITCH(phianalysisrun3_PbPb, processGen1, "Process Generated", false); + void processRec1(EventCandidatesMC::iterator const& collision, TrackCandidatesMC const& tracks, aod::McParticles const& /*mcParticles*/, aod::McCollisions const& /*mcCollisions*/) + { + if (!collision.has_mcCollision()) { + return; + } + if (std::abs(collision.mcCollision().posZ()) > cfgCutVertex || !collision.sel8()) { + return; + } + if (additionalEvSel1 && !collision.selection_bit(aod::evsel::kNoTimeFrameBorder)) { + return; + } + + if (additionalEvSel2 && !collision.selection_bit(aod::evsel::kNoITSROFrameBorder)) { + return; + } + + if (additionalEvSel3 && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + + if (additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + if (additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return; + } + if (additionalEvSel6 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + int occupancy = collision.trackOccupancyInTimeRange(); + if (fillOccupancy && (occupancy > cfgCutOccupancy)) { + return; + } + const int kCentFT0C = 0; + const int kCentFT0A = 1; + const int kCentFT0M = 2; + const int kCentFV0A = 3; + auto multiplicity = -1.0; + if (centestimator == kCentFT0C) { + multiplicity = collision.centFT0C(); + } else if (centestimator == kCentFT0A) { + multiplicity = collision.centFT0A(); + } else if (centestimator == kCentFT0M) { + multiplicity = collision.centFT0M(); + } else if (centestimator == kCentFV0A) { + multiplicity = collision.centFV0A(); + } + histos.fill(HIST("Centrec1"), multiplicity); + histos.fill(HIST("hMC1"), 13.5); + auto oldindex = -999; + for (const auto& track1 : tracks) { + if (!selectionTrack(track1)) { + continue; + } + if (!track1.has_mcParticle()) { + continue; + } + auto track1ID = track1.index(); + for (const auto& track2 : tracks) { + if (!track2.has_mcParticle()) { + continue; + } + if (!selectionTrack(track2)) { + continue; + } + auto track2ID = track2.index(); + if (track2ID <= track1ID) { + continue; + } + if (!selectionPair(track1, track2)) { + continue; + } + if (track1.sign() * track2.sign() > 0) { + continue; + } + const auto mctrack1 = track1.mcParticle(); + const auto mctrack2 = track2.mcParticle(); + int track1PDG = std::abs(mctrack1.pdgCode()); + int track2PDG = std::abs(mctrack2.pdgCode()); + if (!mctrack1.isPhysicalPrimary()) { + continue; + } + if (!mctrack2.isPhysicalPrimary()) { + continue; + } + if (!(track1PDG == PDG_t::kKPlus && track2PDG == PDG_t::kKPlus)) { + continue; + } + for (const auto& mothertrack1 : mctrack1.mothers_as()) { + for (const auto& mothertrack2 : mctrack2.mothers_as()) { + if (mothertrack1.pdgCode() != mothertrack2.pdgCode()) { + continue; + } + if (mothertrack1.globalIndex() != mothertrack2.globalIndex()) { + continue; + } + if (!mothertrack1.producedByGenerator()) { + continue; + } + const double kMaxRapidityCut = 0.5; + + if (std::abs(mothertrack1.y()) >= kMaxRapidityCut) { + continue; + } + + if (std::abs(mothertrack1.pdgCode()) != o2::constants::physics::kPhi) { + continue; + } + if (!(selectionPID(track1) && selectionPID(track2))) { + continue; + } + histos.fill(HIST("TPC_Nsigma1_MC"), track1.tpcNSigmaKa(), multiplicity, track1.pt()); + histos.fill(HIST("TOF_Nsigma1_MC"), track1.tofNSigmaKa(), multiplicity, track1.pt()); + histos.fill(HIST("trkDCAxy"), track1.dcaXY()); + histos.fill(HIST("trkDCAz"), track1.dcaZ()); + if (avoidsplitrackMC && oldindex == mothertrack1.globalIndex()) { + histos.fill(HIST("h1PhiRecsplit1"), mothertrack1.pt()); + continue; + } + oldindex = mothertrack1.globalIndex(); + std::array pvec0 = {track1.px(), track1.py(), track1.pz()}; + std::array pvec1 = {track2.px(), track2.py(), track2.pz()}; + std::array, 2> arrMomrec = {pvec0, pvec1}; + + auto motherP = mothertrack1.p(); + auto motherE = mothertrack1.e(); + genMass = std::sqrt(motherE * motherE - motherP * motherP); + recMass = RecoDecay::m(arrMomrec, array{massKa, massKa}); + + histos.fill(HIST("h1PhifinalRec"), mothertrack1.pt()); + histos.fill(HIST("h3PhifinalRec"), mothertrack1.pt(), multiplicity, recMass); + histos.fill(HIST("h1Phifinalgenmass"), genMass); + } + } + } + } + } + + PROCESS_SWITCH(phianalysisrun3_PbPb, processRec1, "Process Reconstructed", false); void processEvtLossSigLossMC(aod::McCollisions::iterator const& mcCollision, aod::McParticles const& mcParticles, const soa::SmallGroups& recCollisions) { @@ -1134,7 +1720,10 @@ struct phianalysisrun3_PbPb { // Generated MC for (const auto& mcPart : mcParticles) { - if (std::abs(mcPart.y()) >= 0.5 || std::abs(mcPart.pdgCode()) != 333) + const double kMaxRapidity = 0.5; + + if (std::abs(mcPart.y()) >= kMaxRapidity || std::abs(mcPart.pdgCode()) != o2::constants::physics::kPhi) + continue; // signal loss estimation diff --git a/PWGLF/Tasks/Resonances/phipbpb.cxx b/PWGLF/Tasks/Resonances/phipbpb.cxx index 7ab2dd9aa39..521e505ebd2 100644 --- a/PWGLF/Tasks/Resonances/phipbpb.cxx +++ b/PWGLF/Tasks/Resonances/phipbpb.cxx @@ -11,52 +11,54 @@ // Phi meson spin alignment task // sourav.kundu@cern.ch -#include +#include "PWGLF/DataModel/EPCalibrationTables.h" +#include "PWGLF/DataModel/SPCalibrationTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#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/PIDResponseITS.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.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/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 #include +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include -#include + #include +#include #include -#include #include - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "TF1.h" - -#include "PWGLF/DataModel/EPCalibrationTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/PIDResponseITS.h" -#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table +#include using namespace o2; using namespace o2::framework; @@ -92,6 +94,9 @@ struct phipbpb { Configurable cfgCutCentrality{"cfgCutCentrality", 80.0f, "Accepted maximum Centrality"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 3000, "Occupancy cut"}; // track + Configurable cqvas{"cqvas", false, "change q vectors after shift correction"}; + Configurable fillv1{"fillv1", false, "flag to fill v1 histograms"}; + Configurable fillLOCC{"fillLOCC", false, "flag to fill LOCC histograms"}; Configurable useSP{"useSP", false, "use SP"}; Configurable useDcaSyst{"useDcaSyst", false, "useDcaSyst"}; Configurable additionalEvsel{"additionalEvsel", false, "Additional event selcection"}; @@ -117,15 +122,17 @@ struct phipbpb { Configurable checkAllCharge{"checkAllCharge", true, "check all charge for MC weight"}; Configurable cfgDeepAngle{"cfgDeepAngle", 0.04, "Deep Angle cut value"}; Configurable confRapidity{"confRapidity", 0.5, "Rapidity cut"}; - ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {120, 0.98, 1.1}, "#it{M} (GeV/#it{c}^{2})"}; - ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.}, "#it{p}_{T} (GeV/#it{c})"}; - ConfigurableAxis configThnAxisCosThetaStar{"configThnAxisCosThetaStar", {10, -1.0, 1.}, "cos(#vartheta)"}; - ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0., 80}, "Centrality"}; - ConfigurableAxis configThnAxisPhiminusPsi{"configThnAxisPhiminusPsi", {6, 0.0, TMath::Pi()}, "#phi - #psi"}; - ConfigurableAxis configThnAxisV2{"configThnAxisV2", {200, -6, 6}, "V2"}; - ConfigurableAxis configThnAxisRapidity{"configThnAxisRapidity", {8, 0, 0.8}, "Rapidity"}; - ConfigurableAxis configThnAxisSA{"configThnAxisSA", {200, -1, 1}, "SA"}; - ConfigurableAxis configThnAxiscosthetaSA{"configThnAxiscosthetaSA", {200, 0, 1}, "costhetaSA"}; + struct : ConfigurableGroup { + ConfigurableAxis configThnAxisInvMass{"configThnAxisInvMass", {120, 0.98, 1.1}, "#it{M} (GeV/#it{c}^{2})"}; + ConfigurableAxis configThnAxisPt{"configThnAxisPt", {100, 0.0, 10.}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis configThnAxisCosThetaStar{"configThnAxisCosThetaStar", {10, -1.0, 1.}, "cos(#vartheta)"}; + ConfigurableAxis configThnAxisCentrality{"configThnAxisCentrality", {8, 0., 80}, "Centrality"}; + ConfigurableAxis configThnAxisPhiminusPsi{"configThnAxisPhiminusPsi", {6, 0.0, TMath::Pi()}, "#phi - #psi"}; + ConfigurableAxis configThnAxisV2{"configThnAxisV2", {200, -6, 6}, "V2"}; + ConfigurableAxis configThnAxisRapidity{"configThnAxisRapidity", {8, 0, 0.8}, "Rapidity"}; + ConfigurableAxis configThnAxisSA{"configThnAxisSA", {200, -1, 1}, "SA"}; + ConfigurableAxis configThnAxiscosthetaSA{"configThnAxiscosthetaSA", {200, 0, 1}, "costhetaSA"}; + } cnfgaxis; ConfigurableAxis axisPtKaonWeight{"axisPtKaonWeight", {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}, "pt axis"}; Configurable isMC{"isMC", false, "use MC"}; Configurable genacceptancecut{"genacceptancecut", true, "use acceptance cut for generated"}; @@ -133,6 +140,9 @@ struct phipbpb { Configurable islike{"islike", false, "use like"}; Configurable useWeight{"useWeight", true, "use EP dep effi weight"}; Configurable ConfWeightPath{"ConfWeightPath", "Users/s/skundu/My/Object/mcweight", "Path to gain calibration"}; + Configurable spNbins{"spNbins", 2000, "Number of bins in sp"}; + Configurable lbinsp{"lbinsp", -1.0, "lower bin value in sp histograms"}; + Configurable hbinsp{"hbinsp", 1.0, "higher bin value in sp histograms"}; Filter collisionFilter = nabs(aod::collision::posZ) < cfgCutVertex; Filter centralityFilter = nabs(aod::cent::centFT0C) < cfgCutCentrality; @@ -141,6 +151,7 @@ struct phipbpb { Filter PIDcutFilter = nabs(aod::pidtpc::tpcNSigmaKa) < nsigmaCutTPC; using EventCandidates = soa::Filtered>; + using EventCandidatesv1 = soa::Filtered>; using TrackCandidates = soa::Filtered>; using CollisionMCTrueTable = aod::McCollisions; @@ -168,13 +179,13 @@ struct phipbpb { { // std::vector occupancyBinning = {0.0, 500.0, 1000.0, 3000.0, 6000.0, 50000.0}; std::vector occupancyBinning = {-0.5, 500.0, 1000.0, 1500.0, 2000.0, 3000.0, 4000.0, 5000.0, 50000.0}; - const AxisSpec thnAxisInvMass{configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; - const AxisSpec thnAxisPt{configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec thnAxisCosThetaStar{configThnAxisCosThetaStar, "cos(#vartheta_{OP})"}; - const AxisSpec thnAxisCentrality{configThnAxisCentrality, "Centrality (%)"}; - const AxisSpec thnAxisV2{configThnAxisV2, "V2"}; - const AxisSpec thnAxisRapidity{configThnAxisRapidity, "Rapidity"}; - const AxisSpec thnAxisSA{configThnAxisSA, "SA"}; + const AxisSpec thnAxisInvMass{cnfgaxis.configThnAxisInvMass, "#it{M} (GeV/#it{c}^{2})"}; + const AxisSpec thnAxisPt{cnfgaxis.configThnAxisPt, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec thnAxisCosThetaStar{cnfgaxis.configThnAxisCosThetaStar, "cos(#vartheta_{OP})"}; + const AxisSpec thnAxisCentrality{cnfgaxis.configThnAxisCentrality, "Centrality (%)"}; + const AxisSpec thnAxisV2{cnfgaxis.configThnAxisV2, "V2"}; + const AxisSpec thnAxisRapidity{cnfgaxis.configThnAxisRapidity, "Rapidity"}; + const AxisSpec thnAxisSA{cnfgaxis.configThnAxisSA, "SA"}; AxisSpec cumulantAxis = {200, -1, 1, "phi"}; AxisSpec itsAxis = {8, -0.5, 7.5, "its"}; AxisSpec tpcAxis = {130, 69.5, 199.5, "its"}; @@ -184,133 +195,166 @@ struct phipbpb { AxisSpec resAxisSquare = {800, -1, 1, "Res"}; AxisSpec centAxis = {8, 0, 80, "V0M (%)"}; AxisSpec occupancyAxis = {occupancyBinning, "Occupancy"}; + AxisSpec spAxis = {spNbins, lbinsp, hbinsp, "Sp"}; + + if (fillv1) { + histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + + histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {cnfgaxis.configThnAxisCentrality, spAxis}, true); + + histos.add("hpoddvscentpteta", "hpoddvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpoddvscentptetamixacc", "hpoddvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxypvscentptetamixacc", "hpuxyQxypvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxytvscentptetamixacc", "hpuxyQxytvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxvscentptetamixacc", "hpuxvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuyvscentptetamixacc", "hpuyvscentptetamixacc", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpoddvscentptetamixopti", "hpoddvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxypvscentptetamixopti", "hpuxyQxypvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxyQxytvscentptetamixopti", "hpuxyQxytvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuxvscentptetamixopti", "hpuxvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + histos.add("hpuyvscentptetamixopti", "hpuyvscentptetamixopti", HistType::kTHnSparseF, {cnfgaxis.configThnAxisInvMass, cnfgaxis.configThnAxisCentrality, cnfgaxis.configThnAxisPt, cnfgaxis.configThnAxisRapidity, spAxis}, true); + } - histos.add("hTPCglobalmomcorr", "Momentum correlation", kTH3F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}, {8, 0.0f, 80.0f}}); - histos.add("hpTvsRapidity", "pT vs Rapidity", kTH2F, {{100, 0.0f, 10.0f}, {300, -1.5f, 1.5f}}); - histos.add("hFTOCvsTPCNoCut", "Mult correlation FT0C vs. TPC without any cut", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); - histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); - histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{200, 0.0, 200.0}}); histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{400, -20.0, 20.0}}); - histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); - histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); - - histos.add("hITS", "ITS cluster", kTH2F, {{10, -0.5f, 9.5f}, {200, -1.0, 1.0}}); - histos.add("hTPC", "TPC crossed rows", kTH2F, {{90, 69.5f, 159.5f}, {200, -1.0, 1.0}}); - histos.add("hTPCScls", "TPC Shared cluster", kTH2F, {{16, -0.5f, 159.5f}, {200, -1.0, 1.0}}); - histos.add("hTPCSclsFrac", "Fraction of TPC Shared cluster", kTH2F, {{100, -0.0f, 2.0f}, {200, -1.0, 1.0}}); - - histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); - histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); - histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiTPCR", "PsiTPCR", kTH3F, {centAxis, occupancyAxis, phiAxis}); - histos.add("hPsiTPCL", "PsiTPCL", kTH3F, {centAxis, occupancyAxis, phiAxis}); - - histos.add("hSparseV2SameEventCosPhi", "hSparseV2SameEventCosPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventSinPhi", "hSparseV2SameEventSinPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventCosPsi", "hSparseV2SameEventCosPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventSinPsi", "hSparseV2SameEventSinPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); - - histos.add("hSparseV2SameEventCosDeltaPhi", "hSparseV2SameEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCosDeltaPhi", "hSparseV2MixedEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixEPAngleCosDeltaPhi", "hSparseV2MixEPAngleCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - - histos.add("hSparseV2SameEventCos2DeltaPhi", "hSparseV2SameEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCos2DeltaPhi", "hSparseV2MixedEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - - histos.add("hSparseV2SameEventCosDeltaPhiSquare", "hSparseV2SameEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); - histos.add("hSparseV2SameEventCosDeltaPhiCube", "hSparseV2SameEventCosDeltaPhiCube", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCosDeltaPhiSquare", "hSparseV2MixedEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); - - histos.add("hSparseV2SameEventSinDeltaPhi", "hSparseV2SameEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - histos.add("hSparseV2MixedEventSinDeltaPhi", "hSparseV2MixedEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); - - if (fillSA) { - histos.add("hSparseV2SameEventSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MixedEventSA", "hSparseV2MixedEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2SameEventCosThetaStar", "hSparseV2SameEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MixedEventCosThetaStar", "hSparseV2MixedEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - } - // histogram for resolution - histos.add("ResFT0CTPC", "ResFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResFT0ATPC", "ResFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("Res4FT0CTPC", "Res4FT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0CTPCR", "Res4FT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0CTPCL", "Res4FT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4TPCRTPCL", "Res4TPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0CFT0A", "Res4FT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4FT0ATPC", "Res4FT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("ResFT0CTPCSquare", "ResFT0CTPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0CTPCRSquare", "ResFT0CTPCRSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0CTPCLSquare", "ResFT0CTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResTPCRTPCLSquare", "ResTPCRTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0CFT0ASquare", "ResFT0CFT0ASquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - histos.add("ResFT0ATPCSquare", "ResFT0ATPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); - - histos.add("ResSPFT0CTPC", "ResSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0CTPCR", "ResSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0CTPCL", "ResSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPTPCRTPCL", "ResSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0CFT0A", "ResSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResSPFT0ATPC", "ResSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("Res4SPFT0CTPC", "Res4SPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0CTPCR", "Res4SPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0CTPCL", "Res4SPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPTPCRTPCL", "Res4SPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0CFT0A", "Res4SPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("Res4SPFT0ATPC", "Res4SPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - histos.add("ResTrackSPFT0CTPC", "ResTrackSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0CTPCR", "ResTrackSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0CTPCL", "ResTrackSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPTPCRTPCL", "ResTrackSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0CFT0A", "ResTrackSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); - histos.add("ResTrackSPFT0ATPC", "ResTrackSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); - - // MC histogram - if (isMC) { - histos.add("hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); - histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {{100, 0.0f, 10.0f}}); - histos.add("CentPercentileMCRecHist", "MC Centrality", kTH1F, {{100, 0.0f, 100.0f}}); - - histos.add("hSparseV2MCGenSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MCGenCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - - histos.add("hSparseV2MCRecSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); - histos.add("hSparseV2MCRecCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); - - // weight - - histos.add("hSparsePhiMCGenWeight", "hSparsePhiMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCRecWeight", "hSparsePhiMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCGenKaonWeight", "hSparsePhiMCGenKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCRecKaonWeight", "hSparsePhiMCRecKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparsePhiMCRecKaonMissMatchWeight", "hSparsePhiMCRecKaonMissMatchWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - - histos.add("hSparseMCGenWeight", "hSparseMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparseMCRecWeight", "hSparseMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - histos.add("hSparseMCRecAllTrackWeight", "hSparseMCRecAllTrackWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); - - histos.add("hImpactParameter", "Impact parameter", kTH1F, {{200, 0.0f, 20.0f}}); - histos.add("hEventPlaneAngle", "hEventPlaneAngle", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); - histos.add("hEventPlaneAngleRec", "hEventPlaneAngleRec", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); - histos.add("hNchVsImpactParameter", "hNchVsImpactParameter", kTH2F, {{200, 0.0f, 20.0f}, {500, -0.5f, 5000.5f}}); - histos.add("hSparseMCGenV2", "hSparseMCGenV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); - histos.add("hSparseMCRecV2", "hSparseMCRecV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); - // histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); - // histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); - histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); - histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + + if (!fillv1) { + histos.add("hTPCglobalmomcorr", "Momentum correlation", kTH3F, {{200, -10.0f, 10.0f}, {200, -10.0f, 10.0f}, {8, 0.0f, 80.0f}}); + histos.add("hpTvsRapidity", "pT vs Rapidity", kTH2F, {{100, 0.0f, 10.0f}, {300, -1.5f, 1.5f}}); + histos.add("hFTOCvsTPCNoCut", "Mult correlation FT0C vs. TPC without any cut", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPC", "Mult correlation FT0C vs. TPC", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hFTOCvsTPCSelected", "Mult correlation FT0C vs. TPC after selection", kTH2F, {{80, 0.0f, 80.0f}, {100, -0.5f, 5999.5f}}); + histos.add("hEta", "Eta distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaxy", "Dcaxy distribution", kTH1F, {{200, -1.0f, 1.0f}}); + histos.add("hDcaz", "Dcaz distribution", kTH1F, {{200, -1.0f, 1.0f}}); + + histos.add("hITS", "ITS cluster", kTH2F, {{10, -0.5f, 9.5f}, {200, -1.0, 1.0}}); + histos.add("hTPC", "TPC crossed rows", kTH2F, {{90, 69.5f, 159.5f}, {200, -1.0, 1.0}}); + histos.add("hTPCScls", "TPC Shared cluster", kTH2F, {{16, -0.5f, 159.5f}, {200, -1.0, 1.0}}); + histos.add("hTPCSclsFrac", "Fraction of TPC Shared cluster", kTH2F, {{100, -0.0f, 2.0f}, {200, -1.0, 1.0}}); + + histos.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH1F, {{200, -10.0f, 10.0f}}); + histos.add("hPsiFT0C", "PsiFT0C", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiFT0A", "PsiFT0A", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPC", "PsiTPC", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPCR", "PsiTPCR", kTH3F, {centAxis, occupancyAxis, phiAxis}); + histos.add("hPsiTPCL", "PsiTPCL", kTH3F, {centAxis, occupancyAxis, phiAxis}); + + histos.add("hSparseV2SameEventCosPhi", "hSparseV2SameEventCosPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventSinPhi", "hSparseV2SameEventSinPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventCosPsi", "hSparseV2SameEventCosPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventSinPsi", "hSparseV2SameEventSinPsi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, cumulantAxis, thnAxisCentrality}); + + histos.add("hSparseV2SameEventCosDeltaPhi", "hSparseV2SameEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCosDeltaPhi", "hSparseV2MixedEventCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixEPAngleCosDeltaPhi", "hSparseV2MixEPAngleCosDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + + histos.add("hSparseV2SameEventCos2DeltaPhi", "hSparseV2SameEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCos2DeltaPhi", "hSparseV2MixedEventCos2DeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + + histos.add("hSparseV2SameEventCosDeltaPhiSquare", "hSparseV2SameEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); + histos.add("hSparseV2SameEventCosDeltaPhiCube", "hSparseV2SameEventCosDeltaPhiCube", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCosDeltaPhiSquare", "hSparseV2MixedEventCosDeltaPhiSquare", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, squareAxis, thnAxisCentrality}); + + histos.add("hSparseV2SameEventSinDeltaPhi", "hSparseV2SameEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + histos.add("hSparseV2MixedEventSinDeltaPhi", "hSparseV2MixedEventSinDeltaPhi", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisV2, thnAxisCentrality}); + + if (fillSA) { + histos.add("hSparseV2SameEventSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MixedEventSA", "hSparseV2MixedEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2SameEventCosThetaStar", "hSparseV2SameEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MixedEventCosThetaStar", "hSparseV2MixedEventCosThetaStar", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + } + // histogram for resolution + histos.add("ResFT0CTPC", "ResFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CTPCR", "ResFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CTPCL", "ResFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTPCRTPCL", "ResTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0CFT0A", "ResFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResFT0ATPC", "ResFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("Res4FT0CTPC", "Res4FT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0CTPCR", "Res4FT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0CTPCL", "Res4FT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4TPCRTPCL", "Res4TPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0CFT0A", "Res4FT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4FT0ATPC", "Res4FT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("ResFT0CTPCSquare", "ResFT0CTPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0CTPCRSquare", "ResFT0CTPCRSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0CTPCLSquare", "ResFT0CTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResTPCRTPCLSquare", "ResTPCRTPCLSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0CFT0ASquare", "ResFT0CFT0ASquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + histos.add("ResFT0ATPCSquare", "ResFT0ATPCSquare", kTH3F, {centAxis, occupancyAxis, resAxisSquare}); + + histos.add("ResSPFT0CTPC", "ResSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CTPCR", "ResSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CTPCL", "ResSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPTPCRTPCL", "ResSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0CFT0A", "ResSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResSPFT0ATPC", "ResSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("Res4SPFT0CTPC", "Res4SPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0CTPCR", "Res4SPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0CTPCL", "Res4SPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPTPCRTPCL", "Res4SPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0CFT0A", "Res4SPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("Res4SPFT0ATPC", "Res4SPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + histos.add("ResTrackSPFT0CTPC", "ResTrackSPFT0CTPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0CTPCR", "ResTrackSPFT0CTPCR", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0CTPCL", "ResTrackSPFT0CTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPTPCRTPCL", "ResTrackSPTPCRTPCL", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0CFT0A", "ResTrackSPFT0CFT0A", kTH3F, {centAxis, occupancyAxis, resAxis}); + histos.add("ResTrackSPFT0ATPC", "ResTrackSPFT0ATPC", kTH3F, {centAxis, occupancyAxis, resAxis}); + + // MC histogram + if (isMC) { + histos.add("hMC", "MC Event statistics", kTH1F, {{10, 0.0f, 10.0f}}); + histos.add("h1PhiRecsplit", "Phi meson Rec split", kTH1F, {{100, 0.0f, 10.0f}}); + histos.add("CentPercentileMCRecHist", "MC Centrality", kTH1F, {{100, 0.0f, 100.0f}}); + + histos.add("hSparseV2MCGenSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MCGenCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + + histos.add("hSparseV2MCRecSA", "hSparseV2SameEventSA", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisSA, thnAxisRapidity, thnAxisCentrality}); + histos.add("hSparseV2MCRecCosThetaStar_effy", "hSparseV2SameEventCosThetaStar_effy", HistType::kTHnSparseD, {thnAxisInvMass, thnAxisPt, thnAxisCosThetaStar, thnAxisRapidity, thnAxisCentrality}); + + // weight + + histos.add("hSparsePhiMCGenWeight", "hSparsePhiMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCRecWeight", "hSparsePhiMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, thnAxisPt, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCGenKaonWeight", "hSparsePhiMCGenKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCRecKaonWeight", "hSparsePhiMCRecKaonWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparsePhiMCRecKaonMissMatchWeight", "hSparsePhiMCRecKaonMissMatchWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + + histos.add("hSparseMCGenWeight", "hSparseMCGenWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparseMCRecWeight", "hSparseMCRecWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0f, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + histos.add("hSparseMCRecAllTrackWeight", "hSparseMCRecAllTrackWeight", HistType::kTHnSparseD, {thnAxisCentrality, {36, 0.0, TMath::Pi()}, {400, -1.0, 1}, axisPtKaonWeight, {8, -0.8, 0.8}}); + + histos.add("hImpactParameter", "Impact parameter", kTH1F, {{200, 0.0f, 20.0f}}); + histos.add("hEventPlaneAngle", "hEventPlaneAngle", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); + histos.add("hEventPlaneAngleRec", "hEventPlaneAngleRec", kTH1F, {{200, -2.0f * TMath::Pi(), 2.0f * TMath::Pi()}}); + histos.add("hNchVsImpactParameter", "hNchVsImpactParameter", kTH2F, {{200, 0.0f, 20.0f}, {500, -0.5f, 5000.5f}}); + histos.add("hSparseMCGenV2", "hSparseMCGenV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); + histos.add("hSparseMCRecV2", "hSparseMCRecV2", HistType::kTHnSparseD, {thnAxisCentrality, {200, -1.0, 1.0}, axisPtKaonWeight}); + // histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + // histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTHnSparseD, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + histos.add("hSparseMCGenV2Square", "hSparseMCGenV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + histos.add("hSparseMCRecV2Square", "hSparseMCRecV2Square", HistType::kTH3D, {thnAxisCentrality, {1000, 0.0, 1.0}, axisPtKaonWeight}); + } } // Event selection cut additional - Alex if (additionalEvsel) { @@ -460,10 +504,12 @@ struct phipbpb { ConfigurableAxis axisVertex{"axisVertex", {20, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {20, 0, 100}, "multiplicity percentile for bin"}; ConfigurableAxis axisEPAngle{"axisEPAngle", {6, -TMath::Pi() / 2, TMath::Pi() / 2}, "event plane angle"}; + ConfigurableAxis axisSPAngle{"axisSPAngle", {6, -TMath::Pi(), TMath::Pi()}, "spectator plane angle"}; ConfigurableAxis axisOccup{"axisOccup", {20, -0.5, 40000.0}, "occupancy axis"}; // using BinningTypeVertexContributor = ColumnBinningPolicy; using BinningTypeVertexContributor = ColumnBinningPolicy; + using BinningTypeVertexContributorv1 = ColumnBinningPolicy; ROOT::Math::PxPyPzMVector PhiMesonMother, KaonPlus, KaonMinus, fourVecDauCM; ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY, eventplaneVec, eventplaneVecNorm, beamvector; int currentRunNumber = -999; @@ -557,6 +603,7 @@ struct phipbpb { hweight = ccdb->getForTimeStamp(ConfWeightPath.value, bc.timestamp()); } lastRunNumber = currentRunNumber; + int Npostrack = 0; float weight1 = 1.0; float weight2 = 1.0; @@ -653,6 +700,7 @@ struct phipbpb { if (totalweight <= 0.0000005) { totalweight = 1.0; } + // LOGF(info, Form("weight %f %f",weight1, weight2)); if (TMath::Abs(PhiMesonMother.Rapidity()) < confRapidity) { histos.fill(HIST("ResTrackSPFT0CTPC"), centrality, occupancy, QFT0C * QTPC * TMath::Cos(2.0 * (psiFT0C - psiTPC))); @@ -690,6 +738,7 @@ struct phipbpb { histos.fill(HIST("hSparseV2SameEventSinPsi"), PhiMesonMother.M(), PhiMesonMother.Pt(), TMath::Sin(2.0 * psiFT0C), centrality); } } + if (fillSA) { ROOT::Math::Boost boost{PhiMesonMother.BoostToCM()}; fourVecDauCM = boost(KaonMinus); @@ -714,7 +763,153 @@ struct phipbpb { } PROCESS_SWITCH(phipbpb, processSameEvent, "Process Same event", true); + void processSameEventv1(EventCandidatesv1::iterator const& collision, TrackCandidates const& /*tracks, aod::BCs const&*/, aod::BCsWithTimestamps const&) + { + if (!collision.sel8() || !collision.triggereventsp() || !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return; + } + auto centrality = collision.centFT0C(); + auto posThisColl = posTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + auto negThisColl = negTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); + int occupancy = collision.trackOccupancyInTimeRange(); + o2::aod::ITSResponse itsResponse; + if (occupancy > cfgCutOccupancy) { + return; + } + if (additionalEvsel && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return; + } + if (additionalEvselITS && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + + histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hVtxZ"), collision.posZ()); + + auto qxZDCA = collision.qxZDCA(); + auto qxZDCC = collision.qxZDCC(); + auto qyZDCA = collision.qyZDCA(); + auto qyZDCC = collision.qyZDCC(); + auto psiZDCC = collision.psiZDCC(); + auto psiZDCA = collision.psiZDCA(); + + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + if (cqvas) { + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + } else { + modqxZDCA = qxZDCA; + modqyZDCA = qyZDCA; + modqxZDCC = qxZDCC; + modqyZDCC = qyZDCC; + } + + auto QxtQxp = modqxZDCA * modqxZDCC; + auto QytQyp = modqyZDCA * modqyZDCC; + auto Qxytp = QxtQxp + QytQyp; + auto QxpQyt = modqxZDCA * modqyZDCC; + auto QxtQyp = modqxZDCC * modqyZDCA; + + if (fillv1) { + 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); + histos.fill(HIST("hpQxpvscent"), centrality, modqxZDCA); + histos.fill(HIST("hpQxtvscent"), centrality, modqxZDCC); + histos.fill(HIST("hpQypvscent"), centrality, modqyZDCA); + histos.fill(HIST("hpQytvscent"), centrality, modqyZDCC); + } + + int Npostrack = 0; + for (auto track1 : posThisColl) { + // track selection + if (!selectionTrack(track1)) { + continue; + } + // PID check + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(track1)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(track1)) { + continue; + } + if (isTOFOnly && !selectionPID2(track1)) { + continue; + } + if (useGlobalTrack && track1.p() < 1.0 && !(itsResponse.nSigmaITS(track1) > -2.5 && itsResponse.nSigmaITS(track1) < 2.5)) { + continue; + } + auto track1ID = track1.globalIndex(); + for (auto track2 : negThisColl) { + // track selection + if (!selectionTrack(track2)) { + continue; + } + // PID check + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(track2)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(track2)) { + continue; + } + if (isTOFOnly && !selectionPID2(track2)) { + continue; + } + auto track2ID = track2.globalIndex(); + if (track2ID == track1ID) { + continue; + } + if (!selectionPair(track1, track2)) { + continue; + } + if (removefaketrak && isFakeKaon(track1)) { + continue; + } + if (removefaketrak && isFakeKaon(track2)) { + continue; + } + if (useGlobalTrack && track2.p() < 1.0 && !(itsResponse.nSigmaITS(track2) > -2.5 && itsResponse.nSigmaITS(track2) < 2.5)) { + continue; + } + KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + PhiMesonMother = KaonPlus + KaonMinus; + + if (fillv1) { + auto ux = TMath::Cos(GetPhiInRange(PhiMesonMother.Phi())); + auto uy = TMath::Sin(GetPhiInRange(PhiMesonMother.Phi())); + auto uxQxp = ux * modqxZDCA; + auto uyQyp = uy * modqyZDCA; // correlations of particle and ZDC q vectors + auto uxyQxyp = uxQxp + uyQyp; + auto uxQxt = ux * modqxZDCC; + auto uyQyt = uy * modqyZDCC; + auto uxyQxyt = uxQxt + uyQyt; + auto oddv1 = ux * (modqxZDCA - modqxZDCC) + uy * (modqyZDCA - modqyZDCC); + + histos.fill(HIST("hpoddvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), oddv1); + if (fillLOCC) { + histos.fill(HIST("hpuxyQxypvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyp); + histos.fill(HIST("hpuxyQxytvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyt); + histos.fill(HIST("hpuxvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), ux); + histos.fill(HIST("hpuyvscentpteta"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uy); + } + } + } + Npostrack = Npostrack + 1; + } + } + PROCESS_SWITCH(phipbpb, processSameEventv1, "Process Same event for v1", false); + BinningTypeVertexContributor binningOnEPAngle{{axisVertex, axisMultiplicityClass, axisEPAngle}, true}; + BinningTypeVertexContributorv1 binningOnSPAngle{{axisVertex, axisMultiplicityClass, axisSPAngle}, true}; Preslice tracksPerCollision = aod::track::collisionId; void processMEAcc(EventCandidates const& collisions, TrackCandidates const& tracks) { @@ -749,6 +944,7 @@ struct phipbpb { auto centrality = collision1.centFT0C(); auto psiFT0C = collision1.psiFT0C(); auto QFT0C = collision1.qFT0C(); + o2::aod::ITSResponse itsResponse; auto grouptrack1 = tracks.sliceBy(tracksPerCollision, collision2.globalIndex()); auto grouptrack2 = tracks.sliceBy(tracksPerCollision, collision2.globalIndex()); @@ -809,6 +1005,7 @@ struct phipbpb { if (TMath::Abs(PhiMesonMother.Rapidity()) > confRapidity) { continue; } + if (useSP) { histos.fill(HIST("hSparseV2MixEPAngleCosDeltaPhi"), PhiMesonMother.M(), PhiMesonMother.Pt(), v2 * QFT0C, centrality); } else { @@ -818,6 +1015,143 @@ struct phipbpb { } } PROCESS_SWITCH(phipbpb, processMEAcc, "Process ME Acceptance", true); + + void processMEAccv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) + { + for (auto& [collision1, collision2] : selfCombinations(binningOnSPAngle, cfgNoMixedEvents, -1, collisions, collisions)) { + + if (!collision1.sel8() || !collision1.triggereventsp() || !collision1.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + if (!collision2.sel8() || !collision2.triggereventsp() || !collision2.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); + if (occupancy1 > cfgCutOccupancy) { + continue; + } + if (occupancy2 > cfgCutOccupancy) { + continue; + } + if (additionalEvsel && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvsel && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvselITS && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + if (additionalEvselITS && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + auto centrality = collision1.centFT0C(); + + auto qxZDCA = collision1.qxZDCA(); + auto qxZDCC = collision1.qxZDCC(); + auto qyZDCA = collision1.qyZDCA(); + auto qyZDCC = collision1.qyZDCC(); + auto psiZDCC = collision1.psiZDCC(); + auto psiZDCA = collision1.psiZDCA(); + + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + if (cqvas) { + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + } else { + modqxZDCA = qxZDCA; + modqyZDCA = qyZDCA; + modqxZDCC = qxZDCC; + modqyZDCC = qyZDCC; + } + + o2::aod::ITSResponse itsResponse; + auto grouptrack1 = tracks.sliceBy(tracksPerCollision, collision1.globalIndex()); + auto grouptrack2 = tracks.sliceBy(tracksPerCollision, collision2.globalIndex()); + for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(grouptrack1, grouptrack2))) { + if (t2.index() <= t1.index()) { + continue; + } + if (t1.sign() * t2.sign() > 0) { + continue; + } + if (!selectionTrack(t1)) { + continue; + } + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(t1)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(t1)) { + continue; + } + if (isTOFOnly && !selectionPID2(t1)) { + continue; + } + if (useGlobalTrack && t1.p() < 1.0 && !(itsResponse.nSigmaITS(t1) > -2.5 && itsResponse.nSigmaITS(t1) < 2.5)) { + continue; + } + + if (!selectionTrack(t2)) { + continue; + } + if (ispTdepPID && !isTOFOnly && !selectionPIDpTdependent(t2)) { + continue; + } + if (!ispTdepPID && !isTOFOnly && !selectionPID(t2)) { + continue; + } + if (isTOFOnly && !selectionPID2(t2)) { + continue; + } + if (useGlobalTrack && t2.p() < 1.0 && !(itsResponse.nSigmaITS(t2) > -2.5 && itsResponse.nSigmaITS(t2) < 2.5)) { + continue; + } + + if (!selectionPair(t1, t2)) { + continue; + } + if (removefaketrak && isFakeKaon(t1)) { + continue; + } + if (removefaketrak && isFakeKaon(t2)) { + continue; + } + + KaonPlus = ROOT::Math::PxPyPzMVector(t1.px(), t1.py(), t1.pz(), massKa); + KaonMinus = ROOT::Math::PxPyPzMVector(t2.px(), t2.py(), t2.pz(), massKa); + PhiMesonMother = KaonPlus + KaonMinus; + + if (fillv1) { + auto ux = TMath::Cos(GetPhiInRange(PhiMesonMother.Phi())); + auto uy = TMath::Sin(GetPhiInRange(PhiMesonMother.Phi())); + auto uxQxp = ux * modqxZDCA; + auto uyQyp = uy * modqyZDCA; // correlations of particle and ZDC q vectors + auto uxyQxyp = uxQxp + uyQyp; + auto uxQxt = ux * modqxZDCC; + auto uyQyt = uy * modqyZDCC; + auto uxyQxyt = uxQxt + uyQyt; + auto oddv1 = ux * (modqxZDCA - modqxZDCC) + uy * (modqyZDCA - modqyZDCC); + + histos.fill(HIST("hpoddvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), oddv1); + if (fillLOCC) { + histos.fill(HIST("hpuxyQxypvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyp); + histos.fill(HIST("hpuxyQxytvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyt); + histos.fill(HIST("hpuxvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), ux); + histos.fill(HIST("hpuyvscentptetamixacc"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uy); + } + } + } + } + } + PROCESS_SWITCH(phipbpb, processMEAccv1, "Process ME Acceptance v1", false); + void processMixedEventOpti(EventCandidates const& collisions, TrackCandidates const& tracks) { auto tracksTuple = std::make_tuple(tracks); @@ -864,6 +1198,7 @@ struct phipbpb { if (additionalEvselITS && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } + for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { if (track1.sign() * track2.sign() > 0) { continue; @@ -909,6 +1244,7 @@ struct phipbpb { auto v2acc = TMath::Cos(4.0 * phiminuspsi); auto v2sin = TMath::Sin(2.0 * phiminuspsi); histos.fill(HIST("hpTvsRapidity"), PhiMesonMother.Pt(), PhiMesonMother.Rapidity()); + if (TMath::Abs(PhiMesonMother.Rapidity()) < confRapidity) { if (useSP) { histos.fill(HIST("hSparseV2MixedEventCosDeltaPhi"), PhiMesonMother.M(), PhiMesonMother.Pt(), v2 * QFT0C, centrality); @@ -937,6 +1273,132 @@ struct phipbpb { } } PROCESS_SWITCH(phipbpb, processMixedEventOpti, "Process Mixed event new", true); + + void processMixedEventOptiv1(EventCandidatesv1 const& collisions, TrackCandidates const& tracks) + { + auto tracksTuple = std::make_tuple(tracks); + BinningTypeVertexContributorv1 binningOnPositions{{axisVertex, axisMultiplicityClass, axisSPAngle}, true}; + SameKindPair pair{binningOnPositions, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + for (auto& [collision1, tracks1, collision2, tracks2] : pair) { + if (!collision1.sel8() || !collision1.triggereventsp() || !collision1.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + if (!collision2.sel8() || !collision2.triggereventsp() || !collision2.selection_bit(aod::evsel::kNoSameBunchPileup)) { + continue; + } + o2::aod::ITSResponse itsResponse; + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); + if (occupancy1 > cfgCutOccupancy) { + continue; + } + if (occupancy2 > cfgCutOccupancy) { + continue; + } + auto centrality = collision1.centFT0C(); + + if (additionalEvsel && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvsel && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvselITS && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + if (additionalEvselITS && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + + auto qxZDCA = collision1.qxZDCA(); + auto qxZDCC = collision1.qxZDCC(); + auto qyZDCA = collision1.qyZDCA(); + auto qyZDCC = collision1.qyZDCC(); + auto psiZDCC = collision1.psiZDCC(); + auto psiZDCA = collision1.psiZDCA(); + + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + if (cqvas) { + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + } else { + modqxZDCA = qxZDCA; + modqyZDCA = qyZDCA; + modqxZDCC = qxZDCC; + modqyZDCC = qyZDCC; + } + + for (auto& [track1, track2] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(tracks1, tracks2))) { + if (track1.sign() * track2.sign() > 0) { + continue; + } + if (useGlobalTrack && track1.p() < 1.0 && !(itsResponse.nSigmaITS(track1) > -2.5 && itsResponse.nSigmaITS(track1) < 2.5)) { + continue; + } + if (useGlobalTrack && track2.p() < 1.0 && !(itsResponse.nSigmaITS(track2) > -2.5 && itsResponse.nSigmaITS(track2) < 2.5)) { + continue; + } + if (!selectionTrack(track1) || !selectionTrack(track2)) { + continue; + } + // PID check + if (ispTdepPID && !isTOFOnly && (!selectionPIDpTdependent(track1) || !selectionPIDpTdependent(track2))) { + continue; + } + if (!ispTdepPID && !isTOFOnly && (!selectionPID(track1) || !selectionPID(track2))) { + continue; + } + if (isTOFOnly && (!selectionPID2(track1) || !selectionPID2(track2))) { + continue; + } + if (!selectionPair(track1, track2)) { + continue; + } + if (removefaketrak && isFakeKaon(track1)) { + continue; + } + if (removefaketrak && isFakeKaon(track2)) { + continue; + } + if (track1.sign() > 0 && track2.sign() < 0) { + KaonPlus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonMinus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } else if (track1.sign() < 0 && track2.sign() > 0) { + KaonMinus = ROOT::Math::PxPyPzMVector(track1.px(), track1.py(), track1.pz(), massKa); + KaonPlus = ROOT::Math::PxPyPzMVector(track2.px(), track2.py(), track2.pz(), massKa); + } + PhiMesonMother = KaonPlus + KaonMinus; + + if (fillv1) { + auto ux = TMath::Cos(GetPhiInRange(PhiMesonMother.Phi())); + auto uy = TMath::Sin(GetPhiInRange(PhiMesonMother.Phi())); + auto uxQxp = ux * modqxZDCA; + auto uyQyp = uy * modqyZDCA; // correlations of particle and ZDC q vectors + auto uxyQxyp = uxQxp + uyQyp; + auto uxQxt = ux * modqxZDCC; + auto uyQyt = uy * modqyZDCC; + auto uxyQxyt = uxQxt + uyQyt; + auto oddv1 = ux * (modqxZDCA - modqxZDCC) + uy * (modqyZDCA - modqyZDCC); + + histos.fill(HIST("hpoddvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), oddv1); + if (fillLOCC) { + histos.fill(HIST("hpuxyQxypvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyp); + histos.fill(HIST("hpuxyQxytvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uxyQxyt); + histos.fill(HIST("hpuxvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), ux); + histos.fill(HIST("hpuyvscentptetamixopti"), PhiMesonMother.M(), centrality, PhiMesonMother.Pt(), PhiMesonMother.Rapidity(), uy); + } + } + } + } + } + PROCESS_SWITCH(phipbpb, processMixedEventOptiv1, "Process Mixed event new v1", false); + void processMC(CollisionMCTrueTable::iterator const& /*TrueCollision*/, CollisionMCRecTableCentFT0C const& RecCollisions, TrackMCTrueTable const& GenParticles, FilTrackMCRecTable const& RecTracks) { histos.fill(HIST("hMC"), 0); diff --git a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx index 53e7f283150..42773fa2947 100644 --- a/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx +++ b/PWGLF/Tasks/Resonances/xi1530Analysisqa.cxx @@ -430,13 +430,13 @@ struct Xi1530Analysisqa { if (std::abs(track.pt()) < cMinPtcut) return false; if constexpr (IsResoMicrotrack) { - if (std::abs(o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) return false; if (cDCAzToPVAsPt) { - if (std::abs(o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > (cDCAxytoPVByPtPiFirstP0 + cDCAxyToPVByPtPiFirstExp * std::pow(track.pt(), -1.1))) return false; } else { - if (std::abs(o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > cMaxDCAzToPVCut) + if (std::abs(o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())) > cMaxDCAzToPVCut) return false; } } else { @@ -607,8 +607,8 @@ struct Xi1530Analysisqa { float trackPt = candidate.pt(); if constexpr (IsResoMicrotrack) { - tpcNsigmaPionFirst = o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); - tofNsigmaPionFirst = o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()); + tpcNsigmaPionFirst = o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPiFlag()); + tofNsigmaPionFirst = o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPiFlag()); } else { tpcNsigmaPionFirst = candidate.tpcNSigmaPi(); tofNsigmaPionFirst = candidate.tofNSigmaPi(); @@ -700,10 +700,10 @@ struct Xi1530Analysisqa { static float trk1NSigmaPiTPC; static float trk1NSigmaPiTOF; if constexpr (IsResoMicrotrack) { - trk1DCAXY = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags()); - trk1DCAZ = o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags()); - trk1NSigmaPiTPC = o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag()); - trk1NSigmaPiTOF = o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag()); + trk1DCAXY = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(trk1.trackSelectionFlags()); + trk1DCAZ = o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(trk1.trackSelectionFlags()); + trk1NSigmaPiTPC = o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(trk1.pidNSigmaPiFlag()); + trk1NSigmaPiTOF = o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(trk1.pidNSigmaPiFlag()); } else { trk1DCAXY = trk1.dcaXY(); trk1DCAZ = trk1.dcaZ(); diff --git a/PWGLF/Tasks/Strangeness/CMakeLists.txt b/PWGLF/Tasks/Strangeness/CMakeLists.txt index 569768bd273..100b8667aab 100644 --- a/PWGLF/Tasks/Strangeness/CMakeLists.txt +++ b/PWGLF/Tasks/Strangeness/CMakeLists.txt @@ -29,11 +29,6 @@ o2physics_add_dpl_workflow(cascadeanalysis PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore COMPONENT_NAME Analysis) -o2physics_add_dpl_workflow(sigmaminus-task - SOURCES sigmaminustask.cxx - PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore - COMPONENT_NAME Analysis) - o2physics_add_dpl_workflow(cascadeanalysismc SOURCES cascadeanalysisMC.cxx PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore @@ -145,3 +140,23 @@ o2physics_add_dpl_workflow(lambdajetpolarization SOURCES lambdaJetpolarization.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::PWGJECore FastJet::FastJet FastJet::Contrib O2Physics::EventFilteringUtils COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambdaspincorrderived + SOURCES lambdaspincorrderived.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(strangenessderivedbinnedinfo + SOURCES strangenessderivedbinnedinfo.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::EventFilteringUtils + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(lambdatwopartpolarization + SOURCES lambdaTwoPartPolarization.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(cascadeanalysislightions + SOURCES cascadeAnalysisLightIonsDerivedData.cxx + PUBLIC_LINK_LIBRARIES O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGLF/Tasks/Strangeness/cascadeAnalysisLightIonsDerivedData.cxx b/PWGLF/Tasks/Strangeness/cascadeAnalysisLightIonsDerivedData.cxx new file mode 100644 index 00000000000..5d7178c60e5 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/cascadeAnalysisLightIonsDerivedData.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. +// +/// \file cascadeAnalysisLightIonsDerivedData.cxx +/// \brief analysis of cascades (Xi, antiXi, Omega, antiOmega) in light-ion collisions using derived data +/// +/// \author Sara Pucillo (sara.pucillo@cern.ch), Alberto Caliva (alberto.caliva@cern.ch) +// + +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + +#include "Common/CCDB/ctpRateFetcher.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/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CommonConstants/MathConstants.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 + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::math; +using namespace o2::constants::physics; +using std::array; + +using SelCollisions = soa::Join; +using SimCollisions = soa::Join; +using CascadeCandidates = soa::Join; +using CascadeMCCandidates = soa::Join; +using DaughterTracks = soa::Join; +using CollisionMCTrueTable = soa::Join; +using CascadeMCCores = soa::Join; + +struct CascadeAnalysisLightIonsDerivedData { + + // Instantiate the CCDB service and API interface + // 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"}; + } ccdbConfigurations; + + o2::ccdb::CcdbApi ccdbApi; + Service ccdb; + int mRunNumber; + + // Define histogram registries + HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + // Global analysis parameters + Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; + Configurable deltaEtaEdge{"deltaEtaEdge", 0.05, "eta gap from the edge"}; + Configurable nBins{"nBins", 100, "N bins in all QC histos"}; + + // Event selections parameters + Configurable applySel8{"applySel8", true, "0 - no, 1 - yes"}; + Configurable applyVtxZ{"applyVtxZ", true, "0 - no, 1 - yes"}; + Configurable rejectITSROFBorder{"rejectITSROFBorder", true, "reject events at ITS ROF border"}; + Configurable rejectTFBorder{"rejectTFBorder", true, "reject events at TF border"}; + Configurable requireVertexITSTPC{"requireVertexITSTPC", false, "require events with at least one ITS-TPC track"}; + Configurable requireIsGoodZvtxFT0VsPV{"requireIsGoodZvtxFT0VsPV", false, "require is good Zvtx FT0 vs PV"}; + 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"}; + + // Track analysis Parameters + Configurable minITSnCls{"minITSnCls", 4.0f, "min number of ITS clusters"}; + Configurable minTPCnClsFound{"minTPCnClsFound", 80.0f, "min number of found TPC clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 80.0f, "min number of TPC crossed rows"}; + Configurable etaMin{"etaMin", -0.8f, "eta min"}; + Configurable etaMax{"etaMax", +0.8f, "eta max"}; + Configurable rapcut{"rapcut", +0.5f, "rapidity cut"}; + Configurable maxChi2TPC{"maxChi2TPC", 4.0f, "max chi2 per cluster TPC"}; + Configurable requireITS{"requireITS", false, "require ITS hit"}; + Configurable requireTOF{"requireTOF", false, "require TOF hit"}; + + // Configurable parameters for PID selection + Configurable nsigmaTPCmin{"nsigmaTPCmin", -5.0f, "Minimum nsigma TPC"}; + Configurable nsigmaTPCmax{"nsigmaTPCmax", +5.0f, "Maximum nsigma TPC"}; + + // Configurable parameters for TOF PID selection + Configurable nsigmaTOFmin{"nsigmaTOFmin", -3.0f, "Minimum nsigma TOF"}; + Configurable nsigmaTOFmax{"nsigmaTOFmax", +3.0f, "Maximum nsigma TOF"}; + + // Topological Parameters + Configurable dcanegtoPVmin{"dcanegtoPVmin", 0.1f, "Minimum DCA Neg To PV"}; + Configurable dcapostoPVmin{"dcapostoPVmin", 0.1f, "Minimum DCA Pos To PV"}; + Configurable dcabachtopvMin{"dcabachtopvMin", 0.1f, "Minimum DCA bachelor to PV"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.7f, "Maximum DCA Daughters"}; + Configurable dcaV0topvMin{"dcaV0topvMin", 0.02f, "Minimum DCA V0 to PV"}; + Configurable dcaCascDaughtersMax{"dcaCascDaughtersMax", 0.8f, "Maximum DCA Daughters"}; + Configurable v0cospaMin{"v0cospaMin", 0.99f, "Minimum V0 CosPA"}; + Configurable casccospaMin{"casccospaMin", 0.99f, "Minimum Cascade CosPA"}; + Configurable minimumV0Radius{"minimumV0Radius", 2.5f, "Minimum V0 Radius"}; + 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", {501, -0.5, 500.5}, ""}; + ConfigurableAxis centralityBinning{"centralityBinning", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, ""}; + ConfigurableAxis axisNch{"axisNch", {500, 0.0f, +1000.0f}, "Number of charged particles"}; + + // Centrality estimator + Configurable centralityEstimator{"centralityEstimator", 0, "0 = FT0C, 1 = FTOM, 2 = FV0A, 3 = NGlobal"}; + + // List of estimators + enum Option { kFT0C, + kFT0M, + kFV0A, + kNGlobal }; + + // For manual sliceBy + PresliceUnsorted> perMcCollision = aod::v0data::straMCCollisionId; + + void init(InitContext const&) + { + // setting CCDB service + ccdb->setURL(ccdbConfigurations.ccdbUrl); + ccdb->setCaching(true); + ccdb->setFatalWhenNull(false); + ccdb->setLocalObjectValidityChecking(); + ccdb->setCreatedNotAfter( + std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()) + .count()); + + // Axes and Binning + AxisSpec axisCentEstimator = {centEstimatorHistBin, "CentEstimator", "CentEstimatorAxis"}; + AxisSpec centAxis = {centralityBinning, "Centrality", "CentralityAxis"}; + const AxisSpec vertexZAxis = {nBins, -15., 15., "vrtx_{Z} [cm]"}; + const AxisSpec etaAxis{18, -0.9, 0.9, "#eta"}; + const AxisSpec ptAxis{100, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}; + const AxisSpec invMassXiAxis{200, 1.28, 1.36, "m_{p#pi#pi} (GeV/#it{c}^{2})"}; + const AxisSpec invMassOmegaAxis{200, 1.63, 1.71, "m_{p#piK} (GeV/#it{c}^{2})"}; + const AxisSpec nsigmaTOFAxis{200, -10, 10, "n#sigma_{TOF}"}; + const AxisSpec nsigmaTPCAxis{200, -10, 10, "n#sigma_{TPC}"}; + + // Histograms for data + if (doprocessData) { + registryData.add("number_of_events_data", "number of events in data", HistType::kTH1D, {{20, -0.5f, +19.5f}}); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(1, "All collisions"); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(3, "posZ cut"); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(6, "kIsVertexITSTPC"); + registryData.get(HIST("number_of_events_data"))->GetXaxis()->SetBinLabel(7, "kIsGoodZvtxFT0vsPV"); + 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"); + + // QC Histograms + registryQC.add("hVertexZdata", "hVertexZdata", HistType::kTH1F, {vertexZAxis}); + registryQC.add("hv0cosPAdata", "hv0cosPAdata", HistType::kTH1F, {{nBins, 0.95f, 1.f}}); + registryQC.add("hcasccosPAdata", "hcasccosPAdata", HistType::kTH1F, {{nBins, 0.95f, 1.f}}); + registryQC.add("hv0radiusdata", "hv0radiusdata", HistType::kTH1F, {{nBins, 0.0f, 5.0f}}); + registryQC.add("hcascradiusdata", "hcascradiusdata", HistType::kTH1F, {{nBins, 0.0f, 5.0f}}); + registryQC.add("hdcaV0daughtersdata", "hdcaV0daughtersdata", HistType::kTH1F, {{nBins, 0.0f, 1.5f}}); + registryQC.add("hdcacascdaughtersdata", "hdcacascdaughtersdata", HistType::kTH1F, {{nBins, 0.0f, 1.5f}}); + registryQC.add("hdcapostopvdata", "hdcapostopvdata", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + registryQC.add("hdcanegtopvdata", "hdcanegtopvdata", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + registryQC.add("hdcabachtopvdata", "hdcabachtopvdata", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + registryQC.add("hdcav0topvdata", "hdcav0topvdata", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + + // Multiplicity Histograms + registryData.add("hCentEstimator", "hCentEstimator", HistType::kTH1D, {axisCentEstimator}); + registryData.add("hCentralityVsNch", "hCentralityVsNch", HistType::kTH2D, {axisCentEstimator, axisNch}); + + // Histograms for xi (data) + registryData.add("hMassXipos", "hMassXipos", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + registryData.add("hMassXineg", "hMassXineg", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + registryData.add("hMassXiposSelected", "hMassXiposSelected", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + registryData.add("hMassXinegSelected", "hMassXinegSelected", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + + // Histograms for omega (data) + registryData.add("hMassOmegapos", "hMassOmegapos", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + registryData.add("hMassOmeganeg", "hMassOmeganeg", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + registryData.add("hMassOmegaposSelected", "hMassOmegaposSelected", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + registryData.add("hMassOmeganegSelected", "hMassOmeganegSelected", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + } + + if (doprocessMonteCarloRec) { + // Histograms for mc reconstructed + registryMC.add("number_of_events_mc_rec", "number of events in mc_rec", HistType::kTH1D, {{20, -0.5f, +19.5f}}); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(1, "All collisions"); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(2, "sel8 cut"); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(3, "posZ cut"); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(4, "kNoITSROFrameBorder"); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(5, "kNoTimeFrameBorder"); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(6, "kIsVertexITSTPC"); + registryMC.get(HIST("number_of_events_mc_rec"))->GetXaxis()->SetBinLabel(7, "kIsGoodZvtxFT0vsPV"); + 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"); + + // QC Histograms + registryQC.add("hVertexZRec", "hVertexZRec", HistType::kTH1F, {{vertexZAxis}}); + registryQC.add("hv0cosPARec", "hv0cosPARec", HistType::kTH1F, {{nBins, 0.95f, 1.f}}); + registryQC.add("hcasccosPARec", "hcasccosPARec", HistType::kTH1F, {{nBins, 0.95f, 1.f}}); + registryQC.add("hv0radiusRec", "hv0radiusRec", HistType::kTH1F, {{nBins, 0.0f, 5.0f}}); + registryQC.add("hcascradiusRec", "hcascradiusRec", HistType::kTH1F, {{nBins, 0.0f, 5.0f}}); + registryQC.add("hdcaV0daughtersRec", "hdcaV0daughtersRec", HistType::kTH1F, {{nBins, 0.0f, 1.5f}}); + registryQC.add("hdcacascdaughtersRec", "hdcacascdaughtersRec", HistType::kTH1F, {{nBins, 0.0f, 1.5f}}); + registryQC.add("hdcapostopvRec", "hdcapostopvRec", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + registryQC.add("hdcanegtopvRec", "hdcanegtopvRec", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + registryQC.add("hdcabachtopvRec", "hdcabachtopvRec", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + registryQC.add("hdcav0topvRec", "hdcav0topvRec", HistType::kTH1F, {{nBins, 0.0f, 2.0f}}); + + // Multiplicity Histograms + registryMC.add("hCentEstimator_truerec", "hCentEstimator_truerec", HistType::kTH1D, {axisCentEstimator}); + registryMC.add("hCentralityVsNch_truerec", "hCentralityVsNch_truerec", HistType::kTH2D, {axisCentEstimator, axisNch}); + + // Histograms for xi (mc) + registryMC.add("hMassXipos_truerec", "hMassXipos_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + registryMC.add("hMassXineg_truerec", "hMassXineg_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + registryMC.add("hMassXiposSelected_truerec", "hMassXiposSelected_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + registryMC.add("hMassXinegSelected_truerec", "hMassXinegSelected_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassXiAxis}); + + // Histograms for omega (mc) + registryMC.add("hMassOmegapos_truerec", "hMassOmegapos_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + registryMC.add("hMassOmeganeg_truerec", "hMassOmeganeg_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + registryMC.add("hMassOmegaposSelected_truerec", "hMassOmegaposSelected_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + registryMC.add("hMassOmeganegSelected_truerec", "hMassOmeganegSelected_truerec", HistType::kTH3F, {centAxis, ptAxis, invMassOmegaAxis}); + } + + if (doprocessMonteCarloGen) { + // Histograms for mc generated + // QC Histograms + registryQC.add("hVertexZGen", "hVertexZGen", HistType::kTH1F, {{vertexZAxis}}); + // Histograms for xi (mc) + registryMC.add("h2dGenXiMinusVsMultMC_RecoedEvt", "h2dGenXiMinusVsMultMC_RecoedEvt", HistType::kTH2F, {axisNch, ptAxis}); + registryMC.add("h2dGenXiPlusVsMultMC_RecoedEvt", "h2dGenXiPlusVsMultMC_RecoedEvt", HistType::kTH2F, {axisNch, ptAxis}); + registryMC.add("h2dGenXiMinusVsMultMC", "h2dGenXiMinusVsMultMC", HistType::kTH2F, {axisNch, ptAxis}); + registryMC.add("h2dGenXiPlusVsMultMC", "h2dGenXiPlusVsMultMC", HistType::kTH2F, {axisNch, ptAxis}); + + // Histograms for omega (mc) + registryMC.add("h2dGenOmegaMinusVsMultMC_RecoedEvt", "h2dGenOmegaMinusVsMultMC_RecoedEvt", HistType::kTH2F, {axisNch, ptAxis}); + registryMC.add("h2dGenOmegaPlusVsMultMC_RecoedEvt", "h2dGenOmegaPlusVsMultMC_RecoedEvt", HistType::kTH2F, {axisNch, ptAxis}); + registryMC.add("h2dGenOmegaMinusVsMultMC", "h2dGenOmegaMinusVsMultMC", HistType::kTH2F, {axisNch, ptAxis}); + registryMC.add("h2dGenOmegaPlusVsMultMC", "h2dGenOmegaPlusVsMultMC", HistType::kTH2F, {axisNch, ptAxis}); + + // Histograms for event loss/splitting + registryMC.add("hGenEvents", "hGenEvents", HistType::kTH2F, {{axisNch}, {2, -0.5f, +1.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.add("hGenEventCentrality", "hGenEventCentrality", kTH1D, {{101, 0.0f, 101.0f}}); + + registryMC.add("hCentralityVsNcoll_beforeEvSel", "hCentralityVsNcoll_beforeEvSel", HistType::kTH2F, {centAxis, {50, -0.5f, 49.5f}}); + registryMC.add("hCentralityVsNcoll_afterEvSel", "hCentralityVsNcoll_afterEvSel", HistType::kTH2F, {centAxis, {50, -0.5f, 49.5f}}); + + registryMC.add("hCentralityVsMultMC", "hCentralityVsMultMC", HistType::kTH2F, {{101, 0.0f, 101.0f}, axisNch}); + } + } + + // ______________________________________________________ + // Return slicing output + template + auto getGroupedCollisions(TCollisions const& collisions, int globalIndex) + { + return collisions.sliceBy(perMcCollision, globalIndex); + } + + template + void initCCDB(TCollision collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + mRunNumber = collision.runNumber(); + } + + // Find ITS hit + // template + // bool hasITSHitOnLayer(const TrackIts& track, int layer) + // { + // int ibit = layer - 1; + // return (track.itsClusterMap() & (1 << ibit)); + // } + + // Single-Track Selection + template + bool passedSingleTrackSelection(const Track& track) + { + if (requireITS && (!track.hasITS())) + return false; + if (requireITS && track.itsNCls() < minITSnCls) + return false; + if (!track.hasTPC()) + return false; + if (track.tpcNClsFound() < minTPCnClsFound) + return false; + if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) + return false; + if (track.tpcChi2NCl() > maxChi2TPC) + return false; + if (requireTOF && (!track.hasTOF())) + return false; + return true; + } + + // Xi Selection + template + bool passedXiSelection(const Xi& casc, const TrackPos& ptrack, + const TrackNeg& ntrack, const TrackBac& btrack, + const Coll& coll) + { + if (!passedSingleTrackSelection(ptrack)) + return false; + if (!passedSingleTrackSelection(ntrack)) + return false; + if (!passedSingleTrackSelection(btrack)) + return false; + + if (std::abs(casc.yXi()) > rapcut) + return false; + + // Xi+ Selection (Xi+ -> antiL + pi+) + if (casc.sign() > 0) { + + // PID Selections (TPC) + if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || + ntrack.tpcNSigmaPr() > nsigmaTPCmax) + return false; + if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || + ptrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (requireTOF) { + if (casc.tofNSigmaXiLaPr() < nsigmaTOFmin || + casc.tofNSigmaXiLaPr() > nsigmaTOFmax) + return false; + if (casc.tofNSigmaXiLaPi() < nsigmaTOFmin || + casc.tofNSigmaXiLaPi() > nsigmaTOFmax) + return false; + } + } + + // Xi- Selection (Xi- -> L + pi-) + if (casc.sign() < 0) { + + // PID Selections (TPC) + if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || + ptrack.tpcNSigmaPr() > nsigmaTPCmax) + return false; + if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || + ntrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (requireTOF) { + if (casc.tofNSigmaXiLaPr() < nsigmaTOFmin || + casc.tofNSigmaXiLaPr() > nsigmaTOFmax) + return false; + if (casc.tofNSigmaXiLaPi() < nsigmaTOFmin || + casc.tofNSigmaXiLaPi() > nsigmaTOFmax) + return false; + } + } + + if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < v0cospaMin) + return false; + if (casc.v0radius() < minimumV0Radius) + return false; + if (std::fabs(casc.dcaV0daughters()) > dcaV0DaughtersMax) + return false; + if (std::fabs(casc.dcapostopv()) < dcapostoPVmin) + return false; + if (std::fabs(casc.dcanegtopv()) < dcanegtoPVmin) + return false; + + if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < casccospaMin) + return false; + if (casc.cascradius() < minimumCascRadius) + return false; + if (std::fabs(casc.dcabachtopv()) < dcabachtopvMin) + return false; + if (std::fabs(casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ())) < + dcaV0topvMin) + return false; + if (std::fabs(casc.dcacascdaughters()) > dcaCascDaughtersMax) + return false; + + // V0 mass window + if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > + v0masswindow) + return false; + + // reject candidates compatible with omega + if (std::abs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < + competingmassrej) + return false; + + // PID Selection on bachelor + if (btrack.tpcNSigmaPi() < nsigmaTPCmin || + btrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (requireTOF) { + if (casc.tofNSigmaXiPi() < nsigmaTOFmin || + casc.tofNSigmaXiPi() > nsigmaTOFmax) + return false; + } + return true; + } + + // Omega Selection + template + bool passedOmegaSelection(const Omega& casc, const TrackPos& ptrack, + const TrackNeg& ntrack, const TrackBac& btrack, + const Coll& coll) + { + if (!passedSingleTrackSelection(ptrack)) + return false; + if (!passedSingleTrackSelection(ntrack)) + return false; + if (!passedSingleTrackSelection(btrack)) + return false; + + if (std::abs(casc.yOmega()) > rapcut) + return false; + + // Omega+ Selection (Omega+ -> antiL + K+) + if (casc.sign() > 0) { + // PID Selections (TPC) + if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || + ntrack.tpcNSigmaPr() > nsigmaTPCmax) + return false; + if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || + ptrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (requireTOF) { + if (casc.tofNSigmaOmLaPr() < nsigmaTOFmin || + casc.tofNSigmaOmLaPr() > nsigmaTOFmax) + return false; + if (casc.tofNSigmaOmLaPi() < nsigmaTOFmin || + casc.tofNSigmaOmLaPi() > nsigmaTOFmax) + return false; + } + } + + // Omega- Selection (Omega- -> L + K-) + if (casc.sign() < 0) { + // PID Selections (TPC) + if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || + ptrack.tpcNSigmaPr() > nsigmaTPCmax) + return false; + if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || + ntrack.tpcNSigmaPi() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (requireTOF) { + if (casc.tofNSigmaOmLaPr() < nsigmaTOFmin || + casc.tofNSigmaOmLaPr() > nsigmaTOFmax) + return false; + if (casc.tofNSigmaOmLaPi() < nsigmaTOFmin || + casc.tofNSigmaOmLaPi() > nsigmaTOFmax) + return false; + } + } + + if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < v0cospaMin) + return false; + if (casc.v0radius() < minimumV0Radius) + return false; + if (std::fabs(casc.dcaV0daughters()) > dcaV0DaughtersMax) + return false; + if (std::fabs(casc.dcapostopv()) < dcapostoPVmin) + return false; + if (std::fabs(casc.dcanegtopv()) < dcanegtoPVmin) + return false; + + if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < casccospaMin) + return false; + if (casc.cascradius() < minimumCascRadius) + return false; + if (std::fabs(casc.dcabachtopv()) < dcabachtopvMin) + return false; + if (std::fabs(casc.dcav0topv(coll.posX(), coll.posY(), coll.posZ())) < + dcaV0topvMin) + return false; + if (std::fabs(casc.dcacascdaughters()) > dcaCascDaughtersMax) + return false; + + // V0 mass window + if (std::abs(casc.mLambda() - o2::constants::physics::MassLambda0) > + v0masswindow) + return false; + + // Reject candidates compatible with Xi + if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) < + competingmassrej) + return false; + + // PID Selection on bachelor + if (btrack.tpcNSigmaKa() < nsigmaTPCmin || + btrack.tpcNSigmaKa() > nsigmaTPCmax) + return false; + + // PID Selections (TOF) + if (requireTOF) { + if (casc.tofNSigmaOmKa() < nsigmaTOFmin || + casc.tofNSigmaOmKa() > nsigmaTOFmax) + return false; + } + return true; + } + + // Return the list of indices to the recoed collision associated to a given MC collision. + template + std::vector getListOfRecoCollIndices(TMCollisions const& mcCollisions, TCollisions const& collisions) + { + std::vector listBestCollisionIdx(mcCollisions.size()); + for (auto const& mcCollision : mcCollisions) { + auto groupedCollisions = getGroupedCollisions(collisions, mcCollision.globalIndex()); + int biggestNContribs = -1; + int bestCollisionIndex = -1; + for (auto const& collision : groupedCollisions) { + // event selections + if (applySel8 && !collision.sel8()) + continue; + + if (applyVtxZ && std::fabs(collision.posZ()) > zVtx) + continue; + + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + continue; + } + + if (requireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + continue; + } + + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + continue; + } + + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + continue; + } + + if (requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + continue; + } + + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + continue; + } + + // 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()) { + biggestNContribs = collision.multPVTotalContributors(); + bestCollisionIndex = collision.globalIndex(); + } + } + listBestCollisionIdx[mcCollision.globalIndex()] = bestCollisionIndex; + } + return listBestCollisionIdx; + } + + // Fill generated event information (for event loss/splitting estimation) + template + void fillGeneratedEventProperties(TMCCollisions const& mcCollisions, TCollisions const& collisions) + { + std::vector listBestCollisionIdx(mcCollisions.size()); + for (auto const& mcCollisions : mcCollisions) { + // event selections + if (applyVtxZ && std::fabs(mcCollisions.posZ()) > zVtx) + return; + + registryMC.fill(HIST("hGenEvents"), mcCollisions.multMCNParticlesEta05(), 0 /* all gen. events*/); + + auto groupedCollisions = getGroupedCollisions(collisions, mcCollisions.globalIndex()); + // Check if there is at least one of the reconstructed collisions associated to this MC collision + // If so, we consider it + bool atLeastOne = false; + int biggestNContribs = -1; + int nCollisions = 0; + float multiplicitydata = -1.0f; + for (auto const& collision : groupedCollisions) { + // event selections + if (applySel8 && !collision.sel8()) + continue; + + if (applyVtxZ && std::fabs(collision.posZ()) > zVtx) + continue; + + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + continue; + } + + if (requireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + continue; + } + + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + continue; + } + + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + continue; + } + + if (requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + continue; + } + + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + continue; + } + + if (biggestNContribs < collision.multPVTotalContributors()) { + biggestNContribs = collision.multPVTotalContributors(); + if (centralityEstimator == Option::kFT0C) + multiplicitydata = collision.centFT0C(); + if (centralityEstimator == Option::kFT0M) + multiplicitydata = collision.centFT0M(); + if (centralityEstimator == Option::kFV0A) + multiplicitydata = collision.centFV0A(); + if (centralityEstimator == Option::kNGlobal) + multiplicitydata = collision.centNGlobal(); + } + nCollisions++; + + atLeastOne = true; + } + + registryMC.fill(HIST("hCentralityVsNcoll_beforeEvSel"), multiplicitydata, groupedCollisions.size()); + registryMC.fill(HIST("hCentralityVsNcoll_afterEvSel"), multiplicitydata, nCollisions); + registryMC.fill(HIST("hCentralityVsMultMC"), multiplicitydata, mcCollisions.multMCNParticlesEta05()); + + registryQC.fill(HIST("hVertexZGen"), mcCollisions.posZ()); + + if (atLeastOne) { + registryMC.fill(HIST("hGenEvents"), mcCollisions.multMCNParticlesEta05(), 1 /* at least 1 rec. event*/); + + registryMC.fill(HIST("hGenEventCentrality"), multiplicitydata); + } + } + return; + } + + void processData(SelCollisions::iterator const& collision, + CascadeCandidates const& fullCascades, + DaughterTracks const&) + { + // Fill event counter before event selection + registryData.fill(HIST("number_of_events_data"), 0); + + // Initialize CCDB objects using the BC info + initCCDB(collision); + + // event selections + if (applySel8 && !collision.sel8()) + return; + registryData.fill(HIST("number_of_events_data"), 1); + if (applyVtxZ && std::fabs(collision.posZ()) > zVtx) + return; + registryData.fill(HIST("number_of_events_data"), 2); + + if (rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return; + } + registryData.fill(HIST("number_of_events_data"), 3 /* Not at ITS ROF border */); + + if (rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return; + } + registryData.fill(HIST("number_of_events_data"), 4 /* Not at TF border */); + + if (requireVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return; + } + registryData.fill(HIST("number_of_events_data"), 5 /* Contains at least one ITS-TPC track */); + + if (requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return; + } + registryData.fill(HIST("number_of_events_data"), 6 /* PV position consistency check */); + + if (requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return; + } + registryData.fill(HIST("number_of_events_data"), 7 /* PV with at least one contributor matched with TOF */); + + if (requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + return; + } + registryData.fill(HIST("number_of_events_data"), 8 /* PV with at least one contributor matched with TRD */); + + if (rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return; + } + registryData.fill(HIST("number_of_events_data"), 9 /* Not at same bunch pile-up */); + + // Store the Zvtx + registryQC.fill(HIST("hVertexZdata"), std::fabs(collision.posZ())); + + // Store the event multiplicity using different estimators + float multiplicity = -1.0f; + + if (centralityEstimator == Option::kFT0C) + multiplicity = collision.centFT0C(); + if (centralityEstimator == Option::kFT0M) + multiplicity = collision.centFT0M(); + if (centralityEstimator == Option::kFV0A) + multiplicity = collision.centFV0A(); + if (centralityEstimator == Option::kNGlobal) + multiplicity = collision.centNGlobal(); + + registryData.fill(HIST("hCentEstimator"), multiplicity); + registryData.fill(HIST("hCentralityVsNch"), multiplicity, collision.multNTracksPVeta1()); + + // Loop over cascades + 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 + + // Get cascade daughters + auto bach = casc.bachTrackExtra_as(); + auto pos = casc.posTrackExtra_as(); + auto neg = casc.negTrackExtra_as(); + + // ------------------------------------- Store selctions distribution for QC + registryQC.fill(HIST("hv0cosPAdata"), casc.v0cosPA(collision.posX(), collision.posY(), collision.posZ())); + registryQC.fill(HIST("hcasccosPAdata"), casc.casccosPA(collision.posX(), collision.posY(), collision.posZ())); + registryQC.fill(HIST("hv0radiusdata"), casc.v0radius()); + registryQC.fill(HIST("hcascradiusdata"), casc.cascradius()); + registryQC.fill(HIST("hdcaV0daughtersdata"), casc.dcaV0daughters()); + registryQC.fill(HIST("hdcacascdaughtersdata"), casc.dcacascdaughters()); + registryQC.fill(HIST("hdcapostopvdata"), casc.dcapostopv()); + registryQC.fill(HIST("hdcanegtopvdata"), casc.dcanegtopv()); + registryQC.fill(HIST("hdcabachtopvdata"), casc.dcabachtopv()); + registryQC.fill(HIST("hdcav0topvdata"), casc.dcav0topv(collision.posX(), collision.posY(), collision.posZ())); + + // ------------------------------------- Store selctions distribution for analysis + if (casc.sign() < 0) { + registryData.fill(HIST("hMassXineg"), multiplicity, casc.pt(), casc.mXi()); + registryData.fill(HIST("hMassOmeganeg"), multiplicity, casc.pt(), casc.mOmega()); + } + if (casc.sign() > 0) { + registryData.fill(HIST("hMassXipos"), multiplicity, casc.pt(), casc.mXi()); + registryData.fill(HIST("hMassOmegapos"), multiplicity, casc.pt(), casc.mOmega()); + } + + if (casc.sign() < 0 && passedXiSelection(casc, pos, neg, bach, collision)) { + registryData.fill(HIST("hMassXinegSelected"), multiplicity, casc.pt(), casc.mXi()); + } + if (casc.sign() < 0 && passedOmegaSelection(casc, pos, neg, bach, collision)) { + registryData.fill(HIST("hMassOmeganegSelected"), multiplicity, casc.pt(), casc.mOmega()); + } + if (casc.sign() > 0 && passedXiSelection(casc, pos, neg, bach, collision)) { + registryData.fill(HIST("hMassXiposSelected"), multiplicity, casc.pt(), casc.mXi()); + } + if (casc.sign() > 0 && passedOmegaSelection(casc, pos, neg, bach, collision)) { + registryData.fill(HIST("hMassOmegaposSelected"), multiplicity, casc.pt(), casc.mOmega()); + } + } + } + + PROCESS_SWITCH(CascadeAnalysisLightIonsDerivedData, processData, "Process data", true); + + void processMonteCarloRec(SimCollisions const& RecCols, CascadeMCCandidates const& fullCascades, DaughterTracks const&) + { + for (const auto& RecCol : RecCols) { + // Fill event counter before event selection + registryMC.fill(HIST("number_of_events_mc_rec"), 0); + + // Initialize CCDB objects using the BC info + initCCDB(RecCol); + + // event selections + if (applySel8 && !RecCol.sel8()) + continue; + registryMC.fill(HIST("number_of_events_mc_rec"), 1); + + if (applyVtxZ && std::fabs(RecCol.posZ()) > zVtx) + continue; + registryMC.fill(HIST("number_of_events_mc_rec"), 2); + + if (rejectITSROFBorder && !RecCol.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + continue; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 3 /* Not at ITS ROF border */); + + if (rejectTFBorder && !RecCol.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + continue; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 4 /* Not at TF border */); + + 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 */); + + if (requireIsGoodZvtxFT0VsPV && !RecCol.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + continue; + } + registryMC.fill(HIST("number_of_events_mc_rec"), 6 /* PV position consistency check */); + + 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 */); + + 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 */); + + 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 */); + + // Store the Zvtx + registryQC.fill(HIST("hVertexZRec"), RecCol.posZ()); + + // Store the event multiplicity using different estimators + float multiplicityMcRec = -1.0f; + + if (centralityEstimator == Option::kFT0C) + multiplicityMcRec = RecCol.centFT0C(); + if (centralityEstimator == Option::kFT0M) + multiplicityMcRec = RecCol.centFT0M(); + if (centralityEstimator == Option::kFV0A) + multiplicityMcRec = RecCol.centFV0A(); + if (centralityEstimator == Option::kNGlobal) + multiplicityMcRec = RecCol.centNGlobal(); + + registryMC.fill(HIST("hCentEstimator_truerec"), multiplicityMcRec); + registryMC.fill(HIST("hCentralityVsNch_truerec"), multiplicityMcRec, RecCol.multNTracksPVeta1()); + + 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 + + if (!casc.has_cascMCCore()) + continue; + + auto cascMC = casc.template cascMCCore_as(); + + 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())); + + // ------------------------------------- Store selctions distribution for analysis + if (casc.sign() < 0) { + if (pdgParent == kXiMinus) { + registryMC.fill(HIST("hMassXineg_truerec"), multiplicityMcRec, ptmc, casc.mXi()); + } + if (pdgParent == kOmegaMinus) { + registryMC.fill(HIST("hMassOmeganeg_truerec"), multiplicityMcRec, ptmc, casc.mOmega()); + } + } + + if (casc.sign() > 0) { + if (pdgParent == kXiPlusBar) { + registryMC.fill(HIST("hMassXipos_truerec"), multiplicityMcRec, ptmc, casc.mXi()); + } + if (pdgParent == kOmegaPlusBar) { + registryMC.fill(HIST("hMassOmegapos_truerec"), multiplicityMcRec, ptmc, casc.mOmega()); + } + } + + if (casc.sign() < 0 && pdgParent == kXiMinus && passedXiSelection(casc, pos, neg, bach, RecCol)) { + registryMC.fill(HIST("hMassXinegSelected_truerec"), multiplicityMcRec, ptmc, casc.mXi()); + } + if (casc.sign() < 0 && pdgParent == kOmegaMinus && passedOmegaSelection(casc, pos, neg, bach, RecCol)) { + registryMC.fill(HIST("hMassOmeganegSelected_truerec"), multiplicityMcRec, ptmc, casc.mOmega()); + } + if (casc.sign() > 0 && pdgParent == kXiPlusBar && passedXiSelection(casc, pos, neg, bach, RecCol)) { + registryMC.fill(HIST("hMassXiposSelected_truerec"), multiplicityMcRec, ptmc, casc.mXi()); + } + if (casc.sign() > 0 && pdgParent == kOmegaPlusBar && passedOmegaSelection(casc, pos, neg, bach, RecCol)) { + registryMC.fill(HIST("hMassOmegaposSelected_truerec"), multiplicityMcRec, ptmc, casc.mOmega()); + } + } // casc loop + } // rec.collision loop + } + + PROCESS_SWITCH(CascadeAnalysisLightIonsDerivedData, processMonteCarloRec, "Process MC Rec", false); + + void processMonteCarloGen(CollisionMCTrueTable const& mcCollisions, + CascadeMCCores const& CascMCCores, + SimCollisions const& RecCols) + { + // Fill generated event information (for event loss/splitting estimation) + fillGeneratedEventProperties(mcCollisions, RecCols); + std::vector listBestCollisionIdx = getListOfRecoCollIndices(mcCollisions, RecCols); + for (auto const& cascMC : CascMCCores) { + int pdgParent = cascMC.pdgCode(); + bool isPhysPrim = cascMC.isPhysicalPrimary(); + if (pdgParent == 0) + continue; + if (!isPhysPrim) + continue; + + float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); + + auto mcCollision = cascMC.template straMCCollision_as(); + + // event selections + if (applyVtxZ && std::abs(mcCollision.posZ()) > zVtx) + return; + + // Store the Zvtx + registryQC.fill(HIST("hVertexZGen"), mcCollision.posZ()); + + // float centrality = 100.5f; + + if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { + // auto collision = RecCols.iteratorAt(listBestCollisionIdx[mcCollision.globalIndex()]); + // if (centralityEstimator == Option::kFT0C) centrality = collision.centFT0C(); + // if (centralityEstimator == Option::kFT0M) centrality = collision.centFT0M(); + // if (centralityEstimator == Option::kFV0A) centrality = collision.centFV0A(); + // if (centralityEstimator == Option::kNGlobal) centrality = collision.centNGlobal(); + + if (cascMC.pdgCode() == kXiMinus && std::abs(cascMC.rapidityMC(0)) < rapcut) { + registryMC.fill(HIST("h2dGenXiMinusVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == kXiPlusBar && std::abs(cascMC.rapidityMC(0)) < rapcut) { + registryMC.fill(HIST("h2dGenXiPlusVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == kOmegaMinus && std::abs(cascMC.rapidityMC(2)) < rapcut) { + registryMC.fill(HIST("h2dGenOmegaMinusVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == kOmegaPlusBar && std::abs(cascMC.rapidityMC(2)) < rapcut) { + registryMC.fill(HIST("h2dGenOmegaPlusVsMultMC_RecoedEvt"), mcCollision.multMCNParticlesEta05(), ptmc); + } + } + + if (cascMC.pdgCode() == kXiMinus && std::abs(cascMC.rapidityMC(0)) < rapcut) { + registryMC.fill(HIST("h2dGenXiMinusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == kXiPlusBar && std::abs(cascMC.rapidityMC(0)) < rapcut) { + registryMC.fill(HIST("h2dGenXiPlusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == kOmegaMinus && std::abs(cascMC.rapidityMC(2)) < rapcut) { + registryMC.fill(HIST("h2dGenOmegaMinusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + if (cascMC.pdgCode() == kOmegaPlusBar && std::abs(cascMC.rapidityMC(2)) < rapcut) { + registryMC.fill(HIST("h2dGenOmegaPlusVsMultMC"), mcCollision.multMCNParticlesEta05(), ptmc); + } + } // cascMC loop + } + + PROCESS_SWITCH(CascadeAnalysisLightIonsDerivedData, processMonteCarloGen, "Process MC Gen", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx index 632d80dd4d1..c062c2f1a0d 100644 --- a/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx +++ b/PWGLF/Tasks/Strangeness/cascadecorrelations.cxx @@ -15,38 +15,40 @@ // Author: Rik Spijkers (rik.spijkers@cern.ch) // -#include -#include -#include -#include -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/inelGt.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "ReconstructionDataFormats/Track.h" #include "Common/Core/RecoDecay.h" -#include "Common/Core/trackUtilities.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/Core/TrackSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.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 "CCDB/BasicCCDBManager.h" +#include "Common/DataModel/TrackSelectionTables.h" #include "EventFiltering/Zorro.h" -#include "PWGLF/Utils/inelGt.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 "ReconstructionDataFormats/Track.h" + +#include #include -#include #include -#include +#include #include #include +#include + +#include +#include +#include +#include +#include // #include using namespace o2; @@ -84,6 +86,7 @@ using LabeledCascades = soa::Join; struct CascadeSelector { Service ccdb; + Service pdgDB; Produces cascflags; @@ -97,6 +100,8 @@ struct CascadeSelector { 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"}; @@ -105,6 +110,8 @@ struct CascadeSelector { 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 //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* @@ -169,6 +176,12 @@ struct CascadeSelector { {"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"}}}}, }, @@ -184,11 +197,12 @@ struct CascadeSelector { h->GetXaxis()->SetBinLabel(1, "All"); h->GetXaxis()->SetBinLabel(2, "nTPC OK"); h->GetXaxis()->SetBinLabel(3, "nITS OK"); - h->GetXaxis()->SetBinLabel(4, "Topo OK"); - h->GetXaxis()->SetBinLabel(5, "Track eta OK"); - h->GetXaxis()->SetBinLabel(6, "Cascade eta OK"); - h->GetXaxis()->SetBinLabel(7, "V0 PID OK"); - h->GetXaxis()->SetBinLabel(8, "Bach PID 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"); @@ -217,6 +231,12 @@ struct CascadeSelector { 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}); @@ -229,13 +249,22 @@ struct CascadeSelector { 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"}}); } } - bool eventSelection(MyCollisions::iterator const& collision) + template + bool eventSelection(TCollision const& collision) { if (useTrigger) { - auto bc = collision.bc_as(); + auto bc = collision.template bc_as(); zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerList); bool eventTrigger = zorro.isSelected(bc.globalBC()); if (eventTrigger) { @@ -265,7 +294,8 @@ struct CascadeSelector { return true; } - void fillMatchedHistos(LabeledCascades::iterator rec, int flag, MyCollisions::iterator collision) + template + void fillMatchedHistos(LabeledCascades::iterator rec, int flag, TCollision collision) { if (flag == 0) return; @@ -275,7 +305,7 @@ struct CascadeSelector { if (!gen.isPhysicalPrimary()) return; int genpdg = gen.pdgCode(); - if ((flag < 3 && TMath::Abs(genpdg) == 3312) || (flag > 1 && TMath::Abs(genpdg) == 3334)) { + 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()); @@ -295,6 +325,12 @@ struct CascadeSelector { 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()); @@ -312,8 +348,8 @@ struct CascadeSelector { } } - template - int processCandidate(TCascade const& casc, MyCollisions::iterator const& collision) + template + int processCandidate(TCascade const& casc, TCollision const& collision) { // these are the tracks: auto bachTrack = casc.template bachelor_as(); @@ -339,6 +375,12 @@ struct CascadeSelector { 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()); @@ -357,6 +399,14 @@ struct CascadeSelector { 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(); @@ -366,21 +416,21 @@ struct CascadeSelector { casc.v0cosPA(pvx, pvy, pvz) < v0setting_cospa || casc.casccosPA(pvx, pvy, pvz) < cascadesetting_cospa || casc.dcav0topv(pvx, pvy, pvz) < cascadesetting_mindcav0topv || - TMath::Abs(casc.mLambda() - 1.115683) > cascadesetting_v0masswindow) + std::abs(casc.mLambda() - 1.115683) > cascadesetting_v0masswindow) return 0; // It failed at least one topo selection - registry.fill(HIST("hSelectionStatus"), 3); // passes topo + registry.fill(HIST("hSelectionStatus"), 4); // passes topo // registry.fill(HIST("hMassXi3"), casc.mXi(), casc.pt()); - if (TMath::Abs(posTrack.eta()) > etaTracks || TMath::Abs(negTrack.eta()) > etaTracks || TMath::Abs(bachTrack.eta()) > etaTracks) + if (std::abs(posTrack.eta()) > etaTracks || std::abs(negTrack.eta()) > etaTracks || std::abs(bachTrack.eta()) > etaTracks) return 0; - registry.fill(HIST("hSelectionStatus"), 4); // passes track eta + registry.fill(HIST("hSelectionStatus"), 5); // passes track eta - if (TMath::Abs(casc.eta()) > etaCascades) + if (std::abs(casc.eta()) > etaCascades) return 0; - registry.fill(HIST("hSelectionStatus"), 5); // passes candidate eta + registry.fill(HIST("hSelectionStatus"), 6); // passes candidate eta // TODO: TOF (for pT > 2 GeV per track?) @@ -388,28 +438,40 @@ struct CascadeSelector { // Lambda check if (casc.sign() < 0) { // Proton check: - if (TMath::Abs(posTrack.tpcNSigmaPr()) > tpcNsigmaProton) + if (std::abs(posTrack.tpcNSigmaPr()) > tpcNsigmaProton) return 0; // Pion check: - if (TMath::Abs(negTrack.tpcNSigmaPi()) > tpcNsigmaPion) + if (std::abs(negTrack.tpcNSigmaPi()) > tpcNsigmaPion) return 0; } else { // Proton check: - if (TMath::Abs(negTrack.tpcNSigmaPr()) > tpcNsigmaProton) + if (std::abs(negTrack.tpcNSigmaPr()) > tpcNsigmaProton) return 0; // Pion check: - if (TMath::Abs(posTrack.tpcNSigmaPi()) > tpcNsigmaPion) + if (std::abs(posTrack.tpcNSigmaPi()) > tpcNsigmaPion) return 0; } - registry.fill(HIST("hSelectionStatus"), 6); // passes V0 daughters PID + registry.fill(HIST("hSelectionStatus"), 7); // passes V0 daughters PID // registry.fill(HIST("hMassXi4"), casc.mXi(), casc.pt()); - // Bachelor check - if (TMath::Abs(bachTrack.tpcNSigmaPi()) < tpcNsigmaBachelor) { - if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) { - // consistent with both! - registry.fill(HIST("hSelectionStatus"), 7); // passes bach PID - // registry.fill(HIST("hMassXi5"), 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()); @@ -417,35 +479,30 @@ struct CascadeSelector { registry.fill(HIST("hMassXiPlus"), casc.mXi(), casc.pt(), casc.yXi()); registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt(), casc.yOmega()); } - return 2; - } - registry.fill(HIST("hSelectionStatus"), 7); // passes bach PID - // registry.fill(HIST("hMassXi5"), casc.mXi(), casc.pt()); - 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()); - } - return 1; - } else if (TMath::Abs(bachTrack.tpcNSigmaKa()) < tpcNsigmaBachelor) { - registry.fill(HIST("hSelectionStatus"), 7); // 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()); - } - return 3; + 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; } - // if we reach here, the bachelor was neither pion nor kaon - return 0; + + return flag; + } // processCandidate - void processGenMC(aod::McCollision const&, soa::SmallGroups> const&, aod::McParticles const& mcParticles) + void processGenMC(aod::McCollision const&, soa::SmallGroups> const& collisions, aod::McParticles const& mcParticles) { + // N gen events without any event selection or matched reco event + registry.fill(HIST("gen/hNevents"), 0); + for (auto const& mcPart : mcParticles) { if (!mcPart.isPhysicalPrimary()) continue; - if (TMath::Abs(mcPart.eta()) > etaCascades) + if (std::abs(mcPart.eta()) > etaCascades) continue; switch (mcPart.pdgCode()) { @@ -464,15 +521,44 @@ struct CascadeSelector { } } - // if (matchedCollisions.size() < 1) { - // return; - // } else if (matchedCollisions.size() == 1) { - // for (auto const& collision : matchedCollisions) { // not really a loop, as there is only one collision - // } - // } else if (matchedCollisions.size() > 1) { - // registry.fill(HIST("MC/hSplitEvents"), matchedCollisions.size()); - // return; - // } + // 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); + 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 @@ -536,8 +622,9 @@ struct CascadeCorrelations { ConfigurableAxis dcaAxis = {"dcaAxis", {100, 0.0f, 2.0f}, "cm"}; ConfigurableAxis multiplicityAxis{"multiplicityAxis", {100, 0, 100}, "Multiplicity (MultFT0M?)"}; ConfigurableAxis invLambdaMassAxis{"invLambdaMassAxis", {100, 1.07f, 1.17f}, "Inv. Mass (GeV/c^{2})"}; - AxisSpec deltaYAxis{40, -2 * maxRapidity, 2 * maxRapidity, "#Delta y"}; - AxisSpec rapidityAxis{100, -maxRapidity, maxRapidity, "y"}; + 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"}; @@ -583,6 +670,18 @@ struct CascadeCorrelations { 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", { @@ -592,8 +691,8 @@ struct CascadeCorrelations { {"hMassOmegaMinus", "hMassOmegaMinus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, {"hMassOmegaPlus", "hMassOmegaPlus", {HistType::kTH2F, {invMassAxis, ptAxis}}}, // efficiency corrected inv mass - {"hMassXiEffCorrected", "hMassXiEffCorrected", {HistType::kTHnSparseF, {invMassAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, - {"hMassOmegaEffCorrected", "hMassOmegaEffCorrected", {HistType::kTHnSparseF, {invMassAxis, ptAxis, rapidityAxis, vertexAxis, multiplicityAxis}}, true}, + {"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"}}}}, @@ -629,14 +728,9 @@ struct CascadeCorrelations { {"hDeltaPhiSS", "hDeltaPhiSS", {HistType::kTH1F, {deltaPhiAxis}}}, {"hDeltaPhiOS", "hDeltaPhiOS", {HistType::kTH1F, {deltaPhiAxis}}}, - {"hXiXiOS", "hXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hXiXiSS", "hXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hXiOmOS", "hXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hXiOmSS", "hXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmXiOS", "hOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmXiSS", "hOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmOmOS", "hOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"hOmOmSS", "hOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"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}}}, @@ -647,14 +741,9 @@ struct CascadeCorrelations { {"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/hMEXiXiOS", "hMEXiXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEXiXiSS", "hMEXiXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEXiOmOS", "hMEXiOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEXiOmSS", "hMEXiOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmXiOS", "hMEOmXiOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmXiSS", "hMEOmXiSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmOmOS", "hMEOmOmOS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, - {"MixedEvents/hMEOmOmSS", "hMEOmOmSS", {HistType::kTHnSparseF, {deltaPhiAxis, deltaYAxis, ptAxis, ptAxis, invMassAxis, invMassAxis, vertexAxis, multiplicityAxis}}, true}, + {"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}, @@ -711,7 +800,7 @@ struct CascadeCorrelations { weight = getEfficiency(hEffXiPlus, casc.pt()); } // LOGF(info, "casc pt %f, weight %f", casc.pt(), weight); - registry.fill(HIST("hMassXiEffCorrected"), casc.mXi(), casc.pt(), casc.yXi(), collision.posZ(), collision.multFT0M(), weight); + registry.fill(HIST("hMassXiEffCorrected"), casc.mXi(), casc.sign(), casc.pt(), casc.yXi(), collision.posZ(), collision.multFT0M(), weight); registry.fill(HIST("hRapidityXi"), casc.yXi()); } if (casc.isSelected() >= 2) { // consistent with Omega or both @@ -722,7 +811,7 @@ struct CascadeCorrelations { registry.fill(HIST("hMassOmegaPlus"), casc.mOmega(), casc.pt()); weight = getEfficiency(hEffOmegaPlus, casc.pt()); } - registry.fill(HIST("hMassOmegaEffCorrected"), casc.mOmega(), casc.pt(), casc.yOmega(), collision.posZ(), collision.multFT0M(), weight); + registry.fill(HIST("hMassOmegaEffCorrected"), casc.mOmega(), casc.sign(), casc.pt(), casc.yOmega(), collision.posZ(), collision.multFT0M(), weight); registry.fill(HIST("hRapidityOmega"), casc.yOmega()); } registry.fill(HIST("hV0Radius"), casc.v0radius()); @@ -758,12 +847,11 @@ struct CascadeCorrelations { auto trigger = *triggerAddress; auto assoc = *assocAddress; - // track indices for posterior checks - // retains logic of V0 index while being safe wrt data model - int posIdTrigg = trigger.posTrackId(); - int negIdTrigg = trigger.negTrackId(); - int posIdAssoc = assoc.posTrackId(); - int negIdAssoc = assoc.negTrackId(); + // 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); @@ -776,128 +864,42 @@ struct CascadeCorrelations { double weightTrigg = 1.; double weightAssoc = 1.; - // split into opposite-sign or same-sign - if (trigger.sign() * assoc.sign() < 0) { // opposite-sign - // check for autocorrelations between mis-identified kaons (omega bach) and protons (lambda daughter) TODO: improve logic? - if (trigger.isSelected() >= 2) { - if (trigger.sign() > 0 && trigger.bachelorId() == posIdAssoc) { - // K+ from trigger Omega is the same as proton from assoc lambda - registry.fill(HIST("hAutoCorrelationOS"), 1); - continue; - } - if (trigger.sign() < 0 && trigger.bachelorId() == negIdAssoc) { - // K- from trigger Omega is the same as antiproton from assoc antilambda - registry.fill(HIST("hAutoCorrelationOS"), -1); - continue; - } - } - if (assoc.isSelected() >= 2) { - if (assoc.sign() > 0 && assoc.bachelorId() == posIdTrigg) { - // K+ from assoc Omega is the same as proton from trigger lambda - registry.fill(HIST("hAutoCorrelationOS"), 1); - continue; - } - if (assoc.sign() < 0 && assoc.bachelorId() == negIdTrigg) { - // K- from assoc Omega is the same as antiproton from trigger antilambda - registry.fill(HIST("hAutoCorrelationOS"), -1); - continue; - } - } - registry.fill(HIST("hDeltaPhiOS"), dphi); - // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + 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) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hXiXiOS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hXiOmOS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } + 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.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hOmXiOS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hOmOmOS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - } - } else { // same-sign - // make sure to check for autocorrelations - only possible in same-sign correlations (if PID is correct) - if (posIdTrigg == posIdAssoc && negIdTrigg == negIdAssoc) { - // LOGF(info, "same v0 in SS correlation! %d %d", v0dataTrigg.v0Id(), v0dataAssoc.v0Id()); - registry.fill(HIST("hAutoCorrelation"), 0); - continue; - } - int bachIdTrigg = trigger.bachelorId(); - int bachIdAssoc = assoc.bachelorId(); - - if (bachIdTrigg == bachIdAssoc) { - // LOGF(info, "same bachelor in SS correlation! %d %d", bachIdTrigg, bachIdAssoc); - registry.fill(HIST("hAutoCorrelation"), 1); - continue; - } - // check for same tracks in v0's of cascades - if (negIdTrigg == negIdAssoc || posIdTrigg == posIdAssoc) { - // LOGF(info, "cascades have a v0-track in common in SS correlation!"); - registry.fill(HIST("hAutoCorrelation"), 2); - continue; - } - if (trigger.sign() < 0) { // neg cascade - if (negIdTrigg == bachIdAssoc || negIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in neg SS correlation!"); - registry.fill(HIST("hAutoCorrelation"), 3); - continue; - } - } else { // pos cascade - if (posIdTrigg == bachIdAssoc || posIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in pos SS correlation!"); - registry.fill(HIST("hAutoCorrelation"), 3); - continue; - } + 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.multFT0M(), weightTrigg * weightAssoc); } - registry.fill(HIST("hDeltaPhiSS"), dphi); - // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + } + 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) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hXiXiSS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hXiOmSS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } + 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.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("hOmXiSS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("hOmOmSS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, collision.posZ(), collision.multFT0M(), weightTrigg * weightAssoc); - } + 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.multFT0M(), 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 @@ -909,13 +911,12 @@ struct CascadeCorrelations { for (auto const& [col1, cascades1, col2, cascades2] : pair) { if (!col1.sel8() || !col2.sel8()) continue; - if (TMath::Abs(col1.posZ()) > zVertexCut || TMath::Abs(col2.posZ()) > zVertexCut) + 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()); @@ -934,6 +935,11 @@ struct CascadeCorrelations { 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(); @@ -941,146 +947,51 @@ struct CascadeCorrelations { double invMassXiAssoc = assoc.mXi(); double invMassOmAssoc = assoc.mOmega(); - // V0 daughter track ID's used for autocorrelation check - int posIdTrigg = trigger.posTrackId(); - int negIdTrigg = trigger.negTrackId(); - int posIdAssoc = assoc.posTrackId(); - int negIdAssoc = assoc.negTrackId(); - double weightTrigg = 1.; double weightAssoc = 1.; - if (trigger.sign() * assoc.sign() < 0) { // opposite-sign - - // check for autocorrelations between mis-identified kaons (omega bach) and protons (lambda daughter) TODO: improve logic? - if (trigger.isSelected() >= 2) { - if (trigger.sign() > 0 && trigger.bachelorId() == posIdAssoc) { - // K+ from trigger Omega is the same as proton from assoc lambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), 1); - continue; - } - if (trigger.sign() < 0 && trigger.bachelorId() == negIdAssoc) { - // K- from trigger Omega is the same as antiproton from assoc antilambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), -1); - continue; - } - } - if (assoc.isSelected() >= 2) { - if (assoc.sign() > 0 && assoc.bachelorId() == posIdTrigg) { - // K+ from assoc Omega is the same as proton from trigger lambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), 1); - continue; - } - if (assoc.sign() < 0 && assoc.bachelorId() == negIdTrigg) { - // K- from assoc Omega is the same as antiproton from trigger antilambda - registry.fill(HIST("MixedEvents/hMEAutoCorrelationOS"), -1); - continue; - } - } - - registry.fill(HIST("MixedEvents/hMEDeltaPhiOS"), dphi); - - // Fill the different THnSparses depending on PID logic (important for rapidity & inv mass information) - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + 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) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiXiOS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiOmOS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } + 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.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmXiOS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmOmOS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - } - } else { // same sign - // make sure to check for autocorrelations - only possible in same-sign correlations (if PID is correct) - if (posIdTrigg == posIdAssoc && negIdTrigg == negIdAssoc) { - // LOGF(info, "same v0 in SS correlation! %d %d", v0dataTrigg.v0Id(), v0dataAssoc.v0Id()); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 0); - continue; - } - int bachIdTrigg = trigger.bachelorId(); - int bachIdAssoc = assoc.bachelorId(); - - if (bachIdTrigg == bachIdAssoc) { - // LOGF(info, "same bachelor in SS correlation! %d %d", bachIdTrigg, bachIdAssoc); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 1); - continue; - } - // check for same tracks in v0's of cascades - if (negIdTrigg == negIdAssoc || posIdTrigg == posIdAssoc) { - // LOGF(info, "cascades have a v0-track in common in SS correlation!"); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 2); - continue; - } - if (trigger.sign() < 0) { // neg cascade - if (negIdTrigg == bachIdAssoc || negIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in neg SS correlation!"); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 3); - continue; - } - } else { // pos cascade - if (posIdTrigg == bachIdAssoc || posIdAssoc == bachIdTrigg) { - // LOGF(info, "bach of casc == v0-pion of other casc in pos SS correlation!"); - registry.fill(HIST("MixedEvents/hMEAutoCorrelation"), 3); - continue; - } + 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.multFT0M(), weightTrigg * weightAssoc); } - - registry.fill(HIST("MixedEvents/hMEDeltaPhiSS"), dphi); - - if (trigger.isSelected() <= 2 && TMath::Abs(trigger.yXi()) < maxRapidity) { // trigger Xi + } + 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) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffXiMin, trigger.pt()) : getEfficiency(hEffXiPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiXiSS"), dphi, trigger.yXi() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEXiOmSS"), dphi, trigger.yXi() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassXiTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } + 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.multFT0M(), weightTrigg * weightAssoc); } - if (trigger.isSelected() >= 2 && TMath::Abs(trigger.yOmega()) < maxRapidity) { // trigger Omega + if (assoc.isSelected() >= 2 && std::abs(assoc.yOmega()) < maxRapidity) { // assoc Omega if (doEfficiencyCorrection) - weightTrigg = trigger.sign() < 0 ? getEfficiency(hEffOmegaMin, trigger.pt()) : getEfficiency(hEffOmegaPlus, trigger.pt()); - if (assoc.isSelected() <= 2 && TMath::Abs(assoc.yXi()) < maxRapidity) { // assoc Xi - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffXiMin, assoc.pt()) : getEfficiency(hEffXiPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmXiSS"), dphi, trigger.yOmega() - assoc.yXi(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassXiAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } - if (assoc.isSelected() >= 2 && TMath::Abs(assoc.yOmega()) < maxRapidity) { // assoc Omega - if (doEfficiencyCorrection) - weightAssoc = assoc.sign() < 0 ? getEfficiency(hEffOmegaMin, assoc.pt()) : getEfficiency(hEffOmegaPlus, assoc.pt()); - registry.fill(HIST("MixedEvents/hMEOmOmSS"), dphi, trigger.yOmega() - assoc.yOmega(), trigger.pt(), assoc.pt(), invMassOmTrigg, invMassOmAssoc, col1.posZ(), col1.multFT0M(), weightTrigg * weightAssoc); - } + 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.multFT0M(), weightTrigg * weightAssoc); } - } // same sign + } + + // 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 && nabs(aod::mcparticle::eta) < etaGenCascades); + Filter genCascadesFilter = nabs(aod::mcparticle::pdgCode) == 3312; void processMC(aod::McCollision const&, soa::SmallGroups> const& collisions, soa::Filtered const& genCascades, aod::McParticles const& mcParticles) { @@ -1122,10 +1033,12 @@ struct CascadeCorrelations { auto trigger = *triggerAddress; auto assoc = *assocAddress; - double dphi = RecoDecay::constrainAngle(trigger.phi() - assoc.phi(), -PIHalf); - 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 diff --git a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx index 95a25f589e3..5cab36540c3 100644 --- a/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedcascadeanalysis.cxx @@ -76,6 +76,7 @@ struct Derivedcascadeanalysis { ConfigurableAxis axisIR{"axisIR", {510, -1, 50}, "Binning for the interaction rate (kHz)"}; Configurable isXi{"isXi", 1, "Apply cuts for Xi identification"}; + Configurable ispO{"ispO", 0, "Analyse p--O collisions"}; Configurable useCentralityFT0M{"useCentralityFT0M", 0, "If true, use centFT0M"}; Configurable useCentralityFT0A{"useCentralityFT0A", 0, "If true, use centFT0A"}; Configurable useCentralityFT0Cvar1{"useCentralityFT0Cvar1", 0, "If true, use centFT0FT0Cvar1"}; @@ -119,6 +120,18 @@ struct Derivedcascadeanalysis { Configurable maxOccupancy{"maxOccupancy", -1, "Maximal occupancy"}; Configurable minOccupancyFT0{"minOccupancyFT0", -1, "Minimal occupancy"}; Configurable maxOccupancyFT0{"maxOccupancyFT0", -1, "Maximal occupancy"}; + Configurable globalTracksCorrelpar0Low{"globalTracksCorrelpar0Low", 81, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable globalTracksCorrelpar1Low{"globalTracksCorrelpar1Low", -0.0431016, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable globalTracksCorrelpar2Low{"globalTracksCorrelpar2Low", -6, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable globalTracksCorrelpar0High{"globalTracksCorrelpar0High", 226, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable globalTracksCorrelpar1High{"globalTracksCorrelpar1High", -0.0181686, "[0]*exp([1]*centrality)+[2], mean plus 3*sigma"}; + Configurable globalTracksCorrelpar2High{"globalTracksCorrelpar2High", -22, "[0]*exp([1]*centrality)+[2], mean plus 3*sigma"}; + Configurable pvContribCorrelpar0Low{"pvContribCorrelpar0Low", 152, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable pvContribCorrelpar1Low{"pvContribCorrelpar1Low", -0.0431016, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable pvContribCorrelpar2Low{"pvContribCorrelpar2Low", -15.3776, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable pvContribCorrelpar0High{"pvContribCorrelpar0High", 384.861, "[0]*exp([1]*centrality)+[2], mean minus 3*sigma"}; + Configurable pvContribCorrelpar1High{"pvContribCorrelpar1High", -0.0181686, "[0]*exp([1]*centrality)+[2], mean plus 3*sigma"}; + Configurable pvContribCorrelpar2High{"pvContribCorrelpar2High", -39, "[0]*exp([1]*centrality)+[2], mean plus 3*sigma"}; } eventSelectionRun3Flags; struct : ConfigurableGroup { @@ -219,6 +232,8 @@ struct Derivedcascadeanalysis { Configurable rejcomp{"rejcomp", 0.008, "Competing Cascade rejection"}; Configurable masswin{"masswin", 0.05, "Mass window limit"}; Configurable rapCut{"rapCut", 0.5, "Rapidity acceptance"}; + Configurable minRapCut{"minRapCut", -0.845, "minimal rapidity acceptance in case of p--o"}; + Configurable maxRapCut{"maxRapCut", 0.155, "maximal rapidity acceptance in case of p--o"}; Configurable etaDauCut{"etaDauCut", 0.8, "Pseudorapidity acceptance of the cascade daughters"}; Configurable minITSclusters{"minITSclusters", 3, "minimal number of ITS hits for the daughter tracks"}; } candidateSelectionValues; @@ -302,6 +317,10 @@ struct Derivedcascadeanalysis { histos.add("hNCrossedRowsPositive", "", kTH1F, {{400, -200, 200}}); histos.add("hNCrossedRowsBachelor", "", kTH1F, {{400, -200, 200}}); + histos.add("hPseudorapPosDaughter", "", kTH1F, {{50, -1, 1}}); + histos.add("hPseudorapNegDaughter", "", kTH1F, {{50, -1, 1}}); + histos.add("hPseudorapBachelor", "", kTH1F, {{50, -1, 1}}); + histos.add("hEventNchCorrelationAfCuts", "hEventNchCorrelationAfCuts", kTH2F, {{5000, 0, 5000}, {5000, 0, 2500}}); histos.add("hEventPVcontributorsVsCentrality", "hEventPVcontributorsVsCentrality", kTH2F, {{100, 0, 100}, {5000, 0, 5000}}); histos.add("hEventGlobalTracksVsCentrality", "hEventGlobalTracksVsCentrality", kTH2F, {{100, 0, 100}, {2500, 0, 2500}}); @@ -660,9 +679,9 @@ struct Derivedcascadeanalysis { histos.fill(HIST("hEventSelection"), 11.5 /* Not at TF border */); if (eventSelectionRun3Flags.doMultiplicityCorrCut) { - if (coll.multNTracksGlobal() < (1343.3 * std::exp(-0.0443259 * centrality) - 50) || coll.multNTracksGlobal() > (2098.9 * std::exp(-0.0332444 * centrality))) + if (coll.multNTracksGlobal() < (eventSelectionRun3Flags.globalTracksCorrelpar0Low * std::exp(eventSelectionRun3Flags.globalTracksCorrelpar1Low * centrality) + eventSelectionRun3Flags.globalTracksCorrelpar2Low) || coll.multNTracksGlobal() > (eventSelectionRun3Flags.globalTracksCorrelpar0High * std::exp(eventSelectionRun3Flags.globalTracksCorrelpar1High * centrality) + eventSelectionRun3Flags.globalTracksCorrelpar2High)) return false; - if (coll.multNTracksPVeta1() < (3703 * std::exp(-0.0455483 * centrality) - 150) || coll.multNTracksPVeta1() > (4937.33 * std::exp(-0.0372668 * centrality) + 20)) + if (coll.multNTracksPVeta1() < (eventSelectionRun3Flags.pvContribCorrelpar0Low * std::exp(eventSelectionRun3Flags.pvContribCorrelpar1Low * centrality) + eventSelectionRun3Flags.pvContribCorrelpar2Low) || coll.multNTracksPVeta1() > (eventSelectionRun3Flags.pvContribCorrelpar0High * std::exp(eventSelectionRun3Flags.pvContribCorrelpar1High * centrality) + eventSelectionRun3Flags.pvContribCorrelpar2High)) return false; } if (fillHists) @@ -826,13 +845,17 @@ struct Derivedcascadeanalysis { float cut = candidateSelectionValues.masswin; histos.fill(HIST("hCutValue"), 1, cut); cut = candidateSelectionValues.rapCut; + if (ispO) + cut = candidateSelectionValues.maxRapCut; histos.fill(HIST("hCutValue"), 2, cut); if (isXi) { if (std::abs(casc.mXi() - o2::constants::physics::MassXiMinus) > candidateSelectionValues.masswin) { return false; } histos.fill(HIST("hCandidate"), ++counter); - if (std::abs(casc.yXi()) > candidateSelectionValues.rapCut) + if (ispO && (casc.yXi() < candidateSelectionValues.minRapCut || casc.yXi() > candidateSelectionValues.maxRapCut)) + return false; + else if (std::abs(casc.yXi()) > candidateSelectionValues.rapCut) return false; histos.fill(HIST("hCandidate"), ++counter); } else { @@ -840,7 +863,9 @@ struct Derivedcascadeanalysis { return false; } histos.fill(HIST("hCandidate"), ++counter); - if (std::abs(casc.yOmega()) > candidateSelectionValues.rapCut) + if (ispO && (casc.yOmega() < candidateSelectionValues.minRapCut || casc.yOmega() > candidateSelectionValues.maxRapCut)) + return false; + else if (std::abs(casc.yOmega()) > candidateSelectionValues.rapCut) return false; histos.fill(HIST("hCandidate"), ++counter); } @@ -1120,11 +1145,11 @@ struct Derivedcascadeanalysis { auto cascMC = casc.template cascMCCore_as>(); ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); - if (cascMC.isPhysicalPrimary() && ((isXi && std::abs(cascMC.pdgCode()) == 3312) || (!isXi && std::abs(cascMC.pdgCode()) == 3334))) + if (cascMC.isPhysicalPrimary() && ((isXi && std::abs(cascMC.pdgCode()) == PDG_t::kXiMinus) || (!isXi && std::abs(cascMC.pdgCode()) == PDG_t::kOmegaMinus))) isTrueMCCascade = true; - if (isTrueMCCascade && ((isPositive && cascMC.pdgCodePositive() == 211 && cascMC.pdgCodeNegative() == -2212) || (isNegative && cascMC.pdgCodePositive() == 2212 && cascMC.pdgCodeNegative() == -211))) + if (isTrueMCCascade && ((isPositive && cascMC.pdgCodePositive() == PDG_t::kPiPlus && cascMC.pdgCodeNegative() == PDG_t::kProtonBar) || (isNegative && cascMC.pdgCodePositive() == PDG_t::kProton && cascMC.pdgCodeNegative() == PDG_t::kPiMinus))) isCorrectLambdaDecay = true; - if (isTrueMCCascade && isCorrectLambdaDecay && ((isXi && std::abs(cascMC.pdgCodeBachelor()) == 211) || (!isXi && std::abs(cascMC.pdgCodeBachelor()) == 321))) + if (isTrueMCCascade && isCorrectLambdaDecay && ((isXi && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kPiPlus) || (!isXi && std::abs(cascMC.pdgCodeBachelor()) == PDG_t::kKPlus))) isTrueMCCascadeDecay = true; if (qaFlags.doBefSelCheck && isTrueMCCascade) { @@ -1161,6 +1186,10 @@ struct Derivedcascadeanalysis { continue; histos.fill(HIST("hCandidate"), ++counter); + histos.fill(HIST("hPseudorapPosDaughter"), poseta); + histos.fill(HIST("hPseudorapNegDaughter"), negeta); + histos.fill(HIST("hPseudorapBachelor"), bacheta); + if (candidateSelectionFlags.doCascadeCosPaCut) { if (!isCosPAAccepted(casc, coll.posX(), coll.posY(), coll.posZ(), candidateSelectionFlags.doPtDepCosPaCut, true)) continue; @@ -1429,12 +1458,14 @@ struct Derivedcascadeanalysis { float ptmc = RecoDecay::sqrtSumOfSquares(cascMC.pxMC(), cascMC.pyMC()); float ymc = 1e3; - if (std::abs(cascMC.pdgCode()) == 3312) + if (std::abs(cascMC.pdgCode()) == PDG_t::kXiMinus) ymc = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, o2::constants::physics::MassXiMinus); - else if (std::abs(cascMC.pdgCode()) == 3334) + else if (std::abs(cascMC.pdgCode()) == PDG_t::kOmegaMinus) ymc = RecoDecay::y(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()}, o2::constants::physics::MassOmegaMinus); - if (std::abs(ymc) > candidateSelectionValues.rapCut) + if (ispO && (ymc > candidateSelectionValues.maxRapCut || ymc < candidateSelectionValues.minRapCut)) + continue; + else if (std::abs(ymc) > candidateSelectionValues.rapCut) continue; auto mcCollision = cascMC.template straMCCollision_as>(); @@ -1471,7 +1502,7 @@ struct Derivedcascadeanalysis { nChEta1 = collision.multNTracksPVeta1(); } - if (cascMC.pdgCode() == 3312 && isXi) { + if (cascMC.pdgCode() == PDG_t::kXiMinus && isXi) { histos.fill(HIST("h2dGenXiMinus"), centrality, ptmc); histos.fill(HIST("h2dGenXiMinusVsNch"), nChEta1, ptmc); histos.fill(HIST("h2dGenXiMinusEta"), RecoDecay::eta(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()})); @@ -1484,7 +1515,7 @@ struct Derivedcascadeanalysis { histos.fill(HIST("h2dGenXiMinusVsCentIR"), ptmc, centrality, intRate); histos.fill(HIST("h2dGenXiMinusVsNchVsOccupancy"), ptmc, nChEta1, occupancy); } - if (cascMC.pdgCode() == -3312 && isXi) { + if (cascMC.pdgCode() == PDG_t::kXiPlusBar && isXi) { histos.fill(HIST("h2dGenXiPlus"), centrality, ptmc); histos.fill(HIST("h2dGenXiPlusVsNch"), nChEta1, ptmc); histos.fill(HIST("h2dGenXiPlusVsMultMCVsCentrality"), mcCollision.multMCNParticlesEta05(), centrality, ptmc); @@ -1493,7 +1524,7 @@ struct Derivedcascadeanalysis { histos.fill(HIST("h2dGenXiPlusVsNchVsOccupancy"), ptmc, nChEta1, occupancy); histos.fill(HIST("h2dGenXiPlusVsCentIR"), ptmc, centrality, intRate); } - if (cascMC.pdgCode() == 3334 && !isXi) { + if (cascMC.pdgCode() == PDG_t::kOmegaMinus && !isXi) { histos.fill(HIST("h2dGenOmegaMinus"), centrality, ptmc); histos.fill(HIST("h2dGenOmegaMinusVsNch"), nChEta1, ptmc); histos.fill(HIST("h2dGenOmegaMinusEta"), RecoDecay::eta(std::array{cascMC.pxMC(), cascMC.pyMC(), cascMC.pzMC()})); @@ -1506,7 +1537,7 @@ struct Derivedcascadeanalysis { histos.fill(HIST("h2dGenOmegaMinusVsNchVsOccupancy"), ptmc, nChEta1, occupancy); histos.fill(HIST("h2dGenOmegaMinusVsCentIR"), ptmc, centrality, intRate); } - if (cascMC.pdgCode() == -3334 && !isXi) { + if (cascMC.pdgCode() == PDG_t::kOmegaPlusBar && !isXi) { histos.fill(HIST("h2dGenOmegaPlus"), centrality, ptmc); histos.fill(HIST("h2dGenOmegaPlusVsNch"), nChEta1, ptmc); histos.fill(HIST("h2dGenOmegaPlusVsMultMCVsCentrality"), mcCollision.multMCNParticlesEta05(), centrality, ptmc); diff --git a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx index 544ed23807a..2c872c3500f 100644 --- a/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/derivedlambdakzeroanalysis.cxx @@ -83,6 +83,14 @@ using V0McCandidates = soa::Join(1) << static_cast(nbit))) #define BITCHECK(var, nbit) ((var) & (static_cast(1) << static_cast(nbit))) +enum CentEstimator { + kCentFT0C = 0, + kCentFT0M, + kCentFT0CVariant1, + kCentMFT, + kCentNGlobal +}; + struct derivedlambdakzeroanalysis { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -96,6 +104,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, 3:CentFT0CVariant1, 4:CentMFT, 5:CentNGlobal)"}; struct : ConfigurableGroup { Configurable requireSel8{"requireSel8", true, "require sel8 event selection"}; @@ -273,7 +282,7 @@ struct derivedlambdakzeroanalysis { 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 axisK0Mass{"axisK0Mass", {200, 0.4f, 0.6f}, ""}; ConfigurableAxis axisLambdaMass{"axisLambdaMass", {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 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)"}; @@ -971,6 +980,25 @@ struct derivedlambdakzeroanalysis { histos.print(); } + // ______________________________________________________ + // Return slicing output + 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(); + + return -1.f; + } + // ______________________________________________________ // Return slicing output template @@ -1073,34 +1101,34 @@ struct derivedlambdakzeroanalysis { // 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); // ITS only tag @@ -2016,7 +2044,7 @@ struct derivedlambdakzeroanalysis { void fillReconstructedEventProperties(TCollision const& collision, float& centrality, float& collisionOccupancy, double& interactionRate, int& gapSide, int& selGapSide) { if constexpr (requires { collision.centFT0C(); }) { // check if we are in Run 3 - centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + centrality = getCentralityRun3(collision); collisionOccupancy = eventSelections.useFT0CbasedOccupancy ? collision.ft0cOccupancyInTimeRange() : collision.trackOccupancyInTimeRange(); // Fetch interaction rate only if required (in order to limit ccdb calls) interactionRate = !irSource.value.empty() ? rateFetcher.fetch(ccdb.service, collision.timestamp(), collision.runNumber(), irSource) * 1.e-3 : -1; @@ -2098,7 +2126,7 @@ struct derivedlambdakzeroanalysis { if constexpr (run3) { // check if we are in Run 3 if (biggestNContribs < collision.multPVTotalContributors()) { biggestNContribs = collision.multPVTotalContributors(); - centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + centrality = getCentralityRun3(collision); } } else { // we are in Run 2: there should be only one collision in groupedCollisions centrality = eventSelections.useSPDTrackletsCent ? collision.centRun2SPDTracklets() : collision.centRun2V0M(); @@ -2337,7 +2365,7 @@ struct derivedlambdakzeroanalysis { if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { auto collision = collisions.iteratorAt(listBestCollisionIdx[mcCollision.globalIndex()]); if constexpr (requires { collision.centFT0C(); }) { // check if we are in Run 3 - centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + centrality = getCentralityRun3(collision); } else { // no, we are in Run 2 centrality = eventSelections.useSPDTrackletsCent ? collision.centRun2SPDTracklets() : collision.centRun2V0M(); } @@ -2402,7 +2430,7 @@ struct derivedlambdakzeroanalysis { if (listBestCollisionIdx[mcCollision.globalIndex()] > -1) { auto collision = collisions.iteratorAt(listBestCollisionIdx[mcCollision.globalIndex()]); if constexpr (requires { collision.centFT0C(); }) { // check if we are in Run 3 - centrality = doPPAnalysis ? collision.centFT0M() : collision.centFT0C(); + centrality = getCentralityRun3(collision); } else { // no, we are in Run 2 centrality = eventSelections.useSPDTrackletsCent ? collision.centRun2SPDTracklets() : collision.centRun2V0M(); } diff --git a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx index f9952efca40..95e0671ea26 100644 --- a/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx +++ b/PWGLF/Tasks/Strangeness/hStrangeCorrelation.cxx @@ -21,25 +21,28 @@ /// \author David Dobrigkeit Chinellato (david.dobrigkeit.chinellato@cern.ch) /// \author Zhongbao Yin (Zhong-Bao.Yin@cern.ch) -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "PWGLF/DataModel/LFHStrangeCorrelationTables.h" + +#include "Common/DataModel/Centrality.h" #include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + +#include "CCDB/BasicCCDBManager.h" +#include "DataFormatsParameters/GRPMagField.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisTask.h" #include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" #include "Framework/StaticFor.h" -#include "CCDB/BasicCCDBManager.h" +#include "Framework/runDataProcessing.h" + #include -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" +#include +#include using namespace o2; using namespace o2::constants::math; @@ -59,7 +62,7 @@ struct HStrangeCorrelation { HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // event filtering - Configurable zorroMask{"zorroMask", "", "zorro trigger class to select on (empty: none)"}; + Configurable zorroMask{"zorroMask", "", "zorro trigger class to select on (empty: none)"}; Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; @@ -89,6 +92,7 @@ struct HStrangeCorrelation { Configurable doAutocorrelationRejection{"doAutocorrelationRejection", true, "reject pairs where trigger Id is the same as daughter particle Id"}; Configurable doMixingQAandEventQA{"doMixingQAandEventQA", true, "if true, add EvnetQA and MixingQA hist to histos"}; Configurable doITSClustersQA{"doITSClustersQA", true, "if true, add ITSCluster hist to histos"}; + Configurable doDeltaPhiStarCheck{"doDeltaPhiStarCheck", false, "if true, create and fill delta phi star histograms"}; Configurable triggerBinToSelect{"triggerBinToSelect", 0, "trigger bin to select on if processSelectEventWithTrigger enabled"}; Configurable triggerParticleCharge{"triggerParticleCharge", 0, "For checks, if 0 all charged tracks, if -1 only neg., if 1 only positive"}; @@ -212,6 +216,7 @@ struct HStrangeCorrelation { TH2F* hEfficiencyOmegaMinus; TH2F* hEfficiencyOmegaPlus; TH2F* hEfficiencyHadron; + TH1F* hPurityHadron; using BinningType = ColumnBinningPolicy; using BinningTypePbPb = ColumnBinningPolicy; @@ -291,6 +296,7 @@ struct HStrangeCorrelation { hEfficiencyOmegaPlus = static_cast(listEfficiencies->FindObject("hEfficiencyOmegaPlus")); hEfficiencyHadron = static_cast(listEfficiencies->FindObject("hEfficiencyHadron")); hEfficiencyPion = static_cast(listEfficiencies->FindObject("hEfficiencyPion")); + hPurityHadron = static_cast(listEfficiencies->FindObject("hPurityHadron")); LOG(info) << "Efficiencies now loaded for " << mRunNumber; } @@ -511,7 +517,23 @@ struct HStrangeCorrelation { return false; return true; } - void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult) + double calculateAverageDeltaPhiStar(double* trigg, double* assoc, double B) + { + double dPhiStar = 0; + double dPhiStarMean = 0; + + double dPhi = assoc[0] - trigg[0]; + 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) { + dPhiStar = dPhi + std::asin(phaseProton * r) - std::asin(phaseTrack * r); + dPhiStarMean += (dPhiStar / 34); + } + + return dPhiStarMean; + } + void fillCorrelationsV0(aod::TriggerTracks const& triggers, aod::AssocV0s const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) { for (auto const& triggerTrack : triggers) { if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) @@ -532,6 +554,9 @@ struct HStrangeCorrelation { histos.fill(HIST("sameEvent/TriggerParticlesV0"), trigg.pt(), mult, weight); } + double triggSign = trigg.sign(); + double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + for (auto const& assocCandidate : assocs) { auto assoc = assocCandidate.v0Core_as(); @@ -585,9 +610,25 @@ struct HStrangeCorrelation { float etaWeight = 1; if (systCuts.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; - etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } + double phiProton = postrack.phi(); // in Case of K0, both are pions, but the one in proton tagged is the positive one + double phiPion = negtrack.phi(); + double etaProton = postrack.eta(); + double etaPion = negtrack.eta(); + double ptProton = postrack.pt(); + double ptPion = negtrack.pt(); + double signProton = postrack.sign(); + if (assocCandidate.compatible(2, systCuts.dEdxCompatibility)) { + phiProton = negtrack.phi(); + etaProton = negtrack.eta(); + ptProton = negtrack.pt(); + signProton = negtrack.sign(); + } + double assocForDeltaPhiStar[] = {phiProton, ptProton, signProton}; + double assocForDeltaPhiStarPion[] = {phiPion, ptPion, -1}; + static_for<0, 2>([&](auto i) { constexpr int Index = i.value; float efficiency = 1.0f; @@ -604,8 +645,24 @@ struct HStrangeCorrelation { float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; weight = weight * etaWeight; if (TESTBIT(doCorrelation, Index) && (!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) + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { histos.fill(HIST("sameEvent/LeftBg/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + 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); + } + } 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); + } + } + } + } if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) { histos.fill(HIST("sameEvent/Signal/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); if (std::abs(deltaphi) < 0.8 && doITSClustersQA) { @@ -616,9 +673,40 @@ struct HStrangeCorrelation { 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 (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); + } + } 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); + } + } + } } - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) { histos.fill(HIST("sameEvent/RightBg/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + 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); + } + } 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); + } + } + } + } if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) histos.fill(HIST("mixedEvent/LeftBg/") + HIST(kV0names[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) @@ -631,7 +719,7 @@ struct HStrangeCorrelation { } } - void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult) + void fillCorrelationsCascade(aod::TriggerTracks const& triggers, aod::AssocCascades const& assocs, bool mixing, float pvx, float pvy, float pvz, float mult, double bField) { for (auto const& triggerTrack : triggers) { if (doTriggPhysicalPrimary && !triggerTrack.mcPhysicalPrimary()) @@ -651,6 +739,9 @@ struct HStrangeCorrelation { float weight = (applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; histos.fill(HIST("sameEvent/TriggerParticlesCascade"), trigg.pt(), mult, weight); } + double triggSign = trigg.sign(); + double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; + for (auto const& assocCandidate : assocs) { auto assoc = assocCandidate.cascData(); @@ -687,7 +778,17 @@ struct HStrangeCorrelation { continue; } } - + double phiProton = postrack.phi(); + double etaProton = postrack.eta(); + double ptProton = postrack.pt(); + double signProton = postrack.sign(); + if (assoc.sign() > 0) { + phiProton = negtrack.phi(); + etaProton = negtrack.eta(); + ptProton = negtrack.pt(); + signProton = negtrack.sign(); + } + double assocForDeltaPhiStar[] = {phiProton, ptProton, signProton}; //---] track quality check [--- if (postrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || negtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated || bachtrack.tpcNClsCrossedRows() < systCuts.minTPCNCrossedRowsAssociated) continue; @@ -714,7 +815,7 @@ struct HStrangeCorrelation { float etaWeight = 1; if (systCuts.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; - etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } static_for<0, 3>([&](auto i) { @@ -732,12 +833,36 @@ struct HStrangeCorrelation { float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; weight = weight * etaWeight; if (TESTBIT(doCorrelation, Index + 3) && (!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) + if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < -massWindowConfigurations.minBgNSigma) { histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) + 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); + else + histos.fill(HIST("sameEvent/LeftBg/") + HIST(kCascadenames[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) { histos.fill(HIST("sameEvent/Signal/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); - if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && !mixing && +massWindowConfigurations.minBgNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxBgNSigma) + 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); + else + histos.fill(HIST("sameEvent/Signal/") + HIST(kCascadenames[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) { histos.fill(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); + 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); + else + histos.fill(HIST("sameEvent/RightBg/") + HIST(kCascadenames[Index]) + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - etaProton, -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) histos.fill(HIST("mixedEvent/LeftBg/") + HIST(kCascadenames[Index]), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight); if (assocCandidate.compatible(Index, systCuts.dEdxCompatibility) && (!doMCassociation || assocCandidate.mcTrue(Index)) && (!doAssocPhysicalPrimary || assocCandidate.mcPhysicalPrimary()) && mixing && -massWindowConfigurations.maxPeakNSigma < assocCandidate.invMassNSigma(Index) && assocCandidate.invMassNSigma(Index) < +massWindowConfigurations.maxPeakNSigma) @@ -750,7 +875,7 @@ struct HStrangeCorrelation { } } template - void fillCorrelationsHadron(TTriggers const& triggers, THadrons const& assocs, bool mixing, float pvz, float mult) + void fillCorrelationsHadron(TTriggers const& triggers, THadrons const& assocs, bool mixing, float pvz, float mult, double bField) { for (auto const& triggerTrack : triggers) { @@ -774,6 +899,8 @@ struct HStrangeCorrelation { else histos.fill(HIST("sameEvent/TriggerParticlesHadron"), trigg.pt(), mult, weight); } + double triggSign = trigg.sign(); + double triggForDeltaPhiStar[] = {trigg.phi(), trigg.pt(), triggSign}; for (auto const& assocTrack : assocs) { auto assoc = assocTrack.template track_as(); @@ -798,10 +925,13 @@ struct HStrangeCorrelation { float ptassoc = assoc.pt(); float pttrigger = trigg.pt(); + double assocSign = assoc.sign(); + double assocForDeltaPhiStar[] = {assoc.phi(), assoc.pt(), assocSign}; + float etaWeight = 1.; if (systCuts.doOnTheFlyFlattening) { float preWeight = 1 - std::abs(deltaeta) / 1.6; - etaWeight = preWeight != 0 ? 1.0f / preWeight : 0.0f; + etaWeight = preWeight != 0 ? 1.0f / preWeight : 1.0f; } // skip if basic ranges not met @@ -813,25 +943,38 @@ struct HStrangeCorrelation { continue; float efficiency = 1; + float purity = 1.0f; if (applyEfficiencyCorrection) { if constexpr (requires { assocTrack.nSigmaTPCPi(); }) { efficiency = hEfficiencyPion->Interpolate(ptassoc, assoc.eta()); } else { efficiency = hEfficiencyHadron->Interpolate(ptassoc, assoc.eta()); + purity = hPurityHadron->Interpolate(ptassoc); } } if (applyEfficiencyForTrigger) { efficiency = efficiency * hEfficiencyTrigger->Interpolate(pttrigger, trigg.eta()); + purity = purity * hPurityHadron->Interpolate(pttrigger); } if (efficiency == 0) { // check for zero efficiency, do not apply if the case efficiency = 1; } - float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? 1. / efficiency : 1.0f; - + float weight = (applyEfficiencyCorrection || applyEfficiencyForTrigger) ? purity / efficiency : 1.0f; + double deltaPhiStar = calculateAverageDeltaPhiStar(triggForDeltaPhiStar, assocForDeltaPhiStar, bField); if (!mixing) { if constexpr (requires { assocTrack.nSigmaTPCPi(); }) { histos.fill(HIST("sameEvent/Signal/Pion"), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight * etaWeight); + if (triggSign == assocSign && doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Pion") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), 0.5); + } else if (doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Pion") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), -0.5); + } } else { + if (triggSign == assocSign && doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Hadron") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), 0.5); + } else if (doDeltaPhiStarCheck) { + histos.fill(HIST("sameEvent/Signal/Hadron") + HIST("DeltaPhiStar"), deltaPhiStar, trigg.eta() - assoc.eta(), -0.5); + } histos.fill(HIST("sameEvent/Signal/Hadron"), deltaphi, deltaeta, ptassoc, pttrigger, pvz, mult, weight * etaWeight); } } else { @@ -860,6 +1003,7 @@ struct HStrangeCorrelation { hEfficiencyOmegaPlus = 0x0; hEfficiencyHadron = 0x0; + hPurityHadron = 0x0; // set bitmap for convenience doCorrelation = 0; @@ -1094,6 +1238,9 @@ struct HStrangeCorrelation { histos.add(fmt::format("h3d{}Spectrum", kParticlenames[i]).c_str(), fmt::format("h3d{}Spectrum", kParticlenames[i]).c_str(), kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add(fmt::format("h3d{}SpectrumY", kParticlenames[i]).c_str(), fmt::format("h3d{}SpectrumY", kParticlenames[i]).c_str(), kTH3F, {axisPtQA, axisMult, axisMassNSigma}); histos.add(fmt::format("sameEvent/Signal/{}", kParticlenames[i]).c_str(), "", kTHnF, {axisDeltaPhiNDim, axisDeltaEtaNDim, axisPtAssocNDim, axisPtTriggerNDim, axisVtxZNDim, axisMultNDim}); + if (doDeltaPhiStarCheck) { + 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) { hStrange = true; histos.add(fmt::format("h{}EtaVsPtVsPhiBg", kParticlenames[i]).c_str(), "", kTH3F, {axisPtQA, axisEta, axisPhi}); @@ -1298,6 +1445,20 @@ struct HStrangeCorrelation { return true; } + double getMagneticField(uint64_t timestamp) + { + static 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 0.1 * (grpo->getNominalL3Field()); // 1 T = 10 kG + } // if this process function is enabled, it will be such that only events with trigger particles within a given // trigger pt bin are taken for the entire processing. This allows for the calculation of e.g. efficiencies // within an event class that has a trigger (which may differ with respect to other cases, to be checked) @@ -1343,8 +1504,10 @@ struct HStrangeCorrelation { return; } + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); + if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } @@ -1390,13 +1553,15 @@ struct HStrangeCorrelation { if (!isValidAssocHadron(assoc)) continue; float efficiency = 1.0f; + float purity = 1.0f; if (applyEfficiencyCorrection) { efficiency = hEfficiencyHadron->Interpolate(assoc.pt(), assoc.eta()); + purity = hPurityHadron->Interpolate(assoc.pt()); } if (efficiency == 0) { // check for zero efficiency, do not apply if the case efficiency = 1; } - float weight = applyEfficiencyCorrection ? 1. / efficiency : 1.0f; + float weight = applyEfficiencyCorrection ? purity / efficiency : 1.0f; histos.fill(HIST("hAssocHadronsAllSelectedEtaVsPt"), assoc.pt(), assoc.eta(), collision.centFT0M()); histos.fill(HIST("hAssocPtResolution"), assoc.pt(), assocTrack.mcOriginalPt()); if (doAssocPhysicalPrimary && !assocTrack.mcPhysicalPrimary()) @@ -1408,7 +1573,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - hadron correlations - fillCorrelationsHadron(triggerTracks, assocHadrons, false, collision.posZ(), collision.centFT0M()); + fillCorrelationsHadron(triggerTracks, assocHadrons, false, collision.posZ(), collision.centFT0M(), bField); } void processSameEventHV0s(soa::Join::iterator const& collision, @@ -1438,9 +1603,9 @@ struct HStrangeCorrelation { histos.fill(HIST("EventQA/hMultFT0vsTPC"), cent, collision.multNTracksPVeta1()); } // Do basic QA - + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } TH2F* hEfficiencyV0[3]; @@ -1508,7 +1673,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - V0 correlations - fillCorrelationsV0(triggerTracks, associatedV0s, false, collision.posX(), collision.posY(), collision.posZ(), cent); + fillCorrelationsV0(triggerTracks, associatedV0s, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHCascades(soa::Join::iterator const& collision, @@ -1537,8 +1702,9 @@ struct HStrangeCorrelation { histos.fill(HIST("EventQA/hPvz"), collision.posZ()); } // Do basic QA + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } TH2F* hEfficiencyCascade[4]; @@ -1612,7 +1778,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posX(), collision.posY(), collision.posZ(), cent); + fillCorrelationsCascade(triggerTracks, associatedCascades, false, collision.posX(), collision.posY(), collision.posZ(), cent, bField); } void processSameEventHPions(soa::Join::iterator const& collision, soa::Join const& associatedPions, soa::Join const& triggerTracks, @@ -1623,9 +1789,10 @@ struct HStrangeCorrelation { if (triggerPresenceMap.size() > 0 && !TESTBIT(triggerPresenceMap[collision.globalIndex()], triggerBinToSelect)) { return; } + auto bc = collision.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision.bc_as(); initEfficiencyFromCCDB(bc); } @@ -1661,7 +1828,7 @@ struct HStrangeCorrelation { // ________________________________________________ // Do hadron - Pion correlations - fillCorrelationsHadron(triggerTracks, associatedPions, false, collision.posZ(), collision.centFT0M()); + fillCorrelationsHadron(triggerTracks, associatedPions, false, collision.posZ(), collision.centFT0M(), bField); } void processMixedEventHHadrons(soa::Join const& collisions, @@ -1669,9 +1836,10 @@ struct HStrangeCorrelation { TracksComplete const&, aod::BCsWithTimestamps const&) { for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1703,7 +1871,7 @@ struct HStrangeCorrelation { auto slicedAssocHadrons = assocHadrons.sliceBy(collisionSliceHadrons, collision2.globalIndex()); // ________________________________________________ // Do hadron - hadron correlations - fillCorrelationsHadron(slicedTriggerTracks, slicedAssocHadrons, true, collision1.posZ(), collision1.centFT0M()); + fillCorrelationsHadron(slicedTriggerTracks, slicedAssocHadrons, true, collision1.posZ(), collision1.centFT0M(), bField); } } @@ -1717,9 +1885,10 @@ struct HStrangeCorrelation { for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { double cent1 = doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); double cent2 = doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1751,7 +1920,7 @@ struct HStrangeCorrelation { auto slicedAssocV0s = associatedV0s.sliceBy(collisionSliceV0s, collision2.globalIndex()); // ________________________________________________ // Do hadron - V0 correlations - fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1); + fillCorrelationsV0(slicedTriggerTracks, slicedAssocV0s, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } } void processMixedEventHCascades(soa::Join const& collisions, @@ -1765,8 +1934,9 @@ struct HStrangeCorrelation { double cent1 = doPPAnalysis ? collision1.centFT0M() : collision1.centFT0C(); double cent2 = doPPAnalysis ? collision2.centFT0M() : collision2.centFT0C(); // ________________________________________________ + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1797,7 +1967,7 @@ struct HStrangeCorrelation { auto slicedAssocCascades = associatedCascades.sliceBy(collisionSliceCascades, collision2.globalIndex()); // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1); + fillCorrelationsCascade(slicedTriggerTracks, slicedAssocCascades, true, collision1.posX(), collision1.posY(), collision1.posZ(), cent1, bField); } } void processMixedEventHPions(soa::Join const& collisions, @@ -1805,9 +1975,10 @@ struct HStrangeCorrelation { TracksComplete const&, aod::BCsWithTimestamps const&) { for (auto const& [collision1, collision2] : soa::selfCombinations(colBinning, mixingParameter, -1, collisions, collisions)) { + auto bc = collision1.bc_as(); + auto bField = getMagneticField(bc.timestamp()); // ________________________________________________ if (applyEfficiencyCorrection) { - auto bc = collision1.bc_as(); initEfficiencyFromCCDB(bc); } // ________________________________________________ @@ -1839,7 +2010,7 @@ struct HStrangeCorrelation { auto slicedAssocPions = assocPions.sliceBy(collisionSliceHadrons, collision2.globalIndex()); // ________________________________________________ // Do hadron - cascade correlations - fillCorrelationsHadron(slicedTriggerTracks, slicedAssocPions, true, collision1.posZ(), collision1.centFT0M()); + fillCorrelationsHadron(slicedTriggerTracks, slicedAssocPions, true, collision1.posZ(), collision1.centFT0M(), bField); } } diff --git a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx index 3acfbad4d10..cca1bdf193e 100644 --- a/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx +++ b/PWGLF/Tasks/Strangeness/lambdaJetpolarization.cxx @@ -29,6 +29,9 @@ #include #include "TProfile2D.h" #include "PWGLF/DataModel/lambdaJetpolarization.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include "Math/GenVector/Boost.h" #include #include @@ -351,6 +354,8 @@ struct LfMyV0s { } double massPr = o2::constants::physics::MassProton; double massLambda = o2::constants::physics::MassLambda; + double massPi = o2::constants::physics::MassPionCharged; + ROOT::Math::PxPyPzMVector ProtonVec, PionVec, LambdaVec, ProtonBoostedVec, LambdaBoostedVec; TMatrixD LorentzTransInV0frame(double ELambda, double Lambdapx, double Lambdapy, double Lambdapz) { @@ -1233,32 +1238,20 @@ struct LfMyV0s { if (passedLambdaSelection(v0, pos, neg) && ctauLambda < CtauLambda && ifpasslambda) { V0NumbersPerEventsel++; registryLongitudinalPolarization.fill(HIST("hMassVsPtLambda"), v0.pt(), v0.mLambda()); - double PLambda = sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); - double ELambda = sqrt(v0.mLambda() * v0.mLambda() + PLambda * PLambda); - double protonE = sqrt(massPr * massPr + pos.px() * pos.px() + pos.py() * pos.py() + pos.pz() * pos.pz()); - TMatrixD pLabV0(4, 1); - pLabV0(0, 0) = ELambda; - pLabV0(1, 0) = v0.px(); - pLabV0(2, 0) = v0.py(); - pLabV0(3, 0) = v0.pz(); - TMatrixD pLabproton(4, 1); - pLabproton(0, 0) = protonE; - pLabproton(1, 0) = pos.px(); - pLabproton(2, 0) = pos.py(); - pLabproton(3, 0) = pos.pz(); + ProtonVec = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPr); + PionVec = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); + LambdaVec = ProtonVec + PionVec; + LambdaVec.SetM(massLambda); + ROOT::Math::Boost boost{LambdaVec.BoostToCM()}; + ProtonBoostedVec = boost(ProtonVec); + LambdaBoostedVec = boost(LambdaVec); - TMatrixD V0InV0(4, 1); - V0InV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabV0; - registryLongitudinalPolarization.fill(HIST("V0pxInRest_frame"), V0InV0(1, 0)); - registryLongitudinalPolarization.fill(HIST("V0pyInRest_frame"), V0InV0(2, 0)); - registryLongitudinalPolarization.fill(HIST("V0pzInRest_frame"), V0InV0(3, 0)); + registryLongitudinalPolarization.fill(HIST("V0pxInRest_frame"), LambdaBoostedVec.Px()); + registryLongitudinalPolarization.fill(HIST("V0pyInRest_frame"), LambdaBoostedVec.Py()); + registryLongitudinalPolarization.fill(HIST("V0pzInRest_frame"), LambdaBoostedVec.Pz()); - TMatrixD protonInV0(4, 1); - protonInV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabproton; - double protonPInV0 = sqrt(protonInV0(1, 0) * protonInV0(1, 0) + protonInV0(2, 0) * protonInV0(2, 0) + protonInV0(3, 0) * protonInV0(3, 0)); - - double protonCosThetainV0 = protonInV0(3, 0) / protonPInV0; + double protonCosThetainV0 = ProtonBoostedVec.Pz() / ProtonBoostedVec.P(); registryLongitudinalPolarization.fill(HIST("hprotoncosthetainV0"), protonCosThetainV0); registryLongitudinalPolarization.fill(HIST("hprotoncosSquarethetainV0"), protonCosThetainV0 * protonCosThetainV0); @@ -1272,21 +1265,15 @@ struct LfMyV0s { if (passedAntiLambdaSelection(v0, pos, neg) && ctauAntiLambda < CtauLambda && ifpasslambda) { registryLongitudinalPolarization.fill(HIST("hMassVsPtAntiLambda"), v0.pt(), v0.mAntiLambda()); - double PLambda = sqrt(v0.px() * v0.px() + v0.py() * v0.py() + v0.pz() * v0.pz()); - double ELambda = sqrt(v0.mAntiLambda() * v0.mAntiLambda() + PLambda * PLambda); - double protonE = sqrt(massPr * massPr + neg.px() * neg.px() + neg.py() * neg.py() + neg.pz() * neg.pz()); - - TMatrixD pLabproton(4, 1); - pLabproton(0, 0) = protonE; - pLabproton(1, 0) = neg.px(); - pLabproton(2, 0) = neg.py(); - pLabproton(3, 0) = neg.pz(); - - TMatrixD protonInV0(4, 1); - protonInV0 = LorentzTransInV0frame(ELambda, v0.px(), v0.py(), v0.pz()) * pLabproton; - double protonPInV0 = sqrt(protonInV0(1, 0) * protonInV0(1, 0) + protonInV0(2, 0) * protonInV0(2, 0) + protonInV0(3, 0) * protonInV0(3, 0)); + ProtonVec = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPr); + PionVec = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); + LambdaVec = ProtonVec + PionVec; + LambdaVec.SetM(massLambda); + ROOT::Math::Boost boost{LambdaVec.BoostToCM()}; + ProtonBoostedVec = boost(ProtonVec); + LambdaBoostedVec = boost(LambdaVec); - double protonCosThetainV0 = protonInV0(3, 0) / protonPInV0; + double protonCosThetainV0 = ProtonBoostedVec.Pz() / ProtonBoostedVec.P(); registryLongitudinalPolarization.fill(HIST("hantiprotoncosthetainV0"), protonCosThetainV0); registryLongitudinalPolarization.fill(HIST("hantiprotoncosSquarethetainV0"), protonCosThetainV0 * protonCosThetainV0); diff --git a/PWGLF/Tasks/Strangeness/lambdaTwoPartPolarization.cxx b/PWGLF/Tasks/Strangeness/lambdaTwoPartPolarization.cxx new file mode 100644 index 00000000000..43e10b719b8 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/lambdaTwoPartPolarization.cxx @@ -0,0 +1,412 @@ +// 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 Junlee Kim (jikim1290@gmail.com) + +#include "PWGLF/DataModel/LFStrangenessTables.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/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.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/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 "TLorentzVector.h" +#include "TRandom3.h" +#include "TVector3.h" +#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; + +struct lambdaTwoPartPolarization { + using EventCandidates = soa::Join; + using TrackCandidates = soa::Join; + using V0TrackCandidate = aod::V0Datas; + + HistogramRegistry histos{ + "histos", + {}, + OutputObjHandlingPolicy::AnalysisObject}; + + 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; + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + + Configurable cfgCentSel{"cfgCentSel", 100., "Centrality selection"}; + Configurable cfgCentEst{"cfgCentEst", 2, "Centrality estimator, 1: FT0C, 2: FT0M"}; + + Configurable cfgEvtSel{"cfgEvtSel", true, "event selection flag"}; + Configurable cfgPVSel{"cfgPVSel", true, "Additional PV selection flag for syst"}; + Configurable cfgPV{"cfgPV", 10.0, "Additional PV selection range for syst"}; + Configurable cfgAddEvtSelPileup{"cfgAddEvtSelPileup", true, "flag for additional pileup selection"}; + 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 cfgv0radiusMin{"cfgv0radiusMin", 1.2, "minimum decay radius"}; + Configurable cfgDCAPrToPVMin{"cfgDCAPrToPVMin", 0.05, "minimum DCA to PV for proton track"}; + Configurable cfgDCAPiToPVMin{"cfgDCAPiToPVMin", 0.1, "minimum DCA to PV for pion track"}; + Configurable cfgv0CosPA{"cfgv0CosPA", 0.99, "minimum v0 cosine"}; + Configurable cfgDCAV0Dau{"cfgDCAV0Dau", 1.0, "maximum DCA between daughters"}; + + Configurable cfgV0PtMin{"cfgV0PtMin", 0, "minimum pT for lambda"}; + Configurable cfgV0EtaMin{"cfgV0EtaMin", -0.5, "maximum rapidity"}; + Configurable cfgV0EtaMax{"cfgV0EtaMax", 0.5, "maximum rapidity"}; + Configurable cfgV0LifeTime{"cfgV0LifeTime", 30., "maximum lambda lifetime"}; + + Configurable cfgQAv0{"cfgQAv0", false, "QA plot"}; + + Configurable cfgDaughTPCnclsMin{"cfgDaughTPCnclsMin", 50, "minimum fired crossed rows"}; + Configurable cfgDaughPIDCutsTPCPr{"cfgDaughPIDCutsTPCPr", 5, "proton nsigma for TPC"}; + Configurable cfgDaughPIDCutsTPCPi{"cfgDaughPIDCutsTPCPi", 5, "pion nsigma for TPC"}; + Configurable cfgDaughEtaMin{"cfgDaughEtaMin", -0.8, "minimum daughter eta"}; + Configurable cfgDaughEtaMax{"cfgDaughEtaMax", 0.8, "maximum daughter eta"}; + Configurable cfgDaughPrPt{"cfgDaughPrPt", 0.5, "minimum daughter proton pt"}; + Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.2, "minimum daughter pion pt"}; + + Configurable cfgHypMassWindow{"cfgHypMassWindow", 0.005, "single lambda mass selection"}; + + Configurable cfgEffCor{"cfgEffCor", false, "flag to apply efficiency correction"}; + Configurable cfgEffCorPath{"cfgEffCorPath", "", "path for pseudo efficiency correction"}; + + Configurable cfgAccCor{"cfgAccCor", false, "flag to apply acceptance correction"}; + Configurable cfgAccCorPath{"cfgAccCorPath", "", "path for pseudo acceptance correction"}; + + Configurable cfgRotBkg{"cfgRotBkg", true, "flag to construct rotational backgrounds"}; + Configurable cfgNRotBkg{"cfgNRotBkg", 10, "the number of rotational backgrounds"}; + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 10, "Number of mixed events per event"}; + + 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"}; + ConfigurableAxis centAxis{"centAxis", {VARIABLE_WIDTH, 0, 10, 20, 30, 40, 50, 60, 70, 100}, "Centrality interval"}; + ConfigurableAxis RapAxis{"RapAxis", {10, -0.5, 0.5}, "Rapidity axis"}; + ConfigurableAxis detaAxis{"dyAxis", {20, -1, 1}, "relative rapidity axis"}; + ConfigurableAxis dphiAxis{"dphiAxis", {20, -constants::math::PI * 0.5, constants::math::PI * 1.5}, "relative azimuth axis"}; + + ConfigurableAxis cosSigAxis{"cosSigAxis", {110, -1.05, 1.05}, "Signal cosine axis"}; + ConfigurableAxis cosAccAxis{"cosAccAxis", {110, -7.05, 7.05}, "Accepatance cosine axis"}; + + TF1* fMultPVCutLow = nullptr; + TF1* fMultPVCutHigh = nullptr; + + float centrality; + float dphi; + float weight; + + TProfile2D* EffMap = nullptr; + TProfile2D* AccMap = nullptr; + + void init(o2::framework::InitContext&) + { + AxisSpec centQaAxis = {100, 0.0, 100.0}; + AxisSpec PVzQaAxis = {300, -15.0, 15.0}; + AxisSpec epAxis = {6, 0.0, 2.0 * constants::math::PI}; + + AxisSpec pidAxis = {100, -10, 10}; + + AxisSpec shiftAxis = {10, 0, 10, "shift"}; + AxisSpec basisAxis = {20, 0, 20, "basis"}; + + if (cfgQAv0) { + histos.add("QA/CentDist", "", {HistType::kTH1F, {centQaAxis}}); + histos.add("QA/PVzDist", "", {HistType::kTH1F, {PVzQaAxis}}); + + histos.add("QA/nsigma_tpc_pt_ppr", "", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA/nsigma_tpc_pt_ppi", "", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA/nsigma_tpc_pt_mpr", "", {HistType::kTH2F, {ptAxis, pidAxis}}); + histos.add("QA/nsigma_tpc_pt_mpi", "", {HistType::kTH2F, {ptAxis, pidAxis}}); + } + + histos.add("Ana/Signal", "", {HistType::kTHnSparseF, {ptAxis, ptAxis, detaAxis, dphiAxis, centAxis, cosSigAxis}}); + histos.add("Ana/Acceptance", "", {HistType::kTHnSparseF, {ptAxis, centAxis, RapAxis, cosAccAxis}}); + + fMultPVCutLow = new TF1("fMultPVCutLow", "[0]+[1]*x+[2]*x*x+[3]*x*x*x - 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + fMultPVCutLow->SetParameters(2834.66, -87.0127, 0.915126, -0.00330136, 332.513, -12.3476, 0.251663, -0.00272819, 1.12242e-05); + fMultPVCutHigh = new TF1("fMultPVCutHigh", "[0]+[1]*x+[2]*x*x+[3]*x*x*x + 2.5*([4]+[5]*x+[6]*x*x+[7]*x*x*x+[8]*x*x*x*x)", 0, 100); + fMultPVCutHigh->SetParameters(2834.66, -87.0127, 0.915126, -0.00330136, 332.513, -12.3476, 0.251663, -0.00272819, 1.12242e-05); + + 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()); + } + + double massLambda = o2::constants::physics::MassLambda; + double massPr = o2::constants::physics::MassProton; + double massPi = o2::constants::physics::MassPionCharged; + + ROOT::Math::PxPyPzMVector ProtonVec1, PionVec1, LambdaVec1, ProtonBoostedVec1, PionBoostedVec1; + ROOT::Math::PxPyPzMVector ProtonVec2, PionVec2, LambdaVec2, ProtonBoostedVec2, PionBoostedVec2; + int V01Tag; + int V02Tag; + double costhetastar1; + double costhetastar2; + + template + bool eventSelected(TCollision collision) + { + if (!collision.sel8()) { + return 0; + } + if (cfgCentSel < centrality) { + return 0; + } + if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + return 0; + } + if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + return 0; + } + if (cfgPVSel && std::abs(collision.posZ()) > cfgPV) { + return 0; + } + if (cfgAddEvtSelPileup && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return 0; + } + if (collision.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision.trackOccupancyInTimeRange() < cfgMinOccupancy) { + return 0; + } + + return 1; + } // event selection + + template + bool SelectionV0(TCollision const& collision, V0 const& candidate, int LambdaTag) + { + if (candidate.v0radius() < cfgv0radiusMin) + return false; + if (LambdaTag) { + if (std::abs(candidate.dcapostopv()) < cfgDCAPrToPVMin) + return false; + if (std::abs(candidate.dcanegtopv()) < cfgDCAPiToPVMin) + return false; + } else if (!LambdaTag) { + if (std::abs(candidate.dcapostopv()) < cfgDCAPiToPVMin) + return false; + if (std::abs(candidate.dcanegtopv()) < cfgDCAPrToPVMin) + return false; + } + if (candidate.v0cosPA() < cfgv0CosPA) + return false; + if (std::abs(candidate.dcaV0daughters()) > cfgDCAV0Dau) + return false; + if (candidate.pt() < cfgV0PtMin) + return false; + if (candidate.yLambda() < cfgV0EtaMin) + return false; + if (candidate.yLambda() > cfgV0EtaMax) + return false; + if (candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda > cfgV0LifeTime) + return false; + + return true; + } + + template + bool isSelectedV0Daughter(T const& track, int pid) // pid 0: proton, pid 1: pion + { + if (track.tpcNClsFound() < cfgDaughTPCnclsMin) + return false; + if (pid == 0 && std::abs(track.tpcNSigmaPr()) > cfgDaughPIDCutsTPCPr) + return false; + if (pid == 1 && std::abs(track.tpcNSigmaPi()) > cfgDaughPIDCutsTPCPi) + return false; + if (track.eta() > cfgDaughEtaMax) + return false; + if (track.eta() < cfgDaughEtaMin) + return false; + if (pid == 0 && track.pt() < cfgDaughPrPt) + return false; + if (pid == 1 && track.pt() < cfgDaughPiPt) + return false; + + return true; + } + + template + void FillHistograms(C1 const& c1, C2 const& c2, V01 const& V01s, V02 const& V02s) + { + for (auto& v01 : V01s) { + auto postrack_v01 = v01.template posTrack_as(); + auto negtrack_v01 = v01.template negTrack_as(); + + int LambdaTag = 0; + int aLambdaTag = 0; + + if (isSelectedV0Daughter(postrack_v01, 0) && isSelectedV0Daughter(negtrack_v01, 1)) { + LambdaTag = 1; + } + if (isSelectedV0Daughter(negtrack_v01, 0) && isSelectedV0Daughter(postrack_v01, 1)) { + aLambdaTag = 1; + } + + if (LambdaTag == aLambdaTag) + continue; + + if (!SelectionV0(c1, v01, LambdaTag)) + continue; + + if (LambdaTag) { + ProtonVec1 = ROOT::Math::PxPyPzMVector(v01.pxpos(), v01.pypos(), v01.pzpos(), massPr); + PionVec1 = ROOT::Math::PxPyPzMVector(v01.pxneg(), v01.pyneg(), v01.pzneg(), massPi); + V01Tag = 0; + } + if (aLambdaTag) { + ProtonVec1 = ROOT::Math::PxPyPzMVector(v01.pxneg(), v01.pyneg(), v01.pzneg(), massPr); + PionVec1 = ROOT::Math::PxPyPzMVector(v01.pxpos(), v01.pypos(), v01.pzpos(), massPi); + V01Tag = 1; + } + LambdaVec1 = ProtonVec1 + PionVec1; + LambdaVec1.SetM(massLambda); + + ROOT::Math::Boost boost1{LambdaVec1.BoostToCM()}; + ProtonBoostedVec1 = boost1(ProtonVec1); + + costhetastar1 = ProtonBoostedVec1.Pz() / ProtonBoostedVec1.P(); + + histos.fill(HIST("Ana/Acceptance"), v01.pt(), centrality, v01.yLambda(), costhetastar1 * costhetastar1); + + for (auto& v02 : V02s) { + if (v01.v0Id() <= v02.v0Id() && doprocessDataSame) + continue; + auto postrack_v02 = v02.template posTrack_as(); + auto negtrack_v02 = v02.template negTrack_as(); + + LambdaTag = 0; + aLambdaTag = 0; + + if (isSelectedV0Daughter(postrack_v02, 0) && isSelectedV0Daughter(negtrack_v02, 1)) { + LambdaTag = 1; + } + if (isSelectedV0Daughter(negtrack_v02, 0) && isSelectedV0Daughter(postrack_v02, 1)) { + aLambdaTag = 1; + } + + if (LambdaTag == aLambdaTag) + continue; + + if (!SelectionV0(c2, v02, LambdaTag)) + continue; + + if (doprocessDataSame) { + if (postrack_v01.globalIndex() == postrack_v02.globalIndex() || postrack_v01.globalIndex() == negtrack_v02.globalIndex() || negtrack_v01.globalIndex() == postrack_v02.globalIndex() || negtrack_v01.globalIndex() == negtrack_v02.globalIndex()) + continue; // no shared decay products + } + + if (LambdaTag) { + ProtonVec2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), massPr); + PionVec2 = ROOT::Math::PxPyPzMVector(v02.pxneg(), v02.pyneg(), v02.pzneg(), massPi); + V02Tag = 0; + } + if (aLambdaTag) { + ProtonVec2 = ROOT::Math::PxPyPzMVector(v02.pxneg(), v02.pyneg(), v02.pzneg(), massPr); + PionVec2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), massPi); + V02Tag = 1; + } + LambdaVec2 = ProtonVec2 + PionVec2; + LambdaVec2.SetM(massLambda); + + ROOT::Math::Boost boost2{LambdaVec2.BoostToCM()}; + ProtonBoostedVec2 = boost2(ProtonVec2); + + costhetastar2 = ProtonBoostedVec2.Pz() / ProtonBoostedVec2.P(); + + weight = 1.0; + weight *= cfgEffCor ? 1.0 / EffMap->GetBinContent(EffMap->GetXaxis()->FindBin(v01.pt()), EffMap->GetYaxis()->FindBin(centrality)) : 1.; + weight *= cfgAccCor ? 1.0 / AccMap->GetBinContent(AccMap->GetXaxis()->FindBin(v01.pt()), AccMap->GetYaxis()->FindBin(v01.yLambda())) : 1.; + weight *= cfgEffCor ? 1.0 / EffMap->GetBinContent(EffMap->GetXaxis()->FindBin(v02.pt()), EffMap->GetYaxis()->FindBin(centrality)) : 1.; + weight *= cfgAccCor ? 1.0 / AccMap->GetBinContent(AccMap->GetXaxis()->FindBin(v02.pt()), AccMap->GetYaxis()->FindBin(v02.yLambda())) : 1.; + + if (V01Tag != V02Tag) { + weight *= -1.0; + } + + dphi = TVector2::Phi_0_2pi(v01.phi() - v02.phi()); + if (dphi > constants::math::PI * 1.5) { + dphi -= constants::math::PI * 2.0; + } + + histos.fill(HIST("Ana/Signal"), v01.pt(), v02.pt(), v01.yLambda() - v02.yLambda(), dphi, centrality, costhetastar1 * costhetastar2 * weight); + } + } + } + + void processDataSame(EventCandidates::iterator const& collision, + TrackCandidates const& /*tracks*/, aod::V0Datas const& V0s, + aod::BCsWithTimestamps const&) + { + if (cfgCentEst == 1) { + centrality = collision.centFT0C(); + } else if (cfgCentEst == 2) { + centrality = collision.centFT0M(); + } + if (!eventSelected(collision) && cfgEvtSel) { + return; + } + + histos.fill(HIST("QA/CentDist"), centrality, 1.0); + histos.fill(HIST("QA/PVzDist"), collision.posZ(), 1.0); + + auto bc = collision.bc_as(); + if (cfgEffCor) { + EffMap = ccdb->getForTimeStamp(cfgEffCorPath.value, bc.timestamp()); + } + if (cfgAccCor) { + AccMap = ccdb->getForTimeStamp(cfgAccCorPath.value, bc.timestamp()); + } + + FillHistograms(collision, collision, V0s, V0s); + } + PROCESS_SWITCH(lambdaTwoPartPolarization, processDataSame, "Process Event for same data", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc, TaskName{"lf-lambdaTwoPartPolarization"})}; +} diff --git a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx index 270415766a0..105fc94bbc7 100644 --- a/PWGLF/Tasks/Strangeness/lambdapolsp.cxx +++ b/PWGLF/Tasks/Strangeness/lambdapolsp.cxx @@ -11,53 +11,61 @@ // Lambda polarisation task // prottay.das@cern.ch -#include -#include -#include +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/DataModel/SPCalibrationTables.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/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.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/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 +#include +#include +#include #include #include #include #include -#include -#include -#include #include -#include + +#include #include +#include #include -#include -#include "Common/Core/RecoDecay.h" - -#include "TRandom3.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" -#include "TF1.h" - -#include "PWGLF/DataModel/SPCalibrationTables.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/ASoAHelpers.h" -#include "ReconstructionDataFormats/Track.h" -#include "DataFormatsParameters/GRPObject.h" -#include "DataFormatsParameters/GRPMagField.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "Common/DataModel/FT0Corrected.h" +#include +#include +#include +#include // <<< CHANGED: for dedup sets +#include +#include +#include // <<< CHANGED: for seenMap +#include +#include using namespace o2; using namespace o2::framework; @@ -70,10 +78,16 @@ using v0Candidates = soa::Join; struct lambdapolsp { + 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; + int mRunNumber; Service ccdb; Service pdg; - + o2::ccdb::CcdbApi ccdbApi; + TH1D* hwgtAL; // fill output Configurable additionalEvSel{"additionalEvSel", false, "additionalEvSel"}; Configurable additionalEvSel2{"additionalEvSel2", false, "additionalEvSel2"}; @@ -82,14 +96,19 @@ struct lambdapolsp { Configurable globalpt{"globalpt", true, "select tracks based on pt global vs tpc"}; Configurable cqvas{"cqvas", false, "change q vectors after shift correction"}; Configurable useprofile{"useprofile", 3, "flag to select profile vs Sparse"}; - Configurable QxyNbins{"QxyNbins", 100, "Number of bins in QxQy histograms"}; - Configurable lbinQxy{"lbinQxy", -5.0, "lower bin value in QxQy histograms"}; - Configurable hbinQxy{"hbinQxy", 5.0, "higher bin value in QxQy histograms"}; Configurable cfgMaxOccupancy{"cfgMaxOccupancy", 1000, "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 sys{"sys", 1, "flag to select systematic source"}; Configurable dosystematic{"dosystematic", false, "flag to perform systematic study"}; Configurable needetaaxis{"needetaaxis", false, "flag to use last axis"}; + struct : ConfigurableGroup { + Configurable doRandomPsi{"doRandomPsi", true, "randomize psi"}; + Configurable doRandomPsiAC{"doRandomPsiAC", true, "randomize psiAC"}; + Configurable doRandomPhi{"doRandomPhi", true, "randomize phi"}; + Configurable etaMix{"etaMix", 0.1, "eta difference in mixing"}; + Configurable ptMix{"ptMix", 0.1, "pt difference in mixing"}; + Configurable phiMix{"phiMix", 0.1, "phi difference in mixing"}; + } randGrp; // events Configurable cfgCutVertex{"cfgCutVertex", 10.0f, "Accepted z-vertex range"}; Configurable cfgCutCentralityMax{"cfgCutCentralityMax", 50.0f, "Accepted maximum Centrality"}; @@ -115,42 +134,51 @@ struct lambdapolsp { Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 20, "Maximum V0 life time"}; + Configurable analyzeLambda{"analyzeLambda", true, "flag for lambda analysis"}; + Configurable analyzeK0s{"analyzeK0s", false, "flag for K0s analysis"}; + Configurable qtArmenterosMinForK0{"qtArmenterosMinForK0", 0.2, "Armenterous cut for K0s"}; // config for V0 daughters Configurable ConfDaughEta{"ConfDaughEta", 0.8f, "V0 Daugh sel: max eta"}; Configurable cfgDaughPrPt{"cfgDaughPrPt", 0.4, "minimum daughter proton pt"}; Configurable cfgDaughPiPt{"cfgDaughPiPt", 0.2, "minimum daughter pion pt"}; + Configurable rcrfc{"rcrfc", 0.8f, "Ratio of CR to FC"}; Configurable ConfDaughTPCnclsMin{"ConfDaughTPCnclsMin", 50.f, "V0 Daugh sel: Min. nCls TPC"}; Configurable ConfDaughPIDCuts{"ConfDaughPIDCuts", 3, "PID selections for Lambda daughters"}; Configurable usesubdet{"usesubdet", false, "use subdet"}; Configurable useAccCorr{"useAccCorr", false, "use acceptance correction"}; + Configurable useyldwgt{"useyldwgt", false, "use yield weight"}; 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 CentNbins{"CentNbins", 16, "Number of bins in cent histograms"}; - Configurable lbinCent{"lbinCent", 0.0, "lower bin value in cent histograms"}; - Configurable hbinCent{"hbinCent", 80.0, "higher bin value in cent histograms"}; - Configurable SANbins{"SANbins", 20, "Number of bins in costhetastar"}; - Configurable lbinSA{"lbinSA", -1.0, "lower bin value in costhetastar histograms"}; - Configurable hbinSA{"hbinSA", 1.0, "higher bin value in costhetastar histograms"}; - Configurable PolNbins{"PolNbins", 20, "Number of bins in polarisation"}; - Configurable lbinPol{"lbinPol", -1.0, "lower bin value in #phi-#psi histograms"}; - Configurable hbinPol{"hbinPol", 1.0, "higher bin value in #phi-#psi histograms"}; - Configurable IMNbins{"IMNbins", 100, "Number of bins in invariant mass"}; - Configurable lbinIM{"lbinIM", 1.0, "lower bin value in IM histograms"}; - Configurable hbinIM{"hbinIM", 1.2, "higher bin value in IM histograms"}; - Configurable resNbins{"resNbins", 50, "Number of bins in reso"}; - Configurable lbinres{"lbinres", 0.0, "lower bin value in reso histograms"}; - Configurable hbinres{"hbinres", 10.0, "higher bin value in reso histograms"}; - Configurable spNbins{"spNbins", 2000, "Number of bins in sp"}; - Configurable lbinsp{"lbinsp", -1.0, "lower bin value in sp histograms"}; - Configurable hbinsp{"hbinsp", 1.0, "higher bin value in sp histograms"}; - + struct : ConfigurableGroup { + Configurable QxyNbins{"QxyNbins", 100, "Number of bins in QxQy histograms"}; + Configurable lbinQxy{"lbinQxy", -5.0, "lower bin value in QxQy histograms"}; + Configurable hbinQxy{"hbinQxy", 5.0, "higher bin value in QxQy histograms"}; + Configurable PolNbins{"PolNbins", 20, "Number of bins in polarisation"}; + Configurable lbinPol{"lbinPol", -1.0, "lower bin value in #phi-#psi histograms"}; + Configurable hbinPol{"hbinPol", 1.0, "higher bin value in #phi-#psi histograms"}; + Configurable IMNbins{"IMNbins", 100, "Number of bins in invariant mass"}; + Configurable lbinIM{"lbinIM", 1.0, "lower bin value in IM histograms"}; + Configurable hbinIM{"hbinIM", 1.2, "higher bin value in IM histograms"}; + Configurable resNbins{"resNbins", 50, "Number of bins in reso"}; + Configurable lbinres{"lbinres", 0.0, "lower bin value in reso histograms"}; + Configurable hbinres{"hbinres", 10.0, "higher bin value in reso histograms"}; + Configurable spNbins{"spNbins", 2000, "Number of bins in sp"}; + Configurable lbinsp{"lbinsp", -1.0, "lower bin value in sp histograms"}; + Configurable hbinsp{"hbinsp", 1.0, "higher bin value in sp histograms"}; + // Configurable CentNbins{"CentNbins", 16, "Number of bins in cent histograms"}; + // Configurable lbinCent{"lbinCent", 0.0, "lower bin value in cent histograms"}; + // Configurable hbinCent{"hbinCent", 80.0, "higher bin value in cent histograms"}; + } binGrp; + /* ConfigurableAxis configcentAxis{"configcentAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Cent V0M"}; ConfigurableAxis configthnAxispT{"configthnAxisPt", {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}, "#it{p}_{T} (GeV/#it{c})"}; ConfigurableAxis configetaAxis{"configetaAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "Eta"}; 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"}; + */ // 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 requireRCTFlagChecker{"requireRCTFlagChecker", true, "Check event quality in run condition table"}; @@ -158,6 +186,18 @@ struct lambdapolsp { Configurable cfgEvtRCTFlagCheckerZDCCheck{"cfgEvtRCTFlagCheckerZDCCheck", true, "Evt sel: RCT flag checker ZDC check"}; Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", false, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; } rctCut; + struct : ConfigurableGroup { + ConfigurableAxis configcentAxis{"configcentAxis", {VARIABLE_WIDTH, 0.0, 10.0, 40.0, 80.0}, "Cent V0M"}; + ConfigurableAxis configthnAxispT{"configthnAxisPt", {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}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis configetaAxis{"configetaAxis", {VARIABLE_WIDTH, -0.8, -0.4, -0.2, 0, 0.2, 0.4, 0.8}, "Eta"}; + 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; RCTFlagsChecker rctChecker; @@ -169,118 +209,117 @@ struct lambdapolsp { rctChecker.init(rctCut.cfgEvtRCTFlagCheckerLabel, rctCut.cfgEvtRCTFlagCheckerZDCCheck, rctCut.cfgEvtRCTFlagCheckerLimitAcceptAsBad); - AxisSpec thnAxisres{resNbins, lbinres, hbinres, "Reso"}; - AxisSpec thnAxisInvMass{IMNbins, lbinIM, hbinIM, "#it{M} (GeV/#it{c}^{2})"}; - AxisSpec thnAxisCosThetaStar{SANbins, lbinSA, hbinSA, "SA"}; - AxisSpec centAxis = {CentNbins, lbinCent, hbinCent, "V0M (%)"}; - AxisSpec spAxis = {spNbins, lbinsp, hbinsp, "Sp"}; - AxisSpec qxZDCAxis = {QxyNbins, lbinQxy, hbinQxy, "Qx"}; + AxisSpec thnAxisres{binGrp.resNbins, binGrp.lbinres, binGrp.hbinres, "Reso"}; + AxisSpec thnAxisInvMass{binGrp.IMNbins, binGrp.lbinIM, binGrp.hbinIM, "#it{M} (GeV/#it{c}^{2})"}; + AxisSpec spAxis = {binGrp.spNbins, binGrp.lbinsp, binGrp.hbinsp, "Sp"}; + // AxisSpec qxZDCAxis = {binGrp.QxyNbins, binGrp.lbinQxy, binGrp.hbinQxy, "Qx"}; + // AxisSpec centAxis = {CentNbins, lbinCent, hbinCent, "V0M (%)"}; - std::vector runaxes = {thnAxisInvMass, configthnAxispT, configthnAxisPol, configcentAxis}; + std::vector runaxes = {thnAxisInvMass, axisGrp.configthnAxispT, axisGrp.configthnAxisPol, axisGrp.configcentAxis}; if (needetaaxis) - runaxes.insert(runaxes.end(), {configbinAxis}); + runaxes.insert(runaxes.end(), {axisGrp.configbinAxis}); if (checkwithpub) { if (useprofile == 2) { - histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpv21", "hpv21", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpv22", "hpv22", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpv23", "hpv23", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Tx1Ax1Cvscentpteta", "hpx2Tx1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Ty1Ay1Cvscentpteta", "hpx2Ty1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tx1Ay1Cvscentpteta", "hpy2Tx1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Ty1Ax1Cvscentpteta", "hpy2Ty1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Ax1Cvscentpteta", "hpx1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Ay1Cvscentpteta", "hpy1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Avscentpteta", "hpx1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Cvscentpteta", "hpx1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Avscentpteta", "hpy1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Cvscentpteta", "hpy1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpx2Tx1Avscentpteta", "hpx2Tx1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Tx1Cvscentpteta", "hpx2Tx1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Ty1Avscentpteta", "hpx2Ty1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Ty1Cvscentpteta", "hpx2Ty1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tx1Avscentpteta", "hpy2Tx1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Ty1Cvscentpteta", "hpy2Ty1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Ty1Avscentpteta", "hpy2Ty1Avscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tx1Cvscentpteta", "hpy2Tx1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx1Ay1Cvscentpteta", "hpx1Ay1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy1Ax1Cvscentpteta", "hpy1Ax1Cvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpx2Tvscentpteta", "hpx2Tvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpy2Tvscentpteta", "hpy2Tvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpv21", "hpv21", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpv22", "hpv22", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpv23", "hpv23", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Tx1Ax1Cvscentpteta", "hpx2Tx1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Ty1Ay1Cvscentpteta", "hpx2Ty1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tx1Ay1Cvscentpteta", "hpy2Tx1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Ty1Ax1Cvscentpteta", "hpy2Ty1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Ax1Cvscentpteta", "hpx1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Ay1Cvscentpteta", "hpy1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Avscentpteta", "hpx1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Cvscentpteta", "hpx1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Avscentpteta", "hpy1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Cvscentpteta", "hpy1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpx2Tx1Avscentpteta", "hpx2Tx1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Tx1Cvscentpteta", "hpx2Tx1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Ty1Avscentpteta", "hpx2Ty1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Ty1Cvscentpteta", "hpx2Ty1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tx1Avscentpteta", "hpy2Tx1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Ty1Cvscentpteta", "hpy2Ty1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Ty1Avscentpteta", "hpy2Ty1Avscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tx1Cvscentpteta", "hpy2Tx1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx1Ay1Cvscentpteta", "hpx1Ay1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy1Ax1Cvscentpteta", "hpy1Ax1Cvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpx2Tvscentpteta", "hpx2Tvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpy2Tvscentpteta", "hpy2Tvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); /* - histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {centAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + + histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); */ - histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); + 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); - histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); - histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {centAxis, spAxis}, true); + histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); } else { - histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - /*histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - - histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true); - histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {configcentAxis, configthnAxispT, configetaAxis, spAxis}, true);*/ - - histos.add("hpQxtQxpvscent", "hpQxtQxpvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQytQypvscent", "hpQytQypvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxytpvscent", "hpQxytpvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxtQypvscent", "hpQxtQypvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxpQytvscent", "hpQxpQytvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - - histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); - histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {configcentAxis, spAxis}, true); + histos.add("hpuxQxpvscentpteta", "hpuxQxpvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentpteta", "hpuyQypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentpteta", "hpuxQxtvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentpteta", "hpuyQytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentpteta", "hpuxyQxytvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentpteta", "hpuxyQxypvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentpteta", "hpoddv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentpteta", "hpevenv1vscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpuxvscentpteta", "hpuxvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyvscentpteta", "hpuyvscentpteta", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + /*histos.add("hpuxvscentptetaneg", "hpuxvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyvscentptetaneg", "hpuyvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + + histos.add("hpuxQxpvscentptetaneg", "hpuxQxpvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQypvscentptetaneg", "hpuyQypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxQxtvscentptetaneg", "hpuxQxtvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuyQytvscentptetaneg", "hpuyQytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxytvscentptetaneg", "hpuxyQxytvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpuxyQxypvscentptetaneg", "hpuxyQxypvscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpoddv1vscentptetaneg", "hpoddv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true); + histos.add("hpevenv1vscentptetaneg", "hpevenv1vscentptetaneg", HistType::kTHnSparseF, {axisGrp.configcentAxis, axisGrp.configthnAxispT, axisGrp.configetaAxis, spAxis}, true);*/ + + 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); + + histos.add("hpQxpvscent", "hpQxpvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQxtvscent", "hpQxtvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQypvscent", "hpQypvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); + histos.add("hpQytvscent", "hpQytvscent", HistType::kTHnSparseF, {axisGrp.configcentAxis, spAxis}, true); } } - histos.add("hCentrality", "Centrality distribution", kTH1F, {{centAxis}}); + histos.add("hCentrality", "Centrality distribution", kTH1F, {{axisGrp.configcentAxis}}); // histos.add("hpsiApsiC", "hpsiApsiC", kTHnSparseF, {psiACAxis, psiACAxis}); // histos.add("hpsiApsiC", "hpsiApsiC", kTH2F, {psiACAxis, psiACAxis}); // histos.add("hphiminuspsiA", "hphiminuspisA", kTH1F, {{50, 0, 6.28}}, true); @@ -292,12 +331,12 @@ struct lambdapolsp { if (!checkwithpub) { // histos.add("hVtxZ", "Vertex distribution in Z;Z (cm)", kTH1F, {{20, -10.0, 10.0}}); - histos.add("hpRes", "hpRes", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpResSin", "hpResSin", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - /*histos.add("hpCosPsiA", "hpCosPsiA", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpCosPsiC", "hpCosPsiC", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpSinPsiA", "hpSinPsiA", HistType::kTHnSparseF, {configcentAxis, thnAxisres}); - histos.add("hpSinPsiC", "hpSinPsiC", HistType::kTHnSparseF, {configcentAxis, thnAxisres});*/ + histos.add("hpRes", "hpRes", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + // histos.add("hpResSin", "hpResSin", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + /*histos.add("hpCosPsiA", "hpCosPsiA", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + histos.add("hpCosPsiC", "hpCosPsiC", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + histos.add("hpSinPsiA", "hpSinPsiA", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres}); + histos.add("hpSinPsiC", "hpSinPsiC", HistType::kTHnSparseF, {axisGrp.configcentAxis, thnAxisres});*/ /*histos.add("hcentQxZDCA", "hcentQxZDCA", kTH2F, {{centAxis}, {qxZDCAxis}}); histos.add("hcentQyZDCA", "hcentQyZDCA", kTH2F, {{centAxis}, {qxZDCAxis}}); histos.add("hcentQxZDCC", "hcentQxZDCC", kTH2F, {{centAxis}, {qxZDCAxis}}); @@ -325,12 +364,16 @@ struct lambdapolsp { if (usesubdet) { histos.add("hSparseLambdaPolA", "hSparseLambdaPolA", HistType::kTHnSparseF, runaxes, true); histos.add("hSparseLambdaPolC", "hSparseLambdaPolC", HistType::kTHnSparseF, runaxes, true); + histos.add("hSparseLambdaPolAwgt", "hSparseLambdaPolAwgt", HistType::kTHnSparseF, runaxes, true); + histos.add("hSparseLambdaPolCwgt", "hSparseLambdaPolCwgt", HistType::kTHnSparseF, runaxes, true); } histos.add("hSparseAntiLambdaPol", "hSparseAntiLambdaPol", HistType::kTHnSparseF, runaxes, true); histos.add("hSparseAntiLambdaPolwgt", "hSparseAntiLambdaPolwgt", HistType::kTHnSparseF, runaxes, true); if (usesubdet) { histos.add("hSparseAntiLambdaPolA", "hSparseAntiLambdaPolA", HistType::kTHnSparseF, runaxes, true); histos.add("hSparseAntiLambdaPolC", "hSparseAntiLambdaPolC", HistType::kTHnSparseF, runaxes, true); + histos.add("hSparseAntiLambdaPolAwgt", "hSparseAntiLambdaPolAwgt", HistType::kTHnSparseF, runaxes, true); + histos.add("hSparseAntiLambdaPolCwgt", "hSparseAntiLambdaPolCwgt", HistType::kTHnSparseF, runaxes, true); } histos.add("hSparseLambda_corr1a", "hSparseLambda_corr1a", HistType::kTHnSparseF, runaxes, true); histos.add("hSparseLambda_corr1b", "hSparseLambda_corr1b", HistType::kTHnSparseF, runaxes, true); @@ -344,6 +387,14 @@ struct lambdapolsp { histos.add("hSparseAntiLambda_corr2a", "hSparseAntiLambda_corr2a", HistType::kTHnSparseF, runaxes, true); // histos.add("hSparseAntiLambda_corr2b", "hSparseAntiLambda_corr2b", HistType::kTHnSparseF, runaxes, true); } + + 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()); + LOGF(info, "Getting alignment offsets from the CCDB..."); + hwgtAL = ccdb->getForTimeStamp(ConfWgtPathAL.value, cfgCcdbParam.nolaterthan.value); } template @@ -367,6 +418,7 @@ struct lambdapolsp { const float cpav0 = candidate.v0cosPA(); float CtauLambda = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massLambda; + float CtauK0s = candidate.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * massK0s; // float lowmasscutlambda = cMinLambdaMass; // float highmasscutlambda = cMaxLambdaMass; @@ -385,21 +437,28 @@ struct lambdapolsp { if (tranRad > ConfV0TranRadV0Max) { return false; } - if (TMath::Abs(CtauLambda) > cMaxV0LifeTime) { + if (analyzeLambda && TMath::Abs(CtauLambda) > cMaxV0LifeTime) { return false; } - if (TMath::Abs(candidate.yLambda()) > ConfV0Rap) { + if (analyzeK0s && TMath::Abs(CtauK0s) > cMaxV0LifeTime) { + return false; + } + if (analyzeLambda && TMath::Abs(candidate.yLambda()) > ConfV0Rap) { + return false; + } + if (analyzeK0s && TMath::Abs(candidate.yK0Short()) > ConfV0Rap) { return false; } return true; } + template - bool isSelectedV0Daughter(V0 const& candidate, T const& track, int pid) + bool isSelectedV0Daughter(V0 const& candidate, T const& track, int pid, int pid2) { // const auto eta = track.eta(); // const auto pt = track.pt(); const auto tpcNClsF = track.tpcNClsFound(); - if (track.tpcNClsCrossedRows() < 70) { + if (track.tpcNClsCrossedRows() < cfgTPCcluster) { return false; } /*if (TMath::Abs(eta) > ConfDaughEta) { @@ -408,7 +467,7 @@ struct lambdapolsp { if (tpcNClsF < ConfDaughTPCnclsMin) { return false; } - if (track.tpcCrossedRowsOverFindableCls() < 0.8) { + if (track.tpcCrossedRowsOverFindableCls() < rcrfc) { return false; } @@ -428,10 +487,10 @@ struct lambdapolsp { return false; } - if (pid == 0 && (TMath::Abs(candidate.dcapostopv()) < cMinV0DCAPr || TMath::Abs(candidate.dcanegtopv()) < cMinV0DCAPi)) { + if (pid2 == 0 && (TMath::Abs(candidate.dcapostopv()) < cMinV0DCAPr || TMath::Abs(candidate.dcanegtopv()) < cMinV0DCAPi)) { return false; } - if (pid == 1 && (TMath::Abs(candidate.dcapostopv()) < cMinV0DCAPi || TMath::Abs(candidate.dcanegtopv()) < cMinV0DCAPr)) { + if (pid2 == 1 && (TMath::Abs(candidate.dcapostopv()) < cMinV0DCAPi || TMath::Abs(candidate.dcanegtopv()) < cMinV0DCAPr)) { return false; } @@ -459,13 +518,14 @@ struct lambdapolsp { } // check TPC tracking properties - if (posTrackExtra.tpcNClsCrossedRows() < 70 || negTrackExtra.tpcNClsCrossedRows() < 70) { + + if (posTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster || negTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster) { return false; } if (posTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin || negTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin) { return false; } - if (posTrackExtra.tpcCrossedRowsOverFindableCls() < 0.8 || negTrackExtra.tpcCrossedRowsOverFindableCls() < 0.8) { + if (posTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc || negTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc) { return false; } @@ -488,10 +548,49 @@ struct lambdapolsp { return true; } + template + bool isCompatibleK0s(TV0 const& v0) + { + // checks if this V0 is compatible with the requested hypothesis + + // de-ref track extras + auto posTrackExtra = v0.template posTrackExtra_as(); + auto negTrackExtra = v0.template negTrackExtra_as(); + + // check for desired kinematics + if ((v0.positivept() < cfgDaughPrPt || v0.negativept() < cfgDaughPiPt)) { + return false; // doesn´t pass lambda pT sels + } + if (std::abs(v0.positiveeta()) > ConfDaughEta || std::abs(v0.negativeeta()) > ConfDaughEta) { + return false; + } + // check TPC tracking properties + if (posTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster || negTrackExtra.tpcNClsCrossedRows() < cfgTPCcluster) { + return false; + } + if (posTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin || negTrackExtra.tpcNClsFound() < ConfDaughTPCnclsMin) { + return false; + } + if (posTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc || negTrackExtra.tpcCrossedRowsOverFindableCls() < rcrfc) { + return false; + } + // check TPC PID + if (((std::abs(posTrackExtra.tpcNSigmaPi()) > ConfDaughPIDCuts) || (std::abs(negTrackExtra.tpcNSigmaPi()) > ConfDaughPIDCuts))) { + return false; + } + if ((TMath::Abs(v0.dcapostopv()) < cMinV0DCAPi || TMath::Abs(v0.dcanegtopv()) < cMinV0DCAPi)) { + return false; + } + if ((v0.qtarm() / (std::abs(v0.alpha()))) < qtArmenterosMinForK0) { + return false; + } + // if we made it this far, it's good + return true; + } + double GetPhiInRange(double phi) { double result = RecoDecay::constrainAngle(phi); - /* double result = phi; while (result < 0) { @@ -519,12 +618,16 @@ 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 candmass, double candpt, float desbinvalue, double acvalue, double wgtfactor) { + TRandom3 randPhi(0); ROOT::Math::Boost boost{particle.BoostToCM()}; auto fourVecDauCM = boost(daughter); auto phiangle = TMath::ATan2(fourVecDauCM.Py(), fourVecDauCM.Px()); + if (randGrp.doRandomPhi) { + phiangle = randPhi.Uniform(0, 2 * TMath::Pi()); + } auto phiminuspsiC = GetPhiInRange(phiangle - psiZDCC); auto phiminuspsiA = GetPhiInRange(phiangle - psiZDCA); auto phiminuspsi = GetPhiInRange(phiangle - psiZDC); @@ -544,102 +647,113 @@ struct lambdapolsp { // PolA = PolA / acvalue; // Pol = Pol / acvalue; auto Polwgt = Pol / acvalue; + auto PolAwgt = PolA / acvalue; + auto PolCwgt = PolC / acvalue; // Fill histograms using constructed names if (tag2) { if (needetaaxis) { if (usesubdet) { - histos.fill(HIST("hSparseAntiLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality, desbinvalue); + histos.fill(HIST("hSparseAntiLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality, desbinvalue, wgtfactor); } - histos.fill(HIST("hSparseAntiLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality, desbinvalue); + histos.fill(HIST("hSparseAntiLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality, desbinvalue, wgtfactor); if (usesubdet) { - histos.fill(HIST("hSparseAntiLambdaPolA"), candmass, candpt, PolA, centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambdaPolC"), candmass, candpt, PolC, centrality, desbinvalue); + histos.fill(HIST("hSparseAntiLambdaPolA"), candmass, candpt, PolA, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolC"), candmass, candpt, PolC, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolAwgt"), candmass, candpt, PolAwgt, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolCwgt"), candmass, candpt, PolCwgt, centrality, desbinvalue, wgtfactor); } - histos.fill(HIST("hSparseAntiLambdaPol"), candmass, candpt, Pol, centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambdaPolwgt"), candmass, candpt, Polwgt, centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambda_corr1a"), candmass, candpt, sinPhiStar, centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambda_corr1b"), candmass, candpt, cosPhiStar, centrality, desbinvalue); - // histos.fill(HIST("hSparseAntiLambda_corr1c"), candmass, candpt, phiphiStar, centrality, desbinvalue); - histos.fill(HIST("hSparseAntiLambda_corr2a"), candmass, candpt, sinThetaStar, centrality, desbinvalue); - // histos.fill(HIST("hSparseAntiLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality, desbinvalue); + histos.fill(HIST("hSparseAntiLambdaPol"), candmass, candpt, Pol, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolwgt"), candmass, candpt, Polwgt, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambda_corr1a"), candmass, candpt, sinPhiStar, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambda_corr1b"), candmass, candpt, cosPhiStar, centrality, desbinvalue, wgtfactor); + // histos.fill(HIST("hSparseAntiLambda_corr1c"), candmass, candpt, phiphiStar, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseAntiLambda_corr2a"), candmass, candpt, sinThetaStar, centrality, desbinvalue, wgtfactor); + // histos.fill(HIST("hSparseAntiLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality, desbinvalue, wgtfactor); } else { if (usesubdet) { - histos.fill(HIST("hSparseAntiLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality); - histos.fill(HIST("hSparseAntiLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality); - histos.fill(HIST("hSparseAntiLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality); - histos.fill(HIST("hSparseAntiLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality); + histos.fill(HIST("hSparseAntiLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality, wgtfactor); } - histos.fill(HIST("hSparseAntiLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality); - histos.fill(HIST("hSparseAntiLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality); + histos.fill(HIST("hSparseAntiLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality, wgtfactor); if (usesubdet) { - histos.fill(HIST("hSparseAntiLambdaPolA"), candmass, candpt, PolA, centrality); - histos.fill(HIST("hSparseAntiLambdaPolC"), candmass, candpt, PolC, centrality); + histos.fill(HIST("hSparseAntiLambdaPolA"), candmass, candpt, PolA, centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolC"), candmass, candpt, PolC, centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolAwgt"), candmass, candpt, PolAwgt, centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolCwgt"), candmass, candpt, PolCwgt, centrality, wgtfactor); } - histos.fill(HIST("hSparseAntiLambdaPol"), candmass, candpt, Pol, centrality); - histos.fill(HIST("hSparseAntiLambdaPolwgt"), candmass, candpt, Polwgt, centrality); - histos.fill(HIST("hSparseAntiLambda_corr1a"), candmass, candpt, sinPhiStar, centrality); - histos.fill(HIST("hSparseAntiLambda_corr1b"), candmass, candpt, cosPhiStar, centrality); - // histos.fill(HIST("hSparseAntiLambda_corr1c"), candmass, candpt, phiphiStar, centrality); - histos.fill(HIST("hSparseAntiLambda_corr2a"), candmass, candpt, sinThetaStar, centrality); - // histos.fill(HIST("hSparseAntiLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality); + histos.fill(HIST("hSparseAntiLambdaPol"), candmass, candpt, Pol, centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambdaPolwgt"), candmass, candpt, Polwgt, centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambda_corr1a"), candmass, candpt, sinPhiStar, centrality, wgtfactor); + histos.fill(HIST("hSparseAntiLambda_corr1b"), candmass, candpt, cosPhiStar, centrality, wgtfactor); + // 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 (tag1) { if (needetaaxis) { if (usesubdet) { - histos.fill(HIST("hSparseLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality, desbinvalue); - histos.fill(HIST("hSparseLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality, desbinvalue); - histos.fill(HIST("hSparseLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality, desbinvalue); - histos.fill(HIST("hSparseLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality, desbinvalue); + histos.fill(HIST("hSparseLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality, desbinvalue, wgtfactor); } - histos.fill(HIST("hSparseLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality, desbinvalue); - histos.fill(HIST("hSparseLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality, desbinvalue); + histos.fill(HIST("hSparseLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality, desbinvalue, wgtfactor); if (usesubdet) { - histos.fill(HIST("hSparseLambdaPolA"), candmass, candpt, PolA, centrality, desbinvalue); - histos.fill(HIST("hSparseLambdaPolC"), candmass, candpt, PolC, centrality, desbinvalue); + histos.fill(HIST("hSparseLambdaPolA"), candmass, candpt, PolA, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaPolC"), candmass, candpt, PolC, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaPolAwgt"), candmass, candpt, PolAwgt, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaPolCwgt"), candmass, candpt, PolCwgt, centrality, desbinvalue, wgtfactor); } - histos.fill(HIST("hSparseLambdaPol"), candmass, candpt, Pol, centrality, desbinvalue); - histos.fill(HIST("hSparseLambdaPolwgt"), candmass, candpt, Polwgt, centrality, desbinvalue); - histos.fill(HIST("hSparseLambda_corr1a"), candmass, candpt, sinPhiStar, centrality, desbinvalue); - histos.fill(HIST("hSparseLambda_corr1b"), candmass, candpt, cosPhiStar, centrality, desbinvalue); - // histos.fill(HIST("hSparseLambda_corr1c"), candmass, candpt, phiphiStar, centrality, desbinvalue); - histos.fill(HIST("hSparseLambda_corr2a"), candmass, candpt, sinThetaStar, centrality, desbinvalue); - // histos.fill(HIST("hSparseLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality, desbinvalue); + histos.fill(HIST("hSparseLambdaPol"), candmass, candpt, Pol, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambdaPolwgt"), candmass, candpt, Polwgt, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambda_corr1a"), candmass, candpt, sinPhiStar, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambda_corr1b"), candmass, candpt, cosPhiStar, centrality, desbinvalue, wgtfactor); + // histos.fill(HIST("hSparseLambda_corr1c"), candmass, candpt, phiphiStar, centrality, desbinvalue, wgtfactor); + histos.fill(HIST("hSparseLambda_corr2a"), candmass, candpt, sinThetaStar, centrality, desbinvalue, wgtfactor); + // histos.fill(HIST("hSparseLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality, desbinvalue, wgtfactor); } else { if (usesubdet) { - histos.fill(HIST("hSparseLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality); - histos.fill(HIST("hSparseLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality); - histos.fill(HIST("hSparseLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality); - histos.fill(HIST("hSparseLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality); + histos.fill(HIST("hSparseLambdaCosPsiA"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCA))), centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaCosPsiC"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDCC))), centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaSinPsiA"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCA))), centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaSinPsiC"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDCC))), centrality, wgtfactor); } - histos.fill(HIST("hSparseLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality); - histos.fill(HIST("hSparseLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality); + histos.fill(HIST("hSparseLambdaCosPsi"), candmass, candpt, (TMath::Cos(GetPhiInRange(psiZDC))), centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaSinPsi"), candmass, candpt, (TMath::Sin(GetPhiInRange(psiZDC))), centrality, wgtfactor); if (usesubdet) { - histos.fill(HIST("hSparseLambdaPolA"), candmass, candpt, PolA, centrality); - histos.fill(HIST("hSparseLambdaPolC"), candmass, candpt, PolC, centrality); + histos.fill(HIST("hSparseLambdaPolA"), candmass, candpt, PolA, centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaPolC"), candmass, candpt, PolC, centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaPolAwgt"), candmass, candpt, PolAwgt, centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaPolCwgt"), candmass, candpt, PolCwgt, centrality, wgtfactor); } - histos.fill(HIST("hSparseLambdaPol"), candmass, candpt, Pol, centrality); - histos.fill(HIST("hSparseLambdaPolwgt"), candmass, candpt, Polwgt, centrality); - histos.fill(HIST("hSparseLambda_corr1a"), candmass, candpt, sinPhiStar, centrality); - histos.fill(HIST("hSparseLambda_corr1b"), candmass, candpt, cosPhiStar, centrality); - // histos.fill(HIST("hSparseLambda_corr1c"), candmass, candpt, phiphiStar, centrality); - histos.fill(HIST("hSparseLambda_corr2a"), candmass, candpt, sinThetaStar, centrality); - // histos.fill(HIST("hSparseLambda_corr2b"), candmass, candpt, sinThetaStarcosphiphiStar, centrality); + histos.fill(HIST("hSparseLambdaPol"), candmass, candpt, Pol, centrality, wgtfactor); + histos.fill(HIST("hSparseLambdaPolwgt"), candmass, candpt, Polwgt, centrality, wgtfactor); + histos.fill(HIST("hSparseLambda_corr1a"), candmass, candpt, sinPhiStar, centrality, wgtfactor); + histos.fill(HIST("hSparseLambda_corr1b"), candmass, candpt, cosPhiStar, centrality, wgtfactor); + // 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); } } } - ROOT::Math::PxPyPzMVector Lambda, AntiLambda, Lambdadummy, AntiLambdadummy, Proton, Pion, AntiProton, AntiPion, fourVecDauCM; + ROOT::Math::PxPyPzMVector Lambda, AntiLambda, Lambdadummy, AntiLambdadummy, Proton, Pion, AntiProton, AntiPion, fourVecDauCM, K0sdummy, K0s; ROOT::Math::XYZVector threeVecDauCM, threeVecDauCMXY; double phiangle = 0.0; // double angleLambda=0.0; // double angleAntiLambda=0.0; double massLambda = o2::constants::physics::MassLambda; + double massK0s = o2::constants::physics::MassK0Short; double massPr = o2::constants::physics::MassProton; double massPi = o2::constants::physics::MassPionCharged; @@ -728,7 +842,7 @@ struct lambdapolsp { if (!checkwithpub) { // histos.fill(HIST("hVtxZ"), collision.posZ()); histos.fill(HIST("hpRes"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA - psiZDCC)))); - histos.fill(HIST("hpResSin"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA - psiZDCC)))); + // 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)))); @@ -896,10 +1010,10 @@ struct lambdapolsp { continue; } - if (isSelectedV0Daughter(v0, postrack, 0) && isSelectedV0Daughter(v0, negtrack, 1)) { + if (isSelectedV0Daughter(v0, postrack, 0, 0) && isSelectedV0Daughter(v0, negtrack, 1, 0)) { LambdaTag = 1; } - if (isSelectedV0Daughter(v0, negtrack, 0) && isSelectedV0Daughter(v0, postrack, 1)) { + if (isSelectedV0Daughter(v0, negtrack, 0, 1) && isSelectedV0Daughter(v0, postrack, 1, 1)) { aLambdaTag = 1; } @@ -938,6 +1052,14 @@ struct lambdapolsp { accprofileL = ccdb->getForTimeStamp(ConfAccPathL.value, bc.timestamp()); accprofileAL = ccdb->getForTimeStamp(ConfAccPathAL.value, bc.timestamp()); } + int binxwgt; + double wgtvalue; + if (useyldwgt) { + binxwgt = hwgtAL->GetXaxis()->FindBin(v0.pt()); + wgtvalue = hwgtAL->GetBinContent(binxwgt); + } else { + wgtvalue = 1.0; + } float desbinvalue = 0.0; if (dosystematic) { @@ -996,7 +1118,7 @@ struct lambdapolsp { int binx = accprofileL->GetXaxis()->FindBin(v0.eta()); int biny = accprofileL->GetYaxis()->FindBin(v0.pt()); double acvalue = accprofileL->GetBinContent(binx, biny); - fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), desbinvalue, acvalue); + fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), desbinvalue, acvalue, 1.0); } tagb = aLambdaTag; @@ -1006,7 +1128,7 @@ struct lambdapolsp { int binx = accprofileAL->GetXaxis()->FindBin(v0.eta()); int biny = accprofileAL->GetYaxis()->FindBin(v0.pt()); double acvalue = accprofileAL->GetBinContent(binx, biny); - fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), desbinvalue, acvalue); + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), desbinvalue, acvalue, 1.0); } } } else { @@ -1016,7 +1138,7 @@ struct lambdapolsp { int binx = accprofileL->GetXaxis()->FindBin(v0.eta()); int biny = accprofileL->GetYaxis()->FindBin(v0.pt()); double acvalue = accprofileL->GetBinContent(binx, biny); - fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), v0.eta(), acvalue); + fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), v0.eta(), acvalue, 1.0); } tagb = aLambdaTag; @@ -1026,7 +1148,7 @@ struct lambdapolsp { int binx = accprofileAL->GetXaxis()->FindBin(v0.eta()); int biny = accprofileAL->GetYaxis()->FindBin(v0.pt()); double acvalue = accprofileAL->GetBinContent(binx, biny); - fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue); + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue, wgtvalue); } } } @@ -1036,7 +1158,7 @@ struct lambdapolsp { PROCESS_SWITCH(lambdapolsp, processData, "Process data", true); // process function for derived data - mimics the functionality of the original data - void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&, BCsRun3 const&) + void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) { //___________________________________________________________________________________________________ // event selection @@ -1048,6 +1170,10 @@ struct lambdapolsp { return; } + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { + return; + } + if (additionalEvSel && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { return; } @@ -1105,7 +1231,7 @@ struct lambdapolsp { if (!checkwithpub) { // histos.fill(HIST("hVtxZ"), collision.posZ()); histos.fill(HIST("hpRes"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA - psiZDCC)))); - histos.fill(HIST("hpResSin"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA - psiZDCC)))); + // 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)))); @@ -1115,31 +1241,51 @@ struct lambdapolsp { //___________________________________________________________________________________________________ // loop over V0s as necessary for (const auto& v0 : V0s) { + + if (analyzeLambda && analyzeK0s) + continue; + if (!analyzeLambda && !analyzeK0s) + continue; + bool LambdaTag = isCompatible(v0, 0); bool aLambdaTag = isCompatible(v0, 1); - if (!LambdaTag && !aLambdaTag) + bool K0sTag = isCompatibleK0s(v0); + + if (analyzeLambda && !LambdaTag && !aLambdaTag) + continue; + + if (analyzeK0s && !K0sTag) continue; if (!SelectionV0(collision, v0)) { continue; } + if (analyzeLambda) { + if (LambdaTag) { + 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 (LambdaTag) { - 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)) { + continue; + } } - if (shouldReject(LambdaTag, aLambdaTag, Lambdadummy, AntiLambdadummy)) { - continue; + if (analyzeK0s) { + if (K0sTag) { + Pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), massPi); + AntiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), massPi); + K0sdummy = Pion + AntiPion; + } } if (TMath::Abs(v0.eta()) > 0.8) @@ -1147,9 +1293,17 @@ struct lambdapolsp { int taga = LambdaTag; int tagb = aLambdaTag; + int tagc = K0sTag; float desbinvalue = 0.0; - if (dosystematic) { + + 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(); @@ -1199,41 +1353,476 @@ struct lambdapolsp { } /////////////////////////////////////////////////// - if (LambdaTag) { + 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); + fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), desbinvalue, acvalue, 1.0); } tagb = aLambdaTag; - if (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); + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), desbinvalue, acvalue, 1.0); } } } else { - if (LambdaTag) { + 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(), v0.eta(), acvalue); + fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mLambda(), v0.pt(), v0.eta(), acvalue, 1.0); } tagb = aLambdaTag; - if (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(), v0.eta(), acvalue); + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue, 1.0); } } } // lastRunNumber = currentRunNumber; } PROCESS_SWITCH(lambdapolsp, processDerivedData, "Process derived data", false); + + // Processing Event Mixing + using BinningType = ColumnBinningPolicy; + BinningType colBinning{{meGrp.axisVertex, meGrp.axisMultiplicityClass}, true}; + Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only + + void processDerivedDataMixed(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + { + TRandom3 randGen(0); + + for (auto& [collision1, collision2] : selfCombinations(colBinning, meGrp.nMix, -1, collisions, collisions)) { + + if (collision1.index() == collision2.index()) { + continue; + } + + if (!collision1.sel8()) { + continue; + } + if (!collision2.sel8()) { + continue; + } + + if (!collision1.triggereventsp()) { // provided by StraZDCSP + continue; + } + if (!collision2.triggereventsp()) { // provided by StraZDCSP + continue; + } + + if (rctCut.requireRCTFlagChecker && !rctChecker(collision1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(collision2)) { + continue; + } + + if (additionalEvSel && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel2 && (collision1.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision1.trackOccupancyInTimeRange() < cfgMinOccupancy)) { + continue; + } + if (additionalEvSel2 && (collision2.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision2.trackOccupancyInTimeRange() < cfgMinOccupancy)) { + continue; + } + if (additionalEvSel3 && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel3 && (!collision2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + if (additionalEvSel4 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + + auto centrality = collision1.centFT0C(); + auto qxZDCA = collision2.qxZDCA(); + auto qxZDCC = collision2.qxZDCC(); + auto qyZDCA = collision2.qyZDCA(); + auto qyZDCC = collision2.qyZDCC(); + auto psiZDCC = collision2.psiZDCC(); + auto psiZDCA = collision2.psiZDCA(); + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + + auto psiZDC = TMath::ATan2((modqyZDCC - modqyZDCA), (modqxZDCC - modqxZDCA)); // full event plane from collision 2 + auto groupV0 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); + + histos.fill(HIST("hCentrality"), centrality); + + if (randGrp.doRandomPsi) { + psiZDC = randGen.Uniform(0, 2 * TMath::Pi()); + } + if (randGrp.doRandomPsiAC) { + psiZDCA = randGen.Uniform(0, 2 * TMath::Pi()); + psiZDCC = randGen.Uniform(0, 2 * TMath::Pi()); + } + + histos.fill(HIST("hpRes"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA - psiZDCC)))); + // histos.fill(HIST("hpResSin"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA - psiZDCC)))); + + for (const auto& v0 : groupV0) { + + bool LambdaTag = isCompatible(v0, 0); + bool aLambdaTag = isCompatible(v0, 1); + if (!LambdaTag && !aLambdaTag) + continue; + if (!SelectionV0(collision1, v0)) + continue; + if (LambdaTag) { + 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; + } + 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; + } + if (shouldReject(LambdaTag, aLambdaTag, Lambdadummy, AntiLambdadummy)) { + continue; + } + if (TMath::Abs(v0.eta()) > 0.8) + continue; + int taga = LambdaTag; + int tagb = aLambdaTag; + + if (LambdaTag) { + Lambda = Proton + AntiPion; + tagb = 0; + double acvalue = 1.0; + 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; + double acvalue = 1.0; + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0.mAntiLambda(), v0.pt(), v0.eta(), acvalue, 1.0); + } + } + } + } + PROCESS_SWITCH(lambdapolsp, processDerivedDataMixed, "Process mixed event using derived data", false); + + void processDerivedDataMixed2(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + { + TRandom3 randGen(0); + + for (auto& [collision1, collision2] : selfCombinations(colBinning, meGrp.nMix, -1, collisions, collisions)) { + + if (collision1.index() == collision2.index()) { + continue; + } + + if (!collision1.sel8()) { + continue; + } + if (!collision2.sel8()) { + continue; + } + + if (!collision1.triggereventsp()) { // provided by StraZDCSP + continue; + } + if (!collision2.triggereventsp()) { // provided by StraZDCSP + continue; + } + + if (rctCut.requireRCTFlagChecker && !rctChecker(collision1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(collision2)) { + continue; + } + + if (additionalEvSel && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel2 && (collision1.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision1.trackOccupancyInTimeRange() < cfgMinOccupancy)) { + continue; + } + if (additionalEvSel2 && (collision2.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision2.trackOccupancyInTimeRange() < cfgMinOccupancy)) { + continue; + } + if (additionalEvSel3 && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel3 && (!collision2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + if (additionalEvSel4 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + + auto centrality = collision1.centFT0C(); + auto qxZDCA = collision1.qxZDCA(); + auto qxZDCC = collision1.qxZDCC(); + auto qyZDCA = collision1.qyZDCA(); + auto qyZDCC = collision1.qyZDCC(); + auto psiZDCC = collision1.psiZDCC(); + auto psiZDCA = collision1.psiZDCA(); + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + + auto psiZDC = TMath::ATan2((modqyZDCC - modqyZDCA), (modqxZDCC - modqxZDCA)); // full event plane from collision 2 + + histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hpRes"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA - psiZDCC)))); + // histos.fill(HIST("hpResSin"), centrality, (TMath::Sin(GetPhiInRange(psiZDCA - psiZDCC)))); + + // V0s from collision1 to match kinematics + auto v0sCol1 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); + // V0s from collision2 to test + auto v0sCol2 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.index()); + + for (const auto& v0_2 : v0sCol2) { + + bool LambdaTag = isCompatible(v0_2, 0); + bool aLambdaTag = isCompatible(v0_2, 1); + if (!LambdaTag && !aLambdaTag) + continue; + if (!SelectionV0(collision2, v0_2)) + continue; + if (LambdaTag) { + Proton = ROOT::Math::PxPyPzMVector(v0_2.pxpos(), v0_2.pypos(), v0_2.pzpos(), massPr); + AntiPion = ROOT::Math::PxPyPzMVector(v0_2.pxneg(), v0_2.pyneg(), v0_2.pzneg(), massPi); + Lambdadummy = Proton + AntiPion; + } + if (aLambdaTag) { + AntiProton = ROOT::Math::PxPyPzMVector(v0_2.pxneg(), v0_2.pyneg(), v0_2.pzneg(), massPr); + Pion = ROOT::Math::PxPyPzMVector(v0_2.pxpos(), v0_2.pypos(), v0_2.pzpos(), massPi); + AntiLambdadummy = AntiProton + Pion; + } + if (shouldReject(LambdaTag, aLambdaTag, Lambdadummy, AntiLambdadummy)) { + continue; + } + if (TMath::Abs(v0_2.eta()) > 0.8) + continue; + + // Check if lambda kinematics from collision2 matches with collision1 + bool matched = false; + for (const auto& v0_1 : v0sCol1) { + bool LambdaTag1 = isCompatible(v0_1, 0); + bool aLambdaTag1 = isCompatible(v0_1, 1); + if (!LambdaTag1 && !aLambdaTag1) + continue; + if (!SelectionV0(collision1, v0_1)) + continue; + if (TMath::Abs(v0_1.eta()) > 0.8) + continue; + + double deta = std::abs(v0_1.eta() - v0_2.eta()); + double dpt = std::abs(v0_1.pt() - v0_2.pt()); + double dphi = RecoDecay::constrainAngle(v0_1.phi() - v0_2.phi(), 0.0); + if (deta < randGrp.etaMix && dpt < randGrp.ptMix && dphi < randGrp.phiMix && ((v0_1.eta() * v0_2.eta()) > 0.0)) { + matched = true; + break; + } + } + if (!matched) + continue; + + int taga = LambdaTag; + int tagb = aLambdaTag; + + if (LambdaTag) { + Lambda = Proton + AntiPion; + tagb = 0; + double acvalue = 1.0; + fillHistograms(taga, tagb, Lambda, Proton, psiZDCC, psiZDCA, psiZDC, centrality, v0_2.mLambda(), v0_2.pt(), v0_2.eta(), acvalue, 1.0); + } + + tagb = aLambdaTag; + if (aLambdaTag) { + AntiLambda = AntiProton + Pion; + taga = 0; + double acvalue = 1.0; + fillHistograms(taga, tagb, AntiLambda, AntiProton, psiZDCC, psiZDCA, psiZDC, centrality, v0_2.mAntiLambda(), v0_2.pt(), v0_2.eta(), acvalue, 1.0); + } + } + } + } + PROCESS_SWITCH(lambdapolsp, processDerivedDataMixed2, "Process mixed event2 using derived data", false); + + void processDerivedDataMixedFIFO(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + { + + auto nBins = colBinning.getAllBinsCount(); + std::vector> eventPools(nBins); // Pool per bin holding just event indices + + for (auto& collision1 : collisions) { + + if (!collision1.sel8()) { + continue; + } + if (!collision1.triggereventsp()) { // provided by StraZDCSP + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(collision1)) { + continue; + } + + if (additionalEvSel && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (additionalEvSel2 && (collision1.trackOccupancyInTimeRange() > cfgMaxOccupancy || collision1.trackOccupancyInTimeRange() < cfgMinOccupancy)) { + continue; + } + if (additionalEvSel3 && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + + int bin = colBinning.getBin(std::make_tuple(collision1.posZ(), collision1.centFT0C())); + auto groupV0_evt1 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); + float centrality = collision1.centFT0C(); + auto qxZDCA = collision1.qxZDCA(); + auto qxZDCC = collision1.qxZDCC(); + auto qyZDCA = collision1.qyZDCA(); + auto qyZDCC = collision1.qyZDCC(); + auto psiZDCC = collision1.psiZDCC(); + auto psiZDCA = collision1.psiZDCA(); + double modqxZDCA; + double modqyZDCA; + double modqxZDCC; + double modqyZDCC; + + if (bin < 0) + continue; + modqxZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Cos(psiZDCA); + modqyZDCA = TMath::Sqrt((qxZDCA * qxZDCA) + (qyZDCA * qyZDCA)) * TMath::Sin(psiZDCA); + modqxZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Cos(psiZDCC); + modqyZDCC = TMath::Sqrt((qxZDCC * qxZDCC) + (qyZDCC * qyZDCC)) * TMath::Sin(psiZDCC); + + auto psiZDC = TMath::ATan2((modqyZDCC - modqyZDCA), (modqxZDCC - modqxZDCA)); // full event plane from collision + + histos.fill(HIST("hCentrality"), centrality); + histos.fill(HIST("hpRes"), centrality, (TMath::Cos(GetPhiInRange(psiZDCA - psiZDCC)))); + + // For deduplication of (v0_evt1, v0_evt2) pairs per mixed event + std::unordered_map>> seenMap; + + // Loop over Λ candidates in collision1 (keep psi from here) + + for (auto& v0_evt1 : groupV0_evt1) { + if (!SelectionV0(collision1, v0_evt1)) + continue; + bool LambdaTag1 = isCompatible(v0_evt1, 0); + bool aLambdaTag1 = isCompatible(v0_evt1, 1); + ROOT::Math::PxPyPzMVector proton1, pion1, antiproton1, antipion1, LambdaTag1dummy, AntiLambdaTag1dummy; + if (LambdaTag1) { + proton1 = {v0_evt1.pxpos(), v0_evt1.pypos(), v0_evt1.pzpos(), massPr}; + antipion1 = {v0_evt1.pxneg(), v0_evt1.pyneg(), v0_evt1.pzneg(), massPi}; + LambdaTag1dummy = proton1 + antipion1; + } + if (aLambdaTag1) { + antiproton1 = {v0_evt1.pxneg(), v0_evt1.pyneg(), v0_evt1.pzneg(), massPr}; + pion1 = {v0_evt1.pxpos(), v0_evt1.pypos(), v0_evt1.pzpos(), massPi}; + AntiLambdaTag1dummy = antiproton1 + pion1; + } + if (shouldReject(LambdaTag1, aLambdaTag1, LambdaTag1dummy, AntiLambdaTag1dummy)) { + continue; + } + if (TMath::Abs(v0_evt1.eta()) > 0.8) + continue; + + // Loop over all FIFO pool events (mixed events) for this centrality bin + int nMixedEvents = 0; + for (auto it = eventPools[bin].rbegin(); it != eventPools[bin].rend() && nMixedEvents < meGrp.nMix; ++it, ++nMixedEvents) { + int collision2idx = *it; + if (collision1.index() == collision2idx) + continue; + auto groupV0_evt2 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2idx); + + // Now loop over Λ candidates in collision2 to randomize proton phi* (randomize decay angle) + for (auto& v0_evt2 : groupV0_evt2) { + if (!SelectionV0(collision1, v0_evt2)) + continue; + bool LambdaTag2 = isCompatible(v0_evt2, 0); + bool aLambdaTag2 = isCompatible(v0_evt2, 1); + if (!LambdaTag2 && !aLambdaTag2) + continue; + + // Deduplicate (v0_evt1, v0_evt2) pairs per collision2idx + auto key = std::make_pair(v0_evt1.index(), v0_evt2.index()); + if (!seenMap[collision2idx].insert(key).second) + continue; + + ROOT::Math::PxPyPzMVector proton_mix, antiproton_mix, pion_mix, antipion_mix, LambdaTag2dummy, AntiLambdaTag2dummy; + if (LambdaTag2) { + proton_mix = {v0_evt2.pxpos(), v0_evt2.pypos(), v0_evt2.pzpos(), massPr}; + antipion_mix = {v0_evt2.pxneg(), v0_evt2.pyneg(), v0_evt2.pzneg(), massPi}; + LambdaTag2dummy = proton_mix + antipion_mix; + } + if (aLambdaTag2) { + antiproton_mix = {v0_evt2.pxneg(), v0_evt2.pyneg(), v0_evt2.pzneg(), massPr}; + pion_mix = {v0_evt2.pxpos(), v0_evt2.pypos(), v0_evt2.pzpos(), massPi}; + AntiLambdaTag2dummy = antiproton_mix + pion_mix; + } + if (shouldReject(LambdaTag2, aLambdaTag2, LambdaTag2dummy, AntiLambdaTag2dummy)) { + continue; + } + if (TMath::Abs(v0_evt2.eta()) > 0.8) + continue; + if (LambdaTag1) { + double acvalue = 1.0; + fillHistograms(1, 0, LambdaTag1dummy, proton_mix, psiZDCC, psiZDCA, psiZDC, centrality, v0_evt1.mLambda(), v0_evt1.pt(), v0_evt1.eta(), acvalue, 1.0); + } + if (aLambdaTag1) { + double acvalue = 1.0; + fillHistograms(0, 1, AntiLambdaTag1dummy, antiproton_mix, psiZDCC, psiZDCA, psiZDC, centrality, v0_evt1.mAntiLambda(), v0_evt1.pt(), v0_evt1.eta(), acvalue, 1.0); + } + } + } + } + // After processing all mixes, add current event V0s to pool for future mixing + eventPools[bin].push_back(collision1.index()); + // Keep only N last events in FIFO queue + if (static_cast(eventPools[bin].size()) > meGrp.nMix) { + eventPools[bin].pop_front(); + } + } + } + PROCESS_SWITCH(lambdapolsp, processDerivedDataMixedFIFO, "Process mixed event using derived data with FIFO method", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx new file mode 100644 index 00000000000..5db586eb880 --- /dev/null +++ b/PWGLF/Tasks/Strangeness/lambdaspincorrderived.cxx @@ -0,0 +1,501 @@ +// 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 taskLambdaSpinCorr.cxx +/// \brief Analysis task for Lambda spin spin correlation +/// +/// \author sourav.kundu@cern.ch + +#include "PWGLF/DataModel/LFSpincorrelationTables.h" + +#include "Common/Core/trackUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/BinningPolicy.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" +#include + +#include +#include +#include +#include +#include + +#include + +#include // for std::fabs +#include +#include +#include +#include // <<< CHANGED: for dedup sets +#include +#include +#include // <<< CHANGED: for seenMap +#include +#include + +// o2 includes. +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::soa; + +struct lambdaspincorrderived { + // BinningType colBinning; + struct : ConfigurableGroup { + Configurable cfgURL{"cfgURL", "http://alice-ccdb.cern.ch", "Address of the CCDB to browse"}; + Configurable nolaterthan{"ccdb-no-later-than", std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count(), "Latest acceptable timestamp of creation for the object"}; + } cfgCcdbParam; + + // Enable access to the CCDB for the offset and correction constants and save them in dedicated variables. + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + TH3D* hweight1; + TH3D* hweight2; + TH3D* hweight3; + + 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"}; + + // event sel///////// + Configurable centMin{"centMin", 0, "Minimum Centrality"}; + Configurable centMax{"centMax", 80, "Maximum Centrality"}; + + // Lambda selection //////////// + Configurable harmonic{"harmonic", 1, "Harmonic delta phi"}; + Configurable useweight{"useweight", 1, "Use weight"}; + Configurable usePDGM{"usePDGM", 1, "Use PDG mass"}; + Configurable checkDoubleStatus{"checkDoubleStatus", 0, "Check Double status"}; + Configurable cosPA{"cosPA", 0.995, "Cosine Pointing Angle"}; + Configurable radiusMin{"radiusMin", 3, "Minimum V0 radius"}; + Configurable radiusMax{"radiusMax", 30, "Maximum V0 radius"}; + Configurable dcaProton{"dcaProton", 0.1, "DCA Proton"}; + Configurable dcaPion{"dcaPion", 0.2, "DCA Pion"}; + Configurable dcaDaughters{"dcaDaughters", 1.0, "DCA between daughters"}; + Configurable ptMin{"ptMin", 0.5, "V0 Pt minimum"}; + Configurable ptMax{"ptMax", 3.0, "V0 Pt maximum"}; + Configurable rapidity{"rapidity", 0.5, "Rapidity cut on lambda"}; + Configurable v0eta{"v0eta", 0.8, "Eta cut on lambda"}; + + // Event Mixing + 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"}; + + // 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"}; + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + void init(o2::framework::InitContext&) + { + 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("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("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); + + histos.add("hLambdaSameForLL", "hLambdaSameForLL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hLambdaSameForLAL", "hLambdaSameForLAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hAntiLambdaSameForALAL", "hAntiLambdaSameForALAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + + histos.add("hLambdaMixForLL", "hLambdaMixForLL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hLambdaMixForLAL", "hLambdaMixForLAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + histos.add("hAntiLambdaMixForALAL", "hAntiLambdaMixForALAL", HistType::kTH3D, {{50, 0.0, 5.0}, {32, -0.8, 0.8}, {72, 0.0, 2.0 * TMath::Pi()}}, true); + + histos.add("hSparseLambdaLambda", "hSparseLambdaLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseLambdaAntiLambda", "hSparseLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseAntiLambdaAntiLambda", "hSparseAntiLambdaAntiLambda", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + + histos.add("hSparseLambdaLambdaMixed", "hSparseLambdaLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseLambdaAntiLambdaMixed", "hSparseLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + histos.add("hSparseAntiLambdaAntiLambdaMixed", "hSparseAntiLambdaAntiLambdaMixed", HistType::kTHnSparseF, {configThnAxisInvMass, configThnAxisInvMass, configThnAxisPol, configThnAxisCentrality, configThnAxisR}, true); + + 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()); + LOGF(info, "Getting alignment offsets from the CCDB..."); + hweight1 = ccdb->getForTimeStamp(ConfWeightPathLL.value, cfgCcdbParam.nolaterthan.value); + hweight2 = ccdb->getForTimeStamp(ConfWeightPathALAL.value, cfgCcdbParam.nolaterthan.value); + hweight3 = ccdb->getForTimeStamp(ConfWeightPathLAL.value, cfgCcdbParam.nolaterthan.value); + } + + template + bool selectionV0(T const& candidate) + { + auto particle = ROOT::Math::PtEtaPhiMVector(candidate.lambdaPt(), candidate.lambdaEta(), candidate.lambdaPhi(), candidate.lambdaMass()); + if (std::abs(particle.Rapidity()) > rapidity || std::abs(particle.Eta()) > v0eta) { + return false; + } + if (candidate.v0Cospa() < cosPA) { + return false; + } + if (checkDoubleStatus && candidate.doubleStatus()) { + return false; + } + if (candidate.v0Radius() > radiusMax) { + return false; + } + if (candidate.v0Radius() < radiusMin) { + return false; + } + if (candidate.dcaBetweenDaughter() > dcaDaughters) { + return false; + } + if (candidate.v0Status() == 0 && std::abs(candidate.dcaPositive()) < dcaProton && std::abs(candidate.dcaNegative()) < dcaPion) { + return false; + } + if (candidate.v0Status() == 1 && std::abs(candidate.dcaPositive()) < dcaPion && std::abs(candidate.dcaNegative()) < dcaProton) { + return false; + } + if (candidate.lambdaPt() < ptMin) { + return false; + } + if (candidate.lambdaPt() > ptMax) { + return false; + } + return true; + } + + template + bool checkKinematics(T1 const& candidate1, T2 const& candidate2) + { + if (candidate1.v0Status() != candidate2.v0Status()) { + return false; + } + if (std::abs(candidate1.lambdaPt() - candidate2.lambdaPt()) > ptMix) { + return false; + } + if (std::abs(candidate1.lambdaEta() - candidate2.lambdaEta()) > etaMix) { + return false; + } + if (std::abs(RecoDecay::constrainAngle(candidate1.lambdaPhi(), 0.0F, harmonic) - RecoDecay::constrainAngle(candidate2.lambdaPhi(), 0.0F, harmonic)) > phiMix) { + return false; + } + if (std::abs(candidate1.lambdaMass() - candidate2.lambdaMass()) > massMix) { + return false; + } + return true; + } + + 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, + double centrality, int datatype, float mixpairweight) + { + + auto lambda1Mass = 0.0; + auto lambda2Mass = 0.0; + if (!usePDGM) { + lambda1Mass = particle1.M(); + lambda2Mass = particle2.M(); + } else { + 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 + + // Step1: Boosting both Lambdas to Lambda-Lambda pair rest frame + auto lambda1CM = boostPairToCM(particle1Dummy); + auto lambda2CM = boostPairToCM(particle2Dummy); + + // Step 2: 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 + + // Boost protons into their respective Lambda rest frames + auto proton1LambdaRF = boostLambda1ToCM(proton1pairCM); + auto proton2LambdaRF = boostLambda2ToCM(proton2pairCM); + + auto cosThetaDiff = -999.0; + cosThetaDiff = proton1LambdaRF.Vect().Unit().Dot(proton2LambdaRF.Vect().Unit()); + double deltaPhi = std::abs(RecoDecay::constrainAngle(particle1Dummy.Phi(), 0.0F, harmonic) - RecoDecay::constrainAngle(particle2Dummy.Phi(), 0.0F, harmonic)); + double deltaEta = particle1Dummy.Eta() - particle2Dummy.Eta(); + double deltaR = TMath::Sqrt(deltaEta * deltaEta + deltaPhi * deltaPhi); + + if (datatype == 0) { + mixpairweight = 1.0; + histos.fill(HIST("hPtYSame"), particle1.Pt(), particle1.Rapidity(), mixpairweight); + if (tag1 == 0 && tag2 == 0) { + histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR, mixpairweight); + histos.fill(HIST("hLambdaSameForLL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic), mixpairweight); + } else if ((tag1 == 0 && tag2 == 1) || (tag1 == 1 && tag2 == 0)) { + histos.fill(HIST("hSparseLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR, mixpairweight); + histos.fill(HIST("hLambdaSameForLAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic), mixpairweight); + } else if (tag1 == 1 && tag2 == 1) { + histos.fill(HIST("hSparseAntiLambdaAntiLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR, mixpairweight); + histos.fill(HIST("hAntiLambdaSameForALAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic), mixpairweight); + } + } else if (datatype == 1) { + double weight1 = mixpairweight; + double weight2 = mixpairweight; + double weight3 = mixpairweight; + if (useweight) { + weight1 = mixpairweight * hweight1->GetBinContent(hweight1->FindBin(particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic))); + weight2 = mixpairweight * hweight2->GetBinContent(hweight2->FindBin(particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic))); + weight3 = mixpairweight * hweight3->GetBinContent(hweight3->FindBin(particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic))); + } + histos.fill(HIST("hPtYMix"), particle1.Pt(), particle1.Rapidity()); + if (tag1 == 0 && tag2 == 0) { + histos.fill(HIST("hSparseLambdaLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR, weight1); + histos.fill(HIST("hLambdaMixForLL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic), weight1); + } else if ((tag1 == 0 && tag2 == 1) || (tag1 == 1 && tag2 == 0)) { + histos.fill(HIST("hSparseLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR, weight2); + histos.fill(HIST("hLambdaMixForLAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic), weight2); + } else if (tag1 == 1 && tag2 == 1) { + histos.fill(HIST("hSparseAntiLambdaAntiLambdaMixed"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR, weight3); + histos.fill(HIST("hAntiLambdaMixForALAL"), particle1.Pt(), particle1.Eta(), RecoDecay::constrainAngle(particle1.Phi(), 0.0F, harmonic), weight3); + } + } + } + + ROOT::Math::PtEtaPhiMVector lambda0, proton0; + ROOT::Math::PtEtaPhiMVector lambda, proton; + ROOT::Math::PtEtaPhiMVector lambda2, proton2; + + Filter centralityFilter = (nabs(aod::lambdaevent::cent) < centMax && nabs(aod::lambdaevent::cent) > centMin); + + using EventCandidates = soa::Filtered; + using AllTrackCandidates = aod::LambdaPairs; + + void processData(EventCandidates::iterator const& collision, AllTrackCandidates const& V0s) + { + auto centrality = collision.cent(); + for (const auto& v0 : V0s) { + if (!selectionV0(v0)) { + continue; + } + 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()); + for (const auto& v02 : V0s) { + if (v02.index() <= v0.index()) { + continue; + } + if (!selectionV0(v02)) { + continue; + } + if (v0.protonIndex() == v02.protonIndex()) { + continue; + } + if (v0.pionIndex() == v02.pionIndex()) { + 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"), std::abs(RecoDecay::constrainAngle(v0.lambdaPhi(), 0.0F, harmonic) - RecoDecay::constrainAngle(v02.lambdaPhi(), 0.0F, harmonic))); + if (v0.v0Status() == 0 && v02.v0Status() == 0) { + fillHistograms(0, 0, lambda, lambda2, proton, proton2, centrality, 0, 1.0); + } + if (v0.v0Status() == 0 && v02.v0Status() == 1) { + fillHistograms(0, 1, lambda, lambda2, proton, proton2, centrality, 0, 1.0); + } + if (v0.v0Status() == 1 && v02.v0Status() == 0) { + fillHistograms(1, 0, lambda2, lambda, proton2, proton, centrality, 0, 1.0); + } + if (v0.v0Status() == 1 && v02.v0Status() == 1) { + fillHistograms(1, 1, lambda, lambda2, proton, proton2, centrality, 0, 1.0); + } + } + } + } + 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"), std::abs(RecoDecay::constrainAngle(t3.lambdaPhi(), 0.0F, harmonic) - RecoDecay::constrainAngle(t2.lambdaPhi(), 0.0F, harmonic))); + if (t3.v0Status() == 0 && t2.v0Status() == 0) { + fillHistograms(0, 0, lambda, lambda2, proton, proton2, centrality, 1, 1.0); + } + if (t3.v0Status() == 0 && t2.v0Status() == 1) { + fillHistograms(0, 1, lambda, lambda2, proton, proton2, centrality, 1, 1.0); + } + if (t3.v0Status() == 1 && t2.v0Status() == 0) { + fillHistograms(1, 0, lambda2, lambda, proton2, proton, centrality, 1, 1.0); + } + if (t3.v0Status() == 1 && t2.v0Status() == 1) { + fillHistograms(1, 1, lambda, lambda2, proton, proton2, centrality, 1, 1.0); + } + } + } // replacement track pair + } // collision pair + } + PROCESS_SWITCH(lambdaspincorrderived, processME, "Process data ME", false); + + void processMEV2(EventCandidates const& collisions, AllTrackCandidates const& V0s) + { + 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); + + 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; + } + + // 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()); + + 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 (t3.v0Status() == 0 && t2.v0Status() == 0) { + fillHistograms(0, 0, lambda, lambda2, proton, proton2, centrality, 1, invN); + } + if (t3.v0Status() == 0 && t2.v0Status() == 1) { + fillHistograms(0, 1, lambda, lambda2, proton, proton2, centrality, 1, invN); + } + if (t3.v0Status() == 1 && t2.v0Status() == 0) { + fillHistograms(1, 0, lambda2, lambda, proton2, proton, centrality, 1, invN); + } + if (t3.v0Status() == 1 && t2.v0Status() == 1) { + fillHistograms(1, 1, lambda, lambda2, proton, proton2, centrality, 1, invN); + } + } + } // end mixing-event loop + } // end same-event pair loop + + 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 + } + PROCESS_SWITCH(lambdaspincorrderived, processMEV2, "Process data ME", false); +}; +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx index c5388c034a2..488e5815ce0 100644 --- a/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx +++ b/PWGLF/Tasks/Strangeness/nonPromptCascade.cxx @@ -125,6 +125,8 @@ struct NPCascCandidate { float centFT0C; float centFT0A; float centFT0M; + int multNTracksGlobal; + uint32_t toiMask; }; std::array isFromHF(auto& particle) { @@ -173,12 +175,14 @@ struct NonPromptCascadeTask { using TracksExtData = soa::Join; using TracksExtMC = soa::Join; - using CollisionCandidatesRun3 = soa::Join; - using CollisionCandidatesRun3MC = soa::Join; + using CollisionCandidatesRun3 = soa::Join; + using CollisionCandidatesRun3MC = soa::Join; Preslice perCollision = aod::track::collisionId; Preslice perCollisionMC = aod::track::collisionId; + HistogramRegistry mRegistry; + Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; Configurable cfgPropToPCA{"cfgPropToPCA", true, "create tracks version propagated to PCA"}; Configurable cfgRedoPV{"cfgRedoPV", true, "redo PV"}; @@ -206,8 +210,6 @@ struct NonPromptCascadeTask { float mBz = 0.f; o2::vertexing::DCAFitterN<2> mDCAFitter; - HistogramRegistry mRegistry; - void initCCDB(aod::BCsWithTimestamps::iterator const& bc) { if (mRunNumber == bc.runNumber()) { @@ -243,11 +245,20 @@ struct NonPromptCascadeTask { mDCAFitter.setUseAbsDCA(cfgUseAbsDCA); std::vector ptBinning = {0.4, 0.8, 1.2, 1.6, 2.0, 2.4, 2.8, 3.2, 3.6, 4.0, 4.4, 4.8, 5.2, 5.6, 6.0}; - AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + // AxisSpec ptAxis = {ptBinning, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec centAxis = {101, 0., 101., "Centrality"}; + AxisSpec centAxisZoom = {100, 0., 10., "Centrality"}; + AxisSpec multAxis = {10000, 0, 10000, "Multiplicity FT0M"}; + AxisSpec multAxisZoom = {7000, 3000, 10000, "Multiplicity FT0M"}; + AxisSpec nTracksAxis = {100, 0., 100., "NTracksGlobal"}; std::array cutsNames{"# candidates", "hasTOF", "nClusTPC", "nSigmaTPCbach", "nSigmaTPCprotontrack", "nSigmaTPCpiontrack", "cosPA"}; auto cutsOmega{std::get>(mRegistry.add("h_PIDcutsOmega", ";;Invariant mass (GeV/#it{c}^{2})", HistType::kTH2D, {{cutsNames.size(), -0.5, -0.5 + cutsNames.size()}, {125, 1.650, 1.700}}))}; auto cutsXi{std::get>(mRegistry.add("h_PIDcutsXi", ";;Invariant mass (GeV/#it{c}^{2})", HistType::kTH2D, {{6, -0.5, 5.5}, {125, 1.296, 1.346}}))}; + mRegistry.add("hMultVsCent", "hMultVsCent", HistType::kTH2F, {centAxis, multAxis}); + mRegistry.add("hMultVsCentZoom", "hMultVsCentZoom", HistType::kTH2F, {centAxisZoom, multAxisZoom}); + mRegistry.add("hNTracksVsCent", "hNTracksVsCent", HistType::kTH2F, {centAxis, nTracksAxis}); + mRegistry.add("hNTracksVsCentZoom", "hNTracksVsCentZoom", HistType::kTH2F, {centAxisZoom, nTracksAxis}); for (size_t iBin{0}; iBin < cutsNames.size(); ++iBin) { cutsOmega->GetYaxis()->SetBinLabel(iBin + 1, cutsNames[iBin].c_str()); @@ -287,7 +298,7 @@ struct NonPromptCascadeTask { return true; } - void zorroAccounting(const auto& collisions) + void zorroAccounting(const auto& collisions, auto& toiMap) { if (cfgSkimmedProcessing) { int runNumber{-1}; @@ -295,15 +306,38 @@ struct NonPromptCascadeTask { auto bc = coll.template bc_as(); if (runNumber != bc.runNumber()) { mZorro.initCCDB(mCCDB.service, bc.runNumber(), bc.timestamp(), cfgTriggersOfInterest.value); + if (mZorro.getNTOIs() > 32) { + LOG(fatal) << "N TOIs:" << mZorro.getNTOIs() << " Max 32 TOIs possible."; + } mZorro.populateHistRegistry(mRegistry, bc.runNumber()); runNumber = bc.runNumber(); } - mZorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + bool sel = mZorro.isSelected(bc.globalBC()); /// Just let Zorro do the accounting + if (sel) { + std::vector toivect = mZorro.getTriggerOfInterestResults(); + uint32_t toiMask = 0; + for (size_t i{0}; i < toivect.size(); i++) { + toiMask += toivect[i] << i; + } + toiMap[bc.globalBC()] = toiMask; + } } } } + void fillMultHistos(const auto& collisions) + { + // std::cout << "Filling mult histos" << std::endl; + for (const auto& coll : collisions) { + // std::cout << coll.centFT0M() << " mult, cent " << coll.multNTracksGlobal() << std::endl; + mRegistry.fill(HIST("hMultVsCent"), coll.centFT0M(), coll.multFT0M()); + mRegistry.fill(HIST("hMultVsCentZoom"), coll.centFT0M(), coll.multFT0M()); + mRegistry.fill(HIST("hNTracksVsCent"), coll.centFT0M(), (float)coll.multNTracksGlobal()); + mRegistry.fill(HIST("hNTracksVsCentZoom"), coll.centFT0M(), coll.multNTracksGlobal()); + } + }; + template - void fillCandidatesVector(CollisionType const&, TrackType const& tracks, auto const& cascades, auto& candidates) + void fillCandidatesVector(CollisionType const&, TrackType const& tracks, auto const& cascades, auto& candidates, std::map toiMap = {}) { const auto& getCascade = [](auto const& candidate) { @@ -507,6 +541,10 @@ struct NonPromptCascadeTask { } else { o2::base::Propagator::Instance()->propagateToDCA(primaryVertex, ntCascadeTrack, mBz, 2.f, matCorr, &motherDCA); } + uint32_t toiMask = 0x0; + if (toiMap.count(bc.globalBC())) { + toiMask = toiMap[bc.globalBC()]; + } candidates.emplace_back(NPCascCandidate{mcParticleID, trackedCascGlobalIndex, itsTrackGlobalIndex, candidate.collisionId(), matchingChi2, deltaPtITSCascade, deltaPtCascade, cascITSclsSize, hasReassociatedClusters, hasFakeReassociation, isGoodMatch, isGoodCascade, pdgCodeMom, itsTrackPDG, fromHF[0], fromHF[1], collision.numContrib(), cascPVContribs, collision.collisionTimeRes(), primaryVertex.getX(), primaryVertex.getY(), primaryVertex.getZ(), cascadeLvector.pt(), cascadeLvector.eta(), cascadeLvector.phi(), @@ -517,7 +555,7 @@ struct NonPromptCascadeTask { cascITSclusters, protonTrack.itsNCls(), pionTrack.itsNCls(), bachelor.itsNCls(), protonTrack.tpcNClsFound(), pionTrack.tpcNClsFound(), bachelor.tpcNClsFound(), protonTrack.tpcNSigmaPr(), pionTrack.tpcNSigmaPi(), bachelor.tpcNSigmaKa(), bachelor.tpcNSigmaPi(), protonTrack.hasTOF(), pionTrack.hasTOF(), bachelor.hasTOF(), - protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A(), collision.multFT0M(), collision.centFT0C(), collision.centFT0A(), collision.centFT0M()}); + protonTrack.tofNSigmaPr(), pionTrack.tofNSigmaPi(), bachelor.tofNSigmaKa(), bachelor.tofNSigmaPi(), collision.sel8(), collision.multFT0C(), collision.multFT0A(), collision.multFT0M(), collision.centFT0C(), collision.centFT0A(), collision.centFT0M(), collision.multNTracksGlobal(), toiMask}); } } @@ -537,7 +575,7 @@ struct NonPromptCascadeTask { c.protonTPCNSigma, c.pionTPCNSigma, c.bachKaonTPCNSigma, c.bachPionTPCNSigma, c.protonHasTOF, c.pionHasTOF, c.bachHasTOF, c.protonTOFNSigma, c.pionTOFNSigma, c.bachKaonTOFNSigma, c.bachPionTOFNSigma, - c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M); + c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, c.multNTracksGlobal, c.toiMask); } } @@ -576,7 +614,7 @@ struct NonPromptCascadeTask { c.sel8, c.multFT0C, c.multFT0A, c.multFT0M, c.centFT0C, c.centFT0A, c.centFT0M, particle.pt(), particle.eta(), particle.phi(), mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), particle.pdgCode(), mcCollision.posX() - particle.vx(), mcCollision.posY() - particle.vy(), - mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == recCollision.mcCollisionId(), c.hasFakeReassociation, motherDecayDaughters); + mcCollision.posZ() - particle.vz(), mcCollision.globalIndex() == recCollision.mcCollisionId(), c.hasFakeReassociation, motherDecayDaughters, c.multNTracksGlobal, c.toiMask); } } @@ -653,8 +691,10 @@ struct NonPromptCascadeTask { aod::V0s const& /*v0s*/, TracksExtData const& tracks, aod::BCsWithTimestamps const&) { - zorroAccounting(collisions); - fillCandidatesVector(collisions, tracks, trackedCascades, gCandidates); + fillMultHistos(collisions); + std::map toiMap; + zorroAccounting(collisions, toiMap); + fillCandidatesVector(collisions, tracks, trackedCascades, gCandidates, toiMap); fillDataTable(gCandidates); } PROCESS_SWITCH(NonPromptCascadeTask, processTrackedCascadesData, "process cascades from strangeness tracking: Data analysis", false); @@ -663,8 +703,9 @@ struct NonPromptCascadeTask { aod::V0s const& /*v0s*/, TracksExtData const& tracks, aod::BCsWithTimestamps const&) { - zorroAccounting(collisions); - fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT); + std::map toiMap; + zorroAccounting(collisions, toiMap); + fillCandidatesVector(collisions, tracks, cascades, gCandidatesNT, toiMap); fillDataTable(gCandidatesNT); } PROCESS_SWITCH(NonPromptCascadeTask, processCascadesData, "process cascades: Data analysis", false); diff --git a/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx b/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx index c09b05ba107..b38931be584 100644 --- a/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx +++ b/PWGLF/Tasks/Strangeness/phik0shortanalysis.cxx @@ -13,53 +13,77 @@ /// \brief Analysis task for the Phi and K0S rapidity correlations analysis /// \author Stefano Cannito (stefano.cannito@cern.ch) +#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" +#include "Common/DataModel/Centrality.h" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CommonConstants/PhysicsConstants.h" +#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 "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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/EventSelection.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "Framework/ASoAHelpers.h" -#include "CommonConstants/PhysicsConstants.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/Track.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/Core/trackUtilities.h" -#include "Common/Core/TrackSelection.h" -#include "Framework/O2DatabasePDGPlugin.h" -#include "PWGLF/Utils/inelGt.h" -#include "PWGLF/DataModel/mcCentrality.h" -#include "CCDB/BasicCCDBManager.h" +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::aod::track; +enum { + kGlobalplusITSonly = 0, + kGlobalonly, + kITSonly +}; + +enum { + kSpAll = 0, + kSpPion, + kSpKaon, + kSpProton, + kSpOther, + kSpStrangeDecay, + kSpNotPrimary +}; + +enum { + kNoGenpTVar = 0, + kGenpTup, + kGenpTdown +}; + struct Phik0shortanalysis { // Histograms are defined with HistogramRegistry HistogramRegistry dataEventHist{"dataEventHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; @@ -77,6 +101,19 @@ struct Phik0shortanalysis { HistogramRegistry dataPhiPionHist{"dataPhiPionHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry mcPhiPionHist{"mcPhiPionHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry closureMCPhiPionHist{"closureMCPhiPionHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mePhiK0SHist{"mePhiK0SHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry mePhiPionHist{"mePhiPionHist", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + + struct : ConfigurableGroup { + Configurable isData{"isData", true, "Data"}; + Configurable isMC{"isMC", true, "MC"}; + Configurable isClosure{"isClosure", true, "MC Closure"}; + + Configurable isDataNewProc{"isDataNewProc", true, "New procedure for Data"}; + Configurable isMCNewProc{"isMCNewProc", true, "New procedure for MC"}; + Configurable isClosureNewProc{"isClosureNewProc", true, "New procedure for MC Closure"}; + Configurable isMENewProc{"isMENewProc", true, "New procedure for ME"}; + } analysisModeConfigs; // Configurable for event selection Configurable cutZVertex{"cutZVertex", 10.0f, "Accepted z-vertex range (cm)"}; @@ -87,9 +124,10 @@ struct Phik0shortanalysis { // Configurables for track selection (not necessarily common for trigger and the two associated particles) struct : ConfigurableGroup { Configurable cfgCutCharge{"cfgCutCharge", 0.0f, "Cut on charge"}; - Configurable cfgPrimaryTrack{"cfgPrimaryTrack", false, "Primary track selection"}; + Configurable cfgMinAbsCharge{"cfgMinAbsCharge", 3.0f, "Cut on absolute charge"}; Configurable cfgGlobalWoDCATrack{"cfgGlobalWoDCATrack", true, "Global track selection without DCA"}; Configurable cfgPVContributor{"cfgPVContributor", true, "PV contributor track selection"}; + Configurable cMinChargedParticlePtcut{"cMinChargedParticlePtcut", 0.1f, "Track minimum pt cut"}; 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"}; @@ -111,12 +149,15 @@ struct Phik0shortanalysis { Configurable nSigmaCutCombinedKa{"nSigmaCutCombinedKa", 3.0f, "Value of the TOF Nsigma cut for Kaons"}; Configurable nSigmaCutTPCPion{"nSigmaCutTPCPion", 4.0f, "Value of the TPC Nsigma cut for Pions"}; - Configurable cMinPionPtcut{"cMinPionPtcut", 0.3f, "Track minimum pt cut"}; + Configurable cMinPionPtcut{"cMinPionPtcut", 0.2f, "Track minimum pt cut"}; Configurable minTPCnClsFound{"minTPCnClsFound", 70, "min number of found TPC clusters"}; - Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 80, "min number of TPC crossed rows"}; + 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"}; + + Configurable applyExtraPhiCuts{"applyExtraPhiCuts", false, "Enable extra phi cut"}; + Configurable> extraPhiCuts{"extraPhiCuts", {3.07666f, 3.12661f, 0.03f, 6.253f}, "Extra phi cuts"}; } trackConfigs; // Configurables on phi pT bins @@ -154,16 +195,17 @@ struct Phik0shortanalysis { 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"}; // Configurable on pion pT bins - Configurable> binspTPi{"binspTPi", {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"}; + 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"}; // Configurables for delta y selection - Configurable nBinsY{"nBinsY", 80, "Number of bins in y axis"}; - Configurable nBinsDeltaY{"nBinsDeltaY", 24, "Number of bins in deltay axis"}; - Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; - Configurable cfgYAcceptanceSmear{"cfgYAcceptanceSmear", 0.8f, "Rapidity acceptance for smearing matrix study"}; - Configurable cfgFCutOnDeltaY{"cfgFCutOnDeltaY", 0.5f, "First upper bound on Deltay selection"}; - Configurable cfgSCutOnDeltaY{"cfgSCutOnDeltaY", 0.1f, "Second upper bound on Deltay selection"}; - Configurable> cfgDeltaYAcceptanceBins{"cfgDeltaYAcceptanceBins", {1.0f, 0.8f, 0.6f, 0.5f, 0.3f, 0.2f}, "Rapidity acceptance bins"}; + struct : ConfigurableGroup { + Configurable nBinsY{"nBinsY", 20, "Number of bins in y axis"}; + Configurable nBinsDeltaY{"nBinsDeltaY", 20, "Number of bins in deltay axis"}; + Configurable cfgYAcceptance{"cfgYAcceptance", 0.5f, "Rapidity acceptance"}; + Configurable cfgFCutOnDeltaY{"cfgFCutOnDeltaY", 0.5f, "First upper bound on Deltay selection"}; + Configurable cfgSCutOnDeltaY{"cfgSCutOnDeltaY", 0.1f, "Second upper bound on Deltay selection"}; + Configurable> cfgDeltaYAcceptanceBins{"cfgDeltaYAcceptanceBins", {0.5f}, "Rapidity acceptance bins"}; + } deltaYConfigs; // Configurable for RecMC Configurable cfgiskNoITSROFrameBorder{"cfgiskNoITSROFrameBorder", false, "kNoITSROFrameBorder request on RecMC collisions"}; @@ -176,10 +218,20 @@ struct Phik0shortanalysis { // Configurables to choose the filling method Configurable fillMethodMultipleWeights{"fillMethodMultipleWeights", true, "Fill method Multiple Weights"}; Configurable fillMethodSingleWeight{"fillMethodSingleWeight", false, "Fill method Single Weight"}; + Configurable applyEfficiency{"applyEfficiency", false, "Use efficiency for filling histograms"}; + + // Configurables for dN/deta with phi computation + Configurable furtherCheckonMcCollision{"furtherCheckonMcCollision", true, "Further check on MC collisions"}; + Configurable filterOnMcPhi{"filterOnMcPhi", true, "Filter on MC Phi"}; + + // Configurable for event mixing + Configurable cfgNoMixedEvents{"cfgNoMixedEvents", 5, "Number of mixed events per event"}; // Configurable for CCDB + Configurable useCCDB{"useCCDB", false, "Use CCDB for corrections"}; Configurable ccdbUrl{"ccdbUrl", "http://alice-ccdb.cern.ch", "url of the ccdb repository to use"}; Configurable ccdbPurityPath{"ccdbPurityPath", "Users/s/scannito/PhiPuritiesData", "Correction path to file"}; + Configurable ccdbEfficiencyPath{"ccdbEfficiencyPath", "Users/s/scannito/Efficiencies", "Correction path to file"}; // Constants double massKa = o2::constants::physics::MassKPlus; @@ -225,11 +277,23 @@ struct Phik0shortanalysis { using V0DauTracks = soa::Join; using V0DauMCTracks = soa::Join; - // Defining the binning policy for mixed event - using BinningTypeVertexContributor = ColumnBinningPolicy; + // Defining binning policy and axis 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}; + + // Cache for manual slicing SliceCache cache; + // Preslice for manual slicing + struct : PresliceGroup { + Preslice perColl = aod::track::collisionId; + Preslice perMCColl = aod::mcparticle::mcCollisionId; + } preslices; + + // Positive and negative tracks partitions Partition posTracks = aod::track::signed1Pt > trackConfigs.cfgCutCharge; Partition negTracks = aod::track::signed1Pt < trackConfigs.cfgCutCharge; @@ -248,23 +312,32 @@ struct Phik0shortanalysis { // Set of functions for phi purity std::vector> phiPurityFunctions = std::vector>(binsMult->size(), std::vector(binspTPhi->size(), nullptr)); + // Efficiecy maps + TH3F* effMapPhi; + TH3F* effMapK0S; + TH3F* effMapPionTPC; + TH3F* effMapPionTPCTOF; + void init(InitContext&) { // Axes - AxisSpec massK0SAxis = {200, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec massPhiAxis = {200, 0.9f, 1.2f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; AxisSpec sigmassPhiAxis = {nBinsMPhi, lowMPhi, upMPhi, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; - AxisSpec vertexZAxis = {100, -15.f, 15.f, "vrtx_{Z} [cm]"}; + AxisSpec massK0SAxis = {200, 0.45f, 0.55f, "#it{M}_{inv} [GeV/#it{c}^{2}]"}; + AxisSpec nSigmaPiAxis = {100, -10.0f, 10.0f, "N#sigma #pi"}; + AxisSpec vertexZAxis = {100, -cutZVertex, cutZVertex, "vrtx_{Z} [cm]"}; AxisSpec etaAxis = {16, -trackConfigs.etaMax, trackConfigs.etaMax, "#eta"}; - AxisSpec yAxis = {nBinsY, -cfgYAcceptanceSmear, cfgYAcceptanceSmear, "#it{y}"}; - AxisSpec deltayAxis = {nBinsDeltaY, -1.2f, 1.2f, "#Delta#it{y}"}; + AxisSpec yAxis = {deltaYConfigs.nBinsY, -deltaYConfigs.cfgYAcceptance, deltaYConfigs.cfgYAcceptance, "#it{y}"}; + AxisSpec deltayAxis = {deltaYConfigs.nBinsDeltaY, -1.0f, 1.0f, "#Delta#it{y}"}; + AxisSpec phiAxis = {629, 0, o2::constants::math::TwoPI, "#phi"}; AxisSpec multAxis = {120, 0.0f, 120.0f, "centFT0M"}; AxisSpec binnedmultAxis{(std::vector)binsMult, "centFT0M"}; + 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 ptK0SAxis = {60, 0.0f, 6.0f, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec binnedptK0SAxis{(std::vector)binspTK0S, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec ptPiAxis = {30, 0.0f, 3.0f, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec binnedptPiAxis{(std::vector)binspTPi, "#it{p}_{T} (GeV/#it{c})"}; + 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 pTPiAxis = {50, 0.0f, 5.0f, "#it{p}_{T} (GeV/#it{c})"}; + AxisSpec binnedpTPiAxis{(std::vector)binspTPi, "#it{p}_{T} (GeV/#it{c})"}; // Histograms // Number of events per selection @@ -280,9 +353,10 @@ struct Phik0shortanalysis { dataEventHist.add("hVertexZ", "hVertexZ", kTH1F, {vertexZAxis}); dataEventHist.add("hMultiplicityPercent", "Multiplicity Percentile", kTH1F, {multAxis}); dataEventHist.add("hMultiplicityPercentWithPhi", "Multiplicity Percentile in Events with a Phi Candidate", kTH1F, {multAxis}); + dataEventHist.add("h2VertexZvsMult", "Vertex Z vs Multiplicity Percentile", kTH2F, {vertexZAxis, binnedmultAxis}); // Eta distribution for dN/deta values estimation in Data - dataEventHist.add("h2EtaDistribution", "Eta vs multiplicity in Data", kTH2F, {binnedmultAxis, etaAxis}); + dataEventHist.add("h5EtaDistribution", "Eta vs multiplicity in Data", kTHnSparseF, {vertexZAxis, binnedmultAxis, etaAxis, phiAxis, {3, -0.5f, 2.5f}}); // Number of MC events per selection for Rec and Gen mcEventHist.add("hRecMCEventSelection", "hRecMCEventSelection", kTH1F, {{9, -0.5f, 8.5f}}); @@ -304,20 +378,26 @@ struct Phik0shortanalysis { mcEventHist.get(HIST("hGenMCEventSelection"))->GetXaxis()->SetBinLabel(5, "With at least a reco coll"); // MC Event information for Rec and Gen - mcEventHist.add("hRecMCVertexZ", "hRecMCVertexZ", kTH1F, {vertexZAxis}); - mcEventHist.add("hRecMCMultiplicityPercent", "RecMC Multiplicity Percentile", kTH1F, {multAxis}); - mcEventHist.add("hRecMCGenMultiplicityPercent", "RecMC Gen Multiplicity Percentile", kTH1F, {binnedmultAxis}); - mcEventHist.add("hRecMCGenMultiplicityPercentWithPhi", "RecMC Gen Multiplicity Percentile in Events with a Phi Candidate", kTH1F, {binnedmultAxis}); + mcEventHist.add("hRecoMCVertexZ", "hRecoMCVertexZ", kTH1F, {vertexZAxis}); + mcEventHist.add("hUnbinnedRecoMCMultiplicityPercent", "RecoMC Multiplicity Percentile", kTH1F, {multAxis}); + mcEventHist.add("hRecoMCMultiplicityPercent", "RecoMC Multiplicity Percentile", kTH1F, {binnedmultAxis}); + mcEventHist.add("hRecoMCMultiplicityPercentWithPhi", "RecoMC Multiplicity Percentile in Events with a Phi Candidate", kTH1F, {binnedmultAxis}); + mcEventHist.add("h2RecoMCVertexZvsMult", "RecoMC Vertex Z vs Multiplicity Percentile", kTH2F, {vertexZAxis, binnedmultAxis}); mcEventHist.add("hGenMCVertexZ", "hGenMCVertexZ", kTH1F, {vertexZAxis}); mcEventHist.add("hGenMCMultiplicityPercent", "GenMC Multiplicity Percentile", kTH1F, {binnedmultAxis}); mcEventHist.add("hGenMCAssocRecoMultiplicityPercent", "GenMC AssocReco Multiplicity Percentile", kTH1F, {binnedmultAxis}); + mcEventHist.add("hGenMCRecoMultiplicityPercent", "GenMCReco Multiplicity Percentile", kTH1F, {binnedmultAxis}); + mcEventHist.add("h2GenMCRecoVertexZvsMult", "GenMCReco Vertex Z vs Multiplicity Percentile", kTH2F, {vertexZAxis, binnedmultAxis}); // Eta distribution for dN/deta values estimation in MC - mcEventHist.add("h2RecMCEtaDistribution", "Eta vs multiplicity in MCReco", kTH2F, {binnedmultAxis, etaAxis}); + mcEventHist.add("h6RecoMCEtaDistribution", "Eta vs multiplicity in MCReco", kTHnSparseF, {vertexZAxis, binnedmultAxis, etaAxis, phiAxis, {6, -0.5f, 5.5f}, {3, -0.5f, 2.5f}}); + mcEventHist.add("h6RecoCheckMCEtaDistribution", "Eta vs multiplicity in MCReco Check", kTHnSparseF, {vertexZAxis, binnedmultAxis, etaAxis, phiAxis, {6, -0.5f, 5.5f}, {3, -0.5f, 2.5f}}); + mcEventHist.add("h2GenMCEtaDistribution", "Eta vs multiplicity in MCGen", kTH2F, {binnedmultAxis, etaAxis}); mcEventHist.add("h2GenMCEtaDistributionAssocReco", "Eta vs multiplicity in MCGen Assoc Reco", kTH2F, {binnedmultAxis, etaAxis}); - mcEventHist.add("h2GenMCEtaDistributionAssocReco2", "Eta vs multiplicity in MCGen Assoc Reco", kTH2F, {binnedmultAxis, etaAxis}); + mcEventHist.add("h6GenMCEtaDistributionReco", "Eta vs multiplicity in MCGen Reco", kTHnSparseF, {vertexZAxis, binnedmultAxis, etaAxis, phiAxis, {6, -0.5f, 5.5f}, {3, -0.5f, 2.5f}}); + mcEventHist.add("h6GenMCEtaDistributionRecoCheck", "Eta vs multiplicity in MCGen Reco Check", kTHnSparseF, {vertexZAxis, binnedmultAxis, etaAxis, phiAxis, {6, -0.5f, 5.5f}, {3, -0.5f, 2.5f}}); // Phi topological/PID cuts dataPhiHist.add("h2DauTracksPhiDCAxyPreCutData", "Dcaxy distribution vs pt before DCAxy cut", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); @@ -329,19 +409,21 @@ struct Phik0shortanalysis { dataPhiHist.add("hNsigmaKaonTPC", "NsigmaKaon TPC distribution", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); dataPhiHist.add("hNsigmaKaonTOF", "NsigmaKaon TOF distribution", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); - // Phi invariant mass for computing purities and normalisation - dataPhiHist.add("h3PhipurData", "Invariant mass of Phi for Purity (no K0S/Pi) in Data", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + if (analysisModeConfigs.isData) { + // Phi invariant mass for computing purities and normalisation + dataPhiHist.add("h3PhipurData", "Invariant mass of Phi for Purity (no K0S/Pi) in Data", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); - dataPhiHist.add("h4PhipurK0SData", "Invariant mass of Phi for Purity (K0S) in Data", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); - dataPhiHist.get(HIST("h4PhipurK0SData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - dataPhiHist.get(HIST("h4PhipurK0SData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + dataPhiHist.add("h4PhipurK0SData", "Invariant mass of Phi for Purity (K0S) in Data", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + dataPhiHist.get(HIST("h4PhipurK0SData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + dataPhiHist.get(HIST("h4PhipurK0SData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - dataPhiHist.add("h4PhipurPiData", "Invariant mass of Phi for Purity (Pi) in Data", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); - dataPhiHist.get(HIST("h4PhipurPiData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - dataPhiHist.get(HIST("h4PhipurPiData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); + dataPhiHist.add("h4PhipurPiData", "Invariant mass of Phi for Purity (Pi) in Data", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + dataPhiHist.get(HIST("h4PhipurPiData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + dataPhiHist.get(HIST("h4PhipurPiData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } } // DCA plots for phi daughters in MCReco @@ -350,19 +432,21 @@ struct Phik0shortanalysis { mcPhiHist.add("h2DauTracksPhiDCAxyPostCutMCReco", "Dcaxy distribution vs pt after DCAxy cut", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); mcPhiHist.add("h2DauTracksPhiDCAzPostCutMCReco", "Dcaz distribution vs pt after DCAxy cut", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{z} (cm)"}}); - // MCPhi invariant mass for computing purities - closureMCPhiHist.add("h3PhipurMCClosure", "Invariant mass of Phi for Purity (no K0S/Pi)", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + if (analysisModeConfigs.isClosure) { + // MCPhi invariant mass for computing purities + closureMCPhiHist.add("h3PhipurMCClosure", "Invariant mass of Phi for Purity (no K0S/Pi)", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); - closureMCPhiHist.add("h4PhipurK0SMCClosure", "Invariant mass of Phi for Purity (K0S) in MCClosure", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); - closureMCPhiHist.get(HIST("h4PhipurK0SMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - closureMCPhiHist.get(HIST("h4PhipurK0SMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + closureMCPhiHist.add("h4PhipurK0SMCClosure", "Invariant mass of Phi for Purity (K0S) in MCClosure", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + closureMCPhiHist.get(HIST("h4PhipurK0SMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + closureMCPhiHist.get(HIST("h4PhipurK0SMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - closureMCPhiHist.add("h4PhipurPiMCClosure", "Invariant mass of Phi for Purity (Pi) in MCClosure", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); - closureMCPhiHist.get(HIST("h4PhipurPiMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - closureMCPhiHist.get(HIST("h4PhipurPiMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); + closureMCPhiHist.add("h4PhipurPiMCClosure", "Invariant mass of Phi for Purity (Pi) in MCClosure", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + closureMCPhiHist.get(HIST("h4PhipurPiMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + closureMCPhiHist.get(HIST("h4PhipurPiMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } } // K0S topological/PID cuts @@ -371,67 +455,75 @@ struct Phik0shortanalysis { dataK0SHist.add("hNSigmaPosPionFromK0S", "hNSigmaPosPionFromK0Short", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); dataK0SHist.add("hNSigmaNegPionFromK0S", "hNSigmaNegPionFromK0Short", kTH2F, {{100, 0.0, 5.0, "#it{p} (GeV/#it{c})"}, {100, -10.0f, 10.0f}}); - // 2D mass of Phi and K0S for Data - dataPhiK0SHist.add("h5PhiK0SData", "2D Invariant mass of Phi and K0Short for Data", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptK0SAxis, massK0SAxis, sigmassPhiAxis}); - dataPhiK0SHist.get(HIST("h5PhiK0SData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - dataPhiK0SHist.get(HIST("h5PhiK0SData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + if (analysisModeConfigs.isData) { + // 2D mass of Phi and K0S for Data + dataPhiK0SHist.add("h5PhiK0SData", "2D Invariant mass of Phi and K0Short for Data", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTK0SAxis, massK0SAxis, sigmassPhiAxis}); + dataPhiK0SHist.get(HIST("h5PhiK0SData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + dataPhiK0SHist.get(HIST("h5PhiK0SData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // 1D mass of K0S for Data - dataPhiK0SHist.add("h3PhiK0SSEIncNew", "Invariant mass of K0Short for Same Event Inclusive", kTH3F, {binnedmultAxis, binnedptK0SAxis, massK0SAxis}); - dataPhiK0SHist.add("h3PhiK0SSEFCutNew", "Invariant mass of K0Short for Same Event Deltay < FirstCut", kTH3F, {binnedmultAxis, binnedptK0SAxis, massK0SAxis}); - dataPhiK0SHist.add("h3PhiK0SSESCutNew", "Invariant mass of K0Short for Same Event Deltay < SecondCut", kTH3F, {binnedmultAxis, binnedptK0SAxis, massK0SAxis}); + // 1D mass of K0S for Data + dataPhiK0SHist.add("h3PhiK0SSEIncNew", "Invariant mass of K0Short for Same Event Inclusive", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); + dataPhiK0SHist.add("h3PhiK0SSEFCutNew", "Invariant mass of K0Short for Same Event Deltay < FirstCut", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); + dataPhiK0SHist.add("h3PhiK0SSESCutNew", "Invariant mass of K0Short for Same Event Deltay < SecondCut", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); + } // K0S rapidity in Data - dataK0SHist.add("h3K0SRapidityData", "K0Short rapidity for Data", kTH3F, {binnedmultAxis, binnedptK0SAxis, yAxis}); + dataK0SHist.add("h3K0SRapidityData", "K0Short rapidity for Data", kTH3F, {binnedmultAxis, binnedpTK0SAxis, yAxis}); + + if (analysisModeConfigs.isMC) { + // RecMC K0S coupled to Phi + mcPhiK0SHist.add("h4PhiK0SMCReco", "K0S coupled to Phi in MCReco", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); + mcPhiK0SHist.get(HIST("h4PhiK0SMCReco"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + mcPhiK0SHist.get(HIST("h4PhiK0SMCReco"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // RecMC K0S coupled to Phi - mcPhiK0SHist.add("h4PhiK0SMCReco", "K0S coupled to Phi in MCReco", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptK0SAxis, massK0SAxis}); - mcPhiK0SHist.get(HIST("h4PhiK0SMCReco"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - mcPhiK0SHist.get(HIST("h4PhiK0SMCReco"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + // GenMC K0S coupled to Phi + mcPhiK0SHist.add("h3PhiK0SMCGen", "K0S coupled toPhi in MCGen", kTH3F, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTK0SAxis}); + mcPhiK0SHist.get(HIST("h3PhiK0SMCGen"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + mcPhiK0SHist.get(HIST("h3PhiK0SMCGen"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // GenMC K0S coupled to Phi - mcPhiK0SHist.add("h3PhiK0SMCGen", "K0S coupled toPhi in MCGen", kTH3F, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptK0SAxis}); - mcPhiK0SHist.get(HIST("h3PhiK0SMCGen"))->GetXaxis()->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - mcPhiK0SHist.get(HIST("h3PhiK0SMCGen"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); + mcPhiK0SHist.add("h3PhiK0SMCGenAssocReco", "K0S coupled toPhi in MCGen Associated MCReco Collision", kTH3F, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTK0SAxis}); + mcPhiK0SHist.get(HIST("h3PhiK0SMCGenAssocReco"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + mcPhiK0SHist.get(HIST("h3PhiK0SMCGenAssocReco"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } } - mcPhiK0SHist.add("h3PhiK0SMCGenAssocReco", "K0S coupled toPhi in MCGen Associated MCReco Collision", kTH3F, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptK0SAxis}); - mcPhiK0SHist.get(HIST("h3PhiK0SMCGenAssocReco"))->GetXaxis()->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - mcPhiK0SHist.get(HIST("h3PhiK0SMCGenAssocReco"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + if (analysisModeConfigs.isClosure) { + // 2D mass of Phi and K0S for Closure Test + closureMCPhiK0SHist.add("h5PhiK0SMCClosure", "2D Invariant mass of Phi and K0Short for MC Closure Test", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTK0SAxis, massK0SAxis, sigmassPhiAxis}); + closureMCPhiK0SHist.get(HIST("h5PhiK0SMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + closureMCPhiK0SHist.get(HIST("h5PhiK0SMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // 2D mass of Phi and K0S for Closure Test - closureMCPhiK0SHist.add("h5PhiK0SMCClosure", "2D Invariant mass of Phi and K0Short for MC Closure Test", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptK0SAxis, massK0SAxis, sigmassPhiAxis}); - closureMCPhiK0SHist.get(HIST("h5PhiK0SMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - closureMCPhiK0SHist.get(HIST("h5PhiK0SMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); + // 1D mass of K0S for Closure Test + closureMCPhiK0SHist.add("h3ClosureMCPhiK0SSEIncNew", "Invariant mass of K0Short for Inclusive for Closure Test", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); + closureMCPhiK0SHist.add("h3ClosureMCPhiK0SSEFCutNew", "Invariant mass of K0Short for Deltay < FirstCut for Closure Test", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); + closureMCPhiK0SHist.add("h3ClosureMCPhiK0SSESCutNew", "Invariant mass of K0Short for Deltay < SecondCut for Closure Test", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); } - // 1D mass of K0S for Closure Test - closureMCPhiK0SHist.add("h3ClosureMCPhiK0SSEIncNew", "Invariant mass of K0Short for Inclusive for Closure Test", kTH3F, {binnedmultAxis, binnedptK0SAxis, massK0SAxis}); - closureMCPhiK0SHist.add("h3ClosureMCPhiK0SSEFCutNew", "Invariant mass of K0Short for Deltay < FirstCut for Closure Test", kTH3F, {binnedmultAxis, binnedptK0SAxis, massK0SAxis}); - closureMCPhiK0SHist.add("h3ClosureMCPhiK0SSESCutNew", "Invariant mass of K0Short for Deltay < SecondCut for Closure Test", kTH3F, {binnedmultAxis, binnedptK0SAxis, massK0SAxis}); + if (analysisModeConfigs.isData) { + // Phi mass vs Pion NSigma dE/dx for Data + dataPhiPionHist.add("h6PhiPiData", "Phi Invariant mass vs Pion nSigma TPC/TOF for Data", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, sigmassPhiAxis}); + dataPhiPionHist.get(HIST("h6PhiPiData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + dataPhiPionHist.get(HIST("h6PhiPiData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // Phi mass vs Pion NSigma dE/dx for Data - dataPhiPionHist.add("h6PhiPiData", "Phi Invariant mass vs Pion nSigma TPC/TOF for Data", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, sigmassPhiAxis}); - dataPhiPionHist.get(HIST("h6PhiPiData"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - dataPhiPionHist.get(HIST("h6PhiPiData"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); + // Pion NSigma dE/dx for Data + dataPhiPionHist.add("h4PhiPiSEIncNew", "Pion nSigma TPC/TOF for Same Event Inclusive", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + dataPhiPionHist.add("h4PhiPiSEFCutNew", "Pion nSigma TPC/TOF for Same Event Deltay < FirstCut", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + dataPhiPionHist.add("h4PhiPiSESCutNew", "Pion nSigma TPC/TOF for Same Event Deltay < SecondCut", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); } - // Pion NSigma dE/dx for Data - dataPhiPionHist.add("h4PhiPiSEIncNew", "Pion nSigma TPC/TOF for Same Event Inclusive", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); - dataPhiPionHist.add("h4PhiPiSEFCutNew", "Pion nSigma TPC/TOF for Same Event Deltay < FirstCut", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); - dataPhiPionHist.add("h4PhiPiSESCutNew", "Pion nSigma TPC/TOF for Same Event Deltay < SecondCut", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); - // Pion rapidity in Data - dataPionHist.add("h3PiRapidityData", "Pion rapidity for Data", kTH3F, {binnedmultAxis, binnedptPiAxis, yAxis}); + dataPionHist.add("h3PiRapidityData", "Pion rapidity for Data", kTH3F, {binnedmultAxis, binnedpTPiAxis, yAxis}); // DCA plots for pions in Data dataPionHist.add("h2TracksPiDCAxyPreCutData", "Dcaxy distribution vs pt before DCAxy cut", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); @@ -446,113 +538,173 @@ struct Phik0shortanalysis { mcPionHist.add("h2TracksPiDCAzPostCutMCReco", "Dcaz distribution vs pt after DCAxy cut", kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{z} (cm)"}}); // DCA plots for pions in MCReco distinguishing Primaries, Secondaries from Weak Decay and Secondaries from Material - mcPionHist.add("h3RecMCDCAxyPrimPi", "Dcaxy distribution vs pt for Primary Pions", kTH2F, {binnedptPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - mcPionHist.add("h3RecMCDCAxySecWeakDecayPi", "Dcaz distribution vs pt for Secondary Pions from Weak Decay", kTH2F, {binnedptPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - mcPionHist.add("h3RecMCDCAxySecMaterialPi", "Dcaxy distribution vs pt for Secondary Pions from Material", kTH2F, {binnedptPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + mcPionHist.add("h3RecMCDCAxyPrimPi", "Dcaxy distribution vs pt for Primary Pions", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + mcPionHist.add("h3RecMCDCAxySecWeakDecayPi", "Dcaz distribution vs pt for Secondary Pions from Weak Decay", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + mcPionHist.add("h3RecMCDCAxySecMaterialPi", "Dcaxy distribution vs pt for Secondary Pions from Material", kTH2F, {binnedpTPiAxis, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); + + if (analysisModeConfigs.isMC) { + // RecMC Pion coupled to Phi with TPC + mcPhiPionHist.add("h4PhiPiTPCMCReco", "Pion coupled to Phi in MCReco (TPC)", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}}); + mcPhiPionHist.get(HIST("h4PhiPiTPCMCReco"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + mcPhiPionHist.get(HIST("h4PhiPiTPCMCReco"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // RecMC Pion coupled to Phi with TPC - mcPhiPionHist.add("h4PhiPiTPCMCReco", "Pion coupled to Phi in MCReco (TPC)", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}}); - mcPhiPionHist.get(HIST("h4PhiPiTPCMCReco"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - mcPhiPionHist.get(HIST("h4PhiPiTPCMCReco"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + // RecMC Pion coupled to Phi with TPC and TOF + mcPhiPionHist.add("h5PhiPiTPCTOFMCReco", "Pion coupled to Phi in MCReco (TPC and TOF)", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + mcPhiPionHist.get(HIST("h5PhiPiTPCTOFMCReco"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + mcPhiPionHist.get(HIST("h5PhiPiTPCTOFMCReco"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // RecMC Pion coupled to Phi with TPC and TOF - mcPhiPionHist.add("h5PhiPiTPCTOFMCReco", "Pion coupled to Phi in MCReco (TPC and TOF)", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); - mcPhiPionHist.get(HIST("h5PhiPiTPCTOFMCReco"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - mcPhiPionHist.get(HIST("h5PhiPiTPCTOFMCReco"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + mcPhiPionHist.add("h3PhiPiMCGen", "Pion coupled to Phi in MCGen", kTH3F, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPiAxis}); + mcPhiPionHist.get(HIST("h3PhiPiMCGen"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + mcPhiPionHist.get(HIST("h3PhiPiMCGen"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - mcPhiPionHist.add("h3PhiPiMCGen", "Pion coupled to Phi in MCGen", kTH3F, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptPiAxis}); - mcPhiPionHist.get(HIST("h3PhiPiMCGen"))->GetXaxis()->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - mcPhiPionHist.get(HIST("h3PhiPiMCGen"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); + mcPhiPionHist.add("h3PhiPiMCGenAssocReco", "Pion coupled to Phi in MCGen Associated Reco Collision", kTH3F, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPiAxis}); + mcPhiPionHist.get(HIST("h3PhiPiMCGenAssocReco"))->GetXaxis()->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + mcPhiPionHist.get(HIST("h3PhiPiMCGenAssocReco"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } } - mcPhiPionHist.add("h3PhiPiMCGenAssocReco", "Pion coupled to Phi in MCGen Associated Reco Collision", kTH3F, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptPiAxis}); - mcPhiPionHist.get(HIST("h3PhiPiMCGenAssocReco"))->GetXaxis()->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - mcPhiPionHist.get(HIST("h3PhiPiMCGenAssocReco"))->GetXaxis()->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); - } + if (analysisModeConfigs.isClosure) { + // Phi mass vs Pion NSigma dE/dx for Closure Test + closureMCPhiPionHist.add("h6PhiPiMCClosure", "Phi Invariant mass vs Pion nSigma TPC/TOF for MC Closure Test", kTHnSparseF, {{static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, sigmassPhiAxis}); + closureMCPhiPionHist.get(HIST("h6PhiPiMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + closureMCPhiPionHist.get(HIST("h6PhiPiMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", deltaYConfigs.cfgDeltaYAcceptanceBins->at(i))); + } - // Phi mass vs Pion NSigma dE/dx for Closure Test - closureMCPhiPionHist.add("h6PhiPiMCClosure", "Phi Invariant mass vs Pion nSigma TPC/TOF for MC Closure Test", kTHnSparseF, {{static_cast(cfgDeltaYAcceptanceBins->size() + 1), -0.5f, static_cast(cfgDeltaYAcceptanceBins->size() + 1.0f - 0.5f)}, binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}, sigmassPhiAxis}); - closureMCPhiPionHist.get(HIST("h6PhiPiMCClosure"))->GetAxis(0)->SetBinLabel(1, "Inclusive"); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - closureMCPhiPionHist.get(HIST("h6PhiPiMCClosure"))->GetAxis(0)->SetBinLabel(i + 2, Form("|Delta#it{y}| < %.1f", cfgDeltaYAcceptanceBins->at(i))); + // Phi mass vs Pion NSigma dE/dx for Closure Test + closureMCPhiPionHist.add("h4ClosureMCPhiPiSEIncNew", "Pion nSigma TPC/TOF for Inclusive for Closure Test", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + closureMCPhiPionHist.add("h4ClosureMCPhiPiSEFCutNew", "Pion nSigma TPC/TOF for Deltay < FirstCut for Closure Test", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + closureMCPhiPionHist.add("h4ClosureMCPhiPiSESCutNew", "Pion nSigma TPC/TOF for Deltay < SecondCut for Closure Test", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); } - // Phi mass vs Pion NSigma dE/dx for Closure Test - closureMCPhiPionHist.add("h4ClosureMCPhiPiSEIncNew", "Pion nSigma TPC/TOF for Inclusive for Closure Test", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); - closureMCPhiPionHist.add("h4ClosureMCPhiPiSEFCutNew", "Pion nSigma TPC/TOF for Deltay < FirstCut for Closure Test", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); - closureMCPhiPionHist.add("h4ClosureMCPhiPiSESCutNew", "Pion nSigma TPC/TOF for Deltay < SecondCut for Closure Test", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + if (analysisModeConfigs.isMC) { + // MCPhi invariant mass for computing efficiencies and MCnormalisation + mcPhiHist.add("h2PhieffInvMass", "Invariant mass of Phi for Efficiency (no K0S/Pi)", kTH2F, {binnedmultAxis, massPhiAxis}); - // MCPhi invariant mass for computing efficiencies and MCnormalisation - mcPhiHist.add("h2PhieffInvMass", "Invariant mass of Phi for Efficiency (no K0S/Pi)", kTH2F, {binnedmultAxis, massPhiAxis}); + mcPhiHist.add("h3PhieffK0SInvMassInc", "Invariant mass of Phi for Efficiency (K0S) Inclusive", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massPhiAxis}); + mcPhiHist.add("h3PhieffK0SInvMassFCut", "Invariant mass of Phi for Efficiency (K0S) Deltay < FirstCut", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massPhiAxis}); + mcPhiHist.add("h3PhieffK0SInvMassSCut", "Invariant mass of Phi for Efficiency (K0S) Deltay < SecondCut", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massPhiAxis}); - mcPhiHist.add("h3PhieffK0SInvMassInc", "Invariant mass of Phi for Efficiency (K0S) Inclusive", kTH3F, {binnedmultAxis, binnedptK0SAxis, massPhiAxis}); - mcPhiHist.add("h3PhieffK0SInvMassFCut", "Invariant mass of Phi for Efficiency (K0S) Deltay < FirstCut", kTH3F, {binnedmultAxis, binnedptK0SAxis, massPhiAxis}); - mcPhiHist.add("h3PhieffK0SInvMassSCut", "Invariant mass of Phi for Efficiency (K0S) Deltay < SecondCut", kTH3F, {binnedmultAxis, binnedptK0SAxis, massPhiAxis}); + mcPhiHist.add("h3PhieffPiInvMassInc", "Invariant mass of Phi for Efficiency (Pi) Inclusive", kTH3F, {binnedmultAxis, binnedpTPiAxis, massPhiAxis}); + mcPhiHist.add("h3PhieffPiInvMassFCut", "Invariant mass of Phi for Efficiency (Pi) Deltay < FirstCut", kTH3F, {binnedmultAxis, binnedpTPiAxis, massPhiAxis}); + mcPhiHist.add("h3PhieffPiInvMassSCut", "Invariant mass of Phi for Efficiency (Pi) Deltay < SecondCut", kTH3F, {binnedmultAxis, binnedpTPiAxis, massPhiAxis}); - mcPhiHist.add("h3PhieffPiInvMassInc", "Invariant mass of Phi for Efficiency (Pi) Inclusive", kTH3F, {binnedmultAxis, binnedptPiAxis, massPhiAxis}); - mcPhiHist.add("h3PhieffPiInvMassFCut", "Invariant mass of Phi for Efficiency (Pi) Deltay < FirstCut", kTH3F, {binnedmultAxis, binnedptPiAxis, massPhiAxis}); - mcPhiHist.add("h3PhieffPiInvMassSCut", "Invariant mass of Phi for Efficiency (Pi) Deltay < SecondCut", kTH3F, {binnedmultAxis, binnedptPiAxis, massPhiAxis}); + // GenMC Phi and Phi coupled to K0S and Pion + mcPhiHist.add("h1PhiGenMC", "Phi for GenMC", kTH1F, {binnedmultAxis}); + mcPhiHist.add("h1PhiGenMCAssocReco", "Phi for GenMC Associated Reco Collision", kTH1F, {binnedmultAxis}); - // GenMC Phi and Phi coupled to K0S and Pion - mcPhiHist.add("h1PhiGenMC", "Phi for GenMC", kTH1F, {binnedmultAxis}); - mcPhiHist.add("h1PhiGenMCAssocReco", "Phi for GenMC Associated Reco Collision", kTH1F, {binnedmultAxis}); + mcPhiHist.add("h2PhieffK0SGenMCInc", "Phi coupled to K0Short for GenMC Inclusive", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); + mcPhiHist.add("h2PhieffK0SGenMCFCut", "Phi coupled to K0Short for GenMC Deltay < FirstCut", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); + mcPhiHist.add("h2PhieffK0SGenMCSCut", "Phi coupled to K0Short for GenMC Deltay < SecondCut", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); - mcPhiHist.add("h2PhieffK0SGenMCInc", "Phi coupled to K0Short for GenMC Inclusive", kTH2F, {binnedmultAxis, binnedptK0SAxis}); - mcPhiHist.add("h2PhieffK0SGenMCFCut", "Phi coupled to K0Short for GenMC Deltay < FirstCut", kTH2F, {binnedmultAxis, binnedptK0SAxis}); - mcPhiHist.add("h2PhieffK0SGenMCSCut", "Phi coupled to K0Short for GenMC Deltay < SecondCut", kTH2F, {binnedmultAxis, binnedptK0SAxis}); + mcPhiHist.add("h2PhieffK0SGenMCIncAssocReco", "Phi coupled to K0Short for GenMC Inclusive Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); + mcPhiHist.add("h2PhieffK0SGenMCFCutAssocReco", "Phi coupled to K0Short for GenMC Deltay < FirstCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); + mcPhiHist.add("h2PhieffK0SGenMCSCutAssocReco", "Phi coupled to K0Short for GenMC Deltay < SecondCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); - mcPhiHist.add("h2PhieffK0SGenMCIncAssocReco", "Phi coupled to K0Short for GenMC Inclusive Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptK0SAxis}); - mcPhiHist.add("h2PhieffK0SGenMCFCutAssocReco", "Phi coupled to K0Short for GenMC Deltay < FirstCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptK0SAxis}); - mcPhiHist.add("h2PhieffK0SGenMCSCutAssocReco", "Phi coupled to K0Short for GenMC Deltay < SecondCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptK0SAxis}); + mcPhiHist.add("h2PhieffPiGenMCInc", "Phi coupled to Pion for GenMC Inclusive", kTH2F, {binnedmultAxis, binnedpTPiAxis}); + mcPhiHist.add("h2PhieffPiGenMCFCut", "Phi coupled to Pion for GenMC Deltay < FirstCut", kTH2F, {binnedmultAxis, binnedpTPiAxis}); + mcPhiHist.add("h2PhieffPiGenMCSCut", "Phi coupled to Pion for GenMC Deltay < SecondCut", kTH2F, {binnedmultAxis, binnedpTPiAxis}); - mcPhiHist.add("h2PhieffPiGenMCInc", "Phi coupled to Pion for GenMC Inclusive", kTH2F, {binnedmultAxis, binnedptPiAxis}); - mcPhiHist.add("h2PhieffPiGenMCFCut", "Phi coupled to Pion for GenMC Deltay < FirstCut", kTH2F, {binnedmultAxis, binnedptPiAxis}); - mcPhiHist.add("h2PhieffPiGenMCSCut", "Phi coupled to Pion for GenMC Deltay < SecondCut", kTH2F, {binnedmultAxis, binnedptPiAxis}); + mcPhiHist.add("h2PhieffPiGenMCIncAssocReco", "Phi coupled to Pion for GenMC Inclusive Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTPiAxis}); + mcPhiHist.add("h2PhieffPiGenMCFCutAssocReco", "Phi coupled to Pion for GenMC Deltay < FirstCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTPiAxis}); + mcPhiHist.add("h2PhieffPiGenMCSCutAssocReco", "Phi coupled to Pion for GenMC Deltay < SecondCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTPiAxis}); - mcPhiHist.add("h2PhieffPiGenMCIncAssocReco", "Phi coupled to Pion for GenMC Inclusive Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptPiAxis}); - mcPhiHist.add("h2PhieffPiGenMCFCutAssocReco", "Phi coupled to Pion for GenMC Deltay < FirstCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptPiAxis}); - mcPhiHist.add("h2PhieffPiGenMCSCutAssocReco", "Phi coupled to Pion for GenMC Deltay < SecondCut Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptPiAxis}); + // Rapidity smearing matrix for Phi + mcPhiHist.add("h3PhiRapiditySmearing", "Rapidity Smearing Matrix for Phi", kTH3F, {binnedmultAxis, yAxis, yAxis}); - // Rapidity smearing matrix for Phi - mcPhiHist.add("h3PhiRapiditySmearing", "Rapidity Smearing Matrix for Phi", kTH3F, {binnedmultAxis, yAxis, yAxis}); + // MCK0S invariant mass and GenMC K0S for computing efficiencies + mcK0SHist.add("h3K0SMCReco", "K0S for MCReco", kTH3F, {binnedmultAxis, binnedpTK0SAxis, massK0SAxis}); - // MCK0S invariant mass and GenMC K0S for computing efficiencies - mcK0SHist.add("h3K0SMCReco", "K0S for MCReco", kTH3F, {binnedmultAxis, binnedptK0SAxis, massK0SAxis}); + mcK0SHist.add("h2K0SMCGen", "K0S for MCGen", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); + mcK0SHist.add("h2K0SMCGenAssocReco", "K0S for MCGen Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTK0SAxis}); - mcK0SHist.add("h2K0SMCGen", "K0S for MCGen", kTH2F, {binnedmultAxis, binnedptK0SAxis}); - mcK0SHist.add("h2K0SMCGenAssocReco", "K0S for MCGen Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptK0SAxis}); + // Rapidity smearing matrix for K0S and rapidity in GenMC + mcK0SHist.add("h4K0SRapiditySmearing", "Rapidity Smearing Matrix for K0Short", kTHnSparseF, {binnedmultAxis, binnedpTK0SAxis, yAxis, yAxis}); - // Rapidity smearing matrix for K0S and rapidity in GenMC - mcK0SHist.add("h4K0SRapiditySmearing", "Rapidity Smearing Matrix for K0Short", kTHnSparseF, {binnedmultAxis, binnedptK0SAxis, yAxis, yAxis}); + mcK0SHist.add("h3K0SRapidityGenMC", "Rapidity for K0Short for GenMC", kTH3F, {binnedmultAxis, binnedpTK0SAxis, yAxis}); - mcK0SHist.add("h3K0SRapidityGenMC", "Rapidity for K0Short for GenMC", kTH3F, {binnedmultAxis, binnedptK0SAxis, yAxis}); + // MCPion invariant mass and GenMC Pion for computing efficiencies + mcPionHist.add("h3PiTPCMCReco", "Pion for MCReco (TPC)", kTH3F, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}}); + mcPionHist.add("h4PiTPCTOFMCReco", "Pion for MCReco (TPC and TOF)", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); - // MCPion invariant mass and GenMC Pion for computing efficiencies - mcPionHist.add("h3PiTPCMCReco", "Pion for MCReco (TPC)", kTH3F, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}}); - mcPionHist.add("h4PiTPCTOFMCReco", "Pion for MCReco (TPC and TOF)", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, {100, -10.0f, 10.0f}, {100, -10.0f, 10.0f}}); + mcPionHist.add("h2PiMCGen", "Pion for GenMC", kTH2F, {binnedmultAxis, binnedpTPiAxis}); + mcPionHist.add("h2PiMCGenAssocReco", "Pion for GenMC Associated Reco Collision", kTH2F, {binnedmultAxis, binnedpTPiAxis}); - mcPionHist.add("h2PiMCGen", "Pion for GenMC", kTH2F, {binnedmultAxis, binnedptPiAxis}); - mcPionHist.add("h2PiMCGenAssocReco", "Pion for GenMC Associated Reco Collision", kTH2F, {binnedmultAxis, binnedptPiAxis}); + // Rapidity smearing matrix for Pion and rapidity in GenMC + mcPionHist.add("h4PiRapiditySmearing", "Rapidity Smearing Matrix for Pion", kTHnSparseF, {binnedmultAxis, binnedpTPiAxis, yAxis, yAxis}); - // Rapidity smearing matrix for Pion and rapidity in GenMC - mcPionHist.add("h4PiRapiditySmearing", "Rapidity Smearing Matrix for Pion", kTHnSparseF, {binnedmultAxis, binnedptPiAxis, yAxis, yAxis}); + mcPionHist.add("h3PiRapidityGenMC", "Rapidity for Pion for GenMC", kTH3F, {binnedmultAxis, binnedpTPiAxis, yAxis}); + } + + if (analysisModeConfigs.isDataNewProc) { + // Histograms for new analysis procedure (to be finalized and renamed deleting other histograms) + dataPhiHist.add("h3PhiDataNewProc", "Invariant mass of Phi in Data", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + dataPhiK0SHist.add("h5PhiK0SDataNewProc", "2D Invariant mass of Phi and K0Short in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTK0SAxis, massK0SAxis, massPhiAxis}); + dataPhiPionHist.add("h5PhiPiTPCDataNewProc", "Phi Invariant mass vs Pion nSigma TPC in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); + dataPhiPionHist.add("h5PhiPiTOFDataNewProc", "Phi Invariant mass vs Pion nSigma TOF in Data", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); + } + + if (analysisModeConfigs.isClosureNewProc) { + closureMCPhiHist.add("h3PhiMCClosureNewProc", "Invariant mass of Phi in MC Closure test", kTH3F, {binnedmultAxis, binnedpTPhiAxis, massPhiAxis}); + closureMCPhiK0SHist.add("h5PhiK0SMCClosureNewProc", "2D Invariant mass of Phi and K0Short in MC Closure Test", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTK0SAxis, massK0SAxis, massPhiAxis}); + closureMCPhiPionHist.add("h5PhiPiTPCMCClosureNewProc", "Phi Invariant mass vs Pion nSigma TPC in MC Closure Test", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); + closureMCPhiPionHist.add("h5PhiPiTOFMCClosureNewProc", "Phi Invariant mass vs Pion nSigma TOF in MC Closure Test", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); + } + + if (analysisModeConfigs.isMENewProc) { + mePhiK0SHist.add("h5PhiK0SMENewProc", "2D Invariant mass of Phi and K0Short in Mixed Event", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTK0SAxis, massK0SAxis, massPhiAxis}); + mePhiPionHist.add("h5PhiPiTPCMENewProc", "Phi Invariant mass vs Pion nSigma TPC in Mixed Event", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); + mePhiPionHist.add("h5PhiPiTOFMENewProc", "Phi Invariant mass vs Pion nSigma TOF in Mixed Event", kTHnSparseF, {deltayAxis, binnedmultAxis, binnedpTPiAxis, nSigmaPiAxis, massPhiAxis}); + } - mcPionHist.add("h3PiRapidityGenMC", "Rapidity for Pion for GenMC", kTH3F, {binnedmultAxis, binnedptPiAxis, yAxis}); + if (analysisModeConfigs.isMCNewProc) { + mcPhiHist.add("h3PhiMCRecoNewProc", "Phi in MCReco", kTH3F, {binnedmultAxis, pTPhiAxis, yAxis}); + mcK0SHist.add("h3K0SMCRecoNewProc", "K0S in MCReco", kTH3F, {binnedmultAxis, pTK0SAxis, yAxis}); + mcPionHist.add("h3PiMCRecoNewProc", "Pion in MCReco", kTH3F, {binnedmultAxis, pTPiAxis, yAxis}); + mcPionHist.add("h3PiMCReco2NewProc", "Pion in MCReco", kTH3F, {binnedmultAxis, pTPiAxis, yAxis}); - // Initialize CCDB only if purity is requested in the task - if (fillMethodSingleWeight) { + mcPhiHist.add("h3PhiMCGenNewProc", "Phi in MCGen", kTH3F, {binnedmultAxis, pTPhiAxis, yAxis}); + mcK0SHist.add("h3K0SMCGenNewProc", "K0S in MCGen", kTH3F, {binnedmultAxis, pTK0SAxis, yAxis}); + mcPionHist.add("h3PiMCGenNewProc", "Pion in MCGen", kTH3F, {binnedmultAxis, pTPiAxis, yAxis}); + + mcPhiHist.add("h3PhiMCGenAssocRecoNewProc", "Phi in MCGen Associated MCReco", kTH3F, {binnedmultAxis, pTPhiAxis, yAxis}); + mcK0SHist.add("h3K0SMCGenAssocRecoNewProc", "K0S in MCGen Associated MCReco", kTH3F, {binnedmultAxis, pTK0SAxis, yAxis}); + mcPionHist.add("h3PiMCGenAssocRecoNewProc", "Pion in MCGen Associated MCReco", kTH3F, {binnedmultAxis, pTPiAxis, yAxis}); + + mcPhiHist.add("h3PhiMCGenRecoNewProc", "Phi in MCGen MCReco", kTH3F, {binnedmultAxis, pTPhiAxis, yAxis}); + mcK0SHist.add("h3K0SMCGenRecoNewProc", "K0S in MCGen MCReco", kTH3F, {binnedmultAxis, pTK0SAxis, yAxis}); + mcPionHist.add("h3PiMCGenRecoNewProc", "Pion in MCGen MCReco", kTH3F, {binnedmultAxis, pTPiAxis, yAxis}); + + mcPhiHist.add("h3PhiMCGenRecoCheckNewProc", "Phi in MCGen MCReco Check", kTH3F, {binnedmultAxis, pTPhiAxis, yAxis}); + mcK0SHist.add("h3K0SMCGenRecoCheckNewProc", "K0S in MCGen MCReco Check", kTH3F, {binnedmultAxis, pTK0SAxis, yAxis}); + mcPionHist.add("h3PiMCGenRecoCheckNewProc", "Pion in MCGen MCReco Check", kTH3F, {binnedmultAxis, pTPiAxis, yAxis}); + } + + // Initialize CCDB only if purity or efficiencies are requested in the task + if (useCCDB) { ccdb->setURL(ccdbUrl); ccdb->setCaching(true); ccdb->setLocalObjectValidityChecking(); ccdb->setFatalWhenNull(false); - getPhiPurityFunctionsFromCCDB(); + if (fillMethodSingleWeight) + getPhiPurityFunctionsFromCCDB(); + + if (applyEfficiency) { + getEfficiencyMapsFromCCDB(); + } else { + effMapPhi = nullptr; + effMapK0S = nullptr; + effMapPionTPC = nullptr; + effMapPionTPCTOF = nullptr; + } } } @@ -597,7 +749,7 @@ struct Phik0shortanalysis { return false; if (QA) { mcEventHist.fill(HIST("hRecMCEventSelection"), 4); // vertex-Z selected - mcEventHist.fill(HIST("hRecMCVertexZ"), collision.posZ()); + mcEventHist.fill(HIST("hRecoMCVertexZ"), collision.posZ()); } if (!collision.isInelGt0()) return false; @@ -663,10 +815,8 @@ struct Phik0shortanalysis { // Topological track selection template - bool selectionTrackResonance(const T& track, bool isQA) + bool selectionTrackResonance(const T& track, bool doQA) { - if (trackConfigs.cfgPrimaryTrack && !track.isPrimaryTrack()) - return false; if (trackConfigs.cfgGlobalWoDCATrack && !track.isGlobalTrackWoDCA()) return false; if (trackConfigs.cfgPVContributor && !track.isPVContributor()) @@ -677,10 +827,8 @@ struct Phik0shortanalysis { if (track.pt() < trackConfigs.cMinKaonPtcut) return false; - if (std::abs(track.eta()) > trackConfigs.etaMax) - return false; - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPhiHist.fill(HIST("h2DauTracksPhiDCAxyPreCutData"), track.pt(), track.dcaXY()); dataPhiHist.fill(HIST("h2DauTracksPhiDCAzPreCutData"), track.pt(), track.dcaZ()); @@ -691,7 +839,7 @@ struct Phik0shortanalysis { } if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPV1Phi + (trackConfigs.cMaxDCArToPV2Phi / std::pow(track.pt(), trackConfigs.cMaxDCArToPV3Phi))) return false; - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPhiHist.fill(HIST("h2DauTracksPhiDCAxyPostCutData"), track.pt(), track.dcaXY()); dataPhiHist.fill(HIST("h2DauTracksPhiDCAzPostCutData"), track.pt(), track.dcaZ()); @@ -741,35 +889,25 @@ struct Phik0shortanalysis { // Topological selection for pions template - bool selectionPion(const T& track, bool isQA) + bool selectionPion(const T& track, bool doQA) { - if (!track.hasITS()) - return false; - if (track.itsNCls() < trackConfigs.minITSnCls) - return false; - if (track.itsChi2NCl() > trackConfigs.maxChi2ITS) + if (!track.isGlobalTrackWoDCA()) return false; - if (!track.hasTPC()) + if (track.itsNCls() < trackConfigs.minITSnCls) return false; if (track.tpcNClsFound() < trackConfigs.minTPCnClsFound) return false; - if (track.tpcNClsCrossedRows() < trackConfigs.minNCrossedRowsTPC) - return false; - if (track.tpcChi2NCl() > trackConfigs.maxChi2TPC) - return false; if (track.pt() < trackConfigs.cMinPionPtcut) return false; - if (std::abs(track.eta()) > trackConfigs.etaMax) - return false; if constexpr (isTOFChecked) { if (track.pt() >= trackConfigs.pTToUseTOF && !track.hasTOF()) return false; } - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPionHist.fill(HIST("h2TracksPiDCAxyPreCutData"), track.pt(), track.dcaXY()); dataPionHist.fill(HIST("h2TracksPiDCAzPreCutData"), track.pt(), track.dcaZ()); @@ -780,7 +918,7 @@ struct Phik0shortanalysis { } if (std::abs(track.dcaXY()) > trackConfigs.cMaxDCArToPV1Pion + (trackConfigs.cMaxDCArToPV2Pion / std::pow(track.pt(), trackConfigs.cMaxDCArToPV3Pion))) return false; - if (isQA) { + if (doQA) { if constexpr (!isMC) { dataPionHist.fill(HIST("h2TracksPiDCAxyPostCutData"), track.pt(), track.dcaXY()); dataPionHist.fill(HIST("h2TracksPiDCAzPostCutData"), track.pt(), track.dcaZ()); @@ -823,7 +961,7 @@ struct Phik0shortanalysis { continue; if (recPhi.M() < lowMPhi || recPhi.M() > upMPhi) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; nPhi++; @@ -845,7 +983,7 @@ struct Phik0shortanalysis { continue; if (mcParticle.pt() < minPhiPt || mcParticle.pt() > maxPhiPt) continue; - if (std::abs(mcParticle.y()) > cfgYAcceptance) + if (std::abs(mcParticle.y()) > deltaYConfigs.cfgYAcceptance) continue; nPhi++; @@ -856,12 +994,48 @@ struct Phik0shortanalysis { return false; } + template + bool isGenParticleCharged(const T& mcParticle) + { + if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.eta()) > trackConfigs.etaMax) + return false; + + auto pdgTrack = pdgDB->GetParticle(mcParticle.pdgCode()); + if (pdgTrack == nullptr) + return false; + if (std::abs(pdgTrack->Charge()) < trackConfigs.cfgMinAbsCharge) + return false; + + return true; + } + + int fromPDGToEnum(int pdgCode) + { + int pid = kSpAll; + switch (std::abs(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; + } + + return pid; + } + // Get phi-meson purity functions from CCDB void getPhiPurityFunctionsFromCCDB() { TList* listPhiPurityFunctions = ccdb->get(ccdbPurityPath); if (!listPhiPurityFunctions) - LOG(fatal) << "Problem getting TList object with phi purity functions!"; + LOG(error) << "Problem getting TList object with phi purity functions!"; for (size_t multIdx = 0; multIdx < binsMult->size() - 1; multIdx++) { for (size_t ptIdx = 0; ptIdx < binspTPhi->size() - 1; ptIdx++) { @@ -898,6 +1072,34 @@ struct Phik0shortanalysis { return phiPurityFunctions[multIdx][pTIdx]->Eval(Phi.M()); } + void getEfficiencyMapsFromCCDB() + { + TList* listEfficiencyMaps = ccdb->get(ccdbEfficiencyPath); + if (!listEfficiencyMaps) + LOG(error) << "Problem getting TList object with efficiency maps!"; + + effMapPhi = static_cast(listEfficiencyMaps->FindObject("h3EfficiencyPhi")); + if (!effMapPhi) { + LOG(error) << "Problem getting efficiency map for Phi!"; + return; + } + effMapK0S = static_cast(listEfficiencyMaps->FindObject("h3EfficiencyK0S")); + if (!effMapK0S) { + LOG(error) << "Problem getting efficiency map for K0S!"; + return; + } + effMapPionTPC = static_cast(listEfficiencyMaps->FindObject("h3EfficiencyPionTPC")); + if (!effMapPionTPC) { + LOG(error) << "Problem getting efficiency map for Pion with TPC!"; + return; + } + effMapPionTPCTOF = static_cast(listEfficiencyMaps->FindObject("h3EfficiencyPionTPCTOF")); + if (!effMapPionTPCTOF) { + LOG(error) << "Problem getting efficiency map for Pion with TPC and TOF!"; + return; + } + } + // Fill 2D invariant mass histogram for V0 and Phi template void fillInvMass2D(const T& V0, const std::vector& listPhi, float multiplicity, const std::vector& weights) @@ -905,15 +1107,15 @@ struct Phik0shortanalysis { for (const auto& Phi : listPhi) { if constexpr (!isMC) { // same event dataPhiK0SHist.fill(HIST("h5PhiK0SData"), 0, multiplicity, V0.pt(), V0.mK0Short(), Phi.M(), weights.at(0)); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(V0.yK0Short() - Phi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(V0.yK0Short() - Phi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; dataPhiK0SHist.fill(HIST("h5PhiK0SData"), i + 1, multiplicity, V0.pt(), V0.mK0Short(), Phi.M(), weights.at(i + 1)); } } else { // MC event closureMCPhiK0SHist.fill(HIST("h5PhiK0SMCClosure"), 0, multiplicity, V0.pt(), V0.mK0Short(), Phi.M(), weights.at(0)); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(V0.yK0Short() - Phi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(V0.yK0Short() - Phi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; closureMCPhiK0SHist.fill(HIST("h5PhiK0SMCClosure"), i + 1, multiplicity, V0.pt(), V0.mK0Short(), Phi.M(), weights.at(i + 1)); } @@ -930,15 +1132,15 @@ struct Phik0shortanalysis { for (const auto& Phi : listPhi) { if constexpr (!isMC) { // same event dataPhiPionHist.fill(HIST("h6PhiPiData"), 0, multiplicity, Pi.pt(), Pi.tpcNSigmaPi(), nSigmaTOFPi, Phi.M(), weights.at(0)); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(Pi.rapidity(massPi) - Phi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(Pi.rapidity(massPi) - Phi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; dataPhiPionHist.fill(HIST("h6PhiPiData"), i + 1, multiplicity, Pi.pt(), Pi.tpcNSigmaPi(), nSigmaTOFPi, Phi.M(), weights.at(i + 1)); } } else { // MC event closureMCPhiPionHist.fill(HIST("h6PhiPiMCClosure"), 0, multiplicity, Pi.pt(), Pi.tpcNSigmaPi(), nSigmaTOFPi, Phi.M(), weights.at(0)); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(Pi.rapidity(massPi) - Phi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(Pi.rapidity(massPi) - Phi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; closureMCPhiPionHist.fill(HIST("h6PhiPiMCClosure"), i + 1, multiplicity, Pi.pt(), Pi.tpcNSigmaPi(), nSigmaTOFPi, Phi.M(), weights.at(i + 1)); } @@ -1019,7 +1221,7 @@ struct Phik0shortanalysis { ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); if (recPhi.Pt() < minPhiPt || recPhi.Pt() > maxPhiPt) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPhi) { @@ -1033,7 +1235,7 @@ struct Phik0shortanalysis { dataPhiHist.fill(HIST("h3PhipurData"), multiplicity, recPhi.Pt(), recPhi.M()); - std::vector countsK0S(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector countsK0S(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); // V0 already reconstructed by the builder for (const auto& v0 : V0s) { @@ -1057,43 +1259,43 @@ struct Phik0shortanalysis { } } - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) continue; countsK0S.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; countsK0S.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (countsK0S.at(i) > 0) dataPhiHist.fill(HIST("h4PhipurK0SData"), i, multiplicity, recPhi.Pt(), recPhi.M()); } isFilledhV0 = true; - std::vector countsPi(cfgDeltaYAcceptanceBins->size(), 0); + std::vector countsPi(deltaYConfigs.cfgDeltaYAcceptanceBins->size(), 0); // Loop over all primary pion candidates for (const auto& track : fullTracks) { if (!selectionPion(track, false)) continue; - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) continue; countsPi.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; countsPi.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (countsPi.at(i) > 0) dataPhiHist.fill(HIST("h4PhipurPiData"), i, multiplicity, recPhi.Pt(), recPhi.M()); } @@ -1131,12 +1333,12 @@ struct Phik0shortanalysis { dataK0SHist.fill(HIST("h3K0SRapidityData"), multiplicity, v0.pt(), v0.yK0Short()); - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) continue; std::vector listrecPhi; - std::vector counts(cfgDeltaYAcceptanceBins->size() + 1, 0); - std::vector weights(cfgDeltaYAcceptanceBins->size() + 1, 1); + std::vector counts(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector weights(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 1); // Phi reconstruction // Loop over positive tracks @@ -1160,7 +1362,7 @@ struct Phik0shortanalysis { continue; if (recPhi.M() < lowMPhi || recPhi.M() > upMPhi) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; double phiPurity{}; @@ -1172,8 +1374,8 @@ struct Phik0shortanalysis { counts.at(0)++; weights.at(0) *= (1 - phiPurity); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; counts.at(i + 1)++; weights.at(i + 1) *= (1 - phiPurity); @@ -1182,12 +1384,12 @@ struct Phik0shortanalysis { } if (fillMethodMultipleWeights) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1. / static_cast(counts.at(i)) : 0); } fillInvMass2D(v0, listrecPhi, multiplicity, weights); } else if (fillMethodSingleWeight) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1 - weights.at(i) : 0); } fillInvMass(v0, multiplicity, weights); @@ -1218,12 +1420,12 @@ struct Phik0shortanalysis { dataPionHist.fill(HIST("h3PiRapidityData"), multiplicity, track.pt(), track.rapidity(massPi)); - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) continue; std::vector listrecPhi; - std::vector counts(cfgDeltaYAcceptanceBins->size() + 1, 0); - std::vector weights(cfgDeltaYAcceptanceBins->size() + 1, 1); + std::vector counts(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector weights(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 1); // Phi reconstruction // Loop over positive tracks @@ -1247,7 +1449,7 @@ struct Phik0shortanalysis { continue; if (recPhi.M() < lowMPhi || recPhi.M() > upMPhi) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; double phiPurity{}; @@ -1259,8 +1461,8 @@ struct Phik0shortanalysis { counts.at(0)++; weights.at(0) *= (1 - phiPurity); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; counts.at(i + 1)++; weights.at(i + 1) *= (1 - phiPurity); @@ -1269,12 +1471,12 @@ struct Phik0shortanalysis { } if (fillMethodMultipleWeights) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1. / static_cast(counts.at(i)) : 0); } fillInvMassNSigma(track, listrecPhi, multiplicity, weights); } else if (fillMethodSingleWeight) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1 - weights.at(i) : 0); } fillNSigma(track, multiplicity, weights); @@ -1290,7 +1492,7 @@ struct Phik0shortanalysis { return; float multiplicity = collision.centFT0M(); - mcEventHist.fill(HIST("hRecMCMultiplicityPercent"), multiplicity); + mcEventHist.fill(HIST("hUnbinnedRecoMCMultiplicityPercent"), multiplicity); if (!collision.has_mcCollision()) return; @@ -1298,7 +1500,7 @@ struct Phik0shortanalysis { const auto& mcCollision = collision.mcCollision_as(); float genmultiplicity = mcCollision.centFT0M(); - mcEventHist.fill(HIST("hRecMCGenMultiplicityPercent"), genmultiplicity); + mcEventHist.fill(HIST("hRecoMCMultiplicityPercent"), genmultiplicity); // Defining positive and negative tracks for phi reconstruction auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); @@ -1354,7 +1556,7 @@ struct Phik0shortanalysis { mcPhiHist.fill(HIST("h3PhiRapiditySmearing"), genmultiplicity, recPhi.Rapidity(), mcMotherPhi.y()); - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPhi) { @@ -1385,19 +1587,19 @@ struct Phik0shortanalysis { if (v0Configs.cfgFurtherV0Selection && !furtherSelectionV0(v0, collision)) continue; - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedK0S.at(0)) { mcPhiHist.fill(HIST("h3PhieffK0SInvMassInc"), genmultiplicity, v0.pt(), recPhi.M()); isCountedK0S.at(0) = true; } - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgFCutOnDeltaY) + if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > deltaYConfigs.cfgFCutOnDeltaY) continue; if (!isCountedK0S.at(1)) { mcPhiHist.fill(HIST("h3PhieffK0SInvMassFCut"), genmultiplicity, v0.pt(), recPhi.M()); isCountedK0S.at(1) = true; } - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgSCutOnDeltaY) + if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > deltaYConfigs.cfgSCutOnDeltaY) continue; if (!isCountedK0S.at(2)) { mcPhiHist.fill(HIST("h3PhieffK0SInvMassSCut"), genmultiplicity, v0.pt(), recPhi.M()); @@ -1419,19 +1621,19 @@ struct Phik0shortanalysis { if (!selectionPion(track, false)) continue; - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPi.at(0)) { mcPhiHist.fill(HIST("h3PhieffPiInvMassInc"), genmultiplicity, track.pt(), recPhi.M()); isCountedPi.at(0) = true; } - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgFCutOnDeltaY) + if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > deltaYConfigs.cfgFCutOnDeltaY) continue; if (!isCountedPi.at(1)) { mcPhiHist.fill(HIST("h3PhieffPiInvMassFCut"), genmultiplicity, track.pt(), recPhi.M()); isCountedPi.at(1) = true; } - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgSCutOnDeltaY) + if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > deltaYConfigs.cfgSCutOnDeltaY) continue; if (!isCountedPi.at(2)) { mcPhiHist.fill(HIST("h3PhieffPiInvMassSCut"), genmultiplicity, track.pt(), recPhi.M()); @@ -1481,30 +1683,30 @@ struct Phik0shortanalysis { mcK0SHist.fill(HIST("h4K0SRapiditySmearing"), genmultiplicity, v0.pt(), v0.yK0Short(), v0mcparticle.y()); - if (std::abs(v0mcparticle.y()) > cfgYAcceptance) + if (std::abs(v0mcparticle.y()) > deltaYConfigs.cfgYAcceptance) continue; mcK0SHist.fill(HIST("h3K0SMCReco"), genmultiplicity, v0mcparticle.pt(), v0.mK0Short()); - std::vector counts(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector counts(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); for (const auto& mcParticle : mcParticlesThisColl) { if (mcParticle.pdgCode() != o2::constants::physics::Pdg::kPhi) continue; if (mcParticle.pt() < minPhiPt || mcParticle.pt() > maxPhiPt) continue; - if (std::abs(mcParticle.y()) > cfgYAcceptance) + if (std::abs(mcParticle.y()) > deltaYConfigs.cfgYAcceptance) continue; counts.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0mcparticle.y() - mcParticle.y()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(v0mcparticle.y() - mcParticle.y()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; counts.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (counts.at(i) > 0) mcPhiK0SHist.fill(HIST("h4PhiK0SMCReco"), i, genmultiplicity, v0mcparticle.pt(), v0.mK0Short()); } @@ -1545,7 +1747,7 @@ struct Phik0shortanalysis { if (std::abs(mcTrack.pdgCode()) != PDG_t::kPiPlus) continue; - if (std::abs(mcTrack.y()) > cfgYAcceptance) + if (std::abs(mcTrack.y()) > deltaYConfigs.cfgYAcceptance) continue; // Primary pion selection @@ -1564,25 +1766,25 @@ struct Phik0shortanalysis { mcPionHist.fill(HIST("h3PiTPCMCReco"), genmultiplicity, mcTrack.pt(), track.tpcNSigmaPi()); - std::vector countsTPC(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector countsTPC(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); for (const auto& mcParticle : mcParticlesThisColl) { if (mcParticle.pdgCode() != o2::constants::physics::Pdg::kPhi) continue; if (mcParticle.pt() < minPhiPt || mcParticle.pt() > maxPhiPt) continue; - if (std::abs(mcParticle.y()) > cfgYAcceptance) + if (std::abs(mcParticle.y()) > deltaYConfigs.cfgYAcceptance) continue; countsTPC.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(mcTrack.y() - mcParticle.y()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(mcTrack.y() - mcParticle.y()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; countsTPC.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (countsTPC.at(i) > 0) mcPhiPionHist.fill(HIST("h4PhiPiTPCMCReco"), i, genmultiplicity, mcTrack.pt(), track.tpcNSigmaPi()); } @@ -1592,25 +1794,25 @@ struct Phik0shortanalysis { mcPionHist.fill(HIST("h4PiTPCTOFMCReco"), genmultiplicity, mcTrack.pt(), track.tpcNSigmaPi(), track.tofNSigmaPi()); - std::vector countsTPCTOF(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector countsTPCTOF(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); for (const auto& mcParticle : mcParticlesThisColl) { if (mcParticle.pdgCode() != o2::constants::physics::Pdg::kPhi) continue; if (mcParticle.pt() < minPhiPt || mcParticle.pt() > maxPhiPt) continue; - if (std::abs(mcParticle.y()) > cfgYAcceptance) + if (std::abs(mcParticle.y()) > deltaYConfigs.cfgYAcceptance) continue; countsTPCTOF.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(mcTrack.y() - mcParticle.y()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(mcTrack.y() - mcParticle.y()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; countsTPCTOF.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (countsTPCTOF.at(i) > 0) mcPhiPionHist.fill(HIST("h5PhiPiTPCTOFMCReco"), i, genmultiplicity, mcTrack.pt(), track.tpcNSigmaPi(), track.tofNSigmaPi()); } @@ -1631,7 +1833,7 @@ struct Phik0shortanalysis { const auto& mcCollision = collision.mcCollision_as(); float genmultiplicity = mcCollision.centFT0M(); - mcEventHist.fill(HIST("hRecMCGenMultiplicityPercent"), genmultiplicity); + mcEventHist.fill(HIST("hRecoMCMultiplicityPercent"), genmultiplicity); // Defining positive and negative tracks for phi reconstruction auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); @@ -1660,12 +1862,12 @@ struct Phik0shortanalysis { ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); if (recPhi.Pt() < minPhiPt || recPhi.Pt() > maxPhiPt) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPhi) { mcEventHist.fill(HIST("hRecMCEventSelection"), 7); // at least a Phi candidate in the event - mcEventHist.fill(HIST("hRecMCGenMultiplicityPercentWithPhi"), genmultiplicity); + mcEventHist.fill(HIST("hRecoMCMultiplicityPercentWithPhi"), genmultiplicity); isCountedPhi = true; } @@ -1674,7 +1876,7 @@ struct Phik0shortanalysis { closureMCPhiHist.fill(HIST("h3PhipurMCClosure"), genmultiplicity, recPhi.Pt(), recPhi.M()); - std::vector countsK0S(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector countsK0S(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); // V0 already reconstructed by the builder for (const auto& v0 : V0s) { @@ -1694,23 +1896,23 @@ struct Phik0shortanalysis { if (v0Configs.cfgFurtherV0Selection && !furtherSelectionV0(v0, collision)) continue; - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) continue; countsK0S.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; countsK0S.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (countsK0S.at(i) > 0) closureMCPhiHist.fill(HIST("h4PhipurK0SInvMass"), i, genmultiplicity, recPhi.Pt(), recPhi.M()); } - std::vector countsPi(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector countsPi(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); // Loop over all primary pion candidates for (const auto& track : fullMCTracks) { @@ -1725,18 +1927,18 @@ struct Phik0shortanalysis { if (!selectionPion(track, false)) continue; - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) continue; countsPi.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; countsPi.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (countsPi.at(i) > 0) closureMCPhiHist.fill(HIST("h4PhipurPiInvMass"), i, genmultiplicity, recPhi.Pt(), recPhi.M()); } @@ -1782,12 +1984,12 @@ struct Phik0shortanalysis { if (v0Configs.cfgFurtherV0Selection && !furtherSelectionV0(v0, collision)) continue; - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) continue; std::vector listrecPhi; - std::vector counts(cfgDeltaYAcceptanceBins->size() + 1, 0); - std::vector weights(cfgDeltaYAcceptanceBins->size() + 1, 1); + std::vector counts(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector weights(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 1); // Phi reconstruction for (const auto& track1 : posThisColl) { // loop over all selected tracks @@ -1838,7 +2040,7 @@ struct Phik0shortanalysis { continue; if (recPhi.M() < lowMPhi || recPhi.M() > upMPhi) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; double phiPurity{}; @@ -1850,8 +2052,8 @@ struct Phik0shortanalysis { counts.at(0)++; weights.at(0) *= (1 - phiPurity); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; counts.at(i + 1)++; weights.at(i + 1) *= (1 - phiPurity); @@ -1860,12 +2062,12 @@ struct Phik0shortanalysis { } if (fillMethodMultipleWeights) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1. / static_cast(counts.at(i)) : 0); } fillInvMass2D(v0, listrecPhi, genmultiplicity, weights); } else if (fillMethodSingleWeight) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1 - weights.at(i) : 0); } fillInvMass(v0, genmultiplicity, weights); @@ -1904,12 +2106,12 @@ struct Phik0shortanalysis { if (!selectionPion(track, true)) continue; - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) continue; std::vector listrecPhi; - std::vector counts(cfgDeltaYAcceptanceBins->size() + 1, 0); - std::vector weights(cfgDeltaYAcceptanceBins->size() + 1, 1); + std::vector counts(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector weights(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 1); // Phi reconstruction for (const auto& track1 : posThisColl) { // loop over all selected tracks @@ -1960,7 +2162,7 @@ struct Phik0shortanalysis { continue; if (recPhi.M() < lowMPhi || recPhi.M() > upMPhi) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; double phiPurity{}; @@ -1972,8 +2174,8 @@ struct Phik0shortanalysis { counts.at(0)++; weights.at(0) *= (1 - phiPurity); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; counts.at(i + 1)++; weights.at(i + 1) *= (1 - phiPurity); @@ -1982,12 +2184,12 @@ struct Phik0shortanalysis { } if (fillMethodMultipleWeights) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1. / static_cast(counts.at(i)) : 0); } fillInvMassNSigma(track, listrecPhi, genmultiplicity, weights); } else if (fillMethodSingleWeight) { - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { weights.at(i) = (counts.at(i) > 0 ? 1 - weights.at(i) : 0); } fillNSigma(track, genmultiplicity, weights); @@ -2036,7 +2238,7 @@ struct Phik0shortanalysis { } if (!isPosKaon || !isNegKaon) continue; - if (std::abs(mcParticle1.y()) > cfgYAcceptance) + if (std::abs(mcParticle1.y()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPhi) { @@ -2058,7 +2260,7 @@ struct Phik0shortanalysis { if (!mcParticle2.isPhysicalPrimary()) continue; - if (std::abs(mcParticle2.y()) > cfgYAcceptance) + if (std::abs(mcParticle2.y()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedK0S.at(0)) { mcPhiHist.fill(HIST("h2PhieffK0SGenMCInc"), genmultiplicity, mcParticle2.pt()); @@ -2066,7 +2268,7 @@ struct Phik0shortanalysis { mcPhiHist.fill(HIST("h2PhieffK0SGenMCFCutAssocReco"), genmultiplicity, mcParticle2.pt()); isCountedK0S.at(0) = true; } - if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgFCutOnDeltaY) + if (std::abs(mcParticle1.y() - mcParticle2.y()) > deltaYConfigs.cfgFCutOnDeltaY) continue; if (!isCountedK0S.at(1)) { mcPhiHist.fill(HIST("h2PhieffK0SGenMCFCut"), genmultiplicity, mcParticle2.pt()); @@ -2074,7 +2276,7 @@ struct Phik0shortanalysis { mcPhiHist.fill(HIST("h2PhieffK0SGenMCFCutAssocReco"), genmultiplicity, mcParticle2.pt()); isCountedK0S.at(1) = true; } - if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgSCutOnDeltaY) + if (std::abs(mcParticle1.y() - mcParticle2.y()) > deltaYConfigs.cfgSCutOnDeltaY) continue; if (!isCountedK0S.at(2)) { mcPhiHist.fill(HIST("h2PhieffK0SGenMCSCut"), genmultiplicity, mcParticle2.pt()); @@ -2092,7 +2294,7 @@ struct Phik0shortanalysis { if (!mcParticle2.isPhysicalPrimary()) continue; - if (std::abs(mcParticle2.y()) > cfgYAcceptance) + if (std::abs(mcParticle2.y()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPi.at(0)) { mcPhiHist.fill(HIST("h2PhieffPiGenMCInc"), genmultiplicity, mcParticle2.pt()); @@ -2100,7 +2302,7 @@ struct Phik0shortanalysis { mcPhiHist.fill(HIST("h2PhieffPiGenMCIncAssocReco"), genmultiplicity, mcParticle2.pt()); isCountedPi.at(0) = true; } - if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgFCutOnDeltaY) + if (std::abs(mcParticle1.y() - mcParticle2.y()) > deltaYConfigs.cfgFCutOnDeltaY) continue; if (!isCountedPi.at(1)) { mcPhiHist.fill(HIST("h2PhieffPiGenMCFCut"), genmultiplicity, mcParticle2.pt()); @@ -2108,7 +2310,7 @@ struct Phik0shortanalysis { mcPhiHist.fill(HIST("h2PhieffPiGenMCFCutAssocReco"), genmultiplicity, mcParticle2.pt()); isCountedPi.at(1) = true; } - if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgSCutOnDeltaY) + if (std::abs(mcParticle1.y() - mcParticle2.y()) > deltaYConfigs.cfgSCutOnDeltaY) continue; if (!isCountedPi.at(2)) { mcPhiHist.fill(HIST("h2PhieffPiGenMCSCut"), genmultiplicity, mcParticle2.pt()); @@ -2148,14 +2350,14 @@ struct Phik0shortanalysis { mcK0SHist.fill(HIST("h3K0SRapidityGenMC"), genmultiplicity, mcParticle1.pt(), mcParticle1.y()); - if (std::abs(mcParticle1.y()) > cfgYAcceptance) + if (std::abs(mcParticle1.y()) > deltaYConfigs.cfgYAcceptance) continue; mcK0SHist.fill(HIST("h2K0SMCGen"), genmultiplicity, mcParticle1.pt()); if (isAssocColl) mcK0SHist.fill(HIST("h2K0SMCGenAssocReco"), genmultiplicity, mcParticle1.pt()); - std::vector counts(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector counts(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); for (const auto& mcParticle2 : mcParticles) { if (mcParticle2.pdgCode() != o2::constants::physics::Pdg::kPhi) @@ -2176,18 +2378,18 @@ struct Phik0shortanalysis { } if (mcParticle2.pt() < minPhiPt || mcParticle2.pt() > maxPhiPt) continue; - if (std::abs(mcParticle2.y()) > cfgYAcceptance) + if (std::abs(mcParticle2.y()) > deltaYConfigs.cfgYAcceptance) continue; counts.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(mcParticle1.y() - mcParticle2.y()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; counts.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (counts.at(i) > 0) { mcPhiK0SHist.fill(HIST("h3PhiK0SMCGen"), i, genmultiplicity, mcParticle1.pt()); if (isAssocColl) @@ -2225,14 +2427,14 @@ struct Phik0shortanalysis { mcPionHist.fill(HIST("h3PiRapidityGenMC"), genmultiplicity, mcParticle1.pt(), mcParticle1.y()); - if (std::abs(mcParticle1.y()) > cfgYAcceptance) + if (std::abs(mcParticle1.y()) > deltaYConfigs.cfgYAcceptance) continue; mcPionHist.fill(HIST("h2PiMCGen"), genmultiplicity, mcParticle1.pt()); if (isAssocColl) mcPionHist.fill(HIST("h2PiMCGenAssocReco"), genmultiplicity, mcParticle1.pt()); - std::vector counts(cfgDeltaYAcceptanceBins->size() + 1, 0); + std::vector counts(deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1, 0); for (const auto& mcParticle2 : mcParticles) { if (mcParticle2.pdgCode() != o2::constants::physics::Pdg::kPhi) @@ -2253,18 +2455,18 @@ struct Phik0shortanalysis { } if (mcParticle2.pt() < minPhiPt || mcParticle2.pt() > maxPhiPt) continue; - if (std::abs(mcParticle2.y()) > cfgYAcceptance) + if (std::abs(mcParticle2.y()) > deltaYConfigs.cfgYAcceptance) continue; counts.at(0)++; - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(mcParticle1.y() - mcParticle2.y()) > cfgDeltaYAcceptanceBins->at(i)) + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size(); i++) { + if (std::abs(mcParticle1.y() - mcParticle2.y()) > deltaYConfigs.cfgDeltaYAcceptanceBins->at(i)) continue; counts.at(i + 1)++; } } - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size() + 1; i++) { + for (size_t i = 0; i < deltaYConfigs.cfgDeltaYAcceptanceBins->size() + 1; i++) { if (counts.at(i) > 0) { mcPhiPionHist.fill(HIST("h3PhiPiMCGen"), i, genmultiplicity, mcParticle1.pt()); if (isAssocColl) @@ -2276,6 +2478,7 @@ struct Phik0shortanalysis { PROCESS_SWITCH(Phik0shortanalysis, processPhiPionMCGen, "Process function for Phi-Pion Correlations Efficiency correction in MCGen", false); + // dN/deta procedure void processdNdetaWPhiData(SelCollisions::iterator const& collision, FilteredTracks const& filteredTracks) { // Check if the event selection is passed @@ -2289,11 +2492,21 @@ struct Phik0shortanalysis { if (!eventHasPhi(posThisColl, negThisColl)) return; - float multiplicity = collision.centFT0M(); - dataEventHist.fill(HIST("hMultiplicityPercent"), multiplicity); + dataEventHist.fill(HIST("hMultiplicityPercent"), collision.centFT0M()); + dataEventHist.fill(HIST("h2VertexZvsMult"), collision.posZ(), collision.centFT0M()); + + for (const auto& track : filteredTracks) { + if (trackConfigs.applyExtraPhiCuts && ((track.phi() > trackConfigs.extraPhiCuts->at(0) && track.phi() < trackConfigs.extraPhiCuts->at(1)) || + track.phi() <= trackConfigs.extraPhiCuts->at(2) || track.phi() >= trackConfigs.extraPhiCuts->at(3))) + continue; - for (const auto& track : filteredTracks) - dataEventHist.fill(HIST("h2EtaDistribution"), multiplicity, track.eta()); + dataEventHist.fill(HIST("h5EtaDistribution"), collision.posZ(), collision.centFT0M(), track.eta(), track.phi(), kGlobalplusITSonly); + if (track.hasTPC()) { + dataEventHist.fill(HIST("h5EtaDistribution"), collision.posZ(), collision.centFT0M(), track.eta(), track.phi(), kGlobalonly); + } else { + dataEventHist.fill(HIST("h5EtaDistribution"), collision.posZ(), collision.centFT0M(), track.eta(), track.phi(), kITSonly); + } + } } PROCESS_SWITCH(Phik0shortanalysis, processdNdetaWPhiData, "Process function for dN/deta values in Data", false); @@ -2304,17 +2517,22 @@ struct Phik0shortanalysis { return; if (!collision.has_mcCollision()) return; - const auto& mcCollision = collision.mcCollision_as(); - auto mcParticlesThisColl = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + const auto& mcCollision = collision.mcCollision_as(); + auto mcParticlesThisColl = mcParticles.sliceBy(preslices.perMCColl, mcCollision.globalIndex()); - if (!eventHasMCPhi(mcParticlesThisColl)) + if (furtherCheckonMcCollision && (std::abs(mcCollision.posZ()) > cutZVertex || !pwglf::isINELgtNmc(mcParticlesThisColl, 0, pdgDB))) + return; + if (filterOnMcPhi && !eventHasMCPhi(mcParticlesThisColl)) return; - float genmultiplicity = mcCollision.centFT0M(); - mcEventHist.fill(HIST("hRecMCGenMultiplicityPercent"), genmultiplicity); + mcEventHist.fill(HIST("hRecoMCMultiplicityPercent"), mcCollision.centFT0M()); + mcEventHist.fill(HIST("h2RecoMCVertexZvsMult"), collision.posZ(), mcCollision.centFT0M()); for (const auto& track : filteredMCTracks) { + if (trackConfigs.applyExtraPhiCuts && ((track.phi() > trackConfigs.extraPhiCuts->at(0) && track.phi() < trackConfigs.extraPhiCuts->at(1)) || + track.phi() <= trackConfigs.extraPhiCuts->at(2) || track.phi() >= trackConfigs.extraPhiCuts->at(3))) + continue; if (!track.has_mcParticle()) continue; @@ -2322,65 +2540,113 @@ struct Phik0shortanalysis { if (!mcTrack.isPhysicalPrimary() || std::abs(mcTrack.eta()) > trackConfigs.etaMax) continue; - mcEventHist.fill(HIST("h2RecMCEtaDistribution"), genmultiplicity, mcTrack.eta()); + mcEventHist.fill(HIST("h6RecoMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), kSpAll, kGlobalplusITSonly); + if (track.hasTPC()) { + mcEventHist.fill(HIST("h6RecoMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), kSpAll, kGlobalonly); + } else { + mcEventHist.fill(HIST("h6RecoMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), kSpAll, kITSonly); + } + + int pid = fromPDGToEnum(mcTrack.pdgCode()); + mcEventHist.fill(HIST("h6RecoMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), pid, kGlobalplusITSonly); } for (const auto& mcParticle : mcParticlesThisColl) { - if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.eta()) > trackConfigs.etaMax) + if (!isGenParticleCharged(mcParticle)) continue; - auto pdgTrack = pdgDB->GetParticle(mcParticle.pdgCode()); - if (pdgTrack == nullptr) - continue; - if (pdgTrack->Charge() == trackConfigs.cfgCutCharge) - continue; + mcEventHist.fill(HIST("h6GenMCEtaDistributionReco"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kNoGenpTVar); + if (mcParticle.pt() < trackConfigs.cMinChargedParticlePtcut) { + mcEventHist.fill(HIST("h6GenMCEtaDistributionReco"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTup, -10.0f * mcParticle.pt() + 2.0f); + mcEventHist.fill(HIST("h6GenMCEtaDistributionReco"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTdown, 5.0f * mcParticle.pt() + 0.5f); + } else { + mcEventHist.fill(HIST("h6GenMCEtaDistributionReco"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTup); + mcEventHist.fill(HIST("h6GenMCEtaDistributionReco"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTdown); + } - mcEventHist.fill(HIST("h2GenMCEtaDistributionAssocReco"), genmultiplicity, mcParticle.eta()); + int pid = fromPDGToEnum(mcParticle.pdgCode()); + mcEventHist.fill(HIST("h6GenMCEtaDistributionReco"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), pid, kNoGenpTVar); } } PROCESS_SWITCH(Phik0shortanalysis, processdNdetaWPhiMCReco, "Process function for dN/deta values in MCReco", false); - void processdNdetaWPhiMCGen(MCCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles) + void processdNdetaWPhiMCGen(MCCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, FilteredMCTracks const& filteredMCTracks, aod::McParticles const& mcParticles) { if (std::abs(mcCollision.posZ()) > cutZVertex) return; if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) return; - if (!eventHasMCPhi(mcParticles)) + if (filterOnMcPhi && !eventHasMCPhi(mcParticles)) return; - bool isAssocColl = false; + uint64_t numberAssocColl = 0; for (const auto& collision : collisions) { if (acceptEventQA(collision, false)) { - isAssocColl = true; - break; + mcEventHist.fill(HIST("hGenMCRecoMultiplicityPercent"), mcCollision.centFT0M()); + mcEventHist.fill(HIST("h2GenMCRecoVertexZvsMult"), collision.posZ(), mcCollision.centFT0M()); + + auto filteredMCTracksThisColl = filteredMCTracks.sliceBy(preslices.perColl, collision.globalIndex()); + for (const auto& track : filteredMCTracksThisColl) { + if (trackConfigs.applyExtraPhiCuts && ((track.phi() > trackConfigs.extraPhiCuts->at(0) && track.phi() < trackConfigs.extraPhiCuts->at(1)) || + track.phi() <= trackConfigs.extraPhiCuts->at(2) || track.phi() >= trackConfigs.extraPhiCuts->at(3))) + continue; + if (!track.has_mcParticle()) + continue; + + auto mcTrack = track.mcParticle(); + if (!mcTrack.isPhysicalPrimary() || std::abs(mcTrack.eta()) > trackConfigs.etaMax) + continue; + + mcEventHist.fill(HIST("h6RecoCheckMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), kSpAll, kGlobalplusITSonly); + if (track.hasTPC()) { + mcEventHist.fill(HIST("h6RecoCheckMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), kSpAll, kGlobalonly); + } else { + mcEventHist.fill(HIST("h6RecoCheckMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), kSpAll, kITSonly); + } + + int pid = fromPDGToEnum(mcTrack.pdgCode()); + mcEventHist.fill(HIST("h6RecoCheckMCEtaDistribution"), collision.posZ(), mcCollision.centFT0M(), mcTrack.eta(), mcTrack.phi(), pid, kGlobalplusITSonly); + } + + for (const auto& mcParticle : mcParticles) { + if (!isGenParticleCharged(mcParticle)) + continue; + + mcEventHist.fill(HIST("h6GenMCEtaDistributionRecoCheck"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kNoGenpTVar); + if (mcParticle.pt() < trackConfigs.cMinChargedParticlePtcut) { + mcEventHist.fill(HIST("h6GenMCEtaDistributionRecoCheck"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTup, -10.0f * mcParticle.pt() + 2.0f); + mcEventHist.fill(HIST("h6GenMCEtaDistributionRecoCheck"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTdown, 5.0f * mcParticle.pt() + 0.5f); + } else { + mcEventHist.fill(HIST("h6GenMCEtaDistributionRecoCheck"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTup); + mcEventHist.fill(HIST("h6GenMCEtaDistributionRecoCheck"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), kSpAll, kGenpTdown); + } + + int pid = fromPDGToEnum(mcParticle.pdgCode()); + mcEventHist.fill(HIST("h6GenMCEtaDistributionRecoCheck"), collision.posZ(), mcCollision.centFT0M(), mcParticle.eta(), mcParticle.phi(), pid, kNoGenpTVar); + } + + numberAssocColl++; } } - float genmultiplicity = mcCollision.centFT0M(); - mcEventHist.fill(HIST("hGenMCMultiplicityPercent"), genmultiplicity); - if (isAssocColl) - mcEventHist.fill(HIST("hGenMCAssocRecoMultiplicityPercent"), genmultiplicity); + mcEventHist.fill(HIST("hGenMCMultiplicityPercent"), mcCollision.centFT0M()); + if (numberAssocColl > 0) + mcEventHist.fill(HIST("hGenMCAssocRecoMultiplicityPercent"), mcCollision.centFT0M()); for (const auto& mcParticle : mcParticles) { - if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.eta()) > trackConfigs.etaMax) - continue; - - auto pdgTrack = pdgDB->GetParticle(mcParticle.pdgCode()); - if (pdgTrack == nullptr) - continue; - if (pdgTrack->Charge() == trackConfigs.cfgCutCharge) + if (!isGenParticleCharged(mcParticle)) continue; - mcEventHist.fill(HIST("h2GenMCEtaDistribution"), genmultiplicity, mcParticle.eta()); - if (isAssocColl) - mcEventHist.fill(HIST("h2GenMCEtaDistributionAssocReco2"), genmultiplicity, mcParticle.eta()); + mcEventHist.fill(HIST("h2GenMCEtaDistribution"), mcCollision.centFT0M(), mcParticle.eta()); + if (numberAssocColl > 0) + mcEventHist.fill(HIST("h2GenMCEtaDistributionAssocReco"), mcCollision.centFT0M(), mcParticle.eta()); } } PROCESS_SWITCH(Phik0shortanalysis, processdNdetaWPhiMCGen, "Process function for dN/deta values in MCGen", false); + // New 2D analysis procedure void processPhiK0SPionData2D(SelCollisions::iterator const& collision, FullTracks const& fullTracks, FullV0s const& V0s, V0DauTracks const&) { // Check if the event selection is passed @@ -2397,8 +2663,6 @@ struct Phik0shortanalysis { bool isCountedPhi = false; bool isFilledhV0 = false; - double weight{1.0}; - // Loop over all positive tracks for (const auto& track1 : posThisColl) { if (!selectionTrackResonance(track1, true) || !selectionPIDKaonpTdependent(track1)) @@ -2422,7 +2686,7 @@ struct Phik0shortanalysis { ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); if (recPhi.Pt() < minPhiPt || recPhi.Pt() > maxPhiPt) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPhi) { @@ -2431,10 +2695,14 @@ struct Phik0shortanalysis { isCountedPhi = true; } - if (fillMethodSingleWeight) - weight *= (1 - getPhiPurity(multiplicity, recPhi)); - - dataPhiHist.fill(HIST("h3PhipurData"), multiplicity, recPhi.Pt(), recPhi.M()); + float efficiencyPhi = 1.0f; + if (applyEfficiency) { + efficiencyPhi = effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()); + if (efficiencyPhi == 0) + efficiencyPhi = 1.0f; + } + float weightPhi = applyEfficiency ? 1.0f / efficiencyPhi : 1.0f; + dataPhiHist.fill(HIST("h3PhiDataNewProc"), multiplicity, recPhi.Pt(), recPhi.M(), weightPhi); // V0 already reconstructed by the builder for (const auto& v0 : V0s) { @@ -2458,15 +2726,17 @@ struct Phik0shortanalysis { } } - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) continue; - dataPhiK0SHist.fill(HIST("h5PhiK0SData"), 0, multiplicity, v0.pt(), v0.mK0Short(), recPhi.M()); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) - continue; - dataPhiK0SHist.fill(HIST("h5PhiK0SData"), i + 1, multiplicity, v0.pt(), v0.mK0Short(), recPhi.M()); + float efficiencyPhiK0S = 1.0f; + if (applyEfficiency) { + efficiencyPhiK0S = effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapK0S->Interpolate(multiplicity, v0.pt(), v0.yK0Short()); + if (efficiencyPhiK0S == 0) + efficiencyPhiK0S = 1.0f; } + float weightPhiK0S = applyEfficiency ? 1.0f / efficiencyPhiK0S : 1.0f; + dataPhiK0SHist.fill(HIST("h5PhiK0SDataNewProc"), v0.yK0Short() - recPhi.Rapidity(), multiplicity, v0.pt(), v0.mK0Short(), recPhi.M(), weightPhiK0S); } isFilledhV0 = true; @@ -2476,23 +2746,22 @@ struct Phik0shortanalysis { if (!selectionPion(track, false)) continue; - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) continue; - float nSigmaTOFPi = (track.hasTOF() ? track.tofNSigmaPi() : -999); - - dataPhiPionHist.fill(HIST("h6PhiPiData"), 0, multiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M()); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) - continue; - dataPhiPionHist.fill(HIST("h6PhiPiData"), i + 1, multiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M()); + float efficiencyPhiPion = 1.0f; + if (applyEfficiency) { + efficiencyPhiPion = track.pt() < trackConfigs.pTToUseTOF ? effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPionTPC->Interpolate(multiplicity, track.pt(), track.rapidity(massPi)) : effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPionTPCTOF->Interpolate(multiplicity, track.pt(), track.rapidity(massPi)); + if (efficiencyPhiPion == 0) + efficiencyPhiPion = 1.0f; } + float weightPhiPion = applyEfficiency ? 1.0f / efficiencyPhiPion : 1.0f; + dataPhiPionHist.fill(HIST("h5PhiPiTPCDataNewProc"), track.rapidity(massPi) - recPhi.Rapidity(), multiplicity, track.pt(), track.tpcNSigmaPi(), recPhi.M(), weightPhiPion); + if (track.hasTOF()) + dataPhiPionHist.fill(HIST("h5PhiPiTOFDataNewProc"), track.rapidity(massPi) - recPhi.Rapidity(), multiplicity, track.pt(), track.tofNSigmaPi(), recPhi.M(), weightPhiPion); } } } - - weight = 1 - weight; - dataEventHist.fill(HIST("hEventSelection"), 5, weight); // at least a Phi in the event } PROCESS_SWITCH(Phik0shortanalysis, processPhiK0SPionData2D, "Process function for Phi-K0S and Phi-Pion Correlations in Data2D", false); @@ -2508,7 +2777,7 @@ struct Phik0shortanalysis { const auto& mcCollision = collision.mcCollision_as(); float genmultiplicity = mcCollision.centFT0M(); - mcEventHist.fill(HIST("hRecMCGenMultiplicityPercent"), genmultiplicity); + mcEventHist.fill(HIST("hRecoMCMultiplicityPercent"), genmultiplicity); // Defining positive and negative tracks for phi reconstruction auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); @@ -2516,8 +2785,6 @@ struct Phik0shortanalysis { bool isCountedPhi = false; - double weight{1.0}; - // Loop over all positive tracks for (const auto& track1 : posThisColl) { if (!selectionTrackResonance(track1, true) || !selectionPIDKaonpTdependent(track1)) @@ -2537,19 +2804,23 @@ struct Phik0shortanalysis { ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); if (recPhi.Pt() < minPhiPt || recPhi.Pt() > maxPhiPt) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) continue; if (!isCountedPhi) { mcEventHist.fill(HIST("hRecMCEventSelection"), 7); // at least a Phi candidate in the event - mcEventHist.fill(HIST("hRecMCGenMultiplicityPercentWithPhi"), genmultiplicity); + mcEventHist.fill(HIST("hRecoMCMultiplicityPercentWithPhi"), genmultiplicity); isCountedPhi = true; } - if (fillMethodSingleWeight) - weight *= (1 - getPhiPurity(genmultiplicity, recPhi)); - - closureMCPhiHist.fill(HIST("h3PhipurMCClosure"), genmultiplicity, recPhi.Pt(), recPhi.M()); + float efficiencyPhi = 1.0f; + if (applyEfficiency) { + efficiencyPhi = effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()); + if (efficiencyPhi == 0) + efficiencyPhi = 1.0f; + } + float weightPhi = applyEfficiency ? 1.0f / efficiencyPhi : 1.0f; + closureMCPhiHist.fill(HIST("h3PhiMCClosureNewProc"), genmultiplicity, recPhi.Pt(), recPhi.M(), weightPhi); // V0 already reconstructed by the builder for (const auto& v0 : V0s) { @@ -2569,15 +2840,17 @@ struct Phik0shortanalysis { if (v0Configs.cfgFurtherV0Selection && !furtherSelectionV0(v0, collision)) continue; - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) continue; - closureMCPhiK0SHist.fill(HIST("h5PhiK0SMCClosure"), 0, genmultiplicity, v0.pt(), v0.mK0Short(), recPhi.M()); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) - continue; - closureMCPhiK0SHist.fill(HIST("h5PhiK0SMCClosure"), i + 1, genmultiplicity, v0.pt(), v0.mK0Short(), recPhi.M()); + float efficiencyPhiK0S = 1.0f; + if (applyEfficiency) { + efficiencyPhiK0S = effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapK0S->Interpolate(genmultiplicity, v0.pt(), v0.yK0Short()); + if (efficiencyPhiK0S == 0) + efficiencyPhiK0S = 1.0f; } + float weightPhiK0S = applyEfficiency ? 1.0f / efficiencyPhiK0S : 1.0f; + closureMCPhiK0SHist.fill(HIST("h5PhiK0SMCClosureNewProc"), v0.yK0Short() - recPhi.Rapidity(), genmultiplicity, v0.pt(), v0.mK0Short(), recPhi.M(), weightPhiK0S); } // Loop over all primary pion candidates @@ -2593,51 +2866,42 @@ struct Phik0shortanalysis { if (!selectionPion(track, false)) continue; - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) continue; - float nSigmaTOFPi = (track.hasTOF() ? track.tofNSigmaPi() : -999); - - closureMCPhiPionHist.fill(HIST("h6PhiPiMCClosure"), 0, genmultiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M()); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) - continue; - closureMCPhiPionHist.fill(HIST("h6PhiPiMCClosure"), i + 1, genmultiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M()); + float efficiencyPhiPion = 1.0f; + if (applyEfficiency) { + efficiencyPhiPion = track.pt() < trackConfigs.pTToUseTOF ? effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPionTPC->Interpolate(genmultiplicity, track.pt(), track.rapidity(massPi)) : effMapPhi->Interpolate(genmultiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPionTPCTOF->Interpolate(genmultiplicity, track.pt(), track.rapidity(massPi)); + if (efficiencyPhiPion == 0) + efficiencyPhiPion = 1.0f; } + float weightPhiPion = applyEfficiency ? 1.0f / efficiencyPhiPion : 1.0f; + closureMCPhiPionHist.fill(HIST("h5PhiPiTPCMCClosureNewProc"), track.rapidity(massPi) - recPhi.Rapidity(), genmultiplicity, track.pt(), track.tpcNSigmaPi(), recPhi.M(), weightPhiPion); + if (track.hasTOF()) + closureMCPhiPionHist.fill(HIST("h5PhiPiTOFMCClosureNewProc"), track.rapidity(massPi) - recPhi.Rapidity(), genmultiplicity, track.pt(), track.tofNSigmaPi(), recPhi.M(), weightPhiPion); } } } - - weight = 1 - weight; - mcEventHist.fill(HIST("hRecMCEventSelection"), 8, weight); // at least a Phi in the event } PROCESS_SWITCH(Phik0shortanalysis, processPhiK0SPionMCClosure2D, "Process function for Phi-K0S and Phi-Pion Correlations in MCClosure2D", false); - void processPhiK0SPionMCReco2D(SimCollisions::iterator const& collision, FullMCTracks const& fullMCTracks, FullMCV0s const& V0s, V0DauMCTracks const&, MCCollisions const&, aod::McParticles const&) + void processAllPartMCReco(SimCollisions::iterator const& collision, FullMCTracks const& fullMCTracks, FullMCV0s const& V0s, V0DauMCTracks const&, MCCollisions const&, aod::McParticles const& mcParticles) { - if (!acceptEventQA(collision, true)) + if (!acceptEventQA(collision, false)) return; - float multiplicity = collision.centFT0M(); - mcEventHist.fill(HIST("hRecMCMultiplicityPercent"), multiplicity); - if (!collision.has_mcCollision()) return; - mcEventHist.fill(HIST("hRecMCEventSelection"), 6); // with at least a gen collision const auto& mcCollision = collision.mcCollision_as(); float genmultiplicity = mcCollision.centFT0M(); - mcEventHist.fill(HIST("hRecMCGenMultiplicityPercent"), genmultiplicity); // Defining positive and negative tracks for phi reconstruction auto posThisColl = posMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); auto negThisColl = negMCTracks->sliceByCached(aod::track::collisionId, collision.globalIndex(), cache); - bool isCountedPhi = false; - - // Loop over all positive tracks - for (const auto& track1 : posThisColl) { + for (const auto& track1 : posThisColl) { // loop over all selected tracks if (!selectionTrackResonance(track1, false) || !selectionPIDKaonpTdependent(track1)) continue; // topological and PID selection @@ -2649,7 +2913,6 @@ struct Phik0shortanalysis { if (mcTrack1.pdgCode() != PDG_t::kKPlus || !mcTrack1.isPhysicalPrimary()) continue; - // Loop over all negative tracks for (const auto& track2 : negThisColl) { if (!selectionTrackResonance(track2, false) || !selectionPIDKaonpTdependent(track2)) continue; // topological and PID selection @@ -2664,6 +2927,8 @@ struct Phik0shortanalysis { if (mcTrack2.pdgCode() != PDG_t::kKMinus || !mcTrack2.isPhysicalPrimary()) continue; + float pTMother = -1.0f; + float yMother = -1.0f; bool isMCMotherPhi = false; for (const auto& motherOfMcTrack1 : mcTrack1.mothers_as()) { for (const auto& motherOfMcTrack2 : mcTrack2.mothers_as()) { @@ -2673,83 +2938,273 @@ struct Phik0shortanalysis { continue; if (motherOfMcTrack1.pdgCode() != o2::constants::physics::Pdg::kPhi) continue; + + pTMother = motherOfMcTrack1.pt(); + yMother = motherOfMcTrack1.y(); isMCMotherPhi = true; } } + if (!isMCMotherPhi) continue; - - ROOT::Math::PxPyPzMVector recPhi = recMother(track1, track2, massKa, massKa); - if (recPhi.Pt() < minPhiPt || recPhi.Pt() > maxPhiPt) + if (pTMother < minPhiPt || std::abs(yMother) > deltaYConfigs.cfgYAcceptance) continue; - if (std::abs(recPhi.Rapidity()) > cfgYAcceptance) - continue; + mcPhiHist.fill(HIST("h3PhiMCRecoNewProc"), genmultiplicity, pTMother, yMother); + } + } - if (!isCountedPhi) { - mcEventHist.fill(HIST("hRecMCEventSelection"), 7); // at least a Phi in the event - isCountedPhi = true; + for (const auto& v0 : V0s) { + if (!v0.has_mcParticle()) + continue; + + auto v0mcparticle = v0.mcParticle(); + if (v0mcparticle.pdgCode() != PDG_t::kK0Short || !v0mcparticle.isPhysicalPrimary()) + continue; + + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + + if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) + continue; + if (v0Configs.cfgFurtherV0Selection && !furtherSelectionV0(v0, collision)) + continue; + if (std::abs(v0mcparticle.y()) > deltaYConfigs.cfgYAcceptance) + continue; + + mcK0SHist.fill(HIST("h3K0SMCRecoNewProc"), genmultiplicity, v0mcparticle.pt(), v0mcparticle.y()); + } + + for (const auto& track : fullMCTracks) { + // Pion selection + if (!selectionPion(track, false)) + continue; + + if (!track.has_mcParticle()) + continue; + + auto mcTrack = track.mcParticle_as(); + if (std::abs(mcTrack.pdgCode()) != PDG_t::kPiPlus) + continue; + + if (std::abs(mcTrack.y()) > deltaYConfigs.cfgYAcceptance) + continue; + + // Primary pion selection + if (mcTrack.isPhysicalPrimary()) { + mcPionHist.fill(HIST("h3RecMCDCAxyPrimPi"), track.pt(), track.dcaXY()); + } else { + if (mcTrack.getProcess() == 4) { // Selection of secondary pions from weak decay + mcPionHist.fill(HIST("h3RecMCDCAxySecWeakDecayPi"), track.pt(), track.dcaXY()); + } else { // Selection of secondary pions from material interactions + mcPionHist.fill(HIST("h3RecMCDCAxySecMaterialPi"), track.pt(), track.dcaXY()); } + continue; + } - // V0 already reconstructed by the builder - for (const auto& v0 : V0s) { - if (!v0.has_mcParticle()) { - continue; - } + mcPionHist.fill(HIST("h3PiMCRecoNewProc"), genmultiplicity, mcTrack.pt(), mcTrack.y()); - auto v0mcparticle = v0.mcParticle(); - if (v0mcparticle.pdgCode() != PDG_t::kK0Short || !v0mcparticle.isPhysicalPrimary()) - continue; + if (track.pt() >= trackConfigs.pTToUseTOF && !track.hasTOF()) + continue; - const auto& posDaughterTrack = v0.posTrack_as(); - const auto& negDaughterTrack = v0.negTrack_as(); + mcPionHist.fill(HIST("h3PiMCReco2NewProc"), genmultiplicity, mcTrack.pt(), mcTrack.y()); + } - // Cut on V0 dynamic columns - if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) - continue; - if (v0Configs.cfgFurtherV0Selection && !furtherSelectionV0(v0, collision)) - continue; + // Defining McParticles in the collision + auto mcParticlesThisColl = mcParticles.sliceByCached(aod::mcparticle::mcCollisionId, mcCollision.globalIndex(), cache); + + for (const auto& mcParticle : mcParticlesThisColl) { + if (std::abs(mcParticle.y()) > deltaYConfigs.cfgYAcceptance) + continue; + + // Phi selection + if (mcParticle.pdgCode() == o2::constants::physics::Pdg::kPhi && mcParticle.pt() >= minPhiPt) + mcPhiHist.fill(HIST("h3PhiMCGenRecoCheckNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + + // K0S selection + if (mcParticle.pdgCode() == PDG_t::kK0Short && mcParticle.isPhysicalPrimary() && mcParticle.pt() >= v0Configs.v0SettingMinPt) + mcK0SHist.fill(HIST("h3K0SMCGenRecoCheckNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + + // Pion selection + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus && mcParticle.isPhysicalPrimary() && mcParticle.pt() >= trackConfigs.cMinPionPtcut) + mcPionHist.fill(HIST("h3PiMCGenRecoCheckNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + } + } + + PROCESS_SWITCH(Phik0shortanalysis, processAllPartMCReco, "Process function for all particles in MCReco", false); + + void processAllPartMCGen(MCCollisions::iterator const& mcCollision, soa::SmallGroups const& collisions, aod::McParticles const& mcParticles) + { + if (std::abs(mcCollision.posZ()) > cutZVertex) + return; + if (!pwglf::isINELgtNmc(mcParticles, 0, pdgDB)) + return; + + float genmultiplicity = mcCollision.centFT0M(); + + uint64_t numberAssocColl = 0; + for (const auto& collision : collisions) { + if (acceptEventQA(collision, false)) { + mcEventHist.fill(HIST("hGenMCRecoMultiplicityPercent"), genmultiplicity); // Event split numerator - if (std::abs(v0.yK0Short()) > cfgYAcceptance) + for (const auto& mcParticle : mcParticles) { + // The inclusive number of particles is the signal loss denominator, + // while the number of associated particles is the signal loss numerator + if (std::abs(mcParticle.y()) > deltaYConfigs.cfgYAcceptance) continue; - mcPhiK0SHist.fill(HIST("h5PhiK0SMCClosure"), 0, genmultiplicity, v0.pt(), v0.mK0Short(), recPhi.M()); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(v0.yK0Short() - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) - continue; - mcPhiK0SHist.fill(HIST("h5PhiK0SMCClosure"), i + 1, genmultiplicity, v0.pt(), v0.mK0Short(), recPhi.M()); - } + // Phi selection + if (mcParticle.pdgCode() == o2::constants::physics::Pdg::kPhi && mcParticle.pt() >= minPhiPt) + mcPhiHist.fill(HIST("h3PhiMCGenRecoNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + + // K0S selection + if (mcParticle.pdgCode() == PDG_t::kK0Short && mcParticle.isPhysicalPrimary() && mcParticle.pt() >= v0Configs.v0SettingMinPt) + mcK0SHist.fill(HIST("h3K0SMCGenRecoNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + + // Pion selection + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus && mcParticle.isPhysicalPrimary() && mcParticle.pt() >= trackConfigs.cMinPionPtcut) + mcPionHist.fill(HIST("h3PiMCGenRecoNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); } - // Loop over all primary pion candidates - for (const auto& track : fullMCTracks) { - if (!track.has_mcParticle()) - continue; + numberAssocColl++; + } + } - auto mcTrack = track.mcParticle_as(); - if (std::abs(mcTrack.pdgCode()) != PDG_t::kPiPlus || !mcTrack.isPhysicalPrimary()) - continue; + // The inclusive number of events is the event loss denominator, + // while the number of associated events is the event loss numerator + mcEventHist.fill(HIST("hGenMCMultiplicityPercent"), genmultiplicity); + if (numberAssocColl > 0) + mcEventHist.fill(HIST("hGenMCAssocRecoMultiplicityPercent"), genmultiplicity); - if (!selectionPion(track, false)) - continue; + for (const auto& mcParticle : mcParticles) { + // The inclusive number of particles is the signal loss denominator, + // while the number of associated particles is the signal loss numerator + if (std::abs(mcParticle.y()) > deltaYConfigs.cfgYAcceptance) + continue; - if (std::abs(track.rapidity(massPi)) > cfgYAcceptance) - continue; + // Phi selection + if (mcParticle.pdgCode() == o2::constants::physics::Pdg::kPhi && mcParticle.pt() >= minPhiPt) { + mcPhiHist.fill(HIST("h3PhiMCGenNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + if (numberAssocColl > 0) + mcPhiHist.fill(HIST("h3PhiMCGenAssocRecoNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + } - float nSigmaTOFPi = (track.hasTOF() ? track.tofNSigmaPi() : -999); + // K0S selection + if (mcParticle.pdgCode() == PDG_t::kK0Short && mcParticle.isPhysicalPrimary() && mcParticle.pt() >= v0Configs.v0SettingMinPt) { + mcK0SHist.fill(HIST("h3K0SMCGenNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + if (numberAssocColl > 0) + mcK0SHist.fill(HIST("h3K0SMCGenAssocRecoNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + } - closureMCPhiPionHist.fill(HIST("h6PhiPiMCClosure"), 0, genmultiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M()); - for (size_t i = 0; i < cfgDeltaYAcceptanceBins->size(); i++) { - if (std::abs(track.rapidity(massPi) - recPhi.Rapidity()) > cfgDeltaYAcceptanceBins->at(i)) - continue; - closureMCPhiPionHist.fill(HIST("h6PhiPiMCClosure"), i + 1, genmultiplicity, track.pt(), track.tpcNSigmaPi(), nSigmaTOFPi, recPhi.M()); - } + // Pion selection + if (std::abs(mcParticle.pdgCode()) == PDG_t::kPiPlus && mcParticle.isPhysicalPrimary() && mcParticle.pt() >= trackConfigs.cMinPionPtcut) { + mcPionHist.fill(HIST("h3PiMCGenNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + if (numberAssocColl > 0) + mcPionHist.fill(HIST("h3PiMCGenAssocRecoNewProc"), genmultiplicity, mcParticle.pt(), mcParticle.y()); + } + } + } + + PROCESS_SWITCH(Phik0shortanalysis, processAllPartMCGen, "Process function for all particles in MCGen", false); + + void processPhiK0SMixingEvent(SelCollisions const& collisions, FullTracks const& fullTracks, FullV0s const& V0s, V0DauTracks const&) + { + auto tracksV0sTuple = std::make_tuple(fullTracks, V0s); + Pair pairPhiK0S{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tracksV0sTuple, &cache}; + + for (auto const& [collision1, tracks1, collision2, v0s2] : pairPhiK0S) { + float multiplicity = collision1.centFT0M(); + + Partition posMixTracks = aod::track::signed1Pt > trackConfigs.cfgCutCharge; + posMixTracks.bindTable(tracks1); + Partition negMixTracks = aod::track::signed1Pt < trackConfigs.cfgCutCharge; + negMixTracks.bindTable(tracks1); + + for (const auto& [posTrack1, negTrack1, v0] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(posMixTracks, negMixTracks, v0s2))) { + if (!selectionTrackResonance(posTrack1, true) || !selectionPIDKaonpTdependent(posTrack1)) + continue; + if (!selectionTrackResonance(negTrack1, true) || !selectionPIDKaonpTdependent(negTrack1)) + continue; + if (posTrack1.globalIndex() == negTrack1.globalIndex()) + continue; + + ROOT::Math::PxPyPzMVector recPhi = recMother(posTrack1, negTrack1, massKa, massKa); + if (recPhi.Pt() < minPhiPt) + continue; + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) + continue; + + const auto& posDaughterTrack = v0.posTrack_as(); + const auto& negDaughterTrack = v0.negTrack_as(); + + if (!selectionV0(v0, posDaughterTrack, negDaughterTrack)) + continue; + if (v0Configs.cfgFurtherV0Selection && !furtherSelectionV0(v0, collision2)) + continue; + if (std::abs(v0.yK0Short()) > deltaYConfigs.cfgYAcceptance) + continue; + + float efficiencyPhiK0S = 1.0f; + if (applyEfficiency) { + efficiencyPhiK0S = effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapK0S->Interpolate(multiplicity, v0.pt(), v0.yK0Short()); + if (efficiencyPhiK0S == 0) + efficiencyPhiK0S = 1.0f; + } + float weightPhiK0S = applyEfficiency ? 1.0f / efficiencyPhiK0S : 1.0f; + mePhiK0SHist.fill(HIST("h5PhiK0SMENewProc"), v0.yK0Short() - recPhi.Rapidity(), multiplicity, v0.pt(), v0.mK0Short(), recPhi.M(), weightPhiK0S); + } + } + } + + PROCESS_SWITCH(Phik0shortanalysis, processPhiK0SMixingEvent, "Process Mixed Event for Phi-K0S Analysis", false); + + void processPhiPionMixingEvent(SelCollisions const& collisions, FullTracks const& fullTracks) + { + auto tracksTuple = std::make_tuple(fullTracks); + SameKindPair pairPhiPion{binningOnVertexAndCent, cfgNoMixedEvents, -1, collisions, tracksTuple, &cache}; + + for (auto const& [collision1, tracks1, collision2, tracks2] : pairPhiPion) { + float multiplicity = collision1.centFT0M(); + + Partition posMixTracks = aod::track::signed1Pt > trackConfigs.cfgCutCharge; + posMixTracks.bindTable(tracks1); + Partition negMixTracks = aod::track::signed1Pt < trackConfigs.cfgCutCharge; + negMixTracks.bindTable(tracks1); + + for (const auto& [posTrack1, negTrack1, track] : o2::soa::combinations(o2::soa::CombinationsFullIndexPolicy(posMixTracks, negMixTracks, tracks2))) { + if (!selectionTrackResonance(posTrack1, true) || !selectionPIDKaonpTdependent(posTrack1)) + continue; + if (!selectionTrackResonance(negTrack1, true) || !selectionPIDKaonpTdependent(negTrack1)) + continue; + if (posTrack1.globalIndex() == negTrack1.globalIndex()) + continue; + + ROOT::Math::PxPyPzMVector recPhi = recMother(posTrack1, negTrack1, massKa, massKa); + if (recPhi.Pt() < minPhiPt) + continue; + if (std::abs(recPhi.Rapidity()) > deltaYConfigs.cfgYAcceptance) + continue; + + if (!selectionPion(track, false)) + continue; + if (std::abs(track.rapidity(massPi)) > deltaYConfigs.cfgYAcceptance) + continue; + + float efficiencyPhiPion = 1.0f; + if (applyEfficiency) { + efficiencyPhiPion = track.pt() < trackConfigs.pTToUseTOF ? effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPionTPC->Interpolate(multiplicity, track.pt(), track.rapidity(massPi)) : effMapPhi->Interpolate(multiplicity, recPhi.Pt(), recPhi.Rapidity()) * effMapPionTPCTOF->Interpolate(multiplicity, track.pt(), track.rapidity(massPi)); + if (efficiencyPhiPion == 0) + efficiencyPhiPion = 1.0f; } + float weightPhiPion = applyEfficiency ? 1.0f / efficiencyPhiPion : 1.0f; + mePhiPionHist.fill(HIST("h5PhiPiTPCMENewProc"), track.rapidity(massPi) - recPhi.Rapidity(), multiplicity, track.pt(), track.tpcNSigmaPi(), recPhi.M(), weightPhiPion); + if (track.hasTOF()) + mePhiPionHist.fill(HIST("h5PhiPiTOFMENewProc"), track.rapidity(massPi) - recPhi.Rapidity(), multiplicity, track.pt(), track.tofNSigmaPi(), recPhi.M(), weightPhiPion); } } } - PROCESS_SWITCH(Phik0shortanalysis, processPhiK0SPionMCReco2D, "Process function for Phi-K0S and Phi-Pion Correlations Efficiency correction in MCReco2D", false); + PROCESS_SWITCH(Phik0shortanalysis, processPhiPionMixingEvent, "Process Mixed Event for Phi-Pion Analysis", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/sigmaminustask.cxx b/PWGLF/Tasks/Strangeness/sigmaminustask.cxx deleted file mode 100644 index 8b309476913..00000000000 --- a/PWGLF/Tasks/Strangeness/sigmaminustask.cxx +++ /dev/null @@ -1,77 +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 sigmaminustask.cxx -/// \brief Example of a simple task for the analysis of the Sigma-minus -/// \author Francesco Mazzaschi - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Common/DataModel/EventSelection.h" -#include "PWGLF/DataModel/LFKinkDecayTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "ReconstructionDataFormats/PID.h" - -using namespace o2; -using namespace o2::framework; -using namespace o2::framework::expressions; - -using TracksFull = soa::Join; -using CollisionsFull = soa::Join; - -struct sigmaminustask { - // Histograms are defined with HistogramRegistry - HistogramRegistry rEventSelection{"eventSelection", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry rSigmaMinus{"sigmaminus", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - - // Configurable for event selection - Configurable cutzvertex{"cutzvertex", 10.0f, "Accepted z-vertex range (cm)"}; - Configurable cutNSigmaPi{"cutNSigmaPi", 4, "NSigmaTPCPion"}; - - void init(InitContext const&) - { - // Axes - const AxisSpec ptAxis{50, -10, 10, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec nSigmaPiAxis{100, -5, 5, "n#sigma_{#pi}"}; - const AxisSpec sigmaMassAxis{100, 1.1, 1.4, "m (GeV/#it{c}^{2})"}; - const AxisSpec vertexZAxis{100, -15., 15., "vrtx_{Z} [cm]"}; - - // Event selection - rEventSelection.add("hVertexZRec", "hVertexZRec", {HistType::kTH1F, {vertexZAxis}}); - - // Sigma-minus reconstruction - rSigmaMinus.add("h2MassSigmaMinusPt", "h2MassSigmaMinusPt", {HistType::kTH2F, {ptAxis, sigmaMassAxis}}); - rSigmaMinus.add("h2NSigmaPiPt", "h2NSigmaPiPt", {HistType::kTH2F, {ptAxis, nSigmaPiAxis}}); - } - - void process(soa::Join::iterator const& collision, - aod::KinkCands const& KinkCands, TracksFull const&) - { - if (std::abs(collision.posZ()) > cutzvertex || !collision.sel8()) { - return; - } - rEventSelection.fill(HIST("hVertexZRec"), collision.posZ()); - for (const auto& kinkCand : KinkCands) { - auto dauTrack = kinkCand.trackDaug_as(); - if (abs(dauTrack.tpcNSigmaPi()) > cutNSigmaPi) { - continue; - } - rSigmaMinus.fill(HIST("h2MassSigmaMinusPt"), kinkCand.mothSign() * kinkCand.ptMoth(), kinkCand.mSigmaMinus()); - rSigmaMinus.fill(HIST("h2NSigmaPiPt"), kinkCand.mothSign() * kinkCand.ptMoth(), dauTrack.tpcNSigmaPi()); - } - } -}; - -WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) -{ - return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; -} diff --git a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx index b7e65345661..847c6421e54 100644 --- a/PWGLF/Tasks/Strangeness/strangenessInJets.cxx +++ b/PWGLF/Tasks/Strangeness/strangenessInJets.cxx @@ -12,47 +12,56 @@ /// \file strangenessInJets.cxx /// /// \brief task for analysis of strangeness in jets -/// \author Alberto Caliva (alberto.caliva@cern.ch), Francesca Ercolessi (francesca.ercolessi@cern.ch), Nicolò Jacazio (nicolo.jacazio@cern.ch) +/// \author Alberto Calivà (alberto.caliva@cern.ch) +/// \author Francesca Ercolessi (francesca.ercolessi@cern.ch) +/// \author Nicolò Jacazio (nicolo.jacazio@cern.ch) +/// \author Sara Pucillo (sara.pucillo@cern.ch) +/// /// \since May 22, 2024 -#include -#include -#include -#include -#include -#include -#include -#include -#include "CCDB/BasicCCDBManager.h" -#include "CCDB/CcdbApi.h" +#include "PWGJE/Core/JetBkgSubUtils.h" +#include "PWGJE/Core/JetDerivedDataUtilities.h" +#include "PWGJE/DataModel/Jet.h" +#include "PWGJE/DataModel/JetReducedData.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" + #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/EventSelection.h" #include "Common/DataModel/Multiplicity.h" #include "Common/DataModel/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.h" + +#include "CCDB/BasicCCDBManager.h" +#include "CCDB/CcdbApi.h" #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" +#include +#include +#include +#include +#include + +#include #include #include +#include +#include +#include #include #include -#include -#include -#include -#include -#include "PWGJE/Core/JetBkgSubUtils.h" -#include "PWGJE/Core/JetDerivedDataUtilities.h" -#include "PWGJE/DataModel/JetReducedData.h" -#include "PWGJE/DataModel/Jet.h" -#include "EventFiltering/Zorro.h" -#include "EventFiltering/ZorroSummary.h" +#include +#include +#include using namespace std; using namespace o2; @@ -64,132 +73,89 @@ using namespace o2::constants::physics; using namespace o2::constants::math; using std::array; +// Define convenient aliases for joined AOD tables using SelCollisions = soa::Join; using SimCollisions = soa::Join; -using StrHadronDaughterTracks = soa::Join; -using MCTracks = soa::Join; +using DaughterTracks = soa::Join; +using DaughterTracksMC = soa::Join; struct StrangenessInJets { + // Instantiate the CCDB service and API interface Service ccdb; o2::ccdb::CcdbApi ccdbApi; + // Instantiate the Zorro processor for skimmed data and define an output object Zorro zorro; OutputObj zorroSummary{"zorroSummary"}; + // Define histogram registries HistogramRegistry registryData{"registryData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryMC{"registryMC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry registryQC{"registryQC", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - // Global Parameters - Configurable particleOfInterest{"particleOfInterest", 0, "0=v0, 1=cascade, 2=pions, 3=k+-, 4=proton"}; - Configurable minJetPt{"minJetPt", 10.0, "Minimum pt of the jet"}; - Configurable rJet{"rJet", 0.3, "Jet resolution parameter R"}; - Configurable zVtx{"zVtx", 10.0, "Maximum zVertex"}; - Configurable deltaEtaEdge{"deltaEtaEdge", 0.05, "eta gap from the edge"}; - Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "Skimmed dataset processing"}; - - // Axis parameters - struct : ConfigurableGroup { - ConfigurableAxis binsPt{"binsPt", {VARIABLE_WIDTH, 0.0, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.25, 0.3, 0.35, 0.4, 0.45, 0.5, 0.55, 0.6, 0.65, 0.7, 0.75, 0.8, 0.85, 0.9, 0.95, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 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 binsDca{"binsDca", {VARIABLE_WIDTH, -3.0, -2.95, -2.9, -2.85, -2.8, -2.75, -2.7, -2.65, -2.6, -2.55, -2.5, -2.45, -2.4, -2.35, -2.3, -2.25, -2.2, -2.15, -2.1, -2.05, -2.0, -1.975, -1.95, -1.925, -1.9, -1.875, -1.85, -1.825, -1.8, -1.775, -1.75, -1.725, -1.7, -1.675, -1.65, -1.625, -1.6, -1.575, -1.55, -1.525, -1.5, -1.475, -1.45, -1.425, -1.4, -1.375, -1.35, -1.325, -1.3, -1.275, -1.25, -1.225, -1.2, -1.175, -1.15, -1.125, -1.1, -1.075, -1.05, -1.025, -1.0, -0.99, -0.98, -0.97, -0.96, -0.95, -0.94, -0.93, -0.92, -0.91, -0.9, -0.89, -0.88, -0.87, -0.86, -0.85, -0.84, -0.83, -0.82, -0.81, -0.8, -0.79, -0.78, -0.77, -0.76, -0.75, -0.74, -0.73, -0.72, -0.71, -0.7, -0.69, -0.68, -0.67, -0.66, -0.65, -0.64, -0.63, -0.62, -0.61, -0.6, -0.59, -0.58, -0.57, -0.56, -0.55, -0.54, -0.53, -0.52, -0.51, -0.5, -0.49, -0.48, -0.47, -0.46, -0.45, -0.44, -0.43, -0.42, -0.41, -0.4, -0.396, -0.392, -0.388, -0.384, -0.38, -0.376, -0.372, -0.368, -0.364, -0.36, -0.356, -0.352, -0.348, -0.344, -0.34, -0.336, -0.332, -0.328, -0.324, -0.32, -0.316, -0.312, -0.308, -0.304, -0.3, -0.296, -0.292, -0.288, -0.284, -0.28, -0.276, -0.272, -0.268, -0.264, -0.26, -0.256, -0.252, -0.248, -0.244, -0.24, -0.236, -0.232, -0.228, -0.224, -0.22, -0.216, -0.212, -0.208, -0.204, -0.2, -0.198, -0.196, -0.194, -0.192, -0.19, -0.188, -0.186, -0.184, -0.182, -0.18, -0.178, -0.176, -0.174, -0.172, -0.17, -0.168, -0.166, -0.164, -0.162, -0.16, -0.158, -0.156, -0.154, -0.152, -0.15, -0.148, -0.146, -0.144, -0.142, -0.14, -0.138, -0.136, -0.134, -0.132, -0.13, -0.128, -0.126, -0.124, -0.122, -0.12, -0.118, -0.116, -0.114, -0.112, -0.11, -0.108, -0.106, -0.104, -0.102, -0.1, -0.099, -0.098, -0.097, -0.096, -0.095, -0.094, -0.093, -0.092, -0.091, -0.09, -0.089, -0.088, -0.087, -0.086, -0.085, -0.084, -0.083, -0.082, -0.081, -0.08, -0.079, -0.078, -0.077, -0.076, -0.075, -0.074, -0.073, -0.072, -0.071, -0.07, -0.069, -0.068, -0.067, -0.066, -0.065, -0.064, -0.063, -0.062, -0.061, -0.06, -0.059, -0.058, -0.057, -0.056, -0.055, -0.054, -0.053, -0.052, -0.051, -0.05, -0.049, -0.048, -0.047, -0.046, -0.045, -0.044, -0.043, -0.042, -0.041, -0.04, -0.039, -0.038, -0.037, -0.036, -0.035, -0.034, -0.033, -0.032, -0.031, -0.03, -0.029, -0.028, -0.027, -0.026, -0.025, -0.024, -0.023, -0.022, -0.021, -0.02, -0.019, -0.018, -0.017, -0.016, -0.015, -0.014, -0.013, -0.012, -0.011, -0.01, -0.009, -0.008, -0.007, -0.006, -0.005, -0.004, -0.003, -0.002, -0.001, -0.0, 0.001, 0.002, 0.003, 0.004, 0.005, 0.006, 0.007, 0.008, 0.009, 0.01, 0.011, 0.012, 0.013, 0.014, 0.015, 0.016, 0.017, 0.018, 0.019, 0.02, 0.021, 0.022, 0.023, 0.024, 0.025, 0.026, 0.027, 0.028, 0.029, 0.03, 0.031, 0.032, 0.033, 0.034, 0.035, 0.036, 0.037, 0.038, 0.039, 0.04, 0.041, 0.042, 0.043, 0.044, 0.045, 0.046, 0.047, 0.048, 0.049, 0.05, 0.051, 0.052, 0.053, 0.054, 0.055, 0.056, 0.057, 0.058, 0.059, 0.06, 0.061, 0.062, 0.063, 0.064, 0.065, 0.066, 0.067, 0.068, 0.069, 0.07, 0.071, 0.072, 0.073, 0.074, 0.075, 0.076, 0.077, 0.078, 0.079, 0.08, 0.081, 0.082, 0.083, 0.084, 0.085, 0.086, 0.087, 0.088, 0.089, 0.09, 0.091, 0.092, 0.093, 0.094, 0.095, 0.096, 0.097, 0.098, 0.099, 0.1, 0.102, 0.104, 0.106, 0.108, 0.11, 0.112, 0.114, 0.116, 0.118, 0.12, 0.122, 0.124, 0.126, 0.128, 0.13, 0.132, 0.134, 0.136, 0.138, 0.14, 0.142, 0.144, 0.146, 0.148, 0.15, 0.152, 0.154, 0.156, 0.158, 0.16, 0.162, 0.164, 0.166, 0.168, 0.17, 0.172, 0.174, 0.176, 0.178, 0.18, 0.182, 0.184, 0.186, 0.188, 0.19, 0.192, 0.194, 0.196, 0.198, 0.2, 0.204, 0.208, 0.212, 0.216, 0.22, 0.224, 0.228, 0.232, 0.236, 0.24, 0.244, 0.248, 0.252, 0.256, 0.26, 0.264, 0.268, 0.272, 0.276, 0.28, 0.284, 0.288, 0.292, 0.296, 0.3, 0.304, 0.308, 0.312, 0.316, 0.32, 0.324, 0.328, 0.332, 0.336, 0.34, 0.344, 0.348, 0.352, 0.356, 0.36, 0.364, 0.368, 0.372, 0.376, 0.38, 0.384, 0.388, 0.392, 0.396, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1.0, 1.025, 1.05, 1.075, 1.1, 1.125, 1.15, 1.175, 1.2, 1.225, 1.25, 1.275, 1.3, 1.325, 1.35, 1.375, 1.4, 1.425, 1.45, 1.475, 1.5, 1.525, 1.55, 1.575, 1.6, 1.625, 1.65, 1.675, 1.7, 1.725, 1.75, 1.775, 1.8, 1.825, 1.85, 1.875, 1.9, 1.925, 1.95, 1.975, 2.0, 2.05, 2.1, 2.15, 2.2, 2.25, 2.3, 2.35, 2.4, 2.45, 2.5, 2.55, 2.6, 2.65, 2.7, 2.75, 2.8, 2.85, 2.9, 2.95, 3.0}, "Binning of DCA xy and z axis"}; - - } binsOptions; - - // Track Parameters - Configurable minITSnCls{"minITSnCls", 4.0f, "min number of ITS clusters"}; - Configurable minTPCnClsFound{"minTPCnClsFound", 80.0f, "min number of found TPC clusters"}; - Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 80.0f, "min number of TPC crossed rows"}; - Configurable minTpcNcrossedRowsOverFindable{"minTpcNcrossedRowsOverFindable", 0.8, "crossed rows/findable"}; - 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, "eta min"}; - Configurable etaMax{"etaMax", +0.8f, "eta max"}; - Configurable ptMinV0Proton{"ptMinV0Proton", 0.3f, "pt min of proton from V0"}; - Configurable ptMaxV0Proton{"ptMaxV0Proton", 10.0f, "pt max of proton from V0"}; - Configurable ptMinV0Pion{"ptMinV0Pion", 0.1f, "pt min of pion from V0"}; - Configurable ptMaxV0Pion{"ptMaxV0Pion", 1.5f, "pt max of pion from V0"}; - Configurable ptMinK0Pion{"ptMinK0Pion", 0.3f, "pt min of pion from K0"}; - Configurable ptMaxK0Pion{"ptMaxK0Pion", 10.0f, "pt max of pion 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 nsigmaTOFminPionMC{"nsigmaTOFminPionMC", -6.0f, "Minimum nsigma TOF for pion in MC"}; - Configurable nsigmaTOFmaxPionMC{"nsigmaTOFmaxPionMC", +6.0f, "Maximum nsigma TOF for pion in MC"}; - Configurable dcaxyMax{"dcaxyMax", 0.1f, "Maximum DCAxy to primary vertex"}; - Configurable dcazMax{"dcazMax", 0.1f, "Maximum DCAz to primary vertex"}; - Configurable requireITS{"requireITS", false, "require ITS hit"}; - Configurable requireTOF{"requireTOF", false, "require TOF hit"}; - - // V0 Parameters - Configurable minimumV0Radius{"minimumV0Radius", 0.5f, "Minimum V0 Radius"}; - Configurable maximumV0Radius{"maximumV0Radius", 40.0f, "Maximum V0 Radius"}; - Configurable dcanegtoPVmin{"dcanegtoPVmin", 0.1f, "Minimum DCA Neg To PV"}; - Configurable dcapostoPVmin{"dcapostoPVmin", 0.1f, "Minimum DCA Pos To PV"}; - Configurable v0cospaMin{"v0cospaMin", 0.99f, "Minimum V0 CosPA"}; - Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, "Maximum DCA Daughters"}; - - // Cascade Parameters - Configurable minimumCascRadius{"minimumCascRadius", 0.1f, "Minimum Cascade Radius"}; - Configurable maximumCascRadius{"maximumCascRadius", 40.0f, "Maximum Cascade Radius"}; - Configurable casccospaMin{"casccospaMin", 0.99f, "Minimum Cascade CosPA"}; - Configurable dcabachtopvMin{"dcabachtopvMin", 0.1f, "Minimum DCA bachelor to PV"}; - Configurable dcaV0topvMin{"dcaV0topvMin", 0.1f, "Minimum DCA V0 to PV"}; - Configurable dcaCascDaughtersMax{"dcaCascDaughtersMax", 0.5f, "Maximum DCA Daughters"}; - - // Re-weighting - Configurable applyReweighting{"applyReweighting", true, "apply reweighting"}; - Configurable urlToCcdb{"urlToCcdb", "http://alice-ccdb.cern.ch", "url of the personal ccdb"}; - Configurable pathToFile{"pathToFile", "", "path to file with reweighting"}; - Configurable histoNameWeightPiplusJet{"histoNameWeightPiplusJet", "", "reweighting histogram: Pi Plus in jet"}; - Configurable histoNameWeightPiplusUe{"histoNameWeightPiplusUe", "", "reweighting histogram: Pi Plus in ue"}; - Configurable histoNameWeightPiminusJet{"histoNameWeightPiminusJet", "", "reweighting histogram: Pi Minus in jet"}; - Configurable histoNameWeightPiminusUe{"histoNameWeightPiminusUe", "", "reweighting histogram: Pi Minus in ue"}; - Configurable histoNameWeightK0Jet{"histoNameWeightK0Jet", "", "reweighting histogram: K0 in jet"}; - Configurable histoNameWeightK0Ue{"histoNameWeightK0Ue", "", "reweighting histogram: K0 in ue"}; - Configurable histoNameWeightLambdaJet{"histoNameWeightLambdaJet", "", "reweighting histogram: lambda in jet"}; - Configurable histoNameWeightLambdaUe{"histoNameWeightLambdaUe", "", "reweighting histogram: lambda in ue"}; - Configurable histoNameWeightAntilambdaJet{"histoNameWeightAntilambdaJet", "", "reweighting histogram: antilambda in jet"}; - Configurable histoNameWeightAntilambdaUe{"histoNameWeightAntilambdaUe", "", "reweighting histogram: antilambda in ue"}; - Configurable histoNameWeightsXiInJet{"histoNameWeightsXiInJet", "", "reweighting histogram: xi in jet"}; - Configurable histoNameWeightsXiInUe{"histoNameWeightsXiInUe", "", "reweighting histogram: xi in ue"}; - Configurable histoNameWeightsAntiXiInJet{"histoNameWeightsAntiXiInJet", "", "reweighting histogram: antixi in jet"}; - Configurable histoNameWeightsAntiXiInUe{"histoNameWeightsAntiXiInUe", "", "reweighting histogram: antixi in ue"}; - - // Two-dimensional weights - TH2F* twodWeightsPiplusJet = nullptr; - TH2F* twodWeightsPiplusUe = nullptr; - TH2F* twodWeightsPiminusJet = nullptr; - TH2F* twodWeightsPiminusUe = nullptr; - TH2F* twodWeightsK0Jet; - TH2F* twodWeightsK0Ue; - TH2F* twodWeightsLambdaJet; - TH2F* twodWeightsLambdaUe; - TH2F* twodWeightsAntilambdaJet; - TH2F* twodWeightsAntilambdaUe; - TH1F* weightsXiInJet; - TH1F* weightsXiInUe; - TH1F* weightsAntiXiInJet; - TH1F* weightsAntiXiInUe; + // Global analysis parameters + Configurable particleOfInterest{"particleOfInterest", 0, "0 = K0 and Lambda, 1 = Xi and Omega"}; + Configurable minJetPt{"minJetPt", 10.0, "Minimum reconstructed pt of the jet (GeV/c)"}; + Configurable rJet{"rJet", 0.3, "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"}; + + // Track analysis parameters + Configurable minITSnCls{"minITSnCls", 4, "Minimum number of ITS clusters"}; + Configurable minNCrossedRowsTPC{"minNCrossedRowsTPC", 80, "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.3f, "Minimum pt of protons from V0"}; + Configurable ptMaxV0Proton{"ptMaxV0Proton", 10.0f, "Maximum pt of protons from V0"}; + Configurable ptMinV0Pion{"ptMinV0Pion", 0.1f, "Minimum pt of pions from V0"}; + Configurable ptMaxV0Pion{"ptMaxV0Pion", 1.5f, "Maximum pt of pions from V0"}; + Configurable ptMinK0Pion{"ptMinK0Pion", 0.3f, "Minimum pt of pions from K0"}; + Configurable ptMaxK0Pion{"ptMaxK0Pion", 10.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"}; + + // V0 analysis parameters + Configurable minimumV0Radius{"minimumV0Radius", 0.5f, "Minimum V0 Radius"}; + Configurable maximumV0Radius{"maximumV0Radius", 40.0f, "Maximum V0 Radius"}; + Configurable dcanegtoPVmin{"dcanegtoPVmin", 0.1f, "Minimum DCA of negative track to primary vertex"}; + Configurable dcapostoPVmin{"dcapostoPVmin", 0.1f, "Minimum DCA of positive track to primary vertex"}; + Configurable v0cospaMin{"v0cospaMin", 0.99f, "Minimum V0 cosine of pointing angle"}; + Configurable dcaV0DaughtersMax{"dcaV0DaughtersMax", 0.5f, "Maximum DCA between V0 daughters"}; + + // 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 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"}; // List of Particles - enum Option { KZeroLambda, - CascadePart, - ChargedPions, - ChargedKaon, - ProtonAntiproton }; + enum Option { kV0Particles, + kCascades }; - // Jet background subtraction + // Instantiate utility class for jet background subtraction JetBkgSubUtils backgroundSub; + // Initialize CCDB access and histogram registry for Zorro processing void initCCDB(aod::BCsWithTimestamps::iterator const& bc) { if (cfgSkimmedProcessing) { - zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), "fOmega"); + zorro.initCCDB(ccdb.service, bc.runNumber(), bc.timestamp(), triggerName.value); + zorro.populateHistRegistry(registryData, bc.runNumber()); } } @@ -199,251 +165,104 @@ struct StrangenessInJets { zorroSummary.setObject(zorro.getZorroSummary()); } - ccdb->setURL(urlToCcdb.value); - ccdb->setCaching(true); - ccdb->setLocalObjectValidityChecking(); - ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); - ccdb->setFatalWhenNull(false); - - if (applyReweighting) { - getReweightingHistograms(ccdb); - } else { - twodWeightsK0Jet = nullptr; - twodWeightsK0Ue = nullptr; - twodWeightsLambdaJet = nullptr; - twodWeightsLambdaUe = nullptr; - twodWeightsAntilambdaJet = nullptr; - twodWeightsAntilambdaUe = nullptr; - weightsXiInJet = nullptr; - weightsXiInUe = nullptr; - weightsAntiXiInJet = nullptr; - weightsAntiXiInUe = nullptr; - } - - // Event Counters - if (doprocessData) { - 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"}}); - } - - if (doprocessMCefficiency) { - registryMC.add("number_of_events_mc", "number of events in mc", HistType::kTH1D, {{10, 0, 10, "Event Cuts"}}); - } - - // QC Histograms - registryQC.add("deltaEtadeltaPhiJet", "deltaEtadeltaPhiJet", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, o2::constants::math::PIHalf, "#Delta#phi"}}); - registryQC.add("deltaEtadeltaPhi_ue", "deltaEtadeltaPhi_ue", HistType::kTH2F, {{200, -0.5, 0.5, "#Delta#eta"}, {200, 0, o2::constants::math::PIHalf, "#Delta#phi"}}); - registryQC.add("NchJetPlusUE", "NchJetPlusUE", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); - registryQC.add("NchJet", "NchJet", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); - registryQC.add("NchUE", "NchUE", HistType::kTH1F, {{100, 0, 100, "#it{N}_{ch}"}}); - registryQC.add("sumPtJetPlusUE", "sumPtJetPlusUE", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); - registryQC.add("sumPtJet", "sumPtJet", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); - registryQC.add("sumPtUE", "sumPtUE", HistType::kTH1F, {{500, 0, 50, "#it{p}_{T} (GeV/#it{c})"}}); - registryQC.add("nJets_found", "nJets_found", HistType::kTH1F, {{10, 0, 10, "#it{n}_{Jet}"}}); - registryQC.add("nJets_selected", "nJets_selected", HistType::kTH1F, {{10, 0, 10, "#it{n}_{Jet}"}}); - registryQC.add("dcaxy_vs_pt", "dcaxy_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{xy} (cm)"}}); - registryQC.add("dcaz_vs_pt", "dcaz_vs_pt", HistType::kTH2F, {{100, 0.0, 5.0, "#it{p}_{T} (GeV/#it{c})"}, {2000, -0.05, 0.05, "DCA_{z} (cm)"}}); - registryQC.add("jet_jet_overlaps", "jet_jet_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); - registryQC.add("jet_ue_overlaps", "jet_ue_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); - registryQC.add("ue_ue_overlaps", "ue_ue_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); - registryQC.add("tot_overlaps", "tot_overlaps", HistType::kTH2F, {{20, 0.0, 20.0, "#it{n}_{jet}"}, {200, 0.0, 200.0, "#it{n}_{overlaps}"}}); - registryQC.add("survivedK0", "survivedK0", HistType::kTH1F, {{20, 0, 20, "step"}}); - - // Multiplicity Binning + // 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"}; - const AxisSpec etaAxis{18, -0.9, 0.9, "#eta"}; - const AxisSpec ptAxisPi{binsOptions.binsPt, "#it{p}_{T} (GeV/#it{c})"}; const AxisSpec ptAxis{100, 0.0, 10.0, "#it{p}_{T} (GeV/#it{c})"}; - const AxisSpec nsigmaTOFAxis{200, -10, 10, "n#sigma_{TOF}"}; - const AxisSpec nsigmaTPCAxis{200, -10, 10, "n#sigma_{TPC}"}; - const AxisSpec dcaAxis{binsOptions.binsDca, "DCA_{xy} (cm)"}; 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})"}; const AxisSpec invMassOmegaAxis{200, 1.63, 1.71, "m_{p#piK} (GeV/#it{c}^{2})"}; - // Histograms for pions (data) - if (doprocessData || doprocessK0s) { + // Histograms for real data + if (doprocessData) { + + // 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"}}); + + // Histograms for analysis of strange hadrons switch (particleOfInterest) { - case KZeroLambda: - // Histograms for lambda (data) + case 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}); - // Histograms for K0s (data) 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}); break; - case CascadePart: - // Histograms for xi (data) + case 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}); - // Histograms for omega (data) 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}); break; - case ChargedPions: - registryData.add("piplus_tpc_in_jet", "piplus_tpc_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piplus_tof_in_jet", "piplus_tof_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piplus_tpc_in_ue", "piplus_tpc_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piplus_tof_in_ue", "piplus_tof_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piminus_tpc_in_jet", "piminus_tpc_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piminus_tof_in_jet", "piminus_tof_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piminus_tpc_in_ue", "piminus_tpc_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piminus_tof_in_ue", "piminus_tof_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piplus_dcaxy_in_jet", "piplus_dcaxy_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piplus_dcaxy_in_ue", "piplus_dcaxy_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piminus_dcaxy_in_jet", "piminus_dcaxy_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piminus_dcaxy_in_ue", "piminus_dcaxy_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - break; - case ChargedKaon: // Here we keep the name but just change the title to avoid rewriting everything - registryData.add("piplus_tpc_in_jet", "kaplus_tpc_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piplus_tof_in_jet", "kaplus_tof_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piplus_tpc_in_ue", "kaplus_tpc_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piplus_tof_in_ue", "kaplus_tof_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piminus_tpc_in_jet", "kaminus_tpc_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piminus_tof_in_jet", "kaminus_tof_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piminus_tpc_in_ue", "kaminus_tpc_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piminus_tof_in_ue", "kaminus_tof_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piplus_dcaxy_in_jet", "kaplus_dcaxy_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piplus_dcaxy_in_ue", "kaplus_dcaxy_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piminus_dcaxy_in_jet", "kaminus_dcaxy_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piminus_dcaxy_in_ue", "kaminus_dcaxy_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - break; - case ProtonAntiproton: // Here we keep the name but just change the title to avoid rewriting everything - registryData.add("piplus_tpc_in_jet", "prplus_tpc_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piplus_tof_in_jet", "prplus_tof_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piplus_tpc_in_ue", "prplus_tpc_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piplus_tof_in_ue", "prplus_tof_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piminus_tpc_in_jet", "prminus_tpc_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piminus_tof_in_jet", "prminus_tof_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piminus_tpc_in_ue", "prminus_tpc_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTPCAxis}); - registryData.add("piminus_tof_in_ue", "prminus_tof_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, nsigmaTOFAxis}); - registryData.add("piplus_dcaxy_in_jet", "prplus_dcaxy_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piplus_dcaxy_in_ue", "prplus_dcaxy_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piminus_dcaxy_in_jet", "prminus_dcaxy_in_jet", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryData.add("piminus_dcaxy_in_ue", "prminus_dcaxy_in_ue", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - break; default: LOG(fatal) << "Cannot interpret particle " << particleOfInterest; break; } } - // Histograms for efficiency (generated) - if (doprocessMCefficiency) { + // Histograms for mc generated + if (doprocessMCgenerated) { + + // Event counter + registryMC.add("number_of_events_mc_gen", "number of gen events in mc", HistType::kTH1D, {{10, 0, 10, "Event Cuts"}}); + + // Histograms for analysis 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("XiPos_generated", "XiPos_generated", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_generated", "XiNeg_generated", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_generated", "OmegaPos_generated", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_generated", "OmegaNeg_generated", HistType::kTH2F, {multBinning, ptAxis}); + 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}); + } + + // Histograms for mc reconstructed + if (doprocessMCreconstructed) { + + // Event counter + registryMC.add("number_of_events_mc_rec", "number of rec events in mc", HistType::kTH1D, {{10, 0, 10, "Event Cuts"}}); - // Histograms for efficiency (reconstructed) + // Histograms for analysis 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("XiPos_reconstructed", "XiPos_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("XiNeg_reconstructed", "XiNeg_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaPos_reconstructed", "OmegaPos_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("OmegaNeg_reconstructed", "OmegaNeg_reconstructed", HistType::kTH2F, {multBinning, ptAxis}); + 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}); // Histograms for secondary hadrons - registryMC.add("K0s_reconstructed_incl", "K0s_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("Lambda_reconstructed_incl", "Lambda_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); - registryMC.add("AntiLambda_reconstructed_incl", "AntiLambda_reconstructed_incl", HistType::kTH2F, {multBinning, ptAxis}); - - // Histograms for secondary lambda in jet and UE - registryMC.add("Secondary_Lambda_InJet", "Secondary_Lambda_InJet", HistType::kTH1F, {ptAxis}); - registryMC.add("Secondary_Lambda_InUe", "Secondary_Lambda_InUe", HistType::kTH1F, {ptAxis}); - registryMC.add("Secondary_AntiLambda_InJet", "Secondary_AntiLambda_InJet", HistType::kTH1F, {ptAxis}); - registryMC.add("Secondary_AntiLambda_InUe", "Secondary_AntiLambda_InUe", HistType::kTH1F, {ptAxis}); - - // Histograms for 2d reweighting (pion) - registryMC.add("mc_pi_plus_eta_pt/jet", "", HistType::kTH2F, {ptAxisPi, etaAxis}); - registryMC.addClone("mc_pi_plus_eta_pt/jet", "mc_pi_plus_eta_pt/ue"); - registryMC.addClone("mc_pi_plus_eta_pt/jet", "mc_pi_plus_eta_pt/pythia"); - - registryMC.addClone("mc_pi_plus_eta_pt/", "mc_pi_minus_eta_pt/"); - - registryMC.addClone("mc_pi_plus_eta_pt/", "mc_ka_plus_eta_pt/"); - registryMC.addClone("mc_pi_minus_eta_pt/", "mc_ka_minus_eta_pt/"); - - registryMC.addClone("mc_pi_plus_eta_pt/", "mc_pr_plus_eta_pt/"); - registryMC.addClone("mc_pi_minus_eta_pt/", "mc_pr_minus_eta_pt/"); - - // Histograms for 2d reweighting (K0s) - registryMC.add("K0s_eta_pt_jet", "K0s_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("K0s_eta_pt_ue", "K0s_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("K0s_eta_pt_pythia", "K0s_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - - // Histograms for 2d reweighting (Lambda) - registryMC.add("Lambda_eta_pt_jet", "Lambda_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Lambda_eta_pt_ue", "Lambda_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Lambda_eta_pt_pythia", "Lambda_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiLambda_eta_pt_jet", "AntiLambda_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiLambda_eta_pt_ue", "AntiLambda_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiLambda_eta_pt_pythia", "AntiLambda_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - - // Histograms for 2d reweighting (Xi) - registryMC.add("Xi_eta_pt_jet", "Xi_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Xi_eta_pt_ue", "Xi_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Xi_eta_pt_pythia", "Xi_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiXi_eta_pt_jet", "AntiXi_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiXi_eta_pt_ue", "AntiXi_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiXi_eta_pt_pythia", "AntiXi_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - - // Histograms for 2d reweighting (Omega) - registryMC.add("Omega_eta_pt_jet", "Omega_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Omega_eta_pt_ue", "Omega_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("Omega_eta_pt_pythia", "Omega_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiOmega_eta_pt_jet", "AntiOmega_eta_pt_jet", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiOmega_eta_pt_ue", "AntiOmega_eta_pt_ue", HistType::kTH2F, {ptAxis, etaAxis}); - registryMC.add("AntiOmega_eta_pt_pythia", "AntiOmega_eta_pt_pythia", HistType::kTH2F, {ptAxis, etaAxis}); - - // Histograms for efficiency (pions) - registryMC.add("mc_pi_plus/in_jet/gen", "", HistType::kTH2F, {multBinning, ptAxisPi}); - registryMC.addClone("mc_pi_plus/in_jet/gen", "mc_pi_plus/in_jet/rec_tpc"); - registryMC.addClone("mc_pi_plus/in_jet/gen", "mc_pi_plus/in_jet/rec_tof"); - registryMC.addClone("mc_pi_plus/in_jet/", "mc_pi_plus/in_ue/"); - - registryMC.addClone("mc_pi_plus/", "mc_pi_minus/"); - - // Histograms for efficiency (kaons) - registryMC.addClone("mc_pi_plus/", "mc_ka_plus/"); - registryMC.addClone("mc_pi_minus/", "mc_ka_minus/"); - - // Histograms for efficiency (protons) - registryMC.addClone("mc_pi_plus/", "mc_pr_plus/"); - registryMC.addClone("mc_pi_minus/", "mc_pr_minus/"); - - // MC Templates - registryMC.add("pi_plus_dcaxy/prm", "", HistType::kTH3F, {multBinning, ptAxisPi, dcaAxis}); - registryMC.addClone("pi_plus_dcaxy/prm", "pi_plus_dcaxy/sec"); - - registryMC.addClone("pi_plus_dcaxy/", "pi_minus_dcaxy/"); - - registryMC.addClone("pi_plus_dcaxy/", "kaplus_dcaxy/"); - registryMC.addClone("pi_minus_dcaxy/", "kaminus_dcaxy/"); - - registryMC.addClone("pi_plus_dcaxy/", "prplus_dcaxy/"); - registryMC.addClone("pi_minus_dcaxy/", "prminus_dcaxy/"); + 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}); } } + // Calculation of perpendicular axes void getPerpendicularAxis(TVector3 p, TVector3& u, double sign) { // initialization @@ -491,6 +310,7 @@ struct StrangenessInJets { return; } + // Delta phi calculation double getDeltaPhi(double a1, double a2) { double deltaPhi(0); @@ -506,20 +326,19 @@ struct StrangenessInJets { return deltaPhi; } - // ITS hit + // Find ITS hit template - bool hasITSHit(const TrackIts& track, int layer) + bool hasITSHitOnLayer(const TrackIts& track, int layer) { int ibit = layer - 1; return (track.itsClusterMap() & (1 << ibit)); } - // Single-Track Selection for Particles inside Jets + // Single-track selection for particles inside jets template bool passedTrackSelectionForJetReconstruction(const JetTrack& track) { const int minTpcCr = 70; - const double minCrFindable = 0.8; const double maxChi2Tpc = 4.0; const double maxChi2Its = 36.0; const double maxPseudorapidity = 0.8; @@ -531,19 +350,17 @@ struct StrangenessInJets { if (!track.hasITS()) return false; - if ((!hasITSHit(track, 1)) && (!hasITSHit(track, 2)) && (!hasITSHit(track, 3))) + if ((!hasITSHitOnLayer(track, 1)) && (!hasITSHitOnLayer(track, 2)) && (!hasITSHitOnLayer(track, 3))) return false; if (!track.hasTPC()) return false; if (track.tpcNClsCrossedRows() < minTpcCr) return false; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minCrFindable) - return false; if (track.tpcChi2NCl() > maxChi2Tpc) return false; if (track.itsChi2NCl() > maxChi2Its) return false; - if (track.eta() < -maxPseudorapidity || track.eta() > maxPseudorapidity) + if (std::fabs(track.eta()) > maxPseudorapidity) return false; if (track.pt() < minPtTrack) return false; @@ -554,56 +371,25 @@ struct StrangenessInJets { return true; } - template - bool passedTrackSelectionForPions(const pionTrack& track) - { - if (!track.hasITS()) - return false; - if (track.itsNCls() < minITSnCls) - return false; - if (!track.hasTPC()) - return false; - if (track.tpcNClsFound() < minTPCnClsFound) - return false; - if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) - return false; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - return false; - if (track.tpcChi2NCl() > maxChi2TPC) - return false; - if (track.itsChi2NCl() > maxChi2ITS) - return false; - if (track.eta() < etaMin || track.eta() > etaMax) - return false; - if (std::fabs(track.dcaZ()) > dcazMax) - return false; - return true; - } - - // Lambda Selections + // Lambda selections template bool passedLambdaSelection(const Lambda& v0, const TrackPos& ptrack, const TrackNeg& ntrack) { - // Single-Track Selections - if (!passedSingleTrackSelection(ptrack)) - return false; - if (!passedSingleTrackSelection(ntrack)) + // Single-track selections + if (!passedSingleTrackSelection(ptrack) || !passedSingleTrackSelection(ntrack)) return false; - // Momentum of Lambda Daughters + // Momentum of lambda daughters TVector3 proton(v0.pxpos(), v0.pypos(), v0.pzpos()); TVector3 pion(v0.pxneg(), v0.pyneg(), v0.pzneg()); - if (proton.Pt() < ptMinV0Proton) - return false; - if (proton.Pt() > ptMaxV0Proton) - return false; - if (pion.Pt() < ptMinV0Pion) + // Selection on pt of Lambda daughters + if (proton.Pt() < ptMinV0Proton || proton.Pt() > ptMaxV0Proton) return false; - if (pion.Pt() > ptMaxV0Pion) + if (pion.Pt() < ptMinV0Pion || pion.Pt() > ptMaxV0Pion) return false; - // V0 Selections + // V0 selections if (v0.v0cosPA() < v0cospaMin) return false; if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) @@ -615,13 +401,13 @@ struct StrangenessInJets { if (std::fabs(v0.dcanegtopv()) < dcanegtoPVmin) return false; - // PID Selections (TPC) + // PID selections (TPC): positive track = proton, negative track = pion if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) return false; if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF): positive track = proton, negative track = pion if (requireTOF) { if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) return false; @@ -631,30 +417,25 @@ struct StrangenessInJets { return true; } - // AntiLambda Selections + // AntiLambda selections template bool passedAntiLambdaSelection(const AntiLambda& v0, const TrackPos& ptrack, const TrackNeg& ntrack) { - // Single-Track Selections - if (!passedSingleTrackSelection(ptrack)) - return false; - if (!passedSingleTrackSelection(ntrack)) + // Single-track selections + if (!passedSingleTrackSelection(ptrack) || !passedSingleTrackSelection(ntrack)) return false; - // Momentum AntiLambda Daughters + // Momentum AntiLambda daughters TVector3 pion(v0.pxpos(), v0.pypos(), v0.pzpos()); TVector3 proton(v0.pxneg(), v0.pyneg(), v0.pzneg()); - if (proton.Pt() < ptMinV0Proton) + // Selections on pt of Antilambda daughters + if (proton.Pt() < ptMinV0Proton || proton.Pt() > ptMaxV0Proton) return false; - if (proton.Pt() > ptMaxV0Proton) - return false; - if (pion.Pt() < ptMinV0Pion) - return false; - if (pion.Pt() > ptMaxV0Pion) + if (pion.Pt() < ptMinV0Pion || pion.Pt() > ptMaxV0Pion) return false; - // V0 Selections + // V0 selections if (v0.v0cosPA() < v0cospaMin) return false; if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) @@ -666,13 +447,13 @@ struct StrangenessInJets { if (std::fabs(v0.dcanegtopv()) < dcanegtoPVmin) return false; - // PID Selections (TPC) + // PID selections (TPC): negative track = proton, positive track = pion if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) return false; if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF): negative track = proton, positive track = pion if (requireTOF) { if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) return false; @@ -682,30 +463,25 @@ struct StrangenessInJets { return true; } - // K0s Selections + // K0s selections template bool passedK0ShortSelection(const K0short& v0, const TrackPos& ptrack, const TrackNeg& ntrack) { // Single-Track Selections - if (!passedSingleTrackSelection(ptrack)) - return false; - if (!passedSingleTrackSelection(ntrack)) + if (!passedSingleTrackSelection(ptrack) || !passedSingleTrackSelection(ntrack)) return false; - // Momentum K0s Daughters + // Momentum of K0s daughters TVector3 pionPos(v0.pxpos(), v0.pypos(), v0.pzpos()); TVector3 pionNeg(v0.pxneg(), v0.pyneg(), v0.pzneg()); - if (pionPos.Pt() < ptMinK0Pion) - return false; - if (pionPos.Pt() > ptMaxK0Pion) - return false; - if (pionNeg.Pt() < ptMinK0Pion) + // Selections on pt of K0s daughters + if (pionPos.Pt() < ptMinK0Pion || pionPos.Pt() > ptMaxK0Pion) return false; - if (pionNeg.Pt() > ptMaxK0Pion) + if (pionNeg.Pt() < ptMinK0Pion || pionNeg.Pt() > ptMaxK0Pion) return false; - // V0 Selections + // V0 selections if (v0.v0cosPA() < v0cospaMin) return false; if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) @@ -717,13 +493,13 @@ struct StrangenessInJets { if (std::fabs(v0.dcanegtopv()) < dcanegtoPVmin) return false; - // PID Selections (TPC) + // PID selections (TPC) if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) return false; if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF) if (requireTOF) { if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) return false; @@ -737,6 +513,7 @@ struct StrangenessInJets { template bool passedXiSelection(const Xi& casc, const TrackPos& ptrack, const TrackNeg& ntrack, const TrackBac& btrack, const Coll& coll) { + // Single-track selections on cascade daughters if (!passedSingleTrackSelection(ptrack)) return false; if (!passedSingleTrackSelection(ntrack)) @@ -744,59 +521,69 @@ struct StrangenessInJets { if (!passedSingleTrackSelection(btrack)) return false; - // Xi+ Selection (Xi+ -> antiL + pi+) + // Xi+ selection (Xi+ -> antiL + pi+) if (btrack.sign() > 0) { - if (ntrack.pt() < ptMinV0Proton) + if (ntrack.pt() < ptMinV0Proton || ntrack.pt() > ptMaxV0Proton) return false; - if (ntrack.pt() > ptMaxV0Proton) - return false; - if (ptrack.pt() < ptMinV0Pion) - return false; - if (ptrack.pt() > ptMaxV0Pion) + if (ptrack.pt() < ptMinV0Pion || ptrack.pt() > ptMaxV0Pion) return false; - // PID Selections (TPC) + // PID selections (TPC) if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) return false; if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF) if (requireTOF) { if (ntrack.tofNSigmaPr() < nsigmaTOFmin || ntrack.tofNSigmaPr() > nsigmaTOFmax) return false; if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) return false; } + + // Require that V0 is compatible with Lambda + ROOT::Math::PxPyPzMVector pProton; + ROOT::Math::PxPyPzMVector pPion; + pProton.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), MassProton); + pPion.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), MassPionCharged); + double mLambda = (pProton + pPion).M(); + if (std::fabs(mLambda - MassLambda0) > deltaMassLambda) + return false; } - // Xi- Selection (Xi- -> L + pi-) + // Xi- selection (Xi- -> L + pi-) if (btrack.sign() < 0) { - if (ptrack.pt() < ptMinV0Proton) + if (ptrack.pt() < ptMinV0Proton || ptrack.pt() > ptMaxV0Proton) return false; - if (ptrack.pt() > ptMaxV0Proton) - return false; - if (ntrack.pt() < ptMinV0Pion) - return false; - if (ntrack.pt() > ptMaxV0Pion) + if (ntrack.pt() < ptMinV0Pion || ntrack.pt() > ptMaxV0Pion) return false; - // PID Selections (TPC) + // PID selections (TPC) if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) return false; if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF) if (requireTOF) { if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) return false; if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) return false; } + + // Require that V0 is compatible with Lambda + ROOT::Math::PxPyPzMVector pProton; + ROOT::Math::PxPyPzMVector pPion; + pProton.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), MassProton); + pPion.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), MassPionCharged); + double mLambda = (pProton + pPion).M(); + if (std::fabs(mLambda - MassLambda0) > deltaMassLambda) + return false; } - // V0 Selections + // V0 selections if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < v0cospaMin) return false; if (casc.v0radius() < minimumV0Radius || casc.v0radius() > maximumV0Radius) @@ -808,7 +595,7 @@ struct StrangenessInJets { if (std::fabs(casc.dcanegtopv()) < dcanegtoPVmin) return false; - // Cascade Selections + // Cascade selections if (casc.cascradius() < minimumCascRadius || casc.cascradius() > maximumCascRadius) return false; if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < casccospaMin) @@ -820,22 +607,27 @@ struct StrangenessInJets { if (std::fabs(casc.dcacascdaughters()) > dcaCascDaughtersMax) return false; - // PID Selection on bachelor + // PID selection on bachelor if (btrack.tpcNSigmaPi() < nsigmaTPCmin || btrack.tpcNSigmaPi() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF) if (requireTOF) { if (btrack.tofNSigmaPi() < nsigmaTOFmin || btrack.tofNSigmaPi() > nsigmaTOFmax) return false; } + + // Reject candidates compatible with Omega + if (std::fabs(casc.mOmega() - MassOmegaMinus) < deltaMassOmega) + return false; return true; } - // Omega Selections + // Omega selections template bool passedOmegaSelection(const Omega& casc, const TrackPos& ptrack, const TrackNeg& ntrack, const TrackBac& btrack, const Coll& coll) { + // Single-track selections on cascade daughters if (!passedSingleTrackSelection(ptrack)) return false; if (!passedSingleTrackSelection(ntrack)) @@ -843,59 +635,69 @@ struct StrangenessInJets { if (!passedSingleTrackSelection(btrack)) return false; - // Omega+ Selection (Omega+ -> antiL + K+) + // Omega+ selection (Omega+ -> antiL + K+) if (btrack.sign() > 0) { - if (ntrack.pt() < ptMinV0Proton) - return false; - if (ntrack.pt() > ptMaxV0Proton) + if (ntrack.pt() < ptMinV0Proton || ntrack.pt() > ptMaxV0Proton) return false; - if (ptrack.pt() < ptMinV0Pion) - return false; - if (ptrack.pt() > ptMaxV0Pion) + if (ptrack.pt() < ptMinV0Pion || ptrack.pt() > ptMaxV0Pion) return false; - // PID Selections (TPC) + // PID selections (TPC) if (ntrack.tpcNSigmaPr() < nsigmaTPCmin || ntrack.tpcNSigmaPr() > nsigmaTPCmax) return false; if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF) if (requireTOF) { if (ntrack.tofNSigmaPr() < nsigmaTOFmin || ntrack.tofNSigmaPr() > nsigmaTOFmax) return false; if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) return false; } + + // Require that V0 is compatible with Lambda + ROOT::Math::PxPyPzMVector pProton; + ROOT::Math::PxPyPzMVector pPion; + pProton.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), MassProton); + pPion.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), MassPionCharged); + double mLambda = (pProton + pPion).M(); + if (std::fabs(mLambda - MassLambda0) > deltaMassLambda) + return false; } - // Omega- Selection (Omega- -> L + K-) + // Omega- selection (Omega- -> L + K-) if (btrack.sign() < 0) { - if (ptrack.pt() < ptMinV0Proton) + if (ptrack.pt() < ptMinV0Proton || ptrack.pt() > ptMaxV0Proton) return false; - if (ptrack.pt() > ptMaxV0Proton) - return false; - if (ntrack.pt() < ptMinV0Pion) - return false; - if (ntrack.pt() > ptMaxV0Pion) + if (ntrack.pt() < ptMinV0Pion || ntrack.pt() > ptMaxV0Pion) return false; - // PID Selections (TPC) + // PID selections (TPC) if (ptrack.tpcNSigmaPr() < nsigmaTPCmin || ptrack.tpcNSigmaPr() > nsigmaTPCmax) return false; if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF) if (requireTOF) { if (ptrack.tofNSigmaPr() < nsigmaTOFmin || ptrack.tofNSigmaPr() > nsigmaTOFmax) return false; if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) return false; } + + // Require that V0 is compatible with Lambda + ROOT::Math::PxPyPzMVector pProton; + ROOT::Math::PxPyPzMVector pPion; + pProton.SetCoordinates(ptrack.px(), ptrack.py(), ptrack.pz(), MassProton); + pPion.SetCoordinates(ntrack.px(), ntrack.py(), ntrack.pz(), MassPionCharged); + double mLambda = (pProton + pPion).M(); + if (std::fabs(mLambda - MassLambda0) > deltaMassLambda) + return false; } - // V0 Selections + // V0 selections if (casc.v0cosPA(coll.posX(), coll.posY(), coll.posZ()) < v0cospaMin) return false; if (casc.v0radius() < minimumV0Radius || casc.v0radius() > maximumV0Radius) @@ -907,7 +709,7 @@ struct StrangenessInJets { if (std::fabs(casc.dcanegtopv()) < dcanegtoPVmin) return false; - // Cascade Selections + // Cascade selections if (casc.cascradius() < minimumCascRadius || casc.cascradius() > maximumCascRadius) return false; if (casc.casccosPA(coll.posX(), coll.posY(), coll.posZ()) < casccospaMin) @@ -919,19 +721,23 @@ struct StrangenessInJets { if (std::fabs(casc.dcacascdaughters()) > dcaCascDaughtersMax) return false; - // PID Selection on bachelor + // PID selection on bachelor if (btrack.tpcNSigmaKa() < nsigmaTPCmin || btrack.tpcNSigmaKa() > nsigmaTPCmax) return false; - // PID Selections (TOF) + // PID selections (TOF) if (requireTOF) { if (btrack.tofNSigmaKa() < nsigmaTOFmin || btrack.tofNSigmaKa() > nsigmaTOFmax) return false; } + + // Reject candidates compatible with Xi + if (std::fabs(casc.mXi() - MassXiMinus) < deltaMassXi) + return false; return true; } - // Single-Track Selection + // Single-track selection template bool passedSingleTrackSelection(const Track& track) { @@ -941,12 +747,8 @@ struct StrangenessInJets { return false; if (!track.hasTPC()) return false; - if (track.tpcNClsFound() < minTPCnClsFound) - return false; if (track.tpcNClsCrossedRows() < minNCrossedRowsTPC) return false; - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < minTpcNcrossedRowsOverFindable) - return false; if (track.tpcChi2NCl() > maxChi2TPC) return false; if (track.eta() < etaMin || track.eta() > etaMax) @@ -956,114 +758,40 @@ struct StrangenessInJets { return true; } - // Pion Selection - template - bool isHighPurityPion(const pionTrack& track, const float nsigmaTPC, const float nsigmaTOF) - { - double nsigmaPi = 2.0; - double pThreshold = 0.6; - if (track.p() < pThreshold && std::fabs(nsigmaTPC) < nsigmaPi) - return true; - if (track.p() > pThreshold && std::fabs(nsigmaTPC) < nsigmaPi && std::fabs(nsigmaTOF) < nsigmaPi) - return true; - return false; - } - - double getCorrectedPt(double ptRec) - { - // to be developed - return ptRec; - } - - void getReweightingHistograms(o2::framework::Service const& ccdbObj) - { - auto getWeightHistoObj = [&](Configurable name, TH2F*& histo) { - if (name.value == "") { - LOG(info) << "Getting weight histogram for " << name.name << " from " << name.value; - histo = ccdbObj->get(name); - } - }; - - getWeightHistoObj(histoNameWeightPiplusJet, twodWeightsPiplusJet); - getWeightHistoObj(histoNameWeightPiplusUe, twodWeightsPiplusUe); - getWeightHistoObj(histoNameWeightPiminusJet, twodWeightsPiminusJet); - getWeightHistoObj(histoNameWeightPiminusUe, twodWeightsPiminusUe); - - TList* l = ccdbObj->get(pathToFile.value.c_str()); - if (!l) { - LOG(error) << "Could not open the file " << pathToFile.value; - return; - } - l->ls(); - - auto get2DWeightHisto = [&](Configurable name, TH2F*& histo) { - LOG(info) << "Looking for 2D weight histogram '" << name.value << "' for " << name.name; - if (name.value == "") { - LOG(info) << " -> Skipping"; - return; - } - histo = static_cast(l->FindObject(name.value.c_str())); - if (!histo) { - LOG(error) << "Could not open histogram '" << name.value << "'"; - return; - } - LOG(info) << "Opened histogram " << histo->ClassName() << " " << histo->GetName(); - }; - - get2DWeightHisto(histoNameWeightK0Jet, twodWeightsK0Jet); - get2DWeightHisto(histoNameWeightK0Ue, twodWeightsK0Ue); - get2DWeightHisto(histoNameWeightLambdaJet, twodWeightsLambdaJet); - get2DWeightHisto(histoNameWeightLambdaUe, twodWeightsLambdaUe); - get2DWeightHisto(histoNameWeightAntilambdaJet, twodWeightsAntilambdaJet); - get2DWeightHisto(histoNameWeightAntilambdaUe, twodWeightsAntilambdaUe); - - auto get1DWeightHisto = [&](Configurable name, TH1F*& histo) { - LOG(info) << "Looking for 1D weight histogram '" << name.value << "' for " << name.name; - if (name.value == "") { - LOG(info) << " -> Skipping"; - return; - } - histo = static_cast(l->FindObject(name.value.c_str())); - if (!histo) { - LOG(error) << "Could not open histogram '" << name.value << "'"; - return; - } - LOG(info) << "Opened histogram " << histo->ClassName() << " " << histo->GetName(); - }; - - // Secondary Lambda - get1DWeightHisto(histoNameWeightsXiInJet, weightsXiInJet); - get1DWeightHisto(histoNameWeightsXiInUe, weightsXiInUe); - get1DWeightHisto(histoNameWeightsAntiXiInJet, weightsAntiXiInJet); - get1DWeightHisto(histoNameWeightsAntiXiInUe, weightsAntiXiInUe); - } - - void processData(SelCollisions::iterator const& collision, - aod::V0Datas const& fullV0s, - aod::CascDataExt const& Cascades, - StrHadronDaughterTracks const& tracks) + // Process data + void processData(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, + aod::CascDataExt const& Cascades, DaughterTracks const& tracks, + aod::BCsWithTimestamps const&) { - // event counter: before event selection + // Fill event counter before event selection registryData.fill(HIST("number_of_events_data"), 0.5); + // Get the bunch crossing (BC) information associated with the collision auto bc = collision.template bc_as(); + + // Initialize CCDB objects using the BC info initCCDB(bc); + // If skimmed processing is enabled, skip this event unless it passes Zorro selection if (cfgSkimmedProcessing && !zorro.isSelected(collision.template bc_as().globalBC())) { return; } - // event selection + // Fill event counter after zorro selection + registryData.fill(HIST("number_of_events_data"), 1.5); + + // Event selection if (!collision.sel8() || std::fabs(collision.posZ()) > zVtx) return; - // event counter: after event selection - registryData.fill(HIST("number_of_events_data"), 1.5); + // Fill event counter after event selection + registryData.fill(HIST("number_of_events_data"), 2.5); - // loop over reconstructed tracks + // Loop over reconstructed tracks std::vector fjParticles; for (auto const& track : tracks) { + // Require that tracks pass selection criteria if (!passedTrackSelectionForJetReconstruction(track)) continue; @@ -1072,67 +800,75 @@ struct StrangenessInJets { fjParticles.emplace_back(fourMomentum); } - // reject empty events + // Reject empty events if (fjParticles.size() < 1) return; - registryData.fill(HIST("number_of_events_data"), 2.5); + registryData.fill(HIST("number_of_events_data"), 3.5); - // cluster particles using the anti-kt algorithm + // Cluster particles using the anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); 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()); auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // jet selection + // Jet selection bool isAtLeastOneJetSelected = false; std::vector selectedJet; std::vector ue1; std::vector ue2; - for (auto& jet : jets) { // o2-linter: disable=const-ref-in-for-loop (required by backgroundSub) + // Loop over reconstructed jets + for (const auto& jet : jets) { - // jet must be fully contained in the acceptance + // Jet must be fully contained in the acceptance if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) continue; - // jet pt must be larger than threshold - fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jet, rhoPerp, rhoMPerp); - if (getCorrectedPt(jetMinusBkg.pt()) < minJetPt) + // 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; - // perpendicular cone - // double coneRadius = std::sqrt(jet.area() / PI); + // Calculation of perpendicular cones TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); TVector3 ueAxis1(0, 0, 0); TVector3 ueAxis2(0, 0, 0); getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); + // Store jet and UE axes selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); ue2.emplace_back(ueAxis2); } if (!isAtLeastOneJetSelected) return; - registryData.fill(HIST("number_of_events_data"), 3.5); + + // Fill event counter with events with at least one jet + registryData.fill(HIST("number_of_events_data"), 4.5); // Event multiplicity const float multiplicity = collision.centFT0M(); + // Fill event multiplicity registryData.fill(HIST("number_of_events_vsmultiplicity"), multiplicity); + // Loop over selected jets for (int i = 0; i < static_cast(selectedJet.size()); i++) { - // KZeroLambda - if (particleOfInterest == Option::KZeroLambda) { + // kV0Particles + if (particleOfInterest == Option::kV0Particles) { for (const auto& v0 : fullV0s) { - const auto& pos = v0.posTrack_as(); - const auto& neg = v0.negTrack_as(); + // 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 float deltaEtaJet = v0dir.Eta() - selectedJet[i].Eta(); float deltaPhiJet = getDeltaPhi(v0dir.Phi(), selectedJet[i].Phi()); float deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); @@ -1174,27 +910,28 @@ struct StrangenessInJets { } // Cascades - if (particleOfInterest == Option::CascadePart) { + if (particleOfInterest == Option::kCascades) { for (const auto& casc : Cascades) { - auto bach = casc.bachelor_as(); - auto pos = casc.posTrack_as(); - auto neg = casc.negTrack_as(); - + // Get cascade daughters + auto bach = casc.bachelor_as(); + auto pos = casc.posTrack_as(); + auto neg = casc.negTrack_as(); TVector3 cascadeDir(casc.px(), casc.py(), casc.pz()); - float deltaEtaJet = cascadeDir.Eta() - selectedJet[i].Eta(); - float deltaPhiJet = getDeltaPhi(cascadeDir.Phi(), selectedJet[i].Phi()); - float deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - float deltaEtaUe1 = cascadeDir.Eta() - ue1[i].Eta(); - float deltaPhiUe1 = getDeltaPhi(cascadeDir.Phi(), ue1[i].Phi()); - float deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - float deltaEtaUe2 = cascadeDir.Eta() - ue2[i].Eta(); - float deltaPhiUe2 = getDeltaPhi(cascadeDir.Phi(), ue2[i].Phi()); - float deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Calculate distance from jet and UE axes + 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); // Xi+ - if (passedXiSelection(casc, pos, neg, bach, collision) && - bach.sign() > 0) { + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { if (deltaRjet < rJet) { registryData.fill(HIST("XiPos_in_jet"), multiplicity, casc.pt(), casc.mXi()); } @@ -1203,8 +940,7 @@ struct StrangenessInJets { } } // Xi- - if (passedXiSelection(casc, pos, neg, bach, collision) && - bach.sign() < 0) { + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { if (deltaRjet < rJet) { registryData.fill(HIST("XiNeg_in_jet"), multiplicity, casc.pt(), casc.mXi()); } @@ -1213,8 +949,7 @@ struct StrangenessInJets { } } // Omega+ - if (passedOmegaSelection(casc, pos, neg, bach, collision) && - bach.sign() > 0) { + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0) { if (deltaRjet < rJet) { registryData.fill(HIST("OmegaPos_in_jet"), multiplicity, casc.pt(), casc.mOmega()); } @@ -1223,8 +958,7 @@ struct StrangenessInJets { } } // Omega- - if (passedOmegaSelection(casc, pos, neg, bach, collision) && - bach.sign() < 0) { + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0) { if (deltaRjet < rJet) { registryData.fill(HIST("OmegaNeg_in_jet"), multiplicity, casc.pt(), casc.mOmega()); } @@ -1234,759 +968,253 @@ struct StrangenessInJets { } } } - - // Pions - if (particleOfInterest == Option::ChargedPions) { - for (const auto& track : tracks) { - - if (!passedTrackSelectionForPions(track)) - continue; - - TVector3 trackDir(track.px(), track.py(), track.pz()); - const float deltaEtaJet = trackDir.Eta() - selectedJet[i].Eta(); - const float deltaPhiJet = getDeltaPhi(trackDir.Phi(), selectedJet[i].Phi()); - const float deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - const float deltaEtaUe1 = trackDir.Eta() - ue1[i].Eta(); - const float deltaPhiUe1 = getDeltaPhi(trackDir.Phi(), ue1[i].Phi()); - const float deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - const float deltaEtaUe2 = trackDir.Eta() - ue2[i].Eta(); - const float deltaPhiUe2 = getDeltaPhi(trackDir.Phi(), ue2[i].Phi()); - const float deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); - - float nsigmaTPC = 999.f; - float nsigmaTOF = 999.f; - switch (particleOfInterest) { - case Option::ChargedPions: - nsigmaTPC = track.tpcNSigmaPi(); - nsigmaTOF = track.tofNSigmaPi(); - break; - case Option::ChargedKaon: - nsigmaTPC = track.tpcNSigmaKa(); - nsigmaTOF = track.tofNSigmaKa(); - break; - case Option::ProtonAntiproton: - nsigmaTPC = track.tpcNSigmaPr(); - nsigmaTOF = track.tofNSigmaPr(); - break; - } - - bool isInJet = false; - bool isInUe = false; - if (deltaRjet < rJet) - isInJet = true; - if (deltaRue1 < rJet || deltaRue2 < rJet) - isInUe = true; - - if (isHighPurityPion(track, nsigmaTPC, nsigmaTOF)) { - if (track.sign() > 0) { - if (isInJet) - registryData.fill(HIST("piplus_dcaxy_in_jet"), multiplicity, track.pt(), track.dcaXY()); - if (isInUe) - registryData.fill(HIST("piplus_dcaxy_in_ue"), multiplicity, track.pt(), track.dcaXY()); - } else { - if (isInJet) - registryData.fill(HIST("piminus_dcaxy_in_jet"), multiplicity, track.pt(), track.dcaXY()); - if (isInUe) - registryData.fill(HIST("piminus_dcaxy_in_ue"), multiplicity, track.pt(), track.dcaXY()); - } - } - - // DCAxy Selection - if (std::fabs(track.dcaXY()) > dcaxyMax) - continue; - - // TPC - switch (track.sign()) { - case 1: - if (isInJet) { - registryData.fill(HIST("piplus_tpc_in_jet"), multiplicity, track.pt(), nsigmaTPC); - } - if (isInUe) { - registryData.fill(HIST("piplus_tpc_in_ue"), multiplicity, track.pt(), nsigmaTPC); - } - break; - case -1: - if (isInJet) { - registryData.fill(HIST("piminus_tpc_in_jet"), multiplicity, track.pt(), nsigmaTPC); - } - if (isInUe) { - registryData.fill(HIST("piminus_tpc_in_ue"), multiplicity, track.pt(), nsigmaTPC); - } - break; - default: - LOG(fatal) << "Error in the charge"; - } - if (nsigmaTPC < nsigmaTPCmin || nsigmaTPC > nsigmaTPCmax) - continue; - if (!track.hasTOF()) - continue; - - // TOF - switch (track.sign()) { - case 1: - if (isInJet) { - registryData.fill(HIST("piplus_tof_in_jet"), multiplicity, track.pt(), nsigmaTOF); - } - if (isInUe) { - registryData.fill(HIST("piplus_tof_in_ue"), multiplicity, track.pt(), nsigmaTOF); - } - break; - case -1: - if (isInJet) { - registryData.fill(HIST("piminus_tof_in_jet"), multiplicity, track.pt(), nsigmaTOF); - } - if (isInUe) { - registryData.fill(HIST("piminus_tof_in_ue"), multiplicity, track.pt(), nsigmaTOF); - } - break; - default: - LOG(fatal) << "Error in the charge"; - } - } - } } } PROCESS_SWITCH(StrangenessInJets, processData, "Process data", true); - void processK0s(SelCollisions::iterator const& collision, aod::V0Datas const& fullV0s, StrHadronDaughterTracks const&) - { - registryData.fill(HIST("number_of_events_data"), 10.5); - if (!collision.sel8()) - return; - registryData.fill(HIST("number_of_events_data"), 11.5); - if (std::fabs(collision.posZ()) > zVtx) - return; - registryData.fill(HIST("number_of_events_data"), 12.5); - - for (const auto& v0 : fullV0s) { - const auto& ptrack = v0.posTrack_as(); - const auto& ntrack = v0.negTrack_as(); - - registryQC.fill(HIST("survivedK0"), 0.5); - - // Single-Track Selections - if (!passedSingleTrackSelection(ptrack)) - continue; - registryQC.fill(HIST("survivedK0"), 1.5); - - if (!passedSingleTrackSelection(ntrack)) - continue; - registryQC.fill(HIST("survivedK0"), 2.5); - - // Momentum K0s Daughters - TVector3 pionPos(v0.pxpos(), v0.pypos(), v0.pzpos()); - TVector3 pionNeg(v0.pxneg(), v0.pyneg(), v0.pzneg()); - - if (pionPos.Pt() < ptMinK0Pion) - continue; - registryQC.fill(HIST("survivedK0"), 3.5); - - if (pionPos.Pt() > ptMaxK0Pion) - continue; - registryQC.fill(HIST("survivedK0"), 4.5); - - if (pionNeg.Pt() < ptMinK0Pion) - continue; - registryQC.fill(HIST("survivedK0"), 5.5); - - if (pionNeg.Pt() > ptMaxK0Pion) - continue; - registryQC.fill(HIST("survivedK0"), 6.5); + Preslice perCollisionV0 = o2::aod::v0data::collisionId; + Preslice perCollisionCasc = o2::aod::cascade::collisionId; + Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; + Preslice perCollisionTrk = o2::aod::track::collisionId; - // V0 Selections - if (v0.v0cosPA() < v0cospaMin) - continue; - registryQC.fill(HIST("survivedK0"), 7.5); + // Generated MC events + void processMCgenerated(aod::McCollisions const& collisions, aod::McParticles const& mcParticles) + { + // Loop over all simulated collision events + for (const auto& collision : collisions) { - if (v0.v0radius() < minimumV0Radius || v0.v0radius() > maximumV0Radius) - continue; - registryQC.fill(HIST("survivedK0"), 8.5); + // Fill event counter before any selection + registryMC.fill(HIST("number_of_events_mc_gen"), 0.5); - if (std::fabs(v0.dcaV0daughters()) > dcaV0DaughtersMax) - continue; - registryQC.fill(HIST("survivedK0"), 9.5); + // Need to apply event selection to simulated events + registryMC.fill(HIST("number_of_events_mc_gen"), 1.5); - if (std::fabs(v0.dcapostopv()) < dcapostoPVmin) + // Require vertex position within the allowed z range + if (std::fabs(collision.posZ()) > zVtx) continue; - registryQC.fill(HIST("survivedK0"), 10.5); - if (std::fabs(v0.dcanegtopv()) < dcanegtoPVmin) - continue; - registryQC.fill(HIST("survivedK0"), 11.5); + // Fill event counter after selection on z-vertex + registryMC.fill(HIST("number_of_events_mc_gen"), 2.5); - // PID Selections (TPC) - if (ptrack.tpcNSigmaPi() < nsigmaTPCmin || ptrack.tpcNSigmaPi() > nsigmaTPCmax) - continue; - registryQC.fill(HIST("survivedK0"), 12.5); + // Multiplicity of generated event + double genMultiplicity = 0.0; - if (ntrack.tpcNSigmaPi() < nsigmaTPCmin || ntrack.tpcNSigmaPi() > nsigmaTPCmax) - continue; - registryQC.fill(HIST("survivedK0"), 13.5); + // MC particles per collision + auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); - // PID Selections (TOF) - if (requireTOF) { - if (ptrack.tofNSigmaPi() < nsigmaTOFmin || ptrack.tofNSigmaPi() > nsigmaTOFmax) + // Loop over all MC particles and select physical primaries within acceptance + std::vector fjParticles; + for (const auto& particle : mcParticlesPerColl) { + if (!particle.isPhysicalPrimary()) continue; - registryQC.fill(HIST("survivedK0"), 14.5); - - if (ntrack.tofNSigmaPi() < nsigmaTOFmin || ntrack.tofNSigmaPi() > nsigmaTOFmax) + double minPtParticle = 0.1; + if (particle.eta() < etaMin || particle.eta() > etaMax || particle.pt() < minPtParticle) continue; - registryQC.fill(HIST("survivedK0"), 15.5); + + // Build 4-momentum assuming charged pion mass + double energy = std::sqrt(particle.p() * particle.p() + MassPionCharged * MassPionCharged); + fastjet::PseudoJet fourMomentum(particle.px(), particle.py(), particle.pz(), energy); + fourMomentum.set_user_index(particle.pdgCode()); + fjParticles.emplace_back(fourMomentum); } - } - for (const auto& v0 : fullV0s) { - const auto& ptrack = v0.posTrack_as(); - const auto& ntrack = v0.negTrack_as(); - if (!passedK0ShortSelection(v0, ptrack, ntrack)) + // Skip events with no particles + if (fjParticles.size() < 1) continue; - registryQC.fill(HIST("survivedK0"), 16.5); - } - } - PROCESS_SWITCH(StrangenessInJets, processK0s, "Process K0s", false); - - Preslice perCollisionV0 = o2::aod::v0data::collisionId; - Preslice perCollisionCasc = o2::aod::cascade::collisionId; - Preslice perMCCollision = o2::aod::mcparticle::mcCollisionId; - Preslice perCollisionTrk = o2::aod::track::collisionId; + registryMC.fill(HIST("number_of_events_mc_gen"), 3.5); - void processMCefficiency(SimCollisions const& collisions, MCTracks const& mcTracks, aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, const aod::McParticles& mcParticles) - { - for (const auto& collision : collisions) { - registryMC.fill(HIST("number_of_events_mc"), 0.5); - if (!collision.sel8()) - continue; + // Cluster MC particles into jets using anti-kt algorithm + fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); + 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()); - registryMC.fill(HIST("number_of_events_mc"), 1.5); - if (std::fabs(collision.posZ()) > zVtx) - continue; + // Estimate background energy density (rho) in perpendicular cone + auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - registryMC.fill(HIST("number_of_events_mc"), 2.5); - float multiplicity = collision.centFT0M(); + // Loop over clustered jets + for (const auto& jet : jets) { - auto v0sPerColl = fullV0s.sliceBy(perCollisionV0, collision.globalIndex()); - auto cascPerColl = Cascades.sliceBy(perCollisionCasc, collision.globalIndex()); - auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, collision.globalIndex()); - auto tracksPerColl = mcTracks.sliceBy(perCollisionTrk, collision.globalIndex()); + // Jet must be fully contained in acceptance + if ((std::fabs(jet.eta()) + rJet) > (etaMax - deltaEtaEdge)) + continue; - for (const auto& v0 : v0sPerColl) { + // Subtract background energy from jet + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); - const auto& pos = v0.posTrack_as(); - const auto& neg = v0.negTrack_as(); - if (!pos.has_mcParticle()) - continue; - if (!neg.has_mcParticle()) + // Apply jet pT threshold + if (jetMinusBkg.pt() < minJetPt) continue; + registryMC.fill(HIST("number_of_events_mc_gen"), 4.5); - auto posParticle = pos.mcParticle_as(); - auto negParticle = neg.mcParticle_as(); - if (!posParticle.has_mothers()) - continue; - if (!negParticle.has_mothers()) - continue; + // 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); + TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); + getPerpendicularAxis(jetAxis, ueAxis1, +1); + getPerpendicularAxis(jetAxis, ueAxis2, -1); - int pdgParent(0); - bool isPhysPrim = false; - for (const auto& particleMotherOfNeg : negParticle.mothers_as()) { - for (const auto& particleMotherOfPos : posParticle.mothers_as()) { - if (particleMotherOfNeg == particleMotherOfPos) { - pdgParent = particleMotherOfNeg.pdgCode(); - isPhysPrim = particleMotherOfNeg.isPhysicalPrimary(); - } - } - } - if (pdgParent == 0) - continue; + // Loop over MC particles + for (const auto& particle : mcParticlesPerColl) { + if (!particle.isPhysicalPrimary()) + continue; + double minPtParticle = 0.1; + if (particle.eta() < etaMin || particle.eta() > etaMax || particle.pt() < minPtParticle) + continue; - // Generated Momentum of V0 - TVector3 momentumPos(posParticle.px(), posParticle.py(), posParticle.pz()); - TVector3 momentumNeg(negParticle.px(), negParticle.py(), negParticle.pz()); - TVector3 momentumV0 = momentumPos + momentumNeg; - - // Feed-down for lambda - if (passedLambdaSelection(v0, pos, neg) && pdgParent == kLambda0) { - if (!isPhysPrim) { - double wSecLambdaInJet(1.0); - double wSecLambdaInUe(1.0); - int idMother = posParticle.mothersIds()[0]; - const auto& mother = mcParticles.iteratorAt(idMother); - int idGrandMother = mother.mothersIds()[0]; - const auto& grandMother = mcParticles.iteratorAt(idGrandMother); - switch (grandMother.pdgCode()) { + // Compute distance of particles from jet and UE axes + double deltaEtaJet = particle.eta() - jetAxis.Eta(); + double deltaPhiJet = getDeltaPhi(particle.phi(), jetAxis.Phi()); + double deltaRJet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); + double deltaEtaUe1 = particle.eta() - ueAxis1.Eta(); + double deltaPhiUe1 = getDeltaPhi(particle.phi(), ueAxis1.Phi()); + double deltaRUe1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); + double deltaEtaUe2 = particle.eta() - ueAxis2.Eta(); + double deltaPhiUe2 = getDeltaPhi(particle.phi(), ueAxis2.Phi()); + double deltaRUe2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + + // Select particles inside jet + if (deltaRJet < coneRadius) { + switch (particle.pdgCode()) { + case kK0Short: + registryMC.fill(HIST("K0s_generated_jet"), genMultiplicity, particle.pt()); + break; + case kLambda0: + registryMC.fill(HIST("Lambda_generated_jet"), genMultiplicity, particle.pt()); + break; + case kLambda0Bar: + registryMC.fill(HIST("AntiLambda_generated_jet"), genMultiplicity, particle.pt()); + break; case kXiMinus: + registryMC.fill(HIST("XiNeg_generated_jet"), genMultiplicity, particle.pt()); + break; case kXiPlusBar: - // case 3322: - // case -3322: - if (weightsXiInJet) { - int ibinXiInJet = weightsXiInJet->GetXaxis()->FindBin(grandMother.pt()); - wSecLambdaInJet = weightsXiInJet->GetBinContent(ibinXiInJet); - } - if (weightsXiInUe) { - int ibinXiInUe = weightsXiInUe->GetXaxis()->FindBin(grandMother.pt()); - wSecLambdaInUe = weightsXiInUe->GetBinContent(ibinXiInUe); - } + registryMC.fill(HIST("XiPos_generated_jet"), genMultiplicity, particle.pt()); + break; + case kOmegaMinus: + registryMC.fill(HIST("OmegaNeg_generated_jet"), genMultiplicity, particle.pt()); + break; + case kOmegaPlusBar: + registryMC.fill(HIST("OmegaPos_generated_jet"), genMultiplicity, particle.pt()); break; default: break; } - registryMC.fill(HIST("Secondary_Lambda_InJet"), v0.pt(), wSecLambdaInJet); - registryMC.fill(HIST("Secondary_Lambda_InUe"), v0.pt(), wSecLambdaInUe); } - } - // Feed-down for antilambda - if (passedAntiLambdaSelection(v0, pos, neg) && pdgParent == kLambda0Bar) { - if (!isPhysPrim) { - double wSecAntiLambdaInJet(1.0); - double wSecAntiLambdaInUe(1.0); - int idMother = posParticle.mothersIds()[0]; - const auto& mother = mcParticles.iteratorAt(idMother); - int idGrandMother = mother.mothersIds()[0]; - const auto& grandMother = mcParticles.iteratorAt(idGrandMother); - switch (grandMother.pdgCode()) { + // Select particles inside UE cones + if (deltaRUe1 < coneRadius || deltaRUe2 < coneRadius) { + switch (particle.pdgCode()) { + case kK0Short: + registryMC.fill(HIST("K0s_generated_ue"), genMultiplicity, particle.pt()); + break; + case kLambda0: + registryMC.fill(HIST("Lambda_generated_ue"), genMultiplicity, particle.pt()); + break; + case kLambda0Bar: + registryMC.fill(HIST("AntiLambda_generated_ue"), genMultiplicity, particle.pt()); + break; case kXiMinus: + registryMC.fill(HIST("XiNeg_generated_ue"), genMultiplicity, particle.pt()); + break; case kXiPlusBar: - // case 3322: - // case -3322: - if (weightsAntiXiInJet) { - int ibinAntiXiInJet = weightsAntiXiInJet->GetXaxis()->FindBin(grandMother.pt()); - wSecAntiLambdaInJet = weightsAntiXiInJet->GetBinContent(ibinAntiXiInJet); - } - if (weightsAntiXiInUe) { - int ibinAntiXiInUe = weightsAntiXiInUe->GetXaxis()->FindBin(grandMother.pt()); - wSecAntiLambdaInUe = weightsAntiXiInUe->GetBinContent(ibinAntiXiInUe); - } + registryMC.fill(HIST("XiPos_generated_ue"), genMultiplicity, particle.pt()); + break; + case kOmegaMinus: + registryMC.fill(HIST("OmegaNeg_generated_ue"), genMultiplicity, particle.pt()); + break; + case kOmegaPlusBar: + registryMC.fill(HIST("OmegaPos_generated_ue"), genMultiplicity, particle.pt()); break; default: break; } - registryMC.fill(HIST("Secondary_AntiLambda_InJet"), v0.pt(), wSecAntiLambdaInJet); - registryMC.fill(HIST("Secondary_AntiLambda_InUe"), v0.pt(), wSecAntiLambdaInUe); } } - - if (passedK0ShortSelection(v0, pos, neg) && pdgParent == kK0Short) { - registryMC.fill(HIST("K0s_reconstructed_incl"), multiplicity, v0.pt()); - } - if (passedLambdaSelection(v0, pos, neg) && pdgParent == kLambda0) { - registryMC.fill(HIST("Lambda_reconstructed_incl"), multiplicity, v0.pt()); - } - if (passedAntiLambdaSelection(v0, pos, neg) && pdgParent == kLambda0Bar) { - registryMC.fill(HIST("AntiLambda_reconstructed_incl"), multiplicity, v0.pt()); - } - if (!isPhysPrim) - continue; - - double wK0jet(1.0), wK0Ue(1.0), wLambdaJet(1.0), wLambdaUe(1.0), wAntilambdaJet(1.0), wAntilambdaUe(1.0); - if (applyReweighting) { - int ix = twodWeightsK0Jet->GetXaxis()->FindBin(momentumV0.Pt()); - int iy = twodWeightsK0Jet->GetYaxis()->FindBin(momentumV0.Eta()); - wK0jet = twodWeightsK0Jet->GetBinContent(ix, iy); - wK0Ue = twodWeightsK0Ue->GetBinContent(ix, iy); - wLambdaJet = twodWeightsLambdaJet->GetBinContent(ix, iy); - wLambdaUe = twodWeightsLambdaUe->GetBinContent(ix, iy); - wAntilambdaJet = twodWeightsAntilambdaJet->GetBinContent(ix, iy); - wAntilambdaUe = twodWeightsAntilambdaUe->GetBinContent(ix, iy); - - // protections - if (ix == 0 || ix > twodWeightsK0Jet->GetNbinsX()) { - wK0jet = 1.0; - wK0Ue = 1.0; - wLambdaJet = 1.0; - wLambdaUe = 1.0; - wAntilambdaJet = 1.0; - wAntilambdaUe = 1.0; - } - if (iy == 0 || iy > twodWeightsK0Jet->GetNbinsY()) { - wK0jet = 1.0; - wK0Ue = 1.0; - wLambdaJet = 1.0; - wLambdaUe = 1.0; - wAntilambdaJet = 1.0; - wAntilambdaUe = 1.0; - } - } - - if (passedK0ShortSelection(v0, pos, neg) && pdgParent == kK0Short) { - registryMC.fill(HIST("K0s_reconstructed_jet"), multiplicity, v0.pt(), wK0jet); - registryMC.fill(HIST("K0s_reconstructed_ue"), multiplicity, v0.pt(), wK0Ue); - } - if (passedLambdaSelection(v0, pos, neg) && pdgParent == kLambda0) { - registryMC.fill(HIST("Lambda_reconstructed_jet"), multiplicity, v0.pt(), wLambdaJet); - registryMC.fill(HIST("Lambda_reconstructed_ue"), multiplicity, v0.pt(), wLambdaUe); - } - if (passedAntiLambdaSelection(v0, pos, neg) && pdgParent == kLambda0Bar) { - registryMC.fill(HIST("AntiLambda_reconstructed_jet"), multiplicity, v0.pt(), wAntilambdaJet); - registryMC.fill(HIST("AntiLambda_reconstructed_ue"), multiplicity, v0.pt(), wAntilambdaUe); - } - } - - // Cascades - for (const auto& casc : cascPerColl) { - auto bach = casc.template bachelor_as(); - auto neg = casc.template negTrack_as(); - auto pos = casc.template posTrack_as(); - - if (!bach.has_mcParticle()) - continue; - if (!pos.has_mcParticle()) - continue; - if (!neg.has_mcParticle()) - continue; - - auto posParticle = pos.mcParticle_as(); - auto negParticle = neg.mcParticle_as(); - auto bachParticle = bach.mcParticle_as(); - if (!posParticle.has_mothers()) - continue; - if (!negParticle.has_mothers()) - continue; - if (!bachParticle.has_mothers()) - continue; - - int pdgParent(0); - for (const auto& particleMotherOfNeg : negParticle.mothers_as()) { - for (const auto& particleMotherOfPos : posParticle.mothers_as()) { - for (const auto& particleMotherOfBach : bachParticle.mothers_as()) { - if (particleMotherOfNeg != particleMotherOfPos) - continue; - if (std::abs(particleMotherOfNeg.pdgCode()) != kLambda0) - continue; - if (!particleMotherOfBach.isPhysicalPrimary()) - continue; - - pdgParent = particleMotherOfBach.pdgCode(); - } - } - } - if (pdgParent == 0) - continue; - - // Xi+ - if (passedXiSelection(casc, pos, neg, bach, collision) && pdgParent == kXiPlusBar) { - registryMC.fill(HIST("XiPos_reconstructed"), multiplicity, casc.pt()); - } - // Xi- - if (passedXiSelection(casc, pos, neg, bach, collision) && pdgParent == kXiMinus) { - registryMC.fill(HIST("XiNeg_reconstructed"), multiplicity, casc.pt()); - } - // Omega+ - if (passedOmegaSelection(casc, pos, neg, bach, collision) && pdgParent == kOmegaPlusBar) { - registryMC.fill(HIST("OmegaPos_reconstructed"), multiplicity, casc.pt()); - } - // Omega- - if (passedOmegaSelection(casc, pos, neg, bach, collision) && pdgParent == kOmegaMinus) { - registryMC.fill(HIST("OmegaNeg_reconstructed"), multiplicity, casc.pt()); - } - } - - /* - // Reconstructed Tracks - for (const auto& track : tracksPerColl) { - - // Get MC Particle - if (!track.has_mcParticle()) - continue; - // Track Selection - if (!passedTrackSelectionForPions(track)) - continue; - - const auto particle = track.mcParticle(); - switch (std::abs(particle.pdgCode())) { - case kPiPlus: - if (particle.isPhysicalPrimary()) { - if (track.sign() > 0) - registryMC.fill(HIST("pi_plus_dcaxy/prm"), multiplicity, track.pt(), track.dcaXY()); - else - registryMC.fill(HIST("pi_minus_dcaxy/prm"), multiplicity, track.pt(), track.dcaXY()); - } else { - if (track.sign() > 0) - registryMC.fill(HIST("pi_plus_dcaxy/sec"), multiplicity, track.pt(), track.dcaXY()); - else - registryMC.fill(HIST("pi_minus_dcaxy/sec"), multiplicity, track.pt(), track.dcaXY()); - } - break; - case kKPlus: - if (particle.isPhysicalPrimary()) { - if (track.sign() > 0) - registryMC.fill(HIST("ka_plus_dcaxy/prm"), multiplicity, track.pt(), track.dcaXY()); - else - registryMC.fill(HIST("ka_minus_dcaxy/prm"), multiplicity, track.pt(), track.dcaXY()); - } else { - if (track.sign() > 0) - registryMC.fill(HIST("ka_plus_dcaxy/sec"), multiplicity, track.pt(), track.dcaXY()); - else - registryMC.fill(HIST("ka_minus_dcaxy/sec"), multiplicity, track.pt(), track.dcaXY()); - } - break; - case kProton: - if (particle.isPhysicalPrimary()) { - if (track.sign() > 0) - registryMC.fill(HIST("pr_plus_dcaxy/prm"), multiplicity, track.pt(), track.dcaXY()); - else - registryMC.fill(HIST("pr_minus_dcaxy/prm"), multiplicity, track.pt(), track.dcaXY()); - } else { - if (track.sign() > 0) - registryMC.fill(HIST("pr_plus_dcaxy/sec"), multiplicity, track.pt(), track.dcaXY()); - else - registryMC.fill(HIST("pr_minus_dcaxy/sec"), multiplicity, track.pt(), track.dcaXY()); - } - break; - default: - continue; - } - - if (std::fabs(track.dcaXY()) > dcaxyMax) - continue; - - if (track.tpcNSigmaPi() < nsigmaTPCmin || track.tpcNSigmaPi() > nsigmaTPCmax) - continue; - - if (!particle.isPhysicalPrimary()) - continue; - - double wPiplusJet(1.0), wPiplusUe(1.0); - double wPiminusJet(1.0), wPiminusUe(1.0); - if (applyReweighting) { - auto getWeight = [&](TH2F* histo) { - if (!histo) - return 1.0; - const int bx = histo->GetXaxis()->FindBin(track.pt()); - if (bx <= 0 || bx > histo->GetNbinsX()) { - return 1.0; - } - const int by = histo->GetYaxis()->FindBin(track.eta()); - if (by <= 0 || by > histo->GetNbinsX()) { - return 1.0; - } - return histo->GetBinContent(bx, by); - }; - wPiplusJet = getWeight(twodWeightsPiplusJet); - wPiplusUe = getWeight(twodWeightsPiplusUe); - wPiminusJet = getWeight(twodWeightsPiminusJet); - wPiminusUe = getWeight(twodWeightsPiminusUe); - } - - if (track.sign() > 0) { - registryMC.fill(HIST("mc_pi_plus/in_jet/rec_tpc"), multiplicity, track.pt(), wPiplusJet); - registryMC.fill(HIST("mc_pi_plus/in_ue/rec_tpc"), multiplicity, track.pt(), wPiplusUe); - } else { - registryMC.fill(HIST("pi_minus_rec_in_jet_tpc"), multiplicity, track.pt(), wPiminusJet); - registryMC.fill(HIST("pi_minus_rec_in_ue_tpc"), multiplicity, track.pt(), wPiminusUe); - } - - if (!track.hasTOF()) - continue; - if (track.tofNSigmaPi() < nsigmaTOFminPionMC || track.tofNSigmaPi() > nsigmaTOFmaxPionMC) - continue; - - if (track.sign() > 0) { - registryMC.fill(HIST("mc_pi_plus/in_jet/rec_tof"), multiplicity, track.pt(), wPiplusJet); - registryMC.fill(HIST("mc_pi_plus/in_ue/rec_tof"), multiplicity, track.pt(), wPiplusUe); - } else { - registryMC.fill(HIST("pi_minus_rec_in_jet_tof"), multiplicity, track.pt(), wPiminusJet); - registryMC.fill(HIST("pi_minus_rec_in_ue_tof"), multiplicity, track.pt(), wPiminusUe); - } - } - */ - for (const auto& mcParticle : mcParticlesPerColl) { - - if (mcParticle.eta() < etaMin || mcParticle.eta() > etaMax) - continue; - if (!mcParticle.isPhysicalPrimary()) - continue; - - /* - double wPiplusJet(1.0), wPiplusUe(1.0); - double wPiminusJet(1.0), wPiminusUe(1.0); - double wKaplusJet(1.0), wKaplusUe(1.0); - double wKaminusJet(1.0), wKaminusUe(1.0); - double wPrplusJet(1.0), wPrplusUe(1.0); - double wPrminusJet(1.0), wPrminusUe(1.0); - */ - double wK0jet(1.0), wK0Ue(1.0), wLambdaJet(1.0), wLambdaUe(1.0), wAntilambdaJet(1.0), wAntilambdaUe(1.0); - if (applyReweighting) { - /* - auto getWeight = [&](TH2F* histo) { - if (!histo) { - return 1.0; - } - const int bx = histo->GetXaxis()->FindBin(mcParticle.pt()); - if (bx <= 0 || bx > histo->GetNbinsX()) { - return 1.0; - } - const int by = histo->GetYaxis()->FindBin(mcParticle.eta()); - if (by <= 0 || by > histo->GetNbinsX()) { - return 1.0; - } - return histo->GetBinContent(bx, by); - }; - wPiplusJet = getWeight(twodWeightsPiplusJet); - wPiplusUe = getWeight(twodWeightsPiplusUe); - wPiminusJet = getWeight(twodWeightsPiminusJet); - wPiminusUe = getWeight(twodWeightsPiminusUe); - */ - int ix = twodWeightsK0Jet->GetXaxis()->FindBin(mcParticle.pt()); - int iy = twodWeightsK0Jet->GetYaxis()->FindBin(mcParticle.eta()); - wK0jet = twodWeightsK0Jet->GetBinContent(ix, iy); - wK0Ue = twodWeightsK0Ue->GetBinContent(ix, iy); - wLambdaJet = twodWeightsLambdaJet->GetBinContent(ix, iy); - wLambdaUe = twodWeightsLambdaUe->GetBinContent(ix, iy); - wAntilambdaJet = twodWeightsAntilambdaJet->GetBinContent(ix, iy); - wAntilambdaUe = twodWeightsAntilambdaUe->GetBinContent(ix, iy); - - // protections - if (ix == 0 || ix > twodWeightsK0Jet->GetNbinsX()) { - wK0jet = 1.0; - wK0Ue = 1.0; - wLambdaJet = 1.0; - wLambdaUe = 1.0; - wAntilambdaJet = 1.0; - wAntilambdaUe = 1.0; - } - if (iy == 0 || iy > twodWeightsK0Jet->GetNbinsY()) { - wK0jet = 1.0; - wK0Ue = 1.0; - wLambdaJet = 1.0; - wLambdaUe = 1.0; - wAntilambdaJet = 1.0; - wAntilambdaUe = 1.0; - } - } - - switch (mcParticle.pdgCode()) { - /* - case kPiPlus: // Pi+ - registryMC.fill(HIST("mc_pi_plus/in_jet/gen"), multiplicity, mcParticle.pt(), wPiplusJet); - registryMC.fill(HIST("mc_pi_plus/in_ue/gen"), multiplicity, mcParticle.pt(), wPiplusUe); - registryMC.fill(HIST("pi_plus_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kPiMinus: // Pi- - registryMC.fill(HIST("mc_pi_minus/in_jet/gen"), multiplicity, mcParticle.pt(), wPiminusJet); - registryMC.fill(HIST("mc_pi_minus/in_ue/gen"), multiplicity, mcParticle.pt(), wPiminusUe); - registryMC.fill(HIST("pi_minus_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kKPlus: // Ka+ - registryMC.fill(HIST("mc_ka_plus/in_jet/gen"), multiplicity, mcParticle.pt(), wKaplusJet); - registryMC.fill(HIST("mc_ka_plus/in_ue/gen"), multiplicity, mcParticle.pt(), wKaplusUe); - registryMC.fill(HIST("ka_plus_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kKMinus: // Ka- - registryMC.fill(HIST("mc_ka_minus/in_jet/gen"), multiplicity, mcParticle.pt(), wKaminusJet); - registryMC.fill(HIST("mc_ka_minus/in_ue/gen"), multiplicity, mcParticle.pt(), wKaminusUe); - registryMC.fill(HIST("ka_minus_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kProton: // Pr+ - registryMC.fill(HIST("mc_pr_plus/in_jet/gen"), multiplicity, mcParticle.pt(), wPrplusJet); - registryMC.fill(HIST("mc_pr_plus/in_ue/gen"), multiplicity, mcParticle.pt(), wPrplusUe); - registryMC.fill(HIST("pr_plus_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kProtonBar: // Pr- - registryMC.fill(HIST("mc_pr_minus/in_jet/gen"), multiplicity, mcParticle.pt(), wPrminusJet); - registryMC.fill(HIST("mc_pr_minus/in_ue/gen"), multiplicity, mcParticle.pt(), wPrminusUe); - registryMC.fill(HIST("pr_minus_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - */ - case kK0Short: // K0s - registryMC.fill(HIST("K0s_generated_jet"), multiplicity, mcParticle.pt(), wK0jet); - registryMC.fill(HIST("K0s_generated_ue"), multiplicity, mcParticle.pt(), wK0Ue); - registryMC.fill(HIST("K0s_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kLambda0: // Lambda - registryMC.fill(HIST("Lambda_generated_jet"), multiplicity, mcParticle.pt(), wLambdaJet); - registryMC.fill(HIST("Lambda_generated_ue"), multiplicity, mcParticle.pt(), wLambdaUe); - registryMC.fill(HIST("Lambda_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kLambda0Bar: // AntiLambda - registryMC.fill(HIST("AntiLambda_generated_jet"), multiplicity, mcParticle.pt(), wAntilambdaJet); - registryMC.fill(HIST("AntiLambda_generated_ue"), multiplicity, mcParticle.pt(), wAntilambdaUe); - registryMC.fill(HIST("AntiLambda_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kXiPlusBar: // Xi Pos - registryMC.fill(HIST("XiPos_generated"), multiplicity, mcParticle.pt()); - registryMC.fill(HIST("Xi_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kXiMinus: // Xi Neg - registryMC.fill(HIST("XiNeg_generated"), multiplicity, mcParticle.pt()); - registryMC.fill(HIST("AntiXi_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kOmegaPlusBar: // Omega Pos - registryMC.fill(HIST("OmegaPos_generated"), multiplicity, mcParticle.pt()); - registryMC.fill(HIST("Omega_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - case kOmegaMinus: // Omega Neg - registryMC.fill(HIST("OmegaNeg_generated"), multiplicity, mcParticle.pt()); - registryMC.fill(HIST("AntiOmega_eta_pt_pythia"), mcParticle.pt(), mcParticle.eta()); - break; - } } } } - PROCESS_SWITCH(StrangenessInJets, processMCefficiency, "Process MC Efficiency", false); + PROCESS_SWITCH(StrangenessInJets, processMCgenerated, "process generated events", false); - void processGen(o2::aod::McCollisions const& mcCollisions, aod::McParticles const& mcParticles) + // Reconstructed MC events + void processMCreconstructed(SimCollisions const& collisions, DaughterTracksMC const& mcTracks, + aod::V0Datas const& fullV0s, aod::CascDataExt const& Cascades, + const aod::McParticles&) { - for (const auto& mccollision : mcCollisions) { + for (const auto& collision : collisions) { - // Selection on z_{vertex} - if (std::fabs(mccollision.posZ()) > zVtx) + // Fill event counter before any selection + registryMC.fill(HIST("number_of_events_mc_rec"), 0.5); + if (!collision.sel8()) continue; - // MC Particles per Collision - auto mcParticlesPerColl = mcParticles.sliceBy(perMCCollision, mccollision.globalIndex()); + // Fill event counter after event selection + registryMC.fill(HIST("number_of_events_mc_rec"), 1.5); + if (std::fabs(collision.posZ()) > zVtx) + continue; - // loop over generated MC particles - std::vector fjParticles; - for (const auto& particle : mcParticlesPerColl) { + // Fill event counter after selection on z-vertex + registryMC.fill(HIST("number_of_events_mc_rec"), 2.5); - if (!particle.isPhysicalPrimary()) - continue; - if (std::fabs(particle.eta()) > etaMax) - continue; - double ptMinPart = 0.1; - if (particle.pt() < ptMinPart) + // Event multiplicity + const float multiplicity = collision.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()); + + // Loop over reconstructed tracks + std::vector fjParticles; + for (auto const& track : tracksPerColl) { + if (!passedTrackSelectionForJetReconstruction(track)) 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); + fastjet::PseudoJet fourMomentum(track.px(), track.py(), track.pz(), track.energy(MassPionCharged)); fjParticles.emplace_back(fourMomentum); } - // reject empty events + + // Reject empty events if (fjParticles.size() < 1) continue; + registryMC.fill(HIST("number_of_events_mc_rec"), 3.5); - // cluster particles using the anti-kt algorithm + // Cluster particles using the anti-kt algorithm fastjet::JetDefinition jetDef(fastjet::antikt_algorithm, rJet); 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()); auto [rhoPerp, rhoMPerp] = backgroundSub.estimateRhoPerpCone(fjParticles, jets); - // jet selection + // Jet selection bool isAtLeastOneJetSelected = false; std::vector selectedJet; std::vector ue1; std::vector ue2; - for (auto& jet : jets) { // o2-linter: disable=const-ref-in-for-loop (required by backgroundSub) + // 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 - fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jet, rhoPerp, rhoMPerp); - if (getCorrectedPt(jetMinusBkg.pt()) < minJetPt) + auto jetForSub = jet; + fastjet::PseudoJet jetMinusBkg = backgroundSub.doRhoAreaSub(jetForSub, rhoPerp, rhoMPerp); + if (jetMinusBkg.pt() < minJetPt) continue; isAtLeastOneJetSelected = true; - // perpendicular cone + // Perpendicular cones TVector3 jetAxis(jet.px(), jet.py(), jet.pz()); - TVector3 ueAxis1(0, 0, 0); - TVector3 ueAxis2(0, 0, 0); + TVector3 ueAxis1(0, 0, 0), ueAxis2(0, 0, 0); getPerpendicularAxis(jetAxis, ueAxis1, +1); getPerpendicularAxis(jetAxis, ueAxis2, -1); + + // Store selected jet and UE cone axes selectedJet.emplace_back(jetAxis); ue1.emplace_back(ueAxis1); ue2.emplace_back(ueAxis2); @@ -1994,106 +1222,201 @@ struct StrangenessInJets { if (!isAtLeastOneJetSelected) continue; - // loop over selected jets / UE - for (int i = 0; i < static_cast(selectedJet.size()); i++) { - for (const auto& particle : mcParticlesPerColl) { + // Fill event counter for events with at least one selected jet + registryMC.fill(HIST("number_of_events_mc_rec"), 4.5); - if (!particle.isPhysicalPrimary()) - continue; - if (std::fabs(particle.eta()) > etaMax) - continue; - double ptMinPart = 0.1; - if (particle.pt() < ptMinPart) - continue; + // Loop over selected jets + for (int i = 0; i < static_cast(selectedJet.size()); i++) { - TVector3 particleDir(particle.px(), particle.py(), particle.pz()); - float deltaEtaJet = particleDir.Eta() - selectedJet[i].Eta(); - float deltaPhiJet = getDeltaPhi(particleDir.Phi(), selectedJet[i].Phi()); - float deltaRjet = std::sqrt(deltaEtaJet * deltaEtaJet + deltaPhiJet * deltaPhiJet); - float deltaEtaUe1 = particleDir.Eta() - ue1[i].Eta(); - float deltaPhiUe1 = getDeltaPhi(particleDir.Phi(), ue1[i].Phi()); - float deltaRue1 = std::sqrt(deltaEtaUe1 * deltaEtaUe1 + deltaPhiUe1 * deltaPhiUe1); - float deltaEtaUe2 = particleDir.Eta() - ue2[i].Eta(); - float deltaPhiUe2 = getDeltaPhi(particleDir.Phi(), ue2[i].Phi()); - float deltaRue2 = std::sqrt(deltaEtaUe2 * deltaEtaUe2 + deltaPhiUe2 * deltaPhiUe2); + // V0 particles + if (particleOfInterest == Option::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()) + continue; + + // Select particles originating from the same parent + int pdgParent(0); + bool isPhysPrim = false; + for (const auto& particleMotherOfNeg : negParticle.mothers_as()) { + for (const auto& particleMotherOfPos : posParticle.mothers_as()) { + if (particleMotherOfNeg == particleMotherOfPos) { + pdgParent = particleMotherOfNeg.pdgCode(); + isPhysPrim = particleMotherOfNeg.isPhysicalPrimary(); + } + } + } + if (pdgParent == 0) + continue; + + // 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); + + // K0s + if (passedK0ShortSelection(v0, pos, neg) && pdgParent == kK0Short && isPhysPrim) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("K0s_reconstructed_jet"), multiplicity, v0.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("K0s_reconstructed_ue"), multiplicity, v0.pt()); + } + } + // Lambda + if (passedLambdaSelection(v0, pos, neg) && pdgParent == kLambda0 && isPhysPrim) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("Lambda_reconstructed_jet"), multiplicity, v0.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("Lambda_reconstructed_ue"), multiplicity, v0.pt()); + } + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg) && pdgParent == kLambda0Bar && isPhysPrim) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("AntiLambda_reconstructed_jet"), multiplicity, v0.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("AntiLambda_reconstructed_ue"), multiplicity, v0.pt()); + } + } - // In jet - if (deltaRjet < rJet) { - switch (particle.pdgCode()) { - /* - case kPiPlus: - registryMC.fill(HIST("pi_plus_eta_pt_jet"), particle.pt(), particle.eta()); - break; - case kPiMinus: - registryMC.fill(HIST("pi_minus_eta_pt_jet"), particle.pt(), particle.eta()); - break; - */ - case kK0Short: - registryMC.fill(HIST("K0s_eta_pt_jet"), particle.pt(), particle.eta()); - break; - case kLambda0: - registryMC.fill(HIST("Lambda_eta_pt_jet"), particle.pt(), particle.eta()); - break; - case kLambda0Bar: - registryMC.fill(HIST("AntiLambda_eta_pt_jet"), particle.pt(), particle.eta()); - break; - case kXiMinus: - registryMC.fill(HIST("Xi_eta_pt_jet"), particle.pt(), particle.eta()); - break; - case kXiPlusBar: - registryMC.fill(HIST("AntiXi_eta_pt_jet"), particle.pt(), particle.eta()); - break; - case kOmegaMinus: - registryMC.fill(HIST("Omega_eta_pt_jet"), particle.pt(), particle.eta()); - break; - case kOmegaPlusBar: - registryMC.fill(HIST("AntiOmega_eta_pt_jet"), particle.pt(), particle.eta()); - break; - default: - continue; + // Fill inclusive spectra + // K0s + if (passedK0ShortSelection(v0, pos, neg) && pdgParent == kK0Short) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("K0s_reconstructed_jet_incl"), multiplicity, v0.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("K0s_reconstructed_ue_incl"), multiplicity, v0.pt()); + } + } + // Lambda + if (passedLambdaSelection(v0, pos, neg) && pdgParent == kLambda0) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("Lambda_reconstructed_jet_incl"), multiplicity, v0.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("Lambda_reconstructed_ue_incl"), multiplicity, v0.pt()); + } + } + // AntiLambda + if (passedAntiLambdaSelection(v0, pos, neg) && pdgParent == kLambda0Bar) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("AntiLambda_reconstructed_jet_incl"), multiplicity, v0.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("AntiLambda_reconstructed_ue_incl"), multiplicity, v0.pt()); + } } } + } - if (deltaRue1 < rJet || deltaRue2 < rJet) { - switch (particle.pdgCode()) { - /* - case kPiPlus: - registryMC.fill(HIST("pi_plus_eta_pt_ue"), particle.pt(), particle.eta()); - break; - case kPiMinus: - registryMC.fill(HIST("pi_minus_eta_pt_ue"), particle.pt(), particle.eta()); - break; - */ - case kK0Short: - registryMC.fill(HIST("K0s_eta_pt_ue"), particle.pt(), particle.eta()); - break; - case kLambda0: - registryMC.fill(HIST("Lambda_eta_pt_ue"), particle.pt(), particle.eta()); - break; - case kLambda0Bar: - registryMC.fill(HIST("AntiLambda_eta_pt_ue"), particle.pt(), particle.eta()); - break; - case kXiMinus: - registryMC.fill(HIST("Xi_eta_pt_ue"), particle.pt(), particle.eta()); - break; - case kXiPlusBar: - registryMC.fill(HIST("AntiXi_eta_pt_ue"), particle.pt(), particle.eta()); - break; - case kOmegaMinus: - registryMC.fill(HIST("Omega_eta_pt_ue"), particle.pt(), particle.eta()); - break; - case kOmegaPlusBar: - registryMC.fill(HIST("AntiOmega_eta_pt_ue"), particle.pt(), particle.eta()); - break; - default: - continue; + // Cascades + if (particleOfInterest == Option::kCascades) { + for (const auto& casc : cascPerColl) { + auto bach = casc.bachelor_as(); + auto pos = casc.posTrack_as(); + 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(); + if (!posParticle.has_mothers() || !negParticle.has_mothers() || !bachParticle.has_mothers()) + continue; + + // Select particles originating from the same parent + int pdgParent(0); + bool isPhysPrim = false; + for (const auto& particleMotherOfNeg : negParticle.mothers_as()) { + for (const auto& particleMotherOfPos : posParticle.mothers_as()) { + for (const auto& particleMotherOfBach : bachParticle.mothers_as()) { + if (particleMotherOfNeg != particleMotherOfPos) + continue; + if (std::abs(particleMotherOfNeg.pdgCode()) != kLambda0) + continue; + isPhysPrim = particleMotherOfBach.isPhysicalPrimary(); + pdgParent = particleMotherOfBach.pdgCode(); + } + } + } + if (pdgParent == 0) + continue; + if (!isPhysPrim) + 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); + + // Xi+ + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && pdgParent == kXiPlusBar) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("XiPos_reconstructed_jet"), multiplicity, casc.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("XiPos_reconstructed_ue"), multiplicity, casc.pt()); + } + } + // Xi- + if (passedXiSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && pdgParent == kXiMinus) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("XiNeg_reconstructed_jet"), multiplicity, casc.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("XiNeg_reconstructed_ue"), multiplicity, casc.pt()); + } + } + // Omega+ + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() > 0 && pdgParent == kOmegaPlusBar) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("OmegaPos_reconstructed_jet"), multiplicity, casc.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("OmegaPos_reconstructed_ue"), multiplicity, casc.pt()); + } + } + // Omega- + if (passedOmegaSelection(casc, pos, neg, bach, collision) && bach.sign() < 0 && pdgParent == kOmegaMinus) { + if (deltaRjet < rJet) { + registryMC.fill(HIST("OmegaNeg_reconstructed_jet"), multiplicity, casc.pt()); + } + if (deltaRue1 < rJet || deltaRue2 < rJet) { + registryMC.fill(HIST("OmegaNeg_reconstructed_ue"), multiplicity, casc.pt()); + } } } } } } } - PROCESS_SWITCH(StrangenessInJets, processGen, "Process generated MC", false); + PROCESS_SWITCH(StrangenessInJets, processMCreconstructed, "process reconstructed events", false); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) diff --git a/PWGLF/Tasks/Strangeness/strangenessderivedbinnedinfo.cxx b/PWGLF/Tasks/Strangeness/strangenessderivedbinnedinfo.cxx new file mode 100644 index 00000000000..728d8c6675b --- /dev/null +++ b/PWGLF/Tasks/Strangeness/strangenessderivedbinnedinfo.cxx @@ -0,0 +1,844 @@ +// 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 strangenessderivedbinnedinfo.cxx +/// \brief analysis task producing V0/cascade info in binned format +/// +/// \author Romain Schotter , Austrian Academy of Sciences & SMI +// +// ================ +// +// This code loops over V0Cores and CascCores tables and produces some +// standard analysis output. It is meant to be run over +// derived data. +// +// +// Comments, questions, complaints, suggestions? +// Please write to: +// romain.schotter@cern.ch +// + +#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" +#include "Common/DataModel/EventSelection.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" +#include "EventFiltering/Zorro.h" +#include "EventFiltering/ZorroSummary.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 + +// constants +const float ctauXiPDG = 4.91; // Xi PDG lifetime +const float ctauOmegaPDG = 2.461; // Omega PDG lifetime + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using std::array; + +using namespace o2::aod::rctsel; + +using DauTracks = soa::Join; +using V0Candidates = soa::Join; +using CascadeCandidates = soa::Join; + +struct strangenessderivedbinnedinfo { + HistogramRegistry histos{"Histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // master analysis switches + Configurable analyseK0Short{"analyseK0Short", true, "process K0Short-like candidates"}; + Configurable analyseLambda{"analyseLambda", false, "process Lambda-like candidates"}; + Configurable analyseAntiLambda{"analyseAntiLambda", false, "process AntiLambda-like candidates"}; + Configurable analyseXi{"analyseXi", false, "process Xi-like candidates"}; + Configurable analyseOmega{"analyseOmega", false, "process Omega-like candidates"}; + Configurable isPP{"isPP", true, "If running on pp collision, switch it on true"}; + + // for running over skimmed dataset + Configurable doPPAnalysis{"doPPAnalysis", false, "if in pp, set to true"}; + Configurable cfgSkimmedProcessing{"cfgSkimmedProcessing", false, "If running over skimmed data, switch it on true"}; + Configurable cfgSkimmedTrigger{"cfgSkimmedTrigger", "fDoubleXi,fTripleXi,fQuadrupleXi", "(std::string) Comma separated list of triggers of interest"}; + Configurable irSource{"irSource", "T0VTX", "Estimator of the interaction rate (Recommended: pp --> T0VTX, Pb-Pb --> ZNC hadronic)"}; + + struct : ConfigurableGroup { + 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", 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)"}; + 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)"}; + 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"}; + Configurable requireINEL1{"requireINEL1", false, "require INEL>1 event selection"}; + + Configurable maxZVtxPosition{"maxZVtxPosition", 10., "max Z vtx position"}; + + 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; + + static constexpr float defaultSqrtScalingParameters[1][4] = {{0.1, 0.1, 0, 128}}; + + // preselection options + struct : ConfigurableGroup { + std::string prefix = "encodingOpts"; + Configurable useSqrtEncodingForOccupancy{"useSqrtEncodingForOccupancy", false, "Store sqrt(occupancy) instead of occupancy"}; + Configurable useSqrtEncodingForRadius{"useSqrtEncodingForRadius", false, "Store sqrt(radius) instead of radius"}; + Configurable useSqrtScalingForEncodingPt{"useSqrtScalingForEncodingPt", false, "Store sqrt scaling(pT) instead of pT"}; + Configurable> sqrtScalingParameters{"sqrtScalingParameters", {defaultSqrtScalingParameters[0], 4, {"sigma0", "sigma1", "clampMin", "clampMax"}}, "Sqrt scaling parameters"}; + } encodingOpts; + + struct : ConfigurableGroup { + Configurable v0TypeSelection{"v0Selections.v0TypeSelection", 1, "select on a certain V0 type (leave negative if no selection desired)"}; + + // Selection criteria: acceptance + Configurable rapidityCut{"v0Selections.rapidityCut", 0.5, "rapidity"}; + Configurable daughterEtaCut{"v0Selections.daughterEtaCut", 0.8, "max eta for daughters"}; + + // Standard 6 topological criteria + Configurable v0cospa{"v0Selections.v0cospa", 0.97, "min V0 CosPA"}; + Configurable dcav0dau{"v0Selections.dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable dcav0topv{"v0Selections.dcav0topv", .05, "min DCA V0 to PV (cm)"}; + Configurable dcapiontopv{"v0Selections.dcapiontopv", .05, "min DCA Pion To PV (cm)"}; + Configurable dcaprotontopv{"v0Selections.dcaprotontopv", .05, "min DCA Proton To PV (cm)"}; + Configurable v0radius{"v0Selections.v0radius", 1.2, "minimum V0 radius (cm)"}; + Configurable v0radiusMax{"v0Selections.v0radiusMax", 1E5, "maximum V0 radius (cm)"}; + + // invariant mass selection + Configurable v0MassWindow{"v0Selections.v0MassWindow", 0.008, "#Lambda mass (GeV/#it{c}^{2})"}; + Configurable compMassRejection{"v0Selections.compMassRejection", 0.008, "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{"v0Selections.armPodCut", 5.0f, "pT * (cut) > |alpha|, AP cut. Negative: no cut"}; + + // Track quality + Configurable minTPCrows{"v0Selections.minTPCrows", 70, "minimum TPC crossed rows"}; + Configurable minITSclusters{"v0Selections.minITSclusters", -1, "minimum ITS clusters"}; + Configurable requireTPConly{"v0Selections.requireTPConly", false, "require V0s comprised of at least one TPC only prong"}; + Configurable requirePosITSonly{"v0Selections.requirePosITSonly", false, "require that positive track is ITSonly (overrides TPC quality)"}; + Configurable requireNegITSonly{"v0Selections.requireNegITSonly", false, "require that negative track is ITSonly (overrides TPC quality)"}; + + // PID (TPC) + Configurable tpcPidNsigmaCut{"v0Selections.tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; + } v0Selections; + + struct : ConfigurableGroup { + // Selection criteria: acceptance + Configurable rapidityCut{"cascSelections.rapidityCut", 0.5, "rapidity"}; + Configurable daughterEtaCut{"cascSelections.daughterEtaCut", 0.8, "max eta for daughters"}; + + // Standard 6 topological criteria on V0 + Configurable v0cospa{"cascSelections.v0cospa", 0.97, "min V0 CosPA"}; + Configurable dcav0dau{"cascSelections.dcav0dau", 1.0, "max DCA V0 Daughters (cm)"}; + Configurable dcav0topv{"cascSelections.dcav0topv", .05, "min DCA V0 to PV (cm)"}; + Configurable dcapiontopv{"cascSelections.dcapiontopv", .05, "min DCA Pion To PV (cm)"}; + Configurable dcaprotontopv{"cascSelections.dcaprotontopv", .05, "min DCA Proton To PV (cm)"}; + Configurable v0radius{"cascSelections.v0radius", 1.2, "minimum V0 radius (cm)"}; + Configurable v0radiusMax{"cascSelections.v0radiusMax", 1E5, "maximum V0 radius (cm)"}; + + // Standard 6 topological criteria on cascades + Configurable casccospa{"cascSelections.casccospa", 0.97, "min Cascade CosPA"}; + Configurable dcacascdau{"cascSelections.dcacascdau", 1.0, "max DCA Cascade Daughters (cm)"}; + Configurable dcaxybachbaryontopv{"cascSelections.dcaxybachbaryontopv", -1, "DCAxy Bachelor-Baryon to PV (cm)"}; + Configurable bachbaryoncospa{"cascSelections.bachbaryoncospa", -1, "Bachelor-Baryon CosPA"}; + Configurable dcabachtopv{"cascSelections.dcabachtopv", .05, "min DCA Bachelor To PV (cm)"}; + Configurable cascradius{"cascSelections.cascradius", 0.5, "minimum Cascade radius (cm)"}; + Configurable cascradiusMax{"cascSelections.cascradiusMax", 1E5, "maximum Cascade radius (cm)"}; + Configurable cascProperLifeTime{"cascSelections.cascProperLifeTime", 3, "maximum lifetime (ctau)"}; + + // invariant mass selection + Configurable v0MassWindow{"cascSelections.v0MassWindow", 0.008, "#Lambda mass (GeV/#it{c}^{2})"}; + Configurable cascMassWindow{"cascSelections.cascMassWindow", 0.008, "#Lambda mass (GeV/#it{c}^{2})"}; + Configurable compMassRejection{"cascSelections.compMassRejection", 0.008, "Competing mass rejection (GeV/#it{c}^{2})"}; + + // Track quality + Configurable minTPCrows{"cascSelections.minTPCrows", 70, "minimum TPC crossed rows"}; + Configurable minITSclusters{"cascSelections.minITSclusters", -1, "minimum ITS clusters"}; + Configurable skipTPConly{"cascSelections.skipTPConly", false, "skip V0s comprised of at least one TPC only prong"}; + Configurable requireBachITSonly{"cascSelections.requireBachITSonly", false, "require that bachelor track is ITSonly (overrides TPC quality)"}; + Configurable requirePosITSonly{"cascSelections.requirePosITSonly", false, "require that positive track is ITSonly (overrides TPC quality)"}; + Configurable requireNegITSonly{"cascSelections.requireNegITSonly", false, "require that negative track is ITSonly (overrides TPC quality)"}; + + // PID (TPC) + Configurable tpcPidNsigmaCut{"cascSelections.tpcPidNsigmaCut", 5, "tpcPidNsigmaCut"}; + } cascSelections; + + 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}; + + // CCDB options + struct : ConfigurableGroup { + Configurable ccdburl{"ccdbConfigurations.ccdb-url", "http://alice-ccdb.cern.ch", "url of the ccdb repository"}; + Configurable grpPath{"ccdbConfigurations.grpPath", "GLO/GRP/GRP", "Path of the grp file"}; + Configurable grpmagPath{"ccdbConfigurations.grpmagPath", "GLO/Config/GRPMagField", "CCDB path of the GRPMagField object"}; + Configurable lutPath{"ccdbConfigurations.lutPath", "GLO/Param/MatLUT", "Path of the Lut parametrization"}; + Configurable geoPath{"ccdbConfigurations.geoPath", "GLO/Config/GeometryAligned", "Path of the geometry file"}; + Configurable mVtxPath{"ccdbConfigurations.mVtxPath", "GLO/Calib/MeanVertex", "Path of the mean vertex file"}; + } ccdbConfigurations; + + Service ccdb; + o2::ccdb::CcdbApi ccdbApi; + ctpRateFetcher rateFetcher; + int mRunNumber; + std::map metadata; + + Zorro zorro; + OutputObj zorroSummary{"zorroSummary"}; + + static constexpr float defaultLifetimeCuts[1][2] = {{30., 20.}}; + Configurable> lifetimecut{"lifetimecut", {defaultLifetimeCuts[0], 2, {"lifetimecutLambda", "lifetimecutK0S"}}, "lifetimecut"}; + + ConfigurableAxis axisCentrality{"axisCentrality", {VARIABLE_WIDTH, 0.0f, 20.0f, 40.0f, 60.0f, 80.0f, 100.0f}, "Centrality"}; + ConfigurableAxis axisOccupancy{"axisOccupancy", {VARIABLE_WIDTH, 0.0f, 1000.0f, 3000.0f, 10000.0f, 30000.0f}, "Occupancy"}; + + // topological variable QA axes + ConfigurableAxis axisMass{"axisV0Mass", {25, 0.45, 0.55f}, "Invariant mass (GeV/#it{c}^{2})"}; + ConfigurableAxis axisPhi{"axisPhi", {36, 0.0f, constants::math::TwoPI}, "#varphi (rad)"}; + ConfigurableAxis axisEta{"axisEta", {10, -1.0f, 1.0f}, "Pseudo-rapidity #eta"}; + ConfigurableAxis axisRadius{"axisRadius", {10, 0.0f, 250.0f}, "Decay radius (cm)"}; + ConfigurableAxis axisPt{"axisPt", {VARIABLE_WIDTH, 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 1.5f, 2.0f, 2.5f, 3.0f, 4.0f, 5.0f, 7.0f, 9.0f, 11.0f, 15.0f, 30.0f}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis axisAlphaV0{"axisAlphaV0", {1, -1.0f, 1.f}, "V0 #alpha Armenteros"}; + ConfigurableAxis axisPtArmV0{"axisPtArmV0", {1, 0.0f, 10.f}, "V0 #it{p}_{T} Armenteros"}; + + // PDG database + Service pdgDB; + + // Sqrt scaling function + // Author: Marian Ivanov + int codeSqrtScaling(float val, float sigma0, float sigma1, int clampMin, int clampMax) + { + float code_f = std::asinh((sigma1 * val) / sigma0) / sigma0; + return std::clamp(static_cast(std::round(code_f)), clampMin, clampMax); + } + + // Function to decode the sqrt scaling + // Author: Marian Ivanov + float decodeSqrtScaling(int code, float sigma0, float sigma1) + { + float code_f = static_cast(code); + return (sigma0 / sigma1) * std::sinh(sigma0 * code_f); + } + + void init(InitContext const&) + { + if (analyseK0Short + analyseLambda + analyseAntiLambda + analyseXi + analyseOmega > 1) { + LOGF(fatal, "Cannot enable several particles at the same time. Please choose one."); + } + + // Initialise the RCTFlagsChecker + rctFlagsChecker.init(rctConfigurations.cfgRCTLabel.value, rctConfigurations.cfgCheckZDC, rctConfigurations.cfgTreatLimitedAcceptanceAsBad); + + // Event Counters + histos.add("hEventSelection", "hEventSelection", kTH1D, {{21, -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.add("hEventCentrality", "hEventCentrality", kTH1F, {{100, 0.0f, +100.0f}}); + histos.add("hEventOccupancy", "hEventOccupancy", kTH1F, {axisOccupancy}); + + histos.add("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc", "h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc", kTHnSparseF, {axisMass, axisPt, axisPhi, axisEta, axisPtArmV0, axisAlphaV0, axisRadius, axisCentrality, axisOccupancy}); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(0)->SetName("Mass"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(1)->SetName("Pt"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(2)->SetName("Phi"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(3)->SetName("Eta"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(4)->SetName("V0PtArm"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(5)->SetName("V0Alpha"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(6)->SetName("Radius"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(7)->SetName("Centrality"); + histos.get(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"))->GetAxis(8)->SetName("Occupancy"); + + if (cfgSkimmedProcessing) { + zorroSummary.setObject(zorro.getZorroSummary()); + } + + // inspect histogram sizes, please + histos.print(); + } + + template // TCollision should be of the type: soa::Join::iterator or so + void initCCDB(TCollision const& collision) + { + if (mRunNumber == collision.runNumber()) { + return; + } + + mRunNumber = collision.runNumber(); + if (cfgSkimmedProcessing) { + ccdb->setURL(ccdbConfigurations.ccdburl); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + ccdb->setFatalWhenNull(false); + + zorro.initCCDB(ccdb.service, collision.runNumber(), collision.timestamp(), cfgSkimmedTrigger.value); + zorro.populateHistRegistry(histos, collision.runNumber()); + } + } + + template + bool isEventAccepted(TCollision collision, bool fillHists) + // check whether the collision passes our collision selections + { + if (fillHists) + histos.fill(HIST("hEventSelection"), 0. /* all collisions */); + + if (eventSelections.requireSel8 && !collision.sel8()) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 1 /* sel8 collisions */); + + if (eventSelections.requireTriggerTVX && !collision.selection_bit(aod::evsel::kIsTriggerTVX)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 2 /* FT0 vertex (acceptable FT0C-FT0A time difference) collisions */); + + if (eventSelections.rejectITSROFBorder && !collision.selection_bit(o2::aod::evsel::kNoITSROFrameBorder)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 3 /* Not at ITS ROF border */); + + if (eventSelections.rejectTFBorder && !collision.selection_bit(o2::aod::evsel::kNoTimeFrameBorder)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 4 /* Not at TF border */); + + if (std::abs(collision.posZ()) > eventSelections.maxZVtxPosition) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 5 /* vertex-Z selected */); + + if (eventSelections.requireIsVertexITSTPC && !collision.selection_bit(o2::aod::evsel::kIsVertexITSTPC)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 6 /* Contains at least one ITS-TPC track */); + + if (eventSelections.requireIsGoodZvtxFT0VsPV && !collision.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 7 /* PV position consistency check */); + + if (eventSelections.requireIsVertexTOFmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTOFmatched)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 8 /* PV with at least one contributor matched with TOF */); + + if (eventSelections.requireIsVertexTRDmatched && !collision.selection_bit(o2::aod::evsel::kIsVertexTRDmatched)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 9 /* PV with at least one contributor matched with TRD */); + + if (eventSelections.rejectSameBunchPileup && !collision.selection_bit(o2::aod::evsel::kNoSameBunchPileup)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 10 /* Not at same bunch pile-up */); + + if (eventSelections.requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 11 /* No other collision within +/- 2 microseconds or mult above a certain threshold in -4 - -2 microseconds*/); + + if (eventSelections.requireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 12 /* No other collision within +/- 10 microseconds */); + + if (eventSelections.requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 13 /* No other collision within +/- 2 microseconds */); + + if (eventSelections.requireNoCollInROFStd && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 14 /* No other collision within the same ITS ROF with mult. above a certain threshold */); + + if (eventSelections.requireNoCollInROFStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 15 /* No other collision within the same ITS ROF */); + + if (doPPAnalysis) { // we are in pp + if (eventSelections.requireINEL0 && collision.multNTracksPVeta1() < 1) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 16 /* INEL > 0 */); + + if (eventSelections.requireINEL1 && collision.multNTracksPVeta1() < 2) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 17 /* INEL > 1 */); + + } else { // we are in Pb-Pb + float collisionOccupancy = eventSelections.useFT0CbasedOccupancy ? collision.ft0cOccupancyInTimeRange() : collision.trackOccupancyInTimeRange(); + if (eventSelections.minOccupancy >= 0 && collisionOccupancy < eventSelections.minOccupancy) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 16 /* Below min occupancy */); + + if (eventSelections.maxOccupancy >= 0 && collisionOccupancy > eventSelections.maxOccupancy) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 17 /* Above max occupancy */); + } + + // Fetch interaction rate only if required (in order to limit ccdb calls) + double interactionRate = (eventSelections.minIR >= 0 || eventSelections.maxIR >= 0) ? rateFetcher.fetch(ccdb.service, collision.timestamp(), collision.runNumber(), irSource) * 1.e-3 : -1; + if (eventSelections.minIR >= 0 && interactionRate < eventSelections.minIR) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 18 /* Below min IR */); + + if (eventSelections.maxIR >= 0 && interactionRate > eventSelections.maxIR) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 19 /* Above max IR */); + + if (!rctConfigurations.cfgRCTLabel.value.empty() && !rctFlagsChecker(collision)) { + return false; + } + if (fillHists) + histos.fill(HIST("hEventSelection"), 20 /* Pass CBT condition */); + + return true; + } + + template + void fillEventHistograms(TCollision collision, float& centrality, float& occupancy) + { + if (isPP) { // + centrality = collision.centFT0M(); + } else { + centrality = collision.centFT0C(); + occupancy = eventSelections.useFT0CbasedOccupancy ? collision.ft0cOccupancyInTimeRange() : collision.trackOccupancyInTimeRange(); + if (encodingOpts.useSqrtEncodingForOccupancy) + occupancy = std::sqrt(occupancy); + } + histos.fill(HIST("hEventCentrality"), centrality); + histos.fill(HIST("hEventOccupancy"), occupancy); + + return; + } + + template + bool isV0Selected(TV0 v0, TCollision collision, float rapidity) + // precalculate this information so that a check is one mask operation, not many + { + // + // Base topological variables + // + + // v0 radius min/max selections + if (v0.v0radius() < v0Selections.v0radius) + return false; + if (v0.v0radius() > v0Selections.v0radiusMax) + return false; + // DCA proton and pion to PV for Lambda and AntiLambda decay hypotheses + if (analyseK0Short) { + if (std::fabs(v0.dcapostopv()) < v0Selections.dcapiontopv) + return false; + if (std::fabs(v0.dcanegtopv()) < v0Selections.dcapiontopv) + return false; + } + if (analyseLambda) { + if (std::fabs(v0.dcapostopv()) < v0Selections.dcaprotontopv) + return false; + if (std::fabs(v0.dcanegtopv()) < v0Selections.dcapiontopv) + return false; + } + if (analyseAntiLambda) { + if (std::fabs(v0.dcapostopv()) < v0Selections.dcapiontopv) + return false; + if (std::fabs(v0.dcanegtopv()) < v0Selections.dcaprotontopv) + return false; + } + // V0 cosine of pointing angle + if (v0.v0cosPA() < v0Selections.v0cospa) + return false; + // DCA between v0 daughters + if (v0.dcaV0daughters() > v0Selections.dcav0dau) + return false; + // DCA V0 to prim vtx + if (v0.dcav0topv() < v0Selections.dcav0topv) + return false; + + // + // rapidity + // + if (std::fabs(rapidity) > v0Selections.rapidityCut) + return false; + + // + // competing mass rejection + // + if ((analyseLambda || analyseAntiLambda) && std::fabs(v0.mK0Short() - o2::constants::physics::MassK0Short) < v0Selections.compMassRejection) + return false; + if (analyseK0Short && std::fabs(v0.mLambda() - o2::constants::physics::MassLambda0) < v0Selections.compMassRejection) + return false; + + auto posTrackExtra = v0.template posTrackExtra_as(); + auto negTrackExtra = v0.template negTrackExtra_as(); + + // + // ITS quality flags + // + if (posTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; + if (negTrackExtra.itsNCls() < v0Selections.minITSclusters) + return false; + + // + // TPC quality flags + // + if (posTrackExtra.tpcCrossedRows() < v0Selections.minTPCrows) + return false; + if (negTrackExtra.tpcCrossedRows() < v0Selections.minTPCrows) + return false; + + // + // TPC PID + // + if (analyseK0Short) { + if (std::fabs(posTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCut) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCut) + return false; + } + if (analyseLambda) { + if (std::fabs(posTrackExtra.tpcNSigmaPr()) > v0Selections.tpcPidNsigmaCut) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCut) + return false; + } + if (analyseAntiLambda) { + if (std::fabs(posTrackExtra.tpcNSigmaPi()) > v0Selections.tpcPidNsigmaCut) + return false; + if (std::fabs(negTrackExtra.tpcNSigmaPr()) > v0Selections.tpcPidNsigmaCut) + return false; + } + + // + // ITS only tag + if (v0Selections.requirePosITSonly && posTrackExtra.tpcCrossedRows() > 0) + return false; + if (v0Selections.requireNegITSonly && negTrackExtra.tpcCrossedRows() > 0) + return false; + + // + // TPC only tag + if (v0Selections.requireTPConly && posTrackExtra.detectorMap() != o2::aod::track::TPC) + return false; + if (v0Selections.requireTPConly && negTrackExtra.detectorMap() != o2::aod::track::TPC) + return false; + + // + // proper lifetime + if ((analyseLambda || analyseAntiLambda) && + v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassLambda0 > lifetimecut->get("lifetimecutLambda")) + return false; + if (analyseK0Short && + v0.distovertotmom(collision.posX(), collision.posY(), collision.posZ()) * o2::constants::physics::MassK0Short > lifetimecut->get("lifetimecutK0S")) + return false; + + // + // armenteros + if (v0Selections.armPodCut > 1e-4 && v0.qtarm() * v0Selections.armPodCut < std::fabs(v0.alpha())) + return false; + + return true; + } + + template + bool isCascadeSelected(TCascade casc, TCollision collision, float rapidity) + // precalculate this information so that a check is one mask operation, not many + { + // + // 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; + + // + // rapidity + // + if (std::fabs(rapidity) > cascSelections.rapidityCut) + return false; + + // + // competing mass rejection + // + if (analyseXi && std::fabs(casc.mOmega() - o2::constants::physics::MassOmegaMinus) < cascSelections.compMassRejection) + return false; + if (analyseOmega && std::fabs(casc.mXi() - o2::constants::physics::MassXiMinus) < cascSelections.compMassRejection) + return false; + + auto bachTrackExtra = casc.template bachTrackExtra_as(); + auto posTrackExtra = casc.template posTrackExtra_as(); + auto negTrackExtra = casc.template negTrackExtra_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.tpcCrossedRows() < cascSelections.minTPCrows) + return false; + if (posTrackExtra.tpcCrossedRows() < cascSelections.minTPCrows) + return false; + if (negTrackExtra.tpcCrossedRows() < cascSelections.minTPCrows) + return false; + + // + // TPC PID + // + if (analyseXi && std::fabs(bachTrackExtra.tpcNSigmaPi()) > cascSelections.tpcPidNsigmaCut) + return false; + if (analyseOmega && 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; + } + + // + // 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 (analyseXi && distOverTotMom * o2::constants::physics::MassXiMinus / ctauXiPDG > cascSelections.cascProperLifeTime) + return false; + if (analyseOmega && distOverTotMom * o2::constants::physics::MassOmegaMinus / ctauOmegaPDG > cascSelections.cascProperLifeTime) + return false; + + return true; + } + + // ______________________________________________________ + // Real data processing - no MC subscription + void process(soa::Join::iterator const& collision, V0Candidates const& fullV0s, CascadeCandidates const& fullCascades, DauTracks const&) + { + // Fire up CCDB + if (cfgSkimmedProcessing) { + initCCDB(collision); + } + + if (!isEventAccepted(collision, true)) { + return; + } + + if (cfgSkimmedProcessing) { + zorro.isSelected(collision.globalBC()); /// Just let Zorro do the accounting + } + + float centrality = -1; + float occupancy = -1; + fillEventHistograms(collision, centrality, occupancy); + + // __________________________________________ + // perform main analysis + // + if (analyseK0Short || analyseLambda || analyseAntiLambda) { // Look at V0s + for (const auto& 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 (v0.v0Type() != v0Selections.v0TypeSelection && v0Selections.v0TypeSelection > -1) + continue; // skip V0s that are not standard + + float pT = encodingOpts.useSqrtScalingForEncodingPt ? codeSqrtScaling(v0.pt(), encodingOpts.sqrtScalingParameters->get("sigma0"), encodingOpts.sqrtScalingParameters->get("sigma1"), encodingOpts.sqrtScalingParameters->get("clampMin"), encodingOpts.sqrtScalingParameters->get("clampMax")) : v0.pt(); + float decayRadius = encodingOpts.useSqrtEncodingForRadius ? std::sqrt(v0.v0radius()) : v0.v0radius(); + + if (analyseK0Short && isV0Selected(v0, collision, v0.yK0Short())) { + histos.fill(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"), v0.mK0Short(), pT, v0.phi(), v0.eta(), v0.qtarm(), v0.alpha(), decayRadius, centrality, occupancy); + } + if (analyseLambda && isV0Selected(v0, collision, v0.yLambda())) { + histos.fill(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"), v0.mLambda(), pT, v0.phi(), v0.eta(), v0.qtarm(), v0.alpha(), decayRadius, centrality, occupancy); + } + if (analyseAntiLambda && isV0Selected(v0, collision, v0.yLambda())) { + histos.fill(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"), v0.mAntiLambda(), pT, v0.phi(), v0.eta(), v0.qtarm(), v0.alpha(), decayRadius, centrality, occupancy); + } + } // end v0 loop + } + + if (analyseXi || analyseOmega) { // Look at Cascades + for (const auto& cascade : fullCascades) { + if (std::abs(cascade.negativeeta()) > cascSelections.daughterEtaCut || + std::abs(cascade.positiveeta()) > cascSelections.daughterEtaCut || + std::abs(cascade.bacheloreta()) > cascSelections.daughterEtaCut) + continue; // remove acceptance that's badly reproduced by MC / superfluous in future + + float pT = encodingOpts.useSqrtScalingForEncodingPt ? codeSqrtScaling(cascade.pt(), encodingOpts.sqrtScalingParameters->get("sigma0"), encodingOpts.sqrtScalingParameters->get("sigma1"), encodingOpts.sqrtScalingParameters->get("clampMin"), encodingOpts.sqrtScalingParameters->get("clampMax")) : cascade.pt(); + float decayRadius = encodingOpts.useSqrtEncodingForRadius ? std::sqrt(cascade.cascradius()) : cascade.cascradius(); + + if (analyseXi && isCascadeSelected(cascade, collision, cascade.yXi())) { + histos.fill(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"), cascade.m(1), pT, cascade.phi(), cascade.eta(), 0., 0., decayRadius, centrality, occupancy); + } + if (analyseOmega && isCascadeSelected(cascade, collision, cascade.yOmega())) { + histos.fill(HIST("h9dMassPtPhiEtaPtArmV0AlphaV0RadiusCentOcc"), cascade.m(2), pT, cascade.phi(), cascade.eta(), 0., 0., decayRadius, centrality, occupancy); + } + } // end cascade loop + } + } +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx index 9badfb4b4ba..be85c214406 100644 --- a/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx +++ b/PWGLF/Tasks/Strangeness/taskLambdaSpinCorr.cxx @@ -13,36 +13,41 @@ /// \brief Analysis task for Lambda spin spin correlation /// /// \author prottay.das@cern.ch +/// \author sourav.kundu@cern.ch -#include -#include -#include -#include -#include "Math/Vector2D.h" -#include "Math/Vector3D.h" -#include "Math/Vector4D.h" -#include "Math/GenVector/Boost.h" +#include "PWGLF/DataModel/LFStrangenessPIDTables.h" +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StepTHn.h" -#include "Common/DataModel/PIDResponse.h" -#include "Common/DataModel/Multiplicity.h" +#include "Common/Core/TrackSelection.h" +#include "Common/Core/trackUtilities.h" #include "Common/DataModel/Centrality.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Common/DataModel/EventSelection.h" -#include "Common/Core/trackUtilities.h" +#include "Common/DataModel/FT0Corrected.h" +#include "Common/DataModel/Multiplicity.h" +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include "CCDB/BasicCCDBManager.h" #include "CommonConstants/PhysicsConstants.h" -#include "Common/Core/TrackSelection.h" #include "Framework/ASoAHelpers.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/StepTHn.h" +#include "Framework/runDataProcessing.h" #include "ReconstructionDataFormats/Track.h" -#include "CCDB/BasicCCDBManager.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" -#include "PWGLF/DataModel/LFStrangenessPIDTables.h" -#include "Common/DataModel/FT0Corrected.h" -#include "PWGMM/Mult/DataModel/Index.h" // for Particles2Tracks table + +#include "Math/GenVector/Boost.h" +#include "Math/Vector2D.h" +#include "Math/Vector3D.h" +#include "Math/Vector4D.h" + +#include + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -50,6 +55,9 @@ using namespace o2::framework::expressions; using std::array; using namespace o2::aod::rctsel; +using dauTracks = soa::Join; +using v0Candidates = soa::Join; + struct LfTaskLambdaSpinCorr { Service ccdb; @@ -61,9 +69,8 @@ struct LfTaskLambdaSpinCorr { Configurable cfgEvtRCTFlagCheckerLimitAcceptAsBad{"cfgEvtRCTFlagCheckerLimitAcceptAsBad", true, "Evt sel: RCT flag checker treat Limited Acceptance As Bad"}; } rctCut; // mixing - Configurable cosCalculation{"cosCalculation", 1, "cos calculation"}; - Configurable mixingCombination{"mixingCombination", 1, "mixing Combination"}; - Configurable mixingEvSel{"mixingEvSel", false, "mixingEvSel"}; + Configurable cosCalculation{"cosCalculation", 0, "cos calculation"}; + Configurable mixingCombination{"mixingCombination", 0, "mixing Combination"}; Configurable cfgCutOccupancy{"cfgCutOccupancy", 2000, "Occupancy cut"}; ConfigurableAxis axisVertex{"axisVertex", {5, -10, 10}, "vertex axis for bin"}; ConfigurableAxis axisMultiplicityClass{"axisMultiplicityClass", {8, 0, 80}, "multiplicity percentile for bin"}; @@ -91,13 +98,13 @@ struct LfTaskLambdaSpinCorr { Configurable confV0PtMin{"confV0PtMin", 0.f, "Minimum transverse momentum of V0"}; Configurable confV0PtMax{"confV0PtMax", 0.f, "Maximum transverse momentum of V0"}; Configurable confV0Rap{"confV0Rap", 0.8f, "Rapidity range of V0"}; - Configurable confV0DCADaughMax{"confV0DCADaughMax", 0.2f, "Maximum DCA between the V0 daughters"}; + Configurable confV0DCADaughMax{"confV0DCADaughMax", 0.2f, "Maximum DCA between the V0 daughters"}; Configurable confV0CPAMin{"confV0CPAMin", 0.9998f, "Minimum CPA of V0"}; Configurable confV0TranRadV0Min{"confV0TranRadV0Min", 1.5f, "Minimum transverse radius"}; Configurable confV0TranRadV0Max{"confV0TranRadV0Max", 100.f, "Maximum transverse radius"}; Configurable cMaxV0DCA{"cMaxV0DCA", 1.2, "Maximum V0 DCA to PV"}; - Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; - Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; + Configurable cMinV0DCAPr{"cMinV0DCAPr", 0.05, "Minimum V0 daughters DCA to PV for Pr"}; + Configurable cMinV0DCAPi{"cMinV0DCAPi", 0.05, "Minimum V0 daughters DCA to PV for Pi"}; Configurable cMaxV0LifeTime{"cMaxV0LifeTime", 20, "Maximum V0 life time"}; // config for V0 daughters @@ -128,7 +135,8 @@ struct LfTaskLambdaSpinCorr { AxisSpec thnAxisInvMasspair{iMNbinspair, lbinIMpair, hbinIMpair, "#it{M} (GeV/#it{c}^{2})"}; histos.add("hEvtSelInfo", "hEvtSelInfo", kTH1F, {{10, 0, 10.0}}); histos.add("hPtDiff", "hPtDiff", kTH1F, {{1000, 0, 100.0}}); - histos.add("hRDiff", "hRDiff", kTH1F, {{640, 0, 16.0}}); + histos.add("hPhiDiff", "hPhiDiff", kTH1F, {{800, -8.0, 8.0}}); + histos.add("hRDiff", "hRDiff", kTH1F, {{640, -16.0, 16.0}}); histos.add("hv0Mult", "hv0Mult", kTH1F, {{10001, -0.5, 10000.5}}); histos.add("hCentrality", "Centrality distribution", kTH1F, {{configcentAxis}}); histos.add("hSparseLambdaLambda", "hSparseLambdaLambda", HistType::kTHnSparseF, {thnAxisInvMass, thnAxisInvMass, configthnAxisPol, configcentAxis, thnAxisInvMasspair}, true); @@ -244,8 +252,8 @@ struct LfTaskLambdaSpinCorr { const ROOT::Math::PxPyPzMVector& Lambdadummy, const ROOT::Math::PxPyPzMVector& AntiLambdadummy) { - const double minMass = 1.0; - const double maxMass = 2.0; + const double minMass = 1.09; + const double maxMass = 1.14; return (lambdaTag && aLambdaTag && (Lambdadummy.M() > minMass && Lambdadummy.M() < maxMass) && (AntiLambdadummy.M() > minMass && AntiLambdadummy.M() < maxMass)); @@ -293,8 +301,8 @@ struct LfTaskLambdaSpinCorr { double cosTheta2 = proton2LambdaRF.Vect().Unit().Dot(quantizationAxis); cosThetaDiff = cosTheta1 * cosTheta2; } - - double deltaR = TMath::Sqrt(TMath::Power(particle1.Eta() - particle2.Eta(), 2.0) + TMath::Power(particle1.Phi() - particle2.Phi(), 2.0)); + double deltaPhi = RecoDecay::constrainAngle(particle1.Phi() - particle2.Phi(), 0.0); + double deltaR = TMath::Sqrt(TMath::Power(particle1.Eta() - particle2.Eta(), 2.0) + TMath::Power(deltaPhi, 2.0)); if (datatype == 0) { if (tag1 && tag3) { histos.fill(HIST("hSparseLambdaLambda"), particle1.M(), particle2.M(), cosThetaDiff, centrality, deltaR); @@ -374,6 +382,32 @@ struct LfTaskLambdaSpinCorr { return {lambdaTag, aLambdaTag, true}; // Valid candidate } + std::tuple getLambdaTagsDD(const auto& v0, const auto& collision) + { + auto postrack = v0.template posTrackExtra_as(); + auto negtrack = v0.template negTrackExtra_as(); + + int lambdaTag = 0; + int aLambdaTag = 0; + + if (isSelectedV0Daughter(v0, postrack, 0) && isSelectedV0Daughter(v0, negtrack, 1)) { + lambdaTag = 1; + } + if (isSelectedV0Daughter(v0, negtrack, 0) && isSelectedV0Daughter(v0, postrack, 1)) { + aLambdaTag = 1; + } + + if (!lambdaTag && !aLambdaTag) { + return {0, 0, false}; // No valid tags + } + + if (!selectionV0(collision, v0)) { + return {0, 0, false}; // Fails selection + } + + return {lambdaTag, aLambdaTag, true}; // Valid candidate + } + std::tuple getLambdaTagsMC(const auto& v0, const auto& collision) { auto postrack = v0.template posTrack_as(); @@ -411,7 +445,7 @@ struct LfTaskLambdaSpinCorr { return {lambdaTag, aLambdaTag, true}; // Valid candidate } - + ROOT::Math::PxPyPzMVector lambda0, antiLambda0, proton0, pion0, antiProton0, antiPion0; ROOT::Math::PxPyPzMVector lambda, antiLambda, proton, pion, antiProton, antiPion; ROOT::Math::PxPyPzMVector lambda2, antiLambda2, proton2, pion2, antiProton2, antiPion2; ROOT::Math::PxPyPzMVector lambdamc, antiLambdamc, protonmc, pionmc, antiProtonmc, antiPionmc; @@ -478,7 +512,12 @@ struct LfTaskLambdaSpinCorr { pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassPionCharged); antiLambda = antiProton + pion; } - + if (lambdaTag && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } auto postrack1 = v0.template posTrack_as(); auto negtrack1 = v0.template negTrack_as(); @@ -504,6 +543,12 @@ struct LfTaskLambdaSpinCorr { pion2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), o2::constants::physics::MassPionCharged); antiLambda2 = antiProton2 + pion2; } + if (lambdaTag2 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { + continue; + } auto postrack2 = v02.template posTrack_as(); auto negtrack2 = v02.template negTrack_as(); if (postrack1.globalIndex() == postrack2.globalIndex() || negtrack1.globalIndex() == negtrack2.globalIndex()) { @@ -569,7 +614,7 @@ struct LfTaskLambdaSpinCorr { if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - if (mixingEvSel && additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } @@ -579,7 +624,7 @@ struct LfTaskLambdaSpinCorr { if (additionalEvSel4 && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { continue; } - if (mixingEvSel && additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + if (additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { continue; } @@ -630,8 +675,42 @@ struct LfTaskLambdaSpinCorr { if (postrack1.globalIndex() == postrack2.globalIndex() || negtrack1.globalIndex() == negtrack2.globalIndex()) { continue; } - auto samePairSumPt = t1.pt() + t2.pt(); - auto samePairR = TMath::Sqrt(TMath::Power(t1.phi() - t2.phi(), 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + // auto samePairSumPt = t1.pt() + t2.pt(); + double deltaPhiSame = RecoDecay::constrainAngle(t1.phi() - t2.phi(), 0.0); + auto samePairR = TMath::Sqrt(TMath::Power(deltaPhiSame, 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + + if (lambdaTag1) { + proton0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassProton); + antiPion0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassPionCharged); + lambda0 = proton0 + antiPion0; + } + if (aLambdaTag1) { + antiProton0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassProton); + pion0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda0 = antiProton0 + pion0; + } + if (lambdaTag1 && (lambda0.M() < lbinIM || lambda0.M() > hbinIM)) { + continue; + } + if (aLambdaTag1 && (antiLambda0.M() < lbinIM || antiLambda0.M() > hbinIM)) { + continue; + } + if (lambdaTag2) { + proton = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassProton); + antiPion = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassPionCharged); + lambda = proton + antiPion; + } + if (aLambdaTag2) { + antiProton = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassProton); + pion = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda = antiProton + pion; + } + if (lambdaTag2 && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } for (const auto& t3 : groupV03) { // if (pairStatus[t3.index()][t2.index()]) { // LOGF(info, "repeat match found v0 id: (%d, %d)", t3.index(), t2.index()); @@ -653,45 +732,350 @@ struct LfTaskLambdaSpinCorr { if (lambdaTag1 != lambdaTag3 || aLambdaTag1 != aLambdaTag3) { continue; } - // if (std::abs(t1.pt() - t3.pt()) > ptMix) { - // continue; - // } - // if (std::abs(t1.eta() - t3.eta()) > etaMix) { - // continue; - // } - // if (std::abs(t1.phi() - t3.phi()) > phiMix) { - // continue; - // } - auto mixPairSumPt = t3.pt() + t2.pt(); - auto mixPairR = TMath::Sqrt(TMath::Power(t3.phi() - t2.phi(), 2.0) + TMath::Power(t3.eta() - t2.eta(), 2.0)); - histos.fill(HIST("hPtDiff"), TMath::Abs(mixPairSumPt - samePairSumPt)); - histos.fill(HIST("hRDiff"), TMath::Abs(mixPairR - samePairR)); + + if (lambdaTag3) { + proton2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassProton); + antiPion2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassPionCharged); + lambda2 = proton2 + antiPion2; + } + if (aLambdaTag3) { + antiProton2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassProton); + pion2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda2 = antiProton2 + pion2; + } + if (lambdaTag3 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { + continue; + } + if (aLambdaTag3 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { + continue; + } + double deltaPhiMix = RecoDecay::constrainAngle(t3.phi() - t2.phi(), 0.0); + auto mixPairR = TMath::Sqrt(TMath::Power(deltaPhiMix, 2.0) + TMath::Power(t3.eta() - t2.eta(), 2.0)); + auto etaDiff = t1.eta() - t3.eta(); + auto phiDiff = RecoDecay::constrainAngle(t1.phi() - t3.phi(), 0.0); + + histos.fill(HIST("hPtDiff"), t1.pt() - t3.pt()); + histos.fill(HIST("hPhiDiff"), phiDiff); + histos.fill(HIST("hRDiff"), etaDiff); + if (mixingCombination == 0 && std::abs(t1.pt() - t3.pt()) > ptMix) { continue; } - if (mixingCombination == 0 && std::abs(t1.eta() - t3.eta()) > etaMix) { + if (mixingCombination == 0 && t1.eta() * t3.eta() > 0 && std::abs(etaDiff) > etaMix) { continue; } - if (mixingCombination == 0 && std::abs(t1.phi() - t3.phi()) > phiMix) { + if (mixingCombination == 0 && phiDiff > phiMix) { continue; } - if (mixingCombination == 1 && std::abs(mixPairSumPt - samePairSumPt) > ptMix) { + if (mixingCombination == 1 && std::abs(t1.pt() - t3.pt()) > ptMix) { continue; } if (mixingCombination == 1 && std::abs(mixPairR - samePairR) > etaMix) { continue; } - if (lambdaTag2) { - proton = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassProton); - antiPion = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassPionCharged); - lambda = proton + antiPion; + + if (lambdaTag2 && lambdaTag3) { + fillHistograms(1, 0, 1, 0, lambda, lambda2, proton, proton2, centrality, 2); + } else if (aLambdaTag2 && aLambdaTag3) { + fillHistograms(0, 1, 0, 1, antiLambda, antiLambda2, antiProton, antiProton2, centrality, 2); + } else if (lambdaTag2 && aLambdaTag3) { + fillHistograms(1, 0, 0, 1, lambda, antiLambda2, proton, antiProton2, centrality, 2); + } else if (aLambdaTag2 && lambdaTag3) { + fillHistograms(0, 1, 1, 0, antiLambda, lambda2, antiProton, proton2, centrality, 2); + } else { + continue; } - if (aLambdaTag2) { - antiProton = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassProton); - pion = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassPionCharged); - antiLambda = antiProton + pion; + pairfound = true; + pairStatus[t3.index()][t2.index()] = true; + // LOGF(info, "v0 id: (%d, %d)", t3.index(), t2.index()); + if (pairfound) { + // LOGF(info, "Pair found"); + break; + } + } + } + } + } + PROCESS_SWITCH(LfTaskLambdaSpinCorr, processME, "Process data ME", true); + + Filter v0der = (nabs(aod::v0data::dcapostopv) > cMinV0DCAPr && nabs(aod::v0data::dcanegtopv) > cMinV0DCAPi && nabs(aod::v0data::dcaV0daughters) < confV0DCADaughMax); + using v0Cand = soa::Filtered; + + // void processDerivedData(soa::Join::iterator const& collision, v0Candidates const& V0s, dauTracks const&) + void processDerivedData(soa::Join::iterator const& collision, v0Cand const& V0s, dauTracks const&) + { + histos.fill(HIST("hEvtSelInfo"), 0.5); + if (rctCut.requireRCTFlagChecker && !rctChecker(collision)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 1.5); + if (!collision.sel8()) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 2.5); + auto centrality = collision.centFT0C(); + int occupancy = collision.trackOccupancyInTimeRange(); + if (additionalEvSel && (!collision.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 3.5); + if (additionalEvSel3 && (!collision.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 4.5); + if (additionalEvSel4 && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 5.5); + if (additionalEvSel5 && !collision.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 6.5); + if (occupancy > cfgCutOccupancy) { + return; + } + histos.fill(HIST("hEvtSelInfo"), 7.5); + histos.fill(HIST("hCentrality"), centrality); + + for (const auto& v0 : V0s) { + auto [lambdaTag, aLambdaTag, isValid] = getLambdaTagsDD(v0, collision); + if (!isValid) { + continue; + } + + if (lambdaTag && aLambdaTag) { + continue; + } + + if (lambdaTag) { + proton = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassProton); + antiPion = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassPionCharged); + lambda = proton + antiPion; + } + if (aLambdaTag) { + antiProton = ROOT::Math::PxPyPzMVector(v0.pxneg(), v0.pyneg(), v0.pzneg(), o2::constants::physics::MassProton); + pion = ROOT::Math::PxPyPzMVector(v0.pxpos(), v0.pypos(), v0.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda = antiProton + pion; + } + + if (lambdaTag && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } + + // auto postrack1 = v0.template posTrackExtra_as(); + // auto negtrack1 = v0.template negTrackExtra_as(); + + // 2nd loop for combination of lambda lambda + for (const auto& v02 : V0s) { + if (v02.index() <= v0.index()) { + continue; + } + auto [lambdaTag2, aLambdaTag2, isValid2] = getLambdaTagsDD(v02, collision); + if (!isValid2) { + continue; + } + if (lambdaTag2 && aLambdaTag2) { + continue; + } + if (lambdaTag2) { + proton2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), o2::constants::physics::MassProton); + antiPion2 = ROOT::Math::PxPyPzMVector(v02.pxneg(), v02.pyneg(), v02.pzneg(), o2::constants::physics::MassPionCharged); + lambda2 = proton2 + antiPion2; + } + if (aLambdaTag2) { + antiProton2 = ROOT::Math::PxPyPzMVector(v02.pxneg(), v02.pyneg(), v02.pzneg(), o2::constants::physics::MassProton); + pion2 = ROOT::Math::PxPyPzMVector(v02.pxpos(), v02.pypos(), v02.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda2 = antiProton2 + pion2; + } + + if (lambdaTag2 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { + continue; + } + + // auto postrack2 = v02.template posTrackExtra_as(); + // auto negtrack2 = v02.template negTrackExtra_as(); + if (v0.posTrackExtraId() == v02.posTrackExtraId() || v0.negTrackExtraId() == v02.negTrackExtraId()) { + continue; + } + + if (lambdaTag && lambdaTag2) { + fillHistograms(1, 0, 1, 0, lambda, lambda2, proton, proton2, centrality, 0); + } + if (aLambdaTag && aLambdaTag2) { + fillHistograms(0, 1, 0, 1, antiLambda, antiLambda2, antiProton, antiProton2, centrality, 0); + } + if (lambdaTag && aLambdaTag2) { + fillHistograms(1, 0, 0, 1, lambda, antiLambda2, proton, antiProton2, centrality, 0); + } + if (aLambdaTag && lambdaTag2) { + fillHistograms(0, 1, 1, 0, antiLambda, lambda2, antiProton, proton2, centrality, 0); + } + } + } + } + PROCESS_SWITCH(LfTaskLambdaSpinCorr, processDerivedData, "Process derived data", true); + + // Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only + Preslice tracksPerCollisionV0Mixed = o2::aod::v0data::straCollisionId; // for derived data only + // void processDerivedDataMixed(soa::Join const& collisions, v0Candidates const& V0s, dauTracks const&) + void processDerivedDataMixed(soa::Join const& collisions, v0Cand const& V0s, dauTracks const&) + + { + + for (auto& [collision1, collision2] : selfCombinations(colBinning, nMix, -1, collisions, collisions)) { + // LOGF(info, "Mixed event collisions: (%d, %d)", collision1.index(), collision2.index()); + if (rctCut.requireRCTFlagChecker && !rctChecker(collision1)) { + continue; + } + if (rctCut.requireRCTFlagChecker && !rctChecker(collision2)) { + continue; + } + int occupancy1 = collision1.trackOccupancyInTimeRange(); + int occupancy2 = collision2.trackOccupancyInTimeRange(); + + if (collision1.index() == collision2.index()) { + continue; + } + if (!collision1.sel8() || !collision2.sel8()) { + continue; + } + if (additionalEvSel && (!collision1.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision1.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (occupancy1 > cfgCutOccupancy) { + continue; + } + if (additionalEvSel && (!collision2.selection_bit(aod::evsel::kNoSameBunchPileup) || !collision2.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV))) { + continue; + } + if (occupancy2 > cfgCutOccupancy) { + continue; + } + if (additionalEvSel3 && (!collision1.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision1.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel4 && !collision1.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvSel5 && !collision1.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + + if (additionalEvSel3 && (!collision2.selection_bit(aod::evsel::kNoTimeFrameBorder) || !collision2.selection_bit(aod::evsel::kNoITSROFrameBorder))) { + continue; + } + if (additionalEvSel4 && !collision2.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { + continue; + } + if (additionalEvSel5 && !collision2.selection_bit(o2::aod::evsel::kIsGoodITSLayersAll)) { + continue; + } + auto centrality = collision1.centFT0C(); + // auto groupV01 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); + // auto groupV02 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.globalIndex()); + // auto groupV03 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.globalIndex()); + auto groupV01 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); + auto groupV02 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision1.index()); + auto groupV03 = V0s.sliceBy(tracksPerCollisionV0Mixed, collision2.index()); + + size_t rows = groupV03.size() + 1600; + size_t cols = groupV01.size() + 1600; + std::vector> pairStatus(rows, std::vector(cols, false)); + histos.fill(HIST("hv0Mult"), groupV01.size()); + for (auto& [t1, t2] : soa::combinations(o2::soa::CombinationsFullIndexPolicy(groupV01, groupV02))) { + bool pairfound = false; + if (t2.index() <= t1.index()) { + continue; + } + if (t1.straCollisionId() != t2.straCollisionId()) { + continue; + } + + auto [lambdaTag1, aLambdaTag1, isValid1] = getLambdaTagsDD(t1, collision1); + auto [lambdaTag2, aLambdaTag2, isValid2] = getLambdaTagsDD(t2, collision1); + if (!isValid1) { + continue; + } + if (!isValid2) { + continue; + } + if (lambdaTag1 && aLambdaTag1) { + continue; + } + if (lambdaTag2 && aLambdaTag2) { + continue; + } + // auto postrack1 = t1.template posTrackExtra_as(); + // auto negtrack1 = t1.template negTrackExtra_as(); + // auto postrack2 = t2.template posTrackExtra_as(); + // auto negtrack2 = t2.template negTrackExtra_as(); + if (t1.posTrackExtraId() == t2.posTrackExtraId() || t1.negTrackExtraId() == t2.negTrackExtraId()) { + continue; + } + // auto samePairSumPt = t1.pt() + t2.pt(); + // auto samePairR = TMath::Sqrt(TMath::Power(t1.phi() - t2.phi(), 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + + double deltaPhiSame = RecoDecay::constrainAngle(t1.phi() - t2.phi(), 0.0); + auto samePairR = TMath::Sqrt(TMath::Power(deltaPhiSame, 2.0) + TMath::Power(t1.eta() - t2.eta(), 2.0)); + + if (lambdaTag1) { + proton0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassProton); + antiPion0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassPionCharged); + lambda0 = proton0 + antiPion0; + } + if (aLambdaTag1) { + antiProton0 = ROOT::Math::PxPyPzMVector(t1.pxneg(), t1.pyneg(), t1.pzneg(), o2::constants::physics::MassProton); + pion0 = ROOT::Math::PxPyPzMVector(t1.pxpos(), t1.pypos(), t1.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda0 = antiProton0 + pion0; + } + if (lambdaTag1 && (lambda0.M() < lbinIM || lambda0.M() > hbinIM)) { + continue; + } + if (aLambdaTag1 && (antiLambda0.M() < lbinIM || antiLambda0.M() > hbinIM)) { + continue; + } + if (lambdaTag2) { + proton = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassProton); + antiPion = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassPionCharged); + lambda = proton + antiPion; + } + if (aLambdaTag2) { + antiProton = ROOT::Math::PxPyPzMVector(t2.pxneg(), t2.pyneg(), t2.pzneg(), o2::constants::physics::MassProton); + pion = ROOT::Math::PxPyPzMVector(t2.pxpos(), t2.pypos(), t2.pzpos(), o2::constants::physics::MassPionCharged); + antiLambda = antiProton + pion; + } + if (lambdaTag2 && (lambda.M() < lbinIM || lambda.M() > hbinIM)) { + continue; + } + if (aLambdaTag2 && (antiLambda.M() < lbinIM || antiLambda.M() > hbinIM)) { + continue; + } + + for (const auto& t3 : groupV03) { + if (pairStatus[t3.index()][t2.index()]) { + continue; } + if (t1.straCollisionId() == t3.straCollisionId()) { + continue; + } + auto [lambdaTag3, aLambdaTag3, isValid3] = getLambdaTagsDD(t3, collision2); + if (!isValid3) { + continue; + } + if (lambdaTag3 && aLambdaTag3) { + continue; + } + if (lambdaTag1 != lambdaTag3 || aLambdaTag1 != aLambdaTag3) { + continue; + } + if (lambdaTag3) { proton2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassProton); antiPion2 = ROOT::Math::PxPyPzMVector(t3.pxneg(), t3.pyneg(), t3.pzneg(), o2::constants::physics::MassPionCharged); @@ -702,6 +1086,39 @@ struct LfTaskLambdaSpinCorr { pion2 = ROOT::Math::PxPyPzMVector(t3.pxpos(), t3.pypos(), t3.pzpos(), o2::constants::physics::MassPionCharged); antiLambda2 = antiProton2 + pion2; } + if (lambdaTag3 && (lambda2.M() < lbinIM || lambda2.M() > hbinIM)) { + continue; + } + + if (aLambdaTag3 && (antiLambda2.M() < lbinIM || antiLambda2.M() > hbinIM)) { + continue; + } + + double deltaPhiMix = RecoDecay::constrainAngle(t3.phi() - t2.phi(), 0.0); + auto mixPairR = TMath::Sqrt(TMath::Power(deltaPhiMix, 2.0) + TMath::Power(t3.eta() - t2.eta(), 2.0)); + + auto etaDiff = t1.eta() - t3.eta(); + auto phiDiff = RecoDecay::constrainAngle(t1.phi() - t3.phi(), 0.0); + + histos.fill(HIST("hPtDiff"), t1.pt() - t3.pt()); + histos.fill(HIST("hPhiDiff"), phiDiff); + histos.fill(HIST("hRDiff"), etaDiff); + + if (mixingCombination == 0 && std::abs(t1.pt() - t3.pt()) > ptMix) { + continue; + } + if (mixingCombination == 0 && t1.eta() * t3.eta() > 0 && std::abs(etaDiff) > etaMix) { + continue; + } + if (mixingCombination == 0 && phiDiff > phiMix) { + continue; + } + if (mixingCombination == 1 && std::abs(t1.pt() - t3.pt()) > ptMix) { + continue; + } + if (mixingCombination == 1 && std::abs(mixPairR - samePairR) > etaMix) { + continue; + } if (lambdaTag2 && lambdaTag3) { fillHistograms(1, 0, 1, 0, lambda, lambda2, proton, proton2, centrality, 2); } else if (aLambdaTag2 && aLambdaTag3) { @@ -714,18 +1131,16 @@ struct LfTaskLambdaSpinCorr { continue; } pairfound = true; - // pairStatus[t3.index()][t2.index()] = true; pairStatus[t3.index()][t2.index()] = true; - // LOGF(info, "v0 id: (%d, %d)", t3.index(), t2.index()); if (pairfound) { - // LOGF(info, "Pair found"); break; } } } } } - PROCESS_SWITCH(LfTaskLambdaSpinCorr, processME, "Process data ME", true); + + PROCESS_SWITCH(LfTaskLambdaSpinCorr, processDerivedDataMixed, "Process mixed derived data", true); using CollisionMCRecTableCentFT0C = soa::Join; using TrackMCRecTable = soa::Join; diff --git a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx index b5f014ffaba..b6a459fab70 100644 --- a/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx +++ b/PWGLF/Tasks/Strangeness/v0ptinvmassplots.cxx @@ -20,19 +20,25 @@ for different pt ranges (constituting bins). The values are inserted as configur 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 -#include -#include +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/inelGt.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #include "Common/DataModel/EventSelection.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "Common/DataModel/PIDResponse.h" -#include "CommonUtils/StringUtils.h" + #include "CommonConstants/PhysicsConstants.h" +#include "CommonUtils/StringUtils.h" +#include "Framework/AnalysisTask.h" +#include "Framework/O2DatabasePDGPlugin.h" +#include "Framework/runDataProcessing.h" + #include "TPDGCode.h" +#include +#include +#include +#include + // namespace to be used for pt plots and bins namespace pthistos { @@ -55,6 +61,7 @@ struct V0PtInvMassPlots { HistogramRegistry rLambdaMassPlotsPerPtBin{"LambdaMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rAntilambdaMassPlotsPerPtBin{"AntilambdaMassPlotsPerPtBin", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; HistogramRegistry rFeeddownMatrices{"FeeddownMatrices", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry rMCCorrections{"MCCorrections", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; // Configurable for histograms Configurable nBins{"nBins", 100, "N bins in all histos"}; @@ -67,28 +74,85 @@ struct V0PtInvMassPlots { Configurable nSigmaTPCProton{"nSigmaTPCProton", 4, "nSigmaTPCProton"}; Configurable compv0masscut{"compv0masscut", 0.01, "CompetitiveV0masscut (GeV)"}; Configurable etadau{"etadau", 0.8, "Eta Daughters"}; - Configurable rapidityCut{"rapidityCut", 0.5, "V0 Rapidity Window GenMC"}; + Configurable rapidityCut{"rapidityCut", 0.5, "V0 Rapidity Window"}; + Configurable itsMinHits{"itsMinHits", 1.0, "Minimum Hits of Daughter Tracks in the ITS"}; + + // Configurables switches for event selection + Configurable dosel8{"dosel8", true, "Enable sel8 event selection"}; + Configurable doNoTimeFrameBorder{"doNoTimeFrameBorder", true, "Enable NoTimeFrameBorder event selection"}; + Configurable doNoITSROFrameBorder{"doNoITSROFrameBorder", true, "Enable NoITSROFrameBorder event selection"}; + Configurable doIsTriggerTVX{"doIsTriggerTVX", true, "Enable IsTriggerTVX event selection"}; + Configurable docutZVertex{"docutZVertex", true, "Enable cutZVertex event selection"}; + Configurable doIsVertexTOFmatched{"doIsVertexTOFmatched", true, "Enable IsVertexTOFmatched event selection"}; + Configurable doNoSameBunchPileup{"doNoSameBunchPileup", true, "Enable NoSameBunchPileup event selection"}; + Configurable doIsVertexITSTPC{"doIsVertexITSTPC", true, "Enable IsVertexITSTPC event selection"}; + Configurable doisInelGt0{"doisInelGt0", true, "Enable isInelGt0 event selection"}; + + // Configurables switches for v0 selection + Configurable doRapidityCut{"doRapidityCut", true, "Enable rapidity v0 selection"}; + Configurable doDaughterPseudorapidityCut{"doDaughterPseudorapidityCut", true, "Enable Daughter pseudorapidity v0 selection"}; + Configurable doisITSAfterburner{"doisITSAfterburner", true, "Enable ITS Afterburner"}; + Configurable doitsMinHits{"doitsMinHits", true, "Enable ITS Minimum hits"}; + + // Configurables switches for K0sh selection + 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"}; + Configurable doK0shArmenterosCut{"doK0shArmenterosCut", true, "Enable K0sh Armenteros Cut"}; + Configurable doK0shcosPACut{"doK0shcosPACut", true, "Enable K0sh cosPA Topological Cut"}; + Configurable doK0shDCAdauCut{"doK0shDCAdauCut", true, "Enable K0sh DCA daughters Topological Cut"}; + Configurable doK0shv0radiusCut{"doK0shv0radiusCut", true, "Enable K0sh v0radius Topological Cut"}; + Configurable doK0shdcaposdautopv{"doK0shdcaposdautopv", true, "Enable K0sh DCA pos daughter to PV Topological Cut"}; + Configurable doK0shdcanegdautopv{"doK0shdcanegdautopv", true, "Enable K0sh DCA neg daughter to PV Topological Cut"}; + + // Configurables switches for Lambda selection + Configurable doLambdaTPCPID{"doLambdaTPCPID", true, "Enable Lambda TPC PID"}; + Configurable doLambdacomptmasscut{"doLambdacomptmasscut", true, "Enable Lambda Competitive V0 Mass Cut"}; + Configurable doLambdaMaxct{"doLambdaMaxct", true, "Enable Lambda Max ct Cut"}; + Configurable doLambdaArmenterosCut{"doLambdaArmenterosCut", true, "Enable Lambda Armenteros Cut"}; + Configurable doLambdacosPACut{"doLambdacosPACut", true, "Enable Lambda cosPA Topological Cut"}; + Configurable doLambdaDCAdauCut{"doLambdaDCAdauCut", true, "Enable Lambda DCA daughters Topological Cut"}; + Configurable doLambdav0radiusCut{"doLambdav0radiusCut", true, "Enable Lambda v0radius Topological Cut"}; + 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"}; - // Configurable Kaonsh Topological Cuts (best cuts determined by v0topologicalcuts task) + // Configurables switches for Lambda selection + 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"}; + Configurable k0shparamArmenterosCut{"k0shparamArmenterosCut", 0.2, "K0sh Armenteros Cut on parameter"}; - // Configurable Lambda Topological Cuts (best cuts determined by v0topologicalcuts task) + // Configurable Lambda Cuts (best cuts determined by v0topologicalcuts task) Configurable lambdaSettingdcav0dau{"lambdaSettingdcav0dau", 0.3, "DCA V0 Daughters"}; Configurable lambdaSettingdcapostopv{"lambdaSettingdcapostopv", 0.05, "DCA Pos To PV"}; Configurable lambdaSettingdcanegtopv{"lambdaSettingdcanegtopv", 0.09, "DCA Neg To PV"}; Configurable lambdaSettingcosPA{"lambdaSettingcosPA", 0.98, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0 Configurable lambdaSettingradius{"lambdaSettingradius", 0.50, "v0radius"}; + Configurable lambdamaxct{"lambdamaxct", 30.00, "Lambda maximum ct value"}; + Configurable lambdaparamArmenterosCut{"lambdaparamArmenterosCut", 0.2, "Lambda Armenteros Cut on parameter"}; - // Configurable Antilambda Topological 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"}; // Configurables for Specific V0s analysis Configurable kzeroAnalysis{"kzeroAnalysis", true, "Enable Kzerosh Pt Analysis"}; @@ -128,8 +192,9 @@ struct V0PtInvMassPlots { AxisSpec lambdaPtAxis = {lambdaptedgevalues, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec antilambdaPtAxis = {antilambdaPtedgevalues, "#it{p}_{T} (GeV/#it{c})"}; AxisSpec armenterosQtAxis = {nBinsArmenteros, 0.0f, 0.3f, "#it{p}_{T} (GeV/#it{c})"}; - AxisSpec armenterosasymAxis = {nBinsArmenteros, -1.f, 1.f, "#ait{p}^{+}_{||}-it{p}^{-}_{||}/it{p}^{+}_{||}+it{p}^{-}_{||}"}; + 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]"}; + AxisSpec partCutsAxis{10, 0.0f, 10.0f, "Cut index"}; std::vector kaonhistvalue(nmaxHistograms + 1); std::vector lambdahistvalue(nmaxHistograms + 1); @@ -138,7 +203,7 @@ struct V0PtInvMassPlots { for (int i = 0; i < nmaxHistograms + 1; i++) { // Histos won't accept "." character so converting it to "_" std::string kaonptbin = pthistos::kaonPtBins[i]; // getting the value of the bin edge size_t pos = kaonptbin.find("."); // finding the "." character - kaonptbin[pos] = '_'; // changing the "." character of thestring-value to a "_" + kaonptbin[pos] = '_'; // changing the "." character of the string-value to a "_" kaonhistvalue[i] = kaonptbin; // filling bin edges list } // Lambda Histograms Pt Bin Edges (same as K0s above) @@ -156,58 +221,54 @@ struct V0PtInvMassPlots { antilambdahistvalue[i] = antilambdaPtbin; } - rPtAnalysis.add("hVertexZ", "hVertexZ", {HistType::kTH1F, {vertexZAxis}}); + // General Plots + rPtAnalysis.add("hNEvents", "hNEvents", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + rPtAnalysis.add("hNRecEvents_Data", "hNRecEvents_Data", {HistType::kTH1D, {{1, 0.f, 1.f}}}); + rPtAnalysis.add("hNV0s", "hNV0s", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + rPtAnalysis.add("hNK0sh", "hNK0sh", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + rPtAnalysis.add("hNLambda", "hNLambda", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + rPtAnalysis.add("hNAntilambda", "hNAntilambda", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + 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, -10.0f, 10.0f}}}); - // Generated Pt Spectrums For Feeddown - rPtAnalysis.add("GenParticleRapidity", "GenParticleRapidity", {HistType::kTH1F, {{nBins, -10.0f, 10.0f}}}); - rPtAnalysis.add("hXiMinusGeneratedPtSpectrum", "hXiMinusGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hXiZeroGeneratedPtSpectrum", "hXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hOmegaGeneratedPtSpectrum", "hOmegaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hXiPlusGeneratedPtSpectrum", "hXiPlusGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hAntiXiZeroGeneratedPtSpectrum", "hAntiXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hAntiOmegaGeneratedPtSpectrum", "hAntiOmegaGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hPhiGeneratedPtSpectrum", "hPhiGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); - // Adding Kzerosh Histograms to registry if (kzeroAnalysis == true) { - rPtAnalysis.add("hK0ShGeneratedPtSpectrum", "hK0ShGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); - rPtAnalysis.add("hK0ShortReconstructedPtSpectrum", "hK0ShortReconstructedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); - rPtAnalysis.add("hMassK0ShortAll", "hMassK0ShortAll", {HistType::kTH1F, {k0ShortMassAxis}}); - rPtAnalysis.add("hK0ShortPtSpectrumBeforeCuts", "hK0ShortPtSpectrumBeforeCuts", {HistType::kTH1F, {k0ShortPtAxis}}); - rPtAnalysis.add("hMassK0ShortAllAfterCuts", "hMassK0ShortAllAfterCuts", {HistType::kTH1F, {k0ShortMassAxis}}); - rPtAnalysis.add("hNSigmaPosPiFromK0s", "hNSigmaPosPiFromK0s", {HistType::kTH2F, {{100, -5.f, 5.f}, {k0ShortPtAxis}}}); - rPtAnalysis.add("hNSigmaNegPiFromK0s", "hNSigmaNegPiFromK0s", {HistType::kTH2F, {{100, -5.f, 5.f}, {k0ShortPtAxis}}}); - rPtAnalysis.add("hK0shEtaDaughters", "hK0shEtaDaughters", {HistType::kTH1F, {{nBins, -1.2f, 1.2f}}}); - rPtAnalysis.add("hArmenterosPodolanskiPlotK0Short", "hArmenterosPodolanskiPlotK0Short", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); - rPtAnalysis.add("hK0shNegDaughterPt", "hK0shNegDaughterPt", {HistType::kTH1F, {k0ShortPtAxis}}); - rPtAnalysis.add("hK0shPosDaughterPt", "hK0shPosDaughterPt", {HistType::kTH1F, {k0ShortPtAxis}}); - + rPtAnalysis.add("hMassK0ShortvsCuts", "hMassK0ShortvsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); + rPtAnalysis.add("hArmenterosPodolanskiPlotK0sh", "hArmenterosPodolanskiPlotK0sh", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); + rPtAnalysis.add("hNSigmaPosPionFromK0s", "hNSigmaPosPionFromK0s", {HistType::kTH2F, {{100, -5.f, 5.f}, {k0ShortPtAxis}}}); + rPtAnalysis.add("hNSigmaNegPionFromK0s", "hNSigmaNegPionFromK0s", {HistType::kTH2F, {{100, -5.f, 5.f}, {k0ShortPtAxis}}}); + rPtAnalysis.add("hK0shV0radius", "hK0shV0radius", {HistType::kTH1F, {{nBins, 0.0f, 50.0f}}}); + rPtAnalysis.add("hK0shcosPA", "hK0shcosPA", {HistType::kTH1F, {{nBins, 0.95f, 1.0f}}}); + rPtAnalysis.add("hK0shDCAV0Daughters", "hK0shDCAV0Daughters", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); + 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 < nmaxHistograms; i++) { pthistos::kaonPt[i] = rKaonshMassPlotsPerPtBin.add(fmt::format("hPt_from_{0}_to_{1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), fmt::format("hPt_from_{0}_to_{1}", kaonhistvalue[i], kaonhistvalue[i + 1]).c_str(), {HistType::kTH1D, {{k0ShortMassAxis}}}); } + rFeeddownMatrices.add("hK0shFeeddownMatrix", "hK0shFeeddownMatrix", {HistType::kTH2F, {{k0ShortPtAxis}, {k0ShortPtAxis}}}); + rFeeddownMatrices.add("hK0shPhiFeeddownMatrix", "hK0shPhiFeeddownMatrix", {HistType::kTH2F, {{k0ShortPtAxis}, {k0ShortPtAxis}}}); } // Adding Lambda Histograms if (lambdaAnalysis == true) { // same method as in Kzerosh above - rPtAnalysis.add("hLambdaGeneratedPtSpectrum", "hLambdaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hLambdaReconstructedPtSpectrum", "hLambdaReconstructedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hMassLambdaAll", "hMassLambdaAll", {HistType::kTH1F, {lambdaMassAxis}}); - rPtAnalysis.add("hLambdaPtSpectrumBeforeCuts", "hLambdaPtSpectrumBeforeCuts", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hMassLambdaAllAfterCuts", "hMassLambdaAllAfterCuts", {HistType::kTH1F, {lambdaMassAxis}}); - rPtAnalysis.add("hNSigmaPosProtonFromLambda", "hNSigmaPosProtonFromLambda", {HistType::kTH2F, {{100, -5.f, 5.f}, {lambdaPtAxis}}}); - rPtAnalysis.add("hNSigmaNegPionFromLambda", "hNSigmaNegPionFromLambda", {HistType::kTH2F, {{100, -5.f, 5.f}, {lambdaPtAxis}}}); - rPtAnalysis.add("hLambdaEtaDaughters", "hLambdaEtaDaughters", {HistType::kTH1F, {{nBins, -1.2f, 1.2f}}}); + rPtAnalysis.add("hMassLambdavsCuts", "hMassLambdavsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); rPtAnalysis.add("hArmenterosPodolanskiPlotLambda", "hArmenterosPodolanskiPlotLambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); - rPtAnalysis.add("hLambdaNegDaughterPt", "hLambdaNegDaughterPt", {HistType::kTH1F, {lambdaPtAxis}}); - rPtAnalysis.add("hLambdaPosDaughterPt", "hLambdaPosDaughterPt", {HistType::kTH1F, {lambdaPtAxis}}); + rPtAnalysis.add("hLambdaAlphaTestPtSpectrum", "hLambdaAlphaTestPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rPtAnalysis.add("hNSigmaPosProtonFromLambdas", "hNSigmaPosProtonFromLambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {lambdaPtAxis}}}); + rPtAnalysis.add("hNSigmaNegPionFromLambdas", "hNSigmaNegPionFromLambdas", {HistType::kTH2F, {{100, -5.f, 5.f}, {lambdaPtAxis}}}); + rPtAnalysis.add("hLambdaV0radius", "hLambdaV0radius", {HistType::kTH1F, {{nBins, 0.0f, 50.0f}}}); + rPtAnalysis.add("hLambdacosPA", "hLambdacosPA", {HistType::kTH1F, {{nBins, 0.95f, 1.0f}}}); + rPtAnalysis.add("hLambdaDCAV0Daughters", "hLambdaDCAV0Daughters", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); + rPtAnalysis.add("hLambdaDCAPosDaughter", "hLambdaDCAPosDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); + rPtAnalysis.add("hLambdaDCANegDaughter", "hLambdaDCANegDaughter", {HistType::kTH1F, {{nBins, 0.0f, 2.2f}}}); for (int i = 0; i < nmaxHistograms; i++) { pthistos::lambdaPt[i] = rLambdaMassPlotsPerPtBin.add(fmt::format("hPt_from_{0}_to_{1}", lambdahistvalue[i], lambdahistvalue[i + 1]).c_str(), fmt::format("hPt_from_{0}_to_{1}", lambdahistvalue[i], lambdahistvalue[i + 1]).c_str(), {HistType::kTH1D, {{lambdaMassAxis}}}); } // lambdafeeddown matrices + rFeeddownMatrices.add("hLambdaFeeddownMatrix", "hLambdaFeeddownMatrix", {HistType::kTH2F, {{lambdaPtAxis}, {lambdaPtAxis}}}); rFeeddownMatrices.add("hLambdaXiMinusFeeddownMatrix", "hLambdaXiMinusFeeddownMatrix", {HistType::kTH2F, {{lambdaPtAxis}, {lambdaPtAxis}}}); rFeeddownMatrices.add("hLambdaXiZeroFeeddownMatrix", "hLambdaXiZeroFeeddownMatrix", {HistType::kTH2F, {{lambdaPtAxis}, {lambdaPtAxis}}}); rFeeddownMatrices.add("hLambdaOmegaFeeddownMatrix", "hLambdaOmegaFeeddownMatrix", {HistType::kTH2F, {{lambdaPtAxis}, {lambdaPtAxis}}}); @@ -215,99 +276,477 @@ struct V0PtInvMassPlots { // Adding Antilambda Histograms if (antiLambdaAnalysis == true) { // same method as in Lambda and Kzerosh above - rPtAnalysis.add("hAntilambdaGeneratedPtSpectrum", "hAntilambdaGeneratedPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); - rPtAnalysis.add("hAntilambdaReconstructedPtSpectrum", "hAntilambdaReconstructedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hMassAntilambdaAll", "hMassAntilambdaAll", {HistType::kTH1F, {antiLambdaMassAxis}}); - rPtAnalysis.add("hantilambdaPtSpectrumBeforeCuts", "hantilambdaPtSpectrumBeforeCuts", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hMassAntilambdaAllAfterCuts", "hMassAntilambdaAllAfterCuts", {HistType::kTH1F, {antiLambdaMassAxis}}); - rPtAnalysis.add("hNSigmaNegProtonFromAntilambda", "hNSigmaNegProtonFromAntilambda", {HistType::kTH2F, {{100, -5.f, 5.f}, {antilambdaPtAxis}}}); - rPtAnalysis.add("hNSigmaPosPionFromAntilambda", "hNSigmaPosPionFromAntilambda", {HistType::kTH2F, {{100, -5.f, 5.f}, {antilambdaPtAxis}}}); - rPtAnalysis.add("hAntiLambdaEtaDaughters", "hAntiLambdaEtaDaughters", {HistType::kTH1F, {{nBins, -1.2f, 1.2f}}}); - rPtAnalysis.add("hArmenterosPodolanskiPlotAntiLambda", "hArmenterosPodolanskiPlotAntiLambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); - rPtAnalysis.add("hAntiLambdaNegDaughterPt", "hAntiLambdaNegDaughterPt", {HistType::kTH1F, {antilambdaPtAxis}}); - rPtAnalysis.add("hAntiLambdaPosDaughterPt", "hAntiLambdaPosDaughterPt", {HistType::kTH1F, {antilambdaPtAxis}}); + rPtAnalysis.add("hMassAntilambdavsCuts", "hMassAntilambdavsCuts", {HistType::kTH2F, {{partCutsAxis}, {k0ShortMassAxis}}}); + rPtAnalysis.add("hArmenterosPodolanskiPlotAntilambda", "hArmenterosPodolanskiPlotAntilambda", {HistType::kTH2F, {{armenterosasymAxis}, {armenterosQtAxis}}}); + rPtAnalysis.add("hAntilambdaAlphaTestPtSpectrum", "hAntilambdaAlphaTestPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); + 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 < nmaxHistograms; i++) { pthistos::antilambdaPt[i] = rAntilambdaMassPlotsPerPtBin.add(fmt::format("hPt_from_{0}_to_{1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), fmt::format("hPt_from_{0}_to_{1}", antilambdahistvalue[i], antilambdahistvalue[i + 1]).c_str(), {HistType::kTH1D, {{antiLambdaMassAxis}}}); } // antilambdafeeddown matrices + rFeeddownMatrices.add("hAntiLambdaFeeddownMatrix", "hAntiLambdaFeeddownMatrix", {HistType::kTH2F, {{antilambdaPtAxis}, {antilambdaPtAxis}}}); rFeeddownMatrices.add("hAntiLambdaXiPlusFeeddownMatrix", "hAntiLambdaXiPlusFeeddownMatrix", {HistType::kTH2F, {{antilambdaPtAxis}, {antilambdaPtAxis}}}); rFeeddownMatrices.add("hAntiLambdaAntiXiZeroFeeddownMatrix", "hAntiLambdaAntiXiZeroFeeddownMatrix", {HistType::kTH2F, {{antilambdaPtAxis}, {antilambdaPtAxis}}}); rFeeddownMatrices.add("hAntiLambdaAntiOmegaFeeddownMatrix", "hAntiLambdaAntiOmegaPlusFeeddownMatrix", {HistType::kTH2F, {{antilambdaPtAxis}, {antilambdaPtAxis}}}); } + + // Particle Level Corrections + rMCCorrections.add("hK0ShSplitDenominatorPtSpectrum", "hK0ShSplitDenominatorPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaSplitDenominatorPtSpectrum", "hLambdaSplitDenominatorPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaSplitDenominatorPtSpectrum", "hAntilambdaSplitDenominatorPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hK0ShSplitNumenatorPtSpectrum", "hK0ShSplitNumenatorPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaSplitNumenatorPtSpectrum", "hLambdaSplitNumenatorPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaSplitNumenatorPtSpectrum", "hAntilambdaSplitNumenatorPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hK0ShBeforeEventSelectionPtSpectrum", "hK0ShBeforeEventSelectionPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaBeforeEventSelectionPtSpectrum", "hLambdaBeforeEventSelectionPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaBeforeEventSelectionPtSpectrum", "hAntilambdaBeforeEventSelectionPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hK0ShAfterEventSelectionPtSpectrum", "hK0ShAfterEventSelectionPtSpectrum", {HistType::kTH1D, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaAfterEventSelectionPtSpectrum", "hLambdaAfterEventSelectionPtSpectrum", {HistType::kTH1D, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaAfterEventSelectionPtSpectrum", "hAntilambdaAfterEventSelectionPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + + // Event and V0s Corrections + rMCCorrections.add("hNEvents_Corrections", "hNEvents_Corrections", {HistType::kTH1D, {{10, 0.f, 10.f}}}); + rMCCorrections.add("hNRecEvents_MC", "hNRecEvents_MC", {HistType::kTH1D, {{1, 0.f, 1.f}}}); + + // Generated Level Pt Spectrums (with rapidity cut) + rMCCorrections.add("GenParticleRapidity", "GenParticleRapidity", {HistType::kTH1F, {{nBins, -10.0f, 10.0f}}}); + rMCCorrections.add("hK0ShGeneratedPtSpectrum", "hK0ShGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); + rMCCorrections.add("hLambdaGeneratedPtSpectrum", "hLambdaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hAntilambdaGeneratedPtSpectrum", "hAntilambdaGeneratedPtSpectrum", {HistType::kTH1F, {{antilambdaPtAxis}}}); + rMCCorrections.add("hXiMinusGeneratedPtSpectrum", "hXiMinusGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hXiZeroGeneratedPtSpectrum", "hXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hOmegaGeneratedPtSpectrum", "hOmegaGeneratedPtSpectrum", {HistType::kTH1F, {lambdaPtAxis}}); + rMCCorrections.add("hXiPlusGeneratedPtSpectrum", "hXiPlusGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); + rMCCorrections.add("hAntiXiZeroGeneratedPtSpectrum", "hAntiXiZeroGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); + rMCCorrections.add("hAntiOmegaGeneratedPtSpectrum", "hAntiOmegaGeneratedPtSpectrum", {HistType::kTH1F, {antilambdaPtAxis}}); + rMCCorrections.add("hPhiGeneratedPtSpectrum", "hPhiGeneratedPtSpectrum", {HistType::kTH1F, {k0ShortPtAxis}}); } - // Defining filters for events (event selection) - // Processed events will be already fulfilling the event selection requirements - Filter eventFilter = (o2::aod::evsel::sel8 == true); - Filter posZFilterMC = (nabs(o2::aod::mccollision::posZ) < cutZVertex); - Filter posZFilter = (nabs(o2::aod::collision::posZ) < cutZVertex); + // Event selection function + template + bool acceptEvent(TCollision const& collision) + { + rPtAnalysis.fill(HIST("hNEvents"), 0.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(1, "All"); + if (!(collision.sel8() && dosel8)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 1.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(2, "sel 8"); + if (!(collision.selection_bit(aod::evsel::kNoTimeFrameBorder) && doNoTimeFrameBorder)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 2.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(3, "NoTimeFrameBorder"); + if (!(collision.selection_bit(aod::evsel::kNoITSROFrameBorder) && doNoITSROFrameBorder)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 3.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(4, "NoITSROFrameBorder"); + if (!(collision.selection_bit(aod::evsel::kIsTriggerTVX) && doIsTriggerTVX)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 4.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(5, "IsTriggerTVX"); + if (!(std::abs(collision.posZ()) < cutZVertex && docutZVertex)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 5.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(6, "cutZVertex"); + if (!(collision.selection_bit(aod::evsel::kIsVertexTOFmatched) && doIsVertexTOFmatched)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 6.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(7, "IsVertexTOFmatched"); + if (!(collision.selection_bit(aod::evsel::kNoSameBunchPileup) && doNoSameBunchPileup)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 7.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(8, "NoSameBunchPileup"); + if (!(collision.selection_bit(aod::evsel::kIsVertexITSTPC) && doIsVertexITSTPC)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 8.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(9, "IsVertexITSTPC"); + if (!(collision.isInelGt0() && doisInelGt0)) { + return false; + } + rPtAnalysis.fill(HIST("hNEvents"), 9.5); + rPtAnalysis.get(HIST("hNEvents"))->GetXaxis()->SetBinLabel(10, "isInelGt0"); + return true; + + // Cut Plots + rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); + } + + // V0 selection function + template + bool acceptV0(TV0 const& v0) + { + const auto& posDaughterTrack = v0.template posTrack_as(); // Positive Daughter track + const auto& negDaughterTrack = v0.template negTrack_as(); // Negative Daughter track + + rPtAnalysis.fill(HIST("hNV0s"), 0.5); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(1, "All V0s"); + if (std::abs(v0.y()) > rapidityCut && doRapidityCut) { // V0 Rapidity Cut + return false; + } + rPtAnalysis.fill(HIST("hNV0s"), 1.5); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(2, "Rapidity"); + if ((std::abs(posDaughterTrack.eta()) > etadau && std::abs(negDaughterTrack.eta()) > etadau) && doDaughterPseudorapidityCut) { // Daughters Pseudorapidity Cut + return false; + } + rPtAnalysis.fill(HIST("hNV0s"), 2.5); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(3, "Dau Pseudorapidity"); + if ((posDaughterTrack.isITSAfterburner() || negDaughterTrack.isITSAfterburner()) && !doisITSAfterburner) { // ITS After Burner on daughter tracks + return false; + } + rPtAnalysis.fill(HIST("hNV0s"), 3.5); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(4, "ITS Afterburner"); + if (posDaughterTrack.itsNCls() <= itsMinHits && negDaughterTrack.itsNCls() <= itsMinHits && doitsMinHits) { // Minimum hits in the ITS + return false; + rPtAnalysis.fill(HIST("hNV0s"), 4.5); + rPtAnalysis.get(HIST("hNV0s"))->GetXaxis()->SetBinLabel(5, "ITS Min Hits"); + // Cut Plots + rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.template posTrack_as().eta()); + rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.template negTrack_as().eta()); + } + return true; + } + + // K0sh selection function + template + bool acceptK0sh(TV0 const& v0) + { + 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("hMassK0ShortvsCuts"), 0.5, v0.mK0Short()); + if ((std::abs(posDaughterTrack.tpcNSigmaPi()) > nSigmaTPCPion && std::abs(negDaughterTrack.tpcNSigmaPi()) > nSigmaTPCPion) && doK0shTPCPID) { // TPC PID for two pions + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 1.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(2, "TPC_PID"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 1.5, v0.mK0Short()); + if (std::abs(v0.mLambda() - o2::constants::physics::MassLambda0) < compv0masscut && std::abs(v0.mAntiLambda() - o2::constants::physics::MassLambda0) < compv0masscut && doK0shcomptmasscut) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 2.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(3, "Compt_Mass"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 2.5, v0.mK0Short()); + if (v0.v0radius() > kaonshmaxct && doK0shMaxct) { // K0sh max ct + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 3.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(4, "Max_ct"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 3.5, v0.mK0Short()); + if (v0.qtarm() < (k0shparamArmenterosCut * std::abs(v0.alpha())) && doK0shArmenterosCut) { // K0sh Armenteros Cut + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 4.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(5, "Armenteros"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 4.5, v0.mK0Short()); + if (v0.v0cosPA() < kaonshSettingcosPA && doK0shcosPACut) { // K0sh cosPA Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 5.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(6, "cosPA"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 5.5, v0.mK0Short()); + if (v0.dcaV0daughters() > kaonshSettingdcav0dau && doK0shDCAdauCut) { // K0sh DCAdaughters Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 6.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(7, "DCAdau"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 6.5, v0.mK0Short()); + if (v0.v0radius() < kaonshSettingradius && doK0shv0radiusCut) { // K0sh v0radius Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 7.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(8, "v0radius"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 7.5, v0.mK0Short()); + if (std::abs(v0.dcapostopv()) < kaonshSettingdcapostopv && doK0shdcaposdautopv) { // K0sh DCAPosDaughterToPV Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 8.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(9, "DCAPosDautoPV"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 8.5, v0.mK0Short()); + if (std::abs(v0.dcanegtopv()) < kaonshSettingdcanegtopv && doK0shdcanegdautopv) { // K0sh DCANegDaughterToPV Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNK0sh"), 9.5); + rPtAnalysis.get(HIST("hNK0sh"))->GetXaxis()->SetBinLabel(10, "DCANegDautoPV"); + rPtAnalysis.fill(HIST("hMassK0ShortvsCuts"), 9.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("hK0shcosPA"), v0.v0cosPA()); + rPtAnalysis.fill(HIST("hK0shV0radius"), v0.v0radius()); + rPtAnalysis.fill(HIST("hK0shDCAV0Daughters"), v0.dcaV0daughters()); + rPtAnalysis.fill(HIST("hK0shDCAPosDaughter"), v0.dcapostopv()); + rPtAnalysis.fill(HIST("hK0shDCANegDaughter"), v0.dcanegtopv()); + return true; + } + + // Lambda selection function + template + bool acceptLambda(TV0 const& v0) + { + 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("hMassLambdavsCuts"), 0.5, v0.mLambda()); + if (std::abs(posDaughterTrack.tpcNSigmaPr()) > nSigmaTPCProton && std::abs(negDaughterTrack.tpcNSigmaPi()) > nSigmaTPCPion && doLambdaTPCPID) { // TPC PID on daughter pion and proton for Lambda + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 1.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(2, "TPC_PID"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 1.5, v0.mLambda()); + if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < compv0masscut && doLambdacomptmasscut) { // Lambda competitive v0 mass cut (cut out Kaons) + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 2.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(3, "Compt_Mass"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 2.5, v0.mLambda()); + if (v0.v0radius() > lambdamaxct && doLambdaMaxct) { // Lambda max ct + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 3.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(4, "Max_ct"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 3.5, v0.mLambda()); + if (v0.qtarm() < (lambdaparamArmenterosCut * std::abs(v0.alpha())) && doLambdaArmenterosCut) { // Lambda Armenteros Cut + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 4.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(5, "Armenteros"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 4.5, v0.mLambda()); + if (v0.v0cosPA() < lambdaSettingcosPA && doLambdacosPACut) { // Lambda cosPA Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 5.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(6, "cosPA"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 5.5, v0.mLambda()); + if (v0.dcaV0daughters() > lambdaSettingdcav0dau && doLambdaDCAdauCut) { // Lambda DCAdaughters Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 6.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(7, "DCAdau"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 6.5, v0.mLambda()); + if (v0.v0radius() < lambdaSettingradius && doLambdav0radiusCut) { // Lambda v0radius Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 7.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(8, "v0radius"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 7.5, v0.mLambda()); + if (std::abs(v0.dcapostopv()) < lambdaSettingdcapostopv && doLambdadcaposdautopv) { // Lambda DCAPosDaughterToPV Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 8.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(9, "DCAPosDautoPV"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 8.5, v0.mLambda()); + if (std::abs(v0.dcanegtopv()) < lambdaSettingdcanegtopv && doLambdadcanegdautopv) { // Lambda DCANegDaughterToPV Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNLambda"), 9.5); + rPtAnalysis.get(HIST("hNLambda"))->GetXaxis()->SetBinLabel(10, "DCANegDautoPV"); + rPtAnalysis.fill(HIST("hMassLambdavsCuts"), 9.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("hLambdacosPA"), v0.v0cosPA()); + rPtAnalysis.fill(HIST("hLambdaV0radius"), v0.v0radius()); + rPtAnalysis.fill(HIST("hLambdaDCAV0Daughters"), v0.dcaV0daughters()); + rPtAnalysis.fill(HIST("hLambdaDCAPosDaughter"), v0.dcapostopv()); + rPtAnalysis.fill(HIST("hLambdaDCANegDaughter"), v0.dcanegtopv()); + return true; + } + + // Antilambda selection function + template + bool acceptAntilambda(TV0 const& v0) + { + 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()); + if (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"), 1.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(2, "TPC_PID"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 1.5, v0.mAntiLambda()); + if (std::abs(v0.mK0Short() - o2::constants::physics::MassK0Short) < compv0masscut && doAntilambdacomptmasscut) { // Antilambda competitive v0 mass cut (cut out Kaons) + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 2.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(3, "Compt_Mass"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 2.5, v0.mAntiLambda()); + if (v0.v0radius() > antilambdamaxct && doAntilambdaMaxct) { // Antilambda max ct + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 3.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(4, "Max_ct"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 3.5, v0.mAntiLambda()); + if (v0.qtarm() < (antilambdaparamArmenterosCut * std::abs(v0.alpha())) && doAntilambdaArmenterosCut) { // Antilambda Armenteros Cut + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 4.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(5, "Armenteros"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 4.5, v0.mAntiLambda()); + if (v0.v0cosPA() < antilambdaSettingcosPA && doAntilambdacosPACut) { // Antilambda cosPA Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 5.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(6, "cosPA"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 5.5, v0.mAntiLambda()); + if (v0.dcaV0daughters() > antilambdaSettingdcav0dau && doAntilambdaDCAdauCut) { // Antilambda DCAdaughters Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 6.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(7, "DCAdau"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 6.5, v0.mAntiLambda()); + if (v0.v0radius() < antilambdaSettingradius && doAntilambdav0radiusCut) { // Antilambda v0radius Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 7.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(8, "v0radius"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 7.5, v0.mAntiLambda()); + if (std::abs(v0.dcapostopv()) < antilambdaSettingdcapostopv && doAntilambdadcaposdautopv) { // Antilambda DCAPosDaughterToPV Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 8.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(9, "DCAPosDautoPV"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 8.5, v0.mAntiLambda()); + if (std::abs(v0.dcanegtopv()) < antilambdaSettingdcanegtopv && doAntilambdadcanegdautopv) { // Antilambda DCANegDaughterToPV Topological Cut + return false; + } + rPtAnalysis.fill(HIST("hNAntilambda"), 9.5); + rPtAnalysis.get(HIST("hNAntilambda"))->GetXaxis()->SetBinLabel(10, "DCANegDautoPV"); + rPtAnalysis.fill(HIST("hMassAntilambdavsCuts"), 9.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()); + return true; + } // Defining the type of the daughter tracks using DaughterTracks = soa::Join; - // This is the Process for the MC Generated Data - void genMCProcess(soa::Filtered::iterator const&, - const soa::SmallGroups>&, - aod::McParticles const& mcParticles) + void genMCProcess( + aod::McCollisions::iterator const& /*mcCollisions*/, + soa::SmallGroups> const& collisions, + aod::McParticles const& mcParticles) { + // Event Efficiency, Event Split and V0 Signal Loss Corrections + rMCCorrections.fill(HIST("hNEvents_Corrections"), 0.5); // Event Efficiency Denominator + + // 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()) { - rPtAnalysis.fill(HIST("GenParticleRapidity"), mcParticle.y()); + rMCCorrections.fill(HIST("GenParticleRapidity"), mcParticle.y()); if (mcParticle.pdgCode() == kK0Short) // kzero matched { - rPtAnalysis.fill(HIST("hK0ShGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hK0ShGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kLambda0) // lambda matched { - rPtAnalysis.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hLambdaGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched { - rPtAnalysis.fill(HIST("hAntilambdaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hAntilambdaGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kXiMinus) // Xi Minus matched { - rPtAnalysis.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hXiMinusGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kXi0) // Xi Zero matched { - rPtAnalysis.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hXiZeroGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kOmegaMinus) // Omega matched { - rPtAnalysis.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hOmegaGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kXiPlusBar) // Xi Plus matched { - rPtAnalysis.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hXiPlusGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == -kXi0) // Anti-Xi Zero matched { - rPtAnalysis.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hAntiXiZeroGeneratedPtSpectrum"), mcParticle.pt()); } if (mcParticle.pdgCode() == kOmegaPlusBar) // Anti-Omega matched { - rPtAnalysis.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hAntiOmegaGeneratedPtSpectrum"), mcParticle.pt()); } - if (mcParticle.pdgCode() == kPhi) // Anti-Omega matched + if (mcParticle.pdgCode() == kPhi) // Phi { - rPtAnalysis.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt()); + rMCCorrections.fill(HIST("hPhiGeneratedPtSpectrum"), mcParticle.pt()); } } } } + // Signal Loss Numenator Loop + for (const auto& collision : collisions) { + rMCCorrections.fill(HIST("hNEvents_Corrections"), 1.5); // Number of Events Reconsctructed + if (!acceptEvent(collision)) { // Event Selection + return; + } + rMCCorrections.fill(HIST("hNEvents_Corrections"), 2.5); // Event Split Denomimator and Event Efficiency Numenator + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) { + continue; + } + if (std::abs(mcParticle.y()) > rapidityCut) { + continue; + } + if (mcParticle.pdgCode() == kK0Short) // kzero matched + { + rMCCorrections.fill(HIST("hK0ShAfterEventSelectionPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0) // lambda matched + { + rMCCorrections.fill(HIST("hLambdaAfterEventSelectionPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0Bar) // antilambda matched + { + rMCCorrections.fill(HIST("hAntilambdaAfterEventSelectionPtSpectrum"), mcParticle.pt()); + } + } + } + // End of Signal Loss Numenator Loop } // This is the Process for the MC reconstructed Data - void recMCProcess(soa::Filtered>::iterator const& collision, + void recMCProcess(soa::Join::iterator const& collision, soa::Join const& V0s, DaughterTracks const&, // no need to define a variable for tracks, if we don't access them directly - aod::McParticles const&) + aod::McParticles const& mcParticles) { - // PDG mass values for Competitive V0 Cut old: const auto& mK0shPDG = 0.497611; - double mK0shPDG = o2::constants::physics::MassK0Short; - double mLambdaPDG = o2::constants::physics::MassLambda0; - // tokenise strings into individual values pthistos::kaonPtBins = o2::utils::Str::tokenize(kzeroSettingPtBinsString, ','); pthistos::lambdaPtBins = o2::utils::Str::tokenize(lambdaSettingPtBinsString, ','); @@ -323,124 +762,139 @@ struct V0PtInvMassPlots { lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - rPtAnalysis.fill(HIST("hVertexZ"), collision.posZ()); + if (!acceptEvent(collision)) { // Event Selection + return; + } + rMCCorrections.fill(HIST("hNRecEvents_MC"), 0.5); // Event Split Numenator + + // v0 Signal Splitting Numenator Start + for (const auto& mcParticle : mcParticles) { + if (mcParticle.isPhysicalPrimary()) { + if (std::abs(mcParticle.y()) < rapidityCut) { + if (mcParticle.pdgCode() == kK0Short) { // kzero matched + rMCCorrections.fill(HIST("hK0ShSplitNumenatorPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0) { // lambda matched + rMCCorrections.fill(HIST("hLambdaSplitNumenatorPtSpectrum"), mcParticle.pt()); + } + if (mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched + rMCCorrections.fill(HIST("hAntilambdaSplitNumenatorPtSpectrum"), mcParticle.pt()); + } + } + } + } + // V0 Signal Splitting Numenator End + for (const auto& v0 : V0s) { - rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); // Checking that the V0 is a true K0s/Lambdas/Antilambdas and then filling the parameter histograms and the invariant mass plots for different cuts (which are taken from namespace) if (v0.has_mcParticle()) { auto v0mcParticle = v0.mcParticle(); - if (std::abs(v0mcParticle.y()) < rapidityCut) { - rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); - if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); - if (kzeroAnalysis == true) { - if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched - rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0ShortPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // Kzero competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) - // Implementing best kzero topological cuts - if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0ShortReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; 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()); // filling the k0s namespace histograms - } - } - } - } + + // signal splitting demoninator + if (v0mcParticle.isPhysicalPrimary()) { + if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched + rMCCorrections.fill(HIST("hK0ShSplitDenominatorPtSpectrum"), v0mcParticle.pt()); + } + if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched + rMCCorrections.fill(HIST("hLambdaSplitDenominatorPtSpectrum"), v0mcParticle.pt()); + } + if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched + rMCCorrections.fill(HIST("hAntilambdaSplitDenominatorPtSpectrum"), v0mcParticle.pt()); + } + } + // signal splitting demoninator end + + if (!acceptV0(v0)) { // V0 Selections + continue; + } + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), v0.alpha(), v0.qtarm()); + // kzero analysis + if (kzeroAnalysis == true) { + if (v0mcParticle.pdgCode() == kK0Short) { // kzero matched + if (!acceptK0sh(v0)) { // K0sh Selection + continue; + } + + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; 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()); // filling the k0s namespace histograms + } + } + } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mothers = v0mcParticle.mothers_as(); // Get mothers + if (!v0mothers.empty()) { + auto& v0mcParticleMother = v0mothers.front(); // First mother + rFeeddownMatrices.fill(HIST("hK0shFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + if (v0mcParticleMother.pdgCode() == kPhi) { // Phi Mother Matched + rFeeddownMatrices.fill(HIST("hK0shPhiFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); } } } - // lambda analysis - if (lambdaAnalysis == true) { - if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched - rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) - // Implementing best lambda cuts - if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda()); - } - } - } - if (!v0mcParticle.isPhysicalPrimary()) { - auto v0mothers = v0mcParticle.mothers_as(); // Get mothers - if (!v0mothers.empty()) { - auto& v0mcParticleMother = v0mothers.front(); // First mother - if (v0mcParticleMother.pdgCode() == kXiMinus) // Xi Minus Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kXi0) // Xi Zero Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kOmegaMinus) // Omega Mother Matched - { - rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - } - } - } + } + } + // lambda analysis + if (lambdaAnalysis == true) { + if (v0mcParticle.pdgCode() == kLambda0) { // lambda matched + + if (!acceptLambda(v0)) { // Lambda Selections + continue; + } + + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda()); } } } - // antilambda analysis - if (antiLambdaAnalysis == true) { - if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched - rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hantilambdaPtSpectrumBeforeCuts"), v0.pt()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) - // Implementing best antilambda cuts - if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hAntilambdaReconstructedPtSpectrum"), v0.pt()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - if (v0mcParticle.isPhysicalPrimary()) { - for (int i = 0; i < nmaxHistograms; i++) { - if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); - } - } - } - if (!v0mcParticle.isPhysicalPrimary()) { - auto v0mothers = v0mcParticle.mothers_as(); // Get mothers - if (!v0mothers.empty()) { - auto& v0mcParticleMother = v0mothers.front(); // First mother - if (v0mcParticleMother.pdgCode() == kXiPlusBar) // Xi Plus Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == -kXi0) // Anti-Xi Zero Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) // Anti-Omega (minus) Mother Matched - { - rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); - } - } - } - } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mothers = v0mcParticle.mothers_as(); // Get mothers + if (!v0mothers.empty()) { + auto& v0mcParticleMother = v0mothers.front(); // First mother + rFeeddownMatrices.fill(HIST("hLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + if (v0mcParticleMother.pdgCode() == kXiMinus) { // Xi Minus Mother Matched + rFeeddownMatrices.fill(HIST("hLambdaXiMinusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kXi0) { // Xi Zero Mother Matched + rFeeddownMatrices.fill(HIST("hLambdaXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kOmegaMinus) { // Omega Mother Matched + rFeeddownMatrices.fill(HIST("hLambdaOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + } + } + } + } + // antilambda analysis + if (antiLambdaAnalysis == true) { + if (v0mcParticle.pdgCode() == kLambda0Bar) { // antilambda matched + + if (!acceptAntilambda(v0)) { // Antilambda Selections + continue; + } + + if (v0mcParticle.isPhysicalPrimary()) { + for (int i = 0; i < nmaxHistograms; i++) { + if (antilambdaPtedgevalues[i] <= v0.pt() && v0.pt() < antilambdaPtedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); + } + } + } + if (!v0mcParticle.isPhysicalPrimary()) { + auto v0mothers = v0mcParticle.mothers_as(); // Get mothers + if (!v0mothers.empty()) { + auto& v0mcParticleMother = v0mothers.front(); // First mother + rFeeddownMatrices.fill(HIST("hAntiLambdaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + if (v0mcParticleMother.pdgCode() == kXiPlusBar) { // Xi Plus Mother Matched + rFeeddownMatrices.fill(HIST("hAntiLambdaXiPlusFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == -kXi0) { // Anti-Xi Zero Mother Matched + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiXiZeroFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); + } + if (v0mcParticleMother.pdgCode() == kOmegaPlusBar) { // Anti-Omega (minus) Mother Matched + rFeeddownMatrices.fill(HIST("hAntiLambdaAntiOmegaFeeddownMatrix"), v0mcParticle.pt(), v0mcParticleMother.pt()); } } } @@ -450,13 +904,10 @@ struct V0PtInvMassPlots { } } // This is the process for Real Data - void dataProcess(soa::Filtered>::iterator const& collision, + void dataProcess(soa::Join::iterator const& collision, aod::V0Datas const& V0s, DaughterTracks const&) { - double mK0shPDG = o2::constants::physics::MassK0Short; - double mLambdaPDG = o2::constants::physics::MassLambda0; - // tokenise strings into individual values pthistos::kaonPtBins = o2::utils::Str::tokenize(kzeroSettingPtBinsString, ','); pthistos::lambdaPtBins = o2::utils::Str::tokenize(lambdaSettingPtBinsString, ','); @@ -471,98 +922,47 @@ struct V0PtInvMassPlots { lambdaptedgevalues[i] = std::stod(pthistos::lambdaPtBins[i]); antilambdaPtedgevalues[i] = std::stod(pthistos::antilambdaPtBins[i]); } - rPtAnalysis.fill(HIST("hVertexZ"), collision.posZ()); + if (!acceptEvent(collision)) { // Event Selection + return; + } + rPtAnalysis.fill(HIST("hNRecEvents_Data"), 1.0); // Number of Reconstructed Events + for (const auto& v0 : V0s) { - const auto& posDaughterTrack = v0.posTrack_as(); - const auto& negDaughterTrack = v0.negTrack_as(); - // Armenteros-Podolandski Plot Values - double pv0 = std::sqrt((v0.px() * v0.px()) + (v0.py() * v0.py()) + (v0.pz() * v0.pz())); - double pposdauparallelv0 = ((v0.posTrack_as().px() * v0.px()) + (v0.posTrack_as().py() * v0.py()) + (v0.posTrack_as().pz() * v0.pz())) / pv0; - double qValue = std::sqrt(((v0.posTrack_as().px() * v0.posTrack_as().px()) + (v0.posTrack_as().py() * v0.posTrack_as().py()) + (v0.posTrack_as().pz() * v0.posTrack_as().pz())) - (pposdauparallelv0 * pposdauparallelv0)); - double plpos = (v0.posTrack_as().px() * v0.px() / pv0) + (v0.posTrack_as().py() * v0.py() / pv0) + (v0.posTrack_as().pz() * v0.pz() / pv0); - double plneg = (v0.negTrack_as().px() * v0.px() / pv0) + (v0.negTrack_as().py() * v0.py() / pv0) + (v0.negTrack_as().pz() * v0.pz() / pv0); - double aValue = (plpos - plneg) / (plpos + plneg); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), aValue, qValue); - rPtAnalysis.fill(HIST("hVertexZRec"), collision.posZ()); - if (std::abs(v0.y()) < rapidityCut) { - rPtAnalysis.fill(HIST("V0Rapidity"), v0.y()); - if (std::abs(v0.posTrack_as().eta()) < etadau && std::abs(v0.negTrack_as().eta()) < etadau) { // daughters pseudorapidityCut cut - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hV0EtaDaughters"), v0.posTrack_as().eta()); - // kzero analysis - if (kzeroAnalysis == true) { - // Filling the five Kzero invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassK0ShortAll"), v0.mK0Short()); - if (std::abs(v0.mLambda() - mLambdaPDG) > compv0masscut && std::abs(v0.mAntiLambda() - mLambdaPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Lambdas and Anti-Lambdas) - // Implementing best kzero cuts - if (std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pions - rPtAnalysis.fill(HIST("hNSigmaPosPiFromK0s"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPiFromK0s"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - if (v0.v0cosPA() > kaonshSettingcosPA && v0.dcaV0daughters() < kaonshSettingdcav0dau && v0.v0radius() > kaonshSettingradius && std::abs(v0.dcapostopv()) > kaonshSettingdcapostopv && std::abs(v0.dcanegtopv()) > kaonshSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassK0ShortAllAfterCuts"), v0.mK0Short()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hK0shEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotK0Short"), aValue, qValue); - rPtAnalysis.fill(HIST("hK0shNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hK0shPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (kaonptedgevalues[i] <= v0.pt() && v0.pt() < kaonptedgevalues[i + 1]) { - pthistos::kaonPt[i]->Fill(v0.mK0Short()); - } - } - } - } - } + // 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 + continue; + } + rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlot"), v0.alpha(), v0.qtarm()); + // kzero analysis + if (kzeroAnalysis == true) { + if (!acceptK0sh(v0)) { // K0sh Selection + continue; + } + for (int i = 0; i < nmaxHistograms; 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()); // filling the k0s namespace histograms } - // lambda analysis - if (lambdaAnalysis == true) { - // Filling the five lambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassLambdaAll"), v0.mLambda()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // lambda competitive v0 mass cut (cut out Kaons) - if (std::abs(posDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(negDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for Lambda - rPtAnalysis.fill(HIST("hNSigmaPosProtonFromLambda"), posDaughterTrack.tpcNSigmaPr(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegPionFromLambda"), negDaughterTrack.tpcNSigmaPi(), negDaughterTrack.tpcInnerParam()); - // Implementing best lambda cuts - if (v0.v0cosPA() > lambdaSettingcosPA && v0.dcaV0daughters() < lambdaSettingdcav0dau && v0.v0radius() > lambdaSettingradius && std::abs(v0.dcapostopv()) > lambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > lambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassLambdaAllAfterCuts"), v0.mLambda()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotLambda"), aValue, qValue); - rPtAnalysis.fill(HIST("hLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::lambdaPt[i]->Fill(v0.mLambda()); - } - } - } - } - } + } + } + // lambda analysis + if (lambdaAnalysis == true) { + if (!acceptLambda(v0)) { // Lambda Selection + continue; + } + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::lambdaPt[i]->Fill(v0.mLambda()); } - // anti-lambda analysis - if (antiLambdaAnalysis == true) { - // Filling the five Antilambda invariant mass plots for different cuts (which are taken from namespace), for full explanation see the first kzero cut filling in the MC process - rPtAnalysis.fill(HIST("hMassAntilambdaAll"), v0.mAntiLambda()); - if (std::abs(v0.mK0Short() - mK0shPDG) > compv0masscut) { // antilambda competitive v0 mass cut (cut out Kaons) - if (std::abs(negDaughterTrack.tpcNSigmaPr()) < nSigmaTPCProton && std::abs(posDaughterTrack.tpcNSigmaPi()) < nSigmaTPCPion) { // TPC PID on daughter pion and proton for AntiLambda - rPtAnalysis.fill(HIST("hNSigmaPosPionFromAntilambda"), posDaughterTrack.tpcNSigmaPi(), posDaughterTrack.tpcInnerParam()); - rPtAnalysis.fill(HIST("hNSigmaNegProtonFromAntilambda"), negDaughterTrack.tpcNSigmaPr(), negDaughterTrack.tpcInnerParam()); - // implementing best antilambda cuts - if (v0.v0cosPA() > antilambdaSettingcosPA && v0.dcaV0daughters() < antilambdaSettingdcav0dau && v0.v0radius() > antilambdaSettingradius && std::abs(v0.dcapostopv()) > antilambdaSettingdcapostopv && std::abs(v0.dcanegtopv()) > antilambdaSettingdcanegtopv) { - rPtAnalysis.fill(HIST("hMassAntilambdaAllAfterCuts"), v0.mAntiLambda()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.negTrack_as().eta()); - rPtAnalysis.fill(HIST("hAntiLambdaEtaDaughters"), v0.posTrack_as().eta()); - rPtAnalysis.fill(HIST("hArmenterosPodolanskiPlotAntiLambda"), aValue, qValue); - rPtAnalysis.fill(HIST("hAntiLambdaNegDaughterPt"), v0.negTrack_as().pt()); // Neg Daughter Pt - rPtAnalysis.fill(HIST("hAntiLambdaPosDaughterPt"), v0.posTrack_as().pt()); // Pos Daughter Pt - for (int i = 0; i < nmaxHistograms; i++) { - if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { - pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); - } - } - } - } - } + } + } + // anti-lambda analysis + if (antiLambdaAnalysis == true) { + if (!acceptAntilambda(v0)) { // Antilambda Selection + continue; + } + for (int i = 0; i < nmaxHistograms; i++) { + if (lambdaptedgevalues[i] <= v0.pt() && v0.pt() < lambdaptedgevalues[i + 1]) { + pthistos::antilambdaPt[i]->Fill(v0.mAntiLambda()); } } } diff --git a/PWGLF/Utils/collisionCuts.h b/PWGLF/Utils/collisionCuts.h index 399454e9368..b1a80cfe075 100644 --- a/PWGLF/Utils/collisionCuts.h +++ b/PWGLF/Utils/collisionCuts.h @@ -16,15 +16,17 @@ /// original author: Laura Serksnyte, TU München /// /// \author Bong-Hwi Lim +/// \author Hirak Kumar Koley #ifndef PWGLF_UTILS_COLLISIONCUTS_H_ #define PWGLF_UTILS_COLLISIONCUTS_H_ -#include +#include "Common/DataModel/EventSelection.h" #include "Framework/HistogramRegistry.h" #include "Framework/Logger.h" -#include "Common/DataModel/EventSelection.h" + +#include namespace o2::analysis { @@ -185,13 +187,15 @@ class CollisonCuts /// \param col Collision /// \return whether or not the collisions fulfills the specified selections template - bool isSelected(T const& col) + bool isSelected(T const& col, const bool QA = true) { - mHistogramRegistry->fill(HIST("Event/posZ_noCut"), col.posZ()); - if (mCheckIsRun3) { - mHistogramRegistry->fill(HIST("Event/trackOccupancyInTimeRange_noCut"), col.trackOccupancyInTimeRange()); + if (QA) { + mHistogramRegistry->fill(HIST("Event/posZ_noCut"), col.posZ()); + if (mCheckIsRun3) { + mHistogramRegistry->fill(HIST("Event/trackOccupancyInTimeRange_noCut"), col.trackOccupancyInTimeRange()); + } + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kAllEvent); } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kAllEvent); if (std::abs(col.posZ()) > mZvtxMax) { LOGF(debug, "Vertex out of range"); return false; @@ -204,48 +208,66 @@ class CollisonCuts } mInitialColBitScan = false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvertex); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvertex); + } if (mCheckIsRun3) { // Run3 case if (!col.selection_bit(aod::evsel::kIsTriggerTVX) && mTriggerTVXselection) { LOGF(debug, "Offline selection TVX failed (Run3)"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTrigerTVX); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTrigerTVX); + } if (!col.selection_bit(aod::evsel::kNoTimeFrameBorder) && mApplyTFBorderCut) { LOGF(debug, "Time frame border cut failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTimeFrameBorder); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagTimeFrameBorder); + } if (!col.selection_bit(aod::evsel::kNoITSROFrameBorder) && mApplyNoITSROBorderCut) { LOGF(debug, "NoITSRO frame border cut failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagITSROFrameBorder); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagITSROFrameBorder); + } if (!col.sel8() && mCheckOffline) { LOGF(debug, "Offline selection failed (Run3)"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagSel8); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagSel8); + } if (!col.selection_bit(o2::aod::evsel::kIsVertexITSTPC) && mApplyITSTPCvertex) { LOGF(debug, "ITS-TPC matching cut failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagVertexITSTPC); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagVertexITSTPC); + } if (!col.selection_bit(o2::aod::evsel::kNoSameBunchPileup) && mApplyPileupRejection) { LOGF(debug, "Pileup rejection failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagBunchPileup); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagBunchPileup); + } if (!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow) && mApplyCollInTimeRangeNarrow) { LOGF(debug, "NoCollInTimeRangeNarrow selection failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kNoCollInTimeRangeNarrow); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kNoCollInTimeRangeNarrow); + } if (!col.selection_bit(o2::aod::evsel::kIsGoodZvtxFT0vsPV) && mApplyZvertexTimedifference) { LOGF(debug, "Z-vertex time difference cut failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvtxFT0vsPV); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagZvtxFT0vsPV); + } if (mtrackOccupancyInTimeRangeMax > 0 && col.trackOccupancyInTimeRange() > mtrackOccupancyInTimeRangeMax) { LOGF(debug, "trackOccupancyInTimeRange selection failed"); return false; @@ -254,12 +276,16 @@ class CollisonCuts LOGF(debug, "trackOccupancyInTimeRange selection failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagOccupancy); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kFlagOccupancy); + } if ((!col.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) && mApplyCollInTimeRangeStandard) { LOGF(debug, "NoCollInTimeRangeStandard selection failed"); return false; } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kNoCollInTimeRangeStandard); + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kNoCollInTimeRangeStandard); + } } else { // Run2 case if (mCheckOffline && !col.sel7()) { LOGF(debug, "Offline selection failed (sel7)"); @@ -275,9 +301,13 @@ class CollisonCuts LOGF(debug, "INELgtZERO selection failed"); return false; } + if (QA) { + mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kAllpassed); + } + } + if (QA) { mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kAllpassed); } - mHistogramRegistry->fill(HIST("CollCutCounts"), EvtSel::kAllpassed); return true; } diff --git a/PWGLF/Utils/decay3bodyBuilderHelper.h b/PWGLF/Utils/decay3bodyBuilderHelper.h new file mode 100644 index 00000000000..49131c16040 --- /dev/null +++ b/PWGLF/Utils/decay3bodyBuilderHelper.h @@ -0,0 +1,852 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +#ifndef PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ +#define PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ + +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" +#include "Tools/KFparticle/KFUtilities.h" + +#include "CommonConstants/PhysicsConstants.h" +#include "DCAFitter/DCAFitterN.h" +#include "DetectorsBase/GeometryManager.h" +#include "DetectorsVertexing/SVertexHypothesis.h" +#include "Framework/AnalysisDataModel.h" +#include "ReconstructionDataFormats/Track.h" + +#include +#include +#include + +#ifndef HomogeneousField +#define HomogeneousField +#endif + +/// includes KFParticle +#include "KFPTrack.h" +#include "KFPVertex.h" +#include "KFParticle.h" +#include "KFParticleBase.h" +#include "KFVertex.h" + +namespace o2 +{ +namespace pwglf +{ + +//_______________________________________________________________________ +// Deca3body information storage +struct decay3bodyCandidate { + // indexing + int collisionID = -1; + int decay3bodyID = -1; + int protonID = -1; + int pionID = -1; + int deuteronID = -1; + + // daughter properties + std::array momProton = {0.0f, 0.0f, 0.0f}; + std::array momPion = {0.0f, 0.0f, 0.0f}; + std::array momDeuteron = {0.0f, 0.0f, 0.0f}; + std::array posProton = {0.0f, 0.0f, 0.0f}; + std::array posPion = {0.0f, 0.0f, 0.0f}; + std::array posDeuteron = {0.0f, 0.0f, 0.0f}; + std::array trackDCAxyToPV = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + std::array trackDCAzToPV = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + std::array tpcNsigma = {0.0f, 0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron, 3 - bach with pion hyp + double tofNsigmaDeuteron = 0.0f; + std::array averageITSClSize = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + std::array tpcNCl = {0.0f, 0.0f, 0.0f}; // 0 - proton, 1 - pion, 2 - deuteron + int pidForTrackingDeuteron = 0; + + // vertex properties + float mass; + float massV0; + int sign; + float momentum[3]; + float position[3]; + float chi2 = 0.0f; + float trackedClSize = 0.0f; + float cosPA = 0.0f; // cosine of pointing angle + float ctau = 0.0f; // ctau of the candidate + float daughterDCAtoSVaverage = 0.0f; // average of quadratic sum of daughter DCAs to SV + std::array daughterDCAtoSV = {0.0f, 0.0f, 0.0f}; // 0 - pos, 1 - neg, 2 - bach + + // covariance matrix + float covProton[21] = {0.0f}; + float covPion[21] = {0.0f}; + float covDeuteron[21] = {0.0f}; + float covariance[21] = {0.0f}; +}; + +//_______________________________________________________________________ +// builder helper class +class decay3bodyBuilderHelper +{ + public: + decay3bodyBuilderHelper() + { + fitter3body.setPropagateToPCA(true); + fitter3body.setMaxR(200.); //->maxRIni3body + fitter3body.setMinParamChange(1e-3); + fitter3body.setMinRelChi2Change(0.9); + fitter3body.setMaxDZIni(1e9); + fitter3body.setMaxDXYIni(4.0f); + fitter3body.setMaxChi2(1e9); + fitter3body.setUseAbsDCA(true); + + fitterV0.setPropagateToPCA(true); + fitterV0.setMaxR(200.); + fitterV0.setMinParamChange(1e-3); + fitterV0.setMinRelChi2Change(0.9); + fitterV0.setMaxDZIni(1e9); + fitterV0.setMaxChi2(1e9); + fitterV0.setUseAbsDCA(true); + + // mag field has to be set later + fitter3body.setBz(-999.9f); // will NOT make sense if not changed + }; + + o2::vertexing::DCAFitterN<2> fitterV0; // 2-prong o2 dca fitter + o2::vertexing::DCAFitterN<3> fitter3body; // 3-prong o2 dca fitter + + decay3bodyCandidate decay3body; // storage for Decay3body candidate properties + + o2::dataformats::VertexBase mMeanVertex{{0., 0., 0.}, {0.1 * 0.1, 0., 0.1 * 0.1, 0., 0., 6. * 6.}}; + o2::vertexing::SVertexHypothesis mV0Hyps; // 0 - Lambda, 1 - AntiLambda + + // decay3body candidate criteria + struct { + // daughter tracks + float maxEtaDaughters; + int minTPCNClProton; + int minTPCNClPion; + int minTPCNClDeuteron; + float minDCAProtonToPV; + float minDCAPionToPV; + float minDCADeuteronToPV; + float minPtProton; + float minPtPion; + float minPtDeuteron; + float maxPtProton; + float maxPtPion; + float maxPtDeuteron; + float maxTPCnSigma; + double minTOFnSigmaDeuteron; + double maxTOFnSigmaDeuteron; + float minPDeuteronUseTOF; + float maxDCADauToSVaverage; + // candidate + float maxRapidity; + float minPt; + float maxPt; + float minMass; + float maxMass; + float minCtau; + float maxCtau; + float minCosPA; + float maxChi2; + } decay3bodyselections; + + // SVertexer selection criteria + struct { + float minPt2V0; + float maxTgl2V0; + float maxDCAXY2ToMeanVertex3bodyV0; + float minCosPAXYMeanVertex3bodyV0; + float minCosPA3bodyV0; + float maxRDiffV03body; + float minPt3Body; + float maxTgl3Body; + float maxDCAXY3Body; + float maxDCAZ3Body; + } svertexerselections; + + //_______________________________________________________________________ + // build Decay3body from three tracks, including V0 building. + template + bool buildDecay3BodyCandidate(TCollision const& collision, + TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + int decay3bodyIndex, + double tofNsigmaDeuteron, + float trackedClSize, + bool useKFParticle = false, + bool kfSetTopologicalConstraint = false, + bool useSelections = true, + bool useChi2Selection = true, + bool useTPCforPion = false, + bool acceptTPCOnly = false, + bool askOnlyITSMatch = true, + bool calculateCovariance = true, + bool isEventMixing = false) + { + int collisionIndex = collision.globalIndex(); + float pvX = collision.posX(); + float pvY = collision.posY(); + float pvZ = collision.posZ(); + + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + decay3body.collisionID = collisionIndex; + decay3body.decay3bodyID = decay3bodyIndex; + decay3body.protonID = trackProton.globalIndex(); + decay3body.pionID = trackPion.globalIndex(); + decay3body.deuteronID = trackDeuteron.globalIndex(); + + //_______________________________________________________________________ + // track selections + if (useSelections) { + // proton track quality + if (trackProton.tpcNClsFound() < decay3bodyselections.minTPCNClProton) { + decay3body = {}; + return false; + } + // pion track quality + if (useTPCforPion) { + if (trackPion.tpcNClsFound() < decay3bodyselections.minTPCNClPion) { + decay3body = {}; + return false; + } + } + // deuteron track quality + if (trackDeuteron.tpcNClsFound() < decay3bodyselections.minTPCNClDeuteron) { + decay3body = {}; + return false; + } + + // track eta + if (std::fabs(trackProton.eta()) > decay3bodyselections.maxEtaDaughters) { + decay3body = {}; + return false; + } + if (std::fabs(trackPion.eta()) > decay3bodyselections.maxEtaDaughters) { + decay3body = {}; + return false; + } + if (std::fabs(trackDeuteron.eta()) > decay3bodyselections.maxEtaDaughters) { + decay3body = {}; + return false; + } + + // TPC only + if (!acceptTPCOnly) { + if (askOnlyITSMatch) { + if (!trackProton.hasITS() || !trackPion.hasITS() || !trackDeuteron.hasITS()) { + decay3body = {}; + return false; + } + } else { + bool isProtonTPCOnly = !trackProton.hasITS() && !trackProton.hasTOF() && !trackProton.hasTRD(); + bool isPionTPCOnly = !trackPion.hasITS() && !trackPion.hasTOF() && !trackPion.hasTRD(); + bool isDeuteronTPCOnly = !trackDeuteron.hasITS() && !trackDeuteron.hasTOF() && !trackDeuteron.hasTRD(); + if (isProtonTPCOnly || isPionTPCOnly || isDeuteronTPCOnly) { + decay3body = {}; + return false; + } + } + } + + // daughter TPC PID + if (std::fabs(trackProton.tpcNSigmaPr()) > decay3bodyselections.maxTPCnSigma) { + decay3body = {}; + return false; + } + if (useTPCforPion && std::fabs(trackPion.tpcNSigmaPi()) > decay3bodyselections.maxTPCnSigma) { + decay3body = {}; + return false; + } + if (std::fabs(trackDeuteron.tpcNSigmaDe()) > decay3bodyselections.maxTPCnSigma) { + decay3body = {}; + return false; + } + + // deuteron TOF PID + if ((tofNsigmaDeuteron < decay3bodyselections.minTOFnSigmaDeuteron || tofNsigmaDeuteron > decay3bodyselections.maxTOFnSigmaDeuteron) && trackDeuteron.p() > decay3bodyselections.minPDeuteronUseTOF) { + decay3body = {}; + return false; + } + } // end of selections + + //_______________________________________________________________________ + // daughter track DCA to PV associated with decay3body + o2::dataformats::VertexBase mPV; + o2::dataformats::DCA mDcaInfoCov; + auto trackParCovProtonCopy = trackParCovProton; + auto trackParCovPionCopy = trackParCovPion; + auto trackParCovDeuteronCopy = trackParCovDeuteron; + mPV.setPos({pvX, pvY, pvZ}); + mPV.setCov(collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()); + + // proton track + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovProtonCopy, 2.f, fitter3body.getMatCorrType(), &mDcaInfoCov); + decay3body.trackDCAxyToPV[0] = mDcaInfoCov.getY(); + decay3body.trackDCAzToPV[0] = mDcaInfoCov.getZ(); + auto trackProtonDCAToPV = std::sqrt(decay3body.trackDCAxyToPV[0] * decay3body.trackDCAxyToPV[0] + decay3body.trackDCAzToPV[0] * decay3body.trackDCAzToPV[0]); + if (useSelections) { + if (trackProtonDCAToPV < decay3bodyselections.minDCAProtonToPV) { + decay3body = {}; + return false; + } + } + // pion track + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovPionCopy, 2.f, fitter3body.getMatCorrType(), &mDcaInfoCov); + decay3body.trackDCAxyToPV[1] = mDcaInfoCov.getY(); + decay3body.trackDCAzToPV[1] = mDcaInfoCov.getZ(); + auto trackPionDCAToPV = std::sqrt(decay3body.trackDCAxyToPV[1] * decay3body.trackDCAxyToPV[1] + decay3body.trackDCAzToPV[1] * decay3body.trackDCAzToPV[1]); + if (useSelections) { + if (trackPionDCAToPV < decay3bodyselections.minDCAPionToPV) { + decay3body = {}; + return false; + } + } + // deuteron track + o2::base::Propagator::Instance()->propagateToDCABxByBz(mPV, trackParCovDeuteronCopy, 2.f, fitter3body.getMatCorrType(), &mDcaInfoCov); + decay3body.trackDCAxyToPV[2] = mDcaInfoCov.getY(); + decay3body.trackDCAzToPV[2] = mDcaInfoCov.getZ(); + auto trackDeuteronDCAToPV = std::sqrt(decay3body.trackDCAxyToPV[2] * decay3body.trackDCAxyToPV[2] + decay3body.trackDCAzToPV[2] * decay3body.trackDCAzToPV[2]); + if (useSelections) { + if (trackDeuteronDCAToPV < decay3bodyselections.minDCADeuteronToPV) { + decay3body = {}; + return false; + } + } + + //_______________________________________________________________________ + // fit 3body vertex + if (!useKFParticle) { + fitVertexWithDCAFitter(trackProton, trackPion, trackDeuteron, calculateCovariance); + } else { + fitVertexWithKF(collision, trackProton, trackPion, trackDeuteron, kfSetTopologicalConstraint, calculateCovariance); + } + + //_______________________________________________________________________ + // get vertex information + // daughter pT + auto trackProtonPt = std::sqrt(decay3body.momProton[0] * decay3body.momProton[0] + decay3body.momProton[1] * decay3body.momProton[1]); + auto trackPionPt = std::sqrt(decay3body.momPion[0] * decay3body.momPion[0] + decay3body.momPion[1] * decay3body.momPion[1]); + auto trackDeuteronPt = std::sqrt(decay3body.momDeuteron[0] * decay3body.momDeuteron[0] + decay3body.momDeuteron[1] * decay3body.momDeuteron[1]); + + // daughter DCA to SV + // proton daughter + decay3body.daughterDCAtoSV[0] = std::hypot( + decay3body.posProton[0] - decay3body.position[0], + decay3body.posProton[1] - decay3body.position[1], + decay3body.posProton[2] - decay3body.position[2]); + // pion daughter + decay3body.daughterDCAtoSV[1] = std::hypot( + decay3body.posPion[0] - decay3body.position[0], + decay3body.posPion[1] - decay3body.position[1], + decay3body.posPion[2] - decay3body.position[2]); + // deuteron daughter + decay3body.daughterDCAtoSV[2] = std::hypot( + decay3body.posDeuteron[0] - decay3body.position[0], + decay3body.posDeuteron[1] - decay3body.position[1], + decay3body.posDeuteron[2] - decay3body.position[2]); + + // DCA daughters to SV average of quadratic sum + decay3body.daughterDCAtoSVaverage = (decay3body.daughterDCAtoSV[0] * decay3body.daughterDCAtoSV[0] + + decay3body.daughterDCAtoSV[1] * decay3body.daughterDCAtoSV[1] + + decay3body.daughterDCAtoSV[2] * decay3body.daughterDCAtoSV[2]) / + 3; + + //_____________________________________________________ + // selections after vertex fit + if (useSelections) { + // daughter pT + // proton + if (trackProtonPt < decay3bodyselections.minPtProton || trackProtonPt > decay3bodyselections.maxPtProton) { + decay3body = {}; + return false; + } + // pion + if (trackPionPt < decay3bodyselections.minPtPion || trackPionPt > decay3bodyselections.maxPtPion) { + decay3body = {}; + return false; + } + // deuteron + if (trackDeuteronPt < decay3bodyselections.minPtDeuteron || trackDeuteronPt > decay3bodyselections.maxPtDeuteron) { + decay3body = {}; + return false; + } + + // daughter DCAs at SV + if (decay3body.daughterDCAtoSVaverage > decay3bodyselections.maxDCADauToSVaverage) { + decay3body = {}; + return false; + } + + // rapidity + float rapidity = RecoDecay::y(std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}, o2::constants::physics::MassHyperTriton); + if (std::fabs(rapidity) > decay3bodyselections.maxRapidity) { + decay3body = {}; + return false; + } + + // pT + float pT = RecoDecay::pt(std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}); + if (pT < decay3bodyselections.minPt || pT > decay3bodyselections.maxPt) { + decay3body = {}; + return false; + } + + // mass window + if (decay3body.mass < decay3bodyselections.minMass || decay3body.mass > decay3bodyselections.maxMass) { + decay3body = {}; + return false; + } + + // vertex chi2 + if (useChi2Selection && decay3body.chi2 > decay3bodyselections.maxChi2) { + decay3body = {}; + return false; + } + } + + // pointing angle + float cpa = RecoDecay::cpa(std::array{pvX, pvY, pvZ}, std::array{decay3body.position[0], decay3body.position[1], decay3body.position[2]}, std::array{decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]}); + if (useSelections) { + if (cpa < decay3bodyselections.minCosPA) { + decay3body = {}; + return false; + } + } + decay3body.cosPA = cpa; + + // ctau + float P = RecoDecay::sqrtSumOfSquares(decay3body.momentum[0], decay3body.momentum[1], decay3body.momentum[2]); + float ctau = std::sqrt(std::pow(decay3body.position[0] - pvX, 2) + std::pow(decay3body.position[1] - pvY, 2) + std::pow(decay3body.position[2] - pvZ, 2)) / (P + 1E-10) * o2::constants::physics::MassHyperTriton; + if (useSelections) { + if (ctau < decay3bodyselections.minCtau || ctau > decay3bodyselections.maxCtau) { + decay3body = {}; + return false; + } + } + decay3body.ctau = ctau; + + //_______________________________________________________________________ + // SVertexer selections in case of event mixing + if (isEventMixing) { + applySVertexerCuts(collision, trackProton, trackPion, trackDeuteron, /*applyV0Cut = */ true); + } + + //_______________________________________________________________________ + // fill remaining candidate information + // daughter PID + decay3body.tpcNsigma[0] = trackProton.tpcNSigmaPr(); + decay3body.tpcNsigma[1] = trackPion.tpcNSigmaPi(); + decay3body.tpcNsigma[2] = trackDeuteron.tpcNSigmaDe(); + decay3body.tpcNsigma[3] = trackDeuteron.tpcNSigmaPi(); + // recalculated bachelor TOF PID + decay3body.tofNsigmaDeuteron = tofNsigmaDeuteron; + + // average ITS cluster size of daughter tracks + double averageClusterSizeProton(0), averageClusterSizePion(0), averageClusterSizeDeuteron(0); + int nClsProton(0), nClsPion(0), nClsDeuteron(0); + for (int i = 0; i < 7; i++) { + int clusterSizePr = trackProton.itsClsSizeInLayer(i); + int clusterSizePi = trackPion.itsClsSizeInLayer(i); + int clusterSizeDe = trackDeuteron.itsClsSizeInLayer(i); + averageClusterSizeProton += static_cast(clusterSizePr); + averageClusterSizePion += static_cast(clusterSizePi); + averageClusterSizeDeuteron += static_cast(clusterSizeDe); + if (clusterSizePr > 0) + nClsProton++; + if (clusterSizePi > 0) + nClsPion++; + if (clusterSizeDe > 0) + nClsDeuteron++; + } + averageClusterSizeProton = averageClusterSizeProton / static_cast(nClsProton); + averageClusterSizePion = averageClusterSizePion / static_cast(nClsPion); + averageClusterSizeDeuteron = averageClusterSizeDeuteron / static_cast(nClsDeuteron); + decay3body.averageITSClSize[0] = averageClusterSizeProton; + decay3body.averageITSClSize[1] = averageClusterSizePion; + decay3body.averageITSClSize[2] = averageClusterSizeDeuteron; + + // number of TPC clusters + decay3body.tpcNCl[0] = trackProton.tpcNClsFound(); + decay3body.tpcNCl[1] = trackPion.tpcNClsFound(); + decay3body.tpcNCl[2] = trackDeuteron.tpcNClsFound(); + + // PID for tracking of deuteron track + decay3body.pidForTrackingDeuteron = trackDeuteron.pidForTracking(); + + // tracked cluster size + decay3body.trackedClSize = trackedClSize; + + return true; + } + + //___________________________________________________________________________________ + // functionality to fit 3body vertex with KFParticle and fill vertex information + template + void fitVertexWithKF(TCollision const& collision, + TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + bool kfSetTopologicalConstraint = true, + bool calculateCovariance = true) + { + // get TrackParCov daughters + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + // initialise KF primary vertex + KFVertex kfpVertex = createKFPVertexFromCollision(collision); + KFParticle kfpv(kfpVertex); + + // create KFParticle objects + KFParticle kfpProton, kfpPion, kfpDeuteron; + kfpProton = createKFParticleFromTrackParCov(trackParCovProton, trackProton.sign(), constants::physics::MassProton); + kfpPion = createKFParticleFromTrackParCov(trackParCovPion, trackPion.sign(), constants::physics::MassPionCharged); + kfpDeuteron = createKFParticleFromTrackParCov(trackParCovDeuteron, trackDeuteron.sign(), constants::physics::MassDeuteron); + + // construct V0 vertex + KFParticle KFV0; + int nDaughtersV0 = 2; + const KFParticle* DaughtersV0[2] = {&kfpProton, &kfpPion}; + KFV0.SetConstructMethod(2); + try { + KFV0.Construct(DaughtersV0, nDaughtersV0); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to create V0 vertex." << e.what(); + return; + } + + // construct vertex + KFParticle KFH3L; + int nDaughters3body = 3; + const KFParticle* Daughters3body[3] = {&kfpProton, &kfpPion, &kfpDeuteron}; + KFH3L.SetConstructMethod(2); + try { + KFH3L.Construct(Daughters3body, nDaughters3body); + } catch (std::runtime_error& e) { + LOG(debug) << "Failed to create Hyper triton 3-body vertex." << e.what(); + return; + } + + // topological constraint + if (kfSetTopologicalConstraint) { + KFH3L.SetProductionVertex(kfpv); + KFH3L.TransportToDecayVertex(); + } + + // get vertex position and momentum + decay3body.position[0] = KFH3L.GetX(); + decay3body.position[1] = KFH3L.GetY(); + decay3body.position[2] = KFH3L.GetZ(); + decay3body.momentum[0] = KFH3L.GetPx(); + decay3body.momentum[1] = KFH3L.GetPy(); + decay3body.momentum[2] = KFH3L.GetPz(); + + // get sign + decay3body.sign = KFH3L.GetQ() / std::abs(KFH3L.GetQ()); + + // transport all daughter tracks to hypertriton vertex + kfpProton.TransportToPoint(decay3body.position); + kfpPion.TransportToPoint(decay3body.position); + kfpDeuteron.TransportToPoint(decay3body.position); + + // daughter positions + decay3body.posProton[0] = kfpProton.GetX(); + decay3body.posProton[1] = kfpProton.GetY(); + decay3body.posProton[2] = kfpProton.GetZ(); + decay3body.posPion[0] = kfpPion.GetX(); + decay3body.posPion[1] = kfpPion.GetY(); + decay3body.posPion[2] = kfpPion.GetZ(); + decay3body.posDeuteron[0] = kfpDeuteron.GetX(); + decay3body.posDeuteron[1] = kfpDeuteron.GetY(); + decay3body.posDeuteron[2] = kfpDeuteron.GetZ(); + + // daughter momenta + decay3body.momProton[0] = kfpProton.GetPx(); + decay3body.momProton[1] = kfpProton.GetPy(); + decay3body.momProton[2] = kfpProton.GetPz(); + decay3body.momPion[0] = kfpPion.GetPx(); + decay3body.momPion[1] = kfpPion.GetPy(); + decay3body.momPion[2] = kfpPion.GetPz(); + decay3body.momDeuteron[0] = kfpDeuteron.GetPx(); + decay3body.momDeuteron[1] = kfpDeuteron.GetPy(); + decay3body.momDeuteron[2] = kfpDeuteron.GetPz(); + + // candidate mass + float mass, massErr; + KFH3L.GetMass(mass, massErr); + decay3body.mass = mass; + + // V0 mass + float massV0, massV0Err; + KFV0.GetMass(massV0, massV0Err); + decay3body.massV0 = massV0; + + // vertex chi2 + decay3body.chi2 = KFH3L.GetChi2() / KFH3L.GetNDF(); + + // caluclate covariance matrices + if (calculateCovariance) { + // candidate covariance matrix + std::array covKF; + for (int i = 0; i < 21; i++) { // get covariance matrix elements (lower triangle) + covKF[i] = KFH3L.GetCovariance(i); + decay3body.covariance[i] = covKF[i]; + } + // daughter track covariance matrices + for (int i = 0; i < 21; i++) { // get covariance matrix elements (lower triangle) + decay3body.covProton[i] = kfpProton.GetCovariance(i); + decay3body.covPion[i] = kfpPion.GetCovariance(i); + decay3body.covDeuteron[i] = kfpDeuteron.GetCovariance(i); + } + } + + return; + } + + //_______________________________________________________________________ + // functionality to fit 3body vertex with DCAFitter + template + void fitVertexWithDCAFitter(TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + bool calculateCovariance = true) + { + // get TrackParCov daughters + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + // fit the vertex + int n3bodyVtx = fitter3body.process(trackParCovProton, trackParCovPion, trackParCovDeuteron); + if (n3bodyVtx == 0) { // discard this pair + return; + } + + // get vertex position + const auto& vtxXYZ = fitter3body.getPCACandidate(); + for (int i = 0; i < 3; i++) { + decay3body.position[i] = vtxXYZ[i]; + } + + // get daughter momenta + const auto& propagatedTrackProton = fitter3body.getTrack(0); + const auto& propagatedTrackPion = fitter3body.getTrack(1); + const auto& propagatedTrackDeuteron = fitter3body.getTrack(2); + propagatedTrackProton.getPxPyPzGlo(decay3body.momProton); + propagatedTrackPion.getPxPyPzGlo(decay3body.momPion); + propagatedTrackDeuteron.getPxPyPzGlo(decay3body.momDeuteron); + propagatedTrackProton.getXYZGlo(decay3body.posProton); + propagatedTrackPion.getXYZGlo(decay3body.posPion); + propagatedTrackDeuteron.getXYZGlo(decay3body.posDeuteron); + + // get daughter positions at vertex + + // calculate candidate momentum + decay3body.momentum[0] = decay3body.momProton[0] + decay3body.momPion[0] + decay3body.momDeuteron[0]; + decay3body.momentum[1] = decay3body.momProton[1] + decay3body.momPion[1] + decay3body.momDeuteron[1]; + decay3body.momentum[2] = decay3body.momProton[2] + decay3body.momPion[2] + decay3body.momDeuteron[2]; + + // candidate and V0 mass + decay3body.mass = RecoDecay::m( + std::array{std::array{decay3body.momProton[0], decay3body.momProton[1], decay3body.momProton[2]}, + std::array{decay3body.momPion[0], decay3body.momPion[1], decay3body.momPion[2]}, + std::array{decay3body.momDeuteron[0], decay3body.momDeuteron[1], decay3body.momDeuteron[2]}}, + std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged, o2::constants::physics::MassDeuteron}); + decay3body.massV0 = RecoDecay::m( + std::array{std::array{decay3body.momProton[0], decay3body.momProton[1], decay3body.momProton[2]}, + std::array{decay3body.momPion[0], decay3body.momPion[1], decay3body.momPion[2]}}, + std::array{o2::constants::physics::MassProton, o2::constants::physics::MassPionCharged}); + + // vertex chi2 at PCA + decay3body.chi2 = fitter3body.getChi2AtPCACandidate(); + + // candidate sign + decay3body.sign = trackDeuteron.sign(); + + // caluclate covariance matrices + if (calculateCovariance) { + // candidate position covariance matrix + auto covVtxV = fitter3body.calcPCACovMatrix(0); + decay3body.covariance[0] = covVtxV(0, 0); + decay3body.covariance[1] = covVtxV(1, 0); + decay3body.covariance[2] = covVtxV(1, 1); + decay3body.covariance[3] = covVtxV(2, 0); + decay3body.covariance[4] = covVtxV(2, 1); + decay3body.covariance[5] = covVtxV(2, 2); + // daughter covariance matrices + std::array covTproton = {0.}; + std::array covTpion = {0.}; + std::array covTdeuteron = {0.}; + propagatedTrackProton.getCovXYZPxPyPzGlo(covTproton); + propagatedTrackPion.getCovXYZPxPyPzGlo(covTpion); + propagatedTrackDeuteron.getCovXYZPxPyPzGlo(covTdeuteron); + for (int i = 0; i < 21; i++) { + decay3body.covProton[i] = covTproton[i]; + decay3body.covPion[i] = covTpion[i]; + decay3body.covDeuteron[i] = covTdeuteron[i]; + } + // candidate momentum covairance matrix + constexpr int MomInd[6] = {9, 13, 14, 18, 19, 20}; // cov matrix elements for momentum component + for (int i = 0; i < 6; i++) { + decay3body.covariance[MomInd[i]] = covTproton[MomInd[i]] + covTpion[MomInd[i]] + covTdeuteron[MomInd[i]]; + } + /// WARNING: position-momentum covariances are not calculated in the DCAFitter - remain zero + } + + return; + } + + //_______________________________________________________________________ + // functionality to apply SVertexer cuts in case of event mixing + template + void applySVertexerCuts(TCollision const& collision, + TTrack const& trackProton, + TTrack const& trackPion, + TTrack const& trackDeuteron, + bool applyV0Cut = true) + { + // get TrackParCov daughters + auto trackParCovProton = getTrackParCov(trackProton); + auto trackParCovPion = getTrackParCov(trackPion); + auto trackParCovDeuteron = getTrackParCov(trackDeuteron); + + const float pidCutsLambda[o2::vertexing::SVertexHypothesis::NPIDParams] = {0., 20, 0., 5.0, 0.0, 1.09004e-03, 2.62291e-04, 8.93179e-03, 2.83121}; // Lambda + mV0Hyps.set(o2::track::PID::Lambda, o2::track::PID::Proton, o2::track::PID::Pion, pidCutsLambda, fitter3body.getBz()); + + int nV0 = fitterV0.process(trackParCovProton, trackParCovPion); + if (nV0 == 0) { + return; + } + + std::array v0pos = {0.}; + const auto& v0vtxXYZ = fitterV0.getPCACandidate(); + for (int i = 0; i < 3; i++) { + v0pos[i] = v0vtxXYZ[i]; + } + const int cand = 0; + if (!fitterV0.isPropagateTracksToVertexDone(cand) && !fitterV0.propagateTracksToVertex(cand)) { + return; + } + + const auto& trProtonProp = fitterV0.getTrack(0, cand); + const auto& trPionProp = fitterV0.getTrack(1, cand); + std::array pProtonV0{}, pPionV0{}; + trProtonProp.getPxPyPzGlo(pProtonV0); + trPionProp.getPxPyPzGlo(pPionV0); + std::array pV0 = {pProtonV0[0] + pPionV0[0], pProtonV0[1] + pPionV0[1], pProtonV0[2] + pPionV0[2]}; + // Cut for Virtual V0 + float dxv0 = v0pos[0] - mMeanVertex.getX(), dyv0 = v0pos[1] - mMeanVertex.getY(), r2v0 = dxv0 * dxv0 + dyv0 * dyv0; + float rv0 = std::sqrt(r2v0); + float pt2V0 = pV0[0] * pV0[0] + pV0[1] * pV0[1], prodXYv0 = dxv0 * pV0[0] + dyv0 * pV0[1], tDCAXY = prodXYv0 / pt2V0; + if (applyV0Cut && pt2V0 <= svertexerselections.minPt2V0) { + return; + } + if (applyV0Cut && pV0[2] * pV0[2] / pt2V0 > svertexerselections.maxTgl2V0) { // tgLambda cut + return; + } + + float p2V0 = pt2V0 + pV0[2] * pV0[2], ptV0 = std::sqrt(pt2V0); + // apply mass selections + float p2Proton = pProtonV0[0] * pProtonV0[0] + pProtonV0[1] * pProtonV0[1] + pProtonV0[2] * pProtonV0[2], p2Pion = pPionV0[0] * pPionV0[0] + pPionV0[1] * pPionV0[1] + pPionV0[2] * pPionV0[2]; + bool good3bodyV0Hyp = false; + float massForLambdaHyp = mV0Hyps.calcMass(p2Proton, p2Pion, p2V0); + if (massForLambdaHyp - mV0Hyps.getMassV0Hyp() < mV0Hyps.getMargin(ptV0)) { + good3bodyV0Hyp = true; + } + if (applyV0Cut && !good3bodyV0Hyp) { + return; + } + + float dcaX = dxv0 - pV0[0] * tDCAXY, dcaY = dyv0 - pV0[1] * tDCAXY, dca2 = dcaX * dcaX + dcaY * dcaY; + float cosPAXY = prodXYv0 / rv0 * ptV0; + if (applyV0Cut && dca2 > svertexerselections.maxDCAXY2ToMeanVertex3bodyV0) { + return; + } + // FIXME: V0 cosPA cut to be investigated + if (applyV0Cut && cosPAXY < svertexerselections.minCosPAXYMeanVertex3bodyV0) { + return; + } + // Check: CosPA Cut of Virtual V0 may not be used since the V0 may be based on another PV + float dx = v0pos[0] - collision.posX(); + float dy = v0pos[1] - collision.posY(); + float dz = v0pos[2] - collision.posZ(); + float prodXYZv0 = dx * pV0[0] + dy * pV0[1] + dz * pV0[2]; + float v0CosPA = prodXYZv0 / std::sqrt((dx * dx + dy * dy + dz * dz) * p2V0); + if (applyV0Cut && v0CosPA < svertexerselections.minCosPA3bodyV0) { + return; + } + + // 3body vertex + int n3bodyVtx = fitter3body.process(trackParCovProton, trackParCovPion, trackParCovDeuteron); + if (n3bodyVtx == 0) { // discard this pair + return; + } + const auto& vertexXYZ = fitter3body.getPCACandidatePos(); + std::array pos = {0.}; + for (int i = 0; i < 3; i++) { + pos[i] = vertexXYZ[i]; + } + + std::array pProton = {0.}, pPion = {0.}, pDeuteron{0.}; + const auto& propagatedTrackProton = fitter3body.getTrack(0); + const auto& propagatedTrackPion = fitter3body.getTrack(1); + const auto& propagatedTrackDeuteron = fitter3body.getTrack(2); + propagatedTrackProton.getPxPyPzGlo(pProton); + propagatedTrackPion.getPxPyPzGlo(pPion); + propagatedTrackDeuteron.getPxPyPzGlo(pDeuteron); + std::array p3B = {pProton[0] + pPion[0] + pDeuteron[0], pProton[1] + pPion[1] + pDeuteron[1], pProton[2] + pPion[2] + pDeuteron[2]}; + + float r3body = std::hypot(pos[0], pos[1]); + if (r3body < 0.5) { + return; + } + + // Cut for the compatibility of V0 and 3body vertex + float deltaR = std::abs(rv0 - r3body); + if (deltaR > svertexerselections.maxRDiffV03body) { + return; + } + + float pt3B = std::hypot(p3B[0], p3B[1]); + if (pt3B < svertexerselections.minPt3Body) { // pt cut + return; + } + if (p3B[2] / pt3B > svertexerselections.maxTgl3Body) { // tgLambda cut + return; + } + + // H3L DCA Check + auto track3B = o2::track::TrackParCov(vertexXYZ, p3B, trackDeuteron.sign()); + o2::dataformats::DCA dca; + if (!track3B.propagateToDCA({{collision.posX(), collision.posY(), collision.posZ()}, {collision.covXX(), collision.covXY(), collision.covYY(), collision.covXZ(), collision.covYZ(), collision.covZZ()}}, fitter3body.getBz(), &dca, 5.) || + std::abs(dca.getY()) > svertexerselections.maxDCAXY3Body || std::abs(dca.getZ()) > svertexerselections.maxDCAZ3Body) { + return; + } + + return; + } + + private: + // internal helper to calculate DCA (3D) of a straight line to a given PV analytically + 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)); + } +}; + +} // namespace pwglf +} // namespace o2 + +#endif // PWGLF_UTILS_DECAY3BODYBUILDERHELPER_H_ diff --git a/PWGLF/Utils/inelGt.h b/PWGLF/Utils/inelGt.h index 2ed513a902c..70c3de8ab4f 100644 --- a/PWGLF/Utils/inelGt.h +++ b/PWGLF/Utils/inelGt.h @@ -19,6 +19,10 @@ #ifndef PWGLF_UTILS_INELGT_H_ #define PWGLF_UTILS_INELGT_H_ +#include "Framework/O2DatabasePDGPlugin.h" + +#include "TParticlePDG.h" + #include namespace o2 diff --git a/PWGLF/Utils/pidTOFGeneric.h b/PWGLF/Utils/pidTOFGeneric.h new file mode 100644 index 00000000000..3e7dfd58c23 --- /dev/null +++ b/PWGLF/Utils/pidTOFGeneric.h @@ -0,0 +1,496 @@ +// Copyright 2019-2020 CERN and copyright holders of ALICE O2. +// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders. +// All rights not expressly granted are reserved. +// +// This software is distributed under the terms of the GNU General Public +// License v3 (GPL Version 3), copied verbatim in the file "COPYING". +// +// In applying this license CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +/// +/// \file pidTOFGeneric.h +/// \brief Utilities to recalculate secondary tracks TOF PID +/// \author Yuanzhe Wang +/// + +#ifndef PWGLF_UTILS_PIDTOFGENERIC_H_ +#define PWGLF_UTILS_PIDTOFGENERIC_H_ +#include "CollisionTypeHelper.h" +#include "MetadataHelper.h" +#include "TableHelper.h" + +#include "Common/Core/PID/PIDTOF.h" + +#include "CommonDataFormat/InteractionRecord.h" + +#include +#include + +namespace o2::aod +{ + +namespace pidtofgeneric +{ + +// Configuration common to all tasks, copied from pidTOFMerge.cxx but add metadataInfo as a member variable +struct TOFCalibConfig { + template + void init(const CfgType& opt) + { + mUrl = opt.cfgUrl.value; + mPathGrpLhcIf = opt.cfgPathGrpLhcIf.value; + mTimestamp = opt.cfgTimestamp.value; + mTimeShiftCCDBPathPos = opt.cfgTimeShiftCCDBPathPos.value; + mTimeShiftCCDBPathNeg = opt.cfgTimeShiftCCDBPathNeg.value; + mTimeShiftCCDBPathPosMC = opt.cfgTimeShiftCCDBPathPosMC.value; + mTimeShiftCCDBPathNegMC = opt.cfgTimeShiftCCDBPathNegMC.value; + mParamFileName = opt.cfgParamFileName.value; + mParametrizationPath = opt.cfgParametrizationPath.value; + mReconstructionPass = opt.cfgReconstructionPass.value; + mReconstructionPassDefault = opt.cfgReconstructionPassDefault.value; + mFatalOnPassNotAvailable = opt.cfgFatalOnPassNotAvailable.value; + mEnableTimeDependentResponse = opt.cfgEnableTimeDependentResponse.value; + mCollisionSystem = opt.cfgCollisionSystem.value; + mAutoSetProcessFunctions = opt.cfgAutoSetProcessFunctions.value; + } + + template + void getCfg(o2::framework::InitContext& initContext, const std::string name, VType& v, const std::string task) + { + if (!getTaskOptionValue(initContext, task, name, v, false)) { + LOG(fatal) << "Could not get " << name << " from " << task << " task"; + } + } + + void inheritFromBaseTask(o2::framework::InitContext& initContext, const std::string task = "tof-signal") + { + mInitMode = 2; + getCfg(initContext, "ccdb-url", mUrl, task); + getCfg(initContext, "ccdb-path-grplhcif", mPathGrpLhcIf, task); + getCfg(initContext, "ccdb-timestamp", mTimestamp, task); + getCfg(initContext, "timeShiftCCDBPathPos", mTimeShiftCCDBPathPos, task); + getCfg(initContext, "timeShiftCCDBPathNeg", mTimeShiftCCDBPathNeg, task); + getCfg(initContext, "timeShiftCCDBPathPosMC", mTimeShiftCCDBPathPosMC, task); + getCfg(initContext, "timeShiftCCDBPathNegMC", mTimeShiftCCDBPathNegMC, task); + getCfg(initContext, "paramFileName", mParamFileName, task); + getCfg(initContext, "parametrizationPath", mParametrizationPath, task); + getCfg(initContext, "reconstructionPass", mReconstructionPass, task); + getCfg(initContext, "reconstructionPassDefault", mReconstructionPassDefault, task); + getCfg(initContext, "fatalOnPassNotAvailable", mFatalOnPassNotAvailable, task); + getCfg(initContext, "enableTimeDependentResponse", mEnableTimeDependentResponse, task); + getCfg(initContext, "collisionSystem", mCollisionSystem, task); + getCfg(initContext, "autoSetProcessFunctions", mAutoSetProcessFunctions, task); + } + // @brief Set up the configuration from the calibration object from the init function of the task + template + void initSetup(o2::pid::tof::TOFResoParamsV3& mRespParamsV3, + CCDBObject ccdb) + { + mInitMode = 1; + // First we set the CCDB manager + ccdb->setURL(mUrl); + ccdb->setTimestamp(mTimestamp); + ccdb->setCaching(true); + ccdb->setLocalObjectValidityChecking(); + // Not later than now objects + ccdb->setCreatedNotAfter(std::chrono::duration_cast(std::chrono::system_clock::now().time_since_epoch()).count()); + + // Then the information about the metadata + if (mReconstructionPass == "metadata") { + LOG(info) << "Getting pass from metadata"; + if (metadataInfo.isMC()) { + mReconstructionPass = metadataInfo.get("AnchorPassName"); + } else { + mReconstructionPass = metadataInfo.get("RecoPassName"); + } + LOG(info) << "Passed autodetect mode for pass. Taking '" << mReconstructionPass << "'"; + } + LOG(info) << "Using parameter collection, starting from pass '" << mReconstructionPass << "'"; + + if (!mParamFileName.empty()) { // Loading the parametrization from file + LOG(info) << "Loading exp. sigma parametrization from file " << mParamFileName << ", using param: " << mParametrizationPath << " and pass " << mReconstructionPass; + o2::tof::ParameterCollection paramCollection; + paramCollection.loadParamFromFile(mParamFileName, mParametrizationPath); + LOG(info) << "+++ Loaded parameter collection from file +++"; + if (!paramCollection.retrieveParameters(mRespParamsV3, mReconstructionPass)) { + if (mFatalOnPassNotAvailable) { + LOG(fatal) << "Pass '" << mReconstructionPass << "' not available in the retrieved object from file"; + } else { + LOG(warning) << "Pass '" << mReconstructionPass << "' not available in the retrieved object from file, fetching '" << mReconstructionPassDefault << "'"; + if (!paramCollection.retrieveParameters(mRespParamsV3, mReconstructionPassDefault)) { + paramCollection.print(); + LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault; + } else { + if (metadataInfo.isRun3()) { + mRespParamsV3.setResolutionParametrization(paramCollection.getPars(mReconstructionPassDefault)); + } else { + mRespParamsV3.setResolutionParametrizationRun2(paramCollection.getPars(mReconstructionPassDefault)); + } + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPassDefault)); + } + } + } else { // Pass is available, load non standard parameters + if (metadataInfo.isRun3()) { + mRespParamsV3.setResolutionParametrization(paramCollection.getPars(mReconstructionPass)); + } else { + mRespParamsV3.setResolutionParametrizationRun2(paramCollection.getPars(mReconstructionPass)); + } + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection.getPars(mReconstructionPass)); + } + } else if (!mEnableTimeDependentResponse) { // Loading it from CCDB + LOG(info) << "Loading initial exp. sigma parametrization from CCDB, using path: " << mParametrizationPath << " for timestamp " << mTimestamp; + o2::tof::ParameterCollection* paramCollection = ccdb->template getSpecific(mParametrizationPath, mTimestamp); + if (!paramCollection->retrieveParameters(mRespParamsV3, mReconstructionPass)) { // Attempt at loading the parameters with the pass defined + if (mFatalOnPassNotAvailable) { + LOG(fatal) << "Pass '" << mReconstructionPass << "' not available in the retrieved CCDB object"; + } else { + LOG(warning) << "Pass '" << mReconstructionPass << "' not available in the retrieved CCDB object, fetching '" << mReconstructionPassDefault << "'"; + if (!paramCollection->retrieveParameters(mRespParamsV3, mReconstructionPassDefault)) { + paramCollection->print(); + LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault; + } else { + if (metadataInfo.isRun3()) { + mRespParamsV3.setResolutionParametrization(paramCollection->getPars(mReconstructionPassDefault)); + } else { + mRespParamsV3.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPassDefault)); + } + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPassDefault)); + } + } + } else { // Pass is available, load non standard parameters + if (metadataInfo.isRun3()) { + mRespParamsV3.setResolutionParametrization(paramCollection->getPars(mReconstructionPass)); + } else { + mRespParamsV3.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPass)); + } + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPass)); + } + } + + // Loading additional calibration objects + std::map metadata; + if (!mReconstructionPass.empty()) { + metadata["RecoPassName"] = mReconstructionPass; + } + + auto updateTimeShift = [&](const std::string& nameShift, bool isPositive) { + if (nameShift.empty()) { + return; + } + const bool isFromFile = nameShift.find(".root") != std::string::npos; + if (isFromFile) { + LOG(info) << "Initializing the time shift for " << (isPositive ? "positive" : "negative") << " from file '" << nameShift << "'"; + mRespParamsV3.setTimeShiftParameters(nameShift, "ccdb_object", isPositive); + } else if (!mEnableTimeDependentResponse) { // If the response is fixed fetch it at the init time + LOG(info) << "Initializing the time shift for " << (isPositive ? "positive" : "negative") + << " from ccdb '" << nameShift << "' and timestamp " << mTimestamp + << " and pass '" << mReconstructionPass << "'"; + ccdb->setFatalWhenNull(false); + mRespParamsV3.setTimeShiftParameters(ccdb->template getSpecific(nameShift, mTimestamp, metadata), isPositive); + ccdb->setFatalWhenNull(true); + } + LOG(info) << " test getTimeShift at 0 " << (isPositive ? "pos" : "neg") << ": " + << mRespParamsV3.getTimeShift(0, isPositive); + }; + + const std::string nameShiftPos = metadataInfo.isMC() ? mTimeShiftCCDBPathPosMC : mTimeShiftCCDBPathPos; + updateTimeShift(nameShiftPos, true); + const std::string nameShiftNeg = metadataInfo.isMC() ? mTimeShiftCCDBPathNegMC : mTimeShiftCCDBPathNeg; + updateTimeShift(nameShiftNeg, false); + + // Calibration object is defined + LOG(info) << "Parametrization at init time:"; + mRespParamsV3.printFullConfig(); + } + + template + void processSetup(o2::pid::tof::TOFResoParamsV3& mRespParamsV3, + CCDBObject ccdb, + const BcType& bc) + { + LOG(debug) << "Processing setup for run number " << bc.runNumber() << " from run " << mLastRunNumber; + // First we check if this run number was already processed + if (mLastRunNumber == bc.runNumber()) { + return; + } + LOG(info) << "Updating the parametrization from last run " << mLastRunNumber << " to " << bc.runNumber() << " and timestamp from " << mTimestamp << " " << bc.timestamp(); + mLastRunNumber = bc.runNumber(); + mTimestamp = bc.timestamp(); + + // Check the beam type + if (mCollisionSystem == -1) { + o2::parameters::GRPLHCIFData* grpo = ccdb->template getSpecific(mPathGrpLhcIf, + mTimestamp); + mCollisionSystem = CollisionSystemType::getCollisionTypeFromGrp(grpo); + } else { + LOG(debug) << "Not setting collisions system as already set to " << mCollisionSystem << " " << CollisionSystemType::getCollisionSystemName(mCollisionSystem); + } + + if (!mEnableTimeDependentResponse) { + return; + } + LOG(info) << "Updating parametrization from path '" << mParametrizationPath << "' and timestamp " << mTimestamp << " and reconstruction pass '" << mReconstructionPass << "' for run number " << bc.runNumber(); + if (mParamFileName.empty()) { // Not loading if parametrization was taken from file + LOG(info) << "Updating parametrization from ccdb"; + const o2::tof::ParameterCollection* paramCollection = ccdb->template getSpecific(mParametrizationPath, mTimestamp); + if (!paramCollection->retrieveParameters(mRespParamsV3, mReconstructionPass)) { + if (mFatalOnPassNotAvailable) { + LOGF(fatal, "Pass '%s' not available in the retrieved CCDB object", mReconstructionPass.data()); + } else { + LOGF(warning, "Pass '%s' not available in the retrieved CCDB object, fetching '%s'", mReconstructionPass.data(), mReconstructionPassDefault.data()); + if (!paramCollection->retrieveParameters(mRespParamsV3, mReconstructionPassDefault)) { + paramCollection->print(); + LOG(fatal) << "Cannot get default pass for calibration " << mReconstructionPassDefault; + } else { // Found the default case + if (metadataInfo.isRun3()) { + mRespParamsV3.setResolutionParametrization(paramCollection->getPars(mReconstructionPassDefault)); + } else { + mRespParamsV3.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPassDefault)); + } + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPassDefault)); + } + } + } else { // Found the non default case + if (metadataInfo.isRun3()) { + mRespParamsV3.setResolutionParametrization(paramCollection->getPars(mReconstructionPass)); + } else { + mRespParamsV3.setResolutionParametrizationRun2(paramCollection->getPars(mReconstructionPass)); + } + mRespParamsV3.setMomentumChargeShiftParameters(paramCollection->getPars(mReconstructionPass)); + } + } + + // Loading additional calibration objects + std::map metadata; + if (!mReconstructionPass.empty()) { + metadata["RecoPassName"] = mReconstructionPass; + } + + auto updateTimeShift = [&](const std::string& nameShift, bool isPositive) { + if (nameShift.empty()) { + return; + } + const bool isFromFile = nameShift.find(".root") != std::string::npos; + if (isFromFile) { + return; + } + LOG(info) << "Updating the time shift for " << (isPositive ? "positive" : "negative") + << " from ccdb '" << nameShift << "' and timestamp " << mTimestamp + << " and pass '" << mReconstructionPass << "'"; + ccdb->setFatalWhenNull(false); + mRespParamsV3.setTimeShiftParameters(ccdb->template getSpecific(nameShift, mTimestamp, metadata), isPositive); + ccdb->setFatalWhenNull(true); + LOG(info) << " test getTimeShift at 0 " << (isPositive ? "pos" : "neg") << ": " + << mRespParamsV3.getTimeShift(0, isPositive); + }; + + updateTimeShift(metadataInfo.isMC() ? mTimeShiftCCDBPathPosMC : mTimeShiftCCDBPathPos, true); + updateTimeShift(metadataInfo.isMC() ? mTimeShiftCCDBPathNegMC : mTimeShiftCCDBPathNeg, false); + + LOG(info) << "Parametrization at setup time:"; + mRespParamsV3.printFullConfig(); + } + + bool autoSetProcessFunctions() const { return mAutoSetProcessFunctions; } + int collisionSystem() const { return mCollisionSystem; } + + o2::common::core::MetadataHelper metadataInfo; // additional member variable to store metadata information compared to pidTOFMerge.cxx + + private: + int mLastRunNumber = -1; // Last run number for which the calibration was loaded + int mInitMode = 0; // 0: no init, 1: init, 2: inherit + + // Configurable options + std::string mUrl; + std::string mPathGrpLhcIf; + int64_t mTimestamp; + std::string mTimeShiftCCDBPathPos; + std::string mTimeShiftCCDBPathNeg; + std::string mTimeShiftCCDBPathPosMC; + std::string mTimeShiftCCDBPathNegMC; + std::string mParamFileName; + std::string mParametrizationPath; + std::string mReconstructionPass; + std::string mReconstructionPassDefault; + bool mFatalOnPassNotAvailable; + bool mEnableTimeDependentResponse; + int mCollisionSystem; + bool mAutoSetProcessFunctions; +}; + +static constexpr float kCSPEED = TMath::C() * 1.0e2f * 1.0e-12f; // c in cm/ps + +template +class TofPidNewCollision +{ + public: + TofPidNewCollision() = default; + ~TofPidNewCollision() = default; + + o2::pid::tof::TOFResoParamsV3 mRespParamsV3; + o2::track::PID::ID pidType; + + template + using ResponseImplementation = o2::pid::tof::ExpTimes; + static constexpr auto responseEl = ResponseImplementation(); + static constexpr auto responseMu = ResponseImplementation(); + static constexpr auto responsePi = ResponseImplementation(); + static constexpr auto responseKa = ResponseImplementation(); + static constexpr auto responsePr = ResponseImplementation(); + static constexpr auto responseDe = ResponseImplementation(); + static constexpr auto responseTr = ResponseImplementation(); + static constexpr auto responseHe = ResponseImplementation(); + static constexpr auto responseAl = ResponseImplementation(); + + void SetParams(o2::pid::tof::TOFResoParamsV3 const& para) + { + mRespParamsV3.setParameters(para); + } + + void SetPidType(o2::track::PID::ID pidId) + { + pidType = pidId; + } + + template + float GetTOFNSigma(o2::track::PID::ID pidId, const ParamType& parameters, TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D = true); + + template + float GetTOFNSigma(const ParamType& parameters, TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D = true); + + template + float GetTOFNSigma(const ParamType& parameters, TTrack const& track); + template + float GetTOFNSigma(o2::track::PID::ID pidId, const ParamType& parameters, TTrack const& track); + + template + float CalculateTOFNSigma(o2::track::PID::ID pidId, const ParamType& parameters, TTrack const& track, double tofsignal, double evTime, double evTimeErr) + { + + float expSigma, tofNsigma = -999; + + switch (pidId) { + case 0: + expSigma = responseEl.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseEl.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 1: + expSigma = responseMu.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseMu.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 2: + expSigma = responsePi.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responsePi.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 3: + expSigma = responseKa.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseKa.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 4: + expSigma = responsePr.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responsePr.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 5: + expSigma = responseDe.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseDe.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 6: + expSigma = responseTr.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseTr.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 7: + expSigma = responseHe.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseHe.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + case 8: + expSigma = responseAl.GetExpectedSigma(parameters, track, tofsignal, evTimeErr); + tofNsigma = (tofsignal - evTime - responseAl.GetCorrectedExpectedSignal(parameters, track)) / expSigma; + break; + default: + LOG(fatal) << "Wrong particle ID in TofPidSecondary class"; + return -999; + } + + return tofNsigma; + } +}; + +template +template +float TofPidNewCollision::GetTOFNSigma(o2::track::PID::ID pidId, const ParamType& parameters, TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D) +{ + + if (!track.has_collision() || !track.hasTOF()) { + return -999; + } + + float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; + float expTime = track.length() * std::sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v + + float evTime = correctedcol.evTime(); + float evTimeErr = correctedcol.evTimeErr(); + float tofsignal = track.trackTime() * 1000 + expTime; // in ps + + if (originalcol.globalIndex() == correctedcol.globalIndex()) { + evTime = track.evTimeForTrack(); + evTimeErr = track.evTimeErrForTrack(); + } else { + if (EnableBCAO2D) { + auto originalbc = originalcol.template bc_as(); + auto correctedbc = correctedcol.template bc_as(); + o2::InteractionRecord originalIR = o2::InteractionRecord::long2IR(originalbc.globalBC()); + o2::InteractionRecord correctedIR = o2::InteractionRecord::long2IR(correctedbc.globalBC()); + tofsignal += originalIR.differenceInBCNS(correctedIR) * 1000; + } else { + auto originalbc = originalcol.template foundBC_as(); + auto correctedbc = correctedcol.template foundBC_as(); + o2::InteractionRecord originalIR = o2::InteractionRecord::long2IR(originalbc.globalBC()); + o2::InteractionRecord correctedIR = o2::InteractionRecord::long2IR(correctedbc.globalBC()); + tofsignal += originalIR.differenceInBCNS(correctedIR) * 1000; + } + } + + float tofNsigma = CalculateTOFNSigma(pidId, parameters, track, tofsignal, evTime, evTimeErr); + return tofNsigma; +} + +template +template +float TofPidNewCollision::GetTOFNSigma(const ParamType& parameters, TTrack const& track, TCollision const& originalcol, TCollision const& correctedcol, bool EnableBCAO2D) +{ + return GetTOFNSigma(pidType, parameters, track, originalcol, correctedcol, EnableBCAO2D); +} + +template +template +float TofPidNewCollision::GetTOFNSigma(o2::track::PID::ID pidId, const ParamType& parameters, TTrack const& track) +{ + + if (!track.has_collision() || !track.hasTOF()) { + return -999; + } + + float mMassHyp = o2::track::pid_constants::sMasses2Z[track.pidForTracking()]; + float expTime = track.length() * std::sqrt((mMassHyp * mMassHyp) + (track.tofExpMom() * track.tofExpMom())) / (kCSPEED * track.tofExpMom()); // L*E/(p*c) = L/v + + float evTime = track.evTimeForTrack(); + float evTimeErr = track.evTimeErrForTrack(); + float tofsignal = track.trackTime() * 1000 + expTime; // in ps + + float tofNsigma = CalculateTOFNSigma(pidId, parameters, track, tofsignal, evTime, evTimeErr); + return tofNsigma; +} + +template +template +float TofPidNewCollision::GetTOFNSigma(const ParamType& parameters, TTrack const& track) +{ + return GetTOFNSigma(pidType, parameters, track); +} + +} // namespace pidtofgeneric +} // namespace o2::aod + +#endif // PWGLF_UTILS_PIDTOFGENERIC_H_ diff --git a/PWGLF/Utils/strangenessBuilderHelper.h b/PWGLF/Utils/strangenessBuilderHelper.h index 85257418e0a..6eda3c07848 100644 --- a/PWGLF/Utils/strangenessBuilderHelper.h +++ b/PWGLF/Utils/strangenessBuilderHelper.h @@ -160,6 +160,8 @@ struct v0candidate { float daughterDCA = 1000.0f; float pointingAngle = 1.0f; float dcaToPV = 0.0f; + float v0DCAToPVxy = 0.0f; + float v0DCAToPVz = 0.0f; // calculated masses for convenience float massGamma; @@ -346,6 +348,16 @@ class strangenessBuilderHelper } fitter.setCollinear(false); // proper cleaning: when exiting this loop, always reset to not collinear + // Calculate DCAToPV of the V0 + o2::track::TrackPar V0Temp = fitter.createParentTrackPar(); + V0Temp.setAbsCharge(0); // charge zero + std::array dcaV0Info; + + // propagate to collision vertex + o2::base::Propagator::Instance()->propagateToDCABxByBz({pvX, pvY, pvZ}, V0Temp, 2.f, fitter.getMatCorrType(), &dcaV0Info); + v0.v0DCAToPVxy = dcaV0Info[0]; + v0.v0DCAToPVz = dcaV0Info[1]; + v0.positiveTrackX = fitter.getTrack(0).getX(); v0.negativeTrackX = fitter.getTrack(1).getX(); positiveTrackParam = fitter.getTrack(0); diff --git a/PWGLF/Utils/strangenessBuilderModule.h b/PWGLF/Utils/strangenessBuilderModule.h new file mode 100644 index 00000000000..fc33a44f40c --- /dev/null +++ b/PWGLF/Utils/strangenessBuilderModule.h @@ -0,0 +1,2570 @@ +// 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 strangenessBuilderModule.h +/// \brief strangeness builder module +/// \author ALICE + +// simple checkers, but ensure 8 bit integers +#define BITSET(var, nbit) ((var) |= (static_cast(1) << static_cast(nbit))) + +#ifndef PWGLF_UTILS_STRANGENESSBUILDERMODULE_H_ +#define PWGLF_UTILS_STRANGENESSBUILDERMODULE_H_ + +#include "TableHelper.h" + +#include "PWGLF/DataModel/LFStrangenessTables.h" +#include "PWGLF/Utils/strangenessBuilderHelper.h" + +#include "Common/Core/TPCVDriftManager.h" + +#include "DataFormatsCalibration/MeanVertexObject.h" +#include "DataFormatsParameters/GRPMagField.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisHelpers.h" +#include "Framework/Configurable.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/HistogramSpec.h" + +#include +#include +#include +#include +#include + +//__________________________________________ +// strangeness builder module + +namespace o2 +{ +namespace pwglf +{ +namespace strangenessbuilder // avoid polluting other namespaces +{ + +// statics necessary for the configurables in this namespace +static constexpr int nParameters = 1; +static const std::vector tableNames{ + "V0Indices", //.0 (standard analysis: V0Cores) + "V0CoresBase", //.1 (standard analyses: main table) + "V0Covs", //.2 (joinable with V0Cores) + "CascIndices", //.3 (standard analyses: CascData) + "KFCascIndices", //.4 (standard analyses: KFCascData) + "TraCascIndices", //.5 (standard analyses: TraCascData) + "StoredCascCores", //.6 (standard analyses: CascData, main table) + "StoredKFCascCores", //.7 (standard analyses: KFCascData, main table) + "StoredTraCascCores", //.8 (standard analyses: TraCascData, main table) + "CascCovs", //.9 (joinable with CascData) + "KFCascCovs", //.10 (joinable with KFCascData) + "TraCascCovs", //.11 (joinable with TraCascData) + "V0TrackXs", //.12 (joinable with V0Data) + "CascTrackXs", //.13 (joinable with CascData) + "CascBBs", //.14 (standard, bachelor-baryon vars) + "V0DauCovs", //.15 (requested: tracking studies) + "V0DauCovIUs", //.16 (requested: tracking studies) + "V0TraPosAtDCAs", //.17 (requested: tracking studies) + "V0TraPosAtIUs", //.18 (requested: tracking studies) + "V0Ivanovs", //.19 (requested: tracking studies) + "McV0Labels", //.20 (MC/standard analysis) + "V0MCCores", //.21 (MC, all generated desired V0s) + "V0CoreMCLabels", //.22 (MC, refs V0Cores to V0MCCores) + "V0MCCollRefs", //.23 (MC, refs V0MCCores to McCollisions) + "McCascLabels", //.24 (MC/standard analysis) + "McKFCascLabels", //.25 (MC, refs KFCascCores to CascMCCores) + "McTraCascLabels", //.26 (MC, refs TraCascCores to CascMCCores) + "McCascBBTags", //.27 (MC, joinable with CascCores, tags reco-ed) + "CascMCCores", //.28 (MC, all generated desired cascades) + "CascCoreMCLabels", //.29 (MC, refs CascCores to CascMCCores) + "CascMCCollRefs", // 30 (MC, refs CascMCCores to McCollisions) + "CascToTraRefs", //.31 (interlink CascCores -> TraCascCores) + "CascToKFRefs", //.32 (interlink CascCores -> KFCascCores) + "TraToCascRefs", //.33 (interlink TraCascCores -> CascCores) + "KFToCascRefs", //.34 (interlink KFCascCores -> CascCores) + "V0FoundTags", //.35 (tags found vs findable V0s in findable mode) + "CascFoundTags" //.36 (tags found vs findable Cascades in findable mode) +}; + +static constexpr int nTablesConst = 37; + +static const std::vector parameterNames{"enable"}; +static const int defaultParameters[nTablesConst][nParameters]{ + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, // index 9 + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, // index 19 + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, // index 29 + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}, + {-1}}; + +// table index : match order above +enum tableIndex { kV0Indices = 0, + kV0CoresBase, + kV0Covs, + kCascIndices, + kKFCascIndices, + kTraCascIndices, + kStoredCascCores, + kStoredKFCascCores, + kStoredTraCascCores, + kCascCovs, + kKFCascCovs, + kTraCascCovs, + kV0TrackXs, + kCascTrackXs, + kCascBBs, + kV0DauCovs, + kV0DauCovIUs, + kV0TraPosAtDCAs, + kV0TraPosAtIUs, + kV0Ivanovs, + kMcV0Labels, + kV0MCCores, + kV0CoreMCLabels, + kV0MCCollRefs, + kMcCascLabels, + kMcKFCascLabels, + kMcTraCascLabels, + kMcCascBBTags, + kCascMCCores, + kCascCoreMCLabels, + kCascMCCollRefs, + kCascToTraRefs, + kCascToKFRefs, + kTraToCascRefs, + kKFToCascRefs, + kV0FoundTags, + kCascFoundTags, + nTables }; + +enum V0PreSelection : uint8_t { selGamma = 0, + selK0Short, + selLambda, + selAntiLambda }; + +enum CascPreSelection : uint8_t { selXiMinus = 0, + selXiPlus, + selOmegaMinus, + selOmegaPlus }; + +static constexpr float defaultK0MassWindowParameters[1][4] = {{2.81882e-03, 1.14057e-03, 1.72138e-03, 5.00262e-01}}; +static constexpr float defaultLambdaWindowParameters[1][4] = {{1.17518e-03, 1.24099e-04, 5.47937e-03, 3.08009e-01}}; +static constexpr float defaultXiMassWindowParameters[1][4] = {{1.43210e-03, 2.03561e-04, 2.43187e-03, 7.99668e-01}}; +static constexpr float defaultOmMassWindowParameters[1][4] = {{1.43210e-03, 2.03561e-04, 2.43187e-03, 7.99668e-01}}; + +static constexpr float defaultLifetimeCuts[1][4] = {{20, 60, 40, 20}}; + +struct products : o2::framework::ProducesGroup { + //__________________________________________________ + // V0 tables + o2::framework::Produces v0indices; // standard part of V0Datas + o2::framework::Produces v0cores; // standard part of V0Datas + o2::framework::Produces v0covs; // for decay chain reco + + //__________________________________________________ + // cascade tables + o2::framework::Produces cascidx; // standard part of CascDatas + o2::framework::Produces kfcascidx; // standard part of KFCascDatas + o2::framework::Produces tracascidx; // standard part of TraCascDatas + o2::framework::Produces cascdata; // standard part of CascDatas + o2::framework::Produces kfcascdata; // standard part of KFCascDatas + o2::framework::Produces tracascdata; // standard part of TraCascDatas + o2::framework::Produces casccovs; // for decay chain reco + o2::framework::Produces kfcasccovs; // for decay chain reco + o2::framework::Produces tracasccovs; // for decay chain reco + + //__________________________________________________ + // interlink tables + o2::framework::Produces v0dataLink; // de-refs V0s -> V0Data + o2::framework::Produces cascdataLink; // de-refs Cascades -> CascData + o2::framework::Produces kfcascdataLink; // de-refs Cascades -> KFCascData + o2::framework::Produces tracascdataLink; // de-refs Cascades -> TraCascData + + //__________________________________________________ + // secondary auxiliary tables + o2::framework::Produces v0trackXs; // for decay chain reco + o2::framework::Produces cascTrackXs; // for decay chain reco + + //__________________________________________________ + // further auxiliary / optional if desired + o2::framework::Produces cascbb; + o2::framework::Produces v0daucovs; // covariances of daughter tracks + o2::framework::Produces v0daucovIUs; // covariances of daughter tracks + o2::framework::Produces v0dauPositions; // auxiliary debug information + o2::framework::Produces v0dauPositionsIU; // auxiliary debug information + o2::framework::Produces v0ivanovs; // information for Marian's tests + + //__________________________________________________ + // MC information: V0 + o2::framework::Produces v0labels; // MC labels for V0s + o2::framework::Produces v0mccores; // mc info storage + o2::framework::Produces v0CoreMCLabels; // interlink V0Cores -> V0MCCores + o2::framework::Produces v0mccollref; // references collisions from V0MCCores + + // MC information: Cascades + o2::framework::Produces casclabels; // MC labels for cascades + o2::framework::Produces kfcasclabels; // MC labels for KF cascades + o2::framework::Produces tracasclabels; // MC labels for tracked cascades + o2::framework::Produces bbtags; // bb tags (inv structure tagging in mc) + o2::framework::Produces cascmccores; // mc info storage + o2::framework::Produces cascCoreMClabels; // interlink CascCores -> CascMCCores + o2::framework::Produces cascmccollrefs; // references MC collisions from MC cascades + + //__________________________________________________ + // cascade interlinks + // FIXME: commented out until strangederivedbuilder adjusted accordingly + // o2::framework::Produces cascToTraRefs; // cascades -> tracked + // o2::framework::Produces cascToKFRefs; // cascades -> KF + // o2::framework::Produces traToCascRefs; // tracked -> cascades + // o2::framework::Produces kfToCascRefs; // KF -> cascades + + //__________________________________________________ + // Findable tags + o2::framework::Produces v0FoundTag; + o2::framework::Produces cascFoundTag; +}; + +// strangenessBuilder: 1st-order configurables +struct coreConfigurables : o2::framework::ConfigurableGroup { + o2::framework::Configurable> enabledTables{"enabledTables", + {defaultParameters[0], nTables, nParameters, tableNames, parameterNames}, + "Produce this table: -1 for autodetect; otherwise, 0/1 is false/true"}; + std::vector mEnabledTables; // Vector of enabled tables + + // first order deduplication implementation + // more algorithms to be added as necessary + o2::framework::Configurable deduplicationAlgorithm{"deduplicationAlgorithm", 1, "0: disabled; 1: best pointing angle wins; 2: best DCA daughters wins; 3: best pointing and best DCA wins"}; + + // V0 buffer for V0s used in cascades: master switch + // exchanges CPU (generate V0s again) with memory (save pre-generated V0s) + o2::framework::Configurable useV0BufferForCascades{"useV0BufferForCascades", false, "store array of V0s for cascades or not. False (default): save RAM, use more CPU; true: save CPU, use more RAM"}; + + o2::framework::Configurable mc_findableMode{"mc_findableMode", 0, "0: disabled; 1: add findable-but-not-found to existing V0s from AO2D; 2: reset V0s and generate only findable-but-not-found"}; +}; + +// strangenessBuilder: V0 building options +struct v0Configurables : o2::framework::ConfigurableGroup { + std::string prefix = "v0BuilderOpts"; + o2::framework::Configurable generatePhotonCandidates{"generatePhotonCandidates", false, "generate gamma conversion candidates (V0s using TPC-only tracks)"}; + o2::framework::Configurable moveTPCOnlyTracks{"moveTPCOnlyTracks", true, "if dealing with TPC-only tracks, move them according to TPC drift / time info"}; + + // baseline conditionals of V0 building + o2::framework::Configurable minCrossedRows{"minCrossedRows", 50, "minimum TPC crossed rows for daughter tracks"}; + o2::framework::Configurable dcanegtopv{"dcanegtopv", .1, "DCA Neg To PV"}; + o2::framework::Configurable dcapostopv{"dcapostopv", .1, "DCA Pos To PV"}; + o2::framework::Configurable v0cospa{"v0cospa", 0.95, "V0 CosPA"}; // double -> N.B. dcos(x)/dx = 0 at x=0) + o2::framework::Configurable dcav0dau{"dcav0dau", 1.0, "DCA V0 Daughters"}; + o2::framework::Configurable v0radius{"v0radius", 0.9, "v0radius"}; + o2::framework::Configurable maxDaughterEta{"maxDaughterEta", 5.0, "Maximum daughter eta (in abs value)"}; + + // MC builder options + o2::framework::Configurable mc_populateV0MCCoresSymmetric{"mc_populateV0MCCoresSymmetric", false, "populate V0MCCores table for derived data analysis, keep V0MCCores joinable with V0Cores"}; + o2::framework::Configurable mc_populateV0MCCoresAsymmetric{"mc_populateV0MCCoresAsymmetric", true, "populate V0MCCores table for derived data analysis, create V0Cores -> V0MCCores interlink. Saves only labeled V0s."}; + o2::framework::Configurable mc_treatPiToMuDecays{"mc_treatPiToMuDecays", true, "if true, will correctly capture pi -> mu and V0 label will still point to originating V0 decay in those cases. Nota bene: prong info will still be for the muon!"}; + o2::framework::Configurable mc_rapidityWindow{"mc_rapidityWindow", 0.5, "rapidity window to save non-recoed candidates"}; + o2::framework::Configurable mc_keepOnlyPhysicalPrimary{"mc_keepOnlyPhysicalPrimary", false, "Keep only physical primary generated V0s if not recoed"}; + o2::framework::Configurable mc_addGeneratedK0Short{"mc_addGeneratedK0Short", true, "add V0MCCore entry for generated, not-recoed K0Short"}; + o2::framework::Configurable mc_addGeneratedLambda{"mc_addGeneratedLambda", true, "add V0MCCore entry for generated, not-recoed Lambda"}; + o2::framework::Configurable mc_addGeneratedAntiLambda{"mc_addGeneratedAntiLambda", true, "add V0MCCore entry for generated, not-recoed AntiLambda"}; + o2::framework::Configurable mc_addGeneratedGamma{"mc_addGeneratedGamma", false, "add V0MCCore entry for generated, not-recoed Gamma"}; + o2::framework::Configurable mc_addGeneratedGammaMakeCollinear{"mc_addGeneratedGammaMakeCollinear", true, "when adding findable gammas, mark them as collinear"}; + o2::framework::Configurable mc_findableDetachedV0{"mc_findableDetachedV0", false, "if true, generate findable V0s that have collisionId -1. Caution advised."}; +}; + +// strangenessBuilder: cascade building options +struct cascadeConfigurables : o2::framework::ConfigurableGroup { + std::string prefix = "cascadeBuilderOpts"; + o2::framework::Configurable useCascadeMomentumAtPrimVtx{"useCascadeMomentumAtPrimVtx", false, "use cascade momentum at PV"}; + + // conditionals + o2::framework::Configurable minCrossedRows{"minCrossedRows", 50, "minimum TPC crossed rows for daughter tracks"}; + o2::framework::Configurable dcabachtopv{"dcabachtopv", .05, "DCA Bach To PV"}; + o2::framework::Configurable cascradius{"cascradius", 0.9, "cascradius"}; + o2::framework::Configurable casccospa{"casccospa", 0.95, "casccospa"}; + o2::framework::Configurable dcacascdau{"dcacascdau", 1.0, "DCA cascade Daughters"}; + o2::framework::Configurable lambdaMassWindow{"lambdaMassWindow", .010, "Distance from Lambda mass (does not apply to KF path)"}; + o2::framework::Configurable maxDaughterEta{"maxDaughterEta", 5.0, "Maximum daughter eta (in abs value)"}; + + // KF building specific + o2::framework::Configurable kfTuneForOmega{"kfTuneForOmega", false, "if enabled, take main cascade properties from Omega fit instead of Xi fit (= default)"}; + o2::framework::Configurable kfConstructMethod{"kfConstructMethod", 2, "KF Construct Method"}; + o2::framework::Configurable kfUseV0MassConstraint{"kfUseV0MassConstraint", true, "KF: use Lambda mass constraint"}; + o2::framework::Configurable kfUseCascadeMassConstraint{"kfUseCascadeMassConstraint", false, "KF: use Cascade mass constraint - WARNING: not adequate for inv mass analysis of Xi"}; + o2::framework::Configurable kfDoDCAFitterPreMinimV0{"kfDoDCAFitterPreMinimV0", true, "KF: do DCAFitter pre-optimization before KF fit to include material corrections for V0"}; + o2::framework::Configurable kfDoDCAFitterPreMinimCasc{"kfDoDCAFitterPreMinimCasc", true, "KF: do DCAFitter pre-optimization before KF fit to include material corrections for Xi"}; + + // MC builder options + o2::framework::Configurable mc_populateCascMCCoresSymmetric{"mc_populateCascMCCoresSymmetric", false, "populate CascMCCores table for derived data analysis, keep CascMCCores joinable with CascCores"}; + o2::framework::Configurable mc_populateCascMCCoresAsymmetric{"mc_populateCascMCCoresAsymmetric", true, "populate CascMCCores table for derived data analysis, create CascCores -> CascMCCores interlink. Saves only labeled Cascades."}; + o2::framework::Configurable mc_addGeneratedXiMinus{"mc_addGeneratedXiMinus", true, "add CascMCCore entry for generated, not-recoed XiMinus"}; + o2::framework::Configurable mc_addGeneratedXiPlus{"mc_addGeneratedXiPlus", true, "add CascMCCore entry for generated, not-recoed XiPlus"}; + o2::framework::Configurable mc_addGeneratedOmegaMinus{"mc_addGeneratedOmegaMinus", true, "add CascMCCore entry for generated, not-recoed OmegaMinus"}; + o2::framework::Configurable mc_addGeneratedOmegaPlus{"mc_addGeneratedOmegaPlus", true, "add CascMCCore entry for generated, not-recoed OmegaPlus"}; + o2::framework::Configurable mc_treatPiToMuDecays{"mc_treatPiToMuDecays", true, "if true, will correctly capture pi -> mu and V0 label will still point to originating V0 decay in those cases. Nota bene: prong info will still be for the muon!"}; + o2::framework::Configurable mc_rapidityWindow{"mc_rapidityWindow", 0.5, "rapidity window to save non-recoed candidates"}; + o2::framework::Configurable mc_keepOnlyPhysicalPrimary{"mc_keepOnlyPhysicalPrimary", false, "Keep only physical primary generated cascades if not recoed"}; + o2::framework::Configurable mc_findableDetachedCascade{"mc_findableDetachedCascade", false, "if true, generate findable cascades that have collisionId -1. Caution advised."}; +}; + +// preselection options +struct preSelectOpts : o2::framework::ConfigurableGroup { + std::string prefix = "preSelectOpts"; + o2::framework::Configurable preselectOnlyDesiredV0s{"preselectOnlyDesiredV0s", false, "preselect only V0s with compatible TPC PID and mass info"}; + o2::framework::Configurable preselectOnlyDesiredCascades{"preselectOnlyDesiredCascades", false, "preselect only Cascades with compatible TPC PID and mass info"}; + + // lifetime preselection options + // apply lifetime cuts to V0 and cascade candidates + // unit of measurement: centimeters + // lifetime of K0Short ~2.6844 cm, no feeddown and plenty to cut + // lifetime of Lambda ~7.9 cm but keep in mind feeddown from cascades + // lifetime of Xi ~4.91 cm + // lifetime of Omega ~2.461 cm + o2::framework::Configurable> lifetimeCut{"lifetimeCut", {defaultLifetimeCuts[0], 4, {"lifetimeCutK0S", "lifetimeCutLambda", "lifetimeCutXi", "lifetimeCutOmega"}}, "Lifetime cut for V0s and cascades (cm)"}; + + // mass preselection options + o2::framework::Configurable massCutPhoton{"massCutPhoton", 0.3, "Photon max mass"}; + o2::framework::Configurable> massCutK0{"massCutK0", {defaultK0MassWindowParameters[0], 4, {"constant", "linear", "expoConstant", "expoRelax"}}, "mass parameters for K0"}; + o2::framework::Configurable> massCutLambda{"massCutLambda", {defaultLambdaWindowParameters[0], 4, {"constant", "linear", "expoConstant", "expoRelax"}}, "mass parameters for Lambda"}; + o2::framework::Configurable> massCutXi{"massCutXi", {defaultXiMassWindowParameters[0], 4, {"constant", "linear", "expoConstant", "expoRelax"}}, "mass parameters for Xi"}; + o2::framework::Configurable> massCutOm{"massCutOm", {defaultOmMassWindowParameters[0], 4, {"constant", "linear", "expoConstant", "expoRelax"}}, "mass parameters for Omega"}; + o2::framework::Configurable massWindownumberOfSigmas{"massWindownumberOfSigmas", 20, "number of sigmas around mass peaks to keep"}; + o2::framework::Configurable massWindowSafetyMargin{"massWindowSafetyMargin", 0.001, "Extra mass window safety margin (in GeV/c2)"}; + + // TPC PID preselection options + o2::framework::Configurable maxTPCpidNsigma{"maxTPCpidNsigma", 5.0, "Maximum TPC PID N sigma (in abs value)"}; +}; + +class BuilderModule +{ + public: + BuilderModule() + { + // constructor + } + + // mass windows + float getMassSigmaK0Short(float pt) + { + return preSelectOpts.massCutK0->get("constant") + pt * preSelectOpts.massCutK0->get("linear") + preSelectOpts.massCutK0->get("expoConstant") * TMath::Exp(-pt / preSelectOpts.massCutK0->get("expoRelax")); + } + float getMassSigmaLambda(float pt) + { + return preSelectOpts.massCutLambda->get("constant") + pt * preSelectOpts.massCutLambda->get("linear") + preSelectOpts.massCutLambda->get("expoConstant") * TMath::Exp(-pt / preSelectOpts.massCutLambda->get("expoRelax")); + } + float getMassSigmaXi(float pt) + { + return preSelectOpts.massCutXi->get("constant") + pt * preSelectOpts.massCutXi->get("linear") + preSelectOpts.massCutXi->get("expoConstant") * TMath::Exp(-pt / preSelectOpts.massCutXi->get("expoRelax")); + } + float getMassSigmaOmega(float pt) + { + return preSelectOpts.massCutOm->get("constant") + pt * preSelectOpts.massCutOm->get("linear") + preSelectOpts.massCutOm->get("expoConstant") * TMath::Exp(-pt / preSelectOpts.massCutOm->get("expoRelax")); + } + + int nEnabledTables = 0; + + // helper object + o2::pwglf::strangenessBuilderHelper straHelper; + + // for handling TPC-only tracks (photons) + int mRunNumber; + o2::aod::common::TPCVDriftManager mVDriftMgr; + + // for establishing CascData/KFData/TraCascData interlinks + struct { + std::vector cascCoreToCascades; + std::vector kfCascCoreToCascades; + std::vector traCascCoreToCascades; + std::vector cascadeToCascCores; + std::vector cascadeToKFCascCores; + std::vector cascadeToTraCascCores; + } interlinks; + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + // struct to add abstraction layer between V0s, Cascades and build indices + // desirable for adding extra (findable, etc) V0s, Cascades to built list + struct trackEntry { + int globalId = -1; + int originId = -1; + int mcCollisionId = -1; + int pdgCode = -1; + }; + struct v0Entry { + int globalId = -1; + int collisionId = -1; + int posTrackId = -1; + int negTrackId = -1; + int v0Type = 0; + int pdgCode = 0; // undefined if not MC - useful for faster finding + int particleId = -1; // de-reference the V0 particle if necessary + bool isCollinearV0 = false; + bool found = false; + }; + struct cascadeEntry { + int globalId = -1; + int collisionId = -1; + int v0Id = -1; + int posTrackId = -1; + int negTrackId = -1; + int bachTrackId = -1; + bool found = false; + }; + + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + // Helper struct to contain V0MCCore information prior to filling + struct mcV0info { + int label = -1; + int motherLabel = -1; + int pdgCode = 0; + int pdgCodeMother = 0; + int pdgCodePositive = 0; + int pdgCodeNegative = 0; + int mcCollision = -1; + bool isPhysicalPrimary = false; + int processPositive = -1; + int processNegative = -1; + std::array xyz; + std::array posP; + std::array negP; + std::array momentum; + }; + mcV0info thisInfo; + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + // Helper struct to contain CascMCCore information prior to filling + struct mcCascinfo { + int label; + int motherLabel; + int mcCollision; + int pdgCode; + int pdgCodeMother; + int pdgCodeV0; + int pdgCodePositive; + int pdgCodeNegative; + int pdgCodeBachelor; + bool isPhysicalPrimary; + int processPositive = -1; + int processNegative = -1; + int processBachelor = -1; + std::array xyz; + std::array lxyz; + std::array posP; + std::array negP; + std::array bachP; + std::array momentum; + int mcParticlePositive; + int mcParticleNegative; + int mcParticleBachelor; + }; + mcCascinfo thisCascInfo; + //*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+* + + std::vector v0List; + std::vector cascadeList; + std::vector sorted_v0; + std::vector sorted_cascade; + + // for tagging V0s used in cascades + std::vector v0sFromCascades; // Vector of v0 candidates used in cascades + std::vector ao2dV0toV0List; // index to relate v0s -> v0List + std::vector v0Map; // index to relate v0List -> v0sFromCascades + + // declaration of structs here + // (N.B.: will be invisible to the outside, create your own copies) + o2::pwglf::strangenessbuilder::coreConfigurables baseOpts; + o2::pwglf::strangenessbuilder::v0Configurables v0BuilderOpts; + o2::pwglf::strangenessbuilder::cascadeConfigurables cascadeBuilderOpts; + o2::pwglf::strangenessbuilder::preSelectOpts preSelectOpts; + + template + void init(TBaseConfigurables const& inputBaseOpts, TV0Configurables const& inputV0BuilderOpts, TCascadeConfigurables const& inputCascadeBuilderOpts, TPreSelOpts const& inputPreSelectOpts, THistoRegistry& histos, TInitContext& context) + { + // read in configurations from the task where it's used + // could be grouped even further, but should work + baseOpts = inputBaseOpts; + v0BuilderOpts = inputV0BuilderOpts; + cascadeBuilderOpts = inputCascadeBuilderOpts; + preSelectOpts = inputPreSelectOpts; + + baseOpts.mEnabledTables.resize(nTables, 0); + + LOGF(info, "Checking if strangeness building is required"); + auto& workflows = context.services().template get(); + + nEnabledTables = 0; + + TString listOfRequestors[nTables]; + for (int i = 0; i < nTables; i++) { + int f = baseOpts.enabledTables->get(tableNames[i].c_str(), "enable"); + if (f == 1) { + baseOpts.mEnabledTables[i] = 1; + listOfRequestors[i] = "manual enabling"; + } + if (f == -1) { + // autodetect this table in other devices + for (o2::framework::DeviceSpec const& device : workflows.devices) { + // Step 1: check if this device subscribed to the V0data table + for (auto const& input : device.inputs) { + if (o2::framework::DataSpecUtils::partialMatch(input.matcher, o2::header::DataOrigin("AOD"))) { + auto&& [origin, description, version] = o2::framework::DataSpecUtils::asConcreteDataMatcher(input.matcher); + std::string tableNameWithVersion = tableNames[i]; + if (version > 0) { + tableNameWithVersion += Form("_%03d", version); + } + if (input.matcher.binding == tableNameWithVersion) { + LOGF(info, "Device %s has subscribed to %s (version %i)", device.name, tableNames[i], version); + listOfRequestors[i].Append(Form("%s ", device.name.c_str())); + baseOpts.mEnabledTables[i] = 1; + nEnabledTables++; + } + } + } + } + } + } + + if (nEnabledTables == 0) { + LOGF(info, "Strangeness building not required. Will suppress all functionality, including logs, from this point forward."); + return; + } + + // setup bookkeeping histogram + auto h = histos.template add("hTableBuildingStatistics", "hTableBuildingStatistics", o2::framework::kTH1D, {{nTablesConst, -0.5f, static_cast(nTablesConst)}}); + auto h2 = histos.template add("hInputStatistics", "hInputStatistics", o2::framework::kTH1D, {{nTablesConst, -0.5f, static_cast(nTablesConst)}}); + h2->SetTitle("Input table sizes"); + + if (v0BuilderOpts.generatePhotonCandidates.value == true) { + auto hDeduplicationStatistics = histos.template add("hDeduplicationStatistics", "hDeduplicationStatistics", o2::framework::kTH1D, {{2, -0.5f, 1.5f}}); + hDeduplicationStatistics->GetXaxis()->SetBinLabel(1, "AO2D V0s"); + hDeduplicationStatistics->GetXaxis()->SetBinLabel(2, "Deduplicated V0s"); + } + + if (preSelectOpts.preselectOnlyDesiredV0s.value == true) { + auto hPreselectionV0s = histos.template add("hPreselectionV0s", "hPreselectionV0s", o2::framework::kTH1D, {{16, -0.5f, 15.5f}}); + hPreselectionV0s->GetXaxis()->SetBinLabel(1, "Not preselected"); + hPreselectionV0s->GetXaxis()->SetBinLabel(2, "#gamma"); + hPreselectionV0s->GetXaxis()->SetBinLabel(3, "K^{0}_{S}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(4, "#gamma, K^{0}_{S}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(5, "#Lambda"); + hPreselectionV0s->GetXaxis()->SetBinLabel(6, "#gamma, #Lambda"); + hPreselectionV0s->GetXaxis()->SetBinLabel(7, "K^{0}_{S}, #Lambda"); + hPreselectionV0s->GetXaxis()->SetBinLabel(8, "#gamma, K^{0}_{S}, #Lambda"); + hPreselectionV0s->GetXaxis()->SetBinLabel(9, "#bar{#Lambda}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(10, "#gamma, #bar{#Lambda}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(11, "K^{0}_{S}, #bar{#Lambda}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(12, "#gamma, K^{0}_{S}, #bar{#Lambda}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(13, "#Lambda, #bar{#Lambda}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(14, "#gamma, #Lambda, #bar{#Lambda}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(15, "K^{0}_{S}, #Lambda, #bar{#Lambda}"); + hPreselectionV0s->GetXaxis()->SetBinLabel(16, "#gamma, K^{0}_{S}, #Lambda, #bar{#Lambda}"); + } + + if (preSelectOpts.preselectOnlyDesiredCascades.value == true) { + auto hPreselectionCascades = histos.template add("hPreselectionCascades", "hPreselectionCascades", o2::framework::kTH1D, {{16, -0.5f, 15.5f}}); + hPreselectionCascades->GetXaxis()->SetBinLabel(1, "Not preselected"); + hPreselectionCascades->GetXaxis()->SetBinLabel(2, "#Xi^{-}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(3, "#Xi^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(4, "#Xi^{-}, #Xi^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(5, "#Omega^{-}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(6, "#Xi^{-}, #Omega^{-}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(7, "#Xi^{+}, #Omega^{-}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(8, "#Xi^{-}, #Xi^{+}, #Omega^{-}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(9, "#Omega^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(10, "#Xi^{-}, #Omega^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(11, "#Xi^{+}, #Omega^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(12, "#Xi^{-}, #Xi^{+}, #Omega^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(13, "#Omega^{-}, #Omega^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(14, "#Xi^{-}, #Omega^{-}, #Omega^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(15, "#Xi^{+}, #Omega^{-}, #Omega^{+}"); + hPreselectionCascades->GetXaxis()->SetBinLabel(16, "#Xi^{-}, #Xi^{+}, #Omega^{-}, #Omega^{+}"); + } + + if (baseOpts.mc_findableMode.value > 0) { + // save statistics of findable candidate processing + auto hFindable = histos.template add("hFindableStatistics", "hFindableStatistics", o2::framework::kTH1D, {{6, -0.5f, 5.5f}}); + hFindable->SetTitle(Form("Findable mode: %i", static_cast(baseOpts.mc_findableMode.value))); + hFindable->GetXaxis()->SetBinLabel(1, "AO2D V0s"); + hFindable->GetXaxis()->SetBinLabel(2, "V0s to be built"); + hFindable->GetXaxis()->SetBinLabel(3, "V0s with collId -1"); + hFindable->GetXaxis()->SetBinLabel(4, "AO2D Cascades"); + hFindable->GetXaxis()->SetBinLabel(5, "Cascades to be built"); + hFindable->GetXaxis()->SetBinLabel(6, "Cascades with collId -1"); + } + + auto hPrimaryV0s = histos.template add("hPrimaryV0s", "hPrimaryV0s", o2::framework::kTH1D, {{2, -0.5f, 1.5f}}); + hPrimaryV0s->GetXaxis()->SetBinLabel(1, "All V0s"); + hPrimaryV0s->GetXaxis()->SetBinLabel(2, "Primary V0s"); + + mRunNumber = 0; + + for (int i = 0; i < nTables; i++) { + // adjust bookkeeping histogram + h->GetXaxis()->SetBinLabel(i + 1, tableNames[i].c_str()); + h2->GetXaxis()->SetBinLabel(i + 1, tableNames[i].c_str()); + if (baseOpts.mEnabledTables[i] == false) { + h->SetBinContent(i + 1, -1); // mark disabled tables, distinguish from zero counts + } + } + + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + LOGF(info, " Strangeness builder: basic configuration listing"); + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + + if (baseOpts.mc_findableMode.value == 1) { + LOGF(info, " ===> findable mode 1 is enabled: complement reco-ed with non-found findable"); + } + if (baseOpts.mc_findableMode.value == 2) { + LOGF(info, " ===> findable mode 2 is enabled: re-generate all findable from scratch"); + } + + // list enabled tables + + for (int i = 0; i < nTables; i++) { + // printout to be improved in the future + if (baseOpts.mEnabledTables[i]) { + LOGF(info, " -~> Table enabled: %s, requested by %s", tableNames[i], listOfRequestors[i].Data()); + h->SetBinContent(i + 1, 0); // mark enabled + } + } + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + // print base cuts + LOGF(info, "-~> V0 | min crossed rows ..............: %i", v0BuilderOpts.minCrossedRows.value); + LOGF(info, "-~> V0 | DCA pos track to PV ...........: %f", v0BuilderOpts.dcapostopv.value); + LOGF(info, "-~> V0 | DCA neg track to PV ...........: %f", v0BuilderOpts.dcanegtopv.value); + LOGF(info, "-~> V0 | V0 cosine of PA ...............: %f", v0BuilderOpts.v0cospa.value); + LOGF(info, "-~> V0 | DCA between V0 daughters ......: %f", v0BuilderOpts.dcav0dau.value); + LOGF(info, "-~> V0 | V0 2D decay radius ............: %f", v0BuilderOpts.v0radius.value); + LOGF(info, "-~> V0 | Maximum daughter eta ..........: %f", v0BuilderOpts.maxDaughterEta.value); + + LOGF(info, "-~> Cascade | min crossed rows .........: %i", cascadeBuilderOpts.minCrossedRows.value); + LOGF(info, "-~> Cascade | DCA bach track to PV .....: %f", cascadeBuilderOpts.dcabachtopv.value); + LOGF(info, "-~> Cascade | Cascade cosine of PA .....: %f", cascadeBuilderOpts.casccospa.value); + LOGF(info, "-~> Cascade | Cascade daughter DCA .....: %f", cascadeBuilderOpts.dcacascdau.value); + LOGF(info, "-~> Cascade | Cascade radius ...........: %f", cascadeBuilderOpts.cascradius.value); + LOGF(info, "-~> Cascade | Lambda mass window .......: %f", cascadeBuilderOpts.lambdaMassWindow.value); + LOGF(info, "-~> Cascade | Maximum daughter eta .....: %f", cascadeBuilderOpts.maxDaughterEta.value); + LOGF(info, "*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*+-+*"); + + // set V0 parameters in the helper + straHelper.v0selections.minCrossedRows = v0BuilderOpts.minCrossedRows; + straHelper.v0selections.dcanegtopv = v0BuilderOpts.dcanegtopv; + straHelper.v0selections.dcapostopv = v0BuilderOpts.dcapostopv; + straHelper.v0selections.v0cospa = v0BuilderOpts.v0cospa; + straHelper.v0selections.dcav0dau = v0BuilderOpts.dcav0dau; + straHelper.v0selections.v0radius = v0BuilderOpts.v0radius; + straHelper.v0selections.maxDaughterEta = v0BuilderOpts.maxDaughterEta; + + // set cascade parameters in the helper + straHelper.cascadeselections.minCrossedRows = cascadeBuilderOpts.minCrossedRows; + straHelper.cascadeselections.dcabachtopv = cascadeBuilderOpts.dcabachtopv; + straHelper.cascadeselections.cascradius = cascadeBuilderOpts.cascradius; + straHelper.cascadeselections.casccospa = cascadeBuilderOpts.casccospa; + straHelper.cascadeselections.dcacascdau = cascadeBuilderOpts.dcacascdau; + straHelper.cascadeselections.lambdaMassWindow = cascadeBuilderOpts.lambdaMassWindow; + straHelper.cascadeselections.maxDaughterEta = cascadeBuilderOpts.maxDaughterEta; + } + + // for sorting + template + std::vector sort_indices(const std::vector& v, bool doSorting = false) + { + std::vector idx(v.size()); + std::iota(idx.begin(), idx.end(), 0); + if (doSorting) { + // do sorting only if requested (not always necessary) + std::stable_sort(idx.begin(), idx.end(), + [&v](std::size_t i1, std::size_t i2) { return v[i1].collisionId < v[i2].collisionId; }); + } + return idx; + } + + template + bool initCCDB(TCCDB& ccdb, aod::BCsWithTimestamps const& bcs, TCollisions const& collisions) + { + auto bc = collisions.size() ? collisions.begin().template bc_as() : bcs.begin(); + if (!bcs.size()) { + LOGF(warn, "No BC found, skipping this DF."); + return false; // signal to skip this DF + } + + if (mRunNumber == bc.runNumber()) { + return true; + } + + auto timestamp = bc.timestamp(); + + // Fetch magnetic field from ccdb for current collision + auto magneticField = o2::base::Propagator::Instance()->getNominalBz(); + LOG(info) << "Configuring for timestamp " << timestamp << " with magnetic field of " << magneticField << " kG"; + + // Set magnetic field value once known + straHelper.fitter.setBz(magneticField); + + LOG(info) << "Fully configured for run: " << bc.runNumber(); + // mmark this run as configured + mRunNumber = bc.runNumber(); + + if (v0BuilderOpts.generatePhotonCandidates.value && v0BuilderOpts.moveTPCOnlyTracks.value) { + // initialize only if needed, avoid unnecessary CCDB calls + mVDriftMgr.init(&ccdb->instance()); + mVDriftMgr.update(timestamp); + } + + return true; + } + + //__________________________________________________ + void resetInterlinks() + { + interlinks.cascCoreToCascades.clear(); + interlinks.kfCascCoreToCascades.clear(); + interlinks.traCascCoreToCascades.clear(); + interlinks.cascadeToCascCores.clear(); + interlinks.cascadeToKFCascCores.clear(); + interlinks.cascadeToTraCascCores.clear(); + } + + //__________________________________________________ + void populateCascadeInterlinks() + { + // if (mEnabledTables[kCascToKFRefs]) { + // for (const auto& cascCore : interlinks.cascCoreToCascades) { + // cascToKFRefs(interlinks.cascadeToKFCascCores[cascCore]); + // histos.fill(HIST("hTableBuildingStatistics"), kCascToKFRefs); + // } + // } + // if (mEnabledTables[kCascToTraRefs]) { + // for (const auto& cascCore : interlinks.cascCoreToCascades) { + // cascToTraRefs(interlinks.cascadeToTraCascCores[cascCore]); + // histos.fill(HIST("hTableBuildingStatistics"), kCascToTraRefs); + // } + // } + // if (mEnabledTables[kKFToCascRefs]) { + // for (const auto& kfCascCore : interlinks.kfCascCoreToCascades) { + // kfToCascRefs(interlinks.cascadeToCascCores[kfCascCore]); + // histos.fill(HIST("hTableBuildingStatistics"), kKFToCascRefs); + // } + // } + // if (mEnabledTables[kTraToCascRefs]) { + // for (const auto& traCascCore : interlinks.traCascCoreToCascades) { + // traToCascRefs(interlinks.cascadeToCascCores[traCascCore]); + // histos.fill(HIST("hTableBuildingStatistics"), kTraToCascRefs); + // } + // } + } + + //__________________________________________________ + template + void prepareBuildingLists(THistoRegistry& histos, TCollisions const& collisions, TMCCollisions const& mcCollisions, TV0s const& v0s, TCascades const& cascades, TTracks const& tracks, TMCParticles const& mcParticles) + { + // this function prepares the v0List and cascadeList depending on + // how the task has been set up. Standard operation simply uses + // the existing V0s and Cascades from AO2D, while findable MC + // operation either complements with all findable-but-not-found + // or resets and fills with all findable. + // + // Whenever using findable candidates, they will be appropriately + // marked for posterior analysis using 'tag' variables. + // + // findable mode legend: + // 0: simple passthrough of V0s, Cascades in AO2Ds + // (in data, this is the only mode possible!) + // 1: add extra findable that haven't been found + // 2: generate only findable (no background) + + // redo lists from scratch + v0List.clear(); + cascadeList.clear(); + sorted_v0.clear(); + sorted_cascade.clear(); + ao2dV0toV0List.clear(); + + trackEntry currentTrackEntry; + v0Entry currentV0Entry; + cascadeEntry currentCascadeEntry; + + std::vector bestCollisionArray; // stores McCollision -> Collision map + std::vector bestCollisionNContribsArray; // stores Ncontribs for biggest coll assoc to mccoll + + int collisionLessV0s = 0; + int collisionLessCascades = 0; + + if (baseOpts.mc_findableMode.value > 0) { + if constexpr (soa::is_table) { + // if mcCollisions exist, assemble mcColl -> bestRecoColl map here + bestCollisionArray.clear(); + bestCollisionNContribsArray.clear(); + bestCollisionArray.resize(mcCollisions.size(), -1); // marks not reconstructed + bestCollisionNContribsArray.resize(mcCollisions.size(), -1); // marks not reconstructed + + // single loop over double loop at a small cost in memory for extra array + for (const auto& collision : collisions) { + if (collision.has_mcCollision()) { + if (collision.numContrib() > bestCollisionNContribsArray[collision.mcCollisionId()]) { + bestCollisionArray[collision.mcCollisionId()] = collision.globalIndex(); + bestCollisionNContribsArray[collision.mcCollisionId()] = collision.numContrib(); + } + } + } // end collision loop + } // end is_table + } // end findable mode check + + if (baseOpts.mc_findableMode.value < 2) { + // keep all unless de-duplication active + ao2dV0toV0List.resize(v0s.size(), -1); // -1 means keep, -2 means do not keep + + if (baseOpts.deduplicationAlgorithm > 0 && v0BuilderOpts.generatePhotonCandidates) { + // handle duplicates explicitly: group V0s according to (p,n) indices + // will provide a list of collisionIds (in V0group), allowing for + // easy de-duplication when passing to the v0List + std::vector v0tableGrouped = o2::pwglf::groupDuplicates(v0s); + histos.fill(HIST("hDeduplicationStatistics"), 0.0, v0s.size()); + histos.fill(HIST("hDeduplicationStatistics"), 1.0, v0tableGrouped.size()); + + // process grouped duplicates, remove 'bad' ones + for (size_t iV0 = 0; iV0 < v0tableGrouped.size(); iV0++) { + auto pTrack = tracks.rawIteratorAt(v0tableGrouped[iV0].posTrackId); + auto nTrack = tracks.rawIteratorAt(v0tableGrouped[iV0].negTrackId); + + bool isPosTPCOnly = (pTrack.hasTPC() && !pTrack.hasITS() && !pTrack.hasTRD() && !pTrack.hasTOF()); + bool isNegTPCOnly = (nTrack.hasTPC() && !nTrack.hasITS() && !nTrack.hasTRD() && !nTrack.hasTOF()); + + // skip single copy V0s + if (v0tableGrouped[iV0].collisionIds.size() == 1) { + continue; + } + + // don't try to de-duplicate if no track is TPC only + if (!isPosTPCOnly && !isNegTPCOnly) { + continue; + } + + // fitness criteria defined here + float bestPointingAngle = 10; // a nonsense angle, anything's better + size_t bestPointingAngleIndex = -1; + + float bestDCADaughters = 1e+3; // an excessively large DCA + size_t bestDCADaughtersIndex = -1; + + for (size_t ic = 0; ic < v0tableGrouped[iV0].collisionIds.size(); ic++) { + // get track parametrizations, collisions + auto posTrackPar = getTrackParCov(pTrack); + auto negTrackPar = getTrackParCov(nTrack); + auto const& collision = collisions.rawIteratorAt(v0tableGrouped[iV0].collisionIds[ic]); + + // handle TPC-only tracks properly (photon conversions) + if (v0BuilderOpts.moveTPCOnlyTracks) { + if (isPosTPCOnly) { + // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + if (!mVDriftMgr.moveTPCTrack(collision, pTrack, posTrackPar)) { + continue; + } + } + if (isNegTPCOnly) { + // Nota bene: negative is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + if (!mVDriftMgr.moveTPCTrack(collision, nTrack, negTrackPar)) { + continue; + } + } + } // end TPC drift treatment + + // process candidate with helper, generate properties for consulting + // : do not apply selections: do as much as possible to preserve + // candidate at this level and do not select with topo selections + if (straHelper.buildV0Candidate(v0tableGrouped[iV0].collisionIds[ic], collision.posX(), collision.posY(), collision.posZ(), pTrack, nTrack, posTrackPar, negTrackPar, true, false, true)) { + // candidate built, check pointing angle + if (straHelper.v0.pointingAngle < bestPointingAngle) { + bestPointingAngle = straHelper.v0.pointingAngle; + bestPointingAngleIndex = ic; + } + if (straHelper.v0.daughterDCA < bestDCADaughters) { + bestDCADaughters = straHelper.v0.daughterDCA; + bestDCADaughtersIndex = ic; + } + } // end build V0 + } // end candidate loop + + // mark de-duplicated candidates + for (size_t ic = 0; ic < v0tableGrouped[iV0].collisionIds.size(); ic++) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -2; + // algorithm 1: best pointing angle + if (bestPointingAngleIndex == ic && baseOpts.deduplicationAlgorithm.value == 1) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + if (bestDCADaughtersIndex == ic && baseOpts.deduplicationAlgorithm.value == 2) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + if (bestDCADaughtersIndex == ic && bestPointingAngleIndex == ic && baseOpts.deduplicationAlgorithm.value == 3) { + ao2dV0toV0List[v0tableGrouped[iV0].V0Ids[ic]] = -1; // keep best only + } + } + } // end V0 loop + } // end de-duplication process + + for (const auto& v0 : v0s) { + if (ao2dV0toV0List[v0.globalIndex()] == -1) { // keep only de-duplicated + ao2dV0toV0List[v0.globalIndex()] = v0List.size(); // maps V0s to the corresponding v0List entry + currentV0Entry.globalId = v0.globalIndex(); + currentV0Entry.collisionId = v0.collisionId(); + currentV0Entry.posTrackId = v0.posTrackId(); + currentV0Entry.negTrackId = v0.negTrackId(); + currentV0Entry.v0Type = v0.v0Type(); + currentV0Entry.pdgCode = 0; + currentV0Entry.particleId = -1; + currentV0Entry.isCollinearV0 = v0.isCollinearV0(); + currentV0Entry.found = true; + v0List.push_back(currentV0Entry); + } + } + } + // any mode other than 0 will require mcParticles + if constexpr (soa::is_table) { + if (baseOpts.mc_findableMode.value > 0) { + // for search if existing or not + int v0ListReconstructedSize = v0List.size(); + + // find extra candidates, step 1: find subset of tracks that interest + std::vector positiveTrackArray; + std::vector negativeTrackArray; + // vector elements: track index, origin index [, mc collision id, pdg code] + int dummy = -1; // unnecessary in this path + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; // skip this, it's trouble + } + auto particle = track.template mcParticle_as(); + int originParticleIndex = getOriginatingParticle(particle, dummy, v0BuilderOpts.mc_treatPiToMuDecays); + if (originParticleIndex < 0) { + continue; // skip this, it's trouble (2) + } + auto originParticle = mcParticles.rawIteratorAt(originParticleIndex); + + bool trackIsInteresting = false; + if ( + (originParticle.pdgCode() == 310 && v0BuilderOpts.mc_addGeneratedK0Short.value > 0) || + (originParticle.pdgCode() == 3122 && v0BuilderOpts.mc_addGeneratedLambda.value > 0) || + (originParticle.pdgCode() == -3122 && v0BuilderOpts.mc_addGeneratedAntiLambda.value > 0) || + (originParticle.pdgCode() == 22 && v0BuilderOpts.mc_addGeneratedGamma.value > 0)) { + trackIsInteresting = true; + } + if (!trackIsInteresting) { + continue; // skip this, it's uninteresting + } + + currentTrackEntry.globalId = static_cast(track.globalIndex()); + currentTrackEntry.originId = originParticleIndex; + currentTrackEntry.mcCollisionId = originParticle.mcCollisionId(); + currentTrackEntry.pdgCode = originParticle.pdgCode(); + + // now separate according to particle species + if (track.sign() < 0) { + negativeTrackArray.push_back(currentTrackEntry); + } else { + positiveTrackArray.push_back(currentTrackEntry); + } + } + + // Nested loop only with valuable tracks + for (const auto& positiveTrackIndex : positiveTrackArray) { + for (const auto& negativeTrackIndex : negativeTrackArray) { + if (positiveTrackIndex.originId != negativeTrackIndex.originId) { + continue; // not the same originating particle + } + // findable mode 1: add non-reconstructed as v0Type 8 + if (baseOpts.mc_findableMode.value == 1) { + bool detected = false; + for (int ii = 0; ii < v0ListReconstructedSize; ii++) { + // check if this particular combination already exists in v0List + if (v0List[ii].posTrackId == positiveTrackIndex.globalId && + v0List[ii].negTrackId == negativeTrackIndex.globalId) { + detected = true; + // override pdg code with something useful for cascade findable math + v0List[ii].pdgCode = positiveTrackIndex.pdgCode; + break; + } + } + if (detected == false) { + // collision index: from best-version-of-this-mcCollision + // nota bene: this could be negative, caution advised + currentV0Entry.globalId = -1; + currentV0Entry.collisionId = bestCollisionArray[positiveTrackIndex.mcCollisionId]; + currentV0Entry.posTrackId = positiveTrackIndex.globalId; + currentV0Entry.negTrackId = negativeTrackIndex.globalId; + currentV0Entry.v0Type = 1; + currentV0Entry.pdgCode = positiveTrackIndex.pdgCode; + currentV0Entry.particleId = positiveTrackIndex.originId; + currentV0Entry.isCollinearV0 = false; + if (v0BuilderOpts.mc_addGeneratedGammaMakeCollinear.value && currentV0Entry.pdgCode == 22) { + currentV0Entry.isCollinearV0 = true; + } + currentV0Entry.found = false; + if (bestCollisionArray[positiveTrackIndex.mcCollisionId] < 0) { + collisionLessV0s++; + } + if (v0BuilderOpts.mc_findableDetachedV0.value || currentV0Entry.collisionId >= 0) { + v0List.push_back(currentV0Entry); + } + } + } + // findable mode 2 + if (baseOpts.mc_findableMode.value == 2) { + currentV0Entry.globalId = -1; + currentV0Entry.collisionId = bestCollisionArray[positiveTrackIndex.mcCollisionId]; + currentV0Entry.posTrackId = positiveTrackIndex.globalId; + currentV0Entry.negTrackId = negativeTrackIndex.globalId; + currentV0Entry.v0Type = 1; + currentV0Entry.pdgCode = positiveTrackIndex.pdgCode; + currentV0Entry.particleId = positiveTrackIndex.originId; + currentV0Entry.isCollinearV0 = false; + if (v0BuilderOpts.mc_addGeneratedGammaMakeCollinear.value && currentV0Entry.pdgCode == 22) { + currentV0Entry.isCollinearV0 = true; + } + currentV0Entry.found = false; + for (const auto& v0 : v0s) { + if (v0.posTrackId() == positiveTrackIndex.globalId && + v0.negTrackId() == negativeTrackIndex.globalId) { + // this will override type, but not collision index + // N.B.: collision index checks still desirable! + currentV0Entry.globalId = v0.globalIndex(); + currentV0Entry.v0Type = v0.v0Type(); + currentV0Entry.isCollinearV0 = v0.isCollinearV0(); + currentV0Entry.found = true; + break; + } + } + if (v0BuilderOpts.mc_findableDetachedV0.value || currentV0Entry.collisionId >= 0) { + v0List.push_back(currentV0Entry); + } + } + } + } // end positive / negative track loops + + // fill findable statistics table + histos.fill(HIST("hFindableStatistics"), 0.0, v0s.size()); + histos.fill(HIST("hFindableStatistics"), 1.0, v0List.size()); + histos.fill(HIST("hFindableStatistics"), 2.0, collisionLessV0s); + + } // end findableMode > 0 check + } // end soa::is_table + + // determine properly collision-id-sorted index array for later use + // N.B.: necessary also before cascade part + sorted_v0.clear(); + sorted_v0 = sort_indices(v0List, (baseOpts.mc_findableMode.value > 0)); + + // Cascade part if cores are requested, skip otherwise + if (baseOpts.mEnabledTables[kStoredCascCores] || baseOpts.mEnabledTables[kStoredKFCascCores]) { + if (baseOpts.mc_findableMode.value < 2) { + // simple passthrough: copy existing cascades to build list + for (const auto& cascade : cascades) { + auto const& v0 = cascade.v0(); + currentCascadeEntry.globalId = cascade.globalIndex(); + currentCascadeEntry.collisionId = cascade.collisionId(); + currentCascadeEntry.v0Id = ao2dV0toV0List[v0.globalIndex()]; + currentCascadeEntry.posTrackId = v0.posTrackId(); + currentCascadeEntry.negTrackId = v0.negTrackId(); + currentCascadeEntry.bachTrackId = cascade.bachelorId(); + currentCascadeEntry.found = true; + cascadeList.push_back(currentCascadeEntry); + } + } + + // any mode other than 0 will require mcParticles + if constexpr (soa::is_table) { + if (baseOpts.mc_findableMode.value > 0) { + // for search if existing or not + size_t cascadeListReconstructedSize = cascadeList.size(); + + // determine which tracks are of interest + std::vector bachelorTrackArray; + // vector elements: track index, origin index, mc collision id, pdg code] + int dummy = -1; // unnecessary in this path + for (const auto& track : tracks) { + if (!track.has_mcParticle()) { + continue; // skip this, it's trouble + } + auto particle = track.template mcParticle_as(); + int originParticleIndex = getOriginatingParticle(particle, dummy, cascadeBuilderOpts.mc_treatPiToMuDecays); + if (originParticleIndex < 0) { + continue; // skip this, it's trouble (2) + } + auto originParticle = mcParticles.rawIteratorAt(originParticleIndex); + + bool trackIsInteresting = false; + if ( + (originParticle.pdgCode() == 3312 && cascadeBuilderOpts.mc_addGeneratedXiMinus.value > 0) || + (originParticle.pdgCode() == -3312 && cascadeBuilderOpts.mc_addGeneratedXiPlus.value > 0) || + (originParticle.pdgCode() == 3334 && cascadeBuilderOpts.mc_addGeneratedOmegaMinus.value > 0) || + (originParticle.pdgCode() == -3334 && cascadeBuilderOpts.mc_addGeneratedOmegaPlus.value > 0)) { + trackIsInteresting = true; + } + if (!trackIsInteresting) { + continue; // skip this, it's uninteresting + } + + currentTrackEntry.globalId = static_cast(track.globalIndex()); + currentTrackEntry.originId = originParticleIndex; + currentTrackEntry.mcCollisionId = originParticle.mcCollisionId(); + currentTrackEntry.pdgCode = originParticle.pdgCode(); + + // populate list of bachelor tracks to pair + bachelorTrackArray.push_back(currentTrackEntry); + } + + // determine which V0s are of interest to pair and do pairing + for (size_t v0i = 0; v0i < v0List.size(); v0i++) { + auto v0 = v0List[sorted_v0[v0i]]; + + if (std::abs(v0.pdgCode) != 3122) { + continue; // this V0 isn't a lambda, can't come from a cascade: skip + } + if (v0.particleId < 0) { + continue; // no de-referencing possible (e.g. background, ...) + } + auto v0Particle = mcParticles.rawIteratorAt(v0.particleId); + + int v0OriginParticleIndex = -1; + if (v0Particle.has_mothers()) { + auto const& motherList = v0Particle.template mothers_as(); + if (motherList.size() == 1) { + for (const auto& mother : motherList) { + v0OriginParticleIndex = mother.globalIndex(); + } + } + } + if (v0OriginParticleIndex < 0) { + continue; + } + auto v0OriginParticle = mcParticles.rawIteratorAt(v0OriginParticleIndex); + + if (std::abs(v0OriginParticle.pdgCode()) != 3312 && std::abs(v0OriginParticle.pdgCode()) != 3334) { + continue; // this V0 does not come from any particle of interest, don't try + } + for (const auto& bachelorTrackIndex : bachelorTrackArray) { + if (bachelorTrackIndex.originId != v0OriginParticle.globalIndex()) { + continue; + } + // if we are here: v0 origin is 3312 or 3334, bachelor origin matches V0 origin + // findable mode 1: add non-reconstructed as cascadeType 1 + if (baseOpts.mc_findableMode.value == 1) { + bool detected = false; + for (size_t ii = 0; ii < cascadeListReconstructedSize; ii++) { + // check if this particular combination already exists in cascadeList + // caution: use track indices (immutable) but not V0 indices (re-indexing) + if (cascadeList[ii].posTrackId == v0.posTrackId && + cascadeList[ii].negTrackId == v0.negTrackId && + cascadeList[ii].bachTrackId == bachelorTrackIndex.globalId) { + detected = true; + break; + } + } + if (detected == false) { + // collision index: from best-version-of-this-mcCollision + // nota bene: this could be negative, caution advised + currentCascadeEntry.globalId = -1; + currentCascadeEntry.collisionId = bestCollisionArray[bachelorTrackIndex.mcCollisionId]; + currentCascadeEntry.v0Id = v0i; // correct information here + currentCascadeEntry.posTrackId = v0.posTrackId; + currentCascadeEntry.negTrackId = v0.negTrackId; + currentCascadeEntry.bachTrackId = bachelorTrackIndex.globalId; + currentCascadeEntry.found = false; + cascadeList.push_back(currentCascadeEntry); + if (bestCollisionArray[bachelorTrackIndex.mcCollisionId] < 0) { + collisionLessCascades++; + } + if (cascadeBuilderOpts.mc_findableDetachedCascade.value || currentCascadeEntry.collisionId >= 0) { + cascadeList.push_back(currentCascadeEntry); + } + } + } + + // findable mode 2: determine type based on cascade table, + // with type 1 being reserved to findable-but-not-found + if (baseOpts.mc_findableMode.value == 2) { + currentCascadeEntry.globalId = -1; + currentCascadeEntry.collisionId = bestCollisionArray[bachelorTrackIndex.mcCollisionId]; + currentCascadeEntry.v0Id = v0i; // fill this in one go later + currentCascadeEntry.posTrackId = v0.posTrackId; + currentCascadeEntry.negTrackId = v0.negTrackId; + currentCascadeEntry.bachTrackId = bachelorTrackIndex.globalId; + currentCascadeEntry.found = false; + if (bestCollisionArray[bachelorTrackIndex.mcCollisionId] < 0) { + collisionLessCascades++; + } + for (const auto& cascade : cascades) { + auto const& v0fromAOD = cascade.v0(); + if (v0fromAOD.posTrackId() == v0.posTrackId && + v0fromAOD.negTrackId() == v0.negTrackId && + cascade.bachelorId() == bachelorTrackIndex.globalId) { + // this will override type, but not collision index + // N.B.: collision index checks still desirable! + currentCascadeEntry.found = true; + currentCascadeEntry.globalId = cascade.globalIndex(); + break; + } + } + if (cascadeBuilderOpts.mc_findableDetachedCascade.value || currentCascadeEntry.collisionId >= 0) { + cascadeList.push_back(currentCascadeEntry); + } + } + } // end bachelorTrackArray loop + } // end v0List loop + + // at this stage, cascadeList is alright, but the v0 indices are still not + // correct. We'll have to loop over all V0s and find the appropriate matches + // ---> but only in mode 1, and only for AO2D-native V0s + if (baseOpts.mc_findableMode.value == 1) { + for (size_t casci = 0; casci < cascadeListReconstructedSize; casci++) { + // loop over v0List to find corresponding v0 index, but do it in sorted way + for (size_t v0i = 0; v0i < v0List.size(); v0i++) { + auto v0 = v0List[sorted_v0[v0i]]; + if (cascadeList[casci].posTrackId == v0.posTrackId && + cascadeList[casci].negTrackId == v0.negTrackId) { + cascadeList[casci].v0Id = v0i; // fix, point to correct V0 index + break; + } + } + } + } + // we should now be done! collect statistics + histos.fill(HIST("hFindableStatistics"), 3.0, cascades.size()); + histos.fill(HIST("hFindableStatistics"), 4.0, cascadeList.size()); + histos.fill(HIST("hFindableStatistics"), 5.0, collisionLessCascades); + + } // end findable mode check + } // end soa::is_table + + // we need to allow for sorted use of cascadeList + sorted_cascade.clear(); + sorted_cascade = sort_indices(cascadeList, (baseOpts.mc_findableMode.value > 0)); + } + + LOGF(info, "AO2D input: %i V0s, %i cascades. Building list sizes: %i V0s, %i cascades", v0s.size(), cascades.size(), v0List.size(), cascadeList.size()); + } + + //__________________________________________________ + template + void markV0sUsedInCascades(TV0s const& v0s, TCascades const& cascades, TTrackedCascades const& trackedCascades) + { + int v0sUsedInCascades = 0; + v0sFromCascades.clear(); + v0Map.clear(); + v0Map.resize(v0List.size(), -2); // marks not used + if (baseOpts.useV0BufferForCascades.value == false) { + return; // don't attempt to mark needlessly + } + if (baseOpts.mEnabledTables[kStoredCascCores]) { + for (const auto& cascade : cascadeList) { + if (cascade.v0Id < 0) + continue; + if (v0Map[cascade.v0Id] == -2) { + v0sUsedInCascades++; + } + v0Map[cascade.v0Id] = -1; // marks used (but isn't the index of a properly built V0, which would be >= 0) + } + } + int trackedCascadeCount = 0; + if constexpr (soa::is_table) { + // tracked only created outside of findable mode + if (baseOpts.mEnabledTables[kStoredTraCascCores] && baseOpts.mc_findableMode.value == 0) { + trackedCascadeCount = trackedCascades.size(); + for (const auto& trackedCascade : trackedCascades) { + auto const& cascade = trackedCascade.cascade(); + if (v0Map[ao2dV0toV0List[cascade.v0Id()]] == -2) { + v0sUsedInCascades++; + } + v0Map[ao2dV0toV0List[cascade.v0Id()]] = -1; // marks used (but isn't the index of a built V0, which would be >= 0) + } + } + } + LOGF(debug, "V0 total %i, Cascade total %i, Tracked cascade total %i, V0s flagged used in cascades: %i", v0s.size(), cascades.size(), trackedCascadeCount, v0sUsedInCascades); + } + + //__________________________________________________ + template + void buildV0s(THistoRegistry& histos, TCollisions const& collisions, TV0s const& v0s, TTracks const& tracks, TMCParticles const& mcParticles, TProducts& products) + { + // prepare MC containers (not necessarily used) + std::vector mcV0infos; // V0MCCore information + std::vector mcParticleIsReco; + + if constexpr (soa::is_table) { + // do this if provided with a mcParticle table as well + mcParticleIsReco.resize(mcParticles.size(), false); + } + + int nV0s = 0; + // Loops over all V0s in the time frame + histos.fill(HIST("hInputStatistics"), kV0CoresBase, v0s.size()); + for (size_t iv0 = 0; iv0 < v0List.size(); iv0++) { + const auto& v0 = v0List[sorted_v0[iv0]]; + + if (!v0BuilderOpts.generatePhotonCandidates.value && v0.v0Type > 1) { + // skip photons if not requested + products.v0dataLink(-1, -1); + continue; + } + + if (!baseOpts.mEnabledTables[kV0CoresBase] && v0Map[iv0] == -2) { + // this v0 hasn't been used by cascades and we're not generating V0s, so skip it + products.v0dataLink(-1, -1); + continue; + } + + // Get tracks and generate candidate + // if collisionId positive: get vertex, negative: origin + // could be replaced by mean vertex (but without much benefit...) + float pvX = 0.0f, pvY = 0.0f, pvZ = 0.0f; + if (v0.collisionId >= 0) { + auto const& collision = collisions.rawIteratorAt(v0.collisionId); + pvX = collision.posX(); + pvY = collision.posY(); + pvZ = collision.posZ(); + } + auto const& posTrack = tracks.rawIteratorAt(v0.posTrackId); + auto const& negTrack = tracks.rawIteratorAt(v0.negTrackId); + + auto posTrackPar = getTrackParCov(posTrack); + auto negTrackPar = getTrackParCov(negTrack); + + // handle TPC-only tracks properly (photon conversions) + if (v0BuilderOpts.moveTPCOnlyTracks) { + bool isPosTPCOnly = (posTrack.hasTPC() && !posTrack.hasITS() && !posTrack.hasTRD() && !posTrack.hasTOF()); + if (isPosTPCOnly) { + // Nota bene: positive is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + + auto const& collision = collisions.rawIteratorAt(v0.collisionId); + if (!mVDriftMgr.moveTPCTrack(collision, posTrack, posTrackPar)) { + products.v0dataLink(-1, -1); + continue; + } + } + + bool isNegTPCOnly = (negTrack.hasTPC() && !negTrack.hasITS() && !negTrack.hasTRD() && !negTrack.hasTOF()); + if (isNegTPCOnly) { + // Nota bene: negative is TPC-only -> this entire V0 merits treatment as photon candidate + posTrackPar.setPID(o2::track::PID::Electron); + negTrackPar.setPID(o2::track::PID::Electron); + + auto const& collision = collisions.rawIteratorAt(v0.collisionId); + if (!mVDriftMgr.moveTPCTrack(collision, negTrack, negTrackPar)) { + products.v0dataLink(-1, -1); + continue; + } + } + } + + if (!straHelper.buildV0Candidate(v0.collisionId, pvX, pvY, pvZ, posTrack, negTrack, posTrackPar, negTrackPar, v0.isCollinearV0, baseOpts.mEnabledTables[kV0Covs], v0BuilderOpts.generatePhotonCandidates)) { + products.v0dataLink(-1, -1); + continue; + } + if constexpr (requires { posTrack.tpcNSigmaEl(); }) { + if (preSelectOpts.preselectOnlyDesiredV0s) { + float lPt = RecoDecay::sqrtSumOfSquares( + straHelper.v0.positiveMomentum[0] + straHelper.v0.negativeMomentum[0], + straHelper.v0.positiveMomentum[1] + straHelper.v0.negativeMomentum[1]); + + float lPtot = RecoDecay::sqrtSumOfSquares( + straHelper.v0.positiveMomentum[0] + straHelper.v0.negativeMomentum[0], + straHelper.v0.positiveMomentum[1] + straHelper.v0.negativeMomentum[1], + straHelper.v0.positiveMomentum[2] + straHelper.v0.negativeMomentum[2]); + + float lLengthTraveled = RecoDecay::sqrtSumOfSquares( + straHelper.v0.position[0] - pvX, + straHelper.v0.position[1] - pvY, + straHelper.v0.position[2] - pvZ); + + uint8_t maskV0Preselection = 0; + + if ( // photon PID, mass, lifetime selection + std::abs(posTrack.tpcNSigmaEl()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaEl()) < preSelectOpts.maxTPCpidNsigma && + std::abs(straHelper.v0.massGamma) < preSelectOpts.massCutPhoton) { + BITSET(maskV0Preselection, selGamma); + } + + if ( // K0Short PID, mass, lifetime selection + std::abs(posTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + o2::constants::physics::MassKaonNeutral * lLengthTraveled / (lPtot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutK0S") && + std::abs(straHelper.v0.massK0Short - o2::constants::physics::MassKaonNeutral) < preSelectOpts.massWindownumberOfSigmas * getMassSigmaK0Short(lPt) + preSelectOpts.massWindowSafetyMargin) { + BITSET(maskV0Preselection, selK0Short); + } + + if ( // Lambda PID, mass, lifetime selection + std::abs(posTrack.tpcNSigmaPr()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + o2::constants::physics::MassLambda * lLengthTraveled / (lPtot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutLambda") && + std::abs(straHelper.v0.massLambda - o2::constants::physics::MassLambda) < preSelectOpts.massWindownumberOfSigmas * getMassSigmaLambda(lPt) + preSelectOpts.massWindowSafetyMargin) { + BITSET(maskV0Preselection, selLambda); + } + + if ( // antiLambda PID, mass, lifetime selection + std::abs(posTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaPr()) < preSelectOpts.maxTPCpidNsigma && + o2::constants::physics::MassLambda * lLengthTraveled / (lPtot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutLambda") && + std::abs(straHelper.v0.massAntiLambda - o2::constants::physics::MassLambda) < preSelectOpts.massWindownumberOfSigmas * getMassSigmaLambda(lPt) + preSelectOpts.massWindowSafetyMargin) { + BITSET(maskV0Preselection, selAntiLambda); + } + + histos.fill(HIST("hPreselectionV0s"), maskV0Preselection); + + if (maskV0Preselection == 0) { + products.v0dataLink(-1, -1); + continue; + } + } + } + if (v0Map[iv0] == -1 && baseOpts.useV0BufferForCascades) { + v0Map[iv0] = v0sFromCascades.size(); // provide actual valid index in buffer + v0sFromCascades.push_back(straHelper.v0); + } + // fill requested cursors only if type is not 0 + if (v0.v0Type == 1 || (v0.v0Type > 1 && v0BuilderOpts.generatePhotonCandidates)) { + nV0s++; + if (baseOpts.mEnabledTables[kV0Indices]) { + // for referencing (especially - but not only - when using derived data) + products.v0indices(v0.posTrackId, v0.negTrackId, + v0.collisionId, iv0); + histos.fill(HIST("hTableBuildingStatistics"), kV0Indices); + } + if (baseOpts.mEnabledTables[kV0TrackXs]) { + // further decay chains may need this + products.v0trackXs(straHelper.v0.positiveTrackX, straHelper.v0.negativeTrackX); + histos.fill(HIST("hTableBuildingStatistics"), kV0TrackXs); + } + if (baseOpts.mEnabledTables[kV0CoresBase]) { + // standard analysis + products.v0cores(straHelper.v0.position[0], straHelper.v0.position[1], straHelper.v0.position[2], + straHelper.v0.positiveMomentum[0], straHelper.v0.positiveMomentum[1], straHelper.v0.positiveMomentum[2], + straHelper.v0.negativeMomentum[0], straHelper.v0.negativeMomentum[1], straHelper.v0.negativeMomentum[2], + straHelper.v0.daughterDCA, + straHelper.v0.positiveDCAxy, + straHelper.v0.negativeDCAxy, + TMath::Cos(straHelper.v0.pointingAngle), + straHelper.v0.dcaToPV, + v0.v0Type); + products.v0dataLink(products.v0cores.lastIndex(), -1); + histos.fill(HIST("hTableBuildingStatistics"), kV0CoresBase); + } + if (baseOpts.mEnabledTables[kV0TraPosAtDCAs]) { + // for tracking studies + products.v0dauPositions(straHelper.v0.positivePosition[0], straHelper.v0.positivePosition[1], straHelper.v0.positivePosition[2], + straHelper.v0.negativePosition[0], straHelper.v0.negativePosition[1], straHelper.v0.negativePosition[2]); + histos.fill(HIST("hTableBuildingStatistics"), kV0TraPosAtDCAs); + } + if (baseOpts.mEnabledTables[kV0TraPosAtIUs]) { + // for tracking studies + std::array positivePositionIU; + std::array negativePositionIU; + o2::track::TrackPar positiveTrackParam = getTrackPar(posTrack); + o2::track::TrackPar negativeTrackParam = getTrackPar(negTrack); + positiveTrackParam.getXYZGlo(positivePositionIU); + negativeTrackParam.getXYZGlo(negativePositionIU); + products.v0dauPositionsIU(positivePositionIU[0], positivePositionIU[1], positivePositionIU[2], + negativePositionIU[0], negativePositionIU[1], negativePositionIU[2]); + histos.fill(HIST("hTableBuildingStatistics"), kV0TraPosAtIUs); + } + if (baseOpts.mEnabledTables[kV0Covs]) { + products.v0covs(straHelper.v0.positionCovariance, straHelper.v0.momentumCovariance); + histos.fill(HIST("hTableBuildingStatistics"), kV0Covs); + } + + //_________________________________________________________ + // MC handling part + if constexpr (soa::is_table) { + // only worry about this if someone else worried about this + if ((baseOpts.mEnabledTables[kV0MCCores] || baseOpts.mEnabledTables[kMcV0Labels] || baseOpts.mEnabledTables[kV0MCCollRefs])) { + thisInfo.label = -1; + thisInfo.motherLabel = -1; + thisInfo.pdgCode = 0; + thisInfo.pdgCodeMother = 0; + thisInfo.pdgCodePositive = 0; + thisInfo.pdgCodeNegative = 0; + thisInfo.mcCollision = -1; + thisInfo.xyz[0] = thisInfo.xyz[1] = thisInfo.xyz[2] = 0.0f; + thisInfo.posP[0] = thisInfo.posP[1] = thisInfo.posP[2] = 0.0f; + thisInfo.negP[0] = thisInfo.negP[1] = thisInfo.negP[2] = 0.0f; + thisInfo.momentum[0] = thisInfo.momentum[1] = thisInfo.momentum[2] = 0.0f; + + // Association check + // There might be smarter ways of doing this in the future + if (negTrack.has_mcParticle() && posTrack.has_mcParticle()) { + auto lMCNegTrack = negTrack.template mcParticle_as(); + auto lMCPosTrack = posTrack.template mcParticle_as(); + + thisInfo.pdgCodePositive = lMCPosTrack.pdgCode(); + thisInfo.pdgCodeNegative = lMCNegTrack.pdgCode(); + thisInfo.processPositive = lMCPosTrack.getProcess(); + thisInfo.processNegative = lMCNegTrack.getProcess(); + thisInfo.posP[0] = lMCPosTrack.px(); + thisInfo.posP[1] = lMCPosTrack.py(); + thisInfo.posP[2] = lMCPosTrack.pz(); + thisInfo.negP[0] = lMCNegTrack.px(); + thisInfo.negP[1] = lMCNegTrack.py(); + thisInfo.negP[2] = lMCNegTrack.pz(); + + // check for pi -> mu + antineutrino decay + // if present, de-reference original V0 correctly and provide label to original object + // NOTA BENE: the prong info will still correspond to a muon, treat carefully! + int negOriginating = -1, posOriginating = -1, particleForDecayPositionIdx = -1; + negOriginating = getOriginatingParticle(lMCNegTrack, particleForDecayPositionIdx, v0BuilderOpts.mc_treatPiToMuDecays); + posOriginating = getOriginatingParticle(lMCPosTrack, particleForDecayPositionIdx, v0BuilderOpts.mc_treatPiToMuDecays); + + if (negOriginating > -1 && negOriginating == posOriginating) { + auto originatingV0 = mcParticles.rawIteratorAt(negOriginating); + auto particleForDecayPosition = mcParticles.rawIteratorAt(particleForDecayPositionIdx); + + thisInfo.label = originatingV0.globalIndex(); + thisInfo.xyz[0] = particleForDecayPosition.vx(); + thisInfo.xyz[1] = particleForDecayPosition.vy(); + thisInfo.xyz[2] = particleForDecayPosition.vz(); + + if (originatingV0.has_mcCollision()) { + thisInfo.mcCollision = originatingV0.mcCollisionId(); // save this reference, please + } + + // acquire information + thisInfo.pdgCode = originatingV0.pdgCode(); + thisInfo.isPhysicalPrimary = originatingV0.isPhysicalPrimary(); + thisInfo.momentum[0] = originatingV0.px(); + thisInfo.momentum[1] = originatingV0.py(); + thisInfo.momentum[2] = originatingV0.pz(); + + if (originatingV0.has_mothers()) { + for (const auto& lV0Mother : originatingV0.template mothers_as()) { + thisInfo.pdgCodeMother = lV0Mother.pdgCode(); + thisInfo.motherLabel = lV0Mother.globalIndex(); + } + } + } + + } // end association check + // Construct label table (note: this will be joinable with V0Datas!) + if (baseOpts.mEnabledTables[kMcV0Labels]) { + products.v0labels(thisInfo.label, thisInfo.motherLabel); + histos.fill(HIST("hTableBuildingStatistics"), kMcV0Labels); + } + + // Construct found tag + if (baseOpts.mEnabledTables[kV0FoundTags]) { + products.v0FoundTag(v0.found); + histos.fill(HIST("hTableBuildingStatistics"), kV0FoundTags); + } + + // Mark mcParticle as recoed (no searching necessary afterwards) + if (thisInfo.label > -1) { + mcParticleIsReco[thisInfo.label] = true; + } + + // ---] Symmetric populate [--- + // in this approach, V0Cores will be joinable with V0MCCores. + // this is the most pedagogical approach, but it is also more limited + // and it might use more disk space unnecessarily. + if (v0BuilderOpts.mc_populateV0MCCoresSymmetric) { + if (baseOpts.mEnabledTables[kV0MCCores]) { + products.v0mccores( + thisInfo.label, thisInfo.pdgCode, + thisInfo.pdgCodeMother, thisInfo.pdgCodePositive, thisInfo.pdgCodeNegative, + thisInfo.isPhysicalPrimary, thisInfo.xyz[0], thisInfo.xyz[1], thisInfo.xyz[2], + thisInfo.posP[0], thisInfo.posP[1], thisInfo.posP[2], + thisInfo.negP[0], thisInfo.negP[1], thisInfo.negP[2], + thisInfo.momentum[0], thisInfo.momentum[1], thisInfo.momentum[2]); + histos.fill(HIST("hTableBuildingStatistics"), kV0MCCores); + histos.fill(HIST("hPrimaryV0s"), 0); + if (thisInfo.isPhysicalPrimary) + histos.fill(HIST("hPrimaryV0s"), 1); + } + if (baseOpts.mEnabledTables[kV0MCCollRefs]) { + products.v0mccollref(thisInfo.mcCollision); + histos.fill(HIST("hTableBuildingStatistics"), kV0MCCollRefs); + } + + // n.b. placing the interlink index here allows for the writing of + // code that is agnostic with respect to the joinability of + // V0Cores and V0MCCores (always dereference -> safe) + if (baseOpts.mEnabledTables[kV0CoreMCLabels]) { + products.v0CoreMCLabels(iv0); // interlink index + histos.fill(HIST("hTableBuildingStatistics"), kV0CoreMCLabels); + } + } + // ---] Asymmetric populate [--- + // in this approach, V0Cores will NOT be joinable with V0MCCores. + // an additional reference to V0MCCore that IS joinable with V0Cores + // will be provided to the user. + if (v0BuilderOpts.mc_populateV0MCCoresAsymmetric) { + int thisV0MCCoreIndex = -1; + // step 1: check if this element is already provided in the table + // using the packedIndices variable calculated above + for (uint32_t ii = 0; ii < mcV0infos.size(); ii++) { + if (thisInfo.label == mcV0infos[ii].label && mcV0infos[ii].label > -1) { + thisV0MCCoreIndex = ii; + break; // this exists already in list + } + } + if (thisV0MCCoreIndex < 0 && thisInfo.label > -1) { + // this V0MCCore does not exist yet. Create it and reference it + thisV0MCCoreIndex = mcV0infos.size(); + mcV0infos.push_back(thisInfo); + } + if (baseOpts.mEnabledTables[kV0CoreMCLabels]) { + products.v0CoreMCLabels(thisV0MCCoreIndex); // interlink index + histos.fill(HIST("hTableBuildingStatistics"), kV0CoreMCLabels); + } + } + } // enabled tables check + } // constexpr requires check + } else { + products.v0dataLink(-1, -1); + } + } + + // finish populating V0MCCores if in asymmetric mode + if constexpr (soa::is_table) { + if (v0BuilderOpts.mc_populateV0MCCoresAsymmetric && (baseOpts.mEnabledTables[kV0MCCores] || baseOpts.mEnabledTables[kV0MCCollRefs])) { + // first step: add any un-recoed v0mmcores that were requested + for (const auto& mcParticle : mcParticles) { + thisInfo.label = -1; + thisInfo.motherLabel = -1; + thisInfo.pdgCode = 0; + thisInfo.pdgCodeMother = -1; + thisInfo.pdgCodePositive = -1; + thisInfo.pdgCodeNegative = -1; + thisInfo.mcCollision = -1; + thisInfo.xyz[0] = thisInfo.xyz[1] = thisInfo.xyz[2] = 0.0f; + thisInfo.posP[0] = thisInfo.posP[1] = thisInfo.posP[2] = 0.0f; + thisInfo.negP[0] = thisInfo.negP[1] = thisInfo.negP[2] = 0.0f; + thisInfo.momentum[0] = thisInfo.momentum[1] = thisInfo.momentum[2] = 0.0f; + + if (mcParticleIsReco[mcParticle.globalIndex()] == true) + continue; // skip if already created in list + + if (std::fabs(mcParticle.y()) > v0BuilderOpts.mc_rapidityWindow) + continue; // skip outside midrapidity + + if (v0BuilderOpts.mc_keepOnlyPhysicalPrimary && !mcParticle.isPhysicalPrimary()) + continue; // skip secondary MC V0s + + if ( + (v0BuilderOpts.mc_addGeneratedK0Short && mcParticle.pdgCode() == 310) || + (v0BuilderOpts.mc_addGeneratedLambda && mcParticle.pdgCode() == 3122) || + (v0BuilderOpts.mc_addGeneratedAntiLambda && mcParticle.pdgCode() == -3122) || + (v0BuilderOpts.mc_addGeneratedGamma && mcParticle.pdgCode() == 22)) { + thisInfo.pdgCode = mcParticle.pdgCode(); + thisInfo.isPhysicalPrimary = mcParticle.isPhysicalPrimary(); + thisInfo.label = mcParticle.globalIndex(); + + if (mcParticle.has_mcCollision()) { + thisInfo.mcCollision = mcParticle.mcCollisionId(); // save this reference, please + } + + // + thisInfo.momentum[0] = mcParticle.px(); + thisInfo.momentum[1] = mcParticle.py(); + thisInfo.momentum[2] = mcParticle.pz(); + + if (mcParticle.has_mothers()) { + auto const& mother = mcParticle.template mothers_first_as(); + thisInfo.pdgCodeMother = mother.pdgCode(); + thisInfo.motherLabel = mother.globalIndex(); + } + if (mcParticle.has_daughters()) { + auto const& daughters = mcParticle.template daughters_as(); + + for (const auto& dau : daughters) { + if (dau.getProcess() != 4) + continue; + + if (dau.pdgCode() > 0) { + thisInfo.pdgCodePositive = dau.pdgCode(); + thisInfo.processPositive = dau.getProcess(); + thisInfo.posP[0] = dau.px(); + thisInfo.posP[1] = dau.py(); + thisInfo.posP[2] = dau.pz(); + thisInfo.xyz[0] = dau.vx(); + thisInfo.xyz[1] = dau.vy(); + thisInfo.xyz[2] = dau.vz(); + } + if (dau.pdgCode() < 0) { + thisInfo.pdgCodeNegative = dau.pdgCode(); + thisInfo.processNegative = dau.getProcess(); + thisInfo.negP[0] = dau.px(); + thisInfo.negP[1] = dau.py(); + thisInfo.negP[2] = dau.pz(); + } + } + } + + // if I got here, it means this MC particle was not recoed and is of interest. Add it please + mcV0infos.push_back(thisInfo); + } + } + + for (const auto& info : mcV0infos) { + if (baseOpts.mEnabledTables[kV0MCCores]) { + products.v0mccores( + info.label, info.pdgCode, + info.pdgCodeMother, info.pdgCodePositive, info.pdgCodeNegative, + info.isPhysicalPrimary, info.xyz[0], info.xyz[1], info.xyz[2], + info.posP[0], info.posP[1], info.posP[2], + info.negP[0], info.negP[1], info.negP[2], + info.momentum[0], info.momentum[1], info.momentum[2]); + histos.fill(HIST("hTableBuildingStatistics"), kV0MCCores); + histos.fill(HIST("hPrimaryV0s"), 0); + if (info.isPhysicalPrimary) + histos.fill(HIST("hPrimaryV0s"), 1); + } + if (baseOpts.mEnabledTables[kV0MCCollRefs]) { + products.v0mccollref(info.mcCollision); + histos.fill(HIST("hTableBuildingStatistics"), kV0MCCollRefs); + } + } + } // end V0MCCores filling in case of MC + } // end constexpr requires mcParticles + + LOGF(debug, "V0s in DF: %i, V0s built: %i, V0s built and buffered for cascades: %i.", v0s.size(), nV0s, v0sFromCascades.size()); + } + + //__________________________________________________ + template + void extractMonteCarloProperties(TTrack const& posTrack, TTrack const& negTrack, TTrack const& bachTrack, TMCParticles const& mcParticles) + { + // encapsulates acquisition of MC properties from MC + thisCascInfo.pdgCode = -1, thisCascInfo.pdgCodeMother = -1; + thisCascInfo.pdgCodePositive = -1, thisCascInfo.pdgCodeNegative = -1; + thisCascInfo.pdgCodeBachelor = -1, thisCascInfo.pdgCodeV0 = -1; + thisCascInfo.isPhysicalPrimary = false; + thisCascInfo.xyz[0] = -999.0f, thisCascInfo.xyz[1] = -999.0f, thisCascInfo.xyz[2] = -999.0f; + thisCascInfo.lxyz[0] = -999.0f, thisCascInfo.lxyz[1] = -999.0f, thisCascInfo.lxyz[2] = -999.0f; + thisCascInfo.posP[0] = -999.0f, thisCascInfo.posP[1] = -999.0f, thisCascInfo.posP[2] = -999.0f; + thisCascInfo.negP[0] = -999.0f, thisCascInfo.negP[1] = -999.0f, thisCascInfo.negP[2] = -999.0f; + thisCascInfo.bachP[0] = -999.0f, thisCascInfo.bachP[1] = -999.0f, thisCascInfo.bachP[2] = -999.0f; + thisCascInfo.momentum[0] = -999.0f, thisCascInfo.momentum[1] = -999.0f, thisCascInfo.momentum[2] = -999.0f; + thisCascInfo.label = -1, thisCascInfo.motherLabel = -1; + thisCascInfo.mcParticlePositive = -1; + thisCascInfo.mcParticleNegative = -1; + thisCascInfo.mcParticleBachelor = -1; + + // Association check + // There might be smarter ways of doing this in the future + if (negTrack.has_mcParticle() && posTrack.has_mcParticle() && bachTrack.has_mcParticle()) { + auto lMCBachTrack = bachTrack.template mcParticle_as(); + auto lMCNegTrack = negTrack.template mcParticle_as(); + auto lMCPosTrack = posTrack.template mcParticle_as(); + + thisCascInfo.mcParticlePositive = lMCPosTrack.globalIndex(); + thisCascInfo.mcParticleNegative = lMCNegTrack.globalIndex(); + thisCascInfo.mcParticleBachelor = lMCBachTrack.globalIndex(); + thisCascInfo.pdgCodePositive = lMCPosTrack.pdgCode(); + thisCascInfo.pdgCodeNegative = lMCNegTrack.pdgCode(); + thisCascInfo.pdgCodeBachelor = lMCBachTrack.pdgCode(); + thisCascInfo.posP[0] = lMCPosTrack.px(); + thisCascInfo.posP[1] = lMCPosTrack.py(); + thisCascInfo.posP[2] = lMCPosTrack.pz(); + thisCascInfo.negP[0] = lMCNegTrack.px(); + thisCascInfo.negP[1] = lMCNegTrack.py(); + thisCascInfo.negP[2] = lMCNegTrack.pz(); + thisCascInfo.bachP[0] = lMCBachTrack.px(); + thisCascInfo.bachP[1] = lMCBachTrack.py(); + thisCascInfo.bachP[2] = lMCBachTrack.pz(); + thisCascInfo.processPositive = lMCPosTrack.getProcess(); + thisCascInfo.processNegative = lMCNegTrack.getProcess(); + thisCascInfo.processBachelor = lMCBachTrack.getProcess(); + + // Step 0: treat pi -> mu + antineutrino + // if present, de-reference original V0 correctly and provide label to original object + // NOTA BENE: the prong info will still correspond to a muon, treat carefully! + int negOriginating = -1, posOriginating = -1, bachOriginating = -1; + int particleForLambdaDecayPositionIdx = -1, particleForCascadeDecayPositionIdx = -1; + negOriginating = getOriginatingParticle(lMCNegTrack, particleForLambdaDecayPositionIdx, cascadeBuilderOpts.mc_treatPiToMuDecays); + posOriginating = getOriginatingParticle(lMCPosTrack, particleForLambdaDecayPositionIdx, cascadeBuilderOpts.mc_treatPiToMuDecays); + bachOriginating = getOriginatingParticle(lMCBachTrack, particleForCascadeDecayPositionIdx, cascadeBuilderOpts.mc_treatPiToMuDecays); + + if (negOriginating > -1 && negOriginating == posOriginating) { + auto originatingV0 = mcParticles.rawIteratorAt(negOriginating); + auto particleForLambdaDecayPosition = mcParticles.rawIteratorAt(particleForLambdaDecayPositionIdx); + + thisCascInfo.label = originatingV0.globalIndex(); + thisCascInfo.lxyz[0] = particleForLambdaDecayPosition.vx(); + thisCascInfo.lxyz[1] = particleForLambdaDecayPosition.vy(); + thisCascInfo.lxyz[2] = particleForLambdaDecayPosition.vz(); + thisCascInfo.pdgCodeV0 = originatingV0.pdgCode(); + + if (originatingV0.has_mothers()) { + for (const auto& lV0Mother : originatingV0.template mothers_as()) { + if (lV0Mother.globalIndex() == bachOriginating) { // found mother particle + thisCascInfo.label = lV0Mother.globalIndex(); + + if (lV0Mother.has_mcCollision()) { + thisCascInfo.mcCollision = lV0Mother.mcCollisionId(); // save this reference, please + } + + thisCascInfo.pdgCode = lV0Mother.pdgCode(); + thisCascInfo.isPhysicalPrimary = lV0Mother.isPhysicalPrimary(); + thisCascInfo.xyz[0] = originatingV0.vx(); + thisCascInfo.xyz[1] = originatingV0.vy(); + thisCascInfo.xyz[2] = originatingV0.vz(); + thisCascInfo.momentum[0] = lV0Mother.px(); + thisCascInfo.momentum[1] = lV0Mother.py(); + thisCascInfo.momentum[2] = lV0Mother.pz(); + if (lV0Mother.has_mothers()) { + for (const auto& lV0GrandMother : lV0Mother.template mothers_as()) { + thisCascInfo.pdgCodeMother = lV0GrandMother.pdgCode(); + thisCascInfo.motherLabel = lV0GrandMother.globalIndex(); + } + } + } + } // end v0 mother loop + } // end has_mothers check for V0 + } // end conditional of pos/neg originating being the same + } // end association check + } + + //__________________________________________________ + template + void buildCascades(THistoRegistry& histos, TCollisions const& collisions, TCascades const& cascades, TTracks const& tracks, TMCParticles const& mcParticles, TProducts& products) + { + // prepare MC containers (not necessarily used) + std::vector mcCascinfos; // V0MCCore information + std::vector mcParticleIsReco; + + if constexpr (soa::is_table) { + // do this if provided with a mcParticle table as well + mcParticleIsReco.resize(mcParticles.size(), false); + } + + if (!baseOpts.mEnabledTables[kStoredCascCores]) { + return; // don't do if no request for cascades in place + } + int nCascades = 0; + // Loops over all cascades in the time frame + histos.fill(HIST("hInputStatistics"), kStoredCascCores, cascades.size()); + for (size_t icascade = 0; icascade < cascades.size(); icascade++) { + // Get tracks and generate candidate + auto const& cascade = cascades[sorted_cascade[icascade]]; + // if collisionId positive: get vertex, negative: origin + // could be replaced by mean vertex (but without much benefit...) + float pvX = 0.0f, pvY = 0.0f, pvZ = 0.0f; + if (cascade.collisionId >= 0) { + auto const& collision = collisions.rawIteratorAt(cascade.collisionId); + pvX = collision.posX(); + pvY = collision.posY(); + pvZ = collision.posZ(); + } + auto const& posTrack = tracks.rawIteratorAt(cascade.posTrackId); + auto const& negTrack = tracks.rawIteratorAt(cascade.negTrackId); + auto const& bachTrack = tracks.rawIteratorAt(cascade.bachTrackId); + if (baseOpts.useV0BufferForCascades) { + // this processing path uses a buffer of V0s so that no + // additional minimization step is redone. It consumes less + // CPU at the cost of more memory. Since memory is a more + // limited commodity, this isn't the default option. + + // check if cached - if not, skip + if (cascade.v0Id < 0 || v0Map[cascade.v0Id] < 0) { + // this V0 hasn't been stored / cached + products.cascdataLink(-1); + interlinks.cascadeToCascCores.push_back(-1); + continue; // didn't work out, skip + } + + if (!straHelper.buildCascadeCandidate(cascade.collisionId, pvX, pvY, pvZ, + v0sFromCascades[v0Map[cascade.v0Id]], + posTrack, + negTrack, + bachTrack, + baseOpts.mEnabledTables[kCascBBs], + cascadeBuilderOpts.useCascadeMomentumAtPrimVtx, + baseOpts.mEnabledTables[kCascCovs])) { + products.cascdataLink(-1); + interlinks.cascadeToCascCores.push_back(-1); + continue; // didn't work out, skip + } + } else { + // this processing path generates the entire cascade + // from tracks, without any need to have V0s generated. + if (!straHelper.buildCascadeCandidate(cascade.collisionId, pvX, pvY, pvZ, + posTrack, + negTrack, + bachTrack, + baseOpts.mEnabledTables[kCascBBs], + cascadeBuilderOpts.useCascadeMomentumAtPrimVtx, + baseOpts.mEnabledTables[kCascCovs])) { + products.cascdataLink(-1); + interlinks.cascadeToCascCores.push_back(-1); + continue; // didn't work out, skip + } + } + nCascades++; + + if constexpr (requires { posTrack.tpcNSigmaEl(); }) { + if (preSelectOpts.preselectOnlyDesiredCascades) { + float lPt = RecoDecay::sqrtSumOfSquares( + straHelper.cascade.bachelorMomentum[0] + straHelper.cascade.positiveMomentum[0] + straHelper.cascade.negativeMomentum[0], + straHelper.cascade.bachelorMomentum[1] + straHelper.cascade.positiveMomentum[1] + straHelper.cascade.negativeMomentum[1]); + + float lPtot = RecoDecay::sqrtSumOfSquares( + straHelper.cascade.bachelorMomentum[0] + straHelper.cascade.positiveMomentum[0] + straHelper.cascade.negativeMomentum[0], + straHelper.cascade.bachelorMomentum[1] + straHelper.cascade.positiveMomentum[1] + straHelper.cascade.negativeMomentum[1], + straHelper.cascade.bachelorMomentum[2] + straHelper.cascade.positiveMomentum[2] + straHelper.cascade.negativeMomentum[2]); + + float lV0Ptot = RecoDecay::sqrtSumOfSquares( + straHelper.cascade.positiveMomentum[0] + straHelper.cascade.negativeMomentum[0], + straHelper.cascade.positiveMomentum[1] + straHelper.cascade.negativeMomentum[1], + straHelper.cascade.positiveMomentum[2] + straHelper.cascade.negativeMomentum[2]); + + float lLengthTraveled = RecoDecay::sqrtSumOfSquares( + straHelper.cascade.cascadePosition[0] - pvX, + straHelper.cascade.cascadePosition[1] - pvY, + straHelper.cascade.cascadePosition[2] - pvZ); + + float lV0LengthTraveled = RecoDecay::sqrtSumOfSquares( + straHelper.cascade.v0Position[0] - straHelper.cascade.cascadePosition[0], + straHelper.cascade.v0Position[1] - straHelper.cascade.cascadePosition[1], + straHelper.cascade.v0Position[2] - straHelper.cascade.cascadePosition[2]); + + uint8_t maskCascadePreselection = 0; + + if ( // XiMinus PID and mass selection + straHelper.cascade.charge < 0 && + std::abs(posTrack.tpcNSigmaPr()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + std::abs(bachTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + o2::constants::physics::MassLambda * lV0LengthTraveled / (lV0Ptot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutLambda") && + o2::constants::physics::MassXiMinus * lLengthTraveled / (lPtot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutXi") && + std::abs(straHelper.cascade.massXi - o2::constants::physics::MassXiMinus) < preSelectOpts.massWindownumberOfSigmas * getMassSigmaXi(lPt) + preSelectOpts.massWindowSafetyMargin) { + BITSET(maskCascadePreselection, selXiMinus); + } + + if ( // XiPlus PID and mass selection + straHelper.cascade.charge > 0 && + std::abs(posTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaPr()) < preSelectOpts.maxTPCpidNsigma && + std::abs(bachTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + o2::constants::physics::MassLambda * lV0LengthTraveled / (lV0Ptot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutLambda") && + o2::constants::physics::MassXiMinus * lLengthTraveled / (lPtot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutXi") && + std::abs(straHelper.cascade.massXi - o2::constants::physics::MassXiMinus) < preSelectOpts.massWindownumberOfSigmas * getMassSigmaXi(lPt) + preSelectOpts.massWindowSafetyMargin) { + BITSET(maskCascadePreselection, selXiPlus); + } + + if ( // OmegaMinus PID and mass selection + straHelper.cascade.charge < 0 && + std::abs(posTrack.tpcNSigmaPr()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + std::abs(bachTrack.tpcNSigmaKa()) < preSelectOpts.maxTPCpidNsigma && + o2::constants::physics::MassLambda * lV0LengthTraveled / (lV0Ptot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutLambda") && + o2::constants::physics::MassOmegaMinus * lLengthTraveled / (lPtot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutOmega") && + std::abs(straHelper.cascade.massOmega - o2::constants::physics::MassOmegaMinus) < preSelectOpts.massWindownumberOfSigmas * getMassSigmaOmega(lPt) + preSelectOpts.massWindowSafetyMargin) { + BITSET(maskCascadePreselection, selOmegaMinus); + } + + if ( // OmegaPlus PID and mass selection + straHelper.cascade.charge > 0 && + std::abs(posTrack.tpcNSigmaPi()) < preSelectOpts.maxTPCpidNsigma && + std::abs(negTrack.tpcNSigmaPr()) < preSelectOpts.maxTPCpidNsigma && + std::abs(bachTrack.tpcNSigmaKa()) < preSelectOpts.maxTPCpidNsigma && + o2::constants::physics::MassLambda * lV0LengthTraveled / (lV0Ptot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutLambda") && + o2::constants::physics::MassOmegaMinus * lLengthTraveled / (lPtot + 1e-13) < preSelectOpts.lifetimeCut->get("lifetimeCutOmega") && + std::abs(straHelper.cascade.massOmega - o2::constants::physics::MassOmegaMinus) < preSelectOpts.massWindownumberOfSigmas * getMassSigmaOmega(lPt) + preSelectOpts.massWindowSafetyMargin) { + BITSET(maskCascadePreselection, selOmegaPlus); + } + + histos.fill(HIST("hPreselectionCascades"), maskCascadePreselection); + + if (maskCascadePreselection == 0) { + products.cascdataLink(-1); + interlinks.cascadeToCascCores.push_back(-1); + continue; + } + } + } + + // generate analysis tables as required + if (baseOpts.mEnabledTables[kCascIndices]) { + products.cascidx(cascade.globalId, + straHelper.cascade.positiveTrack, straHelper.cascade.negativeTrack, + straHelper.cascade.bachelorTrack, straHelper.cascade.collisionId); + histos.fill(HIST("hTableBuildingStatistics"), kCascIndices); + } + if (baseOpts.mEnabledTables[kStoredCascCores]) { + products.cascdata(straHelper.cascade.charge, straHelper.cascade.massXi, straHelper.cascade.massOmega, + straHelper.cascade.cascadePosition[0], straHelper.cascade.cascadePosition[1], straHelper.cascade.cascadePosition[2], + straHelper.cascade.v0Position[0], straHelper.cascade.v0Position[1], straHelper.cascade.v0Position[2], + straHelper.cascade.positiveMomentum[0], straHelper.cascade.positiveMomentum[1], straHelper.cascade.positiveMomentum[2], + straHelper.cascade.negativeMomentum[0], straHelper.cascade.negativeMomentum[1], straHelper.cascade.negativeMomentum[2], + straHelper.cascade.bachelorMomentum[0], straHelper.cascade.bachelorMomentum[1], straHelper.cascade.bachelorMomentum[2], + straHelper.cascade.cascadeMomentum[0], straHelper.cascade.cascadeMomentum[1], straHelper.cascade.cascadeMomentum[2], + straHelper.cascade.v0DaughterDCA, straHelper.cascade.cascadeDaughterDCA, + straHelper.cascade.positiveDCAxy, straHelper.cascade.negativeDCAxy, + straHelper.cascade.bachelorDCAxy, straHelper.cascade.cascadeDCAxy, straHelper.cascade.cascadeDCAz); + histos.fill(HIST("hTableBuildingStatistics"), kStoredCascCores); + + // interlink always produced if cascades generated + products.cascdataLink(products.cascdata.lastIndex()); + interlinks.cascCoreToCascades.push_back(cascade.globalId); + interlinks.cascadeToCascCores.push_back(products.cascdata.lastIndex()); + } + + if (baseOpts.mEnabledTables[kCascTrackXs]) { + products.cascTrackXs(straHelper.cascade.positiveTrackX, straHelper.cascade.negativeTrackX, straHelper.cascade.bachelorTrackX); + histos.fill(HIST("hTableBuildingStatistics"), kCascTrackXs); + } + if (baseOpts.mEnabledTables[kCascBBs]) { + products.cascbb(straHelper.cascade.bachBaryonCosPA, straHelper.cascade.bachBaryonDCAxyToPV); + histos.fill(HIST("hTableBuildingStatistics"), kCascBBs); + } + if (baseOpts.mEnabledTables[kCascCovs]) { + products.casccovs(straHelper.cascade.covariance); + histos.fill(HIST("hTableBuildingStatistics"), kCascCovs); + } + + //_________________________________________________________ + // MC handling part + if constexpr (soa::is_table) { + // only worry about this if someone else worried about this + if ((baseOpts.mEnabledTables[kCascMCCores] || baseOpts.mEnabledTables[kMcCascLabels] || baseOpts.mEnabledTables[kCascMCCollRefs])) { + extractMonteCarloProperties(posTrack, negTrack, bachTrack, mcParticles); + + // Construct label table (note: this will be joinable with CascDatas) + if (baseOpts.mEnabledTables[kMcCascLabels]) { + products.casclabels( + thisCascInfo.label, thisCascInfo.motherLabel); + histos.fill(HIST("hTableBuildingStatistics"), kMcCascLabels); + } + + // Construct found tag + if (baseOpts.mEnabledTables[kCascFoundTags]) { + products.cascFoundTag(cascade.found); + histos.fill(HIST("hTableBuildingStatistics"), kCascFoundTags); + } + + // Mark mcParticle as recoed (no searching necessary afterwards) + if (thisCascInfo.label > -1) { + mcParticleIsReco[thisCascInfo.label] = true; + } + + if (cascadeBuilderOpts.mc_populateCascMCCoresSymmetric) { + if (baseOpts.mEnabledTables[kCascMCCores]) { + products.cascmccores( + thisCascInfo.pdgCode, thisCascInfo.pdgCodeMother, thisCascInfo.pdgCodeV0, thisCascInfo.isPhysicalPrimary, + thisCascInfo.pdgCodePositive, thisCascInfo.pdgCodeNegative, thisCascInfo.pdgCodeBachelor, + thisCascInfo.xyz[0], thisCascInfo.xyz[1], thisCascInfo.xyz[2], + thisCascInfo.lxyz[0], thisCascInfo.lxyz[1], thisCascInfo.lxyz[2], + thisCascInfo.posP[0], thisCascInfo.posP[1], thisCascInfo.posP[2], + thisCascInfo.negP[0], thisCascInfo.negP[1], thisCascInfo.negP[2], + thisCascInfo.bachP[0], thisCascInfo.bachP[1], thisCascInfo.bachP[2], + thisCascInfo.momentum[0], thisCascInfo.momentum[1], thisCascInfo.momentum[2]); + histos.fill(HIST("hTableBuildingStatistics"), kCascMCCores); + } + if (baseOpts.mEnabledTables[kCascMCCollRefs]) { + products.cascmccollrefs(thisCascInfo.mcCollision); + histos.fill(HIST("hTableBuildingStatistics"), kCascMCCollRefs); + } + } + + if (cascadeBuilderOpts.mc_populateCascMCCoresAsymmetric) { + int thisCascMCCoreIndex = -1; + // step 1: check if this element is already provided in the table + // using the packedIndices variable calculated above + for (uint32_t ii = 0; ii < mcCascinfos.size(); ii++) { + if (thisCascInfo.label == mcCascinfos[ii].label && mcCascinfos[ii].label > -1) { + thisCascMCCoreIndex = ii; + break; // this exists already in list + } + } + if (thisCascMCCoreIndex < 0) { + // this CascMCCore does not exist yet. Create it and reference it + thisCascMCCoreIndex = mcCascinfos.size(); + mcCascinfos.push_back(thisCascInfo); + } + if (baseOpts.mEnabledTables[kCascCoreMCLabels]) { + products.cascCoreMClabels(thisCascMCCoreIndex); // interlink: reconstructed -> MC index + histos.fill(HIST("hTableBuildingStatistics"), kCascCoreMCLabels); + } + } + + } // enabled tables check + + // if BB tags requested, generate them now + if (baseOpts.mEnabledTables[kMcCascBBTags]) { + bool bbTag = false; + if (bachTrack.has_mcParticle()) { + auto bachelorParticle = bachTrack.template mcParticle_as(); + if (bachelorParticle.pdgCode() == 211) { // pi+, look for antiproton in negative prong + if (negTrack.has_mcParticle()) { + auto baryonParticle = negTrack.template mcParticle_as(); + if (baryonParticle.has_mothers() && bachelorParticle.has_mothers() && baryonParticle.pdgCode() == -2212) { + for (const auto& baryonMother : baryonParticle.template mothers_as()) { + for (const auto& pionMother : bachelorParticle.template mothers_as()) { + if (baryonMother.globalIndex() == pionMother.globalIndex() && baryonMother.pdgCode() == -3122) { + bbTag = true; + } + } + } + } + } + } // end if-pion + if (bachelorParticle.pdgCode() == -211) { // pi-, look for proton in positive prong + if (posTrack.has_mcParticle()) { + auto baryonParticle = posTrack.template mcParticle_as(); + if (baryonParticle.has_mothers() && bachelorParticle.has_mothers() && baryonParticle.pdgCode() == 2212) { + for (const auto& baryonMother : baryonParticle.template mothers_as()) { + for (const auto& pionMother : bachelorParticle.template mothers_as()) { + if (baryonMother.globalIndex() == pionMother.globalIndex() && baryonMother.pdgCode() == 3122) { + bbTag = true; + } + } + } + } + } + } // end if-pion + } // end bachelor has mcparticle + // Construct label table (note: this will be joinable with CascDatas) + products.bbtags(bbTag); + histos.fill(HIST("hTableBuildingStatistics"), kMcCascBBTags); + } // end BB tag table enabled check + + } // constexpr requires mcParticles check + } // cascades loop + + //_________________________________________________________ + // MC handling part + if constexpr (soa::is_table) { + if ((baseOpts.mEnabledTables[kCascMCCores] || baseOpts.mEnabledTables[kMcCascLabels] || baseOpts.mEnabledTables[kCascMCCollRefs])) { + // now populate V0MCCores if in asymmetric mode + if (cascadeBuilderOpts.mc_populateCascMCCoresAsymmetric) { + // first step: add any un-recoed v0mmcores that were requested + for (const auto& mcParticle : mcParticles) { + thisCascInfo.pdgCode = -1, thisCascInfo.pdgCodeMother = -1; + thisCascInfo.pdgCodePositive = -1, thisCascInfo.pdgCodeNegative = -1; + thisCascInfo.pdgCodeBachelor = -1, thisCascInfo.pdgCodeV0 = -1; + thisCascInfo.isPhysicalPrimary = false; + thisCascInfo.xyz[0] = 0.0f, thisCascInfo.xyz[1] = 0.0f, thisCascInfo.xyz[2] = 0.0f; + thisCascInfo.lxyz[0] = 0.0f, thisCascInfo.lxyz[1] = 0.0f, thisCascInfo.lxyz[2] = 0.0f; + thisCascInfo.posP[0] = 0.0f, thisCascInfo.posP[1] = 0.0f, thisCascInfo.posP[2] = 0.0f; + thisCascInfo.negP[0] = 0.0f, thisCascInfo.negP[1] = 0.0f, thisCascInfo.negP[2] = 0.0f; + thisCascInfo.bachP[0] = 0.0f, thisCascInfo.bachP[1] = 0.0f, thisCascInfo.bachP[2] = 0.0f; + thisCascInfo.momentum[0] = 0.0f, thisCascInfo.momentum[1] = 0.0f, thisCascInfo.momentum[2] = 0.0f; + thisCascInfo.label = -1, thisCascInfo.motherLabel = -1; + thisCascInfo.mcParticlePositive = -1; + thisCascInfo.mcParticleNegative = -1; + thisCascInfo.mcParticleBachelor = -1; + + if (mcParticleIsReco[mcParticle.globalIndex()] == true) + continue; // skip if already created in list + + if (std::fabs(mcParticle.y()) > cascadeBuilderOpts.mc_rapidityWindow) + continue; // skip outside midrapidity + + if (cascadeBuilderOpts.mc_keepOnlyPhysicalPrimary && !mcParticle.isPhysicalPrimary()) + continue; // skip secondary MC cascades + + if ( + (cascadeBuilderOpts.mc_addGeneratedXiMinus && mcParticle.pdgCode() == 3312) || + (cascadeBuilderOpts.mc_addGeneratedXiPlus && mcParticle.pdgCode() == -3312) || + (cascadeBuilderOpts.mc_addGeneratedOmegaMinus && mcParticle.pdgCode() == 3334) || + (cascadeBuilderOpts.mc_addGeneratedOmegaPlus && mcParticle.pdgCode() == -3334)) { + thisCascInfo.pdgCode = mcParticle.pdgCode(); + thisCascInfo.isPhysicalPrimary = mcParticle.isPhysicalPrimary(); + + if (mcParticle.has_mcCollision()) { + thisCascInfo.mcCollision = mcParticle.mcCollisionId(); // save this reference, please + } + thisCascInfo.momentum[0] = mcParticle.px(); + thisCascInfo.momentum[1] = mcParticle.py(); + thisCascInfo.momentum[2] = mcParticle.pz(); + thisCascInfo.label = mcParticle.globalIndex(); + + if (mcParticle.has_daughters()) { + auto const& daughters = mcParticle.template daughters_as(); + for (const auto& dau : daughters) { + if (dau.getProcess() != 4) // check whether the daughter comes from a decay + continue; + + if (std::abs(dau.pdgCode()) == 211 || std::abs(dau.pdgCode()) == 321) { + thisCascInfo.pdgCodeBachelor = dau.pdgCode(); + thisCascInfo.bachP[0] = dau.px(); + thisCascInfo.bachP[1] = dau.py(); + thisCascInfo.bachP[2] = dau.pz(); + thisCascInfo.xyz[0] = dau.vx(); + thisCascInfo.xyz[1] = dau.vy(); + thisCascInfo.xyz[2] = dau.vz(); + thisCascInfo.mcParticleBachelor = dau.globalIndex(); + } + if (std::abs(dau.pdgCode()) == 2212) { + thisCascInfo.pdgCodeV0 = dau.pdgCode(); + + for (const auto& v0Dau : dau.template daughters_as()) { + if (v0Dau.getProcess() != 4) + continue; + + if (v0Dau.pdgCode() > 0) { + thisCascInfo.pdgCodePositive = v0Dau.pdgCode(); + thisCascInfo.processPositive = v0Dau.getProcess(); + thisCascInfo.posP[0] = v0Dau.px(); + thisCascInfo.posP[1] = v0Dau.py(); + thisCascInfo.posP[2] = v0Dau.pz(); + thisCascInfo.lxyz[0] = v0Dau.vx(); + thisCascInfo.lxyz[1] = v0Dau.vy(); + thisCascInfo.lxyz[2] = v0Dau.vz(); + thisCascInfo.mcParticlePositive = v0Dau.globalIndex(); + } + if (v0Dau.pdgCode() < 0) { + thisCascInfo.pdgCodeNegative = v0Dau.pdgCode(); + thisCascInfo.processNegative = v0Dau.getProcess(); + thisCascInfo.negP[0] = v0Dau.px(); + thisCascInfo.negP[1] = v0Dau.py(); + thisCascInfo.negP[2] = v0Dau.pz(); + thisCascInfo.mcParticleNegative = v0Dau.globalIndex(); + } + } + } + } + } + + // if I got here, it means this MC particle was not recoed and is of interest. Add it please + mcCascinfos.push_back(thisCascInfo); + } + } + + for (const auto& thisInfoToFill : mcCascinfos) { + if (baseOpts.mEnabledTables[kCascMCCores]) { + products.cascmccores( // a lot of the info below will be compressed in case of not-recoed MC (good!) + thisInfoToFill.pdgCode, thisInfoToFill.pdgCodeMother, thisInfoToFill.pdgCodeV0, thisInfoToFill.isPhysicalPrimary, + thisInfoToFill.pdgCodePositive, thisInfoToFill.pdgCodeNegative, thisInfoToFill.pdgCodeBachelor, + thisInfoToFill.xyz[0], thisInfoToFill.xyz[1], thisInfoToFill.xyz[2], + thisInfoToFill.lxyz[0], thisInfoToFill.lxyz[1], thisInfoToFill.lxyz[2], + thisInfoToFill.posP[0], thisInfoToFill.posP[1], thisInfoToFill.posP[2], + thisInfoToFill.negP[0], thisInfoToFill.negP[1], thisInfoToFill.negP[2], + thisInfoToFill.bachP[0], thisInfoToFill.bachP[1], thisInfoToFill.bachP[2], + thisInfoToFill.momentum[0], thisInfoToFill.momentum[1], thisInfoToFill.momentum[2]); + histos.fill(HIST("hTableBuildingStatistics"), kCascMCCores); + } + if (baseOpts.mEnabledTables[kCascMCCollRefs]) { + products.cascmccollrefs(thisInfoToFill.mcCollision); + histos.fill(HIST("hTableBuildingStatistics"), kCascMCCollRefs); + } + } + } + } // enabled tables check + } // constexpr requires mcParticles check + + LOGF(debug, "Cascades in DF: %i, cascades built: %i", cascades.size(), nCascades); + } + + //__________________________________________________ + template + void buildKFCascades(THistoRegistry& histos, TCollisions const& collisions, TCascades const& cascades, TTracks const& tracks, TMCParticles const& mcParticles, TProducts& products) + { + if (!baseOpts.mEnabledTables[kStoredKFCascCores]) { + return; // don't do if no request for cascades in place + } + int nCascades = 0; + // Loops over all cascades in the time frame + histos.fill(HIST("hInputStatistics"), kStoredKFCascCores, cascades.size()); + for (size_t icascade = 0; icascade < cascades.size(); icascade++) { + // Get tracks and generate candidate + auto const& cascade = cascades[sorted_cascade[icascade]]; + // if collisionId positive: get vertex, negative: origin + // could be replaced by mean vertex (but without much benefit...) + float pvX = 0.0f, pvY = 0.0f, pvZ = 0.0f; + if (cascade.collisionId >= 0) { + auto const& collision = collisions.rawIteratorAt(cascade.collisionId); + pvX = collision.posX(); + pvY = collision.posY(); + pvZ = collision.posZ(); + } + auto const& posTrack = tracks.rawIteratorAt(cascade.posTrackId); + auto const& negTrack = tracks.rawIteratorAt(cascade.negTrackId); + auto const& bachTrack = tracks.rawIteratorAt(cascade.bachTrackId); + if (!straHelper.buildCascadeCandidateWithKF(cascade.collisionId, pvX, pvY, pvZ, + posTrack, + negTrack, + bachTrack, + baseOpts.mEnabledTables[kCascBBs], + cascadeBuilderOpts.kfConstructMethod, + cascadeBuilderOpts.kfTuneForOmega, + cascadeBuilderOpts.kfUseV0MassConstraint, + cascadeBuilderOpts.kfUseCascadeMassConstraint, + cascadeBuilderOpts.kfDoDCAFitterPreMinimV0, + cascadeBuilderOpts.kfDoDCAFitterPreMinimCasc)) { + products.kfcascdataLink(-1); + interlinks.cascadeToKFCascCores.push_back(-1); + continue; // didn't work out, skip + } + nCascades++; + + // generate analysis tables as required + if (baseOpts.mEnabledTables[kKFCascIndices]) { + products.kfcascidx(cascade.globalId, + straHelper.cascade.positiveTrack, straHelper.cascade.negativeTrack, + straHelper.cascade.bachelorTrack, straHelper.cascade.collisionId); + histos.fill(HIST("hTableBuildingStatistics"), kKFCascIndices); + } + if (baseOpts.mEnabledTables[kStoredKFCascCores]) { + products.kfcascdata(straHelper.cascade.charge, straHelper.cascade.massXi, straHelper.cascade.massOmega, + straHelper.cascade.cascadePosition[0], straHelper.cascade.cascadePosition[1], straHelper.cascade.cascadePosition[2], + straHelper.cascade.v0Position[0], straHelper.cascade.v0Position[1], straHelper.cascade.v0Position[2], + straHelper.cascade.positivePosition[0], straHelper.cascade.positivePosition[1], straHelper.cascade.positivePosition[2], + straHelper.cascade.negativePosition[0], straHelper.cascade.negativePosition[1], straHelper.cascade.negativePosition[2], + straHelper.cascade.positiveMomentum[0], straHelper.cascade.positiveMomentum[1], straHelper.cascade.positiveMomentum[2], + straHelper.cascade.negativeMomentum[0], straHelper.cascade.negativeMomentum[1], straHelper.cascade.negativeMomentum[2], + straHelper.cascade.bachelorMomentum[0], straHelper.cascade.bachelorMomentum[1], straHelper.cascade.bachelorMomentum[2], + straHelper.cascade.v0Momentum[0], straHelper.cascade.v0Momentum[1], straHelper.cascade.v0Momentum[2], + straHelper.cascade.cascadeMomentum[0], straHelper.cascade.cascadeMomentum[1], straHelper.cascade.cascadeMomentum[2], + straHelper.cascade.v0DaughterDCA, straHelper.cascade.cascadeDaughterDCA, + straHelper.cascade.positiveDCAxy, straHelper.cascade.negativeDCAxy, + straHelper.cascade.bachelorDCAxy, straHelper.cascade.cascadeDCAxy, straHelper.cascade.cascadeDCAz, + straHelper.cascade.kfMLambda, straHelper.cascade.kfV0Chi2, straHelper.cascade.kfCascadeChi2); + histos.fill(HIST("hTableBuildingStatistics"), kStoredKFCascCores); + + // interlink always produced if cascades generated + products.kfcascdataLink(products.kfcascdata.lastIndex()); + interlinks.kfCascCoreToCascades.push_back(cascade.globalId); + interlinks.cascadeToKFCascCores.push_back(products.kfcascdata.lastIndex()); + } + if (baseOpts.mEnabledTables[kKFCascCovs]) { + products.kfcasccovs(straHelper.cascade.covariance, straHelper.cascade.kfTrackCovarianceV0, straHelper.cascade.kfTrackCovariancePos, straHelper.cascade.kfTrackCovarianceNeg); + histos.fill(HIST("hTableBuildingStatistics"), kKFCascCovs); + } + + //_________________________________________________________ + // MC handling part (labels only) + if constexpr (soa::is_table) { + // only worry about this if someone else worried about this + if ((baseOpts.mEnabledTables[kMcKFCascLabels])) { + extractMonteCarloProperties(posTrack, negTrack, bachTrack, mcParticles); + + // Construct label table (note: this will be joinable with KFCascDatas) + products.kfcasclabels(thisCascInfo.label); + histos.fill(HIST("hTableBuildingStatistics"), kMcKFCascLabels); + } // enabled tables check + } // constexpr requires mcParticles check + } // end loop over cascades + + LOGF(debug, "KF Cascades in DF: %i, KF cascades built: %i", cascades.size(), nCascades); + } + + //__________________________________________________ + template + void buildTrackedCascades(THistoRegistry& histos, TCollisions const& collisions, TStrangeTracks const& cascadeTracks, TMCParticles const& mcParticles, TProducts& products) + { + if (!baseOpts.mEnabledTables[kStoredTraCascCores] || baseOpts.mc_findableMode.value != 0) { + return; // don't do if no request for cascades in place or findable mode used + } + int nCascades = 0; + // Loops over all V0s in the time frame + histos.fill(HIST("hInputStatistics"), kStoredTraCascCores, cascadeTracks.size()); + for (const auto& cascadeTrack : cascadeTracks) { + // Get tracks and generate candidate + if (!cascadeTrack.has_track()) + continue; // safety (should be fine but depends on future stratrack dev) + + auto const& strangeTrack = cascadeTrack.template track_as(); + + // if collisionId positive: get vertex, negative: origin + // could be replaced by mean vertex (but without much benefit...) + float pvX = 0.0f, pvY = 0.0f, pvZ = 0.0f; + if (strangeTrack.has_collision()) { + auto const& collision = collisions.rawIteratorAt(strangeTrack.collisionId()); + pvX = collision.posX(); + pvY = collision.posY(); + pvZ = collision.posZ(); + } + auto const& cascade = cascadeTrack.cascade(); + auto const& v0 = cascade.v0(); + auto const& posTrack = v0.template posTrack_as(); + auto const& negTrack = v0.template negTrack_as(); + auto const& bachTrack = cascade.template bachelor_as(); + if (!straHelper.buildCascadeCandidate(strangeTrack.collisionId(), pvX, pvY, pvZ, + posTrack, + negTrack, + bachTrack, + baseOpts.mEnabledTables[kCascBBs], + cascadeBuilderOpts.useCascadeMomentumAtPrimVtx, + baseOpts.mEnabledTables[kCascCovs])) { + products.tracascdataLink(-1); + interlinks.cascadeToTraCascCores.push_back(-1); + continue; // didn't work out, skip + } + + // recalculate DCAxy, DCAz with strange track + auto strangeTrackParCov = getTrackParCov(strangeTrack); + std::array dcaInfo; + strangeTrackParCov.setPID(o2::track::PID::XiMinus); // FIXME: not OK for omegas + o2::base::Propagator::Instance()->propagateToDCABxByBz({pvX, pvY, pvZ}, strangeTrackParCov, 2.f, straHelper.fitter.getMatCorrType(), &dcaInfo); + straHelper.cascade.cascadeDCAxy = dcaInfo[0]; + straHelper.cascade.cascadeDCAz = dcaInfo[1]; + + // get momentum from strange track (should not be very different) + strangeTrackParCov.getPxPyPzGlo(straHelper.cascade.cascadeMomentum); + + // accounting + nCascades++; + + // generate analysis tables as required + if (baseOpts.mEnabledTables[kTraCascIndices]) { + products.tracascidx(cascade.globalIndex(), + straHelper.cascade.positiveTrack, straHelper.cascade.negativeTrack, + straHelper.cascade.bachelorTrack, cascadeTrack.trackId(), straHelper.cascade.collisionId); + histos.fill(HIST("hTableBuildingStatistics"), kTraCascIndices); + } + if (baseOpts.mEnabledTables[kStoredTraCascCores]) { + products.tracascdata(straHelper.cascade.charge, cascadeTrack.xiMass(), cascadeTrack.omegaMass(), + cascadeTrack.decayX(), cascadeTrack.decayY(), cascadeTrack.decayZ(), + straHelper.cascade.v0Position[0], straHelper.cascade.v0Position[1], straHelper.cascade.v0Position[2], + straHelper.cascade.positiveMomentum[0], straHelper.cascade.positiveMomentum[1], straHelper.cascade.positiveMomentum[2], + straHelper.cascade.negativeMomentum[0], straHelper.cascade.negativeMomentum[1], straHelper.cascade.negativeMomentum[2], + straHelper.cascade.bachelorMomentum[0], straHelper.cascade.bachelorMomentum[1], straHelper.cascade.bachelorMomentum[2], + straHelper.cascade.cascadeMomentum[0], straHelper.cascade.cascadeMomentum[1], straHelper.cascade.cascadeMomentum[2], + straHelper.cascade.v0DaughterDCA, straHelper.cascade.cascadeDaughterDCA, + straHelper.cascade.positiveDCAxy, straHelper.cascade.negativeDCAxy, + straHelper.cascade.bachelorDCAxy, straHelper.cascade.cascadeDCAxy, straHelper.cascade.cascadeDCAz, + cascadeTrack.matchingChi2(), cascadeTrack.topologyChi2(), cascadeTrack.itsClsSize()); + histos.fill(HIST("hTableBuildingStatistics"), kStoredTraCascCores); + + // interlink always produced if base core table generated + products.tracascdataLink(products.tracascdata.lastIndex()); + interlinks.traCascCoreToCascades.push_back(cascade.globalIndex()); + interlinks.cascadeToTraCascCores.push_back(products.tracascdata.lastIndex()); + } + if (baseOpts.mEnabledTables[kCascCovs]) { + std::array traCovMat = {0.}; + strangeTrackParCov.getCovXYZPxPyPzGlo(traCovMat); + float traCovMatArray[21]; + for (int ii = 0; ii < 21; ii++) { + traCovMatArray[ii] = traCovMat[ii]; + } + products.tracasccovs(traCovMatArray); + histos.fill(HIST("hTableBuildingStatistics"), kCascCovs); + } + + //_________________________________________________________ + // MC handling part (labels only) + if constexpr (soa::is_table) { + // only worry about this if someone else worried about this + if ((baseOpts.mEnabledTables[kMcTraCascLabels])) { + extractMonteCarloProperties(posTrack, negTrack, bachTrack, mcParticles); + + // Construct label table (note: this will be joinable with KFCascDatas) + products.tracasclabels(thisCascInfo.label); + histos.fill(HIST("hTableBuildingStatistics"), kMcTraCascLabels); + } // enabled tables check + } // constexpr requires mcParticles check + } // end loop over cascades + LOGF(debug, "Tracked cascades in DF: %i, tracked cascades built: %i", cascadeTracks.size(), nCascades); + } + + //__________________________________________________ + // MC kink handling + template + int getOriginatingParticle(mcpart const& part, int& indexForPositionOfDecay, bool treatPiToMuDecays) + { + int returnValue = -1; + if (part.has_mothers()) { + auto const& motherList = part.template mothers_as(); + if (motherList.size() == 1) { + for (const auto& mother : motherList) { + if (std::abs(part.pdgCode()) == 13 && treatPiToMuDecays) { + // muon decay, de-ref mother twice + if (mother.has_mothers()) { + auto grandMotherList = mother.template mothers_as(); + if (grandMotherList.size() == 1) { + for (const auto& grandMother : grandMotherList) { + returnValue = grandMother.globalIndex(); + indexForPositionOfDecay = mother.globalIndex(); // for V0 decay position: grab muon + } + } + } + } else { + returnValue = mother.globalIndex(); + indexForPositionOfDecay = part.globalIndex(); + } + } + } + } + return returnValue; + } + + //__________________________________________________ + template + void dataProcess(TCCDB& ccdb, THistoRegistry& histos, TCollisions const& collisions, TMCCollisions const& mccollisions, TV0s const& v0s, TCascades const& cascades, TTrackedCascades const& trackedCascades, TTracks const& tracks, TBCs const& bcs, TMCParticles const& mcParticles, TProducts& products) + { + if (nEnabledTables == 0) { + return; // fully suppressed + } + + if (!initCCDB(ccdb, bcs, collisions)) + return; + + // reset vectors for cascade interlinks + resetInterlinks(); + + // prepare v0List, cascadeList + prepareBuildingLists(histos, collisions, mccollisions, v0s, cascades, tracks, mcParticles); + + // mark V0s that will be buffered for the cascade building + markV0sUsedInCascades(v0List, cascadeList, trackedCascades); + + // build V0s + buildV0s(histos, collisions, v0List, tracks, mcParticles, products); + + // build cascades + buildCascades(histos, collisions, cascadeList, tracks, mcParticles, products); + buildKFCascades(histos, collisions, cascadeList, tracks, mcParticles, products); + + // build tracked cascades only if subscription is Run 3 like (doesn't exist in Run 2) + if constexpr (soa::is_table) { + buildTrackedCascades(histos, collisions, trackedCascades, mcParticles, products); + } + + populateCascadeInterlinks(); + } +}; // end BuilderModule + +} // namespace strangenessbuilder +} // namespace pwglf +} // namespace o2 + +#endif // PWGLF_UTILS_STRANGENESSBUILDERMODULE_H_ diff --git a/PWGLF/Utils/svPoolCreator.h b/PWGLF/Utils/svPoolCreator.h index 25da298fe34..c0b32c2574e 100644 --- a/PWGLF/Utils/svPoolCreator.h +++ b/PWGLF/Utils/svPoolCreator.h @@ -129,6 +129,10 @@ class svPoolCreator } firstBC++; } + if (firstCollIdx == -1) { + return; + } + // now loop over all the collisions to make the pool for (int i = firstCollIdx; i < collisions.size(); i++) { const auto& collision = collisions.rawIteratorAt(i); diff --git a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx index 2ae0df0c707..7a8c4cfb23e 100644 --- a/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx +++ b/PWGMM/Mult/Tasks/dndetaMFTPbPb.cxx @@ -15,15 +15,19 @@ /// \author Gyula Bencedi, gyula.bencedi@cern.ch /// \since Nov 2024 -#include -#include -#include -#include -#include -#include +#include "Functions.h" +#include "Index.h" +#include "bestCollisionTable.h" -#include "CCDB/BasicCCDBManager.h" +#include "Common/CCDB/ctpRateFetcher.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" @@ -31,22 +35,18 @@ #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/RuntimeError.h" #include "Framework/runDataProcessing.h" - -#include "Common/CCDB/ctpRateFetcher.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 "MathUtils/Utils.h" #include "ReconstructionDataFormats/GlobalTrackID.h" + #include "TPDGCode.h" -#include "Functions.h" -#include "Index.h" -#include "bestCollisionTable.h" +#include +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -57,6 +57,8 @@ using namespace o2::constants::physics; using namespace o2::constants::math; using namespace pwgmm::mult; +auto static constexpr kMinCharge = 3.f; + AxisSpec ptAxis = {1001, -0.005, 10.005}; AxisSpec multAxis = {701, -0.5, 700.5, "N_{trk}"}; AxisSpec zAxis = {60, -30., 30.}; @@ -65,6 +67,18 @@ AxisSpec dcaxyAxis = {500, -1, 50}; AxisSpec phiAxis = {629, 0, TwoPI, "Rad", "#phi"}; AxisSpec etaAxis = {20, -4., -2.}; AxisSpec centAxis{100, 0, 100, "centrality"}; +AxisSpec chiSqAxis = {100, 0., 1000.}; +AxisSpec nclsAxis{10, 0.5, 10.5, "# clusters"}; + +enum TrkSel { + trkSelNCls, + trkSelChi2Ncl, + trkSelEta, + trkSelPhiCut, + trkSelPt, + trkSelCA, + nTrkSel +}; struct DndetaMFTPbPb { SliceCache cache; @@ -83,77 +97,63 @@ 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", "T0VTX", "Estimator of the interaction rate (Pb-Pb: ZNC hadronic)"}; + struct : ConfigurableGroup { Configurable usephiCut{"usephiCut", false, "use azimuthal angle cut"}; - Configurable phiCut{"phiCut", 0.1f, - "Cut on azimuthal angle of MFT tracks"}; + Configurable phiCut{"phiCut", 0.1f, "Cut on azimuthal angle of MFT tracks"}; Configurable minPhi{"minPhi", 0.f, ""}; Configurable maxPhi{"maxPhi", 6.2832, ""}; Configurable minEta{"minEta", -3.6f, ""}; Configurable maxEta{"maxEta", -2.5f, ""}; - Configurable minNclusterMft{"minNclusterMft", 5, - "minimum number of MFT clusters"}; - Configurable maxChi2{"maxChi2", 10.f, ""}; + Configurable minNclusterMft{"minNclusterMft", 5, "minimum number of MFT clusters"}; + Configurable useChi2Cut{"useChi2Cut", false, "use track chi2 cut"}; + Configurable maxChi2NCl{"maxChi2NCl", 1000.f, "maximum chi2 per MFT clusters"}; + Configurable usePtCut{"usePtCut", false, "use track pT cut"}; Configurable minPt{"minPt", 0., "minimum pT of the MFT tracks"}; - Configurable requireCA{ - "requireCA", false, "Use Cellular Automaton track-finding algorithm"}; + Configurable requireCA{"requireCA", false, "Use Cellular Automaton track-finding algorithm"}; Configurable maxDCAxy{"maxDCAxy", 2.0f, "Cut on dcaXY"}; } trackCuts; struct : ConfigurableGroup { - Configurable maxZvtx{"maxZvtx", 10.0f, "Cut on z-vtx"}; - 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 requireNoCollInTimeRangeStrict{"requireNoCollInTimeRangeStrict", true, " requireNoCollInTimeRangeStrict"}; - Configurable requireNoCollInRofStrict{"requireNoCollInRofStrict", true, "requireNoCollInRofStrict"}; + Configurable maxZvtx{"maxZvtx", 10.0f, "maximum cut on z-vtx (cm)"}; + Configurable minZvtx{"minZvtx", -10.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 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", false, " requireNoCollInTimeRangeStrict"}; + Configurable requireNoCollInRofStrict{"requireNoCollInRofStrict", false, "requireNoCollInRofStrict"}; Configurable requireNoCollInRofStandard{"requireNoCollInRofStandard", false, "requireNoCollInRofStandard"}; - Configurable requireNoHighMultCollInPrevRof{"requireNoHighMultCollInPrevRof", true, "requireNoHighMultCollInPrevRof"}; - 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"}; - Configurable maxOccupancy{ - "maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; + Configurable requireNoHighMultCollInPrevRof{"requireNoHighMultCollInPrevRof", false, "requireNoHighMultCollInPrevRof"}; + 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 occupancyEstimator{"occupancyEstimator", 1, "Occupancy estimator: 1 = trackOccupancyInTimeRange, 2 = ft0cOccupancyInTimeRange"}; + Configurable minOccupancy{"minOccupancy", -1, "minimum occupancy from neighbouring collisions"}; + Configurable maxOccupancy{"maxOccupancy", -1, "maximum occupancy from neighbouring collisions"}; Configurable minIR{"minIR", -1, "minimum IR (kHz) collisions"}; Configurable maxIR{"maxIR", -1, "maximum IR (kHz) collisions"}; } eventCuts; - ConfigurableAxis occupancyBins{"occupancyBins", - {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"}; - ConfigurableAxis centralityBins{ - "centralityBins", - {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, - "Centrality"}; + ConfigurableAxis occupancyBins{"occupancyBins", {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"}; + ConfigurableAxis centralityBins{"centralityBins", {VARIABLE_WIDTH, 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, "Centrality"}; ConfigurableAxis irBins{"irBins", {500, 0, 50}, "Interaction rate (kHz)"}; Service pdg; 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 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"}; + + int mRunNumber{-1}; + uint64_t mSOR{0}; + double mMinSeconds{-1.}; + std::unordered_map gHadronicRate; ctpRateFetcher rateFetcher; + TH2* gCurrentHadronicRate; /// @brief init function, definition of histograms void init(InitContext&) @@ -219,8 +219,8 @@ struct DndetaMFTPbPb { "be enabled!"); } - auto hev = registry.add("hEvtSel", "hEvtSel", HistType::kTH1F, - {{16, -0.5f, +15.5f}}); + auto hev = registry.add("Events/hEvtSel", "hEvtSel", HistType::kTH1F, + {{14, -0.5f, +13.5f}}); hev->GetXaxis()->SetBinLabel(1, "All collisions"); hev->GetXaxis()->SetBinLabel(2, "Ev. sel."); hev->GetXaxis()->SetBinLabel(3, "kIsGoodZvtxFT0vsPV"); @@ -234,8 +234,14 @@ struct DndetaMFTPbPb { hev->GetXaxis()->SetBinLabel(11, "kNoHighMultCollInPrevRof"); hev->GetXaxis()->SetBinLabel(12, "Below min occup."); hev->GetXaxis()->SetBinLabel(13, "Above max occup."); - hev->GetXaxis()->SetBinLabel(14, "Below min IR (kHz)"); - hev->GetXaxis()->SetBinLabel(15, "Above max IR (kHz)"); + + registry.add("Tracks/hTrkSel", "Number of tracks; Cut; #Tracks Passed Cut", {HistType::kTH1D, {{nTrkSel, 0, nTrkSel}}}); + registry.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelNCls + 1, "Ncl cut"); + registry.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelChi2Ncl + 1, "#chi^{2}/Ncl cut"); + registry.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelEta + 1, "#eta cut"); + registry.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelPhiCut + 1, "#varphi cut"); + registry.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelPt + 1, "#it{p}_{T} cut"); + registry.get(HIST("Tracks/hTrkSel"))->GetXaxis()->SetBinLabel(trkSelCA + 1, "Tracking algorithm (CA)"); auto hBcSel = registry.add("hBcSel", "hBcSel", HistType::kTH1F, {{3, -0.5f, +2.5f}}); @@ -256,9 +262,6 @@ struct DndetaMFTPbPb { x->SetBinLabel(1, "All"); x->SetBinLabel(2, "Selected"); - qaregistry.add("hOccIRate", "hOccIRate", HistType::kTH2F, - {occupancyAxis, irBins}); - registry.add({"Events/NtrkZvtx", "; N_{trk}; Z_{vtx} (cm); occupancy", {HistType::kTHnSparseF, {multAxis, zAxis, occupancyAxis}}}); @@ -273,14 +276,14 @@ struct DndetaMFTPbPb { qaregistry.add( {"Tracks/Chi2Eta", "; #chi^{2}; #it{#eta}; occupancy", - {HistType::kTHnSparseF, {{600, 0, 20}, etaAxis, occupancyAxis}}}); + {HistType::kTHnSparseF, {chiSqAxis, etaAxis, occupancyAxis}}}); qaregistry.add({"Tracks/Chi2", "; #chi^{2};", - {HistType::kTH2F, {{600, 0, 20}, occupancyAxis}}}); + {HistType::kTH2F, {chiSqAxis, occupancyAxis}}}); qaregistry.add( {"Tracks/NclustersEta", "; nClusters; #eta; occupancy", - {HistType::kTHnSparseF, {{7, 4, 10}, etaAxis, occupancyAxis}}}); + {HistType::kTHnSparseF, {nclsAxis, etaAxis, occupancyAxis}}}); qaregistry.add({"Tracks/NchSel", "; N_{ch}; occupancy", {HistType::kTH2F, {multAxis, occupancyAxis}}}); @@ -301,7 +304,7 @@ struct DndetaMFTPbPb { qaregistry.add( {"Tracks/NclustersEtaBest", "; nClusters; #eta; occupancy", - {HistType::kTHnSparseF, {{7, 4, 10}, etaAxis, occupancyAxis}}}); + {HistType::kTHnSparseF, {nclsAxis, etaAxis, occupancyAxis}}}); qaregistry.add( {"Tracks/DCAXYPt", "; p_{T} (GeV/c) ; DCA_{XY} (cm); occupancy", @@ -342,9 +345,6 @@ struct DndetaMFTPbPb { hstat->GetAxis(0)->SetBinLabel(1, "All"); hstat->GetAxis(0)->SetBinLabel(2, "Selected"); - qaregistry.add("hCentOccIRate", "hCentOccIRate", HistType::kTHnSparseF, - {centralityAxis, occupancyAxis, irBins}); - qaregistry.add({"Events/Centrality/hCent", "; centrality; occupancy", {HistType::kTH2F, {centAxis, occupancyAxis}}, @@ -374,15 +374,15 @@ struct DndetaMFTPbPb { {"Tracks/Centrality/Chi2Eta", "; #chi^{2}; #it{#eta}; centrality; occupancy", {HistType::kTHnSparseF, - {{600, 0, 20}, etaAxis, centralityAxis, occupancyAxis}}}); + {chiSqAxis, etaAxis, centralityAxis, occupancyAxis}}}); qaregistry.add({"Tracks/Centrality/Chi2", "; #chi^{2}; centrality; occupancy", {HistType::kTHnSparseF, - {{600, 0, 20}, centralityAxis, occupancyAxis}}}); + {chiSqAxis, centralityAxis, occupancyAxis}}}); qaregistry.add({"Tracks/Centrality/NclustersEta", "; nClusters; #eta; centrality; occupancy", {HistType::kTHnSparseF, - {{7, 4, 10}, etaAxis, centralityAxis, occupancyAxis}}}); + {nclsAxis, etaAxis, centralityAxis, occupancyAxis}}}); if (doprocessDatawBestTracksCentFT0C || doprocessDatawBestTracksCentFT0CVariant1 || @@ -405,7 +405,7 @@ struct DndetaMFTPbPb { {"Tracks/Centrality/NclustersEtaBest", "; nClusters; #eta; centrality; occupancy", {HistType::kTHnSparseF, - {{7, 4, 10}, etaAxis, centralityAxis, occupancyAxis}}}); + {nclsAxis, etaAxis, centralityAxis, occupancyAxis}}}); qaregistry.add({"Tracks/Centrality/TrackAmbDegree", "; N_{coll}^{comp}; centrality; occupancy", {HistType::kTHnSparseF, @@ -734,41 +734,24 @@ struct DndetaMFTPbPb { using FiltBestTracks = soa::Filtered; using FiltParticles = soa::Filtered; - bool isIRSelected(CollBCs::iterator const& bc, bool fillHis = false) + template + bool isTrackSelected(const T& track) { - double ir = (eventCuts.minIR >= 0 || eventCuts.maxIR >= 0) - ? rateFetcher.fetch(ccdb.service, bc.timestamp(), - bc.runNumber(), "ZNC hadronic") * - 1.e-3 - : -1; - if (eventCuts.minIR >= 0 && ir < eventCuts.minIR) { + if (track.nClusters() < trackCuts.minNclusterMft) { return false; } - if (fillHis) { - registry.fill(HIST("hEvtSel"), 13); + registry.fill(HIST("Tracks/hTrkSel"), trkSelNCls); + if (trackCuts.useChi2Cut) { + float nclMft = std::max(2.0f * track.nClusters() - 5.0f, 1.0f); + float mftChi2NCl = track.chi2() / nclMft; + if (mftChi2NCl > trackCuts.maxChi2NCl) + return false; } - if (eventCuts.maxIR >= 0 && ir > eventCuts.maxIR) { + registry.fill(HIST("Tracks/hTrkSel"), trkSelChi2Ncl); + if (track.eta() < trackCuts.minEta || track.eta() > trackCuts.maxEta) { return false; } - if (fillHis) { - registry.fill(HIST("hEvtSel"), 14); - } - return true; - } - - template - bool isTrackSelected(const T& track) - { - if (track.eta() < trackCuts.minEta || track.eta() > trackCuts.maxEta) - return false; - if (track.chi2() > trackCuts.maxChi2) - return false; - if (trackCuts.requireCA && !track.isCA()) - return false; - if (track.nClusters() < trackCuts.minNclusterMft) - return false; - if (track.pt() < trackCuts.minPt) - return false; + registry.fill(HIST("Tracks/hTrkSel"), trkSelEta); if (trackCuts.usephiCut) { float phi = track.phi(); o2::math_utils::bringTo02Pi(phi); @@ -782,6 +765,15 @@ struct DndetaMFTPbPb { (phi < ((PIHalf - 0.1) * PI) + trackCuts.phiCut))) return false; } + registry.fill(HIST("Tracks/hTrkSel"), trkSelPhiCut); + if (trackCuts.usePtCut && track.pt() < trackCuts.minPt) { + return false; + } + registry.fill(HIST("Tracks/hTrkSel"), trkSelPt); + if (trackCuts.requireCA && !track.isCA()) { + return false; + } + registry.fill(HIST("Tracks/hTrkSel"), trkSelCA); return true; } @@ -927,73 +919,91 @@ struct DndetaMFTPbPb { return -1.f; } + void initHadronicRate(CollBCs::iterator const& bc) + { + if (mRunNumber == bc.runNumber()) { + return; + } + mRunNumber = bc.runNumber(); + if (gHadronicRate.find(mRunNumber) == gHadronicRate.end()) { + auto runDuration = ccdb->getRunDuration(mRunNumber); + mSOR = runDuration.first; + mMinSeconds = std::floor(mSOR * 1.e-3); /// round tsSOR to the highest integer lower than tsSOR + double maxSec = std::ceil(runDuration.second * 1.e-3); /// round tsEOR to the lowest integer higher than tsEOR + const AxisSpec axisSeconds{static_cast((maxSec - mMinSeconds) / 20.f), 0, maxSec - mMinSeconds, "Seconds since SOR"}; + int hadronicRateBins = static_cast(eventCuts.maxIR - eventCuts.minIR); + gHadronicRate[mRunNumber] = registry.add(Form("HadronicRate/%i", mRunNumber), ";Time since SOR (s);Hadronic rate (kHz)", kTH2D, {axisSeconds, {hadronicRateBins, eventCuts.minIR, eventCuts.maxIR}}).get(); + } + gCurrentHadronicRate = gHadronicRate[mRunNumber]; + } + template bool isGoodEvent(C const& collision) { if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 0); + registry.fill(HIST("Events/hEvtSel"), 0); } if (!collision.sel8()) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 1); + registry.fill(HIST("Events/hEvtSel"), 1); } - if (!collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { + if (eventCuts.requireIsGoodZvtxFT0VsPV && !collision.selection_bit(aod::evsel::kIsGoodZvtxFT0vsPV)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 2); + registry.fill(HIST("Events/hEvtSel"), 2); } - if (!collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { + if (eventCuts.requireRejectSameBunchPileup && !collision.selection_bit(aod::evsel::kNoSameBunchPileup)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 3); + registry.fill(HIST("Events/hEvtSel"), 3); } - if (std::abs(collision.posZ()) >= eventCuts.maxZvtx) { + if (collision.posZ() <= eventCuts.minZvtx || collision.posZ() >= eventCuts.maxZvtx) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 4); + registry.fill(HIST("Events/hEvtSel"), 4); } if (eventCuts.requireNoCollInTimeRangeStd && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 5); + registry.fill(HIST("Events/hEvtSel"), 5); } if (eventCuts.requireNoCollInTimeRangeNarrow && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeNarrow)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 6); + registry.fill(HIST("Events/hEvtSel"), 6); } if (eventCuts.requireNoCollInTimeRangeStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStrict)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 7); + registry.fill(HIST("Events/hEvtSel"), 7); } if (eventCuts.requireNoCollInRofStrict && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStrict)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 8); + registry.fill(HIST("Events/hEvtSel"), 8); } if (eventCuts.requireNoCollInRofStandard && !collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 9); + registry.fill(HIST("Events/hEvtSel"), 9); } if (eventCuts.requireNoHighMultCollInPrevRof && !collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof)) { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 10); + registry.fill(HIST("Events/hEvtSel"), 10); } if (eventCuts.minOccupancy >= 0 && getOccupancy(collision, eventCuts.occupancyEstimator) < @@ -1001,7 +1011,7 @@ struct DndetaMFTPbPb { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 11); + registry.fill(HIST("Events/hEvtSel"), 11); } if (eventCuts.maxOccupancy >= 0 && getOccupancy(collision, eventCuts.occupancyEstimator) > @@ -1009,7 +1019,7 @@ struct DndetaMFTPbPb { return false; } if constexpr (fillHis) { - registry.fill(HIST("hEvtSel"), 12); + registry.fill(HIST("Events/hEvtSel"), 12); } return true; } @@ -1023,7 +1033,7 @@ struct DndetaMFTPbPb { if (p != nullptr) { charge = p->Charge(); } - return std::abs(charge) >= 3.; + return std::abs(charge) >= kMinCharge; } template @@ -1109,10 +1119,6 @@ struct DndetaMFTPbPb { auto occ = getOccupancy(collision, eventCuts.occupancyEstimator); float c = getRecoCent(collision); auto bc = collision.template foundBC_as(); - double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), - "ZNC hadronic") * - 1.e-3; - if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/Selection"), 1., c, occ); } else { @@ -1122,8 +1128,15 @@ struct DndetaMFTPbPb { if (!isGoodEvent(collision)) { return; } - if (!isIRSelected(bc, true)) { - return; + + if (cfgDoIR) { + initHadronicRate(bc); + double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), cfgIRSource, cfgIRCrashOnNull) * 1.e-3; + double seconds = bc.timestamp() * 1.e-3 - mMinSeconds; + if (cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate + return; + } + gCurrentHadronicRate->Fill(seconds, ir); } auto z = collision.posZ(); @@ -1131,10 +1144,7 @@ struct DndetaMFTPbPb { registry.fill(HIST("Events/Centrality/Selection"), 2., c, occ); qaregistry.fill(HIST("Events/Centrality/hZvtxCent"), z, c, occ); qaregistry.fill(HIST("Events/Centrality/hCent"), c, occ); - qaregistry.fill(HIST("hCentOccIRate"), c, occ, ir); - } else { - qaregistry.fill(HIST("hOccIRate"), occ, ir); registry.fill(HIST("Events/Selection"), 2., occ); } @@ -1152,16 +1162,11 @@ struct DndetaMFTPbPb { template void processDatawBestTracks( typename C::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, - CollBCs const& /*bcs*/) + soa::SmallGroups const& besttracks, CollBCs const& /*bcs*/) { auto occ = getOccupancy(collision, eventCuts.occupancyEstimator); float c = getRecoCent(collision); auto bc = collision.template foundBC_as(); - double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), - "ZNC hadronic") * - 1.e-3; - if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/Selection"), 1., c, occ); } else { @@ -1171,17 +1176,22 @@ struct DndetaMFTPbPb { if (!isGoodEvent(collision)) { return; } - if (!isIRSelected(bc, true)) { - return; + + if (cfgDoIR) { + initHadronicRate(bc); + double ir = rateFetcher.fetch(ccdb.service, bc.timestamp(), bc.runNumber(), cfgIRSource, cfgIRCrashOnNull) * 1.e-3; + double seconds = bc.timestamp() * 1.e-3 - mMinSeconds; + if (cfgUseIRCut && (ir < eventCuts.minIR || ir > eventCuts.maxIR)) { // cut on hadronic rate + return; + } + gCurrentHadronicRate->Fill(seconds, ir); } auto z = collision.posZ(); if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/Selection"), 2., c, occ); - qaregistry.fill(HIST("hCentOccIRate"), c, occ, ir); } else { registry.fill(HIST("Events/Selection"), 2., occ); - qaregistry.fill(HIST("hOccIRate"), occ, ir); } auto nBestTrks = countBestTracks(tracks, besttracks, z, c, occ); @@ -1251,8 +1261,7 @@ struct DndetaMFTPbPb { void processDatawBestTracksInclusive( Colls::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, - CollBCs const& bcs) + soa::SmallGroups const& besttracks, CollBCs const& bcs) { processDatawBestTracks(collision, tracks, besttracks, bcs); } @@ -1263,8 +1272,7 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentFT0C( CollsCentFT0C::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, - CollBCs const& bcs) + soa::SmallGroups const& besttracks, CollBCs const& bcs) { processDatawBestTracks(collision, tracks, besttracks, bcs); } @@ -1276,11 +1284,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentFT0CVariant1( CollsCentFT0CVariant1::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, - CollBCs const& bcs) + soa::SmallGroups const& besttracks, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, - bcs); + processDatawBestTracks(collision, tracks, besttracks, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentFT0CVariant1, @@ -1290,8 +1296,7 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentFT0M( CollsCentFT0M::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, - CollBCs const& bcs) + soa::SmallGroups const& besttracks, CollBCs const& bcs) { processDatawBestTracks(collision, tracks, besttracks, bcs); } @@ -1302,11 +1307,9 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentNGlobal( CollsCentNGlobal::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, - CollBCs const& bcs) + soa::SmallGroups const& besttracks, CollBCs const& bcs) { - processDatawBestTracks(collision, tracks, besttracks, - bcs); + processDatawBestTracks(collision, tracks, besttracks, bcs); } PROCESS_SWITCH(DndetaMFTPbPb, processDatawBestTracksCentNGlobal, @@ -1316,8 +1319,7 @@ struct DndetaMFTPbPb { void processDatawBestTracksCentMFT( CollsCentMFT::iterator const& collision, FiltMftTracks const& tracks, - soa::SmallGroups const& besttracks, - CollBCs const& bcs) + soa::SmallGroups const& besttracks, CollBCs const& bcs) { processDatawBestTracks(collision, tracks, besttracks, bcs); } @@ -1341,27 +1343,27 @@ struct DndetaMFTPbPb { bool gtZeroColl = false; int gtOneColl = 0; - float cgen = -1; + float cGen = -1; if constexpr (has_reco_cent) { - float crec_min = 105.f; + float crecMin = 105.f; for (const auto& collision : collisions) { if (isGoodEvent(collision)) { float c = getRecoCent(collision); - if (c < crec_min) { - crec_min = c; + if (c < crecMin) { + crecMin = c; } } } - if (cgen < 0) - cgen = crec_min; + if (cGen < 0) + cGen = crecMin; } - float occgen = -1.; + float occGen = -1.; for (const auto& collision : collisions) { if (isGoodEvent(collision)) { float o = getOccupancy(collision, eventCuts.occupancyEstimator); - if (o > occgen) { - occgen = o; + if (o > occGen) { + occGen = o; } } } @@ -1419,9 +1421,9 @@ struct DndetaMFTPbPb { } if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtEffGen"), 3., cgen, occgen); + registry.fill(HIST("Events/Centrality/EvtEffGen"), 3., cGen, occGen); } else { - registry.fill(HIST("Events/EvtEffGen"), 3., occgen); + registry.fill(HIST("Events/EvtEffGen"), 3., occGen); } auto perCollMCsample = mcSample->sliceByCached( @@ -1431,7 +1433,7 @@ struct DndetaMFTPbPb { if (gtOneColl > 1) { if constexpr (has_reco_cent) { - qaregistry.fill(HIST("Events/Centrality/SplitMult"), nchrg, zvtxMC, cgen); + qaregistry.fill(HIST("Events/Centrality/SplitMult"), nchrg, zvtxMC, cGen); } else { qaregistry.fill(HIST("Events/SplitMult"), nchrg, zvtxMC); } @@ -1440,17 +1442,17 @@ struct DndetaMFTPbPb { auto nCharged = countPart(particles); if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/NtrkZvtxGen_t"), nCharged, zvtxMC, - cgen); + cGen); } else { registry.fill(HIST("Events/NtrkZvtxGen_t"), nCharged, zvtxMC); } - fillHistMC>(particles, cgen, occgen, zvtxMC, gtZeroColl); + fillHistMC>(particles, cGen, occGen, zvtxMC, gtZeroColl); if (collisions.size() == 0) { if constexpr (has_reco_cent) { qaregistry.fill(HIST("Events/Centrality/NotFoundEventZvtx"), - mcCollision.posZ(), cgen); + mcCollision.posZ(), cGen); } else { qaregistry.fill(HIST("Events/NotFoundEventZvtx"), mcCollision.posZ()); } @@ -1544,27 +1546,27 @@ struct DndetaMFTPbPb { FiltBestTracks const& besttracks) { bool gtZeroColl = false; - float cgen = -1; + float cGen = -1; if constexpr (has_reco_cent) { - float crec_min = 105.f; + float crecMin = 105.f; for (const auto& collision : collisions) { if (isGoodEvent(collision)) { float c = getRecoCent(collision); - if (c < crec_min) { - crec_min = c; + if (c < crecMin) { + crecMin = c; } } } - if (cgen < 0) - cgen = crec_min; + if (cGen < 0) + cGen = crecMin; } - float occgen = -1.; + float occGen = -1.; for (const auto& collision : collisions) { if (isGoodEvent(collision)) { float o = getOccupancy(collision, eventCuts.occupancyEstimator); - if (o > occgen) { - occgen = o; + if (o > occGen) { + occGen = o; } } } @@ -1607,26 +1609,26 @@ struct DndetaMFTPbPb { } if constexpr (has_reco_cent) { - registry.fill(HIST("Events/Centrality/EvtEffGen"), 3., cgen, occgen); + registry.fill(HIST("Events/Centrality/EvtEffGen"), 3., cGen, occGen); } else { - registry.fill(HIST("Events/EvtEffGen"), 3., occgen); + registry.fill(HIST("Events/EvtEffGen"), 3., occGen); } auto zvtxMC = mcCollision.posZ(); auto nCharged = countPart(particles); if constexpr (has_reco_cent) { registry.fill(HIST("Events/Centrality/NtrkZvtxGen_t"), nCharged, zvtxMC, - cgen); + cGen); } else { registry.fill(HIST("Events/NtrkZvtxGen_t"), nCharged, zvtxMC); } - fillHistMC>(particles, cgen, occgen, zvtxMC, gtZeroColl); + fillHistMC>(particles, cGen, occGen, zvtxMC, gtZeroColl); if (collisions.size() == 0) { if constexpr (has_reco_cent) { qaregistry.fill(HIST("Events/Centrality/NotFoundEventZvtx"), - mcCollision.posZ(), cgen); + mcCollision.posZ(), cGen); } else { qaregistry.fill(HIST("Events/NotFoundEventZvtx"), mcCollision.posZ()); } diff --git a/PWGMM/UE/Tasks/dedxAnalysis.cxx b/PWGMM/UE/Tasks/dedxAnalysis.cxx index 0336638dade..11aea4031be 100644 --- a/PWGMM/UE/Tasks/dedxAnalysis.cxx +++ b/PWGMM/UE/Tasks/dedxAnalysis.cxx @@ -14,20 +14,24 @@ /// \file dedxAnalysis.cxx /// \brief Analysis to do PID +#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/PIDResponse.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Multiplicity.h" + #include "Framework/ASoAHelpers.h" #include "Framework/AnalysisDataModel.h" #include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include "PWGLF/DataModel/LFStrangenessTables.h" #include "ReconstructionDataFormats/Track.h" -#include "Common/Core/TrackSelectionDefaults.h" + +#include "TF1.h" using namespace o2; using namespace o2::framework; @@ -58,6 +62,8 @@ struct DedxAnalysis { float pionTofCut = 1.0; float invMassCut = 0.01; float invMassCutGamma = 0.0015; + float magField = 1; + float pTcut = 2.0; // Configurable Parameters // Tracks cuts @@ -93,16 +99,26 @@ struct DedxAnalysis { "Minimum Mass Gamma"}; Configurable maxMassGamma{"maxMassGamma", 0.002022f, "Maximum Mass Gamma"}; + Configurable nclCut{"nclCut", 135.0f, + "ncl Cut"}; Configurable calibrationMode{"calibrationMode", false, "calibration mode"}; - Configurable additionalCuts{"additionalCuts", false, "additional cuts"}; + Configurable additionalCuts{"additionalCuts", true, "additional cuts"}; // 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 kNclDedxMomentumNegBefore[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Neg_1_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_2_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_3_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_4_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_5_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_6_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_7_Before", "Ncl_vs_dEdx_vs_Momentum_Neg_8_Before"}; + static constexpr std::string_view kNclDedxMomentumPosBefore[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Pos_1_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_2_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_3_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_4_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_5_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_6_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_7_Before", "Ncl_vs_dEdx_vs_Momentum_Pos_8_Before"}; + static constexpr std::string_view kNclDedxMomentumNegAfter[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Neg_1_After", "Ncl_vs_dEdx_vs_Momentum_Neg_2_After", "Ncl_vs_dEdx_vs_Momentum_Neg_3_After", "Ncl_vs_dEdx_vs_Momentum_Neg_4_After", "Ncl_vs_dEdx_vs_Momentum_Neg_5_After", "Ncl_vs_dEdx_vs_Momentum_Neg_6_After", "Ncl_vs_dEdx_vs_Momentum_Neg_7_After", "Ncl_vs_dEdx_vs_Momentum_Neg_8_After"}; + static constexpr std::string_view kNclDedxMomentumPosAfter[kEtaIntervals] = {"Ncl_vs_dEdx_vs_Momentum_Pos_1_After", "Ncl_vs_dEdx_vs_Momentum_Pos_2_After", "Ncl_vs_dEdx_vs_Momentum_Pos_3_After", "Ncl_vs_dEdx_vs_Momentum_Pos_4_After", "Ncl_vs_dEdx_vs_Momentum_Pos_5_After", "Ncl_vs_dEdx_vs_Momentum_Pos_6_After", "Ncl_vs_dEdx_vs_Momentum_Pos_7_After", "Ncl_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}; 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}, ""}; + // phi cut fits + TF1* fphiCutHigh = nullptr; + TF1* fphiCutLow = nullptr; + TrackSelection myTrackSelection() { TrackSelection selectedTracks; @@ -130,6 +146,8 @@ struct DedxAnalysis { AxisSpec ptAxis = {binP, "pT (GeV/c)"}; AxisSpec etaAxis{8, -0.8, 0.8, "#eta"}; AxisSpec pAxis = {binP, "#it{p}/Z (GeV/c)"}; + fphiCutLow = new TF1("StandardPhiCutLow", "0.119297/x/x+pi/18.0-0.000379693", 0, 50); + fphiCutHigh = new TF1("StandardPhiCutHigh", "0.16685/x+pi/18.0+0.00981942", 0, 50); if (calibrationMode) { // MIP for pions registryDeDx.add( @@ -202,6 +220,30 @@ struct DedxAnalysis { "hdEdx_vs_phi", "dE/dx", HistType::kTH2F, {{100, 0.0, 6.4, "#phi"}, {dedxAxis}}); + // phi cut + registryDeDx.add( + "hpt_vs_phi_Ncl_After", "phi cut", HistType::kTH3F, + {{ptAxis}, {100, 0.0, 0.4, "#varphi^{'}"}, {100, 0, 160, "N_{cl}"}}); + + registryDeDx.add( + "hpt_vs_phi_Ncl_Before", "phi cut", HistType::kTH3F, + {{ptAxis}, {100, 0.0, 0.4, "#varphi^{'}"}, {100, 0, 160, "N_{cl}"}}); + + // Ncl vs de/dx + + for (int i = 0; i < kEtaIntervals; ++i) { + registryDeDx.add(kNclDedxMomentumPosBefore[i].data(), "Ncl vs dE/dx vs Momentum Positive before", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + registryDeDx.add(kNclDedxMomentumNegBefore[i].data(), "Ncl vs dE/dx vs Momentum Negative before", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + + registryDeDx.add(kNclDedxMomentumPosAfter[i].data(), "Ncl vs dE/dx vs Momentum Positive after", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + registryDeDx.add(kNclDedxMomentumNegAfter[i].data(), "Ncl vs dE/dx vs Momentum Negative after", HistType::kTH3F, + {{100, 0, 160, "N_{cl}"}, {dedxAxis}, {pAxis}}); + } + + // beta plot registryDeDx.add( "hbeta_vs_p_Neg", "beta", HistType::kTH2F, {{pAxis}, {100, 0.0, 1.1, "#beta"}}); @@ -209,6 +251,7 @@ struct DedxAnalysis { registryDeDx.add( "hbeta_vs_p_Pos", "beta", HistType::kTH2F, {{pAxis}, {100, 0.0, 1.1, "#beta"}}); + // Event Counter registryDeDx.add("histRecVtxZData", "collision z position", HistType::kTH1F, {{100, -20.0, +20.0, "z_{vtx} (cm)"}}); @@ -375,6 +418,176 @@ struct DedxAnalysis { return true; } + // Phi cut + template + bool passedPhiCut(const T& trk, float magField, const TF1& fphiCutLow, const TF1& fphiCutHigh) + { + float pt = trk.pt(); + float phi = trk.phi(); + int charge = trk.sign(); + float eta = trk.eta(); + auto nTPCCl = trk.tpcNClsFindable() - trk.tpcNClsFindableMinusFound(); + float sigP = trk.sign() * trk.tpcInnerParam(); + + if (pt < pTcut) + return true; + + if (magField < 0) // for negatve polarity field + phi = o2::constants::math::TwoPI - phi; + if (charge < 0) // for negatve charge + phi = o2::constants::math::TwoPI - phi; + + // to center gap in the middle + phi += o2::constants::math::PI / 18.0f; + phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + + registryDeDx.fill(HIST("hpt_vs_phi_Ncl_Before"), pt, phi, nTPCCl); + + // cut phi + if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) + return false; // reject track + + if (eta > EtaCut[0] && eta < EtaCut[1]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[0]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[1] && eta < EtaCut[2]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[1]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[2] && eta < EtaCut[3]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[2]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[3] && eta < EtaCut[4]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[3]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[4] && eta < EtaCut[5]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[4]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[5] && eta < EtaCut[6]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[5]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[6] && eta < EtaCut[7]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[6]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[7] && eta < EtaCut[8]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegBefore[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosBefore[7]), nTPCCl, trk.tpcSignal(), sigP); + } + } + + // cut Ncl + if (nTPCCl < nclCut) + return false; + + registryDeDx.fill(HIST("hpt_vs_phi_Ncl_After"), pt, phi, nTPCCl); + + if (eta > EtaCut[0] && eta < EtaCut[1]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[0]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[0]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[1] && eta < EtaCut[2]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[1]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[1]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[2] && eta < EtaCut[3]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[2]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[2]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[3] && eta < EtaCut[4]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[3]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[3]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[4] && eta < EtaCut[5]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[4]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[4]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[5] && eta < EtaCut[6]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[5]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[5]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[6] && eta < EtaCut[7]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[6]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[6]), nTPCCl, trk.tpcSignal(), sigP); + } + } else if (eta > EtaCut[7] && eta < EtaCut[8]) { + if (sigP < 0) { + registryDeDx.fill(HIST(kNclDedxMomentumNegAfter[7]), nTPCCl, trk.tpcSignal(), std::abs(sigP)); + } else { + registryDeDx.fill(HIST(kNclDedxMomentumPosAfter[7]), nTPCCl, trk.tpcSignal(), sigP); + } + } + + return true; + } + + // Phi cut Secondaries + template + bool passedPhiCutSecondaries(const T& trk, float magField, const TF1& fphiCutLow, const TF1& fphiCutHigh) + { + float pt = trk.pt(); + float phi = trk.phi(); + int charge = trk.sign(); + auto nTPCCl = trk.tpcNClsFindable() - trk.tpcNClsFindableMinusFound(); + + if (pt < pTcut) + return true; + + if (magField < 0) // for negatve polarity field + phi = o2::constants::math::TwoPI - phi; + if (charge < 0) // for negatve charge + phi = o2::constants::math::TwoPI - phi; + + // to center gap in the middle + phi += o2::constants::math::PI / 18.0f; + phi = std::fmod(phi, o2::constants::math::PI / 9.0f); + + // cut phi + if (phi < fphiCutHigh.Eval(pt) && phi > fphiCutLow.Eval(pt)) + return false; // reject track + + // cut Ncl + if (nTPCCl < nclCut) + return false; + + return true; + } + // Process Data void process(SelectedCollisions::iterator const& collision, aod::V0Datas const& fullV0s, PIDTracks const& tracks) @@ -410,6 +623,10 @@ struct DedxAnalysis { if (!mySelectionPrim.IsSelected(trk)) continue; + // phi and Ncl cut + if (!passedPhiCut(trk, magField, *fphiCutLow, *fphiCutHigh)) + continue; + float signedP = trk.sign() * trk.tpcInnerParam(); // MIP calibration for pions @@ -518,6 +735,12 @@ struct DedxAnalysis { continue; if (!negTrack.passedTPCRefit()) continue; + // phi and Ncl cut + if (!passedPhiCutSecondaries(posTrack, magField, *fphiCutLow, *fphiCutHigh)) + continue; + + if (!passedPhiCutSecondaries(negTrack, magField, *fphiCutLow, *fphiCutHigh)) + continue; float signedPpos = posTrack.sign() * posTrack.tpcInnerParam(); float signedPneg = negTrack.sign() * negTrack.tpcInnerParam(); diff --git a/PWGUD/AQC/udQC.cxx b/PWGUD/AQC/udQC.cxx index ddaf01338df..3da67d1f683 100644 --- a/PWGUD/AQC/udQC.cxx +++ b/PWGUD/AQC/udQC.cxx @@ -69,6 +69,8 @@ struct UDQC { using ATs = aod::AmbiguousTracks; using AFTs = aod::AmbiguousFwdTracks; + Partition goodTracks = requireGlobalTrackInFilter(); + void init(InitContext& context) { // initialize global variables @@ -220,7 +222,7 @@ struct UDQC { // vertex tracks normally gives PV contributors from collisions registry.get(HIST("collisions/vtxTracks"))->Fill(collision.numContrib()); // global tracks - Partition goodTracks = requireGlobalTrackInFilter(); + // Partition goodTracks = requireGlobalTrackInFilter(); goodTracks.bindTable(tracks); registry.get(HIST("collisions/globalTracks"))->Fill(goodTracks.size()); diff --git a/PWGUD/AQC/udQCmidRap.cxx b/PWGUD/AQC/udQCmidRap.cxx index e7178cfa042..acb35f21f57 100644 --- a/PWGUD/AQC/udQCmidRap.cxx +++ b/PWGUD/AQC/udQCmidRap.cxx @@ -64,6 +64,8 @@ struct UDQCmid { using ATs = aod::AmbiguousTracks; using AFTs = aod::AmbiguousFwdTracks; + Partition goodTracks = requireGlobalTrackInFilter(); + void init(InitContext& context) { // initialize global variables @@ -132,7 +134,7 @@ struct UDQCmid { } } - // ............................................................................................................................................... + //............................................................................................................................................... void processMain(CC const& collision, BCs const& bct0s, TCs const& tracks, FWs const& fwdtracks, ATs const& /*ambtracks*/, AFTs const& /*ambfwdtracks*/, aod::FT0s const& /*ft0s*/, aod::FV0As const& /*fv0as*/, aod::FDDs const& /*fdds*/, @@ -150,7 +152,7 @@ struct UDQCmid { // vertex tracks normally gives PV contributors from collisions registry.get(HIST("collisions/vtxTracks"))->Fill(collision.numContrib()); // global tracks - Partition goodTracks = requireGlobalTrackInFilter(); + goodTracks.bindTable(tracks); registry.get(HIST("collisions/globalTracks"))->Fill(goodTracks.size()); @@ -223,7 +225,7 @@ struct UDQCmid { registry.get(HIST("DG/hMassAll"))->Fill(ivm.M()); } } // coll - } // dgcand + } // dgcand // loop over all tracks float rgtrwTOF = 0.; @@ -322,7 +324,7 @@ struct UDQCmid { if (track.hasTOF()) { registry.get(HIST("DG/dEdxTOF"))->Fill(track.p() / track.sign(), track.beta()); } // fill TOF - } // pv contributor + } // pv contributor } } // Inavariant mass after FIT @@ -489,7 +491,7 @@ struct UDQCmid { // update #PV contributors in collisions with empty FT0 && FV0&& FDCC registry.get(HIST("fpPVC2"))->Fill(collision.numContrib(), 1.); } // fdd - } // fvo + } // fvo } // ft0 } diff --git a/PWGUD/Core/SGSelector.h b/PWGUD/Core/SGSelector.h index 4845818f244..b9fc3ecf2e7 100644 --- a/PWGUD/Core/SGSelector.h +++ b/PWGUD/Core/SGSelector.h @@ -8,17 +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. +// +/// \file SGSelector.h +/// \author Alexander Bylinkin +/// \author Adam Matyja +/// \since 2023-11-21 +/// \brief Support class holding tools to work with Single Gap selection in central barrel UPCs +/// #ifndef PWGUD_CORE_SGSELECTOR_H_ #define PWGUD_CORE_SGSELECTOR_H_ -#include -#include "TDatabasePDG.h" -#include "TLorentzVector.h" -#include "Framework/Logger.h" -#include "Framework/AnalysisTask.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/SGCutParHolder.h" +#include "PWGUD/Core/UDHelpers.h" + +#include "Common/CCDB/RCTSelectionFlags.h" + +#include "Framework/AnalysisTask.h" +#include "Framework/Logger.h" + +#include template struct SelectionResult { @@ -26,10 +35,20 @@ struct SelectionResult { BC* bc; // Pointer to the BC object }; +namespace o2::aod::sgselector +{ +enum TrueGap : int { + NoGap = -1, + SingleGapA = 0, + SingleGapC = 1, + DoubleGap = 2 +}; +} + class SGSelector { public: - SGSelector() : fPDG(TDatabasePDG::Instance()) {} + SGSelector() : myRCTChecker{"CBT"}, myRCTCheckerHadron{"CBT_hadronPID"}, myRCTCheckerZDC{"CBT", true}, myRCTCheckerHadronZDC{"CBT_hadronPID", true} {} template int Print(SGCutParHolder /*diffCuts*/, CC& collision, BCs& /*bcRange*/, TCs& /*tracks*/, FWs& /*fwdtracks*/) @@ -107,7 +126,8 @@ class SGSelector template int FwdTrkSelector(TFwdTrack const& fwdtrack) { - if (fwdtrack.trackType() == 0 || fwdtrack.trackType() == 3) + // if (fwdtrack.trackType() == 0 || fwdtrack.trackType() == 3) + if (fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::GlobalMuonTrack || fwdtrack.trackType() == o2::aod::fwdtrack::ForwardTrackTypeEnum::MuonStandaloneTrack) return 1; else return 0; @@ -125,29 +145,68 @@ class SGSelector FT0C = collision.totalFT0AmplitudeC(); ZNA = collision.energyCommonZNA(); ZNC = collision.energyCommonZNC(); - if (gap == 0) { + if (gap == o2::aod::sgselector::SingleGapA) { // gap == 0 if (FV0A > fit_cut[0] || FT0A > fit_cut[1] || ZNA > zdc_cut) - true_gap = -1; - } else if (gap == 1) { + true_gap = o2::aod::sgselector::NoGap; // -1 + } else if (gap == o2::aod::sgselector::SingleGapC) { // gap == 1 if (FT0C > fit_cut[2] || ZNC > zdc_cut) - true_gap = -1; - } else if (gap == 2) { + true_gap = o2::aod::sgselector::NoGap; // -1 + } else if (gap == o2::aod::sgselector::DoubleGap) { // gap == 2 if ((FV0A > fit_cut[0] || FT0A > fit_cut[1] || ZNA > zdc_cut) && (FT0C > fit_cut[2] || ZNC > zdc_cut)) - true_gap = -1; + true_gap = o2::aod::sgselector::NoGap; // -1 else if ((FV0A > fit_cut[0] || FT0A > fit_cut[1] || ZNA > zdc_cut) && (FT0C <= fit_cut[2] && ZNC <= zdc_cut)) - true_gap = 1; + true_gap = o2::aod::sgselector::SingleGapC; // 1 else if ((FV0A <= fit_cut[0] && FT0A <= fit_cut[1] && ZNA <= zdc_cut) && (FT0C > fit_cut[2] || ZNC > zdc_cut)) - true_gap = 0; + true_gap = o2::aod::sgselector::SingleGapA; // 0 else if (FV0A <= fit_cut[0] && FT0A <= fit_cut[1] && ZNA <= zdc_cut && FT0C <= fit_cut[2] && ZNC <= zdc_cut) - true_gap = 2; + true_gap = o2::aod::sgselector::DoubleGap; // 2 else - std::cout << "Something wrong with DG" << std::endl; + LOGF(info, "Something wrong with DG"); } return true_gap; } + // check CBT flags + template + bool isCBTOk(CC& collision) + { + if (myRCTChecker(collision)) + return true; + return false; + } + + // check CBT+hadronPID flags + template + bool isCBTHadronOk(CC& collision) + { + if (myRCTCheckerHadron(collision)) + return true; + return false; + } + + // check CBT+ZDC flags + template + bool isCBTZdcOk(CC& collision) + { + if (myRCTCheckerZDC(collision)) + return true; + return false; + } + + // check CBT+hadronPID+ZDC flags + template + bool isCBTHadronZdcOk(CC& collision) + { + if (myRCTCheckerHadronZDC(collision)) + return true; + return false; + } + private: - TDatabasePDG* fPDG; + o2::aod::rctsel::RCTFlagsChecker myRCTChecker; + o2::aod::rctsel::RCTFlagsChecker myRCTCheckerHadron; + o2::aod::rctsel::RCTFlagsChecker myRCTCheckerZDC; + o2::aod::rctsel::RCTFlagsChecker myRCTCheckerHadronZDC; }; #endif // PWGUD_CORE_SGSELECTOR_H_ diff --git a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h index 55a13a0e9c5..41af7ec5d78 100644 --- a/PWGUD/Core/UPCTauCentralBarrelHelperRL.h +++ b/PWGUD/Core/UPCTauCentralBarrelHelperRL.h @@ -8,16 +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. -/// -/// \brief + +/// \file UPCTauCentralBarrelHelperRL.h +/// \brief Personal helper file to analyze tau events from UPC collisions /// \author Roman Lavicka, roman.lavicka@cern.ch /// \since 27.10.2022 +/// #ifndef PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ #define PWGUD_CORE_UPCTAUCENTRALBARRELHELPERRL_H_ -#include +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + #include +#include enum MyParticle { P_ELECTRON = 0, @@ -156,6 +162,25 @@ int enumMyParticle(int valuePDG) } } +int trackPDGfromEnum(int trackEnum) +// reads pdg value and returns particle number as in enumMyParticle +{ + if (trackEnum == P_ELECTRON) { + return 11; + } else if (trackEnum == P_MUON) { + return 13; + } else if (trackEnum == P_PION) { + return 211; + } else if (trackEnum == P_KAON) { + return 321; + } else if (trackEnum == P_PROTON) { + return 2212; + } else { + printDebugMessage("PDG value not found in enumMyParticle. Returning -1."); + return -1.; + } +} + float pt(float px, float py) // Just a simple function to return pt { diff --git a/PWGUD/DataModel/TwoTracksEventTables.h b/PWGUD/DataModel/TwoTracksEventTables.h new file mode 100644 index 00000000000..73be3f3c438 --- /dev/null +++ b/PWGUD/DataModel/TwoTracksEventTables.h @@ -0,0 +1,226 @@ +// 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 TwoTracksEventTables.h +/// \author Roman Lavička +/// \since 2025-06-20 +/// \brief A table to store information about events preselected to have exactly two tracks. +/// \brief Good for UPC gammagamma (->elel,mumu,tautau) and gammalead (vector mesons) +/// \brief If MC, careful with filling the mother +/// + +#ifndef PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ +#define PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ + +#include "Framework/AnalysisDataModel.h" + +namespace o2::aod +{ +namespace two_tracks_tree +{ +// event info +DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); +DECLARE_SOA_COLUMN(Bc, bc, int); +DECLARE_SOA_COLUMN(TotalTracks, totalTracks, int); +DECLARE_SOA_COLUMN(NumContrib, numContrib, int); +DECLARE_SOA_COLUMN(GlobalNonPVtracks, globalNonPVtracks, int); +DECLARE_SOA_COLUMN(PosX, posX, float); +DECLARE_SOA_COLUMN(PosY, posY, float); +DECLARE_SOA_COLUMN(PosZ, posZ, float); +DECLARE_SOA_COLUMN(RecoMode, recoMode, int); +DECLARE_SOA_COLUMN(OccupancyInTime, occupancyInTime, int); +DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, double); +DECLARE_SOA_COLUMN(Trs, trs, int); +DECLARE_SOA_COLUMN(Trofs, trofs, int); +DECLARE_SOA_COLUMN(Hmpr, hmpr, int); +DECLARE_SOA_COLUMN(Tfb, tfb, int); +DECLARE_SOA_COLUMN(ItsRofb, itsRofb, int); +DECLARE_SOA_COLUMN(Sbp, sbp, int); +DECLARE_SOA_COLUMN(ZvtxFT0vsPv, zvtxFT0vsPv, int); +DECLARE_SOA_COLUMN(VtxITSTPC, vtxITSTPC, int); +// FIT info +DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float); +DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float); +DECLARE_SOA_COLUMN(TotalFV0AmplitudeA, totalFV0AmplitudeA, float); +DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); +DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); +DECLARE_SOA_COLUMN(TimeFT0A, timeFT0A, float); +DECLARE_SOA_COLUMN(TimeFT0C, timeFT0C, float); +DECLARE_SOA_COLUMN(TimeFV0A, timeFV0A, float); +DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); +DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); +// tracks +DECLARE_SOA_COLUMN(TrkPx, trkPx, float[2]); +DECLARE_SOA_COLUMN(TrkPy, trkPy, float[2]); +DECLARE_SOA_COLUMN(TrkPz, trkPz, float[2]); +DECLARE_SOA_COLUMN(TrkSign, trkSign, int[2]); +DECLARE_SOA_COLUMN(TrkDCAxy, trkDCAxy, float[2]); +DECLARE_SOA_COLUMN(TrkDCAz, trkDCAz, float[2]); +DECLARE_SOA_COLUMN(TrkTimeRes, trkTimeRes, float[2]); +DECLARE_SOA_COLUMN(Trk1ITSclusterSizes, trk1ITSclusterSizes, uint32_t); +DECLARE_SOA_COLUMN(Trk2ITSclusterSizes, trk2ITSclusterSizes, uint32_t); +DECLARE_SOA_COLUMN(TrkTPCsignal, trkTPCsignal, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaEl, trkTPCnSigmaEl, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaMu, trkTPCnSigmaMu, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaPi, trkTPCnSigmaPi, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaKa, trkTPCnSigmaKa, float[2]); +DECLARE_SOA_COLUMN(TrkTPCnSigmaPr, trkTPCnSigmaPr, float[2]); +DECLARE_SOA_COLUMN(TrkTPCinnerParam, trkTPCinnerParam, float[2]); +DECLARE_SOA_COLUMN(TrkTOFsignal, trkTOFsignal, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaEl, trkTOFnSigmaEl, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaMu, trkTOFnSigmaMu, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaPi, trkTOFnSigmaPi, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaKa, trkTOFnSigmaKa, float[2]); +DECLARE_SOA_COLUMN(TrkTOFnSigmaPr, trkTOFnSigmaPr, float[2]); +DECLARE_SOA_COLUMN(TrkTOFexpMom, trkTOFexpMom, float[2]); +// truth event +DECLARE_SOA_COLUMN(TrueChannel, trueChannel, int); +DECLARE_SOA_COLUMN(TrueHasRecoColl, trueHasRecoColl, bool); +DECLARE_SOA_COLUMN(TruePosX, truePosX, float); +DECLARE_SOA_COLUMN(TruePosY, truePosY, float); +DECLARE_SOA_COLUMN(TruePosZ, truePosZ, float); +// truth particles +DECLARE_SOA_COLUMN(TrueMotherPx, trueMotherPx, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPy, trueMotherPy, float[2]); +DECLARE_SOA_COLUMN(TrueMotherPz, trueMotherPz, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPx, trueDaugPx, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPy, trueDaugPy, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPz, trueDaugPz, float[2]); +DECLARE_SOA_COLUMN(TrueDaugPdgCode, trueDaugPdgCode, int[2]); +// additional info +DECLARE_SOA_COLUMN(ProblematicEvent, problematicEvent, bool); + +} // namespace two_tracks_tree +DECLARE_SOA_TABLE(TwoTracks, "AOD", "TWOTRACK", + two_tracks_tree::RunNumber, + two_tracks_tree::Bc, + two_tracks_tree::TotalTracks, + two_tracks_tree::NumContrib, + two_tracks_tree::GlobalNonPVtracks, + two_tracks_tree::PosX, + two_tracks_tree::PosY, + two_tracks_tree::PosZ, + two_tracks_tree::RecoMode, + two_tracks_tree::OccupancyInTime, + two_tracks_tree::HadronicRate, + two_tracks_tree::Trs, + two_tracks_tree::Trofs, + two_tracks_tree::Hmpr, + two_tracks_tree::Tfb, + two_tracks_tree::ItsRofb, + two_tracks_tree::Sbp, + two_tracks_tree::ZvtxFT0vsPv, + two_tracks_tree::VtxITSTPC, + two_tracks_tree::TotalFT0AmplitudeA, + two_tracks_tree::TotalFT0AmplitudeC, + two_tracks_tree::TotalFV0AmplitudeA, + two_tracks_tree::EnergyCommonZNA, + two_tracks_tree::EnergyCommonZNC, + two_tracks_tree::TimeFT0A, + two_tracks_tree::TimeFT0C, + two_tracks_tree::TimeFV0A, + two_tracks_tree::TimeZNA, + two_tracks_tree::TimeZNC, + two_tracks_tree::TrkPx, + two_tracks_tree::TrkPy, + two_tracks_tree::TrkPz, + two_tracks_tree::TrkSign, + two_tracks_tree::TrkDCAxy, + two_tracks_tree::TrkDCAz, + two_tracks_tree::TrkTimeRes, + two_tracks_tree::Trk1ITSclusterSizes, + two_tracks_tree::Trk2ITSclusterSizes, + two_tracks_tree::TrkTPCsignal, + two_tracks_tree::TrkTPCnSigmaEl, + two_tracks_tree::TrkTPCnSigmaMu, + two_tracks_tree::TrkTPCnSigmaPi, + two_tracks_tree::TrkTPCnSigmaKa, + two_tracks_tree::TrkTPCnSigmaPr, + two_tracks_tree::TrkTPCinnerParam, + two_tracks_tree::TrkTOFsignal, + two_tracks_tree::TrkTOFnSigmaEl, + two_tracks_tree::TrkTOFnSigmaMu, + two_tracks_tree::TrkTOFnSigmaPi, + two_tracks_tree::TrkTOFnSigmaKa, + two_tracks_tree::TrkTOFnSigmaPr, + two_tracks_tree::TrkTOFexpMom); + +DECLARE_SOA_TABLE(TrueTwoTracks, "AOD", "TRUETWOTRACK", + two_tracks_tree::RunNumber, + two_tracks_tree::Bc, + two_tracks_tree::TotalTracks, + two_tracks_tree::NumContrib, + two_tracks_tree::GlobalNonPVtracks, + two_tracks_tree::PosX, + two_tracks_tree::PosY, + two_tracks_tree::PosZ, + two_tracks_tree::RecoMode, + two_tracks_tree::OccupancyInTime, + two_tracks_tree::HadronicRate, + two_tracks_tree::Trs, + two_tracks_tree::Trofs, + two_tracks_tree::Hmpr, + two_tracks_tree::Tfb, + two_tracks_tree::ItsRofb, + two_tracks_tree::Sbp, + two_tracks_tree::ZvtxFT0vsPv, + two_tracks_tree::VtxITSTPC, + two_tracks_tree::TotalFT0AmplitudeA, + two_tracks_tree::TotalFT0AmplitudeC, + two_tracks_tree::TotalFV0AmplitudeA, + two_tracks_tree::EnergyCommonZNA, + two_tracks_tree::EnergyCommonZNC, + two_tracks_tree::TimeFT0A, + two_tracks_tree::TimeFT0C, + two_tracks_tree::TimeFV0A, + two_tracks_tree::TimeZNA, + two_tracks_tree::TimeZNC, + two_tracks_tree::TrkPx, + two_tracks_tree::TrkPy, + two_tracks_tree::TrkPz, + two_tracks_tree::TrkSign, + two_tracks_tree::TrkDCAxy, + two_tracks_tree::TrkDCAz, + two_tracks_tree::TrkTimeRes, + two_tracks_tree::Trk1ITSclusterSizes, + two_tracks_tree::Trk2ITSclusterSizes, + two_tracks_tree::TrkTPCsignal, + two_tracks_tree::TrkTPCnSigmaEl, + two_tracks_tree::TrkTPCnSigmaMu, + two_tracks_tree::TrkTPCnSigmaPi, + two_tracks_tree::TrkTPCnSigmaKa, + two_tracks_tree::TrkTPCnSigmaPr, + two_tracks_tree::TrkTPCinnerParam, + two_tracks_tree::TrkTOFsignal, + two_tracks_tree::TrkTOFnSigmaEl, + two_tracks_tree::TrkTOFnSigmaMu, + two_tracks_tree::TrkTOFnSigmaPi, + two_tracks_tree::TrkTOFnSigmaKa, + two_tracks_tree::TrkTOFnSigmaPr, + two_tracks_tree::TrkTOFexpMom, + two_tracks_tree::TrueChannel, + two_tracks_tree::TrueHasRecoColl, + two_tracks_tree::TruePosX, + two_tracks_tree::TruePosY, + two_tracks_tree::TruePosZ, + two_tracks_tree::TrueMotherPx, + two_tracks_tree::TrueMotherPy, + two_tracks_tree::TrueMotherPz, + two_tracks_tree::TrueDaugPx, + two_tracks_tree::TrueDaugPy, + two_tracks_tree::TrueDaugPz, + two_tracks_tree::TrueDaugPdgCode, + two_tracks_tree::ProblematicEvent); + +} // namespace o2::aod + +#endif // PWGUD_DATAMODEL_TWOTRACKSEVENTTABLES_H_ diff --git a/PWGUD/DataModel/UDTables.h b/PWGUD/DataModel/UDTables.h index b84f6cd26e7..8a4251ec74d 100644 --- a/PWGUD/DataModel/UDTables.h +++ b/PWGUD/DataModel/UDTables.h @@ -8,18 +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. +// +/// \file UDTables.h +/// \brief Defines tables and colums for derived data used by UD group +/// \author Paul Buhler , Wiena +/// \since January 2023 +/// \author Sasha Bylinkin , Bergen +/// \since January 2024 +/// \author Adam Matyja , INP PAN Krakow, Poland +/// \since May 2025 #ifndef PWGUD_DATAMODEL_UDTABLES_H_ #define PWGUD_DATAMODEL_UDTABLES_H_ -#include -#include +#include "Common/DataModel/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + #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 +#include namespace o2::aod { @@ -111,6 +122,10 @@ DECLARE_SOA_COLUMN(ITSROFb, itsROFb, int); DECLARE_SOA_COLUMN(Sbp, sbp, int); DECLARE_SOA_COLUMN(ZvtxFT0vPV, zVtxFT0vPV, int); DECLARE_SOA_COLUMN(VtxITSTPC, vtxITSTPC, int); +// information about mask names -> Common/CCDB/RCTSelectionFlags.h +// DECLARE_SOA_COLUMN(Rct, rct, uint32_t); //! run condition table mask +DECLARE_SOA_BITMAP_COLUMN(Rct, rct, 32); //! run condition table mask + // Gap Side Information DECLARE_SOA_COLUMN(GapSide, gapSide, uint8_t); // 0 for side A, 1 for side C, 2 for both sides (or use an enum for better readability) // FIT selection flags @@ -249,6 +264,24 @@ DECLARE_SOA_TABLE_VERSIONED(UDCollisionSelExtras_002, "AOD", "UDCOLSELEXTRA", 2, udcollision::ZvtxFT0vPV, //! kIsGoodZvtxFT0vsPV udcollision::VtxITSTPC); //! kIsVertexITSTPC +DECLARE_SOA_TABLE_VERSIONED(UDCollisionSelExtras_003, "AOD", "UDCOLSELEXTRA", 3, + udcollision::ChFT0A, //! number of active channels in FT0A + udcollision::ChFT0C, //! number of active channels in FT0C + udcollision::ChFDDA, //! number of active channels in FDDA + udcollision::ChFDDC, //! number of active channels in FDDC + udcollision::ChFV0A, //! number of active channels in FV0A + udcollision::OccupancyInTime, //! Occupancy + udcollision::HadronicRate, //! Interaction Rate + udcollision::Trs, //! kNoCollInTimeRangeStandard + udcollision::Trofs, //! kNoCollInRofStandard + udcollision::Hmpr, //! kNoHighMultCollInPrevRof + udcollision::TFb, //! kNoTimeFrameBorder + udcollision::ITSROFb, //! kNoITSROFrameBorder + udcollision::Sbp, //! kNoSameBunchPileup + udcollision::ZvtxFT0vPV, //! kIsGoodZvtxFT0vsPV + udcollision::VtxITSTPC, //! kIsVertexITSTPC + udcollision::Rct); //! RCT mask + // central barrel-specific selections DECLARE_SOA_TABLE(UDCollisionsSelsCent, "AOD", "UDCOLSELCNT", udcollision::DBcTOR, @@ -272,7 +305,7 @@ DECLARE_SOA_TABLE(UDMcCollsLabels, "AOD", "UDMCCOLLSLABEL", udcollision::UDMcCollisionId); using UDCollisions = UDCollisions_001; -using UDCollisionSelExtras = UDCollisionSelExtras_002; +using UDCollisionSelExtras = UDCollisionSelExtras_003; using UDCollision = UDCollisions::iterator; using SGCollision = SGCollisions::iterator; diff --git a/PWGUD/TableProducer/CMakeLists.txt b/PWGUD/TableProducer/CMakeLists.txt index 16dd0773aed..548b052e667 100644 --- a/PWGUD/TableProducer/CMakeLists.txt +++ b/PWGUD/TableProducer/CMakeLists.txt @@ -36,6 +36,11 @@ o2physics_add_dpl_workflow(tau-event-table-producer PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) +o2physics_add_dpl_workflow(two-tracks-event-table-producer + SOURCES twoTracksEventTableProducer.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + o2physics_add_dpl_workflow(fwdtrack-propagation SOURCES fwdTrackPropagation.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::GlobalTracking diff --git a/PWGUD/TableProducer/Converters/CMakeLists.txt b/PWGUD/TableProducer/Converters/CMakeLists.txt index 8230278b45c..7d5a6297ba1 100644 --- a/PWGUD/TableProducer/Converters/CMakeLists.txt +++ b/PWGUD/TableProducer/Converters/CMakeLists.txt @@ -29,3 +29,8 @@ o2physics_add_dpl_workflow(collisionselextras-converter-v002 SOURCES UDCollisionSelExtrasV002Converter.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(collisionselextras-converter-v003 + SOURCES UDCollisionSelExtrasV003Converter.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) diff --git a/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx new file mode 100644 index 00000000000..a41b2c4efa6 --- /dev/null +++ b/PWGUD/TableProducer/Converters/UDCollisionSelExtrasV003Converter.cxx @@ -0,0 +1,126 @@ +// 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 UDCollisionSelExtrasV003Converter.cxx +/// \brief Converts UDCollisionSelExtras table from version 000 to 003 and 001 to 003 and 002 to 003 +/// \author Adam Matyja + +#include "PWGUD/DataModel/UDTables.h" + +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +using namespace o2; +using namespace o2::framework; + +// Converts UDCollisions for version 000 to 003 and 001 to 003 and 002 to 003 +struct UDCollisionSelExtrasV003Converter { + Produces udCollisionSelExtras_003; + + void init(InitContext const&) + { + if (!doprocessV000ToV003 && !doprocessV001ToV003 && !doprocessV002ToV003) { + LOGF(fatal, "Neither processV000ToV003 nor processV001ToV003 nor processV002ToV003 is enabled. Please choose one!"); + } + if (static_cast(doprocessV000ToV003) + static_cast(doprocessV001ToV003) + static_cast(doprocessV002ToV003) > 1) { + LOGF(fatal, "More than one among processV000ToV003, processV001ToV003, processV002ToV003 is enabled. Please choose only one!"); + } + } + + void processV000ToV003(o2::aod::UDCollisionSelExtras_000 const& collisions) + { + + for (const auto& collision : collisions) { + + udCollisionSelExtras_003(collision.chFT0A(), + collision.chFT0C(), + collision.chFDDA(), + collision.chFDDC(), + collision.chFV0A(), + 0, // dummy occupancy + 0.0f, // dummy rate + 0, // dummy trs + 0, // dummy trofs + 0, // dummy hmpr + 0, // dummy tfb + 0, // dummy itsROFb + 0, // dummy sbp + 0, // dummy zVtxFT0vPV + 0, // dummy vtxITSTPC + 0); // dummy rct + } + } + PROCESS_SWITCH(UDCollisionSelExtrasV003Converter, processV000ToV003, "process v000-to-v003 conversion", false); + + void processV001ToV003(o2::aod::UDCollisionSelExtras_001 const& collisions) + { + + for (const auto& collision : collisions) { + + udCollisionSelExtras_003(collision.chFT0A(), + collision.chFT0C(), + collision.chFDDA(), + collision.chFDDC(), + collision.chFV0A(), + collision.occupancyInTime(), + collision.hadronicRate(), + collision.trs(), + collision.trofs(), + collision.hmpr(), + 0, // dummy tfb + 0, // dummy itsROFb + 0, // dummy sbp + 0, // dummy zVtxFT0vPV + 0, // dummy vtxITSTPC + 0); // dummy rct + } + } + PROCESS_SWITCH(UDCollisionSelExtrasV003Converter, processV001ToV003, "process v001-to-v003 conversion", false); + + void processV002ToV003(o2::aod::UDCollisionSelExtras_002 const& collisions) + { + + for (const auto& collision : collisions) { + + udCollisionSelExtras_003(collision.chFT0A(), + collision.chFT0C(), + collision.chFDDA(), + collision.chFDDC(), + collision.chFV0A(), + collision.occupancyInTime(), + collision.hadronicRate(), + collision.trs(), + collision.trofs(), + collision.hmpr(), + collision.tfb(), + collision.itsROFb(), + collision.sbp(), + collision.zVtxFT0vPV(), + collision.vtxITSTPC(), + 0); // dummy rct + } + } + PROCESS_SWITCH(UDCollisionSelExtrasV003Converter, processV002ToV003, "process v002-to-v003 conversion", true); +}; + +/// Spawn the extended table for UDCollisionSelExtras003 to avoid the call to the internal spawner and a consequent circular dependency +// struct UDCollisionSelExtrasSpawner { +// Spawns udCollisionSelExtras_003; +// }; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc), + // adaptAnalysisTask(cfgc), + }; +} diff --git a/PWGUD/TableProducer/DGCandProducer.cxx b/PWGUD/TableProducer/DGCandProducer.cxx index 54c353d3d9a..84c892f5660 100644 --- a/PWGUD/TableProducer/DGCandProducer.cxx +++ b/PWGUD/TableProducer/DGCandProducer.cxx @@ -12,20 +12,23 @@ // \brief Saves relevant information of DG candidates // \author Paul Buehler, paul.buehler@oeaw.ac.at -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "ReconstructionDataFormats/Vertex.h" +#include "PWGUD/Core/DGSelector.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/CCDB/ctpRateFetcher.h" #include "EventFiltering/Zorro.h" #include "EventFiltering/ZorroSummary.h" + #include "CCDB/BasicCCDBManager.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UPCHelpers.h" -#include "PWGUD/Core/DGSelector.h" +#include "Framework/AnalysisTask.h" +#include "Framework/HistogramRegistry.h" +#include "Framework/runDataProcessing.h" +#include "ReconstructionDataFormats/Vertex.h" + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -354,7 +357,7 @@ struct DGCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, 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); + outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, collision.rct_raw()); outputCollsLabels(collision.globalIndex()); // update DGTracks tables diff --git a/PWGUD/TableProducer/SGCandProducer.cxx b/PWGUD/TableProducer/SGCandProducer.cxx index de75fff3e72..37fba3120db 100644 --- a/PWGUD/TableProducer/SGCandProducer.cxx +++ b/PWGUD/TableProducer/SGCandProducer.cxx @@ -14,38 +14,43 @@ /// /// \author Alexander Bylinkin , Uniersity of Bergen /// \since 23.11.2023 +/// \author Adam Matyja , INP PAN Krakow, Poland +/// \since May 2025 // -#include -#include -#include -#include +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/CCDB/EventSelectionParams.h" +#include "Common/CCDB/ctpRateFetcher.h" +#include "Common/DataModel/EventSelection.h" + #include "CCDB/BasicCCDBManager.h" -#include "Framework/ASoA.h" -#include "Framework/AnalysisDataModel.h" -#include "ReconstructionDataFormats/Vertex.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 "DataFormatsParameters/GRPLHCIFData.h" -#include "DataFormatsParameters/AggregatedRunInfo.h" - -#include "Framework/AnalysisTask.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 "Common/CCDB/EventSelectionParams.h" -#include "Common/CCDB/ctpRateFetcher.h" -#include "Common/DataModel/EventSelection.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UPCHelpers.h" -#include "PWGUD/Core/SGSelector.h" +#include "ReconstructionDataFormats/Vertex.h" + +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::dataformats; +using namespace o2::aod::rctsel; #define getHist(type, name) std::get>(histPointers[name]) @@ -80,6 +85,9 @@ struct SGCandProducer { Configurable ITSTPCVertex{"ITSTPCVertex", true, "reject ITS-only vertex"}; // if one wants to look at Single Gap pp events Configurable> generatorIds{"generatorIds", std::vector{-1}, "MC generatorIds to process"}; + 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"}; + // Configurables to decide which tables are filled Configurable fillTrackTables{"fillTrackTables", true, "Fill track tables"}; Configurable fillFwdTrackTables{"fillFwdTrackTables", true, "Fill forward track tables"}; @@ -88,6 +96,9 @@ struct SGCandProducer { SGSelector sgSelector; ctpRateFetcher mRateFetcher; + // initialize RCT flag checker + RCTFlagsChecker myRCTChecker{"CBT"}; + // data tables Produces outputSGCollisions; Produces outputCollisions; @@ -303,6 +314,18 @@ struct SGCandProducer { return; } getHist(TH1, histdir + "/Stat")->Fill(6., 1.); + // RCT CBT for collision check + if (isGoodRCTCollision && !myRCTChecker(collision)) { + return; + } + getHist(TH1, histdir + "/Stat")->Fill(7., 1.); + // RCT CBT+ZDC for collision check + if (isGoodRCTZdc && !myRCTChecker(collision)) { + return; + } + getHist(TH1, histdir + "/Stat")->Fill(8., 1.); + + // int trs = collision.selection_bit(o2::aod::evsel::kNoCollInTimeRangeStandard) ? 1 : 0; int trofs = collision.selection_bit(o2::aod::evsel::kNoCollInRofStandard) ? 1 : 0; int hmpr = collision.selection_bit(o2::aod::evsel::kNoHighMultCollInPrevRof) ? 1 : 0; @@ -331,7 +354,7 @@ struct SGCandProducer { if (verboseInfo) LOGF(info, "No Newbc %i", bc.globalBC()); } - getHist(TH1, histdir + "/Stat")->Fill(issgevent + 8, 1.); + getHist(TH1, histdir + "/Stat")->Fill(issgevent + 10, 1.); if (issgevent <= 2) { if (verboseInfo) LOGF(info, "Current BC: %i, %i, %i", bc.globalBC(), newbc.globalBC(), issgevent); @@ -363,7 +386,7 @@ struct SGCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, 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); + outputCollisionSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, occ, ir, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, collision.rct_raw()); outputCollsLabels(collision.globalIndex()); if (newbc.has_zdc()) { auto zdc = newbc.zdc(); @@ -428,6 +451,10 @@ struct SGCandProducer { if (context.mOptions.get("processMcData")) { histPointers.insert({"MCreco/Stat", registry.add("MCreco/Stat", "Cut statistics; Selection criterion; Collisions", {HistType::kTH1F, {{14, -0.5, 13.5}}})}); } + + if (isGoodRCTZdc) { + myRCTChecker.init("CBT", true); + } } // process function for reconstructed data diff --git a/PWGUD/TableProducer/UPCCandidateProducer.cxx b/PWGUD/TableProducer/UPCCandidateProducer.cxx index e7f029ae91d..2208060bd59 100644 --- a/PWGUD/TableProducer/UPCCandidateProducer.cxx +++ b/PWGUD/TableProducer/UPCCandidateProducer.cxx @@ -12,24 +12,27 @@ /// \author Diana Krupova, diana.krupova@cern.ch /// \since 04.06.2024 -#include -#include -#include -#include -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" +#include "PWGUD/Core/UPCCutparHolder.h" +#include "PWGUD/Core/UPCHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/CCDB/EventSelectionParams.h" #include "Common/DataModel/EventSelection.h" + #include "CommonConstants/LHCConstants.h" #include "DataFormatsFIT/Triggers.h" -#include "PWGUD/Core/UPCCutparHolder.h" -#include "PWGUD/Core/UPCHelpers.h" -#include "PWGUD/DataModel/UDTables.h" #include "DataFormatsITSMFT/ROFRecord.h" +#include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" +#include "Framework/runDataProcessing.h" + +#include +#include +#include +#include +#include +#include +#include using namespace o2::framework; using namespace o2::framework::expressions; @@ -1512,7 +1515,7 @@ struct UpcCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); - eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); eventCandidatesSelsFwd(fitInfo.distClosestBcV0A, fitInfo.distClosestBcT0A, amplitudesT0A, @@ -1828,7 +1831,7 @@ struct UpcCandProducer { fitInfo.BBFT0Apf, fitInfo.BBFT0Cpf, fitInfo.BGFT0Apf, fitInfo.BGFT0Cpf, fitInfo.BBFV0Apf, fitInfo.BGFV0Apf, fitInfo.BBFDDApf, fitInfo.BBFDDCpf, fitInfo.BGFDDApf, fitInfo.BGFDDCpf); - eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC); + eventCandidatesSelExtras(chFT0A, chFT0C, chFDDA, chFDDC, chFV0A, 0, 0, trs, trofs, hmpr, tfb, itsROFb, sbp, zVtxFT0vPv, vtxITSTPC, 0); eventCandidatesSelsFwd(fitInfo.distClosestBcV0A, fitInfo.distClosestBcT0A, amplitudesT0A, diff --git a/PWGUD/TableProducer/fwdTrackPropagation.cxx b/PWGUD/TableProducer/fwdTrackPropagation.cxx index cc6ba621690..52fa510b176 100644 --- a/PWGUD/TableProducer/fwdTrackPropagation.cxx +++ b/PWGUD/TableProducer/fwdTrackPropagation.cxx @@ -99,7 +99,7 @@ struct FwdTrackPropagation { if (run != fRun) { fRun = run; - std::map metadata; + std::map metadata; auto soreor = o2::ccdb::BasicCCDBManager::getRunDuration(fCCDBApi, run); auto ts = soreor.first; auto grpmag = fCCDBApi.retrieveFromTFileAny("GLO/Config/GRPMagField", metadata, ts); diff --git a/PWGUD/TableProducer/tauEventTableProducer.cxx b/PWGUD/TableProducer/tauEventTableProducer.cxx index 8293a76fd4a..548d8701689 100644 --- a/PWGUD/TableProducer/tauEventTableProducer.cxx +++ b/PWGUD/TableProducer/tauEventTableProducer.cxx @@ -43,10 +43,6 @@ #include "PWGUD/DataModel/TauEventTables.h" #include "PWGUD/Core/SGSelector.h" -// ROOT headers -#include "TLorentzVector.h" -#include "TPDGCode.h" - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; @@ -72,11 +68,17 @@ struct TauEventTableProducer { Configurable useNumContribs{"useNumContribs", false, {"Use coll.numContribs as event cut"}}; Configurable cutRecoFlag{"cutRecoFlag", 1, {"0 = std mode, 1 = upc mode"}}; Configurable useRecoFlag{"useRecoFlag", false, {"Use coll.flags as event cut"}}; + Configurable cutRCTflag{"cutRCTflag", 0, {"0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}}; 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 cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; @@ -152,10 +154,47 @@ struct TauEventTableProducer { return true; } + template + bool isGoodRCTflag(C const& coll) + { + switch (cutSample.cutRCTflag) { + case 1: + return sgSelector.isCBTOk(coll); + case 2: + return sgSelector.isCBTZdcOk(coll); + case 3: + return sgSelector.isCBTHadronOk(coll); + case 4: + return sgSelector.isCBTHadronZdcOk(coll); + default: + return true; + } + } + template bool isGoodROFtime(C const& coll) { + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; @@ -262,7 +301,7 @@ struct TauEventTableProducer { return false; // TPC chi2 if (cutGlobalTrack.cutGoodITSTPCmatching) { if (track.itsChi2NCl() < 0.) - return false; // TPC chi2 + return false; // good ITS-TPC matching means ITS ch2 is not negative } // TOF if (track.hasTOF()) { @@ -303,15 +342,16 @@ struct TauEventTableProducer { FullUDTracks const& tracks) { - int gapSide = collision.gapSide(); - int trueGapSide = sgSelector.trueGap(collision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); - - if (cutSample.useTrueGap) - gapSide = trueGapSide; + if (!isGoodRCTflag(collision)) + return; if (!isGoodROFtime(collision)) return; + int gapSide = collision.gapSide(); + int trueGapSide = sgSelector.trueGap(collision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); + if (cutSample.useTrueGap) + gapSide = trueGapSide; if (gapSide != cutSample.whichGapSide) return; diff --git a/PWGUD/TableProducer/twoTracksEventTableProducer.cxx b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx new file mode 100644 index 00000000000..f132315c403 --- /dev/null +++ b/PWGUD/TableProducer/twoTracksEventTableProducer.cxx @@ -0,0 +1,778 @@ +// 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 twoTracksEventTableProducer.cxx +/// \brief Produces derived table from UD tables +/// +/// \author Roman Lavicka , Austrian Academy of Sciences & SMI +/// \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/PIDResponse.h" +#include "Common/DataModel/TrackSelectionTables.h" + +// ROOT +#include "Math/Vector4D.h" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; +using namespace o2::constants::physics; + +struct TwoTracksEventTableProducer { + Produces twoTracks; + Produces trueTwoTracks; + + // Global varialbes + Service pdg; + SGSelector sgSelector; + int nSelection{0}; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // declare configurables + Configurable verboseInfo{"verboseInfo", false, {"Print general info to terminal; default it false."}}; + + struct : ConfigurableGroup { + Configurable whichGapSide{"whichGapSide", 2, {"0 for side A, 1 for side C, 2 for both sides"}}; + Configurable useTrueGap{"useTrueGap", true, {"Calculate gapSide for a given FV0/FT0/ZDC thresholds"}}; + Configurable cutNumContribs{"cutNumContribs", 2, {"How many contributors event has"}}; + Configurable useNumContribs{"useNumContribs", true, {"Use coll.numContribs as event cut"}}; + Configurable cutRecoFlag{"cutRecoFlag", 1, {"0 = std mode, 1 = upc mode"}}; + Configurable useRecoFlag{"useRecoFlag", false, {"Use coll.flags as event cut"}}; + Configurable cutRCTflag{"cutRCTflag", 0, {"0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}}; + 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 cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; + Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; + Configurable cutEvTrs{"cutEvTrs", false, {"Event selection bit kNoCollInTimeRangeStandard"}}; + Configurable cutEvTrofs{"cutEvTrofs", false, {"Event selection bit kNoCollInRofStandard"}}; + Configurable cutEvHmpr{"cutEvHmpr", false, {"Event selection bit kNoHighMultCollInPrevRof"}}; + } cutSample; + + struct : ConfigurableGroup { + Configurable applyGlobalTrackSelection{"applyGlobalTrackSelection", false, {"Applies cut on here defined global tracks"}}; + Configurable cutMinPt{"cutMinPt", 0.1f, {"Global track cut"}}; + Configurable cutMaxPt{"cutMaxPt", 1e10f, {"Global track cut"}}; + Configurable cutMinEta{"cutMinEta", -0.8f, {"Global track cut"}}; + Configurable cutMaxEta{"cutMaxEta", 0.8f, {"Global track cut"}}; + Configurable cutMaxDCAz{"cutMaxDCAz", 2.f, {"Global track cut"}}; + Configurable cutMaxDCAxy{"cutMaxDCAxy", 1e10f, {"Global track cut"}}; + Configurable applyPtDependentDCAxy{"applyPtDependentDCAxy", false, {"Global track cut"}}; + Configurable cutHasITS{"cutHasITS", true, {"Global track cut"}}; + Configurable cutMinITSnCls{"cutMinITSnCls", 1, {"Global track cut"}}; + Configurable cutMaxITSchi2{"cutMaxITSchi2", 36.f, {"Global track cut"}}; + Configurable cutITShitsRule{"cutITShitsRule", 0, {"Global track cut"}}; + Configurable cutHasTPC{"cutHasTPC", true, {"Global track cut"}}; + Configurable cutMinTPCnCls{"cutMinTPCnCls", 1, {"Global track cut"}}; + Configurable cutMinTPCnClsXrows{"cutMinTPCnClsXrows", 70, {"Global track cut"}}; + Configurable cutMinTPCnClsXrowsOverNcls{"cutMinTPCnClsXrowsOverNcls", 0.8f, {"Global track cut"}}; + Configurable cutMaxTPCchi2{"cutMaxTPCchi2", 4.f, {"Global track cut"}}; + Configurable cutGoodITSTPCmatching{"cutGoodITSTPCmatching", true, {"Global track cut"}}; + Configurable cutMaxTOFchi2{"cutMaxTOFchi2", 3.f, {"Global track cut"}}; + } cutGlobalTrack; + + struct : ConfigurableGroup { + Configurable preselAtLeastOneTOFtrack{"preselAtLeastOneTOFtrack", false, {"At least one track is required to hit TOF."}}; + 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 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."}}; + } cutPreselect; + + using FullUDTracks = soa::Join; + using FullSGUDCollisions = soa::Join; + using FullSGUDCollision = FullSGUDCollisions::iterator; + using FullMCUDTracks = soa::Join; + using FullMCSGUDCollisions = soa::Join; + using FullMCSGUDCollision = FullMCSGUDCollisions::iterator; + + // init + void init(InitContext&) + { + if (verboseInfo) + printMediumMessage("INIT METHOD"); + + 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}}); + + } // end init + + template + bool isGoodFITtime(C const& coll, float maxFITtime) + { + + // FTOA + if ((std::abs(coll.timeFT0A()) > maxFITtime) && coll.timeFT0A() > -998.) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // FTOC + if ((std::abs(coll.timeFT0C()) > maxFITtime) && coll.timeFT0C() > -998.) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + return true; + } + + template + bool isGoodRCTflag(C const& coll) + { + switch (cutSample.cutRCTflag) { + case 1: + return sgSelector.isCBTOk(coll); + case 2: + return sgSelector.isCBTZdcOk(coll); + case 3: + return sgSelector.isCBTHadronOk(coll); + case 4: + return sgSelector.isCBTHadronZdcOk(coll); + default: + return true; + } + } + + template + bool isGoodROFtime(C const& coll) + { + + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // Occupancy + if (coll.occupancyInTime() > cutSample.cutEvOccupancy) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoCollInTimeRangeStandard + if (cutSample.cutEvTrs && !coll.trs()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoCollInRofStandard + if (cutSample.cutEvTrofs && !coll.trofs()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // kNoHighMultCollInPrevRof + if (cutSample.cutEvHmpr && !coll.hmpr()) + return false; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + return true; + } + + std::vector>> cutMyRequiredITSHits{}; + + void mySetRequireHitsInITSLayers(int8_t minNRequiredHits, std::set requiredLayers) + { + // layer 0 corresponds to the the innermost ITS layer + cutMyRequiredITSHits.push_back(std::make_pair(minNRequiredHits, requiredLayers)); + } + + void mySetITShitsRule(int matching) + { + switch (matching) { + case 0: // Run3ITSibAny + mySetRequireHitsInITSLayers(1, {0, 1, 2}); + break; + case 1: // Run3ITSibTwo + mySetRequireHitsInITSLayers(2, {0, 1, 2}); + break; + case 2: // Run3ITSallAny + mySetRequireHitsInITSLayers(1, {0, 1, 2, 3, 4, 5, 6}); + break; + case 3: // Run3ITSall7Layers + mySetRequireHitsInITSLayers(7, {0, 1, 2, 3, 4, 5, 6}); + break; + default: + LOG(fatal) << "You chose wrong ITS matching"; + break; + } + } + + bool isFulfillsITSHitRequirementsReinstatement(uint8_t itsClusterMap) const + { + constexpr uint8_t kBit = 1; + for (const auto& kITSrequirement : cutMyRequiredITSHits) { + auto hits = std::count_if(kITSrequirement.second.begin(), kITSrequirement.second.end(), [&](auto&& requiredLayer) { return itsClusterMap & (kBit << requiredLayer); }); + if ((kITSrequirement.first == -1) && (hits > 0)) { + return false; // no hits were required in specified layers + } else if (hits < kITSrequirement.first) { + return false; // not enough hits found in specified layers + } + } + return true; + } + + template + bool isGlobalTrackReinstatement(T const& track) + { + // kInAcceptance copy + if (track.pt() < cutGlobalTrack.cutMinPt || track.pt() > cutGlobalTrack.cutMaxPt) + return false; + if (eta(track.px(), track.py(), track.pz()) < cutGlobalTrack.cutMinEta || eta(track.px(), track.py(), track.pz()) > cutGlobalTrack.cutMaxEta) + return false; + // kPrimaryTracks + // GoldenChi2 cut is only for Run 2 + if (std::abs(track.dcaZ()) > cutGlobalTrack.cutMaxDCAz) + return false; + if (cutGlobalTrack.applyPtDependentDCAxy) { + float maxDCA = 0.0182f + 0.0350f / std::pow(track.pt(), 1.01f); + if (std::abs(track.dcaXY()) > maxDCA) + return false; + } else { + if (std::abs(track.dcaXY()) > cutGlobalTrack.cutMaxDCAxy) + return false; + } + // kQualityTrack + // TrackType is always 1 as per definition of processed Run3 AO2Ds + // ITS + if (cutGlobalTrack.cutHasITS && !track.hasITS()) + return false; // ITS refit + if (track.itsNCls() < cutGlobalTrack.cutMinITSnCls) + return false; + if (track.itsChi2NCl() > cutGlobalTrack.cutMaxITSchi2) + return false; + if (!isFulfillsITSHitRequirementsReinstatement(track.itsClusterMap())) + return false; + // TPC + if (cutGlobalTrack.cutHasTPC && !track.hasTPC()) + return false; // TPC refit + if ((track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()) < cutGlobalTrack.cutMinTPCnCls) + return false; // tpcNClsFound() + if (track.tpcNClsCrossedRows() < cutGlobalTrack.cutMinTPCnClsXrows) + return false; + if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < cutGlobalTrack.cutMinTPCnClsXrowsOverNcls) + return false; + if (track.tpcChi2NCl() > cutGlobalTrack.cutMaxTPCchi2) + return false; // TPC chi2 + if (cutGlobalTrack.cutGoodITSTPCmatching) { + if (track.itsChi2NCl() < 0.) + return false; // good ITS-TPC matching means ITS ch2 is not negative + } + // TOF + if (track.hasTOF()) { + if (track.tpcChi2NCl() > cutGlobalTrack.cutMaxTOFchi2) + return false; // TOF chi2 + } + + return true; + } + + template + float findRightMass(T const& trk1, T const& trk2) + // choose the right mass for the tracks based on comparing combined sigma + // good for same-type particles decays + { + float nSigmasTPCsqrt[5]; + nSigmasTPCsqrt[P_ELECTRON] = std::sqrt(trk1.tpcNSigmaEl() * trk1.tpcNSigmaEl() + trk2.tpcNSigmaEl() * trk2.tpcNSigmaEl()); + nSigmasTPCsqrt[P_MUON] = std::sqrt(trk1.tpcNSigmaMu() * trk1.tpcNSigmaMu() + trk2.tpcNSigmaMu() * trk2.tpcNSigmaMu()); + nSigmasTPCsqrt[P_PION] = std::sqrt(trk1.tpcNSigmaPi() * trk1.tpcNSigmaPi() + trk2.tpcNSigmaPi() * trk2.tpcNSigmaPi()); + nSigmasTPCsqrt[P_KAON] = std::sqrt(trk1.tpcNSigmaKa() * trk1.tpcNSigmaKa() + trk2.tpcNSigmaKa() * trk2.tpcNSigmaKa()); + nSigmasTPCsqrt[P_PROTON] = std::sqrt(trk1.tpcNSigmaPr() * trk1.tpcNSigmaPr() + trk2.tpcNSigmaPr() * trk2.tpcNSigmaPr()); + + int enumChoiceTPC = std::distance(std::begin(nSigmasTPCsqrt), + std::min_element(std::begin(nSigmasTPCsqrt), std::end(nSigmasTPCsqrt))); + + return pdg->Mass(trackPDGfromEnum(enumChoiceTPC)); + } + + void processDataSG(FullSGUDCollision const& collision, + FullUDTracks const& tracks) + { + + nSelection = 0; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (!isGoodRCTflag(collision)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (!isGoodROFtime(collision)) + return; + + int gapSide = collision.gapSide(); + int trueGapSide = sgSelector.trueGap(collision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); + if (cutSample.useTrueGap) + gapSide = trueGapSide; + if (gapSide != cutSample.whichGapSide) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (!isGoodFITtime(collision, cutSample.cutFITtime)) + return; + + if (cutSample.useNumContribs && (collision.numContrib() != cutSample.cutNumContribs)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + if (cutSample.useRecoFlag && (collision.flags() != cutSample.cutRecoFlag)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + int countTracksPerCollision = 0; + int countGoodNonPVtracks = 0; + int countGoodPVtracks = 0; + std::vector vecTrkIdx; + // Loop over tracks with selections + for (const auto& track : tracks) { + countTracksPerCollision++; + if (!isGlobalTrackReinstatement(track)) + continue; + if (!track.isPVContributor()) { + countGoodNonPVtracks++; + continue; + } + countGoodPVtracks++; + vecTrkIdx.push_back(track.index()); + } // Loop over tracks with selections + + // Critical selection, without it the rest of the process function will fail + if (countGoodPVtracks != 2) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + const auto& trk1 = tracks.iteratorAt(vecTrkIdx[0]); + const auto& trk2 = tracks.iteratorAt(vecTrkIdx[1]); + + float thisMass = findRightMass(trk1, trk2); + + // prepare lorentz vectors to create system + ROOT::Math::LorentzVector> twoTrackMother, daug[2]; + daug[0].SetPxPyPzE(trk1.px(), trk1.py(), trk1.pz(), energy(thisMass, trk1.px(), trk1.py(), trk1.pz())); + daug[1].SetPxPyPzE(trk2.px(), trk2.py(), trk2.pz(), energy(thisMass, trk2.px(), trk2.py(), trk2.pz())); + twoTrackMother = daug[0] + daug[1]; + float thisPt = pt(twoTrackMother.px(), twoTrackMother.py()); + + // Apply system selections + // invariant mass + if (twoTrackMother.M() < cutPreselect.preselMinInvariantMass || twoTrackMother.M() > cutPreselect.preselMaxInvariantMass) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // system pt + if (cutPreselect.preselUseOppositeSystemPtCut ? thisPt < cutPreselect.preselSystemPtCut : thisPt > cutPreselect.preselSystemPtCut) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // one track momentum + if (daug[0].P() < cutPreselect.preselMinTrackMomentum && daug[1].P() < cutPreselect.preselMinTrackMomentum) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // both tracks momentum + if (cutPreselect.preselUseMinMomentumOnBothTracks && (daug[0].P() < cutPreselect.preselMinTrackMomentum || daug[1].P() < cutPreselect.preselMinTrackMomentum)) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // track in TOF + if (cutPreselect.preselAtLeastOneTOFtrack && (!trk1.hasTOF() && !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + // tracks in TOF + if (cutPreselect.preselBothAreTOFtracks && (!trk1.hasTOF() || !trk2.hasTOF())) + return; + histos.get(HIST("Reco/hSelections"))->Fill(nSelection); + nSelection++; + + float px[2] = {trk1.px(), trk2.px()}; + float py[2] = {trk1.py(), trk2.py()}; + float pz[2] = {trk1.pz(), trk2.pz()}; + int sign[2] = {trk1.sign(), trk2.sign()}; + float dcaxy[2] = {trk1.dcaXY(), trk2.dcaXY()}; + float dcaz[2] = {trk1.dcaZ(), trk2.dcaZ()}; + float trkTimeRes[2] = {trk1.trackTimeRes(), trk2.trackTimeRes()}; + uint32_t itsClusterSizesTrk1 = trk1.itsClusterSizes(); + uint32_t itsClusterSizesTrk2 = trk2.itsClusterSizes(); + float tpcSignal[2] = {trk1.tpcSignal(), trk2.tpcSignal()}; + float tpcEl[2] = {trk1.tpcNSigmaEl(), trk2.tpcNSigmaEl()}; + float tpcMu[2] = {trk1.tpcNSigmaMu(), trk2.tpcNSigmaMu()}; + float tpcPi[2] = {trk1.tpcNSigmaPi(), trk2.tpcNSigmaPi()}; + float tpcKa[2] = {trk1.tpcNSigmaKa(), trk2.tpcNSigmaKa()}; + float tpcPr[2] = {trk1.tpcNSigmaPr(), trk2.tpcNSigmaPr()}; + float tpcIP[2] = {trk1.tpcInnerParam(), trk2.tpcInnerParam()}; + float tofSignal[2] = {trk1.tofSignal(), trk2.tofSignal()}; + float tofEl[2] = {trk1.tofNSigmaEl(), trk2.tofNSigmaEl()}; + float tofMu[2] = {trk1.tofNSigmaMu(), trk2.tofNSigmaMu()}; + float tofPi[2] = {trk1.tofNSigmaPi(), trk2.tofNSigmaPi()}; + float tofKa[2] = {trk1.tofNSigmaKa(), trk2.tofNSigmaKa()}; + float tofPr[2] = {trk1.tofNSigmaPr(), trk2.tofNSigmaPr()}; + float tofEP[2] = {trk1.tofExpMom(), trk2.tofExpMom()}; + float infoZDC[4] = {collision.energyCommonZNA(), collision.energyCommonZNC(), collision.timeZNA(), collision.timeZNC()}; + + 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(), + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), infoZDC[0], infoZDC[1], + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), infoZDC[2], infoZDC[3], + px, py, pz, sign, dcaxy, dcaz, trkTimeRes, + itsClusterSizesTrk1, itsClusterSizesTrk2, + 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); + + PresliceUnsorted partPerMcCollision = aod::udmcparticle::udMcCollisionId; + PresliceUnsorted colPerMcCollision = aod::udcollision::udMcCollisionId; + PresliceUnsorted trackPerMcParticle = aod::udmctracklabel::udMcParticleId; + Preslice trackPerCollision = aod::udtrack::udCollisionId; // sorted preslice used because the pair track-collision is already sorted in processDataSG function + + void processMonteCarlo(aod::UDMcCollisions const& mccollisions, + aod::UDMcParticles const& parts, + FullMCSGUDCollisions const& recolls, + FullMCUDTracks const& trks) + { + // start loop over generated collisions + for (const auto& mccoll : mccollisions) { + + // prepare local variables for output table + int32_t runNumber = -999; + int bc = -999; + int nTrks[3] = {-999, -999, -999}; // totalTracks, numContrib, globalNonPVtracks + float vtxPos[3] = {-999., -999., -999.}; + int recoMode = -999; + int occupancy = -999.; + double hadronicRate = -999.; + int bcSels[8] = {-999, -999, -999, -999, -999, -999, -999, -999}; + float amplitudesFIT[3] = {-999., -999., -999.}; // FT0A, FT0C, FV0 + float timesFIT[3] = {-999., -999., -999.}; // FT0A, FT0C, FV0 + + float px[2] = {-999., -999.}; + float py[2] = {-999., -999.}; + float pz[2] = {-999., -999.}; + int sign[2] = {-999, -999}; + float dcaxy[2] = {-999., -999.}; + float dcaz[2] = {-999., -999.}; + float trkTimeRes[2] = {-999., -999.}; + uint32_t itsClusterSizesTrk1 = 4294967295; + uint32_t itsClusterSizesTrk2 = 4294967295; + float tpcSignal[2] = {-999, -999}; + float tpcEl[2] = {-999, -999}; + float tpcMu[2] = {-999, -999}; + float tpcPi[2] = {-999, -999}; + float tpcKa[2] = {-999, -999}; + float tpcPr[2] = {-999, -999}; + float tpcIP[2] = {-999, -999}; + float tofSignal[2] = {-999, -999}; + float tofEl[2] = {-999, -999}; + float tofMu[2] = {-999, -999}; + float tofPi[2] = {-999, -999}; + float tofKa[2] = {-999, -999}; + float tofPr[2] = {-999, -999}; + float tofEP[2] = {-999, -999}; + + int trueChannel = -1; + bool trueHasRecoColl = false; + float trueMotherX[2] = {-999., -999.}; + float trueMotherY[2] = {-999., -999.}; + float trueMotherZ[2] = {-999., -999.}; + float trueDaugX[2] = {-999., -999.}; + float trueDaugY[2] = {-999., -999.}; + float trueDaugZ[2] = {-999., -999.}; + int trueDaugPdgCode[2] = {-999, -999}; + bool problem = false; + + // find reconstructed collisions associated to the generated collision + auto const& collFromMcColls = recolls.sliceBy(colPerMcCollision, mccoll.globalIndex()); + // check the generated collision was reconstructed + if (collFromMcColls.size() > 0) { // get the truth and reco-level info + trueHasRecoColl = true; + // check there is exactly one reco-level collision associated to generated collision + if (collFromMcColls.size() > 1) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 reco collision. Skipping this event."); + histos.get(HIST("Truth/hTroubles"))->Fill(1); + problem = true; + continue; + } + // 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 = trks.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(); + nTrks[0] = countTracksPerCollision; + nTrks[1] = collFromMcColl.numContrib(); + nTrks[2] = countGoodNonPVtracks; + 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(); + 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 = parts.sliceBy(partPerMcCollision, mccoll.globalIndex()); + int countMothers = 0; + for (const auto& particle : partsFromMcColl) { + // select only mothers with checking if particle has no mother + if (particle.has_mothers()) + continue; + countMothers++; + // check the generated collision does not have more than 2 mothers + if (countMothers > 2) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(2); + problem = true; + break; + } + // 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 + 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) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. 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(); + + // 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() > 1) { + if (verboseInfo) + printLargeMessage("Daughter has more than 1 associated track. Skipping this daughter."); + histos.get(HIST("Truth/hTroubles"))->Fill(4); + problem = true; + continue; + } + // grab the track and fill info for reconstructed track (should be done twice) + 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) { + 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(); + } // daughters + } // 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; + for (const auto& particle : partsFromMcColl) { + // select only tauons with checking if particle has no mother + if (particle.has_mothers()) + continue; + countMothers++; + // check the generated collision does not have more than 2 mothers + if (countMothers > 2) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 2 no mother particles. Breaking the particle loop."); + histos.get(HIST("Truth/hTroubles"))->Fill(12); + problem = true; + break; + } + // fill info for each tau + trueMotherX[countMothers - 1] = particle.px(); + trueMotherY[countMothers - 1] = particle.py(); + trueMotherZ[countMothers - 1] = particle.pz(); + + // get daughters of the tau + 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) { + if (verboseInfo) + printLargeMessage("Truth collision has more than 1 charged daughters of no mother particles. 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(); + } // daughters + } // particles + } // collisions + + // decide the channel and set the variable. Only two cahnnels suported now. + if ((enumMyParticle(trueDaugPdgCode[0]) == P_ELECTRON) && (enumMyParticle(trueDaugPdgCode[1]) == P_ELECTRON)) + trueChannel = CH_EE; + 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))) + trueChannel = CH_EMUPI; + + trueTwoTracks(runNumber, bc, nTrks[0], nTrks[1], nTrks[2], vtxPos[0], vtxPos[1], vtxPos[2], + recoMode, occupancy, hadronicRate, bcSels[0], bcSels[1], bcSels[2], + bcSels[3], bcSels[4], bcSels[5], bcSels[6], bcSels[7], + amplitudesFIT[0], amplitudesFIT[1], amplitudesFIT[2], -999., -999., // no ZDC info in MC + timesFIT[0], timesFIT[1], timesFIT[2], -999., -999., // no ZDC info in MC + px, py, pz, sign, dcaxy, dcaz, trkTimeRes, + itsClusterSizesTrk1, itsClusterSizesTrk2, + tpcSignal, tpcEl, tpcMu, tpcPi, tpcKa, tpcPr, tpcIP, + tofSignal, tofEl, tofMu, tofPi, tofKa, tofPr, tofEP, + trueChannel, trueHasRecoColl, mccoll.posX(), mccoll.posY(), mccoll.posZ(), + trueMotherX, trueMotherY, trueMotherZ, trueDaugX, trueDaugY, trueDaugZ, trueDaugPdgCode, problem); + } // mccollisions + } + PROCESS_SWITCH(TwoTracksEventTableProducer, processMonteCarlo, "Iterate UD tables with simulated data created by SG-Candidate-Producer.", false); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/CMakeLists.txt b/PWGUD/Tasks/CMakeLists.txt index a193e46587e..37811e8dd4e 100644 --- a/PWGUD/Tasks/CMakeLists.txt +++ b/PWGUD/Tasks/CMakeLists.txt @@ -230,7 +230,7 @@ o2physics_add_dpl_workflow(upc-quarkonia-central-barrel COMPONENT_NAME Analysis) o2physics_add_dpl_workflow(test-mc-std-tabs-rl - SOURCES testMCstdTabsRL.cxx + SOURCES testMcStdTabsRl.cxx PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2::ReconstructionDataFormats O2::DetectorsBase O2::DetectorsCommonDataFormats COMPONENT_NAME Analysis) @@ -246,5 +246,15 @@ o2physics_add_dpl_workflow(flow-cumulants-upc o2physics_add_dpl_workflow(flow-correlations-upc SOURCES flowCorrelationsUpc.cxx - PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGCFCore + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore O2Physics::AnalysisCCDB O2Physics::PWGCFCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(analysis-mc-dpm-jet-sg-v3 + SOURCES analysisMCDPMJetSGv3.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore + COMPONENT_NAME Analysis) + +o2physics_add_dpl_workflow(upc-test-rct-tables + SOURCES upcTestRctTables.cxx + PUBLIC_LINK_LIBRARIES O2::Framework O2Physics::AnalysisCore COMPONENT_NAME Analysis) diff --git a/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx b/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx new file mode 100644 index 00000000000..4347871377a --- /dev/null +++ b/PWGUD/Tasks/analysisMCDPMJetSGv3.cxx @@ -0,0 +1,412 @@ +// 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 AnalysisMCDPMJetSGv3.cxx +/// \brief Process MC DPMJet events for inclusive studies. +/// +/// \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" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct AnalysisMCDPMJetSGv3 { + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // TDatabasePDG* fPDG = TDatabasePDG::Instance(); + + Configurable nBinsPt{"nBinsPt", 100, "N bins in pT histo"}; + + // using myCompleteTracks = soa::Join; + // using myFilteredTracks = soa::Filtered; + using BCs = soa::Join; + + Preslice perCollision = aod::track::collisionId; + Preslice perMcCollision = o2::aod::mcparticle::mcCollisionId; + // using MCTCs = soa::Join; + // using MCTC = MCTCs::iterator; + // define abbreviations + using CCs = soa::Join; + using CC = CCs::iterator; + using MCparticles = aod::UDMcParticles::iterator; + using TCs = soa::Join; + // using TCs = soa::Join; + using TC = TCs::iterator; + using LorentzVectorM = ROOT::Math::LorentzVector>; + + double massPion = 0.; + double massKaon = 0.; + double massProton = 0.; + const int codePion = 211; + const int codeKaon = 321; + const int codeProton = 2212; + + void init(InitContext const&) + { + // TParticlePDG* pionPDG = fPDG->GetParticle(codePion); + // if (pionPDG != nullptr) { + // massPion = pionPDG->Mass(); + // } + // TParticlePDG* kaonPDG = fPDG->GetParticle(codeKaon); + // if (kaonPDG != nullptr) { + // massKaon = kaonPDG->Mass(); + // } + // TParticlePDG* protonPDG = fPDG->GetParticle(codeProton); + // if (protonPDG != nullptr) { + // massProton = protonPDG->Mass(); + // } + massPion = o2::constants::physics::MassPionCharged; + massKaon = o2::constants::physics::MassKaonCharged; + massProton = o2::constants::physics::MassProton; + + // define axes you want to use + const AxisSpec axisCounter{10, 0, 10, ""}; + const AxisSpec axisEta{100, -1.5, +1.5, "#eta"}; + const AxisSpec axisPt{5000, 0, 5, "p_{T}"}; + const AxisSpec axisPtSmall{1000, 0, 1, "p_{T}"}; + const AxisSpec axisMass{nBinsPt, 0, 5, "m_{#pi#pi}"}; + const AxisSpec axisMassSmall{nBinsPt, 0, 2, "m_{#pi#pi}"}; + const AxisSpec axisDeltaPt{100, -1.0, +1.0, "#Delta(p_{T})"}; + const AxisSpec axisBC{1000, -10000.0, +10000.0, "BCs"}; + const AxisSpec axisBCext{100000, -10000000.0, +10000000.0, "BCs"}; + const AxisSpec axisCosTheta{100, -1.0, +1.0, "cos#theta"}; + const AxisSpec axisPhi{600, -o2::constants::math::PI, -o2::constants::math::PI, "#varphi"}; + + // create histograms + histos.add("hdEdx", "p vs dE/dx Signal", kTH2F, {{100, 0.0, 3.0}, {1000, 0.0, 2000.0}}); + histos.add("hSigmaPion", "p vs dE/dx sigma pion TPC ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaPionTruth", "p vs dE/dx sigma pion TPC truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaPionTOF", "p vs dE/dx sigma pion TOF ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaPionTruthTOF", "p vs dE/dx sigma pion TOF truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaon", "p vs dE/dx sigma kaon TPC ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaonTruth", "p vs dE/dx sigma kaon TPC truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaonTOF", "p vs dE/dx sigma kaon TOF ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaKaonTruthTOF", "p vs dE/dx sigma kaon TOF truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProton", "p vs dE/dx sigma proton TPC ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProtonTruth", "p vs dE/dx sigma proton TPC truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProtonTOF", "p vs dE/dx sigma proton TOF ", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + histos.add("hSigmaProtonTruthTOF", "p vs dE/dx sigma proton TOF truth", kTH2F, {{300, 0.0, 3.0}, {200, -10.0, 10.0}}); + + histos.add("hVisibleMultiVsGeneratedMulti", "Multiplicity correlation", kTH2F, {{10000, -0.5, 9999.5}, {1000, -0.5, 999.5}}); + + histos.add("eventCounter", "eventCounter", kTH1F, {axisCounter}); + histos.add("ptResolution", "ptResolution", kTH2F, {axisPt, axisDeltaPt}); + + histos.add("ptGeneratedPion", "ptGeneratedPion", kTH1F, {axisPt}); + histos.add("ptGeneratedKaon", "ptGeneratedKaon", kTH1F, {axisPt}); + histos.add("ptGeneratedProton", "ptGeneratedProton", kTH1F, {axisPt}); + histos.add("ptGeneratedPionAxE", "ptGeneratedPionAxE", kTH1F, {axisPt}); + histos.add("ptGeneratedKaonAxE", "ptGeneratedKaonAxE", kTH1F, {axisPt}); + histos.add("ptGeneratedProtonAxE", "ptGeneratedProtonAxE", kTH1F, {axisPt}); + histos.add("ptGeneratedProtonAxEPos", "ptGeneratedProtonAxEPos", kTH1F, {axisPt}); + histos.add("ptGeneratedProtonAxENeg", "ptGeneratedProtonAxENeg", kTH1F, {axisPt}); + histos.add("ptReconstructedPion", "ptReconstructedPion", kTH1F, {axisPt}); + histos.add("ptReconstructedKaon", "ptReconstructedKaon", kTH1F, {axisPt}); + histos.add("ptReconstructedProton", "ptReconstructedProton", kTH1F, {axisPt}); + histos.add("ptReconstructedProtonPos", "ptReconstructedProtonPos", kTH1F, {axisPt}); + histos.add("ptReconstructedProtonNeg", "ptReconstructedProtonNeg", kTH1F, {axisPt}); + histos.add("ptReconstructedPionTOF", "ptReconstructedPionTOF", kTH1F, {axisPt}); + histos.add("ptReconstructedKaonTOF", "ptReconstructedKaonTOF", kTH1F, {axisPt}); + histos.add("ptReconstructedProtonTOF", "ptReconstructedProtonTOF", kTH1F, {axisPt}); + + histos.add("allreconstructedPFPion", "allreconstructedPFPion", kTH1F, {axisPt}); + histos.add("allreconstructedPFKaon", "allreconstructedPFKaon", kTH1F, {axisPt}); + histos.add("allreconstructedPFProton", "allreconstructedPFProton", kTH1F, {axisPt}); + histos.add("allreconstructedPFProtonPos", "allreconstructedPFProtonPos", kTH1F, {axisPt}); + histos.add("allreconstructedPFProtonNeg", "allreconstructedPFProtonNeg", kTH1F, {axisPt}); + histos.add("allreconstructedPFPionTOF", "allreconstructedPFPionTOF", kTH1F, {axisPt}); + histos.add("allreconstructedPFKaonTOF", "allreconstructedPFKaonTOF", kTH1F, {axisPt}); + histos.add("allreconstructedPFProtonTOF", "allreconstructedPFProtonTOF", kTH1F, {axisPt}); + + histos.add("numberOfRecoCollisions", "numberOfRecoCollisions", kTH1F, {{100, -0.5f, 99.5f}}); + histos.add("numberOfRecoCollisions2", "numberOfRecoCollisions2", kTH1F, {{100, -0.5f, 99.5f}}); + histos.add("numberOfTracksMC", "numberOfTracksMC", kTH1F, {{100, -0.5f, 99.5f}}); + histos.add("numberOfTracksReco", "numberOfTracksReco", kTH1F, {{100, -0.5f, 99.5f}}); + + histos.add("bcResolution", "bcResolution", kTH1F, {axisBC}); + histos.add("mcbcHistogram", "mcbcHistogram", kTH1F, {axisBCext}); + histos.add("bcHistogram", "bcHistogram", kTH1F, {axisBCext}); + histos.add("mcbcModuloOrbitHistogram", "mcbcModuloOrbitHistogram", kTH1F, {axisBC}); + histos.add("bcModuloOrbitHistogram", "bcModuloOrbitHistogram", kTH1F, {axisBC}); + } + //----------------------------------------------------------------------------------------------------------------------- + void processSim(aod::UDMcCollision const& mcCollision, aod::UDMcParticles const& mcParticles) + { + // histos.fill(HIST("eventCounter"), 0.5); + + // auto massPion = 0.; + // TParticlePDG pionPDG = fPDG->GetParticle(codePion); + // massPion = pionPDG.Mass(); + // auto massKaon = 0.; + // TParticlePDG kaonPDG = fPDG->GetParticle(codeKaon); + // massKaon = kaonPDG.Mass(); + // auto massProton = 0.; + // TParticlePDG protonPDG = fPDG->GetParticle(codeProton); + // massProton = protonPDG.Mass(); + histos.fill(HIST("numberOfTracksMC"), mcParticles.size()); + histos.fill(HIST("eventCounter"), mcCollision.size()); + // LOGF(info, "New event! mcParticles.size() = %d", mcParticles.size()); + + int counterMC = 0; + int counter = 0; + for (const auto& mcParticle : mcParticles) { + if (!mcParticle.isPhysicalPrimary()) + continue; + counterMC += 1; + // if(mcParticle.isPhysicalPrimary()) counterMC += 1; + LorentzVectorM protoMC( + mcParticle.px(), + mcParticle.py(), + mcParticle.pz(), + massPion); + double etaMax = 0.8; + double ptMin = 0.1; + if (std::fabs(protoMC.Eta()) < etaMax && protoMC.Pt() > ptMin) { + counter += 1; + } + if (!mcParticle.isPhysicalPrimary()) + continue; + // if(mcParticle.isPhysicalPrimary() && fabs(mcParticle.eta())<0.9){ // do this in the context of the MC loop ! (context matters!!!) + // LorentzVectorM pMC; + LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massPion); + if (std::abs(mcParticle.pdgCode()) == codePion) { + // histos.fill(HIST("ptGeneratedPion"), mcParticle.pt()); + // LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massPion); + histos.fill(HIST("ptGeneratedPion"), pMC.Pt()); + } + if (std::abs(mcParticle.pdgCode()) == codeKaon) { + // histos.fill(HIST("ptGenerateKaon"), mcParticle.pt()); + // LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massKaon); + pMC.SetM(massKaon); + histos.fill(HIST("ptGeneratedKaon"), pMC.Pt()); + } + if (std::abs(mcParticle.pdgCode()) == codeProton) { + // histos.fill(HIST("ptGeneratedProton"), mcParticle.pt()); + // LorentzVectorM pMC(mcParticle.px(), mcParticle.py(), mcParticle.pz(), massProton); + pMC.SetM(massProton); + histos.fill(HIST("ptGeneratedProton"), pMC.Pt()); + } + double yMax = 0.8; + if (std::abs(pMC.Rapidity()) < yMax) { + if (std::abs(mcParticle.pdgCode()) == codePion) + histos.fill(HIST("ptGeneratedPionAxE"), pMC.Pt()); + if (std::abs(mcParticle.pdgCode()) == codeKaon) + histos.fill(HIST("ptGeneratedKaonAxE"), pMC.Pt()); + if (std::abs(mcParticle.pdgCode()) == codeProton) + histos.fill(HIST("ptGeneratedProtonAxE"), pMC.Pt()); + if (mcParticle.pdgCode() == codeProton) { + histos.fill(HIST("ptGeneratedProtonAxEPos"), pMC.Pt()); + } else { + histos.fill(HIST("ptGeneratedProtonAxENeg"), pMC.Pt()); + } + } + } + histos.fill(HIST("hVisibleMultiVsGeneratedMulti"), counterMC, counter); + } + PROCESS_SWITCH(AnalysisMCDPMJetSGv3, processSim, "processSim", true); + + void processReco(CC const& collision, + TCs const& tracks, + // aod::UDMcCollisions const& /*mccollisions*/, + aod::UDMcParticles const& mcParticles) + { + histos.fill(HIST("numberOfRecoCollisions"), 88.); // number of times coll was reco-ed + histos.fill(HIST("numberOfRecoCollisions"), collision.size()); // number of times coll was reco-ed + histos.fill(HIST("numberOfRecoCollisions2"), mcParticles.size()); + Partition pvContributors = aod::udtrack::isPVContributor == true; + pvContributors.bindTable(tracks); + + // auto massPion = 0.; + // TParticlePDG pionPDG = fPDG->GetParticle(codePion); + // massPion = pionPDG.Mass(); + // auto massKaon = 0.; + // TParticlePDG kaonPDG = fPDG->GetParticle(codeKaon); + // massKaon = kaonPDG.Mass(); + // auto massProton = 0.; + // TParticlePDG protonPDG = fPDG->GetParticle(codeProton); + // massProton = protonPDG.Mass(); + + histos.fill(HIST("numberOfTracksReco"), tracks.size()); + // double etaMax = 0.8; + double yMax = 0.8; + double sigmaMax = 3.; + double ptMin = 0.1; + int nFindableMin = 70; + double dcaZlimit = 2.; + + // int counter = 0; + for (const auto& track : tracks) { + if (track.isPVContributor()) { + int nFindable = track.tpcNClsFindable(); + if (nFindable < nFindableMin) { + continue; + } + // int NMinusFound = track.tpcNClsFindableMinusFound(); + // int NCluster = NFindable - NMinusFound; + // if (NCluster < 70) { + // continue; + // } + if (track.pt() < ptMin) { + continue; + } + if (!(std::abs(track.dcaZ()) < dcaZlimit)) { + continue; + } + double dcaLimit = 0.0105 + 0.035 / std::pow(track.pt(), 1.1); + if (!(std::abs(track.dcaXY()) < dcaLimit)) { + continue; + } + + double momentum = std::sqrt(track.px() * track.px() + track.py() * track.py() + track.pz() * track.pz()); + double dEdx = track.tpcSignal(); + histos.fill(HIST("hdEdx"), momentum, dEdx); + + LorentzVectorM pion(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged); + LorentzVectorM kaon(track.px(), track.py(), track.pz(), o2::constants::physics::MassKaonCharged); + LorentzVectorM proton(track.px(), track.py(), track.pz(), o2::constants::physics::MassProton); + auto nSigmaPi = -999.; + auto nSigmaKa = -999.; + auto nSigmaPr = -999.; + auto nSigmaPiTOF = -999.; + auto nSigmaKaTOF = -999.; + auto nSigmaPrTOF = -999.; + // This section makes templates + if (track.hasTPC()) { + nSigmaPi = track.tpcNSigmaPi(); + nSigmaKa = track.tpcNSigmaKa(); + nSigmaPr = track.tpcNSigmaPr(); + if (std::abs(nSigmaPi) < sigmaMax && std::abs(pion.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaPion"), track.pt(), nSigmaPi); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + // if(abs(mcParticle.pdgCode())==codePion && mcParticle.isPhysicalPrimary()) howManyPionsHavePionMCandPrimaries += 1; + if (std::abs(mcParticle.pdgCode()) == codePion) { + histos.fill(HIST("hSigmaPionTruth"), track.pt(), nSigmaPi); + histos.fill(HIST("allreconstructedPFPion"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedPion"), track.pt()); + } + } + } + } + if (std::abs(nSigmaKa) < sigmaMax && std::abs(kaon.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaKaon"), track.pt(), nSigmaKa); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeKaon) { + histos.fill(HIST("hSigmaKaonTruth"), track.pt(), nSigmaKa); + histos.fill(HIST("allreconstructedPFKaon"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedKaon"), track.pt()); + } + } + } + } + if (std::abs(nSigmaPr) < sigmaMax && std::abs(proton.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaProton"), track.pt(), nSigmaPr); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeProton) { + histos.fill(HIST("hSigmaProtonTruth"), track.pt(), nSigmaPr); + histos.fill(HIST("allreconstructedPFProton"), track.pt()); + if (mcParticle.pdgCode() == codeProton) { + histos.fill(HIST("allreconstructedPFProtonPos"), track.pt()); + } else { + histos.fill(HIST("allreconstructedPFProtonNeg"), track.pt()); + } + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedProton"), track.pt()); + if (mcParticle.pdgCode() == codeProton) { + histos.fill(HIST("ptReconstructedProtonPos"), track.pt()); + } else { + histos.fill(HIST("ptReconstructedProtonNeg"), track.pt()); + } + } + } + } + } + } + if (track.hasTPC() && track.hasTOF()) { + // if (track.hasTOF()) { + nSigmaPiTOF = track.tofNSigmaPi(); + nSigmaKaTOF = track.tofNSigmaKa(); + nSigmaPrTOF = track.tofNSigmaPr(); + if (std::abs(nSigmaPiTOF) < sigmaMax && std::abs(pion.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaPionTOF"), track.pt(), nSigmaPiTOF); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + // if(abs(mcParticle.pdgCode())==codePion && mcParticle.isPhysicalPrimary()) howManyPionsHavePionMCandPrimaries += 1; + if (std::abs(mcParticle.pdgCode()) == codePion) { + histos.fill(HIST("hSigmaPionTruthTOF"), track.pt(), nSigmaPiTOF); + histos.fill(HIST("allreconstructedPFPionTOF"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedPionTOF"), track.pt()); + } + } + } + } + if (std::abs(nSigmaKaTOF) < sigmaMax && std::abs(kaon.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaKaonTOF"), track.pt(), nSigmaKaTOF); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeKaon) { + histos.fill(HIST("hSigmaKaonTruthTOF"), track.pt(), nSigmaKaTOF); + histos.fill(HIST("allreconstructedPFKaonTOF"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedKaonTOF"), track.pt()); + } + } + } + } + if (std::abs(nSigmaPrTOF) < sigmaMax && std::abs(proton.Rapidity()) < yMax) { + histos.fill(HIST("hSigmaProtonTOF"), track.pt(), nSigmaPrTOF); + if (track.has_udMcParticle()) { + auto mcParticle = track.udMcParticle(); + if (std::abs(mcParticle.pdgCode()) == codeProton) { + histos.fill(HIST("hSigmaProtonTruthTOF"), track.pt(), nSigmaPrTOF); + histos.fill(HIST("allreconstructedPFProtonTOF"), track.pt()); + if (mcParticle.isPhysicalPrimary()) { + histos.fill(HIST("ptReconstructedProtonTOF"), track.pt()); + } + } + } + } + } + // counter++; + // histos.fill(HIST("hVisibleMultiVsGeneratedMulti"), counterMC, counter); + // histos.fill(HIST("hVisibleMultiVsGeneratedMulti"), mcParticles.size(), counter); + } + } // track loop + + // } // collision loop + } + PROCESS_SWITCH(AnalysisMCDPMJetSGv3, processReco, "processReco", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx index 14ffcc415a4..0f4cbd0be70 100644 --- a/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx +++ b/PWGUD/Tasks/exclusiveRhoTo4Pi.cxx @@ -13,26 +13,31 @@ /// \brief Task for analyzing exclusive rho decays to 4 pions /// \author Anantha Padmanabhan M Nair -#include -#include -#include -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoA.h" -#include "Framework/ASoAHelpers.h" -#include "PWGUD/DataModel/UDTables.h" #include "PWGUD/Core/SGSelector.h" -#include "PWGUD/Core/UDHelpers.h" #include "PWGUD/Core/SGTrackSelector.h" +#include "PWGUD/Core/UDHelpers.h" +#include "PWGUD/DataModel/UDTables.h" + #include "Common/DataModel/PIDResponse.h" -#include -#include -#include "Math/Vector4D.h" -#include "Math/Vector3D.h" -#include "Math/GenVector/Boost.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 using namespace std; using namespace o2; @@ -40,132 +45,135 @@ using namespace o2::aod; using namespace o2::framework; using namespace o2::framework::expressions; +using PtEtaPhiMVector = ROOT::Math::PtEtaPhiMVector; +using Boost = ROOT::Math::Boost; +using XYZVectorF = ROOT::Math::XYZVectorF; +using PxPyPzEVector = ROOT::Math::PxPyPzEVector; +using PxPyPzMVector = ROOT::Math::PxPyPzMVector; + namespace o2::aod { namespace branch { +// Run Number +DECLARE_SOA_COLUMN(RunNumber, runNumber, int); +// Check UPC mode +DECLARE_SOA_COLUMN(IfCheckUPCmode, ifCheckUPCmode, uint16_t); // vertex Position DECLARE_SOA_COLUMN(PosX, posX, double); DECLARE_SOA_COLUMN(PosY, posY, double); DECLARE_SOA_COLUMN(PosZ, posZ, double); - // FIT signals DECLARE_SOA_COLUMN(Fv0signal, fv0signal, double); DECLARE_SOA_COLUMN(Ft0asignal, ft0asignal, double); DECLARE_SOA_COLUMN(Ft0csignal, ft0csignal, double); DECLARE_SOA_COLUMN(Fddasignal, fddasignal, double); DECLARE_SOA_COLUMN(Fddcsignal, fddcsignal, double); - // FIT times DECLARE_SOA_COLUMN(TimeFv0, timeFv0, double); DECLARE_SOA_COLUMN(TimeFt0a, timeFt0a, double); DECLARE_SOA_COLUMN(TimeFt0c, timeFt0c, double); DECLARE_SOA_COLUMN(TimeFdda, timeFdda, double); DECLARE_SOA_COLUMN(TimeFddc, timeFddc, double); - // ZDC times DECLARE_SOA_COLUMN(TimeZna, timeZna, double); DECLARE_SOA_COLUMN(TimeZnc, timeZnc, double); - // Occupancy DECLARE_SOA_COLUMN(Occupancy, occupancy, double); - -// DCA +// Atleast one pion has TOF +DECLARE_SOA_COLUMN(HasAtLeastOneTOF, hasAtLeastOneTOF, bool); +// DCA XY DECLARE_SOA_COLUMN(Dcaxy1, dcaxy1, double); DECLARE_SOA_COLUMN(Dcaxy2, dcaxy2, double); DECLARE_SOA_COLUMN(Dcaxy3, dcaxy3, double); DECLARE_SOA_COLUMN(Dcaxy4, dcaxy4, double); - +// DCA Z DECLARE_SOA_COLUMN(Dcaz1, dcaz1, double); DECLARE_SOA_COLUMN(Dcaz2, dcaz2, double); DECLARE_SOA_COLUMN(Dcaz3, dcaz3, double); DECLARE_SOA_COLUMN(Dcaz4, dcaz4, double); - // TPC nSigmaPi DECLARE_SOA_COLUMN(TpcNsigmaPi1, tpcNsigmaPi1, double); DECLARE_SOA_COLUMN(TpcNsigmaPi2, tpcNsigmaPi2, double); DECLARE_SOA_COLUMN(TpcNsigmaPi3, tpcNsigmaPi3, double); DECLARE_SOA_COLUMN(TpcNsigmaPi4, tpcNsigmaPi4, double); - // TPC nSigmaKa DECLARE_SOA_COLUMN(TpcNsigmaKa1, tpcNsigmaKa1, double); DECLARE_SOA_COLUMN(TpcNsigmaKa2, tpcNsigmaKa2, double); DECLARE_SOA_COLUMN(TpcNsigmaKa3, tpcNsigmaKa3, double); DECLARE_SOA_COLUMN(TpcNsigmaKa4, tpcNsigmaKa4, double); - // TPC nSigmaPr DECLARE_SOA_COLUMN(TpcNsigmaPr1, tpcNsigmaPr1, double); DECLARE_SOA_COLUMN(TpcNsigmaPr2, tpcNsigmaPr2, double); DECLARE_SOA_COLUMN(TpcNsigmaPr3, tpcNsigmaPr3, double); DECLARE_SOA_COLUMN(TpcNsigmaPr4, tpcNsigmaPr4, double); - // TPC nSigmaEl DECLARE_SOA_COLUMN(TpcNsigmaEl1, tpcNsigmaEl1, double); DECLARE_SOA_COLUMN(TpcNsigmaEl2, tpcNsigmaEl2, double); DECLARE_SOA_COLUMN(TpcNsigmaEl3, tpcNsigmaEl3, double); DECLARE_SOA_COLUMN(TpcNsigmaEl4, tpcNsigmaEl4, double); - // TPC nSigmaMu DECLARE_SOA_COLUMN(TpcNsigmaMu1, tpcNsigmaMu1, double); DECLARE_SOA_COLUMN(TpcNsigmaMu2, tpcNsigmaMu2, double); DECLARE_SOA_COLUMN(TpcNsigmaMu3, tpcNsigmaMu3, double); DECLARE_SOA_COLUMN(TpcNsigmaMu4, tpcNsigmaMu4, double); - // TPC Chi2 DECLARE_SOA_COLUMN(TpcChi21, tpcChi21, double); DECLARE_SOA_COLUMN(TpcChi22, tpcChi22, double); DECLARE_SOA_COLUMN(TpcChi23, tpcChi23, double); DECLARE_SOA_COLUMN(TpcChi24, tpcChi24, double); - // TPC NClsFindable DECLARE_SOA_COLUMN(TpcNClsFindable1, tpcNClsFindable1, double); DECLARE_SOA_COLUMN(TpcNClsFindable2, tpcNClsFindable2, double); DECLARE_SOA_COLUMN(TpcNClsFindable3, tpcNClsFindable3, double); DECLARE_SOA_COLUMN(TpcNClsFindable4, tpcNClsFindable4, double); - // ITS Chi2 DECLARE_SOA_COLUMN(ItsChi21, itsChi21, double); DECLARE_SOA_COLUMN(ItsChi22, itsChi22, double); DECLARE_SOA_COLUMN(ItsChi23, itsChi23, double); DECLARE_SOA_COLUMN(ItsChi24, itsChi24, double); - // PionPt DECLARE_SOA_COLUMN(PionPt1, pionPt1, double); DECLARE_SOA_COLUMN(PionPt2, pionPt2, double); DECLARE_SOA_COLUMN(PionPt3, pionPt3, double); DECLARE_SOA_COLUMN(PionPt4, pionPt4, double); - // Pion Eta DECLARE_SOA_COLUMN(PionEta1, pionEta1, double); DECLARE_SOA_COLUMN(PionEta2, pionEta2, double); DECLARE_SOA_COLUMN(PionEta3, pionEta3, double); DECLARE_SOA_COLUMN(PionEta4, pionEta4, double); - // Pion Phi DECLARE_SOA_COLUMN(PionPhi1, pionPhi1, double); DECLARE_SOA_COLUMN(PionPhi2, pionPhi2, double); DECLARE_SOA_COLUMN(PionPhi3, pionPhi3, double); DECLARE_SOA_COLUMN(PionPhi4, pionPhi4, double); - // Pion Rapidity DECLARE_SOA_COLUMN(PionRapidity1, pionRapidity1, double); DECLARE_SOA_COLUMN(PionRapidity2, pionRapidity2, double); DECLARE_SOA_COLUMN(PionRapidity3, pionRapidity3, double); DECLARE_SOA_COLUMN(PionRapidity4, pionRapidity4, double); - +// Four Pion Pt, Eta, Phi Rapidity DECLARE_SOA_COLUMN(FourPionPt, fourPionPt, double); DECLARE_SOA_COLUMN(FourPionEta, fourPionEta, double); DECLARE_SOA_COLUMN(FourPionPhi, fourPionPhi, double); DECLARE_SOA_COLUMN(FourPionRapidity, fourPionRapidity, double); - DECLARE_SOA_COLUMN(FourPionMass, fourPionMass, double); +// Collin-Soper Angles DECLARE_SOA_COLUMN(FourPionPhiPair1, fourPionPhiPair1, double); DECLARE_SOA_COLUMN(FourPionPhiPair2, fourPionPhiPair2, double); +DECLARE_SOA_COLUMN(FourPionPhiPair3, fourPionPhiPair3, double); +DECLARE_SOA_COLUMN(FourPionPhiPair4, fourPionPhiPair4, double); DECLARE_SOA_COLUMN(FourPionCosThetaPair1, fourPionCosThetaPair1, double); DECLARE_SOA_COLUMN(FourPionCosThetaPair2, fourPionCosThetaPair2, double); +DECLARE_SOA_COLUMN(FourPionCosThetaPair3, fourPionCosThetaPair3, double); +DECLARE_SOA_COLUMN(FourPionCosThetaPair4, fourPionCosThetaPair4, double); } // namespace branch DECLARE_SOA_TABLE(SignalData, "AOD", "signalData", + branch::RunNumber, + + branch::IfCheckUPCmode, + branch::PosX, branch::PosY, branch::PosZ, @@ -186,6 +194,8 @@ DECLARE_SOA_TABLE(SignalData, "AOD", "signalData", branch::Occupancy, + branch::HasAtLeastOneTOF, + branch::Dcaxy1, branch::Dcaxy2, branch::Dcaxy3, @@ -263,139 +273,18 @@ DECLARE_SOA_TABLE(SignalData, "AOD", "signalData", branch::FourPionMass, branch::FourPionPhiPair1, branch::FourPionPhiPair2, + branch::FourPionPhiPair3, + branch::FourPionPhiPair4, branch::FourPionCosThetaPair1, - branch::FourPionCosThetaPair2); + branch::FourPionCosThetaPair2, + branch::FourPionCosThetaPair3, + branch::FourPionCosThetaPair4); DECLARE_SOA_TABLE(BkgroundData, "AOD", "bkgroundData", + branch::RunNumber, - branch::PosX, - branch::PosY, - branch::PosZ, - - branch::Fv0signal, - branch::Ft0asignal, - branch::Ft0csignal, - branch::Fddasignal, - branch::Fddcsignal, - - branch::TimeFv0, - branch::TimeFt0a, - branch::TimeFt0c, - branch::TimeFdda, - branch::TimeFddc, - branch::TimeZna, - branch::TimeZnc, - - branch::Occupancy, - - branch::Dcaxy1, - branch::Dcaxy2, - branch::Dcaxy3, - branch::Dcaxy4, - - branch::Dcaz1, - branch::Dcaz2, - branch::Dcaz3, - branch::Dcaz4, - - branch::TpcNsigmaPi1, - branch::TpcNsigmaPi2, - branch::TpcNsigmaPi3, - branch::TpcNsigmaPi4, + branch::IfCheckUPCmode, - branch::TpcNsigmaKa1, - branch::TpcNsigmaKa2, - branch::TpcNsigmaKa3, - branch::TpcNsigmaKa4, - - branch::TpcNsigmaPr1, - branch::TpcNsigmaPr2, - branch::TpcNsigmaPr3, - branch::TpcNsigmaPr4, - - branch::TpcNsigmaEl1, - branch::TpcNsigmaEl2, - branch::TpcNsigmaEl3, - branch::TpcNsigmaEl4, - - branch::TpcNsigmaMu1, - branch::TpcNsigmaMu2, - branch::TpcNsigmaMu3, - branch::TpcNsigmaMu4, - - branch::TpcChi21, - branch::TpcChi22, - branch::TpcChi23, - branch::TpcChi24, - - branch::TpcNClsFindable1, - branch::TpcNClsFindable2, - branch::TpcNClsFindable3, - branch::TpcNClsFindable4, - - branch::ItsChi21, - branch::ItsChi22, - branch::ItsChi23, - branch::ItsChi24, - - branch::PionPt1, - branch::PionPt2, - branch::PionPt3, - branch::PionPt4, - - branch::PionEta1, - branch::PionEta2, - branch::PionEta3, - branch::PionEta4, - - branch::PionPhi1, - branch::PionPhi2, - branch::PionPhi3, - branch::PionPhi4, - - branch::PionRapidity1, - branch::PionRapidity2, - branch::PionRapidity3, - branch::PionRapidity4, - - branch::FourPionPt, - branch::FourPionEta, - branch::FourPionPhi, - branch::FourPionRapidity, - branch::FourPionMass); - -DECLARE_SOA_TABLE(MCgen, "AOD", "MCgen", - branch::PionPt1, - branch::PionPt2, - branch::PionPt3, - branch::PionPt4, - - branch::PionEta1, - branch::PionEta2, - branch::PionEta3, - branch::PionEta4, - - branch::PionPhi1, - branch::PionPhi2, - branch::PionPhi3, - branch::PionPhi4, - - branch::PionRapidity1, - branch::PionRapidity2, - branch::PionRapidity3, - branch::PionRapidity4, - - branch::FourPionPt, - branch::FourPionEta, - branch::FourPionPhi, - branch::FourPionRapidity, - branch::FourPionMass, - branch::FourPionPhiPair1, - branch::FourPionPhiPair2, - branch::FourPionCosThetaPair1, - branch::FourPionCosThetaPair2); - -DECLARE_SOA_TABLE(SignalMCreco, "AOD", "SignalMCreco", branch::PosX, branch::PosY, branch::PosZ, @@ -416,6 +305,8 @@ DECLARE_SOA_TABLE(SignalMCreco, "AOD", "SignalMCreco", branch::Occupancy, + branch::HasAtLeastOneTOF, + branch::Dcaxy1, branch::Dcaxy2, branch::Dcaxy3, @@ -490,383 +381,219 @@ DECLARE_SOA_TABLE(SignalMCreco, "AOD", "SignalMCreco", branch::FourPionEta, branch::FourPionPhi, branch::FourPionRapidity, - branch::FourPionMass, - branch::FourPionPhiPair1, - branch::FourPionPhiPair2, - branch::FourPionCosThetaPair1, - branch::FourPionCosThetaPair2); + branch::FourPionMass); } // namespace o2::aod -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// struct ExclusiveRhoTo4Pi { SGSelector sgSelector; - int rhoPrime = 30113; + // Defining constants int numFourPionTracks = 4; int numPiPlus = 2; int numPiMinus = 2; float zeroPointEight = 0.8; + double mRho0 = 0.77526; // GeV/c^2 + // Run Numbers + static int runNos[113]; + static int numRunNums; + // Derived Data Produces sigFromData; Produces bkgFromData; - Produces generatedMC; - Produces sigFromMC; - - HistogramRegistry histosData{"histosData", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry histosMCgen{"histosMCgen", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - HistogramRegistry histosMCreco{"histosMCreco", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; - - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + // Histogram Registry + HistogramRegistry histosData{"Data", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + HistogramRegistry histosCounter{"counters", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + // Configurable Event parameters + Configurable ifCheckUPCmode{"ifCheckUPCmode", false, "Enable UPC reconstruction only"}; Configurable vZCut{"vZCut", 10., "Vertex Cut"}; Configurable fv0Cut{"fv0Cut", 50., "FV0A threshold"}; - Configurable ft0aCut{"ft0aCut", 150., "FT0A threshold"}; + Configurable ft0aCut{"ft0aCut", 50., "FT0A threshold"}; Configurable ft0cCut{"ft0cCut", 50., "FT0C threshold"}; - Configurable zdcCut{"zdcCut", 1., "ZDC threshold"}; - // Configurable occupancyCut{"occupancyCut", 1000, "Occupancy Cut"}; - - Configurable pvCut{"pvCut", 1.0, "Use Only PV tracks"}; + Configurable zdcCut{"zdcCut", 0., "ZDC threshold"}; Configurable numPVContrib{"numPVContrib", 4, "Number of PV Contributors"}; - Configurable dcaZcut{"dcaZcut", 2, "dcaZ cut"}; - Configurable dcaXYcut{"dcaXYcut", 0, "dcaXY cut"}; - Configurable tpcChi2Cut{"tpcChi2Cut", 4, "Max tpcChi2NCl"}; - Configurable tpcNClsFindableCut{"tpcNClsFindableCut", 70, "Min tpcNClsFindable"}; - Configurable itsChi2Cut{"itsChi2Cut", 36, "Max itsChi2NCl"}; - Configurable etaCut{"etaCut", 0.9, "Track Pseudorapidity"}; + Configurable sbpCut{"sbpCut", 1, "Sbp"}; + Configurable itsROFbCut{"itsROFbCut", 1, "itsROFbCut"}; + Configurable vtxITSTPCcut{"vtxITSTPCcut", 1, "vtxITSTPCcut"}; + Configurable tfbCut{"tfbCut", 1, "tfbCut"}; + // Configurable Track parameters + Configurable useOnlyPVtracks{"useOnlyPVtracks", true, "Use Only PV tracks"}; Configurable pTcut{"pTcut", 0.15, "Track Pt"}; - + Configurable etaCut{"etaCut", 0.9, "Track Pseudorapidity"}; + Configurable dcaXYcut{"dcaXYcut", 0, "dcaXY cut"}; + Configurable dcaZcut{"dcaZcut", 2, "dcaZ cut"}; + Configurable useITStracksOnly{"useITStracksOnly", true, "only use tracks with hit in ITS"}; + Configurable useTPCtracksOnly{"useTPCtracksOnly", true, "only use tracks with hit in TPC"}; + Configurable itsChi2NClsCut{"itsChi2NClsCut", 36, "ITS Chi2NCls"}; + Configurable tpcChi2NClsCut{"tpcChi2NClsCut", 4.0, "TPC Chi2NCls"}; + Configurable tpcNClsFindableCut{"tpcNClsFindableCut", 70, "Min TPC Findable Clusters"}; + // Configurable PID parameters + Configurable useTOF{"useTOF", true, "if track has TOF use TOF"}; Configurable nSigmaTPCcut{"nSigmaTPCcut", 3, "TPC cut"}; Configurable nSigmaTOFcut{"nSigmaTOFcut", 3, "TOF cut"}; - + // Configurable Rho parameters Configurable rhoRapCut{"rhoRapCut", 0.5, "Max abs Rapidity of rho"}; Configurable rhoPtCut{"rhoPtCut", 0.15, "Min Pt of rho"}; + Configurable rhoMassMin{"rhoMassMin", 1, "Min Mass of rho"}; + Configurable rhoMassMax{"rhoMassMax", 2.5, "Max Mass of rho"}; + // Axis Configurations + ConfigurableAxis pTAxis{"pTAxis", {1000, 0, 1}, "Axis for pT histograms"}; + ConfigurableAxis etaAxis{"etaAxis", {1000, -1.1, 1.1}, "Axis for Eta histograms"}; + ConfigurableAxis rapidityAxis{"rapidityAxis", {1000, -2.5, 2.5}, "Axis for Rapidity histograms"}; + ConfigurableAxis invMassAxis{"invMassAxis", {1000, 1, 2.5}, "Axis for Phi histograms"}; + ConfigurableAxis phiAxis{"phiAxis", {360, -1 * o2::constants::math::PI, o2::constants::math::PI}, "Axis for Phi histograms"}; + ConfigurableAxis cosThetaAxis{"cosThetaAxis", {360, -1, 1}, "Axis for cos Theta histograms"}; - Configurable nBinsPt{"nBinsPt", 1000, "Number of bins for pT"}; - Configurable nBinsInvariantMass{"nBinsInvariantMass", 1000, "Number of bins for Invariant Mass"}; - Configurable invariantMassMin{"invariantMassMin", 0.8, "Minimum Invariant Mass"}; - Configurable invariantMassMax{"invariantMassMax", 2.5, "Maximum Invariant Mass"}; - Configurable nBinsRapidity{"nBinsRapidity", 1000, "Number of bins for Rapidity"}; - Configurable nBinsPhi{"nBinsPhi", 360, "Number of bins for Phi"}; - Configurable nBinsCosTheta{"nBinsCosTheta", 360, "Number of bins for cos Theta"}; - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - // Begin of Init Function----------------------------------------------------------------------------------------------------------------------------------------------------- void init(InitContext const&) { - - histosData.add("GapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); - histosData.add("TrueGapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); - histosData.add("EventCounts", "Total Events; Events", kTH1F, {{10, 0, 10}}); - histosData.add("vertexZ", "Vertex Z; Vertex Z [cm]; Counts", kTH1F, {{1000, -20, 20}}); - histosData.add("occupancy", "Occupancy; Occupancy; Counts", kTH1F, {{1500, 0, 1500}}); - histosData.add("dcaXY", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{10000, -5, 5}}); - histosData.add("dcaZ", "dcaZ; dcaZ [cm]; Counts", kTH1F, {{10000, -10, 10}}); - histosData.add("tpcChi2NCl", "TPC Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); - histosData.add("itsChi2NCl", "ITS Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); - histosData.add("tpcNClsFindable", "TPC N Cls Findable; N Cls Findable; Counts", kTH1F, {{200, 0, 200}}); - - // TPC nSigma - histosData.add("tpcNSigmaPi_WTS", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaPi_WTS_PID_Pi", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - - // TPC nSigma of other particles with selected pion tracks - histosData.add("tpcNSigmaKa_WTS_PID_Pi", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaPr_WTS_PID_Pi", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaEl_WTS_PID_Pi", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tpcNSigmaMu_WTS_PID_Pi", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - - // TOF nSigma - histosData.add("tofNSigmaPi_WTS", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaPi_WTS_PID_Pi", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - - // TOF nSigma of other particles with selected pion tracks - histosData.add("tofNSigmaKa_WTS_PID_Pi", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaPr_WTS_PID_Pi", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaEl_WTS_PID_Pi", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosData.add("tofNSigmaMu_WTS_PID_Pi", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - - // Track Transverse Momentum - histosData.add("pT_track_WTS", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); - histosData.add("pT_track_WTS_PID_Pi", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosData.add("pT_track_WTS_PID_Pi_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - - // Track Rapidity - histosData.add("rapidity_track_WTS", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_track_WTS_PID_Pi", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_track_WTS_PID_Pi_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - - // Zero charge Event Transverse Momentum - histosData.add("pT_event_0charge_WTS_PID_Pi", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - - // Non Zero charge Event Transverse Momentum - histosData.add("pT_event_non0charge_WTS_PID_Pi", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - - // Rapidity of 0 charge Events - histosData.add("rapidity_event_0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosData.add("rapidity_event_0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosData.add("rapidity_event_0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - - // Rapidity of non 0 charge Events - histosData.add("rapidity_event_non0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_event_non0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosData.add("rapidity_event_non0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - - // Pair Invariant Mass - histosData.add("invMass_pair_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosData.add("invMass_pair_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosData.add("invMass_pair_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosData.add("invMass_pair_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - - // Invariant Mass of 0 charge events - histosData.add("invMass_event_0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosData.add("invMass_event_0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosData.add("invMass_event_0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT - - // Invariant mass of non 0 charge events - histosData.add("invMass_event_non0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosData.add("invMass_event_non0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosData.add("invMass_event_non0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT - - // tpc signal - histosData.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - histosData.add("tpcSignal_Pi", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - - // tof beta - histosData.add("tofBeta", "TOF beta vs p; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - histosData.add("tofBeta_Pi", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - - // Other signals - histosData.add("FT0A", "T0A amplitude", kTH1F, {{2000, 0.0, 500.0}}); - histosData.add("FT0C", "T0C amplitude", kTH1F, {{2000, 0.0, 500.0}}); + // QA plots: Event and Track Counter + histosCounter.add("EventsCounts_vs_runNo", "Number of Selected 4-Pion Events per Run; Run Number; Number of Events", kTH2F, {{113, 0, 113}, {12, 0, 12}}); + histosCounter.add("TracksCounts_vs_runNo", "Number of Selected Tracks per Run; Run Number; Number of Tracks", kTH2F, {{113, 0, 113}, {14, 0, 14}}); + histosCounter.add("fourPionCounts_0c", "Four Pion Counts; Run Number; Events", kTH1F, {{113, 0, 113}}); + histosCounter.add("fourPionCounts_0c_within_mass", "Four Pion Counts within mass range; Run Number; Events", kTH1F, {{113, 0, 113}}); + histosCounter.add("fourPionCounts_0c_within_rap", "Four Pion Counts; Run Number; Events", kTH1F, {{113, 0, 113}}); + histosCounter.add("fourPionCounts_0c_selected", "Four Pion Counts; Run Number; Events", kTH1F, {{113, 0, 113}}); + histosCounter.add("fourPionCounts_n0c", "Four Pion Counts; Run Number; Events", kTH1F, {{113, 0, 113}}); + histosCounter.add("fourPionCounts_n0c_within_mass", "Four Pion Counts within mass range; Run Number; Events", kTH1F, {{113, 0, 113}}); + histosCounter.add("fourPionCounts_n0c_within_rap", "Four Pion Counts; Run Number; Events", kTH1F, {{113, 0, 113}}); + histosCounter.add("fourPionCounts_n0c_selected", "Four Pion Counts; Run Number; Events", kTH1F, {{113, 0, 113}}); + // QA plots: event selection + histosData.add("UPCmode", "UPC mode; Events", kTH1F, {{5, 0, 5}}); + histosData.add("FT0A", "T0A amplitude", kTH1F, {{500, 0.0, 500.0}}); + histosData.add("FT0C", "T0C amplitude", kTH1F, {{500, 0.0, 500.0}}); + histosData.add("FV0A", "V0A amplitude", kTH1F, {{100, 0.0, 100}}); histosData.add("ZDC_A", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); histosData.add("ZDC_C", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); - histosData.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); - - // Collin Soper Theta and Phi - histosData.add("CS_phi_pair_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosData.add("CS_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosData.add("CS_costheta_pair_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosData.add("CS_costheta_pair_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosData.add("phi_cosTheta_pair_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosData.add("phi_cosTheta_pair_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - - // MC Gen Stuff - - // counts - histosMCgen.add("rhoPrimeCounts", "Total Rho prime Events; Events", kTH1F, {{10, 0, 10}}); - - // Track Stuff - histosMCgen.add("pion_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 10}}); - histosMCgen.add("pion_eta", "Generated Pseudorapidity; #eta; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCgen.add("pion_rapidity", "Generated Rapidity; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - - // Pair Invariant Mass - histosMCgen.add("twoPion_invMass_pair_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCgen.add("twoPion_invMass_pair_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCgen.add("twoPion_invMass_pair_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCgen.add("twoPion_invMass_pair_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - - // Generated Transverse Momentum, Rapidty and Invariant Mass - histosMCgen.add("rhoPrime_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCgen.add("rhoPrime_eta", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCgen.add("rhoPrime_rapidity", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCgen.add("rhoPrime_invmass", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - - histosMCgen.add("fourPion_pT", "Generated pT; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCgen.add("fourPion_eta", "Generated Pseudorapidity; #eta; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCgen.add("fourPion_rapidity", "Generated Rapidity; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCgen.add("fourPion_invmass", "Invariant Mass of 4-Pions; m(4-pion); Events", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); - - // Collin Soper Theta and Phi - histosMCgen.add("fourPion_phi_pair_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCgen.add("fourPion_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCgen.add("fourPion_costheta_pair_1", "#theta Distribution;cos(#theta); Events", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCgen.add("fourPion_costheta_pair_2", "#theta Distribution;cos(#theta); Events", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCgen.add("phi_cosTheta_pair_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosMCgen.add("phi_cosTheta_pair_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - - // MC Reco Stuff - - histosMCreco.add("vertexZ", "Vertex Z; Vertex Z [cm]; Counts", kTH1F, {{1000, -20, 20}}); - histosMCreco.add("occupancy", "Occupancy; Occupancy; Counts", kTH1F, {{1500, 0, 1500}}); - histosMCreco.add("dcaXY", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{10000, -5, 5}}); - histosMCreco.add("dcaZ", "dcaZ; dcaZ [cm]; Counts", kTH1F, {{10000, -10, 10}}); - histosMCreco.add("tpcChi2NCl", "TPC Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); - histosMCreco.add("itsChi2NCl", "ITS Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{200, 0, 200}}); - histosMCreco.add("tpcNClsFindable", "TPC N Cls Findable; N Cls Findable; Counts", kTH1F, {{200, 0, 200}}); - - histosMCreco.add("GapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); - histosMCreco.add("TrueGapSide", "Gap Side; Events", kTH1F, {{4, -1.5, 2.5}}); - histosMCreco.add("EventCounts", "Total Events; Events", kTH1F, {{10, 0, 10}}); - - // TPC nSigma - histosMCreco.add("tpcNSigmaPi_WTS", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaPi_WTS_PID_Pi", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - - // TPC nSigma of other particles with selected pion tracks - histosMCreco.add("tpcNSigmaKa_WTS_PID_Pi", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaPr_WTS_PID_Pi", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaEl_WTS_PID_Pi", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tpcNSigmaMu_WTS_PID_Pi", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - - // TOF nSigma - histosMCreco.add("tofNSigmaPi_WTS", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaPi_WTS_PID_Pi", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - - // TOF nSigma of other particles with selected pion tracks - histosMCreco.add("tofNSigmaKa_WTS_PID_Pi", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaPr_WTS_PID_Pi", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaEl_WTS_PID_Pi", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - histosMCreco.add("tofNSigmaMu_WTS_PID_Pi", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {nBinsPt, 0, 10}}); - + histosData.add("FDDA", "FDD A signal; FDD A signal; Counts", kTH1F, {{500, 0.0, 500}}); + histosData.add("FDDC", "FDD C signal; FDD C signal; Counts", kTH1F, {{500, 0.0, 500}}); + histosData.add("vertexX", "Vertex X; Vertex X [cm]; Counts", kTH1F, {{2000, -0.05, 0.05}}); + histosData.add("vertexY", "Vertex Y; Vertex Y [cm]; Counts", kTH1F, {{2000, -0.05, 0.05}}); + histosData.add("vertexZ", "Vertex Z; Vertex Z [cm]; Counts", kTH1F, {{2000, -15, 15}}); + histosData.add("GapSide", "Gap Side;Gap Side; Events", kTH1F, {{4, 0, 4}}); + histosData.add("TrueGapSide", "True Gap Side; True Gap Side; Events", kTH1F, {{4, 0, 4}}); + histosData.add("occupancy", "Occupancy; Occupancy; Counts", kTH1F, {{20000, 0, 20000}}); + // QA plots: tracks + histosData.add("dcaXY_all", "dcaXY; dcaXY [cm]; Counts", kTH1F, {{2000, -0.1, 0.1}}); + histosData.add("dcaXY_pions", "dcaXY_pions; dcaXY of Pions [cm]; Counts", kTH1F, {{2000, -0.1, 0.1}}); + histosData.add("dcaZ_all", "dcaZ; dcaZ [cm]; Counts", kTH1F, {{2000, -0.1, 0.1}}); + histosData.add("dcaZ_pions", "dcaZ_pions; dcaZ of Pions [cm]; Counts", kTH1F, {{2000, -0.1, 0.1}}); + histosData.add("itsChi2NCl_all", "ITS Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{250, 0, 50}}); + histosData.add("itsChi2_all", "ITS Chi2; ITS Chi2; Counts", kTH1F, {{500, 0, 50}}); + histosData.add("tpcChi2NCl_all", "TPC Chi2/NCl; Chi2/NCl; Counts", kTH1F, {{250, 0, 50}}); + histosData.add("tpcNClsFindable_all", "TPC N Cls Findable; N Cls Findable; Counts", kTH1F, {{200, 0, 200}}); + // QA plots: PID + histosData.add("tpcSignal_all", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); + histosData.add("tpcSignal_pions", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); + histosData.add("tpcNSigmaPi_all", "TPC nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaPi_pions", "TPC nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaKa_pions", "TPC nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaPr_pions", "TPC nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaEl_pions", "TPC nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tpcNSigmaMu_pions", "TPC nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofBeta_all", "TOF beta vs p; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); + histosData.add("tofBeta_pions", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); + histosData.add("tofNSigmaPi_all", "TOF nSigma Pion with track selection; Events", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaPi_pions", "TOF nSigma Pion with track selection and PID Selection of Pi; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaKa_pions", "TOF nSigma Kaon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaPr_pions", "TOF nSigma Proton with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaEl_pions", "TOF nSigma Electron with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); + histosData.add("tofNSigmaMu_pions", "TOF nSigma Muon with track selection and PID Selection of Pion; Entries", kTH2F, {{1000, -15, 15}, {1000, 0, 10}}); // Track Transverse Momentum - histosMCreco.add("pT_track_WTS", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {{nBinsPt, 0, 2}}); - histosMCreco.add("pT_track_WTS_PID_Pi", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - histosMCreco.add("pT_track_WTS_PID_Pi_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - + histosData.add("pT_track_all", "pT with track selection; pT [GeV/c]; Counts", kTH1F, {pTAxis}); + histosData.add("pT_track_pions", "pT with track selection and PID selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosData.add("pT_track_pions_contributed", "pT with track selection and PID selection of Pi which are contributed to selected event; pT [GeV/c]; Events", kTH1F, {pTAxis}); + // Track Pseudorapidity + histosData.add("eta_track_all", "Pseudorapidity with track selection; #eta; Counts", kTH1F, {etaAxis}); + histosData.add("eta_track_pions", "Pseudorapidity with track selection and PID selection of Pi; #eta; Events", kTH1F, {etaAxis}); + histosData.add("eta_track_pions_contributed", "Pseudorapidity with track selection and PID selection of Pi which are contributed to selected event; #eta; Events", kTH1F, {etaAxis}); + // Track Phi + histosData.add("phi_track_all", "Phi with track selection; #phi [rad]; Counts", kTH1F, {phiAxis}); + histosData.add("phi_track_pions", "Phi with track selection and PID selection of Pi; #phi [rad]; Events", kTH1F, {phiAxis}); + histosData.add("phi_track_pions_contributed", "Phi with track selection and PID selection of Pi which are contributed to selected event; #phi [rad]; Events", kTH1F, {phiAxis}); // Track Rapidity - histosMCreco.add("rapidity_track_WTS", "Rapidity with track selection; y; Counts", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_track_WTS_PID_Pi", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_track_WTS_PID_Pi_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - - // Zero charge Event Transverse Momentum - histosMCreco.add("pT_event_0charge_WTS_PID_Pi", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - - // Non Zero charge Event Transverse Momentum - histosMCreco.add("pT_event_non0charge_WTS_PID_Pi", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {{nBinsPt, 0, 2}}); - - // Rapidity of 0 charge Events - histosMCreco.add("rapidity_event_0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{1000, -2.5, 2.5}}); - - // Rapidity of non 0 charge Events - histosMCreco.add("rapidity_event_non0charge_WTS_PID_Pi_domainA", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} < 0.15 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_non0charge_WTS_PID_Pi_domainB", "Rapidity of Events With Track Selection and PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c$; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - histosMCreco.add("rapidity_event_non0charge_WTS_PID_Pi_domainC", "Rapidity of Events With Track Selection and PID Selection of Pi for p_{T} > 0.80 GeV/c; y; Events", kTH1F, {{nBinsRapidity, -2.5, 2.5}}); - + histosData.add("rapidity_track_all", "Rapidity with track selection; y; Counts", kTH1F, {rapidityAxis}); + histosData.add("rapidity_track_pions", "Rapidity with track selection and PID selection of Pi; y; Events", kTH1F, {rapidityAxis}); + histosData.add("rapidity_track_pions_contributed", "Rapidity with track selection and PID selection of Pi which are contributed to selected event; y; Events", kTH1F, {rapidityAxis}); + // Four Pion Transverse Momentum + histosData.add("fourpion_pT_0_charge", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosData.add("fourpion_pT_0_charge_within_rap", "Event pT in 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosData.add("fourpion_pT_non_0_charge", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + histosData.add("fourpion_pT_non_0_charge_within_rap", "Event pT in Non 0 Charge Events With Track Selection and PID Selection of Pi; pT [GeV/c]; Events", kTH1F, {pTAxis}); + // Four Pion Eta + histosData.add("fourpion_eta_0_charge", "Four Pion #eta (0 charge); #eta; Events", kTH1F, {etaAxis}); + histosData.add("fourpion_eta_0_charge_within_rap", "Four Pion #eta (0 charge within rap); #eta; Events", kTH1F, {etaAxis}); + histosData.add("fourpion_eta_non_0_charge", "Four Pion #eta (non 0 charge); #eta; #eta; Events", kTH1F, {etaAxis}); + histosData.add("fourpion_eta_non_0_charge_within_rap", "Four Pion #eta (non 0 charge within rap); #eta; Events", kTH1F, {etaAxis}); + // Four Pion Phi + histosData.add("fourpion_phi_0_charge", "Four Pion #phi (0 charge); #phi [rad]; Events", kTH1F, {phiAxis}); + histosData.add("fourpion_phi_0_charge_within_rap", "Four Pion #phi (0 charge within rap); #phi [rad]; Events", kTH1F, {phiAxis}); + histosData.add("fourpion_phi_non_0_charge", "Four Pion #phi (non 0 charge); #phi [rad]; Events", kTH1F, {phiAxis}); + histosData.add("fourpion_phi_non_0_charge_within_rap", "Four Pion #phi (non 0 charge within rap); #phi [rad]; Events", kTH1F, {phiAxis}); + // Four Pion Rapidity + histosData.add("fourpion_rap_0_charge", "Four Pion Rapidity (0 charge); y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosData.add("fourpion_rap_0_charge_within_rap", "Four Pion Rapidity (0 charge within rap); y; Events", kTH1F, {{1000, -2.5, 2.5}}); + histosData.add("fourpion_rap_non_0_charge", "Four Pion Rapidity (non 0 charge); y; Events", kTH1F, {rapidityAxis}); + histosData.add("fourpion_rap_non_0_charge_within_rap", "Four Pion Rapidity (non 0 charge within rap); y; Events", kTH1F, {rapidityAxis}); + // Four Pion Mass + histosData.add("fourpion_mass_0_charge", "Four Pion Invariant Mass (0 charge); m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]; Events", kTH1F, {invMassAxis}); + histosData.add("fourpion_mass_0_charge_within_rap", "Four Pion Invariant Mass (0 charge within rap); m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]; Events", kTH1F, {invMassAxis}); + histosData.add("fourpion_mass_non_0_charge", "Four Pion Invariant Mass (non 0 charge); m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]; Events", kTH1F, {invMassAxis}); + histosData.add("fourpion_mass_non_0_charge_within_rap", "Four Pion Invariant Mass (non 0 charge within rap); m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]; Events", kTH1F, {invMassAxis}); // Pair Invariant Mass - histosMCreco.add("invMass_pair_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCreco.add("invMass_pair_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCreco.add("invMass_pair_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - histosMCreco.add("invMass_pair_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); - - // Invariant Mass of 0 charge events - histosMCreco.add("invMass_event_0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosMCreco.add("invMass_event_0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosMCreco.add("invMass_event_0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT - - // Invariant mass of non 0 charge events - histosMCreco.add("invMass_event_non0charge_WTS_PID_Pi_domainA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // pT < 0.15GeV - histosMCreco.add("invMass_event_non0charge_WTS_PID_Pi_domainB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.15GeV < pT < 0.8GeV - histosMCreco.add("invMass_event_non0charge_WTS_PID_Pi_domainC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{nBinsInvariantMass, invariantMassMin, invariantMassMax}}); // 0.8GeV < pT - - // tpc signal - histosMCreco.add("tpcSignal", "TPC dEdx vs p; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - histosMCreco.add("tpcSignal_Pi", "TPC dEdx vs p for pions; p [GeV/c]; dEdx [a.u.]", kTH2F, {{500, 0, 10}, {5000, 0.0, 5000.0}}); - - // tof beta - histosMCreco.add("tofBeta", "TOF beta vs p; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - histosMCreco.add("tofBeta_Pi", "TOF beta vs p for pions; p [GeV/c]; #beta", kTH2F, {{500, 0, 10}, {500, 0.0, 1.0}}); - - // Other signals - histosMCreco.add("FT0A", "T0A amplitude", kTH1F, {{2000, 0.0, 500.0}}); - histosMCreco.add("FT0C", "T0C amplitude", kTH1F, {{2000, 0.0, 500.0}}); - histosMCreco.add("ZDC_A", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); - histosMCreco.add("ZDC_C", "ZDC amplitude", kTH1F, {{1000, 0.0, 15}}); - histosMCreco.add("V0A", "V0A amplitude", kTH1F, {{1000, 0.0, 100}}); - - // Collin Soper Theta and Phi - histosMCreco.add("CS_phi_pair_1", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCreco.add("CS_phi_pair_2", "#phi Distribution; #phi; Events", kTH1F, {{nBinsPhi, -3.2, 3.2}}); - histosMCreco.add("CS_costheta_pair_1", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCreco.add("CS_costheta_pair_2", "#theta Distribution;cos(#theta); Counts", kTH1F, {{nBinsCosTheta, -1, 1}}); - histosMCreco.add("phi_cosTheta_pair_1", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - histosMCreco.add("phi_cosTheta_pair_2", "Phi vs cosTheta; #phi; cos(#theta)", kTH2F, {{nBinsPhi, -3.2, 3.2}, {nBinsCosTheta, -1, 1}}); - + histosData.add("twopion_mass_1", "Invariant Mass Distribution of 2 pions 1 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosData.add("twopion_mass_2", "Invariant Mass Distribution of 2 pions 2 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosData.add("twopion_mass_3", "Invariant Mass Distribution of 2 pions 3 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + histosData.add("twopion_mass_4", "Invariant Mass Distribution of 2 pions 4 ; m(#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {{5000, 0, 5}}); + // Four Pion Invariant Mass + histosData.add("fourpion_mass_0_charge_domA", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV + histosData.add("fourpion_mass_0_charge_domB", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV + histosData.add("fourpion_mass_0_charge_domC", "Invariant Mass Distribution of 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT + histosData.add("fourpion_mass_non_0_charge_domA", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} < 0.15 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // pT < 0.15GeV + histosData.add("fourpion_mass_non_0_charge_domB", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for 0.15< p_{T} < 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.15GeV < pT < 0.8GeV + histosData.add("fourpion_mass_non_0_charge_domC", "Invariant Mass Distribution of non 0 charge Events with PID Selection of Pi for p_{T} > 0.80 GeV/c; m(#pi^{+}#pi^{-}#pi^{+}#pi^{-}) [GeV/c]", kTH1F, {invMassAxis}); // 0.8GeV < pT + // Collin Soper Theta and Phi after selection + histosData.add("CSphi_vs_CScosTheta", "Phi vs cosTheta for small mass; #phi; cos(#theta)", kTH2F, {phiAxis, cosThetaAxis}); + setHistBinLabels(); } // End of init function - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - // Calculate the Collins-Soper Frame---------------------------------------------------------------------------------------------------------------------------- - double cosThetaCollinsSoperFrame(ROOT::Math::PtEtaPhiMVector pair1, ROOT::Math::PtEtaPhiMVector pair2, ROOT::Math::PtEtaPhiMVector fourpion) - { - double halfSqrtSnn = 2680.; - double massOfLead208 = 193.6823; - double momentumBeam = std::sqrt(halfSqrtSnn * halfSqrtSnn * 208 * 208 - massOfLead208 * massOfLead208); + //--------------------------------------------------------------------------------------------------------------------------------------------- + // Event Cuts + Filter vertexZcut = (nabs(o2::aod::collision::posZ) <= vZCut); + Filter numPVcontributorsCut = (o2::aod::collision::numContrib == numPVContrib); + Filter fitcuts = (o2::aod::udcollision::totalFV0AmplitudeA <= fv0Cut) && (o2::aod::udcollision::totalFT0AmplitudeA <= ft0aCut) && (o2::aod::udcollision::totalFT0AmplitudeC <= ft0cCut); + Filter zdcCuts = (o2::aod::udzdc::energyCommonZNA <= zdcCut) && (o2::aod::udzdc::energyCommonZNC <= zdcCut); + Filter bcSelectionCuts = (o2::aod::udcollision::sbp == sbpCut) && (o2::aod::udcollision::itsROFb == itsROFbCut) && (o2::aod::udcollision::vtxITSTPC == vtxITSTPCcut) && (o2::aod::udcollision::tfb == tfbCut); + // Track Cuts + Filter onlyPVtracks = o2::aod::udtrack::isPVContributor == useOnlyPVtracks; + Filter tpcchi2nclsFilter = o2::aod::track::tpcChi2NCl <= tpcChi2NClsCut; + Filter itschi2nclsFilter = o2::aod::track::itsChi2NCl <= itsChi2NClsCut; + Filter tpcCuts = (nabs(o2::aod::pidtpc::tpcNSigmaPi) <= nSigmaTPCcut); + //--------------------------------------------------------------------------------------------------------------------------------------------- - ROOT::Math::PxPyPzEVector pProjCM(0., 0., -momentumBeam, halfSqrtSnn * 208); // projectile - ROOT::Math::PxPyPzEVector pTargCM(0., 0., momentumBeam, halfSqrtSnn * 208); // target - - // TVector3 beta = (-1. / fourpion.E()) * fourpion.Vect(); - ROOT::Math::PtEtaPhiMVector v1 = pair1; - ROOT::Math::PtEtaPhiMVector v2 = pair2; - ROOT::Math::PtEtaPhiMVector v12 = fourpion; - - // Boost to center of mass frame - ROOT::Math::Boost boostv12{v12.BoostToCM()}; - ROOT::Math::XYZVectorF v1CM{(boostv12(v1).Vect()).Unit()}; - ROOT::Math::XYZVectorF v2CM{(boostv12(v2).Vect()).Unit()}; - ROOT::Math::XYZVectorF beam1CM{(boostv12(pProjCM).Vect()).Unit()}; - ROOT::Math::XYZVectorF beam2CM{(boostv12(pTargCM).Vect()).Unit()}; - - // Axes - ROOT::Math::XYZVectorF zaxisCS{((beam1CM.Unit() - beam2CM.Unit()).Unit())}; - - double cosThetaCS = zaxisCS.Dot((v1CM)); - return cosThetaCS; - } // End of cosThetaCollinsSoperFrame function------------------------------------------------------------------------------------------------------------------------ + using UDtracks = soa::Join; + using UDCollisions = soa::Join; - // Calculate Phi in Collins-Soper Frame------------------------------------------------------------------------------------------------------------------------ - double phiCollinsSoperFrame(ROOT::Math::PtEtaPhiMVector pair1, ROOT::Math::PtEtaPhiMVector pair2, ROOT::Math::PtEtaPhiMVector fourpion) + void processData(soa::Filtered::iterator const& collision, soa::Filtered const& tracks) { - // Half of the energy per pair of the colliding nucleons. - double halfSqrtSnn = 2680.; - double massOfLead208 = 193.6823; - double momentumBeam = std::sqrt(halfSqrtSnn * halfSqrtSnn * 208 * 208 - massOfLead208 * massOfLead208); - - ROOT::Math::PxPyPzEVector pProjCM(0., 0., -momentumBeam, halfSqrtSnn * 208); // projectile - ROOT::Math::PxPyPzEVector pTargCM(0., 0., momentumBeam, halfSqrtSnn * 208); // target - ROOT::Math::PtEtaPhiMVector v1 = pair1; - ROOT::Math::PtEtaPhiMVector v2 = pair2; - ROOT::Math::PtEtaPhiMVector v12 = fourpion; - // Boost to center of mass frame - ROOT::Math::Boost boostv12{v12.BoostToCM()}; - ROOT::Math::XYZVectorF v1CM{(boostv12(v1).Vect()).Unit()}; - ROOT::Math::XYZVectorF v2CM{(boostv12(v2).Vect()).Unit()}; - ROOT::Math::XYZVectorF beam1CM{(boostv12(pProjCM).Vect()).Unit()}; - ROOT::Math::XYZVectorF beam2CM{(boostv12(pTargCM).Vect()).Unit()}; - // Axes - ROOT::Math::XYZVectorF zaxisCS{((beam1CM.Unit() - beam2CM.Unit()).Unit())}; - ROOT::Math::XYZVectorF yaxisCS{(beam1CM.Cross(beam2CM)).Unit()}; - ROOT::Math::XYZVectorF xaxisCS{(yaxisCS.Cross(zaxisCS)).Unit()}; - double phi = std::atan2(yaxisCS.Dot(v1CM), xaxisCS.Dot(v1CM)); - return phi; - } // End of phiCollinsSoperFrame function------------------------------------------------------------------------------------------------------------------------ + int runIndex = getRunNumberIndex(collision.runNumber()); - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Filter vertexCut = (nabs(o2::aod::collision::posZ) <= vZCut) && (o2::aod::collision::numContrib == numPVContrib); - Filter fitcuts = o2::aod::udcollision::totalFV0AmplitudeA < fv0Cut && o2::aod::udcollision::totalFT0AmplitudeA < ft0aCut && o2::aod::udcollision::totalFT0AmplitudeC < ft0cCut; - Filter zdcCuts = (o2::aod::udzdc::energyCommonZNA < zdcCut) && (o2::aod::udzdc::energyCommonZNC < zdcCut); - using UDtracks = soa::Join; - using UDCollisions = soa::Filtered>; // - using UDCollision = UDCollisions::iterator; - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - // Begin of Process function-------------------------------------------------------------------------------------------------------------------------------------------------- - void processData(UDCollision const& collision, UDtracks const& tracks) - { + // Check if the Event is reconstructed in UPC mode + if (ifCheckUPCmode && (collision.flags() != 1)) { + return; + } - int gapSide = collision.gapSide(); - std::vector parameters = {pvCut, dcaZcut, dcaXYcut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, pTcut}; - int truegapSide = sgSelector.trueGap(collision, fv0Cut, ft0aCut, ft0cCut, zdcCut); - histosData.fill(HIST("GapSide"), gapSide); - histosData.fill(HIST("TrueGapSide"), truegapSide); - histosData.fill(HIST("EventCounts"), 1); + histosData.fill(HIST("GapSide"), collision.gapSide()); + histosData.fill(HIST("TrueGapSide"), sgSelector.trueGap(collision, fv0Cut, ft0aCut, ft0cCut, zdcCut)); + histosData.fill(HIST("vertexX"), collision.posX()); + histosData.fill(HIST("vertexY"), collision.posY()); histosData.fill(HIST("vertexZ"), collision.posZ()); histosData.fill(HIST("occupancy"), collision.occupancyInTime()); - histosData.fill(HIST("V0A"), collision.totalFV0AmplitudeA()); + histosData.fill(HIST("FV0A"), collision.totalFV0AmplitudeA()); histosData.fill(HIST("FT0A"), collision.totalFT0AmplitudeA()); histosData.fill(HIST("FT0C"), collision.totalFT0AmplitudeC()); histosData.fill(HIST("ZDC_A"), collision.energyCommonZNA()); histosData.fill(HIST("ZDC_C"), collision.energyCommonZNC()); + histosData.fill(HIST("FDDA"), collision.totalFDDAmplitudeA()); + histosData.fill(HIST("FDDC"), collision.totalFDDAmplitudeC()); + histosData.fill(HIST("UPCmode"), collision.flags()); std::vector selectedTracks; std::vector selectedPionTracks; @@ -874,18 +601,19 @@ struct ExclusiveRhoTo4Pi { std::vector selectedPionMinusTracks; for (const auto& t0 : tracks) { - if (trackselector(t0, parameters)) { - selectedTracks.push_back(t0); - if (selectionPIDPion(t0, true, nSigmaTPCcut, nSigmaTOFcut)) { - selectedPionTracks.push_back(t0); - if (t0.sign() == 1) { - selectedPionPlusTracks.push_back(t0); - } - if (t0.sign() == -1) { - selectedPionMinusTracks.push_back(t0); - } - } // End of Selection PID Pion - } // End of track selections + if (!isSelectedTrack(t0, pTcut, etaCut, dcaXYcut, dcaZcut, useITStracksOnly, useTPCtracksOnly, itsChi2NClsCut, tpcChi2NClsCut, tpcNClsFindableCut)) { + continue; + } + selectedTracks.push_back(t0); + if (selectionPIDPion(t0, useTOF, nSigmaTPCcut, nSigmaTOFcut)) { + selectedPionTracks.push_back(t0); + if (t0.sign() == 1) { + selectedPionPlusTracks.push_back(t0); + } + if (t0.sign() == -1) { + selectedPionMinusTracks.push_back(t0); + } + } // End of Selection PID Pion } // End of loop over tracks int numSelectedTracks = static_cast(selectedTracks.size()); @@ -894,43 +622,58 @@ struct ExclusiveRhoTo4Pi { int numPionMinusTracks = static_cast(selectedPionMinusTracks.size()); for (int i = 0; i < numSelectedTracks; i++) { - ROOT::Math::PxPyPzMVector selectedTrackVector(selectedTracks[i].px(), selectedTracks[i].py(), selectedTracks[i].pz(), o2::constants::physics::MassPionCharged); - histosData.fill(HIST("tpcSignal"), selectedTrackVector.P(), selectedTracks[i].tpcSignal()); - histosData.fill(HIST("tofBeta"), selectedTrackVector.P(), selectedTracks[i].beta()); - histosData.fill(HIST("tpcNSigmaPi_WTS"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaPi_WTS"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); - histosData.fill(HIST("pT_track_WTS"), selectedTrackVector.Pt()); - histosData.fill(HIST("rapidity_track_WTS"), selectedTrackVector.Rapidity()); - histosData.fill(HIST("itsChi2NCl"), selectedTracks[i].itsChi2NCl()); - histosData.fill(HIST("tpcChi2NCl"), selectedTracks[i].tpcChi2NCl()); - histosData.fill(HIST("tpcNClsFindable"), selectedTracks[i].tpcNClsFindable()); - histosData.fill(HIST("dcaXY"), selectedTracks[i].dcaXY()); - histosData.fill(HIST("dcaZ"), selectedTracks[i].dcaZ()); + PxPyPzMVector selectedTrackVector(selectedTracks[i].px(), selectedTracks[i].py(), selectedTracks[i].pz(), o2::constants::physics::MassPionCharged); + histosData.fill(HIST("pT_track_all"), selectedTrackVector.Pt()); + histosData.fill(HIST("eta_track_all"), selectedTrackVector.Eta()); + histosData.fill(HIST("phi_track_all"), selectedTrackVector.Phi()); + histosData.fill(HIST("rapidity_track_all"), selectedTrackVector.Rapidity()); + + histosData.fill(HIST("dcaXY_all"), selectedTracks[i].dcaXY()); + histosData.fill(HIST("dcaZ_all"), selectedTracks[i].dcaZ()); + + histosData.fill(HIST("itsChi2NCl_all"), selectedTracks[i].itsChi2NCl()); + histosData.fill(HIST("itsChi2_all"), selectedTracks[i].itsChi2NCl() * selectedTracks[i].itsNCls()); + histosData.fill(HIST("tpcChi2NCl_all"), selectedTracks[i].tpcChi2NCl()); + histosData.fill(HIST("tpcNClsFindable_all"), selectedTracks[i].tpcNClsFindable()); + + histosData.fill(HIST("tpcSignal_all"), selectedTrackVector.P(), selectedTracks[i].tpcSignal()); + histosData.fill(HIST("tpcNSigmaPi_all"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); + histosData.fill(HIST("tofBeta_all"), selectedTrackVector.P(), selectedTracks[i].beta()); + histosData.fill(HIST("tofNSigmaPi_all"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); } // End of loop over tracks with selection only for (int i = 0; i < numSelectedPionTracks; i++) { - ROOT::Math::PxPyPzMVector selectedPionTrackVector(selectedPionTracks[i].px(), selectedPionTracks[i].py(), selectedPionTracks[i].pz(), o2::constants::physics::MassPionCharged); - histosData.fill(HIST("tpcSignal_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); - histosData.fill(HIST("tofBeta_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); - histosData.fill(HIST("tpcNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaEl(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tpcNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaMu(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPi(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaKa(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPr(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("tofNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi"), selectedPionTrackVector.Pt()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi"), selectedPionTrackVector.Rapidity()); - } // End of loop over tracks with selection and PID selection of Pions - + PxPyPzMVector selectedPionTrackVector(selectedPionTracks[i].px(), selectedPionTracks[i].py(), selectedPionTracks[i].pz(), o2::constants::physics::MassPionCharged); + + histosData.fill(HIST("pT_track_pions"), selectedPionTrackVector.Pt()); + histosData.fill(HIST("eta_track_pions"), selectedPionTrackVector.Eta()); + histosData.fill(HIST("phi_track_pions"), selectedPionTrackVector.Phi()); + histosData.fill(HIST("rapidity_track_pions"), selectedPionTrackVector.Rapidity()); + + histosData.fill(HIST("dcaXY_pions"), selectedPionTracks[i].dcaXY()); + histosData.fill(HIST("dcaZ_pions"), selectedPionTracks[i].dcaZ()); + + histosData.fill(HIST("tpcSignal_pions"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); + histosData.fill(HIST("tpcNSigmaPi_pions"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaKa_pions"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaPr_pions"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaEl_pions"), selectedPionTracks[i].tpcNSigmaEl(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tpcNSigmaMu_pions"), selectedPionTracks[i].tpcNSigmaMu(), selectedPionTrackVector.Pt()); + + histosData.fill(HIST("tofBeta_pions"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); + histosData.fill(HIST("tofNSigmaPi_pions"), selectedPionTracks[i].tofNSigmaPi(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaKa_pions"), selectedPionTracks[i].tofNSigmaKa(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaPr_pions"), selectedPionTracks[i].tofNSigmaPr(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaEl_pions"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); + histosData.fill(HIST("tofNSigmaMu_pions"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); + } // End of loop over tracks with selection and PID of pions + + // event should have exactly 4 pions if (numSelectedPionTracks != numFourPionTracks) { return; } - // Check if there is at least one track with TOF in the selected events, otherwise return + // Check if there is at least one track with TOF in the selected events (for derived Data) bool hasAtleastOneTOF = false; for (int i = 0; i < numPiPlusTracks; i++) { if (selectedPionPlusTracks[i].hasTOF() == true) { @@ -938,36 +681,43 @@ struct ExclusiveRhoTo4Pi { break; } } - if (!hasAtleastOneTOF) { - return; - } // Selecting Events with net charge = 0 if (numPionMinusTracks == numPiMinus && numPiPlusTracks == numPiPlus) { - ROOT::Math::PtEtaPhiMVector k1, k2, k3, k4, k1234, k13, k14, k23, k24; + PtEtaPhiMVector k1, k2, k3, k4, k1234, k13, k14, k23, k24; + + PxPyPzMVector p1(selectedPionPlusTracks[0].px(), selectedPionPlusTracks[0].py(), selectedPionPlusTracks[0].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p2(selectedPionPlusTracks[1].px(), selectedPionPlusTracks[1].py(), selectedPionPlusTracks[1].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p3(selectedPionMinusTracks[0].px(), selectedPionMinusTracks[0].py(), selectedPionMinusTracks[0].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p4(selectedPionMinusTracks[1].px(), selectedPionMinusTracks[1].py(), selectedPionMinusTracks[1].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p1(selectedPionPlusTracks[0].px(), selectedPionPlusTracks[0].py(), selectedPionPlusTracks[0].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p2(selectedPionPlusTracks[1].px(), selectedPionPlusTracks[1].py(), selectedPionPlusTracks[1].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p3(selectedPionMinusTracks[0].px(), selectedPionMinusTracks[0].py(), selectedPionMinusTracks[0].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p4(selectedPionMinusTracks[1].px(), selectedPionMinusTracks[1].py(), selectedPionMinusTracks[1].pz(), o2::constants::physics::MassPionCharged); + histosData.fill(HIST("pT_track_pions_contributed"), p1.Pt()); + histosData.fill(HIST("pT_track_pions_contributed"), p2.Pt()); + histosData.fill(HIST("pT_track_pions_contributed"), p3.Pt()); + histosData.fill(HIST("pT_track_pions_contributed"), p4.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p1.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p2.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p3.Pt()); - histosData.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p4.Pt()); + histosData.fill(HIST("eta_track_pions_contributed"), p1.Eta()); + histosData.fill(HIST("eta_track_pions_contributed"), p2.Eta()); + histosData.fill(HIST("eta_track_pions_contributed"), p3.Eta()); + histosData.fill(HIST("eta_track_pions_contributed"), p4.Eta()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p1.Rapidity()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p2.Rapidity()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p3.Rapidity()); - histosData.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p4.Rapidity()); + histosData.fill(HIST("phi_track_pions_contributed"), p1.Phi()); + histosData.fill(HIST("phi_track_pions_contributed"), p2.Phi()); + histosData.fill(HIST("phi_track_pions_contributed"), p3.Phi()); + histosData.fill(HIST("phi_track_pions_contributed"), p4.Phi()); + + histosData.fill(HIST("rapidity_track_pions_contributed"), p1.Rapidity()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p2.Rapidity()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p3.Rapidity()); + histosData.fill(HIST("rapidity_track_pions_contributed"), p4.Rapidity()); k1.SetCoordinates(p1.Pt(), p1.Eta(), p1.Phi(), o2::constants::physics::MassPionCharged); k2.SetCoordinates(p2.Pt(), p2.Eta(), p2.Phi(), o2::constants::physics::MassPionCharged); k3.SetCoordinates(p3.Pt(), p3.Eta(), p3.Phi(), o2::constants::physics::MassPionCharged); k4.SetCoordinates(p4.Pt(), p4.Eta(), p4.Phi(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p1234 = p1 + p2 + p3 + p4; + PxPyPzMVector p1234 = p1 + p2 + p3 + p4; k1234 = k1 + k2 + k3 + k4; k13 = k1 + k3; @@ -975,434 +725,536 @@ struct ExclusiveRhoTo4Pi { k23 = k2 + k3; k24 = k2 + k4; - double fourPiPhiPair1 = phiCollinsSoperFrame(k13, k24, k1234); - double fourPiPhiPair2 = phiCollinsSoperFrame(k14, k23, k1234); - double fourPiCosThetaPair1 = cosThetaCollinsSoperFrame(k13, k24, k1234); - double fourPiCosThetaPair2 = cosThetaCollinsSoperFrame(k14, k23, k1234); + histosData.fill(HIST("fourpion_pT_0_charge"), p1234.Pt()); + histosData.fill(HIST("fourpion_eta_0_charge"), p1234.Eta()); + histosData.fill(HIST("fourpion_phi_0_charge"), p1234.Phi()); + histosData.fill(HIST("fourpion_rap_0_charge"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_0_charge"), p1234.M()); + + double fourPiPhiPair1 = collinSoperPhi(k13, k1234); + double fourPiPhiPair2 = collinSoperPhi(k14, k1234); + double fourPiPhiPair3 = collinSoperPhi(k23, k1234); + double fourPiPhiPair4 = collinSoperPhi(k24, k1234); + double fourPiCosThetaPair1 = collinSoperCosTheta(k13, k1234); + double fourPiCosThetaPair2 = collinSoperCosTheta(k14, k1234); + double fourPiCosThetaPair3 = collinSoperCosTheta(k23, k1234); + double fourPiCosThetaPair4 = collinSoperCosTheta(k24, k1234); sigFromData( + // run number + collision.runNumber(), + // UPC mode + collision.flags(), + // vertex collision.posX(), collision.posY(), collision.posZ(), + // FIT Signals collision.totalFV0AmplitudeA(), collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), - collision.timeFV0A(), collision.timeFT0A(), collision.timeFT0C(), collision.timeFDDA(), collision.timeFDDC(), collision.timeZNA(), collision.timeZNC(), collision.occupancyInTime(), + // FIT and ZDC Signals + collision.timeFV0A(), collision.timeFT0A(), collision.timeFT0C(), collision.timeFDDA(), collision.timeFDDC(), collision.timeZNA(), collision.timeZNC(), + // Occupancy + collision.occupancyInTime(), + // has atleast one TOF + hasAtleastOneTOF, + // DCA XY and Z selectedPionPlusTracks[0].dcaXY(), selectedPionPlusTracks[1].dcaXY(), selectedPionMinusTracks[0].dcaXY(), selectedPionMinusTracks[1].dcaXY(), - selectedPionPlusTracks[0].dcaZ(), selectedPionPlusTracks[1].dcaZ(), selectedPionMinusTracks[0].dcaZ(), selectedPionMinusTracks[1].dcaZ(), - + // TPC N Sigma Pi selectedPionPlusTracks[0].tpcNSigmaPi(), selectedPionPlusTracks[1].tpcNSigmaPi(), selectedPionMinusTracks[0].tpcNSigmaPi(), selectedPionMinusTracks[1].tpcNSigmaPi(), - + // TPC N Sigma Ka selectedPionPlusTracks[0].tpcNSigmaKa(), selectedPionPlusTracks[1].tpcNSigmaKa(), selectedPionMinusTracks[0].tpcNSigmaKa(), selectedPionMinusTracks[1].tpcNSigmaKa(), - + // TPC N Sigma Pr selectedPionPlusTracks[0].tpcNSigmaPr(), selectedPionPlusTracks[1].tpcNSigmaPr(), selectedPionMinusTracks[0].tpcNSigmaPr(), selectedPionMinusTracks[1].tpcNSigmaPr(), - + // TPC N Sigma El selectedPionPlusTracks[0].tpcNSigmaEl(), selectedPionPlusTracks[1].tpcNSigmaEl(), selectedPionMinusTracks[0].tpcNSigmaEl(), selectedPionMinusTracks[1].tpcNSigmaEl(), - + // TPC N Sigma Mu selectedPionPlusTracks[0].tpcNSigmaMu(), selectedPionPlusTracks[1].tpcNSigmaMu(), selectedPionMinusTracks[0].tpcNSigmaMu(), selectedPionMinusTracks[1].tpcNSigmaMu(), - + // tpc Chi2 NCl selectedPionPlusTracks[0].tpcChi2NCl(), selectedPionPlusTracks[1].tpcChi2NCl(), selectedPionMinusTracks[0].tpcChi2NCl(), selectedPionMinusTracks[1].tpcChi2NCl(), - + // TPC NCls Findable selectedPionPlusTracks[0].tpcNClsFindable(), selectedPionPlusTracks[1].tpcNClsFindable(), selectedPionMinusTracks[0].tpcNClsFindable(), selectedPionMinusTracks[1].tpcNClsFindable(), - + // ITS Chi2 NCl selectedPionPlusTracks[0].itsChi2NCl(), selectedPionPlusTracks[1].itsChi2NCl(), selectedPionMinusTracks[0].itsChi2NCl(), selectedPionMinusTracks[1].itsChi2NCl(), - + // Pion Pt p1.Pt(), p2.Pt(), p3.Pt(), p4.Pt(), + // Pion Eta p1.Eta(), p2.Eta(), p3.Eta(), p4.Eta(), + // Pion Phi p1.Phi(), p2.Phi(), p3.Phi(), p4.Phi(), + // Pion Rapidity p1.Rapidity(), p2.Rapidity(), p3.Rapidity(), p4.Rapidity(), - p1234.Pt(), p1234.Eta(), p1234.Phi(), p1234.Rapidity(), p1234.M(), - fourPiPhiPair1, fourPiPhiPair2, fourPiCosThetaPair1, fourPiCosThetaPair2); + // Four Pt + p1234.Pt(), + // Four Eta + p1234.Eta(), + // Four Phi + p1234.Phi(), + // Four Rapidity + p1234.Rapidity(), + // Four Mass + p1234.M(), + // Four Collins Soper Phi and CosTheta + fourPiPhiPair1, fourPiPhiPair2, fourPiPhiPair3, fourPiPhiPair4, + fourPiCosThetaPair1, fourPiCosThetaPair2, fourPiCosThetaPair3, fourPiCosThetaPair4); + + histosCounter.fill(HIST("fourPionCounts_0c"), runIndex); + + if (rhoMassMin < p1234.M() && p1234.M() < rhoMassMax) { + histosCounter.fill(HIST("fourPionCounts_0c_within_mass"), runIndex); + } if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosData.fill(HIST("pT_event_0charge_WTS_PID_Pi"), p1234.Pt()); + histosData.fill(HIST("fourpion_pT_0_charge_within_rap"), p1234.Pt()); + histosData.fill(HIST("fourpion_eta_0_charge_within_rap"), p1234.Eta()); + histosData.fill(HIST("fourpion_phi_0_charge_within_rap"), p1234.Phi()); + histosData.fill(HIST("fourpion_rap_0_charge_within_rap"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_0_charge_within_rap"), p1234.M()); + histosCounter.fill(HIST("fourPionCounts_0c_within_rap"), runIndex); if (p1234.Pt() < rhoPtCut) { - histosData.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainA"), p1234.M()); - - histosData.fill(HIST("invMass_pair_1"), (p1 + p3).M()); - histosData.fill(HIST("invMass_pair_2"), (p1 + p4).M()); - histosData.fill(HIST("invMass_pair_3"), (p2 + p3).M()); - histosData.fill(HIST("invMass_pair_4"), (p2 + p4).M()); - - histosData.fill(HIST("CS_phi_pair_1"), fourPiPhiPair1); - histosData.fill(HIST("CS_phi_pair_2"), fourPiPhiPair2); - histosData.fill(HIST("CS_costheta_pair_1"), fourPiCosThetaPair1); - histosData.fill(HIST("CS_costheta_pair_2"), fourPiCosThetaPair2); - - histosData.fill(HIST("phi_cosTheta_pair_1"), fourPiPhiPair1, fourPiCosThetaPair1); - histosData.fill(HIST("phi_cosTheta_pair_2"), fourPiPhiPair2, fourPiCosThetaPair2); - } + if (rhoMassMin < p1234.M() && p1234.M() < rhoMassMax) { + // Selected Four Pion Events + histosCounter.fill(HIST("fourPionCounts_0c_selected"), runIndex); + // Fill the Invariant Mass Histogram + histosData.fill(HIST("fourpion_mass_0_charge_domA"), p1234.M()); + // Two Pion Masses + histosData.fill(HIST("twopion_mass_1"), (p1 + p3).M()); + histosData.fill(HIST("twopion_mass_2"), (p1 + p4).M()); + histosData.fill(HIST("twopion_mass_3"), (p2 + p3).M()); + histosData.fill(HIST("twopion_mass_4"), (p2 + p4).M()); + // Fill the Collins-Soper Frame histograms + double mDiff13 = std::abs((k13.M() - mRho0)); + double mDiff14 = std::abs((k14.M() - mRho0)); + double mDiff23 = std::abs((k23.M() - mRho0)); + double mDiff24 = std::abs((k24.M() - mRho0)); + if ((mDiff13 < mDiff14) && (mDiff13 < mDiff23) && (mDiff13 < mDiff24)) { + histosData.fill(HIST("CSphi_vs_CScosTheta"), fourPiPhiPair1, fourPiCosThetaPair1); + } else if ((mDiff14 < mDiff13) && (mDiff14 < mDiff23) && (mDiff14 < mDiff24)) { + histosData.fill(HIST("CSphi_vs_CScosTheta"), fourPiPhiPair2, fourPiCosThetaPair2); + } else if ((mDiff23 < mDiff13) && (mDiff23 < mDiff14) && (mDiff23 < mDiff24)) { + histosData.fill(HIST("CSphi_vs_CScosTheta"), fourPiPhiPair3, fourPiCosThetaPair3); + } else if ((mDiff24 < mDiff13) && (mDiff24 < mDiff14) && (mDiff24 < mDiff23)) { + histosData.fill(HIST("CSphi_vs_CScosTheta"), fourPiPhiPair4, fourPiCosThetaPair4); + } + } // End of Pt selection for rho mass + } // End of Pt selection for rho mass if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosData.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainB"), p1234.M()); + histosData.fill(HIST("fourpion_mass_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosData.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainC"), p1234.M()); + histosData.fill(HIST("fourpion_mass_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection - } // End of Analysis for 0 charge events // Selecting Events with net charge != 0 for estimation of background if (numPionMinusTracks != numPiMinus && numPiPlusTracks != numPiPlus) { - ROOT::Math::PxPyPzMVector p1(selectedPionTracks[0].px(), selectedPionTracks[0].py(), selectedPionTracks[0].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p2(selectedPionTracks[1].px(), selectedPionTracks[1].py(), selectedPionTracks[1].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p3(selectedPionTracks[2].px(), selectedPionTracks[2].py(), selectedPionTracks[2].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p4(selectedPionTracks[3].px(), selectedPionTracks[3].py(), selectedPionTracks[3].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p1(selectedPionTracks[0].px(), selectedPionTracks[0].py(), selectedPionTracks[0].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p2(selectedPionTracks[1].px(), selectedPionTracks[1].py(), selectedPionTracks[1].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p3(selectedPionTracks[2].px(), selectedPionTracks[2].py(), selectedPionTracks[2].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p4(selectedPionTracks[3].px(), selectedPionTracks[3].py(), selectedPionTracks[3].pz(), o2::constants::physics::MassPionCharged); + PxPyPzMVector p1234 = p1 + p2 + p3 + p4; - ROOT::Math::PxPyPzMVector p1234 = p1 + p2 + p3 + p4; + histosData.fill(HIST("fourpion_pT_non_0_charge"), p1234.Pt()); + histosData.fill(HIST("fourpion_eta_non_0_charge"), p1234.Eta()); + histosData.fill(HIST("fourpion_phi_non_0_charge"), p1234.Phi()); + histosData.fill(HIST("fourpion_rap_non_0_charge"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_non_0_charge"), p1234.M()); bkgFromData( + // Run Number + collision.runNumber(), + // UPC mode + collision.flags(), + // vertex collision.posX(), collision.posY(), collision.posZ(), + // FIT Signals collision.totalFV0AmplitudeA(), collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), - collision.timeFV0A(), collision.timeFT0A(), collision.timeFT0C(), collision.timeFDDA(), collision.timeFDDC(), - collision.timeZNA(), collision.timeZNC(), collision.occupancyInTime(), - selectedPionTracks[0].dcaXY(), selectedPionTracks[1].dcaXY(), selectedPionTracks[0].dcaXY(), selectedPionTracks[1].dcaXY(), - selectedPionTracks[0].dcaZ(), selectedPionTracks[1].dcaZ(), selectedPionTracks[0].dcaZ(), selectedPionTracks[1].dcaZ(), - selectedPionTracks[0].tpcNSigmaPi(), selectedPionTracks[1].tpcNSigmaPi(), selectedPionTracks[0].tpcNSigmaPi(), selectedPionTracks[1].tpcNSigmaPi(), - selectedPionTracks[0].tpcNSigmaKa(), selectedPionTracks[1].tpcNSigmaKa(), selectedPionTracks[0].tpcNSigmaKa(), selectedPionTracks[1].tpcNSigmaKa(), - selectedPionTracks[0].tpcNSigmaPr(), selectedPionTracks[1].tpcNSigmaPr(), selectedPionTracks[0].tpcNSigmaPr(), selectedPionTracks[1].tpcNSigmaPr(), - selectedPionTracks[0].tpcNSigmaEl(), selectedPionTracks[1].tpcNSigmaEl(), selectedPionTracks[0].tpcNSigmaEl(), selectedPionTracks[1].tpcNSigmaEl(), - selectedPionTracks[0].tpcNSigmaMu(), selectedPionTracks[1].tpcNSigmaMu(), selectedPionTracks[0].tpcNSigmaMu(), selectedPionTracks[1].tpcNSigmaMu(), - selectedPionTracks[0].itsChi2NCl(), selectedPionTracks[1].itsChi2NCl(), selectedPionTracks[0].itsChi2NCl(), selectedPionTracks[1].itsChi2NCl(), - selectedPionTracks[0].tpcChi2NCl(), selectedPionTracks[1].tpcChi2NCl(), selectedPionTracks[0].tpcChi2NCl(), selectedPionTracks[1].tpcChi2NCl(), - selectedPionTracks[0].tpcNClsFindable(), selectedPionTracks[1].tpcNClsFindable(), selectedPionTracks[0].tpcNClsFindable(), selectedPionTracks[1].tpcNClsFindable(), + // FIT and ZDC Signals + collision.timeFV0A(), collision.timeFT0A(), collision.timeFT0C(), collision.timeFDDA(), collision.timeFDDC(), collision.timeZNA(), collision.timeZNC(), + // Occupancy + collision.occupancyInTime(), + // has atleast one TOF + hasAtleastOneTOF, + // DCA XY and Z + selectedPionTracks[0].dcaXY(), selectedPionTracks[1].dcaXY(), selectedPionTracks[2].dcaXY(), selectedPionTracks[3].dcaXY(), + selectedPionTracks[0].dcaZ(), selectedPionTracks[1].dcaZ(), selectedPionTracks[2].dcaZ(), selectedPionTracks[3].dcaZ(), + // TPC N Sigma Pi + selectedPionTracks[0].tpcNSigmaPi(), selectedPionTracks[1].tpcNSigmaPi(), selectedPionTracks[2].tpcNSigmaPi(), selectedPionTracks[3].tpcNSigmaPi(), + // TPC N Sigma Ka + selectedPionTracks[0].tpcNSigmaKa(), selectedPionTracks[1].tpcNSigmaKa(), selectedPionTracks[2].tpcNSigmaKa(), selectedPionTracks[3].tpcNSigmaKa(), + // TPC N Sigma Pr + selectedPionTracks[0].tpcNSigmaPr(), selectedPionTracks[1].tpcNSigmaPr(), selectedPionTracks[2].tpcNSigmaPr(), selectedPionTracks[3].tpcNSigmaPr(), + // TPC N Sigma El + selectedPionTracks[0].tpcNSigmaEl(), selectedPionTracks[1].tpcNSigmaEl(), selectedPionTracks[2].tpcNSigmaEl(), selectedPionTracks[3].tpcNSigmaEl(), + // TPC N Sigma Mu + selectedPionTracks[0].tpcNSigmaMu(), selectedPionTracks[1].tpcNSigmaMu(), selectedPionTracks[2].tpcNSigmaMu(), selectedPionTracks[3].tpcNSigmaMu(), + // tpc Chi2 NCl + selectedPionTracks[0].tpcChi2NCl(), selectedPionTracks[1].tpcChi2NCl(), selectedPionTracks[2].tpcChi2NCl(), selectedPionTracks[3].tpcChi2NCl(), + // TPC NCls Findable + selectedPionTracks[0].tpcNClsFindable(), selectedPionTracks[1].tpcNClsFindable(), selectedPionTracks[2].tpcNClsFindable(), selectedPionTracks[3].tpcNClsFindable(), + // ITS Chi2 NCl + selectedPionTracks[0].itsChi2NCl(), selectedPionTracks[1].itsChi2NCl(), selectedPionTracks[2].itsChi2NCl(), selectedPionTracks[3].itsChi2NCl(), + // Pion Pt p1.Pt(), p2.Pt(), p3.Pt(), p4.Pt(), + // Pion Eta p1.Eta(), p2.Eta(), p3.Eta(), p4.Eta(), + // Pion Phi p1.Phi(), p2.Phi(), p3.Phi(), p4.Phi(), + // Pion Rapidity p1.Rapidity(), p2.Rapidity(), p3.Rapidity(), p4.Rapidity(), - p1234.Pt(), p1234.Eta(), p1234.Phi(), p1234.Rapidity(), p1234.M()); - + // Four Pt + p1234.Pt(), + // Four Eta + p1234.Eta(), + // Four Phi + p1234.Phi(), + // Four Rapidity + p1234.Rapidity(), + // Four Mass + p1234.M()); + + histosCounter.fill(HIST("fourPionCounts_n0c"), runIndex); + if (rhoMassMin < p1234.M() && p1234.M() < rhoMassMax) { + histosCounter.fill(HIST("fourPionCounts_n0c_within_mass"), runIndex); + } if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosData.fill(HIST("pT_event_non0charge_WTS_PID_Pi"), p1234.Pt()); - + histosData.fill(HIST("fourpion_pT_non_0_charge_within_rap"), p1234.Pt()); + histosData.fill(HIST("fourpion_eta_non_0_charge_within_rap"), p1234.Eta()); + histosData.fill(HIST("fourpion_phi_non_0_charge_within_rap"), p1234.Phi()); + histosData.fill(HIST("fourpion_rap_non_0_charge_within_rap"), p1234.Rapidity()); + histosData.fill(HIST("fourpion_mass_non_0_charge_within_rap"), p1234.M()); + histosCounter.fill(HIST("fourPionCounts_n0c_within_rap"), runIndex); if (p1234.Pt() < rhoPtCut) { - histosData.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainA"), p1234.M()); + histosData.fill(HIST("fourpion_mass_non_0_charge_domA"), p1234.M()); + histosCounter.fill(HIST("fourPionCounts_n0c_selected"), runIndex); } if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosData.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainB"), p1234.M()); + histosData.fill(HIST("fourpion_mass_non_0_charge_domB"), p1234.M()); } if (p1234.Pt() > zeroPointEight) { - histosData.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosData.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainC"), p1234.M()); + histosData.fill(HIST("fourpion_mass_non_0_charge_domC"), p1234.M()); } } // End of Rapidity range selection } // End of Analysis for non 0 charge events - } // End of 4 Pion Analysis Process function for Data - PROCESS_SWITCH(ExclusiveRhoTo4Pi, processData, "The Process for 4 Pion Analysis from data", true); - //---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + } // End of 4 Pion Analysis Process function for Pass5 Data - // Begin of MC Generation function----------------------------------------------------------------------------------------------------------------------------------------------- - void processMCgen(aod::UDMcCollisions::iterator const&, aod::UDMcParticles const& mcParts) + void processEventCounter(UDCollisions::iterator const& collision) { - std::vector piPlusvectors; - std::vector piMinusvectors; - TVector3 particleVector; - for (const auto& particle : mcParts) { + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 0); - if ((particle.pdgCode() != rhoPrime) || (particle.daughters_as().size() != numFourPionTracks)) { - continue; - } - - particleVector.SetXYZ(particle.px(), particle.py(), particle.pz()); - histosMCgen.fill(HIST("rhoPrimeCounts"), 1); - histosMCgen.fill(HIST("rhoPrime_pT"), particleVector.Pt()); - histosMCgen.fill(HIST("rhoPrime_eta"), particleVector.Eta()); - - for (const auto& daughter : particle.daughters_as()) { - ROOT::Math::PxPyPzMVector daughterVector(daughter.px(), daughter.py(), daughter.pz(), o2::constants::physics::MassPionCharged); - if (daughter.pdgCode() == PDG_t::kPiPlus) { - piPlusvectors.push_back(daughterVector); - } - if (daughter.pdgCode() == PDG_t::kPiMinus) { - piMinusvectors.push_back(daughterVector); - } - } // End of loop over daughters - - } // End of loop over MC particles - - if (static_cast(piPlusvectors.size()) != numPiPlus || static_cast(piMinusvectors.size()) != numPiMinus) { + // UPC mode + if (ifCheckUPCmode && collision.flags() != 1) { return; } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 1); - ROOT::Math::PxPyPzMVector p1234 = piPlusvectors[0] + piPlusvectors[1] + piMinusvectors[0] + piMinusvectors[1]; - - histosMCgen.fill(HIST("pion_pT"), piPlusvectors[0].Pt()); - histosMCgen.fill(HIST("pion_pT"), piPlusvectors[1].Pt()); - histosMCgen.fill(HIST("pion_pT"), piMinusvectors[0].Pt()); - histosMCgen.fill(HIST("pion_pT"), piMinusvectors[1].Pt()); - - histosMCgen.fill(HIST("pion_eta"), piPlusvectors[0].Eta()); - histosMCgen.fill(HIST("pion_eta"), piPlusvectors[1].Eta()); - histosMCgen.fill(HIST("pion_eta"), piMinusvectors[0].Eta()); - histosMCgen.fill(HIST("pion_eta"), piMinusvectors[1].Eta()); - - histosMCgen.fill(HIST("pion_rapidity"), piPlusvectors[0].Rapidity()); - histosMCgen.fill(HIST("pion_rapidity"), piPlusvectors[1].Rapidity()); - histosMCgen.fill(HIST("pion_rapidity"), piMinusvectors[0].Rapidity()); - histosMCgen.fill(HIST("pion_rapidity"), piMinusvectors[1].Rapidity()); - - histosMCgen.fill(HIST("fourPion_pT"), p1234.Pt()); - histosMCgen.fill(HIST("fourPion_eta"), p1234.Eta()); - histosMCgen.fill(HIST("fourPion_rapidity"), p1234.Rapidity()); - histosMCgen.fill(HIST("fourPion_invmass"), p1234.M()); - - histosMCgen.fill(HIST("twoPion_invMass_pair_1"), (piPlusvectors[0] + piMinusvectors[0]).M()); - histosMCgen.fill(HIST("twoPion_invMass_pair_2"), (piPlusvectors[0] + piMinusvectors[1]).M()); - histosMCgen.fill(HIST("twoPion_invMass_pair_3"), (piPlusvectors[1] + piMinusvectors[0]).M()); - histosMCgen.fill(HIST("twoPion_invMass_pair_4"), (piPlusvectors[1] + piMinusvectors[1]).M()); - - ROOT::Math::PtEtaPhiMVector k1, k2, k3, k4, k1234, k13, k14, k23, k24; - - k1.SetCoordinates(piPlusvectors[0].Pt(), piPlusvectors[0].Eta(), piPlusvectors[0].Phi(), o2::constants::physics::MassPionCharged); - k2.SetCoordinates(piPlusvectors[1].Pt(), piPlusvectors[1].Eta(), piPlusvectors[1].Phi(), o2::constants::physics::MassPionCharged); - k3.SetCoordinates(piMinusvectors[0].Pt(), piMinusvectors[0].Eta(), piMinusvectors[0].Phi(), o2::constants::physics::MassPionCharged); - k4.SetCoordinates(piMinusvectors[1].Pt(), piMinusvectors[1].Eta(), piMinusvectors[1].Phi(), o2::constants::physics::MassPionCharged); - - k1234 = k1 + k2 + k3 + k4; - - k13 = k1 + k3; - k14 = k1 + k4; - k23 = k2 + k3; - k24 = k2 + k4; - - auto phiPair1 = phiCollinsSoperFrame(k13, k24, k1234); - auto phiPair2 = phiCollinsSoperFrame(k14, k23, k1234); - auto cosThetaPair1 = cosThetaCollinsSoperFrame(k13, k24, k1234); - auto cosThetaPair2 = cosThetaCollinsSoperFrame(k14, k23, k1234); - - generatedMC( - piPlusvectors[0].Pt(), piPlusvectors[1].Pt(), piMinusvectors[0].Pt(), piMinusvectors[1].Pt(), - piPlusvectors[0].Eta(), piPlusvectors[1].Eta(), piMinusvectors[0].Eta(), piMinusvectors[1].Eta(), - piPlusvectors[0].Phi(), piPlusvectors[1].Phi(), piMinusvectors[0].Phi(), piMinusvectors[1].Phi(), - piPlusvectors[0].Rapidity(), piPlusvectors[1].Rapidity(), piMinusvectors[0].Rapidity(), piMinusvectors[1].Rapidity(), - p1234.Pt(), p1234.Eta(), p1234.Phi(), p1234.Rapidity(), p1234.M(), - phiPair1, phiPair2, cosThetaPair1, cosThetaPair2); - - histosMCgen.fill(HIST("fourPion_phi_pair_1"), phiPair1); - histosMCgen.fill(HIST("fourPion_phi_pair_2"), phiPair2); - histosMCgen.fill(HIST("fourPion_costheta_pair_1"), cosThetaPair1); - histosMCgen.fill(HIST("fourPion_costheta_pair_2"), cosThetaPair2); - histosMCgen.fill(HIST("phi_cosTheta_pair_1"), phiPair1, cosThetaPair1); - histosMCgen.fill(HIST("phi_cosTheta_pair_2"), phiPair2, cosThetaPair2); - - } // End of 4 Pion MC Generation Process function - PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCgen, "The Process for 4 Pion Analysis from MC Generation", false); - - // Begin of MC Reconstruction function----------------------------------------------------------------------------------------------------------------------------------------------- - using CollisionStuff = soa::Filtered>; - using CollisionTotal = CollisionStuff::iterator; - using TrackStuff = soa::Join; - - void processMCrec(CollisionTotal const& collision, TrackStuff const& tracks) - { - - if (!collision.has_udMcCollision()) { + // vtxITSTPC + if (collision.vtxITSTPC() != vtxITSTPCcut) { return; } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 2); - int gapSide = collision.gapSide(); - std::vector parameters = {pvCut, dcaZcut, dcaXYcut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, pTcut}; - int truegapSide = sgSelector.trueGap(collision, fv0Cut, ft0aCut, ft0cCut, zdcCut); - histosMCreco.fill(HIST("GapSide"), gapSide); - histosMCreco.fill(HIST("TrueGapSide"), truegapSide); - histosMCreco.fill(HIST("EventCounts"), 1); - histosMCreco.fill(HIST("vertexZ"), collision.posZ()); - histosMCreco.fill(HIST("occupancy"), collision.occupancyInTime()); - histosMCreco.fill(HIST("V0A"), collision.totalFV0AmplitudeA()); - histosMCreco.fill(HIST("FT0A"), collision.totalFT0AmplitudeA()); - histosMCreco.fill(HIST("FT0C"), collision.totalFT0AmplitudeC()); - histosMCreco.fill(HIST("ZDC_A"), collision.energyCommonZNA()); - histosMCreco.fill(HIST("ZDC_C"), collision.energyCommonZNC()); - - std::vector selectedTracks; - std::vector selectedPionTracks; - std::vector selectedPionPlusTracks; - std::vector selectedPionMinusTracks; - - for (const auto& t0 : tracks) { - if (trackselector(t0, parameters) && t0.has_udMcParticle()) { - selectedTracks.push_back(t0); - if (selectionPIDPion(t0, true, nSigmaTPCcut, nSigmaTOFcut)) { - selectedPionTracks.push_back(t0); - if (t0.sign() == 1) { - selectedPionPlusTracks.push_back(t0); - } - if (t0.sign() == -1) { - selectedPionMinusTracks.push_back(t0); - } - } // End of Selection PID Pion - } // End of track selections - } // End of loop over tracks - - int numSelectedTracks = static_cast(selectedTracks.size()); - int numSelectedPionTracks = static_cast(selectedPionTracks.size()); - int numPiPlusTracks = static_cast(selectedPionPlusTracks.size()); - int numPionMinusTRacks = static_cast(selectedPionMinusTracks.size()); - - for (int i = 0; i < numSelectedTracks; i++) { - ROOT::Math::PxPyPzMVector selectedTrackVector(selectedTracks[i].px(), selectedTracks[i].py(), selectedTracks[i].pz(), o2::constants::physics::MassPionCharged); - histosMCreco.fill(HIST("tpcSignal"), selectedTrackVector.P(), selectedTracks[i].tpcSignal()); - histosMCreco.fill(HIST("tofBeta"), selectedTrackVector.P(), selectedTracks[i].beta()); - histosMCreco.fill(HIST("tpcNSigmaPi_WTS"), selectedTracks[i].tpcNSigmaPi(), selectedTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaPi_WTS"), selectedTracks[i].tofNSigmaPi(), selectedTrackVector.Pt()); - histosMCreco.fill(HIST("pT_track_WTS"), selectedTrackVector.Pt()); - histosMCreco.fill(HIST("rapidity_track_WTS"), selectedTrackVector.Rapidity()); - histosMCreco.fill(HIST("itsChi2NCl"), selectedTracks[i].itsChi2NCl()); - histosMCreco.fill(HIST("tpcChi2NCl"), selectedTracks[i].tpcChi2NCl()); - histosMCreco.fill(HIST("tpcNClsFindable"), selectedTracks[i].tpcNClsFindable()); - histosMCreco.fill(HIST("dcaXY"), selectedTracks[i].dcaXY()); - histosMCreco.fill(HIST("dcaZ"), selectedTracks[i].dcaZ()); - } // End of loop over tracks with selection only - - for (int i = 0; i < numSelectedPionTracks; i++) { - ROOT::Math::PxPyPzMVector selectedPionTrackVector(selectedPionTracks[i].px(), selectedPionTracks[i].py(), selectedPionTracks[i].pz(), o2::constants::physics::MassPionCharged); - histosMCreco.fill(HIST("tpcSignal_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].tpcSignal()); - histosMCreco.fill(HIST("tofBeta_Pi"), selectedPionTrackVector.P(), selectedPionTracks[i].beta()); - histosMCreco.fill(HIST("tpcNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPi(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaKa(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaPr(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaEl(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tpcNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tpcNSigmaMu(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaPi_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPi(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaKa_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaKa(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaPr_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaPr(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaEl_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaEl(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("tofNSigmaMu_WTS_PID_Pi"), selectedPionTracks[i].tofNSigmaMu(), selectedPionTrackVector.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi"), std::sqrt(selectedPionTracks[i].px() * selectedPionTracks[i].px() + selectedPionTracks[i].py() * selectedPionTracks[i].py())); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi"), selectedPionTrackVector.Rapidity()); - } // End of loop over tracks with selection and PID selection of Pions - - if (numSelectedPionTracks != numFourPionTracks) { + // sbp + if (collision.sbp() != sbpCut) { return; } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 3); - // Selecting Events with net charge = 0 - if (numPionMinusTRacks == numPiMinus && numPiPlusTracks == numPiPlus) { - - ROOT::Math::PtEtaPhiMVector k1, k2, k3, k4, k1234, k13, k14, k23, k24; - - ROOT::Math::PxPyPzMVector p1(selectedPionPlusTracks[0].px(), selectedPionPlusTracks[0].py(), selectedPionPlusTracks[0].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p2(selectedPionPlusTracks[1].px(), selectedPionPlusTracks[1].py(), selectedPionPlusTracks[1].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p3(selectedPionMinusTracks[0].px(), selectedPionMinusTracks[0].py(), selectedPionMinusTracks[0].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p4(selectedPionMinusTracks[1].px(), selectedPionMinusTracks[1].py(), selectedPionMinusTracks[1].pz(), o2::constants::physics::MassPionCharged); - - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p1.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p2.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p3.Pt()); - histosMCreco.fill(HIST("pT_track_WTS_PID_Pi_contributed"), p4.Pt()); - - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p1.Rapidity()); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p2.Rapidity()); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p3.Rapidity()); - histosMCreco.fill(HIST("rapidity_track_WTS_PID_Pi_contributed"), p4.Rapidity()); + // itsROFb + if (collision.itsROFb() != itsROFbCut) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 4); - k1.SetCoordinates(p1.Pt(), p1.Eta(), p1.Phi(), o2::constants::physics::MassPionCharged); - k2.SetCoordinates(p2.Pt(), p2.Eta(), p2.Phi(), o2::constants::physics::MassPionCharged); - k3.SetCoordinates(p3.Pt(), p3.Eta(), p3.Phi(), o2::constants::physics::MassPionCharged); - k4.SetCoordinates(p4.Pt(), p4.Eta(), p4.Phi(), o2::constants::physics::MassPionCharged); + // tfb + if (collision.tfb() != tfbCut) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 5); - ROOT::Math::PxPyPzMVector p1234 = p1 + p2 + p3 + p4; - k1234 = k1 + k2 + k3 + k4; + // FT0A + if (collision.totalFT0AmplitudeA() > ft0aCut) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 6); + // FT0C + if (collision.totalFT0AmplitudeC() > ft0cCut) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 7); + // FV0A + if (collision.totalFV0AmplitudeA() > fv0Cut) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 8); - k13 = k1 + k3; - k14 = k1 + k4; - k23 = k2 + k3; - k24 = k2 + k4; + // ZDC + if (collision.energyCommonZNA() > zdcCut || collision.energyCommonZNC() > zdcCut) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 9); - double phiPair1 = phiCollinsSoperFrame(k13, k24, k1234); - double phiPair2 = phiCollinsSoperFrame(k14, k23, k1234); - double cosThetaPair1 = cosThetaCollinsSoperFrame(k13, k24, k1234); - double cosThetaPair2 = cosThetaCollinsSoperFrame(k14, k23, k1234); + // numContributors + if (collision.numContrib() != numPVContrib) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 10); - sigFromMC( - collision.posX(), collision.posY(), collision.posZ(), - collision.totalFV0AmplitudeA(), collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), - collision.timeFV0A(), collision.timeFT0A(), collision.timeFT0C(), collision.timeFDDA(), collision.timeFDDC(), - collision.timeZNA(), collision.timeZNC(), collision.occupancyInTime(), - selectedPionPlusTracks[0].dcaXY(), selectedPionPlusTracks[1].dcaXY(), selectedPionMinusTracks[0].dcaXY(), selectedPionMinusTracks[1].dcaXY(), - selectedPionPlusTracks[0].dcaZ(), selectedPionPlusTracks[1].dcaZ(), selectedPionMinusTracks[0].dcaZ(), selectedPionMinusTracks[1].dcaZ(), - selectedPionPlusTracks[0].tpcNSigmaPi(), selectedPionPlusTracks[1].tpcNSigmaPi(), selectedPionMinusTracks[0].tpcNSigmaPi(), selectedPionMinusTracks[1].tpcNSigmaPi(), - selectedPionPlusTracks[0].tpcNSigmaKa(), selectedPionPlusTracks[1].tpcNSigmaKa(), selectedPionMinusTracks[0].tpcNSigmaKa(), selectedPionMinusTracks[1].tpcNSigmaKa(), - selectedPionPlusTracks[0].tpcNSigmaPr(), selectedPionPlusTracks[1].tpcNSigmaPr(), selectedPionMinusTracks[0].tpcNSigmaPr(), selectedPionMinusTracks[1].tpcNSigmaPr(), - selectedPionPlusTracks[0].tpcNSigmaEl(), selectedPionPlusTracks[1].tpcNSigmaEl(), selectedPionMinusTracks[0].tpcNSigmaEl(), selectedPionMinusTracks[1].tpcNSigmaEl(), - selectedPionPlusTracks[0].tpcNSigmaMu(), selectedPionPlusTracks[1].tpcNSigmaMu(), selectedPionMinusTracks[0].tpcNSigmaMu(), selectedPionMinusTracks[1].tpcNSigmaMu(), - selectedPionPlusTracks[0].tpcChi2NCl(), selectedPionPlusTracks[1].tpcChi2NCl(), selectedPionMinusTracks[0].tpcChi2NCl(), selectedPionMinusTracks[1].tpcChi2NCl(), - selectedPionPlusTracks[0].tpcNClsFindable(), selectedPionPlusTracks[1].tpcNClsFindable(), selectedPionMinusTracks[0].tpcNClsFindable(), selectedPionMinusTracks[1].tpcNClsFindable(), - selectedPionPlusTracks[0].itsChi2NCl(), selectedPionPlusTracks[1].itsChi2NCl(), selectedPionMinusTracks[0].itsChi2NCl(), selectedPionMinusTracks[1].itsChi2NCl(), - p1.Pt(), p2.Pt(), p3.Pt(), p4.Pt(), - p1.Eta(), p2.Eta(), p3.Eta(), p4.Eta(), - p1.Phi(), p2.Phi(), p3.Phi(), p4.Phi(), - p1.Rapidity(), p2.Rapidity(), p3.Rapidity(), p4.Rapidity(), - p1234.Pt(), p1234.Eta(), p1234.Phi(), p1234.Rapidity(), p1234.M(), - phiPair1, phiPair2, cosThetaPair1, cosThetaPair2); + // vertexZ + if (std::abs(collision.posZ()) > vZCut) { + return; + } + histosCounter.fill(HIST("EventsCounts_vs_runNo"), getRunNumberIndex(collision.runNumber()), 11); + } // End of processCounter function - if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosMCreco.fill(HIST("pT_event_0charge_WTS_PID_Pi"), p1234.Pt()); - if (p1234.Pt() < rhoPtCut) { - histosMCreco.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainA"), p1234.M()); - - histosMCreco.fill(HIST("invMass_pair_1"), (p1 + p3).M()); - histosMCreco.fill(HIST("invMass_pair_2"), (p1 + p4).M()); - histosMCreco.fill(HIST("invMass_pair_3"), (p2 + p3).M()); - histosMCreco.fill(HIST("invMass_pair_4"), (p2 + p4).M()); - - histosMCreco.fill(HIST("CS_phi_pair_1"), phiPair1); - histosMCreco.fill(HIST("CS_phi_pair_2"), phiPair2); - histosMCreco.fill(HIST("CS_costheta_pair_1"), cosThetaPair1); - histosMCreco.fill(HIST("CS_costheta_pair_2"), cosThetaPair2); - histosMCreco.fill(HIST("phi_cosTheta_pair_1"), phiPair1, cosThetaPair1); - histosMCreco.fill(HIST("phi_cosTheta_pair_2"), phiPair2, cosThetaPair2); - } - if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainB"), p1234.M()); + void processTrackCounter(soa::Filtered::iterator const& collision, UDtracks const& tracks) + { + int runIndex = getRunNumberIndex(collision.runNumber()); + // Check if the Event is reconstructed in UPC mode + if (ifCheckUPCmode && (collision.flags() != 1)) { + return; + } + for (const auto& track : tracks) { + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 0); + PxPyPzMVector trackVector(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged); + // is PV contributor + if (track.isPVContributor() != useOnlyPVtracks) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 1); + // pt cut + if (trackVector.Pt() < pTcut) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 2); + // eta cut + if (std::abs(trackVector.Eta()) > etaCut) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 3); + // DCA Z cut + if (std::abs(track.dcaZ()) > dcaZcut) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 4); + // DCA XY cut + float maxDCAxy = 0.0105 + 0.035 / std::pow(trackVector.Pt(), 1.1); + if (dcaXYcut == 0 && (std::fabs(track.dcaXY()) > maxDCAxy)) { + continue; + } else if (dcaXYcut != 0 && (std::fabs(track.dcaXY()) > dcaXYcut)) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 5); + // ITS Track only + if (useITStracksOnly && !track.hasITS()) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 6); + // TPC Track only + if (useTPCtracksOnly && !track.hasTPC()) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 7); + // ITS Chi2 N Clusters cut + if (track.hasITS() && track.itsChi2NCl() > itsChi2NClsCut) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 8); + // TPC Chi2 N Clusters cut + if (track.hasTPC() && track.tpcChi2NCl() > tpcChi2NClsCut) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 9); + // TPC N Clusters Findable cut + if (track.hasTPC() && track.tpcNClsFindable() < tpcNClsFindableCut) { + continue; + } + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 10); + // Selection PID Pion + if (selectionPIDPion(track, useTOF, nSigmaTPCcut, nSigmaTOFcut)) { + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 11); + if (track.sign() == 1) { + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 12); } - if (p1234.Pt() > zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_0charge_WTS_PID_Pi_domainC"), p1234.M()); + if (track.sign() == -1) { + histosCounter.fill(HIST("TracksCounts_vs_runNo"), runIndex, 13); } - } // End of Rapidity range selection + } // End of Selection PID Pion + } // End of loop over tracks + } // End of processCounter function - } // End of Analysis for 0 charge events + PROCESS_SWITCH(ExclusiveRhoTo4Pi, processData, "Data Analysis Function", true); + PROCESS_SWITCH(ExclusiveRhoTo4Pi, processEventCounter, "Event Counter Function", true); + PROCESS_SWITCH(ExclusiveRhoTo4Pi, processTrackCounter, "Track Counter Function", true); - // Selecting Events with net charge != 0 for estimation of background - if (numPionMinusTRacks != numPiMinus && numPiPlusTracks != numPiPlus) { - ROOT::Math::PxPyPzMVector p1(selectedPionTracks[0].px(), selectedPionTracks[0].py(), selectedPionTracks[0].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p2(selectedPionTracks[1].px(), selectedPionTracks[1].py(), selectedPionTracks[1].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p3(selectedPionTracks[2].px(), selectedPionTracks[2].py(), selectedPionTracks[2].pz(), o2::constants::physics::MassPionCharged); - ROOT::Math::PxPyPzMVector p4(selectedPionTracks[3].px(), selectedPionTracks[3].py(), selectedPionTracks[3].pz(), o2::constants::physics::MassPionCharged); + double collinSoperPhi(PtEtaPhiMVector twoPionVector, PtEtaPhiMVector fourPionVector) + { + // Half of the energy per pair of the colliding nucleons. + double halfSqrtSnn = 2680.; + double massOfLead208 = 193.6823; + double momentumBeam = std::sqrt(halfSqrtSnn * halfSqrtSnn * 208 * 208 - massOfLead208 * massOfLead208); + PxPyPzEVector pProjCM(0., 0., -momentumBeam, halfSqrtSnn * 208); // projectile + PxPyPzEVector pTargCM(0., 0., momentumBeam, halfSqrtSnn * 208); // target + // Boost to center of mass frame + Boost boosTo4PiCM{fourPionVector.BoostToCM()}; + XYZVectorF twoPionVectorCM{(boosTo4PiCM(twoPionVector).Vect()).Unit()}; + XYZVectorF beam1CM{(boosTo4PiCM(pProjCM).Vect()).Unit()}; + XYZVectorF beam2CM{(boosTo4PiCM(pTargCM).Vect()).Unit()}; + // Axes + XYZVectorF zaxisCS{((beam1CM.Unit() - beam2CM.Unit()).Unit())}; + XYZVectorF yaxisCS{(beam1CM.Cross(beam2CM)).Unit()}; + XYZVectorF xaxisCS{(yaxisCS.Cross(zaxisCS)).Unit()}; + double phi = std::atan2(yaxisCS.Dot(twoPionVectorCM), xaxisCS.Dot(twoPionVectorCM)); + return phi; + } - ROOT::Math::PxPyPzMVector p1234 = p1 + p2 + p3 + p4; + double collinSoperCosTheta(PtEtaPhiMVector twoPionVector, PtEtaPhiMVector fourPionVector) + { + // Half of the energy per pair of the colliding nucleons. + double halfSqrtSnn = 2680.; + double massOfLead208 = 193.6823; + double momentumBeam = std::sqrt(halfSqrtSnn * halfSqrtSnn * 208 * 208 - massOfLead208 * massOfLead208); + PxPyPzEVector pProjCM(0., 0., -momentumBeam, halfSqrtSnn * 208); // projectile + PxPyPzEVector pTargCM(0., 0., momentumBeam, halfSqrtSnn * 208); // target + // Boost to center of mass frame + Boost boosTo4PiCM{fourPionVector.BoostToCM()}; + XYZVectorF twoPionVectorCM{(boosTo4PiCM(twoPionVector).Vect()).Unit()}; + XYZVectorF beam1CM{(boosTo4PiCM(pProjCM).Vect()).Unit()}; + XYZVectorF beam2CM{(boosTo4PiCM(pTargCM).Vect()).Unit()}; + // Axes + XYZVectorF zaxisCS{((beam1CM.Unit() - beam2CM.Unit()).Unit())}; + double cosThetaCS = zaxisCS.Dot(twoPionVectorCM); + return cosThetaCS; + } + + template + bool isSelectedTrack(T const& track, + float ptcut, + float etaCut, + float dcaxycut, + float dcazcut, + bool ifITS, + bool ifTPC, + float itschi2nclscut, + float tpcchi2nclscut, + float tpcnclsfindablecut) + { + PxPyPzMVector trackVector(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged); + // pt cut + if (trackVector.Pt() < ptcut) { + return false; + } + // eta cut + if (std::fabs(trackVector.Eta()) > etaCut) { + return false; + } + // DCA Z cut + if (std::fabs(track.dcaZ()) > dcazcut) { + return false; + } + // DCA XY cut + float maxDCAxy = 0.0105 + 0.035 / std::pow(trackVector.Pt(), 1.1); + if (dcaxycut == 0 && (std::fabs(track.dcaXY()) > maxDCAxy)) { + return false; + } else if (dcaxycut != 0 && (std::fabs(track.dcaXY()) > dcaxycut)) { + return false; + } + // ITS Track only + if (ifITS && !track.hasITS()) { + return false; + } + // TPC Track only + if (ifTPC && !track.hasTPC()) { + return false; + } + // ITS Chi2 N Clusters cut + if (track.hasITS() && track.itsChi2NCl() > itschi2nclscut) { + return false; + } + // TPC Chi2 N Clusters cut + if (track.hasTPC() && track.tpcChi2NCl() > tpcchi2nclscut) { + return false; + } + // TPC N Clusters Findable cut + if (track.hasTPC() && track.tpcNClsFindable() < tpcnclsfindablecut) { + return false; + } + // All cuts passed + return true; + } // End of Track Selection function - if (std::fabs(p1234.Rapidity()) < rhoRapCut) { - histosMCreco.fill(HIST("pT_event_non0charge_WTS_PID_Pi"), p1234.Pt()); + int getRunNumberIndex(int runNumber) + { + for (int i = 0; i < numRunNums; ++i) { + if (runNos[i] == runNumber) { + return i; + } + } + return -1; // Not found + } // End of getRunNumberIndex function - if (p1234.Pt() < rhoPtCut) { - histosMCreco.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainA"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainA"), p1234.M()); - } - if (p1234.Pt() > rhoPtCut && p1234.Pt() < zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainB"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainB"), p1234.M()); - } - if (p1234.Pt() > zeroPointEight) { - histosMCreco.fill(HIST("rapidity_event_non0charge_WTS_PID_Pi_domainC"), p1234.Rapidity()); - histosMCreco.fill(HIST("invMass_event_non0charge_WTS_PID_Pi_domainC"), p1234.M()); - } - } // End of Rapidity range selection + void setHistBinLabels() + { - } // End of Analysis for non 0 charge events + std::string eventLabels[12] = { + "No Cuts", "UPC mode", "vtxITSTPC=1", "sbp=1", "itsROFb=1", "tfb=1", + "FT0A <= 50", "FT0C <= 50", "FV0A <= 50", "ZDC <= 0", + "n PV Contrib = 4", "V_{z} < 10cm"}; + + int numEventCuts = 12; + + std::string trackLabels[14] = { + "No Cuts", "isPVContributor", "pT > 0.15 GeV/c", "|#eta| < 0.9", "DCA Z < 2 cm", + "DCA XY cut", "hasITS", "hasTPC", "itsChi2NCl < 36", "tpcChi2NCl < 4", + "tpcNClsFindable < 70", "#pi tracks", "#pi^{+} tracks", "#pi^{-} tracks"}; + int numTrackCuts = 14; + + auto h1 = histosCounter.get(HIST("EventsCounts_vs_runNo")); + auto h2 = histosCounter.get(HIST("TracksCounts_vs_runNo")); + auto h3 = histosCounter.get(HIST("fourPionCounts_0c")); + auto h4 = histosCounter.get(HIST("fourPionCounts_0c_within_rap")); + auto h5 = histosCounter.get(HIST("fourPionCounts_0c_selected")); + auto h6 = histosCounter.get(HIST("fourPionCounts_n0c")); + auto h7 = histosCounter.get(HIST("fourPionCounts_n0c_within_rap")); + auto h8 = histosCounter.get(HIST("fourPionCounts_n0c_selected")); + + for (int i = 0; i < numRunNums; ++i) { + h1->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + h2->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + h3->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + h4->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + h5->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + h6->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + h7->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + h8->GetXaxis()->SetBinLabel(i + 1, std::to_string(runNos[i]).c_str()); + } + for (int i = 0; i < numEventCuts; ++i) { + h1->GetYaxis()->SetBinLabel(i + 1, eventLabels[i].c_str()); + } + for (int i = 0; i < numTrackCuts; ++i) { + h2->GetYaxis()->SetBinLabel(i + 1, trackLabels[i].c_str()); + } - } // End of 4 Pion Analysis Process function for MC Reconstruction - PROCESS_SWITCH(ExclusiveRhoTo4Pi, processMCrec, "The Process for 4 Pion Analysis from MC Reconstruction", false); + } // end of setHistBinLabels function }; // End of Struct exclusiveRhoTo4Pi -////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int ExclusiveRhoTo4Pi::runNos[113] = { + 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}; + +int ExclusiveRhoTo4Pi::numRunNums = 113; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { diff --git a/PWGUD/Tasks/flowCorrelationsUpc.cxx b/PWGUD/Tasks/flowCorrelationsUpc.cxx index 59aae4d6c86..baf24af6f94 100644 --- a/PWGUD/Tasks/flowCorrelationsUpc.cxx +++ b/PWGUD/Tasks/flowCorrelationsUpc.cxx @@ -14,29 +14,31 @@ /// \author 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 +#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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/ASoAHelpers.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 "CommonConstants/MathConstants.h" -#include "CCDB/BasicCCDBManager.h" -#include "Common/Core/RecoDecay.h" +#include "Framework/runDataProcessing.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/SGSelector.h" +#include "TRandom3.h" -#include "Common/DataModel/EventSelection.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "PWGCF/DataModel/CorrelationsDerived.h" -#include "PWGCF/Core/CorrelationContainer.h" -#include "PWGCF/Core/PairCuts.h" +#include namespace o2::aod { @@ -98,6 +100,9 @@ struct FlowCorrelationsUpc { 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") ConfigurableAxis axisVertex{"axisVertex", {10, -10, 10}, "vertex axis for histograms"}; ConfigurableAxis axisEta{"axisEta", {40, -1., 1.}, "eta axis for histograms"}; @@ -114,6 +119,7 @@ struct FlowCorrelationsUpc { 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"}; + ConfigurableAxis axisSample{"axisSample", {cfgSampleSize, 0, cfgSampleSize}, "sample axis for histograms"}; // Added UPC Cuts SGSelector sgSelector; @@ -149,11 +155,11 @@ struct FlowCorrelationsUpc { registry.add("Nch", "N_{ch}", {HistType::kTH1D, {axisMultiplicity}}); registry.add("zVtx", "zVtx", {HistType::kTH1D, {axisVertex}}); - registry.add("Trig_hist", "", {HistType::kTHnSparseF, {{axisMultiplicity, axisVertex, axisPtTrigger}}}); + 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 - std::vector corrAxis = {{axisMultiplicity, "Nch"}, + std::vector corrAxis = {{axisSample, "Sample"}, {axisVertex, "z-vtx (cm)"}, {axisPtTrigger, "p_{T} (GeV/c)"}, {axisPtAssoc, "p_{T} (GeV/c)"}, @@ -190,19 +196,24 @@ struct FlowCorrelationsUpc { } template - void fillCorrelations(TTracks tracks1, TTracks tracks2, float posZ, int system, float Nch) // 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) // function to fill the Output functions (sparse) and the delta eta and delta phi histograms { + + int fSampleIndex = gRandom->Uniform(0, cfgSampleSize); + // loop over all tracks for (auto const& track1 : tracks1) { if (system == SameEvent) { - registry.fill(HIST("Trig_hist"), Nch, posZ, track1.pt()); + registry.fill(HIST("Trig_hist"), fSampleIndex, posZ, track1.pt()); } for (auto const& track2 : tracks2) { - if (track1.pt() <= track2.pt()) - continue; // skip if the trigger pt is less than the associate p + if (track1.globalIndex() == track2.globalIndex()) + continue; // For pt-differential correlations, skip if the trigger and associate are the same track + if (system == SameEvent && track1.pt() <= track2.pt()) + continue; // Without pt-differential correlations, skip if the trigger pt is less than the associate pt auto momentum1 = std::array{track1.px(), track1.py(), track1.pz()}; auto momentum2 = std::array{track2.px(), track2.py(), track2.pz()}; @@ -213,10 +224,10 @@ struct FlowCorrelationsUpc { // fill the right sparse and histograms if (system == SameEvent) { - same->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + same->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); registry.fill(HIST("deltaEta_deltaPhi_same"), deltaPhi, deltaEta); } else if (system == MixedEvent) { - mixed->getPairHist()->Fill(step, Nch, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); + mixed->getPairHist()->Fill(step, fSampleIndex, posZ, track1.pt(), track2.pt(), deltaPhi, deltaEta); registry.fill(HIST("deltaEta_deltaPhi_mixed"), deltaPhi, deltaEta); } } @@ -247,7 +258,7 @@ struct FlowCorrelationsUpc { registry.fill(HIST("eventcount"), SameEvent); // because its same event i put it in the 1 bin fillYield(collision, tracks); - fillCorrelations(tracks, tracks, collision.posZ(), SameEvent, tracks.size()); // fill the SE histogram and Sparse + fillCorrelations(tracks, tracks, collision.posZ(), SameEvent); // fill the SE histogram and Sparse } PROCESS_SWITCH(FlowCorrelationsUpc, processSame, "Process same event", true); @@ -265,7 +276,7 @@ struct FlowCorrelationsUpc { 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, tracks1.size()); + fillCorrelations(tracks1, tracks2, collision1.posZ(), MixedEvent); } } PROCESS_SWITCH(FlowCorrelationsUpc, processMixed, "Process mixed events", true); diff --git a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx index 20d4f08d1d6..4e139f0b763 100644 --- a/PWGUD/Tasks/sginclusivePhiKstarSD.cxx +++ b/PWGUD/Tasks/sginclusivePhiKstarSD.cxx @@ -51,6 +51,7 @@ struct SginclusivePhiKstarSD { HistogramRegistry registry{"registry", {}, OutputObjHandlingPolicy::AnalysisObject, true, true}; + Configurable cutRCTflag{"cutRCTflag", 0, {"0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}}; Configurable fv0Cut{"fv0Cut", 50., "FV0A threshold"}; Configurable ft0aCut{"ft0aCut", 100., "FT0A threshold"}; Configurable ft0cCut{"ft0cCut", 50., "FT0C threshold"}; @@ -59,6 +60,16 @@ struct SginclusivePhiKstarSD { Configurable zdcCut{"zdcCut", 0., "ZDC threshold"}; Configurable vzCut{"vzCut", 10., "Vz position"}; Configurable occCut{"occCut", 1000., "Occupancy cut"}; + Configurable hadronicRate{"hadronicRate", 1000., "hadronicRate cut"}; + Configurable useTrs{"useTrs", -1, "kNoCollInTimeRangeStandard cut"}; + Configurable useTrofs{"useTrofs", -1, "kNoCollInRofStandard cut"}; + Configurable useHmpr{"useHmpr", -1, "kNoHighMultCollInPrevRof cut"}; + Configurable useTfb{"useTfb", -1, "kNoTimeFrameBorder cut"}; + Configurable useItsrofb{"useItsrofb", -1, "kNoITSROFrameBorder cut"}; + Configurable useSbp{"useSbp", -1, "kNoSameBunchPileup cut"}; + Configurable useZvtxftovpv{"useZvtxftovpv", -1, "kIsGoodZvtxFT0vsPV cut"}; + Configurable useVtxItsTpc{"useVtxItsTpc", -1, "kIsVertexITSTPC cut"}; + Configurable upcflag{"upcflag", -1, "upc run selection, 0 = std, 1= upc"}; // Track Selections Configurable pvCut{"pvCut", 1.0, "Use Only PV tracks"}; @@ -80,7 +91,6 @@ struct SginclusivePhiKstarSD { Configurable nsigmaTpcCut1{"nsigmaTpcCut1", 3.0, "nsigma tpc cut1"}; Configurable nsigmaTpcCut2{"nsigmaTpcCut2", 3.0, "nsigma tpc cut2"}; Configurable nsigmaTpcCut3{"nsigmaTpcCut3", 3.0, "nsigma tpc cut3"}; - Configurable nsigmaTpcCut4{"nsigmaTpcCut4", 3.0, "nsigma tpc cut4"}; Configurable nsigmaTpcCut{"nsigmaTpcCut", 3.0, "nsigma tpc cut"}; Configurable nsigmaTofCut{"nsigmaTofCut", 9.0, "nsigma tpc+tof cut"}; Configurable nsigmaTofCut1{"nsigmaTofCut1", 3.0, "nsigma tof cut"}; @@ -94,6 +104,7 @@ struct SginclusivePhiKstarSD { Configurable qa{"qa", true, ""}; Configurable rapidityGap{"rapidityGap", true, ""}; + Configurable exclusive{"exclusive", false, "for double gap side "}; Configurable phi{"phi", true, ""}; Configurable rho{"rho", true, ""}; @@ -111,8 +122,25 @@ struct SginclusivePhiKstarSD { Configurable reconstruction{"reconstruction", true, ""}; Configurable generatedId{"generatedId", 31, ""}; + // Configurable axes for histogram + ConfigurableAxis dcaAxisConfig{"dcaAxisConfig", {600, -0.3f, 0.3f}, "DCAxy & DCAz axis"}; + ConfigurableAxis etaAxisConfig{"etaAxisConfig", {400, -1.0f, 1.0f}, "Pseudorapidity & Rapidity axis"}; + ConfigurableAxis vrtxXAxisConfig{"vrtxXAxisConfig", {400, -0.1f, 0.1f}, "Vertex X axis"}; + ConfigurableAxis vrtxYAxisConfig{"vrtxYAxisConfig", {200, -0.05f, 0.05f}, "Vertex Y axis"}; + ConfigurableAxis vrtxZAxisConfig{"vrtxZAxisConfig", {600, -15.0f, 15.0f}, "Vertex Z axis"}; + // ConfigurableAxis VrtxZAxisConfig{"VrtxZAxisConfig", {600, -15.0f, 15.0f}, "Vertex Z axis"}; + void init(InitContext const& context) { + // Axes + AxisSpec dcaxyAxis = {dcaAxisConfig, "DCAxy (cm)"}; + AxisSpec dcazAxis = {dcaAxisConfig, "DCAz (cm)"}; + AxisSpec etaAxis = {etaAxisConfig, "#eta"}; + AxisSpec rapAxis = {etaAxisConfig, "y"}; + AxisSpec VrtxXAxis = {vrtxXAxisConfig, "Vertex X (cm)"}; + AxisSpec VrtxYAxis = {vrtxYAxisConfig, "Vertex Y (cm)"}; + AxisSpec VrtxZAxis = {vrtxZAxisConfig, "Vertex Z (cm)"}; + 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}}); @@ -121,56 +149,56 @@ struct SginclusivePhiKstarSD { if (phi) { registry.add("os_KK_pT_0", "pt kaon pair", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_KK_pT_1", "pt kaon pair", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_KK_pT_2", "pt kaon pair", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_KK_pT_2", "pt kaon pair", kTH3F, {{305, 0.98, 2.2}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_KK_ls_pT_0", "kaon pair like sign", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_KK_ls_pT_1", "kaon pair like sign", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_KK_ls_pT_2", "kaon pair like sign", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_KK_ls_pT_2", "kaon pair like sign", kTH3F, {{305, 0.98, 2.2}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_KK_mix_pT_0", "kaon pair mix event", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_KK_mix_pT_1", "kaon pair mix event", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_KK_mix_pT_2", "kaon pair mix event", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_KK_mix_pT_2", "kaon pair mix event", kTH3F, {{305, 0.98, 2.2}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_KK_rot_pT_0", "kaon pair mix event", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_KK_rot_pT_1", "kaon pair mix event", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_KK_rot_pT_2", "kaon pair mix event", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_KK_rot_pT_2", "kaon pair mix event", kTH3F, {{305, 0.98, 2.2}, {80, -2.0, 2.0}, {100, 0, 10}}); } if (rho) { - registry.add("os_pp_pT_0", "pt pion pair", kTH3F, {{120, 1.44, 2.04}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pp_pT_1", "pt pion pair", kTH3F, {{120, 1.44, 2.04}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pp_pT_2", "pt pion pair", kTH3F, {{120, 1.44, 2.04}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pp_ls_pT_0", "pion pair like sign", kTH3F, {{120, 1.44, 2.04}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pp_ls_pT_1", "pion pair like sign", kTH3F, {{120, 1.44, 2.04}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pp_ls_pT_2", "pion pair like sign", kTH3F, {{120, 1.44, 2.04}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pp_pT_0", "pt pion pair", kTH3F, {{200, 1.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pp_pT_1", "pt pion pair", kTH3F, {{200, 1.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pp_pT_2", "pt pion pair", kTH3F, {{200, 1.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pp_ls_pT_0", "pion pair like sign", kTH3F, {{200, 1.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pp_ls_pT_1", "pion pair like sign", kTH3F, {{200, 1.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pp_ls_pT_2", "pion pair like sign", kTH3F, {{200, 1.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); } if (kstar) { registry.add("os_pk_pT_0", "pion-kaon pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_pk_pT_1", "pion-kaon pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pk_pT_2", "pion-kaon pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pk_pT_2", "pion-kaon pair", kTH3F, {{600, 0.0, 3.0}, {80, -2.0, 2.0}, {1000, 0, 10}}); registry.add("os_pk_mix_pT_0", "pion-kaon mix pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_pk_mix_pT_1", "pion-kaon mix pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pk_mix_pT_2", "pion-kaon mix pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pk_mix_pT_2", "pion-kaon mix pair", kTH3F, {{600, 0.0, 3.0}, {80, -2.0, 2.0}, {1000, 0, 10}}); registry.add("os_pk_rot_pT_0", "pion-kaon rotional pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_pk_rot_pT_1", "pion-kaon rotional pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pk_rot_pT_2", "pion-kaon rotional pair", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pk_rot_pT_2", "pion-kaon rotional pair", kTH3F, {{600, 0.0, 3.0}, {80, -2.0, 2.0}, {1000, 0, 10}}); registry.add("os_pk_ls_pT_0", "pion-kaon pair like sign", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); registry.add("os_pk_ls_pT_1", "pion-kaon like sign", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); - registry.add("os_pk_ls_pT_2", "pion-kaon like sign", kTH3F, {{400, 0.0, 2.0}, {80, -2.0, 2.0}, {100, 0, 10}}); + registry.add("os_pk_ls_pT_2", "pion-kaon like sign", kTH3F, {{600, 0.0, 3.0}, {80, -2.0, 2.0}, {1000, 0, 10}}); registry.add("hRotation", "hRotation", kTH1F, {{360, 0.0, o2::constants::math::TwoPI}}); } // qa plots if (qa) { - registry.add("tpc_dedx", "p vs dE/dx", kTH2F, {{100, 0.0, 10.0}, {10000, 0.0, 2500.0}}); - registry.add("tof_beta", "p vs beta", kTH2F, {{100, 0.0, 10.0}, {100, 0.0, 5.0}}); - - registry.add("tpc_dedx_kaon", "p#k dE/dx", kTH2F, {{100, 0.0, 10.0}, {10000, 0.0, 2500.0}}); - registry.add("tpc_dedx_pion", "p#pi dE/dx", kTH2F, {{100, 0.0, 10.0}, {10000, 0.0, 2500.0}}); - registry.add("tpc_dedx_kaon_1", "tpc+tof pid cut p#k dE/dx", kTH2F, {{100, 0.0, 10.0}, {10000, 0.0, 2500.0}}); - registry.add("tpc_dedx_kaon_2", "tpc+tof pid cut1 p#k dE/dx", kTH2F, {{100, 0.0, 10.0}, {10000, 0.0, 2500.0}}); - registry.add("tpc_dedx_pion_1", "tpc+tof pid cut p#pi dE/dx", kTH2F, {{100, 0.0, 10.0}, {10000, 0.0, 25000.0}}); + registry.add("tpc_dedx", "p vs dE/dx", kTH2F, {{500, 0.0, 10.0}, {5000, 0.0, 5000.0}}); + registry.add("tof_beta", "p vs beta", kTH2F, {{500, 0.0, 10.0}, {500, 0.0, 1.0}}); + + registry.add("tpc_dedx_kaon", "p#k dE/dx", kTH2F, {{500, 0.0, 10.0}, {5000, 0.0, 5000.0}}); + registry.add("tpc_dedx_pion", "p#pi dE/dx", kTH2F, {{500, 0.0, 10.0}, {5000, 0.0, 5000.0}}); + registry.add("tpc_dedx_kaon_1", "tpc+tof pid cut p#k dE/dx", kTH2F, {{500, 0.0, 10.0}, {5000, 0.0, 5000.0}}); + registry.add("tpc_dedx_kaon_2", "tpc+tof pid cut1 p#k dE/dx", kTH2F, {{500, 0.0, 10.0}, {5000, 0.0, 5000.0}}); + registry.add("tpc_dedx_pion_1", "tpc+tof pid cut p#pi dE/dx", kTH2F, {{500, 0.0, 10.0}, {5000, 0.0, 5000.0}}); registry.add("tpc_nsigma_kaon", "p#k n#sigma", kTH2F, {{100, 0.0, 10.0}, {100, -10.0, 10.0}}); registry.add("tpc_nsigma_pion", "p#pi n#sigma", kTH2F, {{100, 0.0, 10.0}, {100, -10.0, 10.0}}); registry.add("tpc_tof_nsigma_kaon", "p#k n#sigma TPC vs TOF", kTH2F, {{100, -10.0, 10.0}, {100, -10.0, 10.0}}); @@ -199,10 +227,32 @@ struct SginclusivePhiKstarSD { registry.add("V0A_0", "V0A amplitude", kTH1F, {{1000, 0.0, 1000.0}}); registry.add("V0A_1", "V0A amplitude", kTH1F, {{1000, 0.0, 1000.0}}); + registry.add("hDcaxy_all_before", "DCAxy Distribution of all tracks before track selection; DCAxy (cm); Counts", kTH1F, {dcaxyAxis}); + registry.add("hDcaz_all_before", "DCAz Distribution of all tracks before track selection; DCAz (cm); Counts", kTH1F, {dcazAxis}); + + registry.add("hDcaxy_all_after", "DCAxy Distribution of all tracks after track selection; DCAxy (cm); Counts", kTH1F, {dcaxyAxis}); + registry.add("hDcaz_all_after", "DCAz Distribution of all tracks after track selection; DCAz (cm); Counts", kTH1F, {dcazAxis}); + + registry.add("hDcaxy_pi", "DCAxy Distribution of selected pions; DCAxy (cm); Counts", kTH1F, {dcaxyAxis}); + registry.add("hDcaz_pi", "DCAz Distribution of selected pions; DCAz (cm); Counts", kTH1F, {dcazAxis}); + + registry.add("hDcaxy_ka", "DCAxy Distribution of selected kaons; DCAxy (cm); Counts", kTH1F, {dcaxyAxis}); + registry.add("hDcaz_ka", "DCAz Distribution of selected kaons; DCAz (cm); Counts", kTH1F, {dcazAxis}); + + registry.add("hVertexX", "Vertex X distribution; Vertex X (cm); Counts", kTH1F, {VrtxXAxis}); + registry.add("hVertexY", "Vertex Y distribution; Vertex Y (cm); Counts", kTH1F, {VrtxYAxis}); + registry.add("hVertexZ", "VertexZ distribution; Vertex Z (cm); Counts", kTH1F, {VrtxZAxis}); + + registry.add("hEta_all_after", "Pseudorapidity of all tracks after track selection; #eta; Counts", kTH1F, {etaAxis}); + registry.add("hRap_all_after", "Rapidity of all tracks after track selection; y; Counts", kTH1F, {rapAxis}); + + registry.add("hEta_pi", "Pseudorapidity of selected Pions; #eta; Counts", kTH1F, {etaAxis}); + registry.add("hRap_pi", "Rapidity of selected Pions; y; Counts", kTH1F, {rapAxis}); + + registry.add("hEta_ka", "Pseudorapidity of selected Kaons; #eta; Counts", kTH1F, {etaAxis}); + registry.add("hRap_ka", "Rapidity of selected Kaons; y; Counts", kTH1F, {rapAxis}); + if (rapidityGap) { - registry.add("mult_0", "mult0", kTH1F, {{150, 0, 150}}); - registry.add("mult_1", "mult1", kTH1F, {{150, 0, 150}}); - registry.add("mult_2", "mult2", kTH1F, {{150, 0, 150}}); registry.add("event_rap_gap", "rap_gap", kTH1F, {{15, 0, 15.0}}); registry.add("rap_mult1", "rap_mult1", kTH1F, {{150, 0, 150}}); registry.add("rap_mult2", "rap_mult2", kTH1F, {{150, 0, 150}}); @@ -219,6 +269,10 @@ struct SginclusivePhiKstarSD { registry.add("gap_mult1", "Mult 1", kTH1F, {{100, 0.0, 100.0}}); registry.add("gap_mult2", "Mult 2", kTH1F, {{100, 0.0, 100.0}}); + registry.add("mult_0", "mult0", kTH1F, {{150, 0, 150}}); + registry.add("mult_1", "mult1", kTH1F, {{150, 0, 150}}); + registry.add("mult_2", "mult2", kTH1F, {{150, 0, 150}}); + // Multiplicity plot if (rapidityGap && phi) { registry.add("os_kk_mass_rap", "phi mass1", kTH3F, {{220, 0.98, 1.2}, {80, -2.0, 2.0}, {100, 0, 10}}); @@ -395,9 +449,9 @@ struct SginclusivePhiKstarSD { } //_____________________________________________________________________________ - double cosThetaCollinsSoperFrame(TLorentzVector pair1, - TLorentzVector pair2, - TLorentzVector fourpion) + double cosThetaCollinsSoperFrame(ROOT::Math::PxPyPzMVector pair1, + ROOT::Math::PxPyPzMVector pair2, + ROOT::Math::PxPyPzMVector fourpion) { double halfSqrtSnn = 2680.; double massOfLead208 = 193.6823; @@ -423,6 +477,23 @@ struct SginclusivePhiKstarSD { return cosThetaCs; } + template + bool isGoodRCTflag(C const& coll) + { + switch (cutRCTflag) { + case 1: + return sgSelector.isCBTOk(coll); + case 2: + return sgSelector.isCBTZdcOk(coll); + case 3: + return sgSelector.isCBTHadronOk(coll); + case 4: + return sgSelector.isCBTHadronZdcOk(coll); + default: + return true; + } + } + template bool selectionPIDKaon1(const T& candidate) { @@ -483,7 +554,7 @@ struct SginclusivePhiKstarSD { } //------------------------------------------------------------------------------------------------------ - double phiCollinsSoperFrame(TLorentzVector pair1, TLorentzVector pair2, TLorentzVector fourpion) + double phiCollinsSoperFrame(ROOT::Math::PxPyPzMVector pair1, ROOT::Math::PxPyPzMVector pair2, ROOT::Math::PxPyPzMVector fourpion) { // Half of the energy per pair of the colliding nucleons. double halfSqrtSnn = 2680.; @@ -518,24 +589,24 @@ struct SginclusivePhiKstarSD { void process(UDCollisionFull const& collision, UDtracksfull const& tracks) { - TLorentzVector v0; - TLorentzVector v1; - TLorentzVector v01; + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + ROOT::Math::PxPyPzMVector v01; int gapSide = collision.gapSide(); 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); - TLorentzVector phiv; - TLorentzVector phiv1; + ROOT::Math::PxPyPzMVector phiv; + ROOT::Math::PxPyPzMVector phiv1; - std::vector onlyPionTracksp; + std::vector onlyPionTracksp; std::vector rawPionTracksp; - std::vector onlyPionTrackspm; + std::vector onlyPionTrackspm; std::vector rawPionTrackspm; - std::vector onlyPionTracksn; + std::vector onlyPionTracksn; std::vector rawPionTracksn; registry.fill(HIST("GapSide"), gapSide); @@ -547,7 +618,29 @@ struct SginclusivePhiKstarSD { return; if (std::abs(collision.occupancyInTime()) > occCut) return; + if (std::abs(collision.hadronicRate()) > hadronicRate) + return; + if (useTrs != -1 && collision.trs() != useTrs) + return; + if (useTrofs != -1 && collision.trofs() != useTrofs) + return; + if (useHmpr != -1 && collision.hmpr() != useHmpr) + return; + if (useTfb != -1 && collision.tfb() != useTfb) + return; + if (useItsrofb != -1 && collision.itsROFb() != useItsrofb) + return; + if (useSbp != -1 && collision.sbp() != useSbp) + return; + if (useZvtxftovpv != -1 && collision.zVtxFT0vPV() != useZvtxftovpv) + return; + if (useVtxItsTpc != -1 && collision.vtxITSTPC() != useVtxItsTpc) + return; + if (!isGoodRCTflag(collision)) + return; + if (upcflag != -1 && collision.flags() != upcflag) + return; int mult = collision.numContrib(); if (gapSide == 0) { registry.fill(HIST("gap_mult0"), mult); @@ -569,18 +662,40 @@ struct SginclusivePhiKstarSD { int trackextra = 0; int trackextraDG = 0; - Partition pvContributors1 = aod::udtrack::isPVContributor == true; - pvContributors1.bindTable(tracks); - if (gapSide == 0) { - registry.get(HIST("nPVContributors_data"))->Fill(pvContributors1.size(), 1.); - } - if (gapSide == 1) { - registry.get(HIST("nPVContributors_data_1"))->Fill(pvContributors1.size(), 1.); + if (qa) { + registry.fill(HIST("hVertexX"), collision.posX()); + registry.fill(HIST("hVertexY"), collision.posY()); + registry.fill(HIST("hVertexZ"), collision.posZ()); } + + /* Partition pvContributors1 = aod::udtrack::isPVContributor == true; + pvContributors1.bindTable(tracks); + if (gapSide == 0) { + registry.get(HIST("nPVContributors_data"))->Fill(pvContributors1.size(), 1.); + } + if (gapSide == 1) { + registry.get(HIST("nPVContributors_data_1"))->Fill(pvContributors1.size(), 1.); + } + */ for (const auto& track1 : tracks) { + + if (qa) { + registry.fill(HIST("hDcaxy_all_before"), track1.dcaXY()); + registry.fill(HIST("hDcaz_all_before"), track1.dcaZ()); + } + if (!trackselector(track1, parameters)) continue; - v0.SetXYZM(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassPionCharged); + + v0.SetCoordinates(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassPionCharged); + + if (qa) { + registry.fill(HIST("hDcaxy_all_after"), track1.dcaXY()); + registry.fill(HIST("hDcaz_all_after"), track1.dcaZ()); + registry.fill(HIST("hEta_all_after"), v0.Eta()); + registry.fill(HIST("hRap_all_after"), v0.Rapidity()); + } + if (selectionPIDPion1(track1)) { onlyPionTrackspm.push_back(v0); rawPionTrackspm.push_back(track1); @@ -631,6 +746,10 @@ struct SginclusivePhiKstarSD { registry.fill(HIST("tpc_nsigma_kaon"), v0.Pt(), track1.tpcNSigmaKa()); registry.fill(HIST("tof_nsigma_kaon"), v0.Pt(), track1.tofNSigmaKa()); registry.fill(HIST("tpc_tof_nsigma_kaon"), track1.tpcNSigmaKa(), track1.tofNSigmaKa()); + registry.fill(HIST("hEta_ka"), v0.Eta()); + registry.fill(HIST("hRap_ka"), v0.Rapidity()); + registry.fill(HIST("hDcaxy_ka"), track1.dcaXY()); + registry.fill(HIST("hDcaz_ka"), track1.dcaZ()); } if (selectionPIDPion1(track1)) { @@ -638,9 +757,22 @@ struct SginclusivePhiKstarSD { registry.fill(HIST("tpc_nsigma_pion"), v0.Pt(), track1.tpcNSigmaPi()); registry.fill(HIST("tof_nsigma_pion"), v0.Pt(), track1.tofNSigmaPi()); registry.fill(HIST("tpc_tof_nsigma_pion"), track1.tpcNSigmaPi(), track1.tofNSigmaPi()); + registry.fill(HIST("hEta_pi"), v0.Eta()); + registry.fill(HIST("hRap_pi"), v0.Rapidity()); + registry.fill(HIST("hDcaxy_pi"), track1.dcaXY()); + registry.fill(HIST("hDcaz_pi"), track1.dcaZ()); } } } + if (gapSide == 0) { + registry.fill(HIST("mult_0"), mult0); + } + if (gapSide == 1) { + registry.fill(HIST("mult_1"), mult1); + } + if (gapSide == 2) { + registry.fill(HIST("mult_2"), mult2); + } if (qa) { if (gapSide == 0) { registry.fill(HIST("V0A_0"), collision.totalFV0AmplitudeA()); @@ -648,7 +780,6 @@ struct SginclusivePhiKstarSD { registry.fill(HIST("FT0C_0"), collision.totalFT0AmplitudeC()); registry.fill(HIST("ZDC_A_0"), collision.energyCommonZNA()); registry.fill(HIST("ZDC_C_0"), collision.energyCommonZNC()); - registry.fill(HIST("mult_0"), mult0); } if (gapSide == 1) { registry.fill(HIST("V0A_1"), collision.totalFV0AmplitudeA()); @@ -656,7 +787,6 @@ struct SginclusivePhiKstarSD { registry.fill(HIST("FT0C_1"), collision.totalFT0AmplitudeC()); registry.fill(HIST("ZDC_A_1"), collision.energyCommonZNA()); registry.fill(HIST("ZDC_C_1"), collision.energyCommonZNC()); - registry.fill(HIST("mult_1"), mult1); } if (gapSide == 2) { registry.fill(HIST("V0A"), collision.totalFV0AmplitudeA()); @@ -664,7 +794,6 @@ struct SginclusivePhiKstarSD { registry.fill(HIST("FT0C"), collision.totalFT0AmplitudeC()); registry.fill(HIST("ZDC_A"), collision.energyCommonZNA()); registry.fill(HIST("ZDC_C"), collision.energyCommonZNC()); - registry.fill(HIST("mult_2"), mult2); } if (rapidityGap) { if (trackgapC > 0 && trackgapA == 0 && trackextra == 0) { @@ -719,8 +848,8 @@ struct SginclusivePhiKstarSD { continue; if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -754,8 +883,8 @@ struct SginclusivePhiKstarSD { continue; if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -790,8 +919,8 @@ struct SginclusivePhiKstarSD { continue; if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -825,8 +954,8 @@ struct SginclusivePhiKstarSD { continue; if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -860,8 +989,8 @@ struct SginclusivePhiKstarSD { continue; if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -895,8 +1024,8 @@ struct SginclusivePhiKstarSD { continue; if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -932,8 +1061,8 @@ struct SginclusivePhiKstarSD { if (phi && selectionPIDKaon1(t0) && selectionPIDKaon1(t1)) { // Apply kaon hypothesis and create pairs - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -943,7 +1072,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_KK_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_KK_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } @@ -955,7 +1084,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_KK_ls_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_KK_ls_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } @@ -971,8 +1100,8 @@ struct SginclusivePhiKstarSD { auto rotkaonPx = t0.px() * std::cos(rotangle) - t0.py() * std::sin(rotangle); auto rotkaonPy = t0.px() * std::sin(rotangle) + t0.py() * std::cos(rotangle); - v0.SetXYZM(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; if (t0.sign() != t1.sign()) { if (gapSide == 0) { @@ -981,7 +1110,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_KK_rot_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_KK_rot_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } @@ -994,9 +1123,9 @@ struct SginclusivePhiKstarSD { continue; if (t0.globalIndex() == t1.globalIndex()) continue; - if (rho && selectionPIDProton(t0, useTof, nsigmaTpcCut, nsigmaTofCut) && selectionPIDPion1(t1)) { - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassProton); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + if (rho && selectionPIDProton(t0, useTof, nsigmaTpcCut, nsigmaTofCut) && selectionPIDKaon1(t1)) { + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassProton); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -1006,7 +1135,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_pp_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_pp_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } // same sign pair @@ -1017,7 +1146,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_pp_ls_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_pp_ls_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } @@ -1025,8 +1154,8 @@ struct SginclusivePhiKstarSD { if (kstar && selectionPIDKaon1(t0) && selectionPIDPion1(t1)) { if (kaoncut && t0.tpcNSigmaPi() < pionNsigmaCut) continue; - v0.SetXYZM(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(t0.px(), t0.py(), t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (t0.sign() != t1.sign()) { @@ -1036,7 +1165,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_pk_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_pk_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } // same sign pair @@ -1047,7 +1176,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_pk_ls_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_pk_ls_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } @@ -1062,8 +1191,8 @@ struct SginclusivePhiKstarSD { auto rotkaonPx = t0.px() * std::cos(rotangle) - t0.py() * std::sin(rotangle); auto rotkaonPy = t0.px() * std::sin(rotangle) + t0.py() * std::cos(rotangle); - v0.SetXYZM(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(rotkaonPx, rotkaonPy, t0.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(t1.px(), t1.py(), t1.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; if (t0.sign() != t1.sign()) { if (gapSide == 0) { @@ -1072,7 +1201,7 @@ struct SginclusivePhiKstarSD { if (gapSide == 1) { registry.fill(HIST("os_pk_rot_pT_1"), v01.M(), v01.Rapidity(), v01.Pt()); } - if (gapSide == 2) { + if (exclusive && gapSide == 2 && mult2 == 2) { registry.fill(HIST("os_pk_rot_pT_2"), v01.M(), v01.Rapidity(), v01.Pt()); } } @@ -1082,12 +1211,12 @@ struct SginclusivePhiKstarSD { } if (fourpion) { if (gapSide == 2 && mult2 == 4) { - TLorentzVector pair1, pair2, pair3, pair4; + ROOT::Math::PxPyPzMVector pair1, pair2, pair3, pair4; if (onlyPionTracksp.size() == 2 && onlyPionTracksn.size() == 2) { - TLorentzVector k1 = onlyPionTracksp.at(0); - TLorentzVector k2 = onlyPionTracksp.at(1); - TLorentzVector k3 = onlyPionTracksn.at(0); - TLorentzVector k4 = onlyPionTracksn.at(1); + ROOT::Math::PxPyPzMVector k1 = onlyPionTracksp.at(0); + ROOT::Math::PxPyPzMVector k2 = onlyPionTracksp.at(1); + ROOT::Math::PxPyPzMVector k3 = onlyPionTracksn.at(0); + ROOT::Math::PxPyPzMVector k4 = onlyPionTracksn.at(1); phiv = k1 + k2 + k3 + k4; pair1 = k1 + k3; pair2 = k2 + k4; @@ -1112,10 +1241,10 @@ struct SginclusivePhiKstarSD { if (onlyPionTracksp.size() != 2 && onlyPionTracksn.size() != 2) { if (onlyPionTracksp.size() + onlyPionTracksn.size() != 4) return; - TLorentzVector l1 = onlyPionTrackspm.at(0); - TLorentzVector l2 = onlyPionTrackspm.at(1); - TLorentzVector l3 = onlyPionTrackspm.at(2); - TLorentzVector l4 = onlyPionTrackspm.at(3); + ROOT::Math::PxPyPzMVector l1 = onlyPionTrackspm.at(0); + ROOT::Math::PxPyPzMVector l2 = onlyPionTrackspm.at(1); + ROOT::Math::PxPyPzMVector l3 = onlyPionTrackspm.at(2); + ROOT::Math::PxPyPzMVector l4 = onlyPionTrackspm.at(3); phiv1 = l1 + l2 + l3 + l4; registry.fill(HIST("os_pppp_pT_2_ls"), phiv1.M(), phiv1.Pt(), phiv1.Rapidity()); } @@ -1134,9 +1263,9 @@ struct SginclusivePhiKstarSD { using BinningTypeVertexContributor = ColumnBinningPolicy; void mixprocess(UDCollisionsFull1 const& collisions, UDtracksfull const& /*track*/) { - TLorentzVector v0; - TLorentzVector v1; - TLorentzVector v01; + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + ROOT::Math::PxPyPzMVector v01; float fitCut[5] = {fv0Cut, ft0aCut, ft0cCut, fddaCut, fddcCut}; std::vector parameters = {pvCut, dcazCut, dcaxyCut, tpcChi2Cut, tpcNClsFindableCut, itsChi2Cut, etaCut, ptCut}; BinningTypeVertexContributor binningOnPositions{{axisVertex, axisMultiplicityClass}, true}; @@ -1158,8 +1287,8 @@ struct SginclusivePhiKstarSD { if (!trackselector(track1, parameters) || !trackselector(track2, parameters)) continue; if (phi && selectionPIDKaon1(track1) && selectionPIDKaon1(track2)) { - v0.SetXYZM(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassKaonCharged); v01 = v0 + v1; // Opposite sign pairs if (track1.sign() != track2.sign()) { @@ -1181,8 +1310,8 @@ struct SginclusivePhiKstarSD { if (track1.globalIndex() == track2.globalIndex()) continue; if (kstar && selectionPIDKaon1(track1) && selectionPIDPion1(track2)) { - v0.SetXYZM(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(track1.px(), track1.py(), track1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(track2.px(), track2.py(), track2.pz(), o2::constants::physics::MassPionCharged); v01 = v0 + v1; // Opposite sign pairs if (track1.sign() != track2.sign()) { @@ -1216,11 +1345,11 @@ struct SginclusivePhiKstarSD { void processMCTruth(aod::UDMcCollisions const& mccollisions, CCs const& collisions, aod::UDMcParticles const& McParts, TCs const& tracks) { // number of McCollisions in DF - TLorentzVector v0; - TLorentzVector v1; - TLorentzVector v01; - TLorentzVector vkstar; - TLorentzVector vphi; + ROOT::Math::PxPyPzMVector v0; + ROOT::Math::PxPyPzMVector v1; + ROOT::Math::PxPyPzMVector v01; + ROOT::Math::PxPyPzMVector vkstar; + ROOT::Math::PxPyPzMVector vphi; for (const auto& mccollision : mccollisions) { if (mccollision.generatorsID() != generatedId) continue; @@ -1236,11 +1365,11 @@ struct SginclusivePhiKstarSD { 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) { - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassPionCharged); } else { - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); - v1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); + v1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); } if (!tr1.isPhysicalPrimary() || !tr2.isPhysicalPrimary()) continue; @@ -1255,7 +1384,7 @@ struct SginclusivePhiKstarSD { if (tr1.has_mothers() && tr2.has_mothers()) { for (const auto& mother : tr1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kK0Star892) { - vkstar.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); + 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.); flag = true; } @@ -1279,8 +1408,8 @@ struct SginclusivePhiKstarSD { if (std::abs(tr1.pdgCode()) != kKPlus || std::abs(tr2.pdgCode()) != kKPlus) continue; - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); - v1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); + v1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); if (tr1.pdgCode() == tr2.pdgCode()) continue; v01 = v0 + v1; @@ -1296,7 +1425,7 @@ struct SginclusivePhiKstarSD { if (tr1.has_mothers() && tr2.has_mothers()) { for (const auto& mother : tr1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kPhi) { - vphi.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); + 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.); flag = true; } @@ -1349,25 +1478,48 @@ struct SginclusivePhiKstarSD { 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.); - Partition pvContributors = aod::udtrack::isPVContributor == true; - pvContributors.bindTable(tracks); + // Partition pvContributors = aod::udtrack::isPVContributor == true; + // pvContributors.bindTable(tracks); if (std::abs(collision.posZ()) > vzCut) return; if (std::abs(collision.occupancyInTime()) > occCut) return; + if (std::abs(collision.hadronicRate()) > hadronicRate) + return; + if (useTrs != -1 && collision.trs() != useTrs) + return; + if (useTrofs != -1 && collision.trofs() != useTrofs) + return; + if (useHmpr != -1 && collision.hmpr() != useHmpr) + return; + if (useTfb != -1 && collision.tfb() != useTfb) + return; + if (useItsrofb != -1 && collision.itsROFb() != useItsrofb) + return; + if (useSbp != -1 && collision.sbp() != useSbp) + return; + if (useZvtxftovpv != -1 && collision.zVtxFT0vPV() != useZvtxftovpv) + return; + if (useVtxItsTpc != -1 && collision.vtxITSTPC() != useVtxItsTpc) + return; + if (!isGoodRCTflag(collision)) + return; + if (upcflag != -1 && collision.flags() != upcflag) + return; + registry.get(HIST("Reco/Stat"))->Fill(truegapSide, 1.); if (truegapSide != gapsideMC) return; - registry.get(HIST("Reco/nPVContributors"))->Fill(pvContributors.size(), 1.); - TLorentzVector vphi; - TLorentzVector vkstar; - TLorentzVector v0; - TLorentzVector vr0; - TLorentzVector vr1; - TLorentzVector vr01; - TLorentzVector vr0g; - TLorentzVector vr1g; - TLorentzVector vr01g; + // 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; + ROOT::Math::PxPyPzMVector vr01; + ROOT::Math::PxPyPzMVector vr0g; + ROOT::Math::PxPyPzMVector vr1g; + ROOT::Math::PxPyPzMVector vr01g; int t1 = 0; if (truegapSide == 0) { registry.fill(HIST("V0A_0_mc"), collision.totalFV0AmplitudeA()); @@ -1401,7 +1553,7 @@ struct SginclusivePhiKstarSD { registry.get(HIST("Reco/tr_chi2ncl_2"))->Fill(tr1.tpcChi2NCl(), 1.); registry.get(HIST("Reco/tr_tpcnclfind_2"))->Fill(tr1.tpcNClsFindable(), 1.); registry.get(HIST("Reco/tr_itsChi2NCl_2"))->Fill(tr1.itsChi2NCl(), 1.); - v0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); + v0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); registry.fill(HIST("tpc_dedx_mc"), v0.P(), tr1.tpcSignal()); registry.fill(HIST("tof_beta_mc"), v0.P(), tr1.beta()); @@ -1421,7 +1573,7 @@ struct SginclusivePhiKstarSD { } t1++; - vr0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); + vr0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassKaonCharged); registry.get(HIST("Reco/trpt"))->Fill(vr0.Pt(), 1.); registry.get(HIST("Reco/treta_k"))->Fill(vr0.Eta(), 1.); if (!selectionPIDKaon1(tr1)) @@ -1437,7 +1589,7 @@ struct SginclusivePhiKstarSD { if (t2 > t1) { if (!selectionPIDKaon1(tr2)) continue; - vr1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + 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; @@ -1452,7 +1604,7 @@ struct SginclusivePhiKstarSD { if (mcPart1.has_mothers() && mcPart2.has_mothers()) { for (const auto& mother : mcPart1.mothers_as()) { if (std::abs(mother.pdgCode()) == o2::constants::physics::Pdg::kPhi) { - vphi.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassPhi); + 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.); flag = true; } @@ -1463,8 +1615,8 @@ struct SginclusivePhiKstarSD { } } } - vr0g.SetXYZM(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassKaonCharged); - vr1g.SetXYZM(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); + vr0g.SetCoordinates(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassKaonCharged); + vr1g.SetCoordinates(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); vr01g = vr0g + vr1g; vr01 = vr0 + vr1; @@ -1499,10 +1651,10 @@ struct SginclusivePhiKstarSD { if (tr1.sign() * tr2.sign() > 0) continue; - vr0.SetXYZM(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); - vr1.SetXYZM(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); - vr0g.SetXYZM(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassPionCharged); - vr1g.SetXYZM(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); + vr0.SetCoordinates(tr1.px(), tr1.py(), tr1.pz(), o2::constants::physics::MassPionCharged); + vr1.SetCoordinates(tr2.px(), tr2.py(), tr2.pz(), o2::constants::physics::MassKaonCharged); + vr0g.SetCoordinates(mcPart1.px(), mcPart1.py(), mcPart1.pz(), o2::constants::physics::MassPionCharged); + vr1g.SetCoordinates(mcPart2.px(), mcPart2.py(), mcPart2.pz(), o2::constants::physics::MassKaonCharged); vr01g = vr0g + vr1g; vr01 = vr0 + vr1; if (!trackselector(tr1, parameters) || !trackselector(tr2, parameters)) { @@ -1514,7 +1666,7 @@ struct SginclusivePhiKstarSD { 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.SetXYZM(mother.px(), mother.py(), mother.pz(), o2::constants::physics::MassK0Star892); + 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.); flag = true; } diff --git a/PWGUD/Tasks/testMCstdTabsRL.cxx b/PWGUD/Tasks/testMcStdTabsRl.cxx similarity index 79% rename from PWGUD/Tasks/testMCstdTabsRL.cxx rename to PWGUD/Tasks/testMcStdTabsRl.cxx index 6ac26211e03..9748b28784f 100644 --- a/PWGUD/Tasks/testMCstdTabsRL.cxx +++ b/PWGUD/Tasks/testMcStdTabsRl.cxx @@ -9,7 +9,7 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. // -/// \file testMCstdTabsRL.cxx +/// \file testMcStdTabsRl.cxx /// \brief task to test the Monte Carlo UD production generatorIDs on hyperloop /// /// \author Roman Lavicka , Austrian Academy of Sciences & SMI @@ -17,14 +17,14 @@ // // C++ headers +#include #include #include -#include #include // O2 headers -#include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/HistogramRegistry.h" #include "Framework/O2DatabasePDGPlugin.h" #include "Framework/runDataProcessing.h" @@ -33,24 +33,27 @@ #include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" // ROOT headers -#include "TLorentzVector.h" +#include "Math/Vector4D.h" using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; using namespace o2::constants::physics; -struct TestMCstdTabsRL { +struct TestMcStdTabsRl { // Global varialbes Service pdg; HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + // declare configurables + Configurable useMcgenidGetGeneratorID{"useMcgenidGetGeneratorID", true, {"Use o2::mcgenid::getGeneratorId instead of o2::mccollision::getGeneratorId; default it true."}}; + struct : ConfigurableGroup { - ConfigurableAxis zzAxisNtracks{"zzAxisNtracks", {30, -0.5, 29.5}, "Number of tracks in collision"}; - ConfigurableAxis zzAxisNparticles{"zzAxisNparticles", {60, -0.5, 59.5}, "Number of particles in collision"}; - ConfigurableAxis zzAxisNprocesses{"zzAxisNprocesses", {50, -0.5, 49.5}, "Number of processes"}; + ConfigurableAxis zzAxisNtracks{"zzAxisNtracks", {100, -0.5, 99.5}, "Number of tracks in collision"}; + ConfigurableAxis zzAxisNparticles{"zzAxisNparticles", {100, -0.5, 99.5}, "Number of particles in collision"}; + ConfigurableAxis zzAxisNprocesses{"zzAxisNprocesses", {1000, -0.5, 999.5}, "Number of processes"}; ConfigurableAxis zzAxisInvMassWide{"zzAxisInvMassWide", {1000, 0., 10.}, "Invariant mass (GeV/c^{2}), wider range"}; ConfigurableAxis zzAxisPt{"zzAxisPt", {400, 0., 2.}, "Transversal momentum (GeV/c)"}; ConfigurableAxis zzAxisRap{"zzAxisRap", {50, -1.2, 1.2}, "Rapidity (a.u.)"}; @@ -74,34 +77,36 @@ struct TestMCstdTabsRL { void processMCgen(aod::McCollision const& collision, aod::McParticles const& particles) { - histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(collision.generatorsID(), 1); - histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(collision.generatorsID(), particles.size()); + const auto genID = useMcgenidGetGeneratorID ? o2::mcgenid::getGeneratorId(collision.getGeneratorId()) : collision.getGeneratorId(); + + histos.get(HIST("Events/Truth/hGenIDvsCountCollisions"))->Fill(genID, 1); + histos.get(HIST("Events/Truth/hGenIDvsNparticles"))->Fill(genID, particles.size()); - TLorentzVector mother; + ROOT::Math::LorentzVector> mother; for (const auto& particle : particles) { - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(collision.generatorsID(), particle.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesAll"))->Fill(genID, particle.pdgCode()); // if (!particle.isPhysicalPrimary()) continue; if (particle.has_mothers()) continue; mother.SetPxPyPzE(particle.px(), particle.py(), particle.pz(), energy(pdg->Mass(particle.pdgCode()), particle.px(), particle.py(), particle.pz())); - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesNoMother"))->Fill(collision.generatorsID(), particle.pdgCode()); - histos.get(HIST("Events/Truth/hGenIDvsMotherMass"))->Fill(collision.generatorsID(), mother.M()); - histos.get(HIST("Events/Truth/hGenIDvsMotherPt"))->Fill(collision.generatorsID(), particle.pt()); - histos.get(HIST("Events/Truth/hGenIDvsMotherRap"))->Fill(collision.generatorsID(), particle.y()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesNoMother"))->Fill(genID, particle.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsMotherMass"))->Fill(genID, mother.M()); + histos.get(HIST("Events/Truth/hGenIDvsMotherPt"))->Fill(genID, particle.pt()); + histos.get(HIST("Events/Truth/hGenIDvsMotherRap"))->Fill(genID, particle.y()); const auto& daughters = particle.daughters_as(); - histos.get(HIST("Events/Truth/hGenIDvsNdaughters"))->Fill(collision.generatorsID(), daughters.size()); + histos.get(HIST("Events/Truth/hGenIDvsNdaughters"))->Fill(genID, daughters.size()); for (const auto& daughter : daughters) { - histos.get(HIST("Events/Truth/hGenIDvsPDGcodesDaughters"))->Fill(collision.generatorsID(), daughter.pdgCode()); + histos.get(HIST("Events/Truth/hGenIDvsPDGcodesDaughters"))->Fill(genID, daughter.pdgCode()); } } } // end processMCgenDG - PROCESS_SWITCH(TestMCstdTabsRL, processMCgen, "Iterate Monte Carlo UD tables with truth data.", true); + PROCESS_SWITCH(TestMcStdTabsRl, processMCgen, "Iterate Monte Carlo UD tables with truth data.", true); }; WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc)}; + adaptAnalysisTask(cfgc)}; } diff --git a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx index eb16b83f315..d20a78429dd 100644 --- a/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx +++ b/PWGUD/Tasks/upcPhotonuclearAnalysisJMG.cxx @@ -100,7 +100,8 @@ struct upcPhotonuclearAnalysisJMG { HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; // Declare configurables on events/collisions - Configurable nEvenstMixed{"nEvenstMixed", 3, {"Events to be Mixed"}}; + 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"}}; @@ -275,23 +276,18 @@ struct upcPhotonuclearAnalysisJMG { mixedGapSideC.setObject(new CorrelationContainer("mixedEventGapSideC", "mixedEventGapSideC", corrAxis, effAxis, {})); } - std::vector vtxBinsEdges{VARIABLE_WIDTH, -10.0f, -5.0f, 0.0f, 5.0f, 10.0f}; + 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}; SliceCache cache; + int countGapA = 0; + int countGapC = 0; // Binning only on PosZ without multiplicity // using BinningType = ColumnBinningPolicy; using BinningType = ColumnBinningPolicy; - BinningType bindingOnVtx{{vtxBinsEdges, {gapSideBinsEdges}}, true}; - SameKindPair pairs{bindingOnVtx, nEvenstMixed, -1, &cache}; - - // ColumnBinningPolicy bindingOnVtx{{vtxBinsEdges, multBinsEdges}, true}; - - // SameKindPair, - // FullUDTracks, - // ColumnBinningPolicy> - // pair{bindingOnVtx, 5, -1, &cache}; + BinningType bindingOnVtx{{vtxBinsEdges, gapSideBinsEdges}, true}; + SameKindPair pairs{bindingOnVtx, nEventsMixed, -1, &cache}; template bool isCollisionCutSG(CSG const& collision, int SideGap) @@ -584,7 +580,8 @@ struct upcPhotonuclearAnalysisJMG { if (fillCollisionUD(sameGapSideC, multiplicity) == false) { return; } - // LOGF(debug, "Filling sameGapSideC events"); + histos.fill(HIST("eventcount"), -1); + // LOGF(info, "Filling sameGapSideC events"); fillCorrelationsUD(sameGapSideC, reconstructedTracks, reconstructedTracks, multiplicity, reconstructedCollision.posZ()); break; default: @@ -601,18 +598,34 @@ struct upcPhotonuclearAnalysisJMG { // int sgSide = reconstructedCollision.gapSide(); // int sgSide = 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 + + maxCountGapA = histEventCount->GetBinContent(binA) * factorEventsMixed; + maxCountGapC = histEventCount->GetBinContent(binC) * factorEventsMixed; + } + for (const auto& [collision1, tracks1, collision2, tracks2] : pairs) { if (collision1.size() == 0 || collision2.size() == 0) { - // LOGF(debug, "One or both collisions are empty."); + // LOGF(info, "One or both collisions are empty."); continue; } + if (countGapA >= maxCountGapA && countGapC >= maxCountGapC) { + break; + } float multiplicity = 0; if (collision1.gapSide() == 0 && collision2.gapSide() == 0) { // gap on side A if (isCollisionCutSG(collision1, 0) == false && isCollisionCutSG(collision2, 0) == false) { continue; } - // LOGF(debug, "In the pairs loop, gap side A"); + // 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; @@ -620,20 +633,22 @@ struct upcPhotonuclearAnalysisJMG { // 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(debug, "Filling mixedGapSideA events, Gap for side A"); + // 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; } - // LOGF(debug, "In the pairs loop, gap side C"); + // 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(debug, "Filling mixedGapSideC events, Gap for side C"); + // LOGF(info, "Filling mixedGapSideC events, Gap for side C"); } else { continue; } diff --git a/PWGUD/Tasks/upcRhoAnalysis.cxx b/PWGUD/Tasks/upcRhoAnalysis.cxx index 2bb9865cf34..244096b0a1b 100644 --- a/PWGUD/Tasks/upcRhoAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoAnalysis.cxx @@ -9,41 +9,47 @@ // granted to it by virtue of its status as an Intergovernmental Organization // or submit itself to any jurisdiction. /// -/// \brief task for analysis of rho in UPCs using UD tables (from SG producer) -/// includes event tagging based on ZN information, track selection, reconstruction, +/// \brief Task for analysis of rho in UPCs using UD tables (from SG producer). +/// Includes event tagging based on ZN information, track selection, reconstruction, /// and also some basic stuff for decay phi anisotropy studies /// \author Jakub Juracka, jakub.juracka@cern.ch /// \file upcRhoAnalysis.cxx -#include -#include -#include +#include "PWGUD/Core/SGSelector.h" +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/DataModel/PIDResponse.h" -#include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" -#include -#include "TLorentzVector.h" - -#include "Common/DataModel/PIDResponse.h" +#include "Math/Vector4D.h" +#include "TPDGCode.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include +#include +#include +#include +#include +#include using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using FullUdSgCollision = soa::Join::iterator; -using FullUdDgCollision = soa::Join::iterator; +using FullUdSgCollision = soa::Join::iterator; +using FullUdDgCollision = soa::Join::iterator; using FullUdTracks = soa::Join; +using FullMcUdCollision = soa::Join::iterator; namespace o2::aod { namespace reco_tree { // event info +DECLARE_SOA_COLUMN(RecoSetting, recoSetting, uint16_t); DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); DECLARE_SOA_COLUMN(LocalBC, localBC, int); DECLARE_SOA_COLUMN(NumContrib, numContrib, int); @@ -66,6 +72,7 @@ DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); +DECLARE_SOA_COLUMN(NeutronClass, neutronClass, int); // pion tracks DECLARE_SOA_COLUMN(PhiRandom, phiRandom, float); DECLARE_SOA_COLUMN(PhiCharge, phiCharge, float); @@ -81,10 +88,10 @@ DECLARE_SOA_COLUMN(TrackDcaZ, trackDcaZ, float[2]); DECLARE_SOA_COLUMN(TrackTpcSignal, trackTpcSignal, float[2]); } // namespace reco_tree DECLARE_SOA_TABLE(RecoTree, "AOD", "RECOTREE", - reco_tree::RunNumber, reco_tree::LocalBC, reco_tree::NumContrib, reco_tree::PosX, reco_tree::PosY, reco_tree::PosZ, + reco_tree::RecoSetting, reco_tree::RunNumber, reco_tree::LocalBC, reco_tree::NumContrib, reco_tree::PosX, reco_tree::PosY, reco_tree::PosZ, 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::EnergyCommonZNA, reco_tree::EnergyCommonZNC, reco_tree::TimeZNA, reco_tree::TimeZNC, reco_tree::NeutronClass, reco_tree::PhiRandom, reco_tree::PhiCharge, reco_tree::TrackSign, reco_tree::TrackPt, reco_tree::TrackEta, reco_tree::TrackPhi, reco_tree::TrackPiPID, reco_tree::TrackElPID, reco_tree::TrackKaPID, reco_tree::TrackDcaXY, reco_tree::TrackDcaZ, reco_tree::TrackTpcSignal); namespace mc_tree @@ -113,50 +120,60 @@ struct UpcRhoAnalysis { Produces recoTree; Produces mcTree; - Configurable savePions{"savePions", true, "save pion tracks into derived tables"}; - Configurable saveElectrons{"saveElectrons", false, "save electron tracks into derived tables"}; - Configurable saveKaons{"saveKaons", false, "save kaon tracks into derived tables"}; + SGSelector sgSelector; float pcEtaCut = 0.9; // physics coordination recommendation + + Configurable numPions{"numPions", 2, "required number of pions in the event"}; + + Configurable cutGapSide{"cutGapSide", true, "apply gap side cut"}; + Configurable gapSide{"gapSide", 2, "required gap side"}; + 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 onlyGoldenRuns{"onlyGoldenRuns", false, "process only golden runs"}; + Configurable useRecoFlag{"useRecoFlag", false, "use reco 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 cutRctFlag{"cutRctFlag", 0, "0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}; Configurable collisionsPosZMaxCut{"collisionsPosZMaxCut", 10.0, "max Z position cut on collisions"}; - Configurable collisionsNumContribsMaxCut{"collisionsNumContribsMaxCut", 4, "max number of contributors cut on collisions"}; + 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 tracksTpcNSigmaPiCut{"tracksTpcNSigmaPiCut", 3.0, "TPC nSigma pion cut"}; - Configurable tracksTpcNSigmaElCut{"tracksTpcNSigmaElCut", 3.0, "TPC nSigma electron cut"}; - Configurable tracksTpcNSigmaKaCut{"tracksTpcNSigmaKaCut", 3.0, "TPC nSigma kaon cut"}; Configurable tracksDcaMaxCut{"tracksDcaMaxCut", 1.0, "max DCA cut on tracks"}; - Configurable tracksMinItsNClsCut{"tracksMinItsNClsCut", 6, "min ITS clusters cut"}; + Configurable tracksMinItsNClsCut{"tracksMinItsNClsCut", 4, "min ITS clusters cut"}; Configurable tracksMaxItsChi2NClCut{"tracksMaxItsChi2NClCut", 3.0, "max ITS chi2/Ncls cut"}; Configurable tracksMinTpcNClsCut{"tracksMinTpcNClsCut", 120, "min TPC clusters cut"}; - Configurable tracksMinTpcNClsCrossedRowsCut{"tracksMinTpcNClsCrossedRowsCut", 140, "min TPC crossed rows cut"}; + Configurable tracksMinTpcNClsCrossedRowsCut{"tracksMinTpcNClsCrossedRowsCut", 130, "min TPC crossed rows cut"}; Configurable tracksMinTpcChi2NClCut{"tracksMinTpcChi2NClCut", 1.0, "min TPC chi2/Ncls cut"}; - Configurable tracksMaxTpcChi2NClCut{"tracksMaxTpcChi2NClCut", 1.8, "max TPC chi2/Ncls cut"}; - Configurable tracksMinTpcNClsCrossedOverFindableCut{"tracksMinTpcNClsCrossedOverFindableCut", 1.05, "min TPC crossed rows / findable clusters cut"}; - Configurable tracksMinPtCut{"tracksMinPtCut", 0.2, "min pT cut on tracks"}; + Configurable tracksMaxTpcChi2NClCut{"tracksMaxTpcChi2NClCut", 3.0, "max TPC chi2/Ncls cut"}; + Configurable tracksMinTpcNClsCrossedOverFindableCut{"tracksMinTpcNClsCrossedOverFindableCut", 1.0, "min TPC crossed rows / findable clusters cut"}; + Configurable tracksMinPtCut{"tracksMinPtCut", 0.1, "min pT cut on tracks"}; - Configurable systemMassMinCut{"systemMassMinCut", 0.4, "min M cut for reco system"}; - Configurable systemMassMaxCut{"systemMassMaxCut", 1.2, "max M cut for reco system"}; + Configurable systemMassMinCut{"systemMassMinCut", 0.5, "min M cut for reco system"}; + Configurable systemMassMaxCut{"systemMassMaxCut", 1.0, "max M cut for reco system"}; Configurable systemPtCut{"systemPtCut", 0.1, "max pT cut for reco system"}; Configurable systemYCut{"systemYCut", 0.9, "rapiditiy cut for reco system"}; - ConfigurableAxis mAxis{"mAxis", {1000, 0.0, 10.0}, "m (GeV/#it{c}^{2})"}; - ConfigurableAxis mCutAxis{"mCutAxis", {160, 0.4, 1.2}, "m (GeV/#it{c}^{2})"}; - ConfigurableAxis ptAxis{"ptAxis", {1000, 0.0, 10.0}, "p_{T} (GeV/#it{c})"}; - ConfigurableAxis ptCutAxis{"ptCutAxis", {100, 0.0, 0.1}, "p_{T} (GeV/#it{c})"}; - ConfigurableAxis pt2Axis{"pt2Axis", {100, 0.0, 0.01}, "p_{T}^{2} (GeV^{2}/#it{c}^{2})"}; - ConfigurableAxis etaAxis{"etaAxis", {800, -4.0, 4.0}, "#eta"}; - ConfigurableAxis etaCutAxis{"etaCutAxis", {180, -0.9, 0.9}, "#eta"}; - ConfigurableAxis yAxis{"yAxis", {400, -4.0, 4.0}, "y"}; - ConfigurableAxis yCutAxis{"yCutAxis", {180, -0.9, 0.9}, "y"}; - ConfigurableAxis phiAxis{"phiAxis", {180, 0.0, o2::constants::math::TwoPI}, "#phi"}; - ConfigurableAxis phiAsymmAxis{"phiAsymmAxis", {182, -o2::constants::math::PI, o2::constants::math::PI}, "#phi"}; - ConfigurableAxis momentumFromPhiAxis{"momentumFromPhiAxis", {400, -0.1, 0.1}, "p (GeV/#it{c})"}; + ConfigurableAxis mAxis{"mAxis", {1000, 0.0, 10.0}, "#it{m} (GeV/#it{c}^{2})"}; + ConfigurableAxis ptAxis{"ptAxis", {1000, 0.0, 10.0}, "#it{p}_{T} (GeV/#it{c})"}; + ConfigurableAxis pt2Axis{"pt2Axis", {1000, 0.0, 0.1}, "#it{p}_{T}^{2} (GeV^{2}/#it{c}^{2})"}; + ConfigurableAxis etaAxis{"etaAxis", {300, -1.5, 1.5}, "#it{#eta}"}; + ConfigurableAxis yAxis{"yAxis", {400, -4.0, 4.0}, "#it{y}"}; + ConfigurableAxis phiAxis{"phiAxis", {180, 0.0, o2::constants::math::TwoPI}, "#it{#phi} (rad)"}; + 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 runNumberAxis{"runNumberAxis", {1355, 544012.5, 545367.5}, "run number"}; + ConfigurableAxis nSigmaAxis{"nSigmaAxis", {600, -30.0, 30.0}, "TPC #it{n#sigma}"}; HistogramRegistry rQC{"rQC", {}, OutputObjHandlingPolicy::AnalysisObject}; HistogramRegistry rTracks{"rTracks", {}, OutputObjHandlingPolicy::AnalysisObject}; @@ -167,73 +184,84 @@ struct UpcRhoAnalysis { { // QA // // collisions - rQC.add("QC/collisions/all/hPosXY", ";x (cm);y (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); - rQC.add("QC/collisions/all/hPosZ", ";z (cm);counts", kTH1D, {{400, -20.0, 20.0}}); - rQC.add("QC/collisions/all/hNumContrib", ";number of contributors;counts", kTH1D, {{36, -0.5, 35.5}}); + 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, {{1000, 0.0, 1000.0}}); - rQC.add("QC/collisions/all/hTotalFT0AmplitudeC", ";FT0C amplitude;counts", kTH1D, {{1000, 0.0, 1000.0}}); - rQC.add("QC/collisions/all/hTotalFV0AmplitudeA", ";FV0A amplitude;counts", kTH1D, {{1000, 0.0, 1000.0}}); - rQC.add("QC/collisions/all/hTotalFDDAmplitudeA", ";FDDA amplitude;counts", kTH1D, {{1000, 0.0, 1000.0}}); - rQC.add("QC/collisions/all/hTotalFDDAmplitudeC", ";FDDC amplitude;counts", kTH1D, {{1000, 0.0, 1000.0}}); - rQC.add("QC/collisions/all/hTimeFT0A", ";FT0A time (ns);counts", kTH1D, {{200, -100.0, 100.0}}); - rQC.add("QC/collisions/all/hTimeFT0C", ";FT0C time (ns);counts", kTH1D, {{200, -100.0, 100.0}}); - rQC.add("QC/collisions/all/hTimeFV0A", ";FV0A time (ns);counts", kTH1D, {{200, -100.0, 100.0}}); - rQC.add("QC/collisions/all/hTimeFDDA", ";FDDA time (ns);counts", kTH1D, {{200, -100.0, 100.0}}); - rQC.add("QC/collisions/all/hTimeFDDC", ";FDDC time (ns);counts", kTH1D, {{200, -100.0, 100.0}}); + 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/selected/"); // clone "all" histograms as "selected" + rQC.addClone("QC/collisions/all/", "QC/collisions/trackSelections/"); // clone "all" histograms as "selected" + rQC.addClone("QC/collisions/all/", "QC/collisions/systemSelections/"); // tracks - rQC.add("QC/tracks/all/hTpcNSigmaPi", ";TPC n#sigma(#pi);counts", kTH1D, {{400, -10.0, 30.0}}); - rQC.add("QC/tracks/all/hTpcNSigmaEl", ";TPC n#sigma(e);counts", kTH1D, {{400, -10.0, 30.0}}); - rQC.add("QC/tracks/all/hTpcNSigmaKa", ";TPC n#sigma(K);counts", kTH1D, {{400, -10.0, 30.0}}); - rQC.add("QC/tracks/all/hDcaXYZ", ";DCA_{z} (cm);DCA_{xy} (cm);counts", kTH2D, {{1000, -5.0, 5.0}, {1000, -5.0, 5.0}}); - rQC.add("QC/tracks/all/hItsNCls", ";ITS N_{cls};counts", kTH1D, {{11, -0.5, 10.5}}); - rQC.add("QC/tracks/all/hItsChi2NCl", ";ITS #chi^{2}/N_{cls};counts", kTH1D, {{1000, 0.0, 100.0}}); - rQC.add("QC/tracks/all/hTpcChi2NCl", ";TPC #chi^{2}/N_{cls};counts", kTH1D, {{1000, 0.0, 100.0}}); - rQC.add("QC/tracks/all/hTpcNCls", ";TPC N_{cls} found;counts", kTH1D, {{200, 0.0, 200.0}}); - rQC.add("QC/tracks/all/hTpcNClsCrossedRows", ";TPC crossed rows;counts", kTH1D, {{200, 0.0, 200.0}}); - rQC.add("QC/tracks/all/hTpcNClsCrossedRowsOverNClsFindable", ";TPC crossed rows/findable N_{cls};counts", kTH1D, {{100, 0.0, 10.0}}); - rQC.add("QC/tracks/all/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); - rQC.add("QC/tracks/all/hEta", ";y;counts", kTH1D, {etaAxis}); - rQC.add("QC/tracks/all/hPhi", ";#phi;counts", kTH1D, {phiAxis}); - rQC.add("QC/tracks/all/hTpcSignalVsP", ";p (GeV/#it{c});TPC signal;counts", kTH2D, {ptAxis, {500, 0.0, 500.0}}); - rQC.add("QC/tracks/all/hTpcSignalVsPt", ";p_{T} (GeV/#it{c});TPC signal;counts", kTH2D, {ptAxis, {500, 0.0, 500.0}}); + 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/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};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/selected/"); // clone "raw" histograms as "cut" - rQC.add("QC/tracks/selected/hRemainingTracks", ";remaining tracks;counts", kTH1D, {{21, -0.5, 20.5}}); - rQC.add("QC/tracks/selected/hTpcNSigmaPi2D", ";TPC n#sigma(#pi_{leading});TPC n#sigma(#pi_{subleading});counts", kTH2D, {{400, -10.0, 30.0}, {400, -10.0, 30.0}}); - rQC.add("QC/tracks/selected/hTpcNSigmaEl2D", ";TPC n#sigma(e_{leading});TPC n#sigma(e_{subleading});counts", kTH2D, {{400, -10.0, 30.0}, {400, -10.0, 30.0}}); - rQC.add("QC/tracks/selected/hTpcNSigmaKa2D", ";TPC n#sigma(K_{leading});TPC n#sigma(K_{subleading});counts", kTH2D, {{400, -10.0, 30.0}, {400, -10.0, 30.0}}); + rQC.addClone("QC/tracks/all/", "QC/tracks/trackSelections/"); // clone "raw" histograms as "cut" + 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}); // selection counter - std::vector selectionCounterLabels = {"all tracks", "PV contributor", "ITS hit", "ITS N_{clusters}", "ITS #chi^{2}/N_{clusters}", "TPC hit", "TPC N_{clusters} found", "TPC #chi^{2}/N_{clusters}", "TPC crossed rows", - "TPC crossed rows/N_{clusters}", + std::vector selectionCounterLabels = {"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", - "p_{T}", "DCA", "#eta", "exactly 2 tracks"}; + "#it{p}_{T}", "#it{DCA}", "#it{#eta}", "exactly 2 tracks", "PID"}; rQC.add("QC/tracks/hSelectionCounter", ";;tracks passing selections", kTH1D, {{static_cast(selectionCounterLabels.size()), -0.5, static_cast(selectionCounterLabels.size()) - 0.5}}); - for (int i = 0; i < static_cast(selectionCounterLabels.size()); ++i) + rQC.add("QC/tracks/hSelectionCounterPerRun", ";;run number;tracks passing selections", kTH2D, {{static_cast(selectionCounterLabels.size()), -0.5, static_cast(selectionCounterLabels.size()) - 0.5}, runNumberAxis}); + for (int i = 0; i < static_cast(selectionCounterLabels.size()); ++i) { rQC.get(HIST("QC/tracks/hSelectionCounter"))->GetXaxis()->SetBinLabel(i + 1, selectionCounterLabels[i].c_str()); + rQC.get(HIST("QC/tracks/hSelectionCounterPerRun"))->GetXaxis()->SetBinLabel(i + 1, selectionCounterLabels[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"); // TRACKS (2D) - rTracks.add("tracks/all/unlike-sign/hPt", ";p_{T}(#pi_{leading}) (GeV/#it{c});p_{T}(#pi_{subleading}) (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); - rTracks.add("tracks/all/unlike-sign/hEta", ";#eta(#pi_{leading});#eta(#pi_{subleading});counts", kTH2D, {etaCutAxis, etaCutAxis}); - rTracks.add("tracks/all/unlike-sign/hPhi", ";#phi(#pi_{leading});#phi(#pi_{subleading});counts", kTH2D, {phiAxis, phiAxis}); - rTracks.addClone("tracks/all/unlike-sign/", "tracks/all/like-sign/positive/"); - rTracks.addClone("tracks/all/unlike-sign/", "tracks/all/like-sign/negative/"); - rTracks.addClone("tracks/all/", "tracks/selected/"); + 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};#it{#phi}_{subleading};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", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); - rSystem.add("system/all/unlike-sign/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); - rSystem.add("system/all/unlike-sign/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); - rSystem.add("system/all/unlike-sign/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); - rSystem.add("system/all/unlike-sign/hY", ";y;counts", kTH1D, {yAxis}); - rSystem.add("system/all/unlike-sign/hPhi", ";#phi;counts", kTH1D, {phiAxis}); - rSystem.add("system/all/unlike-sign/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); - rSystem.add("system/all/unlike-sign/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + rSystem.add("system/all/unlike-sign/hM", ";#it{m} (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + 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};counts", kTH1D, {phiAxis}); + rSystem.add("system/all/unlike-sign/hPhiRandom", ";#Delta#it{#phi}_{random};counts", kTH1D, {deltaPhiAxis}); + rSystem.add("system/all/unlike-sign/hPhiCharge", ";#Delta#it{#phi}_{charge};counts", kTH1D, {deltaPhiAxis}); + rSystem.add("system/all/unlike-sign/hPhiRandomVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi}_{random};counts", kTH2D, {mAxis, deltaPhiAxis}); + rSystem.add("system/all/unlike-sign/hPhiChargeVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi}_{charge};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/"); @@ -247,33 +275,40 @@ struct UpcRhoAnalysis { // MC // collisions - rMC.add("MC/collisions/hPosXY", ";x (cm);y (cm);counts", kTH2D, {{2000, -0.1, 0.1}, {2000, -0.1, 0.1}}); - rMC.add("MC/collisions/hPosZ", ";z (cm);counts", kTH1D, {{400, -20.0, 20.0}}); + 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}}); - rMC.add("MC/collisions/hNumOfCollisionRecos", ";number of collision reconstructions;counts", kTH1D, {{11, -0.5, 10.5}}); + rMC.add("MC/collisions/hNumOfCollisionRecos", ";number of collision reconstructions;counts", kTH1D, {{6, -0.5, 5.5}}); + rMC.add("MC/collisions/hRunNumberVsNumOfCollisionRecos", ";number of collision reconstructions;run number;counts", kTH2D, {{6, -0.5, 5.5}, runNumberAxis}); // tracks rMC.add("MC/tracks/all/hPdgCode", ";pdg code;counts", kTH1D, {{2001, -1000.5, 1000.5}}); rMC.add("MC/tracks/all/hProducedByGenerator", ";produced by generator;counts", kTH1D, {{2, -0.5, 1.5}}); rMC.add("MC/tracks/all/hIsPhysicalPrimary", ";is physical primary;counts", kTH1D, {{2, -0.5, 1.5}}); - rMC.add("MC/tracks/all/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); - rMC.add("MC/tracks/all/hEta", ";#eta;counts", kTH1D, {etaAxis}); - rMC.add("MC/tracks/all/hPhi", ";#phi;counts", kTH1D, {phiAxis}); - rMC.add("MC/tracks/hPt", ";p_{T}(#pi_{leading}) (GeV/#it{c});p_{T}(#pi_{subleading}) (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); - rMC.add("MC/tracks/hEta", ";#eta(#pi_{leading});#eta(#pi_{subleading});counts", kTH2D, {etaAxis, etaAxis}); - rMC.add("MC/tracks/hPhi", ";#phi(#pi_{leading});#phi(#pi_{subleading});counts", kTH2D, {phiAxis, phiAxis}); + rMC.add("MC/tracks/all/hPt", ";#it{p}_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); + rMC.add("MC/tracks/all/hEta", ";#it{#eta};counts", kTH1D, {etaAxis}); + rMC.add("MC/tracks/all/hPhi", ";#it{#phi};counts", kTH1D, {phiAxis}); + rMC.add("MC/tracks/hPt", ";#it{p}_{T leading} (GeV/#it{c});#it{p}_{T subleading} (GeV/#it{c});counts", kTH2D, {ptAxis, ptAxis}); + rMC.add("MC/tracks/hEta", ";#it{#eta}_{leading};#it{#eta}_{subleading};counts", kTH2D, {etaAxis, etaAxis}); + rMC.add("MC/tracks/hPhi", ";#it{#phi}_{leading};#it{#phi}_{subleading};counts", kTH2D, {phiAxis, phiAxis}); // system - rMC.add("MC/system/hM", ";m (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); - rMC.add("MC/system/hPt", ";p_{T} (GeV/#it{c});counts", kTH1D, {ptAxis}); - rMC.add("MC/system/hPt2", ";p_{T}^{2} (GeV^{2}/#it{c}^{2});counts", kTH1D, {pt2Axis}); - rMC.add("MC/system/hPtVsM", ";m (GeV/#it{c}^{2});p_{T} (GeV/#it{c});counts", kTH2D, {mAxis, ptAxis}); - rMC.add("MC/system/hY", ";y;counts", kTH1D, {yAxis}); - rMC.add("MC/system/hPhi", ";#phi;counts", kTH1D, {phiAxis}); - rMC.add("MC/system/hPhiRandom", ";#phi;counts", kTH1D, {phiAsymmAxis}); - rMC.add("MC/system/hPhiCharge", ";#phi;counts", kTH1D, {phiAsymmAxis}); + rMC.add("MC/system/hM", ";#it{m} (GeV/#it{c}^{2});counts", kTH1D, {mAxis}); + 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/hY", ";#it{y};counts", kTH1D, {yAxis}); + rMC.add("MC/system/hPhi", ";#it{#phi};counts", kTH1D, {phiAxis}); + rMC.add("MC/system/hPhiRandom", ";#Delta#it{#phi}_{random};counts", kTH1D, {deltaPhiAxis}); + rMC.add("MC/system/hPhiCharge", ";#Delta#it{#phi}_{charge};counts", kTH1D, {deltaPhiAxis}); + rMC.add("MC/system/hPhiRandomVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi};counts", kTH2D, {mAxis, deltaPhiAxis}); + rMC.add("MC/system/hPhiChargeVsM", ";#it{m} (GeV/#it{c}^{2});#Delta#it{#phi};counts", kTH2D, {mAxis, deltaPhiAxis}); rMC.addClone("MC/system/", "MC/system/selected/"); } - static constexpr std::string_view AppliedSelections[2] = {"all/", "selected/"}; + std::unordered_set goldenRuns = {544491, 544474, 544123, 544098, 544121, 544389, 544032, 544454, 544122, + 544510, 544476, 544091, 544095, 544490, 544124, 544508, 544391, 544013, + 544390, 544184, 544451, 544116, 544185, 544492, 544475, 544392, 544477, 544028}; + + static constexpr std::string_view AppliedSelections[3] = {"all/", "trackSelections/", "systemSelections/"}; static constexpr std::string_view ChargeLabel[3] = {"unlike-sign/", "like-sign/positive/", "like-sign/negative/"}; static constexpr std::string_view NeutronClass[5] = {"no-selection/", "0n0n/", "Xn0n/", "0nXn/", "XnXn/"}; @@ -313,7 +348,7 @@ struct UpcRhoAnalysis { rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNCls"), (track.tpcNClsFindable() - track.tpcNClsFindableMinusFound())); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNClsCrossedRows"), track.tpcNClsCrossedRows()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcNClsCrossedRowsOverNClsFindable"), (static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable()))); - rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcSignalVsP"), momentum(track.px(), track.py(), track.pz()), track.tpcSignal()); + rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcSignalVsP"), std::abs(momentum(track.px(), track.py(), track.pz())), track.tpcSignal()); rQC.fill(HIST("QC/tracks/") + HIST(AppliedSelections[cuts]) + HIST("hTpcSignalVsPt"), track.pt(), track.tpcSignal()); } @@ -337,82 +372,147 @@ struct UpcRhoAnalysis { 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); rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPhiCharge"), phiCharge); + rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPhiRandomVsM"), mass, phiRandom); + rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(ChargeLabel[charge]) + HIST("hPhiChargeVsM"), mass, phiCharge); } else { - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hM"), mass); - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt"), pt); - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPt2"), pt * pt); - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPtVsM"), mass, pt); - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hY"), rapidity); - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhi"), phi); - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhiRandom"), phiRandom); - rSystem.fill(HIST("system/") + HIST(AppliedSelections[cuts]) + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhiCharge"), phiCharge); + rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hM"), mass); + 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("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); + rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhiCharge"), phiCharge); + rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhiRandomVsM"), mass, phiRandom); + rSystem.fill(HIST("system/") + HIST("selected/") + HIST(NeutronClass[neutronClass]) + HIST(ChargeLabel[charge]) + HIST("hPhiChargeVsM"), mass, phiCharge); + } + } + + bool cutItsLayers(uint8_t itsClusterMap) const + { + 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; + for (const auto& itsRequirement : requiredITSHits) { + auto hits = std::count_if(itsRequirement.second.begin(), itsRequirement.second.end(), [&](auto&& requiredLayer) { return itsClusterMap & (kBit << requiredLayer); }); + + if ((itsRequirement.first == -1) && (hits > 0)) { + return false; // no hits were required in specified layers + } else if (hits < itsRequirement.first) { + return false; // not enough hits found in specified layers + } + } + return true; + } + + template + bool isGoodRctFlag(const C& collision) + { + switch (cutRctFlag) { + case 1: + return sgSelector.isCBTOk(collision); + case 2: + return sgSelector.isCBTZdcOk(collision); + case 3: + return sgSelector.isCBTHadronOk(collision); + case 4: + return sgSelector.isCBTHadronZdcOk(collision); + default: + return true; } } template bool collisionPassesCuts(const C& collision) // collision cuts { + if (!collision.vtxITSTPC() || !collision.sbp() || !collision.itsROFb() || !collision.tfb()) // not applied automatically in 2023 Pb-Pb pass5 + return false; + if (std::abs(collision.posZ()) > collisionsPosZMaxCut) return false; - if (collision.numContrib() > collisionsNumContribsMaxCut) + if (cutNumContribs && (collision.numContrib() > collisionsNumContribsMaxCut)) return false; + + if (useRctFlag && !isGoodRctFlag(collision)) // check RCT flags + return false; + if (useRecoFlag && (collision.flags() != cutRecoFlag)) // check reconstruction mode + return false; + return true; } - template - bool trackPassesCuts(const T& track) // track cuts (PID done separately) + template + bool trackPassesCuts(const T& track, const C& collision) // track cuts (PID done separately) { if (!track.isPVContributor()) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 1); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 1, collision.runNumber()); if (!track.hasITS()) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 2); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 2, collision.runNumber()); if (track.itsNCls() < tracksMinItsNClsCut) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 3); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 3, collision.runNumber()); - if (track.itsChi2NCl() > tracksMaxItsChi2NClCut) + if (!cutItsLayers(track.itsClusterMap())) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 4); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 4, collision.runNumber()); - if (!track.hasTPC()) + if (track.itsChi2NCl() > tracksMaxItsChi2NClCut) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 5); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 5, collision.runNumber()); - if ((track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()) < tracksMinTpcNClsCut) + if (!track.hasTPC()) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 6); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 6, collision.runNumber()); - if (track.tpcChi2NCl() > tracksMaxTpcChi2NClCut || track.tpcChi2NCl() < tracksMinTpcChi2NClCut) + if ((track.tpcNClsFindable() - track.tpcNClsFindableMinusFound()) < tracksMinTpcNClsCut) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 7); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 7, collision.runNumber()); - if (track.tpcNClsCrossedRows() < tracksMinTpcNClsCrossedRowsCut) + if (track.tpcChi2NCl() > tracksMaxTpcChi2NClCut || track.tpcChi2NCl() < tracksMinTpcChi2NClCut) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 8); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 8, collision.runNumber()); - if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < tracksMinTpcNClsCrossedOverFindableCut) + if (track.tpcNClsCrossedRows() < tracksMinTpcNClsCrossedRowsCut) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 9); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 9, collision.runNumber()); - if (requireTof && !track.hasTOF()) + if ((static_cast(track.tpcNClsCrossedRows()) / static_cast(track.tpcNClsFindable())) < tracksMinTpcNClsCrossedOverFindableCut) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 10); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 10, collision.runNumber()); - if (track.pt() < tracksMinPtCut) + if (requireTof && !track.hasTOF()) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 11); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 11, collision.runNumber()); - if (std::abs(track.dcaZ()) > tracksDcaMaxCut || std::abs(track.dcaXY()) > (0.0105 + 0.0350 / std::pow(track.pt(), 1.01))) + if (track.pt() < tracksMinPtCut) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 12); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 12, collision.runNumber()); - if (std::abs(eta(track.px(), track.py(), track.pz())) > pcEtaCut) + if (std::abs(track.dcaZ()) > tracksDcaMaxCut || std::abs(track.dcaXY()) > (0.0105 + 0.0350 / std::pow(track.pt(), 1.01))) return false; rQC.fill(HIST("QC/tracks/hSelectionCounter"), 13); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 13, collision.runNumber()); + + if (std::abs(eta(track.px(), track.py(), track.pz())) > pcEtaCut) + return false; + rQC.fill(HIST("QC/tracks/hSelectionCounter"), 14); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 14, collision.runNumber()); // if all selections passed return true; } @@ -426,24 +526,6 @@ struct UpcRhoAnalysis { return radius < std::pow(tracksTpcNSigmaPiCut, 2); } - template - bool tracksPassElPID(const T& cutTracks) // n-dimensional electron PID cut - { - float radius = 0.0; - for (const auto& track : cutTracks) - radius += std::pow(track.tpcNSigmaEl(), 2); - return radius < std::pow(tracksTpcNSigmaElCut, 2); - } - - template - bool tracksPassKaPID(const T& cutTracks) // n-dimensional kaon PID cut - { - float radius = 0.0; - for (const auto& track : cutTracks) - radius += std::pow(track.tpcNSigmaKa(), 2); - return radius < std::pow(tracksTpcNSigmaKaCut, 2); - } - template int tracksTotalCharge(const T& cutTracks) // total charge of selected tracks { @@ -462,7 +544,7 @@ struct UpcRhoAnalysis { return charge; } - bool systemPassesCuts(const TLorentzVector& system) // system cuts + bool systemPassesCuts(const ROOT::Math::PxPyPzMVector& system) // system cuts { if (system.M() < systemMassMinCut || system.M() > systemMassMaxCut) return false; @@ -473,100 +555,132 @@ struct UpcRhoAnalysis { return true; } - TLorentzVector reconstructSystem(const std::vector& cutTracksLVs) // reconstruct system from 4-vectors + ROOT::Math::PxPyPzMVector reconstructSystem(const std::vector& cutTracksLVs) // reconstruct system from 4-vectors { - TLorentzVector system; + ROOT::Math::PxPyPzMVector system; for (const auto& trackLV : cutTracksLVs) system += trackLV; return system; } - float getPhiRandom(const std::vector& cutTracksLVs) // decay phi anisotropy - { // two possible definitions of phi: randomize the tracks + double deltaPhi(const ROOT::Math::PxPyPzMVector& p1, const ROOT::Math::PxPyPzMVector& p2) + { + double dPhi = p1.Phi() - p2.Phi(); + dPhi = std::fmod(dPhi + o2::constants::math::PI, o2::constants::math::TwoPI) - o2::constants::math::PI; // normalize to (-pi, pi) + return dPhi; + } + + float getPhiRandom(const std::vector& cutTracksLVs) // decay phi anisotropy + { // two possible definitions of phi: randomize the tracks int indices[2] = {0, 1}; - unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // get time-based seed + unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); // get time-based seed std::shuffle(std::begin(indices), std::end(indices), std::default_random_engine(seed)); // shuffle indices // calculate phi - TLorentzVector pOne = cutTracksLVs[indices[0]]; - TLorentzVector pTwo = cutTracksLVs[indices[1]]; - TLorentzVector pPlus = pOne + pTwo; - TLorentzVector pMinus = pOne - pTwo; - return pPlus.DeltaPhi(pMinus); + ROOT::Math::PxPyPzMVector pOne = cutTracksLVs[indices[0]]; + ROOT::Math::PxPyPzMVector pTwo = cutTracksLVs[indices[1]]; + ROOT::Math::PxPyPzMVector pPlus = pOne + pTwo; + ROOT::Math::PxPyPzMVector pMinus = pOne - pTwo; + return deltaPhi(pPlus, pMinus); } template - float getPhiCharge(const T& cutTracks, const std::vector& cutTracksLVs) + float getPhiCharge(const T& cutTracks, const std::vector& cutTracksLVs) { // two possible definitions of phi: charge-based assignment - TLorentzVector pOne, pTwo; + ROOT::Math::PxPyPzMVector pOne, pTwo; pOne = (cutTracks[0].sign() > 0) ? cutTracksLVs[0] : cutTracksLVs[1]; pTwo = (cutTracks[0].sign() > 0) ? cutTracksLVs[1] : cutTracksLVs[0]; - TLorentzVector pPlus = pOne + pTwo; - TLorentzVector pMinus = pOne - pTwo; - return pPlus.DeltaPhi(pMinus); + ROOT::Math::PxPyPzMVector pPlus = pOne + pTwo; + ROOT::Math::PxPyPzMVector pMinus = pOne - pTwo; + return deltaPhi(pPlus, pMinus); } template - float getPhiChargeMC(const T& cutTracks, const std::vector& cutTracksLVs) + float getPhiChargeMC(const T& cutTracks, const std::vector& cutTracksLVs) { // the same as for data but using pdg code instead of charge - TLorentzVector pOne, pTwo; + ROOT::Math::PxPyPzMVector pOne, pTwo; pOne = (cutTracks[0].pdgCode() > 0) ? cutTracksLVs[0] : cutTracksLVs[1]; pTwo = (cutTracks[0].pdgCode() > 0) ? cutTracksLVs[1] : cutTracksLVs[0]; - TLorentzVector pPlus = pOne + pTwo; - TLorentzVector pMinus = pOne - pTwo; - return pPlus.DeltaPhi(pMinus); + ROOT::Math::PxPyPzMVector pPlus = pOne + pTwo; + ROOT::Math::PxPyPzMVector pMinus = pOne - pTwo; + return deltaPhi(pPlus, pMinus); } template void processReco(C const& collision, T const& tracks) { + // check if the collision run number is contained within the goldenRuns set + if (onlyGoldenRuns && !goldenRuns.contains(collision.runNumber())) + return; + fillCollisionQcHistos<0>(collision); // fill QC histograms before cuts if (!collisionPassesCuts(collision)) return; - bool xnxn = false, onon = false, xnon = false, onxn = false; // note: On == 0n... - if (collision.energyCommonZNA() < znCommonEnergyCut && collision.energyCommonZNC() < znCommonEnergyCut) + int neutronClass = -1; + bool xnxn = false, onon = false, xnon = false, onxn = false; + float energyCommonZNA = collision.energyCommonZNA(), energyCommonZNC = collision.energyCommonZNC(); + float timeZNA = collision.timeZNA(), timeZNC = collision.timeZNC(); + if (std::isinf(energyCommonZNA)) + energyCommonZNA = -999; + if (std::isinf(energyCommonZNC)) + energyCommonZNC = -999; + if (std::isinf(timeZNA)) + timeZNA = -999; + if (std::isinf(timeZNC)) + timeZNC = -999; + + if (energyCommonZNA <= znCommonEnergyCut && energyCommonZNC <= znCommonEnergyCut) { onon = true; - if (collision.energyCommonZNA() > znCommonEnergyCut && std::abs(collision.timeZNA()) < znTimeCut && collision.energyCommonZNC() < znCommonEnergyCut) + neutronClass = 0; + } + if (energyCommonZNA > znCommonEnergyCut && std::abs(timeZNA) <= znTimeCut && energyCommonZNC <= znCommonEnergyCut) { xnon = true; - if (collision.energyCommonZNA() < znCommonEnergyCut && collision.energyCommonZNC() > znCommonEnergyCut && std::abs(collision.timeZNC()) < znTimeCut) + neutronClass = 1; + } + if (energyCommonZNA <= znCommonEnergyCut && energyCommonZNC > znCommonEnergyCut && std::abs(timeZNC) <= znTimeCut) { onxn = true; - if (collision.energyCommonZNA() > znCommonEnergyCut && std::abs(collision.timeZNA()) < znTimeCut && - collision.energyCommonZNC() > znCommonEnergyCut && std::abs(collision.timeZNC()) < znTimeCut) + neutronClass = 2; + } + if (energyCommonZNA > znCommonEnergyCut && std::abs(timeZNA) <= znTimeCut && + energyCommonZNC > znCommonEnergyCut && std::abs(timeZNC) <= znTimeCut) { xnxn = true; + neutronClass = 3; + } std::vector cutTracks; // store selected tracks for (const auto& track : tracks) { rQC.fill(HIST("QC/tracks/hSelectionCounter"), 0); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 0, collision.runNumber()); fillTrackQcHistos<0>(track); // fill QC histograms before cuts - if (!trackPassesCuts(track)) // apply track cuts + if (!trackPassesCuts(track, collision)) // apply track cuts continue; - - fillTrackQcHistos<1>(track); // fill QC histograms after cuts cutTracks.push_back(track); } - rQC.fill(HIST("QC/tracks/selected/hRemainingTracks"), cutTracks.size()); + rQC.fill(HIST("QC/tracks/trackSelections/hRemainingTracks"), cutTracks.size()); - if (cutTracks.size() != 2) // further consider only two pion systems + if (static_cast(cutTracks.size()) != numPions) // further consider only two pion systems return; - for (int i = 0; i < static_cast(cutTracks.size()); i++) - rQC.fill(HIST("QC/tracks/hSelectionCounter"), 14); - rQC.fill(HIST("QC/tracks/selected/hTpcNSigmaPi2D"), cutTracks[0].tpcNSigmaPi(), cutTracks[1].tpcNSigmaPi()); - rQC.fill(HIST("QC/tracks/selected/hTpcNSigmaEl2D"), cutTracks[0].tpcNSigmaEl(), cutTracks[1].tpcNSigmaEl()); - rQC.fill(HIST("QC/tracks/selected/hTpcNSigmaKa2D"), cutTracks[0].tpcNSigmaKa(), cutTracks[1].tpcNSigmaKa()); + for (int i = 0; i < numPions; i++) { + rQC.fill(HIST("QC/tracks/hSelectionCounter"), 15); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 15, collision.runNumber()); + } + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaPi2D"), cutTracks[0].tpcNSigmaPi(), cutTracks[1].tpcNSigmaPi()); + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaEl2D"), cutTracks[0].tpcNSigmaEl(), cutTracks[1].tpcNSigmaEl()); + rQC.fill(HIST("QC/tracks/trackSelections/hTpcNSigmaKa2D"), cutTracks[0].tpcNSigmaKa(), cutTracks[1].tpcNSigmaKa()); // create a vector of 4-vectors for selected tracks - std::vector cutTracksLVs; - for (const auto& track : cutTracks) { - TLorentzVector trackLV; - trackLV.SetXYZM(track.px(), track.py(), track.pz(), o2::constants::physics::MassPionCharged); // apriori assume pion mass - cutTracksLVs.push_back(trackLV); + std::vector cutTracksLVs; + for (const auto& cutTrack : cutTracks) { + cutTracksLVs.push_back(ROOT::Math::PxPyPzMVector(cutTrack.px(), cutTrack.py(), cutTrack.pz(), o2::constants::physics::MassPionCharged)); // apriori assume pion mass } // differentiate leading- and subleading-momentum tracks auto leadingMomentumTrack = momentum(cutTracks[0].px(), cutTracks[0].py(), cutTracks[0].pz()) > momentum(cutTracks[1].px(), cutTracks[1].py(), cutTracks[1].pz()) ? cutTracks[0] : cutTracks[1]; auto subleadingMomentumTrack = (leadingMomentumTrack == cutTracks[0]) ? cutTracks[1] : cutTracks[0]; - rQC.fill(HIST("QC/tracks/hTofHitCheck"), leadingMomentumTrack.hasTOF(), subleadingMomentumTrack.hasTOF()); + + auto positiveTrack = cutTracks[0].sign() > 0 ? cutTracks[0] : cutTracks[1]; + auto negativeTrack = cutTracks[0].sign() > 0 ? cutTracks[1] : cutTracks[0]; float leadingPt = leadingMomentumTrack.pt(); float subleadingPt = subleadingMomentumTrack.pt(); @@ -579,26 +693,34 @@ struct UpcRhoAnalysis { // fill recoTree int localBc = collision.globalBC() % o2::constants::lhc::LHCMaxBunches; - int trackSigns[2] = {leadingMomentumTrack.sign(), subleadingMomentumTrack.sign()}; - float trackPts[2] = {leadingPt, subleadingPt}; - float trackEtas[2] = {leadingEta, subleadingEta}; - float trackPhis[2] = {leadingPhi, subleadingPhi}; - float trackPiPIDs[2] = {leadingMomentumTrack.tpcNSigmaPi(), subleadingMomentumTrack.tpcNSigmaPi()}; - float trackElPIDs[2] = {leadingMomentumTrack.tpcNSigmaEl(), subleadingMomentumTrack.tpcNSigmaEl()}; - float trackKaPIDs[2] = {leadingMomentumTrack.tpcNSigmaKa(), subleadingMomentumTrack.tpcNSigmaKa()}; - float trackDcaXYs[2] = {leadingMomentumTrack.dcaXY(), subleadingMomentumTrack.dcaXY()}; - float trackDcaZs[2] = {leadingMomentumTrack.dcaZ(), subleadingMomentumTrack.dcaZ()}; - float trackTpcSignals[2] = {leadingMomentumTrack.tpcSignal(), subleadingMomentumTrack.tpcSignal()}; - if ((savePions && tracksPassPiPID(cutTracks)) || (saveElectrons && tracksPassElPID(cutTracks)) || (saveKaons && tracksPassKaPID(cutTracks))) - recoTree(collision.runNumber(), localBc, collision.numContrib(), collision.posX(), collision.posY(), collision.posZ(), - collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.totalFV0AmplitudeA(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), - collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), collision.timeFDDA(), collision.timeFDDC(), - collision.energyCommonZNA(), collision.energyCommonZNC(), collision.timeZNA(), collision.timeZNC(), - phiRandom, phiCharge, trackSigns, trackPts, trackEtas, trackPhis, trackPiPIDs, trackElPIDs, trackKaPIDs, trackDcaXYs, trackDcaZs, trackTpcSignals); + int trackSigns[2] = {positiveTrack.sign(), negativeTrack.sign()}; + float trackPts[2] = {positiveTrack.pt(), negativeTrack.pt()}; + float trackEtas[2] = {eta(positiveTrack.px(), positiveTrack.py(), positiveTrack.pz()), eta(negativeTrack.px(), negativeTrack.py(), negativeTrack.pz())}; + float trackPhis[2] = {phi(positiveTrack.px(), positiveTrack.py()), phi(negativeTrack.px(), negativeTrack.py())}; + float trackPiPIDs[2] = {positiveTrack.tpcNSigmaPi(), negativeTrack.tpcNSigmaPi()}; + float trackElPIDs[2] = {positiveTrack.tpcNSigmaEl(), negativeTrack.tpcNSigmaEl()}; + float trackKaPIDs[2] = {positiveTrack.tpcNSigmaKa(), negativeTrack.tpcNSigmaKa()}; + float trackDcaXYs[2] = {positiveTrack.dcaXY(), negativeTrack.dcaXY()}; + float trackDcaZs[2] = {positiveTrack.dcaZ(), negativeTrack.dcaZ()}; + float trackTpcSignals[2] = {positiveTrack.tpcSignal(), negativeTrack.tpcSignal()}; + recoTree(collision.flags(), collision.runNumber(), localBc, collision.numContrib(), collision.posX(), collision.posY(), collision.posZ(), + 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, + phiRandom, phiCharge, trackSigns, trackPts, trackEtas, trackPhis, trackPiPIDs, trackElPIDs, trackKaPIDs, trackDcaXYs, trackDcaZs, trackTpcSignals); if (!tracksPassPiPID(cutTracks)) // apply PID cut return; - TLorentzVector system = reconstructSystem(cutTracksLVs); + + for (const auto& cutTrack : cutTracks) { + rQC.fill(HIST("QC/tracks/hSelectionCounter"), 16); + rQC.fill(HIST("QC/tracks/hSelectionCounterPerRun"), 16, collision.runNumber()); + fillTrackQcHistos<1>(cutTrack); // fill QC histograms after cuts + } + rQC.fill(HIST("QC/tracks/hTofHitCheck"), leadingMomentumTrack.hasTOF(), subleadingMomentumTrack.hasTOF()); + fillCollisionQcHistos<1>(collision); // fill QC histograms after track selections + + ROOT::Math::PxPyPzMVector system = reconstructSystem(cutTracksLVs); int totalCharge = tracksTotalCharge(cutTracks); float mass = system.M(); float pT = system.Pt(); @@ -608,17 +730,17 @@ struct UpcRhoAnalysis { // fill raw histograms according to total charge switch (totalCharge) { case 0: - fillTrack2dHistos<0, 0>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); + fillTrack2dHistos<1, 0>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); fillSystemHistos<0, 0, 0>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); break; case 2: - fillTrack2dHistos<0, 1>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); + fillTrack2dHistos<1, 1>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); fillSystemHistos<0, 0, 1>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); break; case -2: - fillTrack2dHistos<0, 2>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); + fillTrack2dHistos<1, 2>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); fillSystemHistos<0, 0, 2>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); break; @@ -629,12 +751,14 @@ struct UpcRhoAnalysis { // apply cuts to system if (!systemPassesCuts(system)) return; - fillCollisionQcHistos<1>(collision); // fill QC histograms for collisions with selected system // fill histograms for system passing cuts switch (totalCharge) { case 0: - fillTrack2dHistos<1, 0>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); + fillCollisionQcHistos<2>(collision); + for (const auto& cutTrack : cutTracks) + fillTrackQcHistos<2>(cutTrack); + fillTrack2dHistos<2, 0>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); fillSystemHistos<1, 0, 0>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); if (onon) fillSystemHistos<1, 1, 0>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); @@ -647,7 +771,7 @@ struct UpcRhoAnalysis { break; case 2: - fillTrack2dHistos<1, 1>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); + fillTrack2dHistos<2, 1>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); fillSystemHistos<1, 0, 1>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); if (onon) fillSystemHistos<1, 1, 1>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); @@ -660,7 +784,7 @@ struct UpcRhoAnalysis { break; case -2: - fillTrack2dHistos<1, 2>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); + fillTrack2dHistos<2, 2>(leadingPt, subleadingPt, leadingEta, subleadingEta, leadingPhi, subleadingPhi); fillSystemHistos<1, 0, 2>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); if (onon) fillSystemHistos<1, 1, 2>(mass, pT, rapidity, systemPhi, phiRandom, phiCharge); @@ -684,7 +808,7 @@ struct UpcRhoAnalysis { rMC.fill(HIST("MC/collisions/hPosZ"), mcCollision.posZ()); std::vector cutMcParticles; - std::vector mcParticlesLVs; + std::vector mcParticlesLVs; for (auto const& mcParticle : mcParticles) { rMC.fill(HIST("MC/tracks/all/hPdgCode"), mcParticle.pdgCode()); @@ -693,23 +817,23 @@ struct UpcRhoAnalysis { rMC.fill(HIST("MC/tracks/all/hPt"), pt(mcParticle.px(), mcParticle.py())); rMC.fill(HIST("MC/tracks/all/hEta"), eta(mcParticle.px(), mcParticle.py(), mcParticle.pz())); rMC.fill(HIST("MC/tracks/all/hPhi"), phi(mcParticle.px(), mcParticle.py())); - if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.pdgCode()) != 211) + if (!mcParticle.isPhysicalPrimary() || std::abs(mcParticle.pdgCode()) != kPiPlus) continue; cutMcParticles.push_back(mcParticle); - TLorentzVector pionLV; + ROOT::Math::PxPyPzMVector pionLV; pionLV.SetPxPyPzE(mcParticle.px(), mcParticle.py(), mcParticle.pz(), mcParticle.e()); mcParticlesLVs.push_back(pionLV); } rMC.fill(HIST("MC/collisions/hNPions"), cutMcParticles.size()); - if (cutMcParticles.size() != 2) + if (static_cast(cutMcParticles.size()) != numPions) return; if (mcParticlesLVs.size() != cutMcParticles.size()) return; if (tracksTotalChargeMC(cutMcParticles) != 0) // shouldn't happen in theory return; - TLorentzVector system = reconstructSystem(mcParticlesLVs); + ROOT::Math::PxPyPzMVector system = reconstructSystem(mcParticlesLVs); float mass = system.M(); float pT = system.Pt(); float rapidity = system.Rapidity(); @@ -731,6 +855,8 @@ struct UpcRhoAnalysis { rMC.fill(HIST("MC/system/hPhi"), systemPhi); rMC.fill(HIST("MC/system/hPhiRandom"), phiRandom); rMC.fill(HIST("MC/system/hPhiCharge"), phiCharge); + rMC.fill(HIST("MC/system/hPhiRandomVsM"), mass, phiRandom); + rMC.fill(HIST("MC/system/hPhiChargeVsM"), mass, phiCharge); if (systemPassesCuts(system)) { rMC.fill(HIST("MC/system/selected/hM"), mass); @@ -741,14 +867,18 @@ struct UpcRhoAnalysis { rMC.fill(HIST("MC/system/selected/hPhi"), systemPhi); rMC.fill(HIST("MC/system/selected/hPhiRandom"), phiRandom); rMC.fill(HIST("MC/system/selected/hPhiCharge"), phiCharge); + rMC.fill(HIST("MC/system/selected/hPhiRandomVsM"), mass, phiRandom); + rMC.fill(HIST("MC/system/selected/hPhiChargeVsM"), mass, phiCharge); } // fill mcTree + auto positivePion = cutMcParticles[0].pdgCode() > 0 ? cutMcParticles[0] : cutMcParticles[1]; + auto negativePion = cutMcParticles[0].pdgCode() > 0 ? cutMcParticles[1] : cutMcParticles[0]; int localBc = mcCollision.globalBC() % o2::constants::lhc::LHCMaxBunches; - int trackSigns[2] = {leadingMomentumPion.pdgCode() / std::abs(leadingMomentumPion.pdgCode()), subleadingMomentumPion.pdgCode() / std::abs(subleadingMomentumPion.pdgCode())}; - float trackPts[2] = {pt(leadingMomentumPion.px(), leadingMomentumPion.py()), pt(subleadingMomentumPion.px(), subleadingMomentumPion.py())}; - float trackEtas[2] = {eta(leadingMomentumPion.px(), leadingMomentumPion.py(), leadingMomentumPion.pz()), eta(subleadingMomentumPion.px(), subleadingMomentumPion.py(), subleadingMomentumPion.pz())}; - float trackPhis[2] = {phi(leadingMomentumPion.px(), leadingMomentumPion.py()), phi(subleadingMomentumPion.px(), subleadingMomentumPion.py())}; + int trackSigns[2] = {positivePion.pdgCode() / std::abs(positivePion.pdgCode()), negativePion.pdgCode() / std::abs(negativePion.pdgCode())}; + float trackPts[2] = {pt(positivePion.px(), positivePion.py()), pt(negativePion.px(), negativePion.py())}; + float trackEtas[2] = {eta(positivePion.px(), positivePion.py(), positivePion.pz()), eta(negativePion.px(), negativePion.py(), negativePion.pz())}; + float trackPhis[2] = {phi(positivePion.px(), positivePion.py()), phi(negativePion.px(), negativePion.py())}; mcTree(localBc, mcCollision.posX(), mcCollision.posY(), mcCollision.posZ(), phiRandom, phiCharge, trackSigns, trackPts, trackEtas, trackPhis); @@ -758,11 +888,14 @@ struct UpcRhoAnalysis { void checkNumberOfCollisionReconstructions(C const& collisions) { rMC.fill(HIST("MC/collisions/hNumOfCollisionRecos"), collisions.size()); + rMC.fill(HIST("MC/collisions/hRunNumberVsNumOfCollisionRecos"), collisions.size(), collisions.begin().runNumber()); } void processSGdata(FullUdSgCollision const& collision, FullUdTracks const& tracks) { - if (collision.gapSide() != 2) + if (cutGapSide && collision.gapSide() != gapSide) + return; + if (useTrueGap && (collision.gapSide() != sgSelector.trueGap(collision, cutTrueGapSideFV0, cutTrueGapSideFT0A, cutTrueGapSideFT0C, cutTrueGapSideZDC))) // check true gap side return; processReco(collision, tracks); } @@ -780,7 +913,7 @@ struct UpcRhoAnalysis { } PROCESS_SWITCH(UpcRhoAnalysis, processMCdata, "analyse MC data", false); - void processCollisionRecoCheck(aod::McCollision const& /* mcCollision */, soa::SmallGroups> const& collisions) + 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 d4048806854..49b6e478674 100644 --- a/PWGUD/Tasks/upcRhoPrimeAnalysis.cxx +++ b/PWGUD/Tasks/upcRhoPrimeAnalysis.cxx @@ -12,26 +12,26 @@ /// \brief Task for analysis of rho' in UPCs using UD tables (from SG producer). /// \author Cesar Ramirez, cesar.ramirez@cern.ch -#include // Para std::string -#include // Para std::vector +#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "PWGUD/DataModel/UDTables.h" + +#include "Common/DataModel/PIDResponse.h" -#include "Framework/AnalysisTask.h" #include "Framework/AnalysisDataModel.h" +#include "Framework/AnalysisTask.h" #include "Framework/runDataProcessing.h" #include "Math/Vector4D.h" // similiar to TLorentzVector (which is now legacy apparently) -#include -#include "Common/DataModel/PIDResponse.h" - -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UPCTauCentralBarrelHelperRL.h" +#include "random" +#include // Para std::string +#include // Para std::vector using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; -using FullUDSgCollision = soa::Join::iterator; +using FullUDSgCollision = soa::Join::iterator; using FullUDTracks = soa::Join; namespace o2::aod @@ -86,6 +86,10 @@ DECLARE_SOA_COLUMN(TimeZNA, timeZNA, float); DECLARE_SOA_COLUMN(TimeZNC, timeZNC, float); DECLARE_SOA_COLUMN(EnergyCommonZNA, energyCommonZNA, float); DECLARE_SOA_COLUMN(EnergyCommonZNC, energyCommonZNC, float); +DECLARE_SOA_COLUMN(IsChargeZero, isChargeZero, bool); + +DECLARE_SOA_COLUMN(OccupancyInTime, occupancyInTime, int); +DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, double); } // namespace fourpi @@ -94,7 +98,7 @@ DECLARE_SOA_TABLE(SYSTEMTREE, "AOD", "SystemTree", fourpi::RunNumber, fourpi::M, fourpi::TotalFDDAmplitudeA, fourpi::TotalFDDAmplitudeC, fourpi::TimeFT0A, fourpi::TimeFT0C, fourpi::TimeFV0A, fourpi::TimeFDDA, fourpi::TimeFDDC, fourpi::NumContrib, fourpi::Sign, fourpi::TrackPt, fourpi::TrackEta, fourpi::TrackPhi, fourpi::TPCNSigmaEl, fourpi::TPCNSigmaPi, fourpi::TPCNSigmaKa, fourpi::TPCNSigmaPr, fourpi::TrackID, fourpi::IsReconstructedWithUPC, - fourpi::TimeZNA, fourpi::TimeZNC, fourpi::EnergyCommonZNA, fourpi::EnergyCommonZNC); + fourpi::TimeZNA, fourpi::TimeZNC, fourpi::EnergyCommonZNA, fourpi::EnergyCommonZNC, fourpi::IsChargeZero, fourpi::OccupancyInTime, fourpi::HadronicRate); } // namespace o2::aod struct upcRhoPrimeAnalysis { @@ -113,8 +117,8 @@ struct upcRhoPrimeAnalysis { Configurable tracksTpcNSigmaPiCut{"tracksTpcNSigmaPiCut", 3.0, "TPC nSigma pion cut"}; Configurable tracksDcaMaxCut{"tracksDcaMaxCut", 1.0, "max DCA cut on tracks"}; - Configurable systemMassMinCut{"systemMassMinCut", 0.5, "min M cut for reco system"}; - Configurable systemMassMaxCut{"systemMassMaxCut", 1.2, "max M cut for reco system"}; + Configurable systemMassMinCut{"systemMassMinCut", 0.8, "min M cut for reco system"}; + Configurable systemMassMaxCut{"systemMassMaxCut", 2.2, "max M cut for reco system"}; Configurable systemPtCut{"systemPtMaxCut", 0.1, "max pT cut for reco system"}; Configurable systemYCut{"systemYCut", 0.9, "rapiditiy cut for reco system"}; @@ -278,14 +282,14 @@ struct upcRhoPrimeAnalysis { double rapidity = system.Rapidity(); double systemPhi = system.Phi() + o2::constants::math::PI; - if (nTracks == 4 && tracksTotalCharge(cutTracks) == 0) { // 4pi system + if (nTracks == 4) { + bool isChargeZero = (tracksTotalCharge(cutTracks) == 0); std::vector vTrackPt, vTrackEta, vTrackPhi; std::vector vSign, vTrackID; std::vector vTpcNSigmaEl, vTpcNSigmaPi, vTpcNSigmaKa, vTpcNSigmaPr; for (size_t i = 0; i < cutTracks.size(); i++) { - double tPt = cutTracks[i].pt(); double tEta = eta(cutTracks[i].px(), cutTracks[i].py(), cutTracks[i].pz()); double tPhi = phi(cutTracks[i].px(), cutTracks[i].py()); @@ -310,16 +314,17 @@ struct upcRhoPrimeAnalysis { isReconstructedWithUPC = false; } - systemTree(collision.runNumber(), mass, pT, rapidity, systemPhi, collision.posX(), collision.posY(), collision.posZ(), totalCharge, - collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.timeFV0A(), collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), - collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), collision.timeFDDA(), collision.timeFDDC(), - collision.numContrib(), vSign, vTrackPt, vTrackEta, vTrackPhi, vTpcNSigmaEl, vTpcNSigmaPi, vTpcNSigmaKa, vTpcNSigmaPr, vTrackID, isReconstructedWithUPC, - collision.timeZNA(), collision.timeZNC(), collision.energyCommonZNA(), collision.energyCommonZNC()); - - // registry.fill(HIST("4pi/hM"), mass); - // registry.fill(HIST("4pi/hPt"), pT); - // registry.fill(HIST("4pi/hEta"), rapiditiy); - // registry.fill(HIST("4pi/hPhi"), system); + systemTree(collision.runNumber(), mass, pT, rapidity, systemPhi, + collision.posX(), collision.posY(), collision.posZ(), totalCharge, + collision.totalFT0AmplitudeA(), collision.totalFT0AmplitudeC(), collision.timeFV0A(), + collision.totalFDDAmplitudeA(), collision.totalFDDAmplitudeC(), + collision.timeFT0A(), collision.timeFT0C(), collision.timeFV0A(), + collision.timeFDDA(), collision.timeFDDC(), collision.numContrib(), + vSign, vTrackPt, vTrackEta, vTrackPhi, + vTpcNSigmaEl, vTpcNSigmaPi, vTpcNSigmaKa, vTpcNSigmaPr, + vTrackID, isReconstructedWithUPC, collision.timeZNA(), collision.timeZNC(), + collision.energyCommonZNA(), collision.energyCommonZNC(), + isChargeZero, collision.occupancyInTime(), collision.hadronicRate()); } // std::cout<<"Hello World"< useNumContribs{"useNumContribs", true, {"Use coll.numContribs as event cut"}}; Configurable cutRecoFlag{"cutRecoFlag", 1, {"0 = std mode, 1 = upc mode"}}; Configurable useRecoFlag{"useRecoFlag", false, {"Use coll.flags as event cut"}}; + Configurable cutRCTflag{"cutRCTflag", 0, {"0 = off, 1 = CBT, 2 = CBT+ZDC, 3 = CBThadron, 4 = CBThadron+ZDC"}}; Configurable cutTrueGapSideFV0{"cutTrueGapSideFV0", -1, "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", 0., "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 cutFITtime{"cutFITtime", 40., "Maximum FIT time allowed. Default is 40ns"}; + Configurable cutEvTFb{"cutEvTFb", true, {"Event selection bit kNoTimeFrameBorder"}}; + Configurable cutEvITSROFb{"cutEvITSROFb", true, {"Event selection bit kNoITSROFrameBorder"}}; + Configurable cutEvSbp{"cutEvSbp", true, {"Event selection bit kNoSameBunchPileup"}}; + Configurable cutEvZvtxFT0vPV{"cutEvZvtxFT0vPV", false, {"Event selection bit kIsGoodZvtxFT0vsPV"}}; + Configurable cutEvVtxITSTPC{"cutEvVtxITSTPC", true, {"Event selection bit kIsVertexITSTPC"}}; Configurable cutEvOccupancy{"cutEvOccupancy", 100000., "Maximum allowed occupancy"}; Configurable cutEvTrs{"cutEvTrs", true, {"Event selection bit kNoCollInTimeRangeStandard"}}; Configurable cutEvTrofs{"cutEvTrofs", true, {"Event selection bit kNoCollInRofStandard"}}; @@ -762,7 +768,7 @@ struct UpcTauRl { return false; // TPC chi2 if (cutGlobalTrack.cutGoodITSTPCmatching) { if (track.itsChi2NCl() < 0.) - return false; // TPC chi2 + return false; // good ITS-TPC matching means ITS ch2 is not negative } // TOF if (track.hasTOF()) { @@ -858,10 +864,47 @@ struct UpcTauRl { return true; } + template + bool isGoodRCTflag(C const& coll) + { + switch (cutSample.cutRCTflag) { + case 1: + return sgSelector.isCBTOk(coll); + case 2: + return sgSelector.isCBTZdcOk(coll); + case 3: + return sgSelector.isCBTHadronOk(coll); + case 4: + return sgSelector.isCBTHadronZdcOk(coll); + default: + return true; + } + } + template bool isGoodROFtime(C const& coll) { + // kNoTimeFrameBorder + if (cutSample.cutEvTFb && !coll.tfb()) + return false; + + // kNoITSROFrameBorder + if (cutSample.cutEvITSROFb && !coll.itsROFb()) + return false; + + // kNoSameBunchPileup + if (cutSample.cutEvSbp && !coll.sbp()) + return false; + + // kIsGoodZvtxFT0vsPV + if (cutSample.cutEvZvtxFT0vPV && !coll.zVtxFT0vPV()) + return false; + + // kIsVertexITSTPC + if (cutSample.cutEvVtxITSTPC && !coll.vtxITSTPC()) + return false; + // Occupancy if (coll.occupancyInTime() > cutSample.cutEvOccupancy) return false; @@ -1012,7 +1055,7 @@ struct UpcTauRl { template bool selectedTauEvent(T const& trkDaug1, T const& trkDaug2) { - TLorentzVector mother, daug[2], motherOfPions, pion[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2]; daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); daug[1].SetPxPyPzE(trkDaug2.px(), trkDaug2.py(), trkDaug2.pz(), energy(pdg->Mass(trackPDG(trkDaug2, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug2.px(), trkDaug2.py(), trkDaug2.pz())); if (cutTauEvent.useThresholdsPID) { @@ -1182,7 +1225,7 @@ struct UpcTauRl { histos.get(HIST("Events/hChannels"))->Fill(CH_EMUPI); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; + ROOT::Math::LorentzVector> mother, daug[2], motherOfPions, pion[2], motherOfMuons, muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1290,7 +1333,7 @@ struct UpcTauRl { const auto& mupionP = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].P() : daug[0].P(); const auto& mupionE = (cutTauEvent.useThresholdsPID ? isElectronCandidate(trkDaug1) : enumMyParticle(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)) == P_ELECTRON) ? daug[1].E() : daug[0].E(); - TLorentzVector motherOfPiKaon, kaon; + ROOT::Math::LorentzVector> motherOfPiKaon, kaon; if (isElectronCandidate(trkDaug1)) { kaon.SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(MassKaonCharged, trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); motherOfPiKaon = kaon + daug[1]; @@ -1604,7 +1647,7 @@ struct UpcTauRl { } // Loop over tracks with selections if (countPVGT == 2 && doTwoTracks) { - TLorentzVector daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(vecPVnoPIDidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1645,7 +1688,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector daug[2], pion[2], muon[2]; + ROOT::Math::LorentzVector> daug[2], pion[2], muon[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -1844,7 +1887,7 @@ struct UpcTauRl { bool isElEl = (cutTauEvent.useThresholdsPID ? countPVGTelectronsAlt == 2 : countPVGTelectrons == 2); bool isElMuPion = (cutTauEvent.useThresholdsPID ? (countPVGTelectronsAlt == 1 && countPVGTmupionsAlt == 1) : ((countPVGTelectrons == 1 && countPVGTmuons == 1) || (countPVGTelectrons == 1 && countPVGTpions == 1))); if (isTwoSelectedTracks && doTwoTracks) { - TLorentzVector daug[2]; + ROOT::Math::LorentzVector> daug[2]; const auto& trkDaug1 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[0] : vecPVidx[0]); const auto& trkDaug2 = reconstructedBarrelTracks.iteratorAt(cutTauEvent.useThresholdsPID ? vecPVnewPIDidx[1] : vecPVidx[1]); daug[0].SetPxPyPzE(trkDaug1.px(), trkDaug1.py(), trkDaug1.pz(), energy(pdg->Mass(trackPDG(trkDaug1, cutPID.cutSiTPC, cutPID.cutSiTOF, cutPID.usePIDwTOF, cutPID.useScutTOFinTPC)), trkDaug1.px(), trkDaug1.py(), trkDaug1.pz())); @@ -2255,6 +2298,9 @@ struct UpcTauRl { fillRejectionReasonDG(reconstructedCollision); outputGlobalRejectionHistogram(); + if (!isGoodRCTflag(reconstructedCollision)) + return; + if (!isGoodROFtime(reconstructedCollision)) return; @@ -2288,6 +2334,9 @@ struct UpcTauRl { fillRejectionReasonSG(reconstructedCollision); outputGlobalRejectionHistogram(); + if (!isGoodRCTflag(reconstructedCollision)) + return; + int gapSide = reconstructedCollision.gapSide(); int trueGapSide = sgSelector.trueGap(reconstructedCollision, cutSample.cutTrueGapSideFV0, cutSample.cutTrueGapSideFT0A, cutSample.cutTrueGapSideFT0C, cutSample.cutTrueGapSideZDC); diff --git a/PWGUD/Tasks/upcTauTau13topo.cxx b/PWGUD/Tasks/upcTauTau13topo.cxx index 0d18b316b8b..b3ff71675cc 100644 --- a/PWGUD/Tasks/upcTauTau13topo.cxx +++ b/PWGUD/Tasks/upcTauTau13topo.cxx @@ -17,24 +17,25 @@ // copts="--configuration json://tautauConfig.json -b" // o2-analysis-ud-tautau13topo $copts > output.log -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" #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 "TLorentzVector.h" +#include "Math/Vector4D.h" // #include "Common/DataModel/EventSelection.h" // #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "PWGUD/DataModel/UDTables.h" -#include "PWGUD/Core/UDHelpers.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/PIDResponse.h" // #include #include "TPDGCode.h" @@ -52,7 +53,8 @@ namespace tau_tree DECLARE_SOA_COLUMN(RunNumber, runNumber, int32_t); DECLARE_SOA_COLUMN(Bc, bc, int); DECLARE_SOA_COLUMN(TotalTracks, totalTracks, int); -DECLARE_SOA_COLUMN(NumContrib, numContrib, int); +DECLARE_SOA_COLUMN(NumContrib, numContrib, int8_t); +DECLARE_SOA_COLUMN(RctOk, rctOk, int); // DECLARE_SOA_COLUMN(GlobalNonPVtracks, globalNonPVtracks, int); // DECLARE_SOA_COLUMN(PosX, posX, float); // DECLARE_SOA_COLUMN(PosY, posY, float); @@ -63,14 +65,14 @@ DECLARE_SOA_COLUMN(HadronicRate, hadronicRate, double); DECLARE_SOA_COLUMN(Trs, trs, bool); DECLARE_SOA_COLUMN(Trofs, trofs, bool); DECLARE_SOA_COLUMN(Hmpr, hmpr, bool); -// DECLARE_SOA_COLUMN(Tfb, tfb, int); -// DECLARE_SOA_COLUMN(ItsRofb, itsRofb, int); -// DECLARE_SOA_COLUMN(Sbp, sbp, int); -// DECLARE_SOA_COLUMN(ZvtxFT0vsPv, zvtxFT0vsPv, int); -// DECLARE_SOA_COLUMN(VtxITSTPC, vtxITSTPC, int); +DECLARE_SOA_COLUMN(Tfb, tfb, bool); +DECLARE_SOA_COLUMN(ItsRofb, itsRofb, bool); +DECLARE_SOA_COLUMN(Sbp, sbp, bool); +DECLARE_SOA_COLUMN(ZvtxFT0vsPv, zvtxFT0vsPv, bool); +DECLARE_SOA_COLUMN(VtxITSTPC, vtxITSTPC, bool); DECLARE_SOA_COLUMN(ZdcAenergy, zdcAenergy, float); DECLARE_SOA_COLUMN(ZdcCenergy, zdcCenergy, float); -DECLARE_SOA_COLUMN(Qtot, qtot, int16_t); +DECLARE_SOA_COLUMN(Qtot, qtot, int8_t); // FIT info DECLARE_SOA_COLUMN(TotalFT0AmplitudeA, totalFT0AmplitudeA, float); DECLARE_SOA_COLUMN(TotalFT0AmplitudeC, totalFT0AmplitudeC, float); @@ -83,9 +85,14 @@ DECLARE_SOA_COLUMN(TrkPx, trkPx, float[4]); DECLARE_SOA_COLUMN(TrkPy, trkPy, float[4]); DECLARE_SOA_COLUMN(TrkPz, trkPz, float[4]); // DECLARE_SOA_COLUMN(TrkSign, trkSign, int[4]); -// DECLARE_SOA_COLUMN(TrkDCAxy, trkDCAxy, float[4]); -// DECLARE_SOA_COLUMN(TrkDCAz, trkDCAz, float[4]); +DECLARE_SOA_COLUMN(TrkDCAxy, trkDCAxy, float[4]); +DECLARE_SOA_COLUMN(TrkDCAz, trkDCAz, float[4]); DECLARE_SOA_COLUMN(TrkTPCcr, trkTPCcr, int[4]); +DECLARE_SOA_COLUMN(TrkTPCfind, trkTPCfind, int[4]); +DECLARE_SOA_COLUMN(TrkTPCchi2, trkTPCchi2, float[4]); +DECLARE_SOA_COLUMN(TrkITSchi2, trkITSchi2, float[4]); +DECLARE_SOA_COLUMN(TrkITScl, trkITScl, int[4]); + DECLARE_SOA_COLUMN(TrkTPCsignal, trkTPCsignal, float[4]); DECLARE_SOA_COLUMN(TrkTPCnSigmaEl, trkTPCnSigmaEl, float[4]); // DECLARE_SOA_COLUMN(TrkTPCnSigmaMu, trkTPCnSigmaMu, float[4]); @@ -105,19 +112,21 @@ DECLARE_SOA_COLUMN(TrkTOFchi2, trkTOFchi2, float[4]); } // end of namespace tau_tree DECLARE_SOA_TABLE(TauFourTracks, "AOD", "TAUFOURTRACK", tau_tree::RunNumber, tau_tree::Bc, tau_tree::TotalTracks, tau_tree::NumContrib, + tau_tree::RctOk, // tau_tree::GlobalNonPVtracks, // tau_tree::PosX, tau_tree::PosY, tau_tree::PosZ, tau_tree::FlagUPC, tau_tree::OccupancyInTime, tau_tree::HadronicRate, tau_tree::ZdcAenergy, tau_tree::ZdcCenergy, tau_tree::Qtot, tau_tree::Trs, tau_tree::Trofs, tau_tree::Hmpr, - // tau_tree::Tfb, tau_tree::ItsRofb, tau_tree::Sbp, tau_tree::ZvtxFT0vsPv, tau_tree::VtxITSTPC, + tau_tree::Tfb, tau_tree::ItsRofb, tau_tree::Sbp, tau_tree::ZvtxFT0vsPv, tau_tree::VtxITSTPC, tau_tree::TotalFT0AmplitudeA, tau_tree::TotalFT0AmplitudeC, tau_tree::TotalFV0AmplitudeA, // tau_tree::TimeFT0A, tau_tree::TimeFT0C, tau_tree::TimeFV0A, tau_tree::TrkPx, tau_tree::TrkPy, tau_tree::TrkPz, // tau_tree::TrkSign, - // tau_tree::TrkDCAxy, tau_tree::TrkDCAz, + tau_tree::TrkDCAxy, tau_tree::TrkDCAz, tau_tree::TrkTPCcr, + tau_tree::TrkTPCfind, tau_tree::TrkTPCchi2, tau_tree::TrkITSchi2, tau_tree::TrkITScl, tau_tree::TrkTPCsignal, tau_tree::TrkTPCnSigmaEl, tau_tree::TrkTPCnSigmaPi, tau_tree::TrkTPCnSigmaKa, tau_tree::TrkTPCnSigmaPr, tau_tree::TrkTPCnSigmaMu, tau_tree::TrkTOFbeta, tau_tree::TrkTOFnSigmaEl, tau_tree::TrkTOFnSigmaPi, tau_tree::TrkTOFnSigmaKa, tau_tree::TrkTOFnSigmaPr, tau_tree::TrkTOFnSigmaMu, tau_tree::TrkTOFchi2); @@ -138,7 +147,7 @@ struct TauTau13topo { ConfigurableAxis ptAxis{"ptAxis", {120, 0., 4.}, "#it{p} (GeV/#it{c})"}; // ConfigurableAxis etaAxis{"etaAxis", {100, -2., 2.}, "#eta"}; ConfigurableAxis dedxAxis{"dedxAxis", {100, 20., 160.}, "dE/dx"}; - ConfigurableAxis minvAxis{"minvAxis", {100, 0.4, 3.5}, "M_{inv} (GeV/#it{c}^{2})"}; + ConfigurableAxis minvAxis{"minvAxis", {100, 0.5, 5.0}, "M_{inv} (GeV/#it{c}^{2})"}; ConfigurableAxis phiAxis{"phiAxis", {120, 0., 3.2}, "#phi"}; // ConfigurableAxis vectorAxis{"vectorAxis", {100, 0., 2.}, "A_{V}"}; // ConfigurableAxis scalarAxis{"scalarAxis", {100, -1., 1.}, "A_{S}"}; @@ -215,6 +224,7 @@ struct TauTau13topo { const AxisSpec scalarAxis{100, -1., 1., "A_{S}"}; const AxisSpec axisZDC{50, -1., 14., "#it{E} (TeV)"}; const AxisSpec axisInvMass4trk{160, 0.5, 8.5, "#it{M}^{4trk}_{inv} (GeV/#it{c}^{2})"}; + const AxisSpec acoAxis{100, 0., 1., "A^{1+3}"}; if (doprocessDataSG) { registry.add("global/RunNumber", "Run number; Run; Collisions", {HistType::kTH1F, {{150, 544013, 545367}}}); @@ -805,22 +815,78 @@ struct TauTau13topo { registry.add("pidTOF/h3piTOFchi2Cut23", "tof chi2;chi2 TOF;events", {HistType::kTH1F, {{100, 0., 10.}}}); // registry.add("pidTOF/h3piTOFchi2Cut36", "tof chi2;chi2 TOF;events", {HistType::kTH1F, {{100, 0., 10.}}}); // registry.add("pidTOF/h3piTOFchi2Cut37", "tof chi2;chi2 TOF;events", {HistType::kTH1F, {{100, 0., 10.}}}); + + // histograms mass3pi vs acoponarity + registry.add("control/cut0/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut20/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut33/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut21/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut24/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut25/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut28/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut22/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut29/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut26/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut34/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut30/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut27/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut35/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry.add("control/cut23/h3piMassVsAco", "3#pi mass vs acoplanarity, up to 4 entries per event ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + } // end of data histograms // MC part // histograms filled by processSimpleMCSG // CollisionMC histograms - if (doprocessEfficiencyMCSG) { - registry1MC.add("globalMC/hGeneratorID", ";Generator ID;events", {HistType::kTH1F, {{100, 0., 1000.}}}); + if (doprocessEfficiencyMCSG || doprocessSimpleMCSG) { registryMC.add("globalMC/hMCZvertex", ";V_{Z}^{MC} (cm);events", {HistType::kTH1F, {{100, -25., 25.}}}); registryMC.add("globalMC/hMCefficiency", ";Cut Number;events", {HistType::kTH1F, {{20, 0., 20.}}}); + + // efficiency el + registryMC.add("efficiencyMCEl/effiEl", ";Efficiency e3#pi;events", {HistType::kTH1F, {{70, 0., 70.}}}); + // efficiency pi + registryMC.add("efficiencyMCPi/effiPi", ";Efficiency #pi3#pi;events", {HistType::kTH1F, {{20, 0., 20.}}}); + // efficiency mu + registryMC.add("efficiencyMCMu/effiMu", ";Efficiency #mu3#pi;events", {HistType::kTH1F, {{20, 0., 20.}}}); + } + + if (doprocessSimpleMCSG) { registryMC.add("globalMC/hMCnPart", ";N_{part};Type;events", {HistType::kTH2F, {{25, 0., 25.}, {10, 0, 10}}}); + registryMC.add("globalMC/hMCetaGen", ";#eta^{gen};N^{MC particles}", {HistType::kTH1F, {{100, -5., 5.}}}); registryMC.add("globalMC/hMCphiGen", ";#phi^{gen};N^{MC particles}", {HistType::kTH1F, {{100, 0., 6.4}}}); registryMC.add("globalMC/hMCyGen", ";y^{gen};N^{MC particles}", {HistType::kTH1F, {{100, -5., 5.}}}); registryMC.add("globalMC/hMCptGen", ";p_{T}^{gen};N^{MC particles}", {HistType::kTH1F, {{100, 0., 4.}}}); + // tau + registryMC.add("tauMC/hMCeta", ";#eta^{#tau};N^{#tau} ", {HistType::kTH1F, {{100, -5., 5.}}}); + registryMC.add("tauMC/hMCy", ";y^{#tau};N^{#tau}", {HistType::kTH1F, {{100, -5., 5.}}}); + registryMC.add("tauMC/hMCphi", ";#phi^{#tau};N^{#tau}", {HistType::kTH1F, {{100, 0., 6.4}}}); + registryMC.add("tauMC/hMCpt", ";#it{p}_{T}^{#tau};N^{#tau}", {HistType::kTH1F, {{100, 0., 10.}}}); + + registryMC.add("tauMC/hMCdeltaeta", ";#Delta#eta^{#tau};events ", {HistType::kTH1F, {{100, -5., 5.}}}); + registryMC.add("tauMC/hMCdeltaphi", ";#Delta#phi^{#tau}(deg.);events", {HistType::kTH1F, {{100, 131., 181}}}); + + // electron + registryMC.add("electronMC/hMCeta", ";#eta^{e};N^{e}", {HistType::kTH1F, {{100, -5., 5.}}}); + registryMC.add("electronMC/hMCy", ";y^{e};N^{e}", {HistType::kTH1F, {{100, -5., 5.}}}); + registryMC.add("electronMC/hMCphi", ";#phi^{e};N^{e}", {HistType::kTH1F, {{100, 0., 6.4}}}); + registryMC.add("electronMC/hMCpt", ";#it{p}_{T}^{e};N^{e}", {HistType::kTH1F, {{400, 0., 10.}}}); + + // efficiency mu + registryMC.add("efficiencyMCMu/hpTmuon", ";p_{T}^{#mu, gen} (GeV/c);events", {HistType::kTH1F, {{200, 0., 5.}}}); + + // efficiency pi + registryMC.add("efficiencyMCPi/hpTpi", ";p_{T}^{#pi, gen} (GeV/c);events", {HistType::kTH1F, {{200, 0., 5.}}}); + + // efficiency el + registryMC.add("efficiencyMCEl/hpTelec", ";p_{T}^{e, gen} (GeV/c);events", {HistType::kTH1F, {axispt}}); + } + + if (doprocessEfficiencyMCSG) { // MC reconstructed with information from MC true + registry1MC.add("globalMC/hGeneratorID", ";Generator ID;events", {HistType::kTH1F, {{100, 0., 1000.}}}); + registryMC.add("globalMCrec/hMCetaGenCol", ";#eta^{genCol};events", {HistType::kTH1F, {{100, -5., 5.}}}); registryMC.add("globalMCrec/hMCphiGenCol", ";#phi^{genCol};events", {HistType::kTH1F, {{100, 0., 6.4}}}); registryMC.add("globalMCrec/hMCyGenCol", ";y^{genCol};events", {HistType::kTH1F, {{100, -5., 5.}}}); @@ -1461,33 +1527,6 @@ struct TauTau13topo { registryMC.add("controlMCcomb/cut35/hPtSpectrumEl", ";p_{T}^{comb} (GeV/c);entries", {HistType::kTH1F, {axispt}}); // zrobic hpTspectrumEl dla cut 0,20-35: registry.get(HIST("global/hFinalPtSpectrumEl"))->Fill(tmpPt[i]); - // tau - registryMC.add("tauMC/hMCeta", ";#eta^{#tau};N^{#tau} ", {HistType::kTH1F, {{100, -5., 5.}}}); - registryMC.add("tauMC/hMCy", ";y^{#tau};N^{#tau}", {HistType::kTH1F, {{100, -5., 5.}}}); - registryMC.add("tauMC/hMCphi", ";#phi^{#tau};N^{#tau}", {HistType::kTH1F, {{100, 0., 6.4}}}); - registryMC.add("tauMC/hMCpt", ";#it{p}_{T}^{#tau};N^{#tau}", {HistType::kTH1F, {{100, 0., 10.}}}); - - registryMC.add("tauMC/hMCdeltaeta", ";#Delta#eta^{#tau};events ", {HistType::kTH1F, {{100, -5., 5.}}}); - registryMC.add("tauMC/hMCdeltaphi", ";#Delta#phi^{#tau}(deg.);events", {HistType::kTH1F, {{100, 131., 181}}}); - - // electron - registryMC.add("electronMC/hMCeta", ";#eta^{e};N^{e}", {HistType::kTH1F, {{100, -5., 5.}}}); - registryMC.add("electronMC/hMCy", ";y^{e};N^{e}", {HistType::kTH1F, {{100, -5., 5.}}}); - registryMC.add("electronMC/hMCphi", ";#phi^{e};N^{e}", {HistType::kTH1F, {{100, 0., 6.4}}}); - registryMC.add("electronMC/hMCpt", ";#it{p}_{T}^{e};N^{e}", {HistType::kTH1F, {{400, 0., 10.}}}); - - // efficiency mu - registryMC.add("efficiencyMCMu/effiMu", ";Efficiency #mu3#pi;events", {HistType::kTH1F, {{20, 0., 20.}}}); - registryMC.add("efficiencyMCMu/hpTmuon", ";p_{T}^{#mu, gen} (GeV/c);events", {HistType::kTH1F, {{200, 0., 5.}}}); - - // efficiency pi - registryMC.add("efficiencyMCPi/effiPi", ";Efficiency #pi3#pi;events", {HistType::kTH1F, {{20, 0., 20.}}}); - registryMC.add("efficiencyMCPi/hpTpi", ";p_{T}^{#pi, gen} (GeV/c);events", {HistType::kTH1F, {{200, 0., 5.}}}); - - // efficiency el - registryMC.add("efficiencyMCEl/effiEl", ";Efficiency e3#pi;events", {HistType::kTH1F, {{70, 0., 70.}}}); - registryMC.add("efficiencyMCEl/hpTelec", ";p_{T}^{e, gen} (GeV/c);events", {HistType::kTH1F, {axispt}}); - // efficiency el registryMC.add("efficiencyMCEl/hMCdeltaAlphaEpi", ";#Delta#alpha^{e-#pi(3x), gen} (rad);events", {HistType::kTH1F, {{100, -0.1, 3.2}}}); registryMC.add("efficiencyMCEl/hMCdeltaAlphaPiPi", ";#Delta#alpha^{#pi-#pi(3x), gen} (rad);events", {HistType::kTH1F, {{100, -0.1, 3.2}}}); @@ -1506,6 +1545,40 @@ struct TauTau13topo { registryMC.add("efficiencyMCEl/hMCinvmass3pi", ";M_{inv}^{3#pi true} (GeV/c^{2}) ;events", {HistType::kTH1F, {{100, 0.4, 2.4}}}); registryMC.add("efficiencyMCEl/hMCdeltaphi13", ";#Delta#phi^{1-3 true} ;events", {HistType::kTH1F, {{100, 0., 3.2}}}); + // histograms mass3pi vs acoponarity MC true + registry1MC.add("controlMCtrue/cut0/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut20/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut33/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut21/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut24/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut25/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut28/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut22/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut29/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut26/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut34/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut30/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut27/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut35/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCtrue/cut23/h3piMassVsAco", "3#pi mass vs acoplanarity MC sig ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + + // histograms mass3pi vs acoponarity MC comb + registry1MC.add("controlMCcomb/cut0/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut20/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut33/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut21/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut24/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut25/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut28/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut22/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut29/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut26/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut34/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut30/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut27/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut35/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + registry1MC.add("controlMCcomb/cut23/h3piMassVsAco", "3#pi mass vs acoplanarity MC comb ;M_{inv}^{3#pi} (GeV/c^{2});A^{1+3};entries", {HistType::kTH2F, {minvAxis, acoAxis}}); + } // end of MC histograms processEfficiencyMCSG if (doprocessDoSkim) { @@ -1514,31 +1587,31 @@ struct TauTau13topo { } // end of init method - float eta(float px, float py, float pz) - // Just a simple function to return pseudorapidity - { - float arg = -2.; // outside valid range for std::atanh - float mom = std::sqrt(px * px + py * py + pz * pz); - if (mom != 0) - arg = pz / mom; - if (-1. < arg && arg < 1.) - return std::atanh(arg); // definition of eta - return -999.; - } + // float eta(float px, float py, float pz) + // // Just a simple function to return pseudorapidity + // { + // float arg = -2.; // outside valid range for std::atanh + // float mom = std::sqrt(px * px + py * py + pz * pz); + // if (mom != 0) + // arg = pz / mom; + // if (-1. < arg && arg < 1.) + // return std::atanh(arg); // definition of eta + // return -999.; + // } - float phi(float px, float py) - // Just a simple function to return azimuthal angle from 0 to 2pi - { - if (px != 0) - return (std::atan2(py, px) + o2::constants::math::PI); - return -999.; - } + // float phi(float px, float py) + // // Just a simple function to return azimuthal angle from 0 to 2pi + // { + // if (px != 0) + // return (std::atan2(py, px) + o2::constants::math::PI); + // return -999.; + // } - float pt(float px, float py) - // Just a simple function to return pt - { - return std::sqrt(px * px + py * py); - } + // float pt(float px, float py) + // // Just a simple function to return pt + // { + // return std::sqrt(px * px + py * py); + // } float rapidity(float energy, float pz) // Just a simple function to return track rapidity @@ -1557,13 +1630,14 @@ struct TauTau13topo { return angle; } - float invariantMass(float E, float px, float py, float pz) - // Just a simple function to return invariant mass - { - return std::sqrt(E * E - px * px - py * py - pz * pz); - } + // float invariantMass(float E, float px, float py, float pz) + // // Just a simple function to return invariant mass + // { + // return std::sqrt(E * E - px * px - py * py - pz * pz); + // } - float calculateDeltaPhi(TLorentzVector p, TLorentzVector p1) + // float calculateDeltaPhi(TLorentzVector p, TLorentzVector p1) + float calculateDeltaPhi(ROOT::Math::LorentzVector> p, ROOT::Math::LorentzVector> p1) { // float delta = p.Phi(); float delta = RecoDecay::constrainAngle(p.Phi()); @@ -1616,8 +1690,10 @@ struct TauTau13topo { // helper function to calculate scalar asymmetry float scalarAsymMC(auto particle1, auto particle2) { - auto pt1 = pt(particle1.px(), particle1.py()); - auto pt2 = pt(particle2.px(), particle2.py()); + // auto pt1 = pt(particle1.px(), particle1.py()); + auto pt1 = RecoDecay::pt(particle1.px(), particle1.py()); + // auto pt2 = pt(particle2.px(), particle2.py()); + auto pt2 = RecoDecay::pt(particle2.px(), particle2.py()); auto delta = pt1 - pt2; return std::abs(delta) / (pt1 + pt2); } @@ -1651,6 +1727,8 @@ struct TauTau13topo { registry.get(HIST("control/cut") + HIST(kHistoname[mode]) + HIST("/hTPCnCrossedRows"))->Fill(nCRtpc); registry.get(HIST("control/cut") + HIST(kHistoname[mode]) + HIST("/hPtSpectrumEl"))->Fill(ptelec); registry.get(HIST("control/cut") + HIST(kHistoname[mode]) + HIST("/hTofChi2El"))->Fill(tofchi2); + float aco = 1. - pi3deltaPhi / o2::constants::math::PI; + registry.get(HIST("control/cut") + HIST(kHistoname[mode]) + HIST("/h3piMassVsAco"))->Fill(pi3invMass, aco); } // fill control histograms per track in MC true @@ -1671,6 +1749,8 @@ struct TauTau13topo { registryMC.get(HIST("controlMCtrue/cut") + HIST(kHistoname[mode]) + HIST("/hPtSpectrumEl"))->Fill(ptelec); // registryMC.get(HIST("controlMCtrue/cut") + HIST(kHistoname[mode]) + HIST("/h13EtaSum"))->Fill(pi3etasum); registry1MC.get(HIST("controlMCtrue/cut") + HIST(kHistoname[mode]) + HIST("/hTofChi2El"))->Fill(tofchi2); + float aco = 1. - pi3deltaPhi / o2::constants::math::PI; + registry1MC.get(HIST("controlMCtrue/cut") + HIST(kHistoname[mode]) + HIST("/h3piMassVsAco"))->Fill(pi3invMass, aco); } // fill control histograms per track in MC true @@ -1691,6 +1771,8 @@ struct TauTau13topo { registryMC.get(HIST("controlMCcomb/cut") + HIST(kHistoname[mode]) + HIST("/hPtSpectrumEl"))->Fill(ptelec); // registryMC.get(HIST("controlMCtrue/cut") + HIST(kHistoname[mode]) + HIST("/h13EtaSum"))->Fill(pi3etasum); registry1MC.get(HIST("controlMCcomb/cut") + HIST(kHistoname[mode]) + HIST("/hTofChi2El"))->Fill(tofchi2); + float aco = 1. - pi3deltaPhi / o2::constants::math::PI; + registry1MC.get(HIST("controlMCcomb/cut") + HIST(kHistoname[mode]) + HIST("/h3piMassVsAco"))->Fill(pi3invMass, aco); } template @@ -1778,7 +1860,7 @@ struct TauTau13topo { } else { isGlobalTrack = false; } - if (std::abs(eta(track.px(), track.py(), track.pz())) < 0.8) { + if (std::abs(RecoDecay::eta(std::array{track.px(), track.py(), track.pz()})) < 0.8) { registry.get(HIST("global/hTrackEfficiencyPVGlobal"))->Fill(8., 1.); } else { isGlobalTrack = false; @@ -1919,6 +2001,45 @@ struct TauTau13topo { return true; } + // check ITS clusters, how many -1,0,1,7 + 10 if 0,1,2 layers were fired + // analysis track quality check + template + int numberOfItsClustersCheck(T track) + { + if (!track.hasITS()) + return -1; + int nITSbits = 0; + int firstThreeLayers = 0; + uint32_t clusterSizes = track.itsClusterSizes(); + for (int layer = 0; layer < 7; layer++) { + if ((clusterSizes >> (layer * 4)) & 0xf) { + nITSbits++; + if (layer < 3) + firstThreeLayers++; + } + } // end of loop over ITS bits + if (firstThreeLayers == 3) + nITSbits += 10; + + return nITSbits; + } + + // RCT check + template + int isGoodRCTflag(C const& coll) + { + if (sgSelector.isCBTHadronZdcOk(coll)) + return 4; + else if (sgSelector.isCBTHadronOk(coll)) + return 3; + else if (sgSelector.isCBTZdcOk(coll)) + return 2; + else if (sgSelector.isCBTOk(coll)) + return 1; + else + return 0; + } + // using UDCollisionsFull = soa::Join; // using UDCollisionFull = UDCollisionsFull::iterator; using UDTracksFull = soa::Join; @@ -1930,9 +2051,6 @@ struct TauTau13topo { Filter pVContributorFilter = aod::udtrack::isPVContributor == true; using PVTracks = soa::Filtered; - // using LabeledTracks = soa::Join; - using LabeledTracks = soa::Join; - Preslice perCollision = aod::udtrack::udCollisionId; // PVContributors in MC handling // Filter pVContributorFilterMC = aod::udtrack::isPVContributor == true; // using PVTracksMC = soa::Filtered; @@ -2010,7 +2128,8 @@ struct TauTau13topo { int nEtaIn15 = 0; int nITSbits = -1; int npT100 = 0; - TLorentzVector p; + // TLorentzVector p; + ROOT::Math::LorentzVector> p; // auto const pionMass = MassPiPlus; // auto const electronMass = MassElectron; bool flagGlobalCheck = true; @@ -2019,7 +2138,8 @@ struct TauTau13topo { // loop over PV contributors for (const auto& trk : PVContributors) { qtot += trk.sign(); - p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + // p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + p.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassPiPlus)); registry.get(HIST("global/hTrackPtPV"))->Fill(p.Pt()); if (std::abs(p.Eta()) < trkEtacut) nEtaIn15++; // 1.5 is a default @@ -2093,7 +2213,9 @@ struct TauTau13topo { registry.get(HIST("global1/hNTracks"))->Fill(dgtracks.size()); registry.get(HIST("global1/hNTracksPV"))->Fill(PVContributors.size()); for (const auto& trk : PVContributors) { - p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + // p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + // p.SetXYZT(trk.px(), trk.py(), trk.pz(), energy(trk.px(), trk.py(), trk.pz(), MassPiPlus)); + p.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassPiPlus)); registry.get(HIST("global1/hTrackPtPV"))->Fill(p.Pt()); registry.get(HIST("global1/hTrackEtaPhiPV"))->Fill(p.Eta(), p.Phi()); } @@ -2253,23 +2375,27 @@ struct TauTau13topo { // 12 34 | 01 23 |//1 //6 | 0 5 |counter<3?counter:5-counter counter<3?0:1 // 13 24 | 02 13 |//2 //5 | 1 4 | // 14 23 | 03 12 |//3 //4 | 2 3 | - TLorentzVector p1, p2; - TLorentzVector gammaPair[3][2]; - float invMass2El[3][2]; + // TLorentzVector p1, p2; + ROOT::Math::LorentzVector> p1, p2; + // TLorentzVector gammaPair[3][2]; + ROOT::Math::LorentzVector> gammaPair[3][2]; + float invMass2El[3][2]; // inv. mass squared int counterTmp = 0; bool flagIMGam2ePV[4] = {true, true, true, true}; for (const auto& trk : PVContributors) { - p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassElectron); + // p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassElectron); + p.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassElectron)); for (const auto& trk1 : PVContributors) { if (trk.index() >= trk1.index()) continue; if (trk1.hasTPC()) nPiHasTPC[trk.index()]++; - p1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), MassElectron); - invMass2El[(counterTmp < 3 ? counterTmp : 5 - counterTmp)][(counterTmp < 3 ? 0 : 1)] = (p + p1).Mag2(); + // p1.SetXYZM(trk1.px(), trk1.py(), trk1.pz(), MassElectron); + p1.SetXYZT(trk1.px(), trk1.py(), trk1.pz(), RecoDecay::e(trk1.px(), trk1.py(), trk1.pz(), MassElectron)); + invMass2El[(counterTmp < 3 ? counterTmp : 5 - counterTmp)][(counterTmp < 3 ? 0 : 1)] = (p + p1).mag2(); gammaPair[(counterTmp < 3 ? counterTmp : 5 - counterTmp)][(counterTmp < 3 ? 0 : 1)] = (p + p1); - registry.get(HIST("control/cut0/hInvMass2ElAll"))->Fill((p + p1).Mag2()); + registry.get(HIST("control/cut0/hInvMass2ElAll"))->Fill((p + p1).mag2()); counterTmp++; if ((p + p1).M() < 0.015) { flagIMGam2ePV[trk.index()] = false; @@ -2279,15 +2405,17 @@ struct TauTau13topo { } // end of loop over PVContributors // first loop to add all the tracks together - p = TLorentzVector(0., 0., 0., 0.); + // p = TLorentzVector(0., 0., 0., 0.); + p.SetXYZT(0., 0., 0., 0.); for (const auto& trk : PVContributors) { - p1.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + // p1.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + p1.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassPiPlus)); p += p1; scalarPtsum += trk.pt(); } // end of loop over PVContributors float pttot = p.Pt(); - float mass4pi = p.Mag(); + float mass4pi = p.mag(); TVector3 v1(0, 0, 0); TVector3 vtmp(0, 0, 0); @@ -2309,9 +2437,11 @@ struct TauTau13topo { registry.get(HIST("global/hTrkCheck"))->Fill(tmpTrkCheck); // inv mass of 3pi + 1e - p1.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); - p2.SetXYZM(trk.px(), trk.py(), trk.pz(), MassElectron); - mass3pi1e[counterTmp] = (p - p1 + p2).Mag(); + // p1.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + p1.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassPiPlus)); + // p2.SetXYZM(trk.px(), trk.py(), trk.pz(), MassElectron); + p2.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassElectron)); + mass3pi1e[counterTmp] = (p - p1 + p2).mag(); v1.SetXYZ(trk.px(), trk.py(), trk.pz()); for (const auto& trk1 : PVContributors) { @@ -2358,14 +2488,15 @@ struct TauTau13topo { trkTime[counterTmp] = trk.trackTime(); trkTimeRes[counterTmp] = trk.trackTimeRes(); - p1.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + // p1.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + p1.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassPiPlus)); tmpMomentum[counterTmp] = p1.P(); tmpPt[counterTmp] = p1.Pt(); tmpDedx[counterTmp] = trk.tpcSignal(); tmpTofNsigmaEl[counterTmp] = trk.tofNSigmaEl(); deltaPhiTmp = calculateDeltaPhi(p - p1, p1); - pi3invMass[counterTmp] = (p - p1).Mag(); + pi3invMass[counterTmp] = (p - p1).mag(); pi3pt[counterTmp] = (p - p1).Pt(); pi3deltaPhi[counterTmp] = deltaPhiTmp; pi3assymav[counterTmp] = (p1.Pt() - (scalarPtsum - p1.Pt()) / 3.) / (p1.Pt() + (scalarPtsum - p1.Pt()) / 3.); @@ -3216,6 +3347,7 @@ struct TauTau13topo { // loop over MC particles for (const auto& mcParticle : mcParticles) { + // LOGF(info, " mcParticle pdg %d", mcParticle.pdgCode()); // primaries // if (mcParticle.isPhysicalPrimary()) { // countPrim++; @@ -3227,7 +3359,8 @@ struct TauTau13topo { countGen++; if (mcParticle.isPhysicalPrimary()) { countBoth++; - if (mcParticle.pdgCode() != 22 && std::abs(mcParticle.pdgCode()) != 12 && std::abs(mcParticle.pdgCode()) != 14 && std::abs(mcParticle.pdgCode()) != 16 && mcParticle.pdgCode() != 130 && mcParticle.pdgCode() != 111) { + // if (mcParticle.pdgCode() != 22 && std::abs(mcParticle.pdgCode()) != 12 && std::abs(mcParticle.pdgCode()) != 14 && std::abs(mcParticle.pdgCode()) != 16 && mcParticle.pdgCode() != 130 && mcParticle.pdgCode() != 111) { + if (mcParticle.pdgCode() != kGamma && std::abs(mcParticle.pdgCode()) != kNuE && std::abs(mcParticle.pdgCode()) != kNuMu && std::abs(mcParticle.pdgCode()) != kNuTau && mcParticle.pdgCode() != kK0Long && mcParticle.pdgCode() != kPi0) { countCharged++; registryMC.get(HIST("globalMC/hMCetaGen"))->Fill(mcParticle.eta()); @@ -3237,7 +3370,8 @@ struct TauTau13topo { if (mcParticle.has_mothers()) { auto const& mother = mcParticle.mothers_first_as(); - if (std::abs(mother.pdgCode()) == 15) { + // if (std::abs(mother.pdgCode()) == 15) { + if (std::abs(mother.pdgCode()) == kTauMinus) { countChargedFromTau++; } // mother is tau } // mc particle has mother @@ -3248,7 +3382,8 @@ struct TauTau13topo { // // tau+/- // - if (std::abs(mcParticle.pdgCode()) == 15) { // tau+/- + // if (std::abs(mcParticle.pdgCode()) == 15) { // tau+/- + if (std::abs(mcParticle.pdgCode()) == kTauMinus) { // 15 = tau+/- countTau++; if (countTau <= 2) { etaTau[countTau - 1] = mcParticle.eta(); @@ -3265,15 +3400,15 @@ struct TauTau13topo { if (mcParticle.has_daughters()) { for (const auto& daughter : mcParticle.daughters_as()) { // pions from tau - if (std::abs(daughter.pdgCode()) == 211) { // 211 = pi+ + if (std::abs(daughter.pdgCode()) == kPiPlus) { // 211 = pi+ pionCounter++; tmpPionIndex = daughter.index(); // returns index of daughter of tau, not in the event, not in the MC particles if (std::abs(daughter.eta()) > 0.9) partFromTauInEta = false; } // end of pion check // electron from tau - if (std::abs(daughter.pdgCode()) == 11) { // 11 = electron - if (daughter.pdgCode() == 11) + if (std::abs(daughter.pdgCode()) == kElectron) { // 11 = electron + if (daughter.pdgCode() == kElectron) flagElPlusElMinus = true; registryMC.get(HIST("electronMC/hMCeta"))->Fill(daughter.eta()); registryMC.get(HIST("electronMC/hMCphi"))->Fill(daughter.phi()); @@ -3288,8 +3423,8 @@ struct TauTau13topo { partFromTauInEta = false; } // end of electron check // muon from tau - if (std::abs(daughter.pdgCode()) == 13) { - if (daughter.pdgCode() == 13) + if (std::abs(daughter.pdgCode()) == kMuonMinus) { // 13 + if (daughter.pdgCode() == kMuonMinus) // 13 flagMuPlusMuMinus = true; muonFound = !muonFound; partPt = static_cast(daughter.pt()); @@ -3305,7 +3440,7 @@ struct TauTau13topo { singlePionFound = true; singlePionIndex = tmpPionIndex; auto mcPartTmp = mcParticle.daughters_as().begin() + singlePionIndex; - if (mcPartTmp.pdgCode() == -211) + if (mcPartTmp.pdgCode() == kPiMinus) // -211 flagPiPlusPiMinus = true; partPt = static_cast(mcPartTmp.pt()); // motherOfSinglePionIndex = mcParticle.index(); @@ -3393,20 +3528,42 @@ struct TauTau13topo { } // end of processSimpleMCSG + // using LabeledTracks = soa::Join; + using LabeledTracks = soa::Join; + Preslice perCollision = aod::udtrack::udCollisionId; + // ZDC is not reproduced in MC, it is for a consistency + using FullMcUdCollisions = soa::Join; + // using FullMcUdCollisions = soa::Join; + // PresliceUnsorted colPerMcCollision = aod::udcollision::udMcCollisionId; + // PresliceUnsorted partPerMcCollision = aod::udmcparticle::udMcCollisionId; + void processEfficiencyMCSG(aod::UDMcCollision const& mcCollision, + // void processEfficiencyMCSG(aod::UDMcCollisions const& mcCollisions, // soa::SmallGroups> const& collisions, - soa::SmallGroups> const& collisions, + // soa::SmallGroups> const& collisions, + soa::SmallGroups const& collisions, + // FullMcUdCollisions const& collisionsFull, LabeledTracks const& tracks, aod::UDMcParticles const& mcParticles) + // aod::UDMcParticles const& mcParts) { + // LOGF(info, " Per DF: UDMcParticles size %d, UDMcCollisions size %d, FullMcUdCollisions size %d", mcParts.size(), mcCollisions.size(), collisionsFull.size()); + // LOGF(info, " Per DF: UDMcParticles size %d, UDMcCollisions size %d, FullMcUdCollisions size %d", mcParts.size(), mcCollisions.size(), collisions.size()); + + // loop over generated collisions + // for (const auto &mcCollision : mcCollisions) { + // LOGF(info, " Per mcCollision not sliced: UDMcParticles size %d, FullMcUdCollisions size %d", mcParts.size(), collisionsFull.size()); + if (verbose) { LOGF(info, " GeneratorIDtot %d", mcCollision.generatorsID()); // below is not implemented in UDMcCollisions // LOGF(info," GeneratorIDtot %d, GenID %d, subGenID %d, source %d", mcCollision.generatorsID(), mcCollision.getGeneratorId(), mcCollision.getSubGeneratorId(), mcCollision.getSourceId()); } + // registry1MC.get(HIST("globalMC/hGeneratorID"))->Fill(mcCollision.getGeneratorID()); registry1MC.get(HIST("globalMC/hGeneratorID"))->Fill(mcCollision.generatorsID()); registryMC.get(HIST("globalMC/hMCefficiency"))->Fill(10., 1.); if (!(generatorIDMC < 0)) { // do not check generatorsID process if generatorIDMC < 0 + // if (mcCollision.getGeneratorID() != generatorIDMC) if (mcCollision.generatorsID() != generatorIDMC) return; } @@ -3424,26 +3581,38 @@ struct TauTau13topo { bool tauInRapidity = true; bool partFromTauInEta = true; - TLorentzVector tmp(0., 0., 0., 0.); + // TLorentzVector tmp(0., 0., 0., 0.); + ROOT::Math::LorentzVector> tmp(0., 0., 0., 0.); + + // get reconstructed collisions associated to generated collision + // auto const& collisions = collisionsFull.sliceBy(colPerMcCollision, mcCollision.globalIndex()); + // LOGF(info, " per mcCollisions sliced collisions.size %d", collisions.size()); + + // get MC particles associated to generated collision + // auto const& mcParticles = mcParts.sliceBy(partPerMcCollision, mcCollision.globalIndex()); + // LOGF(info, " per mcCollisions sliced mcParticles.size %d", mcParticles.size()); for (const auto& mcParticle : mcParticles) { + // LOGF(info, " mcParticle pdg %d", mcParticle.pdgCode()); if (mcParticle.isPhysicalPrimary()) { - if (mcParticle.pdgCode() != 22 && std::abs(mcParticle.pdgCode()) != 12 && std::abs(mcParticle.pdgCode()) != 14 && std::abs(mcParticle.pdgCode()) != 16 && mcParticle.pdgCode() != 130 && mcParticle.pdgCode() != 111) { + // if (mcParticle.pdgCode() != 22 && std::abs(mcParticle.pdgCode()) != 12 && std::abs(mcParticle.pdgCode()) != 14 && std::abs(mcParticle.pdgCode()) != 16 && mcParticle.pdgCode() != 130 && mcParticle.pdgCode() != 111) { + if (mcParticle.pdgCode() != kGamma && std::abs(mcParticle.pdgCode()) != kNuE && std::abs(mcParticle.pdgCode()) != kNuMu && std::abs(mcParticle.pdgCode()) != kNuTau && mcParticle.pdgCode() != kK0Long && mcParticle.pdgCode() != kPi0) { if (mcParticle.has_mothers()) { auto const& mother = mcParticle.mothers_first_as(); + // LOGF(info, " mcParticle has mother %d",mother.pdgCode()); tmp.SetPxPyPzE(mother.px(), mother.py(), mother.pz(), mother.e()); - if (std::abs(mother.pdgCode()) == 15) { + if (std::abs(mother.pdgCode()) == kTauMinus) { // 15 if (std::abs(rapidity(mother.e(), mother.pz())) > 0.9) // if (std::abs(tmp.Rapidity()) > 0.9) tauInRapidity = false; - if (std::abs(eta(mcParticle.px(), mcParticle.py(), mcParticle.pz())) > 0.9) + if (std::abs(RecoDecay::eta(std::array{mcParticle.px(), mcParticle.py(), mcParticle.pz()})) > 0.9) // if (std::abs(tmp.Eta()) > 0.9) partFromTauInEta = false; - if (std::abs(mcParticle.pdgCode()) == 11) { + if (std::abs(mcParticle.pdgCode()) == kElectron) { // 11 index1ProngMC = mcParticle.index(); is1ProngElectronMC = true; - } else if (std::abs(mcParticle.pdgCode()) == 13) { + } else if (std::abs(mcParticle.pdgCode()) == kMuonMinus) { // 13 index1ProngMC = mcParticle.index(); // is1ProngMuonMC = true; } @@ -3457,16 +3626,15 @@ struct TauTau13topo { } count++; if (collisions.size() > 0) { - registryMC.get(HIST("globalMCrec/hMCetaGenCol"))->Fill(eta(mcParticle.px(), mcParticle.py(), mcParticle.pz())); - registryMC.get(HIST("globalMCrec/hMCphiGenCol"))->Fill(phi(mcParticle.px(), mcParticle.py())); + registryMC.get(HIST("globalMCrec/hMCetaGenCol"))->Fill(RecoDecay::eta(std::array{mcParticle.px(), mcParticle.py(), mcParticle.pz()})); + registryMC.get(HIST("globalMCrec/hMCphiGenCol"))->Fill(RecoDecay::phi(mcParticle.px(), mcParticle.py())); registryMC.get(HIST("globalMCrec/hMCyGenCol"))->Fill(rapidity(mcParticle.e(), mcParticle.pz())); - registryMC.get(HIST("globalMCrec/hMCptGenCol"))->Fill(pt(mcParticle.px(), mcParticle.py())); + registryMC.get(HIST("globalMCrec/hMCptGenCol"))->Fill(RecoDecay::pt(mcParticle.px(), mcParticle.py())); } } // mother is tau } // has mothers } // charged particles } // end if isPhysicalPrimary - } // end loop over mcParticle registryMC.get(HIST("globalMC/hMCefficiency"))->Fill(11., 1.); @@ -3492,10 +3660,10 @@ struct TauTau13topo { // // motherIndex[i] = (tmpMC.mothers_first_as()).globalIndex(); // } int motherIndex1Pi = motherIndex[0]; - int motherIndexNew = -1; + int motherIndexNew = 3; // was -1 int nDifferences = 0; for (int i = 1; i < 4; i++) { - if (motherIndex1Pi != motherIndex[i]) { // the same mother index + if (motherIndex1Pi != motherIndex[i]) { // the same mother (tau) index nDifferences++; motherIndexNew = i; } @@ -3508,8 +3676,8 @@ struct TauTau13topo { // if (!onlyPi) LOGF(info, "ERROR: should be 4 pions, but they are not!"); } // end of special check for pi + 3pi - int index3ProngMC[3]; - if (index1ProngMC > 0) { // electron or muon case + 3pi + int index3ProngMC[3] = {0, 0, 0}; // initialised of request + if (index1ProngMC > 0) { // electron or muon case + 3pi int index3pi = 0; for (int i = 0; i < 4; i++) { if (index1ProngMC == indexProngMC[i]) @@ -3527,7 +3695,8 @@ struct TauTau13topo { auto const& tmpPion2MC = mcParticles.begin() + index3ProngMC[1]; auto const& tmpPion3MC = mcParticles.begin() + index3ProngMC[2]; - if (std::abs(tmpPion1MC.pdgCode()) == 211 && std::abs(tmpPion2MC.pdgCode()) == 211 && std::abs(tmpPion3MC.pdgCode()) == 211) + // if (std::abs(tmpPion1MC.pdgCode()) == 211 && std::abs(tmpPion2MC.pdgCode()) == 211 && std::abs(tmpPion3MC.pdgCode()) == 211) + if (std::abs(tmpPion1MC.pdgCode()) == kPiPlus && std::abs(tmpPion2MC.pdgCode()) == kPiPlus && std::abs(tmpPion3MC.pdgCode()) == kPiPlus) // 211 211 211 is3prong3PiMC = true; // @@ -3547,13 +3716,13 @@ struct TauTau13topo { registryMC.get(HIST("efficiencyMCEl/hMCdeltaAlphaEpi"))->Fill(deltaAlpha2); registryMC.get(HIST("efficiencyMCEl/hMCdeltaAlphaEpi"))->Fill(deltaAlpha3); // - registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiEpi"))->Fill(calculateDeltaPhi(phi(tmp1ProngMC.px(), tmp1ProngMC.py()), phi(tmpPion1MC.px(), tmpPion1MC.py()))); - registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiEpi"))->Fill(calculateDeltaPhi(phi(tmp1ProngMC.px(), tmp1ProngMC.py()), phi(tmpPion2MC.px(), tmpPion2MC.py()))); - registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiEpi"))->Fill(calculateDeltaPhi(phi(tmp1ProngMC.px(), tmp1ProngMC.py()), phi(tmpPion3MC.px(), tmpPion3MC.py()))); + registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiEpi"))->Fill(calculateDeltaPhi(RecoDecay::phi(tmp1ProngMC.px(), tmp1ProngMC.py()), RecoDecay::phi(tmpPion1MC.px(), tmpPion1MC.py()))); + registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiEpi"))->Fill(calculateDeltaPhi(RecoDecay::phi(tmp1ProngMC.px(), tmp1ProngMC.py()), RecoDecay::phi(tmpPion2MC.px(), tmpPion2MC.py()))); + registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiEpi"))->Fill(calculateDeltaPhi(RecoDecay::phi(tmp1ProngMC.px(), tmp1ProngMC.py()), RecoDecay::phi(tmpPion3MC.px(), tmpPion3MC.py()))); // - registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiPipi"))->Fill(calculateDeltaPhi(phi(tmpPion1MC.px(), tmpPion1MC.py()), phi(tmpPion2MC.px(), tmpPion2MC.py()))); - registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiPipi"))->Fill(calculateDeltaPhi(phi(tmpPion1MC.px(), tmpPion1MC.py()), phi(tmpPion3MC.px(), tmpPion3MC.py()))); - registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiPipi"))->Fill(calculateDeltaPhi(phi(tmpPion2MC.px(), tmpPion2MC.py()), phi(tmpPion3MC.px(), tmpPion3MC.py()))); + registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiPipi"))->Fill(calculateDeltaPhi(RecoDecay::phi(tmpPion1MC.px(), tmpPion1MC.py()), RecoDecay::phi(tmpPion2MC.px(), tmpPion2MC.py()))); + registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiPipi"))->Fill(calculateDeltaPhi(RecoDecay::phi(tmpPion1MC.px(), tmpPion1MC.py()), RecoDecay::phi(tmpPion3MC.px(), tmpPion3MC.py()))); + registryMC.get(HIST("efficiencyMCEl/hMCdeltaPhiPipi"))->Fill(calculateDeltaPhi(RecoDecay::phi(tmpPion2MC.px(), tmpPion2MC.py()), RecoDecay::phi(tmpPion3MC.px(), tmpPion3MC.py()))); // auto deltaAlphaPi1 = deltaAlpha(tmpPion1MC, tmpPion2MC); @@ -3566,13 +3735,13 @@ struct TauTau13topo { float energyInCone = 0; float angleLimit = 0.5; if (deltaAlpha1 < angleLimit) { - energyInCone += pt(tmpPion1MC.px(), tmpPion1MC.py()); + energyInCone += RecoDecay::pt(tmpPion1MC.px(), tmpPion1MC.py()); } if (deltaAlpha2 < angleLimit) { - energyInCone += pt(tmpPion2MC.px(), tmpPion2MC.py()); + energyInCone += RecoDecay::pt(tmpPion2MC.px(), tmpPion2MC.py()); } if (deltaAlpha3 < angleLimit) { - energyInCone += pt(tmpPion3MC.px(), tmpPion3MC.py()); + energyInCone += RecoDecay::pt(tmpPion3MC.px(), tmpPion3MC.py()); } registryMC.get(HIST("efficiencyMCEl/hMCvirtCal"))->Fill(energyInCone); // @@ -3585,17 +3754,19 @@ struct TauTau13topo { registryMC.get(HIST("efficiencyMCEl/hMCVector"))->Fill(vectorAsym(tmp1ProngMC, tmpPion3MC)); // add eta phi - registryMC.get(HIST("efficiencyMCEl/hMCptEl"))->Fill(pt(tmp1ProngMC.px(), tmp1ProngMC.py())); + registryMC.get(HIST("efficiencyMCEl/hMCptEl"))->Fill(RecoDecay::pt(tmp1ProngMC.px(), tmp1ProngMC.py())); float px3pi = tmpPion1MC.px() + tmpPion2MC.px() + tmpPion3MC.px(); float py3pi = tmpPion1MC.py() + tmpPion2MC.py() + tmpPion3MC.py(); float pz3pi = tmpPion1MC.pz() + tmpPion2MC.pz() + tmpPion3MC.pz(); float en3pi = tmpPion1MC.e() + tmpPion2MC.e() + tmpPion3MC.e(); - registryMC.get(HIST("efficiencyMCEl/hMCpt4trk"))->Fill(pt(tmp1ProngMC.px() + px3pi, tmp1ProngMC.py() + py3pi)); - registryMC.get(HIST("efficiencyMCEl/hMCinvmass4pi"))->Fill(invariantMass(tmp1ProngMC.e() + en3pi, tmp1ProngMC.px() + px3pi, tmp1ProngMC.py() + py3pi, tmp1ProngMC.pz() + pz3pi)); - registryMC.get(HIST("efficiencyMCEl/hMCinvmass3pi"))->Fill(invariantMass(en3pi, px3pi, py3pi, pz3pi)); - registryMC.get(HIST("efficiencyMCEl/hMCdeltaphi13"))->Fill(calculateDeltaPhi(phi(tmp1ProngMC.px(), tmp1ProngMC.py()), phi(px3pi, py3pi))); + registryMC.get(HIST("efficiencyMCEl/hMCpt4trk"))->Fill(RecoDecay::pt(tmp1ProngMC.px() + px3pi, tmp1ProngMC.py() + py3pi)); + // registryMC.get(HIST("efficiencyMCEl/hMCinvmass4pi"))->Fill(invariantMass(tmp1ProngMC.e() + en3pi, tmp1ProngMC.px() + px3pi, tmp1ProngMC.py() + py3pi, tmp1ProngMC.pz() + pz3pi)); + registryMC.get(HIST("efficiencyMCEl/hMCinvmass4pi"))->Fill(RecoDecay::m(std::array{(tmp1ProngMC.px() + px3pi), (tmp1ProngMC.py() + py3pi), (tmp1ProngMC.pz() + pz3pi)}, (tmp1ProngMC.e() + en3pi))); + // registryMC.get(HIST("efficiencyMCEl/hMCinvmass3pi"))->Fill(invariantMass(en3pi, px3pi, py3pi, pz3pi)); + registryMC.get(HIST("efficiencyMCEl/hMCinvmass3pi"))->Fill(RecoDecay::m(std::array{px3pi, py3pi, pz3pi}, en3pi)); + registryMC.get(HIST("efficiencyMCEl/hMCdeltaphi13"))->Fill(calculateDeltaPhi(RecoDecay::phi(tmp1ProngMC.px(), tmp1ProngMC.py()), RecoDecay::phi(px3pi, py3pi))); // reconstructed event if (collisions.size() < 1) @@ -3724,7 +3895,7 @@ struct TauTau13topo { nPVTracks++; trackCharge += track.sign(); // if (std::abs(eta(track.px(),track.py(),track.pz())) >= trkEtacut) allInEtaAcceptance = false; - if (std::abs(eta(track.px(), track.py(), track.pz())) < trkEtacut) + if (std::abs(RecoDecay::eta(std::array{track.px(), track.py(), track.pz()})) < trkEtacut) nTrkInEtaRange++; if (track.pt() > 0.1) nTrkAbovePtThreshold++; @@ -3857,8 +4028,10 @@ struct TauTau13topo { registryMC.get(HIST("global1MCrec/hNTracks"))->Fill(groupedTracks.size()); registryMC.get(HIST("global1MCrec/hNTracksPV"))->Fill(nPVTracks); - TLorentzVector p, p1; - p.SetXYZM(0., 0., 0., 0.); + // TLorentzVector p, p1; + ROOT::Math::LorentzVector> p, p1; + // p.SetXYZM(0., 0., 0., 0.); + p.SetXYZT(0., 0., 0., 0.); TVector3 v1(0, 0, 0); TVector3 v2(0, 0, 0); float scalarPtsum = 0; @@ -3888,17 +4061,20 @@ struct TauTau13topo { flagVcalPV[i] = true; } } // end of second loop - float tmpEtaData = eta(tmptrack.px(), tmptrack.py(), tmptrack.pz()); - float tmpPhiData = phi(tmptrack.px(), tmptrack.py()); + float tmpEtaData = RecoDecay::eta(std::array{tmptrack.px(), tmptrack.py(), tmptrack.pz()}); + float tmpPhiData = RecoDecay::phi(tmptrack.px(), tmptrack.py()); registryMC.get(HIST("global1MCrec/hTrackEtaPhiPV"))->Fill(tmpEtaData, tmpPhiData); registryMC.get(HIST("global1MCrec/hTrackPtPV"))->Fill(tmptrack.pt()); - p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), MassPiPlus); // in case of ghost + // p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), MassPiPlus); // in case of ghost + p1.SetXYZT(v1.X(), v1.Y(), v1.Z(), RecoDecay::e(v1.X(), v1.Y(), v1.Z(), MassPiPlus)); // in case of ghost if (trackMCId[i] >= 0) { - p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), (std::abs(tmptrack.udMcParticle().pdgCode()) == 211 ? MassPiPlus : MassElectron)); - float tmpPt = pt(tmptrack.udMcParticle().px(), tmptrack.udMcParticle().py()); - float tmpEta = eta(tmptrack.udMcParticle().px(), tmptrack.udMcParticle().py(), tmptrack.udMcParticle().pz()); - float tmpPhi = phi(tmptrack.udMcParticle().px(), tmptrack.udMcParticle().py()); + // p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), (std::abs(tmptrack.udMcParticle().pdgCode()) == 211 ? MassPiPlus : MassElectron)); + // p1.SetXYZT(v1.X(), v1.Y(), v1.Z(), energy(v1.X(), v1.Y(), v1.Z(), (std::abs(tmptrack.udMcParticle().pdgCode()) == 211 ? MassPiPlus : MassElectron))); + p1.SetXYZT(v1.X(), v1.Y(), v1.Z(), RecoDecay::e(v1.X(), v1.Y(), v1.Z(), (std::abs(tmptrack.udMcParticle().pdgCode()) == kPiPlus ? MassPiPlus : MassElectron))); // 211 + float tmpPt = RecoDecay::pt(tmptrack.udMcParticle().px(), tmptrack.udMcParticle().py()); + float tmpEta = RecoDecay::eta(std::array{tmptrack.udMcParticle().px(), tmptrack.udMcParticle().py(), tmptrack.udMcParticle().pz()}); + float tmpPhi = RecoDecay::phi(tmptrack.udMcParticle().px(), tmptrack.udMcParticle().py()); registryMC.get(HIST("global1MCrec/hpTGenRecTracksPV"))->Fill(tmptrack.pt(), tmpPt); registryMC.get(HIST("global1MCrec/hDeltapTGenRecVsRecpTTracksPV"))->Fill(tmptrack.pt() - tmpPt, tmptrack.pt()); registryMC.get(HIST("global1MCrec/hEtaGenRecTracksPV"))->Fill(tmpEtaData, tmpEta); @@ -4010,7 +4186,7 @@ struct TauTau13topo { // // temporary control variables per event with combinatorics float pttot = p.Pt(); - float mass4pi = p.Mag(); + float mass4pi = p.mag(); int counterTmp = 0; float nSigmaEl[4]; @@ -4053,9 +4229,11 @@ struct TauTau13topo { auto const tmptrack = groupedTracks.begin() + trackId[i]; // if (tmptrack.hasTOF()) trkHasTof[i] = true; v1.SetXYZ(tmptrack.px(), tmptrack.py(), tmptrack.pz()); - p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), MassPiPlus); // in case of ghost + // p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), MassPiPlus); // in case of ghost + p1.SetXYZT(v1.X(), v1.Y(), v1.Z(), RecoDecay::e(v1.X(), v1.Y(), v1.Z(), MassPiPlus)); // in case of ghost if (trackMCId[i] >= 0) { - p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), (i == matchedElIndexToData ? MassElectron : MassPiPlus)); + // p1.SetXYZM(v1.X(), v1.Y(), v1.Z(), (i == matchedElIndexToData ? MassElectron : MassPiPlus)); + p1.SetXYZT(v1.X(), v1.Y(), v1.Z(), RecoDecay::e(v1.X(), v1.Y(), v1.Z(), (i == matchedElIndexToData ? MassElectron : MassPiPlus))); } nSigmaEl[counterTmp] = tmptrack.tpcNSigmaEl(); @@ -4097,7 +4275,7 @@ struct TauTau13topo { tmpTofNsigmaEl[counterTmp] = tmptrack.tofNSigmaEl(); deltaPhiTmp = calculateDeltaPhi(p - p1, p1); - pi3invMass[counterTmp] = (p - p1).Mag(); + pi3invMass[counterTmp] = (p - p1).mag(); pi3pt[counterTmp] = (p - p1).Pt(); pi3deltaPhi[counterTmp] = deltaPhiTmp; pi3assymav[counterTmp] = (p1.Pt() - (scalarPtsum - p1.Pt()) / 3.) / (p1.Pt() + (scalarPtsum - p1.Pt()) / 3.); @@ -4816,6 +4994,8 @@ struct TauTau13topo { } // end of loop over collisions } // end of electron + 3pi + // } // end of loop over mcCollisions + } // end of processEfficiencyMCSG // skimming: only 4 tracks selection @@ -4845,11 +5025,13 @@ struct TauTau13topo { int nEtaIn15 = 0; int npT100 = 0; // int qtot = 0; - int16_t qtot = 0; - TLorentzVector p; + int8_t qtot = 0; + // TLorentzVector p; + ROOT::Math::LorentzVector> p; for (const auto& trk : PVContributors) { qtot += trk.sign(); - p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + // p.SetXYZM(trk.px(), trk.py(), trk.pz(), MassPiPlus); + p.SetXYZT(trk.px(), trk.py(), trk.pz(), RecoDecay::e(trk.px(), trk.py(), trk.pz(), MassPiPlus)); if (std::abs(p.Eta()) < trkEtacut) nEtaIn15++; // 0.9 is a default if (trk.pt() > 0.1) @@ -4898,14 +5080,18 @@ struct TauTau13topo { return; registrySkim.get(HIST("skim/efficiency"))->Fill(7., 1.); + // RCT variable + int rct = 0; + rct = isGoodRCTflag(dgcand); + // // variables per track // int counterTmp = 0; float px[4], py[4], pz[4]; // int sign[4]; - // float dcaZ[4]; - // float dcaXY[4]; + float dcaZ[4]; + float dcaXY[4]; float tmpDedx[4]; float tmpTofNsigmaEl[4]; @@ -4922,8 +5108,12 @@ struct TauTau13topo { // float chi2TPC[4]; // float chi2ITS[4]; float chi2TOF[4] = {-1., -1., -1., -1.}; - // float nclTPCfind[4]; int nclTPCcrossedRows[4]; + int nclTPCfind[4]; + float nclTPCchi2[4]; + float trkITSchi2[4]; + int trkITScl[4]; + // double trkTime[4]; // float trkTimeRes[4]; float trkTofSignal[4]; @@ -4934,8 +5124,8 @@ struct TauTau13topo { py[counterTmp] = trk.py(); pz[counterTmp] = trk.pz(); // sign[counterTmp] = trk.sign(); - // dcaZ[counterTmp] = trk.dcaZ(); - // dcaXY[counterTmp] = trk.dcaXY(); + dcaZ[counterTmp] = trk.dcaZ(); + dcaXY[counterTmp] = trk.dcaXY(); tmpDedx[counterTmp] = trk.tpcSignal(); nSigmaEl[counterTmp] = trk.tpcNSigmaEl(); @@ -4958,6 +5148,11 @@ struct TauTau13topo { // nclTPCfind[counterTmp] = trk.tpcNClsFindable(); nclTPCcrossedRows[counterTmp] = trk.tpcNClsCrossedRows(); + nclTPCfind[counterTmp] = trk.tpcNClsFindable(); + nclTPCchi2[counterTmp] = trk.tpcChi2NCl(); + trkITSchi2[counterTmp] = trk.itsChi2NCl(); + trkITScl[counterTmp] = numberOfItsClustersCheck(trk); + // trkTime[counterTmp] = trk.trackTime(); // trkTimeRes[counterTmp] = trk.trackTimeRes(); counterTmp++; @@ -4967,6 +5162,7 @@ struct TauTau13topo { dgcand.globalBC(), // is it necessary dgtracks.size(), dgcand.numContrib(), + rct, // dgcand.posX(), dgcand.posY(), dgcand.posZ(), dgcand.flags(), @@ -4975,12 +5171,12 @@ struct TauTau13topo { energyZNA, energyZNC, qtot, dgcand.trs(), dgcand.trofs(), dgcand.hmpr(), // to test it - // dgcand.tfb(), dgcand.itsROFb(), dgcand.sbp(), dgcand.zVtxFT0vPV(), dgcand.vtxITSTPC(), + dgcand.tfb(), dgcand.itsROFb(), dgcand.sbp(), dgcand.zVtxFT0vPV(), dgcand.vtxITSTPC(), dgcand.totalFT0AmplitudeA(), dgcand.totalFT0AmplitudeC(), dgcand.totalFV0AmplitudeA(), // dgcand.timeFT0A(), dgcand.timeFT0C(), dgcand.timeFV0A(), px, py, pz, // sign, - // dcaXY, dcaZ, - nclTPCcrossedRows, + dcaXY, dcaZ, + nclTPCcrossedRows, nclTPCfind, nclTPCchi2, trkITSchi2, trkITScl, tmpDedx, nSigmaEl, nSigmaPi, nSigmaKa, nSigmaPr, nSigmaMu, trkTofSignal, tmpTofNsigmaEl, tmpTofNsigmaPi, tmpTofNsigmaKa, tmpTofNsigmaPr, tmpTofNsigmaMu, chi2TOF); diff --git a/PWGUD/Tasks/upcTestRctTables.cxx b/PWGUD/Tasks/upcTestRctTables.cxx new file mode 100644 index 00000000000..5f6d1bd8db1 --- /dev/null +++ b/PWGUD/Tasks/upcTestRctTables.cxx @@ -0,0 +1,84 @@ +// 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 upcTestRctTables.cxx +/// \brief Tests Rct Tables in UD tabl;es +/// +/// \author Roman Lavicka , Austrian Academy of Sciences & SMI +/// \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" + +using namespace o2; +using namespace o2::framework; +using namespace o2::framework::expressions; + +struct UpcTestRctTables { + + // Global varialbes + SGSelector sgSelector; + + HistogramRegistry histos{"histos", {}, OutputObjHandlingPolicy::AnalysisObject}; + + // declare configurables + Configurable verboseInfo{"verboseInfo", false, {"Print general info to terminal; default it false."}}; + + using FullSGUDCollisions = soa::Join; + using FullSGUDCollision = FullSGUDCollisions::iterator; + + // init + void init(InitContext&) + { + if (verboseInfo) + printMediumMessage("INIT METHOD"); + + histos.add("OutputTable/hRCTflags", ";RCTflag (-);Number of passed collision (-)", HistType::kTH1D, {{5, -0.5, 4.5}}); + + } // end init + + void processDataSG(FullSGUDCollision const& reconstructedCollision) + { + + histos.get(HIST("OutputTable/hRCTflags"))->Fill(0); + + if (sgSelector.isCBTOk(reconstructedCollision)) + histos.get(HIST("OutputTable/hRCTflags"))->Fill(1); + + if (sgSelector.isCBTZdcOk(reconstructedCollision)) + histos.get(HIST("OutputTable/hRCTflags"))->Fill(2); + + if (sgSelector.isCBTHadronOk(reconstructedCollision)) + histos.get(HIST("OutputTable/hRCTflags"))->Fill(3); + + if (sgSelector.isCBTHadronZdcOk(reconstructedCollision)) + histos.get(HIST("OutputTable/hRCTflags"))->Fill(4); + + } // end processDataSG + + PROCESS_SWITCH(UpcTestRctTables, processDataSG, "Iterate UD tables with measured data created by SG-Candidate-Producer.", true); +}; + +WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) +{ + return WorkflowSpec{ + adaptAnalysisTask(cfgc)}; +} diff --git a/Scripts/format_includes.awk b/Scripts/format_includes.awk new file mode 100644 index 00000000000..47f9132ed80 --- /dev/null +++ b/Scripts/format_includes.awk @@ -0,0 +1,21 @@ +#!/bin/awk -f + +# Fix include style. +# NB: Run before sorting. + +{ + if ($1 ~ /^#include/) { + h = substr($2, 2, length($2) - 2) + if ( h ~ /^(PWG[A-Z]{2}|Common|ALICE3|DPG|EventFiltering|Tools|Tutorials)\/.*\.h/ ) { $2 = "\""h"\"" } # O2Physics + else if ( h ~ /^(Algorithm|CCDB|Common[A-Z]|DataFormats|DCAFitter|Detectors|EMCAL|Field|Framework|FT0|FV0|GlobalTracking|ITS|MathUtils|MFT|MCH|MID|PHOS|PID|ReconstructionDataFormats|SimulationDataFormat|TOF|TPC|ZDC).*\/.*\.h/ ) { $2 = "<"h">" } # O2 + else if ( h ~ /^(T[A-Z]|Math\/|Roo[A-Z])[[:alnum:]\/]+\.h/ ) { $2 = "<"h">" } # ROOT + else if ( h ~ /^KF[A-Z][[:alnum:]]+\.h/ ) { $2 = "<"h">" } # KFParticle + else if ( h ~ /^(fastjet\/|onnxruntime)/ ) { $2 = "<"h">" } # FastJet, ONNX + else if ( h ~ /^.*DataModel\// ) { $2 = "\""h"\"" } # incomplete path to DataModel + else if ( h ~ /^([[:alnum:]_]+\/)+[[:alnum:]_]+\.h/ ) { $2 = "<"h">" } # other third-party + else if ( $2 ~ /^".*\./ ) { } # other local-looking file + else if ( h ~ /^[[:lower:]_]+\.h/ ) { $2 = "<"h">" } # C system + else if ( h ~ /^[[:lower:]_\/]+/ ) { $2 = "<"h">" } # C++ system + } + print +} diff --git a/Scripts/o2_linter.py b/Scripts/o2_linter.py index af7de5f101b..2aa8fefb24f 100644 --- a/Scripts/o2_linter.py +++ b/Scripts/o2_linter.py @@ -248,7 +248,7 @@ def is_disabled(self, line: str, prefix_comment="//") -> bool: if self.name in line: self.n_disabled += 1 # Look for a comment with a reason for disabling. - if re.search(r" \([\w\s]{3,}\)", line): + if re.search(r" \(.{3,}\)", line): return True return False diff --git a/Tools/KFparticle/KFUtilities.h b/Tools/KFparticle/KFUtilities.h index d1545e11651..bec24fd7adc 100644 --- a/Tools/KFparticle/KFUtilities.h +++ b/Tools/KFparticle/KFUtilities.h @@ -22,17 +22,26 @@ #define HomogeneousField #endif -#include +#include "Common/Core/RecoDecay.h" +#include "Common/Core/trackUtilities.h" + +#include +#include +#include +#include #include // FIXME -#include "KFParticle.h" -#include "KFPTrack.h" -#include "KFPVertex.h" -#include "KFParticleBase.h" -#include "KFVertex.h" +#include +#include +#include +#include -#include "Common/Core/RecoDecay.h" +#include +#include +#include +#include +#include /// @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 diff --git a/Tools/ML/MlResponse.h b/Tools/ML/MlResponse.h index 2d16a67bf18..c60946bcb03 100644 --- a/Tools/ML/MlResponse.h +++ b/Tools/ML/MlResponse.h @@ -17,21 +17,18 @@ #ifndef TOOLS_ML_MLRESPONSE_H_ #define TOOLS_ML_MLRESPONSE_H_ -#if __has_include() -#include -#else -#include -#endif +#include "Tools/ML/model.h" + +#include +#include +#include +#include +#include #include #include #include -#include "CCDB/CcdbApi.h" -#include "Framework/Array2D.h" - -#include "Tools/ML/model.h" - namespace o2 { namespace cuts_ml diff --git a/Tools/ML/model.cxx b/Tools/ML/model.cxx index 0c29808c73c..62ccd9f9839 100644 --- a/Tools/ML/model.cxx +++ b/Tools/ML/model.cxx @@ -17,9 +17,22 @@ /// \brief A general-purpose class with functions for ONNX model applications /// -// ONNX includes #include "Tools/ML/model.h" +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + namespace o2 { @@ -75,18 +88,8 @@ void OnnxModel::initModel(std::string localPath, bool enableOptimizations, int t } mEnv = std::make_shared(ORT_LOGGING_LEVEL_WARNING, "onnx-model"); -#if __has_include() - mSession = std::make_shared(*mEnv, modelPath, sessionOptions); -#else mSession = std::make_shared(*mEnv, modelPath.c_str(), sessionOptions); -#endif - -#if __has_include() - mInputNames = mSession->GetInputNames(); - mInputShapes = mSession->GetInputShapes(); - mOutputNames = mSession->GetOutputNames(); - mOutputShapes = mSession->GetOutputShapes(); -#else + Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < mSession->GetInputCount(); ++i) { mInputNames.push_back(mSession->GetInputNameAllocated(i, tmpAllocator).get()); @@ -100,7 +103,6 @@ void OnnxModel::initModel(std::string localPath, bool enableOptimizations, int t for (size_t i = 0; i < mSession->GetOutputCount(); ++i) { mOutputShapes.emplace_back(mSession->GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif LOG(info) << "Input Nodes:"; for (size_t i = 0; i < mInputNames.size(); i++) { LOG(info) << "\t" << mInputNames[i] << " : " << printShape(mInputShapes[i]); diff --git a/Tools/ML/model.h b/Tools/ML/model.h index 84872224104..e08b84f129f 100644 --- a/Tools/ML/model.h +++ b/Tools/ML/model.h @@ -20,23 +20,18 @@ #ifndef TOOLS_ML_MODEL_H_ #define TOOLS_ML_MODEL_H_ -// C++ and system includes -#if __has_include() -#include -#else -#include -#endif -#include -#include -#include -#include -#include +#include -// ROOT includes -#include "TSystem.h" +#include -// O2 includes -#include "Framework/Logger.h" +#include +#include +#include +#include +#include +#include +#include +#include namespace o2 { @@ -62,9 +57,6 @@ class OnnxModel // assert(input[0].GetTensorTypeAndShapeInfo().GetShape() == getNumInputNodes()); --> Fails build in debug mode, TODO: assertion should be checked somehow try { -#if __has_include() - auto outputTensors = mSession->Run(mInputNames, input, mOutputNames); -#else Ort::RunOptions runOptions; std::vector inputNamesChar(mInputNames.size(), nullptr); std::transform(std::begin(mInputNames), std::end(mInputNames), std::begin(inputNamesChar), @@ -74,7 +66,6 @@ class OnnxModel std::transform(std::begin(mOutputNames), std::end(mOutputNames), std::begin(outputNamesChar), [&](const std::string& str) { return str.c_str(); }); auto outputTensors = mSession->Run(runOptions, inputNamesChar.data(), input.data(), input.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif LOG(debug) << "Number of output tensors: " << outputTensors.size(); if (outputTensors.size() != mOutputNames.size()) { LOG(fatal) << "Number of output tensors: " << outputTensors.size() << " does not agree with the model specified size: " << mOutputNames.size(); @@ -100,13 +91,9 @@ class OnnxModel assert(size % mInputShapes[0][1] == 0); std::vector inputShape{size / mInputShapes[0][1], mInputShapes[0][1]}; std::vector inputTensors; -#if __has_include() - inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(input.data(), size, inputShape)); -#else Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.emplace_back(Ort::Value::CreateTensor(memInfo, input.data(), size, inputShape.data(), inputShape.size())); -#endif LOG(debug) << "Input shape calculated from vector: " << printShape(inputShape); return evalModel(inputTensors); } @@ -117,9 +104,7 @@ class OnnxModel { std::vector inputTensors; -#if !__has_include() Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); -#endif for (size_t iinput = 0; iinput < input.size(); iinput++) { [[maybe_unused]] int totalSize = 1; @@ -134,36 +119,24 @@ class OnnxModel inputShape.push_back(mInputShapes[iinput][idim]); } -#if __has_include() - inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(input[iinput].data(), size, inputShape)); -#else inputTensors.emplace_back(Ort::Value::CreateTensor(memInfo, input[iinput].data(), size, inputShape.data(), inputShape.size())); -#endif } return evalModel(inputTensors); } // Reset session -#if __has_include() - void resetSession() { mSession.reset(new Ort::Experimental::Session{*mEnv, modelPath, sessionOptions}); } -#else void resetSession() { mSession.reset(new Ort::Session{*mEnv, modelPath.c_str(), sessionOptions}); } -#endif // Getters & Setters Ort::SessionOptions* getSessionOptions() { return &sessionOptions; } // For optimizations in post -#if __has_include() - std::shared_ptr getSession() { return mSession; } -#else std::shared_ptr getSession() { return mSession; } -#endif int getNumInputNodes() const { return mInputShapes[0][1]; } std::vector> getInputShapes() const { return mInputShapes; } int getNumOutputNodes() const { return mOutputShapes[0][1]; } @@ -174,11 +147,7 @@ class OnnxModel private: // Environment variables for the ONNX runtime std::shared_ptr mEnv = nullptr; -#if __has_include() - std::shared_ptr mSession = nullptr; -#else std::shared_ptr mSession = nullptr; -#endif Ort::SessionOptions sessionOptions; // Input & Output specifications of the loaded network diff --git a/Tools/PIDML/pidMl.h b/Tools/PIDML/pidMl.h index 935440e26f7..cb45360052c 100644 --- a/Tools/PIDML/pidMl.h +++ b/Tools/PIDML/pidMl.h @@ -17,10 +17,14 @@ #ifndef TOOLS_PIDML_PIDML_H_ #define TOOLS_PIDML_PIDML_H_ -#include "Framework/AnalysisDataModel.h" -#include "Common/DataModel/PIDResponse.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 + +#include namespace o2::aod { diff --git a/Tools/PIDML/pidMlBatchEffAndPurProducer.cxx b/Tools/PIDML/pidMlBatchEffAndPurProducer.cxx index 86adb2cf238..34ce845c79d 100644 --- a/Tools/PIDML/pidMlBatchEffAndPurProducer.cxx +++ b/Tools/PIDML/pidMlBatchEffAndPurProducer.cxx @@ -16,22 +16,39 @@ /// \author Michał Olędzki /// \author Marek Mytkowski -#include -#include +#include "Tools/PIDML/pidOnnxModel.h" +#include "Tools/PIDML/pidUtils.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 "Framework/AnalysisDataModel.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/StaticFor.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "Tools/PIDML/pidOnnxModel.h" -#include "Tools/PIDML/pidUtils.h" using namespace o2; using namespace o2::framework; diff --git a/Tools/PIDML/pidMlEffAndPurProducer.cxx b/Tools/PIDML/pidMlEffAndPurProducer.cxx index e3c57763dbf..1441718b336 100644 --- a/Tools/PIDML/pidMlEffAndPurProducer.cxx +++ b/Tools/PIDML/pidMlEffAndPurProducer.cxx @@ -15,16 +15,27 @@ /// \author Michał Olędzki /// \author Marek Mytkowski -#include - -#include "Framework/AnalysisDataModel.h" -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" #include "Tools/PIDML/pidOnnxModel.h" #include "Tools/PIDML/pidUtils.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 using namespace o2; using namespace o2::framework; @@ -91,7 +102,7 @@ struct PidMlEffAndPurProducer { return nSigma; } - bool isNSigmaAccept(const BigTracks::iterator& track, nSigma_t& nSigma) + bool isNSigmaAccept(const BigTracks::iterator& track, const nSigma_t& nSigma) { // FIXME: for current particles it works, but there are some particles, // which can have different sign and pdgSign diff --git a/Tools/PIDML/pidMlProducer.cxx b/Tools/PIDML/pidMlProducer.cxx index de1d65622d0..332a2a8209b 100644 --- a/Tools/PIDML/pidMlProducer.cxx +++ b/Tools/PIDML/pidMlProducer.cxx @@ -15,18 +15,33 @@ /// \author Maja Kabus /// \author Marek Mytkowski -#include -#include -#include "Framework/AnalysisTask.h" -#include "Framework/StaticFor.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" -#include "Common/DataModel/Centrality.h" -#include "Common/DataModel/Multiplicity.h" -#include "Common/DataModel/TrackSelectionTables.h" #include "Tools/PIDML/pidMl.h" #include "Tools/PIDML/pidUtils.h" +// +#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 using namespace o2; using namespace o2::framework; diff --git a/Tools/PIDML/pidOnnxInterface.h b/Tools/PIDML/pidOnnxInterface.h index e97635468ee..6724e5c5167 100644 --- a/Tools/PIDML/pidOnnxInterface.h +++ b/Tools/PIDML/pidOnnxInterface.h @@ -17,14 +17,18 @@ #ifndef TOOLS_PIDML_PIDONNXINTERFACE_H_ #define TOOLS_PIDML_PIDONNXINTERFACE_H_ -#include -#include +#include "Tools/PIDML/pidOnnxModel.h" +// +#include +#include +#include + +#include +#include #include +#include #include -#include "Framework/Array2D.h" -#include "Tools/PIDML/pidOnnxModel.h" - namespace pidml_pt_cuts { static constexpr int NPids = 6; @@ -110,7 +114,7 @@ struct PidONNXInterface { } std::vector> mModels; - std::size_t mNPids; + std::size_t mNPids{0}; o2::framework::LabeledArray mPLimits; }; #endif // TOOLS_PIDML_PIDONNXINTERFACE_H_ diff --git a/Tools/PIDML/pidOnnxModel.h b/Tools/PIDML/pidOnnxModel.h index 1c48a84f2b8..4ee88106ab0 100644 --- a/Tools/PIDML/pidOnnxModel.h +++ b/Tools/PIDML/pidOnnxModel.h @@ -17,30 +17,31 @@ #ifndef TOOLS_PIDML_PIDONNXMODEL_H_ #define TOOLS_PIDML_PIDONNXMODEL_H_ +#include "Tools/PIDML/pidUtils.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 -#if __has_include() -#include -#else -#include -#endif - -#include "rapidjson/document.h" -#include "rapidjson/filereadstream.h" -#include "CCDB/CcdbApi.h" -#include "Tools/PIDML/pidUtils.h" enum PidMLDetector { kTPCOnly = 0, @@ -61,7 +62,7 @@ constexpr MomentumLimitsMatrix defaultModelPLimits({0.0, 0.5, 0.8}); // TODO: Copied from cefpTask, shall we put it in some common utils code? namespace { -bool readJsonFile(const std::string& config, rapidjson::Document& d) +bool readJsonFile(std::string const& config, rapidjson::Document& d) { FILE* fp = fopen(config.data(), "rb"); if (!fp) { @@ -81,7 +82,7 @@ bool readJsonFile(const std::string& config, rapidjson::Document& d) template struct PidONNXModel { public: - PidONNXModel(std::string& localPath, std::string& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, + PidONNXModel(std::string const& localPath, std::string const& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi const& ccdbApi, uint64_t timestamp, int pid, double minCertainty, const double* pLimits = &pidml_pt_cuts::defaultModelPLimits[0]) : mPid(pid), mMinCertainty(minCertainty), mPLimits(pLimits, pLimits + kNDetectors) { @@ -93,19 +94,9 @@ struct PidONNXModel { Ort::SessionOptions sessionOptions; mEnv = std::make_shared(ORT_LOGGING_LEVEL_WARNING, "pid-onnx-inferer"); LOG(info) << "Loading ONNX model from file: " << modelFile; -#if __has_include() - mSession.reset(new Ort::Experimental::Session{*mEnv, modelFile, sessionOptions}); -#else mSession.reset(new Ort::Session{*mEnv, modelFile.c_str(), sessionOptions}); -#endif LOG(info) << "ONNX model loaded"; -#if __has_include() - mInputNames = mSession->GetInputNames(); - mInputShapes = mSession->GetInputShapes(); - mOutputNames = mSession->GetOutputNames(); - mOutputShapes = mSession->GetOutputShapes(); -#else Ort::AllocatorWithDefaultOptions tmpAllocator; for (size_t i = 0; i < mSession->GetInputCount(); ++i) { mInputNames.push_back(mSession->GetInputNameAllocated(i, tmpAllocator).get()); @@ -119,7 +110,6 @@ struct PidONNXModel { for (size_t i = 0; i < mSession->GetOutputCount(); ++i) { mOutputShapes.emplace_back(mSession->GetOutputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif LOG(debug) << "Input Node Name/Shape (" << mInputNames.size() << "):"; for (size_t i = 0; i < mInputNames.size(); i++) { @@ -151,8 +141,8 @@ struct PidONNXModel { return getModelOutput(track) >= mMinCertainty; } - int mPid; - double mMinCertainty; + int mPid{0}; + double mMinCertainty{0}; private: void getModelPaths(std::string const& path, std::string& modelDir, std::string& modelFile, std::string& modelPath, int pid, std::string const& ext) @@ -170,7 +160,7 @@ struct PidONNXModel { modelPath = modelDir + "/" + modelFile; } - void downloadFromCCDB(o2::ccdb::CcdbApi& ccdbApi, std::string const& ccdbFile, uint64_t timestamp, std::string const& localDir, std::string const& localFile) + void downloadFromCCDB(o2::ccdb::CcdbApi const& ccdbApi, std::string const& ccdbFile, uint64_t timestamp, std::string const& localDir, std::string const& localFile) { std::map metadata; bool retrieveSuccess = ccdbApi.retrieveBlob(ccdbFile, localDir, metadata, timestamp, false, localFile); @@ -182,7 +172,7 @@ struct PidONNXModel { } } - void loadInputFiles(std::string const& localPath, std::string const& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi& ccdbApi, uint64_t timestamp, int pid, std::string& modelPath) + void loadInputFiles(std::string const& localPath, std::string const& ccdbPath, bool useCCDB, o2::ccdb::CcdbApi const& ccdbApi, uint64_t timestamp, int pid, std::string& modelPath) { rapidjson::Document trainColumnsDoc; rapidjson::Document scalingParamsDoc; @@ -274,12 +264,8 @@ struct PidONNXModel { std::vector inputTensorValues = getValues(track); std::vector inputTensors; -#if __has_include() - inputTensors.emplace_back(Ort::Experimental::Value::CreateTensor(inputTensorValues.data(), inputTensorValues.size(), inputShape)); -#else Ort::MemoryInfo memInfo = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputTensors.emplace_back(Ort::Value::CreateTensor(memInfo, inputTensorValues.data(), inputTensorValues.size(), inputShape.data(), inputShape.size())); -#endif // Double-check the dimensions of the input tensor assert(inputTensors[0].IsTensor() && @@ -287,9 +273,6 @@ struct PidONNXModel { LOG(debug) << "input tensor shape: " << printShape(inputTensors[0].GetTensorTypeAndShapeInfo().GetShape()); try { -#if __has_include() - auto outputTensors = mSession->Run(mInputNames, inputTensors, mOutputNames); -#else Ort::RunOptions runOptions; std::vector inputNamesChar(mInputNames.size(), nullptr); std::transform(std::begin(mInputNames), std::end(mInputNames), std::begin(inputNamesChar), @@ -299,7 +282,6 @@ struct PidONNXModel { std::transform(std::begin(mOutputNames), std::end(mOutputNames), std::begin(outputNamesChar), [&](const std::string& str) { return str.c_str(); }); auto outputTensors = mSession->Run(runOptions, inputNamesChar.data(), inputTensors.data(), inputTensors.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif // Double-check the dimensions of the output tensors // The number of output tensors is equal to the number of output nodes specified in the Run() call @@ -331,11 +313,7 @@ struct PidONNXModel { std::shared_ptr mEnv = nullptr; // No empty constructors for Session, we need a pointer -#if __has_include() - std::shared_ptr mSession = nullptr; -#else std::shared_ptr mSession = nullptr; -#endif std::vector mPLimits; std::vector mInputNames; diff --git a/Tools/PIDML/qaPid.cxx b/Tools/PIDML/qaPid.cxx index 3480ad7c366..25fba1ee6a0 100644 --- a/Tools/PIDML/qaPid.cxx +++ b/Tools/PIDML/qaPid.cxx @@ -14,15 +14,29 @@ /// \author Łukasz Sawicki /// \since -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" +#include "Common/DataModel/PIDResponseCombined.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.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; @@ -371,7 +385,7 @@ struct QaPid { for (int j = 0; j < kArrLen; ++j) { if (p < PSwitch[j]) { particleNSigma[j] = std::abs(tpcNSigmas[j]); - } else if (p >= PSwitch[j]) { + } else { particleNSigma[j] = combinedSignal(tpcNSigmas[j], tofNSigmas[j]); } } @@ -409,7 +423,7 @@ struct QaPid { for (int j = 0; j < kArrLen; ++j) { if (p < PSwitch[j]) { particleNSigma[j] = std::abs(tpcNSigmas[j]); - } else if (p >= PSwitch[j]) { + } else { particleNSigma[j] = combinedSignal(tpcNSigmas[j], tofNSigmas[j]); } } diff --git a/Tools/PIDML/qaPidMl.cxx b/Tools/PIDML/qaPidMl.cxx index 1fee5330de4..01fca6457e1 100644 --- a/Tools/PIDML/qaPidMl.cxx +++ b/Tools/PIDML/qaPidMl.cxx @@ -14,17 +14,28 @@ /// \author Łukasz Sawicki /// \since -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/StaticFor.h" +#include "Tools/PIDML/pidOnnxModel.h" +// +#include "Common/DataModel/PIDResponseTOF.h" #include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #include -#include "Tools/PIDML/pidOnnxModel.h" + +#include +#include +#include using namespace o2; using namespace o2::framework; @@ -311,7 +322,7 @@ struct QaPidMl { static constexpr float kCertaintyThreshold = 0.5f; - int getParticlePdg(float pidCertainties[]) + int getParticlePdg(const float pidCertainties[]) { // index of the biggest value in an array int index = 0; diff --git a/Tools/PIDML/simpleApplyPidOnnxInterface.cxx b/Tools/PIDML/simpleApplyPidOnnxInterface.cxx index bcfb83cf354..268b0609c25 100644 --- a/Tools/PIDML/simpleApplyPidOnnxInterface.cxx +++ b/Tools/PIDML/simpleApplyPidOnnxInterface.cxx @@ -14,16 +14,26 @@ /// /// \author Maja Kabus +#include "Tools/PIDML/pidOnnxInterface.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 "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" -#include "Tools/PIDML/pidOnnxInterface.h" - using namespace o2; using namespace o2::framework; using namespace o2::framework::expressions; diff --git a/Tools/PIDML/simpleApplyPidOnnxModel.cxx b/Tools/PIDML/simpleApplyPidOnnxModel.cxx index aab1a48fc28..57316713f03 100644 --- a/Tools/PIDML/simpleApplyPidOnnxModel.cxx +++ b/Tools/PIDML/simpleApplyPidOnnxModel.cxx @@ -14,14 +14,23 @@ /// /// \author Maja Kabus -#include - -#include "Framework/runDataProcessing.h" -#include "Framework/AnalysisTask.h" -#include "CCDB/CcdbApi.h" -#include "Common/DataModel/TrackSelectionTables.h" -#include "Common/DataModel/PIDResponse.h" #include "Tools/PIDML/pidOnnxModel.h" +// +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/TrackSelectionTables.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include using namespace o2; using namespace o2::framework; diff --git a/Tutorials/PWGHF/DataModelMini.h b/Tutorials/PWGHF/DataModelMini.h index 7a03f1462b7..720b7207676 100644 --- a/Tutorials/PWGHF/DataModelMini.h +++ b/Tutorials/PWGHF/DataModelMini.h @@ -17,7 +17,12 @@ #ifndef TUTORIALS_PWGHF_DATAMODELMINI_H_ #define TUTORIALS_PWGHF_DATAMODELMINI_H_ -#include "Framework/AnalysisDataModel.h" +#include "Common/Core/RecoDecay.h" + +#include +#include + +#include namespace o2::aod { diff --git a/Tutorials/PWGHF/skimCreatorMini.cxx b/Tutorials/PWGHF/skimCreatorMini.cxx index ac6b12e2004..e3aae5bbaf4 100644 --- a/Tutorials/PWGHF/skimCreatorMini.cxx +++ b/Tutorials/PWGHF/skimCreatorMini.cxx @@ -14,21 +14,28 @@ /// /// \author Vít Kučera , Inha University -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// O2Physics +#include "Tutorials/PWGHF/DataModelMini.h" +// #include "Common/Core/RecoDecay.h" #include "Common/Core/trackUtilities.h" #include "Common/DataModel/TrackSelectionTables.h" -// PWGHF -#include "Tutorials/PWGHF/DataModelMini.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include using namespace o2; using namespace o2::aod; diff --git a/Tutorials/PWGHF/taskMini.cxx b/Tutorials/PWGHF/taskMini.cxx index 871fe710581..813e9879ce4 100644 --- a/Tutorials/PWGHF/taskMini.cxx +++ b/Tutorials/PWGHF/taskMini.cxx @@ -14,23 +14,32 @@ /// /// \author Vít Kučera , Inha University -// O2 -#include "CommonConstants/PhysicsConstants.h" -#include "DCAFitter/DCAFitterN.h" -#include "Framework/AnalysisDataModel.h" -#include "Framework/AnalysisTask.h" -#include "Framework/HistogramRegistry.h" -#include "Framework/runDataProcessing.h" - -// O2Physics +#include "Tutorials/PWGHF/DataModelMini.h" +// +#include "PWGHF/Core/HfHelper.h" +// #include "Common/Core/RecoDecay.h" #include "Common/Core/TrackSelectorPID.h" #include "Common/Core/trackUtilities.h" -#include "Common/DataModel/PIDResponse.h" - -// PWGHF -#include "PWGHF/Core/HfHelper.h" -#include "Tutorials/PWGHF/DataModelMini.h" +#include "Common/DataModel/PIDResponseTOF.h" +#include "Common/DataModel/PIDResponseTPC.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include using namespace o2; using namespace o2::aod; @@ -314,8 +323,8 @@ struct HfTaskMiniD0 { WorkflowSpec defineDataProcessing(ConfigContext const& cfgc) { return WorkflowSpec{ - adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong"}), // o2-linter: disable=name/o2-task - adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong-expressions"}), // o2-linter: disable=name/o2-task + adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong"}), // o2-linter: disable=name/o2-task (wrong hyphenation) + adaptAnalysisTask(cfgc, TaskName{"hf-task-mini-candidate-creator-2prong-expressions"}), // o2-linter: disable=name/o2-task (wrong hyphenation) adaptAnalysisTask(cfgc), adaptAnalysisTask(cfgc)}; } diff --git a/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx b/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx index 07736a3e841..5022d4b602d 100644 --- a/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx +++ b/Tutorials/PWGLF/Resonance/resonancesMicrotrack.cxx @@ -107,9 +107,9 @@ struct ResonancesMicrotrack { } else { if (std::abs(track.pt()) < cMinPtcut) return false; - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags()) > cMaxDCArToPVcut - Epsilon) return false; - if (o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) + if (o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags()) > cMaxDCAzToPVcut - Epsilon) return false; if (cfgPrimaryTrack && !track.isPrimaryTrack()) return false; @@ -132,8 +132,8 @@ struct ResonancesMicrotrack { } // return true; } else { - bool tpcPass = std::abs(o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTPC + Epsilon; - bool tofPass = candidate.hasTOF() ? std::abs(o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTOF + Epsilon : true; + bool tpcPass = std::abs(o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTPC + Epsilon; + bool tofPass = candidate.hasTOF() ? std::abs(o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(candidate.pidNSigmaPrFlag())) < nSigmaCutTOF + Epsilon : true; if (tpcPass && tofPass) { return true; } @@ -173,11 +173,11 @@ struct ResonancesMicrotrack { histos.fill(HIST("hPx_ResoMicroTracks"), track.px()); histos.fill(HIST("hPy_ResoMicroTracks"), track.py()); histos.fill(HIST("hPz_ResoMicroTracks"), track.pz()); - histos.fill(HIST("hDcaxy_ResoMicroTracks"), o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())); - histos.fill(HIST("hDcaz_ResoMicroTracks"), o2::aod::resodmciroaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())); - histos.fill(HIST("hNsigmaKaonTPC_ResoMicroTracks"), o2::aod::resodmciroaughter::PidNSigma::getTPCnSigma(track.pidNSigmaPrFlag())); + histos.fill(HIST("hDcaxy_ResoMicroTracks"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAxy(track.trackSelectionFlags())); + histos.fill(HIST("hDcaz_ResoMicroTracks"), o2::aod::resomicrodaughter::ResoMicroTrackSelFlag::decodeDCAz(track.trackSelectionFlags())); + histos.fill(HIST("hNsigmaKaonTPC_ResoMicroTracks"), o2::aod::resomicrodaughter::PidNSigma::getTPCnSigma(track.pidNSigmaPrFlag())); if (track.hasTOF()) { - histos.fill(HIST("hNsigmaKaonTOF_ResoMicroTracks"), o2::aod::resodmciroaughter::PidNSigma::getTOFnSigma(track.pidNSigmaPrFlag())); + histos.fill(HIST("hNsigmaKaonTOF_ResoMicroTracks"), o2::aod::resomicrodaughter::PidNSigma::getTOFnSigma(track.pidNSigmaPrFlag())); } } } diff --git a/Tutorials/src/reweighting.cxx b/Tutorials/src/reweighting.cxx index 72c17a1cb29..17a4ad4bf33 100644 --- a/Tutorials/src/reweighting.cxx +++ b/Tutorials/src/reweighting.cxx @@ -28,11 +28,7 @@ // This workflow is used to create a flat tree for model training // Use o2-aod-merger to combine dataframes in output AnalysisResults_trees.root -#if __has_include() -#include -#else #include -#endif #include "Framework/runDataProcessing.h" #include "Framework/AnalysisTask.h" #include "Common/DataModel/Multiplicity.h" @@ -82,11 +78,7 @@ struct CreateWeights { Filter centralTracks = nabs(aod::track::eta) < centralEtaCut; /// onnx runtime session handle -#if __has_include() - std::shared_ptr onnxSession = nullptr; -#else std::shared_ptr onnxSession = nullptr; -#endif /// onnx runtime session options Ort::SessionOptions sessionOptions; /// input vectore @@ -98,17 +90,11 @@ struct CreateWeights { { auto path = (std::string)onnxModel; /// create session -#if __has_include() - onnxSession = std::make_shared(env, path, sessionOptions); - /// adjust input shape to use row-by-row model application - inputShapes = onnxSession->GetInputShapes(); -#else onnxSession = std::make_shared(env, path.c_str(), sessionOptions); /// adjust input shape to use row-by-row model application for (size_t i = 0; i < onnxSession->GetInputCount(); ++i) { inputShapes.emplace_back(onnxSession->GetInputTypeInfo(i).GetTensorTypeAndShapeInfo().GetShape()); } -#endif if (inputShapes[0][0] < 0) { LOG(warning) << "Model with negative input shape, setting it to 1."; inputShapes[0][0] = 1; @@ -120,11 +106,6 @@ struct CreateWeights { /// get the input variables auto features = collect(collision, tracks); /// add an entry in input vector -#if __has_include() - inputML.push_back(Ort::Experimental::Value::CreateTensor(features.data(), features.size(), inputShapes[0])); - /// run inference - auto result = onnxSession->Run(onnxSession->GetInputNames(), inputML, onnxSession->GetOutputNames()); -#else Ort::MemoryInfo mem_info = Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeDefault); inputML.push_back(Ort::Value::CreateTensor(mem_info, features.data(), features.size(), inputShapes[0].data(), inputShapes[0].size())); @@ -142,7 +123,6 @@ struct CreateWeights { outputNamesChar.push_back(onnxSession->GetOutputNameAllocated(i, tmpAllocator).get()); } auto result = onnxSession->Run(runOptions, inputNamesChar.data(), inputML.data(), inputML.size(), outputNamesChar.data(), outputNamesChar.size()); -#endif /// extract scores auto scores = result[1].GetTensorMutableData(); LOGP(info, "Col {}: scores ({}, {})", collision.globalIndex(), scores[0], scores[1]); diff --git a/dependencies/FindKFParticle.cmake b/dependencies/FindKFParticle.cmake index 7c789c3f937..6821b601c66 100644 --- a/dependencies/FindKFParticle.cmake +++ b/dependencies/FindKFParticle.cmake @@ -17,7 +17,7 @@ #endif() find_path(KFPARTICLE_INCLUDE_DIR KFParticle.h - PATH_SUFFIXES "include" + PATH_SUFFIXES "include" "include/KFParticle" HINTS "$ENV{KFPARTICLE_ROOT}") find_library(KFPARTICLE_LIBPATH "KFParticle" PATH_SUFFIXES "lib"